diff options
| -rw-r--r-- | backends/graphics/opengl/gltexture.cpp | 57 | ||||
| -rw-r--r-- | backends/graphics/opengl/gltexture.h | 37 | ||||
| -rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 347 | ||||
| -rw-r--r-- | backends/graphics/opengl/opengl-graphics.h | 38 | ||||
| -rw-r--r-- | backends/graphics/openglsdl/openglsdl-graphics.cpp | 29 | ||||
| -rw-r--r-- | backends/graphics/openglsdl/openglsdl-graphics.h | 3 | 
6 files changed, 377 insertions, 134 deletions
diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp index 98291edfac..188386d0ab 100644 --- a/backends/graphics/opengl/gltexture.cpp +++ b/backends/graphics/opengl/gltexture.cpp @@ -56,18 +56,22 @@ static GLuint nextHigher2(GLuint v) {  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 @@ GLTexture::GLTexture(byte bpp, GLenum format, GLenum type)  	_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 @@ void GLTexture::allocBuffer(GLuint w, GLuint h) {  		_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 @@ void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {  	};  	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 @@ void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {  	};  	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();  } diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h index abdb7eceaa..73771fda91 100644 --- a/backends/graphics/opengl/gltexture.h +++ b/backends/graphics/opengl/gltexture.h @@ -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; } + +	/** +	 * 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 @@ protected:  	const GLenum _glFormat;  	const GLenum _glType; -	Graphics::Surface _surface;  	GLuint _realWidth;  	GLuint _realHeight;  	GLuint _textureName;  	GLuint _textureWidth;  	GLuint _textureHeight; -	bool _refresh;  	GLint _filter; +	bool _refresh;  }; diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 5bb496d1ba..6ba4fed474 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -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 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {  	free(_gamePalette);  	free(_cursorPalette); -	if (_cursorData != NULL) -		free(_cursorData);  	if (_gameTexture != NULL)  		delete _gameTexture; @@ -80,11 +78,19 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {  //  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 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {  			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 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {  		}  		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 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)  	// Save the screen palette  	memcpy(_gamePalette + start * 4, colors, num * 4); +	_screenNeedsRedraw = true; +  	if (_cursorPaletteDisabled)  		_cursorNeedsRedraw = true;  } @@ -326,45 +334,65 @@ void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) {  }  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]; - -		// 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; -		} - -		// Update the texture -		_gameTexture->updateBuffer(surface, w * 3, x, y, w, h); +	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); + +	// 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; +	} -		// 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::clearFocusRectangle() {  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 @@ Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {  }  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 @@ void OpenGLGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch  	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 @@ void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int  #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 @@ void OpenGLGraphicsManager::disableCursorPalette(bool disable) {  	_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 @@ void OpenGLGraphicsManager::refreshCursor() {  			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 @@ void OpenGLGraphicsManager::refreshCursor() {  	}  } -// -// 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 @@ void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat,  		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 @@ void OpenGLGraphicsManager::internUpdateScreen() {  	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::initGL() {  }  void OpenGLGraphicsManager::loadTextures() { +#ifdef USE_RGB_COLOR +	if (_transactionDetails.formatChanged && _gameTexture) +		delete _gameTexture; +#endif +  	if (!_gameTexture) {  		byte bpp;  		GLenum format; @@ -679,6 +850,21 @@ void OpenGLGraphicsManager::loadTextures() {  	_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 @@ void OpenGLGraphicsManager::setScale(int newScale) {  	_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); diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index e366216a8c..a372cb9d0d 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -126,12 +126,18 @@ protected:  	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 @@ protected:  	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 @@ protected:  	// Overlay  	//  	GLTexture* _overlayTexture; -	bool _overlayVisible; +	Graphics::Surface _overlayData;  	Graphics::PixelFormat _overlayFormat; +	bool _overlayVisible; +	bool _overlayNeedsRedraw; +	Common::Rect _overlayDirtyRect; +	 +	virtual void refreshOverlay();  	//  	// Mouse @@ -191,21 +207,22 @@ protected:  		// 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 @@ protected:  	bool _cursorPaletteDisabled;  	MousePos _cursorState;  	bool _cursorVisible; -	byte *_cursorData;  	uint32 _cursorKeyColor;  	int _cursorTargetScale;  	bool _cursorNeedsRedraw; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index aa0a9aa717..6f2ba0df9c 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -44,6 +44,28 @@ OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() {  } + +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 @@ void OpenGLSdlGraphicsManager::internUpdateScreen() {  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 @@ bool OpenGLSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {  #endif  		internUpdateScreen();  		return true; -	}*/ +	}  	// Ctrl-Alt-f toggles antialiasing  	if (key == 'f') { @@ -329,6 +351,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {  			_videoMode.hardwareHeight = event.mouse.y;  			_screenResized = true;  			_transactionDetails.sizeChanged = true; +			_transactionDetails.newContext = true;  		endGFXTransaction();  		return true; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index b0bf12cd4d..f11782131c 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -42,6 +42,9 @@ public:  	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  | 
