diff options
Diffstat (limited to 'backends/graphics/opengl/opengl-graphics.cpp')
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 352 |
1 files changed, 244 insertions, 108 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index c455c4ce2e..c491b03f1f 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -23,8 +23,10 @@ #include "backends/graphics/opengl/opengl-graphics.h" #include "backends/graphics/opengl/texture.h" -#include "backends/graphics/opengl/debug.h" -#include "backends/graphics/opengl/extensions.h" +#include "backends/graphics/opengl/pipelines/pipeline.h" +#include "backends/graphics/opengl/pipelines/fixed.h" +#include "backends/graphics/opengl/pipelines/shader.h" +#include "backends/graphics/opengl/shader.h" #include "common/textconsole.h" #include "common/translation.h" @@ -45,18 +47,21 @@ namespace OpenGL { OpenGLGraphicsManager::OpenGLGraphicsManager() : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)), + _pipeline(nullptr), _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(), _gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr), _overlayVisible(false), _cursor(nullptr), - _cursorX(0), _cursorY(0), _cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotXScaled(0), - _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), _cursorKeyColor(0), - _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false) + _cursorX(0), _cursorY(0), _cursorDisplayX(0),_cursorDisplayY(0), _cursorHotspotX(0), _cursorHotspotY(0), + _cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), + _cursorKeyColor(0), _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false), + _forceRedraw(false), _scissorOverride(3) #ifdef USE_OSD , _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr) #endif { memset(_gamePalette, 0, sizeof(_gamePalette)); + g_context.reset(); } OpenGLGraphicsManager::~OpenGLGraphicsManager() { @@ -66,6 +71,9 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { #ifdef USE_OSD delete _osd; #endif +#if !USE_FORCED_GLES + ShaderManager::destroy(); +#endif } bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { @@ -214,8 +222,8 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { // a context existing before, which means we don't know the maximum // supported texture size before this. Thus, we check whether the // requested game resolution is supported over here. - || ( _currentState.gameWidth > (uint)Texture::getMaximumTextureSize() - || _currentState.gameHeight > (uint)Texture::getMaximumTextureSize())) { + || ( _currentState.gameWidth > (uint)g_context.maxTextureSize + || _currentState.gameHeight > (uint)g_context.maxTextureSize)) { if (_transactionMode == kTransactionActive) { // Try to setup the old state in case its valid and is // actually different from the new one. @@ -266,9 +274,9 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { _gameScreen = nullptr; #ifdef USE_RGB_COLOR - _gameScreen = createTexture(_currentState.gameFormat); + _gameScreen = createSurface(_currentState.gameFormat); #else - _gameScreen = createTexture(Graphics::PixelFormat::createFormatCLUT8()); + _gameScreen = createSurface(Graphics::PixelFormat::createFormatCLUT8()); #endif assert(_gameScreen); if (_gameScreen->hasPalette()) { @@ -343,7 +351,10 @@ void OpenGLGraphicsManager::fillScreen(uint32 col) { } void OpenGLGraphicsManager::setShakePos(int shakeOffset) { - _gameScreenShakeOffset = shakeOffset; + if (_gameScreenShakeOffset != shakeOffset) { + _gameScreenShakeOffset = shakeOffset; + _forceRedraw = true; + } } void OpenGLGraphicsManager::updateScreen() { @@ -351,17 +362,47 @@ void OpenGLGraphicsManager::updateScreen() { return; } - // Clear the screen buffer - GLCALL(glClear(GL_COLOR_BUFFER_BIT)); + // We only update the screen when there actually have been any changes. + if ( !_forceRedraw + && !_gameScreen->isDirty() + && !(_overlayVisible && _overlay->isDirty()) + && !(_cursorVisible && _cursor && _cursor->isDirty()) + && _osdAlpha == 0) { + return; + } + _forceRedraw = false; + + // Update changes to textures. + _gameScreen->updateGLTexture(); + if (_cursor) { + _cursor->updateGLTexture(); + } + _overlay->updateGLTexture(); + _osd->updateGLTexture(); + + // Clear the screen buffer. + if (_scissorOverride && !_overlayVisible) { + // In certain cases we need to assure that the whole screen area is + // cleared. For example, when switching from overlay visible to + // invisible, we need to assure that all contents are cleared to + // properly remove all overlay contents. + _backBuffer.enableScissorTest(false); + GL_CALL(glClear(GL_COLOR_BUFFER_BIT)); + _backBuffer.enableScissorTest(true); + + --_scissorOverride; + } else { + GL_CALL(glClear(GL_COLOR_BUFFER_BIT)); + } const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight(); // First step: Draw the (virtual) game screen. - _gameScreen->draw(_displayX, _displayY + shakeOffset, _displayWidth, _displayHeight); + g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _displayX, _displayY + shakeOffset, _displayWidth, _displayHeight); // Second step: Draw the overlay if visible. if (_overlayVisible) { - _overlay->draw(0, 0, _outputScreenWidth, _outputScreenHeight); + g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _outputScreenWidth, _outputScreenHeight); } // Third step: Draw the cursor if visible. @@ -370,8 +411,10 @@ void OpenGLGraphicsManager::updateScreen() { // visible. const GLfloat cursorOffset = _overlayVisible ? 0 : shakeOffset; - _cursor->draw(_cursorX - _cursorHotspotXScaled, _cursorY - _cursorHotspotYScaled + cursorOffset, - _cursorWidthScaled, _cursorHeightScaled); + g_context.getActivePipeline()->drawTexture(_cursor->getGLTexture(), + _cursorDisplayX - _cursorHotspotXScaled, + _cursorDisplayY - _cursorHotspotYScaled + cursorOffset, + _cursorWidthScaled, _cursorHeightScaled); } #ifdef USE_OSD @@ -392,15 +435,17 @@ void OpenGLGraphicsManager::updateScreen() { } // Set the OSD transparency. - GLCALL(glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f)); + g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f); // Draw the OSD texture. - _osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight); + g_context.getActivePipeline()->drawTexture(_osd->getGLTexture(), 0, 0, _outputScreenWidth, _outputScreenHeight); // Reset color. - GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); + g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, 1.0f); } #endif + + refreshScreen(); } Graphics::Surface *OpenGLGraphicsManager::lockScreen() { @@ -435,10 +480,25 @@ int16 OpenGLGraphicsManager::getOverlayHeight() { void OpenGLGraphicsManager::showOverlay() { _overlayVisible = true; + _forceRedraw = true; + + // Allow drawing inside full screen area. + _backBuffer.enableScissorTest(false); + + // Update cursor position. + setMousePosition(_cursorX, _cursorY); } void OpenGLGraphicsManager::hideOverlay() { _overlayVisible = false; + _forceRedraw = true; + + // Limit drawing to screen area. + _backBuffer.enableScissorTest(true); + _scissorOverride = 3; + + // Update cursor position. + setMousePosition(_cursorX, _cursorY); } Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const { @@ -467,6 +527,12 @@ void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) { } bool OpenGLGraphicsManager::showMouse(bool visible) { + // In case the mouse cursor visibility changed we need to redraw the whole + // screen even when nothing else changed. + if (_cursorVisible != visible) { + _forceRedraw = true; + } + bool last = _cursorVisible; _cursorVisible = visible; return last; @@ -501,11 +567,8 @@ void OpenGLGraphicsManager::warpMouse(int x, int y) { return; } - x = (x * _displayWidth) / _gameScreen->getWidth(); - y = (y * _displayHeight) / _gameScreen->getHeight(); - - x += _displayX; - y += _displayY; + x = (x * _outputScreenWidth) / _gameScreen->getWidth(); + y = (y * _outputScreenHeight) / _gameScreen->getHeight(); } setMousePosition(x, y); @@ -562,7 +625,7 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int } else { textureFormat = _defaultFormatAlpha; } - _cursor = createTexture(textureFormat, true); + _cursor = createSurface(textureFormat, true); assert(_cursor); _cursor->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); } @@ -688,6 +751,31 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { #endif } +void OpenGLGraphicsManager::copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) { +#ifdef USE_OSD + warning("implement copyRectToOSD"); //TODO +#endif +} + +void OpenGLGraphicsManager::clearOSD() { +#ifdef USE_OSD + // HACK: Actually no client code should use graphics functions from + // another thread. But the MT-32 emulator still does, thus we need to + // make sure this doesn't happen while a updateScreen call is done. + Common::StackLock lock(_osdMutex); + + Graphics::Surface *dst = _osd->getSurface(); + _osd->fill(0); + _osd->flagDirty(); + + // Init the OSD display parameters. + _osdAlpha = kOSDInitialAlpha; + _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; +#endif +} + +Graphics::PixelFormat OpenGLGraphicsManager::getOSDFormat() { return Graphics::PixelFormat(); } //TODO + void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { assert(_gameScreen->hasPalette()); @@ -708,18 +796,8 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { _outputScreenWidth = width; _outputScreenHeight = height; - // Setup coordinates system. - GLCALL(glViewport(0, 0, _outputScreenWidth, _outputScreenHeight)); - - GLCALL(glMatrixMode(GL_PROJECTION)); - GLCALL(glLoadIdentity()); -#ifdef USE_GLES - GLCALL(glOrthof(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1)); -#else - GLCALL(glOrtho(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1)); -#endif - GLCALL(glMatrixMode(GL_MODELVIEW)); - GLCALL(glLoadIdentity()); + // Setup backbuffer size. + _backBuffer.setDimensions(width, height); uint overlayWidth = width; uint overlayHeight = height; @@ -730,15 +808,15 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { // possible and then scale it to the physical display size. This sounds // bad but actually all recent chips should support full HD resolution // anyway. Thus, it should not be a real issue for modern hardware. - if ( overlayWidth > (uint)Texture::getMaximumTextureSize() - || overlayHeight > (uint)Texture::getMaximumTextureSize()) { + if ( overlayWidth > (uint)g_context.maxTextureSize + || overlayHeight > (uint)g_context.maxTextureSize) { const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; if (outputAspect > (frac_t)FRAC_ONE) { - overlayWidth = Texture::getMaximumTextureSize(); + overlayWidth = g_context.maxTextureSize; overlayHeight = intToFrac(overlayWidth) / outputAspect; } else { - overlayHeight = Texture::getMaximumTextureSize(); + overlayHeight = g_context.maxTextureSize; overlayWidth = fracToInt(overlayHeight * outputAspect); } } @@ -754,7 +832,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { delete _overlay; _overlay = nullptr; - _overlay = createTexture(_defaultFormatAlpha); + _overlay = createSurface(_defaultFormatAlpha); assert(_overlay); // We always filter the overlay with GL_LINEAR. This assures it's // readable in case it needs to be scaled and does not affect it @@ -769,7 +847,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { delete _osd; _osd = nullptr; - _osd = createTexture(_defaultFormatAlpha); + _osd = createSurface(_defaultFormatAlpha); assert(_osd); // We always filter the osd with GL_LINEAR. This assures it's // readable in case it needs to be scaled and does not affect it @@ -789,39 +867,56 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { } void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) { - // Initialize all extensions. - initializeGLExtensions(); + // Initialize context for use. + initializeGLContext(); + + // Initialize pipeline. + delete _pipeline; + _pipeline = nullptr; + +#if !USE_FORCED_GLES + if (g_context.shadersSupported) { + ShaderMan.notifyCreate(); + _pipeline = new ShaderPipeline(ShaderMan.query(ShaderManager::kDefault)); + } +#endif + +#if !USE_FORCED_GLES2 + if (_pipeline == nullptr) { + _pipeline = new FixedPipeline(); + } +#endif + + g_context.setPipeline(_pipeline); // Disable 3D properties. - GLCALL(glDisable(GL_CULL_FACE)); - GLCALL(glDisable(GL_DEPTH_TEST)); - GLCALL(glDisable(GL_LIGHTING)); - GLCALL(glDisable(GL_FOG)); - GLCALL(glDisable(GL_DITHER)); - GLCALL(glShadeModel(GL_FLAT)); - GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); + GL_CALL(glDisable(GL_CULL_FACE)); + GL_CALL(glDisable(GL_DEPTH_TEST)); + GL_CALL(glDisable(GL_DITHER)); - // Default to black as clear color. - GLCALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); - GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); + g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, 1.0f); + + GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + // Setup backbuffer state. + + // Default to black as clear color. + _backBuffer.setClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Setup alpha blend (for overlay and cursor). - GLCALL(glEnable(GL_BLEND)); - GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + _backBuffer.enableBlend(true); + // Setup scissor state accordingly. + _backBuffer.enableScissorTest(!_overlayVisible); - // Enable rendering with vertex and coord arrays. - GLCALL(glEnableClientState(GL_VERTEX_ARRAY)); - GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + g_context.getActivePipeline()->setFramebuffer(&_backBuffer); - GLCALL(glEnable(GL_TEXTURE_2D)); + // Clear the whole screen for the first three frames to assure any + // leftovers are cleared. + _scissorOverride = 3; // We use a "pack" alignment (when reading from textures) to 4 here, // since the only place where we really use it is the BMP screenshot // code and that requires the same alignment too. - GLCALL(glPixelStorei(GL_PACK_ALIGNMENT, 4)); - - // Query information needed by textures. - Texture::queryTextureInformation(); + GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 4)); // Refresh the output screen dimensions if some are set up. if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { @@ -835,42 +930,56 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def _defaultFormatAlpha = defaultFormatAlpha; if (_gameScreen) { - _gameScreen->recreateInternalTexture(); + _gameScreen->recreate(); } if (_overlay) { - _overlay->recreateInternalTexture(); + _overlay->recreate(); } if (_cursor) { - _cursor->recreateInternalTexture(); + _cursor->recreate(); } #ifdef USE_OSD if (_osd) { - _osd->recreateInternalTexture(); + _osd->recreate(); } #endif } void OpenGLGraphicsManager::notifyContextDestroy() { if (_gameScreen) { - _gameScreen->releaseInternalTexture(); + _gameScreen->destroy(); } if (_overlay) { - _overlay->releaseInternalTexture(); + _overlay->destroy(); } if (_cursor) { - _cursor->releaseInternalTexture(); + _cursor->destroy(); } #ifdef USE_OSD if (_osd) { - _osd->releaseInternalTexture(); + _osd->destroy(); + } +#endif + +#if !USE_FORCED_GLES + if (g_context.shadersSupported) { + ShaderMan.notifyDestroy(); } #endif + + // Destroy rendering pipeline. + g_context.setPipeline(nullptr); + delete _pipeline; + _pipeline = nullptr; + + // Rest our context description since the context is gone soon. + g_context.reset(); } void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { @@ -886,24 +995,42 @@ void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { y = (y * _overlay->getHeight()) / _outputScreenHeight; } } else if (_gameScreen) { - x -= _displayX; - y -= _displayY; - const int16 width = _gameScreen->getWidth(); const int16 height = _gameScreen->getHeight(); - x = (x * width) / _displayWidth; - y = (y * height) / _displayHeight; + x = (x * width) / (int)_outputScreenWidth; + y = (y * height) / (int)_outputScreenHeight; + } +} + +void OpenGLGraphicsManager::setMousePosition(int x, int y) { + // Whenever the mouse position changed we force a screen redraw to reflect + // changes properly. + if (_cursorX != x || _cursorY != y) { + _forceRedraw = true; + } - // Make sure we only supply valid coordinates. - x = CLIP<int16>(x, 0, width - 1); - y = CLIP<int16>(y, 0, height - 1); + _cursorX = x; + _cursorY = y; + + if (_overlayVisible) { + _cursorDisplayX = x; + _cursorDisplayY = y; + } else { + _cursorDisplayX = _displayX + (x * _displayWidth) / _outputScreenWidth; + _cursorDisplayY = _displayY + (y * _displayHeight) / _outputScreenHeight; } } -Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &format, bool wantAlpha) { +Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &format, bool wantAlpha) { GLenum glIntFormat, glFormat, glType; if (format.bytesPerPixel == 1) { +#if !USE_FORCED_GLES + if (TextureCLUT8GPU::isSupportedByContext()) { + return new TextureCLUT8GPU(); + } +#endif + const Graphics::PixelFormat &virtFormat = wantAlpha ? _defaultFormatAlpha : _defaultFormat; const bool supported = getGLPixelFormat(virtFormat, glIntFormat, glFormat, glType); if (!supported) { @@ -911,6 +1038,15 @@ Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &forma } else { return new TextureCLUT8(glIntFormat, glFormat, glType, virtFormat); } +#if !USE_FORCED_GL + } else if (isGLESContext() && format == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { + // OpenGL ES does not support a texture format usable for RGB555. + // Since SCUMM uses this pixel format for some games (and there is no + // hope for this to change anytime soon) we use pixel format + // conversion to a supported texture format. However, this is a one + // time exception. + return new TextureRGB555(); +#endif // !USE_FORCED_GL } else { const bool supported = getGLPixelFormat(format, glIntFormat, glFormat, glType); if (!supported) { @@ -946,7 +1082,11 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4; return true; -#ifndef USE_GLES +#if !USE_FORCED_GLES && !USE_FORCED_GLES2 + // The formats below are not supported by every GLES implementation. + // Thus, we do not mark them as supported when a GLES context is setup. + } else if (isGLESContext()) { + return false; #ifdef SCUMM_LITTLE_ENDIAN } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 glIntFormat = GL_RGBA; @@ -955,17 +1095,10 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF return true; #endif } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 - // GL_BGRA does not exist in every GLES implementation so should not be configured if - // USE_GLES is set. glIntFormat = GL_RGB; glFormat = GL_BGRA; glType = GL_UNSIGNED_SHORT_1_5_5_5_REV; return true; - } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)) { // ARGB8888 - glIntFormat = GL_RGBA; - glFormat = GL_BGRA; - glType = GL_UNSIGNED_INT_8_8_8_8_REV; - return true; } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)) { // ARGB4444 glIntFormat = GL_RGBA; glFormat = GL_BGRA; @@ -985,8 +1118,8 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)) { // BGR565 glIntFormat = GL_RGB; - glFormat = GL_BGR; - glType = GL_UNSIGNED_SHORT_5_6_5; + glFormat = GL_RGB; + glType = GL_UNSIGNED_SHORT_5_6_5_REV; return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0)) { // BGRA5551 glIntFormat = GL_RGBA; @@ -1003,7 +1136,7 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF glFormat = GL_BGRA; glType = GL_UNSIGNED_SHORT_4_4_4_4; return true; -#endif +#endif // !USE_FORCED_GLES && !USE_FORCED_GLES2 } else { return false; } @@ -1046,6 +1179,22 @@ void OpenGLGraphicsManager::recalculateDisplayArea() { // We center the screen in the middle for now. _displayX = (_outputScreenWidth - _displayWidth ) / 2; _displayY = (_outputScreenHeight - _displayHeight) / 2; + + // Setup drawing limitation for game graphics. + // This invovles some trickery because OpenGL's viewport coordinate system + // is upside down compared to ours. + _backBuffer.setScissorBox(_displayX, + _outputScreenHeight - _displayHeight - _displayY, + _displayWidth, + _displayHeight); + // Clear the whole screen for the first three frames to remove leftovers. + _scissorOverride = 3; + + // Update the cursor position to adjust for new display area. + setMousePosition(_cursorX, _cursorY); + + // Force a redraw to assure screen is properly redrawn. + _forceRedraw = true; } void OpenGLGraphicsManager::updateCursorPalette() { @@ -1059,20 +1208,7 @@ void OpenGLGraphicsManager::updateCursorPalette() { _cursor->setPalette(0, 256, _gamePalette); } - // We remove all alpha bits from the palette entry of the color key. - // This makes sure its properly handled as color key. - const Graphics::PixelFormat &hardwareFormat = _cursor->getHardwareFormat(); - const uint32 aMask = (0xFF >> hardwareFormat.aLoss) << hardwareFormat.aShift; - - if (hardwareFormat.bytesPerPixel == 2) { - uint16 *palette = (uint16 *)_cursor->getPalette() + _cursorKeyColor; - *palette &= ~aMask; - } else if (hardwareFormat.bytesPerPixel == 4) { - uint32 *palette = (uint32 *)_cursor->getPalette() + _cursorKeyColor; - *palette &= ~aMask; - } else { - warning("OpenGLGraphicsManager::updateCursorPalette: Unsupported pixel depth %d", hardwareFormat.bytesPerPixel); - } + _cursor->setColorKey(_cursorKeyColor); } void OpenGLGraphicsManager::recalculateCursorScaling() { @@ -1122,7 +1258,7 @@ void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const uint8 *pixels = new uint8[lineSize * height]; // Get pixel data from OpenGL buffer - GLCALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels)); + GL_CALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels)); // BMP stores as BGR. Since we can't assume that GL_BGR is supported we // will swap the components from the RGB we read to BGR on our own. |