21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED
27 #include "../SDL_sysrender.h"
28 #include "../../video/SDL_blit.h"
39 #define SDL_GLES2_USE_VBOS 1
41 #define SDL_GLES2_USE_VBOS 0
47 #define RENDERER_CONTEXT_MAJOR 2
48 #define RENDERER_CONTEXT_MINOR 0
80 typedef struct GLES2_FBOList GLES2_FBOList;
89 typedef struct GLES2_TextureData
105 typedef struct GLES2_ShaderCacheEntry
108 GLES2_ShaderType
type;
109 const GLES2_ShaderInstance *instance;
111 Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
112 struct GLES2_ShaderCacheEntry *prev;
113 struct GLES2_ShaderCacheEntry *next;
114 } GLES2_ShaderCacheEntry;
116 typedef struct GLES2_ShaderCache
119 GLES2_ShaderCacheEntry *
head;
122 typedef struct GLES2_ProgramCacheEntry
125 GLES2_ShaderCacheEntry *vertex_shader;
126 GLES2_ShaderCacheEntry *fragment_shader;
127 GLuint uniform_locations[16];
128 Uint8 color_r, color_g, color_b, color_a;
129 Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
131 struct GLES2_ProgramCacheEntry *prev;
132 struct GLES2_ProgramCacheEntry *next;
133 } GLES2_ProgramCacheEntry;
135 typedef struct GLES2_ProgramCache
138 GLES2_ProgramCacheEntry *
head;
139 GLES2_ProgramCacheEntry *
tail;
140 } GLES2_ProgramCache;
144 GLES2_ATTRIBUTE_POSITION = 0,
145 GLES2_ATTRIBUTE_TEXCOORD = 1,
146 GLES2_ATTRIBUTE_ANGLE = 2,
147 GLES2_ATTRIBUTE_CENTER = 3,
152 GLES2_UNIFORM_PROJECTION,
153 GLES2_UNIFORM_TEXTURE,
154 GLES2_UNIFORM_MODULATION,
156 GLES2_UNIFORM_TEXTURE_U,
157 GLES2_UNIFORM_TEXTURE_V
162 GLES2_IMAGESOURCE_SOLID,
163 GLES2_IMAGESOURCE_TEXTURE_ABGR,
164 GLES2_IMAGESOURCE_TEXTURE_ARGB,
165 GLES2_IMAGESOURCE_TEXTURE_RGB,
166 GLES2_IMAGESOURCE_TEXTURE_BGR,
167 GLES2_IMAGESOURCE_TEXTURE_YUV,
168 GLES2_IMAGESOURCE_TEXTURE_NV12,
169 GLES2_IMAGESOURCE_TEXTURE_NV21
172 typedef struct GLES2_DriverContext
183 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
187 GLuint window_framebuffer;
189 int shader_format_count;
191 GLES2_ShaderCache shader_cache;
192 GLES2_ProgramCache program_cache;
193 GLES2_ProgramCacheEntry *current_program;
194 Uint8 clear_r, clear_g, clear_b, clear_a;
196 #if SDL_GLES2_USE_VBOS
200 } GLES2_DriverContext;
202 #define GLES2_MAX_CACHED_PROGRAMS 8
206 GL_TranslateError (
GLenum error)
208 #define GL_ERROR_TRANSLATE(e) case e: return #e;
218 #undef GL_ERROR_TRANSLATE
224 GLES2_DriverContext *
data = (GLES2_DriverContext *) renderer->
driverdata;
226 if (!data->debug_enabled) {
235 GL_CheckAllErrors (
const char *prefix,
SDL_Renderer *renderer,
const char *file,
int line,
const char *
function)
237 GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->
driverdata;
240 if (!data->debug_enabled) {
245 GLenum error = data->glGetError();
247 if (prefix ==
NULL || prefix[0] ==
'\0') {
250 SDL_SetError(
"%s: %s (%d): %s %s (0x%X)", prefix, file, line,
function, GL_TranslateError(error), error);
260 #define GL_CheckError(prefix, renderer)
261 #elif defined(_MSC_VER) || defined(__WATCOMC__)
262 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __FUNCTION__)
264 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __PRETTY_FUNCTION__)
272 static int GLES2_ActivateRenderer(
SDL_Renderer *renderer);
275 static int GLES2_UpdateViewport(
SDL_Renderer * renderer);
276 static void GLES2_DestroyRenderer(
SDL_Renderer *renderer);
277 static int GLES2_SetOrthographicProjection(
SDL_Renderer *renderer);
282 static int GLES2_LoadFunctions(GLES2_DriverContext * data)
284 #if SDL_VIDEO_DRIVER_UIKIT
285 #define __SDL_NOGETPROCADDR__
286 #elif SDL_VIDEO_DRIVER_ANDROID
287 #define __SDL_NOGETPROCADDR__
288 #elif SDL_VIDEO_DRIVER_PANDORA
289 #define __SDL_NOGETPROCADDR__
292 #if defined __SDL_NOGETPROCADDR__
293 #define SDL_PROC(ret,func,params) data->func=func;
295 #define SDL_PROC(ret,func,params) \
297 data->func = SDL_GL_GetProcAddress(#func); \
298 if ( ! data->func ) { \
299 return SDL_SetError("Couldn't load GLES2 function %s: %s", #func, SDL_GetError()); \
309 static GLES2_FBOList *
312 GLES2_FBOList *
result = data->framebuffers;
313 while ((result) && ((result->w != w) || (result->h != h)) ) {
314 result = result->next;
316 if (result ==
NULL) {
320 data->glGenFramebuffers(1, &result->FBO);
321 result->next = data->framebuffers;
322 data->framebuffers =
result;
330 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
332 if (SDL_CurrentContext != data->context) {
334 data->current_program =
NULL;
339 SDL_CurrentContext = data->context;
341 GLES2_UpdateViewport(renderer);
344 GL_ClearErrors(renderer);
352 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
358 SDL_CurrentContext =
NULL;
368 GLES2_GetOutputSize(
SDL_Renderer * renderer,
int *w,
int *h)
440 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
442 if (SDL_CurrentContext != data->context) {
458 if (data->current_program) {
459 GLES2_SetOrthographicProjection(renderer);
461 return GL_CheckError(
"", renderer);
467 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
469 if (SDL_CurrentContext != data->context) {
483 data->glScissor(renderer->
viewport.
x + rect->
x, h - renderer->
viewport.
y - rect->
y - rect->
h, rect->
w, rect->
h);
494 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
498 GLES2_ActivateRenderer(renderer);
501 GLES2_ShaderCacheEntry *entry;
502 GLES2_ShaderCacheEntry *next;
503 entry = data->shader_cache.head;
505 data->glDeleteShader(entry->id);
512 GLES2_ProgramCacheEntry *entry;
513 GLES2_ProgramCacheEntry *next;
514 entry = data->program_cache.head;
516 data->glDeleteProgram(entry->id);
523 while (data->framebuffers) {
524 GLES2_FBOList *nextnode = data->framebuffers->next;
525 data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
526 GL_CheckError(
"", renderer);
528 data->framebuffers = nextnode;
544 const void *
pixels,
int pitch);
547 const Uint8 *Yplane,
int Ypitch,
548 const Uint8 *Uplane,
int Upitch,
549 const Uint8 *Vplane,
int Vpitch);
551 void **
pixels,
int *pitch);
561 if (!hint || *hint ==
'0' ||
SDL_strcasecmp(hint,
"nearest") == 0) {
571 GLES2_DriverContext *renderdata = (GLES2_DriverContext *)renderer->
driverdata;
572 GLES2_TextureData *data;
577 GLES2_ActivateRenderer(renderer);
601 data = (GLES2_TextureData *)
SDL_calloc(1,
sizeof(GLES2_TextureData));
607 data->pixel_format =
format;
608 data->pixel_type =
type;
619 size = texture->
h * data->pitch;
622 size += (2 * (texture->
h * data->pitch) / 4);
626 size += ((texture->
h * data->pitch) / 2);
629 if (!data->pixel_data) {
636 GL_CheckError(
"", renderer);
639 renderdata->glGenTextures(1, &data->texture_v);
640 if (GL_CheckError(
"glGenTexures()", renderer) < 0) {
644 renderdata->glBindTexture(data->texture_type, data->texture_v);
649 renderdata->glTexImage2D(data->texture_type, 0,
format, texture->
w / 2, texture->
h / 2, 0,
format,
type,
NULL);
651 renderdata->glGenTextures(1, &data->texture_u);
652 if (GL_CheckError(
"glGenTexures()", renderer) < 0) {
656 renderdata->glBindTexture(data->texture_type, data->texture_u);
661 renderdata->glTexImage2D(data->texture_type, 0,
format, texture->
w / 2, texture->
h / 2, 0,
format,
type,
NULL);
662 if (GL_CheckError(
"glTexImage2D()", renderer) < 0) {
668 renderdata->glGenTextures(1, &data->texture_u);
669 if (GL_CheckError(
"glGenTexures()", renderer) < 0) {
673 renderdata->glBindTexture(data->texture_type, data->texture_u);
679 if (GL_CheckError(
"glTexImage2D()", renderer) < 0) {
684 renderdata->glGenTextures(1, &data->texture);
685 if (GL_CheckError(
"glGenTexures()", renderer) < 0) {
690 renderdata->glBindTexture(data->texture_type, data->texture);
696 if (GL_CheckError(
"glTexImage2D()", renderer) < 0) {
701 data->fbo = GLES2_GetFBO(renderer->
driverdata, texture->
w, texture->
h);
706 return GL_CheckError(
"", renderer);
710 GLES2_TexSubImage2D(GLES2_DriverContext *data,
GLenum target,
GLint xoffset,
GLint yoffset,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const GLvoid *
pixels,
GLint pitch,
GLint bpp)
718 src_pitch = width * bpp;
719 src = (
Uint8 *)pixels;
720 if (pitch != src_pitch) {
730 pixels = (
Uint8 *)pixels + pitch;
735 data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
744 const void *pixels,
int pitch)
746 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
747 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->
driverdata;
749 GLES2_ActivateRenderer(renderer);
752 if (rect->
w <= 0 || rect->
h <= 0) {
757 data->glBindTexture(tdata->texture_type, tdata->texture);
758 GLES2_TexSubImage2D(data, tdata->texture_type,
769 pixels = (
const void*)((
const Uint8*)pixels + rect->
h * pitch);
771 data->glBindTexture(tdata->texture_type, tdata->texture_v);
773 data->glBindTexture(tdata->texture_type, tdata->texture_u);
775 GLES2_TexSubImage2D(data, tdata->texture_type,
782 pixels, pitch / 2, 1);
785 pixels = (
const void*)((
const Uint8*)pixels + (rect->
h * pitch)/4);
787 data->glBindTexture(tdata->texture_type, tdata->texture_u);
789 data->glBindTexture(tdata->texture_type, tdata->texture_v);
791 GLES2_TexSubImage2D(data, tdata->texture_type,
798 pixels, pitch / 2, 1);
803 pixels = (
const void*)((
const Uint8*)pixels + rect->
h * pitch);
804 data->glBindTexture(tdata->texture_type, tdata->texture_u);
805 GLES2_TexSubImage2D(data, tdata->texture_type,
815 return GL_CheckError(
"glTexSubImage2D()", renderer);
821 const Uint8 *Yplane,
int Ypitch,
822 const Uint8 *Uplane,
int Upitch,
823 const Uint8 *Vplane,
int Vpitch)
825 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
826 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->
driverdata;
828 GLES2_ActivateRenderer(renderer);
831 if (rect->
w <= 0 || rect->
h <= 0) {
835 data->glBindTexture(tdata->texture_type, tdata->texture_v);
836 GLES2_TexSubImage2D(data, tdata->texture_type,
845 data->glBindTexture(tdata->texture_type, tdata->texture_u);
846 GLES2_TexSubImage2D(data, tdata->texture_type,
855 data->glBindTexture(tdata->texture_type, tdata->texture);
856 GLES2_TexSubImage2D(data, tdata->texture_type,
865 return GL_CheckError(
"glTexSubImage2D()", renderer);
870 void **pixels,
int *pitch)
872 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->
driverdata;
875 *pixels = (
Uint8 *)tdata->pixel_data +
876 (tdata->pitch * rect->
y) +
878 *pitch = tdata->pitch;
886 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->
driverdata;
894 GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
900 GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->
driverdata;
901 GLES2_TextureData *texturedata =
NULL;
904 if (texture ==
NULL) {
905 data->glBindFramebuffer(
GL_FRAMEBUFFER, data->window_framebuffer);
907 texturedata = (GLES2_TextureData *) texture->
driverdata;
923 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
924 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->
driverdata;
926 GLES2_ActivateRenderer(renderer);
930 data->glDeleteTextures(1, &tdata->texture);
931 if (tdata->texture_v) {
932 data->glDeleteTextures(1, &tdata->texture_v);
934 if (tdata->texture_u) {
935 data->glDeleteTextures(1, &tdata->texture_u);
947 static GLES2_ShaderCacheEntry *GLES2_CacheShader(
SDL_Renderer *renderer, GLES2_ShaderType type);
948 static void GLES2_EvictShader(
SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry);
949 static GLES2_ProgramCacheEntry *GLES2_CacheProgram(
SDL_Renderer *renderer,
950 GLES2_ShaderCacheEntry *vertex,
951 GLES2_ShaderCacheEntry *fragment);
954 static GLES2_ProgramCacheEntry *
955 GLES2_CacheProgram(
SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
956 GLES2_ShaderCacheEntry *fragment)
958 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
959 GLES2_ProgramCacheEntry *entry;
960 GLES2_ShaderCacheEntry *shaderEntry;
961 GLint linkSuccessful;
964 entry = data->program_cache.head;
966 if (entry->vertex_shader == vertex && entry->fragment_shader == fragment) {
972 if (data->program_cache.head != entry) {
974 entry->next->prev = entry->prev;
977 entry->prev->next = entry->next;
980 entry->next = data->program_cache.head;
981 data->program_cache.head->prev = entry;
982 data->program_cache.head = entry;
988 entry = (GLES2_ProgramCacheEntry *)
SDL_calloc(1,
sizeof(GLES2_ProgramCacheEntry));
993 entry->vertex_shader = vertex;
994 entry->fragment_shader = fragment;
997 entry->id = data->glCreateProgram();
998 data->glAttachShader(entry->id, vertex->id);
999 data->glAttachShader(entry->id, fragment->id);
1000 data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION,
"a_position");
1001 data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD,
"a_texCoord");
1002 data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE,
"a_angle");
1003 data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER,
"a_center");
1004 data->glLinkProgram(entry->id);
1005 data->glGetProgramiv(entry->id,
GL_LINK_STATUS, &linkSuccessful);
1006 if (!linkSuccessful) {
1007 data->glDeleteProgram(entry->id);
1014 entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
1015 data->glGetUniformLocation(entry->id,
"u_projection");
1016 entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] =
1017 data->glGetUniformLocation(entry->id,
"u_texture_v");
1018 entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] =
1019 data->glGetUniformLocation(entry->id,
"u_texture_u");
1020 entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
1021 data->glGetUniformLocation(entry->id,
"u_texture");
1022 entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
1023 data->glGetUniformLocation(entry->id,
"u_modulation");
1024 entry->uniform_locations[GLES2_UNIFORM_COLOR] =
1025 data->glGetUniformLocation(entry->id,
"u_color");
1027 entry->modulation_r = entry->modulation_g = entry->modulation_b = entry->modulation_a = 255;
1028 entry->color_r = entry->color_g = entry->color_b = entry->color_a = 255;
1030 data->glUseProgram(entry->id);
1031 data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2);
1032 data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1);
1033 data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0);
1034 data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1,
GL_FALSE, (
GLfloat *)entry->projection);
1035 data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0f, 1.0f, 1.0f, 1.0f);
1036 data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
1039 if (data->program_cache.head) {
1040 entry->next = data->program_cache.head;
1041 data->program_cache.head->prev = entry;
1043 data->program_cache.tail = entry;
1045 data->program_cache.head = entry;
1046 ++data->program_cache.count;
1049 ++vertex->references;
1050 ++fragment->references;
1053 if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
1054 shaderEntry = data->program_cache.tail->vertex_shader;
1055 if (--shaderEntry->references <= 0) {
1056 GLES2_EvictShader(renderer, shaderEntry);
1058 shaderEntry = data->program_cache.tail->fragment_shader;
1059 if (--shaderEntry->references <= 0) {
1060 GLES2_EvictShader(renderer, shaderEntry);
1062 data->glDeleteProgram(data->program_cache.tail->id);
1063 data->program_cache.tail = data->program_cache.tail->prev;
1064 SDL_free(data->program_cache.tail->next);
1065 data->program_cache.tail->next =
NULL;
1066 --data->program_cache.count;
1071 static GLES2_ShaderCacheEntry *
1072 GLES2_CacheShader(
SDL_Renderer *renderer, GLES2_ShaderType type)
1074 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1075 const GLES2_Shader *
shader;
1076 const GLES2_ShaderInstance *instance =
NULL;
1077 GLES2_ShaderCacheEntry *entry =
NULL;
1082 shader = GLES2_GetShader(type);
1084 SDL_SetError(
"No shader matching the requested characteristics was found");
1089 for (i = 0; i <
shader->instance_count && !instance; ++
i) {
1090 for (
j = 0;
j < data->shader_format_count && !instance; ++
j) {
1091 if (!
shader->instances[i]) {
1094 if (
shader->instances[i]->format != data->shader_formats[
j]) {
1097 instance =
shader->instances[
i];
1101 SDL_SetError(
"The specified shader cannot be loaded on the current platform");
1106 entry = data->shader_cache.head;
1108 if (entry->instance == instance) {
1111 entry = entry->next;
1118 entry = (GLES2_ShaderCacheEntry *)
SDL_calloc(1,
sizeof(GLES2_ShaderCacheEntry));
1124 entry->instance = instance;
1127 entry->id = data->glCreateShader(instance->type);
1128 if (instance->format == (
GLenum)-1) {
1129 data->glShaderSource(entry->id, 1, (
const char **)(
char *)&instance->data,
NULL);
1130 data->glCompileShader(entry->id);
1133 data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
1136 if (!compileSuccessful) {
1144 data->glGetShaderInfoLog(entry->id, length, &length, info);
1153 data->glDeleteShader(entry->id);
1159 if (data->shader_cache.head) {
1160 entry->next = data->shader_cache.head;
1161 data->shader_cache.head->prev = entry;
1163 data->shader_cache.head = entry;
1164 ++data->shader_cache.count;
1169 GLES2_EvictShader(
SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry)
1171 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1175 entry->next->prev = entry->prev;
1178 entry->prev->next = entry->next;
1180 if (data->shader_cache.head == entry) {
1181 data->shader_cache.head = entry->next;
1183 --data->shader_cache.count;
1186 data->glDeleteShader(entry->id);
1193 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1194 GLES2_ShaderCacheEntry *vertex =
NULL;
1195 GLES2_ShaderCacheEntry *fragment =
NULL;
1196 GLES2_ShaderType vtype, ftype;
1197 GLES2_ProgramCacheEntry *
program;
1200 vtype = GLES2_SHADER_VERTEX_DEFAULT;
1202 case GLES2_IMAGESOURCE_SOLID:
1203 ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC;
1205 case GLES2_IMAGESOURCE_TEXTURE_ABGR:
1206 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC;
1208 case GLES2_IMAGESOURCE_TEXTURE_ARGB:
1209 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC;
1211 case GLES2_IMAGESOURCE_TEXTURE_RGB:
1212 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC;
1214 case GLES2_IMAGESOURCE_TEXTURE_BGR:
1215 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
1217 case GLES2_IMAGESOURCE_TEXTURE_YUV:
1218 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC;
1220 case GLES2_IMAGESOURCE_TEXTURE_NV12:
1221 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC;
1223 case GLES2_IMAGESOURCE_TEXTURE_NV21:
1224 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC;
1231 vertex = GLES2_CacheShader(renderer, vtype);
1235 fragment = GLES2_CacheShader(renderer, ftype);
1241 if (data->current_program &&
1242 data->current_program->vertex_shader == vertex &&
1243 data->current_program->fragment_shader == fragment) {
1248 program = GLES2_CacheProgram(renderer, vertex, fragment);
1254 data->glUseProgram(
program->id);
1257 data->current_program =
program;
1260 if (GLES2_SetOrthographicProjection(renderer) < 0) {
1267 if (vertex && vertex->references <= 0) {
1268 GLES2_EvictShader(renderer, vertex);
1270 if (fragment && fragment->references <= 0) {
1271 GLES2_EvictShader(renderer, fragment);
1273 data->current_program =
NULL;
1278 GLES2_SetOrthographicProjection(
SDL_Renderer *renderer)
1280 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1288 projection[0][0] = 2.0f / renderer->
viewport.
w;
1289 projection[0][1] = 0.0f;
1290 projection[0][2] = 0.0f;
1291 projection[0][3] = 0.0f;
1292 projection[1][0] = 0.0f;
1294 projection[1][1] = 2.0f / renderer->
viewport.
h;
1296 projection[1][1] = -2.0f / renderer->
viewport.
h;
1298 projection[1][2] = 0.0f;
1299 projection[1][3] = 0.0f;
1300 projection[2][0] = 0.0f;
1301 projection[2][1] = 0.0f;
1302 projection[2][2] = 0.0f;
1303 projection[2][3] = 0.0f;
1304 projection[3][0] = -1.0f;
1306 projection[3][1] = -1.0f;
1308 projection[3][1] = 1.0f;
1310 projection[3][2] = 0.0f;
1311 projection[3][3] = 1.0f;
1314 if (
SDL_memcmp(data->current_program->projection, projection, sizeof (projection)) != 0) {
1315 const GLuint locProjection = data->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION];
1316 data->glUniformMatrix4fv(locProjection, 1,
GL_FALSE, (
GLfloat *)projection);
1317 SDL_memcpy(data->current_program->projection, projection, sizeof (projection));
1327 static const float inv255f = 1.0f / 255.0f;
1340 static void GLES2_RenderPresent(
SDL_Renderer *renderer);
1349 return (Pixel1 == Pixel2);
1357 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1359 GLES2_ActivateRenderer(renderer);
1361 if (!CompareColors(data->clear_r, data->clear_g, data->clear_b, data->clear_a,
1362 renderer->
r, renderer->
g, renderer->
b, renderer->
a)) {
1378 data->glClearColor((
GLfloat) r * inv255f,
1382 data->clear_r = renderer->
r;
1383 data->clear_g = renderer->
g;
1384 data->clear_b = renderer->
b;
1385 data->clear_a = renderer->
a;
1402 GLES2_SetBlendMode(GLES2_DriverContext *data,
SDL_BlendMode blendMode)
1404 if (blendMode != data->current.blendMode) {
1423 if (enabled != data->current.tex_coords) {
1425 data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1427 data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1429 data->current.tex_coords =
enabled;
1436 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1437 GLES2_ProgramCacheEntry *
program;
1440 GLES2_ActivateRenderer(renderer);
1442 GLES2_SetBlendMode(data, renderer->
blendMode);
1447 if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID) < 0) {
1465 program = data->current_program;
1468 data->glUniform4f(
program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
1479 GLES2_UpdateVertexBuffer(
SDL_Renderer *renderer, GLES2_Attribute attr,
1480 const void *vertexData,
size_t dataSizeInBytes)
1482 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1484 #
if !SDL_GLES2_USE_VBOS
1485 data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2,
GL_FLOAT,
GL_FALSE, 0, vertexData);
1487 if (!data->vertex_buffers[attr]) {
1488 data->glGenBuffers(1, &data->vertex_buffers[attr]);
1493 if (data->vertex_buffer_size[attr] < dataSizeInBytes) {
1495 data->vertex_buffer_size[attr] = dataSizeInBytes;
1497 data->glBufferSubData(
GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
1500 data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2,
GL_FLOAT,
GL_FALSE, 0, 0);
1509 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1513 if (GLES2_SetDrawingState(renderer) < 0) {
1519 for (idx = 0; idx <
count; ++idx) {
1523 vertices[idx * 2] =
x;
1524 vertices[(idx * 2) + 1] = y;
1527 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 *
sizeof(
GLfloat));
1528 data->glDrawArrays(
GL_POINTS, 0, count);
1536 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1540 if (GLES2_SetDrawingState(renderer) < 0) {
1546 for (idx = 0; idx <
count; ++idx) {
1550 vertices[idx * 2] =
x;
1551 vertices[(idx * 2) + 1] = y;
1554 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 *
sizeof(
GLfloat));
1559 points[0].
x != points[count-1].
x || points[0].y != points[count-1].y) {
1560 data->glDrawArrays(
GL_POINTS, count-1, 1);
1564 return GL_CheckError(
"", renderer);
1570 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1574 if (GLES2_SetDrawingState(renderer) < 0) {
1579 for (idx = 0; idx <
count; ++idx) {
1596 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 *
sizeof(
GLfloat));
1599 return GL_CheckError(
"", renderer);
1605 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1606 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->
driverdata;
1607 GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1608 GLES2_ProgramCacheEntry *
program;
1615 switch (texture->
format) {
1620 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1623 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1631 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1634 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1641 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1644 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1647 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1654 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1657 sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1660 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1666 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
1669 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
1672 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
1678 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1681 switch (texture->
format) {
1683 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1686 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1689 sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1692 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1696 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
1699 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
1702 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
1709 if (GLES2_SelectProgram(renderer, sourceType) < 0) {
1716 data->glBindTexture(tdata->texture_type, tdata->texture_v);
1719 data->glBindTexture(tdata->texture_type, tdata->texture_u);
1725 data->glBindTexture(tdata->texture_type, tdata->texture_u);
1729 data->glBindTexture(tdata->texture_type, tdata->texture);
1745 program = data->current_program;
1747 if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
1748 data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
1749 program->modulation_r =
r;
1750 program->modulation_g =
g;
1751 program->modulation_b =
b;
1752 program->modulation_a =
a;
1756 GLES2_SetBlendMode(data, texture->
blendMode);
1758 GLES2_SetTexCoords(data,
SDL_TRUE);
1766 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1770 GLES2_ActivateRenderer(renderer);
1772 if (GLES2_SetupCopy(renderer, texture) < 0) {
1777 vertices[0] = dstrect->
x;
1778 vertices[1] = dstrect->
y;
1779 vertices[2] = (dstrect->
x + dstrect->
w);
1780 vertices[3] = dstrect->
y;
1781 vertices[4] = dstrect->
x;
1782 vertices[5] = (dstrect->
y + dstrect->
h);
1783 vertices[6] = (dstrect->
x + dstrect->
w);
1784 vertices[7] = (dstrect->
y + dstrect->
h);
1786 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 *
sizeof(
GLfloat));
1787 texCoords[0] = srcrect->
x / (
GLfloat)texture->
w;
1788 texCoords[1] = srcrect->
y / (
GLfloat)texture->
h;
1789 texCoords[2] = (srcrect->
x + srcrect->
w) / (
GLfloat)texture->
w;
1790 texCoords[3] = srcrect->
y / (
GLfloat)texture->
h;
1791 texCoords[4] = srcrect->
x / (
GLfloat)texture->
w;
1792 texCoords[5] = (srcrect->
y + srcrect->
h) / (
GLfloat)texture->
h;
1793 texCoords[6] = (srcrect->
x + srcrect->
w) / (
GLfloat)texture->
w;
1794 texCoords[7] = (srcrect->
y + srcrect->
h) / (
GLfloat)texture->
h;
1796 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 *
sizeof(
GLfloat));
1799 return GL_CheckError(
"", renderer);
1806 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1813 GLES2_ActivateRenderer(renderer);
1815 if (GLES2_SetupCopy(renderer, texture) < 0) {
1819 data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
1820 data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
1821 fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (
GLfloat)(360.0
f - angle);
1823 translate[0] = translate[2] = translate[4] = translate[6] = (center->
x + dstrect->
x);
1824 translate[1] = translate[3] = translate[5] = translate[7] = (center->
y + dstrect->
y);
1827 vertices[0] = dstrect->
x;
1828 vertices[1] = dstrect->
y;
1829 vertices[2] = (dstrect->
x + dstrect->
w);
1830 vertices[3] = dstrect->
y;
1831 vertices[4] = dstrect->
x;
1832 vertices[5] = (dstrect->
y + dstrect->
h);
1833 vertices[6] = (dstrect->
x + dstrect->
w);
1834 vertices[7] = (dstrect->
y + dstrect->
h);
1837 vertices[0] = vertices[4] = vertices[2];
1838 vertices[2] = vertices[6] = tmp;
1842 vertices[1] = vertices[3] = vertices[5];
1843 vertices[5] = vertices[7] = tmp;
1850 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 *
sizeof(
GLfloat));
1851 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 *
sizeof(
GLfloat));
1852 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 *
sizeof(
GLfloat));
1854 texCoords[0] = srcrect->
x / (
GLfloat)texture->
w;
1855 texCoords[1] = srcrect->
y / (
GLfloat)texture->
h;
1856 texCoords[2] = (srcrect->
x + srcrect->
w) / (
GLfloat)texture->
w;
1857 texCoords[3] = srcrect->
y / (
GLfloat)texture->
h;
1858 texCoords[4] = srcrect->
x / (
GLfloat)texture->
w;
1859 texCoords[5] = (srcrect->
y + srcrect->
h) / (
GLfloat)texture->
h;
1860 texCoords[6] = (srcrect->
x + srcrect->
w) / (
GLfloat)texture->
w;
1861 texCoords[7] = (srcrect->
y + srcrect->
h) / (
GLfloat)texture->
h;
1863 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 *
sizeof(
GLfloat));
1865 data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
1866 data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
1868 return GL_CheckError(
"", renderer);
1875 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1880 int w, h, length, rows;
1883 GLES2_ActivateRenderer(renderer);
1893 data->glReadPixels(rect->
x, renderer->
target ? rect->
y : (h-rect->
y)-rect->
h,
1895 if (GL_CheckError(
"glReadPixels()", renderer) < 0) {
1902 src = (
Uint8*)temp_pixels + (rect->
h-1)*temp_pitch;
1917 temp_format, temp_pixels, temp_pitch,
1918 pixel_format, pixels, pitch);
1927 GLES2_ActivateRenderer(renderer);
1942 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1943 GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->
driverdata;
1944 GLES2_ActivateRenderer(renderer);
1946 data->glBindTexture(texturedata->texture_type, texturedata->texture);
1960 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->
driverdata;
1961 GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->
driverdata;
1962 GLES2_ActivateRenderer(renderer);
1964 data->glBindTexture(texturedata->texture_type, 0);
1975 #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
1981 GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->
driverdata;
1983 if (SDL_CurrentContext == data->context) {
1984 GLES2_UpdateViewport(renderer);
1986 GLES2_ActivateRenderer(renderer);
1996 data->glClearColor((
GLfloat) data->clear_r * inv255f,
1997 (
GLfloat) data->clear_g * inv255f,
1998 (
GLfloat) data->clear_b * inv255f,
1999 (
GLfloat) data->clear_a * inv255f);
2001 data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
2002 data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
2004 GL_CheckError(
"", renderer);
2011 GLES2_DriverContext *
data;
2017 GLint window_framebuffer;
2019 int profile_mask = 0, major = 0, minor = 0;
2053 data = (GLES2_DriverContext *)
SDL_calloc(1,
sizeof(GLES2_DriverContext));
2055 GLES2_DestroyRenderer(renderer);
2059 renderer->
info = GLES2_RenderDriver.
info;
2066 if (!data->context) {
2067 GLES2_DestroyRenderer(renderer);
2071 GLES2_DestroyRenderer(renderer);
2075 if (GLES2_LoadFunctions(data) < 0) {
2076 GLES2_DestroyRenderer(renderer);
2122 if (!data->shader_formats) {
2123 GLES2_DestroyRenderer(renderer);
2127 data->shader_format_count = nFormats;
2129 data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
2133 data->shader_formats[nFormats - 1] = (
GLenum)-1;
2137 data->framebuffers =
NULL;
2139 data->window_framebuffer = (
GLuint)window_framebuffer;
2171 GLES2_ResetState(renderer);
2176 if (changed_window) {
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
SDL_BlendFactor
The normalized factor used to multiply pixel components.
int(* UpdateClipRect)(SDL_Renderer *renderer)
GLdouble GLdouble GLdouble r
#define GL_INVALID_OPERATION
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
#define SDL_GL_CreateContext
const GLuint * framebuffers
#define GL_COLOR_ATTACHMENT0
GLint GLint GLint GLint GLint x
int(* RenderClear)(SDL_Renderer *renderer)
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
#define GL_COMPILE_STATUS
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
GLuint GLuint GLsizei count
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
GLfloat GLfloat GLfloat GLfloat h
#define GL_SHADER_COMPILER
Uint32 texture_formats[16]
static screen_context_t context
SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
#define SDL_GetWindowFlags
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
#define SDL_BYTESPERPIXEL(X)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
#define GL_TEXTURE_MAG_FILTER
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define GL_TRIANGLE_STRIP
#define GL_FRAMEBUFFER_COMPLETE
#define GL_ONE_MINUS_SRC_ALPHA
SDL_BlendOperation
The blend operation used when combining source and destination pixel components.
#define GL_ONE_MINUS_SRC_COLOR
GLint GLint GLsizei width
GLfixed GLfixed GLint GLint GLfixed points
#define GL_PACK_ALIGNMENT
#define GL_MAX_TEXTURE_SIZE
static SDL_BlendMode blendMode
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
#define SDL_GL_SetAttribute
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
#define SDL_GL_GetDrawableSize
#define GL_ONE_MINUS_DST_ALPHA
SDL_RenderDriver GLES2_RenderDriver
GLenum GLenum GLuint texture
void * SDL_calloc(size_t nmemb, size_t size)
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
int(* UpdateTextureYUV)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
void * SDL_GLContext
An opaque handle to an OpenGL context.
#define SDL_GL_GetSwapInterval
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
static int GetScaleQuality(void)
static SDL_Renderer * renderer
#define SDL_stack_alloc(type, count)
#define SDL_GL_SetSwapInterval
#define GL_TEXTURE_WRAP_T
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
#define GL_LUMINANCE_ALPHA
GLubyte GLubyte GLubyte GLubyte w
GLsizei const GLfloat * value
GLsizei GLsizei GLchar * source
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
GLint GLint GLint GLint GLint GLint y
#define RGBA8888_FROM_RGBA(Pixel, r, g, b, a)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
#define GL_COLOR_BUFFER_BIT
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
GLenum GLenum GLsizei const GLuint GLboolean enabled
Window state change event data (event.window.*)
#define GL_FRAMEBUFFER_BINDING
#define SDL_OutOfMemory()
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
GLint GLint GLsizei GLsizei height
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
#define SDL_GL_MakeCurrent
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
EGLSurface EGLNativeWindowType * window
#define SDL_GetRendererOutputSize
#define GL_FUNC_REVERSE_SUBTRACT
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
GLint GLint GLint yoffset
The type used to identify a window.
#define GL_ONE_MINUS_DST_COLOR
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
#define GL_SHADER_BINARY_FORMATS
Uint32 num_texture_formats
GLuint GLuint GLsizei GLenum type
#define GL_NUM_SHADER_BINARY_FORMATS
#define SDL_GL_GetAttribute
int(* UpdateViewport)(SDL_Renderer *renderer)
GLbitfield GLuint program
#define SDL_ConvertPixels
#define SDL_GL_DeleteContext
EGLSurface EGLint * rects
#define SDL_stack_free(data)
int(* RenderCopyEx)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
#define GL_TEXTURE_WRAP_S
GLuint GLsizei GLsizei * length
#define GL_TEXTURE_MIN_FILTER
void(* RenderPresent)(SDL_Renderer *renderer)
GLboolean GLboolean GLboolean GLboolean a
void(* DestroyRenderer)(SDL_Renderer *renderer)
#define GL_UNPACK_ALIGNMENT
GLboolean GLboolean GLboolean b
#define SDL_GL_SwapWindow
SDL_bool clipping_enabled
A rectangle, with the origin at the upper left.
#define GL_INFO_LOG_LENGTH