aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics/surfacesdl
diff options
context:
space:
mode:
authorEugene Sandulenko2016-08-30 13:54:12 +0200
committerGitHub2016-08-30 13:54:12 +0200
commitbfbfbd3e1a8397cc3b1c9eaff6c7754abe3ddc3d (patch)
tree68851bdc99b78b4b1902944c1df3c3ee5d4f4489 /backends/graphics/surfacesdl
parent7df744c291e5fcf5dc7afd3b21189c2c56810f8e (diff)
parent368f664c813075f8b8cb2c572dce65f60128eda4 (diff)
downloadscummvm-rg350-bfbfbd3e1a8397cc3b1c9eaff6c7754abe3ddc3d.tar.gz
scummvm-rg350-bfbfbd3e1a8397cc3b1c9eaff6c7754abe3ddc3d.tar.bz2
scummvm-rg350-bfbfbd3e1a8397cc3b1c9eaff6c7754abe3ddc3d.zip
Merge pull request #788 from Tkachov/cloud
ALL: Add Cloud storage support
Diffstat (limited to 'backends/graphics/surfacesdl')
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp257
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h20
2 files changed, 225 insertions, 52 deletions
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 5b591e77ff..b4b0d33b85 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,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
drawMouse();
#ifdef USE_OSD
- if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
- SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
- }
+ SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
#endif
#ifdef USE_SDL_DEBUG_FOCUSRECT
@@ -2121,26 +2139,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 +2162,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));
+ // TODO: Rounded corners ? Border?
+ 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 *)((const 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 +2635,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();