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