aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics/opengl
diff options
context:
space:
mode:
authorJohannes Schickel2016-01-04 10:18:15 +0100
committerJohannes Schickel2016-03-16 20:29:26 +0100
commitc4e65732befdfb675111387c3c7edb616bf2f976 (patch)
tree07b506bc66117fdd94ebc45462898369d3c8c87e /backends/graphics/opengl
parent5498982a3754edccb498521587c553e0ecbe7328 (diff)
downloadscummvm-rg350-c4e65732befdfb675111387c3c7edb616bf2f976.tar.gz
scummvm-rg350-c4e65732befdfb675111387c3c7edb616bf2f976.tar.bz2
scummvm-rg350-c4e65732befdfb675111387c3c7edb616bf2f976.zip
OPENGL: Introduce abstraction for framebuffer.
This allows us to use various framebuffer settings easily. Now the GPU accelerated CLUT8 surface implementation does not need to query former framebuffer state anymore.
Diffstat (limited to 'backends/graphics/opengl')
-rw-r--r--backends/graphics/opengl/context.cpp16
-rw-r--r--backends/graphics/opengl/framebuffer.cpp251
-rw-r--r--backends/graphics/opengl/framebuffer.h157
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp61
-rw-r--r--backends/graphics/opengl/opengl-graphics.h17
-rw-r--r--backends/graphics/opengl/opengl-sys.h14
-rw-r--r--backends/graphics/opengl/texture.cpp95
-rw-r--r--backends/graphics/opengl/texture.h8
8 files changed, 487 insertions, 132 deletions
diff --git a/backends/graphics/opengl/context.cpp b/backends/graphics/opengl/context.cpp
index 7402e79ea5..d9c40859dc 100644
--- a/backends/graphics/opengl/context.cpp
+++ b/backends/graphics/opengl/context.cpp
@@ -24,6 +24,7 @@
#include "backends/graphics/opengl/opengl-graphics.h"
#include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/pipeline.h"
+#include "backends/graphics/opengl/framebuffer.h"
#include "common/tokenizer.h"
#include "common/debug.h"
@@ -42,9 +43,24 @@ void Context::reset() {
#include "backends/graphics/opengl/opengl-func.h"
#undef GL_FUNC_DEF
+ activeFramebuffer = nullptr;
activePipeline = nullptr;
}
+Framebuffer *Context::setFramebuffer(Framebuffer *framebuffer) {
+ Framebuffer *oldFramebuffer = activeFramebuffer;
+ if (oldFramebuffer) {
+ oldFramebuffer->deactivate();
+ }
+
+ activeFramebuffer = framebuffer;
+ if (activeFramebuffer) {
+ activeFramebuffer->activate();
+ }
+
+ return oldFramebuffer;
+}
+
Pipeline *Context::setPipeline(Pipeline *pipeline) {
Pipeline *oldPipeline = activePipeline;
diff --git a/backends/graphics/opengl/framebuffer.cpp b/backends/graphics/opengl/framebuffer.cpp
new file mode 100644
index 0000000000..cca00bab03
--- /dev/null
+++ b/backends/graphics/opengl/framebuffer.cpp
@@ -0,0 +1,251 @@
+/* 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/framebuffer.h"
+#include "backends/graphics/opengl/texture.h"
+
+namespace OpenGL {
+
+Framebuffer::Framebuffer()
+ : _viewport(), _projectionMatrix(), _isActive(false), _clearColor(),
+ _blendState(false), _scissorTestState(false), _scissorBox() {
+}
+
+void Framebuffer::activate() {
+ _isActive = true;
+
+ applyViewport();
+ applyClearColor();
+ applyBlendState();
+ applyScissorTestState();
+ applyScissorBox();
+}
+
+void Framebuffer::deactivate() {
+ _isActive = false;
+}
+
+void Framebuffer::setClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
+ _clearColor[0] = r;
+ _clearColor[1] = g;
+ _clearColor[2] = b;
+ _clearColor[3] = a;
+
+ // Directly apply changes when we are active.
+ if (isActive()) {
+ applyClearColor();
+ }
+}
+
+void Framebuffer::enableBlend(bool enable) {
+ _blendState = enable;
+
+ // Directly apply changes when we are active.
+ if (isActive()) {
+ applyBlendState();
+ }
+}
+
+void Framebuffer::enableScissorTest(bool enable) {
+ _scissorTestState = enable;
+
+ // Directly apply changes when we are active.
+ if (isActive()) {
+ applyScissorTestState();
+ }
+}
+
+void Framebuffer::setScissorBox(GLint x, GLint y, GLsizei w, GLsizei h) {
+ _scissorBox[0] = x;
+ _scissorBox[1] = y;
+ _scissorBox[2] = w;
+ _scissorBox[3] = h;
+
+ // Directly apply changes when we are active.
+ if (isActive()) {
+ applyScissorBox();
+ }
+}
+
+void Framebuffer::applyViewport() {
+ GL_CALL(glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]));
+}
+
+void Framebuffer::applyClearColor() {
+ GL_CALL(glClearColor(_clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]));
+}
+
+void Framebuffer::applyBlendState() {
+ if (_blendState) {
+ GL_CALL(glEnable(GL_BLEND));
+ } else {
+ GL_CALL(glDisable(GL_BLEND));
+ }
+}
+
+void Framebuffer::applyScissorTestState() {
+ if (_scissorTestState) {
+ GL_CALL(glEnable(GL_SCISSOR_TEST));
+ } else {
+ GL_CALL(glDisable(GL_SCISSOR_TEST));
+ }
+}
+
+void Framebuffer::applyScissorBox() {
+ GL_CALL(glScissor(_scissorBox[0], _scissorBox[1], _scissorBox[2], _scissorBox[3]));
+}
+
+//
+// Backbuffer implementation
+//
+
+void Backbuffer::activate() {
+ Framebuffer::activate();
+
+#if !USE_FORCED_GLES
+ if (g_context.framebufferObjectSupported) {
+ GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
+ }
+#endif
+}
+
+void Backbuffer::setDimensions(uint width, uint height) {
+ // Set viewport dimensions.
+ _viewport[0] = 0;
+ _viewport[1] = 0;
+ _viewport[2] = width;
+ _viewport[3] = height;
+
+ // Setup orthogonal projection matrix.
+ _projectionMatrix[ 0] = 2.0f / width;
+ _projectionMatrix[ 1] = 0.0f;
+ _projectionMatrix[ 2] = 0.0f;
+ _projectionMatrix[ 3] = 0.0f;
+
+ _projectionMatrix[ 4] = 0.0f;
+ _projectionMatrix[ 5] = -2.0f / height;
+ _projectionMatrix[ 6] = 0.0f;
+ _projectionMatrix[ 7] = 0.0f;
+
+ _projectionMatrix[ 8] = 0.0f;
+ _projectionMatrix[ 9] = 0.0f;
+ _projectionMatrix[10] = 0.0f;
+ _projectionMatrix[11] = 0.0f;
+
+ _projectionMatrix[12] = -1.0f;
+ _projectionMatrix[13] = 1.0f;
+ _projectionMatrix[14] = 0.0f;
+ _projectionMatrix[15] = 1.0f;
+
+ // Directly apply changes when we are active.
+ if (isActive()) {
+ applyViewport();
+ }
+}
+
+//
+// Render to texture target implementation
+//
+
+#if !USE_FORCED_GLES
+TextureTarget::TextureTarget()
+ : _texture(new GLTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE)), _glFBO(0), _needUpdate(true) {
+}
+
+TextureTarget::~TextureTarget() {
+ delete _texture;
+ GL_CALL_SAFE(glDeleteFramebuffers, (1, &_glFBO));
+}
+
+void TextureTarget::activate() {
+ Framebuffer::activate();
+
+ // Allocate framebuffer object if necessary.
+ if (!_glFBO) {
+ GL_CALL(glGenFramebuffers(1, &_glFBO));
+ _needUpdate = true;
+ }
+
+ // Attach destination texture to FBO.
+ GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, _glFBO));
+
+ // If required attach texture to FBO.
+ if (_needUpdate) {
+ GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getGLTexture(), 0));
+ _needUpdate = false;
+ }
+}
+
+void TextureTarget::destroy() {
+ GL_CALL(glDeleteFramebuffers(1, &_glFBO));
+ _glFBO = 0;
+
+ _texture->destroy();
+}
+
+void TextureTarget::create() {
+ _texture->create();
+
+ _needUpdate = true;
+}
+
+void TextureTarget::setSize(uint width, uint height) {
+ _texture->setSize(width, height);
+
+ const uint texWidth = _texture->getWidth();
+ const uint texHeight = _texture->getHeight();
+
+ // Set viewport dimensions.
+ _viewport[0] = 0;
+ _viewport[1] = 0;
+ _viewport[2] = texWidth;
+ _viewport[3] = texHeight;
+
+ // Setup orthogonal projection matrix.
+ _projectionMatrix[ 0] = 2.0f / texWidth;
+ _projectionMatrix[ 1] = 0.0f;
+ _projectionMatrix[ 2] = 0.0f;
+ _projectionMatrix[ 3] = 0.0f;
+
+ _projectionMatrix[ 4] = 0.0f;
+ _projectionMatrix[ 5] = 2.0f / texHeight;
+ _projectionMatrix[ 6] = 0.0f;
+ _projectionMatrix[ 7] = 0.0f;
+
+ _projectionMatrix[ 8] = 0.0f;
+ _projectionMatrix[ 9] = 0.0f;
+ _projectionMatrix[10] = 0.0f;
+ _projectionMatrix[11] = 0.0f;
+
+ _projectionMatrix[12] = -1.0f;
+ _projectionMatrix[13] = -1.0f;
+ _projectionMatrix[14] = 0.0f;
+ _projectionMatrix[15] = 1.0f;
+
+ // Directly apply changes when we are active.
+ if (isActive()) {
+ applyViewport();
+ }
+}
+#endif // !USE_FORCED_GLES
+
+} // End of namespace OpenGL
diff --git a/backends/graphics/opengl/framebuffer.h b/backends/graphics/opengl/framebuffer.h
new file mode 100644
index 0000000000..be829de3d2
--- /dev/null
+++ b/backends/graphics/opengl/framebuffer.h
@@ -0,0 +1,157 @@
+/* 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_FRAMEBUFFER_H
+#define BACKENDS_GRAPHICS_OPENGL_FRAMEBUFFER_H
+
+#include "backends/graphics/opengl/opengl-sys.h"
+
+namespace OpenGL {
+
+/**
+ * Object describing a framebuffer OpenGL can render to.
+ */
+class Framebuffer {
+public:
+ Framebuffer();
+ virtual ~Framebuffer() {};
+
+ /**
+ * Activate framebuffer.
+ *
+ * This is supposed to set all state associated with the framebuffer.
+ */
+ virtual void activate() = 0;
+
+ /**
+ * Deactivate framebuffer.
+ *
+ * This is supposed to make any cleanup required when unbinding the
+ * framebuffer.
+ */
+ virtual void deactivate();
+
+ /**
+ * Set the clear color of the framebuffer.
+ */
+ void setClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+
+ /**
+ * Enable/disable GL_BLEND.
+ */
+ void enableBlend(bool enable);
+
+ /**
+ * Enable/disable GL_SCISSOR_TEST.
+ */
+ void enableScissorTest(bool enable);
+
+ /**
+ * Set scissor box dimensions.
+ */
+ void setScissorBox(GLint x, GLint y, GLsizei w, GLsizei h);
+
+ /**
+ * Obtain projection matrix of the framebuffer.
+ */
+ const GLfloat *getProjectionMatrix() const { return _projectionMatrix; }
+protected:
+ bool isActive() const { return _isActive; }
+
+ GLint _viewport[4];
+ void applyViewport();
+
+ GLfloat _projectionMatrix[4*4];
+private:
+ bool _isActive;
+
+ GLfloat _clearColor[4];
+ void applyClearColor();
+
+ bool _blendState;
+ void applyBlendState();
+
+ bool _scissorTestState;
+ void applyScissorTestState();
+
+ GLint _scissorBox[4];
+ void applyScissorBox();
+};
+
+/**
+ * Default back buffer implementation.
+ */
+class Backbuffer : public Framebuffer {
+public:
+ virtual void activate();
+
+ /**
+ * Set the dimensions (a.k.a. size) of the back buffer.
+ */
+ void setDimensions(uint width, uint height);
+};
+
+#if !USE_FORCED_GLES
+class GLTexture;
+
+/**
+ * Render to texture framebuffer implementation.
+ *
+ * This target allows to render to a texture, which can then be used for
+ * further rendering.
+ */
+class TextureTarget : public Framebuffer {
+public:
+ TextureTarget();
+ virtual ~TextureTarget();
+
+ virtual void activate();
+
+ /**
+ * Notify that the GL context is about to be destroyed.
+ */
+ void destroy();
+
+ /**
+ * Notify that the GL context has been created.
+ */
+ void create();
+
+ /**
+ * Set size of the texture target.
+ */
+ void setSize(uint width, uint height);
+
+ /**
+ * Query pointer to underlying GL texture.
+ */
+ GLTexture *getTexture() const { return _texture; }
+private:
+ GLTexture *_texture;
+ GLuint _glFBO;
+ bool _needUpdate;
+};
+#endif
+
+} // End of namespace OpenGL
+
+#endif
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index a8301482d3..36fc7b88aa 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -57,9 +57,6 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
#ifdef USE_OSD
, _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr)
#endif
-#if !USE_FORCED_GLES
- , _projectionMatrix()
-#endif
{
memset(_gamePalette, 0, sizeof(_gamePalette));
g_context.reset();
@@ -379,9 +376,9 @@ void OpenGLGraphicsManager::updateScreen() {
// cleared. For example, when switching from overlay visible to
// invisible, we need to assure that all contents are cleared to
// properly remove all overlay contents.
- GL_CALL(glDisable(GL_SCISSOR_TEST));
+ _backBuffer.enableScissorTest(false);
GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
- GL_CALL(glEnable(GL_SCISSOR_TEST));
+ _backBuffer.enableScissorTest(true);
--_scissorOverride;
} else {
@@ -475,7 +472,7 @@ void OpenGLGraphicsManager::showOverlay() {
_forceRedraw = true;
// Allow drawing inside full screen area.
- GL_CALL(glDisable(GL_SCISSOR_TEST));
+ _backBuffer.enableScissorTest(false);
// Update cursor position.
setMousePosition(_cursorX, _cursorY);
@@ -486,7 +483,7 @@ void OpenGLGraphicsManager::hideOverlay() {
_forceRedraw = true;
// Limit drawing to screen area.
- GL_CALL(glEnable(GL_SCISSOR_TEST));
+ _backBuffer.enableScissorTest(true);
_scissorOverride = 3;
// Update cursor position.
@@ -763,23 +760,15 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
_outputScreenWidth = width;
_outputScreenHeight = height;
- // Setup coordinate system.
- GL_CALL(glViewport(0, 0, _outputScreenWidth, _outputScreenHeight));
-
- // Orthogonal projection matrix in column major order.
- const GLfloat orthoProjection[4*4] = {
- 2.0f / _outputScreenWidth, 0.0f , 0.0f, 0.0f,
- 0.0f , -2.0f / _outputScreenHeight, 0.0f, 0.0f,
- 0.0f , 0.0f , -1.0f, 0.0f,
- -1.0f , 1.0f , 0.0f, 1.0f
- };
+ // Setup backbuffer size.
+ _backBuffer.setDimensions(width, height);
#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
if (!g_context.shadersSupported) {
#endif
#if !USE_FORCED_GLES2
GL_CALL(glMatrixMode(GL_PROJECTION));
- GL_CALL(glLoadMatrixf(orthoProjection));
+ GL_CALL(glLoadMatrixf(_backBuffer.getProjectionMatrix()));
GL_CALL(glMatrixMode(GL_MODELVIEW));
GL_CALL(glLoadIdentity());
@@ -788,9 +777,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
} else {
#endif
#if !USE_FORCED_GLES
- assert(sizeof(_projectionMatrix) == sizeof(orthoProjection));
- memcpy(_projectionMatrix, orthoProjection, sizeof(_projectionMatrix));
- ShaderMan.query(ShaderManager::kDefault)->activate(_projectionMatrix);
+ ShaderMan.query(ShaderManager::kDefault)->activate(_backBuffer.getProjectionMatrix());
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
}
@@ -890,20 +877,21 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
GL_CALL(glDisable(GL_DEPTH_TEST));
GL_CALL(glDisable(GL_DITHER));
- // Default to black as clear color.
- GL_CALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
g_context.activePipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
- // Setup alpha blend (for overlay and cursor).
- GL_CALL(glEnable(GL_BLEND));
GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
+ // Setup backbuffer state.
+
+ // Default to black as clear color.
+ _backBuffer.setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ // Setup alpha blend (for overlay and cursor).
+ _backBuffer.enableBlend(true);
// Setup scissor state accordingly.
- if (_overlayVisible) {
- GL_CALL(glDisable(GL_SCISSOR_TEST));
- } else {
- GL_CALL(glEnable(GL_SCISSOR_TEST));
- }
+ _backBuffer.enableScissorTest(!_overlayVisible);
+
+ g_context.setFramebuffer(&_backBuffer);
+
// Clear the whole screen for the first three frames to assure any
// leftovers are cleared.
_scissorOverride = 3;
@@ -916,7 +904,7 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
#if !USE_FORCED_GLES
if (g_context.shadersSupported) {
ShaderMan.notifyCreate();
- ShaderMan.query(ShaderManager::kDefault)->activate(_projectionMatrix);
+ ShaderMan.query(ShaderManager::kDefault)->activate(_backBuffer.getProjectionMatrix());
}
#endif
@@ -975,6 +963,9 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
}
#endif
+ // Unset back buffer.
+ g_context.setFramebuffer(nullptr);
+
// Destroy rendering pipeline.
g_context.setPipeline(nullptr);
delete _pipeline;
@@ -1185,10 +1176,10 @@ void OpenGLGraphicsManager::recalculateDisplayArea() {
// Setup drawing limitation for game graphics.
// This invovles some trickery because OpenGL's viewport coordinate system
// is upside down compared to ours.
- GL_CALL(glScissor(_displayX,
- _outputScreenHeight - _displayHeight - _displayY,
- _displayWidth,
- _displayHeight));
+ _backBuffer.setScissorBox(_displayX,
+ _outputScreenHeight - _displayHeight - _displayY,
+ _displayWidth,
+ _displayHeight);
// Clear the whole screen for the first three frames to remove leftovers.
_scissorOverride = 3;
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index f3cd4c437f..35435c156e 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -24,6 +24,7 @@
#define BACKENDS_GRAPHICS_OPENGL_OPENGL_GRAPHICS_H
#include "backends/graphics/opengl/opengl-sys.h"
+#include "backends/graphics/opengl/framebuffer.h"
#include "backends/graphics/graphics.h"
#include "common/frac.h"
@@ -305,6 +306,11 @@ private:
void initializeGLContext();
/**
+ * Render back buffer.
+ */
+ Backbuffer _backBuffer;
+
+ /**
* OpenGL pipeline used for rendering.
*/
Pipeline *_pipeline;
@@ -527,17 +533,6 @@ private:
*/
uint _scissorOverride;
-#if !USE_FORCED_GLES
- //
- // Shaders
- //
-
- /**
- * Projection matrix used.
- */
- GLfloat _projectionMatrix[4*4];
-#endif
-
#ifdef USE_OSD
//
// OSD
diff --git a/backends/graphics/opengl/opengl-sys.h b/backends/graphics/opengl/opengl-sys.h
index f68897ba58..ffc80a23dc 100644
--- a/backends/graphics/opengl/opengl-sys.h
+++ b/backends/graphics/opengl/opengl-sys.h
@@ -88,6 +88,7 @@ enum ContextType {
};
class Pipeline;
+class Framebuffer;
/**
* Description structure of the OpenGL (ES) context.
@@ -123,6 +124,19 @@ struct Context {
#include "backends/graphics/opengl/opengl-func.h"
#undef GL_FUNC_DEF
+ /** Currently active framebuffer. */
+ Framebuffer *activeFramebuffer;
+
+ /**
+ * Set new framebuffer.
+ *
+ * Client is responsible for any memory management related to framebuffers.
+ *
+ * @param framebuffer Framebuffer to activate.
+ * @return Formerly active framebuffer.
+ */
+ Framebuffer *setFramebuffer(Framebuffer *framebuffer);
+
//
// Wrapper functionality to handle fixed-function pipelines and
// programmable pipelines in the same fashion.
diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp
index 828dade0be..02e1b2c325 100644
--- a/backends/graphics/opengl/texture.cpp
+++ b/backends/graphics/opengl/texture.cpp
@@ -23,6 +23,7 @@
#include "backends/graphics/opengl/texture.h"
#include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/pipeline.h"
+#include "backends/graphics/opengl/framebuffer.h"
#include "common/rect.h"
#include "common/textconsole.h"
@@ -515,38 +516,30 @@ void TextureRGB555::updateTexture() {
TextureCLUT8GPU::TextureCLUT8GPU()
: _clut8Texture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE),
_paletteTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE),
- _glTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE),
- _glFBO(0), _clut8Vertices(), _projectionMatrix(),
- _paletteLocation(-1),
+ _target(new TextureTarget()), _clut8Vertices(), _paletteLocation(-1),
_clut8Data(), _userPixelData(), _palette(), _paletteDirty(false) {
// Allocate space for 256 colors.
_paletteTexture.setSize(256, 1);
_paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette");
-
- setupFBO();
}
TextureCLUT8GPU::~TextureCLUT8GPU() {
- GL_CALL_SAFE(glDeleteFramebuffers, (1, &_glFBO));
+ delete _target;
_clut8Data.free();
}
void TextureCLUT8GPU::destroy() {
_clut8Texture.destroy();
_paletteTexture.destroy();
- _glTexture.destroy();
-
- GL_CALL(glDeleteFramebuffers(1, &_glFBO));
- _glFBO = 0;
+ _target->destroy();
}
void TextureCLUT8GPU::recreate() {
_clut8Texture.create();
_paletteTexture.create();
- _glTexture.create();
_paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette");
- setupFBO();
+ _target->create();
// In case image date exists assure it will be completely refreshed next
// time.
@@ -557,13 +550,13 @@ void TextureCLUT8GPU::recreate() {
}
void TextureCLUT8GPU::enableLinearFiltering(bool enable) {
- _glTexture.enableLinearFiltering(enable);
+ _target->getTexture()->enableLinearFiltering(enable);
}
void TextureCLUT8GPU::allocate(uint width, uint height) {
// Assure the texture can contain our user data.
_clut8Texture.setSize(width, height);
- _glTexture.setSize(width, height);
+ _target->setSize(width, height);
// In case the needed texture dimension changed we will reinitialize the
// texture data buffer.
@@ -587,26 +580,6 @@ void TextureCLUT8GPU::allocate(uint width, uint height) {
_clut8Vertices[6] = width;
_clut8Vertices[7] = height;
-
- _projectionMatrix[ 0] = 2.0f / _glTexture.getWidth();
- _projectionMatrix[ 1] = 0.0f;
- _projectionMatrix[ 2] = 0.0f;
- _projectionMatrix[ 3] = 0.0f;
-
- _projectionMatrix[ 4] = 0.0f;
- _projectionMatrix[ 5] = 2.0f / _glTexture.getHeight();
- _projectionMatrix[ 6] = 0.0f;
- _projectionMatrix[ 7] = 0.0f;
-
- _projectionMatrix[ 8] = 0.0f;
- _projectionMatrix[ 9] = 0.0f;
- _projectionMatrix[10] = 0.0f;
- _projectionMatrix[11] = 0.0f;
-
- _projectionMatrix[12] = -1.0f;
- _projectionMatrix[13] = -1.0f;
- _projectionMatrix[14] = 0.0f;
- _projectionMatrix[15] = 1.0f;
}
void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
@@ -619,7 +592,7 @@ void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
updateTextures();
// Set the texture.
- _glTexture.bind();
+ _target->getTexture()->bind();
// Calculate the screen rect where the texture will be drawn.
const GLfloat vertices[4*2] = {
@@ -630,7 +603,7 @@ void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
};
// Setup coordinates for drawing.
- g_context.activePipeline->setDrawCoordinates(vertices, _glTexture.getTexCoords());
+ g_context.activePipeline->setDrawCoordinates(vertices, _target->getTexture()->getTexCoords());
// Draw the texture to the screen buffer.
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
@@ -695,24 +668,7 @@ void TextureCLUT8GPU::lookUpColors() {
GLint oldProgram = 0;
GL_CALL(glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram));
- GLint viewport[4];
- GL_CALL(glGetIntegerv(GL_VIEWPORT, viewport));
-
- GLboolean scissorState;
- GL_ASSIGN(scissorState, glIsEnabled(GL_SCISSOR_TEST));
- GLboolean blendState;
- GL_ASSIGN(blendState, glIsEnabled(GL_BLEND));
-
- GLint oldFBO = 0;
- GL_CALL(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO));
-
- // Update state.
- GL_CALL(glViewport(0, 0, _glTexture.getWidth(), _glTexture.getHeight()));
- GL_CALL(glDisable(GL_SCISSOR_TEST));
- GL_CALL(glDisable(GL_BLEND));
-
- // Bind framebuffer.
- GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, _glFBO));
+ Framebuffer *oldFramebuffer = g_context.setFramebuffer(_target);
// Set the palette texture.
GL_CALL(glActiveTexture(GL_TEXTURE1));
@@ -724,40 +680,15 @@ void TextureCLUT8GPU::lookUpColors() {
// Do color look up.
Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp);
- lookUpShader->activate(_projectionMatrix);
+ lookUpShader->activate(_target->getProjectionMatrix());
lookUpShader->setUniformI(_paletteLocation, 1);
g_context.activePipeline->setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords());
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
// Restore old state.
- GL_CALL(glUseProgram(oldProgram));
- GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, oldFBO));
+ g_context.setFramebuffer(oldFramebuffer);
- if (blendState) {
- GL_CALL(glEnable(GL_BLEND));
- }
- if (scissorState) {
- GL_CALL(glEnable(GL_SCISSOR_TEST));
- }
- GL_CALL(glViewport(viewport[0], viewport[1], viewport[2], viewport[3]));
-}
-
-void TextureCLUT8GPU::setupFBO() {
- // Allocate framebuffer object if necessary.
- if (!_glFBO) {
- GL_CALL(glGenFramebuffers(1, &_glFBO));
- }
-
- // Save old FBO.
- GLint oldFBO = 0;
- GL_CALL(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO));
-
- // Attach destination texture to FBO.
- GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, _glFBO));
- GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _glTexture.getGLTexture(), 0));
-
- // Restore old FBO.
- GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, oldFBO));
+ GL_CALL(glUseProgram(oldProgram));
}
#endif // !USE_FORCED_GLES
diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h
index 5f586f6a2f..df9893fa70 100644
--- a/backends/graphics/opengl/texture.h
+++ b/backends/graphics/opengl/texture.h
@@ -318,6 +318,8 @@ private:
#endif // !USE_FORCED_GL
#if !USE_FORCED_GLES
+class TextureTarget;
+
class TextureCLUT8GPU : public Surface {
public:
TextureCLUT8GPU();
@@ -359,12 +361,10 @@ private:
GLTexture _clut8Texture;
GLTexture _paletteTexture;
- GLTexture _glTexture;
- void setupFBO();
- GLuint _glFBO;
+ TextureTarget *_target;
+
GLfloat _clut8Vertices[4*2];
- GLfloat _projectionMatrix[4*4];
GLint _paletteLocation;