src/video/SDL_renderer_gl.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 16 Nov 2009 07:13:07 +0000
changeset 3435 9f62f47d989b
parent 3433 ad845d9835aa
child 3440 e9502d56ae94
permissions -rw-r--r--
You can specify the format for pixel data in SDL_RenderReadPixels() and SDL_RenderWritePixels()
This code still doesn't quite work yet. :)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #if SDL_VIDEO_RENDER_OGL
    25 
    26 #include "SDL_video.h"
    27 #include "SDL_opengl.h"
    28 #include "SDL_sysvideo.h"
    29 #include "SDL_pixels_c.h"
    30 #include "SDL_rect_c.h"
    31 #include "SDL_yuv_sw_c.h"
    32 
    33 #ifdef __MACOSX__
    34 #include <OpenGL/OpenGL.h>
    35 #endif
    36 
    37 
    38 /* OpenGL renderer implementation */
    39 
    40 /* Details on optimizing the texture path on Mac OS X:
    41    http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/chapter_10_section_2.html
    42 */
    43 
    44 /* !!! FIXME: this should go in a higher level than the GL renderer. */
    45 static __inline__ int
    46 bytes_per_pixel(const Uint32 format)
    47 {
    48     if (!SDL_ISPIXELFORMAT_FOURCC(format)) {
    49         return SDL_BYTESPERPIXEL(format);
    50     }
    51 
    52     /* FOURCC format */
    53     switch (format) {
    54     case SDL_PIXELFORMAT_YV12:
    55     case SDL_PIXELFORMAT_IYUV:
    56     case SDL_PIXELFORMAT_YUY2:
    57     case SDL_PIXELFORMAT_UYVY:
    58     case SDL_PIXELFORMAT_YVYU:
    59         return 2;
    60     default:
    61         return 1;               /* shouldn't ever hit this. */
    62     }
    63 }
    64 
    65 
    66 static const float inv255f = 1.0f / 255.0f;
    67 
    68 static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
    69 static int GL_ActivateRenderer(SDL_Renderer * renderer);
    70 static int GL_DisplayModeChanged(SDL_Renderer * renderer);
    71 static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    72 static int GL_QueryTexturePixels(SDL_Renderer * renderer,
    73                                  SDL_Texture * texture, void **pixels,
    74                                  int *pitch);
    75 static int GL_SetTexturePalette(SDL_Renderer * renderer,
    76                                 SDL_Texture * texture,
    77                                 const SDL_Color * colors, int firstcolor,
    78                                 int ncolors);
    79 static int GL_GetTexturePalette(SDL_Renderer * renderer,
    80                                 SDL_Texture * texture, SDL_Color * colors,
    81                                 int firstcolor, int ncolors);
    82 static int GL_SetTextureColorMod(SDL_Renderer * renderer,
    83                                  SDL_Texture * texture);
    84 static int GL_SetTextureAlphaMod(SDL_Renderer * renderer,
    85                                  SDL_Texture * texture);
    86 static int GL_SetTextureBlendMode(SDL_Renderer * renderer,
    87                                   SDL_Texture * texture);
    88 static int GL_SetTextureScaleMode(SDL_Renderer * renderer,
    89                                   SDL_Texture * texture);
    90 static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    91                             const SDL_Rect * rect, const void *pixels,
    92                             int pitch);
    93 static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    94                           const SDL_Rect * rect, int markDirty, void **pixels,
    95                           int *pitch);
    96 static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    97 static void GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    98                             int numrects, const SDL_Rect * rects);
    99 static int GL_RenderPoint(SDL_Renderer * renderer, int x, int y);
   100 static int GL_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
   101                          int y2);
   102 static int GL_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
   103 static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   104                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
   105 static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   106                                Uint32 pixel_format, void * pixels, int pitch);
   107 static int GL_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   108                                 Uint32 pixel_format, const void * pixels, int pitch);
   109 static void GL_RenderPresent(SDL_Renderer * renderer);
   110 static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
   111 static void GL_DestroyRenderer(SDL_Renderer * renderer);
   112 
   113 
   114 SDL_RenderDriver GL_RenderDriver = {
   115     GL_CreateRenderer,
   116     {
   117      "opengl",
   118      (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD |
   119       SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
   120      (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
   121       SDL_TEXTUREMODULATE_ALPHA),
   122      (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
   123       SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
   124      (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
   125       SDL_TEXTURESCALEMODE_SLOW),
   126      15,
   127      {
   128       SDL_PIXELFORMAT_INDEX1LSB,
   129       SDL_PIXELFORMAT_INDEX1MSB,
   130       SDL_PIXELFORMAT_INDEX8,
   131       SDL_PIXELFORMAT_RGB332,
   132       SDL_PIXELFORMAT_RGB444,
   133       SDL_PIXELFORMAT_RGB555,
   134       SDL_PIXELFORMAT_ARGB4444,
   135       SDL_PIXELFORMAT_ARGB1555,
   136       SDL_PIXELFORMAT_RGB565,
   137       SDL_PIXELFORMAT_RGB24,
   138       SDL_PIXELFORMAT_BGR24,
   139       SDL_PIXELFORMAT_RGB888,
   140       SDL_PIXELFORMAT_BGR888,
   141       SDL_PIXELFORMAT_ARGB8888,
   142       SDL_PIXELFORMAT_ABGR8888,
   143       SDL_PIXELFORMAT_ARGB2101010},
   144      0,
   145      0}
   146 };
   147 
   148 typedef struct
   149 {
   150     SDL_GLContext context;
   151     SDL_bool updateSize;
   152     SDL_bool GL_ARB_texture_rectangle_supported;
   153     SDL_bool GL_EXT_paletted_texture_supported;
   154     SDL_bool GL_APPLE_ycbcr_422_supported;
   155     SDL_bool GL_MESA_ycbcr_texture_supported;
   156     SDL_bool GL_ARB_fragment_program_supported;
   157     int blendMode;
   158     int scaleMode;
   159 
   160     /* OpenGL functions */
   161 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
   162 #include "SDL_glfuncs.h"
   163 #undef SDL_PROC
   164 
   165     PFNGLCOLORTABLEEXTPROC glColorTableEXT;
   166     void (*glTextureRangeAPPLE) (GLenum target, GLsizei length,
   167                                  const GLvoid * pointer);
   168 
   169     PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
   170     PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
   171     PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
   172     PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
   173     PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
   174     PFNGLBINDPROGRAMARBPROC glBindProgramARB;
   175     PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
   176 
   177     /* (optional) fragment programs */
   178     GLuint fragment_program_UYVY;
   179 } GL_RenderData;
   180 
   181 typedef struct
   182 {
   183     GLuint texture;
   184     GLuint shader;
   185     GLenum type;
   186     GLfloat texw;
   187     GLfloat texh;
   188     GLenum format;
   189     GLenum formattype;
   190     Uint8 *palette;
   191     void *pixels;
   192     int pitch;
   193     SDL_DirtyRectList dirty;
   194     int HACK_RYAN_FIXME;
   195 } GL_TextureData;
   196 
   197 
   198 static void
   199 GL_SetError(const char *prefix, GLenum result)
   200 {
   201     const char *error;
   202 
   203     switch (result) {
   204     case GL_NO_ERROR:
   205         error = "GL_NO_ERROR";
   206         break;
   207     case GL_INVALID_ENUM:
   208         error = "GL_INVALID_ENUM";
   209         break;
   210     case GL_INVALID_VALUE:
   211         error = "GL_INVALID_VALUE";
   212         break;
   213     case GL_INVALID_OPERATION:
   214         error = "GL_INVALID_OPERATION";
   215         break;
   216     case GL_STACK_OVERFLOW:
   217         error = "GL_STACK_OVERFLOW";
   218         break;
   219     case GL_STACK_UNDERFLOW:
   220         error = "GL_STACK_UNDERFLOW";
   221         break;
   222     case GL_OUT_OF_MEMORY:
   223         error = "GL_OUT_OF_MEMORY";
   224         break;
   225     case GL_TABLE_TOO_LARGE:
   226         error = "GL_TABLE_TOO_LARGE";
   227         break;
   228     default:
   229         error = "UNKNOWN";
   230         break;
   231     }
   232     SDL_SetError("%s: %s", prefix, error);
   233 }
   234 
   235 static int
   236 GL_LoadFunctions(GL_RenderData * data)
   237 {
   238 #if defined(__QNXNTO__) && (_NTO_VERSION < 630)
   239 #define __SDL_NOGETPROCADDR__
   240 #endif
   241 #ifdef __SDL_NOGETPROCADDR__
   242 #define SDL_PROC(ret,func,params) data->func=func;
   243 #else
   244 #define SDL_PROC(ret,func,params) \
   245     do { \
   246         data->func = SDL_GL_GetProcAddress(#func); \
   247         if ( ! data->func ) { \
   248             SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
   249             return -1; \
   250         } \
   251     } while ( 0 );
   252 #endif /* __SDL_NOGETPROCADDR__ */
   253 
   254 #include "SDL_glfuncs.h"
   255 #undef SDL_PROC
   256     return 0;
   257 }
   258 
   259 void
   260 GL_AddRenderDriver(_THIS)
   261 {
   262     if (_this->GL_CreateContext) {
   263         SDL_AddRenderDriver(0, &GL_RenderDriver);
   264     }
   265 }
   266 
   267 SDL_Renderer *
   268 GL_CreateRenderer(SDL_Window * window, Uint32 flags)
   269 {
   270     SDL_Renderer *renderer;
   271     GL_RenderData *data;
   272     GLint value;
   273     int doublebuffer;
   274 
   275     /* Render directly to the window, unless we're compositing */
   276 #ifndef __MACOSX__
   277     if (flags & SDL_RENDERER_SINGLEBUFFER) {
   278         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
   279     }
   280 #endif
   281     if (!(window->flags & SDL_WINDOW_OPENGL)) {
   282         if (SDL_RecreateWindow(window, window->flags | SDL_WINDOW_OPENGL) < 0) {
   283             return NULL;
   284         }
   285     }
   286 
   287     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   288     if (!renderer) {
   289         SDL_OutOfMemory();
   290         return NULL;
   291     }
   292 
   293     data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
   294     if (!data) {
   295         GL_DestroyRenderer(renderer);
   296         SDL_OutOfMemory();
   297         return NULL;
   298     }
   299 
   300     renderer->ActivateRenderer = GL_ActivateRenderer;
   301     renderer->DisplayModeChanged = GL_DisplayModeChanged;
   302     renderer->CreateTexture = GL_CreateTexture;
   303     renderer->QueryTexturePixels = GL_QueryTexturePixels;
   304     renderer->SetTexturePalette = GL_SetTexturePalette;
   305     renderer->GetTexturePalette = GL_GetTexturePalette;
   306     renderer->SetTextureColorMod = GL_SetTextureColorMod;
   307     renderer->SetTextureAlphaMod = GL_SetTextureAlphaMod;
   308     renderer->SetTextureBlendMode = GL_SetTextureBlendMode;
   309     renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
   310     renderer->UpdateTexture = GL_UpdateTexture;
   311     renderer->LockTexture = GL_LockTexture;
   312     renderer->UnlockTexture = GL_UnlockTexture;
   313     renderer->DirtyTexture = GL_DirtyTexture;
   314     renderer->RenderPoint = GL_RenderPoint;
   315     renderer->RenderLine = GL_RenderLine;
   316     renderer->RenderFill = GL_RenderFill;
   317     renderer->RenderCopy = GL_RenderCopy;
   318     renderer->RenderReadPixels = GL_RenderReadPixels;
   319     renderer->RenderWritePixels = GL_RenderWritePixels;
   320     renderer->RenderPresent = GL_RenderPresent;
   321     renderer->DestroyTexture = GL_DestroyTexture;
   322     renderer->DestroyRenderer = GL_DestroyRenderer;
   323     renderer->info = GL_RenderDriver.info;
   324     renderer->window = window->id;
   325     renderer->driverdata = data;
   326 
   327     renderer->info.flags =
   328         (SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED);
   329 
   330     if (GL_LoadFunctions(data) < 0) {
   331         GL_DestroyRenderer(renderer);
   332         return NULL;
   333     }
   334 
   335     data->context = SDL_GL_CreateContext(window->id);
   336     if (!data->context) {
   337         GL_DestroyRenderer(renderer);
   338         return NULL;
   339     }
   340     if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
   341         GL_DestroyRenderer(renderer);
   342         return NULL;
   343     }
   344 #ifdef __MACOSX__
   345     /* Enable multi-threaded rendering */
   346     /* Disabled until Ryan finishes his VBO/PBO code...
   347        CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
   348      */
   349 #endif
   350 
   351     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   352         SDL_GL_SetSwapInterval(1);
   353     } else {
   354         SDL_GL_SetSwapInterval(0);
   355     }
   356     if (SDL_GL_GetSwapInterval() > 0) {
   357         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   358     }
   359 
   360     if (SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer) == 0) {
   361         if (!doublebuffer) {
   362             renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
   363         }
   364     }
   365 
   366     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
   367     renderer->info.max_texture_width = value;
   368     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
   369     renderer->info.max_texture_height = value;
   370 
   371     if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
   372         || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
   373         data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
   374     }
   375     if (SDL_GL_ExtensionSupported("GL_EXT_paletted_texture")) {
   376         data->GL_EXT_paletted_texture_supported = SDL_TRUE;
   377         data->glColorTableEXT =
   378             (PFNGLCOLORTABLEEXTPROC) SDL_GL_GetProcAddress("glColorTableEXT");
   379     } else {
   380         /* Don't advertise support for 8-bit indexed texture format */
   381         Uint32 i, j;
   382         SDL_RendererInfo *info = &renderer->info;
   383         for (i = 0, j = 0; i < info->num_texture_formats; ++i) {
   384             if (info->texture_formats[i] != SDL_PIXELFORMAT_INDEX8) {
   385                 info->texture_formats[j++] = info->texture_formats[i];
   386             }
   387         }
   388         --info->num_texture_formats;
   389     }
   390     if (SDL_GL_ExtensionSupported("GL_APPLE_ycbcr_422")) {
   391         data->GL_APPLE_ycbcr_422_supported = SDL_TRUE;
   392     }
   393     if (SDL_GL_ExtensionSupported("GL_MESA_ycbcr_texture")) {
   394         data->GL_MESA_ycbcr_texture_supported = SDL_TRUE;
   395     }
   396     if (SDL_GL_ExtensionSupported("GL_APPLE_texture_range")) {
   397         data->glTextureRangeAPPLE =
   398             (void (*)(GLenum, GLsizei, const GLvoid *))
   399             SDL_GL_GetProcAddress("glTextureRangeAPPLE");
   400     }
   401 
   402     /* we might use fragment programs for YUV data, etc. */
   403     if (SDL_GL_ExtensionSupported("GL_ARB_fragment_program")) {
   404         /* !!! FIXME: this doesn't check for errors. */
   405         /* !!! FIXME: this should really reuse the glfuncs.h stuff. */
   406         data->glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)
   407             SDL_GL_GetProcAddress("glGetProgramivARB");
   408         data->glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC)
   409             SDL_GL_GetProcAddress("glGetProgramStringARB");
   410         data->glProgramLocalParameter4fvARB =
   411             (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)
   412             SDL_GL_GetProcAddress("glProgramLocalParameter4fvARB");
   413         data->glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)
   414             SDL_GL_GetProcAddress("glDeleteProgramsARB");
   415         data->glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)
   416             SDL_GL_GetProcAddress("glGenProgramsARB");
   417         data->glBindProgramARB = (PFNGLBINDPROGRAMARBPROC)
   418             SDL_GL_GetProcAddress("glBindProgramARB");
   419         data->glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)
   420             SDL_GL_GetProcAddress("glProgramStringARB");
   421         data->GL_ARB_fragment_program_supported = SDL_TRUE;
   422     }
   423 
   424     /* Set up parameters for rendering */
   425     data->blendMode = -1;
   426     data->scaleMode = -1;
   427     data->glDisable(GL_DEPTH_TEST);
   428     data->glDisable(GL_CULL_FACE);
   429     /* This ended up causing video discrepancies between OpenGL and Direct3D */
   430     /*data->glEnable(GL_LINE_SMOOTH);*/
   431     if (data->GL_ARB_texture_rectangle_supported) {
   432         data->glEnable(GL_TEXTURE_RECTANGLE_ARB);
   433     } else {
   434         data->glEnable(GL_TEXTURE_2D);
   435     }
   436     data->updateSize = SDL_TRUE;
   437 
   438     return renderer;
   439 }
   440 
   441 static int
   442 GL_ActivateRenderer(SDL_Renderer * renderer)
   443 {
   444     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   445     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   446 
   447     if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
   448         return -1;
   449     }
   450     if (data->updateSize) {
   451         data->glMatrixMode(GL_PROJECTION);
   452         data->glLoadIdentity();
   453         data->glMatrixMode(GL_MODELVIEW);
   454         data->glLoadIdentity();
   455         data->glViewport(0, 0, window->w, window->h);
   456         data->glOrtho(0.0, (GLdouble) window->w,
   457                       (GLdouble) window->h, 0.0, 0.0, 1.0);
   458         data->updateSize = SDL_FALSE;
   459     }
   460     return 0;
   461 }
   462 
   463 static int
   464 GL_DisplayModeChanged(SDL_Renderer * renderer)
   465 {
   466     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   467 
   468     /* Rebind the context to the window area and update matrices */
   469     data->updateSize = SDL_TRUE;
   470     return GL_ActivateRenderer(renderer);
   471 }
   472 
   473 static __inline__ int
   474 power_of_2(int input)
   475 {
   476     int value = 1;
   477 
   478     while (value < input) {
   479         value <<= 1;
   480     }
   481     return value;
   482 }
   483 
   484 
   485 //#define DEBUG_PROGRAM_COMPILE 1
   486 
   487 static GLuint
   488 compile_shader(GL_RenderData * data, GLenum shader_type, const char *_code)
   489 {
   490     const int have_texture_rects = data->GL_ARB_texture_rectangle_supported;
   491     const char *replacement = have_texture_rects ? "RECT" : "2D";
   492     const size_t replacementlen = SDL_strlen(replacement);
   493     const char *token = "%TEXTURETARGET%";
   494     const size_t tokenlen = SDL_strlen(token);
   495     char *code = NULL;
   496     char *ptr = NULL;
   497     GLuint program = 0;
   498 
   499     /*
   500      * The TEX instruction needs a different target depending on what we use.
   501      *  To handle this, we use "%TEXTURETARGET%" and replace the string before
   502      *  compiling the shader.
   503      */
   504     code = SDL_strdup(_code);
   505     if (code == NULL)
   506         return 0;
   507 
   508     for (ptr = SDL_strstr(code, token); ptr; ptr = SDL_strstr(ptr + 1, token)) {
   509         SDL_memcpy(ptr, replacement, replacementlen);
   510         SDL_memmove(ptr + replacementlen, ptr + tokenlen,
   511                     SDL_strlen(ptr + tokenlen) + 1);
   512     }
   513 
   514 #if DEBUG_PROGRAM_COMPILE
   515     printf("compiling shader:\n%s\n\n", code);
   516 #endif
   517 
   518     data->glGetError();         /* flush any existing error state. */
   519     data->glGenProgramsARB(1, &program);
   520     data->glBindProgramARB(shader_type, program);
   521     data->glProgramStringARB(shader_type, GL_PROGRAM_FORMAT_ASCII_ARB,
   522                              (GLsizei)SDL_strlen(code), code);
   523 
   524     SDL_free(code);
   525 
   526     if (data->glGetError() == GL_INVALID_OPERATION) {
   527 #if DEBUG_PROGRAM_COMPILE
   528         GLint pos = 0;
   529         const GLubyte *errstr;
   530         data->glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
   531         errstr = data->glGetString(GL_PROGRAM_ERROR_STRING_ARB);
   532         printf("program compile error at position %d: %s\n\n",
   533                (int) pos, (const char *) errstr);
   534 #endif
   535         data->glBindProgramARB(shader_type, 0);
   536         data->glDeleteProgramsARB(1, &program);
   537         return 0;
   538     }
   539 
   540     return program;
   541 }
   542 
   543 
   544 /*
   545  * Fragment program that renders from UYVY textures.
   546  * The UYVY to RGB equasion is:
   547  *   R = 1.164(Y-16) + 1.596(Cr-128)
   548  *   G = 1.164(Y-16) - 0.813(Cr-128) - 0.391(Cb-128)
   549  *   B = 1.164(Y-16) + 2.018(Cb-128)
   550  * Byte layout is Cb, Y1, Cr, Y2, stored in the R, G, B, A channels.
   551  * 4 bytes == 2 pixels: Y1/Cb/Cr, Y2/Cb/Cr
   552  *
   553  * !!! FIXME: this ignores blendmodes, etc.
   554  * !!! FIXME: this could be more efficient...use a dot product for green, etc.
   555  */
   556 static const char *fragment_program_UYVY_source_code = "!!ARBfp1.0\n"
   557     /* outputs... */
   558     "OUTPUT outcolor = result.color;\n"
   559     /* scratch registers... */
   560     "TEMP uyvy;\n" "TEMP luminance;\n" "TEMP work;\n"
   561     /* Halve the coordinates to grab the correct 32 bits for the fragment. */
   562     "MUL work, fragment.texcoord, { 0.5, 1.0, 1.0, 1.0 };\n"
   563     /* Sample the YUV texture. Cb, Y1, Cr, Y2, are stored in x, y, z, w. */
   564     "TEX uyvy, work, texture[0], %TEXTURETARGET%;\n"
   565     /* Do subtractions (128/255, 16/255, 128/255, 16/255) */
   566     "SUB uyvy, uyvy, { 0.501960784313726, 0.06274509803922, 0.501960784313726, 0.06274509803922 };\n"
   567     /* Choose the luminance component by texcoord. */
   568     /* !!! FIXME: laziness wins out for now... just average Y1 and Y2. */
   569     "ADD luminance, uyvy.yyyy, uyvy.wwww;\n"
   570     "MUL luminance, luminance, { 0.5, 0.5, 0.5, 0.5 };\n"
   571     /* Multiply luminance by its magic value. */
   572     "MUL luminance, luminance, { 1.164, 1.164, 1.164, 1.164 };\n"
   573     /* uyvy.xyzw becomes Cr/Cr/Cb/Cb, with multiplications. */
   574     "MUL uyvy, uyvy.zzxx, { 1.596, -0.813, 2.018, -0.391 };\n"
   575     /* Add luminance to Cr and Cb, store to RGB channels. */
   576     "ADD work.rgb, luminance, uyvy;\n"
   577     /* Do final addition for Green channel.  (!!! FIXME: this should be a DPH?) */
   578     "ADD work.g, work.g, uyvy.w;\n"
   579     /* Make sure alpha channel is fully opaque.  (!!! FIXME: blend modes!) */
   580     "MOV work.a, { 1.0 };\n"
   581     /* Store out the final fragment color... */
   582     "MOV outcolor, work;\n"
   583     /* ...and we're done! */
   584     "END\n";
   585 
   586 static __inline__ SDL_bool
   587 convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
   588                GLint* internalFormat, GLenum* format, GLenum* type)
   589 {
   590     switch (pixel_format) {
   591     case SDL_PIXELFORMAT_INDEX1LSB:
   592     case SDL_PIXELFORMAT_INDEX1MSB:
   593         *internalFormat = GL_RGB;
   594         *format = GL_COLOR_INDEX;
   595         *type = GL_BITMAP;
   596         break;
   597     case SDL_PIXELFORMAT_INDEX8:
   598         if (!renderdata->GL_EXT_paletted_texture_supported) {
   599             return SDL_FALSE;
   600         }
   601         *internalFormat = GL_COLOR_INDEX8_EXT;
   602         *format = GL_COLOR_INDEX;
   603         *type = GL_UNSIGNED_BYTE;
   604         break;
   605     case SDL_PIXELFORMAT_RGB332:
   606         *internalFormat = GL_R3_G3_B2;
   607         *format = GL_RGB;
   608         *type = GL_UNSIGNED_BYTE_3_3_2;
   609         break;
   610     case SDL_PIXELFORMAT_RGB444:
   611         *internalFormat = GL_RGB4;
   612         *format = GL_RGB;
   613         *type = GL_UNSIGNED_SHORT_4_4_4_4;
   614         break;
   615     case SDL_PIXELFORMAT_RGB555:
   616         *internalFormat = GL_RGB5;
   617         *format = GL_RGB;
   618         *type = GL_UNSIGNED_SHORT_5_5_5_1;
   619         break;
   620     case SDL_PIXELFORMAT_ARGB4444:
   621         *internalFormat = GL_RGBA4;
   622         *format = GL_BGRA;
   623         *type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
   624         break;
   625     case SDL_PIXELFORMAT_ARGB1555:
   626         *internalFormat = GL_RGB5_A1;
   627         *format = GL_BGRA;
   628         *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
   629         break;
   630     case SDL_PIXELFORMAT_RGB565:
   631         *internalFormat = GL_RGB8;
   632         *format = GL_RGB;
   633         *type = GL_UNSIGNED_SHORT_5_6_5;
   634         break;
   635     case SDL_PIXELFORMAT_RGB24:
   636         *internalFormat = GL_RGB8;
   637         *format = GL_RGB;
   638         *type = GL_UNSIGNED_BYTE;
   639         break;
   640     case SDL_PIXELFORMAT_RGB888:
   641         *internalFormat = GL_RGB8;
   642         *format = GL_BGRA;
   643         *type = GL_UNSIGNED_BYTE;
   644         break;
   645     case SDL_PIXELFORMAT_BGR24:
   646         *internalFormat = GL_RGB8;
   647         *format = GL_BGR;
   648         *type = GL_UNSIGNED_BYTE;
   649         break;
   650     case SDL_PIXELFORMAT_BGR888:
   651         *internalFormat = GL_RGB8;
   652         *format = GL_RGBA;
   653         *type = GL_UNSIGNED_BYTE;
   654         break;
   655     case SDL_PIXELFORMAT_ARGB8888:
   656 #ifdef __MACOSX__
   657         *internalFormat = GL_RGBA;
   658         *format = GL_BGRA;
   659         *type = GL_UNSIGNED_INT_8_8_8_8_REV;
   660 #else
   661         *internalFormat = GL_RGBA8;
   662         *format = GL_BGRA;
   663         *type = GL_UNSIGNED_BYTE;
   664 #endif
   665         break;
   666     case SDL_PIXELFORMAT_ABGR8888:
   667         *internalFormat = GL_RGBA8;
   668         *format = GL_RGBA;
   669         *type = GL_UNSIGNED_BYTE;
   670         break;
   671     case SDL_PIXELFORMAT_ARGB2101010:
   672         *internalFormat = GL_RGB10_A2;
   673         *format = GL_BGRA;
   674         *type = GL_UNSIGNED_INT_2_10_10_10_REV;
   675         break;
   676     case SDL_PIXELFORMAT_UYVY:
   677         if (renderdata->GL_APPLE_ycbcr_422_supported) {
   678             *internalFormat = GL_RGB;
   679             *format = GL_YCBCR_422_APPLE;
   680 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   681             *type = GL_UNSIGNED_SHORT_8_8_APPLE;
   682 #else
   683             *type = GL_UNSIGNED_SHORT_8_8_REV_APPLE;
   684 #endif
   685         } else if (renderdata->GL_MESA_ycbcr_texture_supported) {
   686             *internalFormat = GL_RGB;
   687             *format = GL_YCBCR_MESA;
   688 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   689             *type = GL_UNSIGNED_SHORT_8_8_MESA;
   690 #else
   691             *type = GL_UNSIGNED_SHORT_8_8_REV_MESA;
   692 #endif
   693         } else if (renderdata->GL_ARB_fragment_program_supported) {
   694             *internalFormat = GL_RGBA;
   695             *format = GL_RGBA;
   696             *type = GL_UNSIGNED_BYTE;
   697         } else {
   698             return SDL_FALSE;
   699         }
   700         break;
   701     case SDL_PIXELFORMAT_YUY2:
   702         if (renderdata->GL_APPLE_ycbcr_422_supported) {
   703             *internalFormat = GL_RGB;
   704             *format = GL_YCBCR_422_APPLE;
   705 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   706             *type = GL_UNSIGNED_SHORT_8_8_REV_APPLE;
   707 #else
   708             *type = GL_UNSIGNED_SHORT_8_8_APPLE;
   709 #endif
   710         } else if (renderdata->GL_MESA_ycbcr_texture_supported) {
   711             *internalFormat = GL_RGB;
   712             *format = GL_YCBCR_MESA;
   713 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   714             *type = GL_UNSIGNED_SHORT_8_8_REV_MESA;
   715 #else
   716             *type = GL_UNSIGNED_SHORT_8_8_MESA;
   717 #endif
   718         } else {
   719             return SDL_FALSE;
   720         }
   721         break;
   722     default:
   723         return SDL_FALSE;
   724     }
   725     return SDL_TRUE;
   726 }
   727 
   728 static int
   729 GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   730 {
   731     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   732     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   733     GL_TextureData *data;
   734     GLint internalFormat;
   735     GLenum format, type;
   736     int texture_w, texture_h;
   737     GLuint shader = 0;
   738     GLenum result;
   739 
   740     if (!convert_format(renderdata, texture->format, &internalFormat,
   741                         &format, &type)) {
   742         SDL_SetError("Unsupported texture format");
   743         return -1;
   744     }
   745     if (texture->format == SDL_PIXELFORMAT_UYVY &&
   746         !renderdata->GL_APPLE_ycbcr_422_supported &&
   747         !renderdata->GL_MESA_ycbcr_texture_supported &&
   748         renderdata->GL_ARB_fragment_program_supported) {
   749         if (renderdata->fragment_program_UYVY == 0) {
   750             renderdata->fragment_program_UYVY =
   751                 compile_shader(renderdata, GL_FRAGMENT_PROGRAM_ARB,
   752                                fragment_program_UYVY_source_code);
   753             if (renderdata->fragment_program_UYVY == 0) {
   754                 SDL_SetError("Fragment program compile error");
   755                 return -1;
   756             }
   757         }
   758         shader = renderdata->fragment_program_UYVY;
   759     }
   760 
   761     data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
   762     if (!data) {
   763         SDL_OutOfMemory();
   764         return -1;
   765     }
   766 
   767     data->shader = shader;
   768 
   769     if (texture->format == SDL_PIXELFORMAT_INDEX8) {
   770         data->palette = (Uint8 *) SDL_malloc(3 * 256 * sizeof(Uint8));
   771         if (!data->palette) {
   772             SDL_OutOfMemory();
   773             SDL_free(data);
   774             return -1;
   775         }
   776         SDL_memset(data->palette, 0xFF, 3 * 256 * sizeof(Uint8));
   777     }
   778 
   779     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   780         data->pitch = texture->w * bytes_per_pixel(texture->format);
   781         data->pixels = SDL_malloc(texture->h * data->pitch);
   782         if (!data->pixels) {
   783             SDL_OutOfMemory();
   784             SDL_free(data);
   785             return -1;
   786         }
   787     }
   788 
   789     texture->driverdata = data;
   790 
   791     renderdata->glGetError();
   792     renderdata->glGenTextures(1, &data->texture);
   793     if (renderdata->GL_ARB_texture_rectangle_supported) {
   794         data->type = GL_TEXTURE_RECTANGLE_ARB;
   795         texture_w = texture->w;
   796         texture_h = texture->h;
   797         data->texw = (GLfloat) texture_w;
   798         data->texh = (GLfloat) texture_h;
   799     } else {
   800         data->type = GL_TEXTURE_2D;
   801         texture_w = power_of_2(texture->w);
   802         texture_h = power_of_2(texture->h);
   803         data->texw = (GLfloat) (texture->w) / texture_w;
   804         data->texh = (GLfloat) texture->h / texture_h;
   805     }
   806 
   807     /* YUV formats use RGBA but are really two bytes per pixel */
   808     if (internalFormat == GL_RGBA && bytes_per_pixel(texture->format) < 4) {
   809         data->HACK_RYAN_FIXME = 2;
   810     } else {
   811         data->HACK_RYAN_FIXME = 1;
   812     }
   813     texture_w /= data->HACK_RYAN_FIXME;
   814 
   815     data->format = format;
   816     data->formattype = type;
   817     renderdata->glEnable(data->type);
   818     renderdata->glBindTexture(data->type, data->texture);
   819     renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
   820                                 GL_NEAREST);
   821     renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
   822                                 GL_NEAREST);
   823     renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
   824                                 GL_CLAMP_TO_EDGE);
   825     renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
   826                                 GL_CLAMP_TO_EDGE);
   827 #ifdef __MACOSX__
   828 #ifndef GL_TEXTURE_STORAGE_HINT_APPLE
   829 #define GL_TEXTURE_STORAGE_HINT_APPLE       0x85BC
   830 #endif
   831 #ifndef STORAGE_CACHED_APPLE
   832 #define STORAGE_CACHED_APPLE                0x85BE
   833 #endif
   834 #ifndef STORAGE_SHARED_APPLE
   835 #define STORAGE_SHARED_APPLE                0x85BF
   836 #endif
   837     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   838         renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
   839                                     GL_STORAGE_SHARED_APPLE);
   840     } else {
   841         renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
   842                                     GL_STORAGE_CACHED_APPLE);
   843     }
   844 /* This causes a crash in testoverlay for some reason.  Apple bug? */
   845 #if 0
   846     if (texture->access == SDL_TEXTUREACCESS_STREAMING
   847         && texture->format == SDL_PIXELFORMAT_ARGB8888) {
   848         /*
   849            if (renderdata->glTextureRangeAPPLE) {
   850            renderdata->glTextureRangeAPPLE(data->type,
   851            texture->h * data->pitch,
   852            data->pixels);
   853            }
   854          */
   855         renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
   856         renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
   857                                  texture_h, 0, format, type, data->pixels);
   858     } else
   859 #endif
   860 #endif
   861     {
   862         renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
   863                                  texture_h, 0, format, type, NULL);
   864     }
   865     renderdata->glDisable(data->type);
   866     result = renderdata->glGetError();
   867     if (result != GL_NO_ERROR) {
   868         GL_SetError("glTexImage2D()", result);
   869         return -1;
   870     }
   871     return 0;
   872 }
   873 
   874 static int
   875 GL_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   876                       void **pixels, int *pitch)
   877 {
   878     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   879 
   880     *pixels = data->pixels;
   881     *pitch = data->pitch;
   882     return 0;
   883 }
   884 
   885 static int
   886 GL_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   887                      const SDL_Color * colors, int firstcolor, int ncolors)
   888 {
   889     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   890     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   891     Uint8 *palette;
   892 
   893     if (!data->palette) {
   894         SDL_SetError("Texture doesn't have a palette");
   895         return -1;
   896     }
   897     palette = data->palette + firstcolor * 3;
   898     while (ncolors--) {
   899         *palette++ = colors->r;
   900         *palette++ = colors->g;
   901         *palette++ = colors->b;
   902         ++colors;
   903     }
   904     renderdata->glEnable(data->type);
   905     renderdata->glBindTexture(data->type, data->texture);
   906     renderdata->glColorTableEXT(data->type, GL_RGB8, 256, GL_RGB,
   907                                 GL_UNSIGNED_BYTE, data->palette);
   908     return 0;
   909 }
   910 
   911 static int
   912 GL_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   913                      SDL_Color * colors, int firstcolor, int ncolors)
   914 {
   915     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   916     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   917     Uint8 *palette;
   918 
   919     if (!data->palette) {
   920         SDL_SetError("Texture doesn't have a palette");
   921         return -1;
   922     }
   923     palette = data->palette + firstcolor * 3;
   924     while (ncolors--) {
   925         colors->r = *palette++;
   926         colors->g = *palette++;
   927         colors->b = *palette++;
   928         colors->unused = SDL_ALPHA_OPAQUE;
   929         ++colors;
   930     }
   931     return 0;
   932 }
   933 
   934 static void
   935 SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
   936                    int pitch)
   937 {
   938     if (texture->format == SDL_PIXELFORMAT_INDEX1LSB) {
   939         renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
   940     } else if (texture->format == SDL_PIXELFORMAT_INDEX1MSB) {
   941         renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
   942     }
   943     renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   944     renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
   945                               (pitch / bytes_per_pixel(texture->format)) /
   946                               ((GL_TextureData *) texture->driverdata)->
   947                               HACK_RYAN_FIXME);
   948 }
   949 
   950 static int
   951 GL_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   952 {
   953     return 0;
   954 }
   955 
   956 static int
   957 GL_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   958 {
   959     return 0;
   960 }
   961 
   962 static int
   963 GL_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   964 {
   965     switch (texture->blendMode) {
   966     case SDL_BLENDMODE_NONE:
   967     case SDL_BLENDMODE_MASK:
   968     case SDL_BLENDMODE_BLEND:
   969     case SDL_BLENDMODE_ADD:
   970     case SDL_BLENDMODE_MOD:
   971         return 0;
   972     default:
   973         SDL_Unsupported();
   974         texture->blendMode = SDL_BLENDMODE_NONE;
   975         return -1;
   976     }
   977 }
   978 
   979 static int
   980 GL_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   981 {
   982     switch (texture->scaleMode) {
   983     case SDL_TEXTURESCALEMODE_NONE:
   984     case SDL_TEXTURESCALEMODE_FAST:
   985     case SDL_TEXTURESCALEMODE_SLOW:
   986         return 0;
   987     case SDL_TEXTURESCALEMODE_BEST:
   988         SDL_Unsupported();
   989         texture->scaleMode = SDL_TEXTURESCALEMODE_SLOW;
   990         return -1;
   991     default:
   992         SDL_Unsupported();
   993         texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
   994         return -1;
   995     }
   996 }
   997 
   998 static int
   999 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  1000                  const SDL_Rect * rect, const void *pixels, int pitch)
  1001 {
  1002     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
  1003     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
  1004     GLenum result;
  1005 
  1006     renderdata->glGetError();
  1007     SetupTextureUpdate(renderdata, texture, pitch);
  1008     renderdata->glEnable(data->type);
  1009     renderdata->glBindTexture(data->type, data->texture);
  1010     renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
  1011                                 rect->h, data->format, data->formattype,
  1012                                 pixels);
  1013     renderdata->glDisable(data->type);
  1014     result = renderdata->glGetError();
  1015     if (result != GL_NO_ERROR) {
  1016         GL_SetError("glTexSubImage2D()", result);
  1017         return -1;
  1018     }
  1019     return 0;
  1020 }
  1021 
  1022 static int
  1023 GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
  1024                const SDL_Rect * rect, int markDirty, void **pixels,
  1025                int *pitch)
  1026 {
  1027     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
  1028 
  1029     if (markDirty) {
  1030         SDL_AddDirtyRect(&data->dirty, rect);
  1031     }
  1032 
  1033     *pixels =
  1034         (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
  1035                   rect->x * bytes_per_pixel(texture->format));
  1036     *pitch = data->pitch;
  1037     return 0;
  1038 }
  1039 
  1040 static void
  1041 GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1042 {
  1043 }
  1044 
  1045 static void
  1046 GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
  1047                 const SDL_Rect * rects)
  1048 {
  1049     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
  1050     int i;
  1051 
  1052     for (i = 0; i < numrects; ++i) {
  1053         SDL_AddDirtyRect(&data->dirty, &rects[i]);
  1054     }
  1055 }
  1056 
  1057 static void
  1058 GL_SetBlendMode(GL_RenderData * data, int blendMode, int isprimitive)
  1059 {
  1060     if (blendMode != data->blendMode) {
  1061         switch (blendMode) {
  1062         case SDL_BLENDMODE_NONE:
  1063             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  1064             data->glDisable(GL_BLEND);
  1065             break;
  1066         case SDL_BLENDMODE_MASK:
  1067             if (isprimitive) {
  1068                 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  1069                 data->glDisable(GL_BLEND);
  1070                 /* The same as SDL_BLENDMODE_NONE */
  1071                 blendMode = SDL_BLENDMODE_NONE;
  1072                 break;
  1073             }
  1074             /* fall through */
  1075         case SDL_BLENDMODE_BLEND:
  1076             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1077             data->glEnable(GL_BLEND);
  1078             data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1079             break;
  1080         case SDL_BLENDMODE_ADD:
  1081             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1082             data->glEnable(GL_BLEND);
  1083             data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  1084             break;
  1085         case SDL_BLENDMODE_MOD:
  1086             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1087             data->glEnable(GL_BLEND);
  1088             data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
  1089             break;
  1090         }
  1091         data->blendMode = blendMode;
  1092     }
  1093 }
  1094 
  1095 static int
  1096 GL_RenderPoint(SDL_Renderer * renderer, int x, int y)
  1097 {
  1098     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1099 
  1100     GL_SetBlendMode(data, renderer->blendMode, 1);
  1101 
  1102     data->glColor4f((GLfloat) renderer->r * inv255f,
  1103                     (GLfloat) renderer->g * inv255f,
  1104                     (GLfloat) renderer->b * inv255f,
  1105                     (GLfloat) renderer->a * inv255f);
  1106 
  1107     data->glBegin(GL_POINTS);
  1108     data->glVertex2i(x, y);
  1109     data->glEnd();
  1110 
  1111     return 0;
  1112 }
  1113 
  1114 static int
  1115 GL_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
  1116 {
  1117     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1118 
  1119     GL_SetBlendMode(data, renderer->blendMode, 1);
  1120 
  1121     data->glColor4f((GLfloat) renderer->r * inv255f,
  1122                     (GLfloat) renderer->g * inv255f,
  1123                     (GLfloat) renderer->b * inv255f,
  1124                     (GLfloat) renderer->a * inv255f);
  1125 
  1126     data->glBegin(GL_LINES);
  1127     data->glVertex2i(x1, y1);
  1128     data->glVertex2i(x2, y2);
  1129     data->glEnd();
  1130 
  1131     return 0;
  1132 }
  1133 
  1134 static int
  1135 GL_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
  1136 {
  1137     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1138 
  1139     GL_SetBlendMode(data, renderer->blendMode, 1);
  1140 
  1141     data->glColor4f((GLfloat) renderer->r * inv255f,
  1142                     (GLfloat) renderer->g * inv255f,
  1143                     (GLfloat) renderer->b * inv255f,
  1144                     (GLfloat) renderer->a * inv255f);
  1145 
  1146     data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
  1147 
  1148     return 0;
  1149 }
  1150 
  1151 static int
  1152 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
  1153               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
  1154 {
  1155     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1156     GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
  1157     int minx, miny, maxx, maxy;
  1158     GLfloat minu, maxu, minv, maxv;
  1159 
  1160     if (texturedata->dirty.list) {
  1161         SDL_DirtyRect *dirty;
  1162         void *pixels;
  1163         int bpp = bytes_per_pixel(texture->format);
  1164         int pitch = texturedata->pitch;
  1165 
  1166         SetupTextureUpdate(data, texture, pitch);
  1167         data->glEnable(texturedata->type);
  1168         data->glBindTexture(texturedata->type, texturedata->texture);
  1169         for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
  1170             SDL_Rect *rect = &dirty->rect;
  1171             pixels =
  1172                 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
  1173                           rect->x * bpp);
  1174             data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
  1175                                   rect->w / texturedata->HACK_RYAN_FIXME,
  1176                                   rect->h, texturedata->format,
  1177                                   texturedata->formattype, pixels);
  1178         }
  1179         SDL_ClearDirtyRects(&texturedata->dirty);
  1180     }
  1181 
  1182     minx = dstrect->x;
  1183     miny = dstrect->y;
  1184     maxx = dstrect->x + dstrect->w;
  1185     maxy = dstrect->y + dstrect->h;
  1186 
  1187     minu = (GLfloat) srcrect->x / texture->w;
  1188     minu *= texturedata->texw;
  1189     maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
  1190     maxu *= texturedata->texw;
  1191     minv = (GLfloat) srcrect->y / texture->h;
  1192     minv *= texturedata->texh;
  1193     maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
  1194     maxv *= texturedata->texh;
  1195 
  1196     data->glEnable(texturedata->type);
  1197     data->glBindTexture(texturedata->type, texturedata->texture);
  1198 
  1199     if (texture->modMode) {
  1200         data->glColor4f((GLfloat) texture->r * inv255f,
  1201                         (GLfloat) texture->g * inv255f,
  1202                         (GLfloat) texture->b * inv255f,
  1203                         (GLfloat) texture->a * inv255f);
  1204     } else {
  1205         data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  1206     }
  1207 
  1208     GL_SetBlendMode(data, texture->blendMode, 0);
  1209 
  1210     if (texture->scaleMode != data->scaleMode) {
  1211         switch (texture->scaleMode) {
  1212         case SDL_TEXTURESCALEMODE_NONE:
  1213         case SDL_TEXTURESCALEMODE_FAST:
  1214             data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
  1215                                   GL_NEAREST);
  1216             data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
  1217                                   GL_NEAREST);
  1218             break;
  1219         case SDL_TEXTURESCALEMODE_SLOW:
  1220         case SDL_TEXTURESCALEMODE_BEST:
  1221             data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
  1222                                   GL_LINEAR);
  1223             data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
  1224                                   GL_LINEAR);
  1225             break;
  1226         }
  1227         data->scaleMode = texture->scaleMode;
  1228     }
  1229 
  1230     if (texturedata->shader != 0) {
  1231         data->glEnable(GL_FRAGMENT_PROGRAM_ARB);
  1232         data->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, texturedata->shader);
  1233     }
  1234 
  1235     data->glBegin(GL_TRIANGLE_STRIP);
  1236     data->glTexCoord2f(minu, minv);
  1237     data->glVertex2i(minx, miny);
  1238     data->glTexCoord2f(maxu, minv);
  1239     data->glVertex2i(maxx, miny);
  1240     data->glTexCoord2f(minu, maxv);
  1241     data->glVertex2i(minx, maxy);
  1242     data->glTexCoord2f(maxu, maxv);
  1243     data->glVertex2i(maxx, maxy);
  1244     data->glEnd();
  1245 
  1246     if (texturedata->shader != 0) {
  1247         data->glDisable(GL_FRAGMENT_PROGRAM_ARB);
  1248     }
  1249 
  1250     data->glDisable(texturedata->type);
  1251 
  1252     return 0;
  1253 }
  1254 
  1255 static int
  1256 GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1257                     Uint32 pixel_format, void * pixels, int pitch)
  1258 {
  1259     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1260     GLint internalFormat;
  1261     GLenum format, type;
  1262     Uint8 *src, *dst, *tmp;
  1263     int length, rows;
  1264 
  1265     if (!convert_format(data, pixel_format, &internalFormat, &format, &type)) {
  1266         /* FIXME: Do a temp copy to a format that is supported */
  1267         SDL_SetError("Unsupported pixel format");
  1268         return -1;
  1269     }
  1270 
  1271     if (pixel_format == SDL_PIXELFORMAT_INDEX1LSB) {
  1272         data->glPixelStorei(GL_PACK_LSB_FIRST, 1);
  1273     } else if (pixel_format == SDL_PIXELFORMAT_INDEX1MSB) {
  1274         data->glPixelStorei(GL_PACK_LSB_FIRST, 0);
  1275     }
  1276     data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
  1277     data->glPixelStorei(GL_PACK_ROW_LENGTH,
  1278                         (pitch / bytes_per_pixel(pixel_format)));
  1279 
  1280     data->glReadPixels(rect->x, rect->y+rect->h-1, rect->w, rect->h,
  1281                        format, type, pixels);
  1282 
  1283     /* Flip the rows to be top-down */
  1284     length = rect->w * bytes_per_pixel(pixel_format);
  1285     src = (Uint8*)pixels + (rect->h-1)*pitch;
  1286     dst = (Uint8*)pixels;
  1287     tmp = SDL_stack_alloc(Uint8, length);
  1288     rows = rect->h / 2;
  1289     while (rows--) {
  1290         SDL_memcpy(tmp, dst, length);
  1291         SDL_memcpy(dst, src, length);
  1292         SDL_memcpy(src, tmp, length);
  1293     }
  1294     SDL_stack_free(tmp);
  1295 }
  1296 
  1297 static int
  1298 GL_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1299                      Uint32 pixel_format, const void * pixels, int pitch)
  1300 {
  1301     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1302     GLint internalFormat;
  1303     GLenum format, type;
  1304 
  1305     if (!convert_format(data, pixel_format, &internalFormat, &format, &type)) {
  1306         /* FIXME: Do a temp copy to a format that is supported */
  1307         SDL_SetError("Unsupported pixel format");
  1308         return -1;
  1309     }
  1310 
  1311     /* FIXME: We need to copy the data and flip it */
  1312 
  1313     if (pixel_format == SDL_PIXELFORMAT_INDEX1LSB) {
  1314         data->glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
  1315     } else if (pixel_format == SDL_PIXELFORMAT_INDEX1MSB) {
  1316         data->glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
  1317     }
  1318     data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  1319     data->glPixelStorei(GL_UNPACK_ROW_LENGTH,
  1320                         (pitch / bytes_per_pixel(pixel_format)));
  1321 
  1322     data->glReadPixels(rect->x, rect->y+rect->h-1, rect->w, rect->h,
  1323                        format, type, pixels);
  1324 }
  1325 
  1326 static void
  1327 GL_RenderPresent(SDL_Renderer * renderer)
  1328 {
  1329     SDL_GL_SwapWindow(renderer->window);
  1330 }
  1331 
  1332 static void
  1333 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
  1334 {
  1335     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
  1336     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
  1337 
  1338     if (!data) {
  1339         return;
  1340     }
  1341     if (data->texture) {
  1342         renderdata->glDeleteTextures(1, &data->texture);
  1343     }
  1344     if (data->palette) {
  1345         SDL_free(data->palette);
  1346     }
  1347     if (data->pixels) {
  1348         SDL_free(data->pixels);
  1349     }
  1350     SDL_FreeDirtyRects(&data->dirty);
  1351     SDL_free(data);
  1352     texture->driverdata = NULL;
  1353 }
  1354 
  1355 static void
  1356 GL_DestroyRenderer(SDL_Renderer * renderer)
  1357 {
  1358     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
  1359 
  1360     if (data) {
  1361         if (data->context) {
  1362             if (data->GL_ARB_fragment_program_supported) {
  1363                 data->glDisable(GL_FRAGMENT_PROGRAM_ARB);
  1364                 data->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
  1365                 if (data->fragment_program_UYVY != 0) {
  1366                     data->glDeleteProgramsARB(1,
  1367                                               &data->fragment_program_UYVY);
  1368                 }
  1369             }
  1370 
  1371             /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
  1372             SDL_GL_DeleteContext(data->context);
  1373         }
  1374         SDL_free(data);
  1375     }
  1376     SDL_free(renderer);
  1377 }
  1378 
  1379 #endif /* SDL_VIDEO_RENDER_OGL */
  1380 
  1381 /* vi: set ts=4 sw=4 expandtab: */