diff options
Diffstat (limited to 'backends/graphics/opengl')
-rw-r--r-- | backends/graphics/opengl/glerrorcheck.cpp | 58 | ||||
-rw-r--r-- | backends/graphics/opengl/glerrorcheck.h | 38 | ||||
-rw-r--r-- | backends/graphics/opengl/gltexture.cpp | 177 | ||||
-rw-r--r-- | backends/graphics/opengl/gltexture.h | 86 | ||||
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 498 | ||||
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.h | 190 |
6 files changed, 1047 insertions, 0 deletions
diff --git a/backends/graphics/opengl/glerrorcheck.cpp b/backends/graphics/opengl/glerrorcheck.cpp new file mode 100644 index 0000000000..b93012b965 --- /dev/null +++ b/backends/graphics/opengl/glerrorcheck.cpp @@ -0,0 +1,58 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#if defined(DEBUG) //&& defined(USE_OPENGL) + +#include "backends/graphics/opengl/glerrorcheck.h" +#include "common/debug.h" + +#ifdef USE_GLES +#include <GLES/gl.h> +#else +#include <GL/gl.h> +#endif + +static const char *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"; + } + + static char buf[40]; + snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error); + return buf; +} + +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)); +} + +#endif diff --git a/backends/graphics/opengl/glerrorcheck.h b/backends/graphics/opengl/glerrorcheck.h new file mode 100644 index 0000000000..c5cbf5726b --- /dev/null +++ b/backends/graphics/opengl/glerrorcheck.h @@ -0,0 +1,38 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#if !defined(DEBUG) + +// If not in debug, just do the GL call +#define CHECK_GL_ERROR(call) (call) + +#else + +// If in debug, check for an error after a GL call +#define CHECK_GL_ERROR(call) ((call), 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 new file mode 100644 index 0000000000..139222bc36 --- /dev/null +++ b/backends/graphics/opengl/gltexture.cpp @@ -0,0 +1,177 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#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 inline GLint xdiv(int numerator, int denominator) { + assert(numerator < (1 << 16)); + return (numerator << 16) / denominator; +} + +template <class T> +static T nextHigher2(T k) { + if (k == 0) + return 1; + --k; + for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1) + k = k | k >> i; + return k + 1; +} + +void GLTexture::initGLExtensions() { + const char* ext_string = + reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); + Common::StringTokenizer tokenizer(ext_string, " "); + while (!tokenizer.empty()) { + Common::String token = tokenizer.nextToken(); + if (token == "GL_ARB_texture_non_power_of_two") + npot_supported = true; + } +} + +GLTexture::GLTexture(byte bpp, GLenum format, GLenum type) + : + _bytesPerPixel(bpp), + _glFormat(format), + _glType(type), + _textureWidth(0), + _textureHeight(0) { + + refresh(); + + // This all gets reset later in allocBuffer: + _surface.w = 0; + _surface.h = 0; + _surface.pitch = 0; + _surface.pixels = NULL; + _surface.bytesPerPixel = 0; +} + +GLTexture::~GLTexture() { + debug("Destroying texture %u", _textureName); + CHECK_GL_ERROR( glDeleteTextures(1, &_textureName) ); +} + +void GLTexture::refresh() { + // Generates the texture ID for GL + //CHECK_GL_ERROR( glGenTextures(1, &_textureName) ); + updateBuffer(_surface.pixels, _surface.bytesPerPixel, 0, 0, _surface.w, _surface.h); +} + +void GLTexture::allocBuffer(GLuint w, GLuint h) { + _surface.w = w; + _surface.h = h; + _surface.bytesPerPixel = _bytesPerPixel; + + if (w <= _textureWidth && h <= _textureHeight) + // Already allocated a sufficiently large buffer + return; + + if (npot_supported) { + _textureWidth = w; + _textureHeight = h; + } else { + _textureWidth = nextHigher2(w); + _textureHeight = nextHigher2(h); + } + _surface.pitch = w * _bytesPerPixel; + + //_surface.create(w, h, _bytesPerPixel); + + // Allocate room for the texture now, but pixel data gets uploaded + // later (perhaps with multiple TexSubImage2D operations). + CHECK_GL_ERROR( glBindTexture(GL_TEXTURE_2D, _textureName) ); + CHECK_GL_ERROR( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) ); + CHECK_GL_ERROR( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) ); + 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( glTexImage2D(GL_TEXTURE_2D, 0, _glFormat, + _textureWidth, _textureHeight, + 0, _glFormat, _glType, NULL) ); +} + +void GLTexture::updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, GLuint w, GLuint h) { + CHECK_GL_ERROR( glBindTexture(GL_TEXTURE_2D, _textureName) ); + + if (static_cast<int>(w) * _bytesPerPixel == pitch) { + CHECK_GL_ERROR( glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, + _glFormat, _glType, buf) ); + //memcpy(_surface.pixels, buf, w * pitch); + } else { + // GLES removed the ability to specify pitch, so we + // have to do this row by row. + const byte* src = static_cast<const byte*>(buf); + do { + CHECK_GL_ERROR( glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, + w, 1, _glFormat, _glType, src) ); + //memcpy(_surface.pixels, src, pitch); + ++y; + src += pitch; + } while (--h); + } +} + +void GLTexture::fillBuffer(byte x) { + byte* tmpbuf = new byte[_surface.h * _surface.w * _bytesPerPixel]; + memset(tmpbuf, 0, _surface.h * _surface.w * _bytesPerPixel); + CHECK_GL_ERROR( glBindTexture(GL_TEXTURE_2D, _textureName) ); + CHECK_GL_ERROR( glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _surface.w, _surface.h, + _glFormat, _glType, tmpbuf) ); + delete[] tmpbuf; +} + +void GLTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { + CHECK_GL_ERROR( glBindTexture(GL_TEXTURE_2D, _textureName) ); + + const GLint tex_width = xdiv(_surface.w, _textureWidth); + const GLint tex_height = xdiv(_surface.h, _textureHeight); + const GLint texcoords[] = { + 0, 0, + tex_width, 0, + 0, tex_height, + tex_width, tex_height, + }; + CHECK_GL_ERROR( glTexCoordPointer(2, GL_INT, 0, texcoords) ); + + const GLshort vertices[] = { + x, y, + x + w, y, + x, y + h, + x + w, y + h, + }; + CHECK_GL_ERROR( glVertexPointer(2, GL_SHORT, 0, vertices) ); + + assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords)); + CHECK_GL_ERROR( glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices) / 2) ); +} diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h new file mode 100644 index 0000000000..88a2b59962 --- /dev/null +++ b/backends/graphics/opengl/gltexture.h @@ -0,0 +1,86 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifdef WIN32 +#if defined(ARRAYSIZE) && !defined(_WINDOWS_) +#undef ARRAYSIZE +#endif +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef ARRAYSIZE +#endif + +#if defined(USE_GLES) +#include <GLES/gl.h> +#include <GLES/glext.h> +#elif defined(MACOSX) +#include <gl.h> +#include <glext.h> +#else +#include <GL/gl.h> +#include <GL/glext.h> +#endif + +#include "graphics/surface.h" + +#include "common/rect.h" +#include "common/array.h" + +/** + * OpenGL texture manager class + */ +class GLTexture { +public: + static void initGLExtensions(); + + GLTexture(byte bpp, GLenum format, GLenum type); + virtual ~GLTexture(); + + virtual void refresh(); + + virtual void allocBuffer(GLuint width, GLuint height); + virtual void fillBuffer(byte x); + virtual void updateBuffer(const void *buf, int pitch, GLuint x, GLuint y, + GLuint w, GLuint h); + + virtual void drawTexture() { drawTexture(0, 0, _surface.w, _surface.h); } + virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + + Graphics::Surface *getSurface() { return &_surface; } + + GLuint getWidth() const { return _surface.w; } + GLuint getHeight() const { return _surface.h; } + GLuint getTextureName() const { return _textureName; } + +protected: + const byte _bytesPerPixel; + const GLenum _glFormat; + const GLenum _glType; + + Graphics::Surface _surface; + GLuint _textureName; + GLuint _textureWidth; + GLuint _textureHeight; +}; diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp new file mode 100644 index 0000000000..fc864957d8 --- /dev/null +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -0,0 +1,498 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "backends/graphics/opengl/opengl-graphics.h" +#include "common/mutex.h" + +OpenGLGraphicsManager::OpenGLGraphicsManager() + : + _gameTexture(0), _overlayTexture(0), _mouseTexture(0), + _overlayVisible(false), + _mouseVisible(false), _mouseNeedsRedraw(false), + _screenChangeCount(0), + _currentShakePos(0), _newShakePos(0), + _transactionMode(kTransactionNone) + + { + + memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); + memset(&_videoMode, 0, sizeof(_videoMode)); + memset(&_transactionDetails, 0, sizeof(_transactionDetails)); + + _videoMode.mode = GFX_NORMAL; + _videoMode.scaleFactor = 1; + _videoMode.fullscreen = false; +} + +OpenGLGraphicsManager::~OpenGLGraphicsManager() { + +} + +void OpenGLGraphicsManager::init() { + GLTexture::initGLExtensions(); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_FOG); + glDisable(GL_DITHER); + glShadeModel(GL_FLAT); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glEnable(GL_TEXTURE_2D); +} + +// +// Feature +// + +bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { + return false; +} + +void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + +} + +bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { + return false; +} + +// +// Screen format and modes +// + +static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { + {"1x", "Normal", GFX_NORMAL}, + {0, 0, 0} +}; + +const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() const { + return s_supportedGraphicsModes; +} + +int OpenGLGraphicsManager::getDefaultGraphicsMode() const { + return GFX_NORMAL; +} + +bool OpenGLGraphicsManager::setGraphicsMode(int mode) { + return true; +} + +int OpenGLGraphicsManager::getGraphicsMode() const { + return GFX_NORMAL; +} + +#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 + //avoid redundant format changes + Graphics::PixelFormat newFormat; + if (!format) + newFormat = Graphics::PixelFormat::createFormatCLUT8(); + else + newFormat = *format; + + assert(newFormat.bytesPerPixel > 0); + + 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.needHotswap = false; + _transactionDetails.needUpdatescreen = 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.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) { + errors |= OSystem::kTransactionAspectRatioFailed; + + _videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection;*/ + } 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.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection && + _videoMode.mode == _oldVideoMode.mode && + _videoMode.screenWidth == _oldVideoMode.screenWidth && + _videoMode.screenHeight == _oldVideoMode.screenHeight) { + + // Our new video mode would now be exactly the same as the + // old one. Since we still can not assume SDL_SetVideoMode + // to be working fine, we need to invalidate the old video + // mode, so loadGFXMode would error out properly. + _oldVideoMode.setup = false; + } + } + +#ifdef USE_RGB_COLOR + if (_transactionDetails.sizeChanged || _transactionDetails.formatChanged) { +#else + if (_transactionDetails.sizeChanged) { +#endif + unloadGFXMode(); + if (!loadGFXMode()) { + if (_oldVideoMode.setup) { + _transactionMode = kTransactionRollback; + errors |= endGFXTransaction(); + } + } else { + //setGraphicsModeIntern(); + //clearOverlay(); + + _videoMode.setup = true; + _screenChangeCount++; + } + } else if (_transactionDetails.needHotswap) { + //setGraphicsModeIntern(); + if (!hotswapGFXMode()) { + if (_oldVideoMode.setup) { + _transactionMode = kTransactionRollback; + errors |= endGFXTransaction(); + } + } else { + _videoMode.setup = true; + _screenChangeCount++; + + if (_transactionDetails.needUpdatescreen) + internUpdateScreen(); + } + } else if (_transactionDetails.needUpdatescreen) { + //setGraphicsModeIntern(); + 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) { + +} + +void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { + +} + +void OpenGLGraphicsManager::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { + _gameTexture->updateBuffer(buf, pitch, x, y, w, h); +} + +Graphics::Surface *OpenGLGraphicsManager::lockScreen() { + return _gameTexture->getSurface(); +} + +void OpenGLGraphicsManager::unlockScreen() { + _gameTexture->refresh(); +} + +void OpenGLGraphicsManager::fillScreen(uint32 col) { + if (_gameTexture == NULL) + return; + + _gameTexture->fillBuffer(col); +} + +void OpenGLGraphicsManager::updateScreen() { + assert (_transactionMode == kTransactionNone); + internUpdateScreen(); +} + +void OpenGLGraphicsManager::setShakePos(int shakeOffset) { + assert (_transactionMode == kTransactionNone); + _newShakePos = shakeOffset; +} + +void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) { + +} + +void OpenGLGraphicsManager::clearFocusRectangle() { + +} + +// +// Overlay +// + +void OpenGLGraphicsManager::showOverlay() { + assert (_transactionMode == kTransactionNone); + + _overlayVisible = true; +} + +void OpenGLGraphicsManager::hideOverlay() { + assert (_transactionMode == kTransactionNone); + + _overlayVisible = false; +} + +Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const { + return _overlayFormat; +} + +void OpenGLGraphicsManager::clearOverlay() { + _overlayTexture->fillBuffer(0); +} + +void OpenGLGraphicsManager::grabOverlay(OverlayColor *buf, int pitch) { + const Graphics::Surface* surface = _overlayTexture->getSurface(); + assert(surface->bytesPerPixel == sizeof(buf[0])); + int h = surface->h; + do { + //memcpy(buf, surface->pixels, surface->w * sizeof(buf[0])); + memset(buf, 0, surface->w * sizeof(buf[0])); + buf += pitch; + } while (--h); +} + +void OpenGLGraphicsManager::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { + assert (_transactionMode == kTransactionNone); + + if (_overlayTexture == NULL) + return; + + _overlayTexture->updateBuffer(buf, pitch * sizeof(buf[0]), x, y, w, h); +} + +int16 OpenGLGraphicsManager::getOverlayHeight() { + return _videoMode.overlayHeight; +} + +int16 OpenGLGraphicsManager::getOverlayWidth() { + return _videoMode.overlayWidth; +} + +// +// Cursor +// + +bool OpenGLGraphicsManager::showMouse(bool visible) { + if (_mouseVisible == visible) + return visible; + + bool last = _mouseVisible; + _mouseVisible = visible; + _mouseNeedsRedraw = true; + + return last; +} + +void OpenGLGraphicsManager::setMousePos(int x, int y) { + if (x != _mouseCurState.x || y != _mouseCurState.y) { + _mouseNeedsRedraw = true; + _mouseCurState.x = x; + _mouseCurState.y = y; + } +} + +void OpenGLGraphicsManager::warpMouse(int x, int y) { + setMousePos(x, y); +} + +void OpenGLGraphicsManager::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { + +} + +void OpenGLGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) { + +} + +void OpenGLGraphicsManager::disableCursorPalette(bool disable) { + +} + +// +// Misc +// + +void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { + +} + +// +// Intern +// + +void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &type) { + if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888 + bpp = 4; + glFormat = GL_RGBA; + type = GL_UNSIGNED_BYTE; + } else if (pixelFormat == Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0)) { // RGB888 + bpp = 3; + glFormat = GL_RGB; + type = GL_UNSIGNED_BYTE; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565 + bpp = 2; + glFormat = GL_RGB; + type = GL_UNSIGNED_SHORT_5_6_5; + } else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555 + bpp = 2; + glFormat = GL_RGB; + type = GL_UNSIGNED_SHORT_5_5_5_1; + } else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444 + bpp = 2; + glFormat = GL_RGBA; + type = GL_UNSIGNED_SHORT_4_4_4_4; + } else if (pixelFormat == Graphics::PixelFormat::createFormatCLUT8()) { // CLUT8 + bpp = 1; + glFormat = GL_RGB; + type = GL_COLOR_INDEX; + } else { + error("Not supported format"); + } +} + +void OpenGLGraphicsManager::internUpdateScreen() { + +} + +bool OpenGLGraphicsManager::loadGFXMode() { + if (!_gameTexture) { + byte bpp; + GLenum format; + GLenum type; + getGLPixelFormat(_screenFormat, bpp, format, type); + _gameTexture = new GLTexture(bpp, format, type); + } else + _gameTexture->refresh(); + + if (!_overlayTexture) + _overlayTexture = new GLTexture(2, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4); + else + _overlayTexture->refresh(); + + if (!_mouseTexture) + _mouseTexture = new GLTexture(4, GL_RGBA, GL_UNSIGNED_BYTE); + else + _mouseTexture->refresh(); + + _gameTexture->allocBuffer(_videoMode.screenWidth, _videoMode.screenHeight); + _overlayTexture->allocBuffer(_videoMode.overlayWidth, _videoMode.overlayHeight); + + glViewport(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 0, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + return true; +} + +void OpenGLGraphicsManager::unloadGFXMode() { + +} + +bool OpenGLGraphicsManager::hotswapGFXMode() { + return false; +} diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h new file mode 100644 index 0000000000..17d0b842e9 --- /dev/null +++ b/backends/graphics/opengl/opengl-graphics.h @@ -0,0 +1,190 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_GRAPHICS_OPENGL_H +#define BACKENDS_GRAPHICS_OPENGL_H + +#include "backends/graphics/opengl/gltexture.h" +#include "backends/graphics/graphics.h" + +enum { + GFX_NORMAL = 0 +}; + +/** + * Open GL graphics manager + */ +class OpenGLGraphicsManager : public GraphicsManager { +public: + OpenGLGraphicsManager(); + virtual ~OpenGLGraphicsManager(); + + virtual void init(); + + 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; +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const; + virtual Common::List<Graphics::PixelFormat> 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(); + virtual void setPalette(const byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num); + virtual void copyRectToScreen(const byte *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(OverlayColor *buf, int pitch); + virtual void copyRectToOverlay(const OverlayColor *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 byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL); + virtual void setCursorPalette(const byte *colors, uint start, uint num); + virtual void disableCursorPalette(bool disable); + + virtual void displayMessageOnOSD(const char *msg); + + virtual void setMousePos(int x, int y); + +protected: + GLTexture* _gameTexture; + GLTexture* _overlayTexture; + GLTexture* _mouseTexture; + + virtual void getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &type); + + virtual void internUpdateScreen(); + virtual bool loadGFXMode(); + virtual void unloadGFXMode(); + virtual bool hotswapGFXMode(); + + Graphics::Surface _lockedScreen; + int _screenChangeCount; + +#ifdef USE_RGB_COLOR + Graphics::PixelFormat _screenFormat; + Graphics::PixelFormat _cursorFormat; +#endif + + bool _overlayVisible; + Graphics::PixelFormat _overlayFormat; + + enum { + kTransactionNone = 0, + kTransactionActive = 1, + kTransactionRollback = 2 + }; + + struct TransactionDetails { + bool sizeChanged; + bool needHotswap; + bool needUpdatescreen; +#ifdef USE_RGB_COLOR + bool formatChanged; +#endif + }; + TransactionDetails _transactionDetails; + int _transactionMode; + + struct VideoState { + bool setup; + + bool fullscreen; + //bool aspectRatioCorrection; + //AspectRatio desiredAspectRatio; + + int mode; + int scaleFactor; + + int screenWidth, screenHeight; + int overlayWidth, overlayHeight; + int hardwareWidth, hardwareHeight; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat format; +#endif + }; + VideoState _videoMode, _oldVideoMode; + + + struct MousePos { + // The mouse position, using either virtual (game) or real + // (overlay) 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 pre-scaled cursor image, in real + // coordinates. + int16 rW, rH; + int16 rHotX, rHotY; + + // The size and hotspot of the pre-scaled cursor image, in game + // coordinates. + int16 vW, vH; + int16 vHotX, vHotY; + + 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) + { } + }; + + MousePos _mouseCurState; + bool _mouseVisible; + bool _mouseNeedsRedraw; + + // Shake mode + int _currentShakePos; + int _newShakePos; +}; + +#endif |