[Scummvm-cvs-logs] SF.net SVN: scummvm:[51234] scummvm/branches/gsoc2010-opengl/backends/ graphics/opengl

vgvgf at users.sourceforge.net vgvgf at users.sourceforge.net
Sat Jul 24 07:54:51 CEST 2010


Revision: 51234
          http://scummvm.svn.sourceforge.net/scummvm/?rev=51234&view=rev
Author:   vgvgf
Date:     2010-07-24 05:54:51 +0000 (Sat, 24 Jul 2010)

Log Message:
-----------
OPENGL: Redesign blitting system. Add basics for aspect correction.

Removed the extra surface in GLTexture. Now there are copies of the texture data in their original format (so engine can get the original data when lockScreen or grabOverlay is called). This copies will be updated when the engine calls a function that modifies the game screen/overlay, and the textures will be marked as dirty. When updating screen, the textures will be updated from the copies data if they are dirty.

Modified Paths:
--------------
    scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/gltexture.cpp
    scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/gltexture.h
    scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/opengl-graphics.cpp
    scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/opengl-graphics.h
    scummvm/branches/gsoc2010-opengl/backends/graphics/openglsdl/openglsdl-graphics.cpp
    scummvm/branches/gsoc2010-opengl/backends/graphics/openglsdl/openglsdl-graphics.h

Modified: scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/gltexture.cpp
===================================================================
--- scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/gltexture.cpp	2010-07-24 02:07:35 UTC (rev 51233)
+++ scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/gltexture.cpp	2010-07-24 05:54:51 UTC (rev 51234)
@@ -56,18 +56,22 @@
 void GLTexture::initGLExtensions() {
 	static bool inited = false;
 
+	// Return if extensions already checked
 	if (inited)
 		return;
 
+	// Get a string with all extensions
 	const char* ext_string =
 		reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
 	CHECK_GL_ERROR();
 	Common::StringTokenizer tokenizer(ext_string, " ");
+	// Iterate all string tokens
 	while (!tokenizer.empty()) {
 		Common::String token = tokenizer.nextToken();
 		if (token == "GL_ARB_texture_non_power_of_two")
 			npot_supported = true;
 	}
+
 	inited = true;
 }
 
@@ -83,31 +87,21 @@
 	_refresh(false),
 	_filter(GL_NEAREST) {
 
-	// Generates the texture ID for GL
+	// Generate the texture ID
 	glGenTextures(1, &_textureName); CHECK_GL_ERROR();
-
-	// This all gets reset later in allocBuffer:
-	_surface.w = 0;
-	_surface.h = 0;
-	_surface.pitch = 0;
-	_surface.pixels = NULL;
-	_surface.bytesPerPixel = 0;
 }
 
 GLTexture::~GLTexture() {
+	// Delete the texture
 	glDeleteTextures(1, &_textureName); CHECK_GL_ERROR();
 }
 
 void GLTexture::refresh() {
-	// Generates the texture ID for GL
+	// Generate the texture ID
 	glGenTextures(1, &_textureName); CHECK_GL_ERROR();
 	_refresh = true;
 }
 
-void GLTexture::refreshBuffer() {
-	updateBuffer(_surface.pixels, _surface.pitch, 0, 0, _surface.w, _surface.h);
-}
-
 void GLTexture::allocBuffer(GLuint w, GLuint h) {
 	_realWidth = w;
 	_realHeight = h;
@@ -124,62 +118,47 @@
 		_textureHeight = nextHigher2(h);
 	}
 
-	// Allocate room for the texture now, but pixel data gets uploaded
-	// later (perhaps with multiple TexSubImage2D operations).
+	// Select this OpenGL texture
 	glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
+
+	// Set the texture parameters
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _filter); CHECK_GL_ERROR();
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _filter); CHECK_GL_ERROR();
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR();
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR();
+
+	// Allocate room for the texture
 	glTexImage2D(GL_TEXTURE_2D, 0, _glFormat,
 		     _textureWidth, _textureHeight, 0, _glFormat, _glType, NULL); CHECK_GL_ERROR();
 
