Mercurial > sdl-ios-xcode
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 |