aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
Diffstat (limited to 'backends')
-rw-r--r--backends/graphics/opengl/context.cpp2
-rw-r--r--backends/graphics/opengl/opengl-defs.h17
-rw-r--r--backends/graphics/opengl/opengl-func.h25
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp125
-rw-r--r--backends/graphics/opengl/opengl-graphics.h31
-rw-r--r--backends/graphics/opengl/opengl-sys.h12
-rw-r--r--backends/graphics/opengl/shader.cpp176
-rw-r--r--backends/graphics/opengl/shader.h110
-rw-r--r--backends/graphics/opengl/texture.cpp21
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp20
-rw-r--r--backends/module.mk1
11 files changed, 509 insertions, 31 deletions
diff --git a/backends/graphics/opengl/context.cpp b/backends/graphics/opengl/context.cpp
index 0077cc2746..0944e05f7c 100644
--- a/backends/graphics/opengl/context.cpp
+++ b/backends/graphics/opengl/context.cpp
@@ -44,6 +44,8 @@ void OpenGLGraphicsManager::setContextType(ContextType type) {
type = kContextGL;
#elif USE_FORCED_GLES
type = kContextGLES;
+#elif USE_FORCED_GLES2
+ type = kContextGLES2;
#endif
g_context.type = type;
diff --git a/backends/graphics/opengl/opengl-defs.h b/backends/graphics/opengl/opengl-defs.h
index 4b82d7edd7..fe79caadd4 100644
--- a/backends/graphics/opengl/opengl-defs.h
+++ b/backends/graphics/opengl/opengl-defs.h
@@ -75,11 +75,16 @@ typedef float GLfloat; /* single precision float */
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;
/*
* Constants
*/
+/* Boolean constants */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
/* StringName */
#define GL_VENDOR 0x1F00
#define GL_RENDERER 0x1F01
@@ -216,4 +221,16 @@ typedef double GLclampd; /* double precision float in [0,1] */
#define GL_TRIANGLE_STRIP 0x0005
#define GL_TRIANGLE_FAN 0x0006
+/* Shaders */
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+
+/* Programs */
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_INFO_LOG_LENGTH 0x8B84
+
+/* Textures */
+#define GL_TEXTURE0 0x84C0
+
#endif
diff --git a/backends/graphics/opengl/opengl-func.h b/backends/graphics/opengl/opengl-func.h
index d13dece1ea..633385a4d0 100644
--- a/backends/graphics/opengl/opengl-func.h
+++ b/backends/graphics/opengl/opengl-func.h
@@ -91,3 +91,28 @@ GL_FUNC_DEF(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count));
GL_FUNC_DEF(void, glTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels));
GL_FUNC_DEF(const GLubyte *, glGetString, (GLenum name));
GL_FUNC_DEF(GLenum, glGetError, ());
+
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+GL_FUNC_DEF(void, glVertexAttrib4f, (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w));
+GL_FUNC_DEF(void, glVertexAttribPointer, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer));
+GL_FUNC_DEF(void, glUniformMatrix4fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value));
+GL_FUNC_DEF(void, glUniform1i, (GLint location, GLint v0));
+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, glEnableVertexAttribArray, (GLuint index));
+GL_FUNC_DEF(void, glActiveTexture, (GLenum texture));
+#endif
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 15e6f40271..1b20a31363 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -23,6 +23,7 @@
#include "backends/graphics/opengl/opengl-graphics.h"
#include "backends/graphics/opengl/texture.h"
+#include "backends/graphics/opengl/shader.h"
#include "common/textconsole.h"
#include "common/translation.h"
@@ -54,6 +55,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
#ifdef USE_OSD
, _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr)
#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+ , _shader(nullptr), _projectionMatrix()
+#endif
{
memset(_gamePalette, 0, sizeof(_gamePalette));
g_context.reset(true);
@@ -66,6 +70,9 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
#ifdef USE_OSD
delete _osd;
#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+ delete _shader;
+#endif
}
bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
@@ -418,13 +425,13 @@ void OpenGLGraphicsManager::updateScreen() {
}
// Set the OSD transparency.
- GL_CALL(glColor4f(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f));
+ setColor(1.0f, 1.0f, 1.0f, _osdAlpha / 100.0f);
// Draw the OSD texture.
_osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight);
// Reset color.
- GL_CALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f));
+ setColor(1.0f, 1.0f, 1.0f, 1.0f);
}
#endif
@@ -765,11 +772,29 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
-1.0f , 1.0f , 0.0f, 1.0f
};
- GL_CALL(glMatrixMode(GL_PROJECTION));
- GL_CALL(glLoadMatrixf(orthoProjection));
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ if (g_context.type != kContextGLES2) {
+#endif
+#if !USE_FORCED_GLES2
+ GL_CALL(glMatrixMode(GL_PROJECTION));
+ GL_CALL(glLoadMatrixf(orthoProjection));
- GL_CALL(glMatrixMode(GL_MODELVIEW));
- GL_CALL(glLoadIdentity());
+ GL_CALL(glMatrixMode(GL_MODELVIEW));
+ GL_CALL(glLoadIdentity());
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ } else {
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+ assert(sizeof(_projectionMatrix) == sizeof(orthoProjection));
+ memcpy(_projectionMatrix, orthoProjection, sizeof(_projectionMatrix));
+ if (_shader) {
+ _shader->activate(_projectionMatrix);
+ }
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ }
+#endif
uint overlayWidth = width;
uint overlayHeight = height;
@@ -845,25 +870,51 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
// Disable 3D properties.
GL_CALL(glDisable(GL_CULL_FACE));
GL_CALL(glDisable(GL_DEPTH_TEST));
- GL_CALL(glDisable(GL_LIGHTING));
- GL_CALL(glDisable(GL_FOG));
GL_CALL(glDisable(GL_DITHER));
- GL_CALL(glShadeModel(GL_FLAT));
- GL_CALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
+
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ if (g_context.type != kContextGLES2) {
+#endif
+#if !USE_FORCED_GLES2
+ GL_CALL(glDisable(GL_LIGHTING));
+ GL_CALL(glDisable(GL_FOG));
+ GL_CALL(glShadeModel(GL_FLAT));
+ GL_CALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST));
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ }
+#endif
// Default to black as clear color.
GL_CALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
- GL_CALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f));
+ setColor(1.0f, 1.0f, 1.0f, 1.0f);
// Setup alpha blend (for overlay and cursor).
GL_CALL(glEnable(GL_BLEND));
GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
- // 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 && !USE_FORCED_GLES2
+ 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));
+
+ GL_CALL(glEnable(GL_TEXTURE_2D));
+#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));
- GL_CALL(glEnable(GL_TEXTURE_2D));
+ GL_CALL(glActiveTexture(GL_TEXTURE0));
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ }
+#endif
// Setup scissor state accordingly.
if (_overlayVisible) {
@@ -883,6 +934,22 @@ 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) {
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+ if (!_shader) {
+ _shader = new Shader(g_defaultVertexShader, g_defaultFragmentShader);
+ }
+
+ // TODO: What do we do on failure?
+ _shader->recreate();
+ _shader->activate(_projectionMatrix);
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ }
+#endif
+
// Refresh the output screen dimensions if some are set up.
if (_outputScreenWidth != 0 && _outputScreenHeight != 0) {
setActualScreenSize(_outputScreenWidth, _outputScreenHeight);
@@ -931,6 +998,12 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
_osd->releaseInternalTexture();
}
#endif
+
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+ if (_shader) {
+ _shader->destroy();
+ }
+#endif
}
void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
@@ -1002,6 +1075,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) {
+#endif
+#if !USE_FORCED_GLES2
+ GL_CALL(glColor4f(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));
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ }
+#endif
+}
+
bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const {
#ifdef SCUMM_LITTLE_ENDIAN
if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888
@@ -1027,7 +1118,7 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF
glFormat = GL_RGBA;
glType = GL_UNSIGNED_SHORT_4_4_4_4;
return true;
-#if !USE_FORCED_GLES
+#if !USE_FORCED_GLES && !USE_FORCED_GLES2
// The formats below are not supported by every GLES implementation.
// Thus, we do not mark them as supported when a GLES context is setup.
} else if (isGLESContext()) {
@@ -1081,7 +1172,7 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF
glFormat = GL_BGRA;
glType = GL_UNSIGNED_SHORT_4_4_4_4;
return true;
-#endif // !USE_FORCED_GLES
+#endif // !USE_FORCED_GLES && !USE_FORCED_GLES2
} else {
return false;
}
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 5a2b1bb373..37ab1f8591 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -41,6 +41,9 @@ namespace OpenGL {
#define USE_OSD 1
class Texture;
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+class Shader;
+#endif
enum {
GFX_LINEAR = 0,
@@ -117,9 +120,9 @@ public:
protected:
/**
- * Whether an GLES context is active.
+ * Whether an GLES or GLES2 context is active.
*/
- bool isGLESContext() const { return g_context.type == kContextGLES; }
+ bool isGLESContext() const { return g_context.type == kContextGLES || g_context.type == kContextGLES2; }
/**
* Set up the actual screen size available for the OpenGL code to do any
@@ -300,6 +303,14 @@ private:
*/
void initializeGLContext();
+ /**
+ * Set color which shall be multiplied with each pixel.
+ *
+ * This serves as a wrapper around glColor4f for fixed-function and our
+ * shader pipeline.
+ */
+ void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+
protected:
/**
* Query the address of an OpenGL function by name.
@@ -518,6 +529,22 @@ private:
*/
uint _scissorOverride;
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+ //
+ // Shaders
+ //
+
+ /**
+ * Active shader.
+ */
+ Shader *_shader;
+
+ /**
+ * Projection matrix used.
+ */
+ GLfloat _projectionMatrix[4*4];
+#endif
+
#ifdef USE_OSD
//
// OSD
diff --git a/backends/graphics/opengl/opengl-sys.h b/backends/graphics/opengl/opengl-sys.h
index 250357f92a..ad36226a57 100644
--- a/backends/graphics/opengl/opengl-sys.h
+++ b/backends/graphics/opengl/opengl-sys.h
@@ -35,8 +35,10 @@
// the given selection choices:
// 0 - Force OpenGL context
// 1 - Force OpenGL ES context
-#define USE_FORCED_GL (defined(USE_GLES_MODE) && USE_GLES_MODE == 0)
-#define USE_FORCED_GLES (defined(USE_GLES_MODE) && USE_GLES_MODE == 1)
+// 2 - Force OpenGL ES 2.0 context
+#define USE_FORCED_GL (defined(USE_GLES_MODE) && USE_GLES_MODE == 0)
+#define USE_FORCED_GLES (defined(USE_GLES_MODE) && USE_GLES_MODE == 1)
+#define USE_FORCED_GLES2 (defined(USE_GLES_MODE) && USE_GLES_MODE == 2)
// On Tizen we include the toolchain's OpenGL file. This is something we
// actually want to avoid. However, since Tizen uses eglGetProcAddress which
@@ -69,7 +71,8 @@ namespace OpenGL {
enum ContextType {
kContextGL,
- kContextGLES
+ kContextGLES,
+ kContextGLES2
};
/**
@@ -103,6 +106,7 @@ extern Context g_context;
} // End of namespace OpenGL
-#define GL_CALL(x) GL_WRAP_DEBUG(g_context.x, x)
+#define GL_CALL(x) GL_WRAP_DEBUG(g_context.x, x)
+#define GL_ASSIGN(var, x) GL_WRAP_DEBUG(var = g_context.x, x)
#endif
diff --git a/backends/graphics/opengl/shader.cpp b/backends/graphics/opengl/shader.cpp
new file mode 100644
index 0000000000..6e36307860
--- /dev/null
+++ b/backends/graphics/opengl/shader.cpp
@@ -0,0 +1,176 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "backends/graphics/opengl/shader.h"
+
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+
+#include "common/textconsole.h"
+
+namespace OpenGL {
+
+const char *const g_defaultVertexShader =
+ "attribute vec4 position;\n"
+ "attribute vec2 texCoordIn;\n"
+ "attribute vec4 blendColorIn;\n"
+ "\n"
+ "uniform mat4 projection;\n"
+ "\n"
+ "varying vec2 texCoord;\n"
+ "varying vec4 blendColor;\n"
+ "\n"
+ "void main(void) {\n"
+ "\ttexCoord = texCoordIn;\n"
+ "\tblendColor = blendColorIn;\n"
+ "\tgl_Position = projection * position;\n"
+ "}\n";
+
+const char *const g_defaultFragmentShader =
+ "varying lowp vec2 texCoord;\n"
+ "varying lowp vec4 blendColor;\n"
+ "\n"
+ "uniform sampler2D texture;\n"
+ "\n"
+ "void main(void) {\n"
+ "\tgl_FragColor = blendColor * texture2D(texture, texCoord);\n"
+ "}\n";
+
+Shader::Shader(const Common::String &vertex, const Common::String &fragment)
+ : _vertex(vertex), _fragment(fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
+}
+
+void Shader::destroy() {
+ GL_CALL(glDeleteProgram(_program));
+ _program = 0;
+}
+
+bool Shader::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);
+ if (!fragmentShader) {
+ GL_CALL(glDeleteShader(vertexShader));
+ return false;
+ }
+
+ GL_ASSIGN(_program, glCreateProgram());
+ if (!_program) {
+ GL_CALL(glDeleteShader(vertexShader));
+ GL_CALL(glDeleteShader(fragmentShader));
+ return false;
+ }
+
+ GL_CALL(glAttachShader(_program, vertexShader));
+ GL_CALL(glAttachShader(_program, fragmentShader));
+
+ GL_CALL(glBindAttribLocation(_program, kPositionAttribLocation, "position"));
+ GL_CALL(glBindAttribLocation(_program, kTexCoordAttribLocation, "texCoordIn"));
+ GL_CALL(glBindAttribLocation(_program, kColorAttribLocation, "blendColorIn"));
+
+ GL_CALL(glLinkProgram(_program));
+
+ GL_CALL(glDetachShader(_program, fragmentShader));
+ GL_CALL(glDeleteShader(fragmentShader));
+
+ GL_CALL(glDetachShader(_program, vertexShader));
+ GL_CALL(glDeleteShader(vertexShader));
+
+ GLint result;
+ GL_CALL(glGetProgramiv(_program, GL_LINK_STATUS, &result));
+ if (result == GL_FALSE) {
+ GLint logSize;
+ GL_CALL(glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &logSize));
+
+ GLchar *log = new GLchar[logSize];
+ GL_CALL(glGetProgramInfoLog(_program, logSize, nullptr, log));
+ warning("Could not link shader: \"%s\"", log);
+ delete[] log;
+
+ destroy();
+ return false;
+ }
+
+ GL_ASSIGN(_projectionLocation, glGetUniformLocation(_program, "projection"));
+ if (_projectionLocation == -1) {
+ warning("Shader misses \"projection\" uniform.");
+ destroy();
+ return false;
+ }
+
+ GL_ASSIGN(_textureLocation, glGetUniformLocation(_program, "texture"));
+ if (_textureLocation == -1) {
+ warning("Shader misses \"texture\" uniform.");
+ destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void Shader::activate(const GLfloat *projectionMatrix) {
+ // Activate program.
+ GL_CALL(glUseProgram(_program));
+
+ // Set projection matrix.
+ GL_CALL(glUniformMatrix4fv(_projectionLocation, 1, GL_FALSE, projectionMatrix));
+
+ // We always use texture unit 0.
+ GL_CALL(glUniform1i(_textureLocation, 0));
+}
+
+GLuint Shader::compileShader(const char *source, GLenum shaderType) {
+ GLuint handle;
+ GL_ASSIGN(handle, glCreateShader(shaderType));
+ if (!handle) {
+ return 0;
+ }
+
+ GL_CALL(glShaderSource(handle, 1, &source, nullptr));
+ GL_CALL(glCompileShader(handle));
+
+ GLint result;
+ GL_CALL(glGetShaderiv(handle, GL_COMPILE_STATUS, &result));
+ if (result == GL_FALSE) {
+ GLint logSize;
+ GL_CALL(glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &logSize));
+
+ GLchar *log = new GLchar[logSize];
+ GL_CALL(glGetShaderInfoLog(handle, logSize, nullptr, log));
+ warning("Could not compile shader \"%s\": \"%s\"", source, log);
+ delete[] log;
+
+ GL_CALL(glDeleteShader(handle));
+ return 0;
+ }
+
+ return handle;
+}
+
+} // End of namespace OpenGL
+
+#endif // !USE_FORCED_GL && !USE_FORCED_GLES
diff --git a/backends/graphics/opengl/shader.h b/backends/graphics/opengl/shader.h
new file mode 100644
index 0000000000..e8535e0225
--- /dev/null
+++ b/backends/graphics/opengl/shader.h
@@ -0,0 +1,110 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_OPENGL_SHADER_H
+#define BACKENDS_GRAPHICS_OPENGL_SHADER_H
+
+#include "backends/graphics/opengl/opengl-sys.h"
+
+#if !USE_FORCED_GL && !USE_FORCED_GLES
+
+#include "common/str.h"
+
+namespace OpenGL {
+
+enum {
+ kPositionAttribLocation = 0,
+ kTexCoordAttribLocation = 1,
+ 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);
+ ~Shader() { destroy(); }
+
+ /**
+ * Destroy the shader program.
+ *
+ * This keeps the vertex and fragment shader sources around and thus
+ * allows for recreating the shader on context recreation.
+ */
+ void destroy();
+
+ /**
+ * Recreate shader program.
+ *
+ * @return true on success, false on failure.
+ */
+ bool recreate();
+
+ /**
+ * Make shader active.
+ *
+ * @param projectionMatrix Projection matrix to use.
+ */
+ void activate(const GLfloat *projectionMatrix);
+private:
+ /**
+ * Vertex shader sources.
+ */
+ const Common::String _vertex;
+
+ /**
+ * Fragment shader sources.
+ */
+ const Common::String _fragment;
+
+ /**
+ * 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);
+};
+
+} // End of namespace OpenGL
+
+#endif // !USE_FORCED_GL && !USE_FORCED_GLES
+
+#endif
diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp
index fadfd99aaa..c8c38edbbd 100644
--- a/backends/graphics/opengl/texture.cpp
+++ b/backends/graphics/opengl/texture.cpp
@@ -21,6 +21,7 @@
*/
#include "backends/graphics/opengl/texture.h"
+#include "backends/graphics/opengl/shader.h"
#include "common/rect.h"
#include "common/textconsole.h"
@@ -185,7 +186,6 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
0, texHeight,
texWidth, texHeight
};
- GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords));
// Calculate the screen rect where the texture will be drawn.
const GLfloat vertices[4*2] = {
@@ -194,7 +194,24 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
x, y + h,
x + w, y + h
};
- GL_CALL(glVertexPointer(2, GL_FLOAT, 0, vertices));
+
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ 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));
+#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));
+#endif
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+ }
+#endif
// Draw the texture to the screen buffer.
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 94f5f7aba2..f2af7ccadd 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -57,6 +57,9 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
#define DEFAULT_GLES_MAJOR 1
#define DEFAULT_GLES_MINOR 1
+#define DEFAULT_GLES2_MAJOR 2
+#define DEFAULT_GLES2_MINOR 0
+
#if USE_FORCED_GL
glContextType = OpenGL::kContextGL;
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
@@ -67,6 +70,11 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
_glContextMajor = DEFAULT_GLES_MAJOR;
_glContextMinor = DEFAULT_GLES_MINOR;
+#elif USE_FORCED_GLES2
+ glContextType = OpenGL::kContextGLES2;
+ _glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
+ _glContextMajor = DEFAULT_GLES2_MAJOR;
+ _glContextMinor = DEFAULT_GLES2_MINOR;
#else
bool noDefaults = false;
@@ -102,12 +110,10 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
}
if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_ES) {
- glContextType = OpenGL::kContextGLES;
-
- // We do not support GLES2 contexts right now. Force a GLES1 context.
if (_glContextMajor >= 2) {
- _glContextMajor = DEFAULT_GLES_MAJOR;
- _glContextMinor = DEFAULT_GLES_MINOR;
+ glContextType = OpenGL::kContextGLES2;
+ } else {
+ glContextType = OpenGL::kContextGLES;
}
} else if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_CORE) {
glContextType = OpenGL::kContextGL;
@@ -124,6 +130,8 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
#undef DEFAULT_GL_MINOR
#undef DEFAULT_GLES_MAJOR
#undef DEFAULT_GLES_MINOR
+#undef DEFAULT_GLES2_MAJOR
+#undef DEFAULT_GLES2_MINOR
#endif
setContextType(glContextType);
@@ -296,7 +304,7 @@ Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormat
// RGBA4444
formats.push_back(Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0));
-#if !USE_FORCED_GLES
+#if !USE_FORCED_GLES && !USE_FORCED_GLES2
#if !USE_FORCED_GL
if (!isGLESContext()) {
#endif
diff --git a/backends/module.mk b/backends/module.mk
index e1c3483a9c..e4566d0e8e 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -55,6 +55,7 @@ MODULE_OBJS += \
graphics/opengl/context.o \
graphics/opengl/debug.o \
graphics/opengl/opengl-graphics.o \
+ graphics/opengl/shader.o \
graphics/opengl/texture.o
endif