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