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 int
528 GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
529 {
530  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
531  GLES_TextureData *data;
533  GLenum format, type;
534  int texture_w, texture_h;
535  GLenum scaleMode;
536  GLenum result;
537 
538  GLES_ActivateRenderer(renderer);
539 
540  switch (texture->format) {
543  format = GL_RGBA;
545  break;
546  default:
547  return SDL_SetError("Texture format not supported");
548  }
549 
550  data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
551  if (!data) {
552  return SDL_OutOfMemory();
553  }
554 
555  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
556  data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
557  data->pixels = SDL_calloc(1, texture->h * data->pitch);
558  if (!data->pixels) {
559  SDL_free(data);
560  return SDL_OutOfMemory();
561  }
562  }
563 
564 
565  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
566  if (!renderdata->GL_OES_framebuffer_object_supported) {
567  SDL_free(data);
568  return SDL_SetError("GL_OES_framebuffer_object not supported");
569  }
570  data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h);
571  } else {
572  data->fbo = NULL;
573  }
574 
575 
576  renderdata->glGetError();
577  renderdata->glEnable(GL_TEXTURE_2D);
578  renderdata->glGenTextures(1, &data->texture);
579  result = renderdata->glGetError();
580  if (result != GL_NO_ERROR) {
581  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
582  SDL_free(data->pixels);
583  }
584  SDL_free(data);
585  return GLES_SetError("glGenTextures()", result);
586  }
587 
588  data->type = GL_TEXTURE_2D;
589  /* no NPOV textures allowed in OpenGL ES (yet) */
590  texture_w = power_of_2(texture->w);
591  texture_h = power_of_2(texture->h);
592  data->texw = (GLfloat) texture->w / texture_w;
593  data->texh = (GLfloat) texture->h / texture_h;
594 
595  data->format = format;
596  data->formattype = type;
597  scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
598  renderdata->glBindTexture(data->type, data->texture);
599  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
600  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
601  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
602  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
603 
604  renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
605  texture_h, 0, format, type, NULL);
606  renderdata->glDisable(GL_TEXTURE_2D);
607 
608  result = renderdata->glGetError();
609  if (result != GL_NO_ERROR) {
610  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
611  SDL_free(data->pixels);
612  }
613  SDL_free(data);
614  return GLES_SetError("glTexImage2D()", result);
615  }
616 
617  texture->driverdata = data;
618  return 0;
619 }
620 
621 static int
622 GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
623  const SDL_Rect * rect, const void *pixels, int pitch)
624 {
625  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
626  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
627  Uint8 *blob = NULL;
628  Uint8 *src;
629  int srcPitch;
630  int y;
631 
632  GLES_ActivateRenderer(renderer);
633 
634  /* Bail out if we're supposed to update an empty rectangle */
635  if (rect->w <= 0 || rect->h <= 0) {
636  return 0;
637  }
638 
639  /* Reformat the texture data into a tightly packed array */
640  srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format);
641  src = (Uint8 *)pixels;
642  if (pitch != srcPitch) {
643  blob = (Uint8 *)SDL_malloc(srcPitch * rect->h);
644  if (!blob) {
645  return SDL_OutOfMemory();
646  }
647  src = blob;
648  for (y = 0; y < rect->h; ++y) {
649  SDL_memcpy(src, pixels, srcPitch);
650  src += srcPitch;
651  pixels = (Uint8 *)pixels + pitch;
652  }
653  src = blob;
654  }
655 
656  /* Create a texture subimage with the supplied data */
657  renderdata->glGetError();
658  renderdata->glEnable(data->type);
659  renderdata->glBindTexture(data->type, data->texture);
660  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
661  renderdata->glTexSubImage2D(data->type,
662  0,
663  rect->x,
664  rect->y,
665  rect->w,
666  rect->h,
667  data->format,
668  data->formattype,
669  src);
670  renderdata->glDisable(data->type);
671  SDL_free(blob);
672 
673  if (renderdata->glGetError() != GL_NO_ERROR) {
674  return SDL_SetError("Failed to update texture");
675  }
676  return 0;
677 }
678 
679 static int
680 GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
681  const SDL_Rect * rect, void **pixels, int *pitch)
682 {
683  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
684 
685  *pixels =
686  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
687  rect->x * SDL_BYTESPERPIXEL(texture->format));
688  *pitch = data->pitch;
689  return 0;
690 }
691 
692 static void
693 GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
694 {
695  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
696  SDL_Rect rect;
697 
698  /* We do whole texture updates, at least for now */
699  rect.x = 0;
700  rect.y = 0;
701  rect.w = texture->w;
702  rect.h = texture->h;
703  GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
704 }
705 
706 static int
707 GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
708 {
709  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
710  GLES_TextureData *texturedata = NULL;
711  GLenum status;
712 
713  if (!data->GL_OES_framebuffer_object_supported) {
714  return SDL_SetError("Can't enable render target support in this renderer");
715  }
716 
717  if (texture == NULL) {
718  data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
719  return 0;
720  }
721 
722  texturedata = (GLES_TextureData *) texture->driverdata;
723  data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
724  /* TODO: check if texture pixel format allows this operation */
725  data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
726  /* Check FBO status */
727  status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
728  if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
729  return SDL_SetError("glFramebufferTexture2DOES() failed");
730  }
731  return 0;
732 }
733 
734 static int
735 GLES_UpdateViewport(SDL_Renderer * renderer)
736 {
737  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
738 
739  if (SDL_CurrentContext != data->context) {
740  /* We'll update the viewport after we rebind the context */
741  return 0;
742  }
743 
744  if (renderer->target) {
745  data->glViewport(renderer->viewport.x, renderer->viewport.y,
746  renderer->viewport.w, renderer->viewport.h);
747  } else {
748  int w, h;
749 
750  SDL_GL_GetDrawableSize(renderer->window, &w, &h);
751  data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
752  renderer->viewport.w, renderer->viewport.h);
753  }
754 
755  data->glMatrixMode(GL_PROJECTION);
756  data->glLoadIdentity();
757  if (renderer->viewport.w && renderer->viewport.h) {
758  if (renderer->target) {
759  data->glOrthof((GLfloat) 0,
760  (GLfloat) renderer->viewport.w,
761  (GLfloat) 0,
762  (GLfloat) renderer->viewport.h,
763  0.0, 1.0);
764  } else {
765  data->glOrthof((GLfloat) 0,
766  (GLfloat) renderer->viewport.w,
767  (GLfloat) renderer->viewport.h,
768  (GLfloat) 0,
769  0.0, 1.0);
770  }
771  }
772  data->glMatrixMode(GL_MODELVIEW);
773 
774  return 0;
775 }
776 
777 static int
778 GLES_UpdateClipRect(SDL_Renderer * renderer)
779 {
780  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
781 
782  if (SDL_CurrentContext != data->context) {
783  /* We'll update the clip rect after we rebind the context */
784  return 0;
785  }
786 
787  if (renderer->clipping_enabled) {
788  const SDL_Rect *rect = &renderer->clip_rect;
789  data->glEnable(GL_SCISSOR_TEST);
790  if (renderer->target) {
791  data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h);
792  } else {
793  int w, h;
794 
795  SDL_GL_GetDrawableSize(renderer->window, &w, &h);
796  data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
797  }
798  } else {
799  data->glDisable(GL_SCISSOR_TEST);
800  }
801  return 0;
802 }
803 
804 static void
805 GLES_SetColor(GLES_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
806 {
807  Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
808 
809  if (color != data->current.color) {
810  data->glColor4f((GLfloat) r * inv255f,
811  (GLfloat) g * inv255f,
812  (GLfloat) b * inv255f,
813  (GLfloat) a * inv255f);
814  data->current.color = color;
815  }
816 }
817 
818 static void
819 GLES_SetBlendMode(GLES_RenderData * data, SDL_BlendMode blendMode)
820 {
821  if (blendMode != data->current.blendMode) {
822  if (blendMode == SDL_BLENDMODE_NONE) {
823  data->glDisable(GL_BLEND);
824  } else {
825  data->glEnable(GL_BLEND);
826  if (data->GL_OES_blend_func_separate_supported) {
827  data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
828  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
829  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
830  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
831  } else {
832  data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
833  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
834  }
835  if (data->GL_OES_blend_equation_separate_supported) {
836  data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)),
837  GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode)));
838  } else if (data->GL_OES_blend_subtract_supported) {
839  data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
840  }
841  }
842  data->current.blendMode = blendMode;
843  }
844 }
845 
846 static void
847 GLES_SetTexCoords(GLES_RenderData * data, SDL_bool enabled)
848 {
849  if (enabled != data->current.tex_coords) {
850  if (enabled) {
851  data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
852  } else {
853  data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
854  }
855  data->current.tex_coords = enabled;
856  }
857 }
858 
859 static void
860 GLES_SetDrawingState(SDL_Renderer * renderer)
861 {
862  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
863 
864  GLES_ActivateRenderer(renderer);
865 
866  GLES_SetColor(data, (GLfloat) renderer->r,
867  (GLfloat) renderer->g,
868  (GLfloat) renderer->b,
869  (GLfloat) renderer->a);
870 
871  GLES_SetBlendMode(data, renderer->blendMode);
872 
873  GLES_SetTexCoords(data, SDL_FALSE);
874 }
875 
876 static int
877 GLES_RenderClear(SDL_Renderer * renderer)
878 {
879  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
880 
881  GLES_ActivateRenderer(renderer);
882 
883  data->glClearColor((GLfloat) renderer->r * inv255f,
884  (GLfloat) renderer->g * inv255f,
885  (GLfloat) renderer->b * inv255f,
886  (GLfloat) renderer->a * inv255f);
887 
888  if (renderer->clipping_enabled) {
889  data->glDisable(GL_SCISSOR_TEST);
890  }
891 
892  data->glClear(GL_COLOR_BUFFER_BIT);
893 
894  if (renderer->clipping_enabled) {
895  data->glEnable(GL_SCISSOR_TEST);
896  }
897 
898  return 0;
899 }
900 
901 static int
902 GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
903  int count)
904 {
905  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
906  GLfloat *vertices;
907  int idx;
908 
909  GLES_SetDrawingState(renderer);
910 
911  /* Emit the specified vertices as points */
912  vertices = SDL_stack_alloc(GLfloat, count * 2);
913  for (idx = 0; idx < count; ++idx) {
914  GLfloat x = points[idx].x + 0.5f;
915  GLfloat y = points[idx].y + 0.5f;
916 
917  vertices[idx * 2] = x;
918  vertices[(idx * 2) + 1] = y;
919  }
920 
921  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
922  data->glDrawArrays(GL_POINTS, 0, count);
923  SDL_stack_free(vertices);
924  return 0;
925 }
926 
927 static int
928 GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
929  int count)
930 {
931  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
932  GLfloat *vertices;
933  int idx;
934 
935  GLES_SetDrawingState(renderer);
936 
937  /* Emit a line strip including the specified vertices */
938  vertices = SDL_stack_alloc(GLfloat, count * 2);
939  for (idx = 0; idx < count; ++idx) {
940  GLfloat x = points[idx].x + 0.5f;
941  GLfloat y = points[idx].y + 0.5f;
942 
943  vertices[idx * 2] = x;
944  vertices[(idx * 2) + 1] = y;
945  }
946 
947  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
948  if (count > 2 &&
949  points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
950  /* GL_LINE_LOOP takes care of the final segment */
951  --count;
952  data->glDrawArrays(GL_LINE_LOOP, 0, count);
953  } else {
954  data->glDrawArrays(GL_LINE_STRIP, 0, count);
955  /* We need to close the endpoint of the line */
956  data->glDrawArrays(GL_POINTS, count-1, 1);
957  }
958  SDL_stack_free(vertices);
959 
960  return 0;
961 }
962 
963 static int
964 GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
965  int count)
966 {
967  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
968  int i;
969 
970  GLES_SetDrawingState(renderer);
971 
972  for (i = 0; i < count; ++i) {
973  const SDL_FRect *rect = &rects[i];
974  GLfloat minx = rect->x;
975  GLfloat maxx = rect->x + rect->w;
976  GLfloat miny = rect->y;
977  GLfloat maxy = rect->y + rect->h;
978  GLfloat vertices[8];
979  vertices[0] = minx;
980  vertices[1] = miny;
981  vertices[2] = maxx;
982  vertices[3] = miny;
983  vertices[4] = minx;
984  vertices[5] = maxy;
985  vertices[6] = maxx;
986  vertices[7] = maxy;
987 
988  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
989  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
990  }
991 
992  return 0;
993 }
994 
995 static int
996 GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
997  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
998 {
999  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1000  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1001  GLfloat minx, miny, maxx, maxy;
1002  GLfloat minu, maxu, minv, maxv;
1003  GLfloat vertices[8];
1004  GLfloat texCoords[8];
1005 
1006  GLES_ActivateRenderer(renderer);
1007 
1008  data->glEnable(GL_TEXTURE_2D);
1009 
1010  data->glBindTexture(texturedata->type, texturedata->texture);
1011 
1012  if (texture->modMode) {
1013  GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
1014  } else {
1015  GLES_SetColor(data, 255, 255, 255, 255);
1016  }
1017 
1018  GLES_SetBlendMode(data, texture->blendMode);
1019 
1020  GLES_SetTexCoords(data, SDL_TRUE);
1021 
1022  minx = dstrect->x;
1023  miny = dstrect->y;
1024  maxx = dstrect->x + dstrect->w;
1025  maxy = dstrect->y + dstrect->h;
1026 
1027  minu = (GLfloat) srcrect->x / texture->w;
1028  minu *= texturedata->texw;
1029  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
1030  maxu *= texturedata->texw;
1031  minv = (GLfloat) srcrect->y / texture->h;
1032  minv *= texturedata->texh;
1033  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
1034  maxv *= texturedata->texh;
1035 
1036  vertices[0] = minx;
1037  vertices[1] = miny;
1038  vertices[2] = maxx;
1039  vertices[3] = miny;
1040  vertices[4] = minx;
1041  vertices[5] = maxy;
1042  vertices[6] = maxx;
1043  vertices[7] = maxy;
1044 
1045  texCoords[0] = minu;
1046  texCoords[1] = minv;
1047  texCoords[2] = maxu;
1048  texCoords[3] = minv;
1049  texCoords[4] = minu;
1050  texCoords[5] = maxv;
1051  texCoords[6] = maxu;
1052  texCoords[7] = maxv;
1053 
1054  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
1055  data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
1056  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1057 
1058  data->glDisable(GL_TEXTURE_2D);
1059 
1060  return 0;
1061 }
1062 
1063 static int
1064 GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1065  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1066  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1067 {
1068 
1069  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1070  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1071  GLfloat minx, miny, maxx, maxy;
1072  GLfloat minu, maxu, minv, maxv;
1073  GLfloat centerx, centery;
1074  GLfloat vertices[8];
1075  GLfloat texCoords[8];
1076 
1077 
1078  GLES_ActivateRenderer(renderer);
1079 
1080  data->glEnable(GL_TEXTURE_2D);
1081 
1082  data->glBindTexture(texturedata->type, texturedata->texture);
1083 
1084  if (texture->modMode) {
1085  GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
1086  } else {
1087  GLES_SetColor(data, 255, 255, 255, 255);
1088  }
1089 
1090  GLES_SetBlendMode(data, texture->blendMode);
1091 
1092  GLES_SetTexCoords(data, SDL_TRUE);
1093 
1094  centerx = center->x;
1095  centery = center->y;
1096 
1097  /* Rotate and translate */
1098  data->glPushMatrix();
1099  data->glTranslatef(dstrect->x + centerx, dstrect->y + centery, 0.0f);
1100  data->glRotatef((GLfloat)angle, 0.0f, 0.0f, 1.0f);
1101 
1102  if (flip & SDL_FLIP_HORIZONTAL) {
1103  minx = dstrect->w - centerx;
1104  maxx = -centerx;
1105  } else {
1106  minx = -centerx;
1107  maxx = dstrect->w - centerx;
1108  }
1109 
1110  if (flip & SDL_FLIP_VERTICAL) {
1111  miny = dstrect->h - centery;
1112  maxy = -centery;
1113  } else {
1114  miny = -centery;
1115  maxy = dstrect->h - centery;
1116  }
1117 
1118  minu = (GLfloat) srcrect->x / texture->w;
1119  minu *= texturedata->texw;
1120  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
1121  maxu *= texturedata->texw;
1122  minv = (GLfloat) srcrect->y / texture->h;
1123  minv *= texturedata->texh;
1124  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
1125  maxv *= texturedata->texh;
1126 
1127  vertices[0] = minx;
1128  vertices[1] = miny;
1129  vertices[2] = maxx;
1130  vertices[3] = miny;
1131  vertices[4] = minx;
1132  vertices[5] = maxy;
1133  vertices[6] = maxx;
1134  vertices[7] = maxy;
1135 
1136  texCoords[0] = minu;
1137  texCoords[1] = minv;
1138  texCoords[2] = maxu;
1139  texCoords[3] = minv;
1140  texCoords[4] = minu;
1141  texCoords[5] = maxv;
1142  texCoords[6] = maxu;
1143  texCoords[7] = maxv;
1144  data->glVertexPointer(2, GL_FLOAT, 0, vertices);
1145  data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
1146  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1147  data->glPopMatrix();
1148  data->glDisable(GL_TEXTURE_2D);
1149 
1150  return 0;
1151 }
1152 
1153 static int
1154 GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1155  Uint32 pixel_format, void * pixels, int pitch)
1156 {
1157  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1158  Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
1159  void *temp_pixels;
1160  int temp_pitch;
1161  Uint8 *src, *dst, *tmp;
1162  int w, h, length, rows;
1163  int status;
1164 
1165  GLES_ActivateRenderer(renderer);
1166 
1167  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1168  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1169  if (!temp_pixels) {
1170  return SDL_OutOfMemory();
1171  }
1172 
1173  SDL_GetRendererOutputSize(renderer, &w, &h);
1174 
1175  data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1176 
1177  data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
1178  rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
1179 
1180  /* Flip the rows to be top-down if necessary */
1181  if (!renderer->target) {
1182  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1183  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1184  dst = (Uint8*)temp_pixels;
1185  tmp = SDL_stack_alloc(Uint8, length);
1186  rows = rect->h / 2;
1187  while (rows--) {
1188  SDL_memcpy(tmp, dst, length);
1189  SDL_memcpy(dst, src, length);
1190  SDL_memcpy(src, tmp, length);
1191  dst += temp_pitch;
1192  src -= temp_pitch;
1193  }
1194  SDL_stack_free(tmp);
1195  }
1196 
1197  status = SDL_ConvertPixels(rect->w, rect->h,
1198  temp_format, temp_pixels, temp_pitch,
1199  pixel_format, pixels, pitch);
1200  SDL_free(temp_pixels);
1201 
1202  return status;
1203 }
1204 
1205 static void
1206 GLES_RenderPresent(SDL_Renderer * renderer)
1207 {
1208  GLES_ActivateRenderer(renderer);
1209 
1210  SDL_GL_SwapWindow(renderer->window);
1211 }
1212 
1213 static void
1214 GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1215 {
1216  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
1217 
1218  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
1219 
1220  GLES_ActivateRenderer(renderer);
1221 
1222  if (!data) {
1223  return;
1224  }
1225  if (data->texture) {
1226  renderdata->glDeleteTextures(1, &data->texture);
1227  }
1228  SDL_free(data->pixels);
1229  SDL_free(data);
1230  texture->driverdata = NULL;
1231 }
1232 
1233 static void
1234 GLES_DestroyRenderer(SDL_Renderer * renderer)
1235 {
1236  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1237 
1238  if (data) {
1239  if (data->context) {
1240  while (data->framebuffers) {
1241  GLES_FBOList *nextnode = data->framebuffers->next;
1242  data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
1243  SDL_free(data->framebuffers);
1244  data->framebuffers = nextnode;
1245  }
1246  SDL_GL_DeleteContext(data->context);
1247  }
1248  SDL_free(data);
1249  }
1250  SDL_free(renderer);
1251 }
1252 
1253 static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
1254 {
1255  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1256  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1257  GLES_ActivateRenderer(renderer);
1258 
1259  data->glEnable(GL_TEXTURE_2D);
1260  data->glBindTexture(texturedata->type, texturedata->texture);
1261 
1262  if (texw) {
1263  *texw = (float)texturedata->texw;
1264  }
1265  if (texh) {
1266  *texh = (float)texturedata->texh;
1267  }
1268 
1269  return 0;
1270 }
1271 
1272 static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
1273 {
1274  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1275  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1276  GLES_ActivateRenderer(renderer);
1277  data->glDisable(texturedata->type);
1278 
1279  return 0;
1280 }
1281 
1282 #endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */
1283 
1284 /* vi: set ts=4 sw=4 expandtab: */
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2252
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:65
#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)
#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:91
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 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:2280
#define SDL_GetWindowFlags
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2266
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
float GLfloat
Definition: SDL_opengl.h:187
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:90
#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:99
#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:2287
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:193
#define SDL_GL_GetSwapInterval
GLenum GLenum GLenum input
SDL_Texture * target
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1617
#define GL_STACK_OVERFLOW
Definition: SDL_opengl.h:723
static SDL_Renderer * renderer
uint8_t Uint8
Definition: SDL_stdinc.h:179
#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:195
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:161
#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:2273
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
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define GL_ONE_MINUS_DST_COLOR
Definition: SDL_opengl.h:409
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2259
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:89
GLfloat angle
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
Uint32 format
Definition: SDL_sysrender.h:60
#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:78
#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:92
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
SDL_ScaleMode scaleMode
Definition: SDL_sysrender.h:66
#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