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