mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-02 14:51:40 +00:00
OPENGL: Support GLES2 contexts.
This commit is contained in:
parent
e931018673
commit
fe88375ff3
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
@ -53,6 +54,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
|
||||
_forceRedraw(false), _scissorOverride(3)
|
||||
#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));
|
||||
@ -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));
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
176
backends/graphics/opengl/shader.cpp
Normal file
176
backends/graphics/opengl/shader.cpp
Normal 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
|
110
backends/graphics/opengl/shader.h
Normal file
110
backends/graphics/opengl/shader.h
Normal 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
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
12
configure
vendored
12
configure
vendored
@ -945,6 +945,7 @@ Optional Features:
|
||||
any for runtime detection
|
||||
gl for forcing OpenGL
|
||||
gles for forcing OpenGL ES
|
||||
gles2 for forcing OpenGL ES 2
|
||||
WARNING: only specify this manually if you know what
|
||||
you are doing!
|
||||
|
||||
@ -2659,9 +2660,11 @@ if test -n "$_host"; then
|
||||
# since SDL2 manages dispmanx/GLES2 very well internally.
|
||||
# SDL1 is bit-rotten on this platform.
|
||||
_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.
|
||||
_opengl_mode=gles
|
||||
# The Raspberry Pi always supports OpenGL ES 2.0 contexts, thus we
|
||||
# take advantage of those.
|
||||
_opengl_mode=gles2
|
||||
;;
|
||||
dreamcast)
|
||||
append_var DEFINES "-DDISABLE_DEFAULT_SAVEFILEMANAGER"
|
||||
@ -4224,6 +4227,11 @@ case $_opengl_mode in
|
||||
echo "yes (OpenGL ES)"
|
||||
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
|
||||
|
||||
define_in_config_if_yes "$_opengl" "USE_OPENGL"
|
||||
|
Loading…
x
Reference in New Issue
Block a user