zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_render_gles2.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 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_config.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 "SDL_shaders_gles2.h"
29 
30 /* Used to re-create the window with OpenGL ES capability */
31 extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
32 
33 /*************************************************************************************************
34  * Bootstrap data *
35  *************************************************************************************************/
36 
37 static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags);
38 
39 SDL_RenderDriver GLES2_RenderDriver = {
40  GLES2_CreateRenderer,
41  {
42  "opengles2",
44  4,
49  0,
50  0
51  }
52 };
53 
54 /*************************************************************************************************
55  * Context structures *
56  *************************************************************************************************/
57 
58 typedef struct GLES2_FBOList GLES2_FBOList;
59 
60 struct GLES2_FBOList
61 {
62  Uint32 w, h;
63  GLuint FBO;
64  GLES2_FBOList *next;
65 };
66 
67 typedef struct GLES2_TextureData
68 {
70  GLenum texture_type;
71  GLenum pixel_format;
72  GLenum pixel_type;
73  void *pixel_data;
74  size_t pitch;
75  GLES2_FBOList *fbo;
76 } GLES2_TextureData;
77 
78 typedef struct GLES2_ShaderCacheEntry
79 {
80  GLuint id;
81  GLES2_ShaderType type;
82  const GLES2_ShaderInstance *instance;
83  int references;
84  struct GLES2_ShaderCacheEntry *prev;
85  struct GLES2_ShaderCacheEntry *next;
86 } GLES2_ShaderCacheEntry;
87 
88 typedef struct GLES2_ShaderCache
89 {
90  int count;
91  GLES2_ShaderCacheEntry *head;
92 } GLES2_ShaderCache;
93 
94 typedef struct GLES2_ProgramCacheEntry
95 {
96  GLuint id;
97  SDL_BlendMode blend_mode;
98  GLES2_ShaderCacheEntry *vertex_shader;
99  GLES2_ShaderCacheEntry *fragment_shader;
100  GLuint uniform_locations[16];
101  struct GLES2_ProgramCacheEntry *prev;
102  struct GLES2_ProgramCacheEntry *next;
103 } GLES2_ProgramCacheEntry;
104 
105 typedef struct GLES2_ProgramCache
106 {
107  int count;
108  GLES2_ProgramCacheEntry *head;
109  GLES2_ProgramCacheEntry *tail;
110 } GLES2_ProgramCache;
111 
112 typedef enum
113 {
114  GLES2_ATTRIBUTE_POSITION = 0,
115  GLES2_ATTRIBUTE_TEXCOORD = 1,
116  GLES2_ATTRIBUTE_ANGLE = 2,
117  GLES2_ATTRIBUTE_CENTER = 3,
118 } GLES2_Attribute;
119 
120 typedef enum
121 {
122  GLES2_UNIFORM_PROJECTION,
123  GLES2_UNIFORM_TEXTURE,
124  GLES2_UNIFORM_MODULATION,
125  GLES2_UNIFORM_COLOR,
126  GLES2_UNIFORM_COLORTABLE
127 } GLES2_Uniform;
128 
129 typedef enum
130 {
131  GLES2_IMAGESOURCE_SOLID,
132  GLES2_IMAGESOURCE_TEXTURE_ABGR,
133  GLES2_IMAGESOURCE_TEXTURE_ARGB,
134  GLES2_IMAGESOURCE_TEXTURE_RGB,
135  GLES2_IMAGESOURCE_TEXTURE_BGR
136 } GLES2_ImageSource;
137 
138 typedef struct GLES2_DriverContext
139 {
141  struct {
142  int blendMode;
143  SDL_bool tex_coords;
144  } current;
145 
146 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
147 #include "SDL_gles2funcs.h"
148 #undef SDL_PROC
149  GLES2_FBOList *framebuffers;
150  GLuint window_framebuffer;
151 
152  int shader_format_count;
153  GLenum *shader_formats;
154  GLES2_ShaderCache shader_cache;
155  GLES2_ProgramCache program_cache;
156  GLES2_ProgramCacheEntry *current_program;
157 } GLES2_DriverContext;
158 
159 #define GLES2_MAX_CACHED_PROGRAMS 8
160 
161 /*************************************************************************************************
162  * Renderer state APIs *
163  *************************************************************************************************/
164 
165 static int GLES2_ActivateRenderer(SDL_Renderer *renderer);
166 static void GLES2_WindowEvent(SDL_Renderer * renderer,
167  const SDL_WindowEvent *event);
168 static int GLES2_UpdateViewport(SDL_Renderer * renderer);
169 static void GLES2_DestroyRenderer(SDL_Renderer *renderer);
170 static int GLES2_SetOrthographicProjection(SDL_Renderer *renderer);
171 
172 
173 static SDL_GLContext SDL_CurrentContext = NULL;
174 
175 static int GLES2_LoadFunctions(GLES2_DriverContext * data)
176 {
177 #if SDL_VIDEO_DRIVER_UIKIT
178 #define __SDL_NOGETPROCADDR__
179 #elif SDL_VIDEO_DRIVER_ANDROID
180 #define __SDL_NOGETPROCADDR__
181 #elif SDL_VIDEO_DRIVER_PANDORA
182 #define __SDL_NOGETPROCADDR__
183 #endif
184 
185 #if defined __SDL_NOGETPROCADDR__
186 #define SDL_PROC(ret,func,params) data->func=func;
187 #else
188 #define SDL_PROC(ret,func,params) \
189  do { \
190  data->func = SDL_GL_GetProcAddress(#func); \
191  if ( ! data->func ) { \
192  return SDL_SetError("Couldn't load GLES2 function %s: %s\n", #func, SDL_GetError()); \
193  } \
194  } while ( 0 );
195 #endif /* _SDL_NOGETPROCADDR_ */
196 
197 #include "SDL_gles2funcs.h"
198 #undef SDL_PROC
199  return 0;
200 }
201 
202 GLES2_FBOList *
203 GLES2_GetFBO(GLES2_DriverContext *data, Uint32 w, Uint32 h)
204 {
205  GLES2_FBOList *result = data->framebuffers;
206  while ((result) && ((result->w != w) || (result->h != h)) )
207  {
208  result = result->next;
209  }
210  if (result == NULL)
211  {
212  result = SDL_malloc(sizeof(GLES2_FBOList));
213  result->w = w;
214  result->h = h;
215  data->glGenFramebuffers(1, &result->FBO);
216  result->next = data->framebuffers;
217  data->framebuffers = result;
218  }
219  return result;
220 }
221 
222 static int
223 GLES2_ActivateRenderer(SDL_Renderer * renderer)
224 {
225  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
226 
227  if (SDL_CurrentContext != rdata->context) {
228  /* Null out the current program to ensure we set it again */
229  rdata->current_program = NULL;
230 
231  if (SDL_GL_MakeCurrent(renderer->window, rdata->context) < 0) {
232  return -1;
233  }
234  SDL_CurrentContext = rdata->context;
235 
236  GLES2_UpdateViewport(renderer);
237  }
238  return 0;
239 }
240 
241 static void
242 GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
243 {
244  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
245 
247  event->event == SDL_WINDOWEVENT_SHOWN ||
248  event->event == SDL_WINDOWEVENT_HIDDEN) {
249  /* Rebind the context to the window area */
250  SDL_CurrentContext = NULL;
251  }
252 
253  if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
254  /* According to Apple documentation, we need to finish drawing NOW! */
255  rdata->glFinish();
256  }
257 }
258 
259 static int
260 GLES2_UpdateViewport(SDL_Renderer * renderer)
261 {
262  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
263 
264  if (SDL_CurrentContext != rdata->context) {
265  /* We'll update the viewport after we rebind the context */
266  return 0;
267  }
268 
269  rdata->glViewport(renderer->viewport.x, renderer->viewport.y,
270  renderer->viewport.w, renderer->viewport.h);
271 
272  if (rdata->current_program) {
273  GLES2_SetOrthographicProjection(renderer);
274  }
275  return 0;
276 }
277 
278 static int
279 GLES2_UpdateClipRect(SDL_Renderer * renderer)
280 {
281  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
282  const SDL_Rect *rect = &renderer->clip_rect;
283 
284  if (SDL_CurrentContext != rdata->context) {
285  /* We'll update the clip rect after we rebind the context */
286  return 0;
287  }
288 
289  if (!SDL_RectEmpty(rect)) {
290  rdata->glEnable(GL_SCISSOR_TEST);
291  rdata->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
292  } else {
293  rdata->glDisable(GL_SCISSOR_TEST);
294  }
295  return 0;
296 }
297 
298 static void
299 GLES2_DestroyRenderer(SDL_Renderer *renderer)
300 {
301  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
302 
303  /* Deallocate everything */
304  if (rdata) {
305  GLES2_ActivateRenderer(renderer);
306 
307  {
308  GLES2_ShaderCacheEntry *entry;
309  GLES2_ShaderCacheEntry *next;
310  entry = rdata->shader_cache.head;
311  while (entry)
312  {
313  rdata->glDeleteShader(entry->id);
314  next = entry->next;
315  SDL_free(entry);
316  entry = next;
317  }
318  }
319  {
320  GLES2_ProgramCacheEntry *entry;
321  GLES2_ProgramCacheEntry *next;
322  entry = rdata->program_cache.head;
323  while (entry) {
324  rdata->glDeleteProgram(entry->id);
325  next = entry->next;
326  SDL_free(entry);
327  entry = next;
328  }
329  }
330  if (rdata->context) {
331  while (rdata->framebuffers) {
332  GLES2_FBOList *nextnode = rdata->framebuffers->next;
333  rdata->glDeleteFramebuffers(1, &rdata->framebuffers->FBO);
334  SDL_free(rdata->framebuffers);
335  rdata->framebuffers = nextnode;
336  }
337  SDL_GL_DeleteContext(rdata->context);
338  }
339  SDL_free(rdata->shader_formats);
340  SDL_free(rdata);
341  }
342  SDL_free(renderer);
343 }
344 
345 /*************************************************************************************************
346  * Texture APIs *
347  *************************************************************************************************/
348 
349 static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture);
350 static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
351 static int GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
352  void **pixels, int *pitch);
353 static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
354 static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
355  const void *pixels, int pitch);
356 static int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
357 
358 static GLenum
359 GetScaleQuality(void)
360 {
361  const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
362 
363  if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
364  return GL_NEAREST;
365  } else {
366  return GL_LINEAR;
367  }
368 }
369 
370 static int
371 GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
372 {
373  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
374  GLES2_TextureData *tdata;
375  GLenum format;
376  GLenum type;
377  GLenum scaleMode;
378 
379  GLES2_ActivateRenderer(renderer);
380 
381  /* Determine the corresponding GLES texture format params */
382  switch (texture->format)
383  {
388  format = GL_RGBA;
390  break;
391  default:
392  return SDL_SetError("Texture format not supported");
393  }
394 
395  /* Allocate a texture struct */
396  tdata = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
397  if (!tdata) {
398  return SDL_OutOfMemory();
399  }
400  tdata->texture = 0;
401  tdata->texture_type = GL_TEXTURE_2D;
402  tdata->pixel_format = format;
403  tdata->pixel_type = type;
404  scaleMode = GetScaleQuality();
405 
406  /* Allocate a blob for image data */
407  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
408  tdata->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
409  tdata->pixel_data = SDL_calloc(1, tdata->pitch * texture->h);
410  if (!tdata->pixel_data) {
411  SDL_free(tdata);
412  return SDL_OutOfMemory();
413  }
414  }
415 
416  /* Allocate the texture */
417  rdata->glGetError();
418  rdata->glGenTextures(1, &tdata->texture);
419  if (rdata->glGetError() != GL_NO_ERROR) {
420  SDL_free(tdata);
421  return SDL_SetError("Texture creation failed in glGenTextures()");
422  }
423  rdata->glActiveTexture(GL_TEXTURE0);
424  rdata->glBindTexture(tdata->texture_type, tdata->texture);
425  rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
426  rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
427  rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
428  rdata->glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
429  rdata->glTexImage2D(tdata->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
430  if (rdata->glGetError() != GL_NO_ERROR) {
431  rdata->glDeleteTextures(1, &tdata->texture);
432  SDL_free(tdata);
433  return SDL_SetError("Texture creation failed");
434  }
435  texture->driverdata = tdata;
436 
437  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
438  tdata->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
439  } else {
440  tdata->fbo = NULL;
441  }
442 
443  return 0;
444 }
445 
446 static void
447 GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
448 {
449  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
450  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
451 
452  GLES2_ActivateRenderer(renderer);
453 
454  /* Destroy the texture */
455  if (tdata)
456  {
457  rdata->glDeleteTextures(1, &tdata->texture);
458  SDL_free(tdata->pixel_data);
459  SDL_free(tdata);
460  texture->driverdata = NULL;
461  }
462 }
463 
464 static int
465 GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
466  void **pixels, int *pitch)
467 {
468  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
469 
470  /* Retrieve the buffer/pitch for the specified region */
471  *pixels = (Uint8 *)tdata->pixel_data +
472  (tdata->pitch * rect->y) +
473  (rect->x * SDL_BYTESPERPIXEL(texture->format));
474  *pitch = tdata->pitch;
475 
476  return 0;
477 }
478 
479 static void
480 GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
481 {
482  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
483  SDL_Rect rect;
484 
485  /* We do whole texture updates, at least for now */
486  rect.x = 0;
487  rect.y = 0;
488  rect.w = texture->w;
489  rect.h = texture->h;
490  GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
491 }
492 
493 static int
494 GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
495  const void *pixels, int pitch)
496 {
497  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
498  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
499  Uint8 *blob = NULL;
500  Uint8 *src;
501  int srcPitch;
502  int y;
503 
504  GLES2_ActivateRenderer(renderer);
505 
506  /* Bail out if we're supposed to update an empty rectangle */
507  if (rect->w <= 0 || rect->h <= 0)
508  return 0;
509 
510  /* Reformat the texture data into a tightly packed array */
511  srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format);
512  src = (Uint8 *)pixels;
513  if (pitch != srcPitch) {
514  blob = (Uint8 *)SDL_malloc(srcPitch * rect->h);
515  if (!blob) {
516  return SDL_OutOfMemory();
517  }
518  src = blob;
519  for (y = 0; y < rect->h; ++y)
520  {
521  SDL_memcpy(src, pixels, srcPitch);
522  src += srcPitch;
523  pixels = (Uint8 *)pixels + pitch;
524  }
525  src = blob;
526  }
527 
528  /* Create a texture subimage with the supplied data */
529  rdata->glGetError();
530  rdata->glActiveTexture(GL_TEXTURE0);
531  rdata->glBindTexture(tdata->texture_type, tdata->texture);
532  rdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
533  rdata->glTexSubImage2D(tdata->texture_type,
534  0,
535  rect->x,
536  rect->y,
537  rect->w,
538  rect->h,
539  tdata->pixel_format,
540  tdata->pixel_type,
541  src);
542  SDL_free(blob);
543 
544  if (rdata->glGetError() != GL_NO_ERROR) {
545  return SDL_SetError("Failed to update texture");
546  }
547  return 0;
548 }
549 
550 static int
551 GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
552 {
553  GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
554  GLES2_TextureData *texturedata = NULL;
555  GLenum status;
556 
557  if (texture == NULL) {
558  data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
559  } else {
560  texturedata = (GLES2_TextureData *) texture->driverdata;
561  data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
562  /* TODO: check if texture pixel format allows this operation */
563  data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
564  /* Check FBO status */
565  status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
566  if (status != GL_FRAMEBUFFER_COMPLETE) {
567  return SDL_SetError("glFramebufferTexture2D() failed");
568  }
569  }
570  return 0;
571 }
572 
573 /*************************************************************************************************
574  * Shader management functions *
575  *************************************************************************************************/
576 
577 static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type,
578  SDL_BlendMode blendMode);
579 static void GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry);
580 static GLES2_ProgramCacheEntry *GLES2_CacheProgram(SDL_Renderer *renderer,
581  GLES2_ShaderCacheEntry *vertex,
582  GLES2_ShaderCacheEntry *fragment,
583  SDL_BlendMode blendMode);
584 static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source,
585  SDL_BlendMode blendMode);
586 
587 static GLES2_ProgramCacheEntry *
588 GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
589  GLES2_ShaderCacheEntry *fragment, SDL_BlendMode blendMode)
590 {
591  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
592  GLES2_ProgramCacheEntry *entry;
593  GLES2_ShaderCacheEntry *shaderEntry;
594  GLint linkSuccessful;
595 
596  /* Check if we've already cached this program */
597  entry = rdata->program_cache.head;
598  while (entry)
599  {
600  if (entry->vertex_shader == vertex && entry->fragment_shader == fragment)
601  break;
602  entry = entry->next;
603  }
604  if (entry)
605  {
606  if (rdata->program_cache.head != entry)
607  {
608  if (entry->next)
609  entry->next->prev = entry->prev;
610  if (entry->prev)
611  entry->prev->next = entry->next;
612  entry->prev = NULL;
613  entry->next = rdata->program_cache.head;
614  rdata->program_cache.head->prev = entry;
615  rdata->program_cache.head = entry;
616  }
617  return entry;
618  }
619 
620  /* Create a program cache entry */
621  entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry));
622  if (!entry)
623  {
624  SDL_OutOfMemory();
625  return NULL;
626  }
627  entry->vertex_shader = vertex;
628  entry->fragment_shader = fragment;
629  entry->blend_mode = blendMode;
630 
631  /* Create the program and link it */
632  rdata->glGetError();
633  entry->id = rdata->glCreateProgram();
634  rdata->glAttachShader(entry->id, vertex->id);
635  rdata->glAttachShader(entry->id, fragment->id);
636  rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
637  rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
638  rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
639  rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
640  rdata->glLinkProgram(entry->id);
641  rdata->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
642  if (rdata->glGetError() != GL_NO_ERROR || !linkSuccessful)
643  {
644  rdata->glDeleteProgram(entry->id);
645  SDL_free(entry);
646  SDL_SetError("Failed to link shader program");
647  return NULL;
648  }
649 
650  /* Predetermine locations of uniform variables */
651  entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
652  rdata->glGetUniformLocation(entry->id, "u_projection");
653  entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
654  rdata->glGetUniformLocation(entry->id, "u_texture");
655  entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
656  rdata->glGetUniformLocation(entry->id, "u_modulation");
657  entry->uniform_locations[GLES2_UNIFORM_COLOR] =
658  rdata->glGetUniformLocation(entry->id, "u_color");
659  entry->uniform_locations[GLES2_UNIFORM_COLORTABLE] =
660  rdata->glGetUniformLocation(entry->id, "u_colorTable");
661 
662  /* Cache the linked program */
663  if (rdata->program_cache.head)
664  {
665  entry->next = rdata->program_cache.head;
666  rdata->program_cache.head->prev = entry;
667  }
668  else
669  {
670  rdata->program_cache.tail = entry;
671  }
672  rdata->program_cache.head = entry;
673  ++rdata->program_cache.count;
674 
675  /* Increment the refcount of the shaders we're using */
676  ++vertex->references;
677  ++fragment->references;
678 
679  /* Evict the last entry from the cache if we exceed the limit */
680  if (rdata->program_cache.count > GLES2_MAX_CACHED_PROGRAMS)
681  {
682  shaderEntry = rdata->program_cache.tail->vertex_shader;
683  if (--shaderEntry->references <= 0)
684  GLES2_EvictShader(renderer, shaderEntry);
685  shaderEntry = rdata->program_cache.tail->fragment_shader;
686  if (--shaderEntry->references <= 0)
687  GLES2_EvictShader(renderer, shaderEntry);
688  rdata->glDeleteProgram(rdata->program_cache.tail->id);
689  rdata->program_cache.tail = rdata->program_cache.tail->prev;
690  SDL_free(rdata->program_cache.tail->next);
691  rdata->program_cache.tail->next = NULL;
692  --rdata->program_cache.count;
693  }
694  return entry;
695 }
696 
697 static GLES2_ShaderCacheEntry *
698 GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type, SDL_BlendMode blendMode)
699 {
700  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
701  const GLES2_Shader *shader;
702  const GLES2_ShaderInstance *instance = NULL;
703  GLES2_ShaderCacheEntry *entry = NULL;
704  GLint compileSuccessful = GL_FALSE;
705  int i, j;
706 
707  /* Find the corresponding shader */
708  shader = GLES2_GetShader(type, blendMode);
709  if (!shader)
710  {
711  SDL_SetError("No shader matching the requested characteristics was found");
712  return NULL;
713  }
714 
715  /* Find a matching shader instance that's supported on this hardware */
716  for (i = 0; i < shader->instance_count && !instance; ++i)
717  {
718  for (j = 0; j < rdata->shader_format_count && !instance; ++j)
719  {
720  if (!shader->instances)
721  continue;
722  if (!shader->instances[i])
723  continue;
724  if (shader->instances[i]->format != rdata->shader_formats[j])
725  continue;
726  instance = shader->instances[i];
727  }
728  }
729  if (!instance)
730  {
731  SDL_SetError("The specified shader cannot be loaded on the current platform");
732  return NULL;
733  }
734 
735  /* Check if we've already cached this shader */
736  entry = rdata->shader_cache.head;
737  while (entry)
738  {
739  if (entry->instance == instance)
740  break;
741  entry = entry->next;
742  }
743  if (entry)
744  return entry;
745 
746  /* Create a shader cache entry */
747  entry = (GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(GLES2_ShaderCacheEntry));
748  if (!entry)
749  {
750  SDL_OutOfMemory();
751  return NULL;
752  }
753  entry->type = type;
754  entry->instance = instance;
755 
756  /* Compile or load the selected shader instance */
757  rdata->glGetError();
758  entry->id = rdata->glCreateShader(instance->type);
759  if (instance->format == (GLenum)-1)
760  {
761  rdata->glShaderSource(entry->id, 1, (const char **)&instance->data, NULL);
762  rdata->glCompileShader(entry->id);
763  rdata->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
764  }
765  else
766  {
767  rdata->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
768  compileSuccessful = GL_TRUE;
769  }
770  if (rdata->glGetError() != GL_NO_ERROR || !compileSuccessful)
771  {
772  char *info = NULL;
773  int length = 0;
774 
775  rdata->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
776  if (length > 0) {
777  info = SDL_stack_alloc(char, length);
778  if (info) {
779  rdata->glGetShaderInfoLog(entry->id, length, &length, info);
780  }
781  }
782  if (info) {
783  SDL_SetError("Failed to load the shader: %s", info);
784  SDL_stack_free(info);
785  } else {
786  SDL_SetError("Failed to load the shader");
787  }
788  rdata->glDeleteShader(entry->id);
789  SDL_free(entry);
790  return NULL;
791  }
792 
793  /* Link the shader entry in at the front of the cache */
794  if (rdata->shader_cache.head)
795  {
796  entry->next = rdata->shader_cache.head;
797  rdata->shader_cache.head->prev = entry;
798  }
799  rdata->shader_cache.head = entry;
800  ++rdata->shader_cache.count;
801  return entry;
802 }
803 
804 static void
805 GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry)
806 {
807  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
808 
809  /* Unlink the shader from the cache */
810  if (entry->next)
811  entry->next->prev = entry->prev;
812  if (entry->prev)
813  entry->prev->next = entry->next;
814  if (rdata->shader_cache.head == entry)
815  rdata->shader_cache.head = entry->next;
816  --rdata->shader_cache.count;
817 
818  /* Deallocate the shader */
819  rdata->glDeleteShader(entry->id);
820  SDL_free(entry);
821 }
822 
823 static int
824 GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendMode blendMode)
825 {
826  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
827  GLES2_ShaderCacheEntry *vertex = NULL;
828  GLES2_ShaderCacheEntry *fragment = NULL;
829  GLES2_ShaderType vtype, ftype;
830  GLES2_ProgramCacheEntry *program;
831 
832  /* Select an appropriate shader pair for the specified modes */
833  vtype = GLES2_SHADER_VERTEX_DEFAULT;
834  switch (source)
835  {
836  case GLES2_IMAGESOURCE_SOLID:
837  ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC;
838  break;
839  case GLES2_IMAGESOURCE_TEXTURE_ABGR:
840  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC;
841  break;
842  case GLES2_IMAGESOURCE_TEXTURE_ARGB:
843  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC;
844  break;
845  case GLES2_IMAGESOURCE_TEXTURE_RGB:
846  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC;
847  break;
848  case GLES2_IMAGESOURCE_TEXTURE_BGR:
849  ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
850  break;
851  default:
852  goto fault;
853  }
854 
855  /* Load the requested shaders */
856  vertex = GLES2_CacheShader(renderer, vtype, blendMode);
857  if (!vertex)
858  goto fault;
859  fragment = GLES2_CacheShader(renderer, ftype, blendMode);
860  if (!fragment)
861  goto fault;
862 
863  /* Check if we need to change programs at all */
864  if (rdata->current_program &&
865  rdata->current_program->vertex_shader == vertex &&
866  rdata->current_program->fragment_shader == fragment)
867  return 0;
868 
869  /* Generate a matching program */
870  program = GLES2_CacheProgram(renderer, vertex, fragment, blendMode);
871  if (!program)
872  goto fault;
873 
874  /* Select that program in OpenGL */
875  rdata->glGetError();
876  rdata->glUseProgram(program->id);
877  if (rdata->glGetError() != GL_NO_ERROR)
878  {
879  SDL_SetError("Failed to select program");
880  goto fault;
881  }
882 
883  /* Set the current program */
884  rdata->current_program = program;
885 
886  /* Activate an orthographic projection */
887  if (GLES2_SetOrthographicProjection(renderer) < 0)
888  goto fault;
889 
890  /* Clean up and return */
891  return 0;
892 fault:
893  if (vertex && vertex->references <= 0)
894  GLES2_EvictShader(renderer, vertex);
895  if (fragment && fragment->references <= 0)
896  GLES2_EvictShader(renderer, fragment);
897  rdata->current_program = NULL;
898  return -1;
899 }
900 
901 static int
902 GLES2_SetOrthographicProjection(SDL_Renderer *renderer)
903 {
904  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
905  GLfloat projection[4][4];
906  GLuint locProjection;
907 
908  if (!renderer->viewport.w || !renderer->viewport.h) {
909  return 0;
910  }
911 
912  /* Prepare an orthographic projection */
913  projection[0][0] = 2.0f / renderer->viewport.w;
914  projection[0][1] = 0.0f;
915  projection[0][2] = 0.0f;
916  projection[0][3] = 0.0f;
917  projection[1][0] = 0.0f;
918  if (renderer->target) {
919  projection[1][1] = 2.0f / renderer->viewport.h;
920  } else {
921  projection[1][1] = -2.0f / renderer->viewport.h;
922  }
923  projection[1][2] = 0.0f;
924  projection[1][3] = 0.0f;
925  projection[2][0] = 0.0f;
926  projection[2][1] = 0.0f;
927  projection[2][2] = 0.0f;
928  projection[2][3] = 0.0f;
929  projection[3][0] = -1.0f;
930  if (renderer->target) {
931  projection[3][1] = -1.0f;
932  } else {
933  projection[3][1] = 1.0f;
934  }
935  projection[3][2] = 0.0f;
936  projection[3][3] = 1.0f;
937 
938  /* Set the projection matrix */
939  locProjection = rdata->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION];
940  rdata->glGetError();
941  rdata->glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection);
942  if (rdata->glGetError() != GL_NO_ERROR) {
943  return SDL_SetError("Failed to set orthographic projection");
944  }
945  return 0;
946 }
947 
948 /*************************************************************************************************
949  * Rendering functions *
950  *************************************************************************************************/
951 
952 static const float inv255f = 1.0f / 255.0f;
953 
954 static int GLES2_RenderClear(SDL_Renderer *renderer);
955 static int GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
956 static int GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
957 static int GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count);
958 static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
959  const SDL_FRect *dstrect);
960 static int GLES2_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
961  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
962  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
963 static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
964  Uint32 pixel_format, void * pixels, int pitch);
965 static void GLES2_RenderPresent(SDL_Renderer *renderer);
966 
967 
968 static int
969 GLES2_RenderClear(SDL_Renderer * renderer)
970 {
971  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
972 
973  GLES2_ActivateRenderer(renderer);
974 
975  rdata->glClearColor((GLfloat) renderer->r * inv255f,
976  (GLfloat) renderer->g * inv255f,
977  (GLfloat) renderer->b * inv255f,
978  (GLfloat) renderer->a * inv255f);
979 
980  rdata->glClear(GL_COLOR_BUFFER_BIT);
981 
982  return 0;
983 }
984 
985 static void
986 GLES2_SetBlendMode(GLES2_DriverContext *rdata, int blendMode)
987 {
988  if (blendMode != rdata->current.blendMode) {
989  switch (blendMode) {
990  default:
991  case SDL_BLENDMODE_NONE:
992  rdata->glDisable(GL_BLEND);
993  break;
994  case SDL_BLENDMODE_BLEND:
995  rdata->glEnable(GL_BLEND);
996  rdata->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
997  break;
998  case SDL_BLENDMODE_ADD:
999  rdata->glEnable(GL_BLEND);
1000  rdata->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
1001  break;
1002  case SDL_BLENDMODE_MOD:
1003  rdata->glEnable(GL_BLEND);
1004  rdata->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
1005  break;
1006  }
1007  rdata->current.blendMode = blendMode;
1008  }
1009 }
1010 
1011 static void
1012 GLES2_SetTexCoords(GLES2_DriverContext * rdata, SDL_bool enabled)
1013 {
1014  if (enabled != rdata->current.tex_coords) {
1015  if (enabled) {
1016  rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1017  } else {
1018  rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1019  }
1020  rdata->current.tex_coords = enabled;
1021  }
1022 }
1023 
1024 static int
1025 GLES2_SetDrawingState(SDL_Renderer * renderer)
1026 {
1027  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
1028  int blendMode = renderer->blendMode;
1029  GLuint locColor;
1030 
1031  rdata->glGetError();
1032 
1033  GLES2_ActivateRenderer(renderer);
1034 
1035  GLES2_SetBlendMode(rdata, blendMode);
1036 
1037  GLES2_SetTexCoords(rdata, SDL_FALSE);
1038 
1039  /* Activate an appropriate shader and set the projection matrix */
1040  if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
1041  return -1;
1042 
1043  /* Select the color to draw with */
1044  locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
1045  if (renderer->target &&
1046  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1047  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1048  rdata->glUniform4f(locColor,
1049  renderer->b * inv255f,
1050  renderer->g * inv255f,
1051  renderer->r * inv255f,
1052  renderer->a * inv255f);
1053  } else {
1054  rdata->glUniform4f(locColor,
1055  renderer->r * inv255f,
1056  renderer->g * inv255f,
1057  renderer->b * inv255f,
1058  renderer->a * inv255f);
1059  }
1060  return 0;
1061 }
1062 
1063 static int
1064 GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
1065 {
1066  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
1067  GLfloat *vertices;
1068  int idx;
1069 
1070  if (GLES2_SetDrawingState(renderer) < 0) {
1071  return -1;
1072  }
1073 
1074  /* Emit the specified vertices as points */
1075  vertices = SDL_stack_alloc(GLfloat, count * 2);
1076  for (idx = 0; idx < count; ++idx) {
1077  GLfloat x = points[idx].x + 0.5f;
1078  GLfloat y = points[idx].y + 0.5f;
1079 
1080  vertices[idx * 2] = x;
1081  vertices[(idx * 2) + 1] = y;
1082  }
1083  rdata->glGetError();
1084  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
1085  rdata->glDrawArrays(GL_POINTS, 0, count);
1087  if (rdata->glGetError() != GL_NO_ERROR) {
1088  return SDL_SetError("Failed to render points");
1089  }
1090  return 0;
1091 }
1092 
1093 static int
1094 GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
1095 {
1096  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
1097  GLfloat *vertices;
1098  int idx;
1099 
1100  if (GLES2_SetDrawingState(renderer) < 0) {
1101  return -1;
1102  }
1103 
1104  /* Emit a line strip including the specified vertices */
1105  vertices = SDL_stack_alloc(GLfloat, count * 2);
1106  for (idx = 0; idx < count; ++idx) {
1107  GLfloat x = points[idx].x + 0.5f;
1108  GLfloat y = points[idx].y + 0.5f;
1109 
1110  vertices[idx * 2] = x;
1111  vertices[(idx * 2) + 1] = y;
1112  }
1113  rdata->glGetError();
1114  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
1115  rdata->glDrawArrays(GL_LINE_STRIP, 0, count);
1116 
1117  /* We need to close the endpoint of the line */
1118  if (count == 2 ||
1119  points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
1120  rdata->glDrawArrays(GL_POINTS, count-1, 1);
1121  }
1123  if (rdata->glGetError() != GL_NO_ERROR) {
1124  return SDL_SetError("Failed to render lines");
1125  }
1126  return 0;
1127 }
1128 
1129 static int
1130 GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
1131 {
1132  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
1133  GLfloat vertices[8];
1134  int idx;
1135 
1136  if (GLES2_SetDrawingState(renderer) < 0) {
1137  return -1;
1138  }
1139 
1140  /* Emit a line loop for each rectangle */
1141  rdata->glGetError();
1142  for (idx = 0; idx < count; ++idx) {
1143  const SDL_FRect *rect = &rects[idx];
1144 
1145  GLfloat xMin = rect->x;
1146  GLfloat xMax = (rect->x + rect->w);
1147  GLfloat yMin = rect->y;
1148  GLfloat yMax = (rect->y + rect->h);
1149 
1150  vertices[0] = xMin;
1151  vertices[1] = yMin;
1152  vertices[2] = xMax;
1153  vertices[3] = yMin;
1154  vertices[4] = xMin;
1155  vertices[5] = yMax;
1156  vertices[6] = xMax;
1157  vertices[7] = yMax;
1158  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
1159  rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1160  }
1161  if (rdata->glGetError() != GL_NO_ERROR) {
1162  return SDL_SetError("Failed to render filled rects");
1163  }
1164  return 0;
1165 }
1166 
1167 static int
1168 GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
1169  const SDL_FRect *dstrect)
1170 {
1171  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
1172  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
1173  GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1174  SDL_BlendMode blendMode;
1175  GLfloat vertices[8];
1176  GLfloat texCoords[8];
1177  GLuint locTexture;
1178  GLuint locModulation;
1179 
1180  GLES2_ActivateRenderer(renderer);
1181 
1182  /* Activate an appropriate shader and set the projection matrix */
1183  blendMode = texture->blendMode;
1184  if (renderer->target) {
1185  /* Check if we need to do color mapping between the source and render target textures */
1186  if (renderer->target->format != texture->format) {
1187  switch (texture->format)
1188  {
1190  switch (renderer->target->format)
1191  {
1194  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1195  break;
1197  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1198  break;
1199  }
1200  break;
1202  switch (renderer->target->format)
1203  {
1206  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1207  break;
1209  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1210  break;
1211  }
1212  break;
1214  switch (renderer->target->format)
1215  {
1217  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1218  break;
1220  sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1221  break;
1223  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1224  break;
1225  }
1226  break;
1228  switch (renderer->target->format)
1229  {
1231  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1232  break;
1234  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1235  break;
1237  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1238  break;
1239  }
1240  break;
1241  }
1242  }
1243  else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
1244  }
1245  else {
1246  switch (texture->format)
1247  {
1249  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1250  break;
1252  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1253  break;
1255  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1256  break;
1258  sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1259  break;
1260  default:
1261  return -1;
1262  }
1263  }
1264  if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
1265  return -1;
1266 
1267  /* Select the target texture */
1268  locTexture = rdata->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
1269  rdata->glGetError();
1270  rdata->glActiveTexture(GL_TEXTURE0);
1271  rdata->glBindTexture(tdata->texture_type, tdata->texture);
1272  rdata->glUniform1i(locTexture, 0);
1273 
1274  /* Configure color modulation */
1275  locModulation = rdata->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
1276  if (renderer->target &&
1277  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1278  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1279  rdata->glUniform4f(locModulation,
1280  texture->b * inv255f,
1281  texture->g * inv255f,
1282  texture->r * inv255f,
1283  texture->a * inv255f);
1284  } else {
1285  rdata->glUniform4f(locModulation,
1286  texture->r * inv255f,
1287  texture->g * inv255f,
1288  texture->b * inv255f,
1289  texture->a * inv255f);
1290  }
1291 
1292  /* Configure texture blending */
1293  GLES2_SetBlendMode(rdata, blendMode);
1294 
1295  GLES2_SetTexCoords(rdata, SDL_TRUE);
1296 
1297  /* Emit the textured quad */
1298  vertices[0] = dstrect->x;
1299  vertices[1] = dstrect->y;
1300  vertices[2] = (dstrect->x + dstrect->w);
1301  vertices[3] = dstrect->y;
1302  vertices[4] = dstrect->x;
1303  vertices[5] = (dstrect->y + dstrect->h);
1304  vertices[6] = (dstrect->x + dstrect->w);
1305  vertices[7] = (dstrect->y + dstrect->h);
1306  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
1307  texCoords[0] = srcrect->x / (GLfloat)texture->w;
1308  texCoords[1] = srcrect->y / (GLfloat)texture->h;
1309  texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1310  texCoords[3] = srcrect->y / (GLfloat)texture->h;
1311  texCoords[4] = srcrect->x / (GLfloat)texture->w;
1312  texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1313  texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1314  texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1315  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
1316  rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1317  if (rdata->glGetError() != GL_NO_ERROR) {
1318  return SDL_SetError("Failed to render texture");
1319  }
1320  return 0;
1321 }
1322 
1323 static int
1324 GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
1325  const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1326 {
1327  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
1328  GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
1329  GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1330  SDL_BlendMode blendMode;
1331  GLfloat vertices[8];
1332  GLfloat texCoords[8];
1333  GLuint locTexture;
1334  GLuint locModulation;
1335  GLfloat translate[8];
1336  GLfloat fAngle[4];
1337  GLfloat tmp;
1338 
1339  GLES2_ActivateRenderer(renderer);
1340 
1341  rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
1342  rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
1343  fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
1344  /* Calculate the center of rotation */
1345  translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
1346  translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
1347 
1348  /* Activate an appropriate shader and set the projection matrix */
1349  blendMode = texture->blendMode;
1350  if (renderer->target) {
1351  /* Check if we need to do color mapping between the source and render target textures */
1352  if (renderer->target->format != texture->format) {
1353  switch (texture->format)
1354  {
1356  switch (renderer->target->format)
1357  {
1360  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1361  break;
1363  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1364  break;
1365  }
1366  break;
1368  switch (renderer->target->format)
1369  {
1372  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1373  break;
1375  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1376  break;
1377  }
1378  break;
1380  switch (renderer->target->format)
1381  {
1383  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1384  break;
1386  sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1387  break;
1389  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1390  break;
1391  }
1392  break;
1394  switch (renderer->target->format)
1395  {
1397  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1398  break;
1400  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1401  break;
1403  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1404  break;
1405  }
1406  break;
1407  }
1408  }
1409  else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
1410  }
1411  else {
1412  switch (texture->format)
1413  {
1415  sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
1416  break;
1418  sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
1419  break;
1421  sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
1422  break;
1424  sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
1425  break;
1426  default:
1427  return -1;
1428  }
1429  }
1430  if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
1431  return -1;
1432 
1433  /* Select the target texture */
1434  locTexture = rdata->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE];
1435  rdata->glGetError();
1436  rdata->glActiveTexture(GL_TEXTURE0);
1437  rdata->glBindTexture(tdata->texture_type, tdata->texture);
1438  rdata->glUniform1i(locTexture, 0);
1439 
1440  /* Configure color modulation */
1441  locModulation = rdata->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
1442  if (renderer->target &&
1443  (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
1444  renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
1445  rdata->glUniform4f(locModulation,
1446  texture->b * inv255f,
1447  texture->g * inv255f,
1448  texture->r * inv255f,
1449  texture->a * inv255f);
1450  } else {
1451  rdata->glUniform4f(locModulation,
1452  texture->r * inv255f,
1453  texture->g * inv255f,
1454  texture->b * inv255f,
1455  texture->a * inv255f);
1456  }
1457 
1458  /* Configure texture blending */
1459  GLES2_SetBlendMode(rdata, blendMode);
1460 
1461  GLES2_SetTexCoords(rdata, SDL_TRUE);
1462 
1463  /* Emit the textured quad */
1464  vertices[0] = dstrect->x;
1465  vertices[1] = dstrect->y;
1466  vertices[2] = (dstrect->x + dstrect->w);
1467  vertices[3] = dstrect->y;
1468  vertices[4] = dstrect->x;
1469  vertices[5] = (dstrect->y + dstrect->h);
1470  vertices[6] = (dstrect->x + dstrect->w);
1471  vertices[7] = (dstrect->y + dstrect->h);
1472  if (flip & SDL_FLIP_HORIZONTAL) {
1473  tmp = vertices[0];
1474  vertices[0] = vertices[4] = vertices[2];
1475  vertices[2] = vertices[6] = tmp;
1476  }
1477  if (flip & SDL_FLIP_VERTICAL) {
1478  tmp = vertices[1];
1479  vertices[1] = vertices[3] = vertices[5];
1480  vertices[5] = vertices[7] = tmp;
1481  }
1482 
1483  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
1484  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
1485  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
1486 
1487  texCoords[0] = srcrect->x / (GLfloat)texture->w;
1488  texCoords[1] = srcrect->y / (GLfloat)texture->h;
1489  texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1490  texCoords[3] = srcrect->y / (GLfloat)texture->h;
1491  texCoords[4] = srcrect->x / (GLfloat)texture->w;
1492  texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1493  texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
1494  texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
1495  rdata->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
1496  rdata->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1497  rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
1498  rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
1499  if (rdata->glGetError() != GL_NO_ERROR) {
1500  return SDL_SetError("Failed to render texture");
1501  }
1502  return 0;
1503 }
1504 
1505 static int
1506 GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1507  Uint32 pixel_format, void * pixels, int pitch)
1508 {
1509  GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
1510  Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
1511  void *temp_pixels;
1512  int temp_pitch;
1513  Uint8 *src, *dst, *tmp;
1514  int w, h, length, rows;
1515  int status;
1516 
1517  GLES2_ActivateRenderer(renderer);
1518 
1519  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1520  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1521  if (!temp_pixels) {
1522  return SDL_OutOfMemory();
1523  }
1524 
1525  SDL_GetRendererOutputSize(renderer, &w, &h);
1526 
1527  rdata->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1528 
1529  rdata->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
1530  GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
1531 
1532  /* Flip the rows to be top-down */
1533  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1534  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1535  dst = (Uint8*)temp_pixels;
1536  tmp = SDL_stack_alloc(Uint8, length);
1537  rows = rect->h / 2;
1538  while (rows--) {
1539  SDL_memcpy(tmp, dst, length);
1540  SDL_memcpy(dst, src, length);
1541  SDL_memcpy(src, tmp, length);
1542  dst += temp_pitch;
1543  src -= temp_pitch;
1544  }
1545  SDL_stack_free(tmp);
1546 
1547  status = SDL_ConvertPixels(rect->w, rect->h,
1548  temp_format, temp_pixels, temp_pitch,
1549  pixel_format, pixels, pitch);
1550  SDL_free(temp_pixels);
1551 
1552  return status;
1553 }
1554 
1555 static void
1556 GLES2_RenderPresent(SDL_Renderer *renderer)
1557 {
1558  GLES2_ActivateRenderer(renderer);
1559 
1560  /* Tell the video driver to swap buffers */
1561  SDL_GL_SwapWindow(renderer->window);
1562 }
1563 
1564 
1565 /*************************************************************************************************
1566  * Bind/unbinding of textures
1567  *************************************************************************************************/
1568 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
1569 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
1570 
1571 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh) {
1572  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1573  GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
1574  GLES2_ActivateRenderer(renderer);
1575 
1576  data->glBindTexture(texturedata->texture_type, texturedata->texture);
1577 
1578  if(texw) *texw = 1.0;
1579  if(texh) *texh = 1.0;
1580 
1581  return 0;
1582 }
1583 
1584 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture) {
1585  GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
1586  GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
1587  GLES2_ActivateRenderer(renderer);
1588 
1589  data->glBindTexture(texturedata->texture_type, 0);
1590 
1591  return 0;
1592 }
1593 
1594 
1595 /*************************************************************************************************
1596  * Renderer instantiation *
1597  *************************************************************************************************/
1598 
1599 #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
1600 
1601 static void
1602 GLES2_ResetState(SDL_Renderer *renderer)
1603 {
1604  GLES2_DriverContext *rdata = (GLES2_DriverContext *) renderer->driverdata;
1605 
1606  if (SDL_CurrentContext == rdata->context) {
1607  GLES2_UpdateViewport(renderer);
1608  } else {
1609  GLES2_ActivateRenderer(renderer);
1610  }
1611 
1612  rdata->current.blendMode = -1;
1613  rdata->current.tex_coords = SDL_FALSE;
1614 
1615  rdata->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
1616  rdata->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
1617 }
1618 
1619 static SDL_Renderer *
1620 GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
1621 {
1622  SDL_Renderer *renderer;
1623  GLES2_DriverContext *rdata;
1624  GLint nFormats;
1625 #ifndef ZUNE_HD
1626  GLboolean hasCompiler;
1627 #endif
1628  Uint32 windowFlags;
1629  GLint window_framebuffer;
1630 
1634 
1635  windowFlags = SDL_GetWindowFlags(window);
1636  if (!(windowFlags & SDL_WINDOW_OPENGL)) {
1637  if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) {
1638  /* Uh oh, better try to put it back... */
1639  SDL_RecreateWindow(window, windowFlags);
1640  return NULL;
1641  }
1642  }
1643 
1644  /* Create the renderer struct */
1645  renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
1646  if (!renderer) {
1647  SDL_OutOfMemory();
1648  return NULL;
1649  }
1650 
1651  rdata = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext));
1652  if (!rdata) {
1653  GLES2_DestroyRenderer(renderer);
1654  SDL_OutOfMemory();
1655  return NULL;
1656  }
1657  renderer->info = GLES2_RenderDriver.info;
1659  renderer->driverdata = rdata;
1660  renderer->window = window;
1661 
1662  /* Create an OpenGL ES 2.0 context */
1663  rdata->context = SDL_GL_CreateContext(window);
1664  if (!rdata->context)
1665  {
1666  GLES2_DestroyRenderer(renderer);
1667  return NULL;
1668  }
1669  if (SDL_GL_MakeCurrent(window, rdata->context) < 0) {
1670  GLES2_DestroyRenderer(renderer);
1671  return NULL;
1672  }
1673 
1674  if (GLES2_LoadFunctions(rdata) < 0) {
1675  GLES2_DestroyRenderer(renderer);
1676  return NULL;
1677  }
1678 
1679  if (flags & SDL_RENDERER_PRESENTVSYNC) {
1681  } else {
1683  }
1684  if (SDL_GL_GetSwapInterval() > 0) {
1685  renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
1686  }
1687 
1688  /* Determine supported shader formats */
1689  /* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
1690  rdata->glGetError();
1691 #ifdef ZUNE_HD
1692  nFormats = 1;
1693 #else /* !ZUNE_HD */
1694  rdata->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
1695  rdata->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
1696  if (hasCompiler)
1697  ++nFormats;
1698 #endif /* ZUNE_HD */
1699  rdata->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum));
1700  if (!rdata->shader_formats)
1701  {
1702  GLES2_DestroyRenderer(renderer);
1703  SDL_OutOfMemory();
1704  return NULL;
1705  }
1706  rdata->shader_format_count = nFormats;
1707 #ifdef ZUNE_HD
1708  rdata->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
1709 #else /* !ZUNE_HD */
1710  rdata->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)rdata->shader_formats);
1711  if (rdata->glGetError() != GL_NO_ERROR)
1712  {
1713  GLES2_DestroyRenderer(renderer);
1714  SDL_SetError("Failed to query supported shader formats");
1715  return NULL;
1716  }
1717  if (hasCompiler)
1718  rdata->shader_formats[nFormats - 1] = (GLenum)-1;
1719 #endif /* ZUNE_HD */
1720 
1721  rdata->framebuffers = NULL;
1722  rdata->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
1723  rdata->window_framebuffer = (GLuint)window_framebuffer;
1724 
1725  /* Populate the function pointers for the module */
1726  renderer->WindowEvent = &GLES2_WindowEvent;
1727  renderer->CreateTexture = &GLES2_CreateTexture;
1728  renderer->UpdateTexture = &GLES2_UpdateTexture;
1729  renderer->LockTexture = &GLES2_LockTexture;
1730  renderer->UnlockTexture = &GLES2_UnlockTexture;
1731  renderer->SetRenderTarget = &GLES2_SetRenderTarget;
1732  renderer->UpdateViewport = &GLES2_UpdateViewport;
1733  renderer->UpdateClipRect = &GLES2_UpdateClipRect;
1734  renderer->RenderClear = &GLES2_RenderClear;
1735  renderer->RenderDrawPoints = &GLES2_RenderDrawPoints;
1736  renderer->RenderDrawLines = &GLES2_RenderDrawLines;
1737  renderer->RenderFillRects = &GLES2_RenderFillRects;
1738  renderer->RenderCopy = &GLES2_RenderCopy;
1739  renderer->RenderCopyEx = &GLES2_RenderCopyEx;
1740  renderer->RenderReadPixels = &GLES2_RenderReadPixels;
1741  renderer->RenderPresent = &GLES2_RenderPresent;
1742  renderer->DestroyTexture = &GLES2_DestroyTexture;
1743  renderer->DestroyRenderer = &GLES2_DestroyRenderer;
1744  renderer->GL_BindTexture = &GLES2_BindTexture;
1745  renderer->GL_UnbindTexture = &GLES2_UnbindTexture;
1746 
1747  GLES2_ResetState(renderer);
1748 
1749  return renderer;
1750 }
1751 
1752 #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
1753 
1754 /* vi: set ts=4 sw=4 expandtab: */
#define GL_TRUE
Definition: gl2.h:51
int(* UpdateClipRect)(SDL_Renderer *renderer)
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:57
#define GL_SRC_COLOR
Definition: gl2.h:75
#define GL_LINK_STATUS
Definition: gl2.h:270
#define GL_LINE_STRIP
Definition: gl2.h:57
#define GL_FALSE
Definition: gl2.h:50
#define GL_BLEND
Definition: gl2.h:147
#define GL_ZERO
Definition: gl2.h:73
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:7294
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size)
#define GL_CLAMP_TO_EDGE
Definition: gl2.h:375
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:80
unsigned int GLenum
Definition: gl2.h:23
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
SDL_RendererInfo info
DECLSPEC int SDLCALL SDL_GL_GetSwapInterval(void)
Get the swap interval for the current OpenGL context.
Definition: SDL_video.c:2857
#define GL_SRC_ALPHA
Definition: gl2.h:77
DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch)
Copy a block of pixels of one format to another format.
Definition: SDL_surface.c:984
#define GL_NUM_SHADER_BINARY_FORMATS
Definition: gl2.h:416
#define NULL
Definition: ftobjs.h:61
int(* RenderClear)(SDL_Renderer *renderer)
GLclampf f
Definition: glew.h:3390
#define GL_COLOR_ATTACHMENT0
Definition: gl2.h:452
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:227
unsigned char GLboolean
Definition: gl2.h:24
DECLSPEC SDL_GLContext SDLCALL SDL_GL_CreateContext(SDL_Window *window)
Create an OpenGL context for use with an OpenGL window, and make it current.
Definition: SDL_video.c:2758
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
GLdouble angle
Definition: glew.h:8396
SDL_bool
Definition: SDL_stdinc.h:116
GLenum GLsizei const GLuint GLboolean enabled
Definition: glew.h:2538
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:82
#define GL_TEXTURE_2D
Definition: gl2.h:145
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:118
void * driverdata
EGLSurface EGLint x
Definition: eglext.h:293
#define GL_FRAMEBUFFER_COMPLETE
Definition: gl2.h:458
DECLSPEC void SDLCALL SDL_free(void *mem)
int32_t j
Definition: e_log.c:102
#define GL_INFO_LOG_LENGTH
Definition: gl2.h:410
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:161
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:123
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:99
#define GL_TEXTURE_MAG_FILTER
Definition: gl2.h:319
DECLSPEC int SDLCALL SDL_GetRendererOutputSize(SDL_Renderer *renderer, int *w, int *h)
Get the output size of a rendering context.
Definition: SDL_render.c:338
SDL_Rect clip_rect
switch(yytype)
if(!yyg->yy_init)
GLuint id
Definition: gl2ext.h:1142
#define GL_SHADER_COMPILER
Definition: gl2.h:412
bbox yMin
Definition: ftbbox.c:603
#define GL_TRIANGLE_STRIP
Definition: gl2.h:59
SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r)
Returns true if the rectangle has no area.
Definition: SDL_rect.h:72
SDL_Window * window
SDL_RendererInfo info
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
const GLuint * framebuffers
Definition: glew.h:4126
DECLSPEC int SDLCALL SDL_GL_MakeCurrent(SDL_Window *window, SDL_GLContext context)
Set up an OpenGL context for rendering into an OpenGL window.
Definition: SDL_video.c:2781
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_sysrender.h:97
DECLSPEC int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value)
Set an OpenGL window attribute before window creation.
Definition: SDL_video.c:2469
#define GL_COLOR_BUFFER_BIT
Definition: gl2.h:47
#define GL_NO_ERROR
Definition: gl2.h:157
GLuint64EXT * result
Definition: glew.h:12708
GLuint shader
Definition: glew.h:1799
#define GL_TEXTURE_MIN_FILTER
Definition: gl2.h:320
DECLSPEC int SDLCALL SDL_GL_SetSwapInterval(int interval)
Set the swap interval for the current OpenGL context.
Definition: SDL_video.c:2843
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:89
GLenum GLenum dst
Definition: glew.h:2396
FT_UInt idx
Definition: cffcmap.c:125
SDL_Texture * target
GLsizei GLsizei * length
Definition: gl2ext.h:792
#define GL_ONE
Definition: gl2.h:74
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1317
static int GetScaleQuality(void)
SDL_BlendMode blendMode
#define GL_POINTS
Definition: gl2.h:54
GLint GLsizei count
Definition: gl2ext.h:1011
DECLSPEC void SDLCALL SDL_GL_DeleteContext(SDL_GLContext context)
Delete an OpenGL context.
Definition: SDL_video.c:2889
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
#define GL_PACK_ALIGNMENT
Definition: gl2.h:198
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
DECLSPEC Uint32 SDLCALL SDL_GetWindowFlags(SDL_Window *window)
Get the window flags.
Definition: SDL_video.c:1409
int x
Definition: SDL_rect.h:65
DECLSPEC const char *SDLCALL SDL_GetHint(const char *name)
Get a hint.
Definition: SDL_hints.c:104
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
GLbitfield GLuint program
Definition: gl2ext.h:1203
int w
Definition: SDL_rect.h:66
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
khronos_float_t GLfloat
Definition: gl2.h:33
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
#define GL_LINEAR
Definition: gl2.h:308
#define GL_COMPILE_STATUS
Definition: gl2.h:409
Window state change event data (event.window.*)
Definition: SDL_events.h:160
#define GL_RGBA
Definition: gl2.h:248
EGLSurface EGLint EGLint y
Definition: eglext.h:293
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_EventEntry * tail
Definition: SDL_events.c:79
GLenum GLenum GLuint texture
Definition: gl2ext.h:850
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: gl2ext.h:845
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
int GLint
Definition: gl2.h:28
unsigned int GLuint
Definition: gl2.h:32
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
Definition: SDL_string.c:293
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
#define GL_FRAMEBUFFER_BINDING
Definition: gl2.h:464
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_Rect viewport
#define GL_TEXTURE_WRAP_T
Definition: gl2.h:322
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
int h
Definition: SDL_rect.h:66
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
#define GL_UNSIGNED_BYTE
Definition: gl2.h:236
#define GL_TEXTURE_WRAP_S
Definition: gl2.h:321
#define GL_ONE_MINUS_SRC_ALPHA
Definition: gl2.h:78
Uint32 format
Definition: SDL_sysrender.h:52
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:226
#define GL_FRAMEBUFFER
Definition: gl2.h:427
#define GL_UNPACK_ALIGNMENT
Definition: gl2.h:197
void * driverdata
Definition: SDL_sysrender.h:69
int(* UpdateViewport)(SDL_Renderer *renderer)
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glew.h:3337
#define GL_FLOAT
Definition: gl2.h:241
GLenum src
Definition: glew.h:2396
bbox xMin
Definition: ftbbox.c:602
TParseContext * context
int i
Definition: pngrutil.c:1377
int(* RenderCopyEx)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
while(1)
SDL_EventEntry * head
Definition: SDL_events.c:78
void(* RenderPresent)(SDL_Renderer *renderer)
#define GL_SHADER_BINARY_FORMATS
Definition: gl2.h:415
void(* DestroyRenderer)(SDL_Renderer *renderer)
GLfloat vertices[12]
Definition: modern.h:22
#define GL_SCISSOR_TEST
Definition: gl2.h:151
GLsizei GLsizei GLchar * source
Definition: gl2ext.h:994
int y
Definition: SDL_rect.h:65
DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2)
Definition: SDL_string.c:946
#define GL_TEXTURE0
Definition: gl2.h:339
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:63
DECLSPEC void SDLCALL SDL_GL_SwapWindow(SDL_Window *window)
Swap the OpenGL buffers for a window, if double-buffering is supported.
Definition: SDL_video.c:2871
#define GL_NEAREST
Definition: gl2.h:307
cl_event event
Definition: glew.h:3556