OPENGL: Add support for shaders with GL contexts.

This commit is contained in:
Johannes Schickel 2015-12-20 09:30:11 +01:00
parent 19abd8ccbb
commit fee1aa5502
9 changed files with 360 additions and 56 deletions

View file

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

View file

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

View file

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

View file

@ -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,17 +895,7 @@ 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) {
#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 {
if (g_context.type == kContextGLES2) {
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES
GL_CALL(glEnableVertexAttribArray(kPositionAttribLocation));
@ -912,6 +903,25 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
GL_CALL(glActiveTexture(GL_TEXTURE0));
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
} else {
#endif
#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(glEnable(GL_TEXTURE_2D));
#endif
#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
}
#endif
@ -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 !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
}

View file

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

View file

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

View file

@ -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
Shader::Shader(const Common::String &vertex, const Common::String &fragment)
: _vertex(vertex), _fragment(fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
#if !USE_FORCED_GLES2
ShaderARB::ShaderARB(const Common::String &vertex, const Common::String &fragment)
: Shader(vertex, fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
}
void Shader::destroy() {
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;
}
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

View file

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

View file

@ -196,19 +196,28 @@ 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) {
#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 {
if (g_context.type == kContextGLES2) {
#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
} else {
#endif
#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
}
#endif