diff options
Diffstat (limited to 'backends/graphics/opengl/opengl-graphics.cpp')
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 225 |
1 files changed, 155 insertions, 70 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 4d6a00a3b3..7b41699e80 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -57,7 +57,8 @@ OpenGLGraphicsManager::OpenGLGraphicsManager() _cursorKeyColor(0), _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false), _forceRedraw(false), _scissorOverride(3) #ifdef USE_OSD - , _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr) + , _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr), + _osdIconSurface(nullptr) #endif { memset(_gamePalette, 0, sizeof(_gamePalette)); @@ -69,7 +70,8 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { delete _overlay; delete _cursor; #ifdef USE_OSD - delete _osd; + delete _osdMessageSurface; + delete _osdIconSurface; #endif #if !USE_FORCED_GLES ShaderManager::destroy(); @@ -80,6 +82,7 @@ bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { switch (f) { case OSystem::kFeatureAspectRatioCorrection: case OSystem::kFeatureCursorPalette: + case OSystem::kFeatureFilteringMode: return true; case OSystem::kFeatureOverlaySupportsAlpha: @@ -97,6 +100,20 @@ void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { _currentState.aspectRatioCorrection = enable; break; + case OSystem::kFeatureFilteringMode: + assert(_transactionMode != kTransactionNone); + _currentState.filtering = enable; + + if (_gameScreen) { + _gameScreen->enableLinearFiltering(enable); + } + + if (_cursor) { + _cursor->enableLinearFiltering(enable); + } + + break; + case OSystem::kFeatureCursorPalette: _cursorPaletteEnabled = enable; updateCursorPalette(); @@ -112,6 +129,9 @@ bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { case OSystem::kFeatureAspectRatioCorrection: return _currentState.aspectRatioCorrection; + case OSystem::kFeatureFilteringMode: + return _currentState.filtering; + case OSystem::kFeatureCursorPalette: return _cursorPaletteEnabled; @@ -123,8 +143,7 @@ bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { namespace { const OSystem::GraphicsMode glGraphicsModes[] = { - { "opengl_linear", _s("OpenGL"), GFX_LINEAR }, - { "opengl_nearest", _s("OpenGL (No filtering)"), GFX_NEAREST }, + { "opengl", _s("OpenGL"), GFX_OPENGL }, { nullptr, nullptr, 0 } }; @@ -135,25 +154,15 @@ const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() } int OpenGLGraphicsManager::getDefaultGraphicsMode() const { - return GFX_LINEAR; + return GFX_OPENGL; } bool OpenGLGraphicsManager::setGraphicsMode(int mode) { assert(_transactionMode != kTransactionNone); switch (mode) { - case GFX_LINEAR: - case GFX_NEAREST: + case GFX_OPENGL: _currentState.graphicsMode = mode; - - if (_gameScreen) { - _gameScreen->enableLinearFiltering(mode == GFX_LINEAR); - } - - if (_cursor) { - _cursor->enableLinearFiltering(mode == GFX_LINEAR); - } - return true; default: @@ -248,6 +257,10 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { transactionError |= OSystem::kTransactionModeSwitchFailed; } + if (_oldState.filtering != _currentState.filtering) { + transactionError |= OSystem::kTransactionFilteringFailed; + } + // Roll back to the old state. _currentState = _oldState; _transactionMode = kTransactionRollback; @@ -284,7 +297,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { } _gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight); - _gameScreen->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + _gameScreen->enableLinearFiltering(_currentState.filtering); // We fill the screen to all black or index 0 for CLUT8. #ifdef USE_RGB_COLOR if (_currentState.gameFormat.bytesPerPixel == 1) { @@ -362,12 +375,27 @@ void OpenGLGraphicsManager::updateScreen() { return; } +#ifdef USE_OSD + { + if (_osdMessageChangeRequest) { + osdMessageUpdateSurface(); + } + } + + if (_osdIconSurface) { + _osdIconSurface->updateGLTexture(); + } +#endif + // 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) { +#ifdef USE_OSD + && !_osdMessageSurface && !_osdIconSurface +#endif + ) { return; } _forceRedraw = false; @@ -378,7 +406,6 @@ void OpenGLGraphicsManager::updateScreen() { _cursor->updateGLTexture(); } _overlay->updateGLTexture(); - _osd->updateGLTexture(); // Clear the screen buffer. if (_scissorOverride && !_overlayVisible) { @@ -419,29 +446,45 @@ void OpenGLGraphicsManager::updateScreen() { #ifdef USE_OSD // Fourth step: Draw the OSD. - if (_osdAlpha > 0) { - Common::StackLock lock(_osdMutex); - + if (_osdMessageSurface) { // Update alpha value. - const int diff = g_system->getMillis(false) - _osdFadeStartTime; + const int diff = g_system->getMillis(false) - _osdMessageFadeStartTime; if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { + if (diff >= kOSDMessageFadeOutDuration) { // Back to full transparency. - _osdAlpha = 0; + _osdMessageAlpha = 0; } else { // Do a fade out. - _osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration; + _osdMessageAlpha = kOSDMessageInitialAlpha - diff * kOSDMessageInitialAlpha / kOSDMessageFadeOutDuration; } } // Set the OSD transparency. - g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f); + g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f); + + int dstX = (_outputScreenWidth - _osdMessageSurface->getWidth()) / 2; + int dstY = (_outputScreenHeight - _osdMessageSurface->getHeight()) / 2; // Draw the OSD texture. - g_context.getActivePipeline()->drawTexture(_osd->getGLTexture(), 0, 0, _outputScreenWidth, _outputScreenHeight); + g_context.getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(), + dstX, dstY, _osdMessageSurface->getWidth(), _osdMessageSurface->getHeight()); // Reset color. g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, 1.0f); + + if (_osdMessageAlpha <= 0) { + delete _osdMessageSurface; + _osdMessageSurface = nullptr; + } + } + + if (_osdIconSurface) { + int dstX = _outputScreenWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin; + int dstY = kOSDIconTopMargin; + + // Draw the OSD icon texture. + g_context.getActivePipeline()->drawTexture(_osdIconSurface->getGLTexture(), + dstX, dstY, _osdIconSurface->getWidth(), _osdIconSurface->getHeight()); } #endif @@ -627,7 +670,7 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int } _cursor = createSurface(textureFormat, true); assert(_cursor); - _cursor->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + _cursor->enableLinearFiltering(_currentState.filtering); } _cursorKeyColor = keycolor; @@ -697,57 +740,107 @@ void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uin void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { #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); + _osdMessageChangeRequest = true; + + _osdMessageNextData = msg; +#endif +} - // Slip up the lines. +#ifdef USE_OSD +void OpenGLGraphicsManager::osdMessageUpdateSurface() { + // Split up the lines. Common::Array<Common::String> osdLines; - Common::StringTokenizer tokenizer(msg, "\n"); + Common::StringTokenizer tokenizer(_osdMessageNextData, "\n"); while (!tokenizer.empty()) { osdLines.push_back(tokenizer.nextToken()); } // Do the actual drawing like the SDL backend. const Graphics::Font *font = getFontOSD(); - Graphics::Surface *dst = _osd->getSurface(); - _osd->fill(0); - _osd->flagDirty(); // Determine a rect which would contain the message string (clipped to the // screen dimensions). const int vOffset = 6; const int lineSpacing = 1; const int lineHeight = font->getFontHeight() + 2 * lineSpacing; - int width = 0; - int height = lineHeight * osdLines.size() + 2 * vOffset; + uint width = 0; + uint height = lineHeight * osdLines.size() + 2 * vOffset; for (uint i = 0; i < osdLines.size(); i++) { - width = MAX(width, font->getStringWidth(osdLines[i]) + 14); + width = MAX<uint>(width, font->getStringWidth(osdLines[i]) + 14); } // Clip the rect - width = MIN<int>(width, dst->w); - height = MIN<int>(height, dst->h); + width = MIN<uint>(width, _displayWidth); + height = MIN<uint>(height, _displayHeight); + + delete _osdMessageSurface; + _osdMessageSurface = nullptr; + + _osdMessageSurface = createSurface(_defaultFormatAlpha); + assert(_osdMessageSurface); + // 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 + // otherwise. + _osdMessageSurface->enableLinearFiltering(true); - int dstX = (dst->w - width) / 2; - int dstY = (dst->h - height) / 2; + _osdMessageSurface->allocate(width, height); + + Graphics::Surface *dst = _osdMessageSurface->getSurface(); // Draw a dark gray rect. const uint32 color = dst->format.RGBToColor(40, 40, 40); - dst->fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color); + dst->fillRect(Common::Rect(0, 0, width, height), color); - // Render the message, centered, and in white + // Render the message in white const uint32 white = dst->format.RGBToColor(255, 255, 255); for (uint i = 0; i < osdLines.size(); ++i) { font->drawString(dst, osdLines[i], - dstX, dstY + i * lineHeight + vOffset + lineSpacing, width, + 0, i * lineHeight + vOffset + lineSpacing, width, white, Graphics::kTextAlignCenter); } + _osdMessageSurface->updateGLTexture(); + // Init the OSD display parameters. - _osdAlpha = kOSDInitialAlpha; - _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; + _osdMessageAlpha = kOSDMessageInitialAlpha; + _osdMessageFadeStartTime = g_system->getMillis() + kOSDMessageFadeOutDelay; + + // Clear the text update request + _osdMessageNextData.clear(); + _osdMessageChangeRequest = false; +} +#endif + +void OpenGLGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface *icon) { +#ifdef USE_OSD + if (_osdIconSurface) { + delete _osdIconSurface; + _osdIconSurface = nullptr; + + // Make sure the icon is cleared on the next update + _forceRedraw = true; + } + + if (icon) { + Graphics::Surface *converted = icon->convertTo(_defaultFormatAlpha); + + _osdIconSurface = createSurface(_defaultFormatAlpha); + assert(_osdIconSurface); + // 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 + // otherwise. + _osdIconSurface->enableLinearFiltering(true); + + _osdIconSurface->allocate(converted->w, converted->h); + + Graphics::Surface *dst = _osdIconSurface->getSurface(); + + // Copy the icon to the texture + dst->copyRectToSurface(*converted, 0, 0, Common::Rect(0, 0, converted->w, converted->h)); + + converted->free(); + delete converted; + } #endif } @@ -817,22 +910,6 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { _overlay->allocate(overlayWidth, overlayHeight); _overlay->fill(0); -#ifdef USE_OSD - if (!_osd || _osd->getFormat() != _defaultFormatAlpha) { - delete _osd; - _osd = nullptr; - - _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 - // otherwise. - _osd->enableLinearFiltering(true); - } - _osd->allocate(_overlay->getWidth(), _overlay->getHeight()); - _osd->fill(0); -#endif - // Re-setup the scaling for the screen and cursor recalculateDisplayArea(); recalculateCursorScaling(); @@ -917,8 +994,12 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def } #ifdef USE_OSD - if (_osd) { - _osd->recreate(); + if (_osdMessageSurface) { + _osdMessageSurface->recreate(); + } + + if (_osdIconSurface) { + _osdIconSurface->recreate(); } #endif } @@ -937,8 +1018,12 @@ void OpenGLGraphicsManager::notifyContextDestroy() { } #ifdef USE_OSD - if (_osd) { - _osd->destroy(); + if (_osdMessageSurface) { + _osdMessageSurface->destroy(); + } + + if (_osdIconSurface) { + _osdIconSurface->destroy(); } #endif |