OPENGL: Support GLES2 contexts.

This commit is contained in:
Johannes Schickel 2015-12-20 05:42:54 +01:00
parent e931018673
commit fe88375ff3
12 changed files with 519 additions and 33 deletions

View file

@ -44,6 +44,8 @@ void OpenGLGraphicsManager::setContextType(ContextType type) {
type = kContextGL; type = kContextGL;
#elif USE_FORCED_GLES #elif USE_FORCED_GLES
type = kContextGLES; type = kContextGLES;
#elif USE_FORCED_GLES2
type = kContextGLES2;
#endif #endif
g_context.type = type; g_context.type = type;

View file

@ -75,11 +75,16 @@ typedef float GLfloat; /* single precision float */
typedef float GLclampf; /* single precision float in [0,1] */ typedef float GLclampf; /* single precision float in [0,1] */
typedef double GLdouble; /* double precision float */ typedef double GLdouble; /* double precision float */
typedef double GLclampd; /* double precision float in [0,1] */ typedef double GLclampd; /* double precision float in [0,1] */
typedef char GLchar;
/* /*
* Constants * Constants
*/ */
/* Boolean constants */
#define GL_FALSE 0
#define GL_TRUE 1
/* StringName */ /* StringName */
#define GL_VENDOR 0x1F00 #define GL_VENDOR 0x1F00
#define GL_RENDERER 0x1F01 #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_STRIP 0x0005
#define GL_TRIANGLE_FAN 0x0006 #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 #endif

View file

@ -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(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(const GLubyte *, glGetString, (GLenum name));
GL_FUNC_DEF(GLenum, glGetError, ()); 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

View file

@ -23,6 +23,7 @@
#include "backends/graphics/opengl/opengl-graphics.h" #include "backends/graphics/opengl/opengl-graphics.h"
#include "backends/graphics/opengl/texture.h" #include "backends/graphics/opengl/texture.h"
#include "backends/graphics/opengl/shader.h"
#include "common/textconsole.h" #include "common/textconsole.h"
#include "common/translation.h" #include "common/translation.h"
@ -53,6 +54,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
_forceRedraw(false), _scissorOverride(3) _forceRedraw(false), _scissorOverride(3)
#ifdef USE_OSD #ifdef USE_OSD
, _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr) , _osdAlpha(0), _osdFadeStartTime(0), _osd(nullptr)
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES
, _shader(nullptr), _projectionMatrix()
#endif #endif
{ {
memset(_gamePalette, 0, sizeof(_gamePalette)); memset(_gamePalette, 0, sizeof(_gamePalette));
@ -66,6 +70,9 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
#ifdef USE_OSD #ifdef USE_OSD
delete _osd; delete _osd;
#endif #endif
#if !USE_FORCED_GL && !USE_FORCED_GLES
delete _shader;
#endif
} }
bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
@ -418,13 +425,13 @@ void OpenGLGraphicsManager::updateScreen() {
} }
// Set the OSD transparency. // 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. // Draw the OSD texture.
_osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight); _osd->draw(0, 0, _outputScreenWidth, _outputScreenHeight);
// Reset color. // Reset color.
GL_CALL(glColor4f(1.0f, 1.0f, 1.0f, 1.0f)); setColor(1.0f, 1.0f, 1.0f, 1.0f);
} }
#endif #endif
@ -765,11 +772,29 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
-1.0f , 1.0f , 0.0f, 1.0f -1.0f , 1.0f , 0.0f, 1.0f
}; };
#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(glMatrixMode(GL_PROJECTION));
GL_CALL(glLoadMatrixf(orthoProjection)); GL_CALL(glLoadMatrixf(orthoProjection));
GL_CALL(glMatrixMode(GL_MODELVIEW)); GL_CALL(glMatrixMode(GL_MODELVIEW));
GL_CALL(glLoadIdentity()); 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 overlayWidth = width;
uint overlayHeight = height; uint overlayHeight = height;
@ -845,25 +870,51 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
// Disable 3D properties. // Disable 3D properties.
GL_CALL(glDisable(GL_CULL_FACE)); GL_CALL(glDisable(GL_CULL_FACE));
GL_CALL(glDisable(GL_DEPTH_TEST)); GL_CALL(glDisable(GL_DEPTH_TEST));
GL_CALL(glDisable(GL_DITHER));
#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_LIGHTING));
GL_CALL(glDisable(GL_FOG)); GL_CALL(glDisable(GL_FOG));
GL_CALL(glDisable(GL_DITHER));
GL_CALL(glShadeModel(GL_FLAT)); GL_CALL(glShadeModel(GL_FLAT));
GL_CALL(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)); 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. // Default to black as clear color.
GL_CALL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); 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). // Setup alpha blend (for overlay and cursor).
GL_CALL(glEnable(GL_BLEND)); GL_CALL(glEnable(GL_BLEND));
GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); 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) {
#endif
#if !USE_FORCED_GLES2
// Enable rendering with vertex and coord arrays. // Enable rendering with vertex and coord arrays.
GL_CALL(glEnableClientState(GL_VERTEX_ARRAY)); GL_CALL(glEnableClientState(GL_VERTEX_ARRAY));
GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); GL_CALL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_CALL(glEnable(GL_TEXTURE_2D)); 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(glActiveTexture(GL_TEXTURE0));
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
}
#endif
// Setup scissor state accordingly. // Setup scissor state accordingly.
if (_overlayVisible) { if (_overlayVisible) {
@ -883,6 +934,22 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
// Query information needed by textures. // Query information needed by textures.
Texture::queryTextureInformation(); 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. // Refresh the output screen dimensions if some are set up.
if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { if (_outputScreenWidth != 0 && _outputScreenHeight != 0) {
setActualScreenSize(_outputScreenWidth, _outputScreenHeight); setActualScreenSize(_outputScreenWidth, _outputScreenHeight);
@ -931,6 +998,12 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
_osd->releaseInternalTexture(); _osd->releaseInternalTexture();
} }
#endif #endif
#if !USE_FORCED_GL && !USE_FORCED_GLES
if (_shader) {
_shader->destroy();
}
#endif
} }
void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { 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 { bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const {
#ifdef SCUMM_LITTLE_ENDIAN #ifdef SCUMM_LITTLE_ENDIAN
if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888 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; glFormat = GL_RGBA;
glType = GL_UNSIGNED_SHORT_4_4_4_4; glType = GL_UNSIGNED_SHORT_4_4_4_4;
return true; return true;
#if !USE_FORCED_GLES #if !USE_FORCED_GLES && !USE_FORCED_GLES2
// The formats below are not supported by every GLES implementation. // The formats below are not supported by every GLES implementation.
// Thus, we do not mark them as supported when a GLES context is setup. // Thus, we do not mark them as supported when a GLES context is setup.
} else if (isGLESContext()) { } else if (isGLESContext()) {
@ -1081,7 +1172,7 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF
glFormat = GL_BGRA; glFormat = GL_BGRA;
glType = GL_UNSIGNED_SHORT_4_4_4_4; glType = GL_UNSIGNED_SHORT_4_4_4_4;
return true; return true;
#endif // !USE_FORCED_GLES #endif // !USE_FORCED_GLES && !USE_FORCED_GLES2
} else { } else {
return false; return false;
} }

View file

@ -41,6 +41,9 @@ namespace OpenGL {
#define USE_OSD 1 #define USE_OSD 1
class Texture; class Texture;
#if !USE_FORCED_GL && !USE_FORCED_GLES
class Shader;
#endif
enum { enum {
GFX_LINEAR = 0, GFX_LINEAR = 0,
@ -117,9 +120,9 @@ public:
protected: 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 * Set up the actual screen size available for the OpenGL code to do any
@ -300,6 +303,14 @@ private:
*/ */
void initializeGLContext(); 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: protected:
/** /**
* Query the address of an OpenGL function by name. * Query the address of an OpenGL function by name.
@ -518,6 +529,22 @@ private:
*/ */
uint _scissorOverride; 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 #ifdef USE_OSD
// //
// OSD // OSD

View file

@ -35,8 +35,10 @@
// the given selection choices: // the given selection choices:
// 0 - Force OpenGL context // 0 - Force OpenGL context
// 1 - Force OpenGL ES context // 1 - Force OpenGL ES context
// 2 - Force OpenGL ES 2.0 context
#define USE_FORCED_GL (defined(USE_GLES_MODE) && USE_GLES_MODE == 0) #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_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 // On Tizen we include the toolchain's OpenGL file. This is something we
// actually want to avoid. However, since Tizen uses eglGetProcAddress which // actually want to avoid. However, since Tizen uses eglGetProcAddress which
@ -69,7 +71,8 @@ namespace OpenGL {
enum ContextType { enum ContextType {
kContextGL, kContextGL,
kContextGLES kContextGLES,
kContextGLES2
}; };
/** /**
@ -104,5 +107,6 @@ extern Context g_context;
} // End of namespace OpenGL } // 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 #endif

View file

@ -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

View file

@ -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

View file

@ -21,6 +21,7 @@
*/ */
#include "backends/graphics/opengl/texture.h" #include "backends/graphics/opengl/texture.h"
#include "backends/graphics/opengl/shader.h"
#include "common/rect.h" #include "common/rect.h"
#include "common/textconsole.h" #include "common/textconsole.h"
@ -185,7 +186,6 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
0, texHeight, 0, texHeight,
texWidth, texHeight texWidth, texHeight
}; };
GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords));
// Calculate the screen rect where the texture will be drawn. // Calculate the screen rect where the texture will be drawn.
const GLfloat vertices[4*2] = { const GLfloat vertices[4*2] = {
@ -194,7 +194,24 @@ void Texture::draw(GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
x, y + h, x, y + h,
x + w, y + h x + w, y + h
}; };
#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)); 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. // Draw the texture to the screen buffer.
GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));

