Simplified and improved the process of creating a texture from a surface.
authorSam Lantinga <slouken@libsdl.org>
Thu, 03 Feb 2011 00:54:29 -0800
changeset 5158 b3ccd1947786
parent 5157 657543cc92f9
child 5159 df758fce08e9
Simplified and improved the process of creating a texture from a surface.
include/SDL_render.h
src/render/SDL_render.c
test/testshape.c
test/testsprite2.c
test/testspriteminimal.c
--- a/include/SDL_render.h	Thu Feb 03 00:22:18 2011 -0800
+++ b/include/SDL_render.h	Thu Feb 03 00:54:29 2011 -0800
@@ -172,19 +172,16 @@
 /**
  *  \brief Create a texture from an existing surface.
  *  
- *  \param format The format of the texture, or 0 to pick an appropriate format.
  *  \param surface The surface containing pixel data used to fill the texture.
  *  
- *  \return The created texture is returned, or 0 if no rendering context was 
- *          active,  the format was unsupported, or the surface width or height 
- *          were out of range.
+ *  \return The created texture is returned, or 0 on error.
  *  
  *  \note The surface is not modified or freed by this function.
  *  
  *  \sa SDL_QueryTexture()
  *  \sa SDL_DestroyTexture()
  */
-extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface * surface);
+extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface);
 
 /**
  *  \brief Query the attributes of a texture
--- 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;
         }
     }
 
--- a/test/testshape.c	Thu Feb 03 00:22:18 2011 -0800
+++ b/test/testshape.c	Thu Feb 03 00:54:29 2011 -0800
@@ -118,7 +118,7 @@
     for(i=0;i<num_pictures;i++)
         pictures[i].texture = NULL;
     for(i=0;i<num_pictures;i++) {
-        pictures[i].texture = SDL_CreateTextureFromSurface(renderer,0,pictures[i].surface);
+        pictures[i].texture = SDL_CreateTextureFromSurface(renderer,pictures[i].surface);
         if(pictures[i].texture == NULL) {
             j = 0;
             for(j=0;j<num_pictures;i++)
--- a/test/testsprite2.c	Thu Feb 03 00:22:18 2011 -0800
+++ b/test/testsprite2.c	Thu Feb 03 00:54:29 2011 -0800
@@ -77,11 +77,7 @@
     /* Create textures from the image */
     for (i = 0; i < state->num_windows; ++i) {
         SDL_Renderer *renderer = state->renderers[i];
-        sprites[i] = SDL_CreateTextureFromSurface(renderer, 0, temp);
-        if (!sprites[i]) {
-            SDL_SetColorKey(temp, 0, 0);
-            sprites[i] = SDL_CreateTextureFromSurface(renderer, 0, temp);
-        }
+        sprites[i] = SDL_CreateTextureFromSurface(renderer, temp);
         if (!sprites[i]) {
             fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
             SDL_FreeSurface(temp);
--- a/test/testspriteminimal.c	Thu Feb 03 00:22:18 2011 -0800
+++ b/test/testspriteminimal.c	Thu Feb 03 00:54:29 2011 -0800
@@ -60,11 +60,7 @@
     }
 
     /* Create textures from the image */
-    sprite = SDL_CreateTextureFromSurface(renderer, 0, temp);
-    if (!sprite) {
-        SDL_SetColorKey(temp, 0, 0);
-        sprite = SDL_CreateTextureFromSurface(renderer, 0, temp);
-    }
+    sprite = SDL_CreateTextureFromSurface(renderer, temp);
     if (!sprite) {
         fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
         SDL_FreeSurface(temp);