src/video/SDL_renderer_gles.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 24 Mar 2009 10:33:12 +0000
changeset 3099 82e60908fab1
parent 2964 0faae272a372
child 3122 6c98826d88b0
permissions -rw-r--r--
Date: Mon, 23 Mar 2009 09:17:24 +0200
From: "Mike Gorchak"
Subject: New QNX patches

Please apply patch qnx4.diff, which is attached. What has been done:
1)Added back OpenGL ES renderer for QNX target. Added few corrections to
OpenGL ES renderer to let it work under QNX. OpenGL ES renderer do not
support textures under QNX, so I think some additional work must be done.
2) Added GL_OES_query_matrix extension to SDL_opengles.h header file, which
required by OpenGL ES 1.1 specification.
3) Added attribute clearing at the entrance of function
SDL_GL_GetAttribure(). Added error checking into the function
SDL_GL_GetAttribure(), because some attributes can't be obtained in OpenGL
ES 1.0.
4) Porting testdyngles to OpenGL ES 1.0 (1.1 has glColor4ub() and
glColor4f() functions, but 1.0 has glColor4f() only).
5) Added error checking after obtaining attributes using
SDL_GL_GetAttribute() function to the testgl2 and testgles.
6) Small correction to testmultiaudio with printing errors.
7) Added software and accelerated OpenGL ES 1.0 support into the QNX GF
driver.

Please remove ./src/audio/nto directory - it will not be used anymore.
Please create ./src/audio/qsa directory and add content of the archive
qsa.tar.gz into this directory. I rewrote some sound code, added support for
multiple audio cards, enumeration, etc. Added initial support for capture.

As far as I can understand SDL 1.3 is not supporting audio capture right now
? Sam, Am I right ? Or audio capture must be supported through the
PlayDevice routine ?

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