SDL  2.0
SDL_render_gl.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 && !SDL_RENDER_DISABLED
24 
25 #include "SDL_hints.h"
26 #include "SDL_opengl.h"
27 #include "../SDL_sysrender.h"
28 #include "SDL_shaders_gl.h"
29 
30 #ifdef __MACOSX__
31 #include <OpenGL/OpenGL.h>
32 #endif
33 
34 /* To prevent unnecessary window recreation,
35  * these should match the defaults selected in SDL_GL_ResetAttributes
36  */
37 
38 #define RENDERER_CONTEXT_MAJOR 2
39 #define RENDERER_CONTEXT_MINOR 1
40 
41 /* OpenGL renderer implementation */
42 
43 /* Details on optimizing the texture path on Mac OS X:
44  http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html
45 */
46 
47 /* Used to re-create the window with OpenGL capability */
49 
50 static const float inv255f = 1.0f / 255.0f;
51 
52 typedef struct GL_FBOList GL_FBOList;
53 
54 struct GL_FBOList
55 {
56  Uint32 w, h;
57  GLuint FBO;
58  GL_FBOList *next;
59 };
60 
61 typedef struct
62 {
63  SDL_bool viewport_dirty;
67  int drawablew;
68  int drawableh;
69  SDL_BlendMode blend;
71  SDL_bool cliprect_enabled_dirty;
72  SDL_bool cliprect_enabled;
73  SDL_bool cliprect_dirty;
74  SDL_Rect cliprect;
75  SDL_bool texturing;
76  Uint32 color;
77  Uint32 clear_color;
78 } GL_DrawStateCache;
79 
80 typedef struct
81 {
83 
84  SDL_bool debug_enabled;
85  SDL_bool GL_ARB_debug_output_supported;
86  int errors;
87  char **error_messages;
88  GLDEBUGPROCARB next_error_callback;
89  GLvoid *next_error_userparam;
90 
91  GLenum textype;
92 
93  SDL_bool GL_ARB_texture_non_power_of_two_supported;
94  SDL_bool GL_ARB_texture_rectangle_supported;
95  SDL_bool GL_EXT_framebuffer_object_supported;
96  GL_FBOList *framebuffers;
97 
98  /* OpenGL functions */
99 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
100 #include "SDL_glfuncs.h"
101 #undef SDL_PROC
102 
103  /* Multitexture support */
104  SDL_bool GL_ARB_multitexture_supported;
105  PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
106  GLint num_texture_units;
107 
108  PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
109  PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
110  PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
111  PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
112  PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
113 
114  /* Shader support */
116 
117  GL_DrawStateCache drawstate;
118 } GL_RenderData;
119 
120 typedef struct
121 {
122  GLuint texture;
123  GLfloat texw;
124  GLfloat texh;
125  GLenum format;
126  GLenum formattype;
127  void *pixels;
128  int pitch;
129  SDL_Rect locked_rect;
130 
131  /* YUV texture support */
132  SDL_bool yuv;
133  SDL_bool nv12;
134  GLuint utexture;
135  GLuint vtexture;
136 
137  GL_FBOList *fbo;
138 } GL_TextureData;
139 
140 SDL_FORCE_INLINE const char*
141 GL_TranslateError (GLenum error)
142 {
143 #define GL_ERROR_TRANSLATE(e) case e: return #e;
144  switch (error) {
145  GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
146  GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
147  GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
148  GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
149  GL_ERROR_TRANSLATE(GL_NO_ERROR)
150  GL_ERROR_TRANSLATE(GL_STACK_OVERFLOW)
151  GL_ERROR_TRANSLATE(GL_STACK_UNDERFLOW)
152  GL_ERROR_TRANSLATE(GL_TABLE_TOO_LARGE)
153  default:
154  return "UNKNOWN";
155 }
156 #undef GL_ERROR_TRANSLATE
157 }
158 
159 SDL_FORCE_INLINE void
160 GL_ClearErrors(SDL_Renderer *renderer)
161 {
162  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
163 
164  if (!data->debug_enabled)
165  {
166  return;
167  }
168  if (data->GL_ARB_debug_output_supported) {
169  if (data->errors) {
170  int i;
171  for (i = 0; i < data->errors; ++i) {
172  SDL_free(data->error_messages[i]);
173  }
174  SDL_free(data->error_messages);
175 
176  data->errors = 0;
177  data->error_messages = NULL;
178  }
179  } else if (data->glGetError != NULL) {
180  while (data->glGetError() != GL_NO_ERROR) {
181  /* continue; */
182  }
183  }
184 }
185 
187 GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
188 {
189  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
190  int ret = 0;
191 
192  if (!data->debug_enabled)
193  {
194  return 0;
195  }
196  if (data->GL_ARB_debug_output_supported) {
197  if (data->errors) {
198  int i;
199  for (i = 0; i < data->errors; ++i) {
200  SDL_SetError("%s: %s (%d): %s %s", prefix, file, line, function, data->error_messages[i]);
201  ret = -1;
202  }
203  GL_ClearErrors(renderer);
204  }
205  } else {
206  /* check gl errors (can return multiple errors) */
207  for (;;) {
208  GLenum error = data->glGetError();
209  if (error != GL_NO_ERROR) {
210  if (prefix == NULL || prefix[0] == '\0') {
211  prefix = "generic";
212  }
213  SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
214  ret = -1;
215  } else {
216  break;
217  }
218  }
219  }
220  return ret;
221 }
222 
223 #if 0
224 #define GL_CheckError(prefix, renderer)
225 #else
226 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION)
227 #endif
228 
229 static int
230 GL_LoadFunctions(GL_RenderData * data)
231 {
232 #ifdef __SDL_NOGETPROCADDR__
233 #define SDL_PROC(ret,func,params) data->func=func;
234 #else
235  int retval = 0;
236 #define SDL_PROC(ret,func,params) \
237  do { \
238  data->func = SDL_GL_GetProcAddress(#func); \
239  if ( ! data->func ) { \
240  retval = SDL_SetError("Couldn't load GL function %s: %s", #func, SDL_GetError()); \
241  } \
242  } while ( 0 );
243 #endif /* __SDL_NOGETPROCADDR__ */
244 
245 #include "SDL_glfuncs.h"
246 #undef SDL_PROC
247  return retval;
248 }
249 
250 static int
251 GL_ActivateRenderer(SDL_Renderer * renderer)
252 {
253  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
254 
255  if (SDL_GL_GetCurrentContext() != data->context) {
256  if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
257  return -1;
258  }
259  }
260 
261  GL_ClearErrors(renderer);
262 
263  return 0;
264 }
265 
266 static void APIENTRY
267 GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam)
268 {
270  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
271 
273  /* Record this error */
274  int errors = data->errors + 1;
275  char **error_messages = SDL_realloc(data->error_messages, errors * sizeof(*data->error_messages));
276  if (error_messages) {
277  data->errors = errors;
278  data->error_messages = error_messages;
279  data->error_messages[data->errors-1] = SDL_strdup(message);
280  }
281  }
282 
283  /* If there's another error callback, pass it along, otherwise log it */
284  if (data->next_error_callback) {
285  data->next_error_callback(source, type, id, severity, length, message, data->next_error_userparam);
286  } else {
287  if (type == GL_DEBUG_TYPE_ERROR_ARB) {
289  } else {
291  }
292  }
293 }
294 
295 static GL_FBOList *
296 GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
297 {
298  GL_FBOList *result = data->framebuffers;
299 
300  while (result && ((result->w != w) || (result->h != h))) {
301  result = result->next;
302  }
303 
304  if (!result) {
305  result = SDL_malloc(sizeof(GL_FBOList));
306  if (result) {
307  result->w = w;
308  result->h = h;
309  data->glGenFramebuffersEXT(1, &result->FBO);
310  result->next = data->framebuffers;
311  data->framebuffers = result;
312  }
313  }
314  return result;
315 }
316 
317 static int
318 GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
319 {
321  return 0;
322 }
323 
324 static GLenum GetBlendFunc(SDL_BlendFactor factor)
325 {
326  switch (factor) {
328  return GL_ZERO;
329  case SDL_BLENDFACTOR_ONE:
330  return GL_ONE;
332  return GL_SRC_COLOR;
334  return GL_ONE_MINUS_SRC_COLOR;
336  return GL_SRC_ALPHA;
338  return GL_ONE_MINUS_SRC_ALPHA;
340  return GL_DST_COLOR;
342  return GL_ONE_MINUS_DST_COLOR;
344  return GL_DST_ALPHA;
346  return GL_ONE_MINUS_DST_ALPHA;
347  default:
348  return GL_INVALID_ENUM;
349  }
350 }
351 
352 static GLenum GetBlendEquation(SDL_BlendOperation operation)
353 {
354  switch (operation) {
356  return GL_FUNC_ADD;
358  return GL_FUNC_SUBTRACT;
361  default:
362  return GL_INVALID_ENUM;
363  }
364 }
365 
366 static SDL_bool
367 GL_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
368 {
375 
376  if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
377  GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
378  GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
379  GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
380  GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
381  GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
382  return SDL_FALSE;
383  }
384  if (colorOperation != alphaOperation) {
385  return SDL_FALSE;
386  }
387  return SDL_TRUE;
388 }
389 
391 power_of_2(int input)
392 {
393  int value = 1;
394 
395  while (value < input) {
396  value <<= 1;
397  }
398  return value;
399 }
400 
402 convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
404 {
405  switch (pixel_format) {
409  *format = GL_BGRA;
411  break;
415  *format = GL_RGBA;
417  break;
423  *format = GL_LUMINANCE;
425  break;
426 #ifdef __MACOSX__
431  break;
432 #endif
433  default:
434  return SDL_FALSE;
435  }
436  return SDL_TRUE;
437 }
438 
439 static int
440 GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
441 {
442  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
443  const GLenum textype = renderdata->textype;
444  GL_TextureData *data;
446  GLenum format, type;
447  int texture_w, texture_h;
448  GLenum scaleMode;
449 
450  GL_ActivateRenderer(renderer);
451 
452  renderdata->drawstate.texture = NULL; /* we trash this state. */
453 
454  if (texture->access == SDL_TEXTUREACCESS_TARGET &&
455  !renderdata->GL_EXT_framebuffer_object_supported) {
456  return SDL_SetError("Render targets not supported by OpenGL");
457  }
458 
459  if (!convert_format(renderdata, texture->format, &internalFormat,
460  &format, &type)) {
461  return SDL_SetError("Texture format %s not supported by OpenGL",
463  }
464 
465  data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
466  if (!data) {
467  return SDL_OutOfMemory();
468  }
469 
470  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
471  size_t size;
472  data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
473  size = texture->h * data->pitch;
474  if (texture->format == SDL_PIXELFORMAT_YV12 ||
475  texture->format == SDL_PIXELFORMAT_IYUV) {
476  /* Need to add size for the U and V planes */
477  size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
478  }
479  if (texture->format == SDL_PIXELFORMAT_NV12 ||
480  texture->format == SDL_PIXELFORMAT_NV21) {
481  /* Need to add size for the U/V plane */
482  size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
483  }
484  data->pixels = SDL_calloc(1, size);
485  if (!data->pixels) {
486  SDL_free(data);
487  return SDL_OutOfMemory();
488  }
489  }
490 
491  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
492  data->fbo = GL_GetFBO(renderdata, texture->w, texture->h);
493  } else {
494  data->fbo = NULL;
495  }
496 
497  GL_CheckError("", renderer);
498  renderdata->glGenTextures(1, &data->texture);
499  if (GL_CheckError("glGenTextures()", renderer) < 0) {
500  if (data->pixels) {
501  SDL_free(data->pixels);
502  }
503  SDL_free(data);
504  return -1;
505  }
506  texture->driverdata = data;
507 
508  if (renderdata->GL_ARB_texture_non_power_of_two_supported) {
509  texture_w = texture->w;
510  texture_h = texture->h;
511  data->texw = 1.0f;
512  data->texh = 1.0f;
513  } else if (renderdata->GL_ARB_texture_rectangle_supported) {
514  texture_w = texture->w;
515  texture_h = texture->h;
516  data->texw = (GLfloat) texture_w;
517  data->texh = (GLfloat) texture_h;
518  } else {
519  texture_w = power_of_2(texture->w);
520  texture_h = power_of_2(texture->h);
521  data->texw = (GLfloat) (texture->w) / texture_w;
522  data->texh = (GLfloat) texture->h / texture_h;
523  }
524 
525  data->format = format;
526  data->formattype = type;
527  scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
528  renderdata->glEnable(textype);
529  renderdata->glBindTexture(textype, data->texture);
530  renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode);
531  renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, scaleMode);
532  /* According to the spec, CLAMP_TO_EDGE is the default for TEXTURE_RECTANGLE
533  and setting it causes an INVALID_ENUM error in the latest NVidia drivers.
534  */
535  if (textype != GL_TEXTURE_RECTANGLE_ARB) {
536  renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
538  renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
540  }
541 #ifdef __MACOSX__
542 #ifndef GL_TEXTURE_STORAGE_HINT_APPLE
543 #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
544 #endif
545 #ifndef STORAGE_CACHED_APPLE
546 #define STORAGE_CACHED_APPLE 0x85BE
547 #endif
548 #ifndef STORAGE_SHARED_APPLE
549 #define STORAGE_SHARED_APPLE 0x85BF
550 #endif
551  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
552  renderdata->glTexParameteri(textype, GL_TEXTURE_STORAGE_HINT_APPLE,
554  } else {
555  renderdata->glTexParameteri(textype, GL_TEXTURE_STORAGE_HINT_APPLE,
557  }
558  if (texture->access == SDL_TEXTUREACCESS_STREAMING
559  && texture->format == SDL_PIXELFORMAT_ARGB8888
560  && (texture->w % 8) == 0) {
561  renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
562  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
563  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
564  (data->pitch / SDL_BYTESPERPIXEL(texture->format)));
565  renderdata->glTexImage2D(textype, 0, internalFormat, texture_w,
566  texture_h, 0, format, type, data->pixels);
567  renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
568  }
569  else
570 #endif
571  {
572  renderdata->glTexImage2D(textype, 0, internalFormat, texture_w,
573  texture_h, 0, format, type, NULL);
574  }
575  renderdata->glDisable(textype);
576  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
577  return -1;
578  }
579 
580  if (texture->format == SDL_PIXELFORMAT_YV12 ||
581  texture->format == SDL_PIXELFORMAT_IYUV) {
582  data->yuv = SDL_TRUE;
583 
584  renderdata->glGenTextures(1, &data->utexture);
585  renderdata->glGenTextures(1, &data->vtexture);
586 
587  renderdata->glBindTexture(textype, data->utexture);
588  renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
589  scaleMode);
590  renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
591  scaleMode);
592  renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
594  renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
596  renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w+1)/2,
597  (texture_h+1)/2, 0, format, type, NULL);
598 
599  renderdata->glBindTexture(textype, data->vtexture);
600  renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
601  scaleMode);
602  renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
603  scaleMode);
604  renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
606  renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
608  renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w+1)/2,
609  (texture_h+1)/2, 0, format, type, NULL);
610  }
611 
612  if (texture->format == SDL_PIXELFORMAT_NV12 ||
613  texture->format == SDL_PIXELFORMAT_NV21) {
614  data->nv12 = SDL_TRUE;
615 
616  renderdata->glGenTextures(1, &data->utexture);
617  renderdata->glBindTexture(textype, data->utexture);
618  renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
619  scaleMode);
620  renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
621  scaleMode);
622  renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
624  renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
626  renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w+1)/2,
627  (texture_h+1)/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
628  }
629 
630  return GL_CheckError("", renderer);
631 }
632 
633 static int
634 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
635  const SDL_Rect * rect, const void *pixels, int pitch)
636 {
637  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
638  const GLenum textype = renderdata->textype;
639  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
640  const int texturebpp = SDL_BYTESPERPIXEL(texture->format);
641 
642  SDL_assert(texturebpp != 0); /* otherwise, division by zero later. */
643 
644  GL_ActivateRenderer(renderer);
645 
646  renderdata->drawstate.texture = NULL; /* we trash this state. */
647 
648  renderdata->glBindTexture(textype, data->texture);
649  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
650  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / texturebpp));
651  renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w,
652  rect->h, data->format, data->formattype,
653  pixels);
654  if (data->yuv) {
655  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
656 
657  /* Skip to the correct offset into the next texture */
658  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
659  if (texture->format == SDL_PIXELFORMAT_YV12) {
660  renderdata->glBindTexture(textype, data->vtexture);
661  } else {
662  renderdata->glBindTexture(textype, data->utexture);
663  }
664  renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
665  (rect->w+1)/2, (rect->h+1)/2,
666  data->format, data->formattype, pixels);
667 
668  /* Skip to the correct offset into the next texture */
669  pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
670  if (texture->format == SDL_PIXELFORMAT_YV12) {
671  renderdata->glBindTexture(textype, data->utexture);
672  } else {
673  renderdata->glBindTexture(textype, data->vtexture);
674  }
675  renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
676  (rect->w+1)/2, (rect->h+1)/2,
677  data->format, data->formattype, pixels);
678  }
679 
680  if (data->nv12) {
681  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
682 
683  /* Skip to the correct offset into the next texture */
684  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
685  renderdata->glBindTexture(textype, data->utexture);
686  renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
687  (rect->w + 1)/2, (rect->h + 1)/2,
689  }
690 
691  return GL_CheckError("glTexSubImage2D()", renderer);
692 }
693 
694 static int
695 GL_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
696  const SDL_Rect * rect,
697  const Uint8 *Yplane, int Ypitch,
698  const Uint8 *Uplane, int Upitch,
699  const Uint8 *Vplane, int Vpitch)
700 {
701  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
702  const GLenum textype = renderdata->textype;
703  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
704 
705  GL_ActivateRenderer(renderer);
706 
707  renderdata->drawstate.texture = NULL; /* we trash this state. */
708 
709  renderdata->glBindTexture(textype, data->texture);
710  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
711  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Ypitch);
712  renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w,
713  rect->h, data->format, data->formattype,
714  Yplane);
715 
716  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch);
717  renderdata->glBindTexture(textype, data->utexture);
718  renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
719  (rect->w + 1)/2, (rect->h + 1)/2,
720  data->format, data->formattype, Uplane);
721 
722  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch);
723  renderdata->glBindTexture(textype, data->vtexture);
724  renderdata->glTexSubImage2D(textype, 0, rect->x/2, rect->y/2,
725  (rect->w + 1)/2, (rect->h + 1)/2,
726  data->format, data->formattype, Vplane);
727 
728  return GL_CheckError("glTexSubImage2D()", renderer);
729 }
730 
731 static int
732 GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
733  const SDL_Rect * rect, void **pixels, int *pitch)
734 {
735  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
736 
737  data->locked_rect = *rect;
738  *pixels =
739  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
740  rect->x * SDL_BYTESPERPIXEL(texture->format));
741  *pitch = data->pitch;
742  return 0;
743 }
744 
745 static void
746 GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
747 {
748  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
749  const SDL_Rect *rect;
750  void *pixels;
751 
752  rect = &data->locked_rect;
753  pixels =
754  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
755  rect->x * SDL_BYTESPERPIXEL(texture->format));
756  GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
757 }
758 
759 static void
760 GL_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
761 {
762  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
763  const GLenum textype = renderdata->textype;
764  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
765  GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
766 
767  renderdata->glBindTexture(textype, data->texture);
768  renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
769  renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
770 
771  if (texture->format == SDL_PIXELFORMAT_YV12 ||
772  texture->format == SDL_PIXELFORMAT_IYUV) {
773  renderdata->glBindTexture(textype, data->utexture);
774  renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
775  renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
776 
777  renderdata->glBindTexture(textype, data->vtexture);
778  renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
779  renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
780  }
781 
782  if (texture->format == SDL_PIXELFORMAT_NV12 ||
783  texture->format == SDL_PIXELFORMAT_NV21) {
784  renderdata->glBindTexture(textype, data->utexture);
785  renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
786  renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
787  }
788 }
789 
790 static int
791 GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
792 {
793  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
794  GL_TextureData *texturedata;
795  GLenum status;
796 
797  GL_ActivateRenderer(renderer);
798 
799  if (!data->GL_EXT_framebuffer_object_supported) {
800  return SDL_SetError("Render targets not supported by OpenGL");
801  }
802 
803  data->drawstate.viewport_dirty = SDL_TRUE;
804 
805  if (texture == NULL) {
806  data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
807  return 0;
808  }
809 
810  texturedata = (GL_TextureData *) texture->driverdata;
811  data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texturedata->fbo->FBO);
812  /* TODO: check if texture pixel format allows this operation */
813  data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, data->textype, texturedata->texture, 0);
814  /* Check FBO status */
815  status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
816  if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
817  return SDL_SetError("glFramebufferTexture2DEXT() failed");
818  }
819  return 0;
820 }
821 
822 /* !!! FIXME: all these Queue* calls set up the vertex buffer the way the immediate mode
823  !!! FIXME: renderer wants it, but this might want to operate differently if we move to
824  !!! FIXME: VBOs at some point. */
825 static int
826 GL_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
827 {
828  return 0; /* nothing to do in this backend. */
829 }
830 
831 static int
832 GL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
833 {
834  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
835  int i;
836 
837  if (!verts) {
838  return -1;
839  }
840 
841  cmd->data.draw.count = count;
842  for (i = 0; i < count; i++) {
843  *(verts++) = 0.5f + points[i].x;
844  *(verts++) = 0.5f + points[i].y;
845  }
846 
847  return 0;
848 }
849 
850 static int
851 GL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
852 {
853  int i;
854  const size_t vertlen = (sizeof (GLfloat) * 2) * count;
855  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
856  if (!verts) {
857  return -1;
858  }
859  cmd->data.draw.count = count;
860 
861  /* Offset to hit the center of the pixel. */
862  for (i = 0; i < count; i++) {
863  *(verts++) = 0.5f + points[i].x;
864  *(verts++) = 0.5f + points[i].y;
865  }
866 
867  /* Make the last line segment one pixel longer, to satisfy the
868  diamond-exit rule. */
869  verts -= 4;
870  {
871  const GLfloat xstart = verts[0];
872  const GLfloat ystart = verts[1];
873  const GLfloat xend = verts[2];
874  const GLfloat yend = verts[3];
875 
876  if (ystart == yend) { /* horizontal line */
877  verts[2] += (xend > xstart) ? 1.0f : -1.0f;
878  } else if (xstart == xend) { /* vertical line */
879  verts[3] += (yend > ystart) ? 1.0f : -1.0f;
880  } else { /* bump a pixel in the direction we are moving in. */
881  const GLfloat deltax = xend - xstart;
882  const GLfloat deltay = yend - ystart;
883  const GLfloat angle = SDL_atan2f(deltay, deltax);
884  verts[2] += SDL_cosf(angle);
885  verts[3] += SDL_sinf(angle);
886  }
887  }
888 
889  return 0;
890 }
891 
892 static int
893 GL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
894 {
895  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (GLfloat), 0, &cmd->data.draw.first);
896  int i;
897 
898  if (!verts) {
899  return -1;
900  }
901 
902  cmd->data.draw.count = count;
903  for (i = 0; i < count; i++) {
904  const SDL_FRect *rect = &rects[i];
905  *(verts++) = rect->x;
906  *(verts++) = rect->y;
907  *(verts++) = rect->x + rect->w;
908  *(verts++) = rect->y + rect->h;
909  }
910 
911  return 0;
912 }
913 
914 static int
916  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
917 {
918  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
919  GLfloat minx, miny, maxx, maxy;
920  GLfloat minu, maxu, minv, maxv;
921  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
922 
923  if (!verts) {
924  return -1;
925  }
926 
927  cmd->data.draw.count = 1;
928 
929  minx = dstrect->x;
930  miny = dstrect->y;
931  maxx = dstrect->x + dstrect->w;
932  maxy = dstrect->y + dstrect->h;
933 
934  minu = (GLfloat) srcrect->x / texture->w;
935  minu *= texturedata->texw;
936  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
937  maxu *= texturedata->texw;
938  minv = (GLfloat) srcrect->y / texture->h;
939  minv *= texturedata->texh;
940  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
941  maxv *= texturedata->texh;
942 
943  cmd->data.draw.count = 1;
944  *(verts++) = minx;
945  *(verts++) = miny;
946  *(verts++) = maxx;
947  *(verts++) = maxy;
948  *(verts++) = minu;
949  *(verts++) = maxu;
950  *(verts++) = minv;
951  *(verts++) = maxv;
952  return 0;
953 }
954 
955 static int
956 GL_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
957  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
958  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
959 {
960  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
961  GLfloat minx, miny, maxx, maxy;
962  GLfloat centerx, centery;
963  GLfloat minu, maxu, minv, maxv;
964  GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 11 * sizeof (GLfloat), 0, &cmd->data.draw.first);
965 
966  if (!verts) {
967  return -1;
968  }
969 
970  centerx = center->x;
971  centery = center->y;
972 
973  if (flip & SDL_FLIP_HORIZONTAL) {
974  minx = dstrect->w - centerx;
975  maxx = -centerx;
976  }
977  else {
978  minx = -centerx;
979  maxx = dstrect->w - centerx;
980  }
981 
982  if (flip & SDL_FLIP_VERTICAL) {
983  miny = dstrect->h - centery;
984  maxy = -centery;
985  }
986  else {
987  miny = -centery;
988  maxy = dstrect->h - centery;
989  }
990 
991  minu = (GLfloat) srcrect->x / texture->w;
992  minu *= texturedata->texw;
993  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
994  maxu *= texturedata->texw;
995  minv = (GLfloat) srcrect->y / texture->h;
996  minv *= texturedata->texh;
997  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
998  maxv *= texturedata->texh;
999 
1000  cmd->data.draw.count = 1;
1001  *(verts++) = minx;
1002  *(verts++) = miny;
1003  *(verts++) = maxx;
1004  *(verts++) = maxy;
1005  *(verts++) = minu;
1006  *(verts++) = maxu;
1007  *(verts++) = minv;
1008  *(verts++) = maxv;
1009  *(verts++) = (GLfloat) dstrect->x + centerx;
1010  *(verts++) = (GLfloat) dstrect->y + centery;
1011  *(verts++) = (GLfloat) angle;
1012  return 0;
1013 }
1014 
1015 static void
1016 SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader shader)
1017 {
1018  const SDL_BlendMode blend = cmd->data.draw.blend;
1019 
1020  if (data->drawstate.viewport_dirty) {
1021  const SDL_bool istarget = data->drawstate.target != NULL;
1022  const SDL_Rect *viewport = &data->drawstate.viewport;
1023  data->glMatrixMode(GL_PROJECTION);
1024  data->glLoadIdentity();
1025  data->glViewport(viewport->x,
1026  istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
1027  viewport->w, viewport->h);
1028  if (viewport->w && viewport->h) {
1029  data->glOrtho((GLdouble) 0, (GLdouble) viewport->w,
1030  (GLdouble) istarget ? 0 : viewport->h,
1031  (GLdouble) istarget ? viewport->h : 0,
1032  0.0, 1.0);
1033  }
1034  data->glMatrixMode(GL_MODELVIEW);
1035  data->drawstate.viewport_dirty = SDL_FALSE;
1036  }
1037 
1038  if (data->drawstate.cliprect_enabled_dirty) {
1039  if (!data->drawstate.cliprect_enabled) {
1040  data->glDisable(GL_SCISSOR_TEST);
1041  } else {
1042  data->glEnable(GL_SCISSOR_TEST);
1043  }
1044  data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
1045  }
1046 
1047  if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
1048  const SDL_Rect *viewport = &data->drawstate.viewport;
1049  const SDL_Rect *rect = &data->drawstate.cliprect;
1050  data->glScissor(viewport->x + rect->x,
1051  data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
1052  rect->w, rect->h);
1053  data->drawstate.cliprect_dirty = SDL_FALSE;
1054  }
1055 
1056  if (blend != data->drawstate.blend) {
1057  if (blend == SDL_BLENDMODE_NONE) {
1058  data->glDisable(GL_BLEND);
1059  } else {
1060  data->glEnable(GL_BLEND);
1061  data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
1062  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
1063  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
1064  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
1065  data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
1066  }
1067  data->drawstate.blend = blend;
1068  }
1069 
1070  if (data->shaders && (shader != data->drawstate.shader)) {
1071  GL_SelectShader(data->shaders, shader);
1072  data->drawstate.shader = shader;
1073  }
1074 
1075  if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) {
1076  if (cmd->data.draw.texture == NULL) {
1077  data->glDisable(data->textype);
1078  data->drawstate.texturing = SDL_FALSE;
1079  } else {
1080  data->glEnable(data->textype);
1081  data->drawstate.texturing = SDL_TRUE;
1082  }
1083  }
1084 }
1085 
1086 static void
1087 SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
1088 {
1089  SDL_Texture *texture = cmd->data.draw.texture;
1090  const GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1091  GL_Shader shader;
1092 
1094  shader = SHADER_RGBA;
1095  } else {
1096  shader = SHADER_RGB;
1097  }
1098 
1099  if (data->shaders) {
1100  if (texturedata->yuv || texturedata->nv12) {
1103  if (texturedata->yuv) {
1105  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1107  } else {
1109  }
1110  break;
1112  if (texturedata->yuv) {
1114  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1116  } else {
1118  }
1119  break;
1121  if (texturedata->yuv) {
1123  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1125  } else {
1127  }
1128  break;
1129  default:
1130  SDL_assert(!"unsupported YUV conversion mode");
1131  break;
1132  }
1133  }
1134  }
1135 
1136  SetDrawState(data, cmd, shader);
1137 
1138  if (texture != data->drawstate.texture) {
1139  const GLenum textype = data->textype;
1140  if (texturedata->yuv) {
1141  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1142  data->glBindTexture(textype, texturedata->vtexture);
1143 
1144  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1145  data->glBindTexture(textype, texturedata->utexture);
1146  }
1147  if (texturedata->nv12) {
1148  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1149  data->glBindTexture(textype, texturedata->utexture);
1150  }
1151  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1152  data->glBindTexture(textype, texturedata->texture);
1153 
1154  data->drawstate.texture = texture;
1155  }
1156 }
1157 
1158 static int
1159 GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
1160 {
1161  /* !!! FIXME: it'd be nice to use a vertex buffer instead of immediate mode... */
1162  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1163  size_t i;
1164 
1165  if (GL_ActivateRenderer(renderer) < 0) {
1166  return -1;
1167  }
1168 
1169  data->drawstate.target = renderer->target;
1170  if (!data->drawstate.target) {
1171  SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
1172  }
1173 
1174 
1175  while (cmd) {
1176  switch (cmd->command) {
1178  const Uint8 r = cmd->data.color.r;
1179  const Uint8 g = cmd->data.color.g;
1180  const Uint8 b = cmd->data.color.b;
1181  const Uint8 a = cmd->data.color.a;
1182  const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
1183  if (color != data->drawstate.color) {
1184  data->glColor4f((GLfloat) r * inv255f,
1185  (GLfloat) g * inv255f,
1186  (GLfloat) b * inv255f,
1187  (GLfloat) a * inv255f);
1188  data->drawstate.color = color;
1189  }
1190  break;
1191  }
1192 
1194  SDL_Rect *viewport = &data->drawstate.viewport;
1195  if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
1196  SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
1197  data->drawstate.viewport_dirty = SDL_TRUE;
1198  }
1199  break;
1200  }
1201 
1203  const SDL_Rect *rect = &cmd->data.cliprect.rect;
1204  if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
1205  data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
1206  data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
1207  }
1208  if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
1209  SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
1210  data->drawstate.cliprect_dirty = SDL_TRUE;
1211  }
1212  break;
1213  }
1214 
1215  case SDL_RENDERCMD_CLEAR: {
1216  const Uint8 r = cmd->data.color.r;
1217  const Uint8 g = cmd->data.color.g;
1218  const Uint8 b = cmd->data.color.b;
1219  const Uint8 a = cmd->data.color.a;
1220  const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
1221  if (color != data->drawstate.clear_color) {
1222  const GLfloat fr = ((GLfloat) r) * inv255f;
1223  const GLfloat fg = ((GLfloat) g) * inv255f;
1224  const GLfloat fb = ((GLfloat) b) * inv255f;
1225  const GLfloat fa = ((GLfloat) a) * inv255f;
1226  data->glClearColor(fr, fg, fb, fa);
1227  data->drawstate.clear_color = color;
1228  }
1229 
1230  if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
1231  data->glDisable(GL_SCISSOR_TEST);
1232  data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
1233  }
1234 
1235  data->glClear(GL_COLOR_BUFFER_BIT);
1236 
1237  break;
1238  }
1239 
1241  const size_t count = cmd->data.draw.count;
1242  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
1244  data->glBegin(GL_POINTS);
1245  for (i = 0; i < count; i++, verts += 2) {
1246  data->glVertex2f(verts[0], verts[1]);
1247  }
1248  data->glEnd();
1249  break;
1250  }
1251 
1252  case SDL_RENDERCMD_DRAW_LINES: {
1253  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
1254  const size_t count = cmd->data.draw.count;
1255  SDL_assert(count >= 2);
1257  data->glBegin(GL_LINE_STRIP);
1258  for (i = 0; i < count; ++i, verts += 2) {
1259  data->glVertex2f(verts[0], verts[1]);
1260  }
1261  data->glEnd();
1262  break;
1263  }
1264 
1265  case SDL_RENDERCMD_FILL_RECTS: {
1266  const size_t count = cmd->data.draw.count;
1267  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
1269  for (i = 0; i < count; ++i, verts += 4) {
1270  data->glRectf(verts[0], verts[1], verts[2], verts[3]);
1271  }
1272  break;
1273  }
1274 
1275  case SDL_RENDERCMD_COPY: {
1276  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
1277  const GLfloat minx = verts[0];
1278  const GLfloat miny = verts[1];
1279  const GLfloat maxx = verts[2];
1280  const GLfloat maxy = verts[3];
1281  const GLfloat minu = verts[4];
1282  const GLfloat maxu = verts[5];
1283  const GLfloat minv = verts[6];
1284  const GLfloat maxv = verts[7];
1285  SetCopyState(data, cmd);
1286  data->glBegin(GL_TRIANGLE_STRIP);
1287  data->glTexCoord2f(minu, minv);
1288  data->glVertex2f(minx, miny);
1289  data->glTexCoord2f(maxu, minv);
1290  data->glVertex2f(maxx, miny);
1291  data->glTexCoord2f(minu, maxv);
1292  data->glVertex2f(minx, maxy);
1293  data->glTexCoord2f(maxu, maxv);
1294  data->glVertex2f(maxx, maxy);
1295  data->glEnd();
1296  break;
1297  }
1298 
1299  case SDL_RENDERCMD_COPY_EX: {
1300  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
1301  const GLfloat minx = verts[0];
1302  const GLfloat miny = verts[1];
1303  const GLfloat maxx = verts[2];
1304  const GLfloat maxy = verts[3];
1305  const GLfloat minu = verts[4];
1306  const GLfloat maxu = verts[5];
1307  const GLfloat minv = verts[6];
1308  const GLfloat maxv = verts[7];
1309  const GLfloat translatex = verts[8];
1310  const GLfloat translatey = verts[9];
1311  const GLdouble angle = verts[10];
1312  SetCopyState(data, cmd);
1313 
1314  /* Translate to flip, rotate, translate to position */
1315  data->glPushMatrix();
1316  data->glTranslatef(translatex, translatey, 0.0f);
1317  data->glRotated(angle, 0.0, 0.0, 1.0);
1318  data->glBegin(GL_TRIANGLE_STRIP);
1319  data->glTexCoord2f(minu, minv);
1320  data->glVertex2f(minx, miny);
1321  data->glTexCoord2f(maxu, minv);
1322  data->glVertex2f(maxx, miny);
1323  data->glTexCoord2f(minu, maxv);
1324  data->glVertex2f(minx, maxy);
1325  data->glTexCoord2f(maxu, maxv);
1326  data->glVertex2f(maxx, maxy);
1327  data->glEnd();
1328  data->glPopMatrix();
1329  break;
1330  }
1331 
1332  case SDL_RENDERCMD_NO_OP:
1333  break;
1334  }
1335 
1336  cmd = cmd->next;
1337  }
1338 
1339  return GL_CheckError("", renderer);
1340 }
1341 
1342 static int
1343 GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1344  Uint32 pixel_format, void * pixels, int pitch)
1345 {
1346  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1348  void *temp_pixels;
1349  int temp_pitch;
1351  GLenum format, type;
1352  Uint8 *src, *dst, *tmp;
1353  int w, h, length, rows;
1354  int status;
1355 
1356  GL_ActivateRenderer(renderer);
1357 
1358  if (!convert_format(data, temp_format, &internalFormat, &format, &type)) {
1359  return SDL_SetError("Texture format %s not supported by OpenGL",
1360  SDL_GetPixelFormatName(temp_format));
1361  }
1362 
1363  if (!rect->w || !rect->h) {
1364  return 0; /* nothing to do. */
1365  }
1366 
1367  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1368  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1369  if (!temp_pixels) {
1370  return SDL_OutOfMemory();
1371  }
1372 
1374 
1375  data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1376  data->glPixelStorei(GL_PACK_ROW_LENGTH,
1377  (temp_pitch / SDL_BYTESPERPIXEL(temp_format)));
1378 
1379  data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
1380  rect->w, rect->h, format, type, temp_pixels);
1381 
1382  if (GL_CheckError("glReadPixels()", renderer) < 0) {
1383  SDL_free(temp_pixels);
1384  return -1;
1385  }
1386 
1387  /* Flip the rows to be top-down if necessary */
1388  if (!renderer->target) {
1389  SDL_bool isstack;
1390  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1391  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1392  dst = (Uint8*)temp_pixels;
1393  tmp = SDL_small_alloc(Uint8, length, &isstack);
1394  rows = rect->h / 2;
1395  while (rows--) {
1396  SDL_memcpy(tmp, dst, length);
1397  SDL_memcpy(dst, src, length);
1398  SDL_memcpy(src, tmp, length);
1399  dst += temp_pitch;
1400  src -= temp_pitch;
1401  }
1402  SDL_small_free(tmp, isstack);
1403  }
1404 
1405  status = SDL_ConvertPixels(rect->w, rect->h,
1406  temp_format, temp_pixels, temp_pitch,
1407  pixel_format, pixels, pitch);
1408  SDL_free(temp_pixels);
1409 
1410  return status;
1411 }
1412 
1413 static void
1414 GL_RenderPresent(SDL_Renderer * renderer)
1415 {
1416  GL_ActivateRenderer(renderer);
1417 
1419 }
1420 
1421 static void
1422 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1423 {
1424  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
1425  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
1426 
1427  GL_ActivateRenderer(renderer);
1428 
1429  if (renderdata->drawstate.texture == texture) {
1430  renderdata->drawstate.texture = NULL;
1431  }
1432  if (renderdata->drawstate.target == texture) {
1433  renderdata->drawstate.target = NULL;
1434  }
1435 
1436  if (!data) {
1437  return;
1438  }
1439  if (data->texture) {
1440  renderdata->glDeleteTextures(1, &data->texture);
1441  }
1442  if (data->yuv) {
1443  renderdata->glDeleteTextures(1, &data->utexture);
1444  renderdata->glDeleteTextures(1, &data->vtexture);
1445  }
1446  SDL_free(data->pixels);
1447  SDL_free(data);
1448  texture->driverdata = NULL;
1449 }
1450 
1451 static void
1452 GL_DestroyRenderer(SDL_Renderer * renderer)
1453 {
1454  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1455 
1456  if (data) {
1457  if (data->context != NULL) {
1458  /* make sure we delete the right resources! */
1459  GL_ActivateRenderer(renderer);
1460  }
1461 
1462  GL_ClearErrors(renderer);
1463  if (data->GL_ARB_debug_output_supported) {
1464  PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
1465 
1466  /* Uh oh, we don't have a safe way of removing ourselves from the callback chain, if it changed after we set our callback. */
1467  /* For now, just always replace the callback with the original one */
1468  glDebugMessageCallbackARBFunc(data->next_error_callback, data->next_error_userparam);
1469  }
1470  if (data->shaders) {
1471  GL_DestroyShaderContext(data->shaders);
1472  }
1473  if (data->context) {
1474  while (data->framebuffers) {
1475  GL_FBOList *nextnode = data->framebuffers->next;
1476  /* delete the framebuffer object */
1477  data->glDeleteFramebuffersEXT(1, &data->framebuffers->FBO);
1478  GL_CheckError("", renderer);
1479  SDL_free(data->framebuffers);
1480  data->framebuffers = nextnode;
1481  }
1482  SDL_GL_DeleteContext(data->context);
1483  }
1484  SDL_free(data);
1485  }
1486  SDL_free(renderer);
1487 }
1488 
1489 static int
1490 GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
1491 {
1492  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1493  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1494  const GLenum textype = data->textype;
1495 
1496  GL_ActivateRenderer(renderer);
1497 
1498  data->glEnable(textype);
1499  if (texturedata->yuv) {
1500  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1501  data->glBindTexture(textype, texturedata->vtexture);
1502 
1503  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1504  data->glBindTexture(textype, texturedata->utexture);
1505 
1506  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1507  }
1508  data->glBindTexture(textype, texturedata->texture);
1509 
1510  data->drawstate.texturing = SDL_TRUE;
1511  data->drawstate.texture = texture;
1512 
1513  if(texw) *texw = (float)texturedata->texw;
1514  if(texh) *texh = (float)texturedata->texh;
1515 
1516  return 0;
1517 }
1518 
1519 static int
1520 GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
1521 {
1522  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1523  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1524  const GLenum textype = data->textype;
1525 
1526  GL_ActivateRenderer(renderer);
1527 
1528  if (texturedata->yuv) {
1529  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1530  data->glDisable(textype);
1531 
1532  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1533  data->glDisable(textype);
1534 
1535  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1536  }
1537 
1538  data->glDisable(textype);
1539 
1540  data->drawstate.texturing = SDL_FALSE;
1541  data->drawstate.texture = NULL;
1542 
1543  return 0;
1544 }
1545 
1546 
1547 static SDL_Renderer *
1548 GL_CreateRenderer(SDL_Window * window, Uint32 flags)
1549 {
1551  GL_RenderData *data;
1552  GLint value;
1553  Uint32 window_flags;
1554  int profile_mask = 0, major = 0, minor = 0;
1555  SDL_bool changed_window = SDL_FALSE;
1556 
1560 
1561  window_flags = SDL_GetWindowFlags(window);
1562  if (!(window_flags & SDL_WINDOW_OPENGL) ||
1563  profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
1564 
1565  changed_window = SDL_TRUE;
1567  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
1568  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
1569 
1571  goto error;
1572  }
1573  }
1574 
1575  renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
1576  if (!renderer) {
1577  SDL_OutOfMemory();
1578  goto error;
1579  }
1580 
1581  data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
1582  if (!data) {
1583  SDL_free(renderer);
1584  SDL_OutOfMemory();
1585  goto error;
1586  }
1587 
1588  renderer->GetOutputSize = GL_GetOutputSize;
1589  renderer->SupportsBlendMode = GL_SupportsBlendMode;
1590  renderer->CreateTexture = GL_CreateTexture;
1591  renderer->UpdateTexture = GL_UpdateTexture;
1592  renderer->UpdateTextureYUV = GL_UpdateTextureYUV;
1593  renderer->LockTexture = GL_LockTexture;
1594  renderer->UnlockTexture = GL_UnlockTexture;
1595  renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
1596  renderer->SetRenderTarget = GL_SetRenderTarget;
1597  renderer->QueueSetViewport = GL_QueueSetViewport;
1598  renderer->QueueSetDrawColor = GL_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
1599  renderer->QueueDrawPoints = GL_QueueDrawPoints;
1600  renderer->QueueDrawLines = GL_QueueDrawLines;
1601  renderer->QueueFillRects = GL_QueueFillRects;
1602  renderer->QueueCopy = GL_QueueCopy;
1603  renderer->QueueCopyEx = GL_QueueCopyEx;
1604  renderer->RunCommandQueue = GL_RunCommandQueue;
1605  renderer->RenderReadPixels = GL_RenderReadPixels;
1606  renderer->RenderPresent = GL_RenderPresent;
1607  renderer->DestroyTexture = GL_DestroyTexture;
1608  renderer->DestroyRenderer = GL_DestroyRenderer;
1609  renderer->GL_BindTexture = GL_BindTexture;
1610  renderer->GL_UnbindTexture = GL_UnbindTexture;
1614  renderer->window = window;
1615 
1616  data->context = SDL_GL_CreateContext(window);
1617  if (!data->context) {
1618  SDL_free(renderer);
1619  SDL_free(data);
1620  goto error;
1621  }
1622  if (SDL_GL_MakeCurrent(window, data->context) < 0) {
1623  SDL_GL_DeleteContext(data->context);
1624  SDL_free(renderer);
1625  SDL_free(data);
1626  goto error;
1627  }
1628 
1629  if (GL_LoadFunctions(data) < 0) {
1630  SDL_GL_DeleteContext(data->context);
1631  SDL_free(renderer);
1632  SDL_free(data);
1633  goto error;
1634  }
1635 
1636 #ifdef __MACOSX__
1637  /* Enable multi-threaded rendering */
1638  /* Disabled until Ryan finishes his VBO/PBO code...
1639  CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
1640  */
1641 #endif
1642 
1645  } else {
1647  }
1648  if (SDL_GL_GetSwapInterval() > 0) {
1650  }
1651 
1652  /* Check for debug output support */
1655  data->debug_enabled = SDL_TRUE;
1656  }
1657  if (data->debug_enabled && SDL_GL_ExtensionSupported("GL_ARB_debug_output")) {
1658  PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
1659 
1660  data->GL_ARB_debug_output_supported = SDL_TRUE;
1661  data->glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION_ARB, (GLvoid **)(char *)&data->next_error_callback);
1662  data->glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM_ARB, &data->next_error_userparam);
1663  glDebugMessageCallbackARBFunc(GL_HandleDebugMessage, renderer);
1664 
1665  /* Make sure our callback is called when errors actually happen */
1667  }
1668 
1669  data->textype = GL_TEXTURE_2D;
1670  if (SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
1671  data->GL_ARB_texture_non_power_of_two_supported = SDL_TRUE;
1672  } else if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
1673  SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
1674  data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
1675  data->textype = GL_TEXTURE_RECTANGLE_ARB;
1676  }
1677  if (data->GL_ARB_texture_rectangle_supported) {
1678  data->glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &value);
1681  } else {
1682  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
1685  }
1686 
1687  /* Check for multitexture support */
1688  if (SDL_GL_ExtensionSupported("GL_ARB_multitexture")) {
1689  data->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
1690  if (data->glActiveTextureARB) {
1691  data->GL_ARB_multitexture_supported = SDL_TRUE;
1692  data->glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &data->num_texture_units);
1693  }
1694  }
1695 
1696  /* Check for shader support */
1698  data->shaders = GL_CreateShaderContext();
1699  }
1700  SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
1701  data->shaders ? "ENABLED" : "DISABLED");
1702 
1703  /* We support YV12 textures using 3 textures and a shader */
1704  if (data->shaders && data->num_texture_units >= 3) {
1709  }
1710 
1711 #ifdef __MACOSX__
1713 #endif
1714 
1715  if (SDL_GL_ExtensionSupported("GL_EXT_framebuffer_object")) {
1716  data->GL_EXT_framebuffer_object_supported = SDL_TRUE;
1717  data->glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)
1718  SDL_GL_GetProcAddress("glGenFramebuffersEXT");
1719  data->glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
1720  SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
1721  data->glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
1722  SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
1723  data->glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)
1724  SDL_GL_GetProcAddress("glBindFramebufferEXT");
1725  data->glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
1726  SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
1728  }
1729  data->framebuffers = NULL;
1730 
1731  /* Set up parameters for rendering */
1732  data->glMatrixMode(GL_MODELVIEW);
1733  data->glLoadIdentity();
1734  data->glDisable(GL_DEPTH_TEST);
1735  data->glDisable(GL_CULL_FACE);
1736  data->glDisable(GL_SCISSOR_TEST);
1737  data->glDisable(data->textype);
1738  data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1739  data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1740  /* This ended up causing video discrepancies between OpenGL and Direct3D */
1741  /* data->glEnable(GL_LINE_SMOOTH); */
1742 
1743  data->drawstate.blend = SDL_BLENDMODE_INVALID;
1744  data->drawstate.shader = SHADER_INVALID;
1745  data->drawstate.color = 0xFFFFFFFF;
1746  data->drawstate.clear_color = 0xFFFFFFFF;
1747 
1748  return renderer;
1749 
1750 error:
1751  if (changed_window) {
1752  /* Uh oh, better try to put it back... */
1756  SDL_RecreateWindow(window, window_flags);
1757  }
1758  return NULL;
1759 }
1760 
1761 
1763  GL_CreateRenderer,
1764  {
1765  "opengl",
1767  4,
1768  {
1773  },
1774  0,
1775  0}
1776 };
1777 
1778 
1779 #endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */
1780 
1781 /* 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_GetYUVConversionModeForResolution
#define SDL_GetPixelFormatName
#define SDL_GL_GetAttribute
#define SDL_GL_SetSwapInterval
#define SDL_GL_MakeCurrent
#define SDL_GetRendererOutputSize
#define SDL_malloc
#define SDL_realloc
#define SDL_GL_SetAttribute
#define SDL_LogError
#define SDL_free
#define SDL_strdup
#define SDL_memcmp
#define SDL_GL_GetSwapInterval
#define SDL_GL_DeleteContext
#define SDL_GetHintBoolean
#define SDL_LogDebug
#define SDL_sinf
#define SDL_GL_GetProcAddress
#define SDL_memcpy
#define SDL_GL_CreateContext
#define SDL_GL_ExtensionSupported
#define SDL_GL_GetDrawableSize
#define SDL_LogInfo
#define SDL_calloc
#define SDL_ConvertPixels
#define SDL_GL_GetCurrentContext
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define SDL_HINT_RENDER_OPENGL_SHADERS
A variable controlling whether the OpenGL render driver uses shaders if they are available.
Definition: SDL_hints.h:96
#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
@ SDL_LOG_CATEGORY_RENDER
Definition: SDL_log.h:72
#define GL_TRUE
Definition: SDL_opengl.h:200
#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
void GLvoid
Definition: SDL_opengl.h:179
#define GL_TEXTURE_WRAP_S
Definition: SDL_opengl.h:672
GLAPI void GLAPIENTRY glActiveTextureARB(GLenum texture)
float GLfloat
Definition: SDL_opengl.h:187
#define GL_RGBA8
Definition: SDL_opengl.h:788
#define GL_MAX_TEXTURE_UNITS_ARB
Definition: SDL_opengl.h:2024
#define GL_LUMINANCE_ALPHA
Definition: SDL_opengl.h:511
#define GL_ONE_MINUS_DST_ALPHA
Definition: SDL_opengl.h:407
#define GL_PACK_ROW_LENGTH
Definition: SDL_opengl.h:654
#define APIENTRY
Definition: SDL_opengl.h:139
#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
double GLdouble
Definition: SDL_opengl.h:189
#define GL_SRC_ALPHA
Definition: SDL_opengl.h:404
#define GL_TEXTURE0_ARB
Definition: SDL_opengl.h:1990
#define GL_INVALID_OPERATION
Definition: SDL_opengl.h:722
#define GL_BGRA
Definition: SDL_opengl.h:1511
#define GL_TEXTURE2_ARB
Definition: SDL_opengl.h:1992
unsigned int GLenum
Definition: SDL_opengl.h:176
#define GL_RGB8
Definition: SDL_opengl.h:781
#define GL_LUMINANCE
Definition: SDL_opengl.h:510
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_ZERO
Definition: SDL_opengl.h:400
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
#define GL_NEAREST
Definition: SDL_opengl.h:704
#define GL_UNSIGNED_BYTE
Definition: SDL_opengl.h:204
#define GL_FUNC_REVERSE_SUBTRACT
Definition: SDL_opengl.h:1654
#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
#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
#define GL_FALSE
Definition: SDL_opengl.h:199
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
#define GL_TEXTURE_MAG_FILTER
Definition: SDL_opengl.h:674
#define GL_TABLE_TOO_LARGE
Definition: SDL_opengl.h:1648
#define GL_DST_COLOR
Definition: SDL_opengl.h:408
int GLint
Definition: SDL_opengl.h:182
#define GL_FUNC_SUBTRACT
Definition: SDL_opengl.h:1653
#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_UNSIGNED_INT_8_8_8_8_REV
Definition: SDL_opengl.h:1521
#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_FUNC_ADD
Definition: SDL_opengl.h:1652
#define GL_ONE_MINUS_SRC_COLOR
Definition: SDL_opengl.h:403
#define GL_UNPACK_ROW_LENGTH
Definition: SDL_opengl.h:660
#define GL_TEXTURE1_ARB
Definition: SDL_opengl.h:1991
GLboolean GLboolean GLboolean b
GLfixed GLfixed GLint GLint GLfixed points
#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB
GLenum src
GLuint64EXT * result
GLuint color
#define GL_UNSIGNED_SHORT_8_8_APPLE
#define GL_FRAMEBUFFER_COMPLETE_EXT
#define GL_COLOR_ATTACHMENT0_EXT
#define GL_DEBUG_CALLBACK_USER_PARAM_ARB
GLuint shader
GLsizei GLsizei GLchar * source
GLenum internalFormat
GLboolean GLboolean GLboolean GLboolean a
GLuint GLsizei const GLchar * message
void(APIENTRY * GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
GLenum GLenum dst
const GLuint * framebuffers
#define GL_STORAGE_CACHED_APPLE
GLboolean GLboolean g
GLfloat angle
GLsizei GLsizei GLuint * shaders
GLsizeiptr size
#define GL_DEBUG_CALLBACK_FUNCTION_ARB
GLbitfield flags
#define GL_DEBUG_TYPE_ERROR_ARB
GLenum GLenum GLuint texture
const void * userParam
GLuint GLsizei GLsizei * length
#define GL_UNPACK_CLIENT_STORAGE_APPLE
#define GL_TEXTURE_RECTANGLE_ARB
GLsizei const GLfloat * value
GLenum GLenum severity
GLenum GLenum GLenum input
#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
#define GL_STORAGE_SHARED_APPLE
#define GL_FRAMEBUFFER_EXT
#define GL_TEXTURE_STORAGE_HINT_APPLE
GLenum target
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
#define GL_YCBCR_422_APPLE
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
@ SDL_PIXELFORMAT_UYVY
Definition: SDL_pixels.h:292
@ SDL_PIXELFORMAT_BGR888
Definition: SDL_pixels.h:253
@ SDL_PIXELFORMAT_YV12
Definition: SDL_pixels.h:286
@ SDL_PIXELFORMAT_RGB888
Definition: SDL_pixels.h:246
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:263
@ SDL_PIXELFORMAT_NV12
Definition: SDL_pixels.h:296
@ SDL_PIXELFORMAT_NV21
Definition: SDL_pixels.h:298
@ SDL_PIXELFORMAT_IYUV
Definition: SDL_pixels.h:288
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:257
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)
@ SHADER_RGB
@ SHADER_NV12_JPEG
@ SHADER_NV21_BT709
@ SHADER_NV12_BT601
@ SHADER_NV12_BT709
@ SHADER_SOLID
@ SHADER_NV21_JPEG
@ SHADER_NV21_BT601
@ SHADER_YUV_JPEG
@ SHADER_YUV_BT601
@ SHADER_YUV_BT709
GL_ShaderContext * GL_CreateShaderContext(void)
void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader)
void GL_DestroyShaderContext(GL_ShaderContext *ctx)
struct GL_ShaderContext GL_ShaderContext
GL_Shader
@ SHADER_INVALID
@ SHADER_RGBA
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_YUV_CONVERSION_BT601
Definition: SDL_surface.h:109
@ SDL_YUV_CONVERSION_JPEG
Definition: SDL_surface.h:108
@ SDL_YUV_CONVERSION_BT709
Definition: SDL_surface.h:110
SDL_RenderDriver GL_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_FLAGS
Definition: SDL_video.h:222
@ 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
@ SDL_GL_CONTEXT_DEBUG_FLAG
Definition: SDL_video.h:240
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:195
@ 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_FORCE_INLINE
Definition: begin_code.h:143
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(* UpdateTextureYUV)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, const Uint8 *Vplane, int Vpitch)
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)
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 texture_formats[16]
Definition: SDL_render.h:83
Uint32 num_texture_formats
Definition: SDL_render.h:82
Uint32 format
Definition: SDL_sysrender.h:39
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_bool retval
SDL_Rect rect
Definition: testrelative.c:27
static SDL_Rect viewport
Definition: testviewport.c:28
static screen_context_t context
Definition: video.c:25