src/video/SDL_renderer_gl.c
author Bob Pendleton <bob@pendleton.com>
Fri, 14 Mar 2008 18:17:49 +0000
changeset 2328 91e601d9df8b
parent 2295 dbc6d1893869
child 2778 38dfc890ee6b
permissions -rw-r--r--
re: bug#563. checking in some commented out trace code and a fix so that the in testalpha.c the background only flashes when alpha == 255. The problem that is being
fixed is caused by clearing SDL_COPY_RLE_COLORKEY without setting SDL_COPY_RLE_DESIRED in SDL_UnRELSurface.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 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 /* OpenGL renderer implementation */
    38 
    39 /* Details on optimizing the texture path on Mac OS X:
    40    http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/chapter_10_section_2.html
    41 */
    42 
    43 static const float inv255f = 1.0f / 255.0f;
    44 
    45 static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
    46 static int GL_ActivateRenderer(SDL_Renderer * renderer);
    47 static int GL_DisplayModeChanged(SDL_Renderer * renderer);
    48 static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    49 static int GL_QueryTexturePixels(SDL_Renderer * renderer,
    50                                  SDL_Texture * texture, void **pixels,
    51                                  int *pitch);
    52 static int GL_SetTexturePalette(SDL_Renderer * renderer,
    53                                 SDL_Texture * texture,
    54                                 const SDL_Color * colors, int firstcolor,
    55                                 int ncolors);
    56 static int GL_GetTexturePalette(SDL_Renderer * renderer,
    57                                 SDL_Texture * texture, SDL_Color * colors,
    58                                 int firstcolor, int ncolors);
    59 static int GL_SetTextureColorMod(SDL_Renderer * renderer,
    60                                  SDL_Texture * texture);
    61 static int GL_SetTextureAlphaMod(SDL_Renderer * renderer,
    62                                  SDL_Texture * texture);
    63 static int GL_SetTextureBlendMode(SDL_Renderer * renderer,
    64                                   SDL_Texture * texture);
    65 static int GL_SetTextureScaleMode(SDL_Renderer * renderer,
    66                                   SDL_Texture * texture);
    67 static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    68                             const SDL_Rect * rect, const void *pixels,
    69                             int pitch);
    70 static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    71                           const SDL_Rect * rect, int markDirty, void **pixels,
    72                           int *pitch);
    73 static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    74 static void GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    75                             int numrects, const SDL_Rect * rects);
    76 static int GL_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
    77                          Uint8 a, const SDL_Rect * rect);
    78 static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    79                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
    80 static void GL_RenderPresent(SDL_Renderer * renderer);
    81 static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    82 static void GL_DestroyRenderer(SDL_Renderer * renderer);
    83 
    84 
    85 SDL_RenderDriver GL_RenderDriver = {
    86     GL_CreateRenderer,
    87     {
    88      "opengl",
    89      (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD |
    90       SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
    91      (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
    92       SDL_TEXTUREMODULATE_ALPHA),
    93      (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK |
    94       SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD |
    95       SDL_TEXTUREBLENDMODE_MOD),
    96      (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
    97       SDL_TEXTURESCALEMODE_SLOW),
    98      16,
    99      {
   100       SDL_PIXELFORMAT_INDEX1LSB,
   101       SDL_PIXELFORMAT_INDEX1MSB,
   102       SDL_PIXELFORMAT_INDEX8,
   103       SDL_PIXELFORMAT_RGB332,
   104       SDL_PIXELFORMAT_RGB444,
   105       SDL_PIXELFORMAT_RGB555,
   106       SDL_PIXELFORMAT_ARGB4444,
   107       SDL_PIXELFORMAT_ARGB1555,
   108       SDL_PIXELFORMAT_RGB565,
   109       SDL_PIXELFORMAT_RGB24,
   110       SDL_PIXELFORMAT_BGR24,
   111       SDL_PIXELFORMAT_RGB888,
   112       SDL_PIXELFORMAT_BGR888,
   113       SDL_PIXELFORMAT_ARGB8888,
   114       SDL_PIXELFORMAT_ABGR8888,
   115       SDL_PIXELFORMAT_ARGB2101010},
   116      0,
   117      0}
   118 };
   119 
   120 typedef struct
   121 {
   122     SDL_GLContext context;
   123     SDL_bool updateSize;
   124     SDL_bool GL_ARB_texture_rectangle_supported;
   125     SDL_bool GL_EXT_paletted_texture_supported;
   126     int blendMode;
   127     int scaleMode;
   128 
   129     /* OpenGL functions */
   130 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
   131 #include "SDL_glfuncs.h"
   132 #undef SDL_PROC
   133 
   134     PFNGLCOLORTABLEEXTPROC glColorTableEXT;
   135     void (*glTextureRangeAPPLE) (GLenum target, GLsizei length,
   136                                  const GLvoid * pointer);
   137 } GL_RenderData;
   138 
   139 typedef struct
   140 {
   141     GLuint texture;
   142     GLenum type;
   143     GLfloat texw;
   144     GLfloat texh;
   145     GLenum format;
   146     GLenum formattype;
   147     Uint8 *palette;
   148     void *pixels;
   149     int pitch;
   150     SDL_DirtyRectList dirty;
   151 } GL_TextureData;
   152 
   153 
   154 static void
   155 GL_SetError(const char *prefix, GLenum result)
   156 {
   157     const char *error;
   158 
   159     switch (result) {
   160     case GL_NO_ERROR:
   161         error = "GL_NO_ERROR";
   162         break;
   163     case GL_INVALID_ENUM:
   164         error = "GL_INVALID_ENUM";
   165         break;
   166     case GL_INVALID_VALUE:
   167         error = "GL_INVALID_VALUE";
   168         break;
   169     case GL_INVALID_OPERATION:
   170         error = "GL_INVALID_OPERATION";
   171         break;
   172     case GL_STACK_OVERFLOW:
   173         error = "GL_STACK_OVERFLOW";
   174         break;
   175     case GL_STACK_UNDERFLOW:
   176         error = "GL_STACK_UNDERFLOW";
   177         break;
   178     case GL_OUT_OF_MEMORY:
   179         error = "GL_OUT_OF_MEMORY";
   180         break;
   181     case GL_TABLE_TOO_LARGE:
   182         error = "GL_TABLE_TOO_LARGE";
   183         break;
   184     default:
   185         error = "UNKNOWN";
   186         break;
   187     }
   188     SDL_SetError("%s: %s", prefix, error);
   189 }
   190 
   191 static int
   192 GL_LoadFunctions(GL_RenderData * data)
   193 {
   194 #if defined(__QNXNTO__) && (_NTO_VERSION < 630)
   195 #define __SDL_NOGETPROCADDR__
   196 #elif defined(__MINT__)
   197 #define __SDL_NOGETPROCADDR__
   198 #endif
   199 #ifdef __SDL_NOGETPROCADDR__
   200 #define SDL_PROC(ret,func,params) data->func=func;
   201 #else
   202 #define SDL_PROC(ret,func,params) \
   203     do { \
   204         data->func = SDL_GL_GetProcAddress(#func); \
   205         if ( ! data->func ) { \
   206             SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
   207             return -1; \
   208         } \
   209     } while ( 0 );
   210 #endif /* __SDL_NOGETPROCADDR__ */
   211 
   212 #include "SDL_glfuncs.h"
   213 #undef SDL_PROC
   214     return 0;
   215 }
   216 
   217 void
   218 GL_AddRenderDriver(_THIS)
   219 {
   220     if (_this->GL_CreateContext) {
   221         SDL_AddRenderDriver(0, &GL_RenderDriver);
   222     }
   223 }
   224 
   225 SDL_Renderer *
   226 GL_CreateRenderer(SDL_Window * window, Uint32 flags)
   227 {
   228     SDL_Renderer *renderer;
   229     GL_RenderData *data;
   230     GLint value;
   231     int doublebuffer;
   232 
   233     /* Render directly to the window, unless we're compositing */
   234 #ifndef __MACOSX__
   235     if (flags & SDL_RENDERER_SINGLEBUFFER) {
   236         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
   237     }
   238 #endif
   239     if (!(window->flags & SDL_WINDOW_OPENGL)) {
   240         if (SDL_RecreateWindow(window, window->flags | SDL_WINDOW_OPENGL) < 0) {
   241             return NULL;
   242         }
   243     }
   244 
   245     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   246     if (!renderer) {
   247         SDL_OutOfMemory();
   248         return NULL;
   249     }
   250 
   251     data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
   252     if (!data) {
   253         GL_DestroyRenderer(renderer);
   254         SDL_OutOfMemory();
   255         return NULL;
   256     }
   257 
   258     renderer->ActivateRenderer = GL_ActivateRenderer;
   259     renderer->DisplayModeChanged = GL_DisplayModeChanged;
   260     renderer->CreateTexture = GL_CreateTexture;
   261     renderer->QueryTexturePixels = GL_QueryTexturePixels;
   262     renderer->SetTexturePalette = GL_SetTexturePalette;
   263     renderer->GetTexturePalette = GL_GetTexturePalette;
   264     renderer->SetTextureColorMod = GL_SetTextureColorMod;
   265     renderer->SetTextureAlphaMod = GL_SetTextureAlphaMod;
   266     renderer->SetTextureBlendMode = GL_SetTextureBlendMode;
   267     renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
   268     renderer->UpdateTexture = GL_UpdateTexture;
   269     renderer->LockTexture = GL_LockTexture;
   270     renderer->UnlockTexture = GL_UnlockTexture;
   271     renderer->DirtyTexture = GL_DirtyTexture;
   272     renderer->RenderFill = GL_RenderFill;
   273     renderer->RenderCopy = GL_RenderCopy;
   274     renderer->RenderPresent = GL_RenderPresent;
   275     renderer->DestroyTexture = GL_DestroyTexture;
   276     renderer->DestroyRenderer = GL_DestroyRenderer;
   277     renderer->info = GL_RenderDriver.info;
   278     renderer->window = window->id;
   279     renderer->driverdata = data;
   280 
   281     renderer->info.flags =
   282         (SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED);
   283 
   284     if (GL_LoadFunctions(data) < 0) {
   285         GL_DestroyRenderer(renderer);
   286         return NULL;
   287     }
   288 
   289     data->context = SDL_GL_CreateContext(window->id);
   290     if (!data->context) {
   291         GL_DestroyRenderer(renderer);
   292         return NULL;
   293     }
   294     if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
   295         GL_DestroyRenderer(renderer);
   296         return NULL;
   297     }
   298 #ifdef __MACOSX__
   299     /* Enable multi-threaded rendering */
   300     /* Disabled until Ryan finishes his VBO/PBO code...
   301        CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
   302      */
   303 #endif
   304 
   305     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   306         SDL_GL_SetSwapInterval(1);
   307     } else {
   308         SDL_GL_SetSwapInterval(0);
   309     }
   310     if (SDL_GL_GetSwapInterval() > 0) {
   311         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   312     }
   313 
   314     if (SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer) == 0) {
   315         if (!doublebuffer) {
   316             renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
   317         }
   318     }
   319 
   320     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
   321     renderer->info.max_texture_width = value;
   322     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
   323     renderer->info.max_texture_height = value;
   324 
   325     if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
   326         || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
   327         data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
   328     }
   329     if (SDL_GL_ExtensionSupported("GL_EXT_paletted_texture")) {
   330         data->GL_EXT_paletted_texture_supported = SDL_TRUE;
   331         data->glColorTableEXT =
   332             (PFNGLCOLORTABLEEXTPROC) SDL_GL_GetProcAddress("glColorTableEXT");
   333     } else {
   334         /* Don't advertise support for 8-bit indexed texture format */
   335         Uint32 i, j;
   336         SDL_RendererInfo *info = &renderer->info;
   337         for (i = 0, j = 0; i < info->num_texture_formats; ++i) {
   338             if (info->texture_formats[i] != SDL_PIXELFORMAT_INDEX8) {
   339                 info->texture_formats[j++] = info->texture_formats[i];
   340             }
   341         }
   342         --info->num_texture_formats;
   343     }
   344     if (SDL_GL_ExtensionSupported("GL_APPLE_texture_range")) {
   345         data->glTextureRangeAPPLE =
   346             (void (*)(GLenum, GLsizei, const GLvoid *))
   347             SDL_GL_GetProcAddress("glTextureRangeAPPLE");
   348     }
   349 
   350     /* Set up parameters for rendering */
   351     data->blendMode = -1;
   352     data->scaleMode = -1;
   353     data->glDisable(GL_DEPTH_TEST);
   354     data->glDisable(GL_CULL_FACE);
   355     if (data->GL_ARB_texture_rectangle_supported) {
   356         data->glEnable(GL_TEXTURE_RECTANGLE_ARB);
   357     } else {
   358         data->glEnable(GL_TEXTURE_2D);
   359     }
   360     data->updateSize = SDL_TRUE;
   361 
   362     return renderer;
   363 }
   364 
   365 static int
   366 GL_ActivateRenderer(SDL_Renderer * renderer)
   367 {
   368     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   369     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   370 
   371     if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
   372         return -1;
   373     }
   374     if (data->updateSize) {
   375         data->glMatrixMode(GL_PROJECTION);
   376         data->glLoadIdentity();
   377         data->glMatrixMode(GL_MODELVIEW);
   378         data->glLoadIdentity();
   379         data->glViewport(0, 0, window->w, window->h);
   380         data->glOrtho(0.0, (GLdouble) window->w, (GLdouble) window->h, 0.0,
   381                       0.0, 1.0);
   382         data->updateSize = SDL_FALSE;
   383     }
   384     return 0;
   385 }
   386 
   387 static int
   388 GL_DisplayModeChanged(SDL_Renderer * renderer)
   389 {
   390     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   391 
   392     data->updateSize = SDL_TRUE;
   393     return 0;
   394 }
   395 
   396 static __inline__ int
   397 power_of_2(int input)
   398 {
   399     int value = 1;
   400 
   401     while (value < input) {
   402         value <<= 1;
   403     }
   404     return value;
   405 }
   406 
   407 static int
   408 GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   409 {
   410     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   411     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   412     GL_TextureData *data;
   413     GLint internalFormat;
   414     GLenum format, type;
   415     int texture_w, texture_h;
   416     GLenum result;
   417 
   418     switch (texture->format) {
   419     case SDL_PIXELFORMAT_INDEX1LSB:
   420     case SDL_PIXELFORMAT_INDEX1MSB:
   421         internalFormat = GL_RGB;
   422         format = GL_COLOR_INDEX;
   423         type = GL_BITMAP;
   424         break;
   425     case SDL_PIXELFORMAT_INDEX8:
   426         if (!renderdata->GL_EXT_paletted_texture_supported) {
   427             SDL_SetError("Unsupported texture format");
   428             return -1;
   429         }
   430         internalFormat = GL_COLOR_INDEX8_EXT;
   431         format = GL_COLOR_INDEX;
   432         type = GL_UNSIGNED_BYTE;
   433         break;
   434     case SDL_PIXELFORMAT_RGB332:
   435         internalFormat = GL_R3_G3_B2;
   436         format = GL_RGB;
   437         type = GL_UNSIGNED_BYTE_3_3_2;
   438         break;
   439     case SDL_PIXELFORMAT_RGB444:
   440         internalFormat = GL_RGB4;
   441         format = GL_RGB;
   442         type = GL_UNSIGNED_SHORT_4_4_4_4;
   443         break;
   444     case SDL_PIXELFORMAT_RGB555:
   445         internalFormat = GL_RGB5;
   446         format = GL_RGB;
   447         type = GL_UNSIGNED_SHORT_5_5_5_1;
   448         break;
   449     case SDL_PIXELFORMAT_ARGB4444:
   450         internalFormat = GL_RGBA4;
   451         format = GL_BGRA;
   452         type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
   453         break;
   454     case SDL_PIXELFORMAT_ARGB1555:
   455         internalFormat = GL_RGB5_A1;
   456         format = GL_BGRA;
   457         type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
   458         break;
   459     case SDL_PIXELFORMAT_RGB565:
   460         internalFormat = GL_RGB8;
   461         format = GL_RGB;
   462         type = GL_UNSIGNED_SHORT_5_6_5;
   463         break;
   464     case SDL_PIXELFORMAT_RGB24:
   465         internalFormat = GL_RGB8;
   466         format = GL_RGB;
   467         type = GL_UNSIGNED_BYTE;
   468         break;
   469     case SDL_PIXELFORMAT_RGB888:
   470         internalFormat = GL_RGB8;
   471         format = GL_BGRA;
   472         type = GL_UNSIGNED_BYTE;
   473         break;
   474     case SDL_PIXELFORMAT_BGR24:
   475         internalFormat = GL_RGB8;
   476         format = GL_BGR;
   477         type = GL_UNSIGNED_BYTE;
   478         break;
   479     case SDL_PIXELFORMAT_BGR888:
   480         internalFormat = GL_RGB8;
   481         format = GL_RGBA;
   482         type = GL_UNSIGNED_BYTE;
   483         break;
   484     case SDL_PIXELFORMAT_ARGB8888:
   485 #ifdef __MACOSX__
   486         internalFormat = GL_RGBA;
   487         format = GL_BGRA;
   488         type = GL_UNSIGNED_INT_8_8_8_8_REV;
   489 #else
   490         internalFormat = GL_RGBA8;
   491         format = GL_BGRA;
   492         type = GL_UNSIGNED_BYTE;
   493 #endif
   494         break;
   495     case SDL_PIXELFORMAT_ABGR8888:
   496         internalFormat = GL_RGBA8;
   497         format = GL_RGBA;
   498         type = GL_UNSIGNED_BYTE;
   499         break;
   500     case SDL_PIXELFORMAT_ARGB2101010:
   501         internalFormat = GL_RGB10_A2;
   502         format = GL_BGRA;
   503         type = GL_UNSIGNED_INT_2_10_10_10_REV;
   504         break;
   505     default:
   506         SDL_SetError("Unsupported texture format");
   507         return -1;
   508     }
   509 
   510     data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
   511     if (!data) {
   512         SDL_OutOfMemory();
   513         return -1;
   514     }
   515 
   516     if (texture->format == SDL_PIXELFORMAT_INDEX8) {
   517         data->palette = (Uint8 *) SDL_malloc(3 * 256 * sizeof(Uint8));
   518         if (!data->palette) {
   519             SDL_OutOfMemory();
   520             SDL_free(data);
   521             return -1;
   522         }
   523         SDL_memset(data->palette, 0xFF, 3 * 256 * sizeof(Uint8));
   524     }
   525 
   526     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   527         data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
   528         data->pixels = SDL_malloc(texture->h * data->pitch);
   529         if (!data->pixels) {
   530             SDL_OutOfMemory();
   531             SDL_free(data);
   532             return -1;
   533         }
   534     }
   535 
   536     texture->driverdata = data;
   537 
   538     renderdata->glGetError();
   539     renderdata->glGenTextures(1, &data->texture);
   540     if (renderdata->GL_ARB_texture_rectangle_supported) {
   541         data->type = GL_TEXTURE_RECTANGLE_ARB;
   542         texture_w = texture->w;
   543         texture_h = texture->h;
   544         data->texw = (GLfloat) texture->w;
   545         data->texh = (GLfloat) texture->h;
   546     } else {
   547         data->type = GL_TEXTURE_2D;
   548         texture_w = power_of_2(texture->w);
   549         texture_h = power_of_2(texture->h);
   550         data->texw = (GLfloat) texture->w / texture_w;
   551         data->texh = (GLfloat) texture->h / texture_h;
   552     }
   553     data->format = format;
   554     data->formattype = type;
   555     renderdata->glBindTexture(data->type, data->texture);
   556     renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
   557                                 GL_NEAREST);
   558     renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
   559                                 GL_NEAREST);
   560     renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
   561                                 GL_CLAMP_TO_EDGE);
   562     renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
   563                                 GL_CLAMP_TO_EDGE);
   564 #ifdef __MACOSX__
   565 #ifndef GL_TEXTURE_STORAGE_HINT_APPLE
   566 #define GL_TEXTURE_STORAGE_HINT_APPLE       0x85BC
   567 #endif
   568 #ifndef STORAGE_CACHED_APPLE
   569 #define STORAGE_CACHED_APPLE                0x85BE
   570 #endif
   571 #ifndef STORAGE_SHARED_APPLE
   572 #define STORAGE_SHARED_APPLE                0x85BF
   573 #endif
   574     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   575         renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
   576                                     GL_STORAGE_SHARED_APPLE);
   577     } else {
   578         renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
   579                                     GL_STORAGE_CACHED_APPLE);
   580     }
   581     if (texture->access == SDL_TEXTUREACCESS_STREAMING
   582         && texture->format == SDL_PIXELFORMAT_ARGB8888) {
   583         /*
   584            if (renderdata->glTextureRangeAPPLE) {
   585            renderdata->glTextureRangeAPPLE(data->type,
   586            texture->h * data->pitch,
   587            data->pixels);
   588            }
   589          */
   590         renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
   591         renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
   592                                  texture_h, 0, format, type, data->pixels);
   593     } else
   594 #endif
   595     {
   596         renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
   597                                  texture_h, 0, format, type, NULL);
   598     }
   599     result = renderdata->glGetError();
   600     if (result != GL_NO_ERROR) {
   601         GL_SetError("glTexImage2D()", result);
   602         return -1;
   603     }
   604     return 0;
   605 }
   606 
   607 static int
   608 GL_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   609                       void **pixels, int *pitch)
   610 {
   611     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   612 
   613     *pixels = data->pixels;
   614     *pitch = data->pitch;
   615     return 0;
   616 }
   617 
   618 static int
   619 GL_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   620                      const SDL_Color * colors, int firstcolor, int ncolors)
   621 {
   622     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   623     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   624     Uint8 *palette;
   625 
   626     if (!data->palette) {
   627         SDL_SetError("Texture doesn't have a palette");
   628         return -1;
   629     }
   630     palette = data->palette + firstcolor * 3;
   631     while (ncolors--) {
   632         *palette++ = colors->r;
   633         *palette++ = colors->g;
   634         *palette++ = colors->b;
   635         ++colors;
   636     }
   637     renderdata->glBindTexture(data->type, data->texture);
   638     renderdata->glColorTableEXT(data->type, GL_RGB8, 256, GL_RGB,
   639                                 GL_UNSIGNED_BYTE, data->palette);
   640     return 0;
   641 }
   642 
   643 static int
   644 GL_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   645                      SDL_Color * colors, int firstcolor, int ncolors)
   646 {
   647     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   648     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   649     Uint8 *palette;
   650 
   651     if (!data->palette) {
   652         SDL_SetError("Texture doesn't have a palette");
   653         return -1;
   654     }
   655     palette = data->palette + firstcolor * 3;
   656     while (ncolors--) {
   657         colors->r = *palette++;
   658         colors->g = *palette++;
   659         colors->b = *palette++;
   660         colors->unused = SDL_ALPHA_OPAQUE;
   661         ++colors;
   662     }
   663     return 0;
   664 }
   665 
   666 static void
   667 SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
   668                    int pitch)
   669 {
   670     if (texture->format == SDL_PIXELFORMAT_INDEX1LSB) {
   671         renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
   672     } else if (texture->format == SDL_PIXELFORMAT_INDEX1MSB) {
   673         renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
   674     }
   675     renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   676     renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
   677                               pitch / SDL_BYTESPERPIXEL(texture->format));
   678 }
   679 
   680 static int
   681 GL_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   682 {
   683     return 0;
   684 }
   685 
   686 static int
   687 GL_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   688 {
   689     return 0;
   690 }
   691 
   692 static int
   693 GL_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   694 {
   695     switch (texture->blendMode) {
   696     case SDL_TEXTUREBLENDMODE_NONE:
   697     case SDL_TEXTUREBLENDMODE_MASK:
   698     case SDL_TEXTUREBLENDMODE_BLEND:
   699     case SDL_TEXTUREBLENDMODE_ADD:
   700     case SDL_TEXTUREBLENDMODE_MOD:
   701         return 0;
   702     default:
   703         SDL_Unsupported();
   704         texture->blendMode = SDL_TEXTUREBLENDMODE_NONE;
   705         return -1;
   706     }
   707 }
   708 
   709 static int
   710 GL_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   711 {
   712     switch (texture->scaleMode) {
   713     case SDL_TEXTURESCALEMODE_NONE:
   714     case SDL_TEXTURESCALEMODE_FAST:
   715     case SDL_TEXTURESCALEMODE_SLOW:
   716         return 0;
   717     case SDL_TEXTURESCALEMODE_BEST:
   718         SDL_Unsupported();
   719         texture->scaleMode = SDL_TEXTURESCALEMODE_SLOW;
   720         return -1;
   721     default:
   722         SDL_Unsupported();
   723         texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
   724         return -1;
   725     }
   726 }
   727 
   728 static int
   729 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   730                  const SDL_Rect * rect, const void *pixels, int pitch)
   731 {
   732     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   733     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   734     GLenum result;
   735 
   736     renderdata->glGetError();
   737     SetupTextureUpdate(renderdata, texture, pitch);
   738     renderdata->glBindTexture(data->type, data->texture);
   739     renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
   740                                 rect->h, data->format, data->formattype,
   741                                 pixels);
   742     result = renderdata->glGetError();
   743     if (result != GL_NO_ERROR) {
   744         GL_SetError("glTexSubImage2D()", result);
   745         return -1;
   746     }
   747     return 0;
   748 }
   749 
   750 static int
   751 GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   752                const SDL_Rect * rect, int markDirty, void **pixels,
   753                int *pitch)
   754 {
   755     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   756 
   757     if (markDirty) {
   758         SDL_AddDirtyRect(&data->dirty, rect);
   759     }
   760 
   761     *pixels =
   762         (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
   763                   rect->x * SDL_BYTESPERPIXEL(texture->format));
   764     *pitch = data->pitch;
   765     return 0;
   766 }
   767 
   768 static void
   769 GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   770 {
   771 }
   772 
   773 static void
   774 GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
   775                 const SDL_Rect * rects)
   776 {
   777     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   778     int i;
   779 
   780     for (i = 0; i < numrects; ++i) {
   781         SDL_AddDirtyRect(&data->dirty, &rects[i]);
   782     }
   783 }
   784 
   785 static int
   786 GL_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
   787               const SDL_Rect * rect)
   788 {
   789     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   790     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   791 
   792     data->glClearColor((GLclampf) r * inv255f, (GLclampf) g * inv255f,
   793                        (GLclampf) b * inv255f, (GLclampf) a * inv255f);
   794     data->glViewport(rect->x, window->h - rect->y, rect->w, rect->h);
   795     data->glClear(GL_COLOR_BUFFER_BIT);
   796     data->glViewport(0, 0, window->w, window->h);
   797     return 0;
   798 }
   799 
   800 static int
   801 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   802               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   803 {
   804     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   805     GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
   806     int minx, miny, maxx, maxy;
   807     GLfloat minu, maxu, minv, maxv;
   808 
   809     if (texturedata->dirty.list) {
   810         SDL_DirtyRect *dirty;
   811         void *pixels;
   812         int bpp = SDL_BYTESPERPIXEL(texture->format);
   813         int pitch = texturedata->pitch;
   814 
   815         SetupTextureUpdate(data, texture, pitch);
   816         data->glBindTexture(texturedata->type, texturedata->texture);
   817         for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
   818             SDL_Rect *rect = &dirty->rect;
   819             pixels =
   820                 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
   821                           rect->x * bpp);
   822             data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
   823                                   rect->w, rect->h, texturedata->format,
   824                                   texturedata->formattype, pixels);
   825         }
   826         SDL_ClearDirtyRects(&texturedata->dirty);
   827     }
   828 
   829     minx = dstrect->x;
   830     miny = dstrect->y;
   831     maxx = dstrect->x + dstrect->w;
   832     maxy = dstrect->y + dstrect->h;
   833 
   834     minu = (GLfloat) srcrect->x / texture->w;
   835     minu *= texturedata->texw;
   836     maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
   837     maxu *= texturedata->texw;
   838     minv = (GLfloat) srcrect->y / texture->h;
   839     minv *= texturedata->texh;
   840     maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
   841     maxv *= texturedata->texh;
   842 
   843     data->glBindTexture(texturedata->type, texturedata->texture);
   844 
   845     if (texture->modMode) {
   846         data->glColor4f((GLfloat) texture->r * inv255f,
   847                         (GLfloat) texture->g * inv255f,
   848                         (GLfloat) texture->b * inv255f,
   849                         (GLfloat) texture->a * inv255f);
   850     } else {
   851         data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
   852     }
   853 
   854     if (texture->blendMode != data->blendMode) {
   855         switch (texture->blendMode) {
   856         case SDL_TEXTUREBLENDMODE_NONE:
   857             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
   858             data->glDisable(GL_BLEND);
   859             break;
   860         case SDL_TEXTUREBLENDMODE_MASK:
   861         case SDL_TEXTUREBLENDMODE_BLEND:
   862             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   863             data->glEnable(GL_BLEND);
   864             data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   865             break;
   866         case SDL_TEXTUREBLENDMODE_ADD:
   867             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   868             data->glEnable(GL_BLEND);
   869             data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
   870             break;
   871         case SDL_TEXTUREBLENDMODE_MOD:
   872             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   873             data->glEnable(GL_BLEND);
   874             data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
   875             break;
   876         }
   877         data->blendMode = texture->blendMode;
   878     }
   879 
   880     if (texture->scaleMode != data->scaleMode) {
   881         switch (texture->scaleMode) {
   882         case SDL_TEXTURESCALEMODE_NONE:
   883         case SDL_TEXTURESCALEMODE_FAST:
   884             data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   885                                   GL_NEAREST);
   886             data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   887                                   GL_NEAREST);
   888             break;
   889         case SDL_TEXTURESCALEMODE_SLOW:
   890         case SDL_TEXTURESCALEMODE_BEST:
   891             data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   892                                   GL_LINEAR);
   893             data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   894                                   GL_LINEAR);
   895             break;
   896         }
   897         data->scaleMode = texture->scaleMode;
   898     }
   899 
   900     data->glBegin(GL_TRIANGLE_STRIP);
   901     data->glTexCoord2f(minu, minv);
   902     data->glVertex2i(minx, miny);
   903     data->glTexCoord2f(maxu, minv);
   904     data->glVertex2i(maxx, miny);
   905     data->glTexCoord2f(minu, maxv);
   906     data->glVertex2i(minx, maxy);
   907     data->glTexCoord2f(maxu, maxv);
   908     data->glVertex2i(maxx, maxy);
   909     data->glEnd();
   910 
   911     return 0;
   912 }
   913 
   914 static void
   915 GL_RenderPresent(SDL_Renderer * renderer)
   916 {
   917     SDL_GL_SwapWindow(renderer->window);
   918 }
   919 
   920 static void
   921 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   922 {
   923     GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
   924     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
   925 
   926     if (!data) {
   927         return;
   928     }
   929     if (data->texture) {
   930         renderdata->glDeleteTextures(1, &data->texture);
   931     }
   932     if (data->palette) {
   933         SDL_free(data->palette);
   934     }
   935     if (data->pixels) {
   936         SDL_free(data->pixels);
   937     }
   938     SDL_FreeDirtyRects(&data->dirty);
   939     SDL_free(data);
   940     texture->driverdata = NULL;
   941 }
   942 
   943 static void
   944 GL_DestroyRenderer(SDL_Renderer * renderer)
   945 {
   946     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   947 
   948     if (data) {
   949         if (data->context) {
   950             /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
   951             SDL_GL_DeleteContext(data->context);
   952         }
   953         SDL_free(data);
   954     }
   955     SDL_free(renderer);
   956 }
   957 
   958 #endif /* SDL_VIDEO_RENDER_OGL */
   959 
   960 /* vi: set ts=4 sw=4 expandtab: */