OPENGL: Make shader/framebuffer part of pipeline state.

This commit is contained in:
Johannes Schickel 2016-01-04 11:38:21 +01:00
parent 0b46af2f0e
commit 0fe580d10c
8 changed files with 126 additions and 69 deletions

View file

@ -43,24 +43,9 @@ 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;

View file

@ -22,6 +22,7 @@
#include "backends/graphics/opengl/framebuffer.h"
#include "backends/graphics/opengl/texture.h"
#include "backends/graphics/opengl/pipeline.h"
namespace OpenGL {
@ -34,6 +35,7 @@ void Framebuffer::activate() {
_isActive = true;
applyViewport();
applyProjectionMatrix();
applyClearColor();
applyBlendState();
applyScissorTestState();
@ -90,6 +92,10 @@ void Framebuffer::applyViewport() {
GL_CALL(glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]));
}
void Framebuffer::applyProjectionMatrix() {
g_context.activePipeline->setProjectionMatrix(_projectionMatrix);
}
void Framebuffer::applyClearColor() {
GL_CALL(glClearColor(_clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]));
}
@ -159,6 +165,7 @@ void Backbuffer::setDimensions(uint width, uint height) {
// Directly apply changes when we are active.
if (isActive()) {
applyViewport();
applyProjectionMatrix();
}
}
@ -244,6 +251,7 @@ void TextureTarget::setSize(uint width, uint height) {
// Directly apply changes when we are active.
if (isActive()) {
applyViewport();
applyProjectionMatrix();
}
}
#endif // !USE_FORCED_GLES

View file

@ -81,6 +81,7 @@ protected:
void applyViewport();
GLfloat _projectionMatrix[4*4];
void applyProjectionMatrix();
private:
bool _isActive;

View file

@ -763,26 +763,6 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
// 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(_backBuffer.getProjectionMatrix()));
GL_CALL(glMatrixMode(GL_MODELVIEW));
GL_CALL(glLoadIdentity());
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
} else {
#endif
#if !USE_FORCED_GLES
ShaderMan.query(ShaderManager::kDefault)->activate(_backBuffer.getProjectionMatrix());
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
}
#endif
uint overlayWidth = width;
uint overlayHeight = height;
@ -872,6 +852,14 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
g_context.setPipeline(_pipeline);
#if !USE_FORCED_GLES
if (g_context.shadersSupported) {
ShaderMan.notifyCreate();
g_context.activePipeline->setShader(ShaderMan.query(ShaderManager::kDefault));
}
#endif
// Disable 3D properties.
GL_CALL(glDisable(GL_CULL_FACE));
GL_CALL(glDisable(GL_DEPTH_TEST));
@ -890,7 +878,7 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
// Setup scissor state accordingly.
_backBuffer.enableScissorTest(!_overlayVisible);
g_context.setFramebuffer(&_backBuffer);
g_context.activePipeline->setFramebuffer(&_backBuffer);
// Clear the whole screen for the first three frames to assure any
// leftovers are cleared.
@ -901,13 +889,6 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
// code and that requires the same alignment too.
GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 4));
#if !USE_FORCED_GLES
if (g_context.shadersSupported) {
ShaderMan.notifyCreate();
ShaderMan.query(ShaderManager::kDefault)->activate(_backBuffer.getProjectionMatrix());
}
#endif
// Refresh the output screen dimensions if some are set up.
if (_outputScreenWidth != 0 && _outputScreenHeight != 0) {
setActualScreenSize(_outputScreenWidth, _outputScreenHeight);
@ -963,9 +944,6 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
}
#endif
// Unset back buffer.
g_context.setFramebuffer(nullptr);
// Destroy rendering pipeline.
g_context.setPipeline(nullptr);
delete _pipeline;

View file

@ -124,19 +124,6 @@ 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.

View file

