SDL  2.0
SDL_render_gles2.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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_assert.h"
26 #include "SDL_hints.h"
27 #include "SDL_opengles2.h"
28 #include "../SDL_sysrender.h"
29 #include "../../video/SDL_blit.h"
30 #include "SDL_shaders_gles2.h"
31 
32 /* !!! FIXME: Emscripten makes these into WebGL calls, and WebGL doesn't offer
33  !!! FIXME: client-side arrays (without an Emscripten compatibility hack,
34  !!! FIXME: at least), but the current VBO code here is dramatically
35  !!! FIXME: slower on actual iOS devices, even though the iOS Simulator
36  !!! FIXME: is okay. Some time after 2.0.4 ships, we should revisit this,
37  !!! FIXME: fix the performance bottleneck, and make everything use VBOs.
38 */
39 #ifdef __EMSCRIPTEN__
40 #define SDL_GLES2_USE_VBOS 1
41 #else
42 #define SDL_GLES2_USE_VBOS 0
43 #endif
44 
45 /* To prevent unnecessary window recreation,
46  * these should match the defaults selected in SDL_GL_ResetAttributes
47  */
48 #define RENDERER_CONTEXT_MAJOR 2
49 #define RENDERER_CONTEXT_MINOR 0
50 
51 /* Used to re-create the window with OpenGL ES capability */
53 
54 /*************************************************************************************************
55  * Bootstrap data *
56  *************************************************************************************************/
57 
58 static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags);
59 
61  GLES2_CreateRenderer,
62  {
63  "opengles2",
65  4,
66  {
71  },
72  0,
73  0
74  }
75 };
76 
77 /*************************************************************************************************
78  * Context structures *
79  *************************************************************************************************/
80 
81 typedef struct GLES2_FBOList GLES2_FBOList;
82 
83 struct GLES2_FBOList
84 {
85  Uint32 w, h;
86  GLuint FBO;
87  GLES2_FBOList *next;
88 };
89 
90 typedef struct GLES2_TextureData
91 {
93  GLenum texture_type;
94  GLenum pixel_format;
95  GLenum pixel_type;
96  void *pixel_data;
97  int pitch;
98  /* YUV texture support */
99  SDL_bool yuv;
100  SDL_bool nv12;
101  GLenum texture_v;
102  GLenum texture_u;
103  GLES2_FBOList *fbo;
104 } GLES2_TextureData;
105 
106 typedef struct GLES2_ShaderCacheEntry
107 {
108  GLuint id;
109  GLES2_ShaderType type;
110  const GLES2_ShaderInstance *instance;
111  int references;
112  Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
113  struct GLES2_ShaderCacheEntry *prev;
114  struct GLES2_ShaderCacheEntry *next;
115 } GLES2_ShaderCacheEntry;
116 
117 typedef struct GLES2_ShaderCache
118 {
119  int count;
120  GLES2_ShaderCacheEntry *head;
121 } GLES2_ShaderCache;
122 
123 typedef struct GLES2_ProgramCacheEntry
124 {
125  GLuint id;
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_TEXTURE_EXTERNAL_OES
172 } GLES2_ImageSource;
173 
174 typedef struct GLES2_DriverContext
175 {
177 
178  SDL_bool debug_enabled;
179 
180  struct {
182  SDL_bool tex_coords;
183  } current;
184 
185 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
186 #include "SDL_gles2funcs.h"
187 #undef SDL_PROC
188  GLES2_FBOList *framebuffers;
189  GLuint window_framebuffer;
190 
191  int shader_format_count;
192  GLenum *shader_formats;
193  GLES2_ShaderCache shader_cache;
194  GLES2_ProgramCache program_cache;
195  GLES2_ProgramCacheEntry *current_program;
196  Uint8 clear_r, clear_g, clear_b, clear_a;
197 
198 #if SDL_GLES2_USE_VBOS
199  GLuint vertex_buffers[4];
200  GLsizeiptr vertex_buffer_size[4];
201 #endif
202 } GLES2_DriverContext;
203 
204 #define GLES2_MAX_CACHED_PROGRAMS 8
205 
206 
207 SDL_FORCE_INLINE const char*
208 GL_TranslateError (GLenum error)
209 {
210 #define GL_ERROR_TRANSLATE(e) case e: return #e;
211  switch (error) {
212  GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
213  GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
214  GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
215  GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
216  GL_ERROR_TRANSLATE(GL_NO_ERROR)
217  default:
218  return "UNKNOWN";
219 }
220 #undef GL_ERROR_TRANSLATE
221 }
222 
223 SDL_FORCE_INLINE void
224 GL_ClearErrors(SDL_Renderer *renderer)
225 {
226  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
227 
228  if (!data->debug_enabled) {
229  return;
230  }
231  while (data->glGetError() != GL_NO_ERROR) {
232  continue;
233  }
234 }
235 
237 GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
238 {
239  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
240  int ret = 0;
241 
242  if (!data->debug_enabled) {
243  return 0;
244  }
245  /* check gl errors (can return multiple errors) */
246  for (;;) {
247  GLenum error = data->glGetError();
248  if (error != GL_NO_ERROR) {
249  if (prefix == NULL || prefix[0] == '\0') {
250  prefix = "generic";
251  }
252  SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
253  ret = -1;
254  } else {
255  break;
256  }
257  }
258  return ret;
259 }
260 
261 #if 0
262 #define GL_CheckError(prefix, renderer)
263 #else
264 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_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 #ifdef GL_TEXTURE_EXTERNAL_OES
598  format = GL_NONE;
599  type = GL_NONE;
600  break;
601 #endif
602  default:
603  return SDL_SetError("Texture format not supported");
604  }
605 
606  if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES &&
607  texture->access != SDL_TEXTUREACCESS_STATIC) {
608  return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES");
609  }
610 
611  /* Allocate a texture struct */
612  data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
613  if (!data) {
614  return SDL_OutOfMemory();
615  }
616  data->texture = 0;
617 #ifdef GL_TEXTURE_EXTERNAL_OES
618  data->texture_type = (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
619 #else
620  data->texture_type = GL_TEXTURE_2D;
621 #endif
622  data->pixel_format = format;
623  data->pixel_type = type;
624  data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
625  data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
626  data->texture_u = 0;
627  data->texture_v = 0;
628  scaleMode = GetScaleQuality();
629 
630  /* Allocate a blob for image renderdata */
631  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
632  size_t size;
633  data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
634  size = texture->h * data->pitch;
635  if (data->yuv) {
636  /* Need to add size for the U and V planes */
637  size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
638  }
639  if (data->nv12) {
640  /* Need to add size for the U/V plane */
641  size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
642  }
643  data->pixel_data = SDL_calloc(1, size);
644  if (!data->pixel_data) {
645  SDL_free(data);
646  return SDL_OutOfMemory();
647  }
648  }
649 
650  /* Allocate the texture */
651  GL_CheckError("", renderer);
652 
653  if (data->yuv) {
654  renderdata->glGenTextures(1, &data->texture_v);
655  if (GL_CheckError("glGenTexures()", renderer) < 0) {
656  return -1;
657  }
658  renderdata->glActiveTexture(GL_TEXTURE2);
659  renderdata->glBindTexture(data->texture_type, data->texture_v);
660  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
661  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
662  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
663  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
664  renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
665 
666  renderdata->glGenTextures(1, &data->texture_u);
667  if (GL_CheckError("glGenTexures()", renderer) < 0) {
668  return -1;
669  }
670  renderdata->glActiveTexture(GL_TEXTURE1);
671  renderdata->glBindTexture(data->texture_type, data->texture_u);
672  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
673  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
674  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
675  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
676  renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
677  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
678  return -1;
679  }
680  }
681 
682  if (data->nv12) {
683  renderdata->glGenTextures(1, &data->texture_u);
684  if (GL_CheckError("glGenTexures()", renderer) < 0) {
685  return -1;
686  }
687  renderdata->glActiveTexture(GL_TEXTURE1);
688  renderdata->glBindTexture(data->texture_type, data->texture_u);
689  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
690  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
691  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
692  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
693  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);
694  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
695  return -1;
696  }
697  }
698 
699  renderdata->glGenTextures(1, &data->texture);
700  if (GL_CheckError("glGenTexures()", renderer) < 0) {
701  return -1;
702  }
703  texture->driverdata = data;
704  renderdata->glActiveTexture(GL_TEXTURE0);
705  renderdata->glBindTexture(data->texture_type, data->texture);
706  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
707  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
708  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
709  renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
710  if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
711  renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
712  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
713  return -1;
714  }
715  }
716 
717  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
718  data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
719  } else {
720  data->fbo = NULL;
721  }
722 
723  return GL_CheckError("", renderer);
724 }
725 
726 static int
727 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)
728 {
729  Uint8 *blob = NULL;
730  Uint8 *src;
731  int src_pitch;
732  int y;
733 
734  /* Reformat the texture data into a tightly packed array */
735  src_pitch = width * bpp;
736  src = (Uint8 *)pixels;
737  if (pitch != src_pitch) {
738  blob = (Uint8 *)SDL_malloc(src_pitch * height);
739  if (!blob) {
740  return SDL_OutOfMemory();
741  }
742  src = blob;
743  for (y = 0; y < height; ++y)
744  {
745  SDL_memcpy(src, pixels, src_pitch);
746  src += src_pitch;
747  pixels = (Uint8 *)pixels + pitch;
748  }
749  src = blob;
750  }
751 
752  data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
753  if (blob) {
754  SDL_free(blob);
755  }
756  return 0;
757 }
758 
759 static int
760 GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
761  const void *pixels, int pitch)
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  /* Create a texture subimage with the supplied data */
774  data->glBindTexture(tdata->texture_type, tdata->texture);
775  GLES2_TexSubImage2D(data, tdata->texture_type,
776  rect->x,
777  rect->y,
778  rect->w,
779  rect->h,
780  tdata->pixel_format,
781  tdata->pixel_type,
782  pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
783 
784  if (tdata->yuv) {
785  /* Skip to the correct offset into the next texture */
786  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
787  if (texture->format == SDL_PIXELFORMAT_YV12) {
788  data->glBindTexture(tdata->texture_type, tdata->texture_v);
789  } else {
790  data->glBindTexture(tdata->texture_type, tdata->texture_u);
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  /* Skip to the correct offset into the next texture */
803  pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2));
804  if (texture->format == SDL_PIXELFORMAT_YV12) {
805  data->glBindTexture(tdata->texture_type, tdata->texture_u);
806  } else {
807  data->glBindTexture(tdata->texture_type, tdata->texture_v);
808  }
809  GLES2_TexSubImage2D(data, tdata->texture_type,
810  rect->x / 2,
811  rect->y / 2,
812  (rect->w + 1) / 2,
813  (rect->h + 1) / 2,
814  tdata->pixel_format,
815  tdata->pixel_type,
816  pixels, (pitch + 1) / 2, 1);
817  }
818 
819  if (tdata->nv12) {
820  /* Skip to the correct offset into the next texture */
821  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
822  data->glBindTexture(tdata->texture_type, tdata->texture_u);
823  GLES2_TexSubImage2D(data, tdata->texture_type,
824  rect->x / 2,
825  rect->y / 2,
826  (rect->w + 1) / 2,
827  (rect->h + 1) / 2,
830  pixels, 2 * ((pitch + 1) / 2), 2);
831  }
832 
833  return GL_CheckError("glTexSubImage2D()", renderer);
834 }
835 
836 static int
837 GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
838  const SDL_Rect * rect,
839  const Uint8 *Yplane, int Ypitch,
840  const Uint8 *Uplane, int Upitch,
841  const Uint8 *Vplane, int Vpitch)
842 {
843  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
844  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
845 
846  GLES2_ActivateRenderer(renderer);
847 
848  /* Bail out if we're supposed to update an empty rectangle */
849  if (rect->w <= 0 || rect->h <= 0) {
850  return 0;
851  }
852 
853  data->glBindTexture(tdata->texture_type, tdata->texture_v);
854  GLES2_TexSubImage2D(data, tdata->texture_type,
855  rect->x / 2,
856  rect->y / 2,
857  (rect->w + 1) / 2,
858  (rect->h + 1) / 2,
859  tdata->pixel_format,
860  tdata->pixel_type,
861  Vplane, Vpitch, 1);
862 
863  data->glBindTexture(tdata->texture_type, tdata->texture_u);
864  GLES2_TexSubImage2D(data, tdata->texture_type,
865  rect->x / 2,
866  rect->y / 2,
867  (rect->w + 1) / 2,
868  (rect->h + 1) / 2,
869  tdata->pixel_format,
870  tdata->pixel_type,
871  Uplane, Upitch, 1);
872 
873  data->glBindTexture(tdata->texture_type, tdata->texture);
874  GLES2_TexSubImage2D(data, tdata->texture_type,
875  rect->x,
876  rect->y,
877  rect->w,
878  rect->h,
879  tdata->pixel_format,
880  tdata->pixel_type,
881  Yplane, Ypitch, 1);
882 
883  return GL_CheckError("glTexSubImage2D()", renderer);
884 }
885 
886 static int
887 GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
888  void **pixels, int *pitch)
889 {
890  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
891 
892  /* Retrieve the buffer/pitch for the specified region */
893  *pixels = (Uint8 *)tdata->pixel_data +
894  (tdata->pitch * rect->y) +
895  (rect->x * SDL_BYTESPERPIXEL(texture->format));
896  *pitch = tdata->pitch;
897 
898  return 0;
899 }
900 
901 static void
902 GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
903 {
904  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
905  SDL_Rect rect;
906 
907  /* We do whole texture updates, at least for now */
908  rect.x = 0;
909  rect.y = 0;
910  rect.w = texture->w;
911  rect.h = texture->h;
912  GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
913 }
914 
915 static int
916 GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
917 {
918  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
919  GLES2_TextureData *texturedata = NULL;
920  GLenum status;
921 
922  if (texture == NULL) {
923  data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
924  } else {
925  texturedata = (GLES2_TextureData *) texture->driverdata;
926  data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
927  /* TODO: check if texture pixel format allows this operation */
928  data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
929  /* Check FBO status */
930  status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
931  if (status != GL_FRAMEBUFFER_COMPLETE) {
932  return SDL_SetError("glFramebufferTexture2D() failed");
933  }
934  }
935  return 0;
936 }
937 
938 static void
939 GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
940 {
941  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
942  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
943 
944  GLES2_ActivateRenderer(renderer);
945 
946  /* Destroy the texture */
947  if (tdata) {
948  data->glDeleteTextures(1, &tdata->texture);
949  if (tdata->texture_v) {
950  data->glDeleteTextures(1, &tdata->texture_v);
951  }
952  if (tdata->texture_u) {
953  data->glDeleteTextures(1, &tdata->texture_u);
954  }
955  SDL_free(tdata->pixel_data);
956  SDL_free(tdata);
957  texture->driverdata = NULL;
958  }
959 }
960 
961 /*************************************************************************************************
962  * Shader management functions *
963  *************************************************************************************************/
964 
965 static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type);
966 static void GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry);
967 static GLES2_ProgramCacheEntry *GLES2_CacheProgram(SDL_Renderer *renderer,
968  GLES2_ShaderCacheEntry *vertex,
969  GLES2_ShaderCacheEntry *fragment);
970 static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, int w, int h);
971 
972 static GLES2_ProgramCacheEntry *
973 GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
974  GLES2_ShaderCacheEntry *fragment)
975 {
976  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
977  GLES2_ProgramCacheEntry *entry;
978  GLES2_ShaderCacheEntry *shaderEntry;
979  GLint linkSuccessful;
980 
981  /* Check if we've already cached this program */
982  entry = data->program_cache.head;
983  while (entry) {
984  if (entry->vertex_shader == vertex && entry->fragment_shader == fragment) {
985  break;
986  }
987  entry = entry->next;
988  }
989  if (entry) {
990  if (data->program_cache.head != entry) {
991  if (entry->next) {
992  entry->next->prev = entry->prev;
993  }
994  if (entry->prev) {
995  entry->prev->next = entry->next;
996  }
997  entry->prev = NULL;
998  entry->next = data->program_cache.head;
999  data->program_cache.head->prev = entry;
1000  data->program_cache.head = entry;
1001  }
1002  return entry;
1003  }
1004 
1005  /* Create a program cache entry */
1006  entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry));
1007  if (!entry) {
1008  SDL_OutOfMemory();
1009  return NULL;
1010  }
1011  entry->vertex_shader = vertex;
1012  entry->fragment_shader = fragment;
1013 
1014  /* Create the program and link it */
1015  entry->id = data->glCreateProgram();
1016  data->glAttachShader(entry->id, vertex->id);
1017  data->glAttachShader(entry->id, fragment->id);
1018  data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
1019  data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
1020  data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
1021  data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
1022  data->glLinkProgram(entry->id);
1023  data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
1024  if (!linkSuccessful) {
1025  data->glDeleteProgram(entry->id);
1026  SDL_free(entry);
1027  SDL_SetError("Failed to link shader program");
1028  return NULL;
1029  }
1030 
1031  /* Predetermine locations of uniform variables */
1032  entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
1033  data->glGetUniformLocation(entry->id, "u_projection");
1034  entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] =
1035  data->glGetUniformLocation(entry->id, "u_texture_v");
1036  entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] =
1037  data->glGetUniformLocation(entry->id, "u_texture_u");
1038  entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
1039  data->glGetUniformLocation(entry->id, "u_texture");
1040  entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
1041  data->glGetUniformLocation(entry->id, "u_modulation");
1042  entry->uniform_locations[GLES2_UNIFORM_COLOR] =
1043  data->glGetUniformLocation(entry->id, "u_color");
1044 
1045  entry->modulation_r = entry->modulation_g = entry->modulation_b = entry->modulation_a = 255;
1046  entry->color_r = entry->color_g = entry->color_b = entry->color_a = 255;
1047 
1048  data->glUseProgram(entry->id);
1049  data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */
1050  data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */
1051  data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */
1052  data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
1053  data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0f, 1.0f, 1.0f, 1.0f);
1054  data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
1055 
1056  /* Cache the linked program */
1057  if (data->program_cache.head) {
1058  entry->next = data->program_cache.head;
1059  data->program_cache.head->prev = entry;
1060  } else {
1061  data->program_cache.tail = entry;
1062  }
1063  data->program_cache.head = entry;
1064  ++data->program_cache.count;
1065 
1066  /* Increment the refcount of the shaders we're using */
1067  ++vertex->references;
1068  ++fragment->references;
1069 
1070  /* Evict the last entry from the cache if we exceed the limit */
1071  if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
1072  shaderEntry = data->program_cache.tail->vertex_shader;
1073  if (--shaderEntry->references <= 0) {
1074  GLES2_EvictShader(renderer, shaderEntry);
1075  }
1076  shaderEntry = data->program_cache.tail->fragment_shader;
1077  if (--shaderEntry->references <= 0) {
1078  GLES2_EvictShader(renderer, shaderEntry);
1079  }
1080  data->glDeleteProgram(data->program_cache.tail->id);
1081  data->program_cache.tail = data->program_cache.tail->prev;
1082  SDL_free(data->program_cache.tail->next);
1083  data->program_cache.tail->next = NULL;
1084  --data->program_cache.count;
1085  }
1086  return entry;
1087 }
1088 
1089 static GLES2_ShaderCacheEntry *
1090 GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type)
1091 {
1092  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1093  const GLES2_Shader *shader;
1094  const GLES2_ShaderInstance *instance = NULL;
1095  GLES2_ShaderCacheEntry *entry = NULL;
1096  GLint compileSuccessful = GL_FALSE;
1097  int i, j;
1098 
1099  /* Find the corresponding shader */
1100  shader = GLES2_GetShader(type);
1101  if (!shader) {
1102  SDL_SetError("No shader matching the requested characteristics was found");
1103  return NULL;
1104  }
1105 
1106  /* Find a matching shader instance that's supported on this hardware */
1107  for (i = 0; i < shader->instance_count && !instance; ++i) {
1108  for (j = 0; j < data->shader_format_count && !instance; ++j) {
1109  if (!shader->instances[i]) {
1110  continue;
1111  }
1112  if (shader->instances[i]->format != data->shader_formats[j]) {
1113  continue;
1114  }
1115  instance = shader->instances[i];
1116  }
1117  }
1118  if (!instance) {
1119  SDL_SetError("The specified shader cannot be loaded on the current platform");
1120  return NULL;
1121  }
1122 
1123  /* Check if we've already cached this shader */
1124  entry = data->shader_cache.head;
1125  while (entry) {
1126  if (entry->instance == instance) {
1127  break;
1128  }
1129  entry = entry->next;
1130  }
1131  if (entry) {
1132  return entry;
1133  }
1134 
1135  /* Create a shader cache entry */
1136  entry = (GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(GLES2_ShaderCacheEntry));
1137  if (!entry) {
1138  SDL_OutOfMemory();
1139  return NULL;
1140  }
1141  entry->type = type;
1142  entry->instance = instance;
1143 
1144  /* Compile or load the selected shader instance */
1145  entry->id = data->glCreateShader(instance->type);
1146  if (instance->format == (GLenum)-1) {
1147  data->glShaderSource(entry->id, 1, (const char **)(char *)&instance->data, NULL);
1148  data->glCompileShader(entry->id);
1149  data->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
1150  } else {
1151  data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
1152  compileSuccessful = GL_TRUE;
1153  }
1154  if (!compileSuccessful) {
1155  char *info = NULL;
1156  int length = 0;
1157 
1158  data->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
1159  if (length > 0) {
1160  info = SDL_stack_alloc(char, length);
1161  if (info) {
1162  data->glGetShaderInfoLog(entry->id, length, &length, info);
1163  }
1164  }
1165  if (info) {
1166  SDL_SetError("Failed to load the shader: %s", info);
1167  SDL_stack_free(info);
1168  } else {
1169  SDL_SetError("Failed to load the shader");
1170  }
1171  data->glDeleteShader(entry->id);
1172  SDL_free(entry);
1173  return NULL;
1174  }
1175 
1176  /* Link the shader entry in at the front of the cache */
1177  if (data->shader_cache.head) {
1178  entry->next = data->shader_cache.head;
1179  data->shader_cache.head->prev = entry;
1180  }
1181  data->shader_cache.head = entry;
1182  ++data->shader_cache.count;
1183  return entry;
1184 }
1185 
1186 static void
1187 GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry)
1188 {
1189  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1190 
1191  /* Unlink the shader from the cache */
1192  if (entry->next) {
1193  entry->next->prev = entry->prev;
1194  }
1195  if (entry->prev) {
1196  entry->prev->next = entry->next;
1197  }
1198  if (data->shader_cache.head == entry) {
1199  data->shader_cache.head = entry->next;
1200  }
1201  --data->shader_cache.count;
1202 
1203  /* Deallocate the shader */
1204  data->glDeleteShader(entry->id);
1205  SDL_free(entry);
1206 }
1207 
1208 static int
1209 GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, int w, int h)
1210 {
1211  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1212  GLES2_ShaderCacheEntry *vertex = NULL;
1213  GLES2_ShaderCacheEntry *fragment = NULL;
1214  GLES2_ShaderType vtype, ftype;
1215  GLES2_ProgramCacheEntry *program;
1216 
1217  /* Select an appropriate shader pair for the specified modes */
1218  vtype = GLES2_SHADER_VERTEX_DEFAULT;
1219  switch (source) {
1220  case GLES2_IMAGESOURCE_SOLID:
1221  ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC;
1222  break;
1223  case GLES2_IMAGESOURCE_TEXTURE_ABGR:
1224  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC;
1225  break;
1226  case GLES2_IMAGESOURCE_TEXTURE_ARGB:
1227  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC;
1228  break;
1229  case GLES2_IMAGESOURCE_TEXTURE_RGB:
1230  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC;
1231  break;
1232  case GLES2_IMAGESOURCE_TEXTURE_BGR:
1233  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
1234  break;
1235  case GLES2_IMAGESOURCE_TEXTURE_YUV:
1236  switch (SDL_GetYUVConversionModeForResolution(w, h)) {
1238  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG_SRC;
1239  break;
1241  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601_SRC;
1242  break;
1244  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709_SRC;
1245  break;
1246  default:
1247  SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
1248  goto fault;
1249  }
1250  break;
1251  case GLES2_IMAGESOURCE_TEXTURE_NV12:
1252  switch (SDL_GetYUVConversionModeForResolution(w, h)) {
1254  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG_SRC;
1255  break;
1257  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601_SRC;
1258  break;
1260  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709_SRC;
1261  break;
1262  default:
1263  SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
1264  goto fault;
1265  }
1266  break;
1267  case GLES2_IMAGESOURCE_TEXTURE_NV21:
1268  switch (SDL_GetYUVConversionModeForResolution(w, h)) {
1270  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG_SRC;
1271  break;
1273  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601_SRC;
1274  break;
1276  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709_SRC;
1277  break;
1278  default:
1279  SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
1280  goto fault;
1281  }
1282  break;
1283  case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES:
1284  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC;
1285  break;
1286  default:
1287  goto fault;
1288  }
1289 
1290  /* Load the requested shaders */
1291  vertex = GLES2_CacheShader(renderer, vtype);
1292  if (!vertex) {
1293  goto fault;
1294  }
1295  fragment = GLES2_CacheShader(renderer, ftype);
1296  if (!fragment) {
1297  goto fault;
1298  }
1299 
1300  /* Check if we need to change programs at all */
1301  if (data->current_program &&
1302  data->current_program->vertex_shader == vertex &&
1303  data->current_program->fragment_shader == fragment) {
1304  return 0;
1305  }
1306 
1307  /* Generate a matching program */
1308  program = GLES2_CacheProgram(renderer, vertex, fragment);
1309  if (!program) {
1310  goto fault;
1311  }
1312 
1313  /* Select that program in OpenGL */
1314  data->glUseProgram(program->id);
1315 
1316  /* Set the current program */
1317  data->current_program = program;
1318 
1319  /* Activate an orthographic projection */
1320  if (GLES2_SetOrthographicProjection(renderer) < 0) {
1321  goto fault;
1322  }
1323 
1324  /* Clean up and return */
1325  return 0;
1326 fault:
1327  if (vertex && vertex->references <= 0) {
1328  GLES2_EvictShader(renderer, vertex);
1329  }
1330  if (fragment && fragment->references <= 0) {
1331  GLES2_EvictShader(renderer, fragment);
1332  }
1333  data->current_program = NULL;
1334  return -1;
1335 }
1336 
1337 static int
1338 GLES2_SetOrthographicProjection(SDL_Renderer *renderer)
1339 {
1340  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1341  GLfloat projection[4][4];
1342 
1343  if (!renderer->viewport.w || !renderer->viewport.h) {
1344  return 0;
1345  }
1346 
1347  /* Prepare an orthographic projection */
1348  projection[0][0] = 2.0f / renderer->viewport.w;
1349  projection[0][1] = 0.0f;
1350  projection[0][2] = 0.0f;
1351  projection[0][3] = 0.0f;
1352  projection[1][0] = 0.0f;
1353  if (renderer->target) {
1354  projection[1][1] = 2.0f / renderer->viewport.h;
1355  } else {
1356  projection[1][1] = -2.0f / renderer->viewport.h;
1357  }
1358  projection[1][2] = 0.0f;
1359  projection[1][3] = 0.0f;
1360  projection[2][0] = 0.0f;
1361  projection[2][1] = 0.0f;
1362  projection[2][2] = 0.0f;
1363  projection[2][3] = 0.0f;
1364  projection[3][0] = -1.0f;
1365  if (renderer->target) {
1366  projection[3][1] = -1.0f;
1367  } else {
1368  projection[3][1] = 1.0f;
1369  }
1370  projection[3][2] = 0.0f;
1371  projection[3][3] = 1.0f;
1372 
1373  /* Set the projection matrix */
1374  if (SDL_memcmp(data->current_program->projection, projection, sizeof (projection)) != 0) {
1375  const GLuint locProjection = data->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION];
1376  data->glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection);
1377  SDL_memcpy(data->current_program->projection, projection, sizeof (projection));
1378  }
1379 
1380  return 0;
1381 }
1382 
1383 /*************************************************************************************************
1384  * Rendering functions *
1385  *************************************************************************************************/
1386 
1387 static const float inv255f = 1.0f / 255.0f;
1388 
1389 static int GLES2_RenderClear(SDL_Renderer *renderer);
1390 static int GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
1391 static int GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
1392 static int GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count);
1393 static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
1394  const SDL_FRect *dstrect);
1395 static int GLES2_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1396  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1397  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
1398 static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1399  Uint32 pixel_format, void * pixels, int pitch);
1400 static void GLES2_RenderPresent(SDL_Renderer *renderer);
1401 
1402 static SDL_bool
1403 CompareColors(Uint8 r1, Uint8 g1, Uint8 b1, Uint8 a1,
1404  Uint8 r2, Uint8 g2, Uint8 b2, Uint8 a2)
1405 {
1406  Uint32 Pixel1, Pixel2;
1407  RGBA8888_FROM_RGBA(Pixel1, r1, g1, b1, a1);
1408  RGBA8888_FROM_RGBA(Pixel2, r2, g2, b2, a2);
1409  return (Pixel1 == Pixel2);
1410 }
1411 
1412 static int
1413 GLES2_RenderClear(SDL_Renderer * renderer)
1414 {
1415  Uint8 r, g, b, a;
1416 
1417  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1418 
1419  GLES2_ActivateRenderer(renderer);
1420 
1421  if (!CompareColors(data->clear_r, data->clear_g, data->clear_b, data->clear_a,
1422  renderer->r, renderer->g, renderer->b, renderer->a)) {
1423 
1424  /* Select the color to clear with */
1425  g = renderer->g;
1426  a = renderer->a;
1427 
1428  if (renderer->target &&
1429  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1430  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1431  r = renderer->b;
1432  b = renderer->r;
1433  } else {
1434  r = renderer->r;
1435  b = renderer->b;
1436  }
1437 
1438  data->glClearColor((GLfloat) r * inv255f,
1439  (GLfloat) g * inv255f,
1440  (GLfloat) b * inv255f,
1441  (GLfloat) a * inv255f);
1442  data->clear_r = renderer->r;
1443  data->clear_g = renderer->g;
1444  data->clear_b = renderer->b;
1445  data->clear_a = renderer->a;
1446  }
1447 
1448  if (renderer->clipping_enabled) {
1449  data->glDisable(GL_SCISSOR_TEST);
1450  }
1451 
1452  data->glClear(GL_COLOR_BUFFER_BIT);
1453 
1454  if (renderer->clipping_enabled) {
1455  data->glEnable(GL_SCISSOR_TEST);
1456  }
1457 
1458  return 0;
1459 }
1460 
1461 static void
1462 GLES2_SetBlendMode(GLES2_DriverContext *data, SDL_BlendMode blendMode)
1463 {
1464  if (blendMode != data->current.blendMode) {
1465  if (blendMode == SDL_BLENDMODE_NONE) {
1466  data->glDisable(GL_BLEND);
1467  } else {
1468  data->glEnable(GL_BLEND);
1469  data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
1470  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
1471  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
1472  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
1473  data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)),
1474  GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode)));
1475  }
1476  data->current.blendMode = blendMode;
1477  }
1478 }
1479 
1480 static void
1481 GLES2_SetTexCoords(GLES2_DriverContext * data, SDL_bool enabled)
1482 {
1483  if (enabled != data->current.tex_coords) {
1484  if (enabled) {
1485  data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1486  } else {
1487  data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1488  }
1489  data->current.tex_coords = enabled;
1490  }
1491 }
1492 
1493 static int
1494 GLES2_SetDrawingState(SDL_Renderer * renderer)
1495 {
1496  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1497  GLES2_ProgramCacheEntry *program;
1498  Uint8 r, g, b, a;
1499 
1500  GLES2_ActivateRenderer(renderer);
1501 
1502  GLES2_SetBlendMode(data, renderer->blendMode);
1503 
1504  GLES2_SetTexCoords(data, SDL_FALSE);
1505 
1506  /* Activate an appropriate shader and set the projection matrix */
1507  if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, 0, 0) < 0) {
1508  return -1;
1509  }
1510 
1511  /* Select the color to draw with */
1512  g = renderer->g;
1513  a = renderer->a;
1514 
1515  if (renderer->target &&
1516  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1517  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1518  r = renderer->b;
1519  b = renderer->r;
1520  } else {
1521  r = renderer->r;
1522  b = renderer->b;
1523  }
1524 
1525  program = data->current_program;
1526  if (!CompareColors(program->color_r, program->color_g, program->color_b, program->color_a, r, g, b, a)) {
1527  /* Select the color to draw with */
1528  data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
1529  program->color_r = r;
1530  program->color_g = g;
1531  program->color_b = b;
1532  program->color_a = a;
1533  }
1534 
1535  return 0;
1536 }
1537 
1538 static int
1539 GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
1540  const void *vertexData, size_t dataSizeInBytes)
1541 {
1542  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1543 
1544 #if !SDL_GLES2_USE_VBOS
1545  data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData);
1546 #else
1547  if (!data->vertex_buffers[attr]) {
1548  data->glGenBuffers(1, &data->vertex_buffers[attr]);
1549  }
1550 
1551  data->glBindBuffer(GL_ARRAY_BUFFER, data->vertex_buffers[attr]);
1552 
1553  if (data->vertex_buffer_size[attr] < dataSizeInBytes) {
1554  data->glBufferData(GL_ARRAY_BUFFER, dataSizeInBytes, vertexData, GL_STREAM_DRAW);
1555  data->vertex_buffer_size[attr] = dataSizeInBytes;
1556  } else {
1557  data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
1558  }
1559 
1560  data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0);
1561 #endif
1562 
1563  return 0;
1564 }
1565 
1566 static int
1567 GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
1568 {
1569  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1570  GLfloat *vertices;
1571  int idx;
1572 
1573  if (GLES2_SetDrawingState(renderer) < 0) {
1574  return -1;
1575  }
1576 
1577  /* Emit the specified vertices as points */
1578  vertices = SDL_stack_alloc(GLfloat, count * 2);
1579  for (idx = 0; idx < count; ++idx) {
1580  GLfloat x = points[idx].x + 0.5f;
1581  GLfloat y = points[idx].y + 0.5f;
1582 
1583  vertices[idx * 2] = x;
1584  vertices[(idx * 2) + 1] = y;
1585  }
1586  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1587  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
1588  data->glDrawArrays(GL_POINTS, 0, count);
1589  SDL_stack_free(vertices);
1590  return 0;
1591 }
1592 
1593 static int
1594 GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
1595 {
1596  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1597  GLfloat *vertices;
1598  int idx;
1599 
1600  if (GLES2_SetDrawingState(renderer) < 0) {
1601  return -1;
1602  }
1603 
1604  /* Emit a line strip including the specified vertices */
1605  vertices = SDL_stack_alloc(GLfloat, count * 2);
1606  for (idx = 0; idx < count; ++idx) {
1607  GLfloat x = points[idx].x + 0.5f;
1608  GLfloat y = points[idx].y + 0.5f;
1609 
1610  vertices[idx * 2] = x;
1611  vertices[(idx * 2) + 1] = y;
1612  }
1613  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1614  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
1615  data->glDrawArrays(GL_LINE_STRIP, 0, count);
1616 
1617  /* We need to close the endpoint of the line */
1618  if (count == 2 ||
1619  points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
1620  data->glDrawArrays(GL_POINTS, count-1, 1);
1621  }
1622  SDL_stack_free(vertices);
1623 
1624  return GL_CheckError("", renderer);
1625 }
1626 
1627 static int
1628 GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
1629 {
1630  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1631  GLfloat vertices[8];
1632  int idx;
1633 
1634  if (GLES2_SetDrawingState(renderer) < 0) {
1635  return -1;
1636  }
1637 
1638  /* Emit a line loop for each rectangle */
1639  for (idx = 0; idx < count; ++idx) {
1640  const SDL_FRect *rect = &rects[idx];
1641 
1642  GLfloat xMin = rect->x;
1643  GLfloat xMax = (rect->x + rect->w);
1644  GLfloat yMin = rect->y;
1645  GLfloat yMax = (rect->y + rect->h);
1646 
1647  vertices[0] = xMin;
1648  vertices[1] = yMin;
1649  vertices[2] = xMax;
1650  vertices[3] = yMin;
1651  vertices[4] = xMin;
1652  vertices[5] = yMax;
1653  vertices[6] = xMax;
1654  vertices[7] = yMax;
1655  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1656  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
1657  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1658  }
1659  return GL_CheckError("", renderer);
1660 }
1661 
1662 static int
1663 GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
1664 {
1665  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1666  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
1667  GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1668  GLES2_ProgramCacheEntry *program;
1669  Uint8 r, g, b, a;
1670 
1671  /* Activate an appropriate shader and set the projection matrix */
1672  if (renderer->target) {
1673  /* Check if we need to do color mapping between the source and render target textures */
1674  if (renderer->target->format != texture->format) {
1675  switch (texture->format) {
1677  switch (renderer->target->format) {
1680  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1681  break;
1683  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1684  break;
1685  }
1686  break;
1688  switch (renderer->target->format) {
1691  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1692  break;
1694  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1695  break;
1696  }
1697  break;
1699  switch (renderer->target->format) {
1701  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1702  break;
1704  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1705  break;
1707  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1708  break;
1709  }
1710  break;
1712  switch (renderer->target->format) {
1714  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1715  break;
1717  sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1718  break;
1720  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1721  break;
1722  }
1723  break;
1724  case SDL_PIXELFORMAT_IYUV:
1725  case SDL_PIXELFORMAT_YV12:
1726  sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
1727  break;
1728  case SDL_PIXELFORMAT_NV12:
1729  sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
1730  break;
1731  case SDL_PIXELFORMAT_NV21:
1732  sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
1733  break;
1735  sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
1736  break;
1737  default:
1738  return SDL_SetError("Unsupported texture format");
1739  }
1740  } else {
1741  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
1742  }
1743  } else {
1744  switch (texture->format) {
1746  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1747  break;
1749  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1750  break;
1752  sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1753  break;
1755  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1756  break;
1757  case SDL_PIXELFORMAT_IYUV:
1758  case SDL_PIXELFORMAT_YV12:
1759  sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
1760  break;
1761  case SDL_PIXELFORMAT_NV12:
1762  sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
1763  break;
1764  case SDL_PIXELFORMAT_NV21:
1765  sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
1766  break;
1768  sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
1769  break;
1770  default:
1771  return SDL_SetError("Unsupported texture format");
1772  }
1773  }
1774 
1775  if (GLES2_SelectProgram(renderer, sourceType, texture->w, texture->h) < 0) {
1776  return -1;
1777  }
1778 
1779  /* Select the target texture */
1780  if (tdata->yuv) {
1781  data->glActiveTexture(GL_TEXTURE2);
1782  data->glBindTexture(tdata->texture_type, tdata->texture_v);
1783 
1784  data->glActiveTexture(GL_TEXTURE1);
1785  data->glBindTexture(tdata->texture_type, tdata->texture_u);
1786 
1787  data->glActiveTexture(GL_TEXTURE0);
1788  }
1789  if (tdata->nv12) {
1790  data->glActiveTexture(GL_TEXTURE1);
1791  data->glBindTexture(tdata->texture_type, tdata->texture_u);
1792 
1793  data->glActiveTexture(GL_TEXTURE0);
1794  }
1795  data->glBindTexture(tdata->texture_type, tdata->texture);
1796 
1797  /* Configure color modulation */
1798  g = texture->g;
1799  a = texture->a;
1800 
1801  if (renderer->target &&
1802  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1803  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1804  r = texture->b;
1805  b = texture->r;
1806  } else {
1807  r = texture->r;
1808  b = texture->b;
1809  }
1810 
1811  program = data->current_program;
1812 
1813  if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
1814  data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
1815  program->modulation_r = r;
1816  program->modulation_g = g;
1817  program->modulation_b = b;
1818  program->modulation_a = a;
1819  }
1820 
1821  /* Configure texture blending */
1822  GLES2_SetBlendMode(data, texture->blendMode);
1823 
1824  GLES2_SetTexCoords(data, SDL_TRUE);
1825  return 0;
1826 }
1827 
1828 static int
1829 GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
1830  const SDL_FRect *dstrect)
1831 {
1832  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1833  GLfloat vertices[8];
1834  GLfloat texCoords[8];
1835 
1836  GLES2_ActivateRenderer(renderer);
1837 
1838  if (GLES2_SetupCopy(renderer, texture) < 0) {
1839  return -1;
1840  }
1841 
1842  /* Emit the textured quad */
1843  vertices[0] = dstrect->x;
1844  vertices[1] = dstrect->y;
1845  vertices[2] = (dstrect->x + dstrect->w);
1846  vertices[3] = dstrect->y;
1847  vertices[4] = dstrect->x;
1848  vertices[5] = (dstrect->y + dstrect->h);
1849  vertices[6] = (dstrect->x + dstrect->w);
1850  vertices[7] = (dstrect->y + dstrect->h);
1851  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1852  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
1853  texCoords[0] = srcrect->x / (GLfloat)texture->w;
1854  texCoords[1] = srcrect->y / (GLfloat)texture->h;
1855  texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1856  texCoords[3] = srcrect->y / (GLfloat)texture->h;
1857  texCoords[4] = srcrect->x / (GLfloat)texture->w;
1858  texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1859  texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1860  texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1861  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
1862  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
1863  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1864 
1865  return GL_CheckError("", renderer);
1866 }
1867 
1868 static int
1869 GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
1870  const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1871 {
1872  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1873  GLfloat vertices[8];
1874  GLfloat texCoords[8];
1875  GLfloat translate[8];
1876  GLfloat fAngle[4];
1877  GLfloat tmp;
1878 
1879  GLES2_ActivateRenderer(renderer);
1880 
1881  if (GLES2_SetupCopy(renderer, texture) < 0) {
1882  return -1;
1883  }
1884 
1885  data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
1886  data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
1887  fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
1888  /* Calculate the center of rotation */
1889  translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
1890  translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
1891 
1892  /* Emit the textured quad */
1893  vertices[0] = dstrect->x;
1894  vertices[1] = dstrect->y;
1895  vertices[2] = (dstrect->x + dstrect->w);
1896  vertices[3] = dstrect->y;
1897  vertices[4] = dstrect->x;
1898  vertices[5] = (dstrect->y + dstrect->h);
1899  vertices[6] = (dstrect->x + dstrect->w);
1900  vertices[7] = (dstrect->y + dstrect->h);
1901  if (flip & SDL_FLIP_HORIZONTAL) {
1902  tmp = vertices[0];
1903  vertices[0] = vertices[4] = vertices[2];
1904  vertices[2] = vertices[6] = tmp;
1905  }
1906  if (flip & SDL_FLIP_VERTICAL) {
1907  tmp = vertices[1];
1908  vertices[1] = vertices[3] = vertices[5];
1909  vertices[5] = vertices[7] = tmp;
1910  }
1911 
1912  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
1913  data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
1914  data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
1915 
1916  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat));
1917  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat));
1918  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
1919 
1920  texCoords[0] = srcrect->x / (GLfloat)texture->w;
1921  texCoords[1] = srcrect->y / (GLfloat)texture->h;
1922  texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1923  texCoords[3] = srcrect->y / (GLfloat)texture->h;
1924  texCoords[4] = srcrect->x / (GLfloat)texture->w;
1925  texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1926  texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1927  texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1928  /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
1929  GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
1930  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1931  data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
1932  data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
1933 
1934  return GL_CheckError("", renderer);
1935 }
1936 
1937 static int
1938 GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1939  Uint32 pixel_format, void * pixels, int pitch)
1940 {
1941  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1942  Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
1943  void *temp_pixels;
1944  int temp_pitch;
1945  Uint8 *src, *dst, *tmp;
1946  int w, h, length, rows;
1947  int status;
1948 
1949  GLES2_ActivateRenderer(renderer);
1950 
1951  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1952  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1953  if (!temp_pixels) {
1954  return SDL_OutOfMemory();
1955  }
1956 
1957  SDL_GetRendererOutputSize(renderer, &w, &h);
1958 
1959  data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
1960  rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
1961  if (GL_CheckError("glReadPixels()", renderer) < 0) {
1962  return -1;
1963  }
1964 
1965  /* Flip the rows to be top-down if necessary */
1966  if (!renderer->target) {
1967  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1968  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1969  dst = (Uint8*)temp_pixels;
1970  tmp = SDL_stack_alloc(Uint8, length);
1971  rows = rect->h / 2;
1972  while (rows--) {
1973  SDL_memcpy(tmp, dst, length);
1974  SDL_memcpy(dst, src, length);
1975  SDL_memcpy(src, tmp, length);
1976  dst += temp_pitch;
1977  src -= temp_pitch;
1978  }
1979  SDL_stack_free(tmp);
1980  }
1981 
1982  status = SDL_ConvertPixels(rect->w, rect->h,
1983  temp_format, temp_pixels, temp_pitch,
1984  pixel_format, pixels, pitch);
1985  SDL_free(temp_pixels);
1986 
1987  return status;
1988 }
1989 
1990 static void
1991 GLES2_RenderPresent(SDL_Renderer *renderer)
1992 {
1993  GLES2_ActivateRenderer(renderer);
1994 
1995  /* Tell the video driver to swap buffers */
1996  SDL_GL_SwapWindow(renderer->window);
1997 }
1998 
1999 
2000 /*************************************************************************************************
2001  * Bind/unbinding of textures
2002  *************************************************************************************************/
2003 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
2004 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
2005 
2006 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
2007 {
2008  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
2009  GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
2010  GLES2_ActivateRenderer(renderer);
2011 
2012  data->glBindTexture(texturedata->texture_type, texturedata->texture);
2013 
2014  if (texw) {
2015  *texw = 1.0;
2016  }
2017  if (texh) {
2018  *texh = 1.0;
2019  }
2020 
2021  return 0;
2022 }
2023 
2024 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
2025 {
2026  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
2027  GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
2028  GLES2_ActivateRenderer(renderer);
2029 
2030  data->glBindTexture(texturedata->texture_type, 0);
2031 
2032  return 0;
2033 }
2034 
2035 
2036 /*************************************************************************************************
2037  * Renderer instantiation *
2038  *************************************************************************************************/
2039 
2040 #ifdef ZUNE_HD
2041 #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
2042 #endif
2043 
2044 static void
2045 GLES2_ResetState(SDL_Renderer *renderer)
2046 {
2047  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
2048 
2049  if (SDL_CurrentContext == data->context) {
2050  GLES2_UpdateViewport(renderer);
2051  } else {
2052  GLES2_ActivateRenderer(renderer);
2053  }
2054 
2055  data->current.blendMode = SDL_BLENDMODE_INVALID;
2056  data->current.tex_coords = SDL_FALSE;
2057 
2058  data->glActiveTexture(GL_TEXTURE0);
2059  data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
2060  data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2061 
2062  data->glClearColor((GLfloat) data->clear_r * inv255f,
2063  (GLfloat) data->clear_g * inv255f,
2064  (GLfloat) data->clear_b * inv255f,
2065  (GLfloat) data->clear_a * inv255f);
2066 
2067  data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
2068  data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
2069 
2070  GL_CheckError("", renderer);
2071 }
2072 
2073 static SDL_Renderer *
2074 GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
2075 {
2077  GLES2_DriverContext *data;
2078  GLint nFormats;
2079 #ifndef ZUNE_HD
2080  GLboolean hasCompiler;
2081 #endif
2082  Uint32 window_flags = 0; /* -Wconditional-uninitialized */
2083  GLint window_framebuffer;
2084  GLint value;
2085  int profile_mask = 0, major = 0, minor = 0;
2086  SDL_bool changed_window = SDL_FALSE;
2087 
2088  if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask) < 0) {
2089  goto error;
2090  }
2092  goto error;
2093  }
2095  goto error;
2096  }
2097 
2098  window_flags = SDL_GetWindowFlags(window);
2099  /* OpenGL ES 3.0 is a superset of OpenGL ES 2.0 */
2100  if (!(window_flags & SDL_WINDOW_OPENGL) ||
2101  profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major < RENDERER_CONTEXT_MAJOR) {
2102 
2103  changed_window = SDL_TRUE;
2105  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
2106  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
2107 
2108  if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
2109  goto error;
2110  }
2111  }
2112 
2113  /* Create the renderer struct */
2114  renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
2115  if (!renderer) {
2116  SDL_OutOfMemory();
2117  goto error;
2118  }
2119 
2120  data = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext));
2121  if (!data) {
2122  GLES2_DestroyRenderer(renderer);
2123  SDL_OutOfMemory();
2124  goto error;
2125  }
2126  renderer->info = GLES2_RenderDriver.info;
2128  renderer->driverdata = data;
2129  renderer->window = window;
2130 
2131  /* Create an OpenGL ES 2.0 context */
2132  data->context = SDL_GL_CreateContext(window);
2133  if (!data->context) {
2134  GLES2_DestroyRenderer(renderer);
2135  goto error;
2136  }
2137  if (SDL_GL_MakeCurrent(window, data->context) < 0) {
2138  GLES2_DestroyRenderer(renderer);
2139  goto error;
2140  }
2141 
2142  if (GLES2_LoadFunctions(data) < 0) {
2143  GLES2_DestroyRenderer(renderer);
2144  goto error;
2145  }
2146 
2147 #if __WINRT__
2148  /* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync
2149  * is turned on. Not doing so will freeze the screen's contents to that
2150  * of the first drawn frame.
2151  */
2152  flags |= SDL_RENDERER_PRESENTVSYNC;
2153 #endif
2154 
2155  if (flags & SDL_RENDERER_PRESENTVSYNC) {
2157  } else {
2159  }
2160  if (SDL_GL_GetSwapInterval() > 0) {
2161  renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
2162  }
2163 
2164  /* Check for debug output support */
2165  if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 &&
2166  (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
2167  data->debug_enabled = SDL_TRUE;
2168  }
2169 
2170  value = 0;
2171  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
2172  renderer->info.max_texture_width = value;
2173  value = 0;
2174  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
2175  renderer->info.max_texture_height = value;
2176 
2177  /* Determine supported shader formats */
2178  /* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
2179 #ifdef ZUNE_HD
2180  nFormats = 1;
2181 #else /* !ZUNE_HD */
2182  data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
2183  data->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
2184  if (hasCompiler) {
2185  ++nFormats;
2186  }
2187 #endif /* ZUNE_HD */
2188  data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum));
2189  if (!data->shader_formats) {
2190  GLES2_DestroyRenderer(renderer);
2191  SDL_OutOfMemory();
2192  goto error;
2193  }
2194  data->shader_format_count = nFormats;
2195 #ifdef ZUNE_HD
2196  data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
2197 #else /* !ZUNE_HD */
2198  data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats);
2199  if (hasCompiler) {
2200  data->shader_formats[nFormats - 1] = (GLenum)-1;
2201  }
2202 #endif /* ZUNE_HD */
2203 
2204  data->framebuffers = NULL;
2205  data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
2206  data->window_framebuffer = (GLuint)window_framebuffer;
2207 
2208  /* Populate the function pointers for the module */
2209  renderer->WindowEvent = GLES2_WindowEvent;
2210  renderer->GetOutputSize = GLES2_GetOutputSize;
2211  renderer->SupportsBlendMode = GLES2_SupportsBlendMode;
2212  renderer->CreateTexture = GLES2_CreateTexture;
2213  renderer->UpdateTexture = GLES2_UpdateTexture;
2214  renderer->UpdateTextureYUV = GLES2_UpdateTextureYUV;
2215  renderer->LockTexture = GLES2_LockTexture;
2216  renderer->UnlockTexture = GLES2_UnlockTexture;
2217  renderer->SetRenderTarget = GLES2_SetRenderTarget;
2218  renderer->UpdateViewport = GLES2_UpdateViewport;
2219  renderer->UpdateClipRect = GLES2_UpdateClipRect;
2220  renderer->RenderClear = GLES2_RenderClear;
2221  renderer->RenderDrawPoints = GLES2_RenderDrawPoints;
2222  renderer->RenderDrawLines = GLES2_RenderDrawLines;
2223  renderer->RenderFillRects = GLES2_RenderFillRects;
2224  renderer->RenderCopy = GLES2_RenderCopy;
2225  renderer->RenderCopyEx = GLES2_RenderCopyEx;
2226  renderer->RenderReadPixels = GLES2_RenderReadPixels;
2227  renderer->RenderPresent = GLES2_RenderPresent;
2228  renderer->DestroyTexture = GLES2_DestroyTexture;
2229  renderer->DestroyRenderer = GLES2_DestroyRenderer;
2230  renderer->GL_BindTexture = GLES2_BindTexture;
2231  renderer->GL_UnbindTexture = GLES2_UnbindTexture;
2232 
2237 #ifdef GL_TEXTURE_EXTERNAL_OES
2239 #endif
2240 
2241  GLES2_ResetState(renderer);
2242 
2243  return renderer;
2244 
2245 error:
2246  if (changed_window) {
2247  /* Uh oh, better try to put it back... */
2251  SDL_RecreateWindow(window, window_flags);
2252  }
2253  return NULL;
2254 }
2255 
2256 #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
2257 
2258 /* vi: set ts=4 sw=4 expandtab: */
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2193
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
#define GL_TEXTURE_EXTERNAL_OES
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:143
#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:2221
#define SDL_GetHint
#define SDL_GetWindowFlags
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2207
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_NONE
Definition: SDL_opengl.h:491
#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:2228
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:175
#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:2214
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:2200
#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 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 SDL_GetYUVConversionModeForResolution
#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