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 int
707 GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
708 {
709  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
710  GL_TextureData *data;
711  GLint internalFormat;
712  GLenum format, type;
713  int texture_w, texture_h;
714  GLenum scaleMode;
715 
716  GL_ActivateRenderer(renderer);
717 
718  if (texture->access == SDL_TEXTUREACCESS_TARGET &&
719  !renderdata->GL_EXT_framebuffer_object_supported) {
720  return SDL_SetError("Render targets not supported by OpenGL");
721  }
722 
723  if (!convert_format(renderdata, texture->format, &internalFormat,
724  &format, &type)) {
725  return SDL_SetError("Texture format %s not supported by OpenGL",
726  SDL_GetPixelFormatName(texture->format));
727  }
728 
729  data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
730  if (!data) {
731  return SDL_OutOfMemory();
732  }
733 
734  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
735  size_t size;
736  data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
737  size = texture->h * data->pitch;
738  if (texture->format == SDL_PIXELFORMAT_YV12 ||
739  texture->format == SDL_PIXELFORMAT_IYUV) {
740  /* Need to add size for the U and V planes */
741  size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
742  }
743  if (texture->format == SDL_PIXELFORMAT_NV12 ||
744  texture->format == SDL_PIXELFORMAT_NV21) {
745  /* Need to add size for the U/V plane */
746  size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
747  }
748  data->pixels = SDL_calloc(1, size);
749  if (!data->pixels) {
750  SDL_free(data);
751  return SDL_OutOfMemory();
752  }
753  }
754 
755  if (texture->access == SDL_TEXTUREACCESS_TARGET) {
756  data->fbo = GL_GetFBO(renderdata, texture->w, texture->h);
757  } else {
758  data->fbo = NULL;
759  }
760 
761  GL_CheckError("", renderer);
762  renderdata->glGenTextures(1, &data->texture);
763  if (GL_CheckError("glGenTextures()", renderer) < 0) {
764  if (data->pixels) {
765  SDL_free(data->pixels);
766  }
767  SDL_free(data);
768  return -1;
769  }
770  texture->driverdata = data;
771 
772  if (renderdata->GL_ARB_texture_non_power_of_two_supported) {
773  data->type = GL_TEXTURE_2D;
774  texture_w = texture->w;
775  texture_h = texture->h;
776  data->texw = 1.0f;
777  data->texh = 1.0f;
778  } else if (renderdata->GL_ARB_texture_rectangle_supported) {
779  data->type = GL_TEXTURE_RECTANGLE_ARB;
780  texture_w = texture->w;
781  texture_h = texture->h;
782  data->texw = (GLfloat) texture_w;
783  data->texh = (GLfloat) texture_h;
784  } else {
785  data->type = GL_TEXTURE_2D;
786  texture_w = power_of_2(texture->w);
787  texture_h = power_of_2(texture->h);
788  data->texw = (GLfloat) (texture->w) / texture_w;
789  data->texh = (GLfloat) texture->h / texture_h;
790  }
791 
792  data->format = format;
793  data->formattype = type;
794  scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
795  renderdata->glEnable(data->type);
796  renderdata->glBindTexture(data->type, data->texture);
797  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
798  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
799  /* According to the spec, CLAMP_TO_EDGE is the default for TEXTURE_RECTANGLE
800  and setting it causes an INVALID_ENUM error in the latest NVidia drivers.
801  */
802  if (data->type != GL_TEXTURE_RECTANGLE_ARB) {
803  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
805  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
807  }
808 #ifdef __MACOSX__
809 #ifndef GL_TEXTURE_STORAGE_HINT_APPLE
810 #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
811 #endif
812 #ifndef STORAGE_CACHED_APPLE
813 #define STORAGE_CACHED_APPLE 0x85BE
814 #endif
815 #ifndef STORAGE_SHARED_APPLE
816 #define STORAGE_SHARED_APPLE 0x85BF
817 #endif
818  if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
819  renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
821  } else {
822  renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
824  }
825  if (texture->access == SDL_TEXTUREACCESS_STREAMING
826  && texture->format == SDL_PIXELFORMAT_ARGB8888
827  && (texture->w % 8) == 0) {
828  renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
829  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
830  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
831  (data->pitch / SDL_BYTESPERPIXEL(texture->format)));
832  renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
833  texture_h, 0, format, type, data->pixels);
834  renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
835  }
836  else
837 #endif
838  {
839  renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
840  texture_h, 0, format, type, NULL);
841  }
842  renderdata->glDisable(data->type);
843  if (GL_CheckError("glTexImage2D()", renderer) < 0) {
844  return -1;
845  }
846 
847  if (texture->format == SDL_PIXELFORMAT_YV12 ||
848  texture->format == SDL_PIXELFORMAT_IYUV) {
849  data->yuv = SDL_TRUE;
850 
851  renderdata->glGenTextures(1, &data->utexture);
852  renderdata->glGenTextures(1, &data->vtexture);
853  renderdata->glEnable(data->type);
854 
855  renderdata->glBindTexture(data->type, data->utexture);
856  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
857  scaleMode);
858  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
859  scaleMode);
860  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
862  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
864  renderdata->glTexImage2D(data->type, 0, internalFormat, (texture_w+1)/2,
865  (texture_h+1)/2, 0, format, type, NULL);
866 
867  renderdata->glBindTexture(data->type, data->vtexture);
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->glDisable(data->type);
880  }
881 
882  if (texture->format == SDL_PIXELFORMAT_NV12 ||
883  texture->format == SDL_PIXELFORMAT_NV21) {
884  data->nv12 = SDL_TRUE;
885 
886  renderdata->glGenTextures(1, &data->utexture);
887  renderdata->glEnable(data->type);
888 
889  renderdata->glBindTexture(data->type, data->utexture);
890  renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
891  scaleMode);
892  renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
893  scaleMode);
894  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
896  renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
898  renderdata->glTexImage2D(data->type, 0, GL_LUMINANCE_ALPHA, (texture_w+1)/2,
899  (texture_h+1)/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
900  renderdata->glDisable(data->type);
901  }
902 
903  return GL_CheckError("", renderer);
904 }
905 
906 static int
907 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
908  const SDL_Rect * rect, const void *pixels, int pitch)
909 {
910  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
911  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
912  const int texturebpp = SDL_BYTESPERPIXEL(texture->format);
913 
914  SDL_assert(texturebpp != 0); /* otherwise, division by zero later. */
915 
916  GL_ActivateRenderer(renderer);
917 
918  renderdata->glEnable(data->type);
919  renderdata->glBindTexture(data->type, data->texture);
920  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
921  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / texturebpp));
922  renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
923  rect->h, data->format, data->formattype,
924  pixels);
925  if (data->yuv) {
926  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
927 
928  /* Skip to the correct offset into the next texture */
929  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
930  if (texture->format == SDL_PIXELFORMAT_YV12) {
931  renderdata->glBindTexture(data->type, data->vtexture);
932  } else {
933  renderdata->glBindTexture(data->type, data->utexture);
934  }
935  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
936  (rect->w+1)/2, (rect->h+1)/2,
937  data->format, data->formattype, pixels);
938 
939  /* Skip to the correct offset into the next texture */
940  pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
941  if (texture->format == SDL_PIXELFORMAT_YV12) {
942  renderdata->glBindTexture(data->type, data->utexture);
943  } else {
944  renderdata->glBindTexture(data->type, data->vtexture);
945  }
946  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
947  (rect->w+1)/2, (rect->h+1)/2,
948  data->format, data->formattype, pixels);
949  }
950 
951  if (data->nv12) {
952  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
953 
954  /* Skip to the correct offset into the next texture */
955  pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
956  renderdata->glBindTexture(data->type, data->utexture);
957  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
958  (rect->w + 1)/2, (rect->h + 1)/2,
960  }
961  renderdata->glDisable(data->type);
962 
963  return GL_CheckError("glTexSubImage2D()", renderer);
964 }
965 
966 static int
967 GL_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
968  const SDL_Rect * rect,
969  const Uint8 *Yplane, int Ypitch,
970  const Uint8 *Uplane, int Upitch,
971  const Uint8 *Vplane, int Vpitch)
972 {
973  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
974  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
975 
976  GL_ActivateRenderer(renderer);
977 
978  renderdata->glEnable(data->type);
979  renderdata->glBindTexture(data->type, data->texture);
980  renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
981  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Ypitch);
982  renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
983  rect->h, data->format, data->formattype,
984  Yplane);
985 
986  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch);
987  renderdata->glBindTexture(data->type, data->utexture);
988  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
989  (rect->w + 1)/2, (rect->h + 1)/2,
990  data->format, data->formattype, Uplane);
991 
992  renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch);
993  renderdata->glBindTexture(data->type, data->vtexture);
994  renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
995  (rect->w + 1)/2, (rect->h + 1)/2,
996  data->format, data->formattype, Vplane);
997  renderdata->glDisable(data->type);
998 
999  return GL_CheckError("glTexSubImage2D()", renderer);
1000 }
1001 
1002 static int
1003 GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
1004  const SDL_Rect * rect, void **pixels, int *pitch)
1005 {
1006  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
1007 
1008  data->locked_rect = *rect;
1009  *pixels =
1010  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
1011  rect->x * SDL_BYTESPERPIXEL(texture->format));
1012  *pitch = data->pitch;
1013  return 0;
1014 }
1015 
1016 static void
1017 GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1018 {
1019  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
1020  const SDL_Rect *rect;
1021  void *pixels;
1022 
1023  rect = &data->locked_rect;
1024  pixels =
1025  (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
1026  rect->x * SDL_BYTESPERPIXEL(texture->format));
1027  GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
1028 }
1029 
1030 static int
1031 GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
1032 {
1033  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1034  GL_TextureData *texturedata;
1035  GLenum status;
1036 
1037  GL_ActivateRenderer(renderer);
1038 
1039  if (!data->GL_EXT_framebuffer_object_supported) {
1040  return SDL_SetError("Render targets not supported by OpenGL");
1041  }
1042 
1043  if (texture == NULL) {
1044  data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1045  return 0;
1046  }
1047 
1048  texturedata = (GL_TextureData *) texture->driverdata;
1049  data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texturedata->fbo->FBO);
1050  /* TODO: check if texture pixel format allows this operation */
1051  data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texturedata->type, texturedata->texture, 0);
1052  /* Check FBO status */
1053  status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
1054  if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1055  return SDL_SetError("glFramebufferTexture2DEXT() failed");
1056  }
1057  return 0;
1058 }
1059 
1060 static int
1061 GL_UpdateViewport(SDL_Renderer * renderer)
1062 {
1063  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1064 
1065  if (SDL_CurrentContext != data->context) {
1066  /* We'll update the viewport after we rebind the context */
1067  return 0;
1068  }
1069 
1070  if (renderer->target) {
1071  data->glViewport(renderer->viewport.x, renderer->viewport.y,
1072  renderer->viewport.w, renderer->viewport.h);
1073  } else {
1074  int w, h;
1075 
1076  SDL_GL_GetDrawableSize(renderer->window, &w, &h);
1077  data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
1078  renderer->viewport.w, renderer->viewport.h);
1079  }
1080 
1081  data->glMatrixMode(GL_PROJECTION);
1082  data->glLoadIdentity();
1083  if (renderer->viewport.w && renderer->viewport.h) {
1084  if (renderer->target) {
1085  data->glOrtho((GLdouble) 0,
1086  (GLdouble) renderer->viewport.w,
1087  (GLdouble) 0,
1088  (GLdouble) renderer->viewport.h,
1089  0.0, 1.0);
1090  } else {
1091  data->glOrtho((GLdouble) 0,
1092  (GLdouble) renderer->viewport.w,
1093  (GLdouble) renderer->viewport.h,
1094  (GLdouble) 0,
1095  0.0, 1.0);
1096  }
1097  }
1098  data->glMatrixMode(GL_MODELVIEW);
1099 
1100  return GL_CheckError("", renderer);
1101 }
1102 
1103 static int
1104 GL_UpdateClipRect(SDL_Renderer * renderer)
1105 {
1106  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1107 
1108  if (renderer->clipping_enabled) {
1109  const SDL_Rect *rect = &renderer->clip_rect;
1110  data->glEnable(GL_SCISSOR_TEST);
1111  if (renderer->target) {
1112  data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h);
1113  } else {
1114  int w, h;
1115 
1116  SDL_GL_GetDrawableSize(renderer->window, &w, &h);
1117  data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
1118  }
1119  } else {
1120  data->glDisable(GL_SCISSOR_TEST);
1121  }
1122  return 0;
1123 }
1124 
1125 static void
1126 GL_SetShader(GL_RenderData * data, GL_Shader shader)
1127 {
1128  if (data->shaders && shader != data->current.shader) {
1129  GL_SelectShader(data->shaders, shader);
1130  data->current.shader = shader;
1131  }
1132 }
1133 
1134 static void
1135 GL_SetColor(GL_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1136 {
1137  Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
1138 
1139  if (color != data->current.color) {
1140  data->glColor4f((GLfloat) r * inv255f,
1141  (GLfloat) g * inv255f,
1142  (GLfloat) b * inv255f,
1143  (GLfloat) a * inv255f);
1144  data->current.color = color;
1145  }
1146 }
1147 
1148 static void
1149 GL_SetBlendMode(GL_RenderData * data, SDL_BlendMode blendMode)
1150 {
1151  if (blendMode != data->current.blendMode) {
1152  if (blendMode == SDL_BLENDMODE_NONE) {
1153  data->glDisable(GL_BLEND);
1154  } else {
1155  data->glEnable(GL_BLEND);
1156  data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
1157  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
1158  GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
1159  GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
1160  data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
1161  }
1162  data->current.blendMode = blendMode;
1163  }
1164 }
1165 
1166 static void
1167 GL_SetDrawingState(SDL_Renderer * renderer)
1168 {
1169  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1170 
1171  GL_ActivateRenderer(renderer);
1172 
1173  GL_SetColor(data, renderer->r,
1174  renderer->g,
1175  renderer->b,
1176  renderer->a);
1177 
1178  GL_SetBlendMode(data, renderer->blendMode);
1179 
1180  GL_SetShader(data, SHADER_SOLID);
1181 }
1182 
1183 static int
1184 GL_RenderClear(SDL_Renderer * renderer)
1185 {
1186  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1187 
1188  GL_ActivateRenderer(renderer);
1189 
1190  data->glClearColor((GLfloat) renderer->r * inv255f,
1191  (GLfloat) renderer->g * inv255f,
1192  (GLfloat) renderer->b * inv255f,
1193  (GLfloat) renderer->a * inv255f);
1194 
1195  if (renderer->clipping_enabled) {
1196  data->glDisable(GL_SCISSOR_TEST);
1197  }
1198 
1199  data->glClear(GL_COLOR_BUFFER_BIT);
1200 
1201  if (renderer->clipping_enabled) {
1202  data->glEnable(GL_SCISSOR_TEST);
1203  }
1204 
1205  return 0;
1206 }
1207 
1208 static int
1209 GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
1210  int count)
1211 {
1212  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1213  int i;
1214 
1215  GL_SetDrawingState(renderer);
1216 
1217  data->glBegin(GL_POINTS);
1218  for (i = 0; i < count; ++i) {
1219  data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
1220  }
1221  data->glEnd();
1222 
1223  return 0;
1224 }
1225 
1226 static int
1227 GL_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
1228  int count)
1229 {
1230  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1231  int i;
1232 
1233  GL_SetDrawingState(renderer);
1234 
1235  if (count > 2 &&
1236  points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
1237  data->glBegin(GL_LINE_LOOP);
1238  /* GL_LINE_LOOP takes care of the final segment */
1239  --count;
1240  for (i = 0; i < count; ++i) {
1241  data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
1242  }
1243  data->glEnd();
1244  } else {
1245 #if defined(__MACOSX__) || defined(__WIN32__)
1246 #else
1247  int x1, y1, x2, y2;
1248 #endif
1249 
1250  data->glBegin(GL_LINE_STRIP);
1251  for (i = 0; i < count; ++i) {
1252  data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
1253  }
1254  data->glEnd();
1255 
1256  /* The line is half open, so we need one more point to complete it.
1257  * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
1258  * If we have to, we can use vertical line and horizontal line textures
1259  * for vertical and horizontal lines, and then create custom textures
1260  * for diagonal lines and software render those. It's terrible, but at
1261  * least it would be pixel perfect.
1262  */
1263  data->glBegin(GL_POINTS);
1264 #if defined(__MACOSX__) || defined(__WIN32__)
1265  /* Mac OS X and Windows seem to always leave the last point open */
1266  data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
1267 #else
1268  /* Linux seems to leave the right-most or bottom-most point open */
1269  x1 = points[0].x;
1270  y1 = points[0].y;
1271  x2 = points[count-1].x;
1272  y2 = points[count-1].y;
1273 
1274  if (x1 > x2) {
1275  data->glVertex2f(0.5f + x1, 0.5f + y1);
1276  } else if (x2 > x1) {
1277  data->glVertex2f(0.5f + x2, 0.5f + y2);
1278  }
1279  if (y1 > y2) {
1280  data->glVertex2f(0.5f + x1, 0.5f + y1);
1281  } else if (y2 > y1) {
1282  data->glVertex2f(0.5f + x2, 0.5f + y2);
1283  }
1284 #endif
1285  data->glEnd();
1286  }
1287  return GL_CheckError("", renderer);
1288 }
1289 
1290 static int
1291 GL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
1292 {
1293  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1294  int i;
1295 
1296  GL_SetDrawingState(renderer);
1297 
1298  for (i = 0; i < count; ++i) {
1299  const SDL_FRect *rect = &rects[i];
1300 
1301  data->glRectf(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
1302  }
1303  return GL_CheckError("", renderer);
1304 }
1305 
1306 static int
1307 GL_SetupCopy(SDL_Renderer * renderer, SDL_Texture * texture)
1308 {
1309  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1310  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1311 
1312  data->glEnable(texturedata->type);
1313  if (texturedata->yuv) {
1314  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1315  data->glBindTexture(texturedata->type, texturedata->vtexture);
1316 
1317  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1318  data->glBindTexture(texturedata->type, texturedata->utexture);
1319 
1320  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1321  }
1322  if (texturedata->nv12) {
1323  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1324  data->glBindTexture(texturedata->type, texturedata->utexture);
1325 
1326  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1327  }
1328  data->glBindTexture(texturedata->type, texturedata->texture);
1329 
1330  if (texture->modMode) {
1331  GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
1332  } else {
1333  GL_SetColor(data, 255, 255, 255, 255);
1334  }
1335 
1336  GL_SetBlendMode(data, texture->blendMode);
1337 
1338  if (texturedata->yuv || texturedata->nv12) {
1339  switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
1341  if (texturedata->yuv) {
1342  GL_SetShader(data, SHADER_YUV_JPEG);
1343  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1344  GL_SetShader(data, SHADER_NV12_JPEG);
1345  } else {
1346  GL_SetShader(data, SHADER_NV21_JPEG);
1347  }
1348  break;
1350  if (texturedata->yuv) {
1351  GL_SetShader(data, SHADER_YUV_BT601);
1352  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1353  GL_SetShader(data, SHADER_NV12_BT601);
1354  } else {
1355  GL_SetShader(data, SHADER_NV21_BT601);
1356  }
1357  break;
1359  if (texturedata->yuv) {
1360  GL_SetShader(data, SHADER_YUV_BT709);
1361  } else if (texture->format == SDL_PIXELFORMAT_NV12) {
1362  GL_SetShader(data, SHADER_NV12_BT709);
1363  } else {
1364  GL_SetShader(data, SHADER_NV21_BT709);
1365  }
1366  break;
1367  default:
1368  return SDL_SetError("Unsupported YUV conversion mode");
1369  }
1370  } else {
1371  GL_SetShader(data, SHADER_RGB);
1372  }
1373  return 0;
1374 }
1375 
1376 static int
1377 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1378  const SDL_Rect * srcrect, const SDL_FRect * dstrect)
1379 {
1380  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1381  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1382  GLfloat minx, miny, maxx, maxy;
1383  GLfloat minu, maxu, minv, maxv;
1384 
1385  GL_ActivateRenderer(renderer);
1386 
1387  if (GL_SetupCopy(renderer, texture) < 0) {
1388  return -1;
1389  }
1390 
1391  minx = dstrect->x;
1392  miny = dstrect->y;
1393  maxx = dstrect->x + dstrect->w;
1394  maxy = dstrect->y + dstrect->h;
1395 
1396  minu = (GLfloat) srcrect->x / texture->w;
1397  minu *= texturedata->texw;
1398  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
1399  maxu *= texturedata->texw;
1400  minv = (GLfloat) srcrect->y / texture->h;
1401  minv *= texturedata->texh;
1402  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
1403  maxv *= texturedata->texh;
1404 
1405  data->glBegin(GL_TRIANGLE_STRIP);
1406  data->glTexCoord2f(minu, minv);
1407  data->glVertex2f(minx, miny);
1408  data->glTexCoord2f(maxu, minv);
1409  data->glVertex2f(maxx, miny);
1410  data->glTexCoord2f(minu, maxv);
1411  data->glVertex2f(minx, maxy);
1412  data->glTexCoord2f(maxu, maxv);
1413  data->glVertex2f(maxx, maxy);
1414  data->glEnd();
1415 
1416  data->glDisable(texturedata->type);
1417 
1418  return GL_CheckError("", renderer);
1419 }
1420 
1421 static int
1422 GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
1423  const SDL_Rect * srcrect, const SDL_FRect * dstrect,
1424  const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
1425 {
1426  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1427  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1428  GLfloat minx, miny, maxx, maxy;
1429  GLfloat centerx, centery;
1430  GLfloat minu, maxu, minv, maxv;
1431 
1432  GL_ActivateRenderer(renderer);
1433 
1434  if (GL_SetupCopy(renderer, texture) < 0) {
1435  return -1;
1436  }
1437 
1438  centerx = center->x;
1439  centery = center->y;
1440 
1441  if (flip & SDL_FLIP_HORIZONTAL) {
1442  minx = dstrect->w - centerx;
1443  maxx = -centerx;
1444  }
1445  else {
1446  minx = -centerx;
1447  maxx = dstrect->w - centerx;
1448  }
1449 
1450  if (flip & SDL_FLIP_VERTICAL) {
1451  miny = dstrect->h - centery;
1452  maxy = -centery;
1453  }
1454  else {
1455  miny = -centery;
1456  maxy = dstrect->h - centery;
1457  }
1458 
1459  minu = (GLfloat) srcrect->x / texture->w;
1460  minu *= texturedata->texw;
1461  maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
1462  maxu *= texturedata->texw;
1463  minv = (GLfloat) srcrect->y / texture->h;
1464  minv *= texturedata->texh;
1465  maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
1466  maxv *= texturedata->texh;
1467 
1468  /* Translate to flip, rotate, translate to position */
1469  data->glPushMatrix();
1470  data->glTranslatef((GLfloat)dstrect->x + centerx, (GLfloat)dstrect->y + centery, (GLfloat)0.0);
1471  data->glRotated(angle, (GLdouble)0.0, (GLdouble)0.0, (GLdouble)1.0);
1472 
1473  data->glBegin(GL_TRIANGLE_STRIP);
1474  data->glTexCoord2f(minu, minv);
1475  data->glVertex2f(minx, miny);
1476  data->glTexCoord2f(maxu, minv);
1477  data->glVertex2f(maxx, miny);
1478  data->glTexCoord2f(minu, maxv);
1479  data->glVertex2f(minx, maxy);
1480  data->glTexCoord2f(maxu, maxv);
1481  data->glVertex2f(maxx, maxy);
1482  data->glEnd();
1483  data->glPopMatrix();
1484 
1485  data->glDisable(texturedata->type);
1486 
1487  return GL_CheckError("", renderer);
1488 }
1489 
1490 static int
1491 GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
1492  Uint32 pixel_format, void * pixels, int pitch)
1493 {
1494  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1495  Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ARGB8888;
1496  void *temp_pixels;
1497  int temp_pitch;
1498  GLint internalFormat;
1499  GLenum format, type;
1500  Uint8 *src, *dst, *tmp;
1501  int w, h, length, rows;
1502  int status;
1503 
1504  GL_ActivateRenderer(renderer);
1505 
1506  if (!convert_format(data, temp_format, &internalFormat, &format, &type)) {
1507  return SDL_SetError("Texture format %s not supported by OpenGL",
1508  SDL_GetPixelFormatName(temp_format));
1509  }
1510 
1511  if (!rect->w || !rect->h) {
1512  return 0; /* nothing to do. */
1513  }
1514 
1515  temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
1516  temp_pixels = SDL_malloc(rect->h * temp_pitch);
1517  if (!temp_pixels) {
1518  return SDL_OutOfMemory();
1519  }
1520 
1521  SDL_GetRendererOutputSize(renderer, &w, &h);
1522 
1523  data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1524  data->glPixelStorei(GL_PACK_ROW_LENGTH,
1525  (temp_pitch / SDL_BYTESPERPIXEL(temp_format)));
1526 
1527  data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
1528  rect->w, rect->h, format, type, temp_pixels);
1529 
1530  if (GL_CheckError("glReadPixels()", renderer) < 0) {
1531  SDL_free(temp_pixels);
1532  return -1;
1533  }
1534 
1535  /* Flip the rows to be top-down if necessary */
1536  if (!renderer->target) {
1537  length = rect->w * SDL_BYTESPERPIXEL(temp_format);
1538  src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
1539  dst = (Uint8*)temp_pixels;
1540  tmp = SDL_stack_alloc(Uint8, length);
1541  rows = rect->h / 2;
1542  while (rows--) {
1543  SDL_memcpy(tmp, dst, length);
1544  SDL_memcpy(dst, src, length);
1545  SDL_memcpy(src, tmp, length);
1546  dst += temp_pitch;
1547  src -= temp_pitch;
1548  }
1549  SDL_stack_free(tmp);
1550  }
1551 
1552  status = SDL_ConvertPixels(rect->w, rect->h,
1553  temp_format, temp_pixels, temp_pitch,
1554  pixel_format, pixels, pitch);
1555  SDL_free(temp_pixels);
1556 
1557  return status;
1558 }
1559 
1560 static void
1561 GL_RenderPresent(SDL_Renderer * renderer)
1562 {
1563  GL_ActivateRenderer(renderer);
1564 
1565  SDL_GL_SwapWindow(renderer->window);
1566 }
1567 
1568 static void
1569 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
1570 {
1571  GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
1572  GL_TextureData *data = (GL_TextureData *) texture->driverdata;
1573 
1574  GL_ActivateRenderer(renderer);
1575 
1576  if (!data) {
1577  return;
1578  }
1579  if (data->texture) {
1580  renderdata->glDeleteTextures(1, &data->texture);
1581  }
1582  if (data->yuv) {
1583  renderdata->glDeleteTextures(1, &data->utexture);
1584  renderdata->glDeleteTextures(1, &data->vtexture);
1585  }
1586  SDL_free(data->pixels);
1587  SDL_free(data);
1588  texture->driverdata = NULL;
1589 }
1590 
1591 static void
1592 GL_DestroyRenderer(SDL_Renderer * renderer)
1593 {
1594  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1595 
1596  if (data) {
1597  if (data->context != NULL) {
1598  /* make sure we delete the right resources! */
1599  GL_ActivateRenderer(renderer);
1600  }
1601 
1602  GL_ClearErrors(renderer);
1603  if (data->GL_ARB_debug_output_supported) {
1604  PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
1605 
1606  /* Uh oh, we don't have a safe way of removing ourselves from the callback chain, if it changed after we set our callback. */
1607  /* For now, just always replace the callback with the original one */
1608  glDebugMessageCallbackARBFunc(data->next_error_callback, data->next_error_userparam);
1609  }
1610  if (data->shaders) {
1611  GL_DestroyShaderContext(data->shaders);
1612  }
1613  if (data->context) {
1614  while (data->framebuffers) {
1615  GL_FBOList *nextnode = data->framebuffers->next;
1616  /* delete the framebuffer object */
1617  data->glDeleteFramebuffersEXT(1, &data->framebuffers->FBO);
1618  GL_CheckError("", renderer);
1619  SDL_free(data->framebuffers);
1620  data->framebuffers = nextnode;
1621  }
1622  SDL_GL_DeleteContext(data->context);
1623  }
1624  SDL_free(data);
1625  }
1626  SDL_free(renderer);
1627 }
1628 
1629 static int
1630 GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
1631 {
1632  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1633  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1634  GL_ActivateRenderer(renderer);
1635 
1636  data->glEnable(texturedata->type);
1637  if (texturedata->yuv) {
1638  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1639  data->glBindTexture(texturedata->type, texturedata->vtexture);
1640 
1641  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1642  data->glBindTexture(texturedata->type, texturedata->utexture);
1643 
1644  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1645  }
1646  data->glBindTexture(texturedata->type, texturedata->texture);
1647 
1648  if(texw) *texw = (float)texturedata->texw;
1649  if(texh) *texh = (float)texturedata->texh;
1650 
1651  return 0;
1652 }
1653 
1654 static int
1655 GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
1656 {
1657  GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1658  GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1659  GL_ActivateRenderer(renderer);
1660 
1661  if (texturedata->yuv) {
1662  data->glActiveTextureARB(GL_TEXTURE2_ARB);
1663  data->glDisable(texturedata->type);
1664 
1665  data->glActiveTextureARB(GL_TEXTURE1_ARB);
1666  data->glDisable(texturedata->type);
1667 
1668  data->glActiveTextureARB(GL_TEXTURE0_ARB);
1669  }
1670 
1671  data->glDisable(texturedata->type);
1672 
1673  return 0;
1674 }
1675 
1676 #endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */
1677 
1678 /* vi: set ts=4 sw=4 expandtab: */
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2252
SDL_BlendFactor
The normalized factor used to multiply pixel components.
Definition: SDL_blendmode.h:75
#define GL_ONE
Definition: SDL_opengl.h:401
#define GL_STACK_UNDERFLOW
Definition: SDL_opengl.h:724
int(* UpdateClipRect)(SDL_Renderer *renderer)
SDL_BlendMode blendMode
Definition: SDL_sysrender.h:65
#define SDL_GL_ExtensionSupported
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
#define GL_INVALID_ENUM
Definition: SDL_opengl.h:720
#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)
#define GL_INVALID_OPERATION
Definition: SDL_opengl.h:722
GLuint64EXT * result
#define GL_SCISSOR_TEST
Definition: SDL_opengl.h:615
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:89
#define GL_UNSIGNED_INT_8_8_8_8_REV
Definition: SDL_opengl.h:1521
#define SDL_GL_CreateContext
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
int(* RenderClear)(SDL_Renderer *renderer)
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
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Rect rect
Definition: testrelative.c:27
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:92
#define GL_LINEAR
Definition: SDL_opengl.h:447
#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:2280
#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:2266
GLfloat f
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
#define GL_TEXTURE_MAG_FILTER
Definition: SDL_opengl.h:674
#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB
GLsizei GLsizei GLuint * shaders
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
#define GL_TEXTURE_STORAGE_HINT_APPLE
SDL_RenderDriver GL_RenderDriver
SDL_Rect clip_rect
#define GL_TRIANGLE_STRIP
Definition: SDL_opengl.h:221
float GLfloat
Definition: SDL_opengl.h:187
#define SDL_realloc
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
#define GL_FRAMEBUFFER_COMPLETE_EXT
GLfixed GLfixed GLint GLint GLfixed points
void(APIENTRY * GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
#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
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 GL_SRC_COLOR
Definition: SDL_opengl.h:402
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
#define SDL_GL_SetAttribute
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
#define SDL_GL_GetDrawableSize
#define GL_ONE_MINUS_DST_ALPHA
Definition: SDL_opengl.h:407
#define SDL_memcpy
GLenum GLenum GLuint texture
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:2287
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)
#define SDL_LogDebug
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:193
#define SDL_GL_GetSwapInterval
GL_Shader
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:99
GLenum GLenum GLenum input
SDL_Texture * target
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1617
#define GL_STACK_OVERFLOW
Definition: SDL_opengl.h:723
static SDL_Renderer * renderer
GLenum GLenum severity
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_free
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
struct _cl_event * event
SDL_BlendMode blendMode
#define SDL_GL_SetSwapInterval
#define 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
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
#define GL_LINE_LOOP
Definition: SDL_opengl.h:218
#define GL_LUMINANCE_ALPHA
Definition: SDL_opengl.h:511
#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
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
#define GL_TEXTURE1_ARB
Definition: SDL_opengl.h:1991
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
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int w
Definition: SDL_rect.h:67
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
#define GL_RGB8
Definition: SDL_opengl.h:781
#define GL_STORAGE_SHARED_APPLE
GLsizeiptr size
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
Window state change event data (event.window.*)
Definition: SDL_events.h:195
#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:161
#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:2273
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
Definition: SDL_sysrender.h:90
void GLvoid
Definition: SDL_opengl.h:179
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
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)
#define SDL_calloc
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
#define SDL_GL_MakeCurrent
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
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(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
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
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define GL_ONE_MINUS_DST_COLOR
Definition: SDL_opengl.h:409
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:2259
GLuint color
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Definition: SDL_sysrender.h:91
#define GL_SRC_ALPHA
Definition: SDL_opengl.h:404
#define GL_NEAREST
Definition: SDL_opengl.h:704
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:60
#define GL_DST_ALPHA
Definition: SDL_opengl.h:406
void * driverdata
Definition: SDL_sysrender.h:78
#define GL_DEPTH_TEST
Definition: SDL_opengl.h:327
#define SDL_malloc
#define SDL_GL_GetAttribute
int(* UpdateViewport)(SDL_Renderer *renderer)
#define SDL_ConvertPixels
#define GL_UNSIGNED_SHORT_8_8_APPLE
int GLsizei
Definition: SDL_opengl.h:186
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
SDL_ScaleMode scaleMode
Definition: SDL_sysrender.h:66
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 GL_TEXTURE_WRAP_S
Definition: SDL_opengl.h:672
GLuint GLsizei GLsizei * length
#define GL_TEXTURE_MIN_FILTER
Definition: SDL_opengl.h:675
void(* RenderPresent)(SDL_Renderer *renderer)
GLboolean GLboolean GLboolean GLboolean a
void(* DestroyRenderer)(SDL_Renderer *renderer)
#define GL_UNPACK_ALIGNMENT
Definition: SDL_opengl.h:658
#define GL_FUNC_ADD
Definition: SDL_opengl.h:1652
#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