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