OPENGL: Introduce pipeline abstraction to cleanup code.

This commit is contained in:
Johannes Schickel 2016-01-04 06:41:10 +01:00
parent 08553a09cf
commit f5f1b6eba0
8 changed files with 227 additions and 103 deletions

View file

@ -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
activePipeline = nullptr;
}
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
Pipeline *Context::setPipeline(Pipeline *pipeline) {
Pipeline *oldPipeline = activePipeline;
// 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
activePipeline = pipeline;
if (activePipeline) {
activePipeline->activate();
}
#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
}
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
}
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
}
#endif
return oldPipeline;
}
Context g_context;

View file

@ -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();
}

View file

@ -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.

View file

@ -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();
/** Currently active rendering pipeline. */
Pipeline *activePipeline;
/**
* Set color which shall be multiplied with each pixel.
* Set new pipeline.
*
* Client is responsible for any memory management related to pipelines.
*
* @param pipeline Pipeline to activate.
* @return Formerly active pipeline.
*/
void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
/**
* Set vertex and texture coordinates.
*/
void setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords);
Pipeline *setPipeline(Pipeline *pipeline);
};
/**

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -55,6 +55,7 @@ MODULE_OBJS += \
graphics/opengl/context.o \
graphics/opengl/debug.o \
graphics/opengl/opengl-graphics.o \
graphics/opengl/pipeline.o \
graphics/opengl/shader.o \
graphics/opengl/texture.o
endif