SDL  2.0
SDL_render_gles.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 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 typedef struct GLES_FBOList GLES_FBOList;
56 
57 struct GLES_FBOList
58 {
59  Uint32 w, h;
60  GLuint FBO;
61  GLES_FBOList *next;
62 };
63 
64 typedef struct
65 {
67  SDL_bool viewport_dirty;
70  int drawablew;
71  int drawableh;
72  SDL_BlendMode blend;
73  SDL_bool cliprect_enabled_dirty;
74  SDL_bool cliprect_enabled;
75  SDL_bool cliprect_dirty;
76  SDL_Rect cliprect;
77  SDL_bool texturing;
78  Uint32 color;
79  Uint32 clear_color;
80 } GLES_DrawStateCache;
81 
82 typedef struct
83 {
85 
86 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
87 #define SDL_PROC_OES SDL_PROC
88 #include "SDL_glesfuncs.h"
89 #undef SDL_PROC
90 #undef SDL_PROC_OES
91  SDL_bool GL_OES_framebuffer_object_supported;
92  GLES_FBOList *framebuffers;
93  GLuint window_framebuffer;
94 
95  SDL_bool GL_OES_blend_func_separate_supported;
96  SDL_bool GL_OES_blend_equation_separate_supported;
97  SDL_bool GL_OES_blend_subtract_supported;
98 
99  GLES_DrawStateCache drawstate;
100 } GLES_RenderData;
101 
102 typedef struct
103 {
104  GLuint texture;
105  GLenum type;
106  GLfloat texw;
107  GLfloat texh;
108  GLenum format;
109  GLenum formattype;
110  void *pixels;
111  int pitch;
112  GLES_FBOList *fbo;
113 } GLES_TextureData;
114 
115 static int
116 GLES_SetError(const char *prefix, GLenum result)
117 {
118  const char *error;
119 
120  switch (result) {
121  case GL_NO_ERROR:
122  error = "GL_NO_ERROR";
123  break;
124  case GL_INVALID_ENUM:
125  error = "GL_INVALID_ENUM";
126  break;
127  case GL_INVALID_VALUE:
128  error = "GL_INVALID_VALUE";
129  break;
131  error = "GL_INVALID_OPERATION";
132  break;
133  case GL_STACK_OVERFLOW:
134  error = "GL_STACK_OVERFLOW";
135  break;
136  case GL_STACK_UNDERFLOW:
137  error = "GL_STACK_UNDERFLOW";
138  break;
139  case GL_OUT_OF_MEMORY:
140  error = "GL_OUT_OF_MEMORY";
141  break;
142  default:
143  error = "UNKNOWN";
144  break;
145  }
146  return SDL_SetError("%s: %s", prefix, error);
147 }
148 
149 static int GLES_LoadFunctions(GLES_RenderData * data)
150 {
151 #if SDL_VIDEO_DRIVER_UIKIT
152 #define __SDL_NOGETPROCADDR__
153 #elif SDL_VIDEO_DRIVER_ANDROID
154 #define __SDL_NOGETPROCADDR__
155 #elif SDL_VIDEO_DRIVER_PANDORA
156 #define __SDL_NOGETPROCADDR__
157 #endif
158 
159 #ifdef __SDL_NOGETPROCADDR__
160 #define SDL_PROC(ret,func,params) data->func=func;
161 #define SDL_PROC_OES(ret,func,params) data->func=func;
162 #else
163 #define SDL_PROC(ret,func,params) \
164  do { \
165  data->func = SDL_GL_GetProcAddress(#func); \
166  if ( ! data->func ) { \
167  return SDL_SetError("Couldn't load GLES function %s: %s", #func, SDL_GetError()); \
168  } \
169  } while ( 0 );
170 #define SDL_PROC_OES(ret,func,params) \
171  do { \
172  data->func = SDL_GL_GetProcAddress(#func); \
173  } while ( 0 );
174 #endif /* __SDL_NOGETPROCADDR__ */
175 
176 #include "SDL_glesfuncs.h"
177 #undef SDL_PROC
178 #undef SDL_PROC_OES
179  return 0;
180 }
181 
182 static GLES_FBOList *
183 GLES_GetFBO(GLES_RenderData *data, Uint32 w, Uint32 h)
184 {
185  GLES_FBOList *result = data->framebuffers;
186  while ((result) && ((result->w != w) || (result->h != h)) ) {
187  result = result->next;
188  }
189  if (result == NULL) {
190  result = SDL_malloc(sizeof(GLES_FBOList));
191  result->w = w;
192  result->h = h;
193  data->glGenFramebuffersOES(1, &result->FBO);
194  result->next = data->framebuffers;
195  data->framebuffers = result;
196  }
197  return result;
198 }
199 
200 
201 static int
202 GLES_ActivateRenderer(SDL_Renderer * renderer)
203 {
204  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
205 
206  if (SDL_GL_GetCurrentContext() != data->context) {
207  if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
208  return -1;
209  }
210  }
211 
212  return 0;
213 }
214 
215 static void
216 GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
217 {
218  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
219 
220  if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
221  /* According to Apple documentation, we need to finish drawing NOW! */
222  data->glFinish();
223  }
224 }
225 
226 static int
227 GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
228 {
230  return 0;
231 }
232 
233 static GLenum GetBlendFunc(SDL_BlendFactor factor)
234 {
235  switch (factor) {
237  return GL_ZERO;
238  case SDL_BLENDFACTOR_ONE:
239  return GL_ONE;
241  return GL_SRC_COLOR;
243  return GL_ONE_MINUS_SRC_COLOR;
245  return GL_SRC_ALPHA;
247  return GL_ONE_MINUS_SRC_ALPHA;
249  return GL_DST_COLOR;
251  return GL_ONE_MINUS_DST_COLOR;
253  return GL_DST_ALPHA;
255  return GL_ONE_MINUS_DST_ALPHA;
256  default:
257  return GL_INVALID_ENUM;
258  }
259 }
260 
261 static GLenum GetBlendEquation(SDL_BlendOperation operation)
262 {
263  switch (operation) {
265  return GL_FUNC_ADD_OES;
267  return GL_FUNC_SUBTRACT_OES;
269  return GL_FUNC_REVERSE_SUBTRACT_OES;
270  default:
271  return GL_INVALID_ENUM;
272  }
273 }
274 
275 static SDL_bool
276 GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
277 {
278  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
285 
286  if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
287  GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
288  GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
289  GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
290  GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
291  GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
292  return SDL_FALSE;
293  }
294  if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->GL_OES_blend_func_separate_supported) {
295  return SDL_FALSE;
296  }
297  if (colorOperation != alphaOperation && !data->GL_OES_blend_equation_separate_supported) {
298  return SDL_FALSE;
299  }
300  if (colorOperation != SDL_BLENDOPERATION_ADD && !data->GL_OES_blend_subtract_supported) {
301  return SDL_FALSE;
302  }
303  return SDL_TRUE;
304 }
305 
306 static SDL_INLINE int
307 power_of_2(int input)
308 {
309  int value = 1;
310 
311  while (value < input) {
312  value <<= 1;
313  }
314  return value;
315 }
316 
317 static int
318 GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
319 {
320  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
321  GLES_TextureData *data;
323  GLenum format, type;
324  int texture_w, texture_h;
325  GLenum scaleMode;
326  GLenum result;
327 
328  GLES_ActivateRenderer(renderer);
329 
330  switch (texture->format) {
333  format = GL_RGBA;
335  break;
336  default:
337  return SDL_SetError("Texture format not supported");
338  }
339 
340  data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
341  if (!data) {
342  return SDL_OutOfMemory();
343  }
344 
345  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
346  data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
347  data->pixels = SDL_calloc(1, texture->h * data->pitch);
348  if (!data->pixels) {
349  SDL_free(data);
350  return SDL_OutOfMemory();
351  }
352  }
353 
354 
355  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
356  if (!renderdata->GL_OES_framebuffer_object_supported) {
357  SDL_free(data);
358  return SDL_SetError("GL_OES_framebuffer_object not supported");
359  }
360  data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h);
361  } else {
362  data->fbo = NULL;
363  }
364 
365 
366  renderdata->glGetError();
367  renderdata->glEnable(GL_TEXTURE_2D);
368  renderdata->glGenTextures(1, &data->texture);
369  result = renderdata->glGetError();
370  if (result != GL_NO_ERROR) {
371  SDL_free(data);
372  return GLES_SetError("glGenTextures()", result);
373  }
374 
375  data->type = GL_TEXTURE_2D;
376  /* no NPOV textures allowed in OpenGL ES (yet) */
377  texture_w = power_of_2(texture->w);
378  texture_h = power_of_2(texture->h);
379  data->texw = (GLfloat) texture->w / texture_w;
380  data->texh = (GLfloat) texture->h / texture_h;
381 
382  data->format = format;
383  data->formattype = type;
384  scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
385  renderdata->glBindTexture(data->type, data->texture);
386  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
387  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
388  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
389  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
390 
391  renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
392  texture_h, 0, format, type, NULL);
393  renderdata->glDisable(GL_TEXTURE_2D);
394  renderdata->drawstate.texture = texture;
395  renderdata->drawstate.texturing = SDL_FALSE;
396 
397  result = renderdata->glGetError();
398  if (result != GL_NO_ERROR) {
399  SDL_free(data);
400  return GLES_SetError("glTexImage2D()", result);
401  }
402 
403  texture->driverdata = data;
404  return 0;
405 }
406 
407 static int
408 GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
409  const SDL_Rect * rect, const void *pixels, int pitch)
410 {
411  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
412  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
413  Uint8 *blob = NULL;
414  Uint8 *src;
415  int srcPitch;
416  int y;
417 
418  GLES_ActivateRenderer(renderer);
419 
420  /* Bail out if we're supposed to update an empty rectangle */
421  if (rect->w <= 0 || rect->h <= 0) {
422  return 0;
423  }
424 
425  /* Reformat the texture data into a tightly packed array */
426  srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format);
427  src = (Uint8 *)pixels;
428  if (pitch != srcPitch) {
429  blob = (Uint8 *)SDL_malloc(srcPitch * rect->h);
430  if (!blob) {
431  return SDL_OutOfMemory();
432  }
433  src = blob;
434  for (y = 0; y < rect->h; ++y) {
435  SDL_memcpy(src, pixels, srcPitch);
436  src += srcPitch;
437  pixels = (Uint8 *)pixels + pitch;
438  }
439  src = blob;
440  }
441 
442  /* Create a texture subimage with the supplied data */
443  renderdata->glGetError();
444  renderdata->glEnable(data->type);
445  renderdata->glBindTexture(data->type, data->texture);
446  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
447  renderdata->glTexSubImage2D(data->type,
448  0,
449  rect->x,
450  rect->y,
451  rect->w,
452  rect->h,
453  data->format,
454  data->formattype,
455  src);
456  renderdata->glDisable(data->type);
457  SDL_free(blob);
458 
459  renderdata->drawstate.texture = texture;
460  renderdata->drawstate.texturing = SDL_FALSE;
461 
462  if (renderdata->glGetError() != GL_NO_ERROR) {
463  return SDL_SetError("Failed to update texture");
464  }
465  return 0;
466 }
467 
468 static int
469 GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
470  const SDL_Rect * rect, void **pixels, int *pitch)
471 {
472  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
473 
474  *pixels =
475  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
476  rect->x * SDL_BYTESPERPIXEL(texture->format));
477  *pitch = data->pitch;
478  return 0;
479 }
480 
481 static void
482 GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
483 {
484  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
485  SDL_Rect rect;
486 
487  /* We do whole texture updates, at least for now */
488  rect.x = 0;
489  rect.y = 0;
490  rect.w = texture->w;
491  rect.h = texture->h;
492  GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
493 }
494 
495 static void
496 GLES_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
497 {
498  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
499  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
500  GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
501 
502  renderdata->glBindTexture(data->type, data->texture);
503  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, glScaleMode);
504  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, glScaleMode);
505 }
506 
507 static int
508 GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
509 {
510  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
511  GLES_TextureData *texturedata = NULL;
512  GLenum status;
513 
514  if (!data->GL_OES_framebuffer_object_supported) {
515  return SDL_SetError("Can't enable render target support in this renderer");
516  }
517 
518  data->drawstate.viewport_dirty = SDL_TRUE;
519 
520  if (texture == NULL) {
521  data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
522  return 0;
523  }
524 
525  texturedata = (GLES_TextureData *) texture->driverdata;
526  data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
527  /* TODO: check if texture pixel format allows this operation */
528  data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
529  /* Check FBO status */
530  status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
531  if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
532  return SDL_SetError("glFramebufferTexture2DOES() failed");
533  }
534  return 0;
535 }
536 
537 
538 static int
539 GLES_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
540 {
541  return 0; /* nothing to do in this backend. */
542 }
543 
544 static int
545 GLES_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
546 {
547  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
548  int i;
549 
550  if (!verts) {
551  return -1;
552  }
553 
554  cmd->data.draw.count = count;
555  for (i = 0; i < count; i++) {
556  *(verts++) = 0.5f + points[i].x;
557  *(verts++) = 0.5f + points[i].y;
558  }
559 
560  return 0;
561 }
562 
563 static int
564 GLES_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
565 {
566  int i;
567  const size_t vertlen = (sizeof (GLfloat) * 2) * count;
568  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
569  if (!verts) {
570  return -1;
571  }
572  cmd->data.draw.count = count;
573 
574  /* Offset to hit the center of the pixel. */
575  for (i = 0; i < count; i++) {
576  *(verts++) = 0.5f + points[i].x;
577  *(verts++) = 0.5f + points[i].y;
578  }
579 
580  /* Make the last line segment one pixel longer, to satisfy the
581  diamond-exit rule. */
582  verts -= 4;
583  {
584  const GLfloat xstart = verts[0];
585  const GLfloat ystart = verts[1];
586  const GLfloat xend = verts[2];
587  const GLfloat yend = verts[3];
588 
589  if (ystart == yend) { /* horizontal line */
590  verts[2] += (xend > xstart) ? 1.0f : -1.0f;
591  } else if (xstart == xend) { /* vertical line */
592  verts[3] += (yend > ystart) ? 1.0f : -1.0f;
593  } else { /* bump a pixel in the direction we are moving in. */
594  const GLfloat deltax = xend - xstart;
595  const GLfloat deltay = yend - ystart;
596  const GLfloat angle = SDL_atan2f(deltay, deltax);
597  verts[2] += SDL_cosf(angle);
598  verts[3] += SDL_sinf(angle);
599  }
600  }
601 
602  return 0;
603 }
604 
605 static int
606 GLES_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
607 {
608  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
609  int i;
610 
611  if (!verts) {
612  return -1;
613  }
614 
615  cmd->data.draw.count = count;
616 
617  for (i = 0; i < count; i++) {
618  const SDL_FRect *rect = &rects[i];
619  const GLfloat minx = rect->x;
620  const GLfloat maxx = rect->x + rect->w;
621  const GLfloat miny = rect->y;
622  const GLfloat maxy = rect->y + rect->h;
623  *(verts++) = minx;
624  *(verts++) = miny;
625  *(verts++) = maxx;
626  *(verts++) = miny;
627  *(verts++) = minx;
628  *(verts++) = maxy;
629  *(verts++) = maxx;
630  *(verts++) = maxy;
631  }
632 
633  return 0;
634 }
635 
636 static int
637 GLES_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
638  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
639 {
640  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
641  GLfloat minx, miny, maxx, maxy;
642  GLfloat minu, maxu, minv, maxv;
643  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
644 
645  if (!verts) {
646  return -1;
647  }
648 
649  cmd->data.draw.count = 1;
650 
651  minx = dstrect->x;
652  miny = dstrect->y;
653  maxx = dstrect->x + dstrect->w;
654  maxy = dstrect->y + dstrect->h;
655 
656  minu = (GLfloat) srcrect->x / texture->w;
657  minu *= texturedata->texw;
658  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
659  maxu *= texturedata->texw;
660  minv = (GLfloat) srcrect->y / texture->h;
661  minv *= texturedata->texh;
662  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
663  maxv *= texturedata->texh;
664 
665  *(verts++) = minx;
666  *(verts++) = miny;
667  *(verts++) = maxx;
668  *(verts++) = miny;
669  *(verts++) = minx;
670  *(verts++) = maxy;
671  *(verts++) = maxx;
672  *(verts++) = maxy;
673 
674  *(verts++) = minu;
675  *(verts++) = minv;
676  *(verts++) = maxu;
677  *(verts++) = minv;
678  *(verts++) = minu;
679  *(verts++) = maxv;
680  *(verts++) = maxu;
681  *(verts++) = maxv;
682 
683  return 0;
684 }
685 
686 static int
687 GLES_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
688  const SDL_Rect * srcquad, const SDL_FRect * dstrect,
689  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
690 {
691  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
692  GLfloat minx, miny, maxx, maxy;
693  GLfloat centerx, centery;
694  GLfloat minu, maxu, minv, maxv;
695  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 19 * sizeof (GLfloat), 0, &cmd->data.draw.first);
696 
697  if (!verts) {
698  return -1;
699  }
700 
701  centerx = center->x;
702  centery = center->y;
703 
704  if (flip & SDL_FLIP_HORIZONTAL) {
705  minx = dstrect->w - centerx;
706  maxx = -centerx;
707  }
708  else {
709  minx = -centerx;
710  maxx = dstrect->w - centerx;
711  }
712 
713  if (flip & SDL_FLIP_VERTICAL) {
714  miny = dstrect->h - centery;
715  maxy = -centery;
716  }
717  else {
718  miny = -centery;
719  maxy = dstrect->h - centery;
720  }
721 
722  minu = (GLfloat) srcquad->x / texture->w;
723  minu *= texturedata->texw;
724  maxu = (GLfloat) (srcquad->x + srcquad->w) / texture->w;
725  maxu *= texturedata->texw;
726  minv = (GLfloat) srcquad->y / texture->h;
727  minv *= texturedata->texh;
728  maxv = (GLfloat) (srcquad->y + srcquad->h) / texture->h;
729  maxv *= texturedata->texh;
730 
731  cmd->data.draw.count = 1;
732 
733  *(verts++) = minx;
734  *(verts++) = miny;
735  *(verts++) = maxx;
736  *(verts++) = miny;
737  *(verts++) = minx;
738  *(verts++) = maxy;
739  *(verts++) = maxx;
740  *(verts++) = maxy;
741 
742  *(verts++) = minu;
743  *(verts++) = minv;
744  *(verts++) = maxu;
745  *(verts++) = minv;
746  *(verts++) = minu;
747  *(verts++) = maxv;
748  *(verts++) = maxu;
749  *(verts++) = maxv;
750 
751  *(verts++) = (GLfloat) dstrect->x + centerx;
752  *(verts++) = (GLfloat) dstrect->y + centery;
753  *(verts++) = (GLfloat) angle;
754 
755  return 0;
756 }
757 
758 static void
759 SetDrawState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
760 {
761  const SDL_BlendMode blend = cmd->data.draw.blend;
762  const Uint8 r = cmd->data.draw.r;
763  const Uint8 g = cmd->data.draw.g;
764  const Uint8 b = cmd->data.draw.b;
765  const Uint8 a = cmd->data.draw.a;
766  const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
767 
768  if (color != data->drawstate.color) {
769  const GLfloat fr = ((GLfloat) r) * inv255f;
770  const GLfloat fg = ((GLfloat) g) * inv255f;
771  const GLfloat fb = ((GLfloat) b) * inv255f;
772  const GLfloat fa = ((GLfloat) a) * inv255f;
773  data->glColor4f(fr, fg, fb, fa);
774  data->drawstate.color = color;
775  }
776 
777  if (data->drawstate.viewport_dirty) {
778  const SDL_Rect *viewport = &data->drawstate.viewport;
779  const SDL_bool istarget = (data->drawstate.target != NULL);
780  data->glMatrixMode(GL_PROJECTION);
781  data->glLoadIdentity();
782  data->glViewport(viewport->x,
783  istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
784  viewport->w, viewport->h);
785  if (viewport->w && viewport->h) {
786  data->glOrthof((GLfloat) 0, (GLfloat) viewport->w,
787  (GLfloat) (istarget ? 0 : viewport->h),
788  (GLfloat) (istarget ? viewport->h : 0),
789  0.0, 1.0);
790  }
791  data->glMatrixMode(GL_MODELVIEW);
792  data->drawstate.viewport_dirty = SDL_FALSE;
793  }
794 
795  if (data->drawstate.cliprect_enabled_dirty) {
796  if (data->drawstate.cliprect_enabled) {
797  data->glEnable(GL_SCISSOR_TEST);
798  } else {
799  data->glDisable(GL_SCISSOR_TEST);
800  }
801  data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
802  }
803 
804  if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
805  const SDL_Rect *viewport = &data->drawstate.viewport;
806  const SDL_Rect *rect = &data->drawstate.cliprect;
807  const SDL_bool istarget = (data->drawstate.target != NULL);
808  data->glScissor(viewport->x + rect->x,
809  istarget ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
810  rect->w, rect->h);
811  data->drawstate.cliprect_dirty = SDL_FALSE;
812  }
813 
814  if (blend != data->drawstate.blend) {
815  if (blend == SDL_BLENDMODE_NONE) {
816  data->glDisable(GL_BLEND);
817  } else {
818  data->glEnable(GL_BLEND);
819  if (data->GL_OES_blend_func_separate_supported) {
820  data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
821  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
822  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
823  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
824  } else {
825  data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
826  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)));
827  }
828  if (data->GL_OES_blend_equation_separate_supported) {
829  data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
830  GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
831  } else if (data->GL_OES_blend_subtract_supported) {
832  data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
833  }
834  }
835  data->drawstate.blend = blend;
836  }
837 
838  if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) {
839  if (cmd->data.draw.texture == NULL) {
840  data->glDisable(GL_TEXTURE_2D);
841  data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
842  data->drawstate.texturing = SDL_FALSE;
843  } else {
844  data->glEnable(GL_TEXTURE_2D);
845  data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
846  data->drawstate.texturing = SDL_TRUE;
847  }
848  }
849 }
850 
851 static void
852 SetCopyState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
853 {
854  SDL_Texture *texture = cmd->data.draw.texture;
855  SetDrawState(data, cmd);
856 
857  if (texture != data->drawstate.texture) {
858  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
859  data->glBindTexture(GL_TEXTURE_2D, texturedata->texture);
860  data->drawstate.texture = texture;
861  }
862 }
863 
864 static int
865 GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
866 {
867  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
868  size_t i;
869 
870  if (GLES_ActivateRenderer(renderer) < 0) {
871  return -1;
872  }
873 
874  data->drawstate.target = renderer->target;
875 
876  if (!renderer->target) {
877  SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
878  }
879 
880  while (cmd) {
881  switch (cmd->command) {
883  break; /* not used in this render backend. */
884  }
885 
887  SDL_Rect *viewport = &data->drawstate.viewport;
888  if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
889  SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
890  data->drawstate.viewport_dirty = SDL_TRUE;
891  }
892  break;
893  }
894 
896  const SDL_Rect *rect = &cmd->data.cliprect.rect;
897  if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
898  data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
899  data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
900  }
901  if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
902  SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
903  data->drawstate.cliprect_dirty = SDL_TRUE;
904  }
905  break;
906  }
907 
908  case SDL_RENDERCMD_CLEAR: {
909  const Uint8 r = cmd->data.color.r;
910  const Uint8 g = cmd->data.color.g;
911  const Uint8 b = cmd->data.color.b;
912  const Uint8 a = cmd->data.color.a;
913  const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
914  if (color != data->drawstate.clear_color) {
915  const GLfloat fr = ((GLfloat) r) * inv255f;
916  const GLfloat fg = ((GLfloat) g) * inv255f;
917  const GLfloat fb = ((GLfloat) b) * inv255f;
918  const GLfloat fa = ((GLfloat) a) * inv255f;
919  data->glClearColor(fr, fg, fb, fa);
920  data->drawstate.clear_color = color;
921  }
922 
923  if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
924  data->glDisable(GL_SCISSOR_TEST);
925  data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
926  }
927 
928  data->glClear(GL_COLOR_BUFFER_BIT);
929 
930  break;
931  }
932 
934  const size_t count = cmd->data.draw.count;
935  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
936  SetDrawState(data, cmd);
937  data->glVertexPointer(2, GL_FLOAT, 0, verts);
938  data->glDrawArrays(GL_POINTS, 0, (GLsizei) count);
939  break;
940  }
941 
943  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
944  const size_t count = cmd->data.draw.count;
945  SDL_assert(count >= 2);
946  SetDrawState(data, cmd);
947  data->glVertexPointer(2, GL_FLOAT, 0, verts);
948  data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
949  break;
950  }
951 
953  const size_t count = cmd->data.draw.count;
954  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
955  GLsizei offset = 0;
956  SetDrawState(data, cmd);
957  data->glVertexPointer(2, GL_FLOAT, 0, verts);
958  for (i = 0; i < count; ++i, offset += 4) {
959  data->glDrawArrays(GL_TRIANGLE_STRIP, offset, 4);
960  }
961  break;
962  }
963 
964  case SDL_RENDERCMD_COPY: {
965  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
966  SetCopyState(data, cmd);
967  data->glVertexPointer(2, GL_FLOAT, 0, verts);
968  data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
969  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
970  break;
971  }
972 
973  case SDL_RENDERCMD_COPY_EX: {
974  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
975  const GLfloat translatex = verts[16];
976  const GLfloat translatey = verts[17];
977  const GLfloat angle = verts[18];
978  SetCopyState(data, cmd);
979  data->glVertexPointer(2, GL_FLOAT, 0, verts);
980  data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
981 
982  /* Translate to flip, rotate, translate to position */
983  data->glPushMatrix();
984  data->glTranslatef(translatex, translatey, 0.0f);
985  data->glRotatef(angle, 0.0, 0.0, 1.0);
986  data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
987  data->glPopMatrix();
988  break;
989  }
990 
991  case SDL_RENDERCMD_NO_OP:
992  break;
993  }
994 
995  cmd = cmd->next;
996  }
997 
998  return 0;
999 }
1000 
1001 static int
1002 GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1003  Uint32 pixel_format, void * pixels, int pitch)
1004 {
1005  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1007  void *temp_pixels;
1008  int temp_pitch;
1009  Uint8 *src, *dst, *tmp;
1010  int w, h, length, rows;
1011  int status;
1012 
1013  GLES_ActivateRenderer(renderer);
1014 
1015  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1016  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1017  if (!temp_pixels) {
1018  return SDL_OutOfMemory();
1019  }
1020 
1022 
1023  data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1024 
1025  data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
1026  rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
1027 
1028  /* Flip the rows to be top-down if necessary */
1029  if (!renderer->target) {
1030  SDL_bool isstack;
1031  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1032  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1033  dst = (Uint8*)temp_pixels;
1034  tmp = SDL_small_alloc(Uint8, length, &isstack);
1035  rows = rect->h / 2;
1036  while (rows--) {
1037  SDL_memcpy(tmp, dst, length);
1038  SDL_memcpy(dst, src, length);
1039  SDL_memcpy(src, tmp, length);
1040  dst += temp_pitch;
1041  src -= temp_pitch;
1042  }
1043  SDL_small_free(tmp, isstack);
1044  }
1045 
1046  status = SDL_ConvertPixels(rect->w, rect->h,
1047  temp_format, temp_pixels, temp_pitch,
1048  pixel_format, pixels, pitch);
1049  SDL_free(temp_pixels);
1050 
1051  return status;
1052 }
1053 
1054 static void
1055 GLES_RenderPresent(SDL_Renderer * renderer)
1056 {
1057  GLES_ActivateRenderer(renderer);
1058 
1060 }
1061 
1062 static void
1063 GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1064 {
1065  GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
1066 
1067  GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
1068 
1069  GLES_ActivateRenderer(renderer);
1070 
1071  if (renderdata->drawstate.texture == texture) {
1072  renderdata->drawstate.texture = NULL;
1073  }
1074  if (renderdata->drawstate.target == texture) {
1075  renderdata->drawstate.target = NULL;
1076  }
1077 
1078  if (!data) {
1079  return;
1080  }
1081  if (data->texture) {
1082  renderdata->glDeleteTextures(1, &data->texture);
1083  }
1084  SDL_free(data->pixels);
1085  SDL_free(data);
1086  texture->driverdata = NULL;
1087 }
1088 
1089 static void
1090 GLES_DestroyRenderer(SDL_Renderer * renderer)
1091 {
1092  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1093 
1094  if (data) {
1095  if (data->context) {
1096  while (data->framebuffers) {
1097  GLES_FBOList *nextnode = data->framebuffers->next;
1098  data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
1099  SDL_free(data->framebuffers);
1100  data->framebuffers = nextnode;
1101  }
1102  SDL_GL_DeleteContext(data->context);
1103  }
1104  SDL_free(data);
1105  }
1106  SDL_free(renderer);
1107 }
1108 
1109 static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
1110 {
1111  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1112  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1113  GLES_ActivateRenderer(renderer);
1114 
1115  data->glEnable(GL_TEXTURE_2D);
1116  data->glBindTexture(texturedata->type, texturedata->texture);
1117 
1118  data->drawstate.texture = texture;
1119  data->drawstate.texturing = SDL_TRUE;
1120 
1121  if (texw) {
1122  *texw = (float)texturedata->texw;
1123  }
1124  if (texh) {
1125  *texh = (float)texturedata->texh;
1126  }
1127 
1128  return 0;
1129 }
1130 
1131 static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
1132 {
1133  GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
1134  GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
1135  GLES_ActivateRenderer(renderer);
1136  data->glDisable(texturedata->type);
1137 
1138  data->drawstate.texture = NULL;
1139  data->drawstate.texturing = SDL_FALSE;
1140 
1141  return 0;
1142 }
1143 
1144 static SDL_Renderer *
1145 GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
1146 {
1148  GLES_RenderData *data;
1149  GLint value;
1150  Uint32 window_flags;
1151  int profile_mask = 0, major = 0, minor = 0;
1152  SDL_bool changed_window = SDL_FALSE;
1153 
1157 
1158  window_flags = SDL_GetWindowFlags(window);
1159  if (!(window_flags & SDL_WINDOW_OPENGL) ||
1160  profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
1161 
1162  changed_window = SDL_TRUE;
1164  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
1165  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
1166 
1168  goto error;
1169  }
1170  }
1171 
1172  renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
1173  if (!renderer) {
1174  SDL_OutOfMemory();
1175  goto error;
1176  }
1177 
1178  data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
1179  if (!data) {
1180  GLES_DestroyRenderer(renderer);
1181  SDL_OutOfMemory();
1182  goto error;
1183  }
1184 
1185  renderer->WindowEvent = GLES_WindowEvent;
1186  renderer->GetOutputSize = GLES_GetOutputSize;
1187  renderer->SupportsBlendMode = GLES_SupportsBlendMode;
1188  renderer->CreateTexture = GLES_CreateTexture;
1189  renderer->UpdateTexture = GLES_UpdateTexture;
1190  renderer->LockTexture = GLES_LockTexture;
1191  renderer->UnlockTexture = GLES_UnlockTexture;
1192  renderer->SetTextureScaleMode = GLES_SetTextureScaleMode;
1193  renderer->SetRenderTarget = GLES_SetRenderTarget;
1194  renderer->QueueSetViewport = GLES_QueueSetViewport;
1195  renderer->QueueSetDrawColor = GLES_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
1196  renderer->QueueDrawPoints = GLES_QueueDrawPoints;
1197  renderer->QueueDrawLines = GLES_QueueDrawLines;
1198  renderer->QueueFillRects = GLES_QueueFillRects;
1199  renderer->QueueCopy = GLES_QueueCopy;
1200  renderer->QueueCopyEx = GLES_QueueCopyEx;
1201  renderer->RunCommandQueue = GLES_RunCommandQueue;
1202  renderer->RenderReadPixels = GLES_RenderReadPixels;
1203  renderer->RenderPresent = GLES_RenderPresent;
1204  renderer->DestroyTexture = GLES_DestroyTexture;
1205  renderer->DestroyRenderer = GLES_DestroyRenderer;
1206  renderer->GL_BindTexture = GLES_BindTexture;
1207  renderer->GL_UnbindTexture = GLES_UnbindTexture;
1211  renderer->window = window;
1212 
1213  data->context = SDL_GL_CreateContext(window);
1214  if (!data->context) {
1215  GLES_DestroyRenderer(renderer);
1216  goto error;
1217  }
1218  if (SDL_GL_MakeCurrent(window, data->context) < 0) {
1219  GLES_DestroyRenderer(renderer);
1220  goto error;
1221  }
1222 
1223  if (GLES_LoadFunctions(data) < 0) {
1224  GLES_DestroyRenderer(renderer);
1225  goto error;
1226  }
1227 
1230  } else {
1232  }
1233  if (SDL_GL_GetSwapInterval() > 0) {
1235  }
1236 
1237  value = 0;
1238  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
1240  value = 0;
1241  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
1243 
1244  /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */
1245  if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) {
1246  data->GL_OES_framebuffer_object_supported = SDL_TRUE;
1248 
1249  value = 0;
1250  data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
1251  data->window_framebuffer = (GLuint)value;
1252  }
1253  data->framebuffers = NULL;
1254 
1255  if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
1256  data->GL_OES_blend_func_separate_supported = SDL_TRUE;
1257  }
1258  if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) {
1259  data->GL_OES_blend_equation_separate_supported = SDL_TRUE;
1260  }
1261  if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) {
1262  data->GL_OES_blend_subtract_supported = SDL_TRUE;
1263  }
1264 
1265  /* Set up parameters for rendering */
1266  data->glDisable(GL_DEPTH_TEST);
1267  data->glDisable(GL_CULL_FACE);
1268 
1269  data->glMatrixMode(GL_MODELVIEW);
1270  data->glLoadIdentity();
1271 
1272  data->glEnableClientState(GL_VERTEX_ARRAY);
1273  data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1274 
1275  data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1276 
1277  data->drawstate.blend = SDL_BLENDMODE_INVALID;
1278  data->drawstate.color = 0xFFFFFFFF;
1279  data->drawstate.clear_color = 0xFFFFFFFF;
1280 
1281  return renderer;
1282 
1283 error:
1284  if (changed_window) {
1285  /* Uh oh, better try to put it back... */
1289  SDL_RecreateWindow(window, window_flags);
1290  }
1291  return NULL;
1292 }
1293 
1295  GLES_CreateRenderer,
1296  {
1297  "opengles",
1299  1,
1301  0,
1302  0
1303  }
1304 };
1305 
1306 #endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */
1307 
1308 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:171
SDL_BlendOperation
The blend operation used when combining source and destination pixel components.
Definition: SDL_blendmode.h:66
@ SDL_BLENDOPERATION_REV_SUBTRACT
Definition: SDL_blendmode.h:69
@ SDL_BLENDOPERATION_ADD
Definition: SDL_blendmode.h:67
@ SDL_BLENDOPERATION_SUBTRACT
Definition: SDL_blendmode.h:68
SDL_BlendFactor
The normalized factor used to multiply pixel components.
Definition: SDL_blendmode.h:79
@ SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR
Definition: SDL_blendmode.h:83
@ SDL_BLENDFACTOR_ZERO
Definition: SDL_blendmode.h:80
@ SDL_BLENDFACTOR_SRC_COLOR
Definition: SDL_blendmode.h:82
@ SDL_BLENDFACTOR_SRC_ALPHA
Definition: SDL_blendmode.h:84
@ SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR
Definition: SDL_blendmode.h:87
@ SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA
Definition: SDL_blendmode.h:89
@ SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA
Definition: SDL_blendmode.h:85
@ SDL_BLENDFACTOR_DST_ALPHA
Definition: SDL_blendmode.h:88
@ SDL_BLENDFACTOR_DST_COLOR
Definition: SDL_blendmode.h:86
@ SDL_BLENDFACTOR_ONE
Definition: SDL_blendmode.h:81
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:41
@ SDL_BLENDMODE_NONE
Definition: SDL_blendmode.h:42
@ SDL_BLENDMODE_INVALID
Definition: SDL_blendmode.h:56
#define SDL_SetError
#define SDL_GL_SwapWindow
#define SDL_cosf
#define SDL_atan2f
#define SDL_GetWindowFlags
#define SDL_GL_GetAttribute
#define SDL_GL_SetSwapInterval
#define SDL_GL_MakeCurrent
#define SDL_GetRendererOutputSize
#define SDL_malloc
#define SDL_GL_SetAttribute
#define SDL_free
#define SDL_memcmp
#define SDL_GL_GetSwapInterval
#define SDL_GL_DeleteContext
#define SDL_sinf
#define SDL_memcpy
#define SDL_GL_CreateContext
#define SDL_GL_ExtensionSupported
#define SDL_GL_GetDrawableSize
#define SDL_calloc
#define SDL_ConvertPixels
#define SDL_GL_GetCurrentContext
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
int uint32_t uint32_t uint32_t pixel_format
Definition: SDL_kmsdrmsym.h:52
#define GL_TEXTURE_COORD_ARRAY
Definition: SDL_opengl.h:232
#define GL_INVALID_VALUE
Definition: SDL_opengl.h:721
#define GL_MAX_TEXTURE_SIZE
Definition: SDL_opengl.h:536
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
#define GL_TEXTURE_MIN_FILTER
Definition: SDL_opengl.h:675
#define GL_TEXTURE_WRAP_S
Definition: SDL_opengl.h:672
float GLfloat
Definition: SDL_opengl.h:187
#define GL_ONE_MINUS_DST_ALPHA
Definition: SDL_opengl.h:407
#define GL_PACK_ALIGNMENT
Definition: SDL_opengl.h:652
#define GL_ONE_MINUS_DST_COLOR
Definition: SDL_opengl.h:409
#define GL_DEPTH_TEST
Definition: SDL_opengl.h:327
#define GL_LINEAR
Definition: SDL_opengl.h:447
#define GL_LINE_STRIP
Definition: SDL_opengl.h:219
#define GL_SRC_ALPHA
Definition: SDL_opengl.h:404
#define GL_INVALID_OPERATION
Definition: SDL_opengl.h:722
unsigned int GLenum
Definition: SDL_opengl.h:176
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
#define GL_STACK_OVERFLOW
Definition: SDL_opengl.h:723
unsigned int GLuint
Definition: SDL_opengl.h:185
#define GL_SRC_COLOR
Definition: SDL_opengl.h:402
#define GL_FLOAT
Definition: SDL_opengl.h:209
#define GL_ZERO
Definition: SDL_opengl.h:400
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
#define GL_VERTEX_ARRAY
Definition: SDL_opengl.h:228
#define GL_NEAREST
Definition: SDL_opengl.h:704
#define GL_UNSIGNED_BYTE
Definition: SDL_opengl.h:204
#define GL_PROJECTION
Definition: SDL_opengl.h:272
#define GL_NO_ERROR
Definition: SDL_opengl.h:719
#define GL_MODELVIEW
Definition: SDL_opengl.h:271
#define GL_POINTS
Definition: SDL_opengl.h:216
#define GL_CULL_FACE
Definition: SDL_opengl.h:302
#define GL_UNPACK_ALIGNMENT
Definition: SDL_opengl.h:658
int GLsizei
Definition: SDL_opengl.h:186
#define GL_COLOR_BUFFER_BIT
Definition: SDL_opengl.h:742
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
#define GL_RGBA
Definition: SDL_opengl.h:529
#define GL_BLEND
Definition: SDL_opengl.h:397
#define GL_ONE_MINUS_SRC_ALPHA
Definition: SDL_opengl.h:405
#define GL_ONE
Definition: SDL_opengl.h:401
#define GL_DST_ALPHA
Definition: SDL_opengl.h:406
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
#define GL_SCISSOR_TEST
Definition: SDL_opengl.h:615
#define GL_TEXTURE_WRAP_T
Definition: SDL_opengl.h:673
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
#define GL_TEXTURE_MAG_FILTER
Definition: SDL_opengl.h:674
#define GL_DST_COLOR
Definition: SDL_opengl.h:408
int GLint
Definition: SDL_opengl.h:182
#define GL_OUT_OF_MEMORY
Definition: SDL_opengl.h:725
#define GL_TRIANGLE_STRIP
Definition: SDL_opengl.h:221
#define GL_TEXTURE_2D
Definition: SDL_opengl.h:671
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
#define GL_CLAMP_TO_EDGE
Definition: SDL_opengl.h:1507
#define GL_INVALID_ENUM
Definition: SDL_opengl.h:720
#define GL_STACK_UNDERFLOW
Definition: SDL_opengl.h:724
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
#define GL_ONE_MINUS_SRC_COLOR
Definition: SDL_opengl.h:403
GLboolean GLboolean GLboolean b
struct _cl_event * event
GLfixed GLfixed GLint GLint GLfixed points
GLenum src
GLuint64EXT * result
GLuint color
GLintptr offset
GLenum internalFormat
GLboolean GLboolean GLboolean GLboolean a
GLenum GLenum dst
const GLuint * framebuffers
GLdouble GLdouble z
GLboolean GLboolean g
GLfloat angle
GLbitfield flags
GLenum GLenum GLuint texture
GLuint GLsizei GLsizei * length
GLsizei const GLfloat * value
GLenum GLenum GLenum input
GLenum target
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
#define GL_APIENTRY
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:263
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3393
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3386
void * SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
Definition: SDL_render.c:262
SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3414
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3407
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:3421
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:3400
@ SDL_RENDERER_ACCELERATED
Definition: SDL_render.h:67
@ SDL_RENDERER_PRESENTVSYNC
Definition: SDL_render.h:69
@ SDL_RENDERER_TARGETTEXTURE
Definition: SDL_render.h:71
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:122
@ SDL_FLIP_VERTICAL
Definition: SDL_render.h:125
@ SDL_FLIP_HORIZONTAL
Definition: SDL_render.h:124
@ SDL_TEXTUREACCESS_STREAMING
Definition: SDL_render.h:104
@ SDL_TEXTUREACCESS_TARGET
Definition: SDL_render.h:105
SDL_ScaleMode
The scaling mode for a texture.
Definition: SDL_render.h:92
@ SDL_ScaleModeNearest
Definition: SDL_render.h:93
static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate)
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
uint8_t Uint8
Definition: SDL_stdinc.h:185
uint32_t Uint32
Definition: SDL_stdinc.h:209
SDL_RenderDriver GLES_RenderDriver
@ SDL_RENDERCMD_SETCLIPRECT
Definition: SDL_sysrender.h:70
@ SDL_RENDERCMD_DRAW_LINES
Definition: SDL_sysrender.h:74
@ SDL_RENDERCMD_SETVIEWPORT
Definition: SDL_sysrender.h:69
@ SDL_RENDERCMD_DRAW_POINTS
Definition: SDL_sysrender.h:73
@ SDL_RENDERCMD_NO_OP
Definition: SDL_sysrender.h:68
@ SDL_RENDERCMD_FILL_RECTS
Definition: SDL_sysrender.h:75
@ SDL_RENDERCMD_COPY
Definition: SDL_sysrender.h:76
@ SDL_RENDERCMD_CLEAR
Definition: SDL_sysrender.h:72
@ SDL_RENDERCMD_SETDRAWCOLOR
Definition: SDL_sysrender.h:71
@ SDL_RENDERCMD_COPY_EX
Definition: SDL_sysrender.h:77
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1673
@ SDL_GL_CONTEXT_MAJOR_VERSION
Definition: SDL_video.h:219
@ SDL_GL_CONTEXT_MINOR_VERSION
Definition: SDL_video.h:220
@ SDL_GL_CONTEXT_PROFILE_MASK
Definition: SDL_video.h:223
@ SDL_WINDOW_VULKAN
Definition: SDL_video.h:121
@ SDL_WINDOW_OPENGL
Definition: SDL_video.h:100
@ SDL_WINDOW_METAL
Definition: SDL_video.h:122
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:195
@ SDL_WINDOWEVENT_MINIMIZED
Definition: SDL_video.h:159
@ SDL_GL_CONTEXT_PROFILE_ES
Definition: SDL_video.h:235
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:163
#define SDL_INLINE
Definition: begin_code.h:130
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGLSurface EGLint * rects
Definition: eglext.h:282
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 skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
The structure that defines a point (floating point)
Definition: SDL_rect.h:61
float x
Definition: SDL_rect.h:62
float y
Definition: SDL_rect.h:63
A rectangle, with the origin at the upper left (floating point).
Definition: SDL_rect.h:88
float h
Definition: SDL_rect.h:92
float x
Definition: SDL_rect.h:89
float w
Definition: SDL_rect.h:91
float y
Definition: SDL_rect.h:90
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
int h
Definition: SDL_rect.h:80
int w
Definition: SDL_rect.h:80
int y
Definition: SDL_rect.h:79
int x
Definition: SDL_rect.h:79
struct SDL_RenderCommand::@38::@42 color
struct SDL_RenderCommand * next
struct SDL_RenderCommand::@38::@39 viewport
struct SDL_RenderCommand::@38::@41 draw
SDL_RenderCommandType command
Definition: SDL_sysrender.h:82
union SDL_RenderCommand::@38 data
struct SDL_RenderCommand::@38::@40 cliprect
SDL_RendererInfo info
int(* QueueCopy)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
SDL_Window * window
int(* QueueDrawLines)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
void(* SetTextureScaleMode)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
void(* DestroyRenderer)(SDL_Renderer *renderer)
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
void(* RenderPresent)(SDL_Renderer *renderer)
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
int(* QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
int(* QueueFillRects)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count)
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
int(* RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
int(* QueueCopyEx)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
SDL_RendererInfo info
void * driverdata
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_Texture * target
int(* QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
int max_texture_height
Definition: SDL_render.h:85
Uint32 format
Definition: SDL_sysrender.h:39
Window state change event data (event.window.*)
Definition: SDL_events.h:202
The type used to identify a window.
Definition: SDL_sysvideo.h:75
static SDL_Renderer * renderer
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
SDL_Rect rect
Definition: testrelative.c:27
static SDL_Rect viewport
Definition: testviewport.c:28
static screen_context_t context
Definition: video.c:25