aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2016-01-04 10:18:15 +0100
committerJohannes Schickel2016-03-16 20:29:26 +0100
commitc4e65732befdfb675111387c3c7edb616bf2f976 (patch)
tree07b506bc66117fdd94ebc45462898369d3c8c87e
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.
-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
-rw-r--r--backends/module.mk1
9 files changed, 488 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;
diff --git a/backends/module.mk b/backends/module.mk
index 305942279a..f786933ade 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -54,6 +54,7 @@ ifdef USE_OPENGL
MODULE_OBJS += \
graphics/opengl/context.o \
graphics/opengl/debug.o \
+ graphics/opengl/framebuffer.o \
graphics/opengl/opengl-graphics.o \
graphics/opengl/pipeline.o \
graphics/opengl/shader.o \