aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'backends/graphics')
-rw-r--r--backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp25
-rw-r--r--backends/graphics/gph/gph-graphics.cpp27
-rw-r--r--backends/graphics/graphics.h4
-rw-r--r--backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp25
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp34
-rw-r--r--backends/graphics/opengl/opengl-graphics.h3
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp254
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h20
8 files changed, 319 insertions, 73 deletions
diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp
index 7a248f1859..0938be2d4e 100644
--- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp
+++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp
@@ -259,21 +259,33 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() {
#ifdef USE_OSD
// OSD visible (i.e. non-transparent)?
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+ if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) {
// Updated alpha value
- const int diff = SDL_GetTicks() - _osdFadeStartTime;
+ const int diff = SDL_GetTicks() - _osdMessageFadeStartTime;
if (diff > 0) {
if (diff >= kOSDFadeOutDuration) {
// Back to full transparency
- _osdAlpha = SDL_ALPHA_TRANSPARENT;
+ _osdMessageAlpha = SDL_ALPHA_TRANSPARENT;
} else {
// Do a linear fade out...
const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
- _osdAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
+ _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
}
- SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);
_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
@@ -405,9 +417,8 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() {
drawMouse();
#ifdef USE_OSD
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+ if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT)
SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
- }
#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 65cb3d1d65..bd0f246286 100644
--- a/backends/graphics/gph/gph-graphics.cpp
+++ b/backends/graphics/gph/gph-graphics.cpp
@@ -279,21 +279,33 @@ void GPHGraphicsManager::internUpdateScreen() {
#ifdef USE_OSD
// OSD visible (i.e. non-transparent)?
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+ if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) {
// Updated alpha value
- const int diff = SDL_GetTicks() - _osdFadeStartTime;
+ const int diff = SDL_GetTicks() - _osdMessageFadeStartTime;
if (diff > 0) {
if (diff >= kOSDFadeOutDuration) {
// Back to full transparency
- _osdAlpha = SDL_ALPHA_TRANSPARENT;
+ _osdMessageAlpha = SDL_ALPHA_TRANSPARENT;
} else {
// Do a linear fade out...
const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
- _osdAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
+ _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
}
- SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);
_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
@@ -428,9 +440,8 @@ void GPHGraphicsManager::internUpdateScreen() {
drawMouse();
#ifdef USE_OSD
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+ if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT)
SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
- }
#endif
// Finally, blit all our changes to the screen
SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
@@ -459,7 +470,7 @@ void GPHGraphicsManager::hideOverlay() {
bool GPHGraphicsManager::loadGFXMode() {
- // We don't offer anything other than fullscreen on GPH devices so let’s not even pretend.
+ // We don't offer anything other than fullscreen on GPH devices so let's not even pretend.
_videoMode.fullscreen = true;
// Set the hardware stats to match the LCD.
diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h
index 3671b9f0b9..921dfca61c 100644
--- a/backends/graphics/graphics.h
+++ b/backends/graphics/graphics.h
@@ -84,6 +84,10 @@ 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(); }
+
// Graphics::PaletteManager interface
//virtual void setPalette(const byte *colors, uint start, uint num) = 0;
diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp
index 52e5b42e8b..a69cba24ee 100644
--- a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp
+++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp
@@ -292,21 +292,33 @@ void LinuxmotoSdlGraphicsManager::internUpdateScreen() {
#ifdef USE_OSD
// OSD visible (i.e. non-transparent)?
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+ if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) {
// Updated alpha value
- const int diff = SDL_GetTicks() - _osdFadeStartTime;
+ const int diff = SDL_GetTicks() - _osdMessageFadeStartTime;
if (diff > 0) {
if (diff >= kOSDFadeOutDuration) {
// Back to full transparency
- _osdAlpha = SDL_ALPHA_TRANSPARENT;
+ _osdMessageAlpha = SDL_ALPHA_TRANSPARENT;
} else {
// Do a linear fade out...
const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
- _osdAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
+ _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
}
- SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);
_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
@@ -439,9 +451,8 @@ void LinuxmotoSdlGraphicsManager::internUpdateScreen() {
drawMouse();
#ifdef USE_OSD
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+ if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT)
SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
- }
#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 4d6a00a3b3..8861d364e6 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -367,7 +367,10 @@ void OpenGLGraphicsManager::updateScreen() {
&& !_gameScreen->isDirty()
&& !(_overlayVisible && _overlay->isDirty())
&& !(_cursorVisible && _cursor && _cursor->isDirty())
- && _osdAlpha == 0) {
+#ifdef USE_OSD
+ && _osdAlpha == 0
+#endif
+ ) {
return;
}
_forceRedraw = false;
@@ -378,7 +381,9 @@ void OpenGLGraphicsManager::updateScreen() {
_cursor->updateGLTexture();
}
_overlay->updateGLTexture();
+#ifdef USE_OSD
_osd->updateGLTexture();
+#endif
// Clear the screen buffer.
if (_scissorOverride && !_overlayVisible) {
@@ -751,6 +756,33 @@ void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
#endif
}
+void OpenGLGraphicsManager::copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) {
+#ifdef USE_OSD
+ _osd->copyRectToTexture(x, y, w, h, buf, pitch);
+#endif
+}
+
+void OpenGLGraphicsManager::clearOSD() {
+#ifdef USE_OSD
+ // HACK: Actually no client code should use graphics functions from
+ // another thread. But the MT-32 emulator still does, thus we need to
+ // make sure this doesn't happen while a updateScreen call is done.
+ Common::StackLock lock(_osdMutex);
+
+ Graphics::Surface *dst = _osd->getSurface();
+ _osd->fill(0);
+ _osd->flagDirty();
+
+ // Init the OSD display parameters.
+ _osdAlpha = kOSDInitialAlpha;
+ _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay;
+#endif
+}
+
+Graphics::PixelFormat OpenGLGraphicsManager::getOSDFormat() {
+ return _defaultFormatAlpha;
+}
+
void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
assert(_gameScreen->hasPalette());
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 35435c156e..55d2c5c826 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -115,6 +115,9 @@ 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();
// PaletteManager interface
virtual void setPalette(const byte *colors, uint start, uint num);
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 5b591e77ff..f4a466d740 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -121,7 +121,7 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
:
SdlGraphicsManager(sdlEventSource, window),
#ifdef USE_OSD
- _osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
+ _osdSurface(0), _osdMessageSurface(nullptr), _osdMessageAlpha(SDL_ALPHA_TRANSPARENT), _osdMessageFadeStartTime(0),
#endif
_hwscreen(0),
#if SDL_VERSION_ATLEAST(2, 0, 0)
@@ -883,13 +883,16 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
_osdSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
_hwscreen->w,
_hwscreen->h,
- 16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
+ 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
@@ -946,6 +949,11 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
SDL_FreeSurface(_osdSurface);
_osdSurface = NULL;
}
+
+ if (_osdMessageSurface) {
+ SDL_FreeSurface(_osdMessageSurface);
+ _osdMessageSurface = NULL;
+ }
#endif
DestroyScalers();
@@ -1059,21 +1067,33 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
#ifdef USE_OSD
// OSD visible (i.e. non-transparent)?
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+ if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT) {
// Updated alpha value
- const int diff = SDL_GetTicks() - _osdFadeStartTime;
+ const int diff = SDL_GetTicks() - _osdMessageFadeStartTime;
if (diff > 0) {
if (diff >= kOSDFadeOutDuration) {
// Back to full transparency
- _osdAlpha = SDL_ALPHA_TRANSPARENT;
+ _osdMessageAlpha = SDL_ALPHA_TRANSPARENT;
} else {
// Do a linear fade out...
const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
- _osdAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
+ _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
}
- SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);
_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
@@ -1179,9 +1199,8 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
drawMouse();
#ifdef USE_OSD
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+ if (_osdMessageAlpha != SDL_ALPHA_TRANSPARENT)
SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
- }
#endif
#ifdef USE_SDL_DEBUG_FOCUSRECT
@@ -2121,26 +2140,11 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
- uint i;
-
- // Lock the OSD surface for drawing
- if (SDL_LockSurface(_osdSurface))
- error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError());
-
- Graphics::Surface dst;
- dst.init(_osdSurface->w, _osdSurface->h, _osdSurface->pitch, _osdSurface->pixels,
- Graphics::PixelFormat(_osdSurface->format->BytesPerPixel,
- 8 - _osdSurface->format->Rloss, 8 - _osdSurface->format->Gloss,
- 8 - _osdSurface->format->Bloss, 8 - _osdSurface->format->Aloss,
- _osdSurface->format->Rshift, _osdSurface->format->Gshift,
- _osdSurface->format->Bshift, _osdSurface->format->Ashift));
+ removeOSDMessage();
// The font we are going to use:
const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
- // Clear everything with the "transparent" color, i.e. the colorkey
- SDL_FillRect(_osdSurface, 0, kOSDColorKey);
-
// Split the message into separate lines.
Common::Array<Common::String> lines;
const char *ptr;
@@ -2159,44 +2163,184 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
int width = 0;
int height = lineHeight * lines.size() + 2 * vOffset;
+ uint i;
for (i = 0; i < lines.size(); i++) {
width = MAX(width, font->getStringWidth(lines[i]) + 14);
}
// Clip the rect
- if (width > dst.w)
- width = dst.w;
- if (height > dst.h)
- height = dst.h;
+ if (width > _osdSurface->w)
+ width = _osdSurface->w;
+ if (height > _osdSurface->h)
+ height = _osdSurface->h;
+
+ _osdMessageSurface = SDL_CreateRGBSurface(
+ SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+ width, height, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
+ );
+
+ // Lock the surface
+ if (SDL_LockSurface(_osdMessageSurface))
+ error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError());
// Draw a dark gray rect
// TODO: Rounded corners ? Border?
- SDL_Rect osdRect;
- osdRect.x = (dst.w - width) / 2;
- osdRect.y = (dst.h - height) / 2;
- osdRect.w = width;
- osdRect.h = height;
- SDL_FillRect(_osdSurface, &osdRect, SDL_MapRGB(_osdSurface->format, 64, 64, 64));
+ SDL_FillRect(_osdMessageSurface, nullptr, SDL_MapRGB(_osdMessageSurface->format, 64, 64, 64));
+
+ Graphics::Surface dst;
+ dst.init(_osdMessageSurface->w, _osdMessageSurface->h, _osdMessageSurface->pitch, _osdMessageSurface->pixels,
+ Graphics::PixelFormat(_osdMessageSurface->format->BytesPerPixel,
+ 8 - _osdMessageSurface->format->Rloss, 8 - _osdMessageSurface->format->Gloss,
+ 8 - _osdMessageSurface->format->Bloss, 8 - _osdMessageSurface->format->Aloss,
+ _osdMessageSurface->format->Rshift, _osdMessageSurface->format->Gshift,
+ _osdMessageSurface->format->Bshift, _osdMessageSurface->format->Ashift));
// Render the message, centered, and in white
for (i = 0; i < lines.size(); i++) {
font->drawString(&dst, lines[i],
- osdRect.x, osdRect.y + i * lineHeight + vOffset + lineSpacing, osdRect.w,
- SDL_MapRGB(_osdSurface->format, 255, 255, 255),
- Graphics::kTextAlignCenter);
+ 0, 0 + i * lineHeight + vOffset + lineSpacing, width,
+ SDL_MapRGB(_osdMessageSurface->format, 255, 255, 255),
+ Graphics::kTextAlignCenter);
}
+ // Finished drawing, so unlock the OSD message surface
+ SDL_UnlockSurface(_osdMessageSurface);
+
+ // 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;
+}
+
+void SurfaceSdlGraphicsManager::copyRectToOSD(const void *buf, int pitch, int x, int y, int w, int h) {
+ 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);
+
+#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);
+ }
+#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);
+}
- // Init the OSD display parameters, and the fade out
- _osdAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
- _osdFadeStartTime = SDL_GetTicks() + kOSDFadeOutDelay;
- SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);
+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;
}
+
+void SurfaceSdlGraphicsManager::removeOSDMessage() {
+ // Lock the OSD surface for drawing
+ if (SDL_LockSurface(_osdSurface))
+ error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError());
+
+ //remove 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;
+
+ // 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 (dstFormat.bytesPerPixel == 2)
+ *((uint16 *)dstRow) = color;
+ else
+ *((uint32 *)dstRow) = color;
+
+ dstRow += dstFormat.bytesPerPixel;
+ }
+ }
+}
+
+Graphics::PixelFormat SurfaceSdlGraphicsManager::getOSDFormat() {
+ return _osdFormat;
+}
#endif
bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
@@ -2492,4 +2636,22 @@ 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 25d6ff041c..d8f826aca0 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -145,6 +145,9 @@ 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();
#endif
// Override from Common::EventObserver
@@ -160,12 +163,14 @@ public:
protected:
#ifdef USE_OSD
- /** Surface containing the OSD message */
+ /** Surface containing the OSD */
SDL_Surface *_osdSurface;
- /** Transparency level of the OSD */
- uint8 _osdAlpha;
+ /** Surface containing the OSD message */
+ SDL_Surface *_osdMessageSurface;
+ /** Transparency level of the OSD message */
+ uint8 _osdMessageAlpha;
/** When to start the fade out */
- uint32 _osdFadeStartTime;
+ uint32 _osdMessageFadeStartTime;
/** Enum with OSD options */
enum {
kOSDFadeOutDelay = 2 * 1000, /** < Delay before the OSD is faded out (in milliseconds) */
@@ -173,6 +178,11 @@ protected:
kOSDColorKey = 1, /** < Transparent color key */
kOSDInitialAlpha = 80 /** < Initial alpha level, in percent */
};
+ /** OSD pixel format */
+ Graphics::PixelFormat _osdFormat;
+
+ void removeOSDMessage();
+ void blitOSDMessage(SDL_Rect dstRect);
#endif
/** Hardware screen */
@@ -358,6 +368,8 @@ 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();