aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorJody Northup2009-06-10 05:35:18 +0000
committerJody Northup2009-06-10 05:35:18 +0000
commit0a793f08a4d198f3f766214ed4ce85ac51ccea5e (patch)
treecff62f704ef84f40dcdc17631500c6e61b6af276 /backends
parentc426dd99a4c4149418fa16996e38f0995ddcaea5 (diff)
downloadscummvm-rg350-0a793f08a4d198f3f766214ed4ce85ac51ccea5e.tar.gz
scummvm-rg350-0a793f08a4d198f3f766214ed4ce85ac51ccea5e.tar.bz2
scummvm-rg350-0a793f08a4d198f3f766214ed4ce85ac51ccea5e.zip
SDL backend now dynamically generates 8 or 16-bit color surface depending on engine request (using ad-hoc format).
svn-id: r41416
Diffstat (limited to 'backends')
-rw-r--r--backends/platform/sdl/graphics.cpp244
-rw-r--r--backends/platform/sdl/sdl.cpp3
-rw-r--r--backends/platform/sdl/sdl.h32
3 files changed, 182 insertions, 97 deletions
diff --git a/backends/platform/sdl/graphics.cpp b/backends/platform/sdl/graphics.cpp
index 2872c71f44..142fa94dba 100644
--- a/backends/platform/sdl/graphics.cpp
+++ b/backends/platform/sdl/graphics.cpp
@@ -97,6 +97,9 @@ void OSystem_SDL::beginGFXTransaction(void) {
_transactionDetails.needUpdatescreen = false;
_transactionDetails.normal1xScaler = false;
+#ifdef ENABLE_16BIT
+ _transactionDetails.formatChanged = false;
+#endif
_oldVideoMode = _videoMode;
}
@@ -127,6 +130,12 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction(void) {
_videoMode.screenHeight = _oldVideoMode.screenHeight;
_videoMode.overlayWidth = _oldVideoMode.overlayWidth;
_videoMode.overlayHeight = _oldVideoMode.overlayHeight;
+#ifdef ENABLE_16BIT
+ } else if (_videoMode.format != _oldVideoMode.format) {
+ errors |= kTransactionPixelFormatNotSupported;
+
+ _videoMode.format = _oldVideoMode.format;
+#endif
}
if (_videoMode.fullscreen == _oldVideoMode.fullscreen &&
@@ -143,6 +152,32 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction(void) {
}
}
+#ifdef ENABLE_16BIT
+ if (_transactionDetails.formatChanged) {
+ _screenFormat = getPixelFormat(_videoMode.format);
+ if (!_transactionDetails.sizeChanged) {
+ unloadGFXMode();
+ if (!loadGFXMode()) {
+ if (_oldVideoMode.setup) {
+ _transactionMode = kTransactionRollback;
+ errors |= endGFXTransaction();
+ }
+ } else {
+ setGraphicsModeIntern();
+ clearOverlay();
+
+ _videoMode.setup = true;
+ _modeChanged = true;
+ // OSystem_SDL::pollEvent used to update the screen change count,
+ // but actually it gives problems when a video mode was changed
+ // but OSystem_SDL::pollEvent was not called. This for example
+ // caused a crash under certain circumstances when doing an RTL.
+ // To fix this issue we update the screen change count right here.
+ _screenChangeCount++;
+ }
+ }
+ }
+#endif
if (_transactionDetails.sizeChanged) {
unloadGFXMode();
if (!loadGFXMode()) {
@@ -186,7 +221,7 @@ OSystem::TransactionError OSystem_SDL::endGFXTransaction(void) {
} else if (_transactionDetails.needUpdatescreen) {
setGraphicsModeIntern();
internUpdateScreen();
- }
+ }
_transactionMode = kTransactionNone;
return (TransactionError)errors;
@@ -339,6 +374,102 @@ int OSystem_SDL::getGraphicsMode() const {
assert (_transactionMode == kTransactionNone);
return _videoMode.mode;
}
+#ifdef ENABLE_16BIT
+Graphics::ColorFormat OSystem_SDL::findCompatibleFormat(Common::List<Graphics::ColorFormat> formatList)
+{
+ bool typeAccepted = false;
+ Graphics::ColorFormat format;
+
+ while (!formatList.empty() && !typeAccepted)
+ {
+ typeAccepted = false;
+ format = formatList.front();
+
+ //no need to keep searching if the screen
+ //is already in one of the desired formats
+ if (format == _videoMode.format)
+ return format;
+
+ formatList.pop_front();
+ switch (format & Graphics::kFormatTypeMask)
+ {
+ case Graphics::kFormat8Bit:
+ if (format == Graphics::kFormat8Bit)
+ return format;
+ break;
+ case Graphics::kFormatRGB555:
+ case Graphics::kFormatARGB1555:
+ case Graphics::kFormatRGB565:
+ typeAccepted = true;
+ break;
+ }
+
+ if (!typeAccepted)
+ continue;
+
+ switch (format & Graphics::kFormatOrderMask) {
+ case Graphics::kFormatRGB:
+ case Graphics::kFormatRGBA:
+ return format;
+ default:
+ break;
+ }
+ }
+ return Graphics::kFormat8Bit;
+}
+
+void OSystem_SDL::initFormat(Graphics::ColorFormat format) {
+ assert(_transactionMode == kTransactionActive);
+
+ //avoid redundant format changes
+ if (format == _videoMode.format)
+ return;
+
+ _videoMode.format = format;
+ _transactionDetails.formatChanged = true;
+
+}
+
+//This should only ever be called with a format that is known supported.
+Graphics::PixelFormat OSystem_SDL::getPixelFormat(Graphics::ColorFormat format) {
+ Graphics::PixelFormat result;
+ switch (format & Graphics::kFormatTypeMask) {
+ case Graphics::kFormatARGB1555:
+ result.aLoss = 7;
+ result.bytesPerPixel = 2;
+ result.rLoss = result.gLoss = result.bLoss = 3;
+ case Graphics::kFormatRGB555:
+ result.aLoss = 8;
+ result.bytesPerPixel = 2;
+ result.rLoss = result.gLoss = result.bLoss = 3;
+ break;
+ case Graphics::kFormatRGB565:
+ result.bytesPerPixel = 2;
+ result.aLoss = 8;
+ result.gLoss = 2;
+ result.rLoss = result.bLoss = 3;
+ break;
+ case Graphics::kFormat8Bit:
+ default:
+ result.bytesPerPixel = 1;
+ result.rShift = result.gShift = result.bShift = result.aShift = 0;
+ result.rLoss = result.gLoss = result.bLoss = result.aLoss = 8;
+ return result;
+ }
+ switch (format & Graphics::kFormatOrderMask)
+ {
+ default:
+ case Graphics::kFormatRGBA:
+ result.aShift = 0;
+ case Graphics::kFormatRGB:
+ result.bShift = result.aBits();
+ result.gShift = result.bShift + result.bBits();
+ result.rShift = result.gShift + result.gBits();
+ break;
+ }
+ return result;
+}
+#endif
void OSystem_SDL::initSize(uint w, uint h) {
assert(_transactionMode == kTransactionActive);
@@ -384,9 +515,21 @@ bool OSystem_SDL::loadGFXMode() {
//
// Create the surface that contains the 8 bit game data
//
+#ifdef ENABLE_16BIT
+ _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight,
+ _screenFormat.bytesPerPixel << 3,
+ ((1 << _screenFormat.rBits()) - 1) << _screenFormat.rShift ,
+ ((1 << _screenFormat.gBits()) - 1) << _screenFormat.gShift ,
+ ((1 << _screenFormat.bBits()) - 1) << _screenFormat.bShift ,
+ ((1 << _screenFormat.aBits()) - 1) << _screenFormat.aShift );
+ if (_screen == NULL)
+ error("allocating _screen failed");
+
+#else
_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
if (_screen == NULL)
error("allocating _screen failed");
+#endif
//
// Create the surface that contains the scaled graphics in 16 bit mode
@@ -407,20 +550,6 @@ bool OSystem_SDL::loadGFXMode() {
}
}
-#ifdef ENABLE_16BIT
- //
- // Create the surface that contains the 16 bit game data
- //
- _screen16 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight,
- 16,
- 0x7C00,
- 0x3E0,
- 0x1F,
- 0); //555, not 565
- if (_screen16 == NULL)
- error("allocating _screen16 failed");
-#endif
-
//
// Create the surface used for the graphics in 16 bit before scaling, and also the overlay
//
@@ -498,17 +627,10 @@ bool OSystem_SDL::loadGFXMode() {
}
void OSystem_SDL::unloadGFXMode() {
-#ifdef ENABLE_16BIT
- if (_screen16) {
- SDL_FreeSurface(_screen16);
- _screen16 = NULL;
- }
-#else
if (_screen) {
SDL_FreeSurface(_screen);
_screen = NULL;
}
-#endif
if (_hwscreen) {
SDL_FreeSurface(_hwscreen);
@@ -540,22 +662,13 @@ void OSystem_SDL::unloadGFXMode() {
}
bool OSystem_SDL::hotswapGFXMode() {
-#ifdef ENABLE_16BIT
- if (!_screen16)
-#else
if (!_screen)
-#endif
return false;
// Keep around the old _screen & _overlayscreen so we can restore the screen data
// after the mode switch.
-#ifdef ENABLE_16BIT
- SDL_Surface *old_screen = _screen16;
- _screen16 = NULL;
-#else
SDL_Surface *old_screen = _screen;
_screen = NULL;
-#endif
SDL_Surface *old_overlayscreen = _overlayscreen;
_overlayscreen = NULL;
@@ -574,11 +687,7 @@ bool OSystem_SDL::hotswapGFXMode() {
if (!loadGFXMode()) {
unloadGFXMode();
-#ifdef ENABLE_16BIT
- _screen16 = old_screen;
-#else
_screen = old_screen;
-#endif
_overlayscreen = old_overlayscreen;
return false;
@@ -588,11 +697,7 @@ bool OSystem_SDL::hotswapGFXMode() {
SDL_SetColors(_screen, _currentPalette, 0, 256);
// Restore old screen content
-#ifdef ENABLE_16BIT
- SDL_BlitSurface(old_screen, NULL, _screen16, NULL);
-#else
SDL_BlitSurface(old_screen, NULL, _screen, NULL);
-#endif
SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL);
// Free the old surfaces
@@ -674,11 +779,7 @@ void OSystem_SDL::internUpdateScreen() {
#endif
if (!_overlayVisible) {
-#ifdef ENABLE_16BIT
- origSurf = _screen16;
-#else
origSurf = _screen;
-#endif
srcSurf = _tmpscreen;
width = _videoMode.screenWidth;
height = _videoMode.screenHeight;
@@ -823,12 +924,6 @@ void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int
assert (_transactionMode == kTransactionNone);
assert(src);
-#ifdef ENABLE_16BIT
- if (_screen16 == NULL) {
- warning("OSystem_SDL::copyRectToScreen: _screen16 == NULL");
- return;
- }
-#endif
if (_screen == NULL) {
warning("OSystem_SDL::copyRectToScreen: _screen == NULL");
return;
@@ -877,27 +972,20 @@ void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int
}
// Try to lock the screen surface
-#ifdef ENABLE_16BIT
- if (SDL_LockSurface(_screen16) == -1)
-#else
if (SDL_LockSurface(_screen) == -1)
-#endif
error("SDL_LockSurface failed: %s", SDL_GetError());
#ifdef ENABLE_16BIT
- byte *dst = (byte *)_screen16->pixels + y * _videoMode.screenWidth * 2 + x * 2;
- if (_videoMode.screenWidth == w && pitch == w * 2) {
- memcpy(dst, src, h*w*2);
+ byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth * _screenFormat.bytesPerPixel + x * _screenFormat.bytesPerPixel;
+ if (_videoMode.screenWidth == w && pitch == w * _screenFormat.bytesPerPixel) {
+ memcpy(dst, src, h*w*_screenFormat.bytesPerPixel);
} else {
do {
- memcpy(dst, src, w * 2);
+ memcpy(dst, src, w * _screenFormat.bytesPerPixel);
src += pitch;
- dst += _videoMode.screenWidth * 2;
+ dst += _videoMode.screenWidth * _screenFormat.bytesPerPixel;
} while (--h);
}
-
- // Unlock the screen surface
- SDL_UnlockSurface(_screen16);
#else
byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
if (_videoMode.screenWidth == pitch && pitch == w) {
@@ -909,10 +997,10 @@ void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int
dst += _videoMode.screenWidth;
} while (--h);
}
+#endif
// Unlock the screen surface
SDL_UnlockSurface(_screen);
-#endif
}
Graphics::Surface *OSystem_SDL::lockScreen() {
@@ -926,24 +1014,16 @@ Graphics::Surface *OSystem_SDL::lockScreen() {
_screenIsLocked = true;
// Try to lock the screen surface
-#ifdef ENABLE_16BIT
- if (SDL_LockSurface(_screen16) == -1)
-#else
if (SDL_LockSurface(_screen) == -1)
-#endif
error("SDL_LockSurface failed: %s", SDL_GetError());
-#ifdef ENABLE_16BIT
- _framebuffer.pixels = _screen16->pixels;
- _framebuffer.w = _screen16->w;
- _framebuffer.h = _screen16->h;
- _framebuffer.pitch = _screen16->pitch;
- _framebuffer.bytesPerPixel = 2;
-#else
_framebuffer.pixels = _screen->pixels;
_framebuffer.w = _screen->w;
_framebuffer.h = _screen->h;
_framebuffer.pitch = _screen->pitch;
+#ifdef ENABLE_16BIT
+ _framebuffer.bytesPerPixel = _screenFormat.bytesPerPixel;
+#else
_framebuffer.bytesPerPixel = 1;
#endif
@@ -958,11 +1038,7 @@ void OSystem_SDL::unlockScreen() {
_screenIsLocked = false;
// Unlock the screen surface
-#ifdef ENABLE_16BIT
- SDL_UnlockSurface(_screen16);
-#else
SDL_UnlockSurface(_screen);
-#endif
// Trigger a full screen update
_forceFull = true;
@@ -1133,17 +1209,17 @@ int16 OSystem_SDL::getWidth() {
void OSystem_SDL::setPalette(const byte *colors, uint start, uint num) {
assert(colors);
+#ifdef ENABLE_16BIT
+ if (_screenFormat.bytesPerPixel > 1)
+ return; //not using a paletted pixel format
+#endif
+
// Setting the palette before _screen is created is allowed - for now -
// since we don't actually set the palette until the screen is updated.
// But it could indicate a programming error, so let's warn about it.
-#ifdef ENABLE_16BIT
- if (!_screen16)
- warning("OSystem_SDL::setPalette: _screen16 == NULL");
-#else
if (!_screen)
warning("OSystem_SDL::setPalette: _screen == NULL");
-#endif
const byte *b = colors;
uint i;
@@ -1267,11 +1343,7 @@ void OSystem_SDL::clearOverlay() {
dst.x = dst.y = 1;
src.w = dst.w = _videoMode.screenWidth;
src.h = dst.h = _videoMode.screenHeight;
-#ifdef ENABLE_16BIT
- if (SDL_BlitSurface(_screen16, &src, _tmpscreen, &dst) != 0)
-#else
if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
-#endif
error("SDL_BlitSurface failed: %s", SDL_GetError());
SDL_LockSurface(_tmpscreen);
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 3e8cefc86a..3ec4da1196 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -197,7 +197,8 @@ OSystem_SDL::OSystem_SDL()
#endif
_hwscreen(0), _screen(0), _tmpscreen(0),
#ifdef ENABLE_16BIT
- _screen16(0), _cursorBitDepth(8),
+ _screenFormat(getPixelFormat(Graphics::kFormat8Bit)),
+ _cursorBitDepth(8),
#endif
_overlayVisible(false),
_overlayscreen(0), _tmpscreen2(0),
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 22d3d41b00..513ad73934 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -81,6 +81,22 @@ public:
void beginGFXTransaction(void);
TransactionError endGFXTransaction(void);
+#ifdef ENABLE_16BIT
+ // Find a compatible format from the list of formats supported by the engine
+ // Fallback to CLUT8 if none found
+ virtual Graphics::ColorFormat findCompatibleFormat(Common::List<Graphics::ColorFormat> formatList);
+
+ // Set the depth and format of the video bitmap
+ // Typically, CLUT8
+ virtual void initFormat(Graphics::ColorFormat format);
+
+ // Game screen
+ virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; }
+
+ //Create a Graphics::PixelFormat to describe the requested color mode
+ virtual Graphics::PixelFormat getPixelFormat(Graphics::ColorFormat format);
+#endif
+
// Set the size of the video bitmap.
// Typically, 320x200
virtual void initSize(uint w, uint h); // overloaded by CE backend
@@ -179,11 +195,6 @@ public:
// Overlay
virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
-#ifdef ENABLE_16BIT
- // Game screen
- virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; }
-#endif
-
virtual void showOverlay();
virtual void hideOverlay();
virtual void clearOverlay();
@@ -239,11 +250,6 @@ protected:
SDL_Surface *_screen;
#ifdef ENABLE_16BIT
Graphics::PixelFormat _screenFormat;
-
- //HACK This is a temporary hack to get 16-bit graphics
- //displaying quickly, which will be removed in favor of
- //configuring the format of _screen on a per-game basis
- SDL_Surface *_screen16;
#endif
// temporary screen (for scalers)
@@ -278,6 +284,9 @@ protected:
bool needHotswap;
bool needUpdatescreen;
bool normal1xScaler;
+#ifdef ENABLE_16BIT
+ bool formatChanged;
+#endif
};
TransactionDetails _transactionDetails;
@@ -292,6 +301,9 @@ protected:
int screenWidth, screenHeight;
int overlayWidth, overlayHeight;
+#ifdef ENABLE_16BIT
+ Graphics::ColorFormat format;
+#endif
};
VideoState _videoMode, _oldVideoMode;