-	if (_surface.w != _textureWidth || _surface.h != _textureHeight)
-		_surface.create(_textureWidth, _textureHeight, _bytesPerPixel);
-	else if (_refresh)
-		refreshBuffer();
-
 	_refresh = false;
 }
 
 void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLuint w, GLuint h) {
+	// Select this OpenGL texture
 	glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
 
+	// Check if the buffer has its data contiguously
 	if (static_cast<int>(w) * _bytesPerPixel == pitch) {
 		glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h,
 						_glFormat, _glType, buf); CHECK_GL_ERROR();
-		if (buf != _surface.pixels)
-			memcpy(_surface.getBasePtr(x, y), buf, h * pitch);
 	} else {
+		// Update the texture row by row
 		const byte *src = static_cast<const byte *>(buf);
 		do {
 			glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
 							w, 1, _glFormat, _glType, src); CHECK_GL_ERROR();
-			if (buf != _surface.pixels)
-				memcpy(_surface.getBasePtr(x, y), src, w * _bytesPerPixel);
 			++y;
 			src += pitch;
 		} while (--h);
 	}
 }
 
-void GLTexture::fillBuffer(uint32 x) {
-	if (_bytesPerPixel == 1) 
-		memset(_surface.pixels, x, _surface.w * _surface.h);
-	else {
-		for (int i = 0; i < _surface.w * _surface.h; i++) {
-			memcpy(_surface.pixels, &x, _bytesPerPixel);
-		}
-	}
-
-	glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
-	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _surface.w, _surface.h,
-		_glFormat, _glType, _surface.pixels);  CHECK_GL_ERROR();
-}
-
 void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
+	// Select this OpenGL texture
 	glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR();
 
+	// Calculate the texture rect that will be drawn
 	const GLfloat texWidth = (GLfloat)_realWidth / _textureWidth;//xdiv(_surface.w, _textureWidth);
 	const GLfloat texHeight = (GLfloat)_realHeight / _textureHeight;//xdiv(_surface.h, _textureHeight);
 	const GLfloat texcoords[] = {
@@ -190,6 +169,7 @@
 	};
 	glTexCoordPointer(2, GL_FLOAT, 0, texcoords); CHECK_GL_ERROR();
 
+	// Calculate the screen rect where the texture will be drawn
 	const GLshort vertices[] = {
 		x,	   y,
 		x + w, y,
@@ -198,6 +178,7 @@
 	};
 	glVertexPointer(2, GL_SHORT, 0, vertices); CHECK_GL_ERROR();
 
+	// Draw the texture to the screen buffer
 	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); CHECK_GL_ERROR();
 }
 

Modified: scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/gltexture.h
===================================================================
--- scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/gltexture.h	2010-07-24 02:07:35 UTC (rev 51233)
+++ scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/gltexture.h	2010-07-24 05:54:51 UTC (rev 51234)
@@ -53,28 +53,50 @@
  */
 class GLTexture {
 public:
+	/**
+	 * Initialize OpenGL Extensions
+	 */
 	static void initGLExtensions();
 
 	GLTexture(byte bpp, GLenum format, GLenum type);
 	virtual ~GLTexture();
 
+	/**
+	 * Refresh the texture after a context change. The
+	 * process will be completed on next allocBuffer call.
+	 */
 	virtual void refresh();
-	virtual void refreshBuffer();
 
+	/**
+	 * Allocates memory needed for the given size.
+	 */
 	virtual void allocBuffer(GLuint width, GLuint height);
-	virtual void fillBuffer(uint32 x);
+
+	/**
+	 * Updates the texture pixels.
+	 */
 	virtual void updateBuffer(const void *buf, int pitch, GLuint x, GLuint y,
 		GLuint w, GLuint h);
 
-	virtual void drawTexture() { drawTexture(0, 0, _realWidth, _realHeight); }
+	/**
+	 * Draws the texture to the screen buffer.
+	 */
 	virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h);
 
-	Graphics::Surface *getSurface() { return &_surface; }
+	/**
+	 * Get the texture width.
+	 */
+	GLuint getWidth() const { return _realWidth; }
 
-	GLuint getWidth() const { return _realWidth; }
+	/**
+	 * Get the texture height.
+	 */
 	GLuint getHeight() const { return _realHeight; }
-	GLuint getTextureName() const { return _textureName; }
 
+	/**
+	 * Set the texture filter.
+	 * GL_NEAREST or GL_LINEAR should be passed.
+	 */
 	void setFilter(GLint filter) { _filter = filter; }
 
 protected:
@@ -82,12 +104,11 @@
 	const GLenum _glFormat;
 	const GLenum _glType;
 
-	Graphics::Surface _surface;
 	GLuint _realWidth;
 	GLuint _realHeight;
 	GLuint _textureName;
 	GLuint _textureWidth;
 	GLuint _textureHeight;
