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