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