+	GLint _filter;
 	bool _refresh;
-	GLint _filter;
 };

Modified: scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/opengl-graphics.cpp
===================================================================
--- scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/opengl-graphics.cpp	2010-07-24 02:07:35 UTC (rev 51233)
+++ scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/opengl-graphics.cpp	2010-07-24 05:54:51 UTC (rev 51234)
@@ -33,20 +33,20 @@
 OpenGLGraphicsManager::OpenGLGraphicsManager()
 	:
 	_gameTexture(0), _overlayTexture(0), _cursorTexture(0),
-	_screenChangeCount(0),
+	_screenChangeCount(0), _screenNeedsRedraw(false),
 	_currentShakePos(0), _newShakePos(0),
-	_overlayVisible(false),
+	_overlayVisible(false), _overlayNeedsRedraw(false),
 	_transactionMode(kTransactionNone),
 	_cursorNeedsRedraw(false), _cursorPaletteDisabled(true),
-	_cursorVisible(false), _cursorData(0), _cursorKeyColor(0),
+	_cursorVisible(false), _cursorKeyColor(0),
 	_cursorTargetScale(1) {
 
 	memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
 	memset(&_videoMode, 0, sizeof(_videoMode));
 	memset(&_transactionDetails, 0, sizeof(_transactionDetails));
 
-	_videoMode.mode = OpenGL::GFX_NORMAL;
-	_videoMode.scaleFactor = 1;
+	_videoMode.mode = OpenGL::GFX_DOUBLESIZE;
+	_videoMode.scaleFactor = 2;
 	_videoMode.fullscreen = false;
 	_videoMode.antialiasing = false;
 
@@ -64,8 +64,6 @@
 
 	free(_gamePalette);
 	free(_cursorPalette);
-	if (_cursorData != NULL)
-		free(_cursorData);
 
 	if (_gameTexture != NULL)
 		delete _gameTexture;
@@ -80,11 +78,19 @@
 //
 
 bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
-	return (f == OSystem::kFeatureCursorHasPalette);
+	return
+		(f == OSystem::kFeatureAspectRatioCorrection) ||
+		(f == OSystem::kFeatureCursorHasPalette);
 }
 
 void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
-
+	switch (f) {
+	case OSystem::kFeatureAspectRatioCorrection:
+		setAspectRatioCorrection(enable ? -1 : 0);
+		break;
+	default:
+		break;
+	}
 }
 
 bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
@@ -225,10 +231,10 @@
 			errors |= OSystem::kTransactionFullscreenFailed;
 
 			_videoMode.fullscreen = _oldVideoMode.fullscreen;
-		/*} else if (_videoMode.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) {
+		} else if (_videoMode.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) {
 			errors |= OSystem::kTransactionAspectRatioFailed;
 
-			_videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection;*/
+			_videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection;
 		} else if (_videoMode.mode != _oldVideoMode.mode) {
 			errors |= OSystem::kTransactionModeSwitchFailed;
 
@@ -251,7 +257,7 @@
 		}
 
 		if (_videoMode.fullscreen == _oldVideoMode.fullscreen &&
-			//_videoMode.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection &&
+			_videoMode.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection &&
 			_videoMode.mode == _oldVideoMode.mode &&
 			_videoMode.screenWidth == _oldVideoMode.screenWidth &&
 		   	_videoMode.screenHeight == _oldVideoMode.screenHeight) {
@@ -310,6 +316,8 @@
 	// Save the screen palette
 	memcpy(_gamePalette + start * 4, colors, num * 4);
 
+	_screenNeedsRedraw = true;
+
 	if (_cursorPaletteDisabled)
 		_cursorNeedsRedraw = true;
 }
@@ -326,45 +334,65 @@
 }
 
 void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
