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