src/video/SDL_renderer_gles.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 02 Jan 2009 16:03:37 +0000
changeset 2964 0faae272a372
parent 2949 4eabc35fbb4a
child 3099 82e60908fab1
permissions -rw-r--r--
indent
     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     GLshort vertices[2];
   636     vertices[0] = x;
   637     vertices[1] = y;
   638 
   639     data->glVertexPointer(2, GL_SHORT, 0, vertices);
   640     data->glEnableClientState(GL_VERTEX_ARRAY);
   641     data->glDrawArrays(GL_POINTS, 0, 1);
   642     data->glDisableClientState(GL_VERTEX_ARRAY);
   643 
   644     return 0;
   645 }
   646 
   647 static int
   648 GLES_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
   649 {
   650     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   651 
   652     GLES_SetBlendMode(data, renderer->blendMode);
   653 
   654     data->glColor4f((GLfloat) renderer->r * inv255f,
   655                     (GLfloat) renderer->g * inv255f,
   656                     (GLfloat) renderer->b * inv255f,
   657                     (GLfloat) renderer->a * inv255f);
   658 
   659     GLshort vertices[4];
   660     vertices[0] = x1;
   661     vertices[1] = y1;
   662     vertices[2] = x2;
   663     vertices[3] = y2;
   664 
   665     data->glVertexPointer(2, GL_SHORT, 0, vertices);
   666     data->glEnableClientState(GL_VERTEX_ARRAY);
   667     data->glDrawArrays(GL_LINES, 0, 2);
   668     data->glDisableClientState(GL_VERTEX_ARRAY);
   669 
   670     return 0;
   671 }
   672 
   673 static int
   674 GLES_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
   675 {
   676     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   677 
   678     GLES_SetBlendMode(data, renderer->blendMode);
   679 
   680     data->glColor4f((GLfloat) renderer->r * inv255f,
   681                     (GLfloat) renderer->g * inv255f,
   682                     (GLfloat) renderer->b * inv255f,
   683                     (GLfloat) renderer->a * inv255f);
   684 
   685     GLshort minx = rect->x;
   686     GLshort maxx = rect->x + rect->w;
   687     GLshort miny = rect->y;
   688     GLshort maxy = rect->y + rect->h;
   689 
   690     GLshort vertices[8];
   691     vertices[0] = minx;
   692     vertices[1] = miny;
   693     vertices[2] = maxx;
   694     vertices[3] = miny;
   695     vertices[4] = minx;
   696     vertices[5] = maxy;
   697     vertices[6] = maxx;
   698     vertices[7] = maxy;
   699 
   700     data->glVertexPointer(2, GL_SHORT, 0, vertices);
   701     data->glEnableClientState(GL_VERTEX_ARRAY);
   702     data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   703     data->glDisableClientState(GL_VERTEX_ARRAY);
   704 
   705     return 0;
   706 }
   707 
   708 static int
   709 GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   710                 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   711 {
   712 
   713     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   714     GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
   715     int minx, miny, maxx, maxy;
   716     GLfloat minu, maxu, minv, maxv;
   717     int i;
   718     void *temp_buffer;          /* used for reformatting dirty rect pixels */
   719     void *temp_ptr;
   720 
   721     if (texturedata->dirty.list) {
   722         SDL_DirtyRect *dirty;
   723         void *pixels;
   724         int bpp = SDL_BYTESPERPIXEL(texture->format);
   725         int pitch = texturedata->pitch;
   726 
   727         SetupTextureUpdate(data, texture, pitch);
   728 
   729         data->glBindTexture(texturedata->type, texturedata->texture);
   730         for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
   731             SDL_Rect *rect = &dirty->rect;
   732             pixels =
   733                 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
   734                           rect->x * bpp);
   735             /*      There is no GL_UNPACK_ROW_LENGTH in OpenGLES 
   736                we must do this reformatting ourselves(!)
   737 
   738                maybe it'd be a good idea to keep a temp buffer around
   739                for this purpose rather than allocating it each time
   740              */
   741             temp_buffer = SDL_malloc(rect->w * rect->h * bpp);
   742             temp_ptr = temp_buffer;
   743             for (i = 0; i < rect->h; i++) {
   744                 SDL_memcpy(temp_ptr, pixels, rect->w * bpp);
   745                 temp_ptr += rect->w * bpp;
   746                 pixels += pitch;
   747             }
   748 
   749             data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
   750                                   rect->w, rect->h, texturedata->format,
   751                                   texturedata->formattype, temp_buffer);
   752 
   753             SDL_free(temp_buffer);
   754 
   755         }
   756         SDL_ClearDirtyRects(&texturedata->dirty);
   757     }
   758 
   759     data->glBindTexture(texturedata->type, texturedata->texture);
   760     data->glEnable(GL_TEXTURE_2D);
   761 
   762     if (texture->modMode) {
   763         data->glColor4f((GLfloat) texture->r * inv255f,
   764                         (GLfloat) texture->g * inv255f,
   765                         (GLfloat) texture->b * inv255f,
   766                         (GLfloat) texture->a * inv255f);
   767     } else {
   768         data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
   769     }
   770 
   771     GLES_SetBlendMode(data, texture->blendMode);
   772 
   773     switch (texture->scaleMode) {
   774     case SDL_TEXTURESCALEMODE_NONE:
   775     case SDL_TEXTURESCALEMODE_FAST:
   776         data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   777                               GL_NEAREST);
   778         data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   779                               GL_NEAREST);
   780         break;
   781     case SDL_TEXTURESCALEMODE_SLOW:
   782     case SDL_TEXTURESCALEMODE_BEST:
   783         data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   784                               GL_LINEAR);
   785         data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   786                               GL_LINEAR);
   787         break;
   788     }
   789 
   790     if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
   791         /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
   792         SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   793         GLint cropRect[4];
   794         cropRect[0] = srcrect->x;
   795         cropRect[1] = srcrect->y + srcrect->h;
   796         cropRect[2] = srcrect->w;
   797         cropRect[3] = -srcrect->h;
   798         data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
   799                                cropRect);
   800         data->glDrawTexiOES(dstrect->x, window->h - dstrect->y - dstrect->h,
   801                             0, dstrect->w, dstrect->h);
   802     } else {
   803 
   804         minx = dstrect->x;
   805         miny = dstrect->y;
   806         maxx = dstrect->x + dstrect->w;
   807         maxy = dstrect->y + dstrect->h;
   808 
   809         minu = (GLfloat) srcrect->x / texture->w;
   810         minu *= texturedata->texw;
   811         maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
   812         maxu *= texturedata->texw;
   813         minv = (GLfloat) srcrect->y / texture->h;
   814         minv *= texturedata->texh;
   815         maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
   816         maxv *= texturedata->texh;
   817 
   818         GLshort vertices[8];
   819         GLfloat texCoords[8];
   820 
   821         vertices[0] = minx;
   822         vertices[1] = miny;
   823         vertices[2] = maxx;
   824         vertices[3] = miny;
   825         vertices[4] = minx;
   826         vertices[5] = maxy;
   827         vertices[6] = maxx;
   828         vertices[7] = maxy;
   829 
   830         texCoords[0] = minu;
   831         texCoords[1] = minv;
   832         texCoords[2] = maxu;
   833         texCoords[3] = minv;
   834         texCoords[4] = minu;
   835         texCoords[5] = maxv;
   836         texCoords[6] = maxu;
   837         texCoords[7] = maxv;
   838 
   839         data->glVertexPointer(2, GL_SHORT, 0, vertices);
   840         data->glEnableClientState(GL_VERTEX_ARRAY);
   841         data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
   842         data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   843         data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   844 
   845     }
   846 
   847     return 0;
   848 }
   849 
   850 static void
   851 GLES_RenderPresent(SDL_Renderer * renderer)
   852 {
   853     SDL_GL_SwapWindow(renderer->window);
   854 }
   855 
   856 static void
   857 GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   858 {
   859     GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
   860     GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
   861 
   862     if (!data) {
   863         return;
   864     }
   865     if (data->texture) {
   866         glDeleteTextures(1, &data->texture);
   867     }
   868     if (data->pixels) {
   869         SDL_free(data->pixels);
   870     }
   871     SDL_FreeDirtyRects(&data->dirty);
   872     SDL_free(data);
   873     texture->driverdata = NULL;
   874 }
   875 
   876 static void
   877 GLES_DestroyRenderer(SDL_Renderer * renderer)
   878 {
   879     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   880 
   881     if (data) {
   882         if (data->context) {
   883             /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
   884             SDL_GL_DeleteContext(data->context);
   885         }
   886         SDL_free(data);
   887     }
   888     SDL_free(renderer);
   889 }
   890 
   891 #endif /* SDL_VIDEO_RENDER_OGL */
   892 
   893 /* vi: set ts=4 sw=4 expandtab: */