Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11

Scott Percival 2011-07-03 06:41:51 PDT

This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.

The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION

So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.

The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.

I think that's about everything, let me know if there's anything I've
overlooked.
This commit is contained in:
Sam Lantinga 2012-01-08 02:23:37 -05:00
parent 02fe20203d
commit 296e78b65f
15 changed files with 707 additions and 232 deletions

View file

@ -27,6 +27,9 @@
#include "../SDL_sysrender.h"
#include "SDL_shaders_gles2.h"
/* Used to re-create the window with OpenGL capability */
extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
/*************************************************************************************************
* Bootstrap data *
*************************************************************************************************/
@ -128,6 +131,10 @@ typedef struct GLES2_DriverContext
SDL_bool tex_coords;
} current;
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
#include "SDL_gles2funcs.h"
#undef SDL_PROC
int shader_format_count;
GLenum *shader_formats;
GLES2_ShaderCache shader_cache;
@ -149,6 +156,26 @@ static void GLES2_DestroyRenderer(SDL_Renderer *renderer);
static SDL_GLContext SDL_CurrentContext = NULL;
static int GLES2_LoadFunctions(GLES2_DriverContext * data)
{
#ifdef __SDL_NOGETPROCADDR__
#define SDL_PROC(ret,func,params) data->func=func;
#else
#define SDL_PROC(ret,func,params) \
do { \
data->func = SDL_GL_GetProcAddress(#func); \
if ( ! data->func ) { \
SDL_SetError("Couldn't load GLES2 function %s: %s\n", #func, SDL_GetError()); \
return -1; \
} \
} while ( 0 );
#endif /* _SDL_NOGETPROCADDR_ */
#include "SDL_gles2funcs.h"
#undef SDL_PROC
return 0;
}
static int
GLES2_ActivateRenderer(SDL_Renderer * renderer)
{
@ -171,6 +198,8 @@ GLES2_ActivateRenderer(SDL_Renderer * renderer)
static void
GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
{
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
/* Rebind the context to the window area */
SDL_CurrentContext = NULL;
@ -178,7 +207,7 @@ GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
/* According to Apple documentation, we need to finish drawing NOW! */
glFinish();
rdata->glFinish();
}
}
@ -192,7 +221,7 @@ GLES2_UpdateViewport(SDL_Renderer * renderer)
return 0;
}
glViewport(renderer->viewport.x, renderer->viewport.y,
rdata->glViewport(renderer->viewport.x, renderer->viewport.y,
renderer->viewport.w, renderer->viewport.h);
return 0;
}
@ -212,7 +241,7 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer)
entry = rdata->shader_cache.head;
while (entry)
{
glDeleteShader(entry->id);
rdata->glDeleteShader(entry->id);
next = entry->next;
SDL_free(entry);
entry = next;
@ -223,7 +252,7 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer)
GLES2_ProgramCacheEntry *next;
entry = rdata->program_cache.head;
while (entry) {
glDeleteProgram(entry->id);
rdata->glDeleteProgram(entry->id);
next = entry->next;
SDL_free(entry);
entry = next;
@ -267,6 +296,7 @@ GetScaleQuality(void)
static int
GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
GLES2_TextureData *tdata;
GLenum format;
GLenum type;
@ -316,19 +346,19 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
/* Allocate the texture */
glGetError();
glGenTextures(1, &tdata->texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(tdata->texture_type, tdata->texture);
glTexParameteri(tdata->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
glTexParameteri(tdata->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(tdata->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
if (glGetError() != GL_NO_ERROR)
rdata->glGetError();
rdata->glGenTextures(1, &tdata->texture);
rdata->glActiveTexture(GL_TEXTURE0);
rdata->glBindTexture(tdata->texture_type, tdata->texture);
rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
rdata->glTexImage2D(tdata->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
if (rdata->glGetError() != GL_NO_ERROR)
{
SDL_SetError("Texture creation failed");
glDeleteTextures(1, &tdata->texture);
rdata->glDeleteTextures(1, &tdata->texture);
SDL_free(tdata);
return -1;
}
@ -339,6 +369,7 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
static void
GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
@ -346,7 +377,7 @@ GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
/* Destroy the texture */
if (tdata)
{
glDeleteTextures(1, &tdata->texture);
rdata->glDeleteTextures(1, &tdata->texture);
SDL_free(tdata->pixel_data);
SDL_free(tdata);
texture->driverdata = NULL;
@ -386,6 +417,7 @@ static int
GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
const void *pixels, int pitch)
{
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
Uint8 *blob = NULL;
Uint8 *src;
@ -393,7 +425,7 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
int y;
GLES2_ActivateRenderer(renderer);
/* Bail out if we're supposed to update an empty rectangle */
if (rect->w <= 0 || rect->h <= 0)
return 0;
@ -420,11 +452,11 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
}
/* Create a texture subimage with the supplied data */
glGetError();
glActiveTexture(GL_TEXTURE0);
glBindTexture(tdata->texture_type, tdata->texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage2D(tdata->texture_type,
rdata->glGetError();
rdata->glActiveTexture(GL_TEXTURE0);
rdata->glBindTexture(tdata->texture_type, tdata->texture);
rdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
rdata->glTexSubImage2D(tdata->texture_type,
0,
rect->x,
rect->y,
@ -437,7 +469,7 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
SDL_free(blob);
}
if (glGetError() != GL_NO_ERROR)
if (rdata->glGetError() != GL_NO_ERROR)
{
SDL_SetError("Failed to update texture");
return -1;
@ -505,33 +537,33 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
entry->blend_mode = blendMode;
/* Create the program and link it */
glGetError();
entry->id = glCreateProgram();
glAttachShader(entry->id, vertex->id);
glAttachShader(entry->id, fragment->id);
glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
glLinkProgram(entry->id);
glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
if (glGetError() != GL_NO_ERROR || !linkSuccessful)
rdata->glGetError();
entry->id = rdata->glCreateProgram();
rdata->glAttachShader(entry->id, vertex->id);
rdata->glAttachShader(entry->id, fragment->id);
rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
rdata->glLinkProgram(entry->id);
rdata->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
if (rdata->glGetError() != GL_NO_ERROR || !linkSuccessful)
{
SDL_SetError("Failed to link shader program");
glDeleteProgram(entry->id);
rdata->glDeleteProgram(entry->id);
SDL_free(entry);
return NULL;
}
/* Predetermine locations of uniform variables */
entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
glGetUniformLocation(entry->id, "u_projection");
rdata->glGetUniformLocation(entry->id, "u_projection");
entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
glGetUniformLocation(entry->id, "u_texture");
rdata->glGetUniformLocation(entry->id, "u_texture");
entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
glGetUniformLocation(entry->id, "u_modulation");
rdata->glGetUniformLocation(entry->id, "u_modulation");
entry->uniform_locations[GLES2_UNIFORM_COLOR] =
glGetUniformLocation(entry->id, "u_color");
rdata->glGetUniformLocation(entry->id, "u_color");
entry->uniform_locations[GLES2_UNIFORM_COLORTABLE] =
glGetUniformLocation(entry->id, "u_colorTable");
rdata->glGetUniformLocation(entry->id, "u_colorTable");
/* Cache the linked program */
if (rdata->program_cache.head)
@ -559,7 +591,7 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
shaderEntry = rdata->program_cache.tail->fragment_shader;
if (--shaderEntry->references <= 0)
GLES2_EvictShader(renderer, shaderEntry);
glDeleteProgram(rdata->program_cache.tail->id);
rdata->glDeleteProgram(rdata->program_cache.tail->id);
rdata->program_cache.tail = rdata->program_cache.tail->prev;
SDL_free(rdata->program_cache.tail->next);
rdata->program_cache.tail->next = NULL;
@ -628,29 +660,29 @@ GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type, SDL_BlendMode b
entry->instance = instance;
/* Compile or load the selected shader instance */
glGetError();
entry->id = glCreateShader(instance->type);
rdata->glGetError();
entry->id = rdata->glCreateShader(instance->type);
if (instance->format == (GLenum)-1)
{
glShaderSource(entry->id, 1, (const char **)&instance->data, NULL);
glCompileShader(entry->id);
glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
rdata->glShaderSource(entry->id, 1, (const char **)&instance->data, NULL);
rdata->glCompileShader(entry->id);
rdata->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
}
else
{
glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
rdata->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
compileSuccessful = GL_TRUE;
}
if (glGetError() != GL_NO_ERROR || !compileSuccessful)
if (rdata->glGetError() != GL_NO_ERROR || !compileSuccessful)
{
char *info = NULL;
int length = 0;
glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
rdata->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
if (length > 0) {
info = SDL_stack_alloc(char, length);
if (info) {
glGetShaderInfoLog(entry->id, length, &length, info);
rdata->glGetShaderInfoLog(entry->id, length, &length, info);
}
}
if (info) {
@ -659,7 +691,7 @@ GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type, SDL_BlendMode b
} else {
SDL_SetError("Failed to load the shader");
}
glDeleteShader(entry->id);
rdata->glDeleteShader(entry->id);
SDL_free(entry);
return NULL;
}
@ -690,7 +722,7 @@ GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry)
--rdata->shader_cache.count;
/* Deallocate the shader */
glDeleteShader(entry->id);
rdata->glDeleteShader(entry->id);
SDL_free(entry);
}
@ -746,9 +778,9 @@ GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendM
goto fault;
/* Select that program in OpenGL */
glGetError();
glUseProgram(program->id);
if (glGetError() != GL_NO_ERROR)
rdata->glGetError();
rdata->glUseProgram(program->id);
if (rdata->glGetError() != GL_NO_ERROR)
{
SDL_SetError("Failed to select program");
goto fault;
@ -799,9 +831,9 @@ GLES2_SetOrthographicProjection(SDL_Renderer *renderer)
/* Set the projection matrix */
locProjection = rdata->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION];
glGetError();
glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection);
if (glGetError() != GL_NO_ERROR)
rdata->glGetError();
rdata->glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection);
if (rdata->glGetError() != GL_NO_ERROR)
{
SDL_SetError("Failed to set orthographic projection");
return -1;
@ -829,14 +861,16 @@ static void GLES2_RenderPresent(SDL_Renderer *renderer);
static int
GLES2_RenderClear(SDL_Renderer * renderer)
{
GLES2_ActivateRenderer(renderer);
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
glClearColor((GLfloat) renderer->r * inv255f,
GLES2_ActivateRenderer(renderer);
rdata->glClearColor((GLfloat) renderer->r * inv255f,
(GLfloat) renderer->g * inv255f,
(GLfloat) renderer->b * inv255f,
(GLfloat) renderer->a * inv255f);
glClear(GL_COLOR_BUFFER_BIT);
rdata->glClear(GL_COLOR_BUFFER_BIT);
return 0;
}
@ -848,19 +882,19 @@ GLES2_SetBlendMode(GLES2_DriverContext *rdata, int blendMode)
switch (blendMode) {
default:
case SDL_BLENDMODE_NONE:
glDisable(GL_BLEND);
rdata->glDisable(GL_BLEND);
break;
case SDL_BLENDMODE_BLEND:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
rdata->glEnable(GL_BLEND);
rdata->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case SDL_BLENDMODE_ADD:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
rdata->glEnable(GL_BLEND);
rdata->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
break;
case SDL_BLENDMODE_MOD:
glEnable(GL_BLEND);
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
rdata->glEnable(GL_BLEND);
rdata->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
break;
}
rdata->current.blendMode = blendMode;
@ -872,9 +906,9 @@ GLES2_SetTexCoords(GLES2_DriverContext * rdata, SDL_bool enabled)
{
if (enabled != rdata->current.tex_coords) {
if (enabled) {
glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
} else {
glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
}
rdata->current.tex_coords = enabled;
}
@ -887,7 +921,7 @@ GLES2_SetDrawingState(SDL_Renderer * renderer)
int blendMode = renderer->blendMode;
GLuint locColor;
glGetError();
rdata->glGetError();
GLES2_ActivateRenderer(renderer);
@ -901,7 +935,7 @@ GLES2_SetDrawingState(SDL_Renderer * renderer)
/* Select the color to draw with */
locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
glUniform4f(locColor,
rdata->glUniform4f(locColor,
renderer->r * inv255f,
renderer->g * inv255f,
renderer->b * inv255f,
@ -912,6 +946,7 @@ GLES2_SetDrawingState(SDL_Renderer * renderer)
static int
GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points, int count)
{
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
GLfloat *vertices;
int idx;
@ -929,11 +964,11 @@ GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points, int coun
vertices[idx * 2] = x;
vertices[(idx * 2) + 1] = y;
}
glGetError();
glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawArrays(GL_POINTS, 0, count);
rdata->glGetError();
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
rdata->glDrawArrays(GL_POINTS, 0, count);
SDL_stack_free(vertices);
if (glGetError() != GL_NO_ERROR)
if (rdata->glGetError() != GL_NO_ERROR)
{
SDL_SetError("Failed to render lines");
return -1;
@ -944,6 +979,7 @@ GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points, int coun
static int
GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_Point *points, int count)
{
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
GLfloat *vertices;
int idx;
@ -961,17 +997,17 @@ GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_Point *points, int count
vertices[idx * 2] = x;
vertices[(idx * 2) + 1] = y;
}
glGetError();
glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawArrays(GL_LINE_STRIP, 0, count);
rdata->glGetError();
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
rdata->glDrawArrays(GL_LINE_STRIP, 0, count);
/* We need to close the endpoint of the line */
if (count == 2 ||
points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
glDrawArrays(GL_POINTS, count-1, 1);
rdata->glDrawArrays(GL_POINTS, count-1, 1);
}
SDL_stack_free(vertices);
if (glGetError() != GL_NO_ERROR)
if (rdata->glGetError() != GL_NO_ERROR)
{
SDL_SetError("Failed to render lines");
return -1;
@ -982,6 +1018,7 @@ GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_Point *points, int count
static int
GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_Rect *rects, int count)
{
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
GLfloat vertices[8];
int idx;
@ -990,7 +1027,7 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_Rect *rects, int count)
}
/* Emit a line loop for each rectangle */
glGetError();
rdata->glGetError();
for (idx = 0; idx < count; ++idx) {
const SDL_Rect *rect = &rects[idx];
@ -1007,10 +1044,10 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_Rect *rects, int count)
vertices[5] = yMax;
vertices[6] = xMax;
vertices[7] = yMax;
glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
if (glGetError() != GL_NO_ERROR)
if (rdata->glGetError() != GL_NO_ERROR)
{
SDL_SetError("Failed to render lines");
return -1;
@ -1055,14 +1092,14 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
/* Select the target texture */
locTexture = rdata->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
glGetError();
glActiveTexture(GL_TEXTURE0);
glBindTexture(tdata->texture_type, tdata->texture);
glUniform1i(locTexture, 0);
rdata->glGetError();
rdata->glActiveTexture(GL_TEXTURE0);
rdata->glBindTexture(tdata->texture_type, tdata->texture);
rdata->glUniform1i(locTexture, 0);
/* Configure color modulation */
locModulation = rdata->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
glUniform4f(locModulation,
rdata->glUniform4f(locModulation,
texture->r * inv255f,
texture->g * inv255f,
texture->b * inv255f,
@ -1082,7 +1119,7 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
vertices[5] = (GLfloat)(dstrect->y + dstrect->h);
vertices[6] = (GLfloat)(dstrect->x + dstrect->w);
vertices[7] = (GLfloat)(dstrect->y + dstrect->h);
glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
texCoords[0] = srcrect->x / (GLfloat)texture->w;
texCoords[1] = srcrect->y / (GLfloat)texture->h;
texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
@ -1091,9 +1128,9 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (glGetError() != GL_NO_ERROR)
rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (rdata->glGetError() != GL_NO_ERROR)
{
SDL_SetError("Failed to render texture");
return -1;
@ -1105,6 +1142,7 @@ static int
GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 pixel_format, void * pixels, int pitch)
{
GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
SDL_Window *window = renderer->window;
Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
void *temp_pixels;
@ -1124,9 +1162,9 @@ GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
SDL_GetWindowSize(window, &w, &h);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
rdata->glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
rdata->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
/* Flip the rows to be top-down */
@ -1181,8 +1219,8 @@ GLES2_ResetState(SDL_Renderer *renderer)
rdata->current.blendMode = -1;
rdata->current.tex_coords = SDL_FALSE;
glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
}
static SDL_Renderer *
@ -1194,6 +1232,19 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
#ifndef ZUNE_HD
GLboolean hasCompiler;
#endif
Uint32 windowFlags;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
windowFlags = SDL_GetWindowFlags(window);
if (!(windowFlags & SDL_WINDOW_OPENGL)) {
if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) {
/* Uh oh, better try to put it back... */
SDL_RecreateWindow(window, windowFlags);
return NULL;
}
}
/* Create the renderer struct */
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
@ -1214,9 +1265,6 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->window = window;
/* Create an OpenGL ES 2.0 context */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
rdata->context = SDL_GL_CreateContext(window);
if (!rdata->context)
{
@ -1228,6 +1276,11 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
return NULL;
}
if (GLES2_LoadFunctions(rdata) < 0) {
GLES2_DestroyRenderer(renderer);
return NULL;
}
if (flags & SDL_RENDERER_PRESENTVSYNC) {
SDL_GL_SetSwapInterval(1);
} else {
@ -1239,12 +1292,12 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
/* Determine supported shader formats */
/* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
glGetError();
rdata->glGetError();
#ifdef ZUNE_HD
nFormats = 1;
#else /* !ZUNE_HD */
glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
rdata->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
rdata->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
if (hasCompiler)
++nFormats;
#endif /* ZUNE_HD */
@ -1259,8 +1312,8 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
#ifdef ZUNE_HD
rdata->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
#else /* !ZUNE_HD */
glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)rdata->shader_formats);
if (glGetError() != GL_NO_ERROR)
rdata->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)rdata->shader_formats);
if (rdata->glGetError() != GL_NO_ERROR)
{
GLES2_DestroyRenderer(renderer);
SDL_SetError("Failed to query supported shader formats");