mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-12 14:09:28 +00:00
OPENGL: Unify shader implementation for GL and GLES2.
This commit is contained in:
parent
fc52f73050
commit
8a3eecb73a
@ -77,12 +77,18 @@ typedef double GLdouble; /* double precision float */
|
||||
typedef double GLclampd; /* double precision float in [0,1] */
|
||||
typedef char GLchar;
|
||||
typedef GLchar GLcharARB;
|
||||
#if defined(__APPLE__) || defined(MACOSX)
|
||||
#if defined(MACOSX)
|
||||
typedef void *GLhandleARB;
|
||||
#else
|
||||
typedef uint GLhandleARB;
|
||||
#endif
|
||||
|
||||
// This is an addition from us to alias ARB shader object extensions to
|
||||
// OpenGL (ES) 2.0 style functions. It only works when GLhandleARB and GLuint
|
||||
// are type compatible.
|
||||
typedef GLhandleARB GLprogram;
|
||||
typedef GLhandleARB GLshader;
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
@ -110,44 +110,30 @@ GL_FUNC_2_DEF(void, glUniform1i, glUniform1iARB, (GLint location, GLint v0));
|
||||
GL_FUNC_2_DEF(void, glUniformMatrix4fv, glUniformMatrix4fvARB, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value));
|
||||
GL_FUNC_2_DEF(void, glVertexAttrib4f, glVertexAttrib4fARB, (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w));
|
||||
GL_FUNC_2_DEF(void, glVertexAttribPointer, glVertexAttribPointerARB, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer));
|
||||
|
||||
GL_FUNC_2_DEF(GLprogram, glCreateProgram, glCreateProgramObjectARB, ());
|
||||
GL_FUNC_2_DEF(void, glDeleteProgram, glDeleteObjectARB, (GLprogram program));
|
||||
GL_FUNC_2_DEF(void, glAttachShader, glAttachObjectARB, (GLprogram program, GLshader shader));
|
||||
GL_FUNC_2_DEF(void, glDetachShader, glDetachObjectARB, (GLprogram program, GLshader shader));
|
||||
GL_FUNC_2_DEF(void, glLinkProgram, glLinkProgramARB, (GLprogram program));
|
||||
GL_FUNC_2_DEF(void, glUseProgram, glUseProgramObjectARB, (GLprogram program));
|
||||
GL_FUNC_2_DEF(void, glGetProgramiv, glGetObjectParameterivARB, (GLprogram program, GLenum pname, GLint *params));
|
||||
GL_FUNC_2_DEF(void, glGetProgramInfoLog, glGetInfoLogARB, (GLprogram program, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
GL_FUNC_2_DEF(void, glBindAttribLocation, glBindAttribLocationARB, (GLprogram program, GLuint index, const GLchar *name));
|
||||
GL_FUNC_2_DEF(GLint, glGetUniformLocation, glGetUniformLocationARB, (GLprogram program, const GLchar *name));
|
||||
|
||||
GL_FUNC_2_DEF(GLshader, glCreateShader, glCreateShaderObjectARB, (GLenum type));
|
||||
GL_FUNC_2_DEF(void, glDeleteShader, glDeleteObjectARB, (GLshader shader));
|
||||
GL_FUNC_2_DEF(void, glGetShaderiv, glGetObjectParameterivARB, (GLshader shader, GLenum pname, GLint *params));
|
||||
GL_FUNC_2_DEF(void, glGetShaderInfoLog, glGetInfoLogARB, (GLshader shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
GL_FUNC_2_DEF(void, glShaderSource, glShaderSourceARB, (GLshader shader, GLsizei count, const GLchar *const *string, const GLint *length));
|
||||
GL_FUNC_2_DEF(void, glCompileShader, glCompileShaderARB, (GLshader shader));
|
||||
#endif
|
||||
|
||||
#if !USE_FORCED_GL && !USE_FORCED_GLES
|
||||
GL_FUNC_DEF(void, glDeleteProgram, (GLuint program));
|
||||
GL_FUNC_DEF(void, glDeleteShader, (GLuint shader));
|
||||
GL_FUNC_DEF(GLuint, glCreateProgram, ());
|
||||
GL_FUNC_DEF(void, glAttachShader, (GLuint program, GLuint shader));
|
||||
GL_FUNC_DEF(void, glBindAttribLocation, (GLuint program, GLuint index, const GLchar *name));
|
||||
GL_FUNC_DEF(void, glLinkProgram, (GLuint program));
|
||||
GL_FUNC_DEF(void, glDetachShader, (GLuint program, GLuint shader));
|
||||
GL_FUNC_DEF(void, glGetProgramiv, (GLuint program, GLenum pname, GLint *params));
|
||||
GL_FUNC_DEF(void, glGetProgramInfoLog, (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
GL_FUNC_DEF(GLint, glGetUniformLocation, (GLuint program, const GLchar *name));
|
||||
GL_FUNC_DEF(void, glUseProgram, (GLuint program));
|
||||
GL_FUNC_DEF(GLuint, glCreateShader, (GLenum type));
|
||||
GL_FUNC_DEF(void, glShaderSource, (GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length));
|
||||
GL_FUNC_DEF(void, glCompileShader, (GLuint shader));
|
||||
GL_FUNC_DEF(void, glGetShaderiv, (GLuint shader, GLenum pname, GLint *params));
|
||||
GL_FUNC_DEF(void, glGetShaderInfoLog, (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
GL_FUNC_DEF(void, glActiveTexture, (GLenum texture));
|
||||
#endif
|
||||
|
||||
#if !USE_FORCED_GLES && !USE_FORCED_GLES2
|
||||
GL_EXT_FUNC_DEF(void, glDeleteObjectARB, (GLhandleARB obj));
|
||||
GL_EXT_FUNC_DEF(GLhandleARB, glCreateProgramObjectARB, ());
|
||||
GL_EXT_FUNC_DEF(void, glAttachObjectARB, (GLhandleARB containerObj, GLhandleARB obj));
|
||||
GL_EXT_FUNC_DEF(void, glBindAttribLocationARB, (GLhandleARB programObj, GLuint index, const GLcharARB *name));
|
||||
GL_EXT_FUNC_DEF(void, glLinkProgramARB, (GLhandleARB programObj));
|
||||
GL_EXT_FUNC_DEF(void, glDetachObjectARB, (GLhandleARB containerObj, GLhandleARB attachedObj));
|
||||
GL_EXT_FUNC_DEF(void, glGetObjectParameterivARB, (GLhandleARB obj, GLenum pname, GLint *params));
|
||||
GL_EXT_FUNC_DEF(GLint, glGetUniformLocationARB, (GLhandleARB programObj, const GLcharARB *name));
|
||||
GL_EXT_FUNC_DEF(void, glGetInfoLogARB, (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog));
|
||||
GL_EXT_FUNC_DEF(void, glUseProgramObjectARB, (GLhandleARB programObj));
|
||||
GL_EXT_FUNC_DEF(GLhandleARB, glCreateShaderObjectARB, (GLenum shaderType));
|
||||
GL_EXT_FUNC_DEF(void, glShaderSourceARB, (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length));
|
||||
GL_EXT_FUNC_DEF(void, glCompileShaderARB, (GLhandleARB shaderObj));
|
||||
#endif
|
||||
|
||||
#ifdef DEFINED_GL_EXT_FUNC_DEF
|
||||
#undef DEFINED_GL_EXT_FUNC_DEF
|
||||
#undef GL_EXT_FUNC_DEF
|
||||
|
@ -908,14 +908,14 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
|
||||
if (g_context.type == kContextGLES2) {
|
||||
#endif
|
||||
#if !USE_FORCED_GL
|
||||
_shader = new ShaderGLES2(g_defaultVertexShader, g_defaultFragmentShaderGLES2);
|
||||
_shader = new Shader(g_defaultVertexShader, g_defaultFragmentShaderGLES2);
|
||||
#endif
|
||||
#if !USE_FORCED_GL && !USE_FORCED_GLES2
|
||||
} else {
|
||||
#endif
|
||||
#if !USE_FORCED_GLES2
|
||||
if (g_context.shadersSupported) {
|
||||
_shader = new ShaderARB(g_defaultVertexShader, g_defaultFragmentShaderGL);
|
||||
_shader = new Shader(g_defaultVertexShader, g_defaultFragmentShaderGL);
|
||||
}
|
||||
#endif
|
||||
#if !USE_FORCED_GL && !USE_FORCED_GLES2
|
||||
|
@ -30,6 +30,18 @@
|
||||
#include "backends/platform/sdl/sdl-sys.h"
|
||||
#endif
|
||||
|
||||
// On OS X we only support GL contexts. The reason is that Apple's GL interface
|
||||
// uses "void *" for GLhandleARB which is not type compatible with GLint. This
|
||||
// kills our aliasing trick for extension functions and thus would force us to
|
||||
// supply two different Shader class implementations or introduce other
|
||||
// wrappers. OS X only supports GL contexts right now anyway (at least
|
||||
// according to SDL2 sources), thus it is not much of an issue.
|
||||
#if defined(MACOSX) && (!defined(USE_GLES_MODE) || USE_GLES_MODE != 0)
|
||||
//#warning "Only forced OpenGL mode is supported on Mac OS X. Overriding settings."
|
||||
#undef USE_GLES_MODE
|
||||
#define USE_GLES_MODE 0
|
||||
#endif
|
||||
|
||||
// We allow to force GL or GLES modes on compile time.
|
||||
// For this the USE_GLES_MODE define is used. The following values represent
|
||||
// the given selection choices:
|
||||
|
@ -68,166 +68,39 @@ const char *const g_defaultFragmentShaderGLES2 =
|
||||
"}\n";
|
||||
#endif
|
||||
|
||||
#if !USE_FORCED_GLES2
|
||||
|
||||
ShaderARB::ShaderARB(const Common::String &vertex, const Common::String &fragment)
|
||||
: Shader(vertex, fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
|
||||
Shader::Shader(const Common::String &vertex, const Common::String &fragment)
|
||||
: _vertex(vertex), _fragment(fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
|
||||
}
|
||||
|
||||
ShaderARB::~ShaderARB() {
|
||||
Shader::~Shader() {
|
||||
// According to extension specification glDeleteObjectARB silently ignores
|
||||
// 0. However, with nVidia drivers this can cause GL_INVALID_VALUE, thus
|
||||
// we do not call it with 0 as parameter to avoid warnings.
|
||||
if (_program) {
|
||||
GL_CALL_SAFE(glDeleteObjectARB, (_program));
|
||||
GL_CALL_SAFE(glDeleteProgram, (_program));
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderARB::destroy() {
|
||||
void Shader::destroy() {
|
||||
// According to extension specification glDeleteObjectARB silently ignores
|
||||
// 0. However, with nVidia drivers this can cause GL_INVALID_VALUE, thus
|
||||
// we do not call it with 0 as parameter to avoid warnings.
|
||||
if (_program) {
|
||||
GL_CALL(glDeleteObjectARB(_program));
|
||||
GL_CALL(glDeleteProgram(_program));
|
||||
_program = 0;
|
||||
}
|
||||
_program = 0;
|
||||
}
|
||||
|
||||
bool ShaderARB::recreate() {
|
||||
bool Shader::recreate() {
|
||||
// Make sure any old programs are destroyed properly.
|
||||
destroy();
|
||||
|
||||
GLhandleARB vertexShader = compileShader(_vertex.c_str(), GL_VERTEX_SHADER_ARB);
|
||||
GLshader vertexShader = compileShader(_vertex.c_str(), GL_VERTEX_SHADER);
|
||||
if (!vertexShader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GLhandleARB fragmentShader = compileShader(_fragment.c_str(), GL_FRAGMENT_SHADER_ARB);
|
||||
if (!fragmentShader) {
|
||||
GL_CALL(glDeleteObjectARB(vertexShader));
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_ASSIGN(_program, glCreateProgramObjectARB());
|
||||
if (!_program) {
|
||||
GL_CALL(glDeleteObjectARB(vertexShader));
|
||||
GL_CALL(glDeleteObjectARB(fragmentShader));
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_CALL(glAttachObjectARB(_program, vertexShader));
|
||||
GL_CALL(glAttachObjectARB(_program, fragmentShader));
|
||||
|
||||
GL_CALL(glBindAttribLocationARB(_program, kPositionAttribLocation, "position"));
|
||||
GL_CALL(glBindAttribLocationARB(_program, kTexCoordAttribLocation, "texCoordIn"));
|
||||
GL_CALL(glBindAttribLocationARB(_program, kColorAttribLocation, "blendColorIn"));
|
||||
|
||||
GL_CALL(glLinkProgramARB(_program));
|
||||
|
||||
GL_CALL(glDetachObjectARB(_program, fragmentShader));
|
||||
GL_CALL(glDeleteObjectARB(fragmentShader));
|
||||
|
||||
GL_CALL(glDetachObjectARB(_program, vertexShader));
|
||||
GL_CALL(glDeleteObjectARB(vertexShader));
|
||||
|
||||
GLint result;
|
||||
GL_CALL(glGetObjectParameterivARB(_program, GL_OBJECT_LINK_STATUS_ARB, &result));
|
||||
if (result == GL_FALSE) {
|
||||
GLint logSize;
|
||||
GL_CALL(glGetObjectParameterivARB(_program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logSize));
|
||||
|
||||
GLchar *log = new GLchar[logSize];
|
||||
GL_CALL(glGetInfoLogARB(_program, logSize, nullptr, log));
|
||||
warning("Could not link shader: \"%s\"", log);
|
||||
delete[] log;
|
||||
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_ASSIGN(_projectionLocation, glGetUniformLocationARB(_program, "projection"));
|
||||
if (_projectionLocation == -1) {
|
||||
warning("Shader misses \"projection\" uniform.");
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_ASSIGN(_textureLocation, glGetUniformLocationARB(_program, "texture"));
|
||||
if (_textureLocation == -1) {
|
||||
warning("Shader misses \"texture\" uniform.");
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderARB::activate(const GLfloat *projectionMatrix) {
|
||||
// Activate program.
|
||||
GL_CALL(glUseProgramObjectARB(_program));
|
||||
|
||||
// Set projection matrix.
|
||||
GL_CALL(glUniformMatrix4fv(_projectionLocation, 1, GL_FALSE, projectionMatrix));
|
||||
|
||||
// We always use texture unit 0.
|
||||
GL_CALL(glUniform1i(_textureLocation, 0));
|
||||
}
|
||||
|
||||
GLhandleARB ShaderARB::compileShader(const char *source, GLenum shaderType) {
|
||||
GLuint handle;
|
||||
GL_ASSIGN(handle, glCreateShaderObjectARB(shaderType));
|
||||
if (!handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GL_CALL(glShaderSourceARB(handle, 1, &source, nullptr));
|
||||
GL_CALL(glCompileShaderARB(handle));
|
||||
|
||||
GLint result;
|
||||
GL_CALL(glGetObjectParameterivARB(handle, GL_OBJECT_COMPILE_STATUS_ARB, &result));
|
||||
if (result == GL_FALSE) {
|
||||
GLint logSize;
|
||||
GL_CALL(glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logSize));
|
||||
|
||||
GLchar *log = new GLchar[logSize];
|
||||
GL_CALL(glGetInfoLogARB(handle, logSize, nullptr, log));
|
||||
warning("Could not compile shader \"%s\": \"%s\"", source, log);
|
||||
delete[] log;
|
||||
|
||||
GL_CALL(glDeleteObjectARB(handle));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
#endif // !USE_FORCED_GLES2
|
||||
|
||||
#if !USE_FORCED_GL
|
||||
|
||||
ShaderGLES2::ShaderGLES2(const Common::String &vertex, const Common::String &fragment)
|
||||
: Shader(vertex, fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
|
||||
}
|
||||
|
||||
ShaderGLES2::~ShaderGLES2() {
|
||||
GL_CALL_SAFE(glDeleteProgram, (_program));
|
||||
}
|
||||
|
||||
void ShaderGLES2::destroy() {
|
||||
GL_CALL(glDeleteProgram(_program));
|
||||
_program = 0;
|
||||
}
|
||||
|
||||
bool ShaderGLES2::recreate() {
|
||||
// Make sure any old programs are destroyed properly.
|
||||
destroy();
|
||||
|
||||
GLuint vertexShader = compileShader(_vertex.c_str(), GL_VERTEX_SHADER);
|
||||
if (!vertexShader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint fragmentShader = compileShader(_fragment.c_str(), GL_FRAGMENT_SHADER);
|
||||
GLshader fragmentShader = compileShader(_fragment.c_str(), GL_FRAGMENT_SHADER);
|
||||
if (!fragmentShader) {
|
||||
GL_CALL(glDeleteShader(vertexShader));
|
||||
return false;
|
||||
@ -287,7 +160,7 @@ bool ShaderGLES2::recreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderGLES2::activate(const GLfloat *projectionMatrix) {
|
||||
void Shader::activate(const GLfloat *projectionMatrix) {
|
||||
// Activate program.
|
||||
GL_CALL(glUseProgram(_program));
|
||||
|
||||
@ -298,8 +171,8 @@ void ShaderGLES2::activate(const GLfloat *projectionMatrix) {
|
||||
GL_CALL(glUniform1i(_textureLocation, 0));
|
||||
}
|
||||
|
||||
GLuint ShaderGLES2::compileShader(const char *source, GLenum shaderType) {
|
||||
GLuint handle;
|
||||
GLshader Shader::compileShader(const char *source, GLenum shaderType) {
|
||||
GLshader handle;
|
||||
GL_ASSIGN(handle, glCreateShader(shaderType));
|
||||
if (!handle) {
|
||||
return 0;
|
||||
@ -326,8 +199,6 @@ GLuint ShaderGLES2::compileShader(const char *source, GLenum shaderType) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
#endif // !!USE_FORCED_GL
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
@ -47,9 +47,8 @@ extern const char *const g_defaultFragmentShaderGLES2;
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
Shader(const Common::String &vertex, const Common::String &fragment)
|
||||
: _vertex(vertex), _fragment(fragment) {}
|
||||
virtual ~Shader() {}
|
||||
Shader(const Common::String &vertex, const Common::String &fragment);
|
||||
~Shader();
|
||||
|
||||
/**
|
||||
* Destroy the shader program.
|
||||
@ -57,21 +56,21 @@ public:
|
||||
* This keeps the vertex and fragment shader sources around and thus
|
||||
* allows for recreating the shader on context recreation.
|
||||
*/
|
||||
virtual void destroy() = 0;
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Recreate shader program.
|
||||
*
|
||||
* @return true on success, false on failure.
|
||||
*/
|
||||
virtual bool recreate() = 0;
|
||||
bool recreate();
|
||||
|
||||
/**
|
||||
* Make shader active.
|
||||
*
|
||||
* @param projectionMatrix Projection matrix to use.
|
||||
*/
|
||||
virtual void activate(const GLfloat *projectionMatrix) = 0;
|
||||
void activate(const GLfloat *projectionMatrix);
|
||||
protected:
|
||||
/**
|
||||
* Vertex shader sources.
|
||||
@ -82,24 +81,11 @@ protected:
|
||||
* Fragment shader sources.
|
||||
*/
|
||||
const Common::String _fragment;
|
||||
};
|
||||
|
||||
#if !USE_FORCED_GLES2
|
||||
class ShaderARB : public Shader {
|
||||
public:
|
||||
ShaderARB(const Common::String &vertex, const Common::String &fragment);
|
||||
virtual ~ShaderARB();
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
virtual bool recreate();
|
||||
|
||||
virtual void activate(const GLfloat *projectionMatrix);
|
||||
private:
|
||||
/**
|
||||
* Shader program handle.
|
||||
*/
|
||||
GLhandleARB _program;
|
||||
GLprogram _program;
|
||||
|
||||
/**
|
||||
* Location of the matrix uniform in the shader program.
|
||||
@ -119,48 +105,8 @@ private:
|
||||
* GL_VERTEX_SHADER_ARB)
|
||||
* @return The shader object or 0 on failure.
|
||||
*/
|
||||
static GLhandleARB compileShader(const char *source, GLenum shaderType);
|
||||
static GLshader compileShader(const char *source, GLenum shaderType);
|
||||
};
|
||||
#endif // !USE_FORCED_GLES2
|
||||
|
||||
#if !USE_FORCED_GL
|
||||
class ShaderGLES2 : public Shader {
|
||||
public:
|
||||
ShaderGLES2(const Common::String &vertex, const Common::String &fragment);
|
||||
virtual ~ShaderGLES2();
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
virtual bool recreate();
|
||||
|
||||
virtual void activate(const GLfloat *projectionMatrix);
|
||||
private:
|
||||
/**
|
||||
* Shader program handle.
|
||||
*/
|
||||
GLuint _program;
|
||||
|
||||
/**
|
||||
* Location of the matrix uniform in the shader program.
|
||||
*/
|
||||
GLint _projectionLocation;
|
||||
|
||||
/**
|
||||
* Location of the texture sampler location in the shader program.
|
||||
*/
|
||||
GLint _textureLocation;
|
||||
|
||||
/**
|
||||
* Compile a vertex or fragment shader.
|
||||
*
|
||||
* @param source Sources to the shader.
|
||||
* @param shaderType Type of shader to compile (GL_FRAGMENT_SHADER or
|
||||
* GL_VERTEX_SHADER)
|
||||
* @return The shader object or 0 on failure.
|
||||
*/
|
||||
static GLuint compileShader(const char *source, GLenum shaderType);
|
||||
};
|
||||
#endif
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user