Commit 41c718db859de054daa9fa192406d3f9a44a54fe

Sam Lantinga 2019-05-19T12:04:06

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)

diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 81f9296..faca9fe 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -1189,7 +1189,7 @@ SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
     SDL_bool needAlpha;
     SDL_bool direct_update;
     int i;
-    Uint32 format;
+    Uint32 format = SDL_PIXELFORMAT_UNKNOWN;
     SDL_Texture *texture;
 
     CHECK_RENDERER_MAGIC(renderer, NULL);
@@ -1218,12 +1218,43 @@ SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
         }
     }
 
-    format = renderer->info.texture_formats[0];
-    for (i = 0; i < (int)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;
+    /* Try to have the best pixel format for the texture */
+    /* No alpha, but a colorkey => promote to alpha */
+    if (!fmt->Amask && SDL_HasColorKey(surface)) {
+        if (fmt->format == SDL_PIXELFORMAT_RGB888) {
+            for (i = 0; i < renderer->info.num_texture_formats; ++i) {
+                if (renderer->info.texture_formats[i] == SDL_PIXELFORMAT_ARGB8888) {
+                    format = SDL_PIXELFORMAT_ARGB8888;
+                    break;
+                }
+            }
+        } else if (fmt->format == SDL_PIXELFORMAT_BGR888) {
+            for (i = 0; i < renderer->info.num_texture_formats; ++i) {
+                if (renderer->info.texture_formats[i] == SDL_PIXELFORMAT_ABGR8888) {
+                    format = SDL_PIXELFORMAT_ABGR8888;
+                    break;
+                }
+            }
+        }
+    } else {
+        /* Exact match would be fine */
+        for (i = 0; i < renderer->info.num_texture_formats; ++i) {
+            if (renderer->info.texture_formats[i] == fmt->format) {
+                format = fmt->format;
+                break;
+            }
+        }
+    }
+
+    /* Fallback, choose a valid pixel format */
+    if (format == SDL_PIXELFORMAT_UNKNOWN) {
+        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;
+            }
         }
     }