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