diff src/render/SDL_render.c @ 5161:b3ccd1947786

Simplified and improved the process of creating a texture from a surface.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 03 Feb 2011 00:54:29 -0800
parents 657543cc92f9
children 4d39eeaad00b
line wrap: on
line diff
--- a/src/render/SDL_render.c	Thu Feb 03 00:22:18 2011 -0800
+++ b/src/render/SDL_render.c	Thu Feb 03 00:54:29 2011 -0800
@@ -250,13 +250,15 @@
 }
 
 SDL_Texture *
-SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface * surface)
+SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
 {
-    SDL_Texture *texture;
-    Uint32 requested_format = format;
-    SDL_PixelFormat *fmt;
+    const SDL_PixelFormat *fmt;
+    SDL_bool needAlpha;
+    Uint32 i;
+    Uint32 format;
     int bpp;
     Uint32 Rmask, Gmask, Bmask, Amask;
+    SDL_Texture *texture;
 
     CHECK_RENDERER_MAGIC(renderer, NULL);
 
@@ -264,255 +266,56 @@
         SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
         return NULL;
     }
+
+    /* See what the best texture format is */
     fmt = surface->format;
-
-    if (format) {
-        if (!SDL_PixelFormatEnumToMasks
-            (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
-            SDL_SetError("Unknown pixel format");
-            return 0;
-        }
+    if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) {
+        needAlpha = SDL_TRUE;
     } else {
-        SDL_bool hasColorkey;
-        SDL_BlendMode blendMode;
-        SDL_bool hasBlending;
-
-        hasColorkey = (SDL_GetColorKey(surface, NULL) == 0);
-
-        SDL_GetSurfaceBlendMode(surface, &blendMode);
-        hasBlending = (blendMode == SDL_BLENDMODE_BLEND);
-
-        if (surface->format->Amask || (!hasColorkey && !hasBlending)) {
-            Uint32 it;
-            int pfmt;
-
-            /* Pixel formats, sorted by best first */
-            static const Uint32 sdl_pformats[] = {
-                SDL_PIXELFORMAT_ARGB8888,
-                SDL_PIXELFORMAT_RGBA8888,
-                SDL_PIXELFORMAT_ABGR8888,
-                SDL_PIXELFORMAT_BGRA8888,
-                SDL_PIXELFORMAT_RGB888,
-                SDL_PIXELFORMAT_BGR888,
-                SDL_PIXELFORMAT_RGB24,
-                SDL_PIXELFORMAT_BGR24,
-                SDL_PIXELFORMAT_RGB565,
-                SDL_PIXELFORMAT_BGR565,
-                SDL_PIXELFORMAT_ARGB1555,
-                SDL_PIXELFORMAT_RGBA5551,
-                SDL_PIXELFORMAT_ABGR1555,
-                SDL_PIXELFORMAT_BGRA5551,
-                SDL_PIXELFORMAT_RGB555,
-                SDL_PIXELFORMAT_BGR555,
-                SDL_PIXELFORMAT_ARGB4444,
-                SDL_PIXELFORMAT_RGBA4444,
-                SDL_PIXELFORMAT_ABGR4444,
-                SDL_PIXELFORMAT_BGRA4444,
-                SDL_PIXELFORMAT_RGB444,
-                SDL_PIXELFORMAT_ARGB2101010,
-                SDL_PIXELFORMAT_RGB332,
-                SDL_PIXELFORMAT_UNKNOWN
-            };
-
-            bpp = fmt->BitsPerPixel;
-            Rmask = fmt->Rmask;
-            Gmask = fmt->Gmask;
-            Bmask = fmt->Bmask;
-            Amask = fmt->Amask;
-
-            format =
-                SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
-            if (!format) {
-                SDL_SetError("Unknown pixel format");
-                return 0;
-            }
-
-            /* Search requested format in the supported texture */
-            /* formats by current renderer                      */
-            for (it = 0; it < renderer->info.num_texture_formats; it++) {
-                if (renderer->info.texture_formats[it] == format) {
-                    break;
-                }
-            }
-
-            /* If requested format can't be found, search any best */
-            /* format which renderer provides                      */
-            if (it == renderer->info.num_texture_formats) {
-                pfmt = 0;
-                for (;;) {
-                    if (sdl_pformats[pfmt] == SDL_PIXELFORMAT_UNKNOWN) {
-                        break;
-                    }
-
-                    for (it = 0; it < renderer->info.num_texture_formats;
-                         it++) {
-                        if (renderer->info.texture_formats[it] ==
-                            sdl_pformats[pfmt]) {
-                            break;
-                        }
-                    }
-
-                    if (it != renderer->info.num_texture_formats) {
-                        /* The best format has been found */
-                        break;
-                    }
-                    pfmt++;
-                }
-
-                /* If any format can't be found, then return an error */
-                if (it == renderer->info.num_texture_formats) {
-                    SDL_SetError
-                        ("Any of the supported pixel formats can't be found");
-                    return 0;
-                }
-
-                /* Convert found pixel format back to color masks */
-                if (SDL_PixelFormatEnumToMasks
-                    (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
-                     &Bmask, &Amask) != SDL_TRUE) {
-                    SDL_SetError("Unknown pixel format");
-                    return 0;
-                }
-            }
-        } else {
-            /* Need a format with alpha */
-            Uint32 it;
-            int apfmt;
-
-            /* Pixel formats with alpha, sorted by best first */
-            static const Uint32 sdl_alpha_pformats[] = {
-                SDL_PIXELFORMAT_ARGB8888,
-                SDL_PIXELFORMAT_RGBA8888,
-                SDL_PIXELFORMAT_ABGR8888,
-                SDL_PIXELFORMAT_BGRA8888,
-                SDL_PIXELFORMAT_ARGB1555,
-                SDL_PIXELFORMAT_RGBA5551,
-                SDL_PIXELFORMAT_ABGR1555,
-                SDL_PIXELFORMAT_BGRA5551,
-                SDL_PIXELFORMAT_ARGB4444,
-                SDL_PIXELFORMAT_RGBA4444,
-                SDL_PIXELFORMAT_ABGR4444,
-                SDL_PIXELFORMAT_BGRA4444,
-                SDL_PIXELFORMAT_ARGB2101010,
-                SDL_PIXELFORMAT_UNKNOWN
-            };
-
-            if (surface->format->Amask) {
-                /* If surface already has alpha, then try an original */
-                /* surface format first                               */
-                bpp = fmt->BitsPerPixel;
-                Rmask = fmt->Rmask;
-                Gmask = fmt->Gmask;
-                Bmask = fmt->Bmask;
-                Amask = fmt->Amask;
-            } else {
-                bpp = 32;
-                Rmask = 0x00FF0000;
-                Gmask = 0x0000FF00;
-                Bmask = 0x000000FF;
-                Amask = 0xFF000000;
-            }
-
-            format =
-                SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
-            if (!format) {
-                SDL_SetError("Unknown pixel format");
-                return 0;
-            }
-
-            /* Search this format in the supported texture formats */
-            /* by current renderer                                 */
-            for (it = 0; it < renderer->info.num_texture_formats; it++) {
-                if (renderer->info.texture_formats[it] == format) {
-                    break;
-                }
-            }
-
-            /* If this format can't be found, search any best       */
-            /* compatible format with alpha which renderer provides */
-            if (it == renderer->info.num_texture_formats) {
-                apfmt = 0;
-                for (;;) {
-                    if (sdl_alpha_pformats[apfmt] == SDL_PIXELFORMAT_UNKNOWN) {
-                        break;
-                    }
-
-                    for (it = 0; it < renderer->info.num_texture_formats;
-                         it++) {
-                        if (renderer->info.texture_formats[it] ==
-                            sdl_alpha_pformats[apfmt]) {
-                            break;
-                        }
-                    }
-
-                    if (it != renderer->info.num_texture_formats) {
-                        /* Compatible format has been found */
-                        break;
-                    }
-                    apfmt++;
-                }
-
-                /* If compatible format can't be found, then return an error */
-                if (it == renderer->info.num_texture_formats) {
-                    SDL_SetError("Compatible pixel format can't be found");
-                    return 0;
-                }
-
-                /* Convert found pixel format back to color masks */
-                if (SDL_PixelFormatEnumToMasks
-                    (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
-                     &Bmask, &Amask) != SDL_TRUE) {
-                    SDL_SetError("Unknown pixel format");
-                    return 0;
-                }
-            }
-        }
-
-        format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
-        if (!format) {
-            SDL_SetError("Unknown pixel format");
-            return 0;
+        needAlpha = SDL_FALSE;
+    }
+    format = renderer->info.texture_formats[0];
+    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
+        if (SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
+            format = renderer->info.texture_formats[i];
+            break;
         }
     }
 
-    texture =
-        SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
-                          surface->w, surface->h);
-    if (!texture && !requested_format) {
-        SDL_DisplayMode desktop_mode;
-        SDL_GetDesktopDisplayMode(&desktop_mode);
-        format = desktop_mode.format;
-        texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
-                                    surface->w, surface->h);
+    if (!SDL_PixelFormatEnumToMasks(format, &bpp,
+                                    &Rmask, &Gmask, &Bmask, &Amask)) {
+        SDL_SetError("Unknown pixel format");
+        return NULL;
     }
+
+    texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
+                                surface->w, surface->h);
     if (!texture) {
-        return 0;
+        return NULL;
     }
+
     if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask
         && Bmask == fmt->Bmask && Amask == fmt->Amask) {
         if (SDL_MUSTLOCK(surface)) {
             SDL_LockSurface(surface);
-            SDL_UpdateTexture(texture, NULL, surface->pixels,
-                              surface->pitch);
+            SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
             SDL_UnlockSurface(surface);
         } else {
-            SDL_UpdateTexture(texture, NULL, surface->pixels,
-                              surface->pitch);
+            SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
         }
     } else {
         SDL_PixelFormat dst_fmt;
-        SDL_Surface *dst = NULL;
+        SDL_Surface *temp = NULL;
 
         /* Set up a destination surface for the texture update */
         SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask);
-        dst = SDL_ConvertSurface(surface, &dst_fmt, 0);
-        if (dst) {
-            SDL_UpdateTexture(texture, NULL, dst->pixels, dst->pitch);
-            SDL_FreeSurface(dst);
-        }
-        if (!dst) {
+        temp = SDL_ConvertSurface(surface, &dst_fmt, 0);
+        if (temp) {
+            SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
+            SDL_FreeSurface(temp);
+        } else {
             SDL_DestroyTexture(texture);
-            return 0;
+            return NULL;
         }
     }