-	if (_screenFormat == Graphics::PixelFormat::createFormatCLUT8()) {
-		// Create a temporary RGBA888 surface
-		byte *surface = new byte[w * h * 3];
+	assert(x >= 0 && x < _screenData.w);
+	assert(y >= 0 && y < _screenData.h);
+	assert(h > 0 && y + h <= _screenData.h);
+	assert(w > 0 && x + w <= _screenData.w);
 
-		// Convert the paletted buffer to RGBA888
-		const byte *src = buf;
-		byte *dst = surface;
-		for (int i = 0; i < h; i++) {
-			for (int j = 0; j < w; j++) {
-				dst[0] = _gamePalette[src[j] * 4];
-				dst[1] = _gamePalette[src[j] * 4 + 1];
-				dst[2] = _gamePalette[src[j] * 4 + 2];
-				dst += 3;
-			}
-			src += pitch;
-		}
+	// Copy buffer data to game screen internal buffer
+	const byte *src = buf;
+	byte *dst = (byte *)_screenData.pixels + y * _screenData.pitch;
+	for (int i = 0; i < h; i++) {
+		memcpy(dst + x * _screenData.bytesPerPixel, src, w * _screenData.bytesPerPixel);
+		src += pitch;
+		dst += _screenData.pitch;
+	}
 
-		// Update the texture
-		_gameTexture->updateBuffer(surface, w * 3, x, y, w, h);
-
-		// Free the temp surface
-		delete[] surface;
-	} else
-		_gameTexture->updateBuffer(buf, pitch, x, y, w, h);
+	if (!_screenNeedsRedraw) {
+		const Common::Rect dirtyRect(x, y, x + w, y + h);
+		_screenDirtyRect.extend(dirtyRect);
+	}
 }
 
 Graphics::Surface *OpenGLGraphicsManager::lockScreen() {
-	return _gameTexture->getSurface();
+	return &_screenData;
 }
 
 void OpenGLGraphicsManager::unlockScreen() {
-	_gameTexture->refreshBuffer();
+	_screenNeedsRedraw = true;
 }
 
 void OpenGLGraphicsManager::fillScreen(uint32 col) {
 	if (_gameTexture == NULL)
 		return;
 
-	_gameTexture->fillBuffer(col);
+	if (_screenFormat.bytesPerPixel == 1) {
+		memset(_screenData.pixels, col, _screenData.h * _screenData.pitch);
+	} else if (_screenFormat.bytesPerPixel == 2) {
+		uint16 *pixels = (uint16 *)_screenData.pixels;
+		uint16 col16 = (uint16)col;
+		for (int i = 0; i < _screenData.w * _screenData.h; i++) {
+			pixels[i] = col16;
+		}
+	} else if (_screenFormat.bytesPerPixel == 3) {
+		uint8 *pixels = (uint8 *)_screenData.pixels;
+		byte r =  (col >> 16) & 0xFF;
+		byte g =  (col >> 8) & 0xFF;
+		byte b =  col & 0xFF;
+		for (int i = 0; i < _screenData.w * _screenData.h; i++) {
+			pixels[0] = r;
+			pixels[1] = g;
+			pixels[2] = b;
+			pixels += 3;
+		}
+	} else if (_screenFormat.bytesPerPixel == 4) {
+		uint32 *pixels = (uint32 *)_screenData.pixels;
+		for (int i = 0; i < _screenData.w * _screenData.h; i++) {
+			pixels[i] = col;
+		}
+	}
+
+	_screenNeedsRedraw = true;
 }
 
 void OpenGLGraphicsManager::updateScreen() {
@@ -392,13 +420,23 @@
 void OpenGLGraphicsManager::showOverlay() {
 	assert (_transactionMode == kTransactionNone);
 
+	if (_overlayVisible)
+		return;
+
 	_overlayVisible = true;
+
+	clearOverlay();
 }
 
 void OpenGLGraphicsManager::hideOverlay() {
 	assert (_transactionMode == kTransactionNone);
 
+	if (!_overlayVisible)
+		return;
+
 	_overlayVisible = false;
+
+	clearOverlay();
 }
 
 Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {
@@ -406,21 +444,18 @@
 }
 
 void OpenGLGraphicsManager::clearOverlay() {
-	_overlayTexture->fillBuffer(0);
+	memset(_overlayData.pixels, 0, _overlayData.h * _overlayData.pitch);
+	_overlayNeedsRedraw = true;
 }
 
 void OpenGLGraphicsManager::grabOverlay(OverlayColor *buf, int pitch) {
-	const Graphics::Surface *surface = _overlayTexture->getSurface();
-	assert(surface->bytesPerPixel == sizeof(buf[0]));
-	uint w = _overlayTexture->getWidth();
-	uint h = _overlayTexture->getHeight();
-	const byte *src = (byte *)surface->pixels;
-	do {
-		//memset(buf, 0, w * sizeof(buf[0]));
-		memcpy(buf, src, w * sizeof(buf[0]));
+	assert(_overlayData.bytesPerPixel == sizeof(buf[0]));
+	const byte *src = (byte *)_overlayData.pixels;
+	for (int i = 0; i < _overlayData.h; i++) {
+		memcpy(buf, src, _overlayData.pitch);
 		buf += pitch;
-		src += surface->pitch;
-	} while (--h);
+		src += _overlayData.pitch;
+	}
 }
 
 void OpenGLGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
@@ -429,7 +464,40 @@
 	if (_overlayTexture == NULL)
 		return;
 
-	_overlayTexture->updateBuffer(buf, pitch * sizeof(buf[0]), x, y, w, h);
+	// Clip the coordinates
+	if (x < 0) {
+		w += x;
+		buf -= x;
+		x = 0;
+	}
+
+	if (y < 0) {
+		h += y; buf -= y * pitch;
+		y = 0;
+	}
+
+	if (w > _overlayData.w - x)
+		w = _overlayData.w - x;
+
+	if (h > _overlayData.h - y)
+		h = _overlayData.h - y;
+
+	if (w <= 0 || h <= 0)
+		return;
+
+	// Copy buffer data to internal overlay surface
+	const byte *src = (byte *)buf;
+	byte *dst = (byte *)_overlayData.pixels + y * _overlayData.pitch;
+	for (int i = 0; i < h; i++) {
+		memcpy(dst + x * _overlayData.bytesPerPixel, src, w * _overlayData.bytesPerPixel);
+		src += pitch * sizeof(buf[0]);
+		dst += _overlayData.pitch;
+	}
+
+	if (!_overlayNeedsRedraw) {
+		const Common::Rect dirtyRect(x, y, x + w, y + h);
+		_overlayDirtyRect.extend(dirtyRect);
+	}
 }
 
 int16 OpenGLGraphicsManager::getOverlayHeight() {
@@ -474,9 +542,8 @@
 #endif
 
 	// Save cursor data
-	free(_cursorData);
-	_cursorData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel);
-	memcpy(_cursorData, buf, w * h * _cursorFormat.bytesPerPixel);
+	_cursorData.create(w, h, _cursorFormat.bytesPerPixel);
+	memcpy(_cursorData.pixels, buf, h * _cursorData.pitch);
 
 	// Set cursor info
 	_cursorState.w = w;
