aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics/opengl
diff options
context:
space:
mode:
authorJohannes Schickel2015-12-20 09:30:11 +0100
committerJohannes Schickel2016-03-16 20:29:25 +0100
commitfee1aa550203c3f46ff19afbe19a7baa4771a5cd (patch)
tree86f44f6b8f838f196eb2db5e7e824353c47c7c48 /backends/graphics/opengl
parent19abd8ccbba339c2ea9691ef017a447b7c47701e (diff)
downloadscummvm-rg350-fee1aa550203c3f46ff19afbe19a7baa4771a5cd.tar.gz
scummvm-rg350-fee1aa550203c3f46ff19afbe19a7baa4771a5cd.tar.bz2
scummvm-rg350-fee1aa550203c3f46ff19afbe19a7baa4771a5cd.zip
OPENGL: Add support for shaders with GL contexts.
Diffstat (limited to 'backends/graphics/opengl')
-rw-r--r--backends/graphics/opengl/context.cpp21
-rw-r--r--backends/graphics/opengl/opengl-defs.h13
-rw-r--r--backends/graphics/opengl/opengl-func.h21
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp86
-rw-r--r--backends/graphics/opengl/opengl-graphics.h4
-rw-r--r--backends/graphics/opengl/opengl-sys.h5
-rw-r--r--backends/graphics/opengl/shader.cpp162
-rw-r--r--backends/graphics/opengl/shader.h77
-rw-r--r--backends/graphics/opengl/texture.cpp23
9 files changed, 358 insertions, 54 deletions
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
}