1219 lines
34 KiB
C++
1219 lines
34 KiB
C++
/* ResidualVM - A 3D game interpreter
|
|
*
|
|
* ResidualVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_putenv
|
|
|
|
#include "common/scummsys.h"
|
|
|
|
#if defined(SDL_BACKEND)
|
|
|
|
#include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
|
|
#include "backends/events/sdl/sdl-events.h"
|
|
#include "backends/platform/sdl/sdl.h"
|
|
#include "common/config-manager.h"
|
|
#include "common/mutex.h"
|
|
#include "common/textconsole.h"
|
|
#include "common/translation.h"
|
|
#include "common/util.h"
|
|
#ifdef USE_RGB_COLOR
|
|
#include "common/list.h"
|
|
#endif
|
|
#include "graphics/font.h"
|
|
#include "graphics/fontman.h"
|
|
#include "graphics/scaler.h"
|
|
#include "graphics/surface.h"
|
|
#include "graphics/pixelbuffer.h"
|
|
#include "gui/EventRecorder.h"
|
|
|
|
#ifdef USE_OPENGL
|
|
#include "graphics/opengl/context.h"
|
|
#endif
|
|
|
|
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
|
|
{0, 0, 0}
|
|
};
|
|
|
|
SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window)
|
|
:
|
|
SdlGraphicsManager(sdlEventSource, window),
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
_renderer(nullptr), _screenTexture(nullptr),
|
|
#endif
|
|
_screen(0),
|
|
_subScreen(0),
|
|
_overlayVisible(false),
|
|
_overlayscreen(0),
|
|
_overlayWidth(0), _overlayHeight(0),
|
|
_overlayDirty(true),
|
|
_screenChangeCount(0),
|
|
_lockAspectRatio(true),
|
|
_gameRect()
|
|
#ifdef USE_OPENGL
|
|
, _opengl(false), _overlayNumTex(0), _overlayTexIds(0)
|
|
, _frameBuffer(nullptr)
|
|
#endif
|
|
#ifdef USE_OPENGL_SHADERS
|
|
, _boxShader(nullptr), _boxVerticesVBO(0)
|
|
#endif
|
|
{
|
|
const SDL_VideoInfo *vi = SDL_GetVideoInfo();
|
|
_desktopW = vi->current_w;
|
|
_desktopH = vi->current_h;
|
|
_sideSurfaces[0] = _sideSurfaces[1] = nullptr;
|
|
#ifdef USE_OPENGL
|
|
_sideTextures[0] = _sideTextures[1] = nullptr;
|
|
#endif
|
|
}
|
|
|
|
SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() {
|
|
closeOverlay();
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::activateManager() {
|
|
SdlGraphicsManager::activateManager();
|
|
|
|
// Register the graphics manager as a event observer
|
|
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::deactivateManager() {
|
|
// Unregister the event observer
|
|
if (g_system->getEventManager()->getEventDispatcher()) {
|
|
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
|
|
}
|
|
|
|
SdlGraphicsManager::deactivateManager();
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::resetGraphicsScale() {
|
|
setGraphicsMode(0);
|
|
}
|
|
|
|
bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) {
|
|
return
|
|
(f == OSystem::kFeatureFullscreenMode) ||
|
|
#ifdef USE_OPENGL
|
|
(f == OSystem::kFeatureOpenGL) ||
|
|
(f == OSystem::kFeatureAspectRatioCorrection);
|
|
#else
|
|
false;
|
|
#endif
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
|
|
switch (f) {
|
|
case OSystem::kFeatureFullscreenMode:
|
|
_fullscreen = enable;
|
|
break;
|
|
case OSystem::kFeatureAspectRatioCorrection:
|
|
_lockAspectRatio = enable;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) {
|
|
switch (f) {
|
|
case OSystem::kFeatureFullscreenMode:
|
|
return _fullscreen;
|
|
case OSystem::kFeatureAspectRatioCorrection:
|
|
return _lockAspectRatio;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::getSupportedGraphicsModes() const {
|
|
return s_supportedGraphicsModes;
|
|
}
|
|
|
|
int SurfaceSdlGraphicsManager::getDefaultGraphicsMode() const {
|
|
return 0;// ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::beginGFXTransaction() {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
OSystem::TransactionError SurfaceSdlGraphicsManager::endGFXTransaction() {
|
|
// ResidualVM: not use it
|
|
return OSystem::kTransactionSuccess;
|
|
}
|
|
|
|
#ifdef USE_RGB_COLOR
|
|
Common::List<Graphics::PixelFormat> SurfaceSdlGraphicsManager::getSupportedFormats() const {
|
|
// ResidualVM: not use it
|
|
return _supportedFormats;
|
|
}
|
|
#endif
|
|
|
|
bool SurfaceSdlGraphicsManager::setGraphicsMode(int mode) {
|
|
// ResidualVM: not use it
|
|
return true;
|
|
}
|
|
|
|
int SurfaceSdlGraphicsManager::getGraphicsMode() const {
|
|
// ResidualVM: not use it
|
|
return 0;
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::launcherInitSize(uint w, uint h) {
|
|
closeOverlay();
|
|
setupScreen(w, h, false, false);
|
|
}
|
|
|
|
Graphics::PixelBuffer SurfaceSdlGraphicsManager::setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) {
|
|
uint32 sdlflags;
|
|
int bpp;
|
|
|
|
closeOverlay();
|
|
|
|
#ifdef USE_OPENGL
|
|
_opengl = accel3d;
|
|
_antialiasing = 0;
|
|
#endif
|
|
_fullscreen = fullscreen;
|
|
|
|
ConfMan.registerDefault("fullscreen_res", "desktop");
|
|
const Common::String &fsres = ConfMan.get("fullscreen_res");
|
|
if (fsres != "desktop") {
|
|
uint newW, newH;
|
|
int converted = sscanf(fsres.c_str(), "%ux%u", &newW, &newH);
|
|
if (converted == 2) {
|
|
_desktopW = newW;
|
|
_desktopH = newH;
|
|
} else {
|
|
warning("Could not parse 'fullscreen_res' option: expected WWWxHHH, got %s", fsres.c_str());
|
|
}
|
|
}
|
|
|
|
ConfMan.registerDefault("aspect_ratio", true);
|
|
_lockAspectRatio = ConfMan.getBool("aspect_ratio");
|
|
uint fbW = screenW;
|
|
uint fbH = screenH;
|
|
_gameRect = Math::Rect2d(Math::Vector2d(0, 0), Math::Vector2d(1, 1));
|
|
|
|
#ifdef USE_OPENGL
|
|
bool framebufferSupported = false;
|
|
|
|
// Use the desktop resolution for fullscreen when possible
|
|
if (_fullscreen) {
|
|
if (g_engine->hasFeature(Engine::kSupportsArbitraryResolutions)) {
|
|
// If the game supports arbitrary resolutions, use the desktop mode as the game mode
|
|
screenW = _desktopW;
|
|
screenH = _desktopH;
|
|
} else if (_opengl) {
|
|
// If available, draw to a framebuffer and scale it to the desktop resolution
|
|
#ifndef AMIGAOS
|
|
// Spawn a 32x32 window off-screen
|
|
SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=9000,9000"));
|
|
SDL_SetVideoMode(32, 32, 0, SDL_OPENGL);
|
|
SDL_putenv(const_cast<char *>("SDL_VIDEO_WINDOW_POS=centered"));
|
|
OpenGLContext.initialize(OpenGL::kContextGL);
|
|
framebufferSupported = OpenGLContext.framebufferObjectSupported;
|
|
if (_fullscreen && framebufferSupported) {
|
|
screenW = _desktopW;
|
|
screenH = _desktopH;
|
|
|
|
if (_lockAspectRatio) {
|
|
float scale = MIN(_desktopH / float(fbH), _desktopW / float(fbW));
|
|
float scaledW = scale * (fbW / float(_desktopW));
|
|
float scaledH = scale * (fbH / float(_desktopH));
|
|
_gameRect = Math::Rect2d(
|
|
Math::Vector2d(0.5 - (0.5 * scaledW), 0.5 - (0.5 * scaledH)),
|
|
Math::Vector2d(0.5 + (0.5 * scaledW), 0.5 + (0.5 * scaledH))
|
|
);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (_opengl) {
|
|
if (ConfMan.hasKey("antialiasing"))
|
|
_antialiasing = ConfMan.getInt("antialiasing");
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
|
setAntialiasing(true);
|
|
|
|
sdlflags = SDL_OPENGL;
|
|
bpp = 24;
|
|
} else
|
|
#endif
|
|
{
|
|
bpp = 16;
|
|
sdlflags = SDL_SWSURFACE;
|
|
}
|
|
|
|
if (_fullscreen && !accel3d && _lockAspectRatio) {
|
|
screenW = _desktopW;
|
|
screenH = _desktopH;
|
|
_gameRect = Math::Rect2d(
|
|
Math::Vector2d((_desktopW - fbW) / 2, (_desktopH - fbH) / 2),
|
|
Math::Vector2d((_desktopW + fbW) / 2, (_desktopH + fbH) / 2)
|
|
);
|
|
}
|
|
|
|
if (_fullscreen)
|
|
sdlflags |= SDL_FULLSCREEN;
|
|
|
|
_screen = SDL_SetVideoMode(screenW, screenH, bpp, sdlflags);
|
|
#ifdef USE_OPENGL
|
|
// If 32-bit with antialiasing failed, try 32-bit without antialiasing
|
|
if (!_screen && _opengl && _antialiasing) {
|
|
warning("Couldn't create 32-bit visual with AA, trying 32-bit without AA");
|
|
setAntialiasing(false);
|
|
_screen = SDL_SetVideoMode(screenW, screenH, bpp, sdlflags);
|
|
}
|
|
|
|
// If 32-bit failed, try 16-bit
|
|
if (!_screen && _opengl) {
|
|
warning("Couldn't create 32-bit visual, trying 16-bit");
|
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1);
|
|
setAntialiasing(true);
|
|
_screen = SDL_SetVideoMode(screenW, screenH, 0, sdlflags);
|
|
}
|
|
|
|
// If 16-bit with antialiasing failed, try 16-bit without antialiasing
|
|
if (!_screen && _opengl && _antialiasing) {
|
|
warning("Couldn't create 16-bit visual with AA, trying 16-bit without AA");
|
|
setAntialiasing(false);
|
|
_screen = SDL_SetVideoMode(screenW, screenH, 0, sdlflags);
|
|
}
|
|
|
|
// If 16-bit with alpha failed, try 16-bit without alpha
|
|
if (!_screen && _opengl) {
|
|
warning("Couldn't create 16-bit visual with alpha, trying without alpha");
|
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
|
|
setAntialiasing(true);
|
|
_screen = SDL_SetVideoMode(screenW, screenH, 0, sdlflags);
|
|
}
|
|
|
|
// If 16-bit without alpha and with antialiasing didn't work, try without antialiasing
|
|
if (!_screen && _opengl && _antialiasing) {
|
|
warning("Couldn't create 16-bit visual with AA, trying 16-bit without AA");
|
|
setAntialiasing(false);
|
|
_screen = SDL_SetVideoMode(screenW, screenH, 0, sdlflags);
|
|
}
|
|
#endif
|
|
|
|
if (!_screen) {
|
|
warning("Error: %s", SDL_GetError());
|
|
g_system->quit();
|
|
}
|
|
|
|
#ifdef USE_OPENGL
|
|
if (_opengl) {
|
|
int glflag;
|
|
const GLubyte *str;
|
|
|
|
// apply atribute again for sure based on SDL docs
|
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
|
|
|
str = glGetString(GL_VENDOR);
|
|
debug("INFO: OpenGL Vendor: %s", str);
|
|
str = glGetString(GL_RENDERER);
|
|
debug("INFO: OpenGL Renderer: %s", str);
|
|
str = glGetString(GL_VERSION);
|
|
debug("INFO: OpenGL Version: %s", str);
|
|
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &glflag);
|
|
debug("INFO: OpenGL Red bits: %d", glflag);
|
|
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &glflag);
|
|
debug("INFO: OpenGL Green bits: %d", glflag);
|
|
SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &glflag);
|
|
debug("INFO: OpenGL Blue bits: %d", glflag);
|
|
SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &glflag);
|
|
debug("INFO: OpenGL Alpha bits: %d", glflag);
|
|
SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &glflag);
|
|
debug("INFO: OpenGL Z buffer depth bits: %d", glflag);
|
|
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &glflag);
|
|
debug("INFO: OpenGL Double Buffer: %d", glflag);
|
|
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &glflag);
|
|
debug("INFO: OpenGL Stencil buffer bits: %d", glflag);
|
|
|
|
#ifdef USE_GLEW
|
|
debug("INFO: GLEW Version: %s", glewGetString(GLEW_VERSION));
|
|
GLenum err = glewInit();
|
|
if (err != GLEW_OK) {
|
|
warning("Error: %s", glewGetErrorString(err));
|
|
g_system->quit();
|
|
}
|
|
#endif
|
|
|
|
#ifdef USE_OPENGL_SHADERS
|
|
debug("INFO: GLSL version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
|
|
|
|
const GLfloat vertices[] = {
|
|
0.0, 0.0,
|
|
1.0, 0.0,
|
|
0.0, 1.0,
|
|
1.0, 1.0,
|
|
};
|
|
|
|
// Setup the box shader used to render the overlay
|
|
const char* attributes[] = { "position", "texcoord", NULL };
|
|
_boxShader = OpenGL::Shader::fromStrings("box", OpenGL::BuiltinShaders::boxVertex, OpenGL::BuiltinShaders::boxFragment, attributes);
|
|
_boxVerticesVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices);
|
|
_boxShader->enableVertexAttribute("position", _boxVerticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
|
|
_boxShader->enableVertexAttribute("texcoord", _boxVerticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
|
|
#endif
|
|
|
|
OpenGLContext.initialize(OpenGL::kContextGL);
|
|
|
|
}
|
|
#endif
|
|
|
|
_overlayWidth = screenW;
|
|
_overlayHeight = screenH;
|
|
|
|
#ifdef USE_OPENGL
|
|
if (_opengl) {
|
|
uint32 rmask, gmask, bmask, amask;
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
rmask = 0x00001f00;
|
|
gmask = 0x000007e0;
|
|
bmask = 0x000000f8;
|
|
amask = 0x00000000;
|
|
#else
|
|
rmask = 0x0000f800;
|
|
gmask = 0x000007e0;
|
|
bmask = 0x0000001f;
|
|
amask = 0x00000000;
|
|
#endif
|
|
_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth, _overlayHeight, 16,
|
|
rmask, gmask, bmask, amask);
|
|
_overlayScreenGLFormat = GL_UNSIGNED_SHORT_5_6_5;
|
|
} else
|
|
#endif
|
|
{
|
|
_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth, _overlayHeight, 16,
|
|
_screen->format->Rmask, _screen->format->Gmask, _screen->format->Bmask, _screen->format->Amask);
|
|
}
|
|
|
|
if (!_overlayscreen) {
|
|
warning("Error: %s", SDL_GetError());
|
|
g_system->quit();
|
|
}
|
|
|
|
/*_overlayFormat.bytesPerPixel = _overlayscreen->format->BytesPerPixel;
|
|
|
|
// For some reason the values below aren't right, at least on my system
|
|
_overlayFormat.rLoss = _overlayscreen->format->Rloss;
|
|
_overlayFormat.gLoss = _overlayscreen->format->Gloss;
|
|
_overlayFormat.bLoss = _overlayscreen->format->Bloss;
|
|
_overlayFormat.aLoss = _overlayscreen->format->Aloss;
|
|
|
|
_overlayFormat.rShift = _overlayscreen->format->Rshift;
|
|
_overlayFormat.gShift = _overlayscreen->format->Gshift;
|
|
_overlayFormat.bShift = _overlayscreen->format->Bshift;
|
|
_overlayFormat.aShift = _overlayscreen->format->Ashift;*/
|
|
|
|
_overlayFormat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
|
|
|
|
_screenChangeCount++;
|
|
|
|
SDL_PixelFormat *f = _screen->format;
|
|
_screenFormat = Graphics::PixelFormat(f->BytesPerPixel, 8 - f->Rloss, 8 - f->Gloss, 8 - f->Bloss, 0,
|
|
f->Rshift, f->Gshift, f->Bshift, f->Ashift);
|
|
|
|
#if defined(USE_OPENGL) && !defined(AMIGAOS)
|
|
if (_opengl && _fullscreen
|
|
&& !g_engine->hasFeature(Engine::kSupportsArbitraryResolutions)
|
|
&& framebufferSupported) {
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
_frameBuffer = new OpenGL::FrameBuffer(fbW, fbH);
|
|
_frameBuffer->attach();
|
|
}
|
|
#endif
|
|
if (_fullscreen && !accel3d) {
|
|
_subScreen = SDL_CreateRGBSurface(SDL_SWSURFACE, fbW, fbH, bpp, _screen->format->Rmask, _screen->format->Gmask, _screen->format->Bmask, _screen->format->Amask);
|
|
return Graphics::PixelBuffer(_screenFormat, (byte *)_subScreen->pixels);
|
|
}
|
|
return Graphics::PixelBuffer(_screenFormat, (byte *)_screen->pixels);
|
|
}
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
#define BITMAP_TEXTURE_SIZE 256
|
|
|
|
void SurfaceSdlGraphicsManager::updateOverlayTextures() {
|
|
if (!_overlayscreen)
|
|
return;
|
|
|
|
// remove if already exist
|
|
if (_overlayNumTex > 0) {
|
|
glDeleteTextures(_overlayNumTex, _overlayTexIds);
|
|
delete[] _overlayTexIds;
|
|
_overlayNumTex = 0;
|
|
}
|
|
|
|
_overlayNumTex = ((_overlayWidth + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE) *
|
|
((_overlayHeight + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE);
|
|
_overlayTexIds = new GLuint[_overlayNumTex];
|
|
glGenTextures(_overlayNumTex, _overlayTexIds);
|
|
for (int i = 0; i < _overlayNumTex; i++) {
|
|
glBindTexture(GL_TEXTURE_2D, _overlayTexIds[i]);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, BITMAP_TEXTURE_SIZE, BITMAP_TEXTURE_SIZE, 0, GL_RGB, _overlayScreenGLFormat, NULL);
|
|
}
|
|
|
|
int bpp = _overlayscreen->format->BytesPerPixel;
|
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, bpp);
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, _overlayWidth);
|
|
|
|
int curTexIdx = 0;
|
|
for (int y = 0; y < _overlayHeight; y += BITMAP_TEXTURE_SIZE) {
|
|
for (int x = 0; x < _overlayWidth; x += BITMAP_TEXTURE_SIZE) {
|
|
int t_width = (x + BITMAP_TEXTURE_SIZE >= _overlayWidth) ? (_overlayWidth - x) : BITMAP_TEXTURE_SIZE;
|
|
int t_height = (y + BITMAP_TEXTURE_SIZE >= _overlayHeight) ? (_overlayHeight - y) : BITMAP_TEXTURE_SIZE;
|
|
glBindTexture(GL_TEXTURE_2D, _overlayTexIds[curTexIdx]);
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, t_width, t_height, GL_RGB, _overlayScreenGLFormat,
|
|
(byte *)_overlayscreen->pixels + (y * _overlayscreen->pitch) + (bpp * x));
|
|
curTexIdx++;
|
|
}
|
|
}
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::drawOverlayOpenGL() {
|
|
if (!_overlayscreen)
|
|
return;
|
|
|
|
// Save current state
|
|
glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
|
|
|
|
// prepare view
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0, _overlayWidth, _overlayHeight, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
glDisable(GL_LIGHTING);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDepthMask(GL_FALSE);
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
glScissor(0, 0, _overlayWidth, _overlayHeight);
|
|
|
|
int curTexIdx = 0;
|
|
for (int y = 0; y < _overlayHeight; y += BITMAP_TEXTURE_SIZE) {
|
|
for (int x = 0; x < _overlayWidth; x += BITMAP_TEXTURE_SIZE) {
|
|
glBindTexture(GL_TEXTURE_2D, _overlayTexIds[curTexIdx]);
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(0, 0);
|
|
glVertex2i(x, y);
|
|
glTexCoord2f(1.0f, 0.0f);
|
|
glVertex2i(x + BITMAP_TEXTURE_SIZE, y);
|
|
glTexCoord2f(1.0f, 1.0f);
|
|
glVertex2i(x + BITMAP_TEXTURE_SIZE, y + BITMAP_TEXTURE_SIZE);
|
|
glTexCoord2f(0.0f, 1.0f);
|
|
glVertex2i(x, y + BITMAP_TEXTURE_SIZE);
|
|
glEnd();
|
|
curTexIdx++;
|
|
}
|
|
}
|
|
|
|
// Restore previous state
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
glPopMatrix();
|
|
|
|
glPopAttrib();
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::drawSideTexturesOpenGL() {
|
|
if (_fullscreen && _lockAspectRatio) {
|
|
const Math::Vector2d nudge(1.0 / float(_screen->w), 0);
|
|
if (_sideTextures[0] != nullptr) {
|
|
float left = _gameRect.getBottomLeft().getX() - (float(_screen->h) / float(_sideTextures[0]->getHeight())) * _sideTextures[0]->getWidth() / float(_screen->w);
|
|
drawTexture(*_sideTextures[0], Math::Vector2d(left, 0.0), _gameRect.getBottomLeft() + nudge, true);
|
|
}
|
|
|
|
if (_sideTextures[1] != nullptr) {
|
|
float right = _gameRect.getTopRight().getX() + (float(_screen->h) / float(_sideTextures[1]->getHeight())) * _sideTextures[1]->getWidth() / float(_screen->w);
|
|
drawTexture(*_sideTextures[1], _gameRect.getTopRight() - nudge, Math::Vector2d(right, 1.0), true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::drawTexture(const OpenGL::Texture &tex, const Math::Vector2d &topLeft, const Math::Vector2d &bottomRight, bool flip) {
|
|
#ifndef USE_OPENGL_SHADERS
|
|
// Save current state
|
|
glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
|
|
|
|
// prepare view
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0, 1.0, 1.0, 0, 0, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
glDisable(GL_LIGHTING);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_ALPHA_TEST);
|
|
glDepthMask(GL_FALSE);
|
|
|
|
float texcropX = tex.getWidth() / float(tex.getTexWidth());
|
|
float texcropY = tex.getHeight() / float(tex.getTexHeight());
|
|
float texTop = flip ? 0.0 : texcropY;
|
|
float texBottom = flip ? texcropY : 0.0;
|
|
|
|
float offsetX = topLeft.getX();
|
|
float offsetY = topLeft.getY();
|
|
float sizeX = fabsf(topLeft.getX() - bottomRight.getX());
|
|
float sizeY = fabsf(topLeft.getY() - bottomRight.getY());
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex.getTextureName());
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2f(0, texTop);
|
|
glVertex2f(offsetX, offsetY);
|
|
glTexCoord2f(texcropX, texTop);
|
|
glVertex2f(offsetX + sizeX, offsetY);
|
|
glTexCoord2f(texcropX, texBottom);
|
|
glVertex2f(offsetX + sizeX, offsetY + sizeY);
|
|
glTexCoord2f(0.0, texBottom);
|
|
glVertex2f(offsetX, offsetY + sizeY);
|
|
glEnd();
|
|
|
|
// Restore previous state
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
glPopMatrix();
|
|
|
|
glPopAttrib();
|
|
#else
|
|
glBindTexture(GL_TEXTURE_2D, tex.getTextureName());
|
|
|
|
_boxShader->use();
|
|
float texcropX = tex.getWidth() / float(tex.getTexWidth());
|
|
float texcropY = tex.getHeight() / float(tex.getTexHeight());
|
|
_boxShader->setUniform("texcrop", Math::Vector2d(texcropX, texcropY));
|
|
_boxShader->setUniform("flipY", flip);
|
|
|
|
_boxShader->setUniform("offsetXY", topLeft);
|
|
_boxShader->setUniform("sizeWH", Math::Vector2d(fabsf(topLeft.getX() - bottomRight.getX()), fabsf(topLeft.getY() - bottomRight.getY())));
|
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
_boxShader->unbind();
|
|
#endif
|
|
}
|
|
|
|
#ifdef USE_OPENGL_SHADERS
|
|
void SurfaceSdlGraphicsManager::drawOverlayOpenGLShaders() {
|
|
if (!_overlayscreen)
|
|
return;
|
|
|
|
glDisable(GL_LIGHTING);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDepthMask(GL_FALSE);
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
glScissor(0, 0, _overlayWidth, _overlayHeight);
|
|
|
|
_boxShader->use();
|
|
_boxShader->setUniform("sizeWH", Math::Vector2d(BITMAP_TEXTURE_SIZE / (float)_overlayWidth, BITMAP_TEXTURE_SIZE / (float)_overlayHeight));
|
|
_boxShader->setUniform("flipY", true);
|
|
_boxShader->setUniform("texcrop", Math::Vector2d(1.0, 1.0));
|
|
|
|
int curTexIdx = 0;
|
|
for (int y = 0; y < _overlayHeight; y += BITMAP_TEXTURE_SIZE) {
|
|
for (int x = 0; x < _overlayWidth; x += BITMAP_TEXTURE_SIZE) {
|
|
_boxShader->setUniform("offsetXY", Math::Vector2d(x / (float)_overlayWidth, y / (float)_overlayHeight));
|
|
|
|
glBindTexture(GL_TEXTURE_2D, _overlayTexIds[curTexIdx]);
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
curTexIdx++;
|
|
}
|
|
}
|
|
|
|
_boxShader->unbind();
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
|
|
void SurfaceSdlGraphicsManager::drawSideTextures() {
|
|
if (_fullscreen && _lockAspectRatio) {
|
|
if (_sideSurfaces[0]) {
|
|
SDL_Rect dstrect;
|
|
dstrect.x = _gameRect.getTopLeft().getX() - _sideSurfaces[0]->w;
|
|
dstrect.y = _gameRect.getTopLeft().getY();
|
|
dstrect.w = _sideSurfaces[0]->w;
|
|
dstrect.h = _sideSurfaces[0]->h;
|
|
SDL_BlitSurface(_sideSurfaces[0], NULL, _screen, &dstrect);
|
|
}
|
|
if (_sideSurfaces[1]) {
|
|
SDL_Rect dstrect;
|
|
dstrect.x = _gameRect.getTopRight().getX();
|
|
dstrect.y = _gameRect.getTopLeft().getY();
|
|
dstrect.w = _sideSurfaces[1]->w;
|
|
dstrect.h = _sideSurfaces[1]->h;
|
|
SDL_BlitSurface(_sideSurfaces[1], NULL, _screen, &dstrect);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::drawOverlay() {
|
|
if (!_overlayscreen)
|
|
return;
|
|
|
|
SDL_LockSurface(_screen);
|
|
SDL_LockSurface(_overlayscreen);
|
|
Graphics::PixelBuffer srcBuf(_overlayFormat, (byte *)_overlayscreen->pixels);
|
|
Graphics::PixelBuffer dstBuf(_screenFormat, (byte *)_screen->pixels);
|
|
int h = _overlayHeight;
|
|
|
|
do {
|
|
dstBuf.copyBuffer(0, _overlayWidth, srcBuf);
|
|
|
|
srcBuf.shiftBy(_overlayWidth);
|
|
dstBuf.shiftBy(_overlayWidth);
|
|
} while (--h);
|
|
SDL_UnlockSurface(_screen);
|
|
SDL_UnlockSurface(_overlayscreen);
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::updateScreen() {
|
|
#ifdef USE_OPENGL
|
|
if (_opengl) {
|
|
if (_frameBuffer) {
|
|
_frameBuffer->detach();
|
|
glViewport(0, 0, _screen->w, _screen->h);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
drawSideTexturesOpenGL();
|
|
drawTexture(*_frameBuffer, _gameRect.getTopLeft(), _gameRect.getBottomRight());
|
|
}
|
|
|
|
if (_overlayVisible) {
|
|
if (_overlayDirty) {
|
|
updateOverlayTextures();
|
|
}
|
|
|
|
#ifndef USE_OPENGL_SHADERS
|
|
drawOverlayOpenGL();
|
|
#else
|
|
drawOverlayOpenGLShaders();
|
|
#endif
|
|
}
|
|
|
|
SDL_GL_SwapBuffers();
|
|
|
|
if (_frameBuffer) {
|
|
_frameBuffer->attach();
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
SDL_Rect dstrect;
|
|
dstrect.x = _gameRect.getTopLeft().getX();
|
|
dstrect.y = _gameRect.getTopLeft().getY();
|
|
dstrect.w = _gameRect.getWidth();
|
|
dstrect.h = _gameRect.getHeight();
|
|
SDL_BlitSurface(_subScreen, NULL, _screen, &dstrect);
|
|
if (_overlayVisible) {
|
|
drawOverlay();
|
|
}
|
|
drawSideTextures();
|
|
SDL_Flip(_screen);
|
|
}
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::copyRectToScreen(const void *src, int pitch, int x, int y, int w, int h) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
Graphics::Surface *SurfaceSdlGraphicsManager::lockScreen() {
|
|
return NULL; // ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::unlockScreen() {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::fillScreen(uint32 col) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
int16 SurfaceSdlGraphicsManager::getHeight() {
|
|
// ResidualVM specific
|
|
#ifdef USE_OPENGL
|
|
if (_frameBuffer)
|
|
return _frameBuffer->getHeight();
|
|
else
|
|
#endif
|
|
if (_subScreen)
|
|
return _subScreen->h;
|
|
else
|
|
return _screen->h;
|
|
}
|
|
|
|
int16 SurfaceSdlGraphicsManager::getWidth() {
|
|
// ResidualVM specific
|
|
#ifdef USE_OPENGL
|
|
if (_frameBuffer)
|
|
return _frameBuffer->getWidth();
|
|
else
|
|
#endif
|
|
if (_subScreen)
|
|
return _subScreen->w;
|
|
else
|
|
return _screen->w;
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::setShakePos(int shake_pos) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::setFocusRectangle(const Common::Rect &rect) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::clearFocusRectangle() {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark --- Overlays ---
|
|
#pragma mark -
|
|
|
|
void SurfaceSdlGraphicsManager::showOverlay() {
|
|
if (_overlayVisible)
|
|
return;
|
|
|
|
_overlayVisible = true;
|
|
|
|
clearOverlay();
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::hideOverlay() {
|
|
if (!_overlayVisible)
|
|
return;
|
|
|
|
_overlayVisible = false;
|
|
|
|
clearOverlay();
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::clearOverlay() {
|
|
if (!_overlayscreen)
|
|
return;
|
|
|
|
if (!_overlayVisible)
|
|
return;
|
|
|
|
#ifdef USE_OPENGL
|
|
if (_opengl) {
|
|
SDL_Surface *tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth, _overlayHeight,
|
|
_overlayscreen->format->BytesPerPixel * 8,
|
|
_overlayscreen->format->Rmask, _overlayscreen->format->Gmask,
|
|
_overlayscreen->format->Bmask, _overlayscreen->format->Amask);
|
|
|
|
SDL_LockSurface(tmp);
|
|
SDL_LockSurface(_overlayscreen);
|
|
|
|
glReadPixels(0, 0, _overlayWidth, _overlayHeight, GL_RGB, _overlayScreenGLFormat, tmp->pixels);
|
|
|
|
// Flip pixels vertically
|
|
byte *src = (byte *)tmp->pixels;
|
|
byte *buf = (byte *)_overlayscreen->pixels + (_overlayHeight - 1) * _overlayscreen->pitch;
|
|
int h = _overlayHeight;
|
|
do {
|
|
memcpy(buf, src, _overlayWidth * _overlayscreen->format->BytesPerPixel);
|
|
src += tmp->pitch;
|
|
buf -= _overlayscreen->pitch;
|
|
} while (--h);
|
|
|
|
SDL_UnlockSurface(_overlayscreen);
|
|
SDL_UnlockSurface(tmp);
|
|
|
|
SDL_FreeSurface(tmp);
|
|
} else
|
|
#endif
|
|
{
|
|
SDL_LockSurface(_screen);
|
|
SDL_LockSurface(_overlayscreen);
|
|
Graphics::PixelBuffer srcBuf(_screenFormat, (byte *)_screen->pixels);
|
|
Graphics::PixelBuffer dstBuf(_overlayFormat, (byte *)_overlayscreen->pixels);
|
|
int h = _overlayHeight;
|
|
|
|
do {
|
|
dstBuf.copyBuffer(0, _overlayWidth, srcBuf);
|
|
|
|
srcBuf.shiftBy(_overlayWidth);
|
|
dstBuf.shiftBy(_overlayWidth);
|
|
} while (--h);
|
|
SDL_UnlockSurface(_screen);
|
|
SDL_UnlockSurface(_overlayscreen);
|
|
}
|
|
_overlayDirty = true;
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::setSideTextures(Graphics::Surface *left, Graphics::Surface *right) {
|
|
#ifdef USE_OPENGL
|
|
if (_opengl) {
|
|
delete _sideTextures[0];
|
|
_sideTextures[0] = nullptr;
|
|
delete _sideTextures[1];
|
|
_sideTextures[1] = nullptr;
|
|
if (left) {
|
|
_sideTextures[0] = new OpenGL::Texture(*left);
|
|
}
|
|
if (right) {
|
|
_sideTextures[1] = new OpenGL::Texture(*right);
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
delete _sideSurfaces[0];
|
|
_sideSurfaces[0] = nullptr;
|
|
delete _sideSurfaces[1];
|
|
_sideSurfaces[1] = nullptr;
|
|
if (left) {
|
|
_sideSurfaces[0] = SDL_CreateRGBSurface(SDL_SWSURFACE, left->w, left->h, 32, 0xff << left->format.rShift, 0xff << left->format.gShift, 0xff << left->format.bShift, 0xff << left->format.aShift);
|
|
memcpy(_sideSurfaces[0]->pixels, left->getPixels(), left->w * left->h * 4);
|
|
}
|
|
if (right) {
|
|
_sideSurfaces[1] = SDL_CreateRGBSurface(SDL_SWSURFACE, right->w, right->h, 32, 0xff << right->format.rShift, 0xff << right->format.gShift, 0xff << right->format.bShift, 0xff << right->format.aShift);
|
|
memcpy(_sideSurfaces[1]->pixels, right->getPixels(), right->w * right->h * 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::grabOverlay(void *buf, int pitch) {
|
|
if (_overlayscreen == NULL)
|
|
return;
|
|
|
|
if (SDL_LockSurface(_overlayscreen) == -1)
|
|
error("SDL_LockSurface failed: %s", SDL_GetError());
|
|
|
|
byte *src = (byte *)_overlayscreen->pixels;
|
|
byte *dst = (byte *)buf;
|
|
int h = _overlayHeight;
|
|
do {
|
|
memcpy(dst, src, _overlayWidth * _overlayscreen->format->BytesPerPixel);
|
|
src += _overlayscreen->pitch;
|
|
dst += pitch;
|
|
} while (--h);
|
|
|
|
SDL_UnlockSurface(_overlayscreen);
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
|
|
if (_overlayscreen == NULL)
|
|
return;
|
|
|
|
const byte *src = (const byte *)buf;
|
|
|
|
// Clip the coordinates
|
|
if (x < 0) {
|
|
w += x;
|
|
src -= x * _overlayscreen->format->BytesPerPixel;
|
|
x = 0;
|
|
}
|
|
|
|
if (y < 0) {
|
|
h += y;
|
|
src -= y * pitch;
|
|
y = 0;
|
|
}
|
|
|
|
if (w > _overlayWidth - x) {
|
|
w = _overlayWidth - x;
|
|
}
|
|
|
|
if (h > _overlayHeight - y) {
|
|
h = _overlayHeight - y;
|
|
}
|
|
|
|
if (w <= 0 || h <= 0)
|
|
return;
|
|
|
|
if (SDL_LockSurface(_overlayscreen) == -1)
|
|
error("SDL_LockSurface failed: %s", SDL_GetError());
|
|
|
|
byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * _overlayscreen->format->BytesPerPixel;
|
|
do {
|
|
memcpy(dst, src, w * _overlayscreen->format->BytesPerPixel);
|
|
dst += _overlayscreen->pitch;
|
|
src += pitch;
|
|
} while (--h);
|
|
|
|
SDL_UnlockSurface(_overlayscreen);
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::closeOverlay() {
|
|
SDL_FreeSurface(_sideSurfaces[0]);
|
|
SDL_FreeSurface(_sideSurfaces[1]);
|
|
_sideSurfaces[0] = _sideSurfaces[1] = nullptr;
|
|
#ifdef USE_OPENGL
|
|
delete _sideTextures[0];
|
|
delete _sideTextures[1];
|
|
_sideTextures[0] = _sideTextures[1] = nullptr;
|
|
#endif
|
|
if (_overlayscreen) {
|
|
SDL_FreeSurface(_overlayscreen);
|
|
_overlayscreen = NULL;
|
|
#ifdef USE_OPENGL
|
|
if (_opengl) {
|
|
if (_overlayNumTex > 0) {
|
|
glDeleteTextures(_overlayNumTex, _overlayTexIds);
|
|
delete[] _overlayTexIds;
|
|
_overlayNumTex = 0;
|
|
}
|
|
|
|
if (_frameBuffer) {
|
|
delete _frameBuffer;
|
|
_frameBuffer = nullptr;
|
|
}
|
|
|
|
#ifdef USE_OPENGL_SHADERS
|
|
glDeleteBuffers(1, &_boxVerticesVBO);
|
|
_boxVerticesVBO = 0;
|
|
|
|
delete _boxShader;
|
|
_boxShader = nullptr;
|
|
#endif
|
|
} else if (_subScreen) {
|
|
SDL_FreeSurface(_subScreen);
|
|
_subScreen = nullptr;
|
|
}
|
|
|
|
OpenGL::Context::destroy();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark --- Mouse ---
|
|
#pragma mark -
|
|
|
|
bool SurfaceSdlGraphicsManager::showMouse(bool visible) {
|
|
SDL_ShowCursor(visible);
|
|
return true;
|
|
}
|
|
|
|
// ResidualVM specific method
|
|
bool SurfaceSdlGraphicsManager::lockMouse(bool lock) {
|
|
if (lock)
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
else
|
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
|
return true;
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::warpMouse(int x, int y) {
|
|
//ResidualVM specific
|
|
#ifdef USE_OPENGL
|
|
if (_frameBuffer) {
|
|
// Scale from game coordinates to screen coordinates
|
|
x = (x * _gameRect.getWidth() * _screen->w) / _frameBuffer->getWidth();
|
|
y = (y * _gameRect.getHeight() * _screen->h) / _frameBuffer->getHeight();
|
|
|
|
x += _gameRect.getTopLeft().getX() * _screen->w;
|
|
y += _gameRect.getTopLeft().getY() * _screen->h;
|
|
} else
|
|
#endif
|
|
if (_subScreen) {
|
|
// Scale from game coordinates to screen coordinates
|
|
x = (x * _gameRect.getWidth()) / _subScreen->w;
|
|
y = (y * _gameRect.getHeight()) / _subScreen->h;
|
|
|
|
x += _gameRect.getTopLeft().getX();
|
|
y += _gameRect.getTopLeft().getY();
|
|
}
|
|
|
|
SDL_WarpMouse(x, y);
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
|
|
// ResidualVM: not use it
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark --- On Screen Display ---
|
|
#pragma mark -
|
|
|
|
#ifdef USE_OSD
|
|
void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
|
|
// ResidualVM: not use it
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
void SurfaceSdlGraphicsManager::setAntialiasing(bool enable) {
|
|
// Antialiasing works without setting MULTISAMPLEBUFFERS, but as SDL's official
|
|
// tests set both values, this seems to be the standard way to do it. It could
|
|
// just be that in current OpenGL implementations setting SDL_GL_MULTISAMPLESAMPLES
|
|
// implicitly sets SDL_GL_MULTISAMPLEBUFFERS as well.
|
|
if (_antialiasing && enable) {
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, _antialiasing);
|
|
} else {
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool SurfaceSdlGraphicsManager::notifyEvent(const Common::Event &event) {
|
|
//ResidualVM specific:
|
|
switch ((int)event.type) {
|
|
case Common::EVENT_KEYDOWN:
|
|
break;
|
|
case Common::EVENT_KEYUP:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::notifyVideoExpose() {
|
|
_forceFull = true;
|
|
//ResidualVM specific:
|
|
updateScreen();
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
|
|
bool frames = _subScreen
|
|
#ifdef USE_OPENGL
|
|
|| _frameBuffer
|
|
#endif
|
|
;
|
|
if (_overlayVisible || !frames)
|
|
return;
|
|
|
|
#ifdef USE_OPENGL
|
|
if (_frameBuffer) {
|
|
// Scale from screen coordinates to game coordinates
|
|
point.x -= _gameRect.getTopLeft().getX() * _screen->w;
|
|
point.y -= _gameRect.getTopLeft().getY() * _screen->h;
|
|
|
|
point.x = (point.x * _frameBuffer->getWidth()) / (_gameRect.getWidth() * _screen->w);
|
|
point.y = (point.y * _frameBuffer->getHeight()) / (_gameRect.getHeight() * _screen->h);
|
|
|
|
// Make sure we only supply valid coordinates.
|
|
point.x = CLIP<int16>(point.x, 0, _frameBuffer->getWidth() - 1);
|
|
point.y = CLIP<int16>(point.y, 0, _frameBuffer->getHeight() - 1);
|
|
} else
|
|
#endif
|
|
{
|
|
// Scale from screen coordinates to game coordinates
|
|
point.x -= _gameRect.getTopLeft().getX();
|
|
point.y -= _gameRect.getTopLeft().getY();
|
|
|
|
point.x = (point.x * _subScreen->w) / _gameRect.getWidth();
|
|
point.y = (point.y * _subScreen->h) / _gameRect.getHeight();
|
|
|
|
// Make sure we only supply valid coordinates.
|
|
point.x = CLIP<int16>(point.x, 0, _subScreen->w - 1);
|
|
point.y = CLIP<int16>(point.y, 0, _subScreen->h - 1);
|
|
}
|
|
}
|
|
|
|
void SurfaceSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
|
|
transformMouseCoordinates(mouse);
|
|
// ResidualVM: not use that:
|
|
//setMousePos(mouse.x, mouse.y);
|
|
}
|
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
void SurfaceSdlGraphicsManager::deinitializeRenderer() {
|
|
SDL_DestroyTexture(_screenTexture);
|
|
_screenTexture = nullptr;
|
|
|
|
SDL_DestroyRenderer(_renderer);
|
|
_renderer = nullptr;
|
|
|
|
_window->destroyWindow();
|
|
}
|
|
#endif // SDL_VERSION_ATLEAST(2, 0, 0)
|
|
|
|
#endif
|