From 8a3eecb73a9eb5d885e3585835db6bee738c1de5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 21 Dec 2015 06:35:13 +0100 Subject: OPENGL: Unify shader implementation for GL and GLES2. --- backends/graphics/opengl/opengl-defs.h | 8 +- backends/graphics/opengl/opengl-func.h | 50 ++++----- backends/graphics/opengl/opengl-graphics.cpp | 4 +- backends/graphics/opengl/opengl-sys.h | 12 +++ backends/graphics/opengl/shader.cpp | 155 +++------------------------ backends/graphics/opengl/shader.h | 68 ++---------- 6 files changed, 59 insertions(+), 238 deletions(-) (limited to 'backends/graphics') diff --git a/backends/graphics/opengl/opengl-defs.h b/backends/graphics/opengl/opengl-defs.h index edcf334a0b..5e9bcab6f1 100644 --- a/backends/graphics/opengl/opengl-defs.h +++ b/backends/graphics/opengl/opengl-defs.h @@ -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 */ diff --git a/backends/graphics/opengl/opengl-func.h b/backends/graphics/opengl/opengl-func.h index c85d936497..fb0877913e 100644 --- a/backends/graphics/opengl/opengl-func.h +++ b/backends/graphics/opengl/opengl-func.h @@ -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 diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 6d693a3a27..eb9eed170c 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -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 diff --git a/backends/graphics/opengl/opengl-sys.h b/backends/graphics/opengl/opengl-sys.h index bae318f393..cec1f5100d 100644 --- a/backends/graphics/opengl/opengl-sys.h +++ b/backends/graphics/opengl/opengl-sys.h @@ -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: diff --git a/backends/graphics/opengl/shader.cpp b/backends/graphics/opengl/shader.cpp index 7fdebed493..9e106a81b8 100644 --- a/backends/graphics/opengl/shader.cpp +++ b/backends/graphics/opengl/shader.cpp @@ -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 diff --git a/backends/graphics/opengl/shader.h b/backends/graphics/opengl/shader.h index 60a430214c..f9dcbb0c61 100644 --- a/backends/graphics/opengl/shader.h +++ b/backends/graphics/opengl/shader.h @@ -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); -}; -#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); + static GLshader compileShader(const char *source, GLenum shaderType); }; -#endif } // End of namespace OpenGL -- cgit v1.2.3