comparison src/render/opengles/SDL_renderer_gles.c @ 5159:307ccc9c135e

Made it possible to create a texture of any format, even if not supported by the renderer. This allows me to reduce the set of formats supported by the renderers to the most optimal set, for a nice speed boost.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 03 Feb 2011 00:19:40 -0800
parents fb424691cfc7
children 1bd1e62e648d
comparison
equal deleted inserted replaced
5158:f3ebd1950442 5159:307ccc9c135e
47 47
48 static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags); 48 static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
49 static void GLES_WindowEvent(SDL_Renderer * renderer, 49 static void GLES_WindowEvent(SDL_Renderer * renderer,
50 const SDL_WindowEvent *event); 50 const SDL_WindowEvent *event);
51 static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); 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_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 52 static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
56 const SDL_Rect * rect, const void *pixels, 53 const SDL_Rect * rect, const void *pixels,
57 int pitch); 54 int pitch);
58 static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 55 static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
59 const SDL_Rect * rect, int markDirty, 56 const SDL_Rect * rect, void **pixels, int *pitch);
60 void **pixels, int *pitch);
61 static void GLES_UnlockTexture(SDL_Renderer * renderer, 57 static void GLES_UnlockTexture(SDL_Renderer * renderer,
62 SDL_Texture * texture); 58 SDL_Texture * texture);
63 static void GLES_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
64 int numrects, const SDL_Rect * rects);
65 static int GLES_RenderDrawPoints(SDL_Renderer * renderer, 59 static int GLES_RenderDrawPoints(SDL_Renderer * renderer,
66 const SDL_Point * points, int count); 60 const SDL_Point * points, int count);
67 static int GLES_RenderDrawLines(SDL_Renderer * renderer, 61 static int GLES_RenderDrawLines(SDL_Renderer * renderer,
68 const SDL_Point * points, int count); 62 const SDL_Point * points, int count);
69 static int GLES_RenderFillRects(SDL_Renderer * renderer, 63 static int GLES_RenderFillRects(SDL_Renderer * renderer,
80 SDL_RenderDriver GL_ES_RenderDriver = { 74 SDL_RenderDriver GL_ES_RenderDriver = {
81 GLES_CreateRenderer, 75 GLES_CreateRenderer,
82 { 76 {
83 "opengl_es", 77 "opengl_es",
84 (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED), 78 (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
85 6, 79 1,
86 { 80 {SDL_PIXELFORMAT_ABGR8888},
87 /* OpenGL ES 1.x supported formats list */
88 SDL_PIXELFORMAT_RGBA4444,
89 SDL_PIXELFORMAT_RGBA5551,
90 SDL_PIXELFORMAT_RGB565,
91 SDL_PIXELFORMAT_RGB24,
92 SDL_PIXELFORMAT_BGR888,
93 SDL_PIXELFORMAT_ABGR8888},
94 0, 81 0,
95 0} 82 0}
96 }; 83 };
97 84
98 typedef struct 85 typedef struct
123 GLfloat texh; 110 GLfloat texh;
124 GLenum format; 111 GLenum format;
125 GLenum formattype; 112 GLenum formattype;
126 void *pixels; 113 void *pixels;
127 int pitch; 114 int pitch;
128 SDL_DirtyRectList dirty;
129 } GLES_TextureData; 115 } GLES_TextureData;
130 116
131 static void 117 static void
132 GLES_SetError(const char *prefix, GLenum result) 118 GLES_SetError(const char *prefix, GLenum result)
133 { 119 {
203 return NULL; 189 return NULL;
204 } 190 }
205 191
206 renderer->WindowEvent = GLES_WindowEvent; 192 renderer->WindowEvent = GLES_WindowEvent;
207 renderer->CreateTexture = GLES_CreateTexture; 193 renderer->CreateTexture = GLES_CreateTexture;
208 renderer->QueryTexturePixels = GLES_QueryTexturePixels;
209 renderer->UpdateTexture = GLES_UpdateTexture; 194 renderer->UpdateTexture = GLES_UpdateTexture;
210 renderer->LockTexture = GLES_LockTexture; 195 renderer->LockTexture = GLES_LockTexture;
211 renderer->UnlockTexture = GLES_UnlockTexture; 196 renderer->UnlockTexture = GLES_UnlockTexture;
212 renderer->DirtyTexture = GLES_DirtyTexture;
213 renderer->RenderDrawPoints = GLES_RenderDrawPoints; 197 renderer->RenderDrawPoints = GLES_RenderDrawPoints;
214 renderer->RenderDrawLines = GLES_RenderDrawLines; 198 renderer->RenderDrawLines = GLES_RenderDrawLines;
215 renderer->RenderFillRects = GLES_RenderFillRects; 199 renderer->RenderFillRects = GLES_RenderFillRects;
216 renderer->RenderCopy = GLES_RenderCopy; 200 renderer->RenderCopy = GLES_RenderCopy;
217 renderer->RenderPresent = GLES_RenderPresent; 201 renderer->RenderPresent = GLES_RenderPresent;
341 GLenum result; 325 GLenum result;
342 326
343 GLES_ActivateRenderer(renderer); 327 GLES_ActivateRenderer(renderer);
344 328
345 switch (texture->format) { 329 switch (texture->format) {
346 case SDL_PIXELFORMAT_RGB24:
347 internalFormat = GL_RGB;
348 format = GL_RGB;
349 type = GL_UNSIGNED_BYTE;
350 break;
351 case SDL_PIXELFORMAT_BGR888:
352 case SDL_PIXELFORMAT_ABGR8888: 330 case SDL_PIXELFORMAT_ABGR8888:
353 internalFormat = GL_RGBA; 331 internalFormat = GL_RGBA;
354 format = GL_RGBA; 332 format = GL_RGBA;
355 type = GL_UNSIGNED_BYTE; 333 type = GL_UNSIGNED_BYTE;
356 break;
357 case SDL_PIXELFORMAT_RGB565:
358 internalFormat = GL_RGB;
359 format = GL_RGB;
360 type = GL_UNSIGNED_SHORT_5_6_5;
361 break;
362 case SDL_PIXELFORMAT_RGBA5551:
363 internalFormat = GL_RGBA;
364 format = GL_RGBA;
365 type = GL_UNSIGNED_SHORT_5_5_5_1;
366 break;
367 case SDL_PIXELFORMAT_RGBA4444:
368 internalFormat = GL_RGBA;
369 format = GL_RGBA;
370 type = GL_UNSIGNED_SHORT_4_4_4_4;
371 break; 334 break;
372 default: 335 default:
373 SDL_SetError("Texture format %s not supported by OpenGL ES", 336 SDL_SetError("Texture format %s not supported by OpenGL ES",
374 SDL_GetPixelFormatName(texture->format)); 337 SDL_GetPixelFormatName(texture->format));
375 return -1; 338 return -1;
426 return -1; 389 return -1;
427 } 390 }
428 return 0; 391 return 0;
429 } 392 }
430 393
431 static int
432 GLES_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
433 void **pixels, int *pitch)
434 {
435 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
436
437 *pixels = data->pixels;
438 *pitch = data->pitch;
439 return 0;
440 }
441
442 static void 394 static void
443 SetupTextureUpdate(GLES_RenderData * renderdata, SDL_Texture * texture, 395 SetupTextureUpdate(GLES_RenderData * renderdata, SDL_Texture * texture,
444 int pitch) 396 int pitch)
445 { 397 {
446 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
447 renderdata->glBindTexture(data->type, data->texture);
448 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 398 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
449 } 399 }
450 400
451 static int 401 static int
452 GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 402 GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
461 int i; 411 int i;
462 412
463 GLES_ActivateRenderer(renderer); 413 GLES_ActivateRenderer(renderer);
464 414
465 renderdata->glGetError(); 415 renderdata->glGetError();
416 SetupTextureUpdate(renderdata, texture, pitch);
466 renderdata->glEnable(data->type); 417 renderdata->glEnable(data->type);
467 SetupTextureUpdate(renderdata, texture, pitch); 418 renderdata->glBindTexture(data->type, data->texture);
468 419
469 if( rect->w * bpp == pitch ) { 420 if( rect->w * bpp == pitch ) {
470 temp_buffer = (void *)pixels; /* No need to reformat */ 421 temp_buffer = (void *)pixels; /* No need to reformat */
471 } else { 422 } else {
472 /* Reformatting of mem area required */ 423 /* Reformatting of mem area required */
496 return 0; 447 return 0;
497 } 448 }
498 449
499 static int 450 static int
500 GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 451 GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
501 const SDL_Rect * rect, int markDirty, void **pixels, 452 const SDL_Rect * rect, void **pixels, int *pitch)
502 int *pitch)
503 { 453 {
504 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; 454 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
505
506 if (markDirty) {
507 SDL_AddDirtyRect(&data->dirty, rect);
508 }
509 455
510 *pixels = 456 *pixels =
511 (void *) ((Uint8 *) data->pixels + rect->y * data->pitch + 457 (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
512 rect->x * SDL_BYTESPERPIXEL(texture->format)); 458 rect->x * SDL_BYTESPERPIXEL(texture->format));
513 *pitch = data->pitch; 459 *pitch = data->pitch;
515 } 461 }
516 462
517 static void 463 static void
518 GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) 464 GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
519 { 465 {
520 } 466 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
521
522 static void
523 GLES_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
524 int numrects, const SDL_Rect * rects)
525 {
526 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; 467 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
527 int i; 468
528 469 GLES_ActivateRenderer(renderer);
529 for (i = 0; i < numrects; ++i) { 470
530 SDL_AddDirtyRect(&data->dirty, &rects[i]); 471 SetupTextureUpdate(renderdata, texture, data->pitch);
531 } 472 renderdata->glEnable(data->type);
473 renderdata->glBindTexture(data->type, data->texture);
474 renderdata->glTexSubImage2D(data->type, 0, 0, 0, texture->w,
475 texture->h, data->format, data->formattype,
476 data->pixels);
477 renderdata->glDisable(data->type);
532 } 478 }
533 479
534 static void 480 static void
535 GLES_SetBlendMode(GLES_RenderData * data, int blendMode) 481 GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
536 { 482 {
674 620
675 GLES_ActivateRenderer(renderer); 621 GLES_ActivateRenderer(renderer);
676 622
677 data->glEnable(GL_TEXTURE_2D); 623 data->glEnable(GL_TEXTURE_2D);
678 624
679 if (texturedata->dirty.list) {
680 SDL_DirtyRect *dirty;
681 void *pixels;
682 int bpp = SDL_BYTESPERPIXEL(texture->format);
683 int pitch = texturedata->pitch;
684
685 SetupTextureUpdate(data, texture, pitch);
686
687 data->glBindTexture(texturedata->type, texturedata->texture);
688 for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
689 SDL_Rect *rect = &dirty->rect;
690 pixels =
691 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
692 rect->x * bpp);
693 /* There is no GL_UNPACK_ROW_LENGTH in OpenGLES
694 we must do this reformatting ourselves(!)
695
696 maybe it'd be a good idea to keep a temp buffer around
697 for this purpose rather than allocating it each time
698 */
699 if( rect->x == 0 && rect->w * bpp == pitch ) {
700 temp_buffer = pixels; /* Updating whole texture, no need to reformat */
701 } else {
702 temp_buffer = SDL_malloc(rect->w * rect->h * bpp);
703 temp_ptr = temp_buffer;
704 for (i = 0; i < rect->h; i++) {
705 SDL_memcpy(temp_ptr, pixels, rect->w * bpp);
706 temp_ptr += rect->w * bpp;
707 pixels += pitch;
708 }
709 }
710
711 data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
712 rect->w, rect->h, texturedata->format,
713 texturedata->formattype, temp_buffer);
714
715 if( temp_buffer != pixels ) {
716 SDL_free(temp_buffer);
717 }
718 }
719 SDL_ClearDirtyRects(&texturedata->dirty);
720 }
721
722 data->glBindTexture(texturedata->type, texturedata->texture); 625 data->glBindTexture(texturedata->type, texturedata->texture);
723 626
724 if (texture->modMode) { 627 if (texture->modMode) {
725 data->glColor4f((GLfloat) texture->r * inv255f, 628 data->glColor4f((GLfloat) texture->r * inv255f,
726 (GLfloat) texture->g * inv255f, 629 (GLfloat) texture->g * inv255f,
816 glDeleteTextures(1, &data->texture); 719 glDeleteTextures(1, &data->texture);
817 } 720 }
818 if (data->pixels) { 721 if (data->pixels) {
819 SDL_free(data->pixels); 722 SDL_free(data->pixels);
820 } 723 }
821 SDL_FreeDirtyRects(&data->dirty);
822 SDL_free(data); 724 SDL_free(data);
823 texture->driverdata = NULL; 725 texture->driverdata = NULL;
824 } 726 }
825 727
826 static void 728 static void