SDL  2.0
SDL_render_gles2.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED
24 
25 #include "SDL_hints.h"
26 #include "SDL_opengles2.h"
27 #include "../SDL_sysrender.h"
28 #include "../../video/SDL_blit.h"
29 #include "SDL_shaders_gles2.h"
30 
31 /* !!! FIXME: Emscripten makes these into WebGL calls, and WebGL doesn't offer
32  !!! FIXME: client-side arrays (without an Emscripten compatibility hack,
33  !!! FIXME: at least), but the current VBO code here is dramatically
34  !!! FIXME: slower on actual iOS devices, even though the iOS Simulator
35  !!! FIXME: is okay. Some time after 2.0.4 ships, we should revisit this,
36  !!! FIXME: fix the performance bottleneck, and make everything use VBOs.
37 */
38 #ifdef __EMSCRIPTEN__
39 #define SDL_GLES2_USE_VBOS 1
40 #else
41 #define SDL_GLES2_USE_VBOS 0
42 #endif
43 
44 /* To prevent unnecessary window recreation,
45  * these should match the defaults selected in SDL_GL_ResetAttributes
46  */
47 #define RENDERER_CONTEXT_MAJOR 2
48 #define RENDERER_CONTEXT_MINOR 0
49 
50 /* Used to re-create the window with OpenGL ES capability */
52 
53 /*************************************************************************************************
54  * Bootstrap data *
55  *************************************************************************************************/
56 
57 static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags);
58 
59 SDL_RenderDriver GLES2_RenderDriver = {
60  GLES2_CreateRenderer,
61  {
62  "opengles2",
64  4,
65  {
70  },
71  0,
72  0
73  }
74 };
75 
76 /*************************************************************************************************
77  * Context structures *
78  *************************************************************************************************/
79 
80 typedef struct GLES2_FBOList GLES2_FBOList;
81 
82 struct GLES2_FBOList
83 {
84  Uint32 w, h;
85  GLuint FBO;
86  GLES2_FBOList *next;
87 };
88 
89 typedef struct GLES2_TextureData
90 {
92  GLenum texture_type;
94  GLenum pixel_type;
95  void *pixel_data;
96  int pitch;
97  /* YUV texture support */
98  SDL_bool yuv;
99  SDL_bool nv12;
100  GLenum texture_v;
101  GLenum texture_u;
102  GLES2_FBOList *fbo;
103 } GLES2_TextureData;
104 
105 typedef struct GLES2_ShaderCacheEntry
106 {
107  GLuint id;
108  GLES2_ShaderType type;
109  const GLES2_ShaderInstance *instance;
110  int references;
111  Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
112  struct GLES2_ShaderCacheEntry *prev;
113  struct GLES2_ShaderCacheEntry *next;
114 } GLES2_ShaderCacheEntry;
115 
116 typedef struct GLES2_ShaderCache
117 {
118  int count;
119  GLES2_ShaderCacheEntry *head;
120 } GLES2_ShaderCache;
121 
122 typedef struct GLES2_ProgramCacheEntry
123 {
124  GLuint id;
125  SDL_BlendMode blend_mode;
126  GLES2_ShaderCacheEntry *vertex_shader;
127  GLES2_ShaderCacheEntry *fragment_shader;
128  GLuint uniform_locations[16];
129  Uint8 color_r, color_g, color_b, color_a;
130  Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
131  GLfloat projection[4][4];
132  struct GLES2_ProgramCacheEntry *prev;
133  struct GLES2_ProgramCacheEntry *next;
134 } GLES2_ProgramCacheEntry;
135 
136 typedef struct GLES2_ProgramCache
137 {
138  int count;
139  GLES2_ProgramCacheEntry *head;
140  GLES2_ProgramCacheEntry *tail;
141 } GLES2_ProgramCache;
142 
143 typedef enum
144 {
145  GLES2_ATTRIBUTE_POSITION = 0,
146  GLES2_ATTRIBUTE_TEXCOORD = 1,
147  GLES2_ATTRIBUTE_ANGLE = 2,
148  GLES2_ATTRIBUTE_CENTER = 3,
149 } GLES2_Attribute;
150 
151 typedef enum
152 {
153  GLES2_UNIFORM_PROJECTION,
154  GLES2_UNIFORM_TEXTURE,
155  GLES2_UNIFORM_MODULATION,
156  GLES2_UNIFORM_COLOR,
157  GLES2_UNIFORM_TEXTURE_U,
158  GLES2_UNIFORM_TEXTURE_V
159 } GLES2_Uniform;
160 
161 typedef enum
162 {
163  GLES2_IMAGESOURCE_SOLID,
164  GLES2_IMAGESOURCE_TEXTURE_ABGR,
165  GLES2_IMAGESOURCE_TEXTURE_ARGB,
166  GLES2_IMAGESOURCE_TEXTURE_RGB,
167  GLES2_IMAGESOURCE_TEXTURE_BGR,
168  GLES2_IMAGESOURCE_TEXTURE_YUV,
169  GLES2_IMAGESOURCE_TEXTURE_NV12,
170  GLES2_IMAGESOURCE_TEXTURE_NV21
171 } GLES2_ImageSource;
172 
173 typedef struct GLES2_DriverContext
174 {
175  SDL_GLContext *context;
176 
177  SDL_bool debug_enabled;
178 
179  struct {
180  int blendMode;
181  SDL_bool tex_coords;
182  } current;
183 
184 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
185 #include "SDL_gles2funcs.h"
186 #undef SDL_PROC
187  GLES2_FBOList *framebuffers;
188  GLuint window_framebuffer;
189 
190  int shader_format_count;
191  GLenum *shader_formats;
192  GLES2_ShaderCache shader_cache;
193  GLES2_ProgramCache program_cache;
194  GLES2_ProgramCacheEntry *current_program;
195  Uint8 clear_r, clear_g, clear_b, clear_a;
196 
197 #if SDL_GLES2_USE_VBOS
198  GLuint vertex_buffers[4];
199  GLsizeiptr vertex_buffer_size[4];
200 #endif
201 } GLES2_DriverContext;
202 
203 #define GLES2_MAX_CACHED_PROGRAMS 8
204 
205 
206 SDL_FORCE_INLINE const char*
207 GL_TranslateError (GLenum error)
208 {
209 #define GL_ERROR_TRANSLATE(e) case e: return #e;
210  switch (error) {
211  GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
212  GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
213  GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
214  GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
215  GL_ERROR_TRANSLATE(GL_NO_ERROR)
216  default:
217  return "UNKNOWN";
218 }
219 #undef GL_ERROR_TRANSLATE
220 }
221 
222 SDL_FORCE_INLINE void
223 GL_ClearErrors(SDL_Renderer *renderer)
224 {
225  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
226 
227  if (!data->debug_enabled) {
228  return;
229  }
230  while (data->glGetError() != GL_NO_ERROR) {
231  continue;
232  }
233 }
234 
236 GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
237 {
238  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
239  int ret = 0;
240 
241  if (!data->debug_enabled) {
242  return 0;
243  }
244  /* check gl errors (can return multiple errors) */
245  for (;;) {
246  GLenum error = data->glGetError();
247  if (error != GL_NO_ERROR) {
248  if (prefix == NULL || prefix[0] == '\0') {
249  prefix = "generic";
250  }
251  SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
252  ret = -1;
253  } else {
254  break;
255  }
256  }
257  return ret;
258 }
259 
260 #if 0
261 #define GL_CheckError(prefix, renderer)
262 #elif defined(_MSC_VER)
263 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __FUNCTION__)
264 #else
265 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __PRETTY_FUNCTION__)
266 #endif
267 
268 
269 /*************************************************************************************************
270  * Renderer state APIs *
271  *************************************************************************************************/
272 
273 static int GLES2_ActivateRenderer(SDL_Renderer *renderer);
274 static void GLES2_WindowEvent(SDL_Renderer * renderer,
275  const SDL_WindowEvent *event);
276 static int GLES2_UpdateViewport(SDL_Renderer * renderer);
277 static void GLES2_DestroyRenderer(SDL_Renderer *renderer);
278 static int GLES2_SetOrthographicProjection(SDL_Renderer *renderer);
279 
280 
281 static SDL_GLContext SDL_CurrentContext = NULL;
282 
283 static int GLES2_LoadFunctions(GLES2_DriverContext * data)
284 {
285 #if SDL_VIDEO_DRIVER_UIKIT
286 #define __SDL_NOGETPROCADDR__
287 #elif SDL_VIDEO_DRIVER_ANDROID
288 #define __SDL_NOGETPROCADDR__
289 #elif SDL_VIDEO_DRIVER_PANDORA
290 #define __SDL_NOGETPROCADDR__
291 #endif
292 
293 #if defined __SDL_NOGETPROCADDR__
294 #define SDL_PROC(ret,func,params) data->func=func;
295 #else
296 #define SDL_PROC(ret,func,params) \
297  do { \
298  data->func = SDL_GL_GetProcAddress(#func); \
299  if ( ! data->func ) { \
300  return SDL_SetError("Couldn't load GLES2 function %s: %s\n", #func, SDL_GetError()); \
301  } \
302  } while ( 0 );
303 #endif /* __SDL_NOGETPROCADDR__ */
304 
305 #include "SDL_gles2funcs.h"
306 #undef SDL_PROC
307  return 0;
308 }
309 
310 GLES2_FBOList *
311 GLES2_GetFBO(GLES2_DriverContext *data, Uint32 w, Uint32 h)
312 {
313  GLES2_FBOList *result = data->framebuffers;
314  while ((result) && ((result->w != w) || (result->h != h)) ) {
315  result = result->next;
316  }
317  if (result == NULL) {
318  result = SDL_malloc(sizeof(GLES2_FBOList));
319  result->w = w;
320  result->h = h;
321  data->glGenFramebuffers(1, &result->FBO);
322  result->next = data->framebuffers;
323  data->framebuffers = result;
324  }
325  return result;
326 }
327 
328 static int
329 GLES2_ActivateRenderer(SDL_Renderer * renderer)
330 {
331  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
332 
333  if (SDL_CurrentContext != data->context) {
334  /* Null out the current program to ensure we set it again */
335  data->current_program = NULL;
336 
337  if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
338  return -1;
339  }
340  SDL_CurrentContext = data->context;
341 
342  GLES2_UpdateViewport(renderer);
343  }
344 
345  GL_ClearErrors(renderer);
346 
347  return 0;
348 }
349 
350 static void
351 GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
352 {
353  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
354 
355  if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
356  event->event == SDL_WINDOWEVENT_SHOWN ||
357  event->event == SDL_WINDOWEVENT_HIDDEN) {
358  /* Rebind the context to the window area */
359  SDL_CurrentContext = NULL;
360  }
361 
362  if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
363  /* According to Apple documentation, we need to finish drawing NOW! */
364  data->glFinish();
365  }
366 }
367 
368 static int
369 GLES2_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
370 {
371  SDL_GL_GetDrawableSize(renderer->window, w, h);
372  return 0;
373 }
374 
375 static int
376 GLES2_UpdateViewport(SDL_Renderer * renderer)
377 {
378  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
379 
380  if (SDL_CurrentContext != data->context) {
381  /* We'll update the viewport after we rebind the context */
382  return 0;
383  }
384 
385  if (renderer->target) {
386  data->glViewport(renderer->viewport.x, renderer->viewport.y,
387  renderer->viewport.w, renderer->viewport.h);
388  } else {
389  int w, h;
390 
391  SDL_GetRendererOutputSize(renderer, &w, &h);
392  data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
393  renderer->viewport.w, renderer->viewport.h);
394  }
395 
396  if (data->current_program) {
397  GLES2_SetOrthographicProjection(renderer);
398  }
399  return GL_CheckError("", renderer);
400 }
401 
402 static int
403 GLES2_UpdateClipRect(SDL_Renderer * renderer)
404 {
405  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
406 
407  if (SDL_CurrentContext != data->context) {
408  /* We'll update the clip rect after we rebind the context */
409  return 0;
410  }
411 
412  if (renderer->clipping_enabled) {
413  const SDL_Rect *rect = &renderer->clip_rect;
414  data->glEnable(GL_SCISSOR_TEST);
415  if (renderer->target) {
416  data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h);
417  } else {
418  int w, h;
419 
420  SDL_GetRendererOutputSize(renderer, &w, &h);
421  data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
422  }
423  } else {
424  data->glDisable(GL_SCISSOR_TEST);
425  }
426  return 0;
427 }
428 
429 static void
430 GLES2_DestroyRenderer(SDL_Renderer *renderer)
431 {
432  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
433 
434  /* Deallocate everything */
435  if (data) {
436  GLES2_ActivateRenderer(renderer);
437 
438  {
439  GLES2_ShaderCacheEntry *entry;
440  GLES2_ShaderCacheEntry *next;
441  entry = data->shader_cache.head;
442  while (entry) {
443  data->glDeleteShader(entry->id);
444  next = entry->next;
445  SDL_free(entry);
446  entry = next;
447  }
448  }
449  {
450  GLES2_ProgramCacheEntry *entry;
451  GLES2_ProgramCacheEntry *next;
452  entry = data->program_cache.head;
453  while (entry) {
454  data->glDeleteProgram(entry->id);
455  next = entry->next;
456  SDL_free(entry);
457  entry = next;
458  }
459  }
460  if (data->context) {
461  while (data->framebuffers) {
462  GLES2_FBOList *nextnode = data->framebuffers->next;
463  data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
464  GL_CheckError("", renderer);
465  SDL_free(data->framebuffers);
466  data->framebuffers = nextnode;
467  }
468  SDL_GL_DeleteContext(data->context);
469  }
470  SDL_free(data->shader_formats);
471  SDL_free(data);
472  }
473  SDL_free(renderer);
474 }
475 
476 /*************************************************************************************************
477  * Texture APIs *
478  *************************************************************************************************/
479 
480 static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture);
481 static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
482  const void *pixels, int pitch);
483 static int GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
484  const SDL_Rect * rect,
485  const Uint8 *Yplane, int Ypitch,
486  const Uint8 *Uplane, int Upitch,
487  const Uint8 *Vplane, int Vpitch);
488 static int GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
489  void **pixels, int *pitch);
490 static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
491 static int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
492 static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
493 
494 static GLenum
495 GetScaleQuality(void)
496 {
497  const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
498 
499  if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
500  return GL_NEAREST;
501  } else {
502  return GL_LINEAR;
503  }
504 }
505 
506 static int
507 GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
508 {
509  GLES2_DriverContext *renderdata = (GLES2_DriverContext *)renderer->driverdata;
510  GLES2_TextureData *data;
511  GLenum format;
512  GLenum type;
513  GLenum scaleMode;
514 
515  GLES2_ActivateRenderer(renderer);
516 
517  /* Determine the corresponding GLES texture format params */
518  switch (texture->format)
519  {
524  format = GL_RGBA;
526  break;
533  break;
534  default:
535  return SDL_SetError("Texture format not supported");
536  }
537 
538  /* Allocate a texture struct */
539  data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
540  if (!data) {
541  return SDL_OutOfMemory();
542  }
543  data->texture = 0;
544  data->texture_type = GL_TEXTURE_2D;
545  data->pixel_format = format;
546  data->pixel_type = type;
547  data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
548  data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
549  data->texture_u = 0;
550  data->texture_v = 0;
551  scaleMode = GetScaleQuality();
552 
553  /* Allocate a blob for image renderdata */
554  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
555  size_t size;
556  data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
557  size = texture->h * data->pitch;
558  if (data->yuv) {
559  /* Need to add size for the U and V planes */
560  size += (2 * (texture->h * data->pitch) / 4);
561  }
562  if (data->nv12) {
563  /* Need to add size for the U/V plane */
564  size += ((texture->h * data->pitch) / 2);
565  }
566  data->pixel_data = SDL_calloc(1, size);
567  if (!data->pixel_data) {
568  SDL_free(data);
569  return SDL_OutOfMemory();
570  }
571  }
572 
573  /* Allocate the texture */
574  GL_CheckError("", renderer);
575 
576  if (data->yuv) {
577  renderdata->glGenTextures(1, &data->texture_v);
578  if (GL_CheckError("glGenTexures()", renderer) < 0) {
579  return -1;
580  }
581  renderdata->glActiveTexture(GL_TEXTURE2);
582  renderdata->glBindTexture(data->texture_type, data->texture_v);
583  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
584  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
585  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
586  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
587  renderdata->glTexImage2D(data->texture_type, 0, format, texture->w / 2, texture->h / 2, 0, format, type, NULL);
588 
589  renderdata->glGenTextures(1, &data->texture_u);
590  if (GL_CheckError("glGenTexures()", renderer) < 0) {
591  return -1;
592  }
593  renderdata->glActiveTexture(GL_TEXTURE1);
594  renderdata->glBindTexture(data->texture_type, data->texture_u);
595  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
596  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
597  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
598  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
599  renderdata->glTexImage2D(data->texture_type, 0, format, texture->w / 2, texture->h / 2, 0, format, type, NULL);
600  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
601  return -1;
602  }
603  }
604 
605  if (data->nv12) {
606  renderdata->glGenTextures(1, &data->texture_u);
607  if (GL_CheckError("glGenTexures()", renderer) < 0) {
608  return -1;
609  }
610  renderdata->glActiveTexture(GL_TEXTURE1);
611  renderdata->glBindTexture(data->texture_type, data->texture_u);
612  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
613  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
614  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
615  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
616  renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, texture->w / 2, texture->h / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
617  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
618  return -1;
619  }
620  }
621 
622  renderdata->glGenTextures(1, &data->texture);
623  if (GL_CheckError("glGenTexures()", renderer) < 0) {
624  return -1;
625  }
626  texture->driverdata = data;
627  renderdata->glActiveTexture(GL_TEXTURE0);
628  renderdata->glBindTexture(data->texture_type, data->texture);
629  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
630  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
631  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
632  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
633  renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
634  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
635  return -1;
636  }
637 
638  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
639  data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
640  } else {
641  data->fbo = NULL;
642  }
643 
644  return GL_CheckError("", renderer);
645 }
646 
647 static int
648 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)
649 {
650  Uint8 *blob = NULL;
651  Uint8 *src;
652  int src_pitch;
653  int y;
654 
655  /* Reformat the texture data into a tightly packed array */
656  src_pitch = width * bpp;
657  src = (Uint8 *)pixels;
658  if (pitch != src_pitch) {
659  blob = (Uint8 *)SDL_malloc(src_pitch * height);
660  if (!blob) {
661  return SDL_OutOfMemory();
662  }
663  src = blob;
664  for (y = 0; y < height; ++y)
665  {
666  SDL_memcpy(src, pixels, src_pitch);
667  src += src_pitch;
668  pixels = (Uint8 *)pixels + pitch;
669  }
670  src = blob;
671  }
672 
673  data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
674  if (blob) {
675  SDL_free(blob);
676  }
677  return 0;
678 }
679 
680 static int
681 GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
682  const void *pixels, int pitch)
683 {
684  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
685  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
686 
687  GLES2_ActivateRenderer(renderer);
688 
689  /* Bail out if we're supposed to update an empty rectangle */
690  if (rect->w <= 0 || rect->h <= 0) {
691  return 0;
692  }
693 
694  /* Create a texture subimage with the supplied data */
695  data->glBindTexture(tdata->texture_type, tdata->texture);
696  GLES2_TexSubImage2D(data, tdata->texture_type,
697  rect->x,
698  rect->y,
699  rect->w,
700  rect->h,
701  tdata->pixel_format,
702  tdata->pixel_type,
703  pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
704 
705  if (tdata->yuv) {
706  /* Skip to the correct offset into the next texture */
707  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
708  if (texture->format == SDL_PIXELFORMAT_YV12) {
709  data->glBindTexture(tdata->texture_type, tdata->texture_v);
710  } else {
711  data->glBindTexture(tdata->texture_type, tdata->texture_u);
712  }
713  GLES2_TexSubImage2D(data, tdata->texture_type,
714  rect->x / 2,
715  rect->y / 2,
716  rect->w / 2,
717  rect->h / 2,
718  tdata->pixel_format,
719  tdata->pixel_type,
720  pixels, pitch / 2, 1);
721 
722  /* Skip to the correct offset into the next texture */
723  pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);
724  if (texture->format == SDL_PIXELFORMAT_YV12) {
725  data->glBindTexture(tdata->texture_type, tdata->texture_u);
726  } else {
727  data->glBindTexture(tdata->texture_type, tdata->texture_v);
728  }
729  GLES2_TexSubImage2D(data, tdata->texture_type,
730  rect->x / 2,
731  rect->y / 2,
732  rect->w / 2,
733  rect->h / 2,
734  tdata->pixel_format,
735  tdata->pixel_type,
736  pixels, pitch / 2, 1);
737  }
738 
739  if (tdata->nv12) {
740  /* Skip to the correct offset into the next texture */
741  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
742  data->glBindTexture(tdata->texture_type, tdata->texture_u);
743  GLES2_TexSubImage2D(data, tdata->texture_type,
744  rect->x / 2,
745  rect->y / 2,
746  rect->w / 2,
747  rect->h / 2,
750  pixels, pitch, 2);
751  }
752 
753  return GL_CheckError("glTexSubImage2D()", renderer);
754 }
755 
756 static int
757 GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
758  const SDL_Rect * rect,
759  const Uint8 *Yplane, int Ypitch,
760  const Uint8 *Uplane, int Upitch,
761  const Uint8 *Vplane, int Vpitch)
762 {
763  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
764  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
765 
766  GLES2_ActivateRenderer(renderer);
767 
768  /* Bail out if we're supposed to update an empty rectangle */
769  if (rect->w <= 0 || rect->h <= 0) {
770  return 0;
771  }
772 
773  data->glBindTexture(tdata->texture_type, tdata->texture_v);
774  GLES2_TexSubImage2D(data, tdata->texture_type,
775  rect->x / 2,
776  rect->y / 2,
777  rect->w / 2,
778  rect->h / 2,
779  tdata->pixel_format,
780  tdata->pixel_type,
781  Vplane, Vpitch, 1);
782 
783  data->glBindTexture(tdata->texture_type, tdata->texture_u);
784  GLES2_TexSubImage2D(data, tdata->texture_type,
785  rect->x / 2,
786  rect->y / 2,
787  rect->w / 2,
788  rect->h / 2,
789  tdata->pixel_format,
790  tdata->pixel_type,
791  Uplane, Upitch, 1);
792 
793  data->glBindTexture(tdata->texture_type, tdata->texture);
794  GLES2_TexSubImage2D(data, tdata->texture_type,
795  rect->x,
796  rect->y,
797  rect->w,
798  rect->h,
799  tdata->pixel_format,
800  tdata->pixel_type,
801  Yplane, Ypitch, 1);
802 
803  return GL_CheckError("glTexSubImage2D()", renderer);
804 }
805 
806 static int
807 GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
808  void **pixels, int *pitch)
809 {
810  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
811 
812  /* Retrieve the buffer/pitch for the specified region */
813  *pixels = (Uint8 *)tdata->pixel_data +
814  (tdata->pitch * rect->y) +
815  (rect->x * SDL_BYTESPERPIXEL(texture->format));
816  *pitch = tdata->pitch;
817 
818  return 0;
819 }
820 
821 static void
822 GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
823 {
824  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
825  SDL_Rect rect;
826 
827  /* We do whole texture updates, at least for now */
828  rect.x = 0;
829  rect.y = 0;
830  rect.w = texture->w;
831  rect.h = texture->h;
832  GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
833 }
834 
835 static int
836 GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
837 {
838  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
839  GLES2_TextureData *texturedata = NULL;
840  GLenum status;
841 
842  if (texture == NULL) {
843  data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
844  } else {
845  texturedata = (GLES2_TextureData *) texture->driverdata;
846  data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
847  /* TODO: check if texture pixel format allows this operation */
848  data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
849  /* Check FBO status */
850  status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
851  if (status != GL_FRAMEBUFFER_COMPLETE) {
852  return SDL_SetError("glFramebufferTexture2D() failed");
853  }
854  }
855  return 0;
856 }
857 
858 static void
859 GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
860 {
861  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
862  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
863 
864  GLES2_ActivateRenderer(renderer);
865 
866  /* Destroy the texture */
867  if (tdata) {
868  data->glDeleteTextures(1, &tdata->texture);
869  if (tdata->texture_v) {
870  data->glDeleteTextures(1, &tdata->texture_v);
871  }
872  if (tdata->texture_u) {
873  data->glDeleteTextures(1, &tdata->texture_u);
874  }
875  SDL_free(tdata->pixel_data);
876  SDL_free(tdata);
877  texture->driverdata = NULL;
878  }
879 }
880 
881 /*************************************************************************************************
882  * Shader management functions *
883  *************************************************************************************************/
884 
885 static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type,
887 static void GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry);
888 static GLES2_ProgramCacheEntry *GLES2_CacheProgram(SDL_Renderer *renderer,
889  GLES2_ShaderCacheEntry *vertex,
890  GLES2_ShaderCacheEntry *fragment,
892 static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source,
894 
895 static GLES2_ProgramCacheEntry *
896 GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
897  GLES2_ShaderCacheEntry *fragment, SDL_BlendMode blendMode)
898 {
899  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
900  GLES2_ProgramCacheEntry *entry;
901  GLES2_ShaderCacheEntry *shaderEntry;
902  GLint linkSuccessful;
903 
904  /* Check if we've already cached this program */
905  entry = data->program_cache.head;
906  while (entry) {
907  if (entry->vertex_shader == vertex && entry->fragment_shader == fragment) {
908  break;
909  }
910  entry = entry->next;
911  }
912  if (entry) {
913  if (data->program_cache.head != entry) {
914  if (entry->next) {
915  entry->next->prev = entry->prev;
916  }
917  if (entry->prev) {
918  entry->prev->next = entry->next;
919  }
920  entry->prev = NULL;
921  entry->next = data->program_cache.head;
922  data->program_cache.head->prev = entry;
923  data->program_cache.head = entry;
924  }
925  return entry;
926  }
927 
928  /* Create a program cache entry */
929  entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry));
930  if (!entry) {
931  SDL_OutOfMemory();
932  return NULL;
933  }
934  entry->vertex_shader = vertex;
935  entry->fragment_shader = fragment;
936  entry->blend_mode = blendMode;
937 
938  /* Create the program and link it */
939  entry->id = data->glCreateProgram();
940  data->glAttachShader(entry->id, vertex->id);
941  data->glAttachShader(entry->id, fragment->id);
942  data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
943  data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
944  data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
945  data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
946  data->glLinkProgram(entry->id);
947  data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
948  if (!linkSuccessful) {
949  data->glDeleteProgram(entry->id);
950  SDL_free(entry);
951  SDL_SetError("Failed to link shader program");
952  return NULL;
953  }
954 
955  /* Predetermine locations of uniform variables */
956  entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
957  data->glGetUniformLocation(entry->id, "u_projection");
958  entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] =
959  data->glGetUniformLocation(entry->id, "u_texture_v");
960  entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] =
961  data->glGetUniformLocation(entry->id, "u_texture_u");
962  entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
963  data->glGetUniformLocation(entry->id, "u_texture");
964  entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
965  data->glGetUniformLocation(entry->id, "u_modulation");
966  entry->uniform_locations[GLES2_UNIFORM_COLOR] =
967  data->glGetUniformLocation(entry->id, "u_color");
968 
969  entry->modulation_r = entry->modulation_g = entry->modulation_b = entry->modulation_a = 255;
970  entry->color_r = entry->color_g = entry->color_b = entry->color_a = 255;
971 
972  data->glUseProgram(entry->id);
973  data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */
974  data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */
975  data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */
976  data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
977  data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0f, 1.0f, 1.0f, 1.0f);
978  data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
979 
980  /* Cache the linked program */
981  if (data->program_cache.head) {
982  entry->next = data->program_cache.head;
983  data->program_cache.head->prev = entry;
984  } else {
985  data->program_cache.tail = entry;
986  }
987  data->program_cache.head = entry;
988  ++data->program_cache.count;
989 
990  /* Increment the refcount of the shaders we're using */
991  ++vertex->references;
992  ++fragment->references;
993 
994  /* Evict the last entry from the cache if we exceed the limit */
995  if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
996  shaderEntry = data->program_cache.tail->vertex_shader;
997  if (--shaderEntry->references <= 0) {
998  GLES2_EvictShader(renderer, shaderEntry);
999  }
1000  shaderEntry = data->program_cache.tail->fragment_shader;
1001  if (--shaderEntry->references <= 0) {
1002  GLES2_EvictShader(renderer, shaderEntry);
1003  }
1004  data->glDeleteProgram(data->program_cache.tail->id);
1005  data->program_cache.tail = data->program_cache.tail->prev;
1006  SDL_free(data->program_cache.tail->next);
1007  data->program_cache.tail->next = NULL;
1008  --data->program_cache.count;
1009  }
1010  return entry;
1011 }
1012 
1013 static GLES2_ShaderCacheEntry *
1014 GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type, SDL_BlendMode blendMode)
1015 {
1016  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1017  const GLES2_Shader *shader;
1018  const GLES2_ShaderInstance *instance = NULL;
1019  GLES2_ShaderCacheEntry *entry = NULL;
1020  GLint compileSuccessful = GL_FALSE;
1021  int i, j;
1022 
1023  /* Find the corresponding shader */
1024  shader = GLES2_GetShader(type, blendMode);
1025  if (!shader) {
1026  SDL_SetError("No shader matching the requested characteristics was found");
1027  return NULL;
1028  }
1029 
1030  /* Find a matching shader instance that's supported on this hardware */
1031  for (i = 0; i < shader->instance_count && !instance; ++i) {
1032  for (j = 0; j < data->shader_format_count && !instance; ++j) {
1033  if (!shader->instances[i]) {
1034  continue;
1035  }
1036  if (shader->instances[i]->format != data->shader_formats[j]) {
1037  continue;
1038  }
1039  instance = shader->instances[i];
1040  }
1041  }
1042  if (!instance) {
1043  SDL_SetError("The specified shader cannot be loaded on the current platform");
1044  return NULL;
1045  }
1046 
1047  /* Check if we've already cached this shader */
1048  entry = data->shader_cache.head;
1049  while (entry) {
1050  if (entry->instance == instance) {
1051  break;
1052  }
1053  entry = entry->next;
1054  }
1055  if (entry) {
1056  return entry;
1057  }
1058 
1059  /* Create a shader cache entry */
1060  entry = (GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(GLES2_ShaderCacheEntry));
1061  if (!entry) {
1062  SDL_OutOfMemory();
1063  return NULL;
1064  }
1065  entry->type = type;
1066  entry->instance = instance;
1067 
1068  /* Compile or load the selected shader instance */
1069  entry->id = data->glCreateShader(instance->type);
1070  if (instance->format == (GLenum)-1) {
1071  data->glShaderSource(entry->id, 1, (const char **)&instance->data, NULL);
1072  data->glCompileShader(entry->id);
1073  data->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
1074  } else {
1075  data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
1076  compileSuccessful = GL_TRUE;
1077  }
1078  if (!compileSuccessful) {
1079  char *info = NULL;
1080  int length = 0;
1081 
1082  data->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
1083  if (length > 0) {
1084  info = SDL_stack_alloc(char, length);
1085  if (info) {
1086  data->glGetShaderInfoLog(entry->id, length, &length, info);
1087  }
1088  }
1089  if (info) {
1090  SDL_SetError("Failed to load the shader: %s", info);
1091  SDL_stack_free(info);
1092  } else {
1093  SDL_SetError("Failed to load the shader");
1094  }
1095  data->glDeleteShader(entry->id);
1096  SDL_free(entry);
1097  return NULL;
1098  }
1099 
1100  /* Link the shader entry in at the front of the cache */
1101  if (data->shader_cache.head) {
1102  entry->next = data->shader_cache.head;
1103  data->shader_cache.head->prev = entry;
1104  }
1105  data->shader_cache.head = entry;
1106  ++data->shader_cache.count;
1107  return entry;
1108 }
1109 
1110 static void
1111 GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry)
1112 {
1113  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1114 
1115  /* Unlink the shader from the cache */
1116  if (entry->next) {
1117  entry->next->prev = entry->prev;
1118  }
1119  if (entry->prev) {
1120  entry->prev->next = entry->next;
1121  }
1122  if (data->shader_cache.head == entry) {
1123  data->shader_cache.head = entry->next;
1124  }
1125  --data->shader_cache.count;
1126 
1127  /* Deallocate the shader */
1128  data->glDeleteShader(entry->id);
1129  SDL_free(entry);
1130 }
1131 
1132 static int
1133 GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendMode blendMode)
1134 {
1135  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1136  GLES2_ShaderCacheEntry *vertex = NULL;
1137  GLES2_ShaderCacheEntry *fragment = NULL;
1138  GLES2_ShaderType vtype, ftype;
1139  GLES2_ProgramCacheEntry *program;
1140 
1141  /* Select an appropriate shader pair for the specified modes */
1142  vtype = GLES2_SHADER_VERTEX_DEFAULT;
1143  switch (source) {
1144  case GLES2_IMAGESOURCE_SOLID:
1145  ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC;
1146  break;
1147  case GLES2_IMAGESOURCE_TEXTURE_ABGR:
1148  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC;
1149  break;
1150  case GLES2_IMAGESOURCE_TEXTURE_ARGB:
1151  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC;
1152  break;
1153  case GLES2_IMAGESOURCE_TEXTURE_RGB:
1154  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC;
1155  break;
1156  case GLES2_IMAGESOURCE_TEXTURE_BGR:
1157  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
1158  break;
1159  case GLES2_IMAGESOURCE_TEXTURE_YUV:
1160  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC;
1161  break;
1162  case GLES2_IMAGESOURCE_TEXTURE_NV12:
1163  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC;
1164  break;
1165  case GLES2_IMAGESOURCE_TEXTURE_NV21:
1166  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC;
1167  break;
1168  default:
1169  goto fault;
1170  }
1171 
1172  /* Load the requested shaders */
1173  vertex = GLES2_CacheShader(renderer, vtype, blendMode);
1174  if (!vertex) {
1175  goto fault;
1176  }
1177  fragment = GLES2_CacheShader(renderer, ftype, blendMode);
1178  if (!fragment) {
1179  goto fault;
1180  }
1181 
1182  /* Check if we need to change programs at all */
1183  if (data->current_program &&
1184  data->current_program->vertex_shader == vertex &&
1185  data->current_program->fragment_shader == fragment) {
1186  return 0;
1187  }
1188 
1189  /* Generate a matching program */
1190  program = GLES2_CacheProgram(renderer, vertex, fragment, blendMode);
1191  if (!program) {
1192  goto fault;
1193  }
1194 
1195  /* Select that program in OpenGL */
1196  data->glUseProgram(program->id);
1197 
1198  /* Set the current program */
1199  data->current_program = program;
1200 
1201  /* Activate an orthographic projection */
1202  if (GLES2_SetOrthographicProjection(renderer) < 0) {
1203  goto fault;
1204  }
1205 
1206  /* Clean up and return */
1207  return 0;
1208 fault:
1209  if (vertex && vertex->references <= 0) {
1210  GLES2_EvictShader(renderer, vertex);
1211  }
1212  if (fragment && fragment->references <= 0) {
1213  GLES2_EvictShader(renderer, fragment);
1214  }
1215  data->current_program = NULL;
1216  return -1;
1217 }
1218 
1219 static int
1220 GLES2_SetOrthographicProjection(SDL_Renderer *renderer)
1221 {
1222  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1223  GLfloat projection[4][4];
1224 
1225  if (!renderer->viewport.w || !renderer->viewport.h) {
1226  return 0;
1227  }
1228 
1229  /* Prepare an orthographic projection */
1230  projection[0][0] = 2.0f / renderer->viewport.w;
1231  projection[0][1] = 0.0f;
1232  projection[0][2] = 0.0f;
1233  projection[0][3] = 0.0f;
1234  projection[1][0] = 0.0f;
1235  if (renderer->target) {
1236  projection[1][1] = 2.0f / renderer->viewport.h;
1237  } else {
1238  projection[1][1] = -2.0f / renderer->viewport.h;
1239  }
1240  projection[1][2] = 0.0f;
1241  projection[1][3] = 0.0f;
1242  projection[2][0] = 0.0f;
1243  projection[2][1] = 0.0f;
1244  projection[2][2] = 0.0f;
1245  projection[2][3] = 0.0f;
1246  projection[3][0] = -1.0f;
1247  if (renderer->target) {
1248  projection[3][1] = -1.0f;
1249  } else {
1250  projection[3][1] = 1.0f;
1251  }
1252  projection[3][2] = 0.0f;
1253  projection[3][3] = 1.0f;
1254 
1255  /* Set the projection matrix */
1256  if (SDL_memcmp(data->current_program->projection, projection, sizeof (projection)) != 0) {
1257  const GLuint locProjection = data->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION];
1258  data->glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection);
1259  SDL_memcpy(data->current_program->projection, projection, sizeof (projection));
1260  }
1261 
1262  return 0;
1263 }
1264 
1265 /*************************************************************************************************
1266  * Rendering functions *
1267  *************************************************************************************************/
1268 
1269 static const float inv255f = 1.0f / 255.0f;
1270 
1271 static int GLES2_RenderClear(SDL_Renderer *renderer);
1272 static int GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
1273 static int GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
1274 static int GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count);
1275 static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
1276  const SDL_FRect *dstrect);
1277 static int GLES2_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1278  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1279  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
1280 static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1281  Uint32 pixel_format, void * pixels, int pitch);
1282 static void GLES2_RenderPresent(SDL_Renderer *renderer);
1283 
1284 static SDL_bool
1285 CompareColors(Uint8 r1, Uint8 g1, Uint8 b1, Uint8 a1,
1286  Uint8 r2, Uint8 g2, Uint8 b2, Uint8 a2)
1287 {
1288  Uint32 Pixel1, Pixel2;
1289  RGBA8888_FROM_RGBA(Pixel1, r1, g1, b1, a1);
1290  RGBA8888_FROM_RGBA(Pixel2, r2, g2, b2, a2);
1291  return (Pixel1 == Pixel2);
1292 }
1293 
1294 static int
1295 GLES2_RenderClear(SDL_Renderer * renderer)
1296 {
1297  Uint8 r, g, b, a;
1298 
1299  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1300 
1301  GLES2_ActivateRenderer(renderer);
1302 
1303  if (!CompareColors(data->clear_r, data->clear_g, data->clear_b, data->clear_a,
1304  renderer->r, renderer->g, renderer->b, renderer->a)) {
1305 
1306  /* Select the color to clear with */
1307  g = renderer->g;
1308  a = renderer->a;
1309 
1310  if (renderer->target &&
1311  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1312  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1313  r = renderer->b;
1314  b = renderer->r;
1315  } else {
1316  r = renderer->r;
1317  b = renderer->b;
1318  }
1319 
1320  data->glClearColor((GLfloat) r * inv255f,
1321  (GLfloat) g * inv255f,
1322  (GLfloat) b * inv255f,
1323  (GLfloat) a * inv255f);
1324  data->clear_r = renderer->r;
1325  data->clear_g = renderer->g;
1326  data->clear_b = renderer->b;
1327  data->clear_a = renderer->a;
1328  }
1329 
1330  data->glClear(GL_COLOR_BUFFER_BIT);
1331 
1332  return 0;
1333 }
1334 
1335 static void
1336 GLES2_SetBlendMode(GLES2_DriverContext *data, int blendMode)
1337 {
1338  if (blendMode != data->current.blendMode) {
1339  switch (blendMode) {
1340  default:
1341  case SDL_BLENDMODE_NONE:
1342  data->glDisable(GL_BLEND);
1343  break;
1344  case SDL_BLENDMODE_BLEND:
1345  data->glEnable(GL_BLEND);
1346  data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1347  break;
1348  case SDL_BLENDMODE_ADD:
1349  data->glEnable(GL_BLEND);
1350  data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
1351  break;
1352  case SDL_BLENDMODE_MOD:
1353  data->glEnable(GL_BLEND);
1354  data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
1355  break;
1356  }
1357  data->current.blendMode = blendMode;
1358  }
1359 }
1360 
1361 static void
1362 GLES2_SetTexCoords(GLES2_DriverContext * data, SDL_bool enabled)
1363 {
1364  if (enabled != data->current.tex_coords) {
1365  if (enabled) {
1366  data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1367  } else {
1368  data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1369  }
1370  data->current.tex_coords = enabled;
1371  }
1372 }
1373 
1374 static int
1375 GLES2_SetDrawingState(SDL_Renderer * renderer)
1376 {
1377  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1378  const int blendMode = renderer->blendMode;
1379  GLES2_ProgramCacheEntry *program;
1380  Uint8 r, g, b, a;
1381 
1382  GLES2_ActivateRenderer(renderer);
1383 
1384  GLES2_SetBlendMode(data, blendMode);
1385 
1386  GLES2_SetTexCoords(data, SDL_FALSE);
1387 
1388  /* Activate an appropriate shader and set the projection matrix */
1389  if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0) {
1390  return -1;
1391  }
1392 
1393  /* Select the color to draw with */
1394  g = renderer->g;
1395  a = renderer->a;
1396 
1397  if (renderer->target &&
1398  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1399  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1400  r = renderer->b;
1401  b = renderer->r;
1402  } else {
1403  r = renderer->r;
1404  b = renderer->b;
1405  }
1406 
1407  program = data->current_program;
1408  if (!CompareColors(program->color_r, program->color_g, program->color_b, program->color_a, r, g, b, a)) {
1409  /* Select the color to draw with */
1410  data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
1411  program->color_r = r;
1412  program->color_g = g;
1413  program->color_b = b;
1414  program->color_a = a;
1415  }
1416 
1417  return 0;
1418 }
1419 
1420 static int
1421 GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
1422  const void *vertexData, size_t dataSizeInBytes)
1423 {
1424  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1425 
1426 #if !SDL_GLES2_USE_VBOS
1427  data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData);
1428 #else
1429  if (!data->vertex_buffers[attr]) {
1430  data->glGenBuffers(1, &data->vertex_buffers[attr]);
1431  }
1432 
1433  data->glBindBuffer(GL_ARRAY_BUFFER, data->vertex_buffers[attr]);
1434 
1435  if (data->vertex_buffer_size[attr] < dataSizeInBytes) {
1436  data->glBufferData(GL_ARRAY_BUFFER, dataSizeInBytes, vertexData, GL_STREAM_DRAW);
1437  data->vertex_buffer_size[attr] = dataSizeInBytes;
1438  } else {
1439  data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
1440  }
1441 
1442  data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0);
1443 #endif
1444 
1445  return 0;
1446 }
1447 
1448 static int
1449 GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
1450 {
1451  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1452  GLfloat *vertices;
1453  int idx;
1454 
1455  if (GLES2_SetDrawingState(renderer) < 0) {
1456  return -1;
1457  }
1458 
1459  /* Emit the specified vertices as points */
1460  vertices = SDL_stack_alloc(GLfloat, count * 2);
1461  for (idx = 0; idx < count; ++idx) {
1462  GLfloat x = points[idx].x + 0.5f;
1463  GLfloat y = points[idx].y + 0.5f;
1464 
1465  vertices[idx * 2] = x;
1466  vertices[(idx * 2) + 1] = y;
1467  }
1468  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1469  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
1470  data->glDrawArrays(GL_POINTS, 0, count);
1471  SDL_stack_free(vertices);
1472  return 0;
1473 }
1474 
1475 static int
1476 GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
1477 {
1478  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1479  GLfloat *vertices;
1480  int idx;
1481 
1482  if (GLES2_SetDrawingState(renderer) < 0) {
1483  return -1;
1484  }
1485 
1486  /* Emit a line strip including the specified vertices */
1487  vertices = SDL_stack_alloc(GLfloat, count * 2);
1488  for (idx = 0; idx < count; ++idx) {
1489  GLfloat x = points[idx].x + 0.5f;
1490  GLfloat y = points[idx].y + 0.5f;
1491 
1492  vertices[idx * 2] = x;
1493  vertices[(idx * 2) + 1] = y;
1494  }
1495  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1496  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
1497  data->glDrawArrays(GL_LINE_STRIP, 0, count);
1498 
1499  /* We need to close the endpoint of the line */
1500  if (count == 2 ||
1501  points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
1502  data->glDrawArrays(GL_POINTS, count-1, 1);
1503  }
1504  SDL_stack_free(vertices);
1505 
1506  return GL_CheckError("", renderer);
1507 }
1508 
1509 static int
1510 GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
1511 {
1512  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1513  GLfloat vertices[8];
1514  int idx;
1515 
1516  if (GLES2_SetDrawingState(renderer) < 0) {
1517  return -1;
1518  }
1519 
1520  /* Emit a line loop for each rectangle */
1521  for (idx = 0; idx < count; ++idx) {
1522  const SDL_FRect *rect = &rects[idx];
1523 
1524  GLfloat xMin = rect->x;
1525  GLfloat xMax = (rect->x + rect->w);
1526  GLfloat yMin = rect->y;
1527  GLfloat yMax = (rect->y + rect->h);
1528 
1529  vertices[0] = xMin;
1530  vertices[1] = yMin;
1531  vertices[2] = xMax;
1532  vertices[3] = yMin;
1533  vertices[4] = xMin;
1534  vertices[5] = yMax;
1535  vertices[6] = xMax;
1536  vertices[7] = yMax;
1537  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1538  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
1539  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1540  }
1541  return GL_CheckError("", renderer);
1542 }
1543 
1544 static int
1545 GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
1546 {
1547  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1548  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
1549  GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1551  GLES2_ProgramCacheEntry *program;
1552  Uint8 r, g, b, a;
1553 
1554  /* Activate an appropriate shader and set the projection matrix */
1555  blendMode = texture->blendMode;
1556  if (renderer->target) {
1557  /* Check if we need to do color mapping between the source and render target textures */
1558  if (renderer->target->format != texture->format) {
1559  switch (texture->format) {
1561  switch (renderer->target->format) {
1564  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1565  break;
1567  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1568  break;
1569  }
1570  break;
1572  switch (renderer->target->format) {
1575  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1576  break;
1578  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1579  break;
1580  }
1581  break;
1583  switch (renderer->target->format) {
1585  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1586  break;
1588  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1589  break;
1591  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1592  break;
1593  }
1594  break;
1596  switch (renderer->target->format) {
1598  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1599  break;
1601  sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1602  break;
1604  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1605  break;
1606  }
1607  break;
1608  case SDL_PIXELFORMAT_IYUV:
1609  case SDL_PIXELFORMAT_YV12:
1610  sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
1611  break;
1612  case SDL_PIXELFORMAT_NV12:
1613  sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
1614  break;
1615  case SDL_PIXELFORMAT_NV21:
1616  sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
1617  break;
1618  default:
1619  return SDL_SetError("Unsupported texture format");
1620  }
1621  } else {
1622  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
1623  }
1624  } else {
1625  switch (texture->format) {
1627  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1628  break;
1630  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1631  break;
1633  sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1634  break;
1636  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1637  break;
1638  case SDL_PIXELFORMAT_IYUV:
1639  case SDL_PIXELFORMAT_YV12:
1640  sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
1641  break;
1642  case SDL_PIXELFORMAT_NV12:
1643  sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
1644  break;
1645  case SDL_PIXELFORMAT_NV21:
1646  sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
1647  break;
1648  default:
1649  return SDL_SetError("Unsupported texture format");
1650  }
1651  }
1652 
1653  if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0) {
1654  return -1;
1655  }
1656 
1657  /* Select the target texture */
1658  if (tdata->yuv) {
1659  data->glActiveTexture(GL_TEXTURE2);
1660  data->glBindTexture(tdata->texture_type, tdata->texture_v);
1661 
1662  data->glActiveTexture(GL_TEXTURE1);
1663  data->glBindTexture(tdata->texture_type, tdata->texture_u);
1664 
1665  data->glActiveTexture(GL_TEXTURE0);
1666  }
1667  if (tdata->nv12) {
1668  data->glActiveTexture(GL_TEXTURE1);
1669  data->glBindTexture(tdata->texture_type, tdata->texture_u);
1670 
1671  data->glActiveTexture(GL_TEXTURE0);
1672  }
1673  data->glBindTexture(tdata->texture_type, tdata->texture);
1674 
1675  /* Configure color modulation */
1676  g = texture->g;
1677  a = texture->a;
1678 
1679  if (renderer->target &&
1680  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1681  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1682  r = texture->b;
1683  b = texture->r;
1684  } else {
1685  r = texture->r;
1686  b = texture->b;
1687  }
1688 
1689  program = data->current_program;
1690 
1691  if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
1692  data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
1693  program->modulation_r = r;
1694  program->modulation_g = g;
1695  program->modulation_b = b;
1696  program->modulation_a = a;
1697  }
1698 
1699  /* Configure texture blending */
1700  GLES2_SetBlendMode(data, blendMode);
1701 
1702  GLES2_SetTexCoords(data, SDL_TRUE);
1703  return 0;
1704 }
1705 
1706 static int
1707 GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
1708  const SDL_FRect *dstrect)
1709 {
1710  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1711  GLfloat vertices[8];
1712  GLfloat texCoords[8];
1713 
1714  GLES2_ActivateRenderer(renderer);
1715 
1716  if (GLES2_SetupCopy(renderer, texture) < 0) {
1717  return -1;
1718  }
1719 
1720  /* Emit the textured quad */
1721  vertices[0] = dstrect->x;
1722  vertices[1] = dstrect->y;
1723  vertices[2] = (dstrect->x + dstrect->w);
1724  vertices[3] = dstrect->y;
1725  vertices[4] = dstrect->x;
1726  vertices[5] = (dstrect->y + dstrect->h);
1727  vertices[6] = (dstrect->x + dstrect->w);
1728  vertices[7] = (dstrect->y + dstrect->h);
1729  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1730  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
1731  texCoords[0] = srcrect->x / (GLfloat)texture->w;
1732  texCoords[1] = srcrect->y / (GLfloat)texture->h;
1733  texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1734  texCoords[3] = srcrect->y / (GLfloat)texture->h;
1735  texCoords[4] = srcrect->x / (GLfloat)texture->w;
1736  texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1737  texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1738  texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1739  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
1740  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
1741  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1742 
1743  return GL_CheckError("", renderer);
1744 }
1745 
1746 static int
1747 GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
1748  const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1749 {
1750  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1751  GLfloat vertices[8];
1752  GLfloat texCoords[8];
1753  GLfloat translate[8];
1754  GLfloat fAngle[4];
1755  GLfloat tmp;
1756 
1757  GLES2_ActivateRenderer(renderer);
1758 
1759  if (GLES2_SetupCopy(renderer, texture) < 0) {
1760  return -1;
1761  }
1762 
1763  data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
1764  data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
1765  fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
1766  /* Calculate the center of rotation */
1767  translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
1768  translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
1769 
1770  /* Emit the textured quad */
1771  vertices[0] = dstrect->x;
1772  vertices[1] = dstrect->y;
1773  vertices[2] = (dstrect->x + dstrect->w);
1774  vertices[3] = dstrect->y;
1775  vertices[4] = dstrect->x;
1776  vertices[5] = (dstrect->y + dstrect->h);
1777  vertices[6] = (dstrect->x + dstrect->w);
1778  vertices[7] = (dstrect->y + dstrect->h);
1779  if (flip & SDL_FLIP_HORIZONTAL) {
1780  tmp = vertices[0];
1781  vertices[0] = vertices[4] = vertices[2];
1782  vertices[2] = vertices[6] = tmp;
1783  }
1784  if (flip & SDL_FLIP_VERTICAL) {
1785  tmp = vertices[1];
1786  vertices[1] = vertices[3] = vertices[5];
1787  vertices[5] = vertices[7] = tmp;
1788  }
1789 
1790  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
1791  data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
1792  data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1793 
1794  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat));
1795  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat));
1796  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
1797 
1798  texCoords[0] = srcrect->x / (GLfloat)texture->w;
1799  texCoords[1] = srcrect->y / (GLfloat)texture->h;
1800  texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1801  texCoords[3] = srcrect->y / (GLfloat)texture->h;
1802  texCoords[4] = srcrect->x / (GLfloat)texture->w;
1803  texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1804  texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1805  texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1806  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
1807  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
1808  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1809  data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
1810  data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
1811 
1812  return GL_CheckError("", renderer);
1813 }
1814 
1815 static int
1816 GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1817  Uint32 pixel_format, void * pixels, int pitch)
1818 {
1819  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1820  Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
1821  void *temp_pixels;
1822  int temp_pitch;
1823  Uint8 *src, *dst, *tmp;
1824  int w, h, length, rows;
1825  int status;
1826 
1827  GLES2_ActivateRenderer(renderer);
1828 
1829  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1830  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1831  if (!temp_pixels) {
1832  return SDL_OutOfMemory();
1833  }
1834 
1835  SDL_GetRendererOutputSize(renderer, &w, &h);
1836 
1837  data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
1838  GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
1839  if (GL_CheckError("glReadPixels()", renderer) < 0) {
1840  return -1;
1841  }
1842 
1843  /* Flip the rows to be top-down */
1844  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1845  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1846  dst = (Uint8*)temp_pixels;
1847  tmp = SDL_stack_alloc(Uint8, length);
1848  rows = rect->h / 2;
1849  while (rows--) {
1850  SDL_memcpy(tmp, dst, length);
1851  SDL_memcpy(dst, src, length);
1852  SDL_memcpy(src, tmp, length);
1853  dst += temp_pitch;
1854  src -= temp_pitch;
1855  }
1856  SDL_stack_free(tmp);
1857 
1858  status = SDL_ConvertPixels(rect->w, rect->h,
1859  temp_format, temp_pixels, temp_pitch,
1860  pixel_format, pixels, pitch);
1861  SDL_free(temp_pixels);
1862 
1863  return status;
1864 }
1865 
1866 static void
1867 GLES2_RenderPresent(SDL_Renderer *renderer)
1868 {
1869  GLES2_ActivateRenderer(renderer);
1870 
1871  /* Tell the video driver to swap buffers */
1872  SDL_GL_SwapWindow(renderer->window);
1873 }
1874 
1875 
1876 /*************************************************************************************************
1877  * Bind/unbinding of textures
1878  *************************************************************************************************/
1879 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
1880 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
1881 
1882 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
1883 {
1884  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1885  GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
1886  GLES2_ActivateRenderer(renderer);
1887 
1888  data->glBindTexture(texturedata->texture_type, texturedata->texture);
1889 
1890  if (texw) {
1891  *texw = 1.0;
1892  }
1893  if (texh) {
1894  *texh = 1.0;
1895  }
1896 
1897  return 0;
1898 }
1899 
1900 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
1901 {
1902  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1903  GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
1904  GLES2_ActivateRenderer(renderer);
1905 
1906  data->glBindTexture(texturedata->texture_type, 0);
1907 
1908  return 0;
1909 }
1910 
1911 
1912 /*************************************************************************************************
1913  * Renderer instantiation *
1914  *************************************************************************************************/
1915 
1916 #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
1917 
1918 static void
1919 GLES2_ResetState(SDL_Renderer *renderer)
1920 {
1921  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
1922 
1923  if (SDL_CurrentContext == data->context) {
1924  GLES2_UpdateViewport(renderer);
1925  } else {
1926  GLES2_ActivateRenderer(renderer);
1927  }
1928 
1929  data->current.blendMode = -1;
1930  data->current.tex_coords = SDL_FALSE;
1931 
1932  data->glActiveTexture(GL_TEXTURE0);
1933  data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1934  data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1935 
1936  data->glClearColor((GLfloat) data->clear_r * inv255f,
1937  (GLfloat) data->clear_g * inv255f,
1938  (GLfloat) data->clear_b * inv255f,
1939  (GLfloat) data->clear_a * inv255f);
1940 
1941  data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
1942  data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1943 
1944  GL_CheckError("", renderer);
1945 }
1946 
1947 static SDL_Renderer *
1948 GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
1949 {
1951  GLES2_DriverContext *data;
1952  GLint nFormats;
1953 #ifndef ZUNE_HD
1954  GLboolean hasCompiler;
1955 #endif
1956  Uint32 window_flags;
1957  GLint window_framebuffer;
1958  GLint value;
1959  int profile_mask = 0, major = 0, minor = 0;
1960  SDL_bool changed_window = SDL_FALSE;
1961 
1965 
1966  window_flags = SDL_GetWindowFlags(window);
1967  if (!(window_flags & SDL_WINDOW_OPENGL) ||
1968  profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
1969 
1970  changed_window = SDL_TRUE;
1972  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
1973  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
1974 
1975  if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
1976  goto error;
1977  }
1978  }
1979 
1980  /* Create the renderer struct */
1981  renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
1982  if (!renderer) {
1983  SDL_OutOfMemory();
1984  goto error;
1985  }
1986 
1987  data = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext));
1988  if (!data) {
1989  GLES2_DestroyRenderer(renderer);
1990  SDL_OutOfMemory();
1991  goto error;
1992  }
1993  renderer->info = GLES2_RenderDriver.info;
1995  renderer->driverdata = data;
1996  renderer->window = window;
1997 
1998  /* Create an OpenGL ES 2.0 context */
1999  data->context = SDL_GL_CreateContext(window);
2000  if (!data->context) {
2001  GLES2_DestroyRenderer(renderer);
2002  goto error;
2003  }
2004  if (SDL_GL_MakeCurrent(window, data->context) < 0) {
2005  GLES2_DestroyRenderer(renderer);
2006  goto error;
2007  }
2008 
2009  if (GLES2_LoadFunctions(data) < 0) {
2010  GLES2_DestroyRenderer(renderer);
2011  goto error;
2012  }
2013 
2014 #if __WINRT__
2015  /* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync
2016  * is turned on. Not doing so will freeze the screen's contents to that
2017  * of the first drawn frame.
2018  */
2019  flags |= SDL_RENDERER_PRESENTVSYNC;
2020 #endif
2021 
2022  if (flags & SDL_RENDERER_PRESENTVSYNC) {
2024  } else {
2026  }
2027  if (SDL_GL_GetSwapInterval() > 0) {
2028  renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
2029  }
2030 
2031  /* Check for debug output support */
2032  if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 &&
2033  (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
2034  data->debug_enabled = SDL_TRUE;
2035  }
2036 
2037  value = 0;
2038  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
2039  renderer->info.max_texture_width = value;
2040  value = 0;
2041  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
2042  renderer->info.max_texture_height = value;
2043 
2044  /* Determine supported shader formats */
2045  /* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
2046 #ifdef ZUNE_HD
2047  nFormats = 1;
2048 #else /* !ZUNE_HD */
2049  data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
2050  data->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
2051  if (hasCompiler) {
2052  ++nFormats;
2053  }
2054 #endif /* ZUNE_HD */
2055  data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum));
2056  if (!data->shader_formats) {
2057  GLES2_DestroyRenderer(renderer);
2058  SDL_OutOfMemory();
2059  goto error;
2060  }
2061  data->shader_format_count = nFormats;
2062 #ifdef ZUNE_HD
2063  data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
2064 #else /* !ZUNE_HD */
2065  data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats);
2066  if (hasCompiler) {
2067  data->shader_formats[nFormats - 1] = (GLenum)-1;
2068  }
2069 #endif /* ZUNE_HD */
2070 
2071  data->framebuffers = NULL;
2072  data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
2073  data->window_framebuffer = (GLuint)window_framebuffer;
2074 
2075  /* Populate the function pointers for the module */
2076  renderer->WindowEvent = &GLES2_WindowEvent;
2077  renderer->GetOutputSize = &GLES2_GetOutputSize;
2078  renderer->CreateTexture = &GLES2_CreateTexture;
2079  renderer->UpdateTexture = &GLES2_UpdateTexture;
2080  renderer->UpdateTextureYUV = &GLES2_UpdateTextureYUV;
2081  renderer->LockTexture = &GLES2_LockTexture;
2082  renderer->UnlockTexture = &GLES2_UnlockTexture;
2083  renderer->SetRenderTarget = &GLES2_SetRenderTarget;
2084  renderer->UpdateViewport = &GLES2_UpdateViewport;
2085  renderer->UpdateClipRect = &GLES2_UpdateClipRect;
2086  renderer->RenderClear = &GLES2_RenderClear;
2087  renderer->RenderDrawPoints = &GLES2_RenderDrawPoints;
2088  renderer->RenderDrawLines = &GLES2_RenderDrawLines;
2089  renderer->RenderFillRects = &GLES2_RenderFillRects;
2090  renderer->RenderCopy = &GLES2_RenderCopy;
2091  renderer->RenderCopyEx = &GLES2_RenderCopyEx;
2092  renderer->RenderReadPixels = &GLES2_RenderReadPixels;
2093  renderer->RenderPresent = &GLES2_RenderPresent;
2094  renderer->DestroyTexture = &GLES2_DestroyTexture;
2095  renderer->DestroyRenderer = &GLES2_DestroyRenderer;
2096  renderer->GL_BindTexture = &GLES2_BindTexture;
2097  renderer->GL_UnbindTexture = &GLES2_UnbindTexture;
2098 
2103 
2104  GLES2_ResetState(renderer);
2105 
2106  return renderer;
2107 
2108 error:
2109  if (changed_window) {
2110  /* Uh oh, better try to put it back... */
2114  SDL_RecreateWindow(window, window_flags);
2115  }
2116  return NULL;
2117 }
2118 
2119 #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
2120 
2121 /* vi: set ts=4 sw=4 expandtab: */
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
#define GL_ONE
Definition: SDL_opengl.h:394
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:57
GLint GLint xoffset
Definition: SDL_opengl.h:1566
GLenum GLenum dst
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1565
GLuint id
#define GL_INVALID_ENUM
Definition: SDL_opengl.h:713
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_sysrender.h:97
#define GL_FALSE
Definition: SDL_opengl.h:192
#define GL_INVALID_OPERATION
Definition: SDL_opengl.h:715
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2072
GLuint64EXT * result
#define GL_SCISSOR_TEST
Definition: SDL_opengl.h:608
GLint GLint GLsizei width
Definition: SDL_opengl.h:1565
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:155
#define SDL_GL_CreateContext
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
const GLuint * framebuffers
SDL_RendererInfo info
#define GL_ARRAY_BUFFER
#define GL_TRUE
Definition: SDL_opengl.h:193
#define GL_COLOR_ATTACHMENT0
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
#define GL_COMPILE_STATUS
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1564
SDL_Rect rect
Definition: testrelative.c:27
SDL_Window * window
#define GL_LINEAR
Definition: SDL_opengl.h:440
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:131
#define GL_CLAMP_TO_EDGE
Definition: SDL_opengl.h:1500
GLenum GLenum GLuint texture
#define GL_SHADER_COMPILER
void * driverdata
int GLint
Definition: SDL_opengl.h:175
#define GL_RGBA
Definition: SDL_opengl.h:522
#define GL_STREAM_DRAW
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
Uint32 texture_formats[16]
Definition: SDL_render.h:83
#define SDL_GetHint
#define SDL_GetWindowFlags
GLfloat f
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:127
#define GL_TEXTURE_MAG_FILTER
Definition: SDL_opengl.h:667
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1565
SDL_Rect clip_rect
#define GL_TRIANGLE_STRIP
Definition: SDL_opengl.h:214
#define GL_LINK_STATUS
float GLfloat
Definition: SDL_opengl.h:180
#define SDL_strcasecmp
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1565
int max_texture_height
Definition: SDL_render.h:85
#define GL_FRAMEBUFFER_COMPLETE
#define GL_ONE_MINUS_SRC_ALPHA
Definition: SDL_opengl.h:398
#define SDL_FORCE_INLINE
Definition: begin_code.h:133
#define GL_LUMINANCE
Definition: SDL_opengl.h:503
GLsizeiptr size
SDL_Window * window
SDL_RendererInfo info
int(* RenderClear)(SDL_Renderer *renderer)
#define GL_FRAMEBUFFER
void(* DestroyRenderer)(SDL_Renderer *renderer)
GLfixed GLfixed GLint GLint GLfixed points
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
Definition: SDL_sysrender.h:81
#define GL_PACK_ALIGNMENT
Definition: SDL_opengl.h:645
#define GL_MAX_TEXTURE_SIZE
Definition: SDL_opengl.h:529
#define GL_NO_ERROR
Definition: SDL_opengl.h:712
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
#define GL_BLEND
Definition: SDL_opengl.h:390
SDL_bool
Definition: SDL_stdinc.h:126
GLboolean GLboolean g
#define GL_SRC_COLOR
Definition: SDL_opengl.h:395
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:89
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)
Definition: SDL_sysrender.h:92
SDL_Renderer * renderer
#define SDL_GL_SetAttribute
#define SDL_GL_GetDrawableSize
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1564
#define SDL_memcpy
void * SDL_calloc(size_t nmemb, size_t size)
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:164
#define SDL_GL_GetSwapInterval
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
SDL_Texture * target
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1469
GLsizei const GLfloat * value
static int GetScaleQuality(void)
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:139
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:324
struct _cl_event * event
SDL_BlendMode blendMode
#define SDL_GL_SetSwapInterval
#define GL_LINE_STRIP
Definition: SDL_opengl.h:212
void SDL_free(void *mem)
GLenum target
#define GL_TEXTURE_WRAP_T
Definition: SDL_opengl.h:666
#define SDL_memcmp
#define GL_LUMINANCE_ALPHA
Definition: SDL_opengl.h:504
#define GL_FLOAT
Definition: SDL_opengl.h:202
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
#define GL_TEXTURE_2D
Definition: SDL_opengl.h:664
#define GL_TEXTURE1
Definition: SDL_opengl.h:1768
#define GL_UNSIGNED_BYTE
Definition: SDL_opengl.h:197
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:99
GLsizei GLsizei GLchar * source
#define RGBA8888_FROM_RGBA(Pixel, r, g, b, a)
Definition: SDL_blit.h:240
int x
Definition: SDL_rect.h:66
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* UpdateViewport)(SDL_Renderer *renderer)
#define GL_COLOR_BUFFER_BIT
Definition: SDL_opengl.h:735
#define GL_INVALID_VALUE
Definition: SDL_opengl.h:714
int w
Definition: SDL_rect.h:67
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
GLenum GLenum GLsizei const GLuint GLboolean enabled
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Window state change event data (event.window.*)
Definition: SDL_events.h:171
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)
Definition: SDL_x11sym.h:42
unsigned int GLenum
Definition: SDL_opengl.h:169
#define GL_POINTS
Definition: SDL_opengl.h:209
#define NULL
Definition: begin_code.h:143
#define GL_FRAMEBUFFER_BINDING
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_EventEntry * tail
Definition: SDL_events.c:80
void GLvoid
Definition: SDL_opengl.h:172
unsigned int GLuint
Definition: SDL_opengl.h:178
#define SDL_SetError
#define GL_OUT_OF_MEMORY
Definition: SDL_opengl.h:718
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 SDL_GL_MakeCurrent
#define SDL_GetRendererOutputSize
SDL_Rect viewport
GLint GLint GLint yoffset
Definition: SDL_opengl.h:1566
int h
Definition: SDL_rect.h:67
The type used to identify a window.
Definition: SDL_sysvideo.h:71
unsigned char GLboolean
Definition: SDL_opengl.h:170
GLbitfield GLuint program
#define GL_ZERO
Definition: SDL_opengl.h:393
SDL_Rect rects[MAX_RECTS]
ptrdiff_t GLsizeiptr
#define GL_SRC_ALPHA
Definition: SDL_opengl.h:397
#define GL_NEAREST
Definition: SDL_opengl.h:697
#define GL_TEXTURE2
Definition: SDL_opengl.h:1769
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:80
#define GL_SHADER_BINARY_FORMATS
GLfloat angle
Uint32 pixel_format
Definition: testoverlay2.c:152
Uint32 num_texture_formats
Definition: SDL_render.h:82
Uint32 format
Definition: SDL_sysrender.h:52
#define GL_NUM_SHADER_BINARY_FORMATS
void * driverdata
Definition: SDL_sysrender.h:69
GLbitfield flags
#define SDL_malloc
#define SDL_GL_GetAttribute
GLubyte GLubyte GLubyte GLubyte w
#define SDL_ConvertPixels
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int GLsizei
Definition: SDL_opengl.h:179
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:82
void(* RenderPresent)(SDL_Renderer *renderer)
#define SDL_GL_DeleteContext
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:325
#define GL_TEXTURE_WRAP_S
Definition: SDL_opengl.h:665
SDL_EventEntry * head
Definition: SDL_events.c:79
GLuint GLsizei GLsizei * length
#define GL_TEXTURE_MIN_FILTER
Definition: SDL_opengl.h:668
GLboolean GLboolean GLboolean GLboolean a
#define GL_UNPACK_ALIGNMENT
Definition: SDL_opengl.h:651
int(* UpdateClipRect)(SDL_Renderer *renderer)
GLenum src
GLboolean GLboolean GLboolean b
#define GL_TEXTURE0
Definition: SDL_opengl.h:1767
int y
Definition: SDL_rect.h:66
#define SDL_GL_SwapWindow
GLfloat GLfloat GLfloat GLfloat h
SDL_bool clipping_enabled
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
GLuint shader
#define GL_INFO_LOG_LENGTH
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)
Definition: SDL_x11sym.h:42