SDL  2.0
SDL_render_gles.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED
24 
25 #include "SDL_hints.h"
26 #include "SDL_opengles.h"
27 #include "../SDL_sysrender.h"
28 
29 /* To prevent unnecessary window recreation,
30  * these should match the defaults selected in SDL_GL_ResetAttributes
31  */
32 
33 #define RENDERER_CONTEXT_MAJOR 1
34 #define RENDERER_CONTEXT_MINOR 1
35 
36 #if defined(SDL_VIDEO_DRIVER_PANDORA)
37 
38 /* Empty function stub to get OpenGL ES 1.x support without */
39 /* OpenGL ES extension GL_OES_draw_texture supported */
40 GL_API void GL_APIENTRY
41 glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height)
42 {
43  return;
44 }
45 
46 #endif /* SDL_VIDEO_DRIVER_PANDORA */
47 
48 /* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */
49 
50 /* Used to re-create the window with OpenGL ES capability */
52 
53 static const float inv255f = 1.0f / 255.0f;
54 
55 static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
56 static void GLES_WindowEvent(SDL_Renderer * renderer,
57  const SDL_WindowEvent *event);
58 static int GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
59 static SDL_bool GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
60 static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
61 static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
62  const SDL_Rect * rect, const void *pixels,
63  int pitch);
64 static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
65  const SDL_Rect * rect, void **pixels, int *pitch);
66 static void GLES_UnlockTexture(SDL_Renderer * renderer,
68 static int GLES_SetRenderTarget(SDL_Renderer * renderer,
70 static int GLES_UpdateViewport(SDL_Renderer * renderer);
71 static int GLES_UpdateClipRect(SDL_Renderer * renderer);
72 static int GLES_RenderClear(SDL_Renderer * renderer);
73 static int GLES_RenderDrawPoints(SDL_Renderer * renderer,
74  const SDL_FPoint * points, int count);
75 static int GLES_RenderDrawLines(SDL_Renderer * renderer,
76  const SDL_FPoint * points, int count);
77 static int GLES_RenderFillRects(SDL_Renderer * renderer,
78  const SDL_FRect * rects, int count);
79 static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
80  const SDL_Rect * srcrect,
81  const SDL_FRect * dstrect);
82 static int GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
83  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
84  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
85 static int GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
86  Uint32 pixel_format, void * pixels, int pitch);
87 static void GLES_RenderPresent(SDL_Renderer * renderer);
88 static void GLES_DestroyTexture(SDL_Renderer * renderer,
90 static void GLES_DestroyRenderer(SDL_Renderer * renderer);
91 static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
92 static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
93 
94 typedef struct GLES_FBOList GLES_FBOList;
95 
96 struct GLES_FBOList
97 {
98  Uint32 w, h;
99  GLuint FBO;
100  GLES_FBOList *next;
101 };
102 
103 
105  GLES_CreateRenderer,
106  {
107  "opengles",
109  1,
111  0,
112  0}
113 };
114 
115 typedef struct
116 {
118  struct {
119  Uint32 color;
121  SDL_bool tex_coords;
122  } current;
123 
124 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
125 #define SDL_PROC_OES SDL_PROC
126 #include "SDL_glesfuncs.h"
127 #undef SDL_PROC
128 #undef SDL_PROC_OES
129  SDL_bool GL_OES_framebuffer_object_supported;
130  GLES_FBOList *framebuffers;
131  GLuint window_framebuffer;
132 
133  SDL_bool GL_OES_blend_func_separate_supported;
134  SDL_bool GL_OES_blend_equation_separate_supported;
135  SDL_bool GL_OES_blend_subtract_supported;
136 } GLES_RenderData;
137 
138 typedef struct
139 {
140  GLuint texture;
141  GLenum type;
142  GLfloat texw;
143  GLfloat texh;
144  GLenum format;
145  GLenum formattype;
146  void *pixels;
147  int pitch;
148  GLES_FBOList *fbo;
149 } GLES_TextureData;
150 
151 static int
152 GLES_SetError(const char *prefix, GLenum result)
153 {
154  const char *error;
155 
156  switch (result) {
157  case GL_NO_ERROR:
158  error = "GL_NO_ERROR";
159  break;
160  case GL_INVALID_ENUM:
161  error = "GL_INVALID_ENUM";
162  break;
163  case GL_INVALID_VALUE:
164  error = "GL_INVALID_VALUE";
165  break;
167  error = "GL_INVALID_OPERATION";
168  break;
169  case GL_STACK_OVERFLOW:
170  error = "GL_STACK_OVERFLOW";
171  break;
172  case GL_STACK_UNDERFLOW:
173  error = "GL_STACK_UNDERFLOW";
174  break;
175  case GL_OUT_OF_MEMORY:
176  error = "GL_OUT_OF_MEMORY";
177  break;
178  default:
179  error = "UNKNOWN";
180  break;
181  }
182  return SDL_SetError("%s: %s", prefix, error);
183 }
184 
185 static int GLES_LoadFunctions(GLES_RenderData * data)
186 {
187 #if SDL_VIDEO_DRIVER_UIKIT
188 #define __SDL_NOGETPROCADDR__
189 #elif SDL_VIDEO_DRIVER_ANDROID
190 #define __SDL_NOGETPROCADDR__
191 #elif SDL_VIDEO_DRIVER_PANDORA
192 #define __SDL_NOGETPROCADDR__
193 #endif
194 
195 #ifdef __SDL_NOGETPROCADDR__
196 #define SDL_PROC(ret,func,params) data->func=func;
197 #define SDL_PROC_OES(ret,func,params) data->func=func;
198 #else
199 #define SDL_PROC(ret,func,params) \
200  do { \
201  data->func = SDL_GL_GetProcAddress(#func); \
202  if ( ! data->func ) { \
203  return SDL_SetError("Couldn't load GLES function %s: %s", #func, SDL_GetError()); \
204  } \
205  } while ( 0 );
206 #define SDL_PROC_OES(ret,func,params) \
207  do { \
208  data->func = SDL_GL_GetProcAddress(#func); \
209  } while ( 0 );
210 #endif /* __SDL_NOGETPROCADDR__ */
211 
212 #include "SDL_glesfuncs.h"
213 #undef SDL_PROC
214 #undef SDL_PROC_OES
215  return 0;
216 }
217 
218 static SDL_GLContext SDL_CurrentContext = NULL;
219 
220 static GLES_FBOList *
221 GLES_GetFBO(GLES_RenderData *data, Uint32 w, Uint32 h)
222 {
223  GLES_FBOList *result = data->framebuffers;
224  while ((result) && ((result->w != w) || (result->h != h)) ) {
225  result = result->next;
226  }
227  if (result == NULL) {
228  result = SDL_malloc(sizeof(GLES_FBOList));
229  result->w = w;
230  result->h = h;
231  data->glGenFramebuffersOES(1, &result->FBO);
232  result->next = data->framebuffers;
233  data->framebuffers = result;
234  }
235  return result;
236 }
237 
238 
239 static int
240 GLES_ActivateRenderer(SDL_Renderer * renderer)
241 {
242  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
243 
244  if (SDL_CurrentContext != data->context) {
245  if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
246  return -1;
247  }
248  SDL_CurrentContext = data->context;
249 
250  GLES_UpdateViewport(renderer);
251  }
252  return 0;
253 }
254 
255 /* This is called if we need to invalidate all of the SDL OpenGL state */
256 static void
257 GLES_ResetState(SDL_Renderer *renderer)
258 {
259  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
260 
261  if (SDL_CurrentContext == data->context) {
262  GLES_UpdateViewport(renderer);
263  } else {
264  GLES_ActivateRenderer(renderer);
265  }
266 
267  data->current.color = 0xffffffff;
268  data->current.blendMode = SDL_BLENDMODE_INVALID;
269  data->current.tex_coords = SDL_FALSE;
270 
271  data->glDisable(GL_DEPTH_TEST);
272  data->glDisable(GL_CULL_FACE);
273 
274  data->glMatrixMode(GL_MODELVIEW);
275  data->glLoadIdentity();
276 
277  data->glEnableClientState(GL_VERTEX_ARRAY);
278  data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
279 }
280 
281 SDL_Renderer *
282 GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
283 {
284 
286  GLES_RenderData *data;
287  GLint value;
288  Uint32 window_flags;
289  int profile_mask = 0, major = 0, minor = 0;
290  SDL_bool changed_window = SDL_FALSE;
291 
295 
296  window_flags = SDL_GetWindowFlags(window);
297  if (!(window_flags & SDL_WINDOW_OPENGL) ||
298  profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
299 
300  changed_window = SDL_TRUE;
302  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
303  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
304 
305  if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
306  goto error;
307  }
308  }
309 
310  renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
311  if (!renderer) {
312  SDL_OutOfMemory();
313  goto error;
314  }
315 
316  data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
317  if (!data) {
318  GLES_DestroyRenderer(renderer);
319  SDL_OutOfMemory();
320  goto error;
321  }
322 
323  renderer->WindowEvent = GLES_WindowEvent;
324  renderer->GetOutputSize = GLES_GetOutputSize;
325  renderer->SupportsBlendMode = GLES_SupportsBlendMode;
326  renderer->CreateTexture = GLES_CreateTexture;
327  renderer->UpdateTexture = GLES_UpdateTexture;
328  renderer->LockTexture = GLES_LockTexture;
329  renderer->UnlockTexture = GLES_UnlockTexture;
330  renderer->SetRenderTarget = GLES_SetRenderTarget;
331  renderer->UpdateViewport = GLES_UpdateViewport;
332  renderer->UpdateClipRect = GLES_UpdateClipRect;
333  renderer->RenderClear = GLES_RenderClear;
334  renderer->RenderDrawPoints = GLES_RenderDrawPoints;
335  renderer->RenderDrawLines = GLES_RenderDrawLines;
336  renderer->RenderFillRects = GLES_RenderFillRects;
337  renderer->RenderCopy = GLES_RenderCopy;
338  renderer->RenderCopyEx = GLES_RenderCopyEx;
339  renderer->RenderReadPixels = GLES_RenderReadPixels;
340  renderer->RenderPresent = GLES_RenderPresent;
341  renderer->DestroyTexture = GLES_DestroyTexture;
342  renderer->DestroyRenderer = GLES_DestroyRenderer;
343  renderer->GL_BindTexture = GLES_BindTexture;
344  renderer->GL_UnbindTexture = GLES_UnbindTexture;
345  renderer->info = GLES_RenderDriver.info;
346  renderer->info.flags = SDL_RENDERER_ACCELERATED;
347  renderer->driverdata = data;
348  renderer->window = window;
349 
350  data->context = SDL_GL_CreateContext(window);
351  if (!data->context) {
352  GLES_DestroyRenderer(renderer);
353  goto error;
354  }
355  if (SDL_GL_MakeCurrent(window, data->context) < 0) {
356  GLES_DestroyRenderer(renderer);
357  goto error;
358  }
359 
360  if (GLES_LoadFunctions(data) < 0) {
361  GLES_DestroyRenderer(renderer);
362  goto error;
363  }
364 
365  if (flags & SDL_RENDERER_PRESENTVSYNC) {
367  } else {
369  }
370  if (SDL_GL_GetSwapInterval() > 0) {
371  renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
372  }
373 
374  value = 0;
375  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
376  renderer->info.max_texture_width = value;
377  value = 0;
378  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
379  renderer->info.max_texture_height = value;
380 
381  /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */
382  if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) {
383  data->GL_OES_framebuffer_object_supported = SDL_TRUE;
385 
386  value = 0;
387  data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
388  data->window_framebuffer = (GLuint)value;
389  }
390  data->framebuffers = NULL;
391 
392  if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
393  data->GL_OES_blend_func_separate_supported = SDL_TRUE;
394  }
395  if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) {
396  data->GL_OES_blend_equation_separate_supported = SDL_TRUE;
397  }
398  if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) {
399  data->GL_OES_blend_subtract_supported = SDL_TRUE;
400  }
401 
402  /* Set up parameters for rendering */
403  GLES_ResetState(renderer);
404 
405  return renderer;
406 
407 error:
408  if (changed_window) {
409  /* Uh oh, better try to put it back... */
413  SDL_RecreateWindow(window, window_flags);
414  }
415  return NULL;
416 }
417 
418 static void
419 GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
420 {
421  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
422 
423  if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
424  event->event == SDL_WINDOWEVENT_SHOWN ||
425  event->event == SDL_WINDOWEVENT_HIDDEN) {
426  /* Rebind the context to the window area and update matrices */
427  SDL_CurrentContext = NULL;
428  }
429 
430  if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
431  /* According to Apple documentation, we need to finish drawing NOW! */
432  data->glFinish();
433  }
434 }
435 
436 static int
437 GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
438 {
439  SDL_GL_GetDrawableSize(renderer->window, w, h);
440  return 0;
441 }
442 
443 static GLenum GetBlendFunc(SDL_BlendFactor factor)
444 {
445  switch (factor) {
447  return GL_ZERO;
448  case SDL_BLENDFACTOR_ONE:
449  return GL_ONE;
451  return GL_SRC_COLOR;
453  return GL_ONE_MINUS_SRC_COLOR;
455  return GL_SRC_ALPHA;
457  return GL_ONE_MINUS_SRC_ALPHA;
459  return GL_DST_COLOR;
461  return GL_ONE_MINUS_DST_COLOR;
463  return GL_DST_ALPHA;
465  return GL_ONE_MINUS_DST_ALPHA;
466  default:
467  return GL_INVALID_ENUM;
468  }
469 }
470 
471 static GLenum GetBlendEquation(SDL_BlendOperation operation)
472 {
473  switch (operation) {
475  return GL_FUNC_ADD_OES;
477  return GL_FUNC_SUBTRACT_OES;
479  return GL_FUNC_REVERSE_SUBTRACT_OES;
480  default:
481  return GL_INVALID_ENUM;
482  }
483 }
484 
485 static SDL_bool
486 GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
487 {
488  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
489  SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
490  SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
491  SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
492  SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
493  SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
494  SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
495 
496  if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
497  GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
498  GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
499  GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
500  GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
501  GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
502  return SDL_FALSE;
503  }
504  if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->GL_OES_blend_func_separate_supported) {
505  return SDL_FALSE;
506  }
507  if (colorOperation != alphaOperation && !data->GL_OES_blend_equation_separate_supported) {
508  return SDL_FALSE;
509  }
510  if (colorOperation != SDL_BLENDOPERATION_ADD && !data->GL_OES_blend_subtract_supported) {
511  return SDL_FALSE;
512  }
513  return SDL_TRUE;
514 }
515 
516 static SDL_INLINE int
517 power_of_2(int input)
518 {
519  int value = 1;
520 
521  while (value < input) {
522  value <<= 1;
523  }
524  return value;
525 }
526 
527 static GLenum
528 GetScaleQuality(void)
529 {
530  const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
531 
532  if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
533  return GL_NEAREST;
534  } else {
535  return GL_LINEAR;
536  }
537 }
538 
539 static int
540 GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
541 {
542  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
543  GLES_TextureData *data;
545  GLenum format, type;
546  int texture_w, texture_h;
547  GLenum scaleMode;
548  GLenum result;
549 
550  GLES_ActivateRenderer(renderer);
551 
552  switch (texture->format) {
555  format = GL_RGBA;
557  break;
558  default:
559  return SDL_SetError("Texture format not supported");
560  }
561 
562  data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
563  if (!data) {
564  return SDL_OutOfMemory();
565  }
566 
567  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
568  data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
569  data->pixels = SDL_calloc(1, texture->h * data->pitch);
570  if (!data->pixels) {
571  SDL_free(data);
572  return SDL_OutOfMemory();
573  }
574  }
575 
576 
577  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
578  if (!renderdata->GL_OES_framebuffer_object_supported) {
579  SDL_free(data);
580  return SDL_SetError("GL_OES_framebuffer_object not supported");
581  }
582  data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h);
583  } else {
584  data->fbo = NULL;
585  }
586 
587 
588  renderdata->glGetError();
589  renderdata->glEnable(GL_TEXTURE_2D);
590  renderdata->glGenTextures(1, &data->texture);
591  result = renderdata->glGetError();
592  if (result != GL_NO_ERROR) {
593  SDL_free(data);
594  return GLES_SetError("glGenTextures()", result);
595  }
596 
597  data->type = GL_TEXTURE_2D;
598  /* no NPOV textures allowed in OpenGL ES (yet) */
599  texture_w = power_of_2(texture->w);
600  texture_h = power_of_2(texture->h);
601  data->texw = (GLfloat) texture->w / texture_w;
602  data->texh = (GLfloat) texture->h / texture_h;
603 
604  data->format = format;
605  data->formattype = type;
606  scaleMode = GetScaleQuality();
607  renderdata->glBindTexture(data->type, data->texture);
608  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
609  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
610  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
611  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
612 
613  renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
614  texture_h, 0, format, type, NULL);
615  renderdata->glDisable(GL_TEXTURE_2D);
616 
617  result = renderdata->glGetError();
618  if (result != GL_NO_ERROR) {
619  SDL_free(data);
620  return GLES_SetError("glTexImage2D()", result);
621  }
622 
623  texture->driverdata = data;
624  return 0;
625 }
626 
627 static int
628 GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
629  const SDL_Rect * rect, const void *pixels, int pitch)
630 {
631  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
632  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
633  Uint8 *blob = NULL;
634  Uint8 *src;
635  int srcPitch;
636  int y;
637 
638  GLES_ActivateRenderer(renderer);
639 
640  /* Bail out if we're supposed to update an empty rectangle */
641  if (rect->w <= 0 || rect->h <= 0) {
642  return 0;
643  }
644 
645  /* Reformat the texture data into a tightly packed array */
646  srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format);
647  src = (Uint8 *)pixels;
648  if (pitch != srcPitch) {
649  blob = (Uint8 *)SDL_malloc(srcPitch * rect->h);
650  if (!blob) {
651  return SDL_OutOfMemory();
652  }
653  src = blob;
654  for (y = 0; y < rect->h; ++y) {
655  SDL_memcpy(src, pixels, srcPitch);
656  src += srcPitch;
657  pixels = (Uint8 *)pixels + pitch;
658  }
659  src = blob;
660  }
661 
662  /* Create a texture subimage with the supplied data */
663  renderdata->glGetError();
664  renderdata->glEnable(data->type);
665  renderdata->glBindTexture(data->type, data->texture);
666  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
667  renderdata->glTexSubImage2D(data->type,
668  0,
669  rect->x,
670  rect->y,
671  rect->w,
672  rect->h,
673  data->format,
674  data->formattype,
675  src);
676  renderdata->glDisable(data->type);
677  SDL_free(blob);
678 
679  if (renderdata->glGetError() != GL_NO_ERROR) {
680  return SDL_SetError("Failed to update texture");
681  }
682  return 0;
683 }
684 
685 static int
686 GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
687  const SDL_Rect * rect, void **pixels, int *pitch)
688 {
689  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
690 
691  *pixels =
692  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
693  rect->x * SDL_BYTESPERPIXEL(texture->format));
694  *pitch = data->pitch;
695  return 0;
696 }
697 
698 static void
699 GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
700 {
701  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
702  SDL_Rect rect;
703 
704  /* We do whole texture updates, at least for now */
705  rect.x = 0;
706  rect.y = 0;
707  rect.w = texture->w;
708  rect.h = texture->h;
709  GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
710 }
711 
712 static int
713 GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
714 {
715  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
716  GLES_TextureData *texturedata = NULL;
717  GLenum status;
718 
719  if (!data->GL_OES_framebuffer_object_supported) {
720  return SDL_SetError("Can't enable render target support in this renderer");
721  }
722 
723  if (texture == NULL) {
724  data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
725  return 0;
726  }
727 
728  texturedata = (GLES_TextureData *) texture->driverdata;
729  data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
730  /* TODO: check if texture pixel format allows this operation */
731  data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
732  /* Check FBO status */
733  status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
734  if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
735  return SDL_SetError("glFramebufferTexture2DOES() failed");
736  }
737  return 0;
738 }
739 
740 static int
741 GLES_UpdateViewport(SDL_Renderer * renderer)
742 {
743  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
744 
745  if (SDL_CurrentContext != data->context) {
746  /* We'll update the viewport after we rebind the context */
747  return 0;
748  }
749 
750  if (renderer->target) {
751  data->glViewport(renderer->viewport.x, renderer->viewport.y,
752  renderer->viewport.w, renderer->viewport.h);
753  } else {
754  int w, h;
755 
756  SDL_GL_GetDrawableSize(renderer->window, &w, &h);
757  data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
758  renderer->viewport.w, renderer->viewport.h);
759  }
760 
761  data->glMatrixMode(GL_PROJECTION);
762  data->glLoadIdentity();
763  if (renderer->viewport.w && renderer->viewport.h) {
764  if (renderer->target) {
765  data->glOrthof((GLfloat) 0,
766  (GLfloat) renderer->viewport.w,
767  (GLfloat) 0,
768  (GLfloat) renderer->viewport.h,
769  0.0, 1.0);
770  } else {
771  data->glOrthof((GLfloat) 0,
772  (GLfloat) renderer->viewport.w,
773  (GLfloat) renderer->viewport.h,
774  (GLfloat) 0,
775  0.0, 1.0);
776  }
777  }
778  data->glMatrixMode(GL_MODELVIEW);
779 
780  return 0;
781 }
782 
783 static int
784 GLES_UpdateClipRect(SDL_Renderer * renderer)
785 {
786  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
787 
788  if (SDL_CurrentContext != data->context) {
789  /* We'll update the clip rect after we rebind the context */
790  return 0;
791  }
792 
793  if (renderer->clipping_enabled) {
794  const SDL_Rect *rect = &renderer->clip_rect;
795  data->glEnable(GL_SCISSOR_TEST);
796  if (renderer->target) {
797  data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h);
798  } else {
799  int w, h;
800 
801  SDL_GL_GetDrawableSize(renderer->window, &w, &h);
802  data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
803  }
804  } else {
805  data->glDisable(GL_SCISSOR_TEST);
806  }
807  return 0;
808 }
809 
810 static void
811 GLES_SetColor(GLES_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
812 {
813  Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
814 
815  if (color != data->current.color) {
816  data->glColor4f((GLfloat) r * inv255f,
817  (GLfloat) g * inv255f,
818  (GLfloat) b * inv255f,
819  (GLfloat) a * inv255f);
820  data->current.color = color;
821  }
822 }
823 
824 static void
825 GLES_SetBlendMode(GLES_RenderData * data, SDL_BlendMode blendMode)
826 {
827  if (blendMode != data->current.blendMode) {
828  if (blendMode == SDL_BLENDMODE_NONE) {
829  data->glDisable(GL_BLEND);
830  } else {
831  data->glEnable(GL_BLEND);
832  if (data->GL_OES_blend_func_separate_supported) {
833  data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
834  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
835  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
836  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
837  } else {
838  data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
839  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
840  }
841  if (data->GL_OES_blend_equation_separate_supported) {
842  data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)),
843  GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode)));
844  } else if (data->GL_OES_blend_subtract_supported) {
845  data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
846  }
847  }
848  data->current.blendMode = blendMode;
849  }
850 }
851 
852 static void
853 GLES_SetTexCoords(GLES_RenderData * data, SDL_bool enabled)
854 {
855  if (enabled != data->current.tex_coords) {
856  if (enabled) {
857  data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
858  } else {
859  data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
860  }
861  data->current.tex_coords = enabled;
862  }
863 }
864 
865 static void
866 GLES_SetDrawingState(SDL_Renderer * renderer)
867 {
868  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
869 
870  GLES_ActivateRenderer(renderer);
871 
872  GLES_SetColor(data, (GLfloat) renderer->r,
873  (GLfloat) renderer->g,
874  (GLfloat) renderer->b,
875  (GLfloat) renderer->a);
876 
877  GLES_SetBlendMode(data, renderer->blendMode);
878 
879  GLES_SetTexCoords(data, SDL_FALSE);
880 }
881 
882 static int
883 GLES_RenderClear(SDL_Renderer * renderer)
884 {
885  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
886 
887  GLES_ActivateRenderer(renderer);
888 
889  data->glClearColor((GLfloat) renderer->r * inv255f,
890  (GLfloat) renderer->g * inv255f,
891  (GLfloat) renderer->b * inv255f,
892  (GLfloat) renderer->a * inv255f);
893 
894  if (renderer->clipping_enabled) {
895  data->glDisable(GL_SCISSOR_TEST);
896  }
897 
898  data->glClear(GL_COLOR_BUFFER_BIT);
899 
900  if (renderer->clipping_enabled) {
901  data->glEnable(GL_SCISSOR_TEST);
902  }
903 
904  return 0;
905 }
906 
907 static int
908 GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
909  int count)
910 {
911  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
912  GLfloat *vertices;
913  int idx;
914 
915  GLES_SetDrawingState(renderer);
916 
917  /* Emit the specified vertices as points */
918  vertices = SDL_stack_alloc(GLfloat, count * 2);
919  for (idx = 0; idx < count; ++idx) {
920  GLfloat x = points[idx].x + 0.5f;
921  GLfloat y = points[idx].y + 0.5f;
922 
923  vertices[idx * 2] = x;
924  vertices[(idx * 2) + 1] = y;
925  }
926 
927  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
928  data->glDrawArrays(GL_POINTS, 0, count);
929  SDL_stack_free(vertices);
930  return 0;
931 }
932 
933 static int
934 GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
935  int count)
936 {
937  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
938  GLfloat *vertices;
939  int idx;
940 
941  GLES_SetDrawingState(renderer);
942 
943  /* Emit a line strip including the specified vertices */
944  vertices = SDL_stack_alloc(GLfloat, count * 2);
945  for (idx = 0; idx < count; ++idx) {
946  GLfloat x = points[idx].x + 0.5f;
947  GLfloat y = points[idx].y + 0.5f;
948 
949  vertices[idx * 2] = x;
950  vertices[(idx * 2) + 1] = y;
951  }
952 
953  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
954  if (count > 2 &&
955  points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
956  /* GL_LINE_LOOP takes care of the final segment */
957  --count;
958  data->glDrawArrays(GL_LINE_LOOP, 0, count);
959  } else {
960  data->glDrawArrays(GL_LINE_STRIP, 0, count);
961  /* We need to close the endpoint of the line */
962  data->glDrawArrays(GL_POINTS, count-1, 1);
963  }
964  SDL_stack_free(vertices);
965 
966  return 0;
967 }
968 
969 static int
970 GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
971  int count)
972 {
973  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
974  int i;
975 
976  GLES_SetDrawingState(renderer);
977 
978  for (i = 0; i < count; ++i) {
979  const SDL_FRect *rect = &rects[i];
980  GLfloat minx = rect->x;
981  GLfloat maxx = rect->x + rect->w;
982  GLfloat miny = rect->y;
983  GLfloat maxy = rect->y + rect->h;
984  GLfloat vertices[8];
985  vertices[0] = minx;
986  vertices[1] = miny;
987  vertices[2] = maxx;
988  vertices[3] = miny;
989  vertices[4] = minx;
990  vertices[5] = maxy;
991  vertices[6] = maxx;
992  vertices[7] = maxy;
993 
994  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
995  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
996  }
997 
998  return 0;
999 }
1000 
1001 static int
1002 GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1003  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1004 {
1005  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1006  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1007  GLfloat minx, miny, maxx, maxy;
1008  GLfloat minu, maxu, minv, maxv;
1009  GLfloat vertices[8];
1010  GLfloat texCoords[8];
1011 
1012  GLES_ActivateRenderer(renderer);
1013 
1014  data->glEnable(GL_TEXTURE_2D);
1015 
1016  data->glBindTexture(texturedata->type, texturedata->texture);
1017 
1018  if (texture->modMode) {
1019  GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
1020  } else {
1021  GLES_SetColor(data, 255, 255, 255, 255);
1022  }
1023 
1024  GLES_SetBlendMode(data, texture->blendMode);
1025 
1026  GLES_SetTexCoords(data, SDL_TRUE);
1027 
1028  minx = dstrect->x;
1029  miny = dstrect->y;
1030  maxx = dstrect->x + dstrect->w;
1031  maxy = dstrect->y + dstrect->h;
1032 
1033  minu = (GLfloat) srcrect->x / texture->w;
1034  minu *= texturedata->texw;
1035  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
1036  maxu *= texturedata->texw;
1037  minv = (GLfloat) srcrect->y / texture->h;
1038  minv *= texturedata->texh;
1039  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
1040  maxv *= texturedata->texh;
1041 
1042  vertices[0] = minx;
1043  vertices[1] = miny;
1044  vertices[2] = maxx;
1045  vertices[3] = miny;
1046  vertices[4] = minx;
1047  vertices[5] = maxy;
1048  vertices[6] = maxx;
1049  vertices[7] = maxy;
1050 
1051  texCoords[0] = minu;
1052  texCoords[1] = minv;
1053  texCoords[2] = maxu;
1054  texCoords[3] = minv;
1055  texCoords[4] = minu;
1056  texCoords[5] = maxv;
1057  texCoords[6] = maxu;
1058  texCoords[7] = maxv;
1059 
1060  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
1061  data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
1062  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1063 
1064  data->glDisable(GL_TEXTURE_2D);
1065 
1066  return 0;
1067 }
1068 
1069 static int
1070 GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1071  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1072  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1073 {
1074 
1075  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1076  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1077  GLfloat minx, miny, maxx, maxy;
1078  GLfloat minu, maxu, minv, maxv;
1079  GLfloat centerx, centery;
1080  GLfloat vertices[8];
1081  GLfloat texCoords[8];
1082 
1083 
1084  GLES_ActivateRenderer(renderer);
1085 
1086  data->glEnable(GL_TEXTURE_2D);
1087 
1088  data->glBindTexture(texturedata->type, texturedata->texture);
1089 
1090  if (texture->modMode) {
1091  GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
1092  } else {
1093  GLES_SetColor(data, 255, 255, 255, 255);
1094  }
1095 
1096  GLES_SetBlendMode(data, texture->blendMode);
1097 
1098  GLES_SetTexCoords(data, SDL_TRUE);
1099 
1100  centerx = center->x;
1101  centery = center->y;
1102 
1103  /* Rotate and translate */
1104  data->glPushMatrix();
1105  data->glTranslatef(dstrect->x + centerx, dstrect->y + centery, 0.0f);
1106  data->glRotatef((GLfloat)angle, 0.0f, 0.0f, 1.0f);
1107 
1108  if (flip & SDL_FLIP_HORIZONTAL) {
1109  minx = dstrect->w - centerx;
1110  maxx = -centerx;
1111  } else {
1112  minx = -centerx;
1113  maxx = dstrect->w - centerx;
1114  }
1115 
1116  if (flip & SDL_FLIP_VERTICAL) {
1117  miny = dstrect->h - centery;
1118  maxy = -centery;
1119  } else {
1120  miny = -centery;
1121  maxy = dstrect->h - centery;
1122  }
1123 
1124  minu = (GLfloat) srcrect->x / texture->w;
1125  minu *= texturedata->texw;
1126  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
1127  maxu *= texturedata->texw;
1128  minv = (GLfloat) srcrect->y / texture->h;
1129  minv *= texturedata->texh;
1130  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
1131  maxv *= texturedata->texh;
1132 
1133  vertices[0] = minx;
1134  vertices[1] = miny;
1135  vertices[2] = maxx;
1136  vertices[3] = miny;
1137  vertices[4] = minx;
1138  vertices[5] = maxy;
1139  vertices[6] = maxx;
1140  vertices[7] = maxy;
1141 
1142  texCoords[0] = minu;
1143  texCoords[1] = minv;
1144  texCoords[2] = maxu;
1145  texCoords[3] = minv;
1146  texCoords[4] = minu;
1147  texCoords[5] = maxv;
1148  texCoords[6] = maxu;
1149  texCoords[7] = maxv;
1150  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
1151  data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
1152  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1153  data->glPopMatrix();
1154  data->glDisable(GL_TEXTURE_2D);
1155 
1156  return 0;
1157 }
1158 
1159 static int
1160 GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1161  Uint32 pixel_format, void * pixels, int pitch)
1162 {
1163  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1164  Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
1165  void *temp_pixels;
1166  int temp_pitch;
1167  Uint8 *src, *dst, *tmp;
1168  int w, h, length, rows;
1169  int status;
1170 
1171  GLES_ActivateRenderer(renderer);
1172 
1173  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1174  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1175  if (!temp_pixels) {
1176  return SDL_OutOfMemory();
1177  }
1178 
1179  SDL_GetRendererOutputSize(renderer, &w, &h);
1180 
1181  data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1182 
1183  data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
1184  rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
1185 
1186  /* Flip the rows to be top-down if necessary */
1187  if (!renderer->target) {
1188  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1189  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1190  dst = (Uint8*)temp_pixels;
1191  tmp = SDL_stack_alloc(Uint8, length);
1192  rows = rect->h / 2;
1193  while (rows--) {
1194  SDL_memcpy(tmp, dst, length);
1195  SDL_memcpy(dst, src, length);
1196  SDL_memcpy(src, tmp, length);
1197  dst += temp_pitch;
1198  src -= temp_pitch;
1199  }
1200  SDL_stack_free(tmp);
1201  }
1202 
1203  status = SDL_ConvertPixels(rect->w, rect->h,
1204  temp_format, temp_pixels, temp_pitch,
1205  pixel_format, pixels, pitch);
1206  SDL_free(temp_pixels);
1207 
1208  return status;
1209 }
1210 
1211 static void
1212 GLES_RenderPresent(SDL_Renderer * renderer)
1213 {
1214  GLES_ActivateRenderer(renderer);
1215 
1216  SDL_GL_SwapWindow(renderer->window);
1217 }
1218 
1219 static void
1220 GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1221 {
1222  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
1223 
1224  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
1225 
1226  GLES_ActivateRenderer(renderer);
1227 
1228  if (!data) {
1229  return;
1230  }
1231  if (data->texture) {
1232  renderdata->glDeleteTextures(1, &data->texture);
1233  }
1234  SDL_free(data->pixels);
1235  SDL_free(data);
1236  texture->driverdata = NULL;
1237 }
1238 
1239 static void
1240 GLES_DestroyRenderer(SDL_Renderer * renderer)
1241 {
1242  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1243 
1244  if (data) {
1245  if (data->context) {
1246  while (data->framebuffers) {
1247  GLES_FBOList *nextnode = data->framebuffers->next;
1248  data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
1249  SDL_free(data->framebuffers);
1250  data->framebuffers = nextnode;
1251  }
1252  SDL_GL_DeleteContext(data->context);
1253  }
1254  SDL_free(data);
1255  }
1256  SDL_free(renderer);
1257 }
1258 
1259 static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
1260 {
1261  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1262  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1263  GLES_ActivateRenderer(renderer);
1264 
1265  data->glEnable(GL_TEXTURE_2D);
1266  data->glBindTexture(texturedata->type, texturedata->texture);
1267 
1268  if (texw) {
1269  *texw = (float)texturedata->texw;
1270  }
1271  if (texh) {
1272  *texh = (float)texturedata->texh;
1273  }
1274 
1275  return 0;
1276 }
1277 
1278 static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
1279 {
1280  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1281  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1282  GLES_ActivateRenderer(renderer);
1283  data->glDisable(texturedata->type);
1284 
1285  return 0;
1286 }
1287 
1288 #endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */
1289 
1290 /* vi: set ts=4 sw=4 expandtab: */
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2193
SDL_BlendFactor
The normalized factor used to multiply pixel components.
Definition: SDL_blendmode.h:75
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
#define GL_ONE
Definition: SDL_opengl.h:401
#define GL_STACK_UNDERFLOW
Definition: SDL_opengl.h:724
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:57
#define SDL_GL_ExtensionSupported
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
#define GL_INVALID_ENUM
Definition: SDL_opengl.h:720
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_sysrender.h:98
#define GL_INVALID_OPERATION
Definition: SDL_opengl.h:722
GLdouble GLdouble z
GLuint64EXT * result
#define GL_SCISSOR_TEST
Definition: SDL_opengl.h:615
#define SDL_GL_CreateContext
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
const GLuint * framebuffers
SDL_RendererInfo info
GLenum GLenum dst
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
#define GL_PROJECTION
Definition: SDL_opengl.h:272
SDL_RenderDriver GLES_RenderDriver
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Definition: SDL_sysrender.h:82
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Rect rect
Definition: testrelative.c:27
#define GL_LINEAR
Definition: SDL_opengl.h:447
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:143
#define GL_CLAMP_TO_EDGE
Definition: SDL_opengl.h:1507
GLfloat GLfloat GLfloat GLfloat h
void * driverdata
int GLint
Definition: SDL_opengl.h:182
#define GL_RGBA
Definition: SDL_opengl.h:529
static screen_context_t context
Definition: video.c:25
SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2221
#define SDL_GetHint
#define SDL_GetWindowFlags
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2207
GLfloat f
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
#define GL_TEXTURE_MAG_FILTER
Definition: SDL_opengl.h:674
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
SDL_Rect clip_rect
#define GL_TRIANGLE_STRIP
Definition: SDL_opengl.h:221
uint32_t Uint32
Definition: SDL_stdinc.h:181
float GLfloat
Definition: SDL_opengl.h:187
#define SDL_strcasecmp
GLenum src
int max_texture_height
Definition: SDL_render.h:85
#define GL_ONE_MINUS_SRC_ALPHA
Definition: SDL_opengl.h:405
SDL_BlendOperation
The blend operation used when combining source and destination pixel components.
Definition: SDL_blendmode.h:62
SDL_Window * window
SDL_RendererInfo info
#define GL_ONE_MINUS_SRC_COLOR
Definition: SDL_opengl.h:403
int(* RenderClear)(SDL_Renderer *renderer)
void(* DestroyRenderer)(SDL_Renderer *renderer)
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
GLfixed GLfixed GLint GLint GLfixed points
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
Definition: SDL_sysrender.h:81
#define GL_PACK_ALIGNMENT
Definition: SDL_opengl.h:652
#define GL_MAX_TEXTURE_SIZE
Definition: SDL_opengl.h:536
#define GL_NO_ERROR
Definition: SDL_opengl.h:719
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
#define GL_BLEND
Definition: SDL_opengl.h:397
#define GL_SRC_COLOR
Definition: SDL_opengl.h:402
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:90
#define SDL_GL_SetAttribute
#define SDL_GL_GetDrawableSize
#define GL_ONE_MINUS_DST_ALPHA
Definition: SDL_opengl.h:407
#define SDL_memcpy
GLenum GLenum GLuint texture
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2228
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:175
#define SDL_GL_GetSwapInterval
GLenum GLenum GLenum input
SDL_Texture * target
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1542
#define GL_STACK_OVERFLOW
Definition: SDL_opengl.h:723
static int GetScaleQuality(void)
static SDL_Renderer * renderer
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
struct _cl_event * event
SDL_BlendMode blendMode
#define SDL_GL_SetSwapInterval
#define GL_LINE_STRIP
Definition: SDL_opengl.h:219
#define GL_TEXTURE_WRAP_T
Definition: SDL_opengl.h:673
#define GL_LINE_LOOP
Definition: SDL_opengl.h:218
#define GL_FLOAT
Definition: SDL_opengl.h:209
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
#define GL_TEXTURE_2D
Definition: SDL_opengl.h:671
GLubyte GLubyte GLubyte GLubyte w
GLsizei const GLfloat * value
#define GL_UNSIGNED_BYTE
Definition: SDL_opengl.h:204
#define GL_APIENTRY
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
#define GL_DST_COLOR
Definition: SDL_opengl.h:408
int x
Definition: SDL_rect.h:66
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* UpdateViewport)(SDL_Renderer *renderer)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
#define GL_COLOR_BUFFER_BIT
Definition: SDL_opengl.h:742
#define GL_INVALID_VALUE
Definition: SDL_opengl.h:721
int w
Definition: SDL_rect.h:67
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
GLenum GLenum GLsizei const GLuint GLboolean enabled
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Window state change event data (event.window.*)
Definition: SDL_events.h:174
unsigned int GLenum
Definition: SDL_opengl.h:176
GLenum internalFormat
#define GL_POINTS
Definition: SDL_opengl.h:216
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
#define GL_CULL_FACE
Definition: SDL_opengl.h:302
#define GL_MODELVIEW
Definition: SDL_opengl.h:271
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2214
unsigned int GLuint
Definition: SDL_opengl.h:185
#define SDL_SetError
#define GL_OUT_OF_MEMORY
Definition: SDL_opengl.h:725
GLbitfield flags
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
int(* RenderCopyEx)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
#define SDL_calloc
#define SDL_GL_MakeCurrent
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
#define SDL_GetRendererOutputSize
#define GL_VERTEX_ARRAY
Definition: SDL_opengl.h:228
SDL_Rect viewport
int h
Definition: SDL_rect.h:67
The type used to identify a window.
Definition: SDL_sysvideo.h:73
#define GL_ZERO
Definition: SDL_opengl.h:400
#define GL_ONE_MINUS_DST_COLOR
Definition: SDL_opengl.h:409
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2200
GLuint color
#define GL_SRC_ALPHA
Definition: SDL_opengl.h:404
#define GL_NEAREST
Definition: SDL_opengl.h:704
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:80
GLfloat angle
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
Uint32 format
Definition: SDL_sysrender.h:52
#define GL_TEXTURE_COORD_ARRAY
Definition: SDL_opengl.h:232
#define GL_DST_ALPHA
Definition: SDL_opengl.h:406
void * driverdata
Definition: SDL_sysrender.h:69
#define SDL_INLINE
Definition: begin_code.h:131
#define GL_DEPTH_TEST
Definition: SDL_opengl.h:327
#define SDL_malloc
#define SDL_GL_GetAttribute
#define SDL_ConvertPixels
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:83
void(* RenderPresent)(SDL_Renderer *renderer)
#define SDL_GL_DeleteContext
EGLSurface EGLint * rects
Definition: eglext.h:282
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
#define GL_TEXTURE_WRAP_S
Definition: SDL_opengl.h:672
GLuint GLsizei GLsizei * length
#define GL_TEXTURE_MIN_FILTER
Definition: SDL_opengl.h:675
GLboolean GLboolean GLboolean GLboolean a
#define GL_UNPACK_ALIGNMENT
Definition: SDL_opengl.h:658
int(* UpdateClipRect)(SDL_Renderer *renderer)
GLboolean GLboolean g
GLboolean GLboolean GLboolean b
int y
Definition: SDL_rect.h:66
#define SDL_GL_SwapWindow
SDL_bool clipping_enabled
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64