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