From 8a6e57cba1c89f922e27bb72201cfda55681f6dc Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 15 Aug 2013 18:53:55 +0200 Subject: BACKENDS: Remove OpenGL and OpenGL SDL backend. This breaks our Tizen port. --- backends/graphics/opengl/glerrorcheck.cpp | 67 - backends/graphics/opengl/glerrorcheck.h | 35 - backends/graphics/opengl/gltexture.cpp | 225 ---- backends/graphics/opengl/gltexture.h | 131 -- backends/graphics/opengl/opengl-graphics.cpp | 1396 -------------------- backends/graphics/opengl/opengl-graphics.h | 351 ----- backends/graphics/openglsdl/openglsdl-graphics.cpp | 677 ---------- backends/graphics/openglsdl/openglsdl-graphics.h | 124 -- 8 files changed, 3006 deletions(-) delete mode 100644 backends/graphics/opengl/glerrorcheck.cpp delete mode 100644 backends/graphics/opengl/glerrorcheck.h delete mode 100644 backends/graphics/opengl/gltexture.cpp delete mode 100644 backends/graphics/opengl/gltexture.h delete mode 100644 backends/graphics/opengl/opengl-graphics.cpp delete mode 100644 backends/graphics/opengl/opengl-graphics.h delete mode 100644 backends/graphics/openglsdl/openglsdl-graphics.cpp delete mode 100644 backends/graphics/openglsdl/openglsdl-graphics.h (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/glerrorcheck.cpp b/backends/graphics/opengl/glerrorcheck.cpp deleted file mode 100644 index 439593577d..0000000000 --- a/backends/graphics/opengl/glerrorcheck.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#if defined(DEBUG) && defined(USE_OPENGL) - -#include "backends/graphics/opengl/glerrorcheck.h" -#include "common/textconsole.h" -#include "common/str.h" - -#ifdef WIN32 -#if defined(ARRAYSIZE) && !defined(_WINDOWS_) -#undef ARRAYSIZE -#endif -#define WIN32_LEAN_AND_MEAN -#include -#undef ARRAYSIZE -#endif - -#if defined(USE_GLES) -#include -#elif defined(MACOSX) -#include -#else -#include -#endif - -static Common::String getGlErrStr(GLenum error) { - switch (error) { - case GL_NO_ERROR: return "GL_NO_ERROR"; - case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; - case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; - case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW"; - case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW"; - case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; - } - - return Common::String::format("(Unknown GL error code 0x%x)", error); -} - -void checkGlError(const char *file, int line) { - GLenum error = glGetError(); - if (error != GL_NO_ERROR) - warning("%s:%d: GL error: %s", file, line, getGlErrStr(error).c_str()); -} - -#endif diff --git a/backends/graphics/opengl/glerrorcheck.h b/backends/graphics/opengl/glerrorcheck.h deleted file mode 100644 index 2d5491bdfd..0000000000 --- a/backends/graphics/opengl/glerrorcheck.h +++ /dev/null @@ -1,35 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#if !defined(DEBUG) - -// If not in debug, do nothing -#define CHECK_GL_ERROR() do {} while (false) - -#else - -// If in debug, check for an error after a GL call -#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__) - -void checkGlError(const char *file, int line); - -#endif diff --git a/backends/graphics/opengl/gltexture.cpp b/backends/graphics/opengl/gltexture.cpp deleted file mode 100644 index ca674563df..0000000000 --- a/backends/graphics/opengl/gltexture.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#if defined(USE_OPENGL) - -#include "backends/graphics/opengl/gltexture.h" -#include "backends/graphics/opengl/glerrorcheck.h" - -#include "common/rect.h" -#include "common/array.h" -#include "common/util.h" -#include "common/tokenizer.h" - -// Supported GL extensions -static bool npot_supported = false; -static bool glext_inited = false; - -/*static inline GLint xdiv(int numerator, int denominator) { - assert(numerator < (1 << 16)); - return (numerator << 16) / denominator; -}*/ - -static GLuint nextHigher2(GLuint v) { - if (v == 0) - return 1; - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return ++v; -} - -void GLTexture::initGLExtensions() { - - // Return if extensions were already checked - if (glext_inited) - return; - - // Get a string with all extensions - const char *ext_string = (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; - } - - glext_inited = true; -} - -GLTexture::GLTexture(byte bpp, GLenum internalFormat, GLenum format, GLenum type) - : - _bytesPerPixel(bpp), - _internalFormat(internalFormat), - _glFormat(format), - _glType(type), - _textureWidth(0), - _textureHeight(0), - _realWidth(0), - _realHeight(0), - _refresh(false), - _filter(GL_NEAREST) { - - // Generate the texture ID - glGenTextures(1, &_textureName); CHECK_GL_ERROR(); -} - -GLTexture::~GLTexture() { - // Delete the texture - glDeleteTextures(1, &_textureName); CHECK_GL_ERROR(); -} - -void GLTexture::refresh() { - // Delete previous texture - glDeleteTextures(1, &_textureName); CHECK_GL_ERROR(); - - // Generate the texture ID - glGenTextures(1, &_textureName); CHECK_GL_ERROR(); - _refresh = true; -} - -void GLTexture::allocBuffer(GLuint w, GLuint h) { - _realWidth = w; - _realHeight = h; - - if (!_refresh) { - if (npot_supported && _filter == GL_LINEAR) { - // Check if we already allocated a correctly-sized buffer - // This is so we don't need to duplicate the last row/column - if (w == _textureWidth && h == _textureHeight) - return; - } else { - // Check if we already have a large enough buffer - if (w <= _textureWidth && h <= _textureHeight) - return; - } - } - - if (npot_supported) { - _textureWidth = w; - _textureHeight = h; - } else { - _textureWidth = nextHigher2(w); - _textureHeight = nextHigher2(h); - } - - // 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, _internalFormat, - _textureWidth, _textureHeight, 0, _glFormat, _glType, NULL); CHECK_GL_ERROR(); - - _refresh = false; -} - -void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLuint w, GLuint h) { - // Skip empty updates. - if (w * h == 0) - return; - - // Select this OpenGL texture - glBindTexture(GL_TEXTURE_2D, _textureName); CHECK_GL_ERROR(); - - // Check if the buffer has its data contiguously - if ((int)w * _bytesPerPixel == pitch) { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, - _glFormat, _glType, buf); CHECK_GL_ERROR(); - } else { - // Update the texture row by row - const byte *src = (const byte *)buf; - GLuint curY = y; - GLuint height = h; - do { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, curY, - w, 1, _glFormat, _glType, src); CHECK_GL_ERROR(); - curY++; - src += pitch; - } while (--height); - } - - // If we're in linear filter mode, repeat the last row/column if the real dimensions - // doesn't match the texture dimensions. - if (_filter == GL_LINEAR) { - if (_realWidth != _textureWidth && x + w == _realWidth) { - const byte *src = (const byte *)buf + (w - 1) * _bytesPerPixel; - GLuint curY = y; - GLuint height = h; - - do { - glTexSubImage2D(GL_TEXTURE_2D, 0, x + w, - curY, 1, 1, _glFormat, _glType, src); CHECK_GL_ERROR(); - - curY++; - src += pitch; - } while (--height); - } - - if (_realHeight != _textureHeight && y + h == _realHeight) { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y + h, - w, 1, _glFormat, _glType, (const byte *)buf + pitch * (h - 1)); 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[] = { - 0, 0, - texWidth, 0, - 0, texHeight, - texWidth, texHeight, - }; - glTexCoordPointer(2, GL_FLOAT, 0, texcoords); CHECK_GL_ERROR(); - - // Calculate the screen rect where the texture will be drawn - const GLshort vertices[] = { - x, y, - (GLshort)(x + w), y, - x, (GLshort)(y + h), - (GLshort)(x + w), (GLshort)(y + 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(); -} - -#endif diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h deleted file mode 100644 index 6ef80923ae..0000000000 --- a/backends/graphics/opengl/gltexture.h +++ /dev/null @@ -1,131 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef BACKENDS_GRAPHICS_OPENGL_GLTEXTURE_H -#define BACKENDS_GRAPHICS_OPENGL_GLTEXTURE_H - -#include "common/scummsys.h" - -#ifdef WIN32 -#if defined(ARRAYSIZE) && !defined(_WINDOWS_) -#undef ARRAYSIZE -#endif -#define WIN32_LEAN_AND_MEAN -#include -#undef ARRAYSIZE -#endif - -// HACK: At this point in Windows platforms, common/util.h has been included -// via common/rect.h (from backends/graphics/sdl/sdl-graphics.h), via -// backends/graphics/openglsdl/openglsdl-graphics.h. Thus, we end up with -// COMMON_UTIL_H defined, and ARRAYSIZE undefined (bad!). Therefore, -// ARRAYSIZE is undefined in openglsdl-graphics.cpp. This is a temporary -// hackish solution fo fix compilation under Windows. -#if !defined(ARRAYSIZE) && defined(COMMON_UTIL_H) -#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0]))) -#endif - -#if defined(TIZEN) -#include -using namespace Tizen::Graphics::Opengl; -#elif defined(USE_GLES) -#include -#elif defined(SDL_BACKEND) -#include -#else -#include -#endif - -#include "graphics/surface.h" - -/** - * OpenGL texture manager class - */ -class GLTexture { -public: - /** - * Initialize OpenGL Extensions - */ - static void initGLExtensions(); - - GLTexture(byte bpp, GLenum internalFormat, GLenum format, GLenum type); - ~GLTexture(); - - /** - * Refresh the texture after a context change. The - * process will be completed on next allocBuffer call. - */ - void refresh(); - - /** - * Allocates memory needed for the given size. - */ - void allocBuffer(GLuint width, GLuint height); - - /** - * Updates the texture pixels. - */ - void updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, - GLuint w, GLuint h); - - /** - * Draws the texture to the screen buffer. - */ - void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); - - /** - * Get the texture width. - */ - GLuint getWidth() const { return _realWidth; } - - /** - * Get the texture height. - */ - GLuint getHeight() const { return _realHeight; } - - /** - * Get the bytes per pixel. - */ - uint getBytesPerPixel() const { return _bytesPerPixel; } - - /** - * Set the texture filter. - * @filter the filter type, GL_NEAREST or GL_LINEAR - */ - void setFilter(GLint filter) { _filter = filter; } - -private: - const byte _bytesPerPixel; - const GLenum _internalFormat; - const GLenum _glFormat; - const GLenum _glType; - - GLuint _realWidth; - GLuint _realHeight; - GLuint _textureName; - GLuint _textureWidth; - GLuint _textureHeight; - GLint _filter; - bool _refresh; -}; - -#endif diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp deleted file mode 100644 index 84be83d524..0000000000 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ /dev/null @@ -1,1396 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#if defined(USE_OPENGL) - -#include "backends/graphics/opengl/opengl-graphics.h" -#include "backends/graphics/opengl/glerrorcheck.h" -#include "common/config-manager.h" -#include "common/file.h" -#include "common/mutex.h" -#include "common/textconsole.h" -#include "common/translation.h" -#ifdef USE_OSD -#include "common/tokenizer.h" -#endif -#include "graphics/font.h" -#include "graphics/fontman.h" - -OpenGLGraphicsManager::OpenGLGraphicsManager() - : -#ifdef USE_OSD - _osdTexture(0), _osdAlpha(0), _osdFadeStartTime(0), _requireOSDUpdate(false), -#endif - _gameTexture(0), _overlayTexture(0), _cursorTexture(0), - _screenChangeCount(1 << (sizeof(int) * 8 - 2)), _screenNeedsRedraw(false), - _shakePos(0), - _overlayVisible(false), _overlayNeedsRedraw(false), - _transactionMode(kTransactionNone), - _cursorNeedsRedraw(false), _cursorPaletteDisabled(true), - _cursorVisible(false), _cursorKeyColor(0), - _cursorDontScale(false), - _formatBGR(false), - _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0) { - - memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); - memset(&_videoMode, 0, sizeof(_videoMode)); - memset(&_transactionDetails, 0, sizeof(_transactionDetails)); - - _videoMode.mode = OpenGL::GFX_NORMAL; - _videoMode.scaleFactor = 2; - _videoMode.fullscreen = ConfMan.getBool("fullscreen"); - _videoMode.antialiasing = false; - - _gamePalette = (byte *)calloc(sizeof(byte) * 3, 256); - _cursorPalette = (byte *)calloc(sizeof(byte) * 3, 256); -} - -OpenGLGraphicsManager::~OpenGLGraphicsManager() { - free(_gamePalette); - free(_cursorPalette); - - _screenData.free(); - _overlayData.free(); - _cursorData.free(); - _osdSurface.free(); - - delete _gameTexture; - delete _overlayTexture; - delete _cursorTexture; -} - -// -// Feature -// - -bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { - return - (f == OSystem::kFeatureAspectRatioCorrection) || - (f == OSystem::kFeatureCursorPalette); -} - -void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { - switch (f) { - case OSystem::kFeatureFullscreenMode: - setFullscreenMode(enable); - break; - - case OSystem::kFeatureAspectRatioCorrection: - _videoMode.aspectRatioCorrection = enable; - _transactionDetails.needRefresh = true; - break; - - case OSystem::kFeatureCursorPalette: - _cursorPaletteDisabled = !enable; - _cursorNeedsRedraw = true; - break; - - default: - break; - } -} - -bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { - switch (f) { - case OSystem::kFeatureFullscreenMode: - return _videoMode.fullscreen; - - case OSystem::kFeatureAspectRatioCorrection: - return _videoMode.aspectRatioCorrection; - - case OSystem::kFeatureCursorPalette: - return !_cursorPaletteDisabled; - - default: - return false; - } -} - -// -// Screen format and modes -// - -static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {"gl1", _s("OpenGL Normal"), OpenGL::GFX_NORMAL}, - {"gl2", _s("OpenGL Conserve"), OpenGL::GFX_CONSERVE}, - {"gl4", _s("OpenGL Original"), OpenGL::GFX_ORIGINAL}, - {0, 0, 0} -}; - -const OSystem::GraphicsMode *OpenGLGraphicsManager::supportedGraphicsModes() { - return s_supportedGraphicsModes; -} - -const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() const { - return s_supportedGraphicsModes; -} - -int OpenGLGraphicsManager::getDefaultGraphicsMode() const { - return OpenGL::GFX_NORMAL; -} - -bool OpenGLGraphicsManager::setGraphicsMode(int mode) { - assert(_transactionMode == kTransactionActive); - - setScale(2); - - if (_oldVideoMode.setup && _oldVideoMode.mode == mode) - return true; - - switch (mode) { - case OpenGL::GFX_NORMAL: - case OpenGL::GFX_CONSERVE: - case OpenGL::GFX_ORIGINAL: - break; - default: - warning("Unknown gfx mode %d", mode); - return false; - } - - _videoMode.mode = mode; - _transactionDetails.needRefresh = true; - - return true; -} - -int OpenGLGraphicsManager::getGraphicsMode() const { - assert(_transactionMode == kTransactionNone); - return _videoMode.mode; -} - -void OpenGLGraphicsManager::resetGraphicsScale() { - setScale(1); -} - -#ifdef USE_RGB_COLOR -Graphics::PixelFormat OpenGLGraphicsManager::getScreenFormat() const { - return _screenFormat; -} -#endif - -void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) { - assert(_transactionMode == kTransactionActive); - -#ifdef USE_RGB_COLOR - Graphics::PixelFormat newFormat; - if (!format) - newFormat = Graphics::PixelFormat::createFormatCLUT8(); - else - newFormat = *format; - - assert(newFormat.bytesPerPixel > 0); - - // Avoid redundant format changes - if (newFormat != _videoMode.format) { - _videoMode.format = newFormat; - _transactionDetails.formatChanged = true; - _screenFormat = newFormat; - } -#endif - - // Avoid redundant res changes - if ((int)width == _videoMode.screenWidth && (int)height == _videoMode.screenHeight) - return; - - _videoMode.screenWidth = width; - _videoMode.screenHeight = height; - - _transactionDetails.sizeChanged = true; -} - -int OpenGLGraphicsManager::getScreenChangeID() const { - return _screenChangeCount; -} - -// -// GFX -// - -void OpenGLGraphicsManager::beginGFXTransaction() { - assert(_transactionMode == kTransactionNone); - - _transactionMode = kTransactionActive; - _transactionDetails.sizeChanged = false; - _transactionDetails.needRefresh = false; - _transactionDetails.needUpdatescreen = false; - _transactionDetails.filterChanged = false; -#ifdef USE_RGB_COLOR - _transactionDetails.formatChanged = false; -#endif - - _oldVideoMode = _videoMode; -} - -OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { - int errors = OSystem::kTransactionSuccess; - - assert(_transactionMode != kTransactionNone); - - if (_transactionMode == kTransactionRollback) { - if (_videoMode.fullscreen != _oldVideoMode.fullscreen) { - errors |= OSystem::kTransactionFullscreenFailed; - - _videoMode.fullscreen = _oldVideoMode.fullscreen; - } else if (_videoMode.mode != _oldVideoMode.mode) { - errors |= OSystem::kTransactionModeSwitchFailed; - - _videoMode.mode = _oldVideoMode.mode; - _videoMode.scaleFactor = _oldVideoMode.scaleFactor; -#ifdef USE_RGB_COLOR - } else if (_videoMode.format != _oldVideoMode.format) { - errors |= OSystem::kTransactionFormatNotSupported; - - _videoMode.format = _oldVideoMode.format; - _screenFormat = _videoMode.format; -#endif - } else if (_videoMode.screenWidth != _oldVideoMode.screenWidth || _videoMode.screenHeight != _oldVideoMode.screenHeight) { - errors |= OSystem::kTransactionSizeChangeFailed; - - _videoMode.screenWidth = _oldVideoMode.screenWidth; - _videoMode.screenHeight = _oldVideoMode.screenHeight; - _videoMode.overlayWidth = _oldVideoMode.overlayWidth; - _videoMode.overlayHeight = _oldVideoMode.overlayHeight; - } - - if (_videoMode.fullscreen == _oldVideoMode.fullscreen && - _videoMode.mode == _oldVideoMode.mode && - _videoMode.screenWidth == _oldVideoMode.screenWidth && - _videoMode.screenHeight == _oldVideoMode.screenHeight) { - - _oldVideoMode.setup = false; - } - } - - if (_transactionDetails.sizeChanged || _transactionDetails.needRefresh) { - unloadGFXMode(); - if (!loadGFXMode()) { - if (_oldVideoMode.setup) { - _transactionMode = kTransactionRollback; - errors |= endGFXTransaction(); - } - } else { - clearOverlay(); - - _videoMode.setup = true; - _screenChangeCount++; - } -#ifdef USE_RGB_COLOR - } else if (_transactionDetails.filterChanged || _transactionDetails.formatChanged) { -#else - } else if (_transactionDetails.filterChanged) { -#endif - loadTextures(); - internUpdateScreen(); - } else if (_transactionDetails.needUpdatescreen) { - internUpdateScreen(); - } - - _transactionMode = kTransactionNone; - return (OSystem::TransactionError)errors; -} - -// -// Screen -// - -int16 OpenGLGraphicsManager::getHeight() { - return _videoMode.screenHeight; -} - -int16 OpenGLGraphicsManager::getWidth() { - return _videoMode.screenWidth; -} - -void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { - assert(colors); - -#ifdef USE_RGB_COLOR - assert(_screenFormat.bytesPerPixel == 1); -#endif - - // Save the screen palette - memcpy(_gamePalette + start * 3, colors, num * 3); - - _screenNeedsRedraw = true; - - if (_cursorPaletteDisabled) - _cursorNeedsRedraw = true; -} - -void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { - assert(colors); - -#ifdef USE_RGB_COLOR - assert(_screenFormat.bytesPerPixel == 1); -#endif - - // Copies current palette to buffer - memcpy(colors, _gamePalette + start * 3, num * 3); -} - -void OpenGLGraphicsManager::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int 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 = (const byte *)buf; - byte *dst = (byte *)_screenData.getBasePtr(x, y); - for (int i = 0; i < h; i++) { - memcpy(dst, src, w * _screenData.format.bytesPerPixel); - src += pitch; - dst += _screenData.pitch; - } - - // Extend dirty area if not full screen redraw is flagged - if (!_screenNeedsRedraw) { - const Common::Rect dirtyRect(x, y, x + w, y + h); - _screenDirtyRect.extend(dirtyRect); - } -} - -Graphics::Surface *OpenGLGraphicsManager::lockScreen() { - return &_screenData; -} - -void OpenGLGraphicsManager::unlockScreen() { - _screenNeedsRedraw = true; -} - -void OpenGLGraphicsManager::fillScreen(uint32 col) { - if (_gameTexture == NULL) - return; - -#ifdef USE_RGB_COLOR - if (_screenFormat.bytesPerPixel == 1) { - memset(_screenData.getPixels(), col, _screenData.h * _screenData.pitch); - } else if (_screenFormat.bytesPerPixel == 2) { - uint16 *pixels = (uint16 *)_screenData.getPixels(); - 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.getPixels(); - 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.getPixels(); - for (int i = 0; i < _screenData.w * _screenData.h; i++) { - pixels[i] = col; - } - } -#else - memset(_screenData.getPixels(), col, _screenData.h * _screenData.pitch); -#endif - _screenNeedsRedraw = true; -} - -void OpenGLGraphicsManager::updateScreen() { - assert(_transactionMode == kTransactionNone); - internUpdateScreen(); -} - -void OpenGLGraphicsManager::setShakePos(int shakeOffset) { - assert(_transactionMode == kTransactionNone); - _shakePos = shakeOffset; -} - -void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect &rect) { -} - -void OpenGLGraphicsManager::clearFocusRectangle() { -} - -// -// Overlay -// - -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 { - return _overlayFormat; -} - -void OpenGLGraphicsManager::clearOverlay() { - // Set all pixels to 0 - memset(_overlayData.getPixels(), 0, _overlayData.h * _overlayData.pitch); - _overlayNeedsRedraw = true; -} - -void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) { - const byte *src = (byte *)_overlayData.getPixels(); - byte *dst = (byte *)buf; - for (int i = 0; i < _overlayData.h; i++) { - // Copy overlay data to buffer - memcpy(dst, src, _overlayData.pitch); - dst += pitch; - src += _overlayData.pitch; - } -} - -void OpenGLGraphicsManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) { - assert(_transactionMode == kTransactionNone); - - if (_overlayTexture == NULL) - return; - - const byte *src = (const byte *)buf; - - // Clip the coordinates - if (x < 0) { - w += x; - src -= x * 2; - x = 0; - } - - if (y < 0) { - h += y; - src -= 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 - byte *dst = (byte *)_overlayData.getBasePtr(0, y); - for (int i = 0; i < h; i++) { - memcpy(dst + x * _overlayData.format.bytesPerPixel, src, w * _overlayData.format.bytesPerPixel); - src += pitch; - dst += _overlayData.pitch; - } - - // Extend dirty area if not full screen redraw is flagged - if (!_overlayNeedsRedraw) { - const Common::Rect dirtyRect(x, y, x + w, y + h); - _overlayDirtyRect.extend(dirtyRect); - } -} - -int16 OpenGLGraphicsManager::getOverlayHeight() { - return _videoMode.overlayHeight; -} - -int16 OpenGLGraphicsManager::getOverlayWidth() { - return _videoMode.overlayWidth; -} - -// -// Cursor -// - -bool OpenGLGraphicsManager::showMouse(bool visible) { - if (_cursorVisible == visible) - return visible; - - bool last = _cursorVisible; - _cursorVisible = visible; - - return last; -} - -void OpenGLGraphicsManager::warpMouse(int x, int y) { - int scaledX = x; - int scaledY = y; - - int16 currentX = _cursorState.x; - int16 currentY = _cursorState.y; - - adjustMousePosition(currentX, currentY); - - // Do not adjust the real screen position, when the current game / overlay - // coordinates match the requested coordinates. This avoids a slight - // movement which might occur otherwise when the mouse is at a subpixel - // position. - if (x == currentX && y == currentY) - return; - - if (_videoMode.mode == OpenGL::GFX_NORMAL) { - if (_videoMode.hardwareWidth != _videoMode.overlayWidth) - scaledX = scaledX * _videoMode.hardwareWidth / _videoMode.overlayWidth; - if (_videoMode.hardwareHeight != _videoMode.overlayHeight) - scaledY = scaledY * _videoMode.hardwareHeight / _videoMode.overlayHeight; - - if (!_overlayVisible) { - scaledX *= _videoMode.scaleFactor; - scaledY *= _videoMode.scaleFactor; - } - } else { - if (_overlayVisible) { - if (_displayWidth != _videoMode.overlayWidth) - scaledX = scaledX * _displayWidth / _videoMode.overlayWidth; - if (_displayHeight != _videoMode.overlayHeight) - scaledY = scaledY * _displayHeight / _videoMode.overlayHeight; - } else { - if (_displayWidth != _videoMode.screenWidth) - scaledX = scaledX * _displayWidth / _videoMode.screenWidth; - if (_displayHeight != _videoMode.screenHeight) - scaledY = scaledY * _displayHeight / _videoMode.screenHeight; - } - - scaledX += _displayX; - scaledY += _displayY; - } - - setMousePosition(scaledX, scaledY); - setInternalMousePosition(scaledX, scaledY); -} - -void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { -#ifdef USE_RGB_COLOR - if (format) - _cursorFormat = *format; - else - _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); -#else - assert(keycolor <= 255); - _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); -#endif - - // Allocate space for cursor data - if (_cursorData.w != w || _cursorData.h != h || - _cursorData.format.bytesPerPixel != _cursorFormat.bytesPerPixel) - _cursorData.create(w, h, _cursorFormat); - - // Save cursor data - memcpy(_cursorData.getPixels(), buf, h * _cursorData.pitch); - - // Set cursor info - _cursorState.w = w; - _cursorState.h = h; - _cursorState.hotX = hotspotX; - _cursorState.hotY = hotspotY; - _cursorKeyColor = keycolor; - _cursorDontScale = dontScale; - _cursorNeedsRedraw = true; - - refreshCursorScale(); -} - -void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) { - assert(colors); - - // Save the cursor palette - memcpy(_cursorPalette + start * 3, colors, num * 3); - - _cursorPaletteDisabled = false; - _cursorNeedsRedraw = true; -} - -// -// Misc -// - -void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { - assert(_transactionMode == kTransactionNone); - assert(msg); - -#ifdef USE_OSD - // Split the message into separate lines. - _osdLines.clear(); - - Common::StringTokenizer tokenizer(msg, "\n"); - while (!tokenizer.empty()) - _osdLines.push_back(tokenizer.nextToken()); - - // Request update of the texture - _requireOSDUpdate = true; - - // Init the OSD display parameters, and the fade out - _osdAlpha = kOSDInitialAlpha; - _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; -#endif -} - -// -// Intern -// - -void OpenGLGraphicsManager::setFullscreenMode(bool enable) { - assert(_transactionMode == kTransactionActive); - - if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable) - return; - - if (_transactionMode == kTransactionActive) { - _videoMode.fullscreen = enable; - _transactionDetails.needRefresh = true; - } -} - -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.format.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.getBasePtr(0, y); - src += x * _screenData.format.bytesPerPixel; - byte *dst = surface; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - dst[0] = _gamePalette[src[j] * 3]; - dst[1] = _gamePalette[src[j] * 3 + 1]; - dst[2] = _gamePalette[src[j] * 3 + 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.getBasePtr(x, y), _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.format.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.getBasePtr(0, y); - src += x * _overlayData.format.bytesPerPixel; - byte *dst = surface; - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - dst[0] = _gamePalette[src[j] * 3]; - dst[1] = _gamePalette[src[j] * 3 + 1]; - dst[2] = _gamePalette[src[j] * 3 + 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.getBasePtr(x, y), _overlayData.pitch, x, y, w, h); - } - - _overlayNeedsRedraw = false; - _overlayDirtyRect = Common::Rect(); -} - -void OpenGLGraphicsManager::refreshCursor() { - _cursorNeedsRedraw = false; - - // Allocate a texture big enough for cursor - _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h); - - // Create a temporary RGBA8888 surface - byte *surface = new byte[_cursorState.w * _cursorState.h * 4]; - memset(surface, 0, _cursorState.w * _cursorState.h * 4); - - byte *dst = surface; - - // Convert the paletted cursor to RGBA8888 - if (_cursorFormat.bytesPerPixel == 1) { - // Select palette - byte *palette; - if (_cursorPaletteDisabled) - palette = _gamePalette; - else - palette = _cursorPalette; - - // Convert the paletted cursor to RGBA8888 - const byte *src = (byte *)_cursorData.getPixels(); - for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { - // Check for keycolor - if (src[i] != _cursorKeyColor) { - dst[0] = palette[src[i] * 3]; - dst[1] = palette[src[i] * 3 + 1]; - dst[2] = palette[src[i] * 3 + 2]; - dst[3] = 255; - } - dst += 4; - } - } else { - const bool gotNoAlpha = (_cursorFormat.aLoss == 8); - - // Convert the RGB cursor to RGBA8888 - if (_cursorFormat.bytesPerPixel == 2) { - const uint16 *src = (uint16 *)_cursorData.getPixels(); - for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { - // Check for keycolor - if (src[i] != _cursorKeyColor) { - _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]); - - if (gotNoAlpha) - dst[3] = 255; - } - dst += 4; - } - } else if (_cursorFormat.bytesPerPixel == 4) { - const uint32 *src = (uint32 *)_cursorData.getPixels(); - for (int i = 0; i < _cursorState.w * _cursorState.h; i++) { - // Check for keycolor - if (src[i] != _cursorKeyColor) { - _cursorFormat.colorToARGB(src[i], dst[3], dst[0], dst[1], dst[2]); - - if (gotNoAlpha) - dst[3] = 255; - } - dst += 4; - } - } - } - - // Update the texture with new cursor - _cursorTexture->updateBuffer(surface, _cursorState.w * 4, 0, 0, _cursorState.w, _cursorState.h); - - // Free the temp surface - delete[] surface; -} - -void OpenGLGraphicsManager::refreshCursorScale() { - // Calculate the scale factors of the screen. - // We also totally ignore the aspect of the overlay cursor, since aspect - // ratio correction only applies to the game screen. - // TODO: It might make sense to always ignore scaling of the mouse cursor - // when the overlay is visible. - uint screenScaleFactorX = _videoMode.hardwareWidth * 10000 / _videoMode.screenWidth; - uint screenScaleFactorY = _videoMode.hardwareHeight * 10000 / _videoMode.screenHeight; - - // Ignore scaling when the cursor should not be scaled. - if (_cursorDontScale) { - screenScaleFactorX = 10000; - screenScaleFactorY = 10000; - } - - // Apply them (without any possible) aspect ratio correction to the - // overlay. - _cursorState.rW = (int16)(_cursorState.w * screenScaleFactorX / 10000); - _cursorState.rH = (int16)(_cursorState.h * screenScaleFactorY / 10000); - _cursorState.rHotX = (int16)(_cursorState.hotX * screenScaleFactorX / 10000); - _cursorState.rHotY = (int16)(_cursorState.hotY * screenScaleFactorY / 10000); - - // Only apply scaling when it's desired. - if (_cursorDontScale) { - screenScaleFactorX = 10000; - screenScaleFactorY = 10000; - } else { - // Make sure we properly scale the cursor according to the desired aspect. - int width, height; - calculateDisplaySize(width, height); - screenScaleFactorX = (width * 10000 / _videoMode.screenWidth); - screenScaleFactorY = (height * 10000 / _videoMode.screenHeight); - } - - // Apply the scale cursor scaling for the game screen. - _cursorState.vW = (int16)(_cursorState.w * screenScaleFactorX / 10000); - _cursorState.vH = (int16)(_cursorState.h * screenScaleFactorY / 10000); - _cursorState.vHotX = (int16)(_cursorState.hotX * screenScaleFactorX / 10000); - _cursorState.vHotY = (int16)(_cursorState.hotY * screenScaleFactorY / 10000); -} - -void OpenGLGraphicsManager::calculateDisplaySize(int &width, int &height) { - if (_videoMode.mode == OpenGL::GFX_ORIGINAL) { - width = _videoMode.screenWidth; - height = _videoMode.screenHeight; - } else { - width = _videoMode.hardwareWidth; - height = _videoMode.hardwareHeight; - - uint aspectRatio = (_videoMode.hardwareWidth * 10000 + 5000) / _videoMode.hardwareHeight; - uint desiredAspectRatio = getAspectRatio(); - - // Adjust one screen dimension for mantaining the aspect ratio - if (aspectRatio < desiredAspectRatio) - height = (width * 10000 + 5000) / desiredAspectRatio; - else if (aspectRatio > desiredAspectRatio) - width = (height * desiredAspectRatio + 5000) / 10000; - } -} - -void OpenGLGraphicsManager::refreshDisplaySize() { - calculateDisplaySize(_displayWidth, _displayHeight); - - // Adjust x and y for centering the screen - _displayX = (_videoMode.hardwareWidth - _displayWidth) / 2; - _displayY = (_videoMode.hardwareHeight - _displayHeight) / 2; -} - -void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &intFormat, GLenum &glFormat, GLenum &gltype) { - if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 - bpp = 4; - intFormat = GL_RGBA; - glFormat = GL_RGBA; - gltype = GL_UNSIGNED_INT_8_8_8_8; - } else if (pixelFormat == Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0)) { // RGB888 - bpp = 3; - intFormat = GL_RGB; - glFormat = GL_RGB; - gltype = GL_UNSIGNED_BYTE; - } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 - bpp = 2; - intFormat = GL_RGB; - glFormat = GL_RGB; - gltype = GL_UNSIGNED_SHORT_5_6_5; - } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGB5551 - bpp = 2; - intFormat = GL_RGBA; - glFormat = GL_RGBA; - gltype = GL_UNSIGNED_SHORT_5_5_5_1; - } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444 - bpp = 2; - intFormat = GL_RGBA; - glFormat = GL_RGBA; - gltype = GL_UNSIGNED_SHORT_4_4_4_4; - } else if (pixelFormat.bytesPerPixel == 1) { // CLUT8 - // If uses a palette, create texture as RGB888. The pixel data will be converted - // later. - bpp = 3; - intFormat = GL_RGB; - glFormat = GL_RGB; - gltype = GL_UNSIGNED_BYTE; -#ifndef USE_GLES - } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 - // GL_BGRA does not exist in every GLES implementation so should not be configured if - // USE_GLES is set. - bpp = 2; - intFormat = GL_RGB; - glFormat = GL_BGRA; - gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV; - } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)) { // ARGB8888 - bpp = 4; - intFormat = GL_RGBA; - glFormat = GL_BGRA; - gltype = GL_UNSIGNED_INT_8_8_8_8_REV; - } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)) { // ARGB4444 - bpp = 2; - intFormat = GL_RGBA; - glFormat = GL_BGRA; - gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV; - } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888 - bpp = 4; - intFormat = GL_RGBA; - glFormat = GL_RGBA; - gltype = GL_UNSIGNED_INT_8_8_8_8_REV; - } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0)) { // BGRA8888 - bpp = 4; - intFormat = GL_RGBA; - glFormat = GL_BGRA; - gltype = GL_UNSIGNED_BYTE; - } else if (pixelFormat == Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0)) { // BGR888 - bpp = 3; - intFormat = GL_RGB; - glFormat = GL_BGR; - gltype = GL_UNSIGNED_BYTE; - } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)) { // BGR565 - bpp = 2; - intFormat = GL_RGB; - glFormat = GL_BGR; - gltype = GL_UNSIGNED_SHORT_5_6_5; - } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0)) { // BGRA5551 - bpp = 2; - intFormat = GL_RGBA; - glFormat = GL_BGRA; - gltype = GL_UNSIGNED_SHORT_5_5_5_1; - } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12)) { // ABGR4444 - bpp = 2; - intFormat = GL_RGBA; - glFormat = GL_RGBA; - gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV; - } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)) { // BGRA4444 - bpp = 2; - intFormat = GL_RGBA; - glFormat = GL_BGRA; - gltype = GL_UNSIGNED_SHORT_4_4_4_4; -#endif - } else { - error("OpenGLGraphicsManager: Pixel format not supported"); - } -} - -void OpenGLGraphicsManager::internUpdateScreen() { - // Clear the screen buffer - glClear(GL_COLOR_BUFFER_BIT); CHECK_GL_ERROR(); - - if (_screenNeedsRedraw || !_screenDirtyRect.isEmpty()) - // Refresh texture if dirty - refreshGameScreen(); - - int scaleFactor = _videoMode.hardwareHeight / _videoMode.screenHeight; - - glPushMatrix(); - - // Adjust game screen shake position - glTranslatef(0, _shakePos * scaleFactor, 0); CHECK_GL_ERROR(); - - // Draw the game screen - _gameTexture->drawTexture(_displayX, _displayY, _displayWidth, _displayHeight); - - glPopMatrix(); - - if (_overlayVisible) { - if (_overlayNeedsRedraw || !_overlayDirtyRect.isEmpty()) - // Refresh texture if dirty - refreshOverlay(); - - // Draw the overlay - _overlayTexture->drawTexture(0, 0, _videoMode.overlayWidth, _videoMode.overlayHeight); - } - - if (_cursorVisible) { - if (_cursorNeedsRedraw) - // Refresh texture if dirty - refreshCursor(); - - glPushMatrix(); - - // Adjust mouse shake position, unless the overlay is visible - glTranslatef(0, _overlayVisible ? 0 : _shakePos * scaleFactor, 0); CHECK_GL_ERROR(); - - // Draw the cursor - if (_overlayVisible) - _cursorTexture->drawTexture(_cursorState.x - _cursorState.rHotX, - _cursorState.y - _cursorState.rHotY, _cursorState.rW, _cursorState.rH); - else - _cursorTexture->drawTexture(_cursorState.x - _cursorState.vHotX, - _cursorState.y - _cursorState.vHotY, _cursorState.vW, _cursorState.vH); - - glPopMatrix(); - } - -#ifdef USE_OSD - if (_osdAlpha > 0) { - if (_requireOSDUpdate) { - updateOSD(); - _requireOSDUpdate = false; - } - - // Update alpha value - const int diff = g_system->getMillis() - _osdFadeStartTime; - if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { - // Back to full transparency - _osdAlpha = 0; - } else { - // Do a fade out - _osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration; - } - } - // Set the osd transparency - glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f); CHECK_GL_ERROR(); - - // Draw the osd texture - _osdTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); - - // Reset color - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); CHECK_GL_ERROR(); - } -#endif -} - -void OpenGLGraphicsManager::initGL() { - // Check available GL Extensions - GLTexture::initGLExtensions(); - - // Disable 3D properties - glDisable(GL_CULL_FACE); CHECK_GL_ERROR(); - glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR(); - glDisable(GL_LIGHTING); CHECK_GL_ERROR(); - glDisable(GL_FOG); CHECK_GL_ERROR(); - glDisable(GL_DITHER); CHECK_GL_ERROR(); - glShadeModel(GL_FLAT); CHECK_GL_ERROR(); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); CHECK_GL_ERROR(); - - // Setup alpha blend (For overlay and cursor) - glEnable(GL_BLEND); CHECK_GL_ERROR(); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CHECK_GL_ERROR(); - - // Enable rendering with vertex and coord arrays - glEnableClientState(GL_VERTEX_ARRAY); CHECK_GL_ERROR(); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_GL_ERROR(); - - glEnable(GL_TEXTURE_2D); CHECK_GL_ERROR(); - - // Setup the GL viewport - glViewport(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); CHECK_GL_ERROR(); - - // Setup coordinates system - glMatrixMode(GL_PROJECTION); CHECK_GL_ERROR(); - glLoadIdentity(); CHECK_GL_ERROR(); -#ifdef USE_GLES - glOrthof(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); CHECK_GL_ERROR(); -#else - glOrtho(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); CHECK_GL_ERROR(); -#endif - glMatrixMode(GL_MODELVIEW); CHECK_GL_ERROR(); - glLoadIdentity(); CHECK_GL_ERROR(); -} - -void OpenGLGraphicsManager::loadTextures() { -#ifdef USE_RGB_COLOR - if (_transactionDetails.formatChanged && _gameTexture) { - delete _gameTexture; - _gameTexture = 0; - } -#endif - - if (!_gameTexture) { - byte bpp; - GLenum intformat; - GLenum format; - GLenum type; -#ifdef USE_RGB_COLOR - getGLPixelFormat(_screenFormat, bpp, intformat, format, type); -#else - getGLPixelFormat(Graphics::PixelFormat::createFormatCLUT8(), bpp, intformat, format, type); -#endif - _gameTexture = new GLTexture(bpp, intformat, format, type); - } else - _gameTexture->refresh(); - - _overlayFormat = Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0); - - if (!_overlayTexture) { - byte bpp; - GLenum intformat; - GLenum format; - GLenum type; - getGLPixelFormat(_overlayFormat, bpp, intformat, format, type); - _overlayTexture = new GLTexture(bpp, intformat, format, type); - } else - _overlayTexture->refresh(); - - if (!_cursorTexture) - _cursorTexture = new GLTexture(4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); - else - _cursorTexture->refresh(); - - GLint filter = _videoMode.antialiasing ? GL_LINEAR : GL_NEAREST; - _gameTexture->setFilter(filter); - _overlayTexture->setFilter(filter); - _cursorTexture->setFilter(filter); - - // Allocate texture memory and finish refreshing - _gameTexture->allocBuffer(_videoMode.screenWidth, _videoMode.screenHeight); - _overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); - _cursorTexture->allocBuffer(_cursorState.w, _cursorState.h); - - if ( -#ifdef USE_RGB_COLOR - _transactionDetails.formatChanged || -#endif - _oldVideoMode.screenWidth != _videoMode.screenWidth || - _oldVideoMode.screenHeight != _videoMode.screenHeight) - _screenData.create(_videoMode.screenWidth, _videoMode.screenHeight, -#ifdef USE_RGB_COLOR - _screenFormat -#else - Graphics::PixelFormat::createFormatCLUT8() -#endif - ); - - - if (_oldVideoMode.overlayWidth != _videoMode.overlayWidth || - _oldVideoMode.overlayHeight != _videoMode.overlayHeight) - _overlayData.create(_videoMode.overlayWidth, _videoMode.overlayHeight, - _overlayFormat); - - _screenNeedsRedraw = true; - _overlayNeedsRedraw = true; - _cursorNeedsRedraw = true; - - // We need to setup a proper unpack alignment value here, else we will - // get problems with the texture updates, in case the surface data is - // not properly aligned. - // It is noteworthy this assumes the OSD uses the same BPP as the overlay - // and that the cursor works with any alignment setting. - int newAlignment = Common::gcd(_gameTexture->getBytesPerPixel(), _overlayTexture->getBytesPerPixel()); - assert(newAlignment == 1 || newAlignment == 2 || newAlignment == 4); - glPixelStorei(GL_UNPACK_ALIGNMENT, newAlignment); - - // We use a "pack" alignment (when reading from textures) to 4 here, - // since the only place where we really use it is the BMP screenshot - // code and that requires the same alignment too. - glPixelStorei(GL_PACK_ALIGNMENT, 4); - -#ifdef USE_OSD - if (!_osdTexture) - _osdTexture = new GLTexture(2, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1); - else - _osdTexture->refresh(); - - _osdTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); - - // Update the OSD in case it is used right now - _requireOSDUpdate = true; -#endif -} - -bool OpenGLGraphicsManager::loadGFXMode() { - // Initialize OpenGL settings - initGL(); - - loadTextures(); - - refreshCursorScale(); - - refreshDisplaySize(); - - internUpdateScreen(); - - return true; -} - -void OpenGLGraphicsManager::unloadGFXMode() { - -} - -void OpenGLGraphicsManager::setScale(int newScale) { - assert(_transactionMode == kTransactionActive); - - if (newScale == _videoMode.scaleFactor) - return; - - _videoMode.scaleFactor = newScale; - _transactionDetails.sizeChanged = true; -} - -void OpenGLGraphicsManager::toggleAntialiasing() { - assert(_transactionMode == kTransactionActive); - - _videoMode.antialiasing = !_videoMode.antialiasing; - _transactionDetails.filterChanged = true; -} - -uint OpenGLGraphicsManager::getAspectRatio() const { - // In case we enable aspect ratio correction we force a 4/3 ratio. - // But just for 320x200 and 640x400 games, since other games do not need - // this. - // TODO: This makes OpenGL Normal behave like OpenGL Conserve, when aspect - // ratio correction is enabled, but it's better than the previous 4/3 mode - // mess at least... - if (_videoMode.aspectRatioCorrection - && ((_videoMode.screenWidth == 320 && _videoMode.screenHeight == 200) - || (_videoMode.screenWidth == 640 && _videoMode.screenHeight == 400))) - return 13333; - else if (_videoMode.mode == OpenGL::GFX_NORMAL) - return _videoMode.hardwareWidth * 10000 / _videoMode.hardwareHeight; - else - return _videoMode.screenWidth * 10000 / _videoMode.screenHeight; -} - -void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { - if (_overlayVisible) - return; - - x -= _displayX; - y -= _displayY; - - if (_displayWidth != _videoMode.screenWidth) - x = x * _videoMode.screenWidth / _displayWidth; - if (_displayHeight != _videoMode.screenHeight) - y = y * _videoMode.screenHeight / _displayHeight; -} - -bool OpenGLGraphicsManager::saveScreenshot(const char *filename) { - int width = _videoMode.hardwareWidth; - int height = _videoMode.hardwareHeight; - - // A line of a BMP image must have a size divisible by 4. - // We calculate the padding bytes needed here. - // Since we use a 3 byte per pixel mode, we can use width % 4 here, since - // it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the - // usual way of computing the padding bytes required). - const int linePaddingSize = width % 4; - const int lineSize = width * 3 + linePaddingSize; - - // Allocate memory for screenshot - uint8 *pixels = new uint8[lineSize * height]; - - // Get pixel data from OpenGL buffer -#ifdef USE_GLES - glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR(); -#else - if (_formatBGR) { - glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR(); - } else { - glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); CHECK_GL_ERROR(); - } -#endif - - // Open file - Common::DumpFile out; - out.open(filename); - - // Write BMP header - out.writeByte('B'); - out.writeByte('M'); - out.writeUint32LE(height * lineSize + 54); - out.writeUint32LE(0); - out.writeUint32LE(54); - out.writeUint32LE(40); - out.writeUint32LE(width); - out.writeUint32LE(height); - out.writeUint16LE(1); - out.writeUint16LE(24); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.writeUint32LE(0); - out.writeUint32LE(0); - - // Write pixel data to BMP - out.write(pixels, lineSize * height); - - // Free allocated memory - delete[] pixels; - - return true; -} - -const char *OpenGLGraphicsManager::getCurrentModeName() { - const char *modeName = 0; - const OSystem::GraphicsMode *g = getSupportedGraphicsModes(); - while (g->name) { - if (g->id == _videoMode.mode) { - modeName = g->description; - break; - } - g++; - } - return modeName; -} - -#ifdef USE_OSD -const Graphics::Font *OpenGLGraphicsManager::getFontOSD() { - return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont); -} - -void OpenGLGraphicsManager::updateOSD() { - // The font we are going to use: - const Graphics::Font *font = getFontOSD(); - - if (_osdSurface.w != _osdTexture->getWidth() || _osdSurface.h != _osdTexture->getHeight()) - _osdSurface.create(_osdTexture->getWidth(), _osdTexture->getHeight(), _overlayFormat); - else - // Clear everything - memset(_osdSurface.getPixels(), 0, _osdSurface.h * _osdSurface.pitch); - - // Determine a rect which would contain the message string (clipped to the - // screen dimensions). - const int vOffset = 6; - const int lineSpacing = 1; - const int lineHeight = font->getFontHeight() + 2 * lineSpacing; - int width = 0; - int height = lineHeight * _osdLines.size() + 2 * vOffset; - for (uint i = 0; i < _osdLines.size(); i++) { - width = MAX(width, font->getStringWidth(_osdLines[i]) + 14); - } - - // Clip the rect - if (width > _osdSurface.w) - width = _osdSurface.w; - if (height > _osdSurface.h) - height = _osdSurface.h; - - int dstX = (_osdSurface.w - width) / 2; - int dstY = (_osdSurface.h - height) / 2; - - // Draw a dark gray rect (R = 40, G = 40, B = 40) - const uint16 color = 0x294B; - _osdSurface.fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color); - - // Render the message, centered, and in white - for (uint i = 0; i < _osdLines.size(); i++) { - font->drawString(&_osdSurface, _osdLines[i], - dstX, dstY + i * lineHeight + vOffset + lineSpacing, width, - 0xFFFF, Graphics::kTextAlignCenter); - } - - // Update the texture - _osdTexture->updateBuffer(_osdSurface.getPixels(), _osdSurface.pitch, 0, 0, - _osdSurface.w, _osdSurface.h); -} -#endif - -#endif diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h deleted file mode 100644 index 9d8d418d11..0000000000 --- a/backends/graphics/opengl/opengl-graphics.h +++ /dev/null @@ -1,351 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef BACKENDS_GRAPHICS_OPENGL_H -#define BACKENDS_GRAPHICS_OPENGL_H - -#include "backends/graphics/opengl/gltexture.h" -#include "backends/graphics/graphics.h" -#include "common/array.h" -#include "common/rect.h" -#include "graphics/font.h" -#include "graphics/pixelformat.h" - -// Uncomment this to enable the 'on screen display' code. -#define USE_OSD 1 - -namespace OpenGL { -// The OpenGL GFX modes. They have to be inside the OpenGL namespace so they -// do not clash with the SDL GFX modes. -enum { - GFX_NORMAL = 0, - GFX_CONSERVE = 1, - GFX_ORIGINAL = 2 -}; - -} - -/** - * OpenGL graphics manager. This is an abstract class, it does not do the - * window and OpenGL context initialization. - * Derived classes should at least override internUpdateScreen for doing - * the buffers swap, and implement loadGFXMode for handling the window/context if - * needed. If USE_RGB_COLOR is enabled, getSupportedFormats must be implemented. - */ -class OpenGLGraphicsManager : public GraphicsManager { -public: - OpenGLGraphicsManager(); - virtual ~OpenGLGraphicsManager(); - - virtual bool hasFeature(OSystem::Feature f); - virtual void setFeatureState(OSystem::Feature f, bool enable); - virtual bool getFeatureState(OSystem::Feature f); - - static const OSystem::GraphicsMode *supportedGraphicsModes(); - virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - virtual bool setGraphicsMode(int mode); - virtual int getGraphicsMode() const; - virtual void resetGraphicsScale(); -#ifdef USE_RGB_COLOR - virtual Graphics::PixelFormat getScreenFormat() const; - virtual Common::List getSupportedFormats() const = 0; -#endif - virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL); - virtual int getScreenChangeID() const; - - virtual void beginGFXTransaction(); - virtual OSystem::TransactionError endGFXTransaction(); - - virtual int16 getHeight(); - virtual int16 getWidth(); -protected: - // PaletteManager API - virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); - -public: - virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); - virtual void fillScreen(uint32 col); - virtual void updateScreen(); - virtual void setShakePos(int shakeOffset); - virtual void setFocusRectangle(const Common::Rect &rect); - virtual void clearFocusRectangle(); - - virtual void showOverlay(); - virtual void hideOverlay(); - virtual Graphics::PixelFormat getOverlayFormat() const; - virtual void clearOverlay(); - virtual void grabOverlay(void *buf, int pitch); - virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h); - virtual int16 getOverlayHeight(); - virtual int16 getOverlayWidth(); - - virtual bool showMouse(bool visible); - virtual void warpMouse(int x, int y); - virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL); - virtual void setCursorPalette(const byte *colors, uint start, uint num); - - virtual void displayMessageOnOSD(const char *msg); -protected: - /** - * Setup OpenGL settings - */ - virtual void initGL(); - - /** - * Creates and refreshs OpenGL textures. - */ - virtual void loadTextures(); - - // - // GFX and video - // - enum { - kTransactionNone = 0, - kTransactionActive = 1, - kTransactionRollback = 2 - }; - - struct TransactionDetails { - bool sizeChanged; - bool needRefresh; - bool needUpdatescreen; - bool filterChanged; -#ifdef USE_RGB_COLOR - bool formatChanged; -#endif - }; - TransactionDetails _transactionDetails; - int _transactionMode; - - struct VideoState { - bool setup; - - bool fullscreen; - - int mode; - int scaleFactor; - bool antialiasing; - bool aspectRatioCorrection; - - int screenWidth, screenHeight; - int overlayWidth, overlayHeight; - int hardwareWidth, hardwareHeight; -#ifdef USE_RGB_COLOR - Graphics::PixelFormat format; -#endif - }; - VideoState _videoMode, _oldVideoMode; - - /** - * Sets the OpenGL texture format for the given pixel format. If format is not support will raise an error. - */ - virtual void getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &intFormat, GLenum &glFormat, GLenum &type); - - virtual void internUpdateScreen(); - virtual bool loadGFXMode(); - virtual void unloadGFXMode(); - - /** - * Setup the fullscreen mode state. - */ - void setFullscreenMode(bool enable); - - /** - * Query the fullscreen state. - */ - inline bool getFullscreenMode() const { return _videoMode.fullscreen; } - - /** - * Set the scale factor. - * - * This can only be used in a GFX transaction. - * - * @param newScale New scale factor. - */ - void setScale(int newScale); - - /** - * Query the scale factor. - */ - inline int getScale() const { return _videoMode.scaleFactor; } - - /** - * Toggle the antialiasing state of the current video mode. - * - * This can only be used in a GFX transaction. - */ - void toggleAntialiasing(); - - /** - * Query the antialiasing state. - */ - inline bool getAntialiasingState() const { return _videoMode.antialiasing; } - - // Drawing coordinates for the current display mode and scale - int _displayX; - int _displayY; - int _displayWidth; - int _displayHeight; - - virtual const char *getCurrentModeName(); - - virtual void calculateDisplaySize(int &width, int &height); - virtual void refreshDisplaySize(); - - uint getAspectRatio() const; - - void setFormatIsBGR(bool isBGR) { _formatBGR = isBGR; } - bool _formatBGR; - - // - // Game screen - // - GLTexture *_gameTexture; - 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 _shakePos; - - // - // Overlay - // - GLTexture *_overlayTexture; - Graphics::Surface _overlayData; - Graphics::PixelFormat _overlayFormat; - bool _overlayVisible; - bool _overlayNeedsRedraw; - Common::Rect _overlayDirtyRect; - - virtual void refreshOverlay(); - - // - // Mouse - // - struct MousePos { - // The mouse position in hardware screen coordinates. - int16 x, y; - - // The size and hotspot of the original cursor image. - int16 w, h; - int16 hotX, hotY; - - // The size and hotspot of the scaled cursor, in real coordinates. - int16 rW, rH; - int16 rHotX, rHotY; - - // The size and hotspot of the scaled cursor, in game coordinates. - int16 vW, vH; - int16 vHotX, vHotY; - - 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) {} - }; - - GLTexture *_cursorTexture; - Graphics::Surface _cursorData; - Graphics::PixelFormat _cursorFormat; - byte *_cursorPalette; - bool _cursorPaletteDisabled; - MousePos _cursorState; - bool _cursorVisible; - uint32 _cursorKeyColor; - bool _cursorDontScale; - bool _cursorNeedsRedraw; - - /** - * Set up the mouse position for graphics output. - * - * @param x X coordinate in native coordinates. - * @param y Y coordinate in native coordinates. - */ - void setMousePosition(int x, int y) { _cursorState.x = x; _cursorState.y = y; } - - virtual void refreshCursor(); - virtual void refreshCursorScale(); - - /** - * Set up the mouse position for the (event) system. - * - * @param x X coordinate in native coordinates. - * @param y Y coordinate in native coordinates. - */ - virtual void setInternalMousePosition(int x, int y) = 0; - - /** - * Adjusts hardware screen coordinates to either overlay or game screen - * coordinates depending on whether the overlay is visible or not. - * - * @param x X coordinate of the mouse position. - * @param y Y coordinate of the mouse position. - */ - virtual void adjustMousePosition(int16 &x, int16 &y); - - // - // Misc - // - virtual bool saveScreenshot(const char *filename); - -#ifdef USE_OSD - /** - * Returns the font used for on screen display - */ - virtual const Graphics::Font *getFontOSD(); - - /** - * Update the OSD texture / surface. - */ - void updateOSD(); - - /** - * The OSD contents. - */ - Common::Array _osdLines; - - GLTexture *_osdTexture; - Graphics::Surface _osdSurface; - uint8 _osdAlpha; - uint32 _osdFadeStartTime; - bool _requireOSDUpdate; - enum { - kOSDFadeOutDelay = 2 * 1000, - kOSDFadeOutDuration = 500, - kOSDInitialAlpha = 80 - }; -#endif -}; - -#endif diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp deleted file mode 100644 index c5605cae87..0000000000 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ /dev/null @@ -1,677 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "common/scummsys.h" - -#if defined(SDL_BACKEND) && defined(USE_OPENGL) - -#include "backends/graphics/openglsdl/openglsdl-graphics.h" -#include "backends/platform/sdl/sdl.h" -#include "common/config-manager.h" -#include "common/textconsole.h" -#include "common/translation.h" - -OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource) - : - SdlGraphicsManager(eventSource), - _hwscreen(0), - _screenResized(false), - _activeFullscreenMode(-2), - _lastFullscreenModeWidth(0), - _lastFullscreenModeHeight(0), - _desktopWidth(0), - _desktopHeight(0), - _ignoreResizeFrames(0) { - - // Initialize SDL video subsystem - if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { - error("Could not initialize SDL: %s", SDL_GetError()); - } - - // This is also called in initSDL(), but initializing graphics - // may reset it. - SDL_EnableUNICODE(1); - - // Disable OS cursor - SDL_ShowCursor(SDL_DISABLE); - - // Get desktop resolution - // TODO: In case the OpenGL manager is created *after* a plain SDL manager - // has been used, this will return the last setup graphics mode rather - // than the desktop resolution. We should really look into a way to - // properly retrieve the desktop resolution. - const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); - if (videoInfo->current_w > 0 && videoInfo->current_h > 0) { - _desktopWidth = videoInfo->current_w; - _desktopHeight = videoInfo->current_h; - } - - if (ConfMan.hasKey("last_fullscreen_mode_width") && ConfMan.hasKey("last_fullscreen_mode_height")) { - _lastFullscreenModeWidth = ConfMan.getInt("last_fullscreen_mode_width"); - _lastFullscreenModeHeight = ConfMan.getInt("last_fullscreen_mode_height"); - } -} - -OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() { - // Unregister the event observer - if (g_system->getEventManager()->getEventDispatcher() != NULL) - g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); -} - -void OpenGLSdlGraphicsManager::initEventObserver() { - // Register the graphics manager as a event observer - g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); -} - -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::kFeatureIconifyWindow: - if (enable) - SDL_WM_IconifyWindow(); - break; - default: - OpenGLGraphicsManager::setFeatureState(f, enable); - } -} - -#ifdef USE_RGB_COLOR - -Common::List OpenGLSdlGraphicsManager::getSupportedFormats() const { - assert(!_supportedFormats.empty()); - return _supportedFormats; -} - -void OpenGLSdlGraphicsManager::detectSupportedFormats() { - - // Clear old list - _supportedFormats.clear(); - - // Some tables with standard formats that we always list - // as "supported". If frontend code tries to use one of - // these, we will perform the necessary format - // conversion in the background. Of course this incurs a - // performance hit, but on desktop ports this should not - // matter. We still push the currently active format to - // the front, so if frontend code just uses the first - // available format, it will get one that is "cheap" to - // use. - const Graphics::PixelFormat RGBList[] = { -#if defined(ENABLE_32BIT) - Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), // RGBA8888 -#ifndef USE_GLES - Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), // ARGB8888 -#endif - Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0), // RGB888 -#endif - Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), // RGB565 - Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0), // RGB5551 - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), // RGB555 - Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), // RGBA4444 -#ifndef USE_GLES - Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12) // ARGB4444 -#endif - }; -#ifndef USE_GLES - const Graphics::PixelFormat BGRList[] = { -#ifdef ENABLE_32BIT - Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24), // ABGR8888 - Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0), // BGRA8888 - Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), // BGR888 -#endif - Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0), // BGR565 - Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0), // BGRA5551 - Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12), // ABGR4444 - Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0) // BGRA4444 - }; -#endif - - Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); - if (_hwscreen) { - // Get our currently set hardware format - format = Graphics::PixelFormat(_hwscreen->format->BytesPerPixel, - 8 - _hwscreen->format->Rloss, 8 - _hwscreen->format->Gloss, - 8 - _hwscreen->format->Bloss, 8 - _hwscreen->format->Aloss, - _hwscreen->format->Rshift, _hwscreen->format->Gshift, - _hwscreen->format->Bshift, _hwscreen->format->Ashift); - - // Workaround to SDL not providing an accurate Aloss value on Mac OS X. - if (_hwscreen->format->Amask == 0) - format.aLoss = 8; - - // Push it first, as the prefered format if available - for (int i = 0; i < ARRAYSIZE(RGBList); i++) { - if (RGBList[i] == format) { - _supportedFormats.push_back(format); - break; - } - } -#ifndef USE_GLES - for (int i = 0; i < ARRAYSIZE(BGRList); i++) { - if (BGRList[i] == format) { - _supportedFormats.push_back(format); - break; - } - } -#endif - } - - // Push some RGB formats - for (int i = 0; i < ARRAYSIZE(RGBList); i++) { - if (_hwscreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel)) - continue; - if (RGBList[i] != format) - _supportedFormats.push_back(RGBList[i]); - } -#ifndef USE_GLES - // Push some BGR formats - for (int i = 0; i < ARRAYSIZE(BGRList); i++) { - if (_hwscreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel)) - continue; - if (BGRList[i] != format) - _supportedFormats.push_back(BGRList[i]); - } -#endif - _supportedFormats.push_back(Graphics::PixelFormat::createFormatCLUT8()); -} - -#endif - -void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) { - SDL_WarpMouse(x, y); -} - -void OpenGLSdlGraphicsManager::updateScreen() { - if (_ignoreResizeFrames) - _ignoreResizeFrames -= 1; - - OpenGLGraphicsManager::updateScreen(); -} - -// -// Intern -// - -bool OpenGLSdlGraphicsManager::setupFullscreenMode() { - SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_OPENGL); - - // SDL_ListModes() returns -1 in case any dimension is okay. In that - // case we'll reuse the current desktop resolution for fullscreen. - if (availableModes == (void *)-1) { - _videoMode.hardwareWidth = _desktopWidth; - _videoMode.hardwareHeight = _desktopHeight; - _activeFullscreenMode = -2; - return true; - } - - // If -2, autodetect the fullscreen mode - // The last used fullscreen mode will be prioritized, if there is no last fullscreen - // mode, the desktop resolution will be used, and in case the desktop resolution - // is not available as a fullscreen mode, the one with smallest metric will be selected. - if (_activeFullscreenMode == -2) { - // Desktop resolution - int desktopModeIndex = -1; - - // Best metric mode - const SDL_Rect *bestMode = availableModes[0]; - int bestModeIndex = 0; - uint bestMetric = (uint)-1; - - // Iterate over all available fullscreen modes - for (int i = 0; const SDL_Rect *mode = availableModes[i]; i++) { - // Try to setup the last used fullscreen mode - if (mode->w == _lastFullscreenModeWidth && mode->h == _lastFullscreenModeHeight) { - _videoMode.hardwareWidth = _lastFullscreenModeWidth; - _videoMode.hardwareHeight = _lastFullscreenModeHeight; - _activeFullscreenMode = i; - return true; - } - - if (mode->w == _desktopWidth && mode->h == _desktopHeight) - desktopModeIndex = i; - - if (mode->w < _videoMode.overlayWidth) - continue; - if (mode->h < _videoMode.overlayHeight) - continue; - - uint metric = mode->w * mode->h - _videoMode.overlayWidth * _videoMode.overlayHeight; - if (metric < bestMetric) { - bestMode = mode; - bestMetric = metric; - bestModeIndex = i; - } - } - - if (desktopModeIndex >= 0) { - _videoMode.hardwareWidth = _desktopWidth; - _videoMode.hardwareHeight = _desktopHeight; - - _activeFullscreenMode = desktopModeIndex; - return true; - } else if (bestMode) { - _videoMode.hardwareWidth = bestMode->w; - _videoMode.hardwareHeight = bestMode->h; - - _activeFullscreenMode = bestModeIndex; - return true; - } - } else { - // Use last fullscreen mode if looping backwards from the first mode - if (_activeFullscreenMode == -1) { - do { - _activeFullscreenMode++; - } while(availableModes[_activeFullscreenMode]); - _activeFullscreenMode--; - } - - // Use first fullscreen mode if looping from last mode - if (!availableModes[_activeFullscreenMode]) - _activeFullscreenMode = 0; - - // Check if the fullscreen mode is valid - if (availableModes[_activeFullscreenMode]) { - _videoMode.hardwareWidth = availableModes[_activeFullscreenMode]->w; - _videoMode.hardwareHeight = availableModes[_activeFullscreenMode]->h; - return true; - } - } - - // Could not find any suiting fullscreen mode, return false. - return false; -} - -bool OpenGLSdlGraphicsManager::loadGFXMode() { - // If the screen was resized, do not change its size - if (!_screenResized) { - const int scaleFactor = getScale(); - _videoMode.overlayWidth = _videoMode.hardwareWidth = _videoMode.screenWidth * scaleFactor; - _videoMode.overlayHeight = _videoMode.hardwareHeight = _videoMode.screenHeight * scaleFactor; - - // The only modes where we need to adapt the aspect ratio are 320x200 - // and 640x400. That is since our aspect ratio correction in fact is - // only used to ensure that the original pixel size aspect for these - // modes is used. - // (Non-square pixels on old monitors vs square pixel on new ones). - if (_videoMode.aspectRatioCorrection) { - if (_videoMode.screenWidth == 320 && _videoMode.screenHeight == 200) - _videoMode.overlayHeight = _videoMode.hardwareHeight = 240 * scaleFactor; - else if (_videoMode.screenWidth == 640 && _videoMode.screenHeight == 400) - _videoMode.overlayHeight = _videoMode.hardwareHeight = 480 * scaleFactor; - } - } - - _screenResized = false; - - // Setup OpenGL attributes for SDL - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - - const bool isFullscreen = getFullscreenMode(); - - // In case we have an fullscreen mode and we are not in a rollback, detect - // a proper mode to use. In case we are in a rollback, we already detected - // a proper mode when setting up that mode, thus there is no need to run - // the detection again. - if (isFullscreen && _transactionMode != kTransactionRollback) { - if (!setupFullscreenMode()) - // Failed setuping a fullscreen mode - return false; - } - - _videoMode.overlayWidth = _videoMode.hardwareWidth; - _videoMode.overlayHeight = _videoMode.hardwareHeight; - - uint32 flags = SDL_OPENGL; - - if (isFullscreen) - flags |= SDL_FULLSCREEN; - else - flags |= SDL_RESIZABLE; - - // Create our window - _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 32, flags); -#ifdef USE_RGB_COLOR - detectSupportedFormats(); -#endif - - if (_hwscreen == NULL) { - // DON'T use error(), as this tries to bring up the debug - // console, which WON'T WORK now that _hwscreen is hosed. - - if (!_oldVideoMode.setup) { - warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError()); - g_system->quit(); - } else - // Cancel GFX load, and go back to last mode - return false; - } - - // Check if the screen is BGR format - setFormatIsBGR(_hwscreen->format->Rshift != 0); - - if (isFullscreen) { - _lastFullscreenModeWidth = _videoMode.hardwareWidth; - _lastFullscreenModeHeight = _videoMode.hardwareHeight; - ConfMan.setInt("last_fullscreen_mode_width", _lastFullscreenModeWidth); - ConfMan.setInt("last_fullscreen_mode_height", _lastFullscreenModeHeight); - } - - // Call and return parent implementation of this method - return OpenGLGraphicsManager::loadGFXMode(); -} - -void OpenGLSdlGraphicsManager::unloadGFXMode() { - if (_hwscreen) { - SDL_FreeSurface(_hwscreen); - _hwscreen = NULL; - } -} - -void OpenGLSdlGraphicsManager::internUpdateScreen() { - // Call to parent implementation of this method - OpenGLGraphicsManager::internUpdateScreen(); - - // Swap OpenGL buffers - SDL_GL_SwapBuffers(); -} - -#ifdef USE_OSD -void OpenGLSdlGraphicsManager::displayModeChangedMsg() { - const char *newModeName = getCurrentModeName(); - if (newModeName) { - const int scaleFactor = getScale(); - - Common::String osdMessage = Common::String::format( - "%s: %s\n%d x %d -> %d x %d", - _("Current display mode"), - newModeName, - _videoMode.screenWidth * scaleFactor, - _videoMode.screenHeight * scaleFactor, - _hwscreen->w, _hwscreen->h - ); - displayMessageOnOSD(osdMessage.c_str()); - } -} -void OpenGLSdlGraphicsManager::displayScaleChangedMsg() { - const int scaleFactor = getScale(); - Common::String osdMessage = Common::String::format( - "%s: x%d\n%d x %d -> %d x %d", - _("Current scale"), - scaleFactor, - _videoMode.screenWidth, _videoMode.screenHeight, - _videoMode.overlayWidth, _videoMode.overlayHeight - ); - displayMessageOnOSD(osdMessage.c_str()); -} -#endif - -bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) { - if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { - if (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS || - event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS || - event.kbd.keycode == 'a' || event.kbd.keycode == 'f') - return true; - } else if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_SHIFT)) == (Common::KBD_CTRL|Common::KBD_SHIFT)) { - if (event.kbd.keycode == 'a' || event.kbd.keycode == 'f') - return true; - } else if ((event.kbd.flags & (Common::KBD_ALT)) == (Common::KBD_ALT) && event.kbd.keycode == 's') { - return true; - } - return false; -} - -void OpenGLSdlGraphicsManager::toggleFullScreen(int loop) { - beginGFXTransaction(); - const bool isFullscreen = getFullscreenMode(); - - if (isFullscreen && loop) { - _activeFullscreenMode += loop; - setFullscreenMode(true); - } else { - _activeFullscreenMode = -2; - setFullscreenMode(!isFullscreen); - } - - // HACK: We need to force a refresh here, since we change the - // fullscreen mode. - _transactionDetails.needRefresh = true; - endGFXTransaction(); - - // Ignore resize events for the next 10 frames - _ignoreResizeFrames = 10; - -#ifdef USE_OSD - Common::String osdMessage; - if (getFullscreenMode()) - osdMessage = Common::String::format("%s\n%d x %d", - _("Fullscreen mode"), - _hwscreen->w, _hwscreen->h - ); - else - osdMessage = Common::String::format("%s\n%d x %d", - _("Windowed mode"), - _hwscreen->w, _hwscreen->h - ); - displayMessageOnOSD(osdMessage.c_str()); -#endif -} - -bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { - switch (event.type) { - case Common::EVENT_KEYDOWN: - if (event.kbd.hasFlags(Common::KBD_ALT)) { - // Alt-Return and Alt-Enter toggle full screen mode - if (event.kbd.keycode == Common::KEYCODE_RETURN || - event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) { - toggleFullScreen(0); - return true; - } - - // Alt-S create a screenshot - if (event.kbd.keycode == 's') { - Common::String filename; - - for (int n = 0;; n++) { - SDL_RWops *file; - - filename = Common::String::format("scummvm%05d.bmp", n); - file = SDL_RWFromFile(filename.c_str(), "r"); - if (!file) - break; - SDL_RWclose(file); - } - if (saveScreenshot(filename.c_str())) - debug("Saved screenshot '%s'", filename.c_str()); - else - warning("Could not save screenshot"); - return true; - } - } - - if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT)) { - // Ctrl-Alt-Return and Ctrl-Alt-Enter switch between full screen modes - if (event.kbd.keycode == Common::KEYCODE_RETURN || - event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) { - toggleFullScreen(1); - return true; - } - - // Ctrl-Alt-a switch between display modes - if (event.kbd.keycode == 'a') { - beginGFXTransaction(); - setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection)); - endGFXTransaction(); -#ifdef USE_OSD - Common::String osdMessage; - if (getFeatureState(OSystem::kFeatureAspectRatioCorrection)) - osdMessage = Common::String::format("%s\n%d x %d -> %d x %d", - _("Enabled aspect ratio correction"), - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h); - else - osdMessage = Common::String::format("%s\n%d x %d -> %d x %d", - _("Disabled aspect ratio correction"), - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h); - displayMessageOnOSD(osdMessage.c_str()); -#endif - internUpdateScreen(); - return true; - } - - // Ctrl-Alt-f toggles antialiasing - if (event.kbd.keycode == 'f') { - beginGFXTransaction(); - toggleAntialiasing(); - endGFXTransaction(); - -#ifdef USE_OSD - // TODO: This makes guesses about what internal antialiasing - // modes we use, we might want to consider a better way of - // displaying information to the user. - if (getAntialiasingState()) - displayMessageOnOSD(_("Active filter mode: Linear")); - else - displayMessageOnOSD(_("Active filter mode: Nearest")); -#endif - return true; - } - - SDLKey sdlKey = (SDLKey)event.kbd.keycode; - - // Ctrl+Alt+Plus/Minus Increase/decrease the scale factor - if ((sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS || - sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS)) { - int factor = getScale(); - factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1; - if (0 < factor && factor < 4) { - // Check if the desktop resolution has been detected - if (_desktopWidth > 0 && _desktopHeight > 0) - // If the new scale factor is too big, do not scale - if (_videoMode.screenWidth * factor > _desktopWidth || - _videoMode.screenHeight * factor > _desktopHeight) - return false; - - beginGFXTransaction(); - setScale(factor); - endGFXTransaction(); -#ifdef USE_OSD - displayScaleChangedMsg(); -#endif - return true; - } - } - - const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_3); - const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP3); - - // Ctrl-Alt- will change the GFX mode - if (isNormalNumber || isKeypadNumber) { - if (sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1) <= 3) { -#ifdef USE_OSD - int lastMode = _videoMode.mode; -#endif - // We need to query the scale and set it up, because - // setGraphicsMode sets the default scale to 2 - int oldScale = getScale(); - beginGFXTransaction(); - setGraphicsMode(sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1)); - setScale(oldScale); - endGFXTransaction(); -#ifdef USE_OSD - if (lastMode != _videoMode.mode) - displayModeChangedMsg(); -#endif - internUpdateScreen(); - } - } - } - - if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_SHIFT)) { - // Ctrl-Shift-Return and Ctrl-Shift-Enter switch backwards between full screen modes - if (event.kbd.keycode == Common::KEYCODE_RETURN || - event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) { - toggleFullScreen(-1); - return true; - } - } - break; - - case Common::EVENT_KEYUP: - return isHotkey(event); - - default: - break; - } - - return false; -} - -void OpenGLSdlGraphicsManager::notifyVideoExpose() { -} - -void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) { - // Do not resize if ignoring resize events. - if (!_ignoreResizeFrames && !getFullscreenMode()) { - bool scaleChanged = false; - beginGFXTransaction(); - _videoMode.hardwareWidth = width; - _videoMode.hardwareHeight = height; - - _screenResized = true; - - int scale = MIN(_videoMode.hardwareWidth / _videoMode.screenWidth, - _videoMode.hardwareHeight / _videoMode.screenHeight); - - if (getScale() != scale) { - scaleChanged = true; - setScale(MAX(MIN(scale, 3), 1)); - } - - _transactionDetails.sizeChanged = true; - endGFXTransaction(); -#ifdef USE_OSD - if (scaleChanged) - displayScaleChangedMsg(); -#endif - } -} - -void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { - adjustMousePosition(point.x, point.y); -} - -void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) { - setMousePosition(mouse.x, mouse.y); -} - -#endif diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h deleted file mode 100644 index 1587183328..0000000000 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ /dev/null @@ -1,124 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef BACKENDS_GRAPHICS_OPENGLSDL_H -#define BACKENDS_GRAPHICS_OPENGLSDL_H - -#include "backends/platform/sdl/sdl-sys.h" -#if defined(ARRAYSIZE) && !defined(_WINDOWS_) -#undef ARRAYSIZE -#endif -#include "backends/graphics/sdl/sdl-graphics.h" -#include "backends/graphics/opengl/opengl-graphics.h" - -#include "common/events.h" - -/** - * SDL OpenGL graphics manager - */ -class OpenGLSdlGraphicsManager : public OpenGLGraphicsManager, public SdlGraphicsManager, public Common::EventObserver { -public: - OpenGLSdlGraphicsManager(SdlEventSource *eventSource); - virtual ~OpenGLSdlGraphicsManager(); - - virtual bool hasFeature(OSystem::Feature f); - virtual void setFeatureState(OSystem::Feature f, bool enable); - -#ifdef USE_RGB_COLOR - virtual Common::List getSupportedFormats() const; -#endif - - virtual void initEventObserver(); - virtual bool notifyEvent(const Common::Event &event); - - virtual void updateScreen(); - - // SdlGraphicsManager interface - virtual void notifyVideoExpose(); - virtual void notifyResize(const uint width, const uint height); - virtual void transformMouseCoordinates(Common::Point &point); - virtual void notifyMousePos(Common::Point mouse); - -protected: - virtual void internUpdateScreen(); - - virtual bool loadGFXMode(); - virtual void unloadGFXMode(); - virtual bool isHotkey(const Common::Event &event); - -#ifdef USE_RGB_COLOR - Common::List _supportedFormats; - - /** - * Update the list of supported pixel formats. - * This method is invoked by loadGFXMode(). - */ - void detectSupportedFormats(); -#endif - - /** - * Toggles fullscreen. - * @loop loop direction for switching fullscreen mode, if 0 toggles it. - */ - virtual void toggleFullScreen(int loop); - - int _activeFullscreenMode; - - /** - * Setup the fullscreen mode. - * @return false if failed finding a mode, true otherwise. - */ - virtual bool setupFullscreenMode(); - - virtual void setInternalMousePosition(int x, int y); - - int _lastFullscreenModeWidth; - int _lastFullscreenModeHeight; - int _desktopWidth; - int _desktopHeight; - - // Hardware screen - SDL_Surface *_hwscreen; - - // If screen was resized by the user - bool _screenResized; - - // Ignore resize events for the number of updateScreen() calls. - // Normaly resize events are user generated when resizing the window - // from its borders, but in some cases a resize event can be generated - // after a fullscreen change. - int _ignoreResizeFrames; - -#ifdef USE_OSD - /** - * Displays a mode change message in OSD - */ - void displayModeChangedMsg(); - - /** - * Displays a scale change message in OSD - */ - void displayScaleChangedMsg(); -#endif -}; - -#endif -- cgit v1.2.3 From 46323074e77622e7d08fe20bfdcc459b8eba08a3 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 16 Aug 2013 05:29:56 +0200 Subject: OPENGL: Add new generic OpenGL (ES) backend. This backend is based on ideas of the old OpenGL backend, of the Android GL backend and of the iPhone GL backend. --- backends/graphics/opengl/debug.cpp | 65 ++ backends/graphics/opengl/debug.h | 39 ++ backends/graphics/opengl/extensions.cpp | 48 ++ backends/graphics/opengl/extensions.h | 41 ++ backends/graphics/opengl/opengl-graphics.cpp | 922 +++++++++++++++++++++++++++ backends/graphics/opengl/opengl-graphics.h | 418 ++++++++++++ backends/graphics/opengl/opengl-sys.h | 57 ++ backends/graphics/opengl/texture.cpp | 305 +++++++++ backends/graphics/opengl/texture.h | 159 +++++ 9 files changed, 2054 insertions(+) create mode 100644 backends/graphics/opengl/debug.cpp create mode 100644 backends/graphics/opengl/debug.h create mode 100644 backends/graphics/opengl/extensions.cpp create mode 100644 backends/graphics/opengl/extensions.h create mode 100644 backends/graphics/opengl/opengl-graphics.cpp create mode 100644 backends/graphics/opengl/opengl-graphics.h create mode 100644 backends/graphics/opengl/opengl-sys.h create mode 100644 backends/graphics/opengl/texture.cpp create mode 100644 backends/graphics/opengl/texture.h (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/debug.cpp b/backends/graphics/opengl/debug.cpp new file mode 100644 index 0000000000..69006bb975 --- /dev/null +++ b/backends/graphics/opengl/debug.cpp @@ -0,0 +1,65 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "backends/graphics/opengl/debug.h" +#include "backends/graphics/opengl/opengl-sys.h" + +#include "common/str.h" +#include "common/textconsole.h" + +#ifdef OPENGL_DEBUG + +namespace OpenGL { + +namespace { +Common::String getGLErrStr(GLenum error) { + switch (error) { + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + } + + return Common::String::format("(Unknown GL error code 0x%X)", error); +} +} // End of anonymous namespace + +void checkGLError(const char *expr, const char *file, int line) { + GLenum error = glGetError(); + + if (error != GL_NO_ERROR) { + // We cannot use error here because we do not know whether we have a + // working screen or not. + warning("GL ERROR: %s on %s (%s:%d)", getGLErrStr(error).c_str(), expr, file, line); + } +} +} // End of namespace OpenGL + +#endif diff --git a/backends/graphics/opengl/debug.h b/backends/graphics/opengl/debug.h new file mode 100644 index 0000000000..ff6b678870 --- /dev/null +++ b/backends/graphics/opengl/debug.h @@ -0,0 +1,39 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGL_DEBUG_H +#define BACKENDS_GRAPHICS_OPENGL_DEBUG_H + +#define OPENGL_DEBUG + +#ifdef OPENGL_DEBUG + +namespace OpenGL { +void checkGLError(const char *expr, const char *file, int line); +} // End of namespace OpenGL + +#define GLCALL(x) do { (x); OpenGL::checkGLError(#x, __FILE__, __LINE__); } while (false) +#else +#define GLCALL(x) do { (x); } while (false) +#endif + +#endif diff --git a/backends/graphics/opengl/extensions.cpp b/backends/graphics/opengl/extensions.cpp new file mode 100644 index 0000000000..4482ef82b5 --- /dev/null +++ b/backends/graphics/opengl/extensions.cpp @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "backends/graphics/opengl/extensions.h" +#include "backends/graphics/opengl/opengl-sys.h" + +#include "common/tokenizer.h" + +namespace OpenGL { + +bool g_extNPOTSupported = false; + +void initializeGLExtensions() { + const char *extString = (const char *)glGetString(GL_EXTENSIONS); + + // Initialize default state. + g_extNPOTSupported = false; + + Common::StringTokenizer tokenizer(extString, " "); + while (!tokenizer.empty()) { + Common::String token = tokenizer.nextToken(); + + if (token == "GL_ARB_texture_non_power_of_two") { + g_extNPOTSupported = true; + } + } +} + +} // End of namespace OpenGL diff --git a/backends/graphics/opengl/extensions.h b/backends/graphics/opengl/extensions.h new file mode 100644 index 0000000000..87452429e2 --- /dev/null +++ b/backends/graphics/opengl/extensions.h @@ -0,0 +1,41 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGL_EXTENSIONS_H +#define BACKENDS_GRAPHICS_OPENGL_EXTENSIONS_H + +namespace OpenGL { + +/** + * Checks for availability of extensions we want to use and initializes them + * when available. + */ +void initializeGLExtensions(); + +/** + * Whether non power of two textures are supported + */ +extern bool g_extNPOTSupported; + +} // End of namespace OpenGL + +#endif diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp new file mode 100644 index 0000000000..7ea880c92e --- /dev/null +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -0,0 +1,922 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "backends/graphics/opengl/opengl-graphics.h" +#include "backends/graphics/opengl/texture.h" +#include "backends/graphics/opengl/debug.h" +#include "backends/graphics/opengl/extensions.h" + +#include "common/textconsole.h" +#include "common/translation.h" +#include "common/algorithm.h" + +#include "graphics/conversion.h" + +namespace OpenGL { + +OpenGLGraphicsManager::OpenGLGraphicsManager() + : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)), + _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0), + _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(), + _gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr), + _overlayVisible(false), _cursor(nullptr), + _cursorX(0), _cursorY(0), _cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotXScaled(0), + _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), _cursorKeyColor(0), + _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false) { + memset(_gamePalette, 0, sizeof(_gamePalette)); +} + +OpenGLGraphicsManager::~OpenGLGraphicsManager() { + delete _gameScreen; + delete _overlay; + delete _cursor; +} + +bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { + switch (f) { + case OSystem::kFeatureAspectRatioCorrection: + case OSystem::kFeatureCursorPalette: + return true; + + case OSystem::kFeatureOverlaySupportsAlpha: + return _defaultFormatAlpha.aBits() > 3; + + default: + return false; + } +} + +void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + switch (f) { + case OSystem::kFeatureAspectRatioCorrection: + assert(_transactionMode != kTransactionNone); + _currentState.aspectRatioCorrection = enable; + break; + + case OSystem::kFeatureCursorPalette: + _cursorPaletteEnabled = enable; + updateCursorPalette(); + break; + + default: + break; + } +} + +bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { + switch (f) { + case OSystem::kFeatureAspectRatioCorrection: + return _currentState.aspectRatioCorrection; + + case OSystem::kFeatureCursorPalette: + return _cursorPaletteEnabled; + + default: + return false; + } +} + +namespace { + +const OSystem::GraphicsMode glGraphicsModes[] = { + { "opengl_linear", _s("OpenGL"), GFX_LINEAR }, + { "opengl_nearest", _s("OpenGL (No filtering)"), GFX_NEAREST }, + { nullptr, nullptr, 0 } +}; + +} // End of anonymous namespace + +const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() const { + return glGraphicsModes; +} + +int OpenGLGraphicsManager::getDefaultGraphicsMode() const { + return GFX_LINEAR; +} + +bool OpenGLGraphicsManager::setGraphicsMode(int mode) { + assert(_transactionMode != kTransactionNone); + + switch (mode) { + case GFX_LINEAR: + case GFX_NEAREST: + _currentState.graphicsMode = mode; + + if (_gameScreen) { + _gameScreen->enableLinearFiltering(mode == GFX_LINEAR); + } + + if (_overlay) { + _overlay->enableLinearFiltering(mode == GFX_LINEAR); + } + + if (_cursor) { + _cursor->enableLinearFiltering(mode == GFX_LINEAR); + } + return true; + + default: + warning("OpenGLGraphicsManager::setGraphicsMode(%d): Unknown graphics mode", mode); + return false; + } +} + +int OpenGLGraphicsManager::getGraphicsMode() const { + return _currentState.graphicsMode; +} + +#ifdef USE_RGB_COLOR +Graphics::PixelFormat OpenGLGraphicsManager::getScreenFormat() const { + return _currentState.gameFormat; +} +#endif + +void OpenGLGraphicsManager::beginGFXTransaction() { + assert(_transactionMode == kTransactionNone); + + // Start a transaction. + _oldState = _currentState; + _transactionMode = kTransactionActive; +} + +OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { + assert(_transactionMode == kTransactionActive); + + uint transactionError = OSystem::kTransactionSuccess; + + bool setupNewGameScreen = false; + if ( _oldState.gameWidth != _currentState.gameWidth + || _oldState.gameHeight != _currentState.gameHeight) { + setupNewGameScreen = true; + } + +#ifdef USE_RGB_COLOR + if (_oldState.gameFormat != _currentState.gameFormat) { + setupNewGameScreen = true; + } + + // Check whether the requested format can actually be used. + Common::List supportedFormats = getSupportedFormats(); + // In case the requested format is not usable we will fall back to CLUT8. + if (Common::find(supportedFormats.begin(), supportedFormats.end(), _currentState.gameFormat) == supportedFormats.end()) { + _currentState.gameFormat = Graphics::PixelFormat::createFormatCLUT8(); + transactionError |= OSystem::kTransactionFormatNotSupported; + } +#endif + + do { + uint requestedWidth = _currentState.gameWidth; + uint requestedHeight = _currentState.gameHeight; + const uint desiredAspect = getDesiredGameScreenAspect(); + requestedHeight = intToFrac(requestedWidth) / desiredAspect; + + if (!loadVideoMode(requestedWidth, requestedHeight, +#ifdef USE_RGB_COLOR + _currentState.gameFormat +#else + Graphics::PixelFormat::createFormatCLUT8() +#endif + )) { + if (_transactionMode == kTransactionActive) { + // Try to setup the old state in case its valid and is + // actually different from the new one. + if (_oldState.valid && _oldState != _currentState) { + // Give some hints on what failed to set up. + if ( _oldState.gameWidth != _currentState.gameWidth + || _oldState.gameHeight != _currentState.gameHeight) { + transactionError |= OSystem::kTransactionSizeChangeFailed; + } + +#ifdef USE_RGB_COLOR + if (_oldState.gameFormat != _currentState.gameFormat) { + transactionError |= OSystem::kTransactionFormatNotSupported; + } +#endif + + if (_oldState.aspectRatioCorrection != _currentState.aspectRatioCorrection) { + transactionError |= OSystem::kTransactionAspectRatioFailed; + } + + if (_oldState.graphicsMode != _currentState.graphicsMode) { + transactionError |= OSystem::kTransactionModeSwitchFailed; + } + + // Roll back to the old state. + _currentState = _oldState; + _transactionMode = kTransactionRollback; + + // Try to set up the old state. + continue; + } + } + + // DON'T use error(), as this tries to bring up the debug + // console, which WON'T WORK now that we might no have a + // proper screen. + warning("OpenGLGraphicsManager::endGFXTransaction: Could not load any graphics mode!"); + g_system->quit(); + } + + // In case we reach this we have a valid state, yay. + _transactionMode = kTransactionNone; + _currentState.valid = true; + } while (_transactionMode == kTransactionRollback); + + if (setupNewGameScreen) { + delete _gameScreen; + _gameScreen = nullptr; + + GLenum glIntFormat, glFormat, glType; +#ifdef USE_RGB_COLOR + if (_currentState.gameFormat.bytesPerPixel == 1) { +#endif + const bool supported = getGLPixelFormat(_defaultFormat, glIntFormat, glFormat, glType); + assert(supported); + _gameScreen = new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormat); + _gameScreen->setPalette(0, 255, _gamePalette); +#ifdef USE_RGB_COLOR + } else { + const bool supported = getGLPixelFormat(_currentState.gameFormat, glIntFormat, glFormat, glType); + assert(supported); + _gameScreen = new Texture(glIntFormat, glFormat, glType, _currentState.gameFormat); + } +#endif + + _gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight); + _gameScreen->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + // We fill the screen to all black or index 0 for CLUT8. + if (_currentState.gameFormat.bytesPerPixel == 1) { + _gameScreen->fill(0); + } else { + _gameScreen->fill(_gameScreen->getSurface()->format.RGBToColor(0, 0, 0)); + } + } + + // Update our display area and cursor scaling. This makes sure we pick up + // aspect ratio correction and game screen changes correctly. + recalculateDisplayArea(); + recalculateCursorScaling(); + + // Something changed, so update the screen change ID. + ++_screenChangeID; + + // Since transactionError is a ORd list of TransactionErrors this is + // clearly wrong. But our API is simply broken. + return (OSystem::TransactionError)transactionError; +} + +int OpenGLGraphicsManager::getScreenChangeID() const { + return _screenChangeID; +} + +void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::PixelFormat *format) { + Graphics::PixelFormat requestedFormat; +#ifdef USE_RGB_COLOR + if (!format) { + requestedFormat = Graphics::PixelFormat::createFormatCLUT8(); + } else { + requestedFormat = *format; + } + _currentState.gameFormat = requestedFormat; +#endif + + _currentState.gameWidth = width; + _currentState.gameHeight = height; +} + +int16 OpenGLGraphicsManager::getWidth() { + return _currentState.gameWidth; +} + +int16 OpenGLGraphicsManager::getHeight() { + return _currentState.gameHeight; +} + +void OpenGLGraphicsManager::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) { + _gameScreen->copyRectToTexture(x, y, w, h, buf, pitch); +} + +void OpenGLGraphicsManager::fillScreen(uint32 col) { + // FIXME: This does not conform to the OSystem specs because fillScreen + // is always taking CLUT8 color values and use color indexed mode. This is, + // however, plain odd and probably was a forgotten when we introduced + // RGB support. Thus, we simply do the "sane" thing here and hope OSystem + // gets fixed one day. + _gameScreen->fill(col); +} + +void OpenGLGraphicsManager::setShakePos(int shakeOffset) { + _gameScreenShakeOffset = shakeOffset; +} + +void OpenGLGraphicsManager::updateScreen() { + if (!_gameScreen) { + return; + } + + // Clear the screen buffer + GLCALL(glClear(GL_COLOR_BUFFER_BIT)); + + const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight(); + + // First step: Draw the (virtual) game screen. + glPushMatrix(); + + // Adjust game screen shake position + GLCALL(glTranslatef(0, shakeOffset, 0)); + + // Draw the game screen + _gameScreen->draw(_displayX, _displayY, _displayWidth, _displayHeight); + + glPopMatrix(); + + // Second step: Draw the overlay if visible. + if (_overlayVisible) { + _overlay->draw(0, 0, _outputScreenWidth, _outputScreenHeight); + } + + // Third step: Draw the cursor if visible. + if (_cursorVisible && _cursor) { + glPushMatrix(); + + // Adjust game screen shake position, but only when the overlay is not + // visible. + if (!_overlayVisible) { + GLCALL(glTranslatef(0, shakeOffset, 0)); + } + + _cursor->draw(_cursorX - _cursorHotspotXScaled, _cursorY - _cursorHotspotYScaled, + _cursorWidthScaled, _cursorHeightScaled); + + glPopMatrix(); + } +} + +Graphics::Surface *OpenGLGraphicsManager::lockScreen() { + return _gameScreen->getSurface(); +} + +void OpenGLGraphicsManager::unlockScreen() { + _gameScreen->flagDirty(); +} + +void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) { +} + +void OpenGLGraphicsManager::clearFocusRectangle() { +} + +int16 OpenGLGraphicsManager::getOverlayWidth() { + if (_overlay) { + return _overlay->getWidth(); + } else { + return 0; + } +} + +int16 OpenGLGraphicsManager::getOverlayHeight() { + if (_overlay) { + return _overlay->getHeight(); + } else { + return 0; + } +} + +void OpenGLGraphicsManager::showOverlay() { + _overlayVisible = true; +} + +void OpenGLGraphicsManager::hideOverlay() { + _overlayVisible = false; +} + +Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const { + return _overlay->getFormat(); +} + +void OpenGLGraphicsManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) { + _overlay->copyRectToTexture(x, y, w, h, buf, pitch); +} + +void OpenGLGraphicsManager::clearOverlay() { + _overlay->fill(0); +} + +void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) { + const Graphics::Surface *overlayData = _overlay->getSurface(); + + const byte *src = (const byte *)overlayData->getPixels(); + byte *dst = (byte *)buf; + + for (uint h = overlayData->h; h > 0; --h) { + memcpy(dst, src, overlayData->w * overlayData->format.bytesPerPixel); + dst += pitch; + src += overlayData->pitch; + } +} + +bool OpenGLGraphicsManager::showMouse(bool visible) { + bool last = _cursorVisible; + _cursorVisible = visible; + return last; +} + +void OpenGLGraphicsManager::warpMouse(int x, int y) { + int16 currentX = _cursorX; + int16 currentY = _cursorY; + adjustMousePosition(currentX, currentY); + + // Check whether the (virtual) coordinate actually changed. If not, then + // simply do nothing. This avoids ugly "jittering" due to the actual + // output screen having a bigger resolution than the virtual coordinates. + if (currentX == x && currentY == y) { + return; + } + + // Scale the virtual coordinates into actual physical coordinates. + if (_overlayVisible) { + if (!_overlay) { + return; + } + + // It might be confusing that we actually have to handle something + // here when the overlay is visible. This is because for very small + // resolutions we have a minimal overlay size and have to adjust + // for that. + x = (x * _outputScreenWidth) / _overlay->getWidth(); + y = (y * _outputScreenHeight) / _overlay->getHeight(); + } else { + if (!_gameScreen) { + return; + } + + x = (x * _displayWidth) / _gameScreen->getWidth(); + y = (y * _displayHeight) / _gameScreen->getHeight(); + + x += _displayX; + y += _displayY; + } + + setMousePosition(x, y); + setInternalMousePosition(x, y); +} + +namespace { +template +void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) { + const uint srcAdd = srcPitch - w * sizeof(SrcPixel); + const uint dstAdd = dstPitch - w * sizeof(DstPixel); + + while (h-- > 0) { + for (uint x = w; x > 0; --x, ++dst, ++src) { + if (*src == keyColor) { + *dst &= ~alphaMask; + } + } + + dst = (DstPixel *)((byte *)dst + dstAdd); + src = (const SrcPixel *)((const byte *)src + srcAdd); + } +} +} // End of anonymous namespace + +void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { + Graphics::PixelFormat inputFormat; +#ifdef USE_RGB_COLOR + if (format) { + inputFormat = *format; + } else { + inputFormat = Graphics::PixelFormat::createFormatCLUT8(); + } +#else + inputFormat = Graphics::PixelFormat::createFormatCLUT8(); +#endif + + // In case the color format has changed we will need to create the texture. + if (!_cursor || _cursor->getFormat() != inputFormat) { + delete _cursor; + _cursor = nullptr; + + GLenum glIntFormat, glFormat, glType; + + if (inputFormat.bytesPerPixel == 1) { + // In case this is not supported this is a serious programming + // error and the assert a bit below will trigger! + const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); + assert(supported); + _cursor = new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormatAlpha); + } else { + // Try to use the format specified as input directly. We can only + // do so when it actually has alpha bits. + if (inputFormat.aBits() != 0 && getGLPixelFormat(inputFormat, glIntFormat, glFormat, glType)) { + _cursor = new Texture(glIntFormat, glFormat, glType, inputFormat); + } + + // Otherwise fall back to the default alpha format. + if (!_cursor) { + const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); + assert(supported); + _cursor = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); + } + } + + assert(_cursor); + _cursor->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + } + + _cursorKeyColor = keycolor; + _cursorHotspotX = hotspotX; + _cursorHotspotY = hotspotY; + _cursorDontScale = dontScale; + + _cursor->allocate(w, h); + if (inputFormat.bytesPerPixel == 1) { + // For CLUT8 cursors we can simply copy the input data into the + // texture. + _cursor->copyRectToTexture(0, 0, w, h, buf, w * inputFormat.bytesPerPixel); + } else { + // Otherwise it is a bit more ugly because we have to handle a key + // color properly. + + Graphics::Surface *dst = _cursor->getSurface(); + const uint srcPitch = w * inputFormat.bytesPerPixel; + + // In case the actual cursor format differs from the requested format + // we will need to convert the format. This might be the case because + // the cursor format does not have any alpha bits. + if (dst->format != inputFormat) { + Graphics::crossBlit((byte *)dst->getPixels(), (const byte *)buf, dst->pitch, srcPitch, + w, h, dst->format, inputFormat); + } + + // We apply the color key by setting the alpha bits of the pixels to + // fully transparent. + const uint32 aMask = (0xFF >> dst->format.aLoss) << dst->format.aShift; + if (dst->format.bytesPerPixel == 2) { + if (inputFormat.bytesPerPixel == 2) { + applyColorKey((uint16 *)dst->getPixels(), (const uint16 *)buf, w, h, + dst->pitch, srcPitch, keycolor, aMask); + } else if (inputFormat.bytesPerPixel == 4) { + applyColorKey((uint16 *)dst->getPixels(), (const uint32 *)buf, w, h, + dst->pitch, srcPitch, keycolor, aMask); + } + } else { + if (inputFormat.bytesPerPixel == 2) { + applyColorKey((uint32 *)dst->getPixels(), (const uint16 *)buf, w, h, + dst->pitch, srcPitch, keycolor, aMask); + } else if (inputFormat.bytesPerPixel == 4) { + applyColorKey((uint32 *)dst->getPixels(), (const uint32 *)buf, w, h, + dst->pitch, srcPitch, keycolor, aMask); + } + } + + // Flag the texture as dirty. + _cursor->flagDirty(); + } + + // In case we actually use a palette set that up properly. + if (inputFormat.bytesPerPixel == 1) { + updateCursorPalette(); + } + + // Update the scaling. + recalculateCursorScaling(); +} + +void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) { + // FIXME: For some reason client code assumes that usage of this function + // automatically enables the cursor palette. + _cursorPaletteEnabled = true; + + memcpy(_cursorPalette + start * 3, colors, num * 3); + updateCursorPalette(); +} + +void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { +} + +void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { + assert(_gameScreen->hasPalette()); + + memcpy(_gamePalette + start * 3, colors, num * 3); + _gameScreen->setPalette(start, num, colors); + + // We might need to update the cursor palette here. + updateCursorPalette(); +} + +void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { + assert(_gameScreen->hasPalette()); + + memcpy(colors, _gamePalette + start * 3, num * 3); +} + +void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { + _outputScreenWidth = width; + _outputScreenHeight = height; + + // Setup coordinates system. + GLCALL(glViewport(0, 0, _outputScreenWidth, _outputScreenHeight)); + + GLCALL(glMatrixMode(GL_PROJECTION)); + GLCALL(glLoadIdentity()); +#ifdef USE_GLES + GLCALL(glOrthof(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1)); +#else + GLCALL(glOrtho(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1)); +#endif + GLCALL(glMatrixMode(GL_MODELVIEW)); + GLCALL(glLoadIdentity()); + + // HACK: We limit the minimal overlay size to 256x200, which is the + // minimum of the dimensions of the two resolutions 256x240 (NES) and + // 320x200 (many DOS games use this). This hopefully assure that our + // GUI has working layouts. + const uint overlayWidth = MAX(width, 256); + const uint overlayHeight = MAX(height, 200); + + if (!_overlay || _overlay->getFormat() != _defaultFormatAlpha) { + delete _overlay; + _overlay = nullptr; + + GLenum glIntFormat, glFormat, glType; + const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); + assert(supported); + _overlay = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); + _overlay->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + } + _overlay->allocate(overlayWidth, overlayHeight); + _overlay->fill(0); + + // Re-setup the scaling for the screen and cursor + recalculateDisplayArea(); + recalculateCursorScaling(); + + // Something changed, so update the screen change ID. + ++_screenChangeID; +} + +void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) { + // Initialize all extensions. + initializeGLExtensions(); + + // Disable 3D properties. + GLCALL(glDisable(GL_CULL_FACE)); + GLCALL(glDisable(GL_DEPTH_TEST)); + GLCALL(glDisable(GL_LIGHTING)); + GLCALL(glDisable(GL_FOG)); + GLCALL(glDisable(GL_DITHER)); + GLCALL(glShadeModel(GL_FLAT)); + GLCALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); + + // Default to black as clear color. + GLCALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); + GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); + + // Setup alpha blend (for overlay and cursor). + GLCALL(glEnable(GL_BLEND)); + GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + + // Enable rendering with vertex and coord arrays. + GLCALL(glEnableClientState(GL_VERTEX_ARRAY)); + GLCALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + + GLCALL(glEnable(GL_TEXTURE_2D)); + + // Refresh the output screen dimensions if some are set up. + if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { + setActualScreenSize(_outputScreenWidth, _outputScreenHeight); + } + + // TODO: Should we try to convert textures into one of those formats if + // possible? For example, when _gameScreen is CLUT8 we might want to use + // defaultFormat now. + _defaultFormat = defaultFormat; + _defaultFormatAlpha = defaultFormatAlpha; + + if (_gameScreen) { + _gameScreen->recreateInternalTexture(); + } + + if (_overlay) { + _overlay->recreateInternalTexture(); + } + + if (_cursor) { + _cursor->recreateInternalTexture(); + } +} + +void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { + if (_overlayVisible) { + // It might be confusing that we actually have to handle something + // here when the overlay is visible. This is because for very small + // resolutions we have a minimal overlay size and have to adjust + // for that. + if (_overlay) { + x = (x * _overlay->getWidth()) / _outputScreenWidth; + y = (y * _overlay->getHeight()) / _outputScreenHeight; + } + } else if (_gameScreen) { + x -= _displayX; + y -= _displayY; + + const int16 width = _gameScreen->getWidth(); + const int16 height = _gameScreen->getHeight(); + + x = (x * width) / _displayWidth; + y = (y * height) / _displayHeight; + + // Make sure we only supply valid coordinates. + x = CLIP(x, 0, width - 1); + y = CLIP(y, 0, height - 1); + } +} + +bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const { + if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 + glIntFormat = GL_RGBA; + glFormat = GL_RGBA; + glType = GL_UNSIGNED_INT_8_8_8_8; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 + glIntFormat = GL_RGB; + glFormat = GL_RGB; + glType = GL_UNSIGNED_SHORT_5_6_5; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGBA5551 + glIntFormat = GL_RGBA; + glFormat = GL_RGBA; + glType = GL_UNSIGNED_SHORT_5_5_5_1; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444 + glIntFormat = GL_RGBA; + glFormat = GL_RGBA; + glType = GL_UNSIGNED_SHORT_4_4_4_4; + return true; +#ifndef USE_GLES + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 + // GL_BGRA does not exist in every GLES implementation so should not be configured if + // USE_GLES is set. + glIntFormat = GL_RGB; + glFormat = GL_BGRA; + glType = GL_UNSIGNED_SHORT_1_5_5_5_REV; + return true; + } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)) { // ARGB8888 + glIntFormat = GL_RGBA; + glFormat = GL_BGRA; + glType = GL_UNSIGNED_INT_8_8_8_8_REV; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)) { // ARGB4444 + glIntFormat = GL_RGBA; + glFormat = GL_BGRA; + glType = GL_UNSIGNED_SHORT_4_4_4_4_REV; + return true; + } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888 + glIntFormat = GL_RGBA; + glFormat = GL_RGBA; + glType = GL_UNSIGNED_INT_8_8_8_8_REV; + return true; + } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0)) { // BGRA8888 + glIntFormat = GL_RGBA; + glFormat = GL_BGRA; + glType = GL_UNSIGNED_INT_8_8_8_8; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)) { // BGR565 + glIntFormat = GL_RGB; + glFormat = GL_BGR; + glType = GL_UNSIGNED_SHORT_5_6_5; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0)) { // BGRA5551 + glIntFormat = GL_RGBA; + glFormat = GL_BGRA; + glType = GL_UNSIGNED_SHORT_5_5_5_1; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12)) { // ABGR4444 + glIntFormat = GL_RGBA; + glFormat = GL_RGBA; + glType = GL_UNSIGNED_SHORT_4_4_4_4_REV; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)) { // BGRA4444 + glIntFormat = GL_RGBA; + glFormat = GL_BGRA; + glType = GL_UNSIGNED_SHORT_4_4_4_4; + return true; +#endif + } else { + return false; + } +} + +frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const { + const uint width = _currentState.gameWidth; + const uint height = _currentState.gameHeight; + + if (_currentState.aspectRatioCorrection) { + // In case we enable aspect ratio correction we force a 4/3 ratio. + // But just for 320x200 and 640x400 games, since other games do not need + // this. + if ((width == 320 && height == 200) || (width == 640 && height == 400)) { + return intToFrac(4) / 3; + } + } + + return intToFrac(width) / height; +} + +void OpenGLGraphicsManager::recalculateDisplayArea() { + if (!_gameScreen || _outputScreenHeight == 0) { + return; + } + + const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; + const frac_t desiredAspect = getDesiredGameScreenAspect(); + + _displayWidth = _outputScreenWidth; + _displayHeight = _outputScreenHeight; + + // Adjust one dimension for mantaining the aspect ratio. + if (outputAspect < desiredAspect) { + _displayHeight = intToFrac(_displayWidth) / desiredAspect; + } else if (outputAspect > desiredAspect) { + _displayWidth = fracToInt(_displayHeight * desiredAspect); + } + + // We center the screen in the middle for now. + _displayX = (_outputScreenWidth - _displayWidth ) / 2; + _displayY = (_outputScreenHeight - _displayHeight) / 2; +} + +void OpenGLGraphicsManager::updateCursorPalette() { + if (!_cursor || !_cursor->hasPalette()) { + return; + } + + if (_cursorPaletteEnabled) { + _cursor->setPalette(0, 256, _cursorPalette); + } else { + _cursor->setPalette(0, 256, _gamePalette); + } + + // We remove all alpha bits from the palette entry of the color key. + // This makes sure its properly handled as color key. + const Graphics::PixelFormat &hardwareFormat = _cursor->getHardwareFormat(); + const uint32 aMask = (0xFF >> hardwareFormat.aLoss) << hardwareFormat.aShift; + + if (hardwareFormat.bytesPerPixel == 2) { + uint16 *palette = (uint16 *)_cursor->getPalette() + _cursorKeyColor; + *palette &= ~aMask; + } else if (hardwareFormat.bytesPerPixel == 4) { + uint32 *palette = (uint32 *)_cursor->getPalette() + _cursorKeyColor; + *palette &= ~aMask; + } else { + warning("OpenGLGraphicsManager::updateCursorPalette: Unsupported pixel depth %d", hardwareFormat.bytesPerPixel); + } +} + +void OpenGLGraphicsManager::recalculateCursorScaling() { + if (!_cursor || !_gameScreen) { + return; + } + + // By default we use the unscaled versions. + _cursorHotspotXScaled = _cursorHotspotX; + _cursorHotspotYScaled = _cursorHotspotY; + _cursorWidthScaled = _cursor->getWidth(); + _cursorHeightScaled = _cursor->getHeight(); + + // In case scaling is actually enabled we will scale the cursor according + // to the game screen. + if (!_cursorDontScale) { + const uint screenScaleFactorX = _displayWidth * 10000 / _gameScreen->getWidth(); + const uint screenScaleFactorY = _displayHeight * 10000 / _gameScreen->getHeight(); + + _cursorHotspotXScaled = (_cursorHotspotXScaled * screenScaleFactorX) / 10000; + _cursorWidthScaled = (_cursorWidthScaled * screenScaleFactorX) / 10000; + + _cursorHotspotYScaled = (_cursorHotspotYScaled * screenScaleFactorY) / 10000; + _cursorHeightScaled = (_cursorHeightScaled * screenScaleFactorY) / 10000; + } +} + +} // End of namespace OpenGL diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h new file mode 100644 index 0000000000..e21bda4b8a --- /dev/null +++ b/backends/graphics/opengl/opengl-graphics.h @@ -0,0 +1,418 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H +#define BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H + +#include "backends/graphics/opengl/opengl-sys.h" +#include "backends/graphics/graphics.h" + +#include "common/frac.h" + +namespace OpenGL { + +class Texture; + +enum { + GFX_LINEAR = 0, + GFX_NEAREST = 1 +}; + +class OpenGLGraphicsManager : public GraphicsManager { +public: + OpenGLGraphicsManager(); + virtual ~OpenGLGraphicsManager(); + + // GraphicsManager API + virtual bool hasFeature(OSystem::Feature f); + virtual void setFeatureState(OSystem::Feature f, bool enable); + virtual bool getFeatureState(OSystem::Feature f); + + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; + virtual int getDefaultGraphicsMode() const; + virtual bool setGraphicsMode(int mode); + virtual int getGraphicsMode() const; + + virtual void resetGraphicsScale() {} + +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const; + virtual Common::List getSupportedFormats() const = 0; +#endif + + virtual void beginGFXTransaction(); + virtual OSystem::TransactionError endGFXTransaction(); + + virtual int getScreenChangeID() const; + + virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format); + + virtual int16 getWidth(); + virtual int16 getHeight(); + + virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); + virtual void fillScreen(uint32 col); + + virtual void setShakePos(int shakeOffset); + + virtual void updateScreen(); + + virtual Graphics::Surface *lockScreen(); + virtual void unlockScreen(); + + virtual void setFocusRectangle(const Common::Rect& rect); + virtual void clearFocusRectangle(); + + virtual int16 getOverlayWidth(); + virtual int16 getOverlayHeight(); + + virtual void showOverlay(); + virtual void hideOverlay(); + + virtual Graphics::PixelFormat getOverlayFormat() const; + + virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h); + virtual void clearOverlay(); + virtual void grabOverlay(void *buf, int pitch); + + virtual bool showMouse(bool visible); + virtual void warpMouse(int x, int y); + virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format); + virtual void setCursorPalette(const byte *colors, uint start, uint num); + + virtual void displayMessageOnOSD(const char *msg); + + // PaletteManager interface + virtual void setPalette(const byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num); + +protected: + /** + * Set up the actual screen size available for the OpenGL code to do any + * drawing. + * + * @param width The width of the screen. + * @param height The height of the screen. + */ + void setActualScreenSize(uint width, uint height); + + /** + * Notify the manager of a OpenGL context change. This should be the first + * thing to call when you create an OpenGL (ES) context! + * + * @param defaultFormat The new default format for the game screen + * (this is used for the CLUT8 game screens). + * @param defaultFromatAlpha The new default format with an alpha channel + * (this is used for the overlay and cursor). + */ + void notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha); + + /** + * Adjust the physical mouse coordinates according to the currently visible screen. + */ + void adjustMousePosition(int16 &x, int16 &y); + + /** + * Set up the mouse position for graphics output. + * + * @param x X coordinate in physical coordinates. + * @param y Y coordinate in physical coordinates. + */ + void setMousePosition(int x, int y) { _cursorX = x; _cursorY = y; } + + /** + * Set up the mouse position for the (event) system. + * + * @param x X coordinate in physical coordinates. + * @param y Y coordinate in physical coordinates. + */ + virtual void setInternalMousePosition(int x, int y) = 0; + +private: + // + // Transaction support + // + struct VideoState { + VideoState() : valid(false), gameWidth(0), gameHeight(0), +#ifdef USE_RGB_COLOR + gameFormat(), +#endif + aspectRatioCorrection(false), graphicsMode(GFX_LINEAR) { + } + + bool valid; + + uint gameWidth, gameHeight; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat gameFormat; +#endif + bool aspectRatioCorrection; + int graphicsMode; + + bool operator==(const VideoState &right) { + return gameWidth == right.gameWidth && gameHeight == right.gameHeight +#ifdef USE_RGB_COLOR + && gameFormat == right.gameFormat +#endif + && aspectRatioCorrection == right.aspectRatioCorrection + && graphicsMode == right.graphicsMode; + } + + bool operator!=(const VideoState &right) { + return !(*this == right); + } + }; + + /** + * The currently setup video state. + */ + VideoState _currentState; + + /** + * The old video state used when doing a transaction rollback. + */ + VideoState _oldState; + +protected: + enum TransactionMode { + kTransactionNone = 0, + kTransactionActive = 1, + kTransactionRollback = 2 + }; + + TransactionMode getTransactionMode() const { return _transactionMode; } + +private: + /** + * The current transaction mode. + */ + TransactionMode _transactionMode; + + /** + * The current screen change ID. + */ + int _screenChangeID; + +protected: + /** + * Set up the requested video mode. This takes parameters which describe + * what resolution the game screen requests (this is possibly aspect ratio + * corrected!). + * + * A sub-class should take these parameters as hints. It might very well + * set up a mode which it thinks suites the situation best. + * + * @parma requestedWidth This is the requested actual game screen width. + * @param requestedHeight This is the requested actual game screen height. + * @param format This is the requested pixel format of the virtual game screen. + * @return true on success, false otherwise + */ + virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0; + +private: + // + // OpenGL utilities + // + + /** + * Try to determine the internal parameters for a given pixel format. + * + * @return true when the format can be used, false otherwise. + */ + bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const; + + // + // Actual hardware screen + // + + /** + * The width of the physical output. + */ + uint _outputScreenWidth; + + /** + * The height of the physical output. + */ + uint _outputScreenHeight; + + /** + * @return The desired aspect of the game screen. + */ + frac_t getDesiredGameScreenAspect() const; + + /** + * Recalculates the area used to display the game screen. + */ + void recalculateDisplayArea(); + + /** + * The X coordinate of the game screen. + */ + uint _displayX; + + /** + * The Y coordinate of the game screen. + */ + uint _displayY; + + /** + * The width of the game screen in physical coordinates. + */ + uint _displayWidth; + + /** + * The height of the game screen in physical coordinates. + */ + uint _displayHeight; + + /** + * The default pixel format of the backend. + */ + Graphics::PixelFormat _defaultFormat; + + /** + * The default pixel format with an alpha channel. + */ + Graphics::PixelFormat _defaultFormatAlpha; + + // + // Game screen + // + + /** + * The virtual game screen. + */ + Texture *_gameScreen; + + /** + * The game palette if in CLUT8 mode. + */ + byte _gamePalette[3 * 256]; + + /** + * The offset by which the screen is moved vertically. + */ + int _gameScreenShakeOffset; + + // + // Overlay + // + + /** + * The overlay screen. + */ + Texture *_overlay; + + /** + * Whether the overlay is visible or not. + */ + bool _overlayVisible; + + // + // Cursor + // + + /** + * Set up the correct cursor palette. + */ + void updateCursorPalette(); + + /** + * The cursor image. + */ + Texture *_cursor; + + /** + * X coordinate of the cursor in phyiscal coordinates. + */ + uint _cursorX; + + /** + * Y coordinate of the cursor in physical coordinates. + */ + uint _cursorY; + + /** + * The X offset for the cursor hotspot in unscaled coordinates. + */ + uint _cursorHotspotX; + + /** + * The Y offset for the cursor hotspot in unscaled coordinates. + */ + uint _cursorHotspotY; + + /** + * Recalculate the cursor scaling. Scaling is always done according to + * the game screen. + */ + void recalculateCursorScaling(); + + /** + * The X offset for the cursor hotspot in scaled coordinates. + */ + uint _cursorHotspotXScaled; + + /** + * The Y offset for the cursor hotspot in scaled coordinates. + */ + uint _cursorHotspotYScaled; + + /** + * The width of the cursor scaled coordinates. + */ + uint _cursorWidthScaled; + + /** + * The height of the cursor scaled coordinates. + */ + uint _cursorHeightScaled; + + /** + * The key color. + */ + uint32 _cursorKeyColor; + + /** + * Whether the cursor is actually visible. + */ + bool _cursorVisible; + + /** + * Whether no cursor scaling should be applied. + */ + bool _cursorDontScale; + + /** + * Whether the special cursor palette is enabled. + */ + bool _cursorPaletteEnabled; + + /** + * The special cursor palette in case enabled. + */ + byte _cursorPalette[3 * 256]; +}; + +} // End of namespace OpenGL + +#endif diff --git a/backends/graphics/opengl/opengl-sys.h b/backends/graphics/opengl/opengl-sys.h new file mode 100644 index 0000000000..a3524b28d2 --- /dev/null +++ b/backends/graphics/opengl/opengl-sys.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGL_OPENGL_H +#define BACKENDS_GRAPHICS_OPENGL_OPENGL_H + +// The purpose of this header is to include the OpenGL headers in an uniform +// fashion. A notable example for a non standard port is the Tizen port. + +#include "common/scummsys.h" + +#ifdef WIN32 +#if defined(ARRAYSIZE) && !defined(_WINDOWS_) +#undef ARRAYSIZE +#endif +#define WIN32_LEAN_AND_MEAN +#include +#undef ARRAYSIZE +#endif + +// HACK: In case common/util.h has been included already we need to make sure +// to define ARRAYSIZE again in case of Windows. +#if !defined(ARRAYSIZE) && defined(COMMON_UTIL_H) +#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0]))) +#endif + +#if defined(TIZEN) +#include +using namespace Tizen::Graphics::Opengl; +#elif defined(USE_GLES) +#include +#elif defined(SDL_BACKEND) +#include +#else +#include +#endif + +#endif diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp new file mode 100644 index 0000000000..3067aa7d1c --- /dev/null +++ b/backends/graphics/opengl/texture.cpp @@ -0,0 +1,305 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "backends/graphics/opengl/texture.h" +#include "backends/graphics/opengl/extensions.h" +#include "backends/graphics/opengl/debug.h" + +#include "common/rect.h" +#include "common/textconsole.h" + +namespace OpenGL { + +static GLuint nextHigher2(GLuint v) { + if (v == 0) + return 1; + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return ++v; +} + +Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) + : _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType), _format(format), _glFilter(GL_NEAREST), + _glTexture(0), _textureData(), _userPixelData(), _allDirty(false) { + recreateInternalTexture(); +} + +Texture::~Texture() { + releaseInternalTexture(); + _textureData.free(); +} + +void Texture::releaseInternalTexture() { + GLCALL(glDeleteTextures(1, &_glTexture)); + _glTexture = 0; +} + +void Texture::recreateInternalTexture() { + // Get a new texture name. + GLCALL(glGenTextures(1, &_glTexture)); + + // Set up all texture parameters. + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + + // In case there is an actual texture setup we reinitialize it. + if (_textureData.getPixels()) { + // Mark dirts such that it will be completely refreshed the next time. + flagDirty(); + } +} + +void Texture::enableLinearFiltering(bool enable) { + if (enable) { + _glFilter = GL_LINEAR; + } else { + _glFilter = GL_NEAREST; + } + + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter)); + GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter)); +} + +void Texture::allocate(uint width, uint height) { + uint texWidth = width, texHeight = height; + if (!g_extNPOTSupported) { + texWidth = nextHigher2(texWidth); + texHeight = nextHigher2(texHeight); + } + + // In case the needed texture dimension changed we will reinitialize the + // texture. + if (texWidth != _textureData.w || texHeight != _textureData.h) { + // Create a buffer for the texture data. + _textureData.create(texWidth, texHeight, _format); + } + + // Create a sub-buffer for raw access. + _userPixelData = _textureData.getSubArea(Common::Rect(width, height)); +} + +void Texture::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcPtr, uint srcPitch) { + Graphics::Surface *dstSurf = getSurface(); + assert(x + w <= dstSurf->w); + assert(y + h <= dstSurf->h); + + const byte *src = (const byte *)srcPtr; + byte *dst = (byte *)dstSurf->getBasePtr(x, y); + const uint pitch = dstSurf->pitch; + const uint bytesPerPixel = dstSurf->format.bytesPerPixel; + + if (srcPitch == pitch && x == 0 && w == dstSurf->w) { + memcpy(dst, src, h * pitch); + } else { + while (h-- > 0) { + memcpy(dst, src, w * bytesPerPixel); + dst += pitch; + src += srcPitch; + } + } + + flagDirty(); +} + +void Texture::fill(uint32 color) { + Graphics::Surface *dst = getSurface(); + dst->fillRect(Common::Rect(dst->w, dst->h), color); + + flagDirty(); +} + +void Texture::draw(GLuint x, GLuint y, GLuint w, GLuint h) { + // Only do any processing when the Texture is initialized. + if (!_textureData.getPixels()) { + return; + } + + // First update any potentional changes. + updateTexture(); + + // Set the texture. + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + + // Calculate the texture rect that will be drawn. + const GLfloat texWidth = (GLfloat)_userPixelData.w / _textureData.w; + const GLfloat texHeight = (GLfloat)_userPixelData.h / _textureData.h; + const GLfloat texcoords[4*2] = { + 0, 0, + texWidth, 0, + 0, texHeight, + texWidth, texHeight + }; + GLCALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); + + // Calculate the screen rect where the texture will be drawn. + const GLshort vertices[4*2] = { + (GLshort)x, (GLshort)y, + (GLshort)(x + w), (GLshort)y, + (GLshort)x, (GLshort)(y + h), + (GLshort)(x + w), (GLshort)(y + h) + }; + GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices)); + + // Draw the texture to the screen buffer. + GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); +} + +void Texture::updateTexture() { + if (!isDirty()) { + return; + } + + // In case we use linear filtering we might need to duplicate the last + // pixel row/column to avoid glitches with filtering. + if (_glFilter == GL_LINEAR) { + if (_textureData.w != _userPixelData.w) { + uint height = _userPixelData.h; + + const byte *src = (const byte *)_textureData.getBasePtr(_userPixelData.w - 1, 0); + byte *dst = (byte *)_textureData.getBasePtr(_userPixelData.w, 0); + + while (height-- > 0) { + memcpy(dst, src, _textureData.format.bytesPerPixel); + dst += _textureData.pitch; + src += _textureData.pitch; + } + } + + if (_textureData.h != _userPixelData.h) { + const byte *src = (const byte *)_textureData.getBasePtr(0, _userPixelData.h - 1); + byte *dst = (byte *)_textureData.getBasePtr(0, _userPixelData.h); + memcpy(dst, src, _userPixelData.w * _textureData.format.bytesPerPixel); + } + } + + // Set the texture. + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + + // Update the actual texture. + GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, _textureData.h, 0, _glFormat, _glType, _textureData.getPixels())); + + // We should have handled everything, thus not dirty anymore. + clearDirty(); +} + +TextureCLUT8::TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) + : Texture(glIntFormat, glFormat, glType, format), _clut8Data(), _palette(new byte[256 * format.bytesPerPixel]) { + memset(_palette, 0, sizeof(byte) * format.bytesPerPixel); +} + +TextureCLUT8::~TextureCLUT8() { + delete[] _palette; + _palette = nullptr; + _clut8Data.free(); +} + +void TextureCLUT8::allocate(uint width, uint height) { + Texture::allocate(width, height); + + // We only need to reinitialize our CLUT8 surface when the output size + // changed. + if (width == _clut8Data.w && width == _clut8Data.h) { + return; + } + + _clut8Data.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); +} + +Graphics::PixelFormat TextureCLUT8::getFormat() const { + return Graphics::PixelFormat::createFormatCLUT8(); +} + +namespace { +template +inline void convertPalette(ColorType *dst, const byte *src, uint colors, const Graphics::PixelFormat &format) { + while (colors-- > 0) { + *dst++ = format.RGBToColor(src[0], src[1], src[2]); + src += 3; + } +} +} // End of anonymous namespace + +void TextureCLUT8::setPalette(uint start, uint colors, const byte *palData) { + const Graphics::PixelFormat &hardwareFormat = getHardwareFormat(); + + if (hardwareFormat.bytesPerPixel == 2) { + convertPalette((uint16 *)_palette + start, palData, colors, hardwareFormat); + } else if (hardwareFormat.bytesPerPixel == 4) { + convertPalette((uint32 *)_palette + start, palData, colors, hardwareFormat); + } else { + warning("TextureCLUT8::setPalette: Unsupported pixel depth: %d", hardwareFormat.bytesPerPixel); + } + + // A palette changes means we need to refresh the whole surface. + flagDirty(); +} + +namespace { +template +inline void doPaletteLookUp(PixelType *dst, const byte *src, uint width, uint height, uint dstPitch, uint srcPitch, const PixelType *palette) { + uint srcAdd = srcPitch - width; + uint dstAdd = dstPitch - width * sizeof(PixelType); + + while (height-- > 0) { + for (uint x = width; x > 0; --x) { + *dst++ = palette[*src++]; + } + + dst = (PixelType *)((byte *)dst + dstAdd); + src += srcAdd; + } +} +} // End of anonymous namespace + +void TextureCLUT8::updateTexture() { + if (!isDirty()) { + return; + } + + // Do the palette look up + Graphics::Surface *outSurf = Texture::getSurface(); + + if (outSurf->format.bytesPerPixel == 2) { + doPaletteLookUp((uint16 *)outSurf->getPixels(), (const byte *)_clut8Data.getPixels(), _clut8Data.w, _clut8Data.h, + outSurf->pitch, _clut8Data.pitch, (const uint16 *)_palette); + } else if (outSurf->format.bytesPerPixel == 4) { + doPaletteLookUp((uint32 *)outSurf->getPixels(), (const byte *)_clut8Data.getPixels(), _clut8Data.w, _clut8Data.h, + outSurf->pitch, _clut8Data.pitch, (const uint32 *)_palette); + } else { + warning("TextureCLUT8::updateTexture: Unsupported pixel depth: %d", outSurf->format.bytesPerPixel); + } + + // Do generic handling of updating the texture. + Texture::updateTexture(); +} + +} // End of namespace OpenGL diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h new file mode 100644 index 0000000000..1127aed350 --- /dev/null +++ b/backends/graphics/opengl/texture.h @@ -0,0 +1,159 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGL_TEXTURE_H +#define BACKENDS_GRAPHICS_OPENGL_TEXTURE_H + +#include "backends/graphics/opengl/opengl-sys.h" + +#include "graphics/pixelformat.h" +#include "graphics/surface.h" + +namespace OpenGL { + +/** + * An OpenGL texture wrapper. It automatically takes care of all OpenGL + * texture handling issues and also provides access to the texture data. + */ +class Texture { +public: + /** + * Create a new texture with the specific internal format. + * + * @param glIntFormat The internal format to use. + * @param glFormat The input format. + * @param glType The input type. + * @param format The format used for the texture input. + */ + Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format); + virtual ~Texture(); + + /** + * Destroy the OpenGL texture name. + */ + void releaseInternalTexture(); + + /** + * Create the OpenGL texture name and flag the whole texture as dirty. + */ + void recreateInternalTexture(); + + /** + * Enable or disable linear texture filtering. + * + * @param enable true to enable and false to disable. + */ + void enableLinearFiltering(bool enable); + + /** + * Allocate texture space for the desired dimensions. This wraps any + * handling of requirements for POT textures. + * + * @param width The desired logical width. + * @param height The desired logical height. + */ + virtual void allocate(uint width, uint height); + + void copyRectToTexture(uint x, uint y, uint w, uint h, const void *src, uint srcPitch); + + void fill(uint32 color); + + void draw(GLuint x, GLuint y, GLuint w, GLuint h); + + void flagDirty() { _allDirty = true; } + bool isDirty() const { return _allDirty; } + + uint getWidth() const { return _userPixelData.w; } + uint getHeight() const { return _userPixelData.h; } + + /** + * @return The hardware format of the texture data. + */ + const Graphics::PixelFormat &getHardwareFormat() const { return _format; } + + /** + * @return The logical format of the texture data. + */ + virtual Graphics::PixelFormat getFormat() const { return _format; } + + virtual Graphics::Surface *getSurface() { return &_userPixelData; } + virtual const Graphics::Surface *getSurface() const { return &_userPixelData; } + + /** + * @return Whether the texture data is using a palette. + */ + virtual bool hasPalette() const { return false; } + + virtual void setPalette(uint start, uint colors, const byte *palData) {} + + virtual void *getPalette() { return 0; } + virtual const void *getPalette() const { return 0; } + +protected: + virtual void updateTexture(); + +private: + const GLenum _glIntFormat; + const GLenum _glFormat; + const GLenum _glType; + const Graphics::PixelFormat _format; + + GLint _glFilter; + GLuint _glTexture; + + Graphics::Surface _textureData; + Graphics::Surface _userPixelData; + + bool _allDirty; + void clearDirty() { _allDirty = false; } +}; + +class TextureCLUT8 : public Texture { +public: + TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format); + virtual ~TextureCLUT8(); + + virtual void allocate(uint width, uint height); + + virtual Graphics::PixelFormat getFormat() const; + + virtual bool hasPalette() const { return true; } + + virtual void setPalette(uint start, uint colors, const byte *palData); + + virtual void *getPalette() { return _palette; } + virtual const void *getPalette() const { return _palette; } + + virtual Graphics::Surface *getSurface() { return &_clut8Data; } + virtual const Graphics::Surface *getSurface() const { return &_clut8Data; } + +protected: + virtual void updateTexture(); + +private: + Graphics::Surface _clut8Data; + byte *_palette; +}; + +} // End of namespace OpenGL + +#endif -- cgit v1.2.3 From 5ce830b97643fc76bdcafdbbe09e226519a9d2e6 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 18 Aug 2013 16:56:34 +0200 Subject: SDL: Add a OpenGL SDL backend and hook it into the SDL backend. The hooking code is nearly exactly the old hooking code. Only the OpenGL SDL creation has been adapted since it uses a different constructor now. --- backends/graphics/opengl/opengl-graphics.cpp | 4 + backends/graphics/opengl/opengl-graphics.h | 4 + backends/graphics/openglsdl/openglsdl-graphics.cpp | 487 +++++++++++++++++++++ backends/graphics/openglsdl/openglsdl-graphics.h | 115 +++++ 4 files changed, 610 insertions(+) create mode 100644 backends/graphics/openglsdl/openglsdl-graphics.cpp create mode 100644 backends/graphics/openglsdl/openglsdl-graphics.h (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 7ea880c92e..87d6d3c2e5 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -106,6 +106,10 @@ const OSystem::GraphicsMode glGraphicsModes[] = { } // End of anonymous namespace +const OSystem::GraphicsMode *OpenGLGraphicsManager::supportedGraphicsModes() { + return glGraphicsModes; +} + const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() const { return glGraphicsModes; } diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index e21bda4b8a..5aa521cb7a 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -47,6 +47,10 @@ public: virtual void setFeatureState(OSystem::Feature f, bool enable); virtual bool getFeatureState(OSystem::Feature f); + // HACK: This is required for the SDL backend to switch between OpenGL SDL + // and Surface SDL. + static const OSystem::GraphicsMode *supportedGraphicsModes(); + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; virtual int getDefaultGraphicsMode() const; virtual bool setGraphicsMode(int mode); diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp new file mode 100644 index 0000000000..ce6d7ec7f0 --- /dev/null +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -0,0 +1,487 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "backends/graphics/openglsdl/openglsdl-graphics.h" + +#include "common/textconsole.h" +#include "common/config-manager.h" + +OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource) + : SdlGraphicsManager(eventSource), _lastVideoModeLoad(0), _hwScreen(nullptr), _lastRequestedWidth(0), _lastRequestedHeight(0), + _graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0), + _desiredFullscreenWidth(0), _desiredFullscreenHeight(0) { + // Initialize SDL video subsystem + if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { + error("Could not initialize SDL: %s", SDL_GetError()); + } + + // Setup OpenGL attributes for SDL + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + // This is also called in initSDL(), but initializing graphics + // may reset it. + SDL_EnableUNICODE(1); + + // Disable OS cursor + SDL_ShowCursor(SDL_DISABLE); + + // Retrieve a list of working fullscreen modes + const SDL_Rect *const *availableModes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN); + if (availableModes != (void *)-1) { + for (;*availableModes; ++availableModes) { + const SDL_Rect *mode = *availableModes; + + _fullscreenVideoModes.push_back(VideoMode(mode->w, mode->h)); + } + + // Sort the modes in ascending order. + Common::sort(_fullscreenVideoModes.begin(), _fullscreenVideoModes.end()); + } + + // In case SDL is fine with every mode we will force the desktop mode. + // TODO? We could also try to add some default resolutions here. + if (_fullscreenVideoModes.empty() && desktopWidth && desktopHeight) { + _fullscreenVideoModes.push_back(VideoMode(desktopWidth, desktopHeight)); + } + + // Get information about display sizes from the previous runs. + if (ConfMan.hasKey("last_fullscreen_mode_width", Common::ConfigManager::kApplicationDomain) && ConfMan.hasKey("last_fullscreen_mode_height", Common::ConfigManager::kApplicationDomain)) { + _desiredFullscreenWidth = ConfMan.getInt("last_fullscreen_mode_width", Common::ConfigManager::kApplicationDomain); + _desiredFullscreenHeight = ConfMan.getInt("last_fullscreen_mode_height", Common::ConfigManager::kApplicationDomain); + } else { + // Use the desktop resolutions when no previous default has been setup. + _desiredFullscreenWidth = desktopWidth; + _desiredFullscreenHeight = desktopHeight; + } +} + +OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() { + // Unregister the event observer + if (g_system->getEventManager()->getEventDispatcher()) { + g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); + } +} + +void OpenGLSdlGraphicsManager::initEventObserver() { + // Register the graphics manager as a event observer + g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); +} + +bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + case OSystem::kFeatureIconifyWindow: + return true; + + default: + return OpenGLGraphicsManager::hasFeature(f); + } +} + +void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + assert(getTransactionMode() != kTransactionNone); + _wantsFullScreen = enable; + // When we switch to windowed mode we will ignore resize events. This + // avoids bad resizes to the (former) fullscreen resolution. + if (!enable) { + _ignoreResizeEvents = 10; + } + break; + + case OSystem::kFeatureIconifyWindow: + if (enable) { + SDL_WM_IconifyWindow(); + } + break; + + default: + OpenGLGraphicsManager::setFeatureState(f, enable); + } +} + +bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) { + switch (f) { + case OSystem::kFeatureFullscreenMode: + if (_hwScreen) { + return (_hwScreen->flags & SDL_FULLSCREEN) != 0; + } else { + return _wantsFullScreen; + } + + default: + return OpenGLGraphicsManager::getFeatureState(f); + } +} + +bool OpenGLSdlGraphicsManager::setGraphicsMode(int mode) { + // HACK: This is stupid but the SurfaceSDL backend defaults to 2x. This + // assures that the launcher (which requests 320x200) has a reasonable + // size. It also makes small games have a reasonable size (i.e. at least + // 640x400). We follow the same logic here until we have a better way to + // give hints to our backend for that. + _graphicsScale = 2; + + return OpenGLGraphicsManager::setGraphicsMode(mode); +} + +void OpenGLSdlGraphicsManager::resetGraphicsScale() { + OpenGLGraphicsManager::resetGraphicsScale(); + + // HACK: See OpenGLSdlGraphicsManager::setGraphicsMode. + _graphicsScale = 1; +} + +#ifdef USE_RGB_COLOR +Common::List OpenGLSdlGraphicsManager::getSupportedFormats() const { + Common::List formats; + + // RGBA8888 + formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); + // RGB565 + formats.push_back(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); + // RGBA5551 + formats.push_back(Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); + // RGBA4444 + formats.push_back(Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)); + +#ifndef USE_GLES + // ARGB8888, this should not be here, but Sword25 requires it. :-/ + formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)); + + // RGB555, this is used by SCUMM HE 16 bit games. + formats.push_back(Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); +#endif + + formats.push_back(Graphics::PixelFormat::createFormatCLUT8()); + + return formats; +} +#endif + +void OpenGLSdlGraphicsManager::updateScreen() { + if (_ignoreResizeEvents) { + --_ignoreResizeEvents; + } + + OpenGLGraphicsManager::updateScreen(); + + // Swap OpenGL buffers + SDL_GL_SwapBuffers(); +} + +void OpenGLSdlGraphicsManager::notifyVideoExpose() { +} + +void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) { + if (!_ignoreResizeEvents && _hwScreen && !(_hwScreen->flags & SDL_FULLSCREEN)) { + // We save that we handled a resize event here. We need to know this + // so we do not overwrite the users requested window size whenever we + // switch aspect ratio or similar. + _gotResize = true; + if (!setupMode(width, height)) { + warning("OpenGLSdlGraphicsManager::notifyResize: Resize failed ('%s')", SDL_GetError()); + g_system->quit(); + } + } +} + +void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { + adjustMousePosition(point.x, point.y); +} + +void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) { + setMousePosition(mouse.x, mouse.y); +} + +void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) { + SDL_WarpMouse(x, y); +} + +bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) { + // In some cases we might not want to load the requested video mode. This + // will assure that the window size is not altered. + if (_ignoreLoadVideoMode) { + _ignoreLoadVideoMode = false; + return true; + } + + // This function should never be called from notifyResize thus we know + // that the requested size came from somewhere else. + _gotResize = false; + + // Save the requested dimensions. + _lastRequestedWidth = requestedWidth; + _lastRequestedHeight = requestedHeight; + + // Apply the currently saved scale setting. + requestedWidth *= _graphicsScale; + requestedHeight *= _graphicsScale; + + // Set up the mode. + return setupMode(requestedWidth, requestedHeight); +} + +bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { + // In case we request a fullscreen mode we will use the mode the user + // has chosen last time or the biggest mode available. + if (_wantsFullScreen) { + if (_desiredFullscreenWidth && _desiredFullscreenHeight) { + // In case only a distinct set of modes is available we check + // whether the requested mode is actually available. + if (!_fullscreenVideoModes.empty()) { + VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(), + _fullscreenVideoModes.end(), + VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight)); + // It's not available fall back to default. + if (i == _fullscreenVideoModes.end()) { + _desiredFullscreenWidth = 0; + _desiredFullscreenHeight = 0; + } + } + } + + // In case no desired mode has been set we default to the biggest mode + // available or the requested mode in case we don't know any + // any fullscreen modes. + if (!_desiredFullscreenWidth || !_desiredFullscreenHeight) { + if (!_fullscreenVideoModes.empty()) { + VideoModeArray::const_iterator i = _fullscreenVideoModes.end(); + --i; + + _desiredFullscreenWidth = i->width; + _desiredFullscreenHeight = i->height; + } else { + _desiredFullscreenWidth = width; + _desiredFullscreenHeight = height; + } + } + + // Remember our choice. + ConfMan.setInt("last_fullscreen_mode_width", _desiredFullscreenWidth, Common::ConfigManager::kApplicationDomain); + ConfMan.setInt("last_fullscreen_mode_height", _desiredFullscreenHeight, Common::ConfigManager::kApplicationDomain); + + // Use our choice. + width = _desiredFullscreenWidth; + height = _desiredFullscreenHeight; + } + + // WORKAROUND: Working around infamous SDL bugs when switching + // resolutions too fast. This might cause the event system to supply + // incorrect mouse position events otherwise. + // Reference: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=665779 + const uint32 curTime = SDL_GetTicks(); + if (_hwScreen && (curTime < _lastVideoModeLoad || curTime - _lastVideoModeLoad < 100)) { + for (int i = 10; i > 0; --i) { + SDL_PumpEvents(); + SDL_Delay(10); + } + } + _lastVideoModeLoad = curTime; + + uint32 flags = SDL_OPENGL; + if (_wantsFullScreen) { + flags |= SDL_FULLSCREEN; + } else { + flags |= SDL_RESIZABLE; + } + + _hwScreen = SDL_SetVideoMode(width, height, 32, flags); + + if (!_hwScreen) { + // We treat fullscreen requests as a "hint" for now. This means in + // case it is not available we simply ignore it. + if (_wantsFullScreen) { + _hwScreen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL | SDL_RESIZABLE); + } + } + + if (_hwScreen) { + const Graphics::PixelFormat rgba8888 = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); + notifyContextChange(rgba8888, rgba8888); + setActualScreenSize(_hwScreen->w, _hwScreen->h); + } + + return _hwScreen != nullptr; +} + +bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { + switch (event.type) { + case Common::EVENT_KEYUP: + return isHotkey(event); + + case Common::EVENT_KEYDOWN: + if (event.kbd.hasFlags(Common::KBD_ALT)) { + if ( event.kbd.keycode == Common::KEYCODE_RETURN + || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER) { + // Alt-Return and Alt-Enter toggle full screen mode + beginGFXTransaction(); + setFeatureState(OSystem::kFeatureFullscreenMode, !getFeatureState(OSystem::kFeatureFullscreenMode)); + endGFXTransaction(); + return true; + } + } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) { + if ( event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS + || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS) { + // Ctrl+Alt+Plus/Minus Increase/decrease the size + const int direction = (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_KP_PLUS) ? +1 : -1; + + if (getFeatureState(OSystem::kFeatureFullscreenMode)) { + // In case we are in fullscreen we will choose the previous + // or next mode. + + // In case no modes are available we do nothing. + if (_fullscreenVideoModes.empty()) { + return true; + } + + // Look for the current mode. + VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(), + _fullscreenVideoModes.end(), + VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight)); + if (i == _fullscreenVideoModes.end()) { + return true; + } + + // Cycle through the modes in the specified direction. + if (direction > 0) { + ++i; + if (i == _fullscreenVideoModes.end()) { + i = _fullscreenVideoModes.begin(); + } + } else { + if (i == _fullscreenVideoModes.begin()) { + i = _fullscreenVideoModes.end(); + } + --i; + } + + _desiredFullscreenWidth = i->width; + _desiredFullscreenHeight = i->height; + + // Try to setup the mode. + if (!setupMode(_lastRequestedWidth, _lastRequestedHeight)) { + warning("OpenGLSdlGraphicsManager::notifyEvent: Fullscreen resize failed ('%s')", SDL_GetError()); + g_system->quit(); + } + } else { + // Calculate the next scaling setting. We approximate the + // current scale setting in case the user resized the + // window. Then we apply the direction change. + _graphicsScale = MAX(_hwScreen->w / _lastRequestedWidth, _hwScreen->h / _lastRequestedHeight); + _graphicsScale = MAX(_graphicsScale + direction, 1); + + // Since we overwrite a user resize here we reset its + // flag here. This makes enabling AR smoother because it + // will change the window size like in surface SDL. + _gotResize = false; + + // Try to setup the mode. + if (!setupMode(_lastRequestedWidth * _graphicsScale, _lastRequestedHeight * _graphicsScale)) { + warning("OpenGLSdlGraphicsManager::notifyEvent: Window resize failed ('%s')", SDL_GetError()); + g_system->quit(); + } + } + + return true; + } else if (event.kbd.keycode == Common::KEYCODE_a) { + // In case the user changed the window size manually we will + // not change the window size again here. + _ignoreLoadVideoMode = _gotResize; + + // Ctrl+Alt+a toggles the aspect ratio correction state. + beginGFXTransaction(); + setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection)); + endGFXTransaction(); + + // Make sure we do not ignore the next resize. This + // effectively checks whether loadVideoMode has been called. + assert(!_ignoreLoadVideoMode); + + return true; + } else if (event.kbd.keycode == Common::KEYCODE_f) { + // Ctrl+Alt+f toggles the graphics modes. + + // We are crazy we will allow the OpenGL base class to + // introduce new graphics modes like shaders for special + // filtering. If some other OpenGL subclass needs this, + // we can think of refactoring this. + int mode = getGraphicsMode(); + const OSystem::GraphicsMode *supportedModes = getSupportedGraphicsModes(); + const OSystem::GraphicsMode *modeDesc = nullptr; + + // Search the current mode. + for (; supportedModes->name; ++supportedModes) { + if (supportedModes->id == mode) { + modeDesc = supportedModes; + break; + } + } + assert(modeDesc); + + // Try to use the next mode in the list. + ++modeDesc; + if (!modeDesc->name) { + modeDesc = getSupportedGraphicsModes(); + } + + // Never ever try to resize the window when we simply want to + // switch the graphics mode. This assures that the window size + // does not change. + _ignoreLoadVideoMode = true; + + beginGFXTransaction(); + setGraphicsMode(modeDesc->id); + endGFXTransaction(); + + // Make sure we do not ignore the next resize. This + // effectively checks whether loadVideoMode has been called. + assert(!_ignoreLoadVideoMode); + + return true; + } + } + // Fall through + + default: + return false; + } +} + +bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) { + if (event.kbd.hasFlags(Common::KBD_ALT)) { + return event.kbd.keycode == Common::KEYCODE_RETURN + || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER; + } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) { + return event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS + || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS + || event.kbd.keycode == Common::KEYCODE_a + || event.kbd.keycode == Common::KEYCODE_f; + } + + return false; +} diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h new file mode 100644 index 0000000000..0644f27602 --- /dev/null +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -0,0 +1,115 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGLSDL_OPENGLSDL_GRAPHICS_H +#define BACKENDS_GRAPHICS_OPENGLSDL_OPENGLSDL_GRAPHICS_H + +#include "backends/graphics/opengl/opengl-graphics.h" +#include "backends/graphics/sdl/sdl-graphics.h" +#include "backends/platform/sdl/sdl-sys.h" + +#include "common/array.h" +#include "common/events.h" + +class OpenGLSdlGraphicsManager : public OpenGL::OpenGLGraphicsManager, public SdlGraphicsManager, public Common::EventObserver { +public: + OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource); + virtual ~OpenGLSdlGraphicsManager(); + + void initEventObserver(); + + // GraphicsManager API + virtual bool hasFeature(OSystem::Feature f); + virtual void setFeatureState(OSystem::Feature f, bool enable); + virtual bool getFeatureState(OSystem::Feature f); + + virtual bool setGraphicsMode(int mode); + virtual void resetGraphicsScale(); + +#ifdef USE_RGB_COLOR + virtual Common::List getSupportedFormats() const; +#endif + + virtual void updateScreen(); + + // EventObserver API + virtual bool notifyEvent(const Common::Event &event); + + // SdlGraphicsManager API + virtual void notifyVideoExpose(); + virtual void notifyResize(const uint width, const uint height); + virtual void transformMouseCoordinates(Common::Point &point); + virtual void notifyMousePos(Common::Point mouse); + +protected: + virtual void setInternalMousePosition(int x, int y); + + virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format); +private: + bool setupMode(uint width, uint height); + + uint32 _lastVideoModeLoad; + SDL_Surface *_hwScreen; + + uint _lastRequestedWidth; + uint _lastRequestedHeight; + uint _graphicsScale; + bool _ignoreLoadVideoMode; + bool _gotResize; + + bool _wantsFullScreen; + uint _ignoreResizeEvents; + + struct VideoMode { + VideoMode() : width(0), height(0) {} + VideoMode(uint w, uint h) : width(w), height(h) {} + + bool operator<(const VideoMode &right) const { + if (width < right.width) { + return true; + } else if (width == right.width && height < right.height) { + return true; + } else { + return false; + } + } + + bool operator==(const VideoMode &right) const { + return width == right.width && height == right.height; + } + + bool operator!=(const VideoMode &right) const { + return !(*this == right); + } + + uint width, height; + }; + typedef Common::Array VideoModeArray; + VideoModeArray _fullscreenVideoModes; + + uint _desiredFullscreenWidth; + uint _desiredFullscreenHeight; + + virtual bool isHotkey(const Common::Event &event); +}; + +#endif -- cgit v1.2.3 From cc9c991d7711ec08b7f06ca712cd7dfabe69f752 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 19 Aug 2013 00:44:55 +0200 Subject: OPENGL: Add OSD support. --- backends/graphics/opengl/opengl-graphics.cpp | 131 ++++++++++++++++++++++++++- backends/graphics/opengl/opengl-graphics.h | 48 ++++++++++ 2 files changed, 178 insertions(+), 1 deletion(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 87d6d3c2e5..3223075fbd 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -29,8 +29,16 @@ #include "common/textconsole.h" #include "common/translation.h" #include "common/algorithm.h" +#ifdef USE_OSD +#include "common/tokenizer.h" +#include "common/rect.h" +#endif #include "graphics/conversion.h" +#ifdef USE_OSD +#include "graphics/fontman.h" +#include "graphics/font.h" +#endif namespace OpenGL { @@ -42,7 +50,11 @@ OpenGLGraphicsManager::OpenGLGraphicsManager() _overlayVisible(false), _cursor(nullptr), _cursorX(0), _cursorY(0), _cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), _cursorKeyColor(0), - _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false) { + _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false) +#ifdef USE_OSD + , _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr) +#endif + { memset(_gamePalette, 0, sizeof(_gamePalette)); } @@ -50,6 +62,9 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { delete _gameScreen; delete _overlay; delete _cursor; +#ifdef USE_OSD + delete _osd; +#endif } bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { @@ -137,6 +152,12 @@ bool OpenGLGraphicsManager::setGraphicsMode(int mode) { if (_cursor) { _cursor->enableLinearFiltering(mode == GFX_LINEAR); } + +#ifdef USE_OSD + if (_osd) { + _osd->enableLinearFiltering(mode == GFX_LINEAR); + } +#endif return true; default: @@ -374,6 +395,34 @@ void OpenGLGraphicsManager::updateScreen() { glPopMatrix(); } + +#ifdef USE_OSD + // Fourth step: Draw the OSD. + if (_osdAlpha > 0) { + Common::StackLock lock(_osdMutex); + + // Update alpha value. + const int diff = g_system->getMillis(false) - _osdFadeStartTime; + if (diff > 0) { + if (diff >= kOSDFadeOutDuration) { + // Back to full transparency. + _osdAlpha = 0; + } else { + // Do a fade out. + _osdAlpha = kOSDInitialAlpha - diff * kOSDInitialAlpha / kOSDFadeOutDuration; + } + } + + // Set the OSD transparency. + GLCALL(glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f)); + + // Draw the OSD texture. + _osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight); + + // Reset color. + GLCALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); + } +#endif } Graphics::Surface *OpenGLGraphicsManager::lockScreen() { @@ -617,6 +666,59 @@ void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uin } void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { +#ifdef USE_OSD + // HACK: Actually no client code should use graphics functions from + // another thread. But the MT-32 emulator still does, thus we need to + // make sure this doesn't happen while a updateScreen call is done. + Common::StackLock lock(_osdMutex); + + // Slip up the lines. + Common::Array osdLines; + Common::StringTokenizer tokenizer(msg, "\n"); + while (!tokenizer.empty()) { + osdLines.push_back(tokenizer.nextToken()); + } + + // Do the actual drawing like the SDL backend. + const Graphics::Font *font = getFontOSD(); + Graphics::Surface *dst = _osd->getSurface(); + _osd->fill(0); + _osd->flagDirty(); + + // Determine a rect which would contain the message string (clipped to the + // screen dimensions). + const int vOffset = 6; + const int lineSpacing = 1; + const int lineHeight = font->getFontHeight() + 2 * lineSpacing; + int width = 0; + int height = lineHeight * osdLines.size() + 2 * vOffset; + for (uint i = 0; i < osdLines.size(); i++) { + width = MAX(width, font->getStringWidth(osdLines[i]) + 14); + } + + // Clip the rect + width = MIN(width, dst->w); + height = MIN(height, dst->h); + + int dstX = (dst->w - width) / 2; + int dstY = (dst->h - height) / 2; + + // Draw a dark gray rect. + const uint32 color = dst->format.RGBToColor(40, 40, 40); + dst->fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color); + + // Render the message, centered, and in white + const uint32 white = dst->format.RGBToColor(255, 255, 255); + for (uint i = 0; i < osdLines.size(); ++i) { + font->drawString(dst, osdLines[i], + dstX, dstY + i * lineHeight + vOffset + lineSpacing, width, + white, Graphics::kTextAlignCenter); + } + + // Init the OSD display parameters. + _osdAlpha = kOSDInitialAlpha; + _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; +#endif } void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) { @@ -672,6 +774,21 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { _overlay->allocate(overlayWidth, overlayHeight); _overlay->fill(0); +#ifdef USE_OSD + if (!_osd || _osd->getFormat() != _defaultFormatAlpha) { + delete _osd; + _osd = nullptr; + + GLenum glIntFormat, glFormat, glType; + const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); + assert(supported); + _osd = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); + _osd->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + } + _osd->allocate(_outputScreenWidth, _outputScreenHeight); + _osd->fill(0); +#endif + // Re-setup the scaling for the screen and cursor recalculateDisplayArea(); recalculateCursorScaling(); @@ -729,6 +846,12 @@ void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &def if (_cursor) { _cursor->recreateInternalTexture(); } + +#ifdef USE_OSD + if (_osd) { + _osd->recreateInternalTexture(); + } +#endif } void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { @@ -923,4 +1046,10 @@ void OpenGLGraphicsManager::recalculateCursorScaling() { } } +#ifdef USE_OSD +const Graphics::Font *OpenGLGraphicsManager::getFontOSD() { + return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont); +} +#endif + } // End of namespace OpenGL diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 5aa521cb7a..d4bd0137ed 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -27,9 +27,19 @@ #include "backends/graphics/graphics.h" #include "common/frac.h" +#include "common/mutex.h" + +namespace Graphics { +class Font; +} // End of namespace Graphics namespace OpenGL { +// HACK: We use glColor in the OSD code. This might not be working on GL ES but +// we still enable it because Tizen already shipped with it. Also, the +// SurfaceSDL backend enables it and disabling it can cause issues in sdl.cpp. +#define USE_OSD 1 + class Texture; enum { @@ -415,6 +425,44 @@ private: * The special cursor palette in case enabled. */ byte _cursorPalette[3 * 256]; + +#ifdef USE_OSD + // + // OSD + // +protected: + /** + * Returns the font used for on screen display + */ + virtual const Graphics::Font *getFontOSD(); + +private: + /** + * The OSD's contents. + */ + Texture *_osd; + + /** + * Current opacity level of the OSD. + */ + uint8 _osdAlpha; + + /** + * When fading the OSD has started. + */ + uint32 _osdFadeStartTime; + + /** + * Mutex to allow displayMessageOnOSD to be used from the audio thread. + */ + Common::Mutex _osdMutex; + + enum { + kOSDFadeOutDelay = 2 * 1000, + kOSDFadeOutDuration = 500, + kOSDInitialAlpha = 80 + }; +#endif }; } // End of namespace OpenGL -- cgit v1.2.3 From 50a86463c1caf689922a72cfa6cece06c2ed3455 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 19 Aug 2013 00:54:41 +0200 Subject: SDL: Use OSD in OpenGL SDL backend. --- backends/graphics/openglsdl/openglsdl-graphics.cpp | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index ce6d7ec7f0..a1a3e8590a 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -24,6 +24,9 @@ #include "common/textconsole.h" #include "common/config-manager.h" +#ifdef USE_OSD +#include "common/translation.h" +#endif OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource) : SdlGraphicsManager(eventSource), _lastVideoModeLoad(0), _hwScreen(nullptr), _lastRequestedWidth(0), _lastRequestedHeight(0), @@ -342,6 +345,14 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { beginGFXTransaction(); setFeatureState(OSystem::kFeatureFullscreenMode, !getFeatureState(OSystem::kFeatureFullscreenMode)); endGFXTransaction(); + +#ifdef USE_OSD + if (getFeatureState(OSystem::kFeatureFullscreenMode)) { + displayMessageOnOSD("Fullscreen mode"); + } else { + displayMessageOnOSD("Windowed mode"); + } +#endif return true; } } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) { @@ -407,6 +418,11 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { } } +#ifdef USE_OSD + const Common::String osdMsg = Common::String::format("Resolution: %dx%d", _hwScreen->w, _hwScreen->h); + displayMessageOnOSD(osdMsg.c_str()); +#endif + return true; } else if (event.kbd.keycode == Common::KEYCODE_a) { // In case the user changed the window size manually we will @@ -422,6 +438,12 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { // effectively checks whether loadVideoMode has been called. assert(!_ignoreLoadVideoMode); +#ifdef USE_OSD + Common::String osdMsg = "Aspect ratio correction: "; + osdMsg += getFeatureState(OSystem::kFeatureAspectRatioCorrection) ? "enabled" : "disabled"; + displayMessageOnOSD(osdMsg.c_str()); +#endif + return true; } else if (event.kbd.keycode == Common::KEYCODE_f) { // Ctrl+Alt+f toggles the graphics modes. @@ -462,6 +484,11 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { // effectively checks whether loadVideoMode has been called. assert(!_ignoreLoadVideoMode); +#ifdef USE_OSD + const Common::String osdMsg = Common::String::format("Graphics mode: %s", _(modeDesc->description)); + displayMessageOnOSD(osdMsg.c_str()); +#endif + return true; } } -- cgit v1.2.3 From decc013e53ebf2a7c83e599ed676bfec27ade14f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 5 Oct 2013 02:38:13 +0200 Subject: OPENGL: Implement dirty rect handling. --- backends/graphics/opengl/texture.cpp | 85 ++++++++++++++++++++++++++++++------ backends/graphics/opengl/texture.h | 8 +++- 2 files changed, 78 insertions(+), 15 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 3067aa7d1c..d89bd00ac4 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -71,6 +71,10 @@ void Texture::recreateInternalTexture() { // In case there is an actual texture setup we reinitialize it. if (_textureData.getPixels()) { + // Allocate storage for OpenGL texture. + GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, + _textureData.h, 0, _glFormat, _glType, NULL)); + // Mark dirts such that it will be completely refreshed the next time. flagDirty(); } @@ -101,6 +105,13 @@ void Texture::allocate(uint width, uint height) { if (texWidth != _textureData.w || texHeight != _textureData.h) { // Create a buffer for the texture data. _textureData.create(texWidth, texHeight, _format); + + // Set the texture. + GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); + + // Allocate storage for OpenGL texture. + GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, + _textureData.h, 0, _glFormat, _glType, NULL)); } // Create a sub-buffer for raw access. @@ -112,6 +123,16 @@ void Texture::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcP assert(x + w <= dstSurf->w); assert(y + h <= dstSurf->h); + // *sigh* Common::Rect::extend behaves unexpected whenever one of the two + // parameters is an empty rect. Thus, we check whether the current dirty + // area is valid. In case it is not we simply use the parameters as new + // dirty area. Otherwise, we simply call extend. + if (_dirtyArea.isEmpty()) { + _dirtyArea = Common::Rect(x, y, x + w, y + h); + } else { + _dirtyArea.extend(Common::Rect(x, y, x + w, y + h)); + } + const byte *src = (const byte *)srcPtr; byte *dst = (byte *)dstSurf->getBasePtr(x, y); const uint pitch = dstSurf->pitch; @@ -126,8 +147,6 @@ void Texture::copyRectToTexture(uint x, uint y, uint w, uint h, const void *srcP src += srcPitch; } } - - flagDirty(); } void Texture::fill(uint32 color) { @@ -178,26 +197,34 @@ void Texture::updateTexture() { return; } + Common::Rect dirtyArea = getDirtyArea(); + // In case we use linear filtering we might need to duplicate the last // pixel row/column to avoid glitches with filtering. if (_glFilter == GL_LINEAR) { - if (_textureData.w != _userPixelData.w) { - uint height = _userPixelData.h; + if (dirtyArea.right == _userPixelData.w && _userPixelData.w != _textureData.w) { + uint height = dirtyArea.height(); - const byte *src = (const byte *)_textureData.getBasePtr(_userPixelData.w - 1, 0); - byte *dst = (byte *)_textureData.getBasePtr(_userPixelData.w, 0); + const byte *src = (const byte *)_textureData.getBasePtr(_userPixelData.w - 1, dirtyArea.top); + byte *dst = (byte *)_textureData.getBasePtr(_userPixelData.w, dirtyArea.top); while (height-- > 0) { memcpy(dst, src, _textureData.format.bytesPerPixel); dst += _textureData.pitch; src += _textureData.pitch; } + + // Extend the dirty area. + ++dirtyArea.right; } - if (_textureData.h != _userPixelData.h) { - const byte *src = (const byte *)_textureData.getBasePtr(0, _userPixelData.h - 1); - byte *dst = (byte *)_textureData.getBasePtr(0, _userPixelData.h); - memcpy(dst, src, _userPixelData.w * _textureData.format.bytesPerPixel); + if (dirtyArea.bottom == _userPixelData.h && _userPixelData.h != _textureData.h) { + const byte *src = (const byte *)_textureData.getBasePtr(dirtyArea.left, _userPixelData.h - 1); + byte *dst = (byte *)_textureData.getBasePtr(dirtyArea.left, _userPixelData.h); + memcpy(dst, src, dirtyArea.width() * _textureData.format.bytesPerPixel); + + // Extend the dirty area. + ++dirtyArea.bottom; } } @@ -205,12 +232,38 @@ void Texture::updateTexture() { GLCALL(glBindTexture(GL_TEXTURE_2D, _glTexture)); // Update the actual texture. - GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _textureData.w, _textureData.h, 0, _glFormat, _glType, _textureData.getPixels())); + // Although we keep track of the dirty part of the texture buffer we + // cannot take advantage of the left/right boundries here because it is + // not possible to specify a pitch to glTexSubImage2D. To be precise, with + // plain OpenGL we could set GL_UNPACK_ROW_LENGTH to achieve this. However, + // OpenGL ES 1.0 does not support GL_UNPACK_ROW_LENGTH. Thus, we are left + // with the following options: + // + // 1) (As we do right now) Simply always update the whole texture lines of + // rect changed. This is simplest to implement. In case performance is + // really an issue we can think of switching to another method. + // + // 2) Copy the dirty rect to a temporary buffer and upload that by using + // glTexSubImage2D. This is what the Android backend does. It is more + // complicated though. + // + // 3) Use glTexSubImage2D per line changed. This is what the old OpenGL + // graphics manager did but it is much slower! Thus, we do not use it. + GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, dirtyArea.top, _textureData.w, dirtyArea.height(), + _glFormat, _glType, _textureData.getBasePtr(0, dirtyArea.top))); // We should have handled everything, thus not dirty anymore. clearDirty(); } +Common::Rect Texture::getDirtyArea() const { + if (_allDirty) { + return Common::Rect(_userPixelData.w, _userPixelData.h); + } else { + return _dirtyArea; + } +} + TextureCLUT8::TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) : Texture(glIntFormat, glFormat, glType, format), _clut8Data(), _palette(new byte[256 * format.bytesPerPixel]) { memset(_palette, 0, sizeof(byte) * format.bytesPerPixel); @@ -288,11 +341,17 @@ void TextureCLUT8::updateTexture() { // Do the palette look up Graphics::Surface *outSurf = Texture::getSurface(); + Common::Rect dirtyArea = getDirtyArea(); + if (outSurf->format.bytesPerPixel == 2) { - doPaletteLookUp((uint16 *)outSurf->getPixels(), (const byte *)_clut8Data.getPixels(), _clut8Data.w, _clut8Data.h, + doPaletteLookUp((uint16 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top), + (const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top), + dirtyArea.width(), dirtyArea.height(), outSurf->pitch, _clut8Data.pitch, (const uint16 *)_palette); } else if (outSurf->format.bytesPerPixel == 4) { - doPaletteLookUp((uint32 *)outSurf->getPixels(), (const byte *)_clut8Data.getPixels(), _clut8Data.w, _clut8Data.h, + doPaletteLookUp((uint32 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top), + (const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top), + dirtyArea.width(), dirtyArea.height(), outSurf->pitch, _clut8Data.pitch, (const uint32 *)_palette); } else { warning("TextureCLUT8::updateTexture: Unsupported pixel depth: %d", outSurf->format.bytesPerPixel); diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h index 1127aed350..273e7b7319 100644 --- a/backends/graphics/opengl/texture.h +++ b/backends/graphics/opengl/texture.h @@ -28,6 +28,8 @@ #include "graphics/pixelformat.h" #include "graphics/surface.h" +#include "common/rect.h" + namespace OpenGL { /** @@ -80,7 +82,7 @@ public: void draw(GLuint x, GLuint y, GLuint w, GLuint h); void flagDirty() { _allDirty = true; } - bool isDirty() const { return _allDirty; } + bool isDirty() const { return _allDirty || !_dirtyArea.isEmpty(); } uint getWidth() const { return _userPixelData.w; } uint getHeight() const { return _userPixelData.h; } @@ -111,6 +113,7 @@ public: protected: virtual void updateTexture(); + Common::Rect getDirtyArea() const; private: const GLenum _glIntFormat; const GLenum _glFormat; @@ -124,7 +127,8 @@ private: Graphics::Surface _userPixelData; bool _allDirty; - void clearDirty() { _allDirty = false; } + Common::Rect _dirtyArea; + void clearDirty() { _allDirty = false; _dirtyArea = Common::Rect(); } }; class TextureCLUT8 : public Texture { -- cgit v1.2.3 From 20e4a7f0ce86bc93511643e4943b29044c84263f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 19 Aug 2013 02:10:43 +0200 Subject: TIZEN: Adapt to new OpenGL code. Thanks to Chris Warren-Smith for testing this a bit. --- backends/graphics/opengl/opengl-graphics.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index d4bd0137ed..67ad5aa067 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -153,6 +153,11 @@ protected: */ void setMousePosition(int x, int y) { _cursorX = x; _cursorY = y; } + /** + * Query the mouse position in physical coordinates. + */ + void getMousePosition(int16 &x, int16 &y) const { x = _cursorX; y = _cursorY; } + /** * Set up the mouse position for the (event) system. * -- cgit v1.2.3 From bb1d49ba9cbdb5b50cbce0c6d714d2fd2e3c6da9 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 18 Oct 2013 00:17:46 +0200 Subject: OPENGL: Limit maximum Surface size to maximum texture size. This is mostly aimed at old graphics chips. For example, wjp's old laptop only supports 1024x1024 textures but has a 1280x800 screen. Switching to fullscreen would create a bigger overlay than supported. Now it will get limited to an smaller resolution and then scaled too. Alternatively we could think of tiling surfaces into textures. But then handling scaling would be more complicated since it might result in artifacts on texture tile borders. --- backends/graphics/opengl/opengl-graphics.cpp | 60 +++++++++++++++++++++------- backends/graphics/opengl/texture.cpp | 7 ++++ backends/graphics/opengl/texture.h | 12 ++++++ 3 files changed, 64 insertions(+), 15 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 3223075fbd..e3c56dccca 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -145,19 +145,10 @@ bool OpenGLGraphicsManager::setGraphicsMode(int mode) { _gameScreen->enableLinearFiltering(mode == GFX_LINEAR); } - if (_overlay) { - _overlay->enableLinearFiltering(mode == GFX_LINEAR); - } - if (_cursor) { _cursor->enableLinearFiltering(mode == GFX_LINEAR); } -#ifdef USE_OSD - if (_osd) { - _osd->enableLinearFiltering(mode == GFX_LINEAR); - } -#endif return true; default: @@ -221,7 +212,13 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { #else Graphics::PixelFormat::createFormatCLUT8() #endif - )) { + ) + // HACK: This is really nasty but we don't have any guarantees of + // a context existing before, which means we don't know the maximum + // supported texture size before this. Thus, we check whether the + // requested game resolution is supported over here. + || ( _currentState.gameWidth > (uint)Texture::getMaximumTextureSize() + || _currentState.gameHeight > (uint)Texture::getMaximumTextureSize())) { if (_transactionMode == kTransactionActive) { // Try to setup the old state in case its valid and is // actually different from the new one. @@ -754,12 +751,34 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { GLCALL(glMatrixMode(GL_MODELVIEW)); GLCALL(glLoadIdentity()); + uint overlayWidth = width; + uint overlayHeight = height; + + // WORKAROUND: We can only support surfaces up to the maximum supported + // texture size. Thus, in case we encounter a physical size bigger than + // this maximum texture size we will simply use an overlay as big as + // possible and then scale it to the physical display size. This sounds + // bad but actually all recent chips should support full HD resolution + // anyway. Thus, it should not be a real issue for modern hardware. + if ( overlayWidth > (uint)Texture::getMaximumTextureSize() + || overlayHeight > (uint)Texture::getMaximumTextureSize()) { + const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; + + if (outputAspect > (frac_t)FRAC_ONE) { + overlayWidth = Texture::getMaximumTextureSize(); + overlayHeight = intToFrac(overlayWidth) / outputAspect; + } else { + overlayHeight = Texture::getMaximumTextureSize(); + overlayWidth = fracToInt(overlayHeight * outputAspect); + } + } + // HACK: We limit the minimal overlay size to 256x200, which is the // minimum of the dimensions of the two resolutions 256x240 (NES) and // 320x200 (many DOS games use this). This hopefully assure that our // GUI has working layouts. - const uint overlayWidth = MAX(width, 256); - const uint overlayHeight = MAX(height, 200); + overlayWidth = MAX(overlayWidth, 256); + overlayHeight = MAX(overlayHeight, 200); if (!_overlay || _overlay->getFormat() != _defaultFormatAlpha) { delete _overlay; @@ -769,7 +788,10 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); assert(supported); _overlay = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); - _overlay->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + // We always filter the overlay with GL_LINEAR. This assures it's + // readable in case it needs to be scaled and does not affect it + // otherwise. + _overlay->enableLinearFiltering(true); } _overlay->allocate(overlayWidth, overlayHeight); _overlay->fill(0); @@ -783,9 +805,12 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); assert(supported); _osd = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); - _osd->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + // We always filter the osd with GL_LINEAR. This assures it's + // readable in case it needs to be scaled and does not affect it + // otherwise. + _osd->enableLinearFiltering(true); } - _osd->allocate(_outputScreenWidth, _outputScreenHeight); + _osd->allocate(_overlay->getWidth(), _overlay->getHeight()); _osd->fill(0); #endif @@ -824,6 +849,9 @@ void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &def GLCALL(glEnable(GL_TEXTURE_2D)); + // Query information needed by textures. + Texture::queryTextureInformation(); + // Refresh the output screen dimensions if some are set up. if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { setActualScreenSize(_outputScreenWidth, _outputScreenHeight); @@ -860,6 +888,8 @@ void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { // here when the overlay is visible. This is because for very small // resolutions we have a minimal overlay size and have to adjust // for that. + // This can also happen when the overlay is smaller than the actual + // display size because of texture size limitations. if (_overlay) { x = (x * _overlay->getWidth()) / _outputScreenWidth; y = (y * _overlay->getHeight()) / _outputScreenHeight; diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index d89bd00ac4..917bf70534 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -41,6 +41,13 @@ static GLuint nextHigher2(GLuint v) { return ++v; } +GLint Texture::_maxTextureSize = 0; + +void Texture::queryTextureInformation() { + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize); + debug(5, "OpenGL maximum texture size: %d", _maxTextureSize); +} + Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) : _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType), _format(format), _glFilter(GL_NEAREST), _glTexture(0), _textureData(), _userPixelData(), _allDirty(false) { diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h index 273e7b7319..e28d980de4 100644 --- a/backends/graphics/opengl/texture.h +++ b/backends/graphics/opengl/texture.h @@ -110,6 +110,16 @@ public: virtual void *getPalette() { return 0; } virtual const void *getPalette() const { return 0; } + /** + * Query texture related OpenGL information from the context. This only + * queries the maximum texture size for now. + */ + static void queryTextureInformation(); + + /** + * @return Return the maximum texture dimensions supported. + */ + static GLint getMaximumTextureSize() { return _maxTextureSize; } protected: virtual void updateTexture(); @@ -129,6 +139,8 @@ private: bool _allDirty; Common::Rect _dirtyArea; void clearDirty() { _allDirty = false; _dirtyArea = Common::Rect(); } + + static GLint _maxTextureSize; }; class TextureCLUT8 : public Texture { -- cgit v1.2.3 From 05c347fc8ad8edc990c9d6e7c15a12d93bd8a3a3 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 19 Oct 2013 20:39:01 +0200 Subject: OPENGL/SDL: Add screenshot support. --- backends/graphics/opengl/opengl-graphics.cpp | 63 ++++++++++++++++++++++ backends/graphics/opengl/opengl-graphics.h | 8 +++ backends/graphics/openglsdl/openglsdl-graphics.cpp | 23 +++++++- 3 files changed, 93 insertions(+), 1 deletion(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index e3c56dccca..00e8dc358e 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -29,6 +29,7 @@ #include "common/textconsole.h" #include "common/translation.h" #include "common/algorithm.h" +#include "common/file.h" #ifdef USE_OSD #include "common/tokenizer.h" #include "common/rect.h" @@ -849,6 +850,11 @@ void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &def GLCALL(glEnable(GL_TEXTURE_2D)); + // We use a "pack" alignment (when reading from textures) to 4 here, + // since the only place where we really use it is the BMP screenshot + // code and that requires the same alignment too. + GLCALL(glPixelStorei(GL_PACK_ALIGNMENT, 4)); + // Query information needed by textures. Texture::queryTextureInformation(); @@ -1082,4 +1088,61 @@ const Graphics::Font *OpenGLGraphicsManager::getFontOSD() { } #endif +void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const { + const uint width = _outputScreenWidth; + const uint height = _outputScreenHeight; + + // A line of a BMP image must have a size divisible by 4. + // We calculate the padding bytes needed here. + // Since we use a 3 byte per pixel mode, we can use width % 4 here, since + // it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the + // usual way of computing the padding bytes required). + const uint linePaddingSize = width % 4; + const uint lineSize = width * 3 + linePaddingSize; + + // Allocate memory for screenshot + uint8 *pixels = new uint8[lineSize * height]; + + // Get pixel data from OpenGL buffer + GLCALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels)); + + // BMP stores as BGR. Since we can't assume that GL_BGR is supported we + // will swap the components from the RGB we read to BGR on our own. + for (uint y = height; y-- > 0;) { + uint8 *line = pixels + y * lineSize; + + for (uint x = width; x > 0; --x, line += 3) { + SWAP(line[0], line[2]); + } + } + + // Open file + Common::DumpFile out; + out.open(filename); + + // Write BMP header + out.writeByte('B'); + out.writeByte('M'); + out.writeUint32LE(height * lineSize + 54); + out.writeUint32LE(0); + out.writeUint32LE(54); + out.writeUint32LE(40); + out.writeUint32LE(width); + out.writeUint32LE(height); + out.writeUint16LE(1); + out.writeUint16LE(24); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + out.writeUint32LE(0); + + // Write pixel data to BMP + out.write(pixels, lineSize * height); + + // Free allocated memory + delete[] pixels; +} + } // End of namespace OpenGL diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 67ad5aa067..ebfe38fb60 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -247,6 +247,14 @@ protected: */ virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0; + /** + * Save a screenshot of the full display as BMP to the given file. This + * uses Common::DumpFile for writing the screenshot. + * + * @param filename The output filename. + */ + void saveScreenshot(const Common::String &filename) const; + private: // // OpenGL utilities diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index a1a3e8590a..925237b75e 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -355,6 +355,26 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { #endif return true; } + + if (event.kbd.keycode == Common::KEYCODE_s) { + // Alt-s creates a screenshot + Common::String filename; + + for (int n = 0;; n++) { + SDL_RWops *file; + + filename = Common::String::format("scummvm%05d.bmp", n); + file = SDL_RWFromFile(filename.c_str(), "r"); + if (!file) + break; + SDL_RWclose(file); + } + + saveScreenshot(filename.c_str()); + debug("Saved screenshot '%s'", filename.c_str()); + + return true; + } } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) { if ( event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS) { @@ -502,7 +522,8 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) { if (event.kbd.hasFlags(Common::KBD_ALT)) { return event.kbd.keycode == Common::KEYCODE_RETURN - || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER; + || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER + || event.kbd.keycode == Common::KEYCODE_s; } else if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) { return event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS -- cgit v1.2.3 From 6e46e9dfaf141fda10af798d9770b9f2b0555575 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 20 Oct 2013 22:27:50 +0200 Subject: SDL: Clean up graphics manager switching slighty. Sadly this also requires us to extend GraphicsManager for this SDL specific feature. However, since that's only used in the SDL backend and Tizen it should be fine for now... --- backends/graphics/graphics.h | 21 +++++++++++++++++++++ backends/graphics/openglsdl/openglsdl-graphics.cpp | 17 +++++++++++++---- backends/graphics/openglsdl/openglsdl-graphics.h | 5 +++-- backends/graphics/sdl/sdl-graphics.cpp | 9 +++++++-- backends/graphics/sdl/sdl-graphics.h | 3 +++ .../graphics/surfacesdl/surfacesdl-graphics.cpp | 19 ++++++++++++++----- backends/graphics/surfacesdl/surfacesdl-graphics.h | 3 ++- 7 files changed, 63 insertions(+), 14 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 24397228e6..74258b8910 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -37,6 +37,27 @@ class GraphicsManager : public PaletteManager { public: virtual ~GraphicsManager() {} + /** + * Makes this graphics manager active. That means it should be ready to + * process inputs now. However, even without being active it should be + * able to query the supported modes and other bits. + * + * HACK: Actually this is specific to SdlGraphicsManager subclasses. + * But sadly we cannot cast from GraphicsManager to SdlGraphicsManager + * because there is no relation between these two. + */ + virtual void activateManager() {} + + /** + * Makes this graphics manager inactive. This should allow another + * graphics manager to become active again. + * + * HACK: Actually this is specific to SdlGraphicsManager subclasses. + * But sadly we cannot cast from GraphicsManager to SdlGraphicsManager + * because there is no relation between these two. + */ + virtual void deactivateManager() {} + virtual bool hasFeature(OSystem::Feature f) = 0; virtual void setFeatureState(OSystem::Feature f, bool enable) = 0; virtual bool getFeatureState(OSystem::Feature f) = 0; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 925237b75e..088e97b1f7 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -82,15 +82,24 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt } OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() { +} + +void OpenGLSdlGraphicsManager::activateManager() { + OpenGLGraphicsManager::activateManager(); + initEventSource(); + + // Register the graphics manager as a event observer + g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); +} + +void OpenGLSdlGraphicsManager::deactivateManager() { // Unregister the event observer if (g_system->getEventManager()->getEventDispatcher()) { g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); } -} -void OpenGLSdlGraphicsManager::initEventObserver() { - // Register the graphics manager as a event observer - g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); + deinitEventSource(); + OpenGLGraphicsManager::deactivateManager(); } bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) { diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index 0644f27602..9934ca79e2 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -35,9 +35,10 @@ public: OpenGLSdlGraphicsManager(uint desktopWidth, uint desktopHeight, SdlEventSource *eventSource); virtual ~OpenGLSdlGraphicsManager(); - void initEventObserver(); - // GraphicsManager API + virtual void activateManager(); + virtual void deactivateManager(); + virtual bool hasFeature(OSystem::Feature f); virtual void setFeatureState(OSystem::Feature f, bool enable); virtual bool getFeatureState(OSystem::Feature f); diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index 2eca4b8aab..417f4faf54 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -26,10 +26,15 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source) : _eventSource(source) { - _eventSource->setGraphicsManager(this); } SdlGraphicsManager::~SdlGraphicsManager() { - _eventSource->setGraphicsManager(0); } +void SdlGraphicsManager::initEventSource() { + _eventSource->setGraphicsManager(this); +} + +void SdlGraphicsManager::deinitEventSource() { + _eventSource->setGraphicsManager(0); +} diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index ea9149fccb..4d4338af16 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -80,6 +80,9 @@ public: virtual void notifyMousePos(Common::Point mouse) = 0; protected: + void initEventSource(); + void deinitEventSource(); + SdlEventSource *_eventSource; }; diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 871c6c49b2..ba8807aaf4 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -193,10 +193,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou } SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() { - // Unregister the event observer - if (g_system->getEventManager()->getEventDispatcher() != NULL) - g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); - unloadGFXMode(); if (_mouseSurface) SDL_FreeSurface(_mouseSurface); @@ -211,11 +207,24 @@ SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() { free(_mouseData); } -void SurfaceSdlGraphicsManager::initEventObserver() { +void SurfaceSdlGraphicsManager::activateManager() { + GraphicsManager::activateManager(); + initEventSource(); + // Register the graphics manager as a event observer g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); } +void SurfaceSdlGraphicsManager::deactivateManager() { + // Unregister the event observer + if (g_system->getEventManager()->getEventDispatcher()) { + g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); + } + + deinitEventSource(); + GraphicsManager::deactivateManager(); +} + bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) { return (f == OSystem::kFeatureFullscreenMode) || diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 97de0f9c97..0bee70bf0c 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -80,7 +80,8 @@ public: SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource); virtual ~SurfaceSdlGraphicsManager(); - virtual void initEventObserver(); + virtual void activateManager(); + virtual void deactivateManager(); virtual bool hasFeature(OSystem::Feature f); virtual void setFeatureState(OSystem::Feature f, bool enable); -- cgit v1.2.3 From 1a56b521b598efcb1587dd8934b6564cf5799b7b Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 20 Oct 2013 23:00:28 +0200 Subject: SDL: Always initialize video subsystem in initSDL. --- backends/graphics/openglsdl/openglsdl-graphics.cpp | 12 ------------ backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 10 ---------- 2 files changed, 22 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 088e97b1f7..e39cd35870 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -32,11 +32,6 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt : SdlGraphicsManager(eventSource), _lastVideoModeLoad(0), _hwScreen(nullptr), _lastRequestedWidth(0), _lastRequestedHeight(0), _graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0), _desiredFullscreenWidth(0), _desiredFullscreenHeight(0) { - // Initialize SDL video subsystem - if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { - error("Could not initialize SDL: %s", SDL_GetError()); - } - // Setup OpenGL attributes for SDL SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); @@ -44,13 +39,6 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - // This is also called in initSDL(), but initializing graphics - // may reset it. - SDL_EnableUNICODE(1); - - // Disable OS cursor - SDL_ShowCursor(SDL_DISABLE); - // Retrieve a list of working fullscreen modes const SDL_Rect *const *availableModes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN); if (availableModes != (void *)-1) { diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index ba8807aaf4..8ad0bcbdd7 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -142,14 +142,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou #endif _transactionMode(kTransactionNone) { - if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { - error("Could not initialize SDL: %s", SDL_GetError()); - } - - // This is also called in initSDL(), but initializing graphics - // may reset it. - SDL_EnableUNICODE(1); - // allocate palette storage _currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256); _cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256); @@ -165,8 +157,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou _enableFocusRectDebugCode = ConfMan.getBool("use_sdl_debug_focusrect"); #endif - SDL_ShowCursor(SDL_DISABLE); - memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); memset(&_videoMode, 0, sizeof(_videoMode)); memset(&_transactionDetails, 0, sizeof(_transactionDetails)); -- cgit v1.2.3 From d34c9d5bcbbad9fdde59143d15d7e18bc82231c1 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 21 Oct 2013 01:03:29 +0200 Subject: SDL: Do not require a static graphics mode list in OpenGL and SurfaceSDL. --- backends/graphics/opengl/opengl-graphics.cpp | 4 ---- backends/graphics/opengl/opengl-graphics.h | 4 ---- backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 4 ---- backends/graphics/surfacesdl/surfacesdl-graphics.h | 1 - 4 files changed, 13 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 00e8dc358e..9ad0e62f37 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -122,10 +122,6 @@ const OSystem::GraphicsMode glGraphicsModes[] = { } // End of anonymous namespace -const OSystem::GraphicsMode *OpenGLGraphicsManager::supportedGraphicsModes() { - return glGraphicsModes; -} - const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() const { return glGraphicsModes; } diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index ebfe38fb60..d2d0358407 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -57,10 +57,6 @@ public: virtual void setFeatureState(OSystem::Feature f, bool enable); virtual bool getFeatureState(OSystem::Feature f); - // HACK: This is required for the SDL backend to switch between OpenGL SDL - // and Surface SDL. - static const OSystem::GraphicsMode *supportedGraphicsModes(); - virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; virtual int getDefaultGraphicsMode() const; virtual bool setGraphicsMode(int mode); diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 8ad0bcbdd7..c946b8e747 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -262,10 +262,6 @@ bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) { } } -const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::supportedGraphicsModes() { - return s_supportedGraphicsModes; -} - const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::getSupportedGraphicsModes() const { return s_supportedGraphicsModes; } diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 0bee70bf0c..00c05ff2bf 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -87,7 +87,6 @@ public: virtual void setFeatureState(OSystem::Feature f, bool enable); virtual bool getFeatureState(OSystem::Feature f); - static const OSystem::GraphicsMode *supportedGraphicsModes(); virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; virtual int getDefaultGraphicsMode() const; virtual bool setGraphicsMode(int mode); -- cgit v1.2.3 From 281672e1718d5f960061b714f79924125922e1e5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Oct 2013 00:03:09 +0200 Subject: SDL: Let SdlGraphicsManager inherit from GraphicsManager. --- backends/graphics/opengl/opengl-graphics.h | 2 +- backends/graphics/sdl/sdl-graphics.h | 7 +++---- backends/graphics/surfacesdl/surfacesdl-graphics.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index d2d0358407..93c0c5bc83 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -47,7 +47,7 @@ enum { GFX_NEAREST = 1 }; -class OpenGLGraphicsManager : public GraphicsManager { +class OpenGLGraphicsManager : virtual public GraphicsManager { public: OpenGLGraphicsManager(); virtual ~OpenGLGraphicsManager(); diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 4d4338af16..ebf8078f23 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -23,6 +23,8 @@ #ifndef BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H #define BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H +#include "backends/graphics/graphics.h" + #include "common/rect.h" class SdlEventSource; @@ -31,11 +33,8 @@ class SdlEventSource; * Base class for a SDL based graphics manager. * * It features a few extra a few extra features required by SdlEventSource. - * FIXME/HACK: - * Note it does not inherit from GraphicsManager to avoid a diamond inheritance - * in the current OpenGLSdlGraphicsManager. */ -class SdlGraphicsManager { +class SdlGraphicsManager : virtual public GraphicsManager { public: SdlGraphicsManager(SdlEventSource *source); virtual ~SdlGraphicsManager(); diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 00c05ff2bf..22b7780675 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -75,7 +75,7 @@ public: /** * SDL graphics manager */ -class SurfaceSdlGraphicsManager : public GraphicsManager, public SdlGraphicsManager, public Common::EventObserver { +class SurfaceSdlGraphicsManager : public SdlGraphicsManager, public Common::EventObserver { public: SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource); virtual ~SurfaceSdlGraphicsManager(); -- cgit v1.2.3 From ea6d38d5f3b123b765e5bf8e2dc4f957e4b43eb6 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Oct 2013 00:06:32 +0200 Subject: SDL: Make activateManager/deactivateManager SdlGraphicsManager specific. We can do this now that we can use virtual inheritance and dynamic_cast because we enabled RTTI. --- backends/graphics/graphics.h | 21 --------------------- backends/graphics/openglsdl/openglsdl-graphics.cpp | 4 ++-- backends/graphics/sdl/sdl-graphics.h | 13 +++++++++++++ .../graphics/surfacesdl/surfacesdl-graphics.cpp | 4 ++-- 4 files changed, 17 insertions(+), 25 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 74258b8910..24397228e6 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -37,27 +37,6 @@ class GraphicsManager : public PaletteManager { public: virtual ~GraphicsManager() {} - /** - * Makes this graphics manager active. That means it should be ready to - * process inputs now. However, even without being active it should be - * able to query the supported modes and other bits. - * - * HACK: Actually this is specific to SdlGraphicsManager subclasses. - * But sadly we cannot cast from GraphicsManager to SdlGraphicsManager - * because there is no relation between these two. - */ - virtual void activateManager() {} - - /** - * Makes this graphics manager inactive. This should allow another - * graphics manager to become active again. - * - * HACK: Actually this is specific to SdlGraphicsManager subclasses. - * But sadly we cannot cast from GraphicsManager to SdlGraphicsManager - * because there is no relation between these two. - */ - virtual void deactivateManager() {} - virtual bool hasFeature(OSystem::Feature f) = 0; virtual void setFeatureState(OSystem::Feature f, bool enable) = 0; virtual bool getFeatureState(OSystem::Feature f) = 0; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index e39cd35870..f76d7b2ec0 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -73,7 +73,7 @@ OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() { } void OpenGLSdlGraphicsManager::activateManager() { - OpenGLGraphicsManager::activateManager(); + SdlGraphicsManager::activateManager(); initEventSource(); // Register the graphics manager as a event observer @@ -87,7 +87,7 @@ void OpenGLSdlGraphicsManager::deactivateManager() { } deinitEventSource(); - OpenGLGraphicsManager::deactivateManager(); + SdlGraphicsManager::deactivateManager(); } bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) { diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index ebf8078f23..fea743b3ca 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -39,6 +39,19 @@ public: SdlGraphicsManager(SdlEventSource *source); virtual ~SdlGraphicsManager(); + /** + * Makes this graphics manager active. That means it should be ready to + * process inputs now. However, even without being active it should be + * able to query the supported modes and other bits. + */ + virtual void activateManager() {} + + /** + * Makes this graphics manager inactive. This should allow another + * graphics manager to become active again. + */ + virtual void deactivateManager() {} + /** * Notify the graphics manager that the graphics needs to be redrawn, since * the application window was modified. diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index c946b8e747..15193e2da4 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -198,7 +198,7 @@ SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() { } void SurfaceSdlGraphicsManager::activateManager() { - GraphicsManager::activateManager(); + SdlGraphicsManager::activateManager(); initEventSource(); // Register the graphics manager as a event observer @@ -212,7 +212,7 @@ void SurfaceSdlGraphicsManager::deactivateManager() { } deinitEventSource(); - GraphicsManager::deactivateManager(); + SdlGraphicsManager::deactivateManager(); } bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) { -- cgit v1.2.3 From cfa6b1b4ae690a6712ef9b2fa6a5f21ff3c2173b Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Oct 2013 00:09:17 +0200 Subject: SDL: Further small cleanup related to manager switching. --- backends/graphics/openglsdl/openglsdl-graphics.cpp | 2 -- backends/graphics/sdl/sdl-graphics.cpp | 4 ++-- backends/graphics/sdl/sdl-graphics.h | 7 ++----- backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 2 -- 4 files changed, 4 insertions(+), 11 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index f76d7b2ec0..3f9fc1fbd5 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -74,7 +74,6 @@ OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() { void OpenGLSdlGraphicsManager::activateManager() { SdlGraphicsManager::activateManager(); - initEventSource(); // Register the graphics manager as a event observer g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); @@ -86,7 +85,6 @@ void OpenGLSdlGraphicsManager::deactivateManager() { g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); } - deinitEventSource(); SdlGraphicsManager::deactivateManager(); } diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index 417f4faf54..40b97b267b 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -31,10 +31,10 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source) SdlGraphicsManager::~SdlGraphicsManager() { } -void SdlGraphicsManager::initEventSource() { +void SdlGraphicsManager::activateManager() { _eventSource->setGraphicsManager(this); } -void SdlGraphicsManager::deinitEventSource() { +void SdlGraphicsManager::deactivateManager() { _eventSource->setGraphicsManager(0); } diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index fea743b3ca..3791961cfa 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -44,13 +44,13 @@ public: * process inputs now. However, even without being active it should be * able to query the supported modes and other bits. */ - virtual void activateManager() {} + virtual void activateManager(); /** * Makes this graphics manager inactive. This should allow another * graphics manager to become active again. */ - virtual void deactivateManager() {} + virtual void deactivateManager(); /** * Notify the graphics manager that the graphics needs to be redrawn, since @@ -92,9 +92,6 @@ public: virtual void notifyMousePos(Common::Point mouse) = 0; protected: - void initEventSource(); - void deinitEventSource(); - SdlEventSource *_eventSource; }; diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 15193e2da4..d15fd6d8ef 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -199,7 +199,6 @@ SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() { void SurfaceSdlGraphicsManager::activateManager() { SdlGraphicsManager::activateManager(); - initEventSource(); // Register the graphics manager as a event observer g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); @@ -211,7 +210,6 @@ void SurfaceSdlGraphicsManager::deactivateManager() { g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); } - deinitEventSource(); SdlGraphicsManager::deactivateManager(); } -- cgit v1.2.3 From 2094bd31ec92db57c3da48bfad27252ad5a55ed2 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 17 Nov 2013 20:28:16 +0100 Subject: OPENGL: Fix >1Bpp mouse cursors which do not require format conversion. --- backends/graphics/opengl/opengl-graphics.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 9ad0e62f37..a97f680f15 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -608,13 +608,10 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int Graphics::Surface *dst = _cursor->getSurface(); const uint srcPitch = w * inputFormat.bytesPerPixel; - // In case the actual cursor format differs from the requested format - // we will need to convert the format. This might be the case because - // the cursor format does not have any alpha bits. - if (dst->format != inputFormat) { - Graphics::crossBlit((byte *)dst->getPixels(), (const byte *)buf, dst->pitch, srcPitch, - w, h, dst->format, inputFormat); - } + // Copy the cursor data to the actual texture surface. This will make + // sure that the data is also converted to the expected format. + Graphics::crossBlit((byte *)dst->getPixels(), (const byte *)buf, dst->pitch, srcPitch, + w, h, dst->format, inputFormat); // We apply the color key by setting the alpha bits of the pixels to // fully transparent. -- cgit v1.2.3 From fb05395dedfb3098c6b421352da2be3b6fa58db9 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 20 Nov 2013 21:46:29 +0100 Subject: OPENGL: Fix texture re-allocation check This fixes a crash when opening the menu in the SCI Laura Bow 2 intro. --- backends/graphics/opengl/texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 917bf70534..8f17ed7eeb 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -287,7 +287,7 @@ void TextureCLUT8::allocate(uint width, uint height) { // We only need to reinitialize our CLUT8 surface when the output size // changed. - if (width == _clut8Data.w && width == _clut8Data.h) { + if (width == _clut8Data.w && height == _clut8Data.h) { return; } -- cgit v1.2.3 From 97953ff40d1281da7bf3d7fe466db6d317c466d5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 7 Jan 2014 01:46:28 +0100 Subject: SDL: Fix return value of getDefaultGraphicsMode when scalers are disabled. --- backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index c946b8e747..9b71a1e3a4 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -267,7 +267,11 @@ const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::getSupportedGraphicsMode } int SurfaceSdlGraphicsManager::getDefaultGraphicsMode() const { +#ifdef USE_SCALERS return GFX_DOUBLESIZE; +#else + return GFX_NORMAL; +#endif } void SurfaceSdlGraphicsManager::resetGraphicsScale() { -- cgit v1.2.3 From 0c7f795c5bfac931436d1089aa97a15906b3f1a7 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 7 Jan 2014 01:47:43 +0100 Subject: SDL: Silence unused variable warning when scalers are disabled. --- backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 9b71a1e3a4..0a4dcf3ea3 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -1080,7 +1080,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { for (r = _dirtyRectList; r != lastRect; ++r) { register int dst_y = r->y + _currentShakePos; register int dst_h = 0; +#ifdef USE_SCALERS register int orig_dst_y = 0; +#endif register int rx1 = r->x * scale1; if (dst_y < height) { @@ -1088,7 +1090,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { if (dst_h > height - dst_y) dst_h = height - dst_y; +#ifdef USE_SCALERS orig_dst_y = dst_y; +#endif dst_y = dst_y * scale1; if (_videoMode.aspectRatioCorrection && !_overlayVisible) -- cgit v1.2.3 From 6677a973c2b9b742897441d3b8571b81b41fd297 Mon Sep 17 00:00:00 2001 From: Einar Johan Trøan Sømåen Date: Sat, 11 Jan 2014 16:36:04 +0100 Subject: SDL: Avoid having SDL_SRCALPHA set even if we have alpha in the pixelformat. --- backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 0a4dcf3ea3..89802ac8ab 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -746,6 +746,8 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { if (_screen == NULL) error("allocating _screen failed"); + // Avoid having SDL_SRCALPHA set even if we supplied an alpha-channel in the format. + SDL_SetAlpha(_screen, 0, 255); #else _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0); if (_screen == NULL) -- cgit v1.2.3 From 0f36a56b813c4270033804de8dd4f3412bedca55 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 21 Jan 2014 23:52:20 +0100 Subject: OPENGL: Properly query for OpenGL errors. There might be various error flags and we need to clear all of them to get precise error results. Thus, we need to call glGetError in a loop to achieve that. --- backends/graphics/opengl/debug.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/debug.cpp b/backends/graphics/opengl/debug.cpp index 69006bb975..d5d73fb5ec 100644 --- a/backends/graphics/opengl/debug.cpp +++ b/backends/graphics/opengl/debug.cpp @@ -52,9 +52,9 @@ Common::String getGLErrStr(GLenum error) { } // End of anonymous namespace void checkGLError(const char *expr, const char *file, int line) { - GLenum error = glGetError(); + GLenum error; - if (error != GL_NO_ERROR) { + while ((error = glGetError()) != GL_NO_ERROR) { // We cannot use error here because we do not know whether we have a // working screen or not. warning("GL ERROR: %s on %s (%s:%d)", getGLErrStr(error).c_str(), expr, file, line); -- cgit v1.2.3 From 602d3034a97517ecdaabde14a8b4928ddb3b9303 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 11 Feb 2014 11:07:37 +0100 Subject: OPENGL: Release old texture name before creating a new one. This prevents any texture name leaks (and thus memory leaks) on recreateInternalTexture calls. --- backends/graphics/opengl/texture.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 8f17ed7eeb..dff483dc0d 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -65,6 +65,9 @@ void Texture::releaseInternalTexture() { } void Texture::recreateInternalTexture() { + // Release old texture name in case it exists. + releaseInternalTexture(); + // Get a new texture name. GLCALL(glGenTextures(1, &_glTexture)); -- cgit v1.2.3 From 8be41e4f2ce353a97a2d41bee78cc99ca12b619a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 11 Feb 2014 11:07:37 +0100 Subject: OPENGL: Add notification function about context destruction. --- backends/graphics/opengl/opengl-graphics.cpp | 20 ++++++++++++++++++++ backends/graphics/opengl/opengl-graphics.h | 8 ++++++++ 2 files changed, 28 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index a97f680f15..3b92acc505 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -881,6 +881,26 @@ void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &def #endif } +void OpenGLGraphicsManager::notifyContextDestroy() { + if (_gameScreen) { + _gameScreen->releaseInternalTexture(); + } + + if (_overlay) { + _overlay->releaseInternalTexture(); + } + + if (_cursor) { + _cursor->releaseInternalTexture(); + } + +#ifdef USE_OSD + if (_osd) { + _osd->releaseInternalTexture(); + } +#endif +} + void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { if (_overlayVisible) { // It might be confusing that we actually have to handle something diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 93c0c5bc83..8d53dbe062 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -136,6 +136,14 @@ protected: */ void notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha); + /** + * Notify the manager that the OpenGL context is about to be destroyed. + * This will free up/reset internal OpenGL related state and *must* be + * called whenever a context might be created again after destroying a + * context. + */ + void notifyContextDestroy(); + /** * Adjust the physical mouse coordinates according to the currently visible screen. */ -- cgit v1.2.3 From b5ca9f5f108ffd46a514656630c7ea9824a035ce Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 11 Feb 2014 11:07:37 +0100 Subject: OPENGLSDL: Notify OpenGL manager about context destruction. --- backends/graphics/openglsdl/openglsdl-graphics.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 3f9fc1fbd5..70190b4c63 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -308,6 +308,14 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { flags |= SDL_RESIZABLE; } + if (_hwScreen) { + // When a video mode has been setup already we notify the manager that + // the context is about to be destroyed. + // We do this because on Windows SDL_SetVideoMode can destroy and + // recreate the OpenGL context. + notifyContextDestroy(); + } + _hwScreen = SDL_SetVideoMode(width, height, 32, flags); if (!_hwScreen) { -- cgit v1.2.3 From 006356848407065bbe26488cffe0b0a927fdbb9a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 11 Feb 2014 11:07:37 +0100 Subject: OPENGL: Rename notifyContextChange to notifyContextCreate. --- backends/graphics/opengl/opengl-graphics.cpp | 2 +- backends/graphics/opengl/opengl-graphics.h | 4 ++-- backends/graphics/openglsdl/openglsdl-graphics.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 3b92acc505..adae8cdd0a 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -816,7 +816,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { ++_screenChangeID; } -void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) { +void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) { // Initialize all extensions. initializeGLExtensions(); diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 8d53dbe062..0512a65746 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -127,14 +127,14 @@ protected: /** * Notify the manager of a OpenGL context change. This should be the first - * thing to call when you create an OpenGL (ES) context! + * thing to call after you created an OpenGL (ES) context! * * @param defaultFormat The new default format for the game screen * (this is used for the CLUT8 game screens). * @param defaultFromatAlpha The new default format with an alpha channel * (this is used for the overlay and cursor). */ - void notifyContextChange(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha); + void notifyContextCreate(const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha); /** * Notify the manager that the OpenGL context is about to be destroyed. diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 70190b4c63..6df67d0c1d 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -328,7 +328,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { if (_hwScreen) { const Graphics::PixelFormat rgba8888 = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); - notifyContextChange(rgba8888, rgba8888); + notifyContextCreate(rgba8888, rgba8888); setActualScreenSize(_hwScreen->w, _hwScreen->h); } -- cgit v1.2.3 From 1f4638fe823d87ca6b45a79779aff9712e06ec58 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 11 Feb 2014 11:07:38 +0100 Subject: OPENGL: Refactor texture instantiation. --- backends/graphics/opengl/opengl-graphics.cpp | 77 ++++++++++++++-------------- backends/graphics/opengl/opengl-graphics.h | 8 +++ 2 files changed, 47 insertions(+), 38 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index adae8cdd0a..c60069f6df 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -265,21 +265,15 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { delete _gameScreen; _gameScreen = nullptr; - GLenum glIntFormat, glFormat, glType; #ifdef USE_RGB_COLOR - if (_currentState.gameFormat.bytesPerPixel == 1) { + _gameScreen = createTexture(_currentState.gameFormat); +#else + _gameScreen = createTexture(Graphics::PixelFormat::createFormatCLUT8()); #endif - const bool supported = getGLPixelFormat(_defaultFormat, glIntFormat, glFormat, glType); - assert(supported); - _gameScreen = new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormat); + assert(_gameScreen); + if (_gameScreen->hasPalette()) { _gameScreen->setPalette(0, 255, _gamePalette); -#ifdef USE_RGB_COLOR - } else { - const bool supported = getGLPixelFormat(_currentState.gameFormat, glIntFormat, glFormat, glType); - assert(supported); - _gameScreen = new Texture(glIntFormat, glFormat, glType, _currentState.gameFormat); } -#endif _gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight); _gameScreen->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); @@ -566,27 +560,19 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int GLenum glIntFormat, glFormat, glType; - if (inputFormat.bytesPerPixel == 1) { - // In case this is not supported this is a serious programming - // error and the assert a bit below will trigger! - const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); - assert(supported); - _cursor = new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormatAlpha); + Graphics::PixelFormat textureFormat; + if (inputFormat.bytesPerPixel == 1 || (inputFormat.aBits() && getGLPixelFormat(inputFormat, glIntFormat, glFormat, glType))) { + // There is two cases when we can use the cursor format directly. + // The first is when it's CLUT8, here color key handling can + // always be applied because we use the alpha channel of + // _defaultFormatAlpha for that. + // The other is when the input format has alpha bits and + // furthermore is directly supported. + textureFormat = inputFormat; } else { - // Try to use the format specified as input directly. We can only - // do so when it actually has alpha bits. - if (inputFormat.aBits() != 0 && getGLPixelFormat(inputFormat, glIntFormat, glFormat, glType)) { - _cursor = new Texture(glIntFormat, glFormat, glType, inputFormat); - } - - // Otherwise fall back to the default alpha format. - if (!_cursor) { - const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); - assert(supported); - _cursor = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); - } + textureFormat = _defaultFormatAlpha; } - + _cursor = createTexture(textureFormat); assert(_cursor); _cursor->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); } @@ -778,10 +764,8 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { delete _overlay; _overlay = nullptr; - GLenum glIntFormat, glFormat, glType; - const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); - assert(supported); - _overlay = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); + _overlay = createTexture(_defaultFormatAlpha); + assert(_overlay); // We always filter the overlay with GL_LINEAR. This assures it's // readable in case it needs to be scaled and does not affect it // otherwise. @@ -795,10 +779,8 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { delete _osd; _osd = nullptr; - GLenum glIntFormat, glFormat, glType; - const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); - assert(supported); - _osd = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); + _osd = createTexture(_defaultFormatAlpha); + assert(_osd); // We always filter the osd with GL_LINEAR. This assures it's // readable in case it needs to be scaled and does not affect it // otherwise. @@ -929,6 +911,25 @@ void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { } } +Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &format) { + GLenum glIntFormat, glFormat, glType; + if (format.bytesPerPixel == 1) { + const bool supported = getGLPixelFormat(_defaultFormat, glIntFormat, glFormat, glType); + if (!supported) { + return nullptr; + } else { + return new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormat); + } + } else { + const bool supported = getGLPixelFormat(format, glIntFormat, glFormat, glType); + if (!supported) { + return nullptr; + } else { + return new Texture(glIntFormat, glFormat, glType, format); + } + } +} + bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const { if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 glIntFormat = GL_RGBA; diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 0512a65746..5d80968089 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -171,6 +171,14 @@ protected: virtual void setInternalMousePosition(int x, int y) = 0; private: + /** + * Create a texture with the specified pixel format. + * + * @param format The pixel format the Texture object should accept as input. + * @return A pointer to the texture or nullptr on failure. + */ + Texture *createTexture(const Graphics::PixelFormat &format); + // // Transaction support // -- cgit v1.2.3 From 16898486fa28cb428183d94552f2c9884a718c9f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 11 Feb 2014 11:07:38 +0100 Subject: OPENGL: Properly setup full game palette on video mode change if required. --- backends/graphics/opengl/opengl-graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index c60069f6df..3321689366 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -272,7 +272,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { #endif assert(_gameScreen); if (_gameScreen->hasPalette()) { - _gameScreen->setPalette(0, 255, _gamePalette); + _gameScreen->setPalette(0, 256, _gamePalette); } _gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight); -- cgit v1.2.3 From abcadb5d8728fdc18bf544d8b40418880fa1a145 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 11 Feb 2014 12:19:30 +0100 Subject: OPENGL: Fix cursor regression when defaultFormat doesn't have an alpha channel. --- backends/graphics/opengl/opengl-graphics.cpp | 9 +++++---- backends/graphics/opengl/opengl-graphics.h | 7 +++++-- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 3321689366..925b2c5a82 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -572,7 +572,7 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int } else { textureFormat = _defaultFormatAlpha; } - _cursor = createTexture(textureFormat); + _cursor = createTexture(textureFormat, true); assert(_cursor); _cursor->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); } @@ -911,14 +911,15 @@ void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { } } -Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &format) { +Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &format, bool wantAlpha) { GLenum glIntFormat, glFormat, glType; if (format.bytesPerPixel == 1) { - const bool supported = getGLPixelFormat(_defaultFormat, glIntFormat, glFormat, glType); + const Graphics::PixelFormat &virtFormat = wantAlpha ? _defaultFormatAlpha : _defaultFormat; + const bool supported = getGLPixelFormat(virtFormat, glIntFormat, glFormat, glType); if (!supported) { return nullptr; } else { - return new TextureCLUT8(glIntFormat, glFormat, glType, _defaultFormat); + return new TextureCLUT8(glIntFormat, glFormat, glType, virtFormat); } } else { const bool supported = getGLPixelFormat(format, glIntFormat, glFormat, glType); diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 5d80968089..6b13db8558 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -174,10 +174,13 @@ private: /** * Create a texture with the specified pixel format. * - * @param format The pixel format the Texture object should accept as input. + * @param format The pixel format the Texture object should accept as + * input. + * @param wantAlpha For CLUT8 textures this marks whether an alpha + * channel should be used. * @return A pointer to the texture or nullptr on failure. */ - Texture *createTexture(const Graphics::PixelFormat &format); + Texture *createTexture(const Graphics::PixelFormat &format, bool wantAlpha = false); // // Transaction support -- cgit v1.2.3 From ddc70ed9ee635ee71e08b7b3bce0211198f01be5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 12 Feb 2014 17:15:07 +0100 Subject: OPENGL: Properly use signed types for cursor hotspot. --- backends/graphics/opengl/opengl-graphics.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 6b13db8558..46fd687666 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -396,12 +396,12 @@ private: /** * The X offset for the cursor hotspot in unscaled coordinates. */ - uint _cursorHotspotX; + int _cursorHotspotX; /** * The Y offset for the cursor hotspot in unscaled coordinates. */ - uint _cursorHotspotY; + int _cursorHotspotY; /** * Recalculate the cursor scaling. Scaling is always done according to @@ -412,12 +412,12 @@ private: /** * The X offset for the cursor hotspot in scaled coordinates. */ - uint _cursorHotspotXScaled; + int _cursorHotspotXScaled; /** * The Y offset for the cursor hotspot in scaled coordinates. */ - uint _cursorHotspotYScaled; + int _cursorHotspotYScaled; /** * The width of the cursor scaled coordinates. -- cgit v1.2.3 From 49dcd36e72889b3edb67ce098af7cb854e499cb8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 12 Feb 2014 17:15:07 +0100 Subject: OPENGL: Use signed types for mouse coordinates. This adjusts for the fact that our event handling also uses signed coordinates. --- backends/graphics/opengl/opengl-graphics.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 46fd687666..d16f92d148 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -386,12 +386,12 @@ private: /** * X coordinate of the cursor in phyiscal coordinates. */ - uint _cursorX; + int _cursorX; /** * Y coordinate of the cursor in physical coordinates. */ - uint _cursorY; + int _cursorY; /** * The X offset for the cursor hotspot in unscaled coordinates. -- cgit v1.2.3 From 1709486859db9c38f5e4287e3e7fa817f76c1ee7 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 12 Feb 2014 17:15:07 +0100 Subject: OPENGL: Use GLfloat for draw cooridnates in Texture. --- backends/graphics/opengl/texture.cpp | 14 +++++++------- backends/graphics/opengl/texture.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index dff483dc0d..7b0b22d630 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -166,7 +166,7 @@ void Texture::fill(uint32 color) { flagDirty(); } -void Texture::draw(GLuint x, GLuint y, GLuint w, GLuint h) { +void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { // Only do any processing when the Texture is initialized. if (!_textureData.getPixels()) { return; @@ -190,13 +190,13 @@ void Texture::draw(GLuint x, GLuint y, GLuint w, GLuint h) { GLCALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); // Calculate the screen rect where the texture will be drawn. - const GLshort vertices[4*2] = { - (GLshort)x, (GLshort)y, - (GLshort)(x + w), (GLshort)y, - (GLshort)x, (GLshort)(y + h), - (GLshort)(x + w), (GLshort)(y + h) + const GLfloat vertices[4*2] = { + x, y, + x + w, y, + x, y + h, + x + w, y + h }; - GLCALL(glVertexPointer(2, GL_SHORT, 0, vertices)); + GLCALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); // Draw the texture to the screen buffer. GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h index e28d980de4..ad70833544 100644 --- a/backends/graphics/opengl/texture.h +++ b/backends/graphics/opengl/texture.h @@ -79,7 +79,7 @@ public: void fill(uint32 color); - void draw(GLuint x, GLuint y, GLuint w, GLuint h); + void draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h); void flagDirty() { _allDirty = true; } bool isDirty() const { return _allDirty || !_dirtyArea.isEmpty(); } -- cgit v1.2.3 From 6576dd758bfaf078abfb430d4b9c99b7047e4308 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 12 Feb 2014 17:15:07 +0100 Subject: OPENGL: Simplify shake offset application. --- backends/graphics/opengl/opengl-graphics.cpp | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 925b2c5a82..a0651f2eb1 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -353,15 +353,7 @@ void OpenGLGraphicsManager::updateScreen() { const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight(); // First step: Draw the (virtual) game screen. - glPushMatrix(); - - // Adjust game screen shake position - GLCALL(glTranslatef(0, shakeOffset, 0)); - - // Draw the game screen - _gameScreen->draw(_displayX, _displayY, _displayWidth, _displayHeight); - - glPopMatrix(); + _gameScreen->draw(_displayX, _displayY + shakeOffset, _displayWidth, _displayHeight); // Second step: Draw the overlay if visible. if (_overlayVisible) { @@ -370,18 +362,12 @@ void OpenGLGraphicsManager::updateScreen() { // Third step: Draw the cursor if visible. if (_cursorVisible && _cursor) { - glPushMatrix(); - // Adjust game screen shake position, but only when the overlay is not // visible. - if (!_overlayVisible) { - GLCALL(glTranslatef(0, shakeOffset, 0)); - } + const GLfloat cursorOffset = _overlayVisible ? 0 : shakeOffset; - _cursor->draw(_cursorX - _cursorHotspotXScaled, _cursorY - _cursorHotspotYScaled, + _cursor->draw(_cursorX - _cursorHotspotXScaled, _cursorY - _cursorHotspotYScaled + cursorOffset, _cursorWidthScaled, _cursorHeightScaled); - - glPopMatrix(); } #ifdef USE_OSD -- cgit v1.2.3 From ac5907a8046cd7ab66e43ac7e7e2d39863984917 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 12 Feb 2014 17:15:07 +0100 Subject: OPENGL: Use frac_t for cursor scaling. --- backends/graphics/opengl/opengl-graphics.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index a0651f2eb1..dfba14abe6 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -1072,14 +1072,14 @@ void OpenGLGraphicsManager::recalculateCursorScaling() { // In case scaling is actually enabled we will scale the cursor according // to the game screen. if (!_cursorDontScale) { - const uint screenScaleFactorX = _displayWidth * 10000 / _gameScreen->getWidth(); - const uint screenScaleFactorY = _displayHeight * 10000 / _gameScreen->getHeight(); + const frac_t screenScaleFactorX = intToFrac(_displayWidth) / _gameScreen->getWidth(); + const frac_t screenScaleFactorY = intToFrac(_displayHeight) / _gameScreen->getHeight(); - _cursorHotspotXScaled = (_cursorHotspotXScaled * screenScaleFactorX) / 10000; - _cursorWidthScaled = (_cursorWidthScaled * screenScaleFactorX) / 10000; + _cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX); + _cursorWidthScaled = fracToInt(_cursorWidthScaled * screenScaleFactorX); - _cursorHotspotYScaled = (_cursorHotspotYScaled * screenScaleFactorY) / 10000; - _cursorHeightScaled = (_cursorHeightScaled * screenScaleFactorY) / 10000; + _cursorHotspotYScaled = fracToInt(_cursorHotspotYScaled * screenScaleFactorY); + _cursorHeightScaled = fracToInt(_cursorHeightScaled * screenScaleFactorY); } } -- cgit v1.2.3 From 2cab30ee80a7611945ac5e9260c63d6b86f658cf Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 12 Feb 2014 18:06:29 +0100 Subject: OPENGL: Move RGBA8888 (logical layout) to OpenGL specific formats. The reason here is that GL_UNSIGNED_INT_8_8_8_8 is not supported by the GLES standard. Thus we cannot use it outside OpenGL specific code paths. --- backends/graphics/opengl/opengl-graphics.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index dfba14abe6..d7d37a2025 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -918,12 +918,7 @@ Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &forma } bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const { - if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 - glIntFormat = GL_RGBA; - glFormat = GL_RGBA; - glType = GL_UNSIGNED_INT_8_8_8_8; - return true; - } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 + if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 glIntFormat = GL_RGB; glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; @@ -939,6 +934,11 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF glType = GL_UNSIGNED_SHORT_4_4_4_4; return true; #ifndef USE_GLES + } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 + glIntFormat = GL_RGBA; + glFormat = GL_RGBA; + glType = GL_UNSIGNED_INT_8_8_8_8; + return true; } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 // GL_BGRA does not exist in every GLES implementation so should not be configured if // USE_GLES is set. -- cgit v1.2.3 From 5d78542ab8c6a76e266a453b8590bf6bbd70b631 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 12 Feb 2014 18:06:29 +0100 Subject: OPENGL: Always support RGBA8888 (memory layout). --- backends/graphics/opengl/opengl-graphics.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index d7d37a2025..0a034128fe 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -918,7 +918,16 @@ Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &forma } bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const { - if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 +#ifdef SCUMM_LITTLE_ENDIAN + if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888 +#else + if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 +#endif + glIntFormat = GL_RGBA; + glFormat = GL_RGBA; + glType = GL_UNSIGNED_BYTE; + return true; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 glIntFormat = GL_RGB; glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; @@ -934,11 +943,13 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF glType = GL_UNSIGNED_SHORT_4_4_4_4; return true; #ifndef USE_GLES +#ifdef SCUMM_LITTLE_ENDIAN } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 glIntFormat = GL_RGBA; glFormat = GL_RGBA; glType = GL_UNSIGNED_INT_8_8_8_8; return true; +#endif } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 // GL_BGRA does not exist in every GLES implementation so should not be configured if // USE_GLES is set. @@ -956,11 +967,13 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF glFormat = GL_BGRA; glType = GL_UNSIGNED_SHORT_4_4_4_4_REV; return true; +#ifdef SCUMM_BIG_ENDIAN } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888 glIntFormat = GL_RGBA; glFormat = GL_RGBA; glType = GL_UNSIGNED_INT_8_8_8_8_REV; return true; +#endif } else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0)) { // BGRA8888 glIntFormat = GL_RGBA; glFormat = GL_BGRA; -- cgit v1.2.3 From 5883f4cc3fe5861c314afedb00c692f31f1a1124 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 12 Feb 2014 18:06:29 +0100 Subject: OPENGL/SDL: Default to RGBA8888 (memory layout). This makes sure the default mode also works for OpenGL ES contexts. --- backends/graphics/openglsdl/openglsdl-graphics.cpp | 29 +++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'backends/graphics') diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 6df67d0c1d..9540a19e9e 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -158,8 +158,18 @@ void OpenGLSdlGraphicsManager::resetGraphicsScale() { Common::List OpenGLSdlGraphicsManager::getSupportedFormats() const { Common::List formats; + // Our default mode is (memory layout wise) RGBA8888 which is a different + // logical layout depending on the endianness. We chose this mode because + // it is the only 32bit color mode we can safely assume to be present in + // OpenGL and OpenGL ES implementations. Thus, we need to supply different + // logical formats based on endianness. +#ifdef SCUMM_LITTLE_ENDIAN + // ABGR8888 + formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)); +#else // RGBA8888 formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); +#endif // RGB565 formats.push_back(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); // RGBA5551 @@ -168,6 +178,13 @@ Common::List OpenGLSdlGraphicsManager::getSupportedFormat formats.push_back(Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)); #ifndef USE_GLES +#ifdef SCUMM_LITTLE_ENDIAN + // RGBA8888 + formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); +#else + // ABGR8888 + formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)); +#endif // ARGB8888, this should not be here, but Sword25 requires it. :-/ formats.push_back(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)); @@ -327,7 +344,17 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { } if (_hwScreen) { - const Graphics::PixelFormat rgba8888 = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); + // This is pretty confusing since RGBA8888 talks about the memory + // layout here. This is a different logical layout depending on + // whether we run on little endian or big endian. However, we can + // only safely assume that RGBA8888 in memory layout is supported. + // Thus, we chose this one. + const Graphics::PixelFormat rgba8888 = +#ifdef SCUMM_LITTLE_ENDIAN + Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24); +#else + Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); +#endif notifyContextCreate(rgba8888, rgba8888); setActualScreenSize(_hwScreen->w, _hwScreen->h); } -- cgit v1.2.3 From 121687d2ed7811c6805a11b17e295d7e9517b9c6 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:18 +0100 Subject: BACKENDS: Make GPL headers consistent in themselves. --- backends/graphics/default-palette.h | 4 ++-- backends/graphics/graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/default-palette.h b/backends/graphics/default-palette.h index 8f3fcb2db1..a66e1862b7 100644 --- a/backends/graphics/default-palette.h +++ b/backends/graphics/default-palette.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 24397228e6..3671b9f0b9 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From 7803ce2fa40d55fec3814306eabf2b91473d3d16 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:19 +0100 Subject: DINGUX: Make GPL headers consistent in themselves. --- backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp | 4 ++-- backends/graphics/dinguxsdl/dinguxsdl-graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp index bd87c9fafd..343efa4da6 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.h b/backends/graphics/dinguxsdl/dinguxsdl-graphics.h index ecdd01d166..fc70e721cf 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.h +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From 96564e95b4293b460685168d089be51d4a52490e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:20 +0100 Subject: GPH: Make GPL headers consistent in themselves. --- backends/graphics/gph/gph-graphics.cpp | 4 ++-- backends/graphics/gph/gph-graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/gph/gph-graphics.cpp b/backends/graphics/gph/gph-graphics.cpp index 92553564bf..247e5ed490 100644 --- a/backends/graphics/gph/gph-graphics.cpp +++ b/backends/graphics/gph/gph-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/gph/gph-graphics.h b/backends/graphics/gph/gph-graphics.h index f1f3d18b41..4a68ea6eed 100644 --- a/backends/graphics/gph/gph-graphics.h +++ b/backends/graphics/gph/gph-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From 872b5fdf415b72685b2db2910924defd618f28c9 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:22 +0100 Subject: LINUXMOTO: Make GPL headers consistent in themselves. --- backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp | 4 ++-- backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp index a005d74919..22b271ae1a 100644 --- a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h index ee2a566d71..8760c5004d 100644 --- a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From 4f34f44fbf1e08c95c68b7902ff815aebe3a30f4 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:22 +0100 Subject: MAEMO: Make GPL headers consistent in themselves. --- backends/graphics/maemosdl/maemosdl-graphics.cpp | 4 ++-- backends/graphics/maemosdl/maemosdl-graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/maemosdl/maemosdl-graphics.cpp b/backends/graphics/maemosdl/maemosdl-graphics.cpp index 527ef82b9d..07d6d32d3a 100644 --- a/backends/graphics/maemosdl/maemosdl-graphics.cpp +++ b/backends/graphics/maemosdl/maemosdl-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/maemosdl/maemosdl-graphics.h b/backends/graphics/maemosdl/maemosdl-graphics.h index 81064d2d5f..c255e94653 100644 --- a/backends/graphics/maemosdl/maemosdl-graphics.h +++ b/backends/graphics/maemosdl/maemosdl-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From 56528d9201d9da2b422d4421641ce92bc27e3db8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:23 +0100 Subject: NULL: Make GPL headers consistent in themselves. --- backends/graphics/null/null-graphics.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/null/null-graphics.h b/backends/graphics/null/null-graphics.h index 276be7d3fa..67306c29f3 100644 --- a/backends/graphics/null/null-graphics.h +++ b/backends/graphics/null/null-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From cc2f3e23a4b21b562240c747cedaae4d77d8d9e5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:23 +0100 Subject: OPENPANDORA: Make GPL headers consistent in themselves. --- backends/graphics/openpandora/op-graphics.cpp | 4 ++-- backends/graphics/openpandora/op-graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/openpandora/op-graphics.cpp b/backends/graphics/openpandora/op-graphics.cpp index f371081fde..1ded1614de 100644 --- a/backends/graphics/openpandora/op-graphics.cpp +++ b/backends/graphics/openpandora/op-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/openpandora/op-graphics.h b/backends/graphics/openpandora/op-graphics.h index 2e3d63e3ad..8b498d632b 100644 --- a/backends/graphics/openpandora/op-graphics.h +++ b/backends/graphics/openpandora/op-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From a3d012357ef54972f4814d0995cef3815e6a7b4b Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:24 +0100 Subject: SAMSUNGTV: Make GPL headers consistent in themselves. --- backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp | 4 ++-- backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp index 95e0875f55..3603d8a861 100644 --- a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp +++ b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h index 2d0ff636f4..15ba3dca48 100644 --- a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h +++ b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From 63304ee9ec4bf37cc96949f32f5c8dd53a6d3cc4 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:24 +0100 Subject: SDL: Make GPL headers consistent in themselves. --- backends/graphics/sdl/sdl-graphics.cpp | 4 ++-- backends/graphics/sdl/sdl-graphics.h | 4 ++-- backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 4 ++-- backends/graphics/surfacesdl/surfacesdl-graphics.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index 40b97b267b..b5e49fa397 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 3791961cfa..3ef540708a 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index b3af08e2e8..7f3c99fcea 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 22b7780675..49bd66b3e5 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From 1b5c324811c06b1128883ada7763f1f14c85afd8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:25 +0100 Subject: SYMBIAN: Make GPL headers consistent in themselves. --- backends/graphics/symbiansdl/symbiansdl-graphics.cpp | 4 ++-- backends/graphics/symbiansdl/symbiansdl-graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/symbiansdl/symbiansdl-graphics.cpp b/backends/graphics/symbiansdl/symbiansdl-graphics.cpp index 5fe8b19887..e339fecd1c 100644 --- a/backends/graphics/symbiansdl/symbiansdl-graphics.cpp +++ b/backends/graphics/symbiansdl/symbiansdl-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/symbiansdl/symbiansdl-graphics.h b/backends/graphics/symbiansdl/symbiansdl-graphics.h index 73e810a629..f514db286c 100644 --- a/backends/graphics/symbiansdl/symbiansdl-graphics.h +++ b/backends/graphics/symbiansdl/symbiansdl-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From 224cec46a7d8de2c2744c492e42e4cbdf9a8272a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 18 Feb 2014 02:34:27 +0100 Subject: WINCE: Make GPL headers consistent in themselves. --- backends/graphics/wincesdl/wincesdl-graphics.cpp | 4 ++-- backends/graphics/wincesdl/wincesdl-graphics.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/wincesdl/wincesdl-graphics.cpp b/backends/graphics/wincesdl/wincesdl-graphics.cpp index f075f8cf8a..8e4685dbd8 100644 --- a/backends/graphics/wincesdl/wincesdl-graphics.cpp +++ b/backends/graphics/wincesdl/wincesdl-graphics.cpp @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/backends/graphics/wincesdl/wincesdl-graphics.h b/backends/graphics/wincesdl/wincesdl-graphics.h index 2897ca5f40..50b422c10d 100644 --- a/backends/graphics/wincesdl/wincesdl-graphics.h +++ b/backends/graphics/wincesdl/wincesdl-graphics.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -- cgit v1.2.3 From da57eeeeb2548bd872b8b8fe7f3be040382b3b9b Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Tue, 25 Feb 2014 00:09:16 +0100 Subject: OPENGL: Fix building with --disable-16bit --- backends/graphics/opengl/opengl-graphics.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 0a034128fe..cbd06e9161 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -278,11 +278,15 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { _gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight); _gameScreen->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); // We fill the screen to all black or index 0 for CLUT8. +#ifdef USE_RGB_COLOR if (_currentState.gameFormat.bytesPerPixel == 1) { _gameScreen->fill(0); } else { _gameScreen->fill(_gameScreen->getSurface()->format.RGBToColor(0, 0, 0)); } +#else + _gameScreen->fill(0); +#endif } // Update our display area and cursor scaling. This makes sure we pick up -- cgit v1.2.3 From 92e02457f59e30c0bedb9ae36cb02ba2e42e24bb Mon Sep 17 00:00:00 2001 From: Alyssa Milburn Date: Tue, 10 Jun 2014 22:01:38 +0200 Subject: OPENGLSDL: Always ignore bad resolution changes. Otherwise we can end up with the wrong resolution when we make multiple resizes in quick succession. --- backends/graphics/openglsdl/openglsdl-graphics.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 9540a19e9e..3f42d62a3a 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -104,11 +104,6 @@ void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) case OSystem::kFeatureFullscreenMode: assert(getTransactionMode() != kTransactionNone); _wantsFullScreen = enable; - // When we switch to windowed mode we will ignore resize events. This - // avoids bad resizes to the (former) fullscreen resolution. - if (!enable) { - _ignoreResizeEvents = 10; - } break; case OSystem::kFeatureIconifyWindow: @@ -359,6 +354,11 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { setActualScreenSize(_hwScreen->w, _hwScreen->h); } + // Ignore resize events (from SDL) for a few frames. This avoids + // bad resizes to a (former) resolution for which we haven't + // processed an event yet. + _ignoreResizeEvents = 10; + return _hwScreen != nullptr; } -- cgit v1.2.3