SDL  2.0
SDL_render_gl.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED
24 
25 #include "SDL_hints.h"
26 #include "SDL_log.h"
27 #include "SDL_assert.h"
28 #include "SDL_opengl.h"
29 #include "../SDL_sysrender.h"
30 #include "SDL_shaders_gl.h"
31 
32 #ifdef __MACOSX__
33 #include <OpenGL/OpenGL.h>
34 #endif
35 
36 /* To prevent unnecessary window recreation,
37  * these should match the defaults selected in SDL_GL_ResetAttributes
38  */
39 
40 #define RENDERER_CONTEXT_MAJOR 2
41 #define RENDERER_CONTEXT_MINOR 1
42 
43 /* OpenGL renderer implementation */
44 
45 /* Details on optimizing the texture path on Mac OS X:
46  http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html
47 */
48 
49 /* Used to re-create the window with OpenGL capability */
51 
52 static const float inv255f = 1.0f / 255.0f;
53 
54 static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
55 static void GL_WindowEvent(SDL_Renderer * renderer,
56  const SDL_WindowEvent *event);
57 static int GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
58 static SDL_bool GL_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
59 static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
60 static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
61  const SDL_Rect * rect, const void *pixels,
62  int pitch);
63 static int GL_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
64  const SDL_Rect * rect,
65  const Uint8 *Yplane, int Ypitch,
66  const Uint8 *Uplane, int Upitch,
67  const Uint8 *Vplane, int Vpitch);
68 static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
69  const SDL_Rect * rect, void **pixels, int *pitch);
70 static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
71 static int GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
72 static int GL_UpdateViewport(SDL_Renderer * renderer);
73 static int GL_UpdateClipRect(SDL_Renderer * renderer);
74 static int GL_RenderClear(SDL_Renderer * renderer);
75 static int GL_RenderDrawPoints(SDL_Renderer * renderer,
76  const SDL_FPoint * points, int count);
77 static int GL_RenderDrawLines(SDL_Renderer * renderer,
78  const SDL_FPoint * points, int count);
79 static int GL_RenderFillRects(SDL_Renderer * renderer,
80  const SDL_FRect * rects, int count);
81 static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
82  const SDL_Rect * srcrect, const SDL_FRect * dstrect);
83 static int GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
84  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
85  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
86 static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
87  Uint32 pixel_format, void * pixels, int pitch);
88 static void GL_RenderPresent(SDL_Renderer * renderer);
89 static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
90 static void GL_DestroyRenderer(SDL_Renderer * renderer);
91 static int GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
92 static int GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
93 
95  GL_CreateRenderer,
96  {
97  "opengl",
99  1,
101  0,
102  0}
103 };
104 
105 typedef struct GL_FBOList GL_FBOList;
106 
107 struct GL_FBOList
108 {
109  Uint32 w, h;
110  GLuint FBO;
111  GL_FBOList *next;
112 };
113 
114 typedef struct
115 {
117 
118  SDL_bool debug_enabled;
119  SDL_bool GL_ARB_debug_output_supported;
120  int errors;
121  char **error_messages;
122  GLDEBUGPROCARB next_error_callback;
123  GLvoid *next_error_userparam;
124 
125  SDL_bool GL_ARB_texture_non_power_of_two_supported;
126  SDL_bool GL_ARB_texture_rectangle_supported;
127  struct {
129  Uint32 color;
131  } current;
132 
133  SDL_bool GL_EXT_framebuffer_object_supported;
134  GL_FBOList *framebuffers;
135 
136  /* OpenGL functions */
137 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
138 #include "SDL_glfuncs.h"
139 #undef SDL_PROC
140 
141  /* Multitexture support */
142  SDL_bool GL_ARB_multitexture_supported;
143  PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
144  GLint num_texture_units;
145 
146  PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
147  PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
148  PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
149  PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
150  PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
151 
152  /* Shader support */
154 
155 } GL_RenderData;
156 
157 typedef struct
158 {
159  GLuint texture;
160  GLenum type;
161  GLfloat texw;
162  GLfloat texh;
163  GLenum format;
164  GLenum formattype;
165  void *pixels;
166  int pitch;
167  SDL_Rect locked_rect;
168 
169  /* YUV texture support */
170  SDL_bool yuv;
171  SDL_bool nv12;
172  GLuint utexture;
173  GLuint vtexture;
174 
175  GL_FBOList *fbo;
176 } GL_TextureData;
177 
178 SDL_FORCE_INLINE const char*
179 GL_TranslateError (GLenum error)
180 {
181 #define GL_ERROR_TRANSLATE(e) case e: return #e;
182  switch (error) {
183  GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
184  GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
185  GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
186  GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
187  GL_ERROR_TRANSLATE(GL_NO_ERROR)
188  GL_ERROR_TRANSLATE(GL_STACK_OVERFLOW)
189  GL_ERROR_TRANSLATE(GL_STACK_UNDERFLOW)
190  GL_ERROR_TRANSLATE(GL_TABLE_TOO_LARGE)
191  default:
192  return "UNKNOWN";
193 }
194 #undef GL_ERROR_TRANSLATE
195 }
196 
197 SDL_FORCE_INLINE void
198 GL_ClearErrors(SDL_Renderer *renderer)
199 {
200  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
201 
202  if (!data->debug_enabled)
203  {
204  return;
205  }
206  if (data->GL_ARB_debug_output_supported) {
207  if (data->errors) {
208  int i;
209  for (i = 0; i < data->errors; ++i) {
210  SDL_free(data->error_messages[i]);
211  }
212  SDL_free(data->error_messages);
213 
214  data->errors = 0;
215  data->error_messages = NULL;
216  }
217  } else {
218  while (data->glGetError() != GL_NO_ERROR) {
219  continue;
220  }
221  }
222 }
223 
225 GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
226 {
227  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
228  int ret = 0;
229 
230  if (!data->debug_enabled)
231  {
232  return 0;
233  }
234  if (data->GL_ARB_debug_output_supported) {
235  if (data->errors) {
236  int i;
237  for (i = 0; i < data->errors; ++i) {
238  SDL_SetError("%s: %s (%d): %s %s", prefix, file, line, function, data->error_messages[i]);
239  ret = -1;
240  }
241  GL_ClearErrors(renderer);
242  }
243  } else {
244  /* check gl errors (can return multiple errors) */
245  for (;;) {
246  GLenum error = data->glGetError();
247  if (error != GL_NO_ERROR) {
248  if (prefix == NULL || prefix[0] == '\0') {
249  prefix = "generic";
250  }
251  SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
252  ret = -1;
253  } else {
254  break;
255  }
256  }
257  }
258  return ret;
259 }
260 
261 #if 0
262 #define GL_CheckError(prefix, renderer)
263 #else
264 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION)
265 #endif
266 
267 static int
268 GL_LoadFunctions(GL_RenderData * data)
269 {
270 #ifdef __SDL_NOGETPROCADDR__
271 #define SDL_PROC(ret,func,params) data->func=func;
272 #else
273 #define SDL_PROC(ret,func,params) \
274  do { \
275  data->func = SDL_GL_GetProcAddress(#func); \
276  if ( ! data->func ) { \
277  return SDL_SetError("Couldn't load GL function %s: %s", #func, SDL_GetError()); \
278  } \
279  } while ( 0 );
280 #endif /* __SDL_NOGETPROCADDR__ */
281 
282 #include "SDL_glfuncs.h"
283 #undef SDL_PROC
284  return 0;
285 }
286 
287 static SDL_GLContext SDL_CurrentContext = NULL;
288 
289 static int
290 GL_ActivateRenderer(SDL_Renderer * renderer)
291 {
292  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
293 
294  if (SDL_CurrentContext != data->context ||
295  SDL_GL_GetCurrentContext() != data->context) {
296  if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
297  return -1;
298  }
299  SDL_CurrentContext = data->context;
300 
301  GL_UpdateViewport(renderer);
302  }
303 
304  GL_ClearErrors(renderer);
305 
306  return 0;
307 }
308 
309 /* This is called if we need to invalidate all of the SDL OpenGL state */
310 static void
311 GL_ResetState(SDL_Renderer *renderer)
312 {
313  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
314 
315  if (SDL_GL_GetCurrentContext() == data->context) {
316  GL_UpdateViewport(renderer);
317  } else {
318  GL_ActivateRenderer(renderer);
319  }
320 
321  data->current.shader = SHADER_NONE;
322  data->current.color = 0xffffffff;
323  data->current.blendMode = SDL_BLENDMODE_INVALID;
324 
325  data->glDisable(GL_DEPTH_TEST);
326  data->glDisable(GL_CULL_FACE);
327  /* This ended up causing video discrepancies between OpenGL and Direct3D */
328  /* data->glEnable(GL_LINE_SMOOTH); */
329 
330  data->glMatrixMode(GL_MODELVIEW);
331  data->glLoadIdentity();
332 
333  GL_CheckError("", renderer);
334 }
335 
336 static void APIENTRY
337 GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam)
338 {
339  SDL_Renderer *renderer = (SDL_Renderer *) userParam;
340  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
341 
342  if (type == GL_DEBUG_TYPE_ERROR_ARB) {
343  /* Record this error */
344  int errors = data->errors + 1;
345  char **error_messages = SDL_realloc(data->error_messages, errors * sizeof(*data->error_messages));
346  if (error_messages) {
347  data->errors = errors;
348  data->error_messages = error_messages;
349  data->error_messages[data->errors-1] = SDL_strdup(message);
350  }
351  }
352 
353  /* If there's another error callback, pass it along, otherwise log it */
354  if (data->next_error_callback) {
355  data->next_error_callback(source, type, id, severity, length, message, data->next_error_userparam);
356  } else {
357  if (type == GL_DEBUG_TYPE_ERROR_ARB) {
358  SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", message);
359  } else {
360  SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "%s", message);
361  }
362  }
363 }
364 
365 static GL_FBOList *
366 GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
367 {
368  GL_FBOList *result = data->framebuffers;
369 
370  while (result && ((result->w != w) || (result->h != h))) {
371  result = result->next;
372  }
373 
374  if (!result) {
375  result = SDL_malloc(sizeof(GL_FBOList));
376  if (result) {
377  result->w = w;
378  result->h = h;
379  data->glGenFramebuffersEXT(1, &result->FBO);
380  result->next = data->framebuffers;
381  data->framebuffers = result;
382  }
383  }
384  return result;
385 }
386 
387 SDL_Renderer *
388 GL_CreateRenderer(SDL_Window * window, Uint32 flags)
389 {
391  GL_RenderData *data;
392  GLint value;
393  Uint32 window_flags;
394  int profile_mask = 0, major = 0, minor = 0;
395  SDL_bool changed_window = SDL_FALSE;
396 
400 
401  window_flags = SDL_GetWindowFlags(window);
402  if (!(window_flags & SDL_WINDOW_OPENGL) ||
403  profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
404 
405  changed_window = SDL_TRUE;
407  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
408  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
409 
410  if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
411  goto error;
412  }
413  }
414 
415  renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
416  if (!renderer) {
417  SDL_OutOfMemory();
418  goto error;
419  }
420 
421  data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
422  if (!data) {
423  GL_DestroyRenderer(renderer);
424  SDL_OutOfMemory();
425  goto error;
426  }
427 
428  renderer->WindowEvent = GL_WindowEvent;
429  renderer->GetOutputSize = GL_GetOutputSize;
430  renderer->SupportsBlendMode = GL_SupportsBlendMode;
431  renderer->CreateTexture = GL_CreateTexture;
432  renderer->UpdateTexture = GL_UpdateTexture;
433  renderer->UpdateTextureYUV = GL_UpdateTextureYUV;
434  renderer->LockTexture = GL_LockTexture;
435  renderer->UnlockTexture = GL_UnlockTexture;
436  renderer->SetRenderTarget = GL_SetRenderTarget;
437  renderer->UpdateViewport = GL_UpdateViewport;
438  renderer->UpdateClipRect = GL_UpdateClipRect;
439  renderer->RenderClear = GL_RenderClear;
440  renderer->RenderDrawPoints = GL_RenderDrawPoints;
441  renderer->RenderDrawLines = GL_RenderDrawLines;
442  renderer->RenderFillRects = GL_RenderFillRects;
443  renderer->RenderCopy = GL_RenderCopy;
444  renderer->RenderCopyEx = GL_RenderCopyEx;
445  renderer->RenderReadPixels = GL_RenderReadPixels;
446  renderer->RenderPresent = GL_RenderPresent;
447  renderer->DestroyTexture = GL_DestroyTexture;
448  renderer->DestroyRenderer = GL_DestroyRenderer;
449  renderer->GL_BindTexture = GL_BindTexture;
450  renderer->GL_UnbindTexture = GL_UnbindTexture;
451  renderer->info = GL_RenderDriver.info;
452  renderer->info.flags = SDL_RENDERER_ACCELERATED;
453  renderer->driverdata = data;
454  renderer->window = window;
455 
456  data->context = SDL_GL_CreateContext(window);
457  if (!data->context) {
458  GL_DestroyRenderer(renderer);
459  goto error;
460  }
461  if (SDL_GL_MakeCurrent(window, data->context) < 0) {
462  GL_DestroyRenderer(renderer);
463  goto error;
464  }
465 
466  if (GL_LoadFunctions(data) < 0) {
467  GL_DestroyRenderer(renderer);
468  goto error;
469  }
470 
471 #ifdef __MACOSX__
472  /* Enable multi-threaded rendering */
473  /* Disabled until Ryan finishes his VBO/PBO code...
474  CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
475  */
476 #endif
477 
478  if (flags & SDL_RENDERER_PRESENTVSYNC) {
480  } else {
482  }
483  if (SDL_GL_GetSwapInterval() > 0) {
484  renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
485  }
486 
487  /* Check for debug output support */
488  if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 &&
489  (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
490  data->debug_enabled = SDL_TRUE;
491  }
492  if (data->debug_enabled && SDL_GL_ExtensionSupported("GL_ARB_debug_output")) {
493  PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
494 
495  data->GL_ARB_debug_output_supported = SDL_TRUE;
496  data->glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION_ARB, (GLvoid **)(char *)&data->next_error_callback);
497  data->glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM_ARB, &data->next_error_userparam);
498  glDebugMessageCallbackARBFunc(GL_HandleDebugMessage, renderer);
499 
500  /* Make sure our callback is called when errors actually happen */
501  data->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
502  }
503 
504  if (SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
505  data->GL_ARB_texture_non_power_of_two_supported = SDL_TRUE;
506  } else if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
507  SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
508  data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
509  }
510  if (data->GL_ARB_texture_rectangle_supported) {
511  data->glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &value);
512  renderer->info.max_texture_width = value;
513  renderer->info.max_texture_height = value;
514  } else {
515  data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
516  renderer->info.max_texture_width = value;
517  renderer->info.max_texture_height = value;
518  }
519 
520  /* Check for multitexture support */
521  if (SDL_GL_ExtensionSupported("GL_ARB_multitexture")) {
522  data->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
523  if (data->glActiveTextureARB) {
524  data->GL_ARB_multitexture_supported = SDL_TRUE;
525  data->glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &data->num_texture_units);
526  }
527  }
528 
529  /* Check for shader support */
531  data->shaders = GL_CreateShaderContext();
532  }
533  SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
534  data->shaders ? "ENABLED" : "DISABLED");
535 
536  /* We support YV12 textures using 3 textures and a shader */
537  if (data->shaders && data->num_texture_units >= 3) {
542  }
543 
544 #ifdef __MACOSX__
546 #endif
547 
548  if (SDL_GL_ExtensionSupported("GL_EXT_framebuffer_object")) {
549  data->GL_EXT_framebuffer_object_supported = SDL_TRUE;
550  data->glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)
551  SDL_GL_GetProcAddress("glGenFramebuffersEXT");
552  data->glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
553  SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
554  data->glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
555  SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
556  data->glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)
557  SDL_GL_GetProcAddress("glBindFramebufferEXT");
558  data->glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
559  SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
561  }
562  data->framebuffers = NULL;
563 
564  /* Set up parameters for rendering */
565  GL_ResetState(renderer);
566 
567  return renderer;
568 
569 error:
570  if (changed_window) {
571  /* Uh oh, better try to put it back... */
575  SDL_RecreateWindow(window, window_flags);
576  }
577  return NULL;
578 }
579 
580 static void
581 GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
582 {
583  if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
584  event->event == SDL_WINDOWEVENT_SHOWN ||
585  event->event == SDL_WINDOWEVENT_HIDDEN) {
586  /* Rebind the context to the window area and update matrices */
587  SDL_CurrentContext = NULL;
588  }
589 }
590 
591 static int
592 GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
593 {
594  SDL_GL_GetDrawableSize(renderer->window, w, h);
595  return 0;
596 }
597 
598 static GLenum GetBlendFunc(SDL_BlendFactor factor)
599 {
600  switch (factor) {
602  return GL_ZERO;
603  case SDL_BLENDFACTOR_ONE:
604  return GL_ONE;
606  return GL_SRC_COLOR;
608  return GL_ONE_MINUS_SRC_COLOR;
610  return GL_SRC_ALPHA;
612  return GL_ONE_MINUS_SRC_ALPHA;
614  return GL_DST_COLOR;
616  return GL_ONE_MINUS_DST_COLOR;
618  return GL_DST_ALPHA;
620  return GL_ONE_MINUS_DST_ALPHA;
621  default:
622  return GL_INVALID_ENUM;
623  }
624 }
625 
626 static GLenum GetBlendEquation(SDL_BlendOperation operation)
627 {
628  switch (operation) {
630  return GL_FUNC_ADD;
632  return GL_FUNC_SUBTRACT;
635  default:
636  return GL_INVALID_ENUM;
637  }
638 }
639 
640 static SDL_bool
641 GL_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
642 {
643  SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
644  SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
645  SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
646  SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
647  SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
648  SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
649 
650  if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
651  GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
652  GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
653  GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
654  GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
655  GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
656  return SDL_FALSE;
657  }
658  if (colorOperation != alphaOperation) {
659  return SDL_FALSE;
660  }
661  return SDL_TRUE;
662 }
663 
665 power_of_2(int input)
666 {
667  int value = 1;
668 
669  while (value < input) {
670  value <<= 1;
671  }
672  return value;
673 }
674 
676 convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
678 {
679  switch (pixel_format) {
681  *internalFormat = GL_RGBA8;
682  *format = GL_BGRA;
684  break;
689  *internalFormat = GL_LUMINANCE;
690  *format = GL_LUMINANCE;
691  *type = GL_UNSIGNED_BYTE;
692  break;
693 #ifdef __MACOSX__
695  *internalFormat = GL_RGB8;
696  *format = GL_YCBCR_422_APPLE;
698  break;
699 #endif
700  default:
701  return SDL_FALSE;
702  }
703  return SDL_TRUE;
704 }
705 
706 static GLenum
707 GetScaleQuality(void)
708 {
709  const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
710 
711  if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
712  return GL_NEAREST;
713  } else {
714  return GL_LINEAR;
715  }
716 }
717 
718 static int
719 GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
720 {
721  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
722  GL_TextureData *data;
723  GLint internalFormat;
724  GLenum format, type;
725  int texture_w, texture_h;
726  GLenum scaleMode;
727 
728  GL_ActivateRenderer(renderer);
729 
730  if (texture->access == SDL_TEXTUREACCESS_TARGET &&
731  !renderdata->GL_EXT_framebuffer_object_supported) {
732  return SDL_SetError("Render targets not supported by OpenGL");
733  }
734 
735  if (!convert_format(renderdata, texture->format, &internalFormat,
736  &format, &type)) {
737  return SDL_SetError("Texture format %s not supported by OpenGL",
738  SDL_GetPixelFormatName(texture->format));
739  }
740 
741  data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
742  if (!data) {
743  return SDL_OutOfMemory();
744  }
745 
746  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
747  size_t size;
748  data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
749  size = texture->h * data->pitch;
750  if (texture->format == SDL_PIXELFORMAT_YV12 ||
751  texture->format == SDL_PIXELFORMAT_IYUV) {
752  /* Need to add size for the U and V planes */
753  size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
754  }
755  if (texture->format == SDL_PIXELFORMAT_NV12 ||
756  texture->format == SDL_PIXELFORMAT_NV21) {
757  /* Need to add size for the U/V plane */
758  size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
759  }
760  data->pixels = SDL_calloc(1, size);
761  if (!data->pixels) {
762  SDL_free(data);
763  return SDL_OutOfMemory();
764  }
765  }
766 
767  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
768  data->fbo = GL_GetFBO(renderdata, texture->w, texture->h);
769  } else {
770  data->fbo = NULL;
771  }
772 
773  GL_CheckError("", renderer);
774  renderdata->glGenTextures(1, &data->texture);
775  if (GL_CheckError("glGenTextures()", renderer) < 0) {
776  if (data->pixels) {
777  SDL_free(data->pixels);
778  }
779  SDL_free(data);
780  return -1;
781  }
782  texture->driverdata = data;
783 
784  if (renderdata->GL_ARB_texture_non_power_of_two_supported) {
785  data->type = GL_TEXTURE_2D;
786  texture_w = texture->w;
787  texture_h = texture->h;
788  data->texw = 1.0f;
789  data->texh = 1.0f;
790  } else if (renderdata->GL_ARB_texture_rectangle_supported) {
791  data->type = GL_TEXTURE_RECTANGLE_ARB;
792  texture_w = texture->w;
793  texture_h = texture->h;
794  data->texw = (GLfloat) texture_w;
795  data->texh = (GLfloat) texture_h;
796  } else {
797  data->type = GL_TEXTURE_2D;
798  texture_w = power_of_2(texture->w);
799  texture_h = power_of_2(texture->h);
800  data->texw = (GLfloat) (texture->w) / texture_w;
801  data->texh = (GLfloat) texture->h / texture_h;
802  }
803 
804  data->format = format;
805  data->formattype = type;
806  scaleMode = GetScaleQuality();
807  renderdata->glEnable(data->type);
808  renderdata->glBindTexture(data->type, data->texture);
809  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
810  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
811  /* According to the spec, CLAMP_TO_EDGE is the default for TEXTURE_RECTANGLE
812  and setting it causes an INVALID_ENUM error in the latest NVidia drivers.
813  */
814  if (data->type != GL_TEXTURE_RECTANGLE_ARB) {
815  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
817  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
819  }
820 #ifdef __MACOSX__
821 #ifndef GL_TEXTURE_STORAGE_HINT_APPLE
822 #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
823 #endif
824 #ifndef STORAGE_CACHED_APPLE
825 #define STORAGE_CACHED_APPLE 0x85BE
826 #endif
827 #ifndef STORAGE_SHARED_APPLE
828 #define STORAGE_SHARED_APPLE 0x85BF
829 #endif
830  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
831  renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
833  } else {
834  renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
836  }
837  if (texture->access == SDL_TEXTUREACCESS_STREAMING
838  && texture->format == SDL_PIXELFORMAT_ARGB8888
839  && (texture->w % 8) == 0) {
840  renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
841  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
842  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
843  (data->pitch / SDL_BYTESPERPIXEL(texture->format)));
844  renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
845  texture_h, 0, format, type, data->pixels);
846  renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
847  }
848  else
849 #endif
850  {
851  renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
852  texture_h, 0, format, type, NULL);
853  }
854  renderdata->glDisable(data->type);
855  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
856  return -1;
857  }
858 
859  if (texture->format == SDL_PIXELFORMAT_YV12 ||
860  texture->format == SDL_PIXELFORMAT_IYUV) {
861  data->yuv = SDL_TRUE;
862 
863  renderdata->glGenTextures(1, &data->utexture);
864  renderdata->glGenTextures(1, &data->vtexture);
865  renderdata->glEnable(data->type);
866 
867  renderdata->glBindTexture(data->type, data->utexture);
868  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
869  scaleMode);
870  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
871  scaleMode);
872  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
874  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
876  renderdata->glTexImage2D(data->type, 0, internalFormat, (texture_w+1)/2,
877  (texture_h+1)/2, 0, format, type, NULL);
878 
879  renderdata->glBindTexture(data->type, data->vtexture);
880  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
881  scaleMode);
882  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
883  scaleMode);
884  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
886  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
888  renderdata->glTexImage2D(data->type, 0, internalFormat, (texture_w+1)/2,
889  (texture_h+1)/2, 0, format, type, NULL);
890 
891  renderdata->glDisable(data->type);
892  }
893 
894  if (texture->format == SDL_PIXELFORMAT_NV12 ||
895  texture->format == SDL_PIXELFORMAT_NV21) {
896  data->nv12 = SDL_TRUE;
897 
898  renderdata->glGenTextures(1, &data->utexture);
899  renderdata->glEnable(data->type);
900 
901  renderdata->glBindTexture(data->type, data->utexture);
902  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
903  scaleMode);
904  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
905  scaleMode);
906  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
908  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
910  renderdata->glTexImage2D(data->type, 0, GL_LUMINANCE_ALPHA, (texture_w+1)/2,
911  (texture_h+1)/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
912  renderdata->glDisable(data->type);
913  }
914 
915  return GL_CheckError("", renderer);
916 }
917 
918 static int
919 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
920  const SDL_Rect * rect, const void *pixels, int pitch)
921 {
922  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
923  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
924  const int texturebpp = SDL_BYTESPERPIXEL(texture->format);
925 
926  SDL_assert(texturebpp != 0); /* otherwise, division by zero later. */
927 
928  GL_ActivateRenderer(renderer);
929 
930  renderdata->glEnable(data->type);
931  renderdata->glBindTexture(data->type, data->texture);
932  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
933  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / texturebpp));
934  renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
935  rect->h, data->format, data->formattype,
936  pixels);
937  if (data->yuv) {
938  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
939 
940  /* Skip to the correct offset into the next texture */
941  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
942  if (texture->format == SDL_PIXELFORMAT_YV12) {
943  renderdata->glBindTexture(data->type, data->vtexture);
944  } else {
945  renderdata->glBindTexture(data->type, data->utexture);
946  }
947  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
948  (rect->w+1)/2, (rect->h+1)/2,
949  data->format, data->formattype, pixels);
950 
951  /* Skip to the correct offset into the next texture */
952  pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
953  if (texture->format == SDL_PIXELFORMAT_YV12) {
954  renderdata->glBindTexture(data->type, data->utexture);
955  } else {
956  renderdata->glBindTexture(data->type, data->vtexture);
957  }
958  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
959  (rect->w+1)/2, (rect->h+1)/2,
960  data->format, data->formattype, pixels);
961  }
962 
963  if (data->nv12) {
964  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
965 
966  /* Skip to the correct offset into the next texture */
967  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
968  renderdata->glBindTexture(data->type, data->utexture);
969  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
970  (rect->w + 1)/2, (rect->h + 1)/2,
972  }
973  renderdata->glDisable(data->type);
974 
975  return GL_CheckError("glTexSubImage2D()", renderer);
976 }
977 
978 static int
979 GL_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
980  const SDL_Rect * rect,
981  const Uint8 *Yplane, int Ypitch,
982  const Uint8 *Uplane, int Upitch,
983  const Uint8 *Vplane, int Vpitch)
984 {
985  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
986  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
987 
988  GL_ActivateRenderer(renderer);
989 
990  renderdata->glEnable(data->type);
991  renderdata->glBindTexture(data->type, data->texture);
992  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
993  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Ypitch);
994  renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
995  rect->h, data->format, data->formattype,
996  Yplane);
997 
998  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch);
999  renderdata->glBindTexture(data->type, data->utexture);
1000  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
1001  (rect->w + 1)/2, (rect->h + 1)/2,
1002  data->format, data->formattype, Uplane);
1003 
1004  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch);
1005  renderdata->glBindTexture(data->type, data->vtexture);
1006  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
1007  (rect->w + 1)/2, (rect->h + 1)/2,
1008  data->format, data->formattype, Vplane);
1009  renderdata->glDisable(data->type);
1010 
1011  return GL_CheckError("glTexSubImage2D()", renderer);
1012 }
1013 
1014 static int
1015 GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1016  const SDL_Rect * rect, void **pixels, int *pitch)
1017 {
1018  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
1019 
1020  data->locked_rect = *rect;
1021  *pixels =
1022  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
1023  rect->x * SDL_BYTESPERPIXEL(texture->format));
1024  *pitch = data->pitch;
1025  return 0;
1026 }
1027 
1028 static void
1029 GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1030 {
1031  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
1032  const SDL_Rect *rect;
1033  void *pixels;
1034 
1035  rect = &data->locked_rect;
1036  pixels =
1037  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
1038  rect->x * SDL_BYTESPERPIXEL(texture->format));
1039  GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
1040 }
1041 
1042 static int
1043 GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
1044 {
1045  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1046  GL_TextureData *texturedata;
1047  GLenum status;
1048 
1049  GL_ActivateRenderer(renderer);
1050 
1051  if (!data->GL_EXT_framebuffer_object_supported) {
1052  return SDL_SetError("Render targets not supported by OpenGL");
1053  }
1054 
1055  if (texture == NULL) {
1056  data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1057  return 0;
1058  }
1059 
1060  texturedata = (GL_TextureData *) texture->driverdata;
1061  data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texturedata->fbo->FBO);
1062  /* TODO: check if texture pixel format allows this operation */
1063  data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texturedata->type, texturedata->texture, 0);
1064  /* Check FBO status */
1065  status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1066  if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1067  return SDL_SetError("glFramebufferTexture2DEXT() failed");
1068  }
1069  return 0;
1070 }
1071 
1072 static int
1073 GL_UpdateViewport(SDL_Renderer * renderer)
1074 {
1075  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1076 
1077  if (SDL_CurrentContext != data->context) {
1078  /* We'll update the viewport after we rebind the context */
1079  return 0;
1080  }
1081 
1082  if (renderer->target) {
1083  data->glViewport(renderer->viewport.x, renderer->viewport.y,
1084  renderer->viewport.w, renderer->viewport.h);
1085  } else {
1086  int w, h;
1087 
1088  SDL_GL_GetDrawableSize(renderer->window, &w, &h);
1089  data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
1090  renderer->viewport.w, renderer->viewport.h);
1091  }
1092 
1093  data->glMatrixMode(GL_PROJECTION);
1094  data->glLoadIdentity();
1095  if (renderer->viewport.w && renderer->viewport.h) {
1096  if (renderer->target) {
1097  data->glOrtho((GLdouble) 0,
1098  (GLdouble) renderer->viewport.w,
1099  (GLdouble) 0,
1100  (GLdouble) renderer->viewport.h,
1101  0.0, 1.0);
1102  } else {
1103  data->glOrtho((GLdouble) 0,
1104  (GLdouble) renderer->viewport.w,
1105  (GLdouble) renderer->viewport.h,
1106  (GLdouble) 0,
1107  0.0, 1.0);
1108  }
1109  }
1110  data->glMatrixMode(GL_MODELVIEW);
1111 
1112  return GL_CheckError("", renderer);
1113 }
1114 
1115 static int
1116 GL_UpdateClipRect(SDL_Renderer * renderer)
1117 {
1118  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1119 
1120  if (renderer->clipping_enabled) {
1121  const SDL_Rect *rect = &renderer->clip_rect;
1122  data->glEnable(GL_SCISSOR_TEST);
1123  if (renderer->target) {
1124  data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h);
1125  } else {
1126  int w, h;
1127 
1128  SDL_GL_GetDrawableSize(renderer->window, &w, &h);
1129  data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
1130  }
1131  } else {
1132  data->glDisable(GL_SCISSOR_TEST);
1133  }
1134  return 0;
1135 }
1136 
1137 static void
1138 GL_SetShader(GL_RenderData * data, GL_Shader shader)
1139 {
1140  if (data->shaders && shader != data->current.shader) {
1141  GL_SelectShader(data->shaders, shader);
1142  data->current.shader = shader;
1143  }
1144 }
1145 
1146 static void
1147 GL_SetColor(GL_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1148 {
1149  Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
1150 
1151  if (color != data->current.color) {
1152  data->glColor4f((GLfloat) r * inv255f,
1153  (GLfloat) g * inv255f,
1154  (GLfloat) b * inv255f,
1155  (GLfloat) a * inv255f);
1156  data->current.color = color;
1157  }
1158 }
1159 
1160 static void
1161 GL_SetBlendMode(GL_RenderData * data, SDL_BlendMode blendMode)
1162 {
1163  if (blendMode != data->current.blendMode) {
1164  if (blendMode == SDL_BLENDMODE_NONE) {
1165  data->glDisable(GL_BLEND);
1166  } else {
1167  data->glEnable(GL_BLEND);
1168  data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
1169  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
1170  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
1171  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
1172  data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
1173  }
1174  data->current.blendMode = blendMode;
1175  }
1176 }
1177 
1178 static void
1179 GL_SetDrawingState(SDL_Renderer * renderer)
1180 {
1181  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1182 
1183  GL_ActivateRenderer(renderer);
1184 
1185  GL_SetColor(data, renderer->r,
1186  renderer->g,
1187  renderer->b,
1188  renderer->a);
1189 
1190  GL_SetBlendMode(data, renderer->blendMode);
1191 
1192  GL_SetShader(data, SHADER_SOLID);
1193 }
1194 
1195 static int
1196 GL_RenderClear(SDL_Renderer * renderer)
1197 {
1198  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1199 
1200  GL_ActivateRenderer(renderer);
1201 
1202  data->glClearColor((GLfloat) renderer->r * inv255f,
1203  (GLfloat) renderer->g * inv255f,
1204  (GLfloat) renderer->b * inv255f,
1205  (GLfloat) renderer->a * inv255f);
1206 
1207  if (renderer->clipping_enabled) {
1208  data->glDisable(GL_SCISSOR_TEST);
1209  }
1210 
1211  data->glClear(GL_COLOR_BUFFER_BIT);
1212 
1213  if (renderer->clipping_enabled) {
1214  data->glEnable(GL_SCISSOR_TEST);
1215  }
1216 
1217  return 0;
1218 }
1219 
1220 static int
1221 GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
1222  int count)
1223 {
1224  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1225  int i;
1226 
1227  GL_SetDrawingState(renderer);
1228 
1229  data->glBegin(GL_POINTS);
1230  for (i = 0; i < count; ++i) {
1231  data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
1232  }
1233  data->glEnd();
1234 
1235  return 0;
1236 }
1237 
1238 static int
1239 GL_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
1240  int count)
1241 {
1242  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1243  int i;
1244 
1245  GL_SetDrawingState(renderer);
1246 
1247  if (count > 2 &&
1248  points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
1249  data->glBegin(GL_LINE_LOOP);
1250  /* GL_LINE_LOOP takes care of the final segment */
1251  --count;
1252  for (i = 0; i < count; ++i) {
1253  data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
1254  }
1255  data->glEnd();
1256  } else {
1257 #if defined(__MACOSX__) || defined(__WIN32__)
1258 #else
1259  int x1, y1, x2, y2;
1260 #endif
1261 
1262  data->glBegin(GL_LINE_STRIP);
1263  for (i = 0; i < count; ++i) {
1264  data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
1265  }
1266  data->glEnd();
1267 
1268  /* The line is half open, so we need one more point to complete it.
1269  * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
1270  * If we have to, we can use vertical line and horizontal line textures
1271  * for vertical and horizontal lines, and then create custom textures
1272  * for diagonal lines and software render those. It's terrible, but at
1273  * least it would be pixel perfect.
1274  */
1275  data->glBegin(GL_POINTS);
1276 #if defined(__MACOSX__) || defined(__WIN32__)
1277  /* Mac OS X and Windows seem to always leave the last point open */
1278  data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
1279 #else
1280  /* Linux seems to leave the right-most or bottom-most point open */
1281  x1 = points[0].x;
1282  y1 = points[0].y;
1283  x2 = points[count-1].x;
1284  y2 = points[count-1].y;
1285 
1286  if (x1 > x2) {
1287  data->glVertex2f(0.5f + x1, 0.5f + y1);
1288  } else if (x2 > x1) {
1289  data->glVertex2f(0.5f + x2, 0.5f + y2);
1290  }
1291  if (y1 > y2) {
1292  data->glVertex2f(0.5f + x1, 0.5f + y1);
1293  } else if (y2 > y1) {
1294  data->glVertex2f(0.5f + x2, 0.5f + y2);
1295  }
1296 #endif
1297  data->glEnd();
1298  }
1299  return GL_CheckError("", renderer);
1300 }
1301 
1302 static int
1303 GL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
1304 {
1305  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1306  int i;
1307 
1308  GL_SetDrawingState(renderer);
1309 
1310  for (i = 0; i < count; ++i) {
1311  const SDL_FRect *rect = &rects[i];
1312 
1313  data->glRectf(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
1314  }
1315  return GL_CheckError("", renderer);
1316 }
1317 
1318 static int
1319 GL_SetupCopy(SDL_Renderer * renderer, SDL_Texture * texture)
1320 {
1321  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1322  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1323 
1324  data->glEnable(texturedata->type);
1325  if (texturedata->yuv) {
1326  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1327  data->glBindTexture(texturedata->type, texturedata->vtexture);
1328 
1329  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1330  data->glBindTexture(texturedata->type, texturedata->utexture);
1331 
1332  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1333  }
1334  if (texturedata->nv12) {
1335  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1336  data->glBindTexture(texturedata->type, texturedata->utexture);
1337 
1338  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1339  }
1340  data->glBindTexture(texturedata->type, texturedata->texture);
1341 
1342  if (texture->modMode) {
1343  GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
1344  } else {
1345  GL_SetColor(data, 255, 255, 255, 255);
1346  }
1347 
1348  GL_SetBlendMode(data, texture->blendMode);
1349 
1350  if (texturedata->yuv || texturedata->nv12) {
1351  switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
1353  if (texturedata->yuv) {
1354  GL_SetShader(data, SHADER_YUV_JPEG);
1355  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1356  GL_SetShader(data, SHADER_NV12_JPEG);
1357  } else {
1358  GL_SetShader(data, SHADER_NV21_JPEG);
1359  }
1360  break;
1362  if (texturedata->yuv) {
1363  GL_SetShader(data, SHADER_YUV_BT601);
1364  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1365  GL_SetShader(data, SHADER_NV12_BT601);
1366  } else {
1367  GL_SetShader(data, SHADER_NV21_BT601);
1368  }
1369  break;
1371  if (texturedata->yuv) {
1372  GL_SetShader(data, SHADER_YUV_BT709);
1373  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1374  GL_SetShader(data, SHADER_NV12_BT709);
1375  } else {
1376  GL_SetShader(data, SHADER_NV21_BT709);
1377  }
1378  break;
1379  default:
1380  return SDL_SetError("Unsupported YUV conversion mode");
1381  }
1382  } else {
1383  GL_SetShader(data, SHADER_RGB);
1384  }
1385  return 0;
1386 }
1387 
1388 static int
1389 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1390  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1391 {
1392  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1393  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1394  GLfloat minx, miny, maxx, maxy;
1395  GLfloat minu, maxu, minv, maxv;
1396 
1397  GL_ActivateRenderer(renderer);
1398 
1399  if (GL_SetupCopy(renderer, texture) < 0) {
1400  return -1;
1401  }
1402 
1403  minx = dstrect->x;
1404  miny = dstrect->y;
1405  maxx = dstrect->x + dstrect->w;
1406  maxy = dstrect->y + dstrect->h;
1407 
1408  minu = (GLfloat) srcrect->x / texture->w;
1409  minu *= texturedata->texw;
1410  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
1411  maxu *= texturedata->texw;
1412  minv = (GLfloat) srcrect->y / texture->h;
1413  minv *= texturedata->texh;
1414  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
1415  maxv *= texturedata->texh;
1416 
1417  data->glBegin(GL_TRIANGLE_STRIP);
1418  data->glTexCoord2f(minu, minv);
1419  data->glVertex2f(minx, miny);
1420  data->glTexCoord2f(maxu, minv);
1421  data->glVertex2f(maxx, miny);
1422  data->glTexCoord2f(minu, maxv);
1423  data->glVertex2f(minx, maxy);
1424  data->glTexCoord2f(maxu, maxv);
1425  data->glVertex2f(maxx, maxy);
1426  data->glEnd();
1427 
1428  data->glDisable(texturedata->type);
1429 
1430  return GL_CheckError("", renderer);
1431 }
1432 
1433 static int
1434 GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1435  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1436  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1437 {
1438  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1439  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1440  GLfloat minx, miny, maxx, maxy;
1441  GLfloat centerx, centery;
1442  GLfloat minu, maxu, minv, maxv;
1443 
1444  GL_ActivateRenderer(renderer);
1445 
1446  if (GL_SetupCopy(renderer, texture) < 0) {
1447  return -1;
1448  }
1449 
1450  centerx = center->x;
1451  centery = center->y;
1452 
1453  if (flip & SDL_FLIP_HORIZONTAL) {
1454  minx = dstrect->w - centerx;
1455  maxx = -centerx;
1456  }
1457  else {
1458  minx = -centerx;
1459  maxx = dstrect->w - centerx;
1460  }
1461 
1462  if (flip & SDL_FLIP_VERTICAL) {
1463  miny = dstrect->h - centery;
1464  maxy = -centery;
1465  }
1466  else {
1467  miny = -centery;
1468  maxy = dstrect->h - centery;
1469  }
1470 
1471  minu = (GLfloat) srcrect->x / texture->w;
1472  minu *= texturedata->texw;
1473  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
1474  maxu *= texturedata->texw;
1475  minv = (GLfloat) srcrect->y / texture->h;
1476  minv *= texturedata->texh;
1477  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
1478  maxv *= texturedata->texh;
1479 
1480  /* Translate to flip, rotate, translate to position */
1481  data->glPushMatrix();
1482  data->glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0);
1483  data->glRotated(angle, (GLdouble)0.0, (GLdouble)0.0, (GLdouble)1.0);
1484 
1485  data->glBegin(GL_TRIANGLE_STRIP);
1486  data->glTexCoord2f(minu, minv);
1487  data->glVertex2f(minx, miny);
1488  data->glTexCoord2f(maxu, minv);
1489  data->glVertex2f(maxx, miny);
1490  data->glTexCoord2f(minu, maxv);
1491  data->glVertex2f(minx, maxy);
1492  data->glTexCoord2f(maxu, maxv);
1493  data->glVertex2f(maxx, maxy);
1494  data->glEnd();
1495  data->glPopMatrix();
1496 
1497  data->glDisable(texturedata->type);
1498 
1499  return GL_CheckError("", renderer);
1500 }
1501 
1502 static int
1503 GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1504  Uint32 pixel_format, void * pixels, int pitch)
1505 {
1506  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1507  Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ARGB8888;
1508  void *temp_pixels;
1509  int temp_pitch;
1510  GLint internalFormat;
1511  GLenum format, type;
1512  Uint8 *src, *dst, *tmp;
1513  int w, h, length, rows;
1514  int status;
1515 
1516  GL_ActivateRenderer(renderer);
1517 
1518  if (!convert_format(data, temp_format, &internalFormat, &format, &type)) {
1519  return SDL_SetError("Texture format %s not supported by OpenGL",
1520  SDL_GetPixelFormatName(temp_format));
1521  }
1522 
1523  if (!rect->w || !rect->h) {
1524  return 0; /* nothing to do. */
1525  }
1526 
1527  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1528  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1529  if (!temp_pixels) {
1530  return SDL_OutOfMemory();
1531  }
1532 
1533  SDL_GetRendererOutputSize(renderer, &w, &h);
1534 
1535  data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1536  data->glPixelStorei(GL_PACK_ROW_LENGTH,
1537  (temp_pitch / SDL_BYTESPERPIXEL(temp_format)));
1538 
1539  data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
1540  rect->w, rect->h, format, type, temp_pixels);
1541 
1542  if (GL_CheckError("glReadPixels()", renderer) < 0) {
1543  SDL_free(temp_pixels);
1544  return -1;
1545  }
1546 
1547  /* Flip the rows to be top-down if necessary */
1548  if (!renderer->target) {
1549  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1550  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1551  dst = (Uint8*)temp_pixels;
1552  tmp = SDL_stack_alloc(Uint8, length);
1553  rows = rect->h / 2;
1554  while (rows--) {
1555  SDL_memcpy(tmp, dst, length);
1556  SDL_memcpy(dst, src, length);
1557  SDL_memcpy(src, tmp, length);
1558  dst += temp_pitch;
1559  src -= temp_pitch;
1560  }
1561  SDL_stack_free(tmp);
1562  }
1563 
1564  status = SDL_ConvertPixels(rect->w, rect->h,
1565  temp_format, temp_pixels, temp_pitch,
1566  pixel_format, pixels, pitch);
1567  SDL_free(temp_pixels);
1568 
1569  return status;
1570 }
1571 
1572 static void
1573 GL_RenderPresent(SDL_Renderer * renderer)
1574 {
1575  GL_ActivateRenderer(renderer);
1576 
1577  SDL_GL_SwapWindow(renderer->window);
1578 }
1579 
1580 static void
1581 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1582 {
1583  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
1584  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
1585 
1586  GL_ActivateRenderer(renderer);
1587 
1588  if (!data) {
1589  return;
1590  }
1591  if (data->texture) {
1592  renderdata->glDeleteTextures(1, &data->texture);
1593  }
1594  if (data->yuv) {
1595  renderdata->glDeleteTextures(1, &data->utexture);
1596  renderdata->glDeleteTextures(1, &data->vtexture);
1597  }
1598  SDL_free(data->pixels);
1599  SDL_free(data);
1600  texture->driverdata = NULL;
1601 }
1602 
1603 static void
1604 GL_DestroyRenderer(SDL_Renderer * renderer)
1605 {
1606  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1607 
1608  if (data) {
1609  if (data->context != NULL) {
1610  /* make sure we delete the right resources! */
1611  GL_ActivateRenderer(renderer);
1612  }
1613 
1614  GL_ClearErrors(renderer);
1615  if (data->GL_ARB_debug_output_supported) {
1616  PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
1617 
1618  /* Uh oh, we don't have a safe way of removing ourselves from the callback chain, if it changed after we set our callback. */
1619  /* For now, just always replace the callback with the original one */
1620  glDebugMessageCallbackARBFunc(data->next_error_callback, data->next_error_userparam);
1621  }
1622  if (data->shaders) {
1623  GL_DestroyShaderContext(data->shaders);
1624  }
1625  if (data->context) {
1626  while (data->framebuffers) {
1627  GL_FBOList *nextnode = data->framebuffers->next;
1628  /* delete the framebuffer object */
1629  data->glDeleteFramebuffersEXT(1, &data->framebuffers->FBO);
1630  GL_CheckError("", renderer);
1631  SDL_free(data->framebuffers);
1632  data->framebuffers = nextnode;
1633  }
1634  SDL_GL_DeleteContext(data->context);
1635  }
1636  SDL_free(data);
1637  }
1638  SDL_free(renderer);
1639 }
1640 
1641 static int
1642 GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
1643 {
1644  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1645  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1646  GL_ActivateRenderer(renderer);
1647 
1648  data->glEnable(texturedata->type);
1649  if (texturedata->yuv) {
1650  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1651  data->glBindTexture(texturedata->type, texturedata->vtexture);
1652 
1653  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1654  data->glBindTexture(texturedata->type, texturedata->utexture);
1655 
1656  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1657  }
1658  data->glBindTexture(texturedata->type, texturedata->texture);
1659 
1660  if(texw) *texw = (float)texturedata->texw;
1661  if(texh) *texh = (float)texturedata->texh;
1662 
1663  return 0;
1664 }
1665 
1666 static int
1667 GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
1668 {
1669  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1670  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1671  GL_ActivateRenderer(renderer);
1672 
1673  if (texturedata->yuv) {
1674  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1675  data->glDisable(texturedata->type);
1676 
1677  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1678  data->glDisable(texturedata->type);
1679 
1680  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1681  }
1682 
1683  data->glDisable(texturedata->type);
1684 
1685  return 0;
1686 }
1687 
1688 #endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */
1689 
1690 /* vi: set ts=4 sw=4 expandtab: */
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2193
SDL_BlendFactor
The normalized factor used to multiply pixel components.
Definition: SDL_blendmode.h:75
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
#define GL_ONE
Definition: SDL_opengl.h:401
#define GL_STACK_UNDERFLOW
Definition: SDL_opengl.h:724
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:57
#define SDL_GL_ExtensionSupported
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
#define GL_INVALID_ENUM
Definition: SDL_opengl.h:720
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_sysrender.h:98
#define GL_FALSE
Definition: SDL_opengl.h:199
#define GL_STORAGE_CACHED_APPLE
#define GL_UNPACK_CLIENT_STORAGE_APPLE
GLuint GLfloat GLfloat GLfloat x1
GL_ShaderContext * GL_CreateShaderContext(void)
void(APIENTRY * GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
#define GL_INVALID_OPERATION
Definition: SDL_opengl.h:722
GLuint64EXT * result
#define GL_SCISSOR_TEST
Definition: SDL_opengl.h:615
#define GL_UNSIGNED_INT_8_8_8_8_REV
Definition: SDL_opengl.h:1521
#define SDL_GL_CreateContext
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
const GLuint * framebuffers
SDL_RendererInfo info
#define GL_TEXTURE0_ARB
Definition: SDL_opengl.h:1990
GLenum GLenum dst
#define GL_TRUE
Definition: SDL_opengl.h:200
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
#define GL_YCBCR_422_APPLE
GLuint GLsizei const GLchar * message
#define GL_DEBUG_CALLBACK_USER_PARAM_ARB
#define GL_PROJECTION
Definition: SDL_opengl.h:272
#define GL_TEXTURE2_ARB
Definition: SDL_opengl.h:1992
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Definition: SDL_sysrender.h:82
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Rect rect
Definition: testrelative.c:27
#define GL_LINEAR
Definition: SDL_opengl.h:447
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
Definition: SDL_hints.h:143
#define GL_CLAMP_TO_EDGE
Definition: SDL_opengl.h:1507
GLfloat GLfloat GLfloat GLfloat h
#define GL_RGBA8
Definition: SDL_opengl.h:788
void * driverdata
GLfixed GLfixed GLfixed y2
#define APIENTRY
Definition: SDL_opengl.h:139
int GLint
Definition: SDL_opengl.h:182
Uint32 texture_formats[16]
Definition: SDL_render.h:83
static screen_context_t context
Definition: video.c:25
SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2221
#define SDL_GetHint
#define SDL_GetWindowFlags
#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
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2207
GLfloat f
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
#define GL_TEXTURE_MAG_FILTER
Definition: SDL_opengl.h:674
#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
GLsizei GLsizei GLuint * shaders
#define GL_TEXTURE_STORAGE_HINT_APPLE
SDL_RenderDriver GL_RenderDriver
SDL_Rect clip_rect
#define GL_TRIANGLE_STRIP
Definition: SDL_opengl.h:221
uint32_t Uint32
Definition: SDL_stdinc.h:181
float GLfloat
Definition: SDL_opengl.h:187
#define SDL_realloc
#define SDL_strcasecmp
GLenum src
struct GL_ShaderContext GL_ShaderContext
int max_texture_height
Definition: SDL_render.h:85
#define GL_MAX_TEXTURE_UNITS_ARB
Definition: SDL_opengl.h:2024
#define GL_ONE_MINUS_SRC_ALPHA
Definition: SDL_opengl.h:405
SDL_BlendOperation
The blend operation used when combining source and destination pixel components.
Definition: SDL_blendmode.h:62
#define GL_UNPACK_ROW_LENGTH
Definition: SDL_opengl.h:660
#define SDL_FORCE_INLINE
Definition: begin_code.h:144
#define GL_LUMINANCE
Definition: SDL_opengl.h:510
SDL_Window * window
SDL_RendererInfo info
#define GL_ONE_MINUS_SRC_COLOR
Definition: SDL_opengl.h:403
GLfixed GLfixed x2
int(* RenderClear)(SDL_Renderer *renderer)
#define GL_FRAMEBUFFER_COMPLETE_EXT
void(* DestroyRenderer)(SDL_Renderer *renderer)
GLfixed GLfixed GLint GLint GLfixed points
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
Definition: SDL_sysrender.h:81
#define GL_PACK_ROW_LENGTH
Definition: SDL_opengl.h:654
#define GL_TEXTURE_RECTANGLE_ARB
#define SDL_GetHintBoolean
GLfixed y1
#define GL_PACK_ALIGNMENT
Definition: SDL_opengl.h:652
void GL_DestroyShaderContext(GL_ShaderContext *ctx)
#define SDL_LogError
#define GL_MAX_TEXTURE_SIZE
Definition: SDL_opengl.h:536
#define GL_NO_ERROR
Definition: SDL_opengl.h:719
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
#define GL_BLEND
Definition: SDL_opengl.h:397
#define GL_TABLE_TOO_LARGE
Definition: SDL_opengl.h:1648
#define GL_SRC_COLOR
Definition: SDL_opengl.h:402
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:90
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)
Definition: SDL_sysrender.h:93
#define SDL_GL_SetAttribute
#define SDL_GL_GetDrawableSize
#define GL_ONE_MINUS_DST_ALPHA
Definition: SDL_opengl.h:407
#define SDL_memcpy
GLenum GLenum GLuint texture
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2228
#define SDL_LogDebug
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:175
#define SDL_GL_GetSwapInterval
GL_Shader
GLenum GLenum GLenum input
SDL_Texture * target
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1542
#define GL_STACK_OVERFLOW
Definition: SDL_opengl.h:723
static int GetScaleQuality(void)
static SDL_Renderer * renderer
GLenum GLenum severity
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
struct _cl_event * event
SDL_BlendMode blendMode
#define SDL_GL_SetSwapInterval
#define SDL_GL_GetProcAddress
#define GL_LINE_STRIP
Definition: SDL_opengl.h:219
#define GL_COLOR_ATTACHMENT0_EXT
#define GL_TEXTURE_WRAP_T
Definition: SDL_opengl.h:673
#define GL_LINE_LOOP
Definition: SDL_opengl.h:218
#define GL_LUMINANCE_ALPHA
Definition: SDL_opengl.h:511
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
#define GL_TEXTURE_2D
Definition: SDL_opengl.h:671
GLubyte GLubyte GLubyte GLubyte w
GLsizei const GLfloat * value
#define GL_UNSIGNED_BYTE
Definition: SDL_opengl.h:204
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
GLsizei GLsizei GLchar * source
#define GL_DEBUG_CALLBACK_FUNCTION_ARB
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
#define GL_DST_COLOR
Definition: SDL_opengl.h:408
int x
Definition: SDL_rect.h:66
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
#define GL_TEXTURE1_ARB
Definition: SDL_opengl.h:1991
int(* UpdateViewport)(SDL_Renderer *renderer)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
#define GL_COLOR_BUFFER_BIT
Definition: SDL_opengl.h:742
#define GL_INVALID_VALUE
Definition: SDL_opengl.h:721
int w
Definition: SDL_rect.h:67
#define GL_RGB8
Definition: SDL_opengl.h:781
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define GL_STORAGE_SHARED_APPLE
GLsizeiptr size
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Window state change event data (event.window.*)
Definition: SDL_events.h:174
#define SDL_assert(condition)
Definition: SDL_assert.h:169
unsigned int GLenum
Definition: SDL_opengl.h:176
GLenum internalFormat
#define GL_POINTS
Definition: SDL_opengl.h:216
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
#define GL_CULL_FACE
Definition: SDL_opengl.h:302
#define GL_MODELVIEW
Definition: SDL_opengl.h:271
#define SDL_GL_GetCurrentContext
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2214
void GLvoid
Definition: SDL_opengl.h:179
unsigned int GLuint
Definition: SDL_opengl.h:185
#define SDL_SetError
#define GL_OUT_OF_MEMORY
Definition: SDL_opengl.h:725
GLbitfield flags
GLAPI void GLAPIENTRY glActiveTextureARB(GLenum texture)
int(* RenderCopyEx)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
#define SDL_calloc
#define SDL_GL_MakeCurrent
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
#define SDL_GetRendererOutputSize
#define GL_FUNC_REVERSE_SUBTRACT
Definition: SDL_opengl.h:1654
#define SDL_LogInfo
SDL_Rect viewport
int h
Definition: SDL_rect.h:67
#define SDL_strdup
The type used to identify a window.
Definition: SDL_sysvideo.h:73
#define GL_ZERO
Definition: SDL_opengl.h:400
#define GL_ONE_MINUS_DST_COLOR
Definition: SDL_opengl.h:409
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2200
GLuint color
#define GL_SRC_ALPHA
Definition: SDL_opengl.h:404
#define GL_NEAREST
Definition: SDL_opengl.h:704
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:80
GLfloat angle
#define GL_FUNC_SUBTRACT
Definition: SDL_opengl.h:1653
Uint32 num_texture_formats
Definition: SDL_render.h:82
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
Uint32 format
Definition: SDL_sysrender.h:52
#define GL_DST_ALPHA
Definition: SDL_opengl.h:406
void * driverdata
Definition: SDL_sysrender.h:69
#define GL_DEPTH_TEST
Definition: SDL_opengl.h:327
#define SDL_malloc
#define SDL_GL_GetAttribute
#define SDL_ConvertPixels
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define GL_UNSIGNED_SHORT_8_8_APPLE
int GLsizei
Definition: SDL_opengl.h:186
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:83
void(* RenderPresent)(SDL_Renderer *renderer)
double GLdouble
Definition: SDL_opengl.h:189
#define SDL_GL_DeleteContext
EGLSurface EGLint * rects
Definition: eglext.h:282
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
#define SDL_GetYUVConversionModeForResolution
#define GL_TEXTURE_WRAP_S
Definition: SDL_opengl.h:672
GLuint GLsizei GLsizei * length
#define GL_TEXTURE_MIN_FILTER
Definition: SDL_opengl.h:675
GLboolean GLboolean GLboolean GLboolean a
#define GL_UNPACK_ALIGNMENT
Definition: SDL_opengl.h:658
#define GL_FUNC_ADD
Definition: SDL_opengl.h:1652
int(* UpdateClipRect)(SDL_Renderer *renderer)
#define GL_DEBUG_TYPE_ERROR_ARB
const void * userParam
GLboolean GLboolean g
GLboolean GLboolean GLboolean b
int y
Definition: SDL_rect.h:66
#define SDL_GL_SwapWindow
void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader)
SDL_bool clipping_enabled
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
GLuint shader
#define GL_BGRA
Definition: SDL_opengl.h:1511
#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
#define GL_FRAMEBUFFER_EXT
#define SDL_GetPixelFormatName