21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED
27 #include "../SDL_sysrender.h"
33 #define RENDERER_CONTEXT_MAJOR 1
34 #define RENDERER_CONTEXT_MINOR 1
36 #if defined(SDL_VIDEO_DRIVER_PANDORA)
53 static const float inv255f = 1.0f / 255.0f;
94 typedef struct GLES_FBOList GLES_FBOList;
124 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
125 #define SDL_PROC_OES SDL_PROC
129 SDL_bool GL_OES_framebuffer_object_supported;
131 GLuint window_framebuffer;
133 SDL_bool GL_OES_blend_func_separate_supported;
134 SDL_bool GL_OES_blend_equation_separate_supported;
135 SDL_bool GL_OES_blend_subtract_supported;
158 error =
"GL_NO_ERROR";
161 error =
"GL_INVALID_ENUM";
164 error =
"GL_INVALID_VALUE";
167 error =
"GL_INVALID_OPERATION";
170 error =
"GL_STACK_OVERFLOW";
173 error =
"GL_STACK_UNDERFLOW";
176 error =
"GL_OUT_OF_MEMORY";
185 static int GLES_LoadFunctions(GLES_RenderData *
data)
187 #if SDL_VIDEO_DRIVER_UIKIT
188 #define __SDL_NOGETPROCADDR__
189 #elif SDL_VIDEO_DRIVER_ANDROID
190 #define __SDL_NOGETPROCADDR__
191 #elif SDL_VIDEO_DRIVER_PANDORA
192 #define __SDL_NOGETPROCADDR__
195 #ifdef __SDL_NOGETPROCADDR__
196 #define SDL_PROC(ret,func,params) data->func=func;
197 #define SDL_PROC_OES(ret,func,params) data->func=func;
199 #define SDL_PROC(ret,func,params) \
201 data->func = SDL_GL_GetProcAddress(#func); \
202 if ( ! data->func ) { \
203 return SDL_SetError("Couldn't load GLES function %s: %s", #func, SDL_GetError()); \
206 #define SDL_PROC_OES(ret,func,params) \
208 data->func = SDL_GL_GetProcAddress(#func); \
220 static GLES_FBOList *
223 GLES_FBOList *result = data->framebuffers;
224 while ((result) && ((result->w != w) || (result->h != h)) ) {
225 result = result->next;
227 if (result ==
NULL) {
231 data->glGenFramebuffersOES(1, &result->FBO);
232 result->next = data->framebuffers;
233 data->framebuffers =
result;
242 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
244 if (SDL_CurrentContext != data->context) {
248 SDL_CurrentContext = data->context;
250 GLES_UpdateViewport(renderer);
259 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
261 if (SDL_CurrentContext == data->context) {
262 GLES_UpdateViewport(renderer);
264 GLES_ActivateRenderer(renderer);
267 data->current.color = 0xffffffff;
275 data->glLoadIdentity();
286 GLES_RenderData *
data;
289 int profile_mask = 0, major = 0, minor = 0;
316 data = (GLES_RenderData *)
SDL_calloc(1,
sizeof(*data));
318 GLES_DestroyRenderer(renderer);
345 renderer->
info = GLES_RenderDriver.
info;
351 if (!data->context) {
352 GLES_DestroyRenderer(renderer);
356 GLES_DestroyRenderer(renderer);
360 if (GLES_LoadFunctions(data) < 0) {
361 GLES_DestroyRenderer(renderer);
383 data->GL_OES_framebuffer_object_supported =
SDL_TRUE;
387 data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
388 data->window_framebuffer = (
GLuint)value;
390 data->framebuffers =
NULL;
393 data->GL_OES_blend_func_separate_supported =
SDL_TRUE;
396 data->GL_OES_blend_equation_separate_supported =
SDL_TRUE;
399 data->GL_OES_blend_subtract_supported =
SDL_TRUE;
403 GLES_ResetState(renderer);
408 if (changed_window) {
421 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
427 SDL_CurrentContext =
NULL;
437 GLES_GetOutputSize(
SDL_Renderer * renderer,
int *w,
int *h)
475 return GL_FUNC_ADD_OES;
477 return GL_FUNC_SUBTRACT_OES;
479 return GL_FUNC_REVERSE_SUBTRACT_OES;
488 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
504 if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->GL_OES_blend_func_separate_supported) {
507 if (colorOperation != alphaOperation && !data->GL_OES_blend_equation_separate_supported) {
517 power_of_2(
int input)
521 while (value < input) {
530 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->
driverdata;
531 GLES_TextureData *data;
534 int texture_w, texture_h;
538 GLES_ActivateRenderer(renderer);
540 switch (texture->
format) {
550 data = (GLES_TextureData *)
SDL_calloc(1,
sizeof(*data));
557 data->pixels =
SDL_calloc(1, texture->
h * data->pitch);
566 if (!renderdata->GL_OES_framebuffer_object_supported) {
568 return SDL_SetError(
"GL_OES_framebuffer_object not supported");
570 data->fbo = GLES_GetFBO(renderer->
driverdata, texture->
w, texture->
h);
576 renderdata->glGetError();
578 renderdata->glGenTextures(1, &data->texture);
579 result = renderdata->glGetError();
582 return GLES_SetError(
"glGenTextures()", result);
587 texture_w = power_of_2(texture->
w);
588 texture_h = power_of_2(texture->
h);
589 data->texw = (
GLfloat) texture->
w / texture_w;
590 data->texh = (
GLfloat) texture->
h / texture_h;
593 data->formattype =
type;
595 renderdata->glBindTexture(data->type, data->texture);
601 renderdata->glTexImage2D(data->type, 0,
internalFormat, texture_w,
605 result = renderdata->glGetError();
608 return GLES_SetError(
"glTexImage2D()", result);
619 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->
driverdata;
620 GLES_TextureData *data = (GLES_TextureData *) texture->
driverdata;
626 GLES_ActivateRenderer(renderer);
629 if (rect->
w <= 0 || rect->
h <= 0) {
635 src = (
Uint8 *)pixels;
636 if (pitch != srcPitch) {
642 for (y = 0; y < rect->
h; ++
y) {
645 pixels = (
Uint8 *)pixels + pitch;
651 renderdata->glGetError();
652 renderdata->glEnable(data->type);
653 renderdata->glBindTexture(data->type, data->texture);
655 renderdata->glTexSubImage2D(data->type,
664 renderdata->glDisable(data->type);
675 const SDL_Rect * rect,
void **pixels,
int *pitch)
677 GLES_TextureData *data = (GLES_TextureData *) texture->
driverdata;
680 (
void *) ((
Uint8 *) data->pixels + rect->
y * data->pitch +
682 *pitch = data->pitch;
689 GLES_TextureData *data = (GLES_TextureData *) texture->
driverdata;
697 GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
703 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
704 GLES_TextureData *texturedata =
NULL;
707 if (!data->GL_OES_framebuffer_object_supported) {
708 return SDL_SetError(
"Can't enable render target support in this renderer");
711 if (texture ==
NULL) {
712 data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
716 texturedata = (GLES_TextureData *) texture->
driverdata;
717 data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
719 data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
721 status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
722 if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
723 return SDL_SetError(
"glFramebufferTexture2DOES() failed");
731 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
733 if (SDL_CurrentContext != data->context) {
750 data->glLoadIdentity();
774 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
776 if (SDL_CurrentContext != data->context) {
790 data->glScissor(renderer->
viewport.
x + rect->
x, h - renderer->
viewport.
y - rect->
y - rect->
h, rect->
w, rect->
h);
801 Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
803 if (color != data->current.color) {
804 data->glColor4f((
GLfloat) r * inv255f,
808 data->current.color =
color;
813 GLES_SetBlendMode(GLES_RenderData * data,
SDL_BlendMode blendMode)
815 if (blendMode != data->current.blendMode) {
820 if (data->GL_OES_blend_func_separate_supported) {
829 if (data->GL_OES_blend_equation_separate_supported) {
832 }
else if (data->GL_OES_blend_subtract_supported) {
843 if (enabled != data->current.tex_coords) {
849 data->current.tex_coords =
enabled;
856 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
858 GLES_ActivateRenderer(renderer);
860 GLES_SetColor(data, (
GLfloat) renderer->
r,
865 GLES_SetBlendMode(data, renderer->
blendMode);
873 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
875 GLES_ActivateRenderer(renderer);
877 data->glClearColor((
GLfloat) renderer->
r * inv255f,
899 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
903 GLES_SetDrawingState(renderer);
907 for (idx = 0; idx <
count; ++idx) {
911 vertices[idx * 2] =
x;
912 vertices[(idx * 2) + 1] = y;
915 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
925 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
929 GLES_SetDrawingState(renderer);
933 for (idx = 0; idx <
count; ++idx) {
937 vertices[idx * 2] =
x;
938 vertices[(idx * 2) + 1] = y;
941 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
943 points[0].
x == points[count-1].
x && points[0].y == points[count-1].y) {
950 data->glDrawArrays(
GL_POINTS, count-1, 1);
961 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
964 GLES_SetDrawingState(renderer);
982 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
993 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
994 GLES_TextureData *texturedata = (GLES_TextureData *) texture->
driverdata;
995 GLfloat minx, miny, maxx, maxy;
996 GLfloat minu, maxu, minv, maxv;
1000 GLES_ActivateRenderer(renderer);
1004 data->glBindTexture(texturedata->type, texturedata->texture);
1007 GLES_SetColor(data, texture->
r, texture->
g, texture->
b, texture->
a);
1009 GLES_SetColor(data, 255, 255, 255, 255);
1012 GLES_SetBlendMode(data, texture->
blendMode);
1018 maxx = dstrect->
x + dstrect->
w;
1019 maxy = dstrect->
y + dstrect->
h;
1021 minu = (
GLfloat) srcrect->
x / texture->
w;
1022 minu *= texturedata->texw;
1023 maxu = (
GLfloat) (srcrect->
x + srcrect->
w) / texture->
w;
1024 maxu *= texturedata->texw;
1025 minv = (
GLfloat) srcrect->
y / texture->
h;
1026 minv *= texturedata->texh;
1027 maxv = (
GLfloat) (srcrect->
y + srcrect->
h) / texture->
h;
1028 maxv *= texturedata->texh;
1039 texCoords[0] = minu;
1040 texCoords[1] = minv;
1041 texCoords[2] = maxu;
1042 texCoords[3] = minv;
1043 texCoords[4] = minu;
1044 texCoords[5] = maxv;
1045 texCoords[6] = maxu;
1046 texCoords[7] = maxv;
1048 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
1049 data->glTexCoordPointer(2,
GL_FLOAT, 0, texCoords);
1063 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1064 GLES_TextureData *texturedata = (GLES_TextureData *) texture->
driverdata;
1065 GLfloat minx, miny, maxx, maxy;
1066 GLfloat minu, maxu, minv, maxv;
1072 GLES_ActivateRenderer(renderer);
1076 data->glBindTexture(texturedata->type, texturedata->texture);
1079 GLES_SetColor(data, texture->
r, texture->
g, texture->
b, texture->
a);
1081 GLES_SetColor(data, 255, 255, 255, 255);
1084 GLES_SetBlendMode(data, texture->
blendMode);
1088 centerx = center->
x;
1089 centery = center->
y;
1092 data->glPushMatrix();
1093 data->glTranslatef(dstrect->
x + centerx, dstrect->
y + centery, 0.0f);
1094 data->glRotatef((
GLfloat)angle, 0.0
f, 0.0
f, 1.0
f);
1097 minx = dstrect->
w - centerx;
1101 maxx = dstrect->
w - centerx;
1105 miny = dstrect->
h - centery;
1109 maxy = dstrect->
h - centery;
1112 minu = (
GLfloat) srcrect->
x / texture->
w;
1113 minu *= texturedata->texw;
1114 maxu = (
GLfloat) (srcrect->
x + srcrect->
w) / texture->
w;
1115 maxu *= texturedata->texw;
1116 minv = (
GLfloat) srcrect->
y / texture->
h;
1117 minv *= texturedata->texh;
1118 maxv = (
GLfloat) (srcrect->
y + srcrect->
h) / texture->
h;
1119 maxv *= texturedata->texh;
1130 texCoords[0] = minu;
1131 texCoords[1] = minv;
1132 texCoords[2] = maxu;
1133 texCoords[3] = minv;
1134 texCoords[4] = minu;
1135 texCoords[5] = maxv;
1136 texCoords[6] = maxu;
1137 texCoords[7] = maxv;
1138 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
1139 data->glTexCoordPointer(2,
GL_FLOAT, 0, texCoords);
1141 data->glPopMatrix();
1149 Uint32 pixel_format,
void * pixels,
int pitch)
1151 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1159 GLES_ActivateRenderer(renderer);
1171 data->glReadPixels(rect->
x, renderer->
target ? rect->
y : (h-rect->
y)-rect->
h,
1177 src = (
Uint8*)temp_pixels + (rect->
h-1)*temp_pitch;
1192 temp_format, temp_pixels, temp_pitch,
1193 pixel_format, pixels, pitch);
1202 GLES_ActivateRenderer(renderer);
1210 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->
driverdata;
1212 GLES_TextureData *data = (GLES_TextureData *) texture->
driverdata;
1214 GLES_ActivateRenderer(renderer);
1219 if (data->texture) {
1220 renderdata->glDeleteTextures(1, &data->texture);
1230 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1233 if (data->context) {
1234 while (data->framebuffers) {
1235 GLES_FBOList *nextnode = data->framebuffers->next;
1236 data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
1238 data->framebuffers = nextnode;
1249 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1250 GLES_TextureData *texturedata = (GLES_TextureData *) texture->
driverdata;
1251 GLES_ActivateRenderer(renderer);
1254 data->glBindTexture(texturedata->type, texturedata->texture);
1257 *texw = (float)texturedata->texw;
1260 *texh = (float)texturedata->texh;
1268 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1269 GLES_TextureData *texturedata = (GLES_TextureData *) texture->
driverdata;
1270 GLES_ActivateRenderer(renderer);
1271 data->glDisable(texturedata->type);