OPENGL: Introduce ShaderManager to handle builtin shaders.

This commit is contained in:
Johannes Schickel 2016-01-04 07:07:37 +01:00
parent f5f1b6eba0
commit 5498982a37
6 changed files with 106 additions and 54 deletions

View File

@ -58,7 +58,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
, _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr)
#endif
#if !USE_FORCED_GLES
, _shader(nullptr), _projectionMatrix()
, _projectionMatrix()
#endif
{
memset(_gamePalette, 0, sizeof(_gamePalette));
@ -73,7 +73,7 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
delete _osd;
#endif
#if !USE_FORCED_GLES
delete _shader;
ShaderManager::destroy();
#endif
}
@ -790,9 +790,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
#if !USE_FORCED_GLES
assert(sizeof(_projectionMatrix) == sizeof(orthoProjection));
memcpy(_projectionMatrix, orthoProjection, sizeof(_projectionMatrix));
if (_shader) {
_shader->activate(_projectionMatrix);
}
ShaderMan.query(ShaderManager::kDefault)->activate(_projectionMatrix);
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
}
@ -916,18 +914,9 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 4));
#if !USE_FORCED_GLES
if (!_shader) {
if (g_context.shadersSupported) {
_shader = new Shader(g_defaultVertexShader, g_defaultFragmentShader);
}
}
#endif
#if !USE_FORCED_GLES
if (_shader) {
// TODO: What do we do on failure?
_shader->recreate();
_shader->activate(_projectionMatrix);
if (g_context.shadersSupported) {
ShaderMan.notifyCreate();
ShaderMan.query(ShaderManager::kDefault)->activate(_projectionMatrix);
}
#endif
@ -981,8 +970,8 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
#endif
#if !USE_FORCED_GLES
if (_shader) {
_shader->destroy();
if (g_context.shadersSupported) {
ShaderMan.notifyDestroy();
}
#endif

View File

@ -532,11 +532,6 @@ private:
// Shaders
//
/**
* Active shader.
*/
Shader *_shader;
/**
* Projection matrix used.
*/

View File

@ -27,8 +27,14 @@
#include "common/textconsole.h"
#include "common/util.h"
namespace Common {
DECLARE_SINGLETON(OpenGL::ShaderManager);
}
namespace OpenGL {
namespace {
const char *const g_defaultVertexShader =
"attribute vec4 position;\n"
"attribute vec2 texCoordIn;\n"
@ -55,7 +61,20 @@ const char *const g_defaultFragmentShader =
"\tgl_FragColor = blendColor * texture2D(texture, texCoord);\n"
"}\n";
namespace {
const char *const g_lookUpFragmentShader =
"varying vec2 texCoord;\n"
"varying vec4 blendColor;\n"
"\n"
"uniform sampler2D texture;\n"
"uniform sampler2D palette;\n"
"\n"
"const float adjustFactor = 255.0 / 256.0 + 1.0 / (2.0 * 256.0);"
"\n"
"void main(void) {\n"
"\tvec4 index = texture2D(texture, texCoord);\n"
"\tgl_FragColor = blendColor * texture2D(palette, vec2(index.a * adjustFactor, 0.0));\n"
"}\n";
// Taken from: https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_03#OpenGL_ES_2_portability
const char *const g_precisionDefines =
@ -219,6 +238,38 @@ GLshader Shader::compileShader(const char *source, GLenum shaderType) {
return handle;
}
ShaderManager::ShaderManager() {
_builtIn[kDefault] = new Shader(g_defaultVertexShader, g_defaultFragmentShader);
_builtIn[kCLUT8LookUp] = new Shader(g_defaultVertexShader, g_lookUpFragmentShader);
}
ShaderManager::~ShaderManager() {
for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) {
delete _builtIn[i];
}
}
void ShaderManager::notifyDestroy() {
for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) {
_builtIn[i]->destroy();
}
}
void ShaderManager::notifyCreate() {
for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) {
_builtIn[i]->recreate();
}
}
Shader *ShaderManager::query(ShaderUsage shader) const {
if (shader == kMaxUsages) {
warning("OpenGL: ShaderManager::query used with kMaxUsages");
return nullptr;
}
return _builtIn[shader];
}
} // End of namespace OpenGL
#endif // !USE_FORCED_GLES

View File

@ -28,6 +28,7 @@
#if !USE_FORCED_GLES
#include "common/str.h"
#include "common/singleton.h"
namespace OpenGL {
@ -37,9 +38,6 @@ enum {
kColorAttribLocation = 2
};
extern const char *const g_defaultVertexShader;
extern const char *const g_defaultFragmentShader;
class Shader {
public:
Shader(const Common::String &vertex, const Common::String &fragment);
@ -121,8 +119,47 @@ protected:
static GLshader compileShader(const char *source, GLenum shaderType);
};
class ShaderManager : public Common::Singleton<ShaderManager> {
public:
enum ShaderUsage {
/** Default shader implementing the GL fixed-function pipeline. */
kDefault = 0,
/** CLUT8 look up shader. */
kCLUT8LookUp,
/** Number of built-in shaders. Should not be used for query. */
kMaxUsages
};
/**
* Notify shader manager about context destruction.
*/
void notifyDestroy();
/**
* Notify shader manager about context creation.
*/
void notifyCreate();
/**
* Query a built-in shader.
*/
Shader *query(ShaderUsage shader) const;
private:
friend class Common::Singleton<SingletonBaseType>;
ShaderManager();
~ShaderManager();
Shader *_builtIn[kMaxUsages];
};
} // End of namespace OpenGL
/** Shortcut for accessing the font manager. */
#define ShaderMan (OpenGL::ShaderManager::instance())
#endif // !USE_FORCED_GLES
#endif

View File

@ -506,21 +506,6 @@ void TextureRGB555::updateTexture() {
#endif // !USE_FORCED_GL
#if !USE_FORCED_GLES
namespace {
const char *const g_lookUpFragmentShader =
"varying vec2 texCoord;\n"
"varying vec4 blendColor;\n"
"\n"
"uniform sampler2D texture;\n"
"uniform sampler2D palette;\n"
"\n"
"const float adjustFactor = 255.0 / 256.0 + 1.0 / (2.0 * 256.0);"
"\n"
"void main(void) {\n"
"\tvec4 index = texture2D(texture, texCoord);\n"
"\tgl_FragColor = blendColor * texture2D(palette, vec2(index.a * adjustFactor, 0.0));\n"
"}\n";
} // End of anonymous namespace
// _clut8Texture needs 8 bits internal precision, otherwise graphics glitches
// can occur. GL_ALPHA does not have any internal precision requirements.
@ -532,20 +517,17 @@ TextureCLUT8GPU::TextureCLUT8GPU()
_paletteTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE),
_glTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE),
_glFBO(0), _clut8Vertices(), _projectionMatrix(),
_lookUpShader(nullptr), _paletteLocation(-1),
_paletteLocation(-1),
_clut8Data(), _userPixelData(), _palette(), _paletteDirty(false) {
// Allocate space for 256 colors.
_paletteTexture.setSize(256, 1);
_lookUpShader = new Shader(g_defaultVertexShader, g_lookUpFragmentShader);
_lookUpShader->recreate();
_paletteLocation = _lookUpShader->getUniformLocation("palette");
_paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette");
setupFBO();
}
TextureCLUT8GPU::~TextureCLUT8GPU() {
delete _lookUpShader;
GL_CALL_SAFE(glDeleteFramebuffers, (1, &_glFBO));
_clut8Data.free();
}
@ -554,7 +536,6 @@ void TextureCLUT8GPU::destroy() {
_clut8Texture.destroy();
_paletteTexture.destroy();
_glTexture.destroy();
_lookUpShader->destroy();
GL_CALL(glDeleteFramebuffers(1, &_glFBO));
_glFBO = 0;
@ -564,8 +545,7 @@ void TextureCLUT8GPU::recreate() {
_clut8Texture.create();
_paletteTexture.create();
_glTexture.create();
_lookUpShader->recreate();
_paletteLocation = _lookUpShader->getUniformLocation("palette");
_paletteLocation = ShaderMan.query(ShaderManager::kCLUT8LookUp)->getUniformLocation("palette");
setupFBO();
// In case image date exists assure it will be completely refreshed next
@ -743,8 +723,9 @@ void TextureCLUT8GPU::lookUpColors() {
_clut8Texture.bind();
// Do color look up.
_lookUpShader->activate(_projectionMatrix);
_lookUpShader->setUniformI(_paletteLocation, 1);
Shader *lookUpShader = ShaderMan.query(ShaderManager::kCLUT8LookUp);
lookUpShader->activate(_projectionMatrix);
lookUpShader->setUniformI(_paletteLocation, 1);
g_context.activePipeline->setDrawCoordinates(_clut8Vertices, _clut8Texture.getTexCoords());
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));

View File

@ -366,7 +366,6 @@ private:
GLfloat _clut8Vertices[4*2];
GLfloat _projectionMatrix[4*4];
Shader *_lookUpShader;
GLint _paletteLocation;
Graphics::Surface _clut8Data;