Commit fe2b0d97 authored by Sam Lantinga's avatar Sam Lantinga

Simplified and improved the process of creating a texture from a surface.

parent 31b3ad24
...@@ -172,19 +172,16 @@ extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer, ...@@ -172,19 +172,16 @@ extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,
/** /**
* \brief Create a texture from an existing surface. * \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. * \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 * \return The created texture is returned, or 0 on error.
* active, the format was unsupported, or the surface width or height
* were out of range.
* *
* \note The surface is not modified or freed by this function. * \note The surface is not modified or freed by this function.
* *
* \sa SDL_QueryTexture() * \sa SDL_QueryTexture()
* \sa SDL_DestroyTexture() * \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 * \brief Query the attributes of a texture
......
...@@ -250,13 +250,15 @@ SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int ...@@ -250,13 +250,15 @@ SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int
} }
SDL_Texture * SDL_Texture *
SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface * surface) SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
{ {
SDL_Texture *texture; const SDL_PixelFormat *fmt;
Uint32 requested_format = format; SDL_bool needAlpha;
SDL_PixelFormat *fmt; Uint32 i;
Uint32 format;
int bpp; int bpp;
Uint32 Rmask, Gmask, Bmask, Amask; Uint32 Rmask, Gmask, Bmask, Amask;
SDL_Texture *texture;
CHECK_RENDERER_MAGIC(renderer, NULL); CHECK_RENDERER_MAGIC(renderer, NULL);
...@@ -264,255 +266,56 @@ SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface ...@@ -264,255 +266,56 @@ SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface
SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface"); SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
return NULL; return NULL;
} }
fmt = surface->format;
if (format) {
if (!SDL_PixelFormatEnumToMasks
(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
SDL_SetError("Unknown pixel format");
return 0;
}
} else {
SDL_bool hasColorkey;
SDL_BlendMode blendMode;
SDL_bool hasBlending;
hasColorkey = (SDL_GetColorKey(surface, NULL) == 0); /* See what the best texture format is */
fmt = surface->format;
SDL_GetSurfaceBlendMode(surface, &blendMode); if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) {
hasBlending = (blendMode == SDL_BLENDMODE_BLEND); needAlpha = SDL_TRUE;
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 { } else {
bpp = 32; needAlpha = SDL_FALSE;
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;
} }
format = renderer->info.texture_formats[0];
/* Search this format in the supported texture formats */ for (i = 0; i < renderer->info.num_texture_formats; ++i) {
/* by current renderer */ if (SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
for (it = 0; it < renderer->info.num_texture_formats; it++) { format = renderer->info.texture_formats[i];
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; break;
} }
apfmt++;
} }
/* If compatible format can't be found, then return an error */ if (!SDL_PixelFormatEnumToMasks(format, &bpp,
if (it == renderer->info.num_texture_formats) { &Rmask, &Gmask, &Bmask, &Amask)) {
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"); SDL_SetError("Unknown pixel format");
return 0; return NULL;
}
} }
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, texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
surface->w, surface->h); surface->w, surface->h);
}
if (!texture) { if (!texture) {
return 0; return NULL;
} }
if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask
&& Bmask == fmt->Bmask && Amask == fmt->Amask) { && Bmask == fmt->Bmask && Amask == fmt->Amask) {
if (SDL_MUSTLOCK(surface)) { if (SDL_MUSTLOCK(surface)) {
SDL_LockSurface(surface); SDL_LockSurface(surface);
SDL_UpdateTexture(texture, NULL, surface->pixels, SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
surface->pitch);
SDL_UnlockSurface(surface); SDL_UnlockSurface(surface);
} else { } else {
SDL_UpdateTexture(texture, NULL, surface->pixels, SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
surface->pitch);
} }
} else { } else {
SDL_PixelFormat dst_fmt; SDL_PixelFormat dst_fmt;
SDL_Surface *dst = NULL; SDL_Surface *temp = NULL;
/* Set up a destination surface for the texture update */ /* Set up a destination surface for the texture update */
SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask); SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask);
dst = SDL_ConvertSurface(surface, &dst_fmt, 0); temp = SDL_ConvertSurface(surface, &dst_fmt, 0);
if (dst) { if (temp) {
SDL_UpdateTexture(texture, NULL, dst->pixels, dst->pitch); SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
SDL_FreeSurface(dst); SDL_FreeSurface(temp);
} } else {
if (!dst) {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
return 0; return NULL;
} }
} }
......
...@@ -118,7 +118,7 @@ int main(int argc,char** argv) ...@@ -118,7 +118,7 @@ int main(int argc,char** argv)
for(i=0;i<num_pictures;i++) for(i=0;i<num_pictures;i++)
pictures[i].texture = NULL; pictures[i].texture = NULL;
for(i=0;i<num_pictures;i++) { 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) { if(pictures[i].texture == NULL) {
j = 0; j = 0;
for(j=0;j<num_pictures;i++) for(j=0;j<num_pictures;i++)
......
...@@ -77,11 +77,7 @@ LoadSprite(char *file) ...@@ -77,11 +77,7 @@ LoadSprite(char *file)
/* Create textures from the image */ /* Create textures from the image */
for (i = 0; i < state->num_windows; ++i) { for (i = 0; i < state->num_windows; ++i) {
SDL_Renderer *renderer = state->renderers[i]; SDL_Renderer *renderer = state->renderers[i];
sprites[i] = SDL_CreateTextureFromSurface(renderer, 0, temp); sprites[i] = SDL_CreateTextureFromSurface(renderer, temp);
if (!sprites[i]) {
SDL_SetColorKey(temp, 0, 0);
sprites[i] = SDL_CreateTextureFromSurface(renderer, 0, temp);
}
if (!sprites[i]) { if (!sprites[i]) {
fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError()); fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
SDL_FreeSurface(temp); SDL_FreeSurface(temp);
......
...@@ -60,11 +60,7 @@ LoadSprite(char *file, SDL_Renderer *renderer) ...@@ -60,11 +60,7 @@ LoadSprite(char *file, SDL_Renderer *renderer)
} }
/* Create textures from the image */ /* Create textures from the image */
sprite = SDL_CreateTextureFromSurface(renderer, 0, temp); sprite = SDL_CreateTextureFromSurface(renderer, temp);
if (!sprite) {
SDL_SetColorKey(temp, 0, 0);
sprite = SDL_CreateTextureFromSurface(renderer, 0, temp);
}
if (!sprite) { if (!sprite) {
fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError()); fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
SDL_FreeSurface(temp); SDL_FreeSurface(temp);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment