From fee1aa550203c3f46ff19afbe19a7baa4771a5cd Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 20 Dec 2015 09:30:11 +0100 Subject: OPENGL: Add support for shaders with GL contexts. --- backends/graphics/opengl/context.cpp | 21 ++++ backends/graphics/opengl/opengl-defs.h | 13 +++ backends/graphics/opengl/opengl-func.h | 21 ++++ backends/graphics/opengl/opengl-graphics.cpp | 86 +++++++++----- backends/graphics/opengl/opengl-graphics.h | 4 +- backends/graphics/opengl/opengl-sys.h | 5 + backends/graphics/opengl/shader.cpp | 162 +++++++++++++++++++++++++-- backends/graphics/opengl/shader.h | 77 +++++++++++-- backends/graphics/opengl/texture.cpp | 23 ++-- 9 files changed, 358 insertions(+), 54 deletions(-) (limited to 'backends/graphics/opengl') diff --git a/backends/graphics/opengl/context.cpp b/backends/graphics/opengl/context.cpp index 764cabcbde..618be07a57 100644 --- a/backends/graphics/opengl/context.cpp +++ b/backends/graphics/opengl/context.cpp @@ -74,14 +74,35 @@ void OpenGLGraphicsManager::initializeGLContext() { const char *extString = (const char *)g_context.glGetString(GL_EXTENSIONS); +#if !USE_FORCED_GLES && !USE_FORCED_GLES2 + bool ARBShaderObjects = false; + bool ARBShadingLanguage100 = false; + bool ARBVertexShader = false; + bool ARBFragmentShader = false; +#endif + Common::StringTokenizer tokenizer(extString, " "); while (!tokenizer.empty()) { Common::String token = tokenizer.nextToken(); if (token == "GL_ARB_texture_non_power_of_two") { g_context.NPOTSupported = true; +#if !USE_FORCED_GLES && !USE_FORCED_GLES2 + } else if (token == "GL_ARB_shader_objects") { + ARBShaderObjects = true; + } else if (token == "GL_ARB_shading_language_100") { + ARBShadingLanguage100 = true; + } else if (token == "GL_ARB_vertex_shader") { + ARBVertexShader = true; + } else if (token == "GL_ARB_fragment_shader") { + ARBFragmentShader = true; +#endif } } + +#if !USE_FORCED_GLES && !USE_FORCED_GLES2 + g_context.shadersSupported = ARBShaderObjects & ARBShadingLanguage100 & ARBVertexShader & ARBFragmentShader; +#endif } } // End of namespace OpenGL diff --git a/backends/graphics/opengl/opengl-defs.h b/backends/graphics/opengl/opengl-defs.h index fe79caadd4..edcf334a0b 100644 --- a/backends/graphics/opengl/opengl-defs.h +++ b/backends/graphics/opengl/opengl-defs.h @@ -76,6 +76,12 @@ typedef float GLclampf; /* single precision float in [0,1] */ 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) +typedef void *GLhandleARB; +#else +typedef uint GLhandleARB; +#endif /* * Constants @@ -223,13 +229,20 @@ typedef char GLchar; /* Shaders */ #define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAGMENT_SHADER_ARB 0x8B30 + #define GL_VERTEX_SHADER 0x8B31 +#define GL_VERTEX_SHADER_ARB 0x8B31 /* Programs */ #define GL_COMPILE_STATUS 0x8B81 #define GL_LINK_STATUS 0x8B82 #define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 + /* Textures */ #define GL_TEXTURE0 0x84C0 diff --git a/backends/graphics/opengl/opengl-func.h b/backends/graphics/opengl/opengl-func.h index 633385a4d0..d022d00b30 100644 --- a/backends/graphics/opengl/opengl-func.h +++ b/backends/graphics/opengl/opengl-func.h @@ -116,3 +116,24 @@ GL_FUNC_DEF(void, glGetShaderInfoLog, (GLuint shader, GLsizei bufSize, GLsizei * GL_FUNC_DEF(void, glEnableVertexAttribArray, (GLuint index)); 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(void, glUniformMatrix4fvARB, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)); +GL_EXT_FUNC_DEF(void, glUniform1iARB, (GLint location, GLint v0)); +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)); +GL_EXT_FUNC_DEF(void, glVertexAttribPointerARB, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer)); +GL_EXT_FUNC_DEF(void, glVertexAttrib4fARB, (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)); +GL_EXT_FUNC_DEF(void, glEnableVertexAttribArrayARB, (GLuint index)); +#endif diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 7078aa896f..9203390489 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -55,7 +55,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager() #ifdef USE_OSD , _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr) #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES +#if !USE_FORCED_GLES , _shader(nullptr), _projectionMatrix() #endif { @@ -70,7 +70,7 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { #ifdef USE_OSD delete _osd; #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES +#if !USE_FORCED_GLES delete _shader; #endif } @@ -773,7 +773,8 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { }; #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type != kContextGLES2) { + if (g_context.type == kContextGLES + || (g_context.type == kContextGL && !g_context.shadersSupported)) { #endif #if !USE_FORCED_GLES2 GL_CALL(glMatrixMode(GL_PROJECTION)); @@ -785,7 +786,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } else { #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES +#if !USE_FORCED_GLES assert(sizeof(_projectionMatrix) == sizeof(orthoProjection)); memcpy(_projectionMatrix, orthoProjection, sizeof(_projectionMatrix)); if (_shader) { @@ -894,23 +895,32 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type != kContextGLES2) { + if (g_context.type == kContextGLES2) { #endif -#if !USE_FORCED_GLES2 - // Enable rendering with vertex and coord arrays. - GL_CALL(glEnableClientState(GL_VERTEX_ARRAY)); - GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); +#if !USE_FORCED_GL && !USE_FORCED_GLES + GL_CALL(glEnableVertexAttribArray(kPositionAttribLocation)); + GL_CALL(glEnableVertexAttribArray(kTexCoordAttribLocation)); - GL_CALL(glEnable(GL_TEXTURE_2D)); + GL_CALL(glActiveTexture(GL_TEXTURE0)); #endif #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } else { #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES - GL_CALL(glEnableVertexAttribArray(kPositionAttribLocation)); - GL_CALL(glEnableVertexAttribArray(kTexCoordAttribLocation)); +#if !USE_FORCED_GLES2 +#if !USE_FORCED_GLES + if (g_context.shadersSupported) { + GL_CALL(glEnableVertexAttribArrayARB(kPositionAttribLocation)); + GL_CALL(glEnableVertexAttribArrayARB(kTexCoordAttribLocation)); + } else { +#endif + // Enable rendering with vertex and coord arrays. + GL_CALL(glEnableClientState(GL_VERTEX_ARRAY)); + GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); +#if !USE_FORCED_GLES + } +#endif - GL_CALL(glActiveTexture(GL_TEXTURE0)); + GL_CALL(glEnable(GL_TEXTURE_2D)); #endif #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } @@ -934,19 +944,33 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def // Query information needed by textures. Texture::queryTextureInformation(); -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type == kContextGLES2) { +#if !USE_FORCED_GLES + if (!_shader) { +#if !USE_FORCED_GL && !USE_FORCED_GLES2 + if (g_context.type == kContextGLES2) { #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES - if (!_shader) { - _shader = new Shader(g_defaultVertexShader, g_defaultFragmentShader); +#if !USE_FORCED_GL + _shader = new ShaderGLES2(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); + } +#endif +#if !USE_FORCED_GL && !USE_FORCED_GLES2 } +#endif + } +#endif +#if !USE_FORCED_GLES + if (_shader) { // TODO: What do we do on failure? _shader->recreate(); _shader->activate(_projectionMatrix); -#endif -#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } #endif @@ -999,7 +1023,7 @@ void OpenGLGraphicsManager::notifyContextDestroy() { } #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES +#if !USE_FORCED_GLES if (_shader) { _shader->destroy(); } @@ -1080,16 +1104,24 @@ Texture *OpenGLGraphicsManager::createTexture(const Graphics::PixelFormat &forma void OpenGLGraphicsManager::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type != kContextGLES2) { + if (g_context.type == kContextGLES2) { #endif -#if !USE_FORCED_GLES2 - GL_CALL(glColor4f(r, g, b, a)); +#if !USE_FORCED_GL && !USE_FORCED_GLES + GL_CALL(glVertexAttrib4f(kColorAttribLocation, r, g, b, a)); #endif #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } else { #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES - GL_CALL(glVertexAttrib4f(kColorAttribLocation, r, g, b, a)); +#if !USE_FORCED_GLES2 +#if !USE_FORCED_GLES + if (g_context.shadersSupported) { + GL_CALL(glVertexAttrib4fARB(kColorAttribLocation, r, g, b, a)); + } else { +#endif + GL_CALL(glColor4f(r, g, b, a)); +#if !USE_FORCED_GLES + } +#endif #endif #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index 37ab1f8591..55e18cf7f0 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -41,7 +41,7 @@ namespace OpenGL { #define USE_OSD 1 class Texture; -#if !USE_FORCED_GL && !USE_FORCED_GLES +#if !USE_FORCED_GLES class Shader; #endif @@ -529,7 +529,7 @@ private: */ uint _scissorOverride; -#if !USE_FORCED_GL && !USE_FORCED_GLES +#if !USE_FORCED_GLES // // Shaders // diff --git a/backends/graphics/opengl/opengl-sys.h b/backends/graphics/opengl/opengl-sys.h index ad36226a57..f8acb9302c 100644 --- a/backends/graphics/opengl/opengl-sys.h +++ b/backends/graphics/opengl/opengl-sys.h @@ -92,6 +92,11 @@ struct Context { /** Whether GL_ARB_texture_non_power_of_two is available or not. */ bool NPOTSupported; +#if !USE_FORCED_GLES && !USE_FORCED_GLES2 + /** Whether shader support is available or not. */ + bool shadersSupported; +#endif + #define GL_FUNC_DEF(ret, name, param) ret (GL_CALL_CONV *name)param #define GL_EXT_FUNC_DEF GL_FUNC_DEF #include "backends/graphics/opengl/opengl-func.h" diff --git a/backends/graphics/opengl/shader.cpp b/backends/graphics/opengl/shader.cpp index 6e36307860..c28036cb4e 100644 --- a/backends/graphics/opengl/shader.cpp +++ b/backends/graphics/opengl/shader.cpp @@ -22,7 +22,7 @@ #include "backends/graphics/opengl/shader.h" -#if !USE_FORCED_GL && !USE_FORCED_GLES +#if !USE_FORCED_GLES #include "common/textconsole.h" @@ -44,7 +44,20 @@ const char *const g_defaultVertexShader = "\tgl_Position = projection * position;\n" "}\n"; -const char *const g_defaultFragmentShader = +#if !USE_FORCED_GLES2 +const char *const g_defaultFragmentShaderGL = + "varying vec2 texCoord;\n" + "varying vec4 blendColor;\n" + "\n" + "uniform sampler2D texture;\n" + "\n" + "void main(void) {\n" + "\tgl_FragColor = blendColor * texture2D(texture, texCoord);\n" + "}\n"; +#endif + +#if !USE_FORCED_GL +const char *const g_defaultFragmentShaderGLES2 = "varying lowp vec2 texCoord;\n" "varying lowp vec4 blendColor;\n" "\n" @@ -53,17 +66,146 @@ const char *const g_defaultFragmentShader = "void main(void) {\n" "\tgl_FragColor = blendColor * texture2D(texture, texCoord);\n" "}\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) { +void ShaderARB::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)); + } + _program = 0; } -void Shader::destroy() { +bool ShaderARB::recreate() { + // Make sure any old programs are destroyed properly. + destroy(); + + GLhandleARB vertexShader = compileShader(_vertex.c_str(), GL_VERTEX_SHADER_ARB); + 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(glUniformMatrix4fvARB(_projectionLocation, 1, GL_FALSE, projectionMatrix)); + + // We always use texture unit 0. + GL_CALL(glUniform1iARB(_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) { +} + +void ShaderGLES2::destroy() { GL_CALL(glDeleteProgram(_program)); _program = 0; } -bool Shader::recreate() { +bool ShaderGLES2::recreate() { // Make sure any old programs are destroyed properly. destroy(); @@ -132,7 +274,7 @@ bool Shader::recreate() { return true; } -void Shader::activate(const GLfloat *projectionMatrix) { +void ShaderGLES2::activate(const GLfloat *projectionMatrix) { // Activate program. GL_CALL(glUseProgram(_program)); @@ -143,7 +285,7 @@ void Shader::activate(const GLfloat *projectionMatrix) { GL_CALL(glUniform1i(_textureLocation, 0)); } -GLuint Shader::compileShader(const char *source, GLenum shaderType) { +GLuint ShaderGLES2::compileShader(const char *source, GLenum shaderType) { GLuint handle; GL_ASSIGN(handle, glCreateShader(shaderType)); if (!handle) { @@ -171,6 +313,8 @@ GLuint Shader::compileShader(const char *source, GLenum shaderType) { return handle; } +#endif // !!USE_FORCED_GL + } // End of namespace OpenGL -#endif // !USE_FORCED_GL && !USE_FORCED_GLES +#endif // !USE_FORCED_GLES diff --git a/backends/graphics/opengl/shader.h b/backends/graphics/opengl/shader.h index e8535e0225..8c457f8f91 100644 --- a/backends/graphics/opengl/shader.h +++ b/backends/graphics/opengl/shader.h @@ -25,7 +25,7 @@ #include "backends/graphics/opengl/opengl-sys.h" -#if !USE_FORCED_GL && !USE_FORCED_GLES +#if !USE_FORCED_GLES #include "common/str.h" @@ -38,12 +38,18 @@ enum { }; extern const char *const g_defaultVertexShader; -extern const char *const g_defaultFragmentShader; +#if !USE_FORCED_GLES2 +extern const char *const g_defaultFragmentShaderGL; +#endif +#if !USE_FORCED_GL +extern const char *const g_defaultFragmentShaderGLES2; +#endif class Shader { public: - Shader(const Common::String &vertex, const Common::String &fragment); - ~Shader() { destroy(); } + Shader(const Common::String &vertex, const Common::String &fragment) + : _vertex(vertex), _fragment(fragment) {} + virtual ~Shader() {} /** * Destroy the shader program. @@ -51,22 +57,22 @@ public: * This keeps the vertex and fragment shader sources around and thus * allows for recreating the shader on context recreation. */ - void destroy(); + virtual void destroy() = 0; /** * Recreate shader program. * * @return true on success, false on failure. */ - bool recreate(); + virtual bool recreate() = 0; /** * Make shader active. * * @param projectionMatrix Projection matrix to use. */ - void activate(const GLfloat *projectionMatrix); -private: + virtual void activate(const GLfloat *projectionMatrix) = 0; +protected: /** * Vertex shader sources. */ @@ -76,7 +82,59 @@ private: * 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() { destroy(); } + + virtual void destroy(); + + virtual bool recreate(); + virtual void activate(const GLfloat *projectionMatrix); +private: + /** + * Shader program handle. + */ + GLhandleARB _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_ARB or + * 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() { destroy(); } + + virtual void destroy(); + + virtual bool recreate(); + + virtual void activate(const GLfloat *projectionMatrix); +private: /** * Shader program handle. */ @@ -102,9 +160,10 @@ private: */ static GLuint compileShader(const char *source, GLenum shaderType); }; +#endif } // End of namespace OpenGL -#endif // !USE_FORCED_GL && !USE_FORCED_GLES +#endif // !USE_FORCED_GLES #endif diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index c8c38edbbd..0b01430728 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -196,18 +196,27 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { }; #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 - if (g_context.type != kContextGLES2) { + if (g_context.type == kContextGLES2) { #endif -#if !USE_FORCED_GLES2 - GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); - GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); +#if !USE_FORCED_GL && !USE_FORCED_GLES + GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); + GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); #endif #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } else { #endif -#if !USE_FORCED_GL && !USE_FORCED_GLES - GL_CALL(glVertexAttribPointer(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); - GL_CALL(glVertexAttribPointer(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); +#if !USE_FORCED_GLES2 +#if !USE_FORCED_GLES + if (g_context.shadersSupported) { + GL_CALL(glVertexAttribPointerARB(kTexCoordAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords)); + GL_CALL(glVertexAttribPointerARB(kPositionAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices)); + } else { +#endif + GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); + GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices)); +#if !USE_FORCED_GLES + } +#endif #endif #if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2 } -- cgit v1.2.3