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