From 521ba2cb8ac6cbe4240ad4da7ad44d13449e3943 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Tue, 13 Sep 2016 20:25:13 +0200 Subject: OSYSTEM: Introduce a method allowing to draw a background activity icon --- backends/graphics/graphics.h | 1 + backends/modular-backend.cpp | 4 ++++ backends/modular-backend.h | 1 + common/system.h | 19 +++++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 921dfca61c..271a482032 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -87,6 +87,7 @@ public: virtual void copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) {} virtual void clearOSD() {} virtual Graphics::PixelFormat getOSDFormat() { return Graphics::PixelFormat(); } + virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) {} // Graphics::PaletteManager interface diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index e1bdf15571..13db277a75 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -253,6 +253,10 @@ Graphics::PixelFormat ModularBackend::getOSDFormat() { return _graphicsManager->getOSDFormat(); } +void ModularBackend::displayActivityIconOnOSD(const Graphics::Surface *icon) { + _graphicsManager->displayActivityIconOnOSD(icon); +} + void ModularBackend::quit() { exit(0); } diff --git a/backends/modular-backend.h b/backends/modular-backend.h index 9cde27915f..886f91c320 100644 --- a/backends/modular-backend.h +++ b/backends/modular-backend.h @@ -130,6 +130,7 @@ public: virtual void copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h); virtual void clearOSD(); virtual Graphics::PixelFormat getOSDFormat(); + virtual void displayActivityIconOnOSD(const Graphics::Surface *icon); //@} diff --git a/common/system.h b/common/system.h index eb9a39bbdf..b07a5ffd1e 100644 --- a/common/system.h +++ b/common/system.h @@ -1101,6 +1101,25 @@ public: */ virtual void displayMessageOnOSD(const char *msg) = 0; + /** + * Display an icon indicating background activity + * + * The icon is displayed in an 'on screen display'. It is visible above + * the regular screen content or near it. + * + * The caller keeps ownership of the icon. It is acceptable to free + * the surface just after the call. + * + * There is no preferred pixel format for the icon. The backend should + * convert its copy of the icon to an appropriate format. + * + * The caller must call this method again with a null pointer + * as a parameter to indicate the icon should no longer be displayed. + * + * @param icon the icon to display on screen + */ + virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) = 0; + /** * Blit a bitmap to the 'on screen display'. * -- cgit v1.2.3 From 4d68b93abacf78dae480a52e242a0644896e5101 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Tue, 13 Sep 2016 20:29:09 +0200 Subject: CLOUD: Switch to the new OSD API --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 1 + backends/cloud/googledrive/googledrivestorage.cpp | 1 + backends/networking/curl/cloudicon.cpp | 46 +++++++--------------- backends/networking/curl/cloudicon.h | 8 ++-- 4 files changed, 20 insertions(+), 36 deletions(-) diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 3c31ddba73..0b90ec6d2c 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -27,6 +27,7 @@ #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" #include "common/json.h" +#include "common/debug.h" namespace Cloud { namespace Dropbox { diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index f4a6fba10f..ec4c84400c 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -33,6 +33,7 @@ #include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" +#include "common/debug.h" #include #ifdef ENABLE_RELEASE diff --git a/backends/networking/curl/cloudicon.cpp b/backends/networking/curl/cloudicon.cpp index 3ae6fd225e..9aa08af9fb 100644 --- a/backends/networking/curl/cloudicon.cpp +++ b/backends/networking/curl/cloudicon.cpp @@ -39,7 +39,11 @@ CloudIcon::CloudIcon(): initIcons(); } -CloudIcon::~CloudIcon() {} +CloudIcon::~CloudIcon() { + _icon.free(); + _disabledIcon.free(); + _alphaIcon.free(); +} bool CloudIcon::draw() { bool stop = false; @@ -48,7 +52,6 @@ bool CloudIcon::draw() { if (CloudMan.isWorking() || _disabledFrames > 0) { if (g_system) { if (!_wasVisible) { - g_system->clearOSD(); _wasVisible = true; } --_disabledFrames; @@ -81,13 +84,11 @@ bool CloudIcon::draw() { } if (g_system) { - Graphics::TransparentSurface *surface = &_icon; - makeAlphaIcon((_showingDisabled ? _disabledIcon : _icon), _currentAlpha); - if (_alphaIcon.getPixels()) - surface = &_alphaIcon; - if (surface && surface->getPixels()) { - int x = g_system->getOverlayWidth() - surface->w - 10, y = 10; - g_system->copyRectToOSD(surface->getPixels(), surface->pitch, x, y, surface->w, surface->h); + if (!stop) { + makeAlphaIcon((_showingDisabled ? _disabledIcon : _icon), _currentAlpha); + g_system->displayActivityIconOnOSD(&_alphaIcon); + } else { + g_system->displayActivityIconOnOSD(nullptr); } } @@ -112,36 +113,17 @@ void CloudIcon::initIcons() { _iconsInited = true; } -void CloudIcon::loadIcon(Graphics::TransparentSurface &icon, byte *data, uint32 size) { +void CloudIcon::loadIcon(Graphics::Surface &icon, byte *data, uint32 size) { Image::PNGDecoder decoder; Common::MemoryReadStream stream(data, size); if (!decoder.loadStream(stream)) error("CloudIcon::loadIcon: error decoding PNG"); - Graphics::TransparentSurface *s = new Graphics::TransparentSurface(*decoder.getSurface(), true); - if (s) { - Graphics::PixelFormat f = g_system->getOSDFormat(); - if (f != s->format) { - // Graphics::TransparentSurface::convertTo(f) errors out if the format is not 2Bpp or 4Bpp. - // We don't need to error out as we can recover from it. So check the format before calling convertTo(f); - Graphics::TransparentSurface *s2 = nullptr; - if (f.bytesPerPixel == 2 || f.bytesPerPixel == 4) - s2 = s->convertTo(f); - if (s2) - icon.copyFrom(*s2); - else - warning("CloudIcon::loadIcon: failed converting TransparentSurface"); - delete s2; - } else { - icon.copyFrom(*s); - } - delete s; - } else { - warning("CloudIcon::loadIcon: failed reading TransparentSurface from PNGDecoder"); - } + const Graphics::Surface *s = decoder.getSurface(); + return icon.copyFrom(*s); } -void CloudIcon::makeAlphaIcon(Graphics::TransparentSurface &icon, float alpha) { +void CloudIcon::makeAlphaIcon(Graphics::Surface &icon, float alpha) { _alphaIcon.copyFrom(icon); byte *pixels = (byte *)_alphaIcon.getPixels(); diff --git a/backends/networking/curl/cloudicon.h b/backends/networking/curl/cloudicon.h index 316cb67370..d6ea60bd51 100644 --- a/backends/networking/curl/cloudicon.h +++ b/backends/networking/curl/cloudicon.h @@ -23,7 +23,7 @@ #ifndef BACKENDS_NETWORKING_CURL_CLOUDICON_H #define BACKENDS_NETWORKING_CURL_CLOUDICON_H -#include "graphics/transparent_surface.h" +#include "graphics/surface.h" namespace Networking { @@ -31,14 +31,14 @@ class CloudIcon { static const float ALPHA_STEP, ALPHA_MAX, ALPHA_MIN; bool _wasVisible, _iconsInited, _showingDisabled; - Graphics::TransparentSurface _icon, _disabledIcon, _alphaIcon; + Graphics::Surface _icon, _disabledIcon, _alphaIcon; float _currentAlpha; bool _alphaRising; int _disabledFrames; void initIcons(); - void loadIcon(Graphics::TransparentSurface &icon, byte *data, uint32 size); - void makeAlphaIcon(Graphics::TransparentSurface &icon, float alpha); + void loadIcon(Graphics::Surface &icon, byte *data, uint32 size); + void makeAlphaIcon(Graphics::Surface &icon, float alpha); public: CloudIcon(); -- cgit v1.2.3 From 05bc82b6225f79ad42e6259be8e227aed6e7c0dc Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Tue, 13 Sep 2016 20:33:42 +0200 Subject: SDL: Switch the surface renderer to use small surfaces for OSD drawing --- backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp | 39 +-- backends/graphics/gph/gph-graphics.cpp | 40 +-- .../linuxmotosdl/linuxmotosdl-graphics.cpp | 40 +-- .../graphics/surfacesdl/surfacesdl-graphics.cpp | 330 ++++++++------------- backends/graphics/surfacesdl/surfacesdl-graphics.h | 23 +- 5 files changed, 149 insertions(+), 323 deletions(-) diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp index 0938be2d4e..9e75dd10f4 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp @@ -257,38 +257,6 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { _forceFull = true; } -#ifdef USE_OSD - // OSD visible (i.e. non-transparent)? - if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) { - // Updated alpha value - const int diff = SDL_GetTicks() - _osdMessageFadeStartTime; - if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { - // Back to full transparency - _osdMessageAlpha = SDL_ALPHA_TRANSPARENT; - } else { - // Do a linear fade out... - const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; - _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration; - } - _forceFull = true; - } - - if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) { - removeOSDMessage(); - } else { - if (_osdMessageSurface && _osdSurface) { - SDL_Rect dstRect; - dstRect.x = (_osdSurface->w - _osdMessageSurface->w) / 2; - dstRect.y = (_osdSurface->h - _osdMessageSurface->h) / 2; - dstRect.w = _osdMessageSurface->w; - dstRect.h = _osdMessageSurface->h; - blitOSDMessage(dstRect); - } - } - } -#endif - if (!_overlayVisible) { origSurf = _screen; srcSurf = _tmpscreen; @@ -310,6 +278,10 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { if (_mouseNeedsRedraw) undrawMouse(); +#ifdef USE_OSD + updateOSD(); +#endif + // Force a full redraw if requested if (_forceFull) { _numDirtyRects = 1; @@ -417,8 +389,7 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { drawMouse(); #ifdef USE_OSD - if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) - SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0); + drawOSD(); #endif // Finally, blit all our changes to the screen SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); diff --git a/backends/graphics/gph/gph-graphics.cpp b/backends/graphics/gph/gph-graphics.cpp index bd0f246286..a19512110f 100644 --- a/backends/graphics/gph/gph-graphics.cpp +++ b/backends/graphics/gph/gph-graphics.cpp @@ -277,38 +277,6 @@ void GPHGraphicsManager::internUpdateScreen() { _forceFull = true; } -#ifdef USE_OSD - // OSD visible (i.e. non-transparent)? - if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) { - // Updated alpha value - const int diff = SDL_GetTicks() - _osdMessageFadeStartTime; - if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { - // Back to full transparency - _osdMessageAlpha = SDL_ALPHA_TRANSPARENT; - } else { - // Do a linear fade out... - const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; - _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration; - } - _forceFull = true; - } - - if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) { - removeOSDMessage(); - } else { - if (_osdMessageSurface && _osdSurface) { - SDL_Rect dstRect; - dstRect.x = (_osdSurface->w - _osdMessageSurface->w) / 2; - dstRect.y = (_osdSurface->h - _osdMessageSurface->h) / 2; - dstRect.w = _osdMessageSurface->w; - dstRect.h = _osdMessageSurface->h; - blitOSDMessage(dstRect); - } - } - } -#endif - if (!_overlayVisible) { origSurf = _screen; srcSurf = _tmpscreen; @@ -331,6 +299,10 @@ void GPHGraphicsManager::internUpdateScreen() { if (_mouseNeedsRedraw) undrawMouse(); +#ifdef USE_OSD + updateOSD(); +#endif + // Force a full redraw if requested if (_forceFull) { _numDirtyRects = 1; @@ -440,9 +412,9 @@ void GPHGraphicsManager::internUpdateScreen() { drawMouse(); #ifdef USE_OSD - if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) - SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0); + drawOSD(); #endif + // Finally, blit all our changes to the screen SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); } diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp index a69cba24ee..6a920e9eae 100644 --- a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp @@ -290,38 +290,6 @@ void LinuxmotoSdlGraphicsManager::internUpdateScreen() { _forceFull = true; } -#ifdef USE_OSD - // OSD visible (i.e. non-transparent)? - if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) { - // Updated alpha value - const int diff = SDL_GetTicks() - _osdMessageFadeStartTime; - if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { - // Back to full transparency - _osdMessageAlpha = SDL_ALPHA_TRANSPARENT; - } else { - // Do a linear fade out... - const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; - _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration; - } - _forceFull = true; - } - - if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) { - removeOSDMessage(); - } else { - if (_osdMessageSurface && _osdSurface) { - SDL_Rect dstRect; - dstRect.x = (_osdSurface->w - _osdMessageSurface->w) / 2; - dstRect.y = (_osdSurface->h - _osdMessageSurface->h) / 2; - dstRect.w = _osdMessageSurface->w; - dstRect.h = _osdMessageSurface->h; - blitOSDMessage(dstRect); - } - } - } -#endif - if (!_overlayVisible) { origSurf = _screen; srcSurf = _tmpscreen; @@ -343,6 +311,10 @@ void LinuxmotoSdlGraphicsManager::internUpdateScreen() { if (_mouseNeedsRedraw) undrawMouse(); +#ifdef USE_OSD + updateOSD(); +#endif + // Force a full redraw if requested if (_forceFull) { _numDirtyRects = 1; @@ -451,9 +423,9 @@ void LinuxmotoSdlGraphicsManager::internUpdateScreen() { drawMouse(); #ifdef USE_OSD - if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) - SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0); + drawOSD(); #endif + // Finally, blit all our changes to the screen SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); } diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index f4a466d740..cd89440929 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -121,7 +121,8 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou : SdlGraphicsManager(sdlEventSource, window), #ifdef USE_OSD - _osdSurface(0), _osdMessageSurface(nullptr), _osdMessageAlpha(SDL_ALPHA_TRANSPARENT), _osdMessageFadeStartTime(0), + _osdMessageSurface(nullptr), _osdMessageAlpha(SDL_ALPHA_TRANSPARENT), _osdMessageFadeStartTime(0), + _osdIconSurface(nullptr), #endif _hwscreen(0), #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -879,23 +880,6 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { if (_tmpscreen2 == NULL) error("allocating _tmpscreen2 failed"); -#ifdef USE_OSD - _osdSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, - _hwscreen->w, - _hwscreen->h, - 32, - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF - ); - if (_osdSurface == NULL) - error("allocating _osdSurface failed"); - - _osdFormat = getSurfaceFormat(_osdSurface); - SDL_SetColorKey(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOSDColorKey); -#endif - #if !SDL_VERSION_ATLEAST(2, 0, 0) // For SDL2 the output resolution might differ from the requested // resolution. We handle resetting the keyboard emulation properly inside @@ -945,15 +929,15 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() { } #ifdef USE_OSD - if (_osdSurface) { - SDL_FreeSurface(_osdSurface); - _osdSurface = NULL; - } - if (_osdMessageSurface) { SDL_FreeSurface(_osdMessageSurface); _osdMessageSurface = NULL; } + + if (_osdIconSurface) { + SDL_FreeSurface(_osdIconSurface); + _osdIconSurface = NULL; + } #endif DestroyScalers(); @@ -983,11 +967,6 @@ bool SurfaceSdlGraphicsManager::hotswapGFXMode() { SDL_FreeSurface(_tmpscreen); _tmpscreen = NULL; SDL_FreeSurface(_tmpscreen2); _tmpscreen2 = NULL; -#ifdef USE_OSD - // Release the OSD surface - SDL_FreeSurface(_osdSurface); _osdSurface = NULL; -#endif - // Setup the new GFX mode if (!loadGFXMode()) { unloadGFXMode(); @@ -1065,38 +1044,6 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { _forceFull = true; } -#ifdef USE_OSD - // OSD visible (i.e. non-transparent)? - if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) { - // Updated alpha value - const int diff = SDL_GetTicks() - _osdMessageFadeStartTime; - if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { - // Back to full transparency - _osdMessageAlpha = SDL_ALPHA_TRANSPARENT; - } else { - // Do a linear fade out... - const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; - _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration; - } - _forceFull = true; - } - - if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) { - removeOSDMessage(); - } else { - if (_osdMessageSurface && _osdSurface) { - SDL_Rect dstRect; - dstRect.x = (_osdSurface->w - _osdMessageSurface->w) / 2; - dstRect.y = (_osdSurface->h - _osdMessageSurface->h) / 2; - dstRect.w = _osdMessageSurface->w; - dstRect.h = _osdMessageSurface->h; - blitOSDMessage(dstRect); - } - } - } -#endif - if (!_overlayVisible) { origSurf = _screen; srcSurf = _tmpscreen; @@ -1119,6 +1066,10 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { if (_mouseNeedsRedraw) undrawMouse(); +#ifdef USE_OSD + updateOSD(); +#endif + // Force a full redraw if requested if (_forceFull) { _numDirtyRects = 1; @@ -1199,8 +1150,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { drawMouse(); #ifdef USE_OSD - if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) - SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0); + drawOSD(); #endif #ifdef USE_SDL_DEBUG_FOCUSRECT @@ -2169,14 +2119,14 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) { } // Clip the rect - if (width > _osdSurface->w) - width = _osdSurface->w; - if (height > _osdSurface->h) - height = _osdSurface->h; + if (width > _hwscreen->w) + width = _hwscreen->w; + if (height > _hwscreen->h) + height = _hwscreen->h; _osdMessageSurface = SDL_CreateRGBSurface( - SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, - width, height, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF + SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCALPHA, + width, height, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask ); // Lock the surface @@ -2209,138 +2159,120 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) { // Init the OSD display parameters, and the fade out _osdMessageAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; _osdMessageFadeStartTime = SDL_GetTicks() + kOSDFadeOutDelay; +} - // Ensure a full redraw takes place next time the screen is updated - _forceFull = true; +SDL_Rect SurfaceSdlGraphicsManager::getOSDMessageRect() const { + SDL_Rect rect; + rect.x = (_hwscreen->w - _osdMessageSurface->w) / 2; + rect.y = (_hwscreen->h - _osdMessageSurface->h) / 2; + rect.w = _osdMessageSurface->w; + rect.h = _osdMessageSurface->h; + return rect; } -void SurfaceSdlGraphicsManager::copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) { +void SurfaceSdlGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface *icon) { assert(_transactionMode == kTransactionNone); - assert(buf); Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - // Lock the OSD surface for drawing - if (SDL_LockSurface(_osdSurface)) - error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError()); - - // Mark that area as "dirty" - addDirtyRect(x, y, w, h, true); + if (_osdIconSurface) { + SDL_FreeSurface(_osdIconSurface); + _osdIconSurface = nullptr; + } + + if (icon) { + const Graphics::PixelFormat &iconFormat = icon->format; + + _osdIconSurface = SDL_CreateRGBSurface( + SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCALPHA, + icon->w, icon->h, iconFormat.bytesPerPixel * 8, + ((0xFF >> iconFormat.rLoss) << iconFormat.rShift), + ((0xFF >> iconFormat.gLoss) << iconFormat.gShift), + ((0xFF >> iconFormat.bLoss) << iconFormat.bShift), + ((0xFF >> iconFormat.aLoss) << iconFormat.aShift) + ); + + // Lock the surface + if (SDL_LockSurface(_osdIconSurface)) + error("displayActivityIconOnOSD: SDL_LockSurface failed: %s", SDL_GetError()); + + byte *dst = (byte *) _osdIconSurface->pixels; + const byte *src = (const byte *) icon->getPixels(); + for (uint y = 0; y < icon->h; y++) { + memcpy(dst, src, icon->w * iconFormat.bytesPerPixel); + src += icon->pitch; + dst += _osdIconSurface->pitch; + } -#ifdef USE_RGB_COLOR - byte *dst = (byte *)_osdSurface->pixels + y * _osdSurface->pitch + x * _osdSurface->format->BytesPerPixel; - if (_videoMode.screenWidth == w && pitch == _osdSurface->pitch) { - memcpy(dst, buf, h*pitch); - } else { - const byte *src = (const byte *)buf; - do { - memcpy(dst, src, w * _osdSurface->format->BytesPerPixel); - src += pitch; - dst += _osdSurface->pitch; - } while (--h); + // Finished drawing, so unlock the OSD icon surface + SDL_UnlockSurface(_osdIconSurface); } -#else - byte *dst = (byte *)_osdSurface->pixels + y * _osdSurface->pitch + x; - if (_osdSurface->pitch == pitch && pitch == w) { - memcpy(dst, buf, h*w); - } else { - const byte *src = (const byte *)buf; - do { - memcpy(dst, src, w); - src += pitch; - dst += _osdSurface->pitch; - } while (--h); - } -#endif - - // Finished drawing, so unlock the OSD surface again - SDL_UnlockSurface(_osdSurface); } -void SurfaceSdlGraphicsManager::clearOSD() { - assert(_transactionMode == kTransactionNone); - - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends - - // Lock the OSD surface for drawing - if (SDL_LockSurface(_osdSurface)) - error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError()); - - // Clear everything with the "transparent" color, i.e. the colorkey - SDL_FillRect(_osdSurface, 0, kOSDColorKey); - - // Finished drawing, so unlock the OSD surface again - SDL_UnlockSurface(_osdSurface); - - // Remove OSD message as well - removeOSDMessage(); - - // Ensure a full redraw takes place next time the screen is updated - _forceFull = true; +SDL_Rect SurfaceSdlGraphicsManager::getOSDIconRect() const { + SDL_Rect dstRect; + dstRect.x = _hwscreen->w - _osdIconSurface->w - 10; + dstRect.y = 10; + dstRect.w = _osdIconSurface->w; + dstRect.h = _osdIconSurface->h; + return dstRect; } void SurfaceSdlGraphicsManager::removeOSDMessage() { - // Lock the OSD surface for drawing - if (SDL_LockSurface(_osdSurface)) - error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError()); - - //remove previous message + // Remove the previous message if (_osdMessageSurface) { - SDL_Rect osdRect; - osdRect.x = (_osdSurface->w - _osdMessageSurface->w) / 2; - osdRect.y = (_osdSurface->h - _osdMessageSurface->h) / 2; - osdRect.w = _osdMessageSurface->w; - osdRect.h = _osdMessageSurface->h; - SDL_FillRect(_osdSurface, &osdRect, kOSDColorKey); SDL_FreeSurface(_osdMessageSurface); } _osdMessageSurface = NULL; _osdMessageAlpha = SDL_ALPHA_TRANSPARENT; +} - // Finished drawing, so unlock the OSD surface again - SDL_UnlockSurface(_osdSurface); -} - -void SurfaceSdlGraphicsManager::blitOSDMessage(SDL_Rect dstRect) { - SDL_Surface *src = _osdMessageSurface; - SDL_Surface *dst = _osdSurface; - Graphics::PixelFormat srcFormat = getSurfaceFormat(src); - Graphics::PixelFormat dstFormat = _osdFormat; - for (int y = 0; y < dstRect.h; y++) { - const byte *srcRow = (const byte *)((const byte *)(src->pixels) + y * src->pitch); //src (x, y) == (0, 0) - byte *dstRow = (byte *)((byte *)(dst->pixels) + (dstRect.y + y) * dst->pitch + dstRect.x * dstFormat.bytesPerPixel); - - for (int x = 0; x < dstRect.w; x++) { - uint32 srcColor; - if (dst->format->BytesPerPixel == 2) - srcColor = READ_UINT16(srcRow); - else if (dst->format->BytesPerPixel == 3) - srcColor = READ_UINT24(srcRow); - else - srcColor = READ_UINT32(srcRow); - - srcRow += srcFormat.bytesPerPixel; +void SurfaceSdlGraphicsManager::updateOSD() { + // OSD message visible (i.e. non-transparent)? + if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) { + // Updated alpha value + const int diff = SDL_GetTicks() - _osdMessageFadeStartTime; + if (diff > 0) { + if (diff >= kOSDFadeOutDuration) { + // Back to full transparency + _osdMessageAlpha = SDL_ALPHA_TRANSPARENT; + } else { + // Do a linear fade out... + const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; + _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration; + } + SDL_SetAlpha(_osdMessageSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdMessageAlpha); + } - // Convert that color to the new format - byte r, g, b, a; - srcFormat.colorToARGB(srcColor, a, r, g, b); - a = _osdMessageAlpha; //this is the important line, because apart from that this is plain surface copying - uint32 color = dstFormat.ARGBToColor(a, r, g, b); + if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) { + removeOSDMessage(); + } + } - if (dstFormat.bytesPerPixel == 2) - *((uint16 *)dstRow) = color; - else - *((uint32 *)dstRow) = color; + if (_osdMessageSurface) { + SDL_Rect dstRect = getOSDMessageRect(); + addDirtyRect(dstRect.x, dstRect.y, dstRect.w, dstRect.h, true); + } - dstRow += dstFormat.bytesPerPixel; - } + if (_osdIconSurface) { + SDL_Rect dstRect = getOSDIconRect(); + addDirtyRect(dstRect.x, dstRect.y, dstRect.w, dstRect.h, true); } } -Graphics::PixelFormat SurfaceSdlGraphicsManager::getOSDFormat() { - return _osdFormat; +void SurfaceSdlGraphicsManager::drawOSD() { + if (_osdMessageSurface) { + SDL_Rect dstRect = getOSDMessageRect(); + SDL_BlitSurface(_osdMessageSurface, 0, _hwscreen, &dstRect); + } + + if (_osdIconSurface) { + SDL_Rect dstRect = getOSDIconRect(); + SDL_BlitSurface(_osdIconSurface, 0, _hwscreen, &dstRect); + } } + #endif bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { @@ -2402,26 +2334,24 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { setGraphicsMode(newMode); endGFXTransaction(); #ifdef USE_OSD - if (_osdSurface) { - const char *newScalerName = 0; - const OSystem::GraphicsMode *g = getSupportedGraphicsModes(); - while (g->name) { - if (g->id == _videoMode.mode) { - newScalerName = g->description; - break; - } - g++; - } - if (newScalerName) { - char buffer[128]; - sprintf(buffer, "%s %s\n%d x %d -> %d x %d", - _("Active graphics filter:"), - newScalerName, - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h - ); - displayMessageOnOSD(buffer); + const char *newScalerName = 0; + const OSystem::GraphicsMode *g = getSupportedGraphicsModes(); + while (g->name) { + if (g->id == _videoMode.mode) { + newScalerName = g->description; + break; } + g++; + } + if (newScalerName) { + char buffer[128]; + sprintf(buffer, "%s %s\n%d x %d -> %d x %d", + _("Active graphics filter:"), + newScalerName, + _videoMode.screenWidth, _videoMode.screenHeight, + _hwscreen->w, _hwscreen->h + ); + displayMessageOnOSD(buffer); } #endif internUpdateScreen(); @@ -2636,22 +2566,4 @@ void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrect } #endif // SDL_VERSION_ATLEAST(2, 0, 0) -Graphics::PixelFormat SurfaceSdlGraphicsManager::getSurfaceFormat(SDL_Surface *surface) { - Graphics::PixelFormat format; - if (surface) { - format.bytesPerPixel = surface->format->BytesPerPixel; - - format.rLoss = surface->format->Rloss; - format.gLoss = surface->format->Gloss; - format.bLoss = surface->format->Bloss; - format.aLoss = surface->format->Aloss; - - format.rShift = surface->format->Rshift; - format.gShift = surface->format->Gshift; - format.bShift = surface->format->Bshift; - format.aShift = surface->format->Ashift; - } - return format; -} - #endif diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index d8f826aca0..82f4a33d8e 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -145,9 +145,7 @@ public: #ifdef USE_OSD virtual void displayMessageOnOSD(const char *msg); - virtual void copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h); - virtual void clearOSD(); - virtual Graphics::PixelFormat getOSDFormat(); + virtual void displayActivityIconOnOSD(const Graphics::Surface *icon); #endif // Override from Common::EventObserver @@ -163,8 +161,6 @@ public: protected: #ifdef USE_OSD - /** Surface containing the OSD */ - SDL_Surface *_osdSurface; /** Surface containing the OSD message */ SDL_Surface *_osdMessageSurface; /** Transparency level of the OSD message */ @@ -175,14 +171,19 @@ protected: enum { kOSDFadeOutDelay = 2 * 1000, /** < Delay before the OSD is faded out (in milliseconds) */ kOSDFadeOutDuration = 500, /** < Duration of the OSD fade out (in milliseconds) */ - kOSDColorKey = 1, /** < Transparent color key */ kOSDInitialAlpha = 80 /** < Initial alpha level, in percent */ }; - /** OSD pixel format */ - Graphics::PixelFormat _osdFormat; - + /** Screen rectangle where the OSD message is drawn */ + SDL_Rect getOSDMessageRect() const; + /** Clear the currently displayed OSD message if any */ void removeOSDMessage(); - void blitOSDMessage(SDL_Rect dstRect); + /** Surface containing the OSD background activity icon */ + SDL_Surface *_osdIconSurface; + /** Screen rectangle where the OSD background activity icon is drawn */ + SDL_Rect getOSDIconRect() const; + + void updateOSD(); + void drawOSD(); #endif /** Hardware screen */ @@ -368,8 +369,6 @@ protected: Common::Rect _focusRect; #endif - static Graphics::PixelFormat getSurfaceFormat(SDL_Surface *surface); - virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false); virtual void drawMouse(); -- cgit v1.2.3 From 9cbaad61405f0a4c8b88eb4e6637b84a12633c1a Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Tue, 13 Sep 2016 20:35:05 +0200 Subject: SDL: Switch the OpenGL renderer to use small textures to draw the OSD --- backends/graphics/opengl/opengl-graphics.cpp | 209 ++++++++++++++++++--------- backends/graphics/opengl/opengl-graphics.h | 77 ++++++++-- 2 files changed, 201 insertions(+), 85 deletions(-) diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 8861d364e6..3e2be6e8cd 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), + _osdIconChangeRequest(false), _osdIconSurface(nullptr) #endif { memset(_gamePalette, 0, sizeof(_gamePalette)); @@ -69,7 +70,9 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { delete _overlay; delete _cursor; #ifdef USE_OSD - delete _osd; + delete _osdMessageSurface; + delete _osdIconSurface; + _osdIconNextData.free(); #endif #if !USE_FORCED_GLES ShaderManager::destroy(); @@ -362,13 +365,27 @@ void OpenGLGraphicsManager::updateScreen() { return; } +#ifdef USE_OSD + { + Common::StackLock lock(_osdMutex); + + if (_osdMessageChangeRequest) { + osdMessageUpdateSurface(); + } + + if (_osdIconChangeRequest) { + osdIconUpdateSurface(); + } + } +#endif + // We only update the screen when there actually have been any changes. if ( !_forceRedraw && !_gameScreen->isDirty() && !(_overlayVisible && _overlay->isDirty()) && !(_cursorVisible && _cursor && _cursor->isDirty()) #ifdef USE_OSD - && _osdAlpha == 0 + && !_osdMessageSurface && !_osdIconSurface #endif ) { return; @@ -381,9 +398,6 @@ void OpenGLGraphicsManager::updateScreen() { _cursor->updateGLTexture(); } _overlay->updateGLTexture(); -#ifdef USE_OSD - _osd->updateGLTexture(); -#endif // Clear the screen buffer. if (_scissorOverride && !_overlayVisible) { @@ -424,29 +438,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 @@ -703,85 +733,130 @@ 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. + // another thread. But the MT-32 emulator and network synchronization still do, + // thus we need to make sure this doesn't happen while a updateScreen call is done. Common::StackLock lock(_osdMutex); - // Slip up the lines. + _osdMessageChangeRequest = true; + + _osdMessageNextData = msg; +#endif +} + +#ifdef USE_OSD +void OpenGLGraphicsManager::osdMessageUpdateSurface() { + // Split up the lines. Common::Array 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(width, font->getStringWidth(osdLines[i]) + 14); } // Clip the rect - width = MIN(width, dst->w); - height = MIN(height, dst->h); + width = MIN(width, _displayWidth); + height = MIN(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); + + _osdMessageSurface->allocate(width, height); - int dstX = (dst->w - width) / 2; - int dstY = (dst->h - height) / 2; + 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; -#endif -} + _osdMessageAlpha = kOSDMessageInitialAlpha; + _osdMessageFadeStartTime = g_system->getMillis() + kOSDMessageFadeOutDelay; -void OpenGLGraphicsManager::copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) { -#ifdef USE_OSD - _osd->copyRectToTexture(x, y, w, h, buf, pitch); -#endif + // Clear the text update request + _osdMessageNextData.clear(); + _osdMessageChangeRequest = false; } +#endif -void OpenGLGraphicsManager::clearOSD() { +void OpenGLGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface *icon) { #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. + // another thread. But the MT-32 emulator and network synchronization still do, + // thus we need to make sure this doesn't happen while a updateScreen call is done. + // HACK: We can't make OpenGL calls outside of the main thread. This method + // stores a copy of the icon. The main thread will pick up the changed icon, + // and copy it to an OpenGL texture. Common::StackLock lock(_osdMutex); - Graphics::Surface *dst = _osd->getSurface(); - _osd->fill(0); - _osd->flagDirty(); + _osdIconChangeRequest = true; - // Init the OSD display parameters. - _osdAlpha = kOSDInitialAlpha; - _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; + _osdIconNextData.free(); + _osdIconNextData.copyFrom(*icon); #endif } -Graphics::PixelFormat OpenGLGraphicsManager::getOSDFormat() { - return _defaultFormatAlpha; +#ifdef USE_OSD +void OpenGLGraphicsManager::osdIconUpdateSurface() { + delete _osdIconSurface; + _osdIconSurface = nullptr; + + if (_osdIconNextData.getPixels()) { + Graphics::Surface *converted = _osdIconNextData.convertTo(_defaultFormatAlpha); + _osdIconNextData.free(); + + _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; + + _osdIconSurface->updateGLTexture(); + } + + _osdIconChangeRequest = false; } +#endif void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { assert(_gameScreen->hasPalette()); @@ -849,22 +924,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(); @@ -949,8 +1008,12 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def } #ifdef USE_OSD - if (_osd) { - _osd->recreate(); + if (_osdMessageSurface) { + _osdMessageSurface->recreate(); + } + + if (_osdIconSurface) { + _osdIconSurface->recreate(); } #endif } @@ -969,8 +1032,12 @@ void OpenGLGraphicsManager::notifyContextDestroy() { } #ifdef USE_OSD - if (_osd) { - _osd->destroy(); + if (_osdMessageSurface) { + _osdMessageSurface->destroy(); + } + + if (_osdIconSurface) { + _osdIconSurface->destroy(); } #endif diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 55d2c5c826..366ad48fad 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -30,6 +30,8 @@ #include "common/frac.h" #include "common/mutex.h" +#include "graphics/surface.h" + namespace Graphics { class Font; } // End of namespace Graphics @@ -115,9 +117,7 @@ public: virtual void setCursorPalette(const byte *colors, uint start, uint num); virtual void displayMessageOnOSD(const char *msg); - virtual void copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h); - virtual void clearOSD(); - virtual Graphics::PixelFormat getOSDFormat(); + virtual void displayActivityIconOnOSD(const Graphics::Surface *icon); // PaletteManager interface virtual void setPalette(const byte *colors, uint start, uint num); @@ -548,30 +548,79 @@ protected: private: /** - * The OSD's contents. + * Request for the OSD icon surface to be updated. */ - Surface *_osd; + bool _osdMessageChangeRequest; /** - * Current opacity level of the OSD. + * The next OSD message. + * + * If this value is not empty, the OSD message will be set + * to it on the next frame. */ - uint8 _osdAlpha; + Common::String _osdMessageNextData; /** - * When fading the OSD has started. + * Set the OSD message surface with the value of the next OSD message. */ - uint32 _osdFadeStartTime; + void osdMessageUpdateSurface(); /** - * Mutex to allow displayMessageOnOSD to be used from the audio thread. + * The OSD message's contents. */ - Common::Mutex _osdMutex; + Surface *_osdMessageSurface; + + /** + * Current opacity level of the OSD message. + */ + uint8 _osdMessageAlpha; + + /** + * When fading the OSD message has started. + */ + uint32 _osdMessageFadeStartTime; + + enum { + kOSDMessageFadeOutDelay = 2 * 1000, + kOSDMessageFadeOutDuration = 500, + kOSDMessageInitialAlpha = 80 + }; + + /** + * Request for the OSD icon surface to be updated. + */ + bool _osdIconChangeRequest; + + /** + * The next OSD background activity icon. + * + * The OSD icon will be updated with this data on the next frame. + * Can be an unallocated surface if the OSD icon should not be displayed. + */ + Graphics::Surface _osdIconNextData; + + /** + * Set the OSD icon surface with the value of the next OSD icon. + */ + void osdIconUpdateSurface(); + + /** + * The OSD background activity icon's contents. + */ + Surface *_osdIconSurface; enum { - kOSDFadeOutDelay = 2 * 1000, - kOSDFadeOutDuration = 500, - kOSDInitialAlpha = 80 + kOSDIconTopMargin = 10, + kOSDIconRightMargin = 10 }; + + /** + * Mutex for the OSD draw calls. + * + * Mutex to allow displayMessageOnOSD and displayActivityIconOnOSD + * to be used from the audio and network threads. + */ + Common::Mutex _osdMutex; #endif }; -- cgit v1.2.3 From 0802bbd8ee526552da751141ce03cce2a8e3ec30 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Tue, 13 Sep 2016 20:35:46 +0200 Subject: OSYSTEM: Remove the API allowing to draw to the OSD surface directly --- backends/base-backend.cpp | 14 -------------- backends/base-backend.h | 3 --- backends/graphics/graphics.h | 3 --- backends/modular-backend.cpp | 12 ------------ backends/modular-backend.h | 3 --- common/system.h | 39 --------------------------------------- 6 files changed, 74 deletions(-) diff --git a/backends/base-backend.cpp b/backends/base-backend.cpp index dfb9e284ce..3e95c3e26a 100644 --- a/backends/base-backend.cpp +++ b/backends/base-backend.cpp @@ -39,20 +39,6 @@ void BaseBackend::displayMessageOnOSD(const char *msg) { dialog.runModal(); } -void BaseBackend::copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) { - warning("BaseBackend::copyRectToOSD not implemented"); //TODO -} - -void BaseBackend::clearOSD() { - warning("BaseBackend::clearOSD not implemented"); //TODO - //what should I do? Remove all TimedMessageDialogs? -} - -Graphics::PixelFormat BaseBackend::getOSDFormat() { - warning("BaseBackend::getOSDFormat not implemented"); - return Graphics::PixelFormat(); -} - void BaseBackend::initBackend() { // Init Event manager #ifndef DISABLE_DEFAULT_EVENT_MANAGER diff --git a/backends/base-backend.h b/backends/base-backend.h index 2394edaf38..598f682b32 100644 --- a/backends/base-backend.h +++ b/backends/base-backend.h @@ -33,9 +33,6 @@ public: virtual void initBackend(); virtual void displayMessageOnOSD(const char *msg); - virtual void copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h); - virtual void clearOSD(); - virtual Graphics::PixelFormat getOSDFormat(); virtual void fillScreen(uint32 col); }; diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 271a482032..db8b6a920b 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -84,9 +84,6 @@ public: virtual void setCursorPalette(const byte *colors, uint start, uint num) = 0; virtual void displayMessageOnOSD(const char *msg) {} - virtual void copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) {} - virtual void clearOSD() {} - virtual Graphics::PixelFormat getOSDFormat() { return Graphics::PixelFormat(); } virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) {} diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index 13db277a75..1fef5c5a48 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -241,18 +241,6 @@ void ModularBackend::displayMessageOnOSD(const char *msg) { _graphicsManager->displayMessageOnOSD(msg); } -void ModularBackend::copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) { - _graphicsManager->copyRectToOSD(buf, pitch, x, y, w, h); -} - -void ModularBackend::clearOSD() { - _graphicsManager->clearOSD(); -} - -Graphics::PixelFormat ModularBackend::getOSDFormat() { - return _graphicsManager->getOSDFormat(); -} - void ModularBackend::displayActivityIconOnOSD(const Graphics::Surface *icon) { _graphicsManager->displayActivityIconOnOSD(icon); } diff --git a/backends/modular-backend.h b/backends/modular-backend.h index 886f91c320..23f0e2d547 100644 --- a/backends/modular-backend.h +++ b/backends/modular-backend.h @@ -127,9 +127,6 @@ public: virtual void quit(); virtual void displayMessageOnOSD(const char *msg); - virtual void copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h); - virtual void clearOSD(); - virtual Graphics::PixelFormat getOSDFormat(); virtual void displayActivityIconOnOSD(const Graphics::Surface *icon); //@} diff --git a/common/system.h b/common/system.h index b07a5ffd1e..cbaa30c19d 100644 --- a/common/system.h +++ b/common/system.h @@ -1120,45 +1120,6 @@ public: */ virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) = 0; - /** - * Blit a bitmap to the 'on screen display'. - * - * If the current pixel format has one byte per pixel, the graphics data - * uses 8 bits per pixel, using the palette specified via setPalette. - * If more than one byte per pixel is in use, the graphics data uses the - * pixel format returned by getScreenFormat. - * - * @param buf the buffer containing the graphics data source - * @param pitch the pitch of the buffer (number of bytes in a scanline) - * @param x the x coordinate of the destination rectangle - * @param y the y coordinate of the destination rectangle - * @param w the width of the destination rectangle - * @param h the height of the destination rectangle - * - * @note The specified destination rectangle must be completly contained - * in the visible screen space, and must be non-empty. If not, a - * backend may or may not perform clipping, trigger an assert or - * silently corrupt memory. - * - * @see updateScreen - * @see getScreenFormat - * @see copyRectToScreen - */ - - virtual void copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) = 0; - - /** - * Clears 'on screen display' from everything drawn on it. - */ - - virtual void clearOSD() = 0; - - /** - * Returns 'on screen display' pixel format. - */ - - virtual Graphics::PixelFormat getOSDFormat() = 0; - /** * Return the SaveFileManager, used to store and load savestates * and other modifiable persistent game data. For more information, -- cgit v1.2.3