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 5158b3ccd1947786
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
     1.1 --- a/include/SDL_render.h	Thu Feb 03 00:22:18 2011 -0800
     1.2 +++ b/include/SDL_render.h	Thu Feb 03 00:54:29 2011 -0800
     1.3 @@ -172,19 +172,16 @@
     1.4  /**
     1.5   *  \brief Create a texture from an existing surface.
     1.6   *  
     1.7 - *  \param format The format of the texture, or 0 to pick an appropriate format.
     1.8   *  \param surface The surface containing pixel data used to fill the texture.
     1.9   *  
    1.10 - *  \return The created texture is returned, or 0 if no rendering context was 
    1.11 - *          active,  the format was unsupported, or the surface width or height 
    1.12 - *          were out of range.
    1.13 + *  \return The created texture is returned, or 0 on error.
    1.14   *  
    1.15   *  \note The surface is not modified or freed by this function.
    1.16   *  
    1.17   *  \sa SDL_QueryTexture()
    1.18   *  \sa SDL_DestroyTexture()
    1.19   */
    1.20 -extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface * surface);
    1.21 +extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface);
    1.22  
    1.23  /**
    1.24   *  \brief Query the attributes of a texture
     2.1 --- a/src/render/SDL_render.c	Thu Feb 03 00:22:18 2011 -0800
     2.2 +++ b/src/render/SDL_render.c	Thu Feb 03 00:54:29 2011 -0800
     2.3 @@ -250,13 +250,15 @@
     2.4  }
     2.5  
     2.6  SDL_Texture *
     2.7 -SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface * surface)
     2.8 +SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
     2.9  {
    2.10 -    SDL_Texture *texture;
    2.11 -    Uint32 requested_format = format;
    2.12 -    SDL_PixelFormat *fmt;
    2.13 +    const SDL_PixelFormat *fmt;
    2.14 +    SDL_bool needAlpha;
    2.15 +    Uint32 i;
    2.16 +    Uint32 format;
    2.17      int bpp;
    2.18      Uint32 Rmask, Gmask, Bmask, Amask;
    2.19 +    SDL_Texture *texture;
    2.20  
    2.21      CHECK_RENDERER_MAGIC(renderer, NULL);
    2.22  
    2.23 @@ -264,255 +266,56 @@
    2.24          SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
    2.25          return NULL;
    2.26      }
    2.27 +
    2.28 +    /* See what the best texture format is */
    2.29      fmt = surface->format;
    2.30 -
    2.31 -    if (format) {
    2.32 -        if (!SDL_PixelFormatEnumToMasks
    2.33 -            (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
    2.34 -            SDL_SetError("Unknown pixel format");
    2.35 -            return 0;
    2.36 -        }
    2.37 +    if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) {
    2.38 +        needAlpha = SDL_TRUE;
    2.39      } else {
    2.40 -        SDL_bool hasColorkey;
    2.41 -        SDL_BlendMode blendMode;
    2.42 -        SDL_bool hasBlending;
    2.43 -
    2.44 -        hasColorkey = (SDL_GetColorKey(surface, NULL) == 0);
    2.45 -
    2.46 -        SDL_GetSurfaceBlendMode(surface, &blendMode);
    2.47 -        hasBlending = (blendMode == SDL_BLENDMODE_BLEND);
    2.48 -
    2.49 -        if (surface->format->Amask || (!hasColorkey && !hasBlending)) {
    2.50 -            Uint32 it;
    2.51 -            int pfmt;
    2.52 -
    2.53 -            /* Pixel formats, sorted by best first */
    2.54 -            static const Uint32 sdl_pformats[] = {
    2.55 -                SDL_PIXELFORMAT_ARGB8888,
    2.56 -                SDL_PIXELFORMAT_RGBA8888,
    2.57 -                SDL_PIXELFORMAT_ABGR8888,
    2.58 -                SDL_PIXELFORMAT_BGRA8888,
    2.59 -                SDL_PIXELFORMAT_RGB888,
    2.60 -                SDL_PIXELFORMAT_BGR888,
    2.61 -                SDL_PIXELFORMAT_RGB24,
    2.62 -                SDL_PIXELFORMAT_BGR24,
    2.63 -                SDL_PIXELFORMAT_RGB565,
    2.64 -                SDL_PIXELFORMAT_BGR565,
    2.65 -                SDL_PIXELFORMAT_ARGB1555,
    2.66 -                SDL_PIXELFORMAT_RGBA5551,
    2.67 -                SDL_PIXELFORMAT_ABGR1555,
    2.68 -                SDL_PIXELFORMAT_BGRA5551,
    2.69 -                SDL_PIXELFORMAT_RGB555,
    2.70 -                SDL_PIXELFORMAT_BGR555,
    2.71 -                SDL_PIXELFORMAT_ARGB4444,
    2.72 -                SDL_PIXELFORMAT_RGBA4444,
    2.73 -                SDL_PIXELFORMAT_ABGR4444,
    2.74 -                SDL_PIXELFORMAT_BGRA4444,
    2.75 -                SDL_PIXELFORMAT_RGB444,
    2.76 -                SDL_PIXELFORMAT_ARGB2101010,
    2.77 -                SDL_PIXELFORMAT_RGB332,
    2.78 -                SDL_PIXELFORMAT_UNKNOWN
    2.79 -            };
    2.80 -
    2.81 -            bpp = fmt->BitsPerPixel;
    2.82 -            Rmask = fmt->Rmask;
    2.83 -            Gmask = fmt->Gmask;
    2.84 -            Bmask = fmt->Bmask;
    2.85 -            Amask = fmt->Amask;
    2.86 -
    2.87 -            format =
    2.88 -                SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
    2.89 -            if (!format) {
    2.90 -                SDL_SetError("Unknown pixel format");
    2.91 -                return 0;
    2.92 -            }
    2.93 -
    2.94 -            /* Search requested format in the supported texture */
    2.95 -            /* formats by current renderer                      */
    2.96 -            for (it = 0; it < renderer->info.num_texture_formats; it++) {
    2.97 -                if (renderer->info.texture_formats[it] == format) {
    2.98 -                    break;
    2.99 -                }
   2.100 -            }
   2.101 -
   2.102 -            /* If requested format can't be found, search any best */
   2.103 -            /* format which renderer provides                      */
   2.104 -            if (it == renderer->info.num_texture_formats) {
   2.105 -                pfmt = 0;
   2.106 -                for (;;) {
   2.107 -                    if (sdl_pformats[pfmt] == SDL_PIXELFORMAT_UNKNOWN) {
   2.108 -                        break;
   2.109 -                    }
   2.110 -
   2.111 -                    for (it = 0; it < renderer->info.num_texture_formats;
   2.112 -                         it++) {
   2.113 -                        if (renderer->info.texture_formats[it] ==
   2.114 -                            sdl_pformats[pfmt]) {
   2.115 -                            break;
   2.116 -                        }
   2.117 -                    }
   2.118 -
   2.119 -                    if (it != renderer->info.num_texture_formats) {
   2.120 -                        /* The best format has been found */
   2.121 -                        break;
   2.122 -                    }
   2.123 -                    pfmt++;
   2.124 -                }
   2.125 -
   2.126 -                /* If any format can't be found, then return an error */
   2.127 -                if (it == renderer->info.num_texture_formats) {
   2.128 -                    SDL_SetError
   2.129 -                        ("Any of the supported pixel formats can't be found");
   2.130 -                    return 0;
   2.131 -                }
   2.132 -
   2.133 -                /* Convert found pixel format back to color masks */
   2.134 -                if (SDL_PixelFormatEnumToMasks
   2.135 -                    (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
   2.136 -                     &Bmask, &Amask) != SDL_TRUE) {
   2.137 -                    SDL_SetError("Unknown pixel format");
   2.138 -                    return 0;
   2.139 -                }
   2.140 -            }
   2.141 -        } else {
   2.142 -            /* Need a format with alpha */
   2.143 -            Uint32 it;
   2.144 -            int apfmt;
   2.145 -
   2.146 -            /* Pixel formats with alpha, sorted by best first */
   2.147 -            static const Uint32 sdl_alpha_pformats[] = {
   2.148 -                SDL_PIXELFORMAT_ARGB8888,
   2.149 -                SDL_PIXELFORMAT_RGBA8888,
   2.150 -                SDL_PIXELFORMAT_ABGR8888,
   2.151 -                SDL_PIXELFORMAT_BGRA8888,
   2.152 -                SDL_PIXELFORMAT_ARGB1555,
   2.153 -                SDL_PIXELFORMAT_RGBA5551,
   2.154 -                SDL_PIXELFORMAT_ABGR1555,
   2.155 -                SDL_PIXELFORMAT_BGRA5551,
   2.156 -                SDL_PIXELFORMAT_ARGB4444,
   2.157 -                SDL_PIXELFORMAT_RGBA4444,
   2.158 -                SDL_PIXELFORMAT_ABGR4444,
   2.159 -                SDL_PIXELFORMAT_BGRA4444,
   2.160 -                SDL_PIXELFORMAT_ARGB2101010,
   2.161 -                SDL_PIXELFORMAT_UNKNOWN
   2.162 -            };
   2.163 -
   2.164 -            if (surface->format->Amask) {
   2.165 -                /* If surface already has alpha, then try an original */
   2.166 -                /* surface format first                               */
   2.167 -                bpp = fmt->BitsPerPixel;
   2.168 -                Rmask = fmt->Rmask;
   2.169 -                Gmask = fmt->Gmask;
   2.170 -                Bmask = fmt->Bmask;
   2.171 -                Amask = fmt->Amask;
   2.172 -            } else {
   2.173 -                bpp = 32;
   2.174 -                Rmask = 0x00FF0000;
   2.175 -                Gmask = 0x0000FF00;
   2.176 -                Bmask = 0x000000FF;
   2.177 -                Amask = 0xFF000000;
   2.178 -            }
   2.179 -
   2.180 -            format =
   2.181 -                SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
   2.182 -            if (!format) {
   2.183 -                SDL_SetError("Unknown pixel format");
   2.184 -                return 0;
   2.185 -            }
   2.186 -
   2.187 -            /* Search this format in the supported texture formats */
   2.188 -            /* by current renderer                                 */
   2.189 -            for (it = 0; it < renderer->info.num_texture_formats; it++) {
   2.190 -                if (renderer->info.texture_formats[it] == format) {
   2.191 -                    break;
   2.192 -                }
   2.193 -            }
   2.194 -
   2.195 -            /* If this format can't be found, search any best       */
   2.196 -            /* compatible format with alpha which renderer provides */
   2.197 -            if (it == renderer->info.num_texture_formats) {
   2.198 -                apfmt = 0;
   2.199 -                for (;;) {
   2.200 -                    if (sdl_alpha_pformats[apfmt] == SDL_PIXELFORMAT_UNKNOWN) {
   2.201 -                        break;
   2.202 -                    }
   2.203 -
   2.204 -                    for (it = 0; it < renderer->info.num_texture_formats;
   2.205 -                         it++) {
   2.206 -                        if (renderer->info.texture_formats[it] ==
   2.207 -                            sdl_alpha_pformats[apfmt]) {
   2.208 -                            break;
   2.209 -                        }
   2.210 -                    }
   2.211 -
   2.212 -                    if (it != renderer->info.num_texture_formats) {
   2.213 -                        /* Compatible format has been found */
   2.214 -                        break;
   2.215 -                    }
   2.216 -                    apfmt++;
   2.217 -                }
   2.218 -
   2.219 -                /* If compatible format can't be found, then return an error */
   2.220 -                if (it == renderer->info.num_texture_formats) {
   2.221 -                    SDL_SetError("Compatible pixel format can't be found");
   2.222 -                    return 0;
   2.223 -                }
   2.224 -
   2.225 -                /* Convert found pixel format back to color masks */
   2.226 -                if (SDL_PixelFormatEnumToMasks
   2.227 -                    (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
   2.228 -                     &Bmask, &Amask) != SDL_TRUE) {
   2.229 -                    SDL_SetError("Unknown pixel format");
   2.230 -                    return 0;
   2.231 -                }
   2.232 -            }
   2.233 -        }
   2.234 -
   2.235 -        format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
   2.236 -        if (!format) {
   2.237 -            SDL_SetError("Unknown pixel format");
   2.238 -            return 0;
   2.239 +        needAlpha = SDL_FALSE;
   2.240 +    }
   2.241 +    format = renderer->info.texture_formats[0];
   2.242 +    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
   2.243 +        if (SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
   2.244 +            format = renderer->info.texture_formats[i];
   2.245 +            break;
   2.246          }
   2.247      }
   2.248  
   2.249 -    texture =
   2.250 -        SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
   2.251 -                          surface->w, surface->h);
   2.252 -    if (!texture && !requested_format) {
   2.253 -        SDL_DisplayMode desktop_mode;
   2.254 -        SDL_GetDesktopDisplayMode(&desktop_mode);
   2.255 -        format = desktop_mode.format;
   2.256 -        texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
   2.257 -                                    surface->w, surface->h);
   2.258 +    if (!SDL_PixelFormatEnumToMasks(format, &bpp,
   2.259 +                                    &Rmask, &Gmask, &Bmask, &Amask)) {
   2.260 +        SDL_SetError("Unknown pixel format");
   2.261 +        return NULL;
   2.262      }
   2.263 +
   2.264 +    texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
   2.265 +                                surface->w, surface->h);
   2.266      if (!texture) {
   2.267 -        return 0;
   2.268 +        return NULL;
   2.269      }
   2.270 +
   2.271      if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask
   2.272          && Bmask == fmt->Bmask && Amask == fmt->Amask) {
   2.273          if (SDL_MUSTLOCK(surface)) {
   2.274              SDL_LockSurface(surface);
   2.275 -            SDL_UpdateTexture(texture, NULL, surface->pixels,
   2.276 -                              surface->pitch);
   2.277 +            SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
   2.278              SDL_UnlockSurface(surface);
   2.279          } else {
   2.280 -            SDL_UpdateTexture(texture, NULL, surface->pixels,
   2.281 -                              surface->pitch);
   2.282 +            SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
   2.283          }
   2.284      } else {
   2.285          SDL_PixelFormat dst_fmt;
   2.286 -        SDL_Surface *dst = NULL;
   2.287 +        SDL_Surface *temp = NULL;
   2.288  
   2.289          /* Set up a destination surface for the texture update */
   2.290          SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask);
   2.291 -        dst = SDL_ConvertSurface(surface, &dst_fmt, 0);
   2.292 -        if (dst) {
   2.293 -            SDL_UpdateTexture(texture, NULL, dst->pixels, dst->pitch);
   2.294 -            SDL_FreeSurface(dst);
   2.295 -        }
   2.296 -        if (!dst) {
   2.297 +        temp = SDL_ConvertSurface(surface, &dst_fmt, 0);
   2.298 +        if (temp) {
   2.299 +            SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
   2.300 +            SDL_FreeSurface(temp);
   2.301 +        } else {
   2.302              SDL_DestroyTexture(texture);
   2.303 -            return 0;
   2.304 +            return NULL;
   2.305          }
   2.306      }
   2.307  
     3.1 --- a/test/testshape.c	Thu Feb 03 00:22:18 2011 -0800
     3.2 +++ b/test/testshape.c	Thu Feb 03 00:54:29 2011 -0800
     3.3 @@ -118,7 +118,7 @@
     3.4      for(i=0;i<num_pictures;i++)
     3.5          pictures[i].texture = NULL;
     3.6      for(i=0;i<num_pictures;i++) {
     3.7 -        pictures[i].texture = SDL_CreateTextureFromSurface(renderer,0,pictures[i].surface);
     3.8 +        pictures[i].texture = SDL_CreateTextureFromSurface(renderer,pictures[i].surface);
     3.9          if(pictures[i].texture == NULL) {
    3.10              j = 0;
    3.11              for(j=0;j<num_pictures;i++)
     4.1 --- a/test/testsprite2.c	Thu Feb 03 00:22:18 2011 -0800
     4.2 +++ b/test/testsprite2.c	Thu Feb 03 00:54:29 2011 -0800
     4.3 @@ -77,11 +77,7 @@
     4.4      /* Create textures from the image */
     4.5      for (i = 0; i < state->num_windows; ++i) {
     4.6          SDL_Renderer *renderer = state->renderers[i];
     4.7 -        sprites[i] = SDL_CreateTextureFromSurface(renderer, 0, temp);
     4.8 -        if (!sprites[i]) {
     4.9 -            SDL_SetColorKey(temp, 0, 0);
    4.10 -            sprites[i] = SDL_CreateTextureFromSurface(renderer, 0, temp);
    4.11 -        }
    4.12 +        sprites[i] = SDL_CreateTextureFromSurface(renderer, temp);
    4.13          if (!sprites[i]) {
    4.14              fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
    4.15              SDL_FreeSurface(temp);
     5.1 --- a/test/testspriteminimal.c	Thu Feb 03 00:22:18 2011 -0800
     5.2 +++ b/test/testspriteminimal.c	Thu Feb 03 00:54:29 2011 -0800
     5.3 @@ -60,11 +60,7 @@
     5.4      }
     5.5  
     5.6      /* Create textures from the image */
     5.7 -    sprite = SDL_CreateTextureFromSurface(renderer, 0, temp);
     5.8 -    if (!sprite) {
     5.9 -        SDL_SetColorKey(temp, 0, 0);
    5.10 -        sprite = SDL_CreateTextureFromSurface(renderer, 0, temp);
    5.11 -    }
    5.12 +    sprite = SDL_CreateTextureFromSurface(renderer, temp);
    5.13      if (!sprite) {
    5.14          fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
    5.15          SDL_FreeSurface(temp);