mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-26 12:48:16 +00:00
OPENGL: Introduce ShaderManager to handle builtin shaders.
This commit is contained in:
parent
f5f1b6eba0
commit
5498982a37
@ -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
|
||||
|
||||
|
@ -532,11 +532,6 @@ private:
|
||||
// Shaders
|
||||
//
|
||||
|
||||
/**
|
||||
* Active shader.
|
||||
*/
|
||||
Shader *_shader;
|
||||
|
||||
/**
|
||||
* Projection matrix used.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
||||
|
@ -366,7 +366,6 @@ private:
|
||||
GLfloat _clut8Vertices[4*2];
|
||||
GLfloat _projectionMatrix[4*4];
|
||||
|
||||
Shader *_lookUpShader;
|
||||
GLint _paletteLocation;
|
||||
|
||||
Graphics::Surface _clut8Data;
|
||||
|
Loading…
x
Reference in New Issue
Block a user