21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED
29 #include "../SDL_sysrender.h"
33 #include <OpenGL/OpenGL.h>
40 #define RENDERER_CONTEXT_MAJOR 2
41 #define RENDERER_CONTEXT_MINOR 1
52 static const float inv255f = 1.0f / 255.0f;
54 typedef struct GL_FBOList GL_FBOList;
87 SDL_bool GL_ARB_debug_output_supported;
89 char **error_messages;
91 GLvoid *next_error_userparam;
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;
101 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
106 SDL_bool GL_ARB_multitexture_supported;
108 GLint num_texture_units;
110 PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
111 PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
112 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
113 PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
114 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
119 GL_DrawStateCache drawstate;
143 GL_TranslateError (
GLenum error)
145 #define GL_ERROR_TRANSLATE(e) case e: return #e;
158 #undef GL_ERROR_TRANSLATE
170 if (
data->GL_ARB_debug_output_supported) {
173 for (
i = 0;
i <
data->errors; ++
i) {
181 }
else if (
data->glGetError !=
NULL) {
189 GL_CheckAllErrors (
const char *prefix,
SDL_Renderer *
renderer,
const char *file,
int line,
const char *
function)
198 if (
data->GL_ARB_debug_output_supported) {
201 for (
i = 0;
i <
data->errors; ++
i) {
202 SDL_SetError(
"%s: %s (%d): %s %s", prefix, file, line,
function,
data->error_messages[
i]);
212 if (prefix ==
NULL || prefix[0] ==
'\0') {
215 SDL_SetError(
"%s: %s (%d): %s %s (0x%X)", prefix, file, line,
function, GL_TranslateError(error), error);
226 #define GL_CheckError(prefix, renderer)
228 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION)
232 GL_LoadFunctions(GL_RenderData *
data)
234 #ifdef __SDL_NOGETPROCADDR__
235 #define SDL_PROC(ret,func,params) data->func=func;
238 #define SDL_PROC(ret,func,params) \
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()); \
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;
286 if (
data->next_error_callback) {
386 if (colorOperation != alphaOperation) {
393 power_of_2(
int input)
404 convert_format(GL_RenderData *renderdata,
Uint32 pixel_format,
407 switch (pixel_format) {
445 const GLenum textype = renderdata->textype;
446 GL_TextureData *
data;
449 int texture_w, texture_h;
454 renderdata->drawstate.texture =
NULL;
457 !renderdata->GL_EXT_framebuffer_object_supported) {
458 return SDL_SetError(
"Render targets not supported by OpenGL");
463 return SDL_SetError(
"Texture format %s not supported by OpenGL",
500 renderdata->glGenTextures(1, &
data->texture);
501 if (GL_CheckError(
"glGenTextures()",
renderer) < 0) {
510 if (renderdata->GL_ARB_texture_non_power_of_two_supported) {
515 }
else if (renderdata->GL_ARB_texture_rectangle_supported) {
521 texture_w = power_of_2(
texture->w);
522 texture_h = power_of_2(
texture->h);
530 renderdata->glEnable(textype);
531 renderdata->glBindTexture(textype,
data->texture);
544 #ifndef GL_TEXTURE_STORAGE_HINT_APPLE
545 #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
547 #ifndef STORAGE_CACHED_APPLE
548 #define STORAGE_CACHED_APPLE 0x85BE
550 #ifndef STORAGE_SHARED_APPLE
551 #define STORAGE_SHARED_APPLE 0x85BF
577 renderdata->glDisable(textype);
578 if (GL_CheckError(
"glTexImage2D()",
renderer) < 0) {
586 renderdata->glGenTextures(1, &
data->utexture);
587 renderdata->glGenTextures(1, &
data->vtexture);
588 renderdata->glEnable(textype);
590 renderdata->glBindTexture(textype,
data->utexture);
599 renderdata->glTexImage2D(textype, 0,
internalFormat, (texture_w+1)/2,
602 renderdata->glBindTexture(textype,
data->vtexture);
611 renderdata->glTexImage2D(textype, 0,
internalFormat, (texture_w+1)/2,
614 renderdata->glDisable(textype);
621 renderdata->glGenTextures(1, &
data->utexture);
622 renderdata->glEnable(textype);
624 renderdata->glBindTexture(textype,
data->utexture);
635 renderdata->glDisable(textype);
646 const GLenum textype = renderdata->textype;
647 GL_TextureData *
data = (GL_TextureData *)
texture->driverdata;
654 renderdata->drawstate.texture =
NULL;
656 renderdata->glEnable(textype);
657 renderdata->glBindTexture(textype,
data->texture);
669 renderdata->glBindTexture(textype,
data->vtexture);
671 renderdata->glBindTexture(textype,
data->utexture);
673 renderdata->glTexSubImage2D(textype, 0,
rect->
x/2,
rect->
y/2,
680 renderdata->glBindTexture(textype,
data->utexture);
682 renderdata->glBindTexture(textype,
data->vtexture);
684 renderdata->glTexSubImage2D(textype, 0,
rect->
x/2,
rect->
y/2,
694 renderdata->glBindTexture(textype,
data->utexture);
695 renderdata->glTexSubImage2D(textype, 0,
rect->
x/2,
rect->
y/2,
699 renderdata->glDisable(textype);
701 return GL_CheckError(
"glTexSubImage2D()",
renderer);
707 const Uint8 *Yplane,
int Ypitch,
708 const Uint8 *Uplane,
int Upitch,
709 const Uint8 *Vplane,
int Vpitch)
712 const GLenum textype = renderdata->textype;
713 GL_TextureData *
data = (GL_TextureData *)
texture->driverdata;
717 renderdata->drawstate.texture =
NULL;
719 renderdata->glEnable(textype);
720 renderdata->glBindTexture(textype,
data->texture);
728 renderdata->glBindTexture(textype,
data->utexture);
729 renderdata->glTexSubImage2D(textype, 0,
rect->
x/2,
rect->
y/2,
731 data->format,
data->formattype, Uplane);
734 renderdata->glBindTexture(textype,
data->vtexture);
735 renderdata->glTexSubImage2D(textype, 0,
rect->
x/2,
rect->
y/2,
737 data->format,
data->formattype, Vplane);
738 renderdata->glDisable(textype);
740 return GL_CheckError(
"glTexSubImage2D()",
renderer);
747 GL_TextureData *
data = (GL_TextureData *)
texture->driverdata;
753 *pitch =
data->pitch;
760 GL_TextureData *
data = (GL_TextureData *)
texture->driverdata;
775 const GLenum textype = renderdata->textype;
776 GL_TextureData *
data = (GL_TextureData *)
texture->driverdata;
779 renderdata->glEnable(textype);
780 renderdata->glBindTexture(textype,
data->texture);
783 renderdata->glDisable(textype);
787 renderdata->glEnable(textype);
788 renderdata->glBindTexture(textype,
data->utexture);
792 renderdata->glBindTexture(textype,
data->vtexture);
795 renderdata->glDisable(textype);
800 renderdata->glEnable(textype);
801 renderdata->glBindTexture(textype,
data->utexture);
804 renderdata->glDisable(textype);
812 GL_TextureData *texturedata;
817 if (!
data->GL_EXT_framebuffer_object_supported) {
818 return SDL_SetError(
"Render targets not supported by OpenGL");
828 texturedata = (GL_TextureData *)
texture->driverdata;
835 return SDL_SetError(
"glFramebufferTexture2DEXT() failed");
881 *(verts++) =
rect->
x;
882 *(verts++) =
rect->
y;
894 GL_TextureData *texturedata = (GL_TextureData *)
texture->driverdata;
895 GLfloat minx, miny, maxx, maxy;
896 GLfloat minu, maxu, minv, maxv;
907 maxx = dstrect->
x + dstrect->
w;
908 maxy = dstrect->
y + dstrect->
h;
911 minu *= texturedata->texw;
913 maxu *= texturedata->texw;
915 minv *= texturedata->texh;
917 maxv *= texturedata->texh;
936 GL_TextureData *texturedata = (GL_TextureData *)
texture->driverdata;
937 GLfloat minx, miny, maxx, maxy;
939 GLfloat minu, maxu, minv, maxv;
950 minx = dstrect->
w - centerx;
955 maxx = dstrect->
w - centerx;
959 miny = dstrect->
h - centery;
964 maxy = dstrect->
h - centery;
968 minu *= texturedata->texw;
970 maxu *= texturedata->texw;
972 minv *= texturedata->texh;
974 maxv *= texturedata->texh;
985 *(verts++) = (
GLfloat) dstrect->
x + centerx;
986 *(verts++) = (
GLfloat) dstrect->
y + centery;
996 if (
data->drawstate.viewport_dirty) {
1000 data->glLoadIdentity();
1014 if (
data->drawstate.cliprect_enabled_dirty) {
1015 if (!
data->drawstate.cliprect_enabled) {
1023 if (
data->drawstate.cliprect_enabled &&
data->drawstate.cliprect_dirty) {
1032 if (blend !=
data->drawstate.blend) {
1043 data->drawstate.blend = blend;
1066 const GL_TextureData *texturedata = (GL_TextureData *)
texture->driverdata;
1075 if (
data->shaders) {
1076 if (texturedata->yuv || texturedata->nv12) {
1079 if (texturedata->yuv) {
1088 if (texturedata->yuv) {
1097 if (texturedata->yuv) {
1106 SDL_assert(!
"unsupported YUV conversion mode");
1116 if (texturedata->yuv) {
1118 data->glBindTexture(textype, texturedata->vtexture);
1121 data->glBindTexture(textype, texturedata->utexture);
1123 if (texturedata->nv12) {
1125 data->glBindTexture(textype, texturedata->utexture);
1128 data->glBindTexture(textype, texturedata->texture);
1146 if (!
data->drawstate.target) {
1197 if (
color !=
data->drawstate.clear_color) {
1202 data->glClearColor(fr, fg, fb, fa);
1206 if (
data->drawstate.cliprect_enabled ||
data->drawstate.cliprect_enabled_dirty) {
1208 data->drawstate.cliprect_enabled_dirty =
data->drawstate.cliprect_enabled;
1221 for (
i = 0;
i <
count;
i++, verts += 2) {
1222 data->glVertex2f(verts[0], verts[1]);
1232 if (
count > 2 && (verts[0] == verts[(
count-1)*2]) && (verts[1] == verts[(
count*2)-1])) {
1235 for (
i = 1;
i <
count; ++
i, verts += 2) {
1236 data->glVertex2f(verts[0], verts[1]);
1240 #if defined(__MACOSX__) || defined(__WIN32__)
1246 for (
i = 0;
i <
count; ++
i, verts += 2) {
1247 data->glVertex2f(verts[0], verts[1]);
1261 #if defined(__MACOSX__) || defined(__WIN32__)
1273 }
else if (
x2 >
x1) {
1278 }
else if (
y2 >
y1) {
1291 for (
i = 0;
i <
count; ++
i, verts += 4) {
1292 data->glRectf(verts[0], verts[1], verts[2], verts[3]);
1299 const GLfloat minx = verts[0];
1300 const GLfloat miny = verts[1];
1301 const GLfloat maxx = verts[2];
1302 const GLfloat maxy = verts[3];
1303 const GLfloat minu = verts[4];
1304 const GLfloat maxu = verts[5];
1305 const GLfloat minv = verts[6];
1306 const GLfloat maxv = verts[7];
1307 SetCopyState(
data, cmd);
1309 data->glTexCoord2f(minu, minv);
1310 data->glVertex2f(minx, miny);
1311 data->glTexCoord2f(maxu, minv);
1312 data->glVertex2f(maxx, miny);
1313 data->glTexCoord2f(minu, maxv);
1314 data->glVertex2f(minx, maxy);
1315 data->glTexCoord2f(maxu, maxv);
1316 data->glVertex2f(maxx, maxy);
1323 const GLfloat minx = verts[0];
1324 const GLfloat miny = verts[1];
1325 const GLfloat maxx = verts[2];
1326 const GLfloat maxy = verts[3];
1327 const GLfloat minu = verts[4];
1328 const GLfloat maxu = verts[5];
1329 const GLfloat minv = verts[6];
1330 const GLfloat maxv = verts[7];
1331 const GLfloat translatex = verts[8];
1332 const GLfloat translatey = verts[9];
1334 SetCopyState(
data, cmd);
1337 data->glPushMatrix();
1338 data->glTranslatef(translatex, translatey, 0.0
f);
1341 data->glTexCoord2f(minu, minv);
1342 data->glVertex2f(minx, miny);
1343 data->glTexCoord2f(maxu, minv);
1344 data->glVertex2f(maxx, miny);
1345 data->glTexCoord2f(minu, maxv);
1346 data->glVertex2f(minx, maxy);
1347 data->glTexCoord2f(maxu, maxv);
1348 data->glVertex2f(maxx, maxy);
1350 data->glPopMatrix();
1361 return GL_CheckError(
"",
renderer);
1381 return SDL_SetError(
"Texture format %s not supported by OpenGL",
1404 if (GL_CheckError(
"glReadPixels()",
renderer) < 0) {
1428 temp_format, temp_pixels, temp_pitch,
1429 pixel_format,
pixels, pitch);
1447 GL_TextureData *
data = (GL_TextureData *)
texture->driverdata;
1451 if (renderdata->drawstate.texture ==
texture) {
1452 renderdata->drawstate.texture =
NULL;
1454 if (renderdata->drawstate.target ==
texture) {
1455 renderdata->drawstate.target =
NULL;
1461 if (
data->texture) {
1462 renderdata->glDeleteTextures(1, &
data->texture);
1465 renderdata->glDeleteTextures(1, &
data->utexture);
1466 renderdata->glDeleteTextures(1, &
data->vtexture);
1485 if (
data->GL_ARB_debug_output_supported) {
1486 PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC)
SDL_GL_GetProcAddress(
"glDebugMessageCallbackARB");
1490 glDebugMessageCallbackARBFunc(
data->next_error_callback,
data->next_error_userparam);
1492 if (
data->shaders) {
1495 if (
data->context) {
1496 while (
data->framebuffers) {
1497 GL_FBOList *nextnode =
data->framebuffers->next;
1499 data->glDeleteFramebuffersEXT(1, &
data->framebuffers->FBO);
1502 data->framebuffers = nextnode;
1515 GL_TextureData *texturedata = (GL_TextureData *)
texture->driverdata;
1520 data->glEnable(textype);
1521 if (texturedata->yuv) {
1523 data->glBindTexture(textype, texturedata->vtexture);
1526 data->glBindTexture(textype, texturedata->utexture);
1530 data->glBindTexture(textype, texturedata->texture);
1535 if(texw) *texw = (float)texturedata->texw;
1536 if(texh) *texh = (float)texturedata->texh;
1545 GL_TextureData *texturedata = (GL_TextureData *)
texture->driverdata;
1550 if (texturedata->yuv) {
1552 data->glDisable(textype);
1555 data->glDisable(textype);
1560 data->glDisable(textype);
1573 GL_RenderData *
data;
1576 int profile_mask = 0, major = 0, minor = 0;
1639 if (!
data->context) {
1651 if (GL_LoadFunctions(
data) < 0) {
1680 PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC)
SDL_GL_GetProcAddress(
"glDebugMessageCallbackARB");
1685 glDebugMessageCallbackARBFunc(GL_HandleDebugMessage,
renderer);
1693 data->GL_ARB_texture_non_power_of_two_supported =
SDL_TRUE;
1699 if (
data->GL_ARB_texture_rectangle_supported) {
1712 if (
data->glActiveTextureARB) {
1723 data->shaders ?
"ENABLED" :
"DISABLED");
1726 if (
data->shaders &&
data->num_texture_units >= 3) {
1739 data->glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)
1741 data->glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
1743 data->glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
1745 data->glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)
1747 data->glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
1755 data->glLoadIdentity();
1760 data->glClearColor(1.0
f, 1.0
f, 1.0
f, 1.0
f);
1761 data->glColor4f(1.0
f, 1.0
f, 1.0
f, 1.0
f);
1767 data->drawstate.color = 0xFFFFFFFF;
1768 data->drawstate.clear_color = 0xFFFFFFFF;
1773 if (changed_window) {