@@ -503,10 +570,106 @@
 	_cursorNeedsRedraw = true;
 }
 
+//
+// Misc
+//
+
+void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
+
+}
+
+//
+// Intern
+//
+
+void OpenGLGraphicsManager::refreshGameScreen() {
+	if (_screenNeedsRedraw)
+		_screenDirtyRect = Common::Rect(0, 0, _screenData.w, _screenData.h);
+
+	int x = _screenDirtyRect.left;
+	int y = _screenDirtyRect.top;
+	int w = _screenDirtyRect.width();
+	int h = _screenDirtyRect.height();
+
+	if (_screenData.bytesPerPixel == 1) {
+		// Create a temporary RGB888 surface
+		byte *surface = new byte[w * h * 3];
+
+		// Convert the paletted buffer to RGB888
+		const byte *src = (byte *)_screenData.pixels + y * _screenData.pitch;
+		src += x * _screenData.bytesPerPixel;
+		byte *dst = surface;
+		for (int i = 0; i < h; i++) {
+			for (int j = 0; j < w; j++) {
+				dst[0] = _gamePalette[src[j] * 4];
+				dst[1] = _gamePalette[src[j] * 4 + 1];
+				dst[2] = _gamePalette[src[j] * 4 + 2];
+				dst += 3;
+			}
+			src += _screenData.pitch;
+		}
+
+		// Update the texture
+		_gameTexture->updateBuffer(surface, w * 3, x, y, w, h);
+
+		// Free the temp surface
+		delete[] surface;
+	} else {
+		// Update the texture
+		_gameTexture->updateBuffer((byte *)_screenData.pixels + y * _screenData.pitch +
+			x * _screenData.bytesPerPixel, _screenData.pitch, x, y, w, h);
+	}
+
+	_screenNeedsRedraw = false;
+	_screenDirtyRect = Common::Rect();
+}
+
+void OpenGLGraphicsManager::refreshOverlay() {
+	if (_overlayNeedsRedraw)
+		_overlayDirtyRect = Common::Rect(0, 0, _overlayData.w, _overlayData.h);
+
+	int x = _overlayDirtyRect.left;
+	int y = _overlayDirtyRect.top;
+	int w = _overlayDirtyRect.width();
+	int h = _overlayDirtyRect.height();
+
+	if (_overlayData.bytesPerPixel == 1) {
+		// Create a temporary RGB888 surface
+		byte *surface = new byte[w * h * 3];
+
+		// Convert the paletted buffer to RGB888
+		const byte *src = (byte *)_overlayData.pixels + y * _overlayData.pitch;
+		src += x * _overlayData.bytesPerPixel;
+		byte *dst = surface;
+		for (int i = 0; i < h; i++) {
+			for (int j = 0; j < w; j++) {
+				dst[0] = _gamePalette[src[j] * 4];
+				dst[1] = _gamePalette[src[j] * 4 + 1];
+				dst[2] = _gamePalette[src[j] * 4 + 2];
+				dst += 3;
+			}
+			src += _screenData.pitch;
+		}
+
+		// Update the texture
+		_overlayTexture->updateBuffer(surface, w * 3, x, y, w, h);
+
+		// Free the temp surface
+		delete[] surface;
+	} else {
+		// Update the texture
+		_overlayTexture->updateBuffer((byte *)_overlayData.pixels + y * _overlayData.pitch +
+			x * _overlayData.bytesPerPixel, _overlayData.pitch, x, y, w, h);
+	}
+
+	_overlayNeedsRedraw = false;
+	_overlayDirtyRect = Common::Rect();
+}
+
 void OpenGLGraphicsManager::refreshCursor() {
 	_cursorNeedsRedraw = false;
 
-	if (_cursorFormat == Graphics::PixelFormat::createFormatCLUT8()) {
+	if (_cursorFormat.bytesPerPixel == 1) {
 		// Create a temporary RGBA8888 surface
 		byte *surface = new byte[_cursorState.w * _cursorState.h * 4];
 		memset(surface, 0, _cursorState.w * _cursorState.h * 4);
@@ -519,13 +682,14 @@
 			palette = _cursorPalette;
 
 		// Convert the paletted cursor to RGBA8888
+		const byte *src = (byte *)_cursorData.pixels;
 		byte *dst = surface;
 		for (int i = 0; i < _cursorState.w * _cursorState.h; i++) {
 			// Check for keycolor
-			if (_cursorData[i] != _cursorKeyColor) {
-				dst[0] = palette[_cursorData[i] * 4];
-				dst[1] = palette[_cursorData[i] * 4 + 1];
-				dst[2] = palette[_cursorData[i] * 4 + 2];
+			if (src[i] != _cursorKeyColor) {
+				dst[0] = palette[src[i] * 4];
+				dst[1] = palette[src[i] * 4 + 1];
+				dst[2] = palette[src[i] * 4 + 2];
 				dst[3] = 255;
 			}
 			dst += 4;
@@ -542,18 +706,6 @@
 	}
 }
 
-//
-// Misc
-//
-
-void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) {
-
-}
-
-//
-// Intern
-//
-
 void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &gltype) {
 	if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888
 		bpp = 4;
@@ -575,13 +727,14 @@
 		bpp = 2;
 		glFormat = GL_RGBA;
 		gltype = GL_UNSIGNED_SHORT_4_4_4_4;
-	} else if (pixelFormat == Graphics::PixelFormat::createFormatCLUT8()) {  // CLUT8
-		// If uses a palette, create as RGBA888, then convert
+	} else if (pixelFormat.bytesPerPixel == 1) {  // CLUT8
+		// If uses a palette, create texture as RGB888. The pixel data will be converted
+		// later.
 		bpp = 3;
 		glFormat = GL_RGB;
 		gltype = GL_UNSIGNED_BYTE;
 	} else {
-		error("Not supported format");
+		error("Pixel format not supported");
 	}
 }
 