View file

@ -57,6 +57,9 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
#define DEFAULT_GLES_MAJOR 1 #define DEFAULT_GLES_MAJOR 1
#define DEFAULT_GLES_MINOR 1 #define DEFAULT_GLES_MINOR 1
#define DEFAULT_GLES2_MAJOR 2
#define DEFAULT_GLES2_MINOR 0
#if USE_FORCED_GL #if USE_FORCED_GL
glContextType = OpenGL::kContextGL; glContextType = OpenGL::kContextGL;
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY; _glContextProfileMask = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
@ -67,6 +70,11 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES; _glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
_glContextMajor = DEFAULT_GLES_MAJOR; _glContextMajor = DEFAULT_GLES_MAJOR;
_glContextMinor = DEFAULT_GLES_MINOR; _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 #else
bool noDefaults = false; bool noDefaults = false;
@ -102,12 +110,10 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
} }
if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_ES) { 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) { if (_glContextMajor >= 2) {
_glContextMajor = DEFAULT_GLES_MAJOR; glContextType = OpenGL::kContextGLES2;
_glContextMinor = DEFAULT_GLES_MINOR; } else {
glContextType = OpenGL::kContextGLES;
} }
} else if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_CORE) { } else if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_CORE) {
glContextType = OpenGL::kContextGL; glContextType = OpenGL::kContextGL;
@ -124,6 +130,8 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
#undef DEFAULT_GL_MINOR #undef DEFAULT_GL_MINOR
#undef DEFAULT_GLES_MAJOR #undef DEFAULT_GLES_MAJOR
#undef DEFAULT_GLES_MINOR #undef DEFAULT_GLES_MINOR
#undef DEFAULT_GLES2_MAJOR
#undef DEFAULT_GLES2_MINOR
#endif #endif
setContextType(glContextType); setContextType(glContextType);
@ -296,7 +304,7 @@ Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormat
// RGBA4444 // RGBA4444
formats.push_back(Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)); 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 !USE_FORCED_GL
if (!isGLESContext()) { if (!isGLESContext()) {
#endif #endif

View file

@ -55,6 +55,7 @@ MODULE_OBJS += \
graphics/opengl/context.o \ graphics/opengl/context.o \
graphics/opengl/debug.o \ graphics/opengl/debug.o \
graphics/opengl/opengl-graphics.o \ graphics/opengl/opengl-graphics.o \
graphics/opengl/shader.o \
graphics/opengl/texture.o graphics/opengl/texture.o
endif endif

12
configure vendored
View file

@ -945,6 +945,7 @@ Optional Features:
any for runtime detection any for runtime detection
gl for forcing OpenGL gl for forcing OpenGL
gles for forcing OpenGL ES gles for forcing OpenGL ES
gles2 for forcing OpenGL ES 2
WARNING: only specify this manually if you know what WARNING: only specify this manually if you know what
you are doing! you are doing!
@ -2659,9 +2660,11 @@ if test -n "$_host"; then
# since SDL2 manages dispmanx/GLES2 very well internally. # since SDL2 manages dispmanx/GLES2 very well internally.
# SDL1 is bit-rotten on this platform. # SDL1 is bit-rotten on this platform.
_sdlconfig=sdl2-config _sdlconfig=sdl2-config
# OpenGL(ES) support is mature enough as to be the best option on # OpenGL ES support is mature enough as to be the best option on
# the Raspberry Pi, so it's enabled by default. # the Raspberry Pi, so it's enabled by default.
_opengl_mode=gles # The Raspberry Pi always supports OpenGL ES 2.0 contexts, thus we
# take advantage of those.
_opengl_mode=gles2
;; ;;
dreamcast) dreamcast)
append_var DEFINES "-DDISABLE_DEFAULT_SAVEFILEMANAGER" append_var DEFINES "-DDISABLE_DEFAULT_SAVEFILEMANAGER"
@ -4224,6 +4227,11 @@ case $_opengl_mode in
echo "yes (OpenGL ES)" echo "yes (OpenGL ES)"
add_line_to_config_h "#define USE_GLES_MODE 1" add_line_to_config_h "#define USE_GLES_MODE 1"
;; ;;
gles2)
echo "yes (OpenGL ES 2)"
add_line_to_config_h "#define USE_GLES_MODE 2"
;;
esac esac
define_in_config_if_yes "$_opengl" "USE_OPENGL" define_in_config_if_yes "$_opengl" "USE_OPENGL"