diff options
Diffstat (limited to 'backends/graphics/opengl')
-rw-r--r-- | backends/graphics/opengl/glerrorcheck.cpp | 4 | ||||
-rw-r--r-- | backends/graphics/opengl/glerrorcheck.h | 2 | ||||
-rw-r--r-- | backends/graphics/opengl/gltexture.cpp | 173 | ||||
-rw-r--r-- | backends/graphics/opengl/gltexture.h | 112 | ||||
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 32 | ||||
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.h | 15 |
6 files changed, 330 insertions, 8 deletions
diff --git a/backends/graphics/opengl/glerrorcheck.cpp b/backends/graphics/opengl/glerrorcheck.cpp index 76e8de9d8a..b93012b965 100644 --- a/backends/graphics/opengl/glerrorcheck.cpp +++ b/backends/graphics/opengl/glerrorcheck.cpp @@ -34,7 +34,7 @@ #include <GL/gl.h> #endif -static const char* getGlErrStr(GLenum error) { +static const char *getGlErrStr(GLenum error) { switch (error) { case GL_NO_ERROR: return "GL_NO_ERROR"; case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; @@ -49,7 +49,7 @@ static const char* getGlErrStr(GLenum error) { return buf; } -void checkGlError(const char* file, int line) { +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)); diff --git a/backends/graphics/opengl/glerrorcheck.h b/backends/graphics/opengl/glerrorcheck.h index 7c997eb288..c5cbf5726b 100644 --- a/backends/graphics/opengl/glerrorcheck.h +++ b/backends/graphics/opengl/glerrorcheck.h @@ -33,6 +33,6 @@ // 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); +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..de9bd13eaf --- /dev/null +++ b/backends/graphics/opengl/gltexture.cpp @@ -0,0 +1,173 @@ +/* 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() : + _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) ); +} + +void GLTexture::allocBuffer(GLuint w, GLuint h) { + int bpp = bytesPerPixel(); + _surface.w = w; + _surface.h = h; + _surface.bytesPerPixel = bpp; + + if (w <= _textureWidth && h <= _textureHeight) + // Already allocated a sufficiently large buffer + return; + + if (npot_supported) { + _textureWidth = _surface.w; + _textureHeight = _surface.h; + } else { + _textureWidth = nextHigher2(_surface.w); + _textureHeight = nextHigher2(_surface.h); + } + _surface.pitch = _textureWidth * bpp; + + _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(GLuint x, GLuint y, GLuint w, GLuint h, const void* buf, int pitch) { + 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..7a33c88098 --- /dev/null +++ b/backends/graphics/opengl/gltexture.h @@ -0,0 +1,112 @@ +/* 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 + +#ifdef USE_GLES +#include <GLES/gl.h> +#include <GLES/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(); + virtual ~GLTexture(); + + virtual void refresh(); + + virtual void allocBuffer(GLuint width, GLuint height); + virtual void fillBuffer(byte x); + virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height, + const void* buf, int pitch); + + virtual void drawTexture() { drawTexture(0, 0, _surface.w, _surface.h); } + virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + + const Graphics::Surface* getSurface() const { return &_surface; } + + GLuint getWidth() const { return _surface.w; } + GLuint getHeight() const { return _surface.h; } + GLuint getTextureName() const { return _textureName; } + +protected: + virtual byte bytesPerPixel() const = 0; + virtual GLenum glFormat() const = 0; + virtual GLenum glType() const = 0; + Graphics::Surface _surface; + GLuint _textureName; + GLuint _textureWidth; + GLuint _textureHeight; +}; + +/** + * OpenGL RGBA 32 bit texture + */ +class GL32Texture : public GLTexture { +protected: + virtual byte bytesPerPixel() const { return 4; } + virtual GLenum glFormat() const { return GL_RGBA; } + virtual GLenum glType() const { return GL_UNSIGNED_BYTE; } +}; + +/** + * OpenGL RGBA4444 texture + */ +class GL4444Texture : public GLTexture { +protected: + virtual byte bytesPerPixel() const { return 2; } + virtual GLenum glFormat() const { return GL_RGBA; } + virtual GLenum glType() const { return GL_UNSIGNED_SHORT_4_4_4_4; } +}; + +/** + * OpenGL RGB565 texture + */ +class GL565Texture : public GLTexture { +protected: + virtual byte bytesPerPixel() const { return 2; } + virtual GLenum glFormat() const { return GL_RGB; } + virtual GLenum glType() const { return GL_UNSIGNED_SHORT_5_6_5; } +}; diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index bd1d6c22ff..fd3824b394 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -24,15 +24,21 @@ */ #include "backends/graphics/opengl/opengl-graphics.h" +#include "common/mutex.h" -OpenGLGraphicsManager::OpenGLGraphicsManager() { - +OpenGLGraphicsManager::OpenGLGraphicsManager() + : + _gameTexture(0), _overlayTexture(0), _mouseTexture(0) { } OpenGLGraphicsManager::~OpenGLGraphicsManager() { } +void OpenGLGraphicsManager::init() { + +} + // // Feature // @@ -63,7 +69,7 @@ const OSystem::GraphicsMode *OpenGLGraphicsManager::getSupportedGraphicsModes() } int OpenGLGraphicsManager::getDefaultGraphicsMode() const { - return 0; + return GFX_NORMAL; } bool OpenGLGraphicsManager::setGraphicsMode(int mode) { @@ -226,3 +232,23 @@ void OpenGLGraphicsManager::disableCursorPalette(bool disable) { void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { } + +// +// Intern +// + +void OpenGLGraphicsManager::internUpdateScreen() { + +} + +bool OpenGLGraphicsManager::loadGFXMode() { + return false; +} + +void OpenGLGraphicsManager::unloadGFXMode() { + +} + +bool OpenGLGraphicsManager::hotswapGFXMode() { + return false; +} diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 9da8b16242..664b1c138d 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -26,10 +26,9 @@ #ifndef BACKENDS_GRAPHICS_OPENGL_H #define BACKENDS_GRAPHICS_OPENGL_H +#include "backends/graphics/opengl/gltexture.h" #include "backends/graphics/graphics.h" -#include "graphics/surface.h" - enum { GFX_NORMAL = 0, }; @@ -42,6 +41,8 @@ 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); @@ -91,7 +92,17 @@ public: virtual void displayMessageOnOSD(const char *msg); protected: + GLTexture* _gameTexture; + GLTexture* _overlayTexture; + GLTexture* _mouseTexture; + + Graphics::Surface _lockedScreen; + + virtual void internUpdateScreen(); + virtual bool loadGFXMode(); + virtual void unloadGFXMode(); + virtual bool hotswapGFXMode(); }; #endif |