src/video/SDL_renderer_gles.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 31 Dec 2008 07:56:56 +0000
changeset 2936 066384910f50
parent 2884 9dde605c7540
child 2937 017d4334accf
permissions -rw-r--r--
iPhone build compiles again (drawing routines need to be implemented)
     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_ES
    25 
    26 #include "SDL_video.h"
    27 #include "SDL_opengles.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 /* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */
    34 
    35 static const float inv255f = 1.0f / 255.0f;
    36 
    37 static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
    38 static int GLES_ActivateRenderer(SDL_Renderer * renderer);
    39 static int GLES_DisplayModeChanged(SDL_Renderer * renderer);
    40 static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    41 static int GLES_QueryTexturePixels(SDL_Renderer * renderer,
    42                                    SDL_Texture * texture, void **pixels,
    43                                    int *pitch);
    44 static int GLES_SetTexturePalette(SDL_Renderer * renderer,
    45                                   SDL_Texture * texture,
    46                                   const SDL_Color * colors, int firstcolor,
    47                                   int ncolors);
    48 static int GLES_GetTexturePalette(SDL_Renderer * renderer,
    49                                   SDL_Texture * texture, SDL_Color * colors,
    50                                   int firstcolor, int ncolors);
    51 static int GLES_SetTextureColorMod(SDL_Renderer * renderer,
    52                                    SDL_Texture * texture);
    53 static int GLES_SetTextureAlphaMod(SDL_Renderer * renderer,
    54                                    SDL_Texture * texture);
    55 static int GLES_SetTextureBlendMode(SDL_Renderer * renderer,
    56                                     SDL_Texture * texture);
    57 static int GLES_SetTextureScaleMode(SDL_Renderer * renderer,
    58                                     SDL_Texture * texture);
    59 static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    60                               const SDL_Rect * rect, const void *pixels,
    61                               int pitch);
    62 static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    63                             const SDL_Rect * rect, int markDirty,
    64                             void **pixels, int *pitch);
    65 static void GLES_UnlockTexture(SDL_Renderer * renderer,
    66                                SDL_Texture * texture);
    67 static void GLES_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    68                               int numrects, const SDL_Rect * rects);
    69 static int GLES_RenderPoint(SDL_Renderer * renderer, int x, int y);
    70 static int GLES_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
    71                            int y2);
    72 static int GLES_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
    73 static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
    74                            const SDL_Rect * srcrect,
    75                            const SDL_Rect * dstrect);
    76 static void GLES_RenderPresent(SDL_Renderer * renderer);
    77 static void GLES_DestroyTexture(SDL_Renderer * renderer,
    78                                 SDL_Texture * texture);
    79 static void GLES_DestroyRenderer(SDL_Renderer * renderer);
    80 
    81 
    82 SDL_RenderDriver GL_ES_RenderDriver = {
    83     GLES_CreateRenderer,
    84     {
    85      "opengl_es",
    86      (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD |
    87       SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
    88      (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
    89       SDL_TEXTUREMODULATE_ALPHA),
    90      (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
    91       SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
    92      (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
    93       SDL_TEXTURESCALEMODE_SLOW), 2,
    94      {
    95       SDL_PIXELFORMAT_RGB24,
    96       SDL_PIXELFORMAT_ABGR8888,
    97       },
    98      0,
    99      0}
   100 };
   101 
   102 typedef struct
   103 {
   104     SDL_GLContext context;
   105     SDL_bool updateSize;
   106     int blendMode;
   107 
   108 #ifndef APIENTRY
   109 #define APIENTRY
   110 #endif
   111 
   112     SDL_bool useDrawTexture;
   113     SDL_bool GL_OES_draw_texture_supported;
   114 
   115     /* OpenGL ES functions */
   116 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
   117 #include "SDL_glesfuncs.h"
   118 #undef SDL_PROC
   119 
   120 } GLES_RenderData;
   121 
   122 typedef struct
   123 {
   124     GLuint texture;
   125     GLenum type;
   126     GLfloat texw;
   127     GLfloat texh;
   128     GLenum format;
   129     GLenum formattype;
   130     void *pixels;
   131     int pitch;
   132     SDL_DirtyRectList dirty;
   133 } GLES_TextureData;
   134 
   135 static void
   136 GLES_SetError(const char *prefix, GLenum result)
   137 {
   138     const char *error;
   139 
   140     switch (result) {
   141     case GL_NO_ERROR:
   142         error = "GL_NO_ERROR";
   143         break;
   144     case GL_INVALID_ENUM:
   145         error = "GL_INVALID_ENUM";
   146         break;
   147     case GL_INVALID_VALUE:
   148         error = "GL_INVALID_VALUE";
   149         break;
   150     case GL_INVALID_OPERATION:
   151         error = "GL_INVALID_OPERATION";
   152         break;
   153     case GL_STACK_OVERFLOW:
   154         error = "GL_STACK_OVERFLOW";
   155         break;
   156     case GL_STACK_UNDERFLOW:
   157         error = "GL_STACK_UNDERFLOW";
   158         break;
   159     case GL_OUT_OF_MEMORY:
   160         error = "GL_OUT_OF_MEMORY";
   161         break;
   162     default:
   163         error = "UNKNOWN";
   164         break;
   165     }
   166     SDL_SetError("%s: %s", prefix, error);
   167 }
   168 
   169 static int
   170 GLES_LoadFunctions(GLES_RenderData * data)
   171 {
   172 
   173 #define SDL_PROC(ret,func,params) \
   174 	data->func = func;
   175 #include "SDL_glesfuncs.h"
   176 #undef SDL_PROC
   177 
   178     return 0;
   179 }
   180 
   181 void
   182 GLES_AddRenderDriver(_THIS)
   183 {
   184     if (_this->GL_CreateContext) {
   185         SDL_AddRenderDriver(0, &GL_ES_RenderDriver);
   186     }
   187 }
   188 
   189 SDL_Renderer *
   190 GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
   191 {
   192 
   193     SDL_Renderer *renderer;
   194     GLES_RenderData *data;
   195     GLint value;
   196     int doublebuffer;
   197 
   198     if (!(window->flags & SDL_WINDOW_OPENGL)) {
   199         if (SDL_RecreateWindow(window, window->flags | SDL_WINDOW_OPENGL) < 0) {
   200             return NULL;
   201         }
   202     }
   203 
   204     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   205     if (!renderer) {
   206         SDL_OutOfMemory();
   207         return NULL;
   208     }
   209 
   210     data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
   211     if (!data) {
   212         GLES_DestroyRenderer(renderer);
   213         SDL_OutOfMemory();
   214         return NULL;
   215     }
   216 
   217     renderer->ActivateRenderer = GLES_ActivateRenderer;
   218     renderer->DisplayModeChanged = GLES_DisplayModeChanged;
   219     renderer->CreateTexture = GLES_CreateTexture;
   220     renderer->QueryTexturePixels = GLES_QueryTexturePixels;
   221     renderer->SetTexturePalette = GLES_SetTexturePalette;
   222     renderer->GetTexturePalette = GLES_GetTexturePalette;
   223     renderer->SetTextureColorMod = GLES_SetTextureColorMod;
   224     renderer->SetTextureAlphaMod = GLES_SetTextureAlphaMod;
   225     renderer->SetTextureBlendMode = GLES_SetTextureBlendMode;
   226     renderer->SetTextureScaleMode = GLES_SetTextureScaleMode;
   227     renderer->UpdateTexture = GLES_UpdateTexture;
   228     renderer->LockTexture = GLES_LockTexture;
   229     renderer->UnlockTexture = GLES_UnlockTexture;
   230     renderer->DirtyTexture = GLES_DirtyTexture;
   231     renderer->RenderPoint = GLES_RenderPoint;
   232     renderer->RenderLine = GLES_RenderLine;
   233     renderer->RenderFill = GLES_RenderFill;
   234     renderer->RenderCopy = GLES_RenderCopy;
   235     renderer->RenderPresent = GLES_RenderPresent;
   236     renderer->DestroyTexture = GLES_DestroyTexture;
   237     renderer->DestroyRenderer = GLES_DestroyRenderer;
   238     renderer->info = GL_ES_RenderDriver.info;
   239     renderer->window = window->id;
   240     renderer->driverdata = data;
   241 
   242 
   243     renderer->info.flags =
   244         (SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED);
   245 
   246     if (GLES_LoadFunctions(data) < 0) {
   247         GLES_DestroyRenderer(renderer);
   248         return NULL;
   249     }
   250 
   251     data->context = SDL_GL_CreateContext(window->id);
   252     if (!data->context) {
   253         GLES_DestroyRenderer(renderer);
   254         return NULL;
   255     }
   256     if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
   257         GLES_DestroyRenderer(renderer);
   258         return NULL;
   259     }
   260 
   261     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   262         SDL_GL_SetSwapInterval(1);
   263     } else {
   264         SDL_GL_SetSwapInterval(0);
   265     }
   266     if (SDL_GL_GetSwapInterval() > 0) {
   267         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   268     }
   269 
   270     if (SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer) == 0) {
   271         if (!doublebuffer) {
   272             renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
   273         }
   274     }
   275 
   276     if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) {
   277         data->GL_OES_draw_texture_supported = SDL_TRUE;
   278         data->useDrawTexture = SDL_TRUE;
   279     } else {
   280         data->GL_OES_draw_texture_supported = SDL_FALSE;
   281         data->useDrawTexture = SDL_FALSE;
   282     }
   283 
   284     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
   285     renderer->info.max_texture_width = value;
   286     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
   287     renderer->info.max_texture_height = value;
   288 
   289     /* Set up parameters for rendering */
   290     data->blendMode = -1;
   291     data->glDisable(GL_DEPTH_TEST);
   292     data->glDisable(GL_CULL_FACE);
   293     data->glEnable(GL_TEXTURE_2D);
   294     data->updateSize = SDL_TRUE;
   295 
   296     return renderer;
   297 }
   298 
   299 static int
   300 GLES_ActivateRenderer(SDL_Renderer * renderer)
   301 {
   302 
   303     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   304     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   305 
   306     if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
   307         return -1;
   308     }
   309     if (data->updateSize) {
   310         data->glMatrixMode(GL_PROJECTION);
   311         data->glLoadIdentity();
   312         data->glMatrixMode(GL_MODELVIEW);
   313         data->glLoadIdentity();
   314         data->glViewport(0, 0, window->w, window->h);
   315         data->glOrthof(0.0, (GLfloat) window->w, (GLfloat) window->h, 0.0,
   316                        0.0, 1.0);
   317         data->updateSize = SDL_FALSE;
   318     }
   319     return 0;
   320 }
   321 
   322 static int
   323 GLES_DisplayModeChanged(SDL_Renderer * renderer)
   324 {
   325     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   326 
   327     data->updateSize = SDL_TRUE;
   328     return 0;
   329 }
   330 
   331 static __inline__ int
   332 power_of_2(int input)
   333 {
   334     int value = 1;
   335 
   336     while (value < input) {
   337         value <<= 1;
   338     }
   339     return value;
   340 }
   341 
   342 static int
   343 GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   344 {
   345     GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
   346     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   347     GLES_TextureData *data;
   348     GLint internalFormat;
   349     GLenum format, type;
   350     int texture_w, texture_h;
   351     GLenum result;
   352     switch (texture->format) {
   353     case SDL_PIXELFORMAT_INDEX1LSB:
   354     case SDL_PIXELFORMAT_INDEX1MSB:
   355     case SDL_PIXELFORMAT_INDEX8:
   356     case SDL_PIXELFORMAT_RGB332:
   357     case SDL_PIXELFORMAT_RGB444:
   358     case SDL_PIXELFORMAT_RGB555:
   359     case SDL_PIXELFORMAT_ARGB4444:
   360     case SDL_PIXELFORMAT_ARGB1555:
   361     case SDL_PIXELFORMAT_BGR24:
   362     case SDL_PIXELFORMAT_BGR888:
   363     case SDL_PIXELFORMAT_RGB888:
   364     case SDL_PIXELFORMAT_RGBA8888:
   365     case SDL_PIXELFORMAT_ARGB2101010:
   366     case SDL_PIXELFORMAT_ARGB8888:
   367     case SDL_PIXELFORMAT_RGB24:
   368         internalFormat = GL_RGB;
   369         format = GL_RGB;
   370         type = GL_UNSIGNED_BYTE;
   371         break;
   372     case SDL_PIXELFORMAT_ABGR8888:
   373         internalFormat = GL_RGBA;
   374         format = GL_RGBA;
   375         type = GL_UNSIGNED_BYTE;
   376         break;
   377         /*
   378            These formats would be supported if SDL had the necessary pixel formats
   379            case SDL_PIXELFORMAT_BGR565:
   380            internalFormat = GL_RGB;
   381            format = GL_RGB;
   382            type = GL_UNSIGNED_SHORT_5_6_5;
   383            break;                       
   384            case SDL_PIXELFORMAT_ABGR5551:
   385            internalFormat = GL_RGBA;
   386            format = GL_RGBA;
   387            type = GL_UNSIGNED_SHORT_5_5_5_1;
   388            break;
   389            case SDL_PIXELFORMAT_ABGR4444:
   390            internalFormat = GL_RGBA;
   391            format = GL_RGBA;
   392            type = GL_UNSIGNED_SHORT_4_4_4_4;
   393            break;
   394          */
   395     default:
   396         SDL_SetError("Unsupported texture format");
   397         return -1;
   398     }
   399 
   400     data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
   401     if (!data) {
   402         SDL_OutOfMemory();
   403         return -1;
   404     }
   405 
   406     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   407         data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
   408         data->pixels = SDL_malloc(texture->h * data->pitch);
   409         if (!data->pixels) {
   410             SDL_OutOfMemory();
   411             SDL_free(data);
   412             return -1;
   413         }
   414     }
   415 
   416     texture->driverdata = data;
   417 
   418     renderdata->glGetError();
   419     renderdata->glGenTextures(1, &data->texture);
   420 
   421     data->type = GL_TEXTURE_2D;
   422     /* no NPOV textures allowed in OpenGL ES (yet) */
   423     texture_w = power_of_2(texture->w);
   424     texture_h = power_of_2(texture->h);
   425     data->texw = (GLfloat) texture->w / texture_w;
   426     data->texh = (GLfloat) texture->h / texture_h;
   427 
   428     data->format = format;
   429     data->formattype = type;
   430     renderdata->glBindTexture(data->type, data->texture);
   431     renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
   432                                 GL_NEAREST);
   433     renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
   434                                 GL_NEAREST);
   435     renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
   436                                 GL_CLAMP_TO_EDGE);
   437     renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
   438                                 GL_CLAMP_TO_EDGE);
   439 
   440     renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
   441                              texture_h, 0, format, type, NULL);
   442 
   443     result = renderdata->glGetError();
   444     if (result != GL_NO_ERROR) {
   445         GLES_SetError("glTexImage2D()", result);
   446         return -1;
   447     }
   448     return 0;
   449 }
   450 
   451 static int
   452 GLES_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   453                         void **pixels, int *pitch)
   454 {
   455     GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
   456 
   457     *pixels = data->pixels;
   458     *pitch = data->pitch;
   459     return 0;
   460 }
   461 
   462 static int
   463 GLES_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   464                        const SDL_Color * colors, int firstcolor, int ncolors)
   465 {
   466     SDL_SetError("OpenGL ES does not support paletted textures");
   467     return -1;
   468 }
   469 
   470 static int
   471 GLES_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   472                        SDL_Color * colors, int firstcolor, int ncolors)
   473 {
   474     SDL_SetError("OpenGL ES does not support paletted textures");
   475     return -1;
   476 }
   477 
   478 static void
   479 SetupTextureUpdate(GLES_RenderData * renderdata, SDL_Texture * texture,
   480                    int pitch)
   481 {
   482 
   483 
   484     GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
   485     renderdata->glBindTexture(data->type, data->texture);
   486     renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   487 }
   488 
   489 static int
   490 GLES_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   491 {
   492     return 0;
   493 }
   494 
   495 static int
   496 GLES_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   497 {
   498     return 0;
   499 }
   500 
   501 static int
   502 GLES_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   503 {
   504     switch (texture->blendMode) {
   505     case SDL_BLENDMODE_NONE:
   506     case SDL_BLENDMODE_MASK:
   507     case SDL_BLENDMODE_BLEND:
   508     case SDL_BLENDMODE_ADD:
   509     case SDL_BLENDMODE_MOD:
   510         return 0;
   511     default:
   512         SDL_Unsupported();
   513         texture->blendMode = SDL_BLENDMODE_NONE;
   514         return -1;
   515     }
   516 }
   517 
   518 static int
   519 GLES_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   520 {
   521     switch (texture->scaleMode) {
   522     case SDL_TEXTURESCALEMODE_NONE:
   523     case SDL_TEXTURESCALEMODE_FAST:
   524     case SDL_TEXTURESCALEMODE_SLOW:
   525         return 0;
   526     case SDL_TEXTURESCALEMODE_BEST:
   527         SDL_Unsupported();
   528         texture->scaleMode = SDL_TEXTURESCALEMODE_SLOW;
   529         return -1;
   530     default:
   531         SDL_Unsupported();
   532         texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
   533         return -1;
   534     }
   535 }
   536 
   537 static int
   538 GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   539                    const SDL_Rect * rect, const void *pixels, int pitch)
   540 {
   541     GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
   542     GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
   543     GLenum result;
   544 
   545     SetupTextureUpdate(renderdata, texture, pitch);
   546     renderdata->glGetError();
   547     renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
   548                                 rect->h, data->format, data->formattype,
   549                                 pixels);
   550     result = renderdata->glGetError();
   551     if (result != GL_NO_ERROR) {
   552         GLES_SetError("glTexSubImage2D()", result);
   553         return -1;
   554     }
   555     return 0;
   556 }
   557 
   558 static int
   559 GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   560                  const SDL_Rect * rect, int markDirty, void **pixels,
   561                  int *pitch)
   562 {
   563     GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
   564 
   565     if (markDirty) {
   566         SDL_AddDirtyRect(&data->dirty, rect);
   567     }
   568 
   569     *pixels =
   570         (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
   571                   rect->x * SDL_BYTESPERPIXEL(texture->format));
   572     *pitch = data->pitch;
   573     return 0;
   574 }
   575 
   576 static void
   577 GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   578 {
   579 }
   580 
   581 static void
   582 GLES_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   583                   int numrects, const SDL_Rect * rects)
   584 {
   585     GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
   586     int i;
   587 
   588     for (i = 0; i < numrects; ++i) {
   589         SDL_AddDirtyRect(&data->dirty, &rects[i]);
   590     }
   591 }
   592 
   593 static void
   594 GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
   595 {
   596     if (blendMode != data->blendMode) {
   597         switch (blendMode) {
   598         case SDL_BLENDMODE_NONE:
   599             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   600             data->glDisable(GL_BLEND);
   601             break;
   602         case SDL_BLENDMODE_MASK:
   603         case SDL_BLENDMODE_BLEND:
   604             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   605             data->glEnable(GL_BLEND);
   606             data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   607             break;
   608         case SDL_BLENDMODE_ADD:
   609             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   610             data->glEnable(GL_BLEND);
   611             data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
   612             break;
   613         case SDL_BLENDMODE_MOD:
   614             data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   615             data->glEnable(GL_BLEND);
   616             data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
   617             break;
   618         }
   619         data->blendMode = blendMode;
   620     }
   621 }
   622 
   623 static int
   624 GLES_RenderPoint(SDL_Renderer * renderer, int x, int y)
   625 {
   626     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   627 
   628     GLES_SetBlendMode(data, renderer->blendMode);
   629 
   630     data->glColor4f((GLfloat) renderer->r * inv255f,
   631                     (GLfloat) renderer->g * inv255f,
   632                     (GLfloat) renderer->b * inv255f,
   633                     (GLfloat) renderer->a * inv255f);
   634 
   635 /* FIXME:
   636     data->glBegin(GL_POINTS);
   637     data->glVertex2i(x, y);
   638     data->glEnd();
   639 */
   640     return 0;
   641 }
   642 
   643 static int
   644 GLES_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
   645 {
   646     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   647 
   648     GLES_SetBlendMode(data, renderer->blendMode);
   649 
   650     data->glColor4f((GLfloat) renderer->r * inv255f,
   651                     (GLfloat) renderer->g * inv255f,
   652                     (GLfloat) renderer->b * inv255f,
   653                     (GLfloat) renderer->a * inv255f);
   654 
   655 /* FIXME:
   656     data->glBegin(GL_LINES);
   657     data->glVertex2i(x1, y1);
   658     data->glVertex2i(x2, y2);
   659     data->glEnd();
   660 */
   661     return 0;
   662 }
   663 
   664 static int
   665 GLES_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
   666 {
   667     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   668     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   669 
   670     GLES_SetBlendMode(data, renderer->blendMode);
   671 
   672     data->glColor4f((GLfloat) renderer->r * inv255f,
   673                     (GLfloat) renderer->g * inv255f,
   674                     (GLfloat) renderer->b * inv255f,
   675                     (GLfloat) renderer->a * inv255f);
   676 
   677 /* FIXME:
   678     data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
   679 */
   680     return 0;
   681 }
   682 
   683 static int
   684 GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   685                 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   686 {
   687 
   688     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   689     GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
   690     int minx, miny, maxx, maxy;
   691     GLfloat minu, maxu, minv, maxv;
   692     int i;
   693     void *temp_buffer;          /* used for reformatting dirty rect pixels */
   694     void *temp_ptr;
   695 
   696     if (texturedata->dirty.list) {
   697         SDL_DirtyRect *dirty;
   698         void *pixels;
   699         int bpp = SDL_BYTESPERPIXEL(texture->format);
   700         int pitch = texturedata->pitch;
   701 
   702         SetupTextureUpdate(data, texture, pitch);
   703 
   704         data->glBindTexture(texturedata->type, texturedata->texture);
   705         for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
   706             SDL_Rect *rect = &dirty->rect;
   707             pixels =
   708                 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
   709                           rect->x * bpp);
   710             /*      There is no GL_UNPACK_ROW_LENGTH in OpenGLES 
   711                we must do this reformatting ourselves(!)
   712 
   713                maybe it'd be a good idea to keep a temp buffer around
   714                for this purpose rather than allocating it each time
   715              */
   716             temp_buffer = SDL_malloc(rect->w * rect->h * bpp);
   717             temp_ptr = temp_buffer;
   718             for (i = 0; i < rect->h; i++) {
   719                 SDL_memcpy(temp_ptr, pixels, rect->w * bpp);
   720                 temp_ptr += rect->w * bpp;
   721                 pixels += pitch;
   722             }
   723 
   724             data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
   725                                   rect->w, rect->h, texturedata->format,
   726                                   texturedata->formattype, temp_buffer);
   727 
   728             SDL_free(temp_buffer);
   729 
   730         }
   731         SDL_ClearDirtyRects(&texturedata->dirty);
   732     }
   733 
   734     data->glBindTexture(texturedata->type, texturedata->texture);
   735     data->glEnable(GL_TEXTURE_2D);
   736 
   737     if (texture->modMode) {
   738         data->glColor4f((GLfloat) texture->r * inv255f,
   739                         (GLfloat) texture->g * inv255f,
   740                         (GLfloat) texture->b * inv255f,
   741                         (GLfloat) texture->a * inv255f);
   742     } else {
   743         data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
   744     }
   745 
   746     GLES_SetBlendMode(data, texture->blendMode);
   747 
   748     switch (texture->scaleMode) {
   749     case SDL_TEXTURESCALEMODE_NONE:
   750     case SDL_TEXTURESCALEMODE_FAST:
   751         data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   752                               GL_NEAREST);
   753         data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   754                               GL_NEAREST);
   755         break;
   756     case SDL_TEXTURESCALEMODE_SLOW:
   757     case SDL_TEXTURESCALEMODE_BEST:
   758         data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   759                               GL_LINEAR);
   760         data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   761                               GL_LINEAR);
   762         break;
   763     }
   764 
   765     if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
   766         /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
   767         SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   768         GLint cropRect[4];
   769         cropRect[0] = srcrect->x;
   770         cropRect[1] = srcrect->y + srcrect->h;
   771         cropRect[2] = srcrect->w;
   772         cropRect[3] = -srcrect->h;
   773         data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
   774                                cropRect);
   775         data->glDrawTexiOES(dstrect->x, window->h - dstrect->y - dstrect->h,
   776                             0, dstrect->w, dstrect->h);
   777     } else {
   778 
   779         minx = dstrect->x;
   780         miny = dstrect->y;
   781         maxx = dstrect->x + dstrect->w;
   782         maxy = dstrect->y + dstrect->h;
   783 
   784         minu = (GLfloat) srcrect->x / texture->w;
   785         minu *= texturedata->texw;
   786         maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
   787         maxu *= texturedata->texw;
   788         minv = (GLfloat) srcrect->y / texture->h;
   789         minv *= texturedata->texh;
   790         maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
   791         maxv *= texturedata->texh;
   792 
   793         GLshort vertices[8];
   794         GLfloat texCoords[8];
   795 
   796         vertices[0] = minx;
   797         vertices[1] = miny;
   798         vertices[2] = maxx;
   799         vertices[3] = miny;
   800         vertices[4] = minx;
   801         vertices[5] = maxy;
   802         vertices[6] = maxx;
   803         vertices[7] = maxy;
   804 
   805         texCoords[0] = minu;
   806         texCoords[1] = minv;
   807         texCoords[2] = maxu;
   808         texCoords[3] = minv;
   809         texCoords[4] = minu;
   810         texCoords[5] = maxv;
   811         texCoords[6] = maxu;
   812         texCoords[7] = maxv;
   813 
   814         data->glVertexPointer(2, GL_SHORT, 0, vertices);
   815         data->glEnableClientState(GL_VERTEX_ARRAY);
   816         data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
   817         data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   818         data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   819 
   820     }
   821 
   822     return 0;
   823 }
   824 
   825 static void
   826 GLES_RenderPresent(SDL_Renderer * renderer)
   827 {
   828     SDL_GL_SwapWindow(renderer->window);
   829 }
   830 
   831 static void
   832 GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   833 {
   834     GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
   835     GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
   836 
   837     if (!data) {
   838         return;
   839     }
   840     if (data->texture) {
   841         glDeleteTextures(1, &data->texture);
   842     }
   843     if (data->pixels) {
   844         SDL_free(data->pixels);
   845     }
   846     SDL_FreeDirtyRects(&data->dirty);
   847     SDL_free(data);
   848     texture->driverdata = NULL;
   849 }
   850 
   851 static void
   852 GLES_DestroyRenderer(SDL_Renderer * renderer)
   853 {
   854     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   855 
   856     if (data) {
   857         if (data->context) {
   858             /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
   859             SDL_GL_DeleteContext(data->context);
   860         }
   861         SDL_free(data);
   862     }
   863     SDL_free(renderer);
   864 }
   865 
   866 #endif /* SDL_VIDEO_RENDER_OGL */
   867 
   868 /* vi: set ts=4 sw=4 expandtab: */