[Scummvm-cvs-logs] SF.net SVN: scummvm:[41416] scummvm/branches/gsoc2009-16bit

upthorn at users.sourceforge.net upthorn at users.sourceforge.net
Wed Jun 10 07:35:18 CEST 2009


Revision: 41416
          http://scummvm.svn.sourceforge.net/scummvm/?rev=41416&view=rev
Author:   upthorn
Date:     2009-06-10 05:35:18 +0000 (Wed, 10 Jun 2009)

Log Message:
-----------
SDL backend now dynamically generates 8 or 16-bit color surface depending on engine request (using ad-hoc format).

Modified Paths:
--------------
    scummvm/branches/gsoc2009-16bit/backends/platform/sdl/graphics.cpp
    scummvm/branches/gsoc2009-16bit/backends/platform/sdl/sdl.cpp
    scummvm/branches/gsoc2009-16bit/backends/platform/sdl/sdl.h
    scummvm/branches/gsoc2009-16bit/base/main.cpp
    scummvm/branches/gsoc2009-16bit/common/system.h

Modified: scummvm/branches/gsoc2009-16bit/backends/platform/sdl/graphics.cpp
===================================================================
--- scummvm/branches/gsoc2009-16bit/backends/platform/sdl/graphics.cpp	2009-06-10 02:59:53 UTC (rev 41415)
+++ scummvm/branches/gsoc2009-16bit/backends/platform/sdl/graphics.cpp	2009-06-10 05:35:18 UTC (rev 41416)
@@ -97,6 +97,9 @@
 	_transactionDetails.needUpdatescreen = false;
 
 	_transactionDetails.normal1xScaler = false;
+#ifdef ENABLE_16BIT
+	_transactionDetails.formatChanged = false;
+#endif
 
 	_oldVideoMode = _videoMode;
 }
@@ -127,6 +130,12 @@
 			_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 @@
 		}
 	}
 
+#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 @@
 	} else if (_transactionDetails.needUpdatescreen) {
 		setGraphicsModeIntern();
 		internUpdateScreen();
-	}
+	} 
 
 	_transactionMode = kTransactionNone;
 	return (TransactionError)errors;
@@ -339,7 +374,103 @@
 	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 @@
 	//
 	// 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,21 +550,7 @@
 		}
 	}
 
-#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 @@
 }
 
 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 @@
 }
 
 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 @@
 	if (!loadGFXMode()) {
 		unloadGFXMode();
 
-#ifdef ENABLE_16BIT
-		_screen16 = old_screen;
-#else
 		_screen = old_screen;
-#endif
 		_overlayscreen = old_overlayscreen;
 
 		return false;
@@ -588,11 +697,7 @@
 	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 @@
 #endif
 
 	if (!_overlayVisible) {
-#ifdef ENABLE_16BIT
-		origSurf = _screen16;
-#else
 		origSurf = _screen;
-#endif
 		srcSurf = _tmpscreen;
 		width = _videoMode.screenWidth;
 		height = _videoMode.screenHeight;
@@ -823,12 +924,6 @@
 	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 @@
 	}
 
 	// 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 @@
 			dst += _videoMode.screenWidth;
 		} while (--h);
 	}
+#endif
 
 	// Unlock the screen surface
 	SDL_UnlockSurface(_screen);
-#endif
 }
 
 Graphics::Surface *OSystem_SDL::lockScreen() {
@@ -926,24 +1014,16 @@
 	_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 @@
 	_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 @@
 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 @@
 	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);

Modified: scummvm/branches/gsoc2009-16bit/backends/platform/sdl/sdl.cpp
===================================================================
--- scummvm/branches/gsoc2009-16bit/backends/platform/sdl/sdl.cpp	2009-06-10 02:59:53 UTC (rev 41415)
+++ scummvm/branches/gsoc2009-16bit/backends/platform/sdl/sdl.cpp	2009-06-10 05:35:18 UTC (rev 41416)
@@ -197,7 +197,8 @@
 #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),

Modified: scummvm/branches/gsoc2009-16bit/backends/platform/sdl/sdl.h
===================================================================
--- scummvm/branches/gsoc2009-16bit/backends/platform/sdl/sdl.h	2009-06-10 02:59:53 UTC (rev 41415)
+++ scummvm/branches/gsoc2009-16bit/backends/platform/sdl/sdl.h	2009-06-10 05:35:18 UTC (rev 41416)
@@ -81,6 +81,22 @@
 	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 @@
 	// 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 @@
 	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 @@
 		bool needHotswap;
 		bool needUpdatescreen;
 		bool normal1xScaler;
+#ifdef ENABLE_16BIT
+		bool formatChanged;
+#endif
 	};
 	TransactionDetails _transactionDetails;
 
@@ -292,6 +301,9 @@
 
 		int screenWidth, screenHeight;
 		int overlayWidth, overlayHeight;
+#ifdef ENABLE_16BIT
+		Graphics::ColorFormat format;
+#endif
 	};
 	VideoState _videoMode, _oldVideoMode;
 

Modified: scummvm/branches/gsoc2009-16bit/base/main.cpp
===================================================================
--- scummvm/branches/gsoc2009-16bit/base/main.cpp	2009-06-10 02:59:53 UTC (rev 41415)
+++ scummvm/branches/gsoc2009-16bit/base/main.cpp	2009-06-10 05:35:18 UTC (rev 41416)
@@ -226,6 +226,9 @@
 		// Set the user specified graphics mode (if any).
 		system.setGraphicsMode(ConfMan.get("gfx_mode").c_str());
 
+#ifdef ENABLE_16BIT
+		system.initFormat(Graphics::kFormat8Bit);
+#endif
 		system.initSize(320, 200);
 
 		if (ConfMan.hasKey("aspect_ratio"))

Modified: scummvm/branches/gsoc2009-16bit/common/system.h
===================================================================
--- scummvm/branches/gsoc2009-16bit/common/system.h	2009-06-10 02:59:53 UTC (rev 41415)
+++ scummvm/branches/gsoc2009-16bit/common/system.h	2009-06-10 05:35:18 UTC (rev 41416)
@@ -343,7 +343,54 @@
 	 */
 	virtual int getGraphicsMode() const = 0;
 
+#ifdef ENABLE_16BIT
 	/**
+	 * Find a supported color format from a list of requested formats. Typical formats include:
+	 *  CLUT8 (e.g. 256 color, for most games), all backends must provide support for this format
+	 *  RGB555 (e.g. 16-bit color, for later SCUMM HE games)
+	 *  RGB565 (e.g. 16-bit color, for Urban Runner)
+	 *
+	 * These are the pixel formats for which the client code can generates data;
+	 * they are not necessarily equal to the hardware pixel format. For example,
+	 * a backend may perform color lookup of 8-bit graphics before pushing the 
+	 * screen buffer to hardware, or perform transformations of the ARGB color order.
+	 *
+	 * @param formatList	A list of requested pixel formats, ordered by priority
+	 *
+	 * @return a supported ColorFormat from the list, or kFormat8Bit if no supported format was found
+	 */
+	virtual Graphics::ColorFormat findCompatibleFormat(Common::List<Graphics::ColorFormat> formatList) = 0;
+
+	/**
+	 * Set the color format of the virtual screen. Typical formats include:
+	 *  CLUT8 (e.g. 256 color, for most games)
+	 *  RGB555 (e.g. 16-bit color, for later SCUMM HE games)
+	 *  RGB565 (e.g. 16-bit color, for Urban Runner)
+	 *
+	 * This is the pixel format for which the client code generates data;
+	 * this is not necessarily equal to the hardware pixel format. For example,
+	 * a backend may perform color lookup of 8-bit graphics before pushing
+	 * a screen to hardware, or correct the ARGB color order.
+	 *
+	 * @param format	A pixel format that the backend screen will use
+	 */
+	virtual void initFormat(Graphics::ColorFormat format) = 0;
+
+	/**
+	 * Returns the pixel format description of the screen.
+	 * @see Graphics::PixelFormat
+	 */
+	virtual Graphics::PixelFormat getScreenFormat() const = 0;
+
+	/**
+	 * Returns the pixel format description of the requested color mode
+	 * @see Graphics::PixelFormat
+	 */
+	virtual Graphics::PixelFormat getPixelFormat(Graphics::ColorFormat format) = 0;
+
+#endif
+
+	/**
 	 * Set the size of the virtual screen. Typical sizes include:
 	 *  - 320x200 (e.g. for most SCUMM games, and Simon)
 	 *  - 320x240 (e.g. for FM-TOWN SCUMM games)
@@ -608,15 +655,7 @@
 	 */
 	virtual Graphics::PixelFormat getOverlayFormat() const = 0;
 
-#ifdef ENABLE_16BIT
 	/**
-	 * Returns the pixel format description of the game screen.
-	 * @see Graphics::PixelFormat
-	 */
-	virtual Graphics::PixelFormat getScreenFormat() const = 0;
-#endif
-
-	/**
 	 * Reset the overlay.
 	 *
 	 * After calling this method while the overlay mode is active, the user


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list