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