@ -22,9 +22,29 @@
#include "backends/graphics/opengl/pipeline.h"
#include "backends/graphics/opengl/shader.h"
#include "backends/graphics/opengl/framebuffer.h"
namespace OpenGL {
Pipeline::Pipeline()
: _activeFramebuffer(nullptr) {
}
Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
Framebuffer *oldFramebuffer = _activeFramebuffer;
if (oldFramebuffer) {
oldFramebuffer->deactivate();
}
_activeFramebuffer = framebuffer;
if (_activeFramebuffer) {
_activeFramebuffer->activate();
setProjectionMatrix(_activeFramebuffer->getProjectionMatrix());
}
return oldFramebuffer;
}
#if !USE_FORCED_GLES2
void FixedPipeline::activate() {
GL_CALL(glDisable(GL_LIGHTING));
@ -51,9 +71,21 @@ void FixedPipeline::setDrawCoordinates(const GLfloat *vertices, const GLfloat *t
GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texCoords));
GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices));
}
void FixedPipeline::setProjectionMatrix(const GLfloat *projectionMatrix) {
GL_CALL(glMatrixMode(GL_PROJECTION));
GL_CALL(glLoadMatrixf(projectionMatrix));
GL_CALL(glMatrixMode(GL_MODELVIEW));
GL_CALL(glLoadIdentity());
}
#endif // !USE_FORCED_GLES2
#if !USE_FORCED_GLES
ShaderPipeline::ShaderPipeline()
: _activeShader(nullptr) {
}
void ShaderPipeline::activate() {
GL_CALL(glEnableVertexAttribArray(kPositionAttribLocation));
GL_CALL(glEnableVertexAttribArray(kTexCoordAttribLocation));
@ -63,6 +95,17 @@ void ShaderPipeline::activate() {
}
}
Shader *ShaderPipeline::setShader(Shader *shader) {
Shader *oldShader = _activeShader;
_activeShader = shader;
if (_activeShader && _activeFramebuffer) {
_activeShader->activate(_activeFramebuffer->getProjectionMatrix());
}
return oldShader;
}
void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
GL_CALL(glVertexAttrib4f(kColorAttribLocation, r, g, b, a));
}
@ -71,6 +114,12 @@ void ShaderPipeline::setDrawCoordinates(const GLfloat *vertices, const GLfloat *
GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texCoords));
GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices));
}
void ShaderPipeline::setProjectionMatrix(const GLfloat *projectionMatrix) {
if (_activeShader) {
_activeShader->activate(projectionMatrix);
}
}
#endif // !USE_FORCED_GLES
} // End of namespace OpenGL

View file

@ -27,6 +27,11 @@
namespace OpenGL {
class Framebuffer;
#if !USE_FORCED_GLES
class Shader;
#endif
/**
* Interface for OpenGL pipeline functionality.
*
@ -35,6 +40,7 @@ namespace OpenGL {
*/
class Pipeline {
public:
Pipeline();
virtual ~Pipeline() {}
/**
@ -45,6 +51,31 @@ public:
*/
virtual void activate() = 0;
/**
* Set framebuffer to render to.
*
* Client is responsible for any memory management related to framebuffer.
*
* @param framebuffer Framebuffer to activate.
* @return Formerly active framebuffer.
*/
Framebuffer *setFramebuffer(Framebuffer *framebuffer);
#if !USE_FORCED_GLES
/**
* Set shader program.
*
* Not all pipelines support shader programs. This is method exits at this
* place for convenience only.
*
* Client is responsible for any memory management related to shader.
*
* @param shader Shader program to activate.
* @return Formerly active shader program.
*/
virtual Shader *setShader(Shader *shader) { return nullptr; }
#endif
/**
* Set modulation color.
*
@ -63,6 +94,16 @@ public:
* each vertex.
*/
virtual void setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords) = 0;
/**
* Set the projection matrix.
*
* This is intended to be only ever be used by Framebuffer subclasses.
*/
virtual void setProjectionMatrix(const GLfloat *projectionMatrix) = 0;
protected:
Framebuffer *_activeFramebuffer;
};
#if !USE_FORCED_GLES2
@ -73,17 +114,28 @@ public:
virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
virtual void setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords);
virtual void setProjectionMatrix(const GLfloat *projectionMatrix);
};
#endif // !USE_FORCED_GLES2
#if !USE_FORCED_GLES
class ShaderPipeline : public Pipeline {
public:
ShaderPipeline();
virtual void activate();
virtual Shader *setShader(Shader *shader);
virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
virtual void setDrawCoordinates(const GLfloat *vertices, const GLfloat *texCoords);
virtual void setProjectionMatrix(const GLfloat *projectionMatrix);
private:
Shader *_activeShader;
};
#endif // !USE_FORCED_GLES

View file

@ -657,7 +657,7 @@ void TextureCLUT8GPU::updateTextures() {
_paletteDirty = false;
}
// In case any data changed, do color look up and save result in _glTexture.
// In case any data changed, do color look up and store result in _target.
if (needLookUp) {
lookUpColors();
}
@ -665,10 +665,11 @@ void TextureCLUT8GPU::updateTextures() {
void TextureCLUT8GPU::lookUpColors() {
// Save old state.
GLint oldProgram = 0;
GL_CALL(glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram));
Framebuffer *oldFramebuffer = g_context.activePipeline->setFramebuffer(_target);
Framebuffer *oldFramebuffer = g_context.setFramebuffer(_target);
Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp);
Shader *oldShader = g_context.activePipeline->setShader(lookUpShader);
lookUpShader->setUniformI(_paletteLocation, 1);
// Set the palette texture.
GL_CALL(glActiveTexture(GL_TEXTURE1));
@ -679,16 +680,12 @@ void TextureCLUT8GPU::lookUpColors() {
_clut8Texture.bind();
// Do color look up.
Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp);
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.
g_context.setFramebuffer(oldFramebuffer);
GL_CALL(glUseProgram(oldProgram));
g_context.activePipeline->setShader(oldShader);
g_context.activePipeline->setFramebuffer(oldFramebuffer);
}
#endif // !USE_FORCED_GLES