@@ -590,16 +743,29 @@
 	glClear(GL_COLOR_BUFFER_BIT); CHECK_GL_ERROR();
 
 	// Draw the game screen
+	if (_screenNeedsRedraw || !_screenDirtyRect.isEmpty())
+		// Refresh texture if dirty
+		refreshGameScreen();
+
 	_gameTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
 
 	// Draw the overlay
-	if (_overlayVisible)
+	if (_overlayVisible) {
+
+		// Refresh texture if dirty
+		if (_overlayNeedsRedraw || !_overlayDirtyRect.isEmpty())
+			refreshOverlay();
+
 		_overlayTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
+	}
 
 	// Draw the cursor
 	if (_cursorVisible) {
+
+		// Refresh texture if dirty
 		if (_cursorNeedsRedraw)
 			refreshCursor();
+
 		_cursorTexture->drawTexture(_cursorState.x - _cursorState.hotX,
 		_cursorState.y - _cursorState.hotY,	_cursorState.w, _cursorState.h);
 	}
@@ -640,6 +806,11 @@
 }
 
 void OpenGLGraphicsManager::loadTextures() {
+#ifdef USE_RGB_COLOR
+	if (_transactionDetails.formatChanged && _gameTexture)
+		delete _gameTexture;
+#endif
+
 	if (!_gameTexture) {
 		byte bpp;
 		GLenum format;
@@ -679,6 +850,21 @@
 	_gameTexture->allocBuffer(_videoMode.screenWidth, _videoMode.screenHeight);
 	_overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight);
 	_cursorTexture->allocBuffer(_cursorState.w, _cursorState.h);
+
+	if (_transactionDetails.formatChanged || 
+			_oldVideoMode.screenWidth != _videoMode.screenWidth ||
+			_oldVideoMode.screenHeight != _videoMode.screenHeight)
+		_screenData.create(_videoMode.screenWidth, _videoMode.screenHeight,
+			_screenFormat.bytesPerPixel);
+
+	if (_oldVideoMode.overlayWidth != _videoMode.overlayWidth ||
+		_oldVideoMode.overlayHeight != _videoMode.overlayHeight)
+		_overlayData.create(_videoMode.overlayWidth, _videoMode.overlayHeight,
+			_overlayFormat.bytesPerPixel);
+	
+	_screenNeedsRedraw = true;
+	_overlayNeedsRedraw = true;
+	_cursorNeedsRedraw = true;
 }
 
 bool OpenGLGraphicsManager::loadGFXMode() {
@@ -705,6 +891,19 @@
 	_transactionDetails.sizeChanged = true;
 }
 
