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