From f5f1b6eba0d409abcda2a3c037a177d6f6e41a2e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 4 Jan 2016 06:41:10 +0100 Subject: OPENGL: Introduce pipeline abstraction to cleanup code. --- backends/graphics/opengl/context.cpp | 92 +++------------------------- backends/graphics/opengl/opengl-graphics.cpp | 34 ++++++++-- backends/graphics/opengl/opengl-graphics.h | 6 ++ backends/graphics/opengl/opengl-sys.h | 22 +++---- backends/graphics/opengl/pipeline.cpp | 76 +++++++++++++++++++++++ backends/graphics/opengl/pipeline.h | 92 ++++++++++++++++++++++++++++ backends/graphics/opengl/texture.cpp | 7 ++- 7 files changed, 226 insertions(+), 103 deletions(-) create mode 100644 backends/graphics/opengl/pipeline.cpp create mode 100644 backends/graphics/opengl/pipeline.h (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/context.cpp b/backends/graphics/opengl/context.cpp index 89f0ed7910..7402e79ea5 100644 --- a/backends/graphics/opengl/context.cpp +++ b/backends/graphics/opengl/context.cpp @@ -23,6 +23,7 @@ #include "backends/graphics/opengl/opengl-sys.h" #include "backends/graphics/opengl/opengl-graphics.h" #include "backends/graphics/opengl/shader.h" +#include "backends/graphics/opengl/pipeline.h" #include "common/tokenizer.h" #include "common/debug.h" @@ -40,94 +41,19 @@ void Context::reset() { #define GL_FUNC_DEF(ret, name, param) name = nullptr; #include "backends/graphics/opengl/opengl-func.h" #undef GL_FUNC_DEF -} - -void Context::initializePipeline() { -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type != kContextGLES2) { -#endif -#if !USE_FORCED_GLES2 - GL_CALL(glDisable(GL_LIGHTING)); - GL_CALL(glDisable(GL_FOG)); - GL_CALL(glShadeModel(GL_FLAT)); - GL_CALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); -#endif -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - } -#endif - // Enable rendering with vertex and coord arrays. -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.shadersSupported) { -#endif -#if !USE_FORCED_GLES - GL_CALL(glEnableVertexAttribArray(kPositionAttribLocation)); - GL_CALL(glEnableVertexAttribArray(kTexCoordAttribLocation)); -#endif -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 - } else { -#endif -#if !USE_FORCED_GLES2 - GL_CALL(glEnableClientState(GL_VERTEX_ARRAY)); - GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); -#endif -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 - } -#endif - -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type == kContextGLES2) { -#endif -#if !USE_FORCED_GL && !USE_FORCED_GLES - GL_CALL(glActiveTexture(GL_TEXTURE0)); -#endif -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - } else { -#endif -#if !USE_FORCED_GLES2 - GL_CALL(glEnable(GL_TEXTURE_2D)); -#endif -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - } -#endif + activePipeline = nullptr; } -void Context::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.shadersSupported) { -#endif -#if !USE_FORCED_GLES - GL_CALL(glVertexAttrib4f(kColorAttribLocation, r, g, b, a)); -#endif -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 - } else { -#endif -#if !USE_FORCED_GLES2 - GL_CALL(glColor4f(r, g, b, a)); -#endif -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 - } -#endif -} +Pipeline *Context::setPipeline(Pipeline *pipeline) { + Pipeline *oldPipeline = activePipeline; -void Context::setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords) { -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.shadersSupported) { -#endif -#if !USE_FORCED_GLES - GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texCoords)); - GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); -#endif -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 - } else { -#endif -#if !USE_FORCED_GLES2 - GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texCoords)); - GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); -#endif -#if !USE_FORCED_GLES && !USE_FORCED_GLES2 + activePipeline = pipeline; + if (activePipeline) { + activePipeline->activate(); } -#endif + + return oldPipeline; } Context g_context; diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 1ec40015af..0a9b040f83 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -23,6 +23,7 @@ #include "backends/graphics/opengl/opengl-graphics.h" #include "backends/graphics/opengl/texture.h" +#include "backends/graphics/opengl/pipeline.h" #include "backends/graphics/opengl/shader.h" #include "common/textconsole.h" @@ -44,6 +45,7 @@ namespace OpenGL { OpenGLGraphicsManager::OpenGLGraphicsManager() : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)), + _pipeline(nullptr), _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0), _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(), _gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr), @@ -425,13 +427,13 @@ void OpenGLGraphicsManager::updateScreen() { } // Set the OSD transparency. - g_context.setColor(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f); + g_context.activePipeline->setColor(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f); // Draw the OSD texture. _osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight); // Reset color. - g_context.setColor(1.0f, 1.0f, 1.0f, 1.0f); + g_context.activePipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f); } #endif @@ -867,6 +869,24 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def // Initialize context for use. initializeGLContext(); + // Initialize pipeline. + delete _pipeline; + _pipeline = nullptr; + +#if !USE_FORCED_GLES + if (g_context.shadersSupported) { + _pipeline = new ShaderPipeline(); + } +#endif + +#if !USE_FORCED_GLES2 + if (_pipeline == nullptr) { + _pipeline = new FixedPipeline(); + } +#endif + + g_context.setPipeline(_pipeline); + // Disable 3D properties. GL_CALL(glDisable(GL_CULL_FACE)); GL_CALL(glDisable(GL_DEPTH_TEST)); @@ -874,15 +894,12 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def // Default to black as clear color. GL_CALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); - g_context.setColor(1.0f, 1.0f, 1.0f, 1.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)); - // Initialize the context specific state of the pipeline. - g_context.initializePipeline(); - // Setup scissor state accordingly. if (_overlayVisible) { GL_CALL(glDisable(GL_SCISSOR_TEST)); @@ -969,6 +986,11 @@ void OpenGLGraphicsManager::notifyContextDestroy() { } #endif + // Destroy rendering pipeline. + g_context.setPipeline(nullptr); + delete _pipeline; + _pipeline = nullptr; + // Rest our context description since the context is gone soon. g_context.reset(); } diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 40605f0259..95ba4e7377 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -41,6 +41,7 @@ namespace OpenGL { #define USE_OSD 1 class Surface; +class Pipeline; #if !USE_FORCED_GLES class Shader; #endif @@ -303,6 +304,11 @@ private: */ void initializeGLContext(); + /** + * OpenGL pipeline used for rendering. + */ + Pipeline *_pipeline; + protected: /** * Query the address of an OpenGL function by name. diff --git a/backends/graphics/opengl/opengl-sys.h b/backends/graphics/opengl/opengl-sys.h index a584259abe..f68897ba58 100644 --- a/backends/graphics/opengl/opengl-sys.h +++ b/backends/graphics/opengl/opengl-sys.h @@ -87,6 +87,8 @@ enum ContextType { kContextGLES2 }; +class Pipeline; + /** * Description structure of the OpenGL (ES) context. */ @@ -126,20 +128,18 @@ struct Context { // programmable pipelines in the same fashion. // - /** - * Initializes the pipeline state. - */ - void initializePipeline(); - - /** - * Set color which shall be multiplied with each pixel. - */ - void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a); + /** Currently active rendering pipeline. */ + Pipeline *activePipeline; /** - * Set vertex and texture coordinates. + * Set new pipeline. + * + * Client is responsible for any memory management related to pipelines. + * + * @param pipeline Pipeline to activate. + * @return Formerly active pipeline. */ - void setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords); + Pipeline *setPipeline(Pipeline *pipeline); }; /** diff --git a/backends/graphics/opengl/pipeline.cpp b/backends/graphics/opengl/pipeline.cpp new file mode 100644 index 0000000000..362f15a36b --- /dev/null +++ b/backends/graphics/opengl/pipeline.cpp @@ -0,0 +1,76 @@ +/* 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/pipeline.h" +#include "backends/graphics/opengl/shader.h" + +namespace OpenGL { + +#if !USE_FORCED_GLES2 +void FixedPipeline::activate() { + GL_CALL(glDisable(GL_LIGHTING)); + GL_CALL(glDisable(GL_FOG)); + GL_CALL(glShadeModel(GL_FLAT)); + GL_CALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); + + GL_CALL(glEnableClientState(GL_VERTEX_ARRAY)); + GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + +#if !USE_FORCED_GLES + if (g_context.multitextureSupported) { + GL_CALL(glActiveTexture(GL_TEXTURE0)); + } +#endif + GL_CALL(glEnable(GL_TEXTURE_2D)); +} + +void FixedPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { + GL_CALL(glColor4f(r, g, b, a)); +} + +void FixedPipeline::setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords) { + GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texCoords)); + GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); +} +#endif // !USE_FORCED_GLES2 + +#if !USE_FORCED_GLES +void ShaderPipeline::activate() { + GL_CALL(glEnableVertexAttribArray(kPositionAttribLocation)); + GL_CALL(glEnableVertexAttribArray(kTexCoordAttribLocation)); + + if (g_context.multitextureSupported) { + GL_CALL(glActiveTexture(GL_TEXTURE0)); + } +} + +void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { + GL_CALL(glVertexAttrib4f(kColorAttribLocation, r, g, b, a)); +} + +void ShaderPipeline::setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords) { + GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texCoords)); + GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); +} +#endif // !USE_FORCED_GLES + +} // End of namespace OpenGL diff --git a/backends/graphics/opengl/pipeline.h b/backends/graphics/opengl/pipeline.h new file mode 100644 index 0000000000..e12390bcce --- /dev/null +++ b/backends/graphics/opengl/pipeline.h @@ -0,0 +1,92 @@ +/* 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_PIEPLINE_H +#define BACKENDS_GRAPHICS_OPENGL_PIEPLINE_H + +#include "backends/graphics/opengl/opengl-sys.h" + +namespace OpenGL { + +/** + * Interface for OpenGL pipeline functionality. + * + * This encapsulates differences in various rendering pipelines used for + * OpenGL, OpenGL ES 1, and OpenGL ES 2. + */ +class Pipeline { +public: + virtual ~Pipeline() {} + + /** + * Activate the pipeline. + * + * This sets the OpenGL state to make use of drawing with the given + * OpenGL pipeline. + */ + virtual void activate() = 0; + + /** + * Set modulation color. + * + * @param r Red component in [0,1]. + * @param g Green component in [0,1]. + * @param b Blue component in [0,1]. + * @param a Alpha component in [0,1]. + */ + virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) = 0; + + /** + * Setup coordinates for drawing with glDrawArrays. + * + * @param vertices The list of vertices, 2 coordinates for each vertex. + * @param texCoords The list of texture coordinates, 2 coordinates for + * each vertex. + */ + virtual void setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords) = 0; +}; + +#if !USE_FORCED_GLES2 +class FixedPipeline : public Pipeline { +public: + virtual void activate(); + + virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a); + + virtual void setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords); +}; +#endif // !USE_FORCED_GLES2 + +#if !USE_FORCED_GLES +class ShaderPipeline : public Pipeline { +public: + virtual void activate(); + + virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a); + + virtual void setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords); +}; +#endif // !USE_FORCED_GLES + +} // End of namespace OpenGL + +#endif diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index f98bf8be06..61e8dc37b3 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -22,6 +22,7 @@ #include "backends/graphics/opengl/texture.h" #include "backends/graphics/opengl/shader.h" +#include "backends/graphics/opengl/pipeline.h" #include "common/rect.h" #include "common/textconsole.h" @@ -282,7 +283,7 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { }; // Setup coordinates for drawing. - g_context.setDrawCoordinates(vertices, _glTexture.getTexCoords()); + g_context.activePipeline->setDrawCoordinates(vertices, _glTexture.getTexCoords()); // Draw the texture to the screen buffer. GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); @@ -649,7 +650,7 @@ void TextureCLUT8GPU::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { }; // Setup coordinates for drawing. - g_context.setDrawCoordinates(vertices, _glTexture.getTexCoords()); + g_context.activePipeline->setDrawCoordinates(vertices, _glTexture.getTexCoords()); // Draw the texture to the screen buffer. GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); @@ -744,7 +745,7 @@ void TextureCLUT8GPU::lookUpColors() { // Do color look up. _lookUpShader->activate(_projectionMatrix); _lookUpShader->setUniformI(_paletteLocation, 1); - g_context.setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); + g_context.activePipeline->setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords()); GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); // Restore old state. -- cgit v1.2.3