+void OpenGLGraphicsManager::setAspectRatioCorrection(int ratio) {
+	if (_oldVideoMode.setup && _oldVideoMode.aspectRatioCorrection == ratio)
+		return;
+
+	if (_transactionMode == kTransactionActive) {
+		if (ratio == -1)
+			_videoMode.aspectRatioCorrection = (_videoMode.aspectRatioCorrection + 1) % 4;
+		else
+			_videoMode.aspectRatioCorrection = ratio;
+		_transactionDetails.needHotswap = true;
+	}
+}
+
 void OpenGLGraphicsManager::adjustMouseEvent(const Common::Event &event) {
 	if (!event.synthetic) {
 		Common::Event newEvent(event);

Modified: scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/opengl-graphics.h
===================================================================
--- scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/opengl-graphics.h	2010-07-24 02:07:35 UTC (rev 51233)
+++ scummvm/branches/gsoc2010-opengl/backends/graphics/opengl/opengl-graphics.h	2010-07-24 05:54:51 UTC (rev 51234)
@@ -126,12 +126,18 @@
 	TransactionDetails _transactionDetails;
 	int _transactionMode;
 
+	enum {
+		kAspectRatioNone,
+		kAspectRatioConserve,
+		kAspectRatio4_3,
+		kAspectRatio16_10
+	};
+
 	struct VideoState {
 		bool setup;
 
 		bool fullscreen;
-		//bool aspectRatioCorrection;
-		//AspectRatio desiredAspectRatio;
+		int aspectRatioCorrection;
 
 		int mode;
 		int scaleFactor;
@@ -153,19 +159,24 @@
 	virtual void unloadGFXMode();
 
 	virtual void setScale(int newScale);
+	virtual void setAspectRatioCorrection(int mode);
 
 	//
 	// Game screen
 	//
 	GLTexture* _gameTexture;
-	Graphics::Surface _lockedScreen;
+	Graphics::Surface _screenData;
 	int _screenChangeCount;
+	bool _screenNeedsRedraw;
+	Common::Rect _screenDirtyRect;
 
 #ifdef USE_RGB_COLOR
 	Graphics::PixelFormat _screenFormat;
 #endif
 	byte *_gamePalette;
 
+	virtual void refreshGameScreen();
+
 	// Shake mode
 	int _currentShakePos;
 	int _newShakePos;
@@ -174,8 +185,13 @@
 	// Overlay
 	//
 	GLTexture* _overlayTexture;
+	Graphics::Surface _overlayData;
+	Graphics::PixelFormat _overlayFormat;
 	bool _overlayVisible;
-	Graphics::PixelFormat _overlayFormat;
+	bool _overlayNeedsRedraw;
+	Common::Rect _overlayDirtyRect;
+	
+	virtual void refreshOverlay();
 
 	//
 	// Mouse
@@ -191,21 +207,22 @@
 
 		// The size and hotspot of the pre-scaled cursor image, in real
 		// coordinates.
-		int16 rW, rH;
-		int16 rHotX, rHotY;
+		//int16 rW, rH;
+		//int16 rHotX, rHotY;
 
 		// The size and hotspot of the pre-scaled cursor image, in game
 		// coordinates.
-		int16 vW, vH;
-		int16 vHotX, vHotY;
+		//int16 vW, vH;
+		//int16 vHotX, vHotY;
 
-		MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0),
+		MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0)/*,
 		             rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
-		             vHotX(0), vHotY(0)
+		             vHotX(0), vHotY(0)*/
 			{ }
 	};
 
 	GLTexture* _cursorTexture;
+	Graphics::Surface _cursorData;
 #ifdef USE_RGB_COLOR
 	Graphics::PixelFormat _cursorFormat;
 #endif
@@ -213,7 +230,6 @@
 	bool _cursorPaletteDisabled;
 	MousePos _cursorState;
 	bool _cursorVisible;
-	byte *_cursorData;
 	uint32 _cursorKeyColor;
 	int _cursorTargetScale;
 	bool _cursorNeedsRedraw;

Modified: scummvm/branches/gsoc2010-opengl/backends/graphics/openglsdl/openglsdl-graphics.cpp
===================================================================
--- scummvm/branches/gsoc2010-opengl/backends/graphics/openglsdl/openglsdl-graphics.cpp	2010-07-24 02:07:35 UTC (rev 51233)
+++ scummvm/branches/gsoc2010-opengl/backends/graphics/openglsdl/openglsdl-graphics.cpp	2010-07-24 05:54:51 UTC (rev 51234)
@@ -44,6 +44,28 @@
 
 }
 
+
+bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) {
+	return
+		(f == OSystem::kFeatureFullscreenMode) ||
+		(f == OSystem::kFeatureIconifyWindow) ||
+		OpenGLGraphicsManager::hasFeature(f);
+}
+
+void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+	switch (f) {
+	case OSystem::kFeatureFullscreenMode:
+		setFullscreenMode(enable);
+		break;
+	case OSystem::kFeatureIconifyWindow:
+		if (enable)
+			SDL_WM_IconifyWindow();
+		break;
+	default:
+		OpenGLGraphicsManager::setFeatureState(f, enable);
+	}
+}
+
 #ifdef USE_RGB_COLOR
 
 const Graphics::PixelFormat RGBList[] = {
@@ -202,9 +224,9 @@
 bool OpenGLSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
 
 	// Ctrl-Alt-a toggles aspect ratio correction
-	/*if (key == 'a') {
+	if (key == 'a') {
 		beginGFXTransaction();
-			setFeatureState(OSystem::kFeatureAspectRatioCorrection, !_videoMode.aspectRatioCorrection);
+			setAspectRatioCorrection(-1);
 		endGFXTransaction();
 #ifdef USE_OSD
 		char buffer[128];
@@ -222,7 +244,7 @@
 #endif
 		internUpdateScreen();
 		return true;
-	}*/
+	}
 
 	// Ctrl-Alt-f toggles antialiasing
 	if (key == 'f') {
@@ -329,6 +351,7 @@
 			_videoMode.hardwareHeight = event.mouse.y;
 			_screenResized = true;
 			_transactionDetails.sizeChanged = true;
+			_transactionDetails.newContext = true;
 		endGFXTransaction();
 		return true;
 

Modified: scummvm/branches/gsoc2010-opengl/backends/graphics/openglsdl/openglsdl-graphics.h
===================================================================
--- scummvm/branches/gsoc2010-opengl/backends/graphics/openglsdl/openglsdl-graphics.h	2010-07-24 02:07:35 UTC (rev 51233)
+++ scummvm/branches/gsoc2010-opengl/backends/graphics/openglsdl/openglsdl-graphics.h	2010-07-24 05:54:51 UTC (rev 51234)
@@ -42,6 +42,9 @@
 	OpenGLSdlGraphicsManager();
 	virtual ~OpenGLSdlGraphicsManager();
 
+	virtual bool hasFeature(OSystem::Feature f);
+	virtual void setFeatureState(OSystem::Feature f, bool enable);
+
 #ifdef USE_RGB_COLOR
 	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
 #endif


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