aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sandulenko2016-09-13 22:15:32 +0200
committerGitHub2016-09-13 22:15:32 +0200
commit2a9d29f067a8e5f292514ab0c10d055c286178de (patch)
tree878a6d546b3661195671c83e556917cf86362465
parent8204a23032f10a5d7a2195ba8f606f1111bf6db7 (diff)
parent0802bbd8ee526552da751141ce03cce2a8e3ec30 (diff)
downloadscummvm-rg350-2a9d29f067a8e5f292514ab0c10d055c286178de.tar.gz
scummvm-rg350-2a9d29f067a8e5f292514ab0c10d055c286178de.tar.bz2
scummvm-rg350-2a9d29f067a8e5f292514ab0c10d055c286178de.zip
Merge pull request #824 from bgK/osd
OSYSTEM: Allow drawing a background activity icon on the OSD
-rw-r--r--backends/base-backend.cpp14
-rw-r--r--backends/base-backend.h3
-rw-r--r--backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp1
-rw-r--r--backends/cloud/googledrive/googledrivestorage.cpp1
-rw-r--r--backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp39
-rw-r--r--backends/graphics/gph/gph-graphics.cpp40
-rw-r--r--backends/graphics/graphics.h4
-rw-r--r--backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp40
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp209
-rw-r--r--backends/graphics/opengl/opengl-graphics.h77
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp330
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h23
-rw-r--r--backends/modular-backend.cpp12
-rw-r--r--backends/modular-backend.h4
-rw-r--r--backends/networking/curl/cloudicon.cpp46
-rw-r--r--backends/networking/curl/cloudicon.h8
-rw-r--r--common/system.h54
17 files changed, 391 insertions, 514 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/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 <curl/curl.h>
#ifdef ENABLE_RELEASE
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/graphics.h b/backends/graphics/graphics.h
index 921dfca61c..db8b6a920b 100644
--- a/backends/graphics/graphics.h
+++ b/backends/graphics/graphics.h
@@ -84,9 +84,7 @@ 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) {}
// Graphics::PaletteManager interface
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/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<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);
+
+ _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
};
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();
diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp
index e1bdf15571..1fef5c5a48 100644
--- a/backends/modular-backend.cpp
+++ b/backends/modular-backend.cpp
@@ -241,16 +241,8 @@ 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);
}
void ModularBackend::quit() {
diff --git a/backends/modular-backend.h b/backends/modular-backend.h
index 9cde27915f..23f0e2d547 100644
--- a/backends/modular-backend.h
+++ b/backends/modular-backend.h
@@ -127,9 +127,7 @@ 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/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();
diff --git a/common/system.h b/common/system.h
index eb9a39bbdf..cbaa30c19d 100644
--- a/common/system.h
+++ b/common/system.h
@@ -1102,43 +1102,23 @@ public:
virtual void displayMessageOnOSD(const char *msg) = 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;
+ * 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;
/**
* Return the SaveFileManager, used to store and load savestates