Fixed bug 4469 - make SDL_CreateTextureFromSurface pick a more appropriate format
authorSam Lantinga <slouken@libsdl.org>
Sun, 19 May 2019 12:04:06 -0700
changeset 12739ae1dd7bee797
parent 12738 64dabb27041d
child 12740 8a533504ed44
Fixed bug 4469 - make SDL_CreateTextureFromSurface pick a more appropriate format

Sylvain

Currently SDL_CreateTextureFromSurface picks first valid format, and do a conversion.

format = renderer->info.texture_formats[0];
for (i = 0; i < renderer->info.num_texture_formats; ++i) {
if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
format = renderer->info.texture_formats[i];
break;

It could try to find a better format, for instance :

if SDL_Surface has no Amask, but a colorkey :
if surface fmt is RGB888, try to pick ARGB8888 renderer fmt
if surface fmt is BGR888, try to pick ABGR8888 renderer fmt
else
try to pick the same renderer format as surface fmt

if no format has been picked, use the fallback.


I think it goes with bug 4290 fastpath BlitNtoN
when you expand a surface with pixel format of size 24 to 32, there is a fast path possible.


So with this issue:

- if you have a surface with colorkey (RGB or BGR, not palette), it takes a renderer format where the conversion is faster.
(it avoids, if possible, RGB -> ABGR which means switching RGB to BGR)

- if you have a surface ABGR format, it try to take the ABGR from the renderer.
(it avoids, if possible, ABGR -> ARGB, which means switch RGB to BGR)
src/render/SDL_render.c
     1.1 --- a/src/render/SDL_render.c	Sun May 19 11:56:26 2019 -0700
     1.2 +++ b/src/render/SDL_render.c	Sun May 19 12:04:06 2019 -0700
     1.3 @@ -1189,7 +1189,7 @@
     1.4      SDL_bool needAlpha;
     1.5      SDL_bool direct_update;
     1.6      int i;
     1.7 -    Uint32 format;
     1.8 +    Uint32 format = SDL_PIXELFORMAT_UNKNOWN;
     1.9      SDL_Texture *texture;
    1.10  
    1.11      CHECK_RENDERER_MAGIC(renderer, NULL);
    1.12 @@ -1218,12 +1218,43 @@
    1.13          }
    1.14      }
    1.15  
    1.16 -    format = renderer->info.texture_formats[0];
    1.17 -    for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
    1.18 -        if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
    1.19 -            SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
    1.20 -            format = renderer->info.texture_formats[i];
    1.21 -            break;
    1.22 +    /* Try to have the best pixel format for the texture */
    1.23 +    /* No alpha, but a colorkey => promote to alpha */
    1.24 +    if (!fmt->Amask && SDL_HasColorKey(surface)) {
    1.25 +        if (fmt->format == SDL_PIXELFORMAT_RGB888) {
    1.26 +            for (i = 0; i < renderer->info.num_texture_formats; ++i) {
    1.27 +                if (renderer->info.texture_formats[i] == SDL_PIXELFORMAT_ARGB8888) {
    1.28 +                    format = SDL_PIXELFORMAT_ARGB8888;
    1.29 +                    break;
    1.30 +                }
    1.31 +            }
    1.32 +        } else if (fmt->format == SDL_PIXELFORMAT_BGR888) {
    1.33 +            for (i = 0; i < renderer->info.num_texture_formats; ++i) {
    1.34 +                if (renderer->info.texture_formats[i] == SDL_PIXELFORMAT_ABGR8888) {
    1.35 +                    format = SDL_PIXELFORMAT_ABGR8888;
    1.36 +                    break;
    1.37 +                }
    1.38 +            }
    1.39 +        }
    1.40 +    } else {
    1.41 +        /* Exact match would be fine */
    1.42 +        for (i = 0; i < renderer->info.num_texture_formats; ++i) {
    1.43 +            if (renderer->info.texture_formats[i] == fmt->format) {
    1.44 +                format = fmt->format;
    1.45 +                break;
    1.46 +            }
    1.47 +        }
    1.48 +    }
    1.49 +
    1.50 +    /* Fallback, choose a valid pixel format */
    1.51 +    if (format == SDL_PIXELFORMAT_UNKNOWN) {
    1.52 +        format = renderer->info.texture_formats[0];
    1.53 +        for (i = 0; i < renderer->info.num_texture_formats; ++i) {
    1.54 +            if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
    1.55 +                    SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
    1.56 +                format = renderer->info.texture_formats[i];
    1.57 +                break;
    1.58 +            }
    1.59          }
    1.60      }
    1.61