Add internal SDL_UpdateTextureFromSurface(), making SDL_CreateTextureFromSurface() lighter

This commit is contained in:
Sylvain 2024-08-07 10:22:57 +02:00 committed by Sylvain Becker
parent 20a6193eaa
commit a57c566988
1 changed files with 105 additions and 53 deletions

View File

@ -1495,10 +1495,111 @@ SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, SDL_PixelFormat format, S
return texture;
}
static int SDL_UpdateTextureFromSurface(SDL_Texture *texture, SDL_Rect *rect, SDL_Surface *surface)
{
int access;
SDL_bool direct_update;
SDL_PixelFormat tex_format;
SDL_PropertiesID surface_props;
SDL_PropertiesID tex_props;
SDL_Colorspace surface_colorspace = SDL_COLORSPACE_UNKNOWN;
SDL_Colorspace texture_colorspace = SDL_COLORSPACE_UNKNOWN;
if (texture == NULL || surface == NULL) {
return -1;
}
tex_props = SDL_GetTextureProperties(texture);
if (!tex_props) {
return -1;
}
surface_props = SDL_GetSurfaceProperties(surface);
if (!surface_props) {
return -1;
}
tex_format = SDL_GetNumberProperty(tex_props, SDL_PROP_TEXTURE_FORMAT_NUMBER, 0);
access = SDL_GetNumberProperty(tex_props, SDL_PROP_TEXTURE_ACCESS_NUMBER, 0);
if (access != SDL_TEXTUREACCESS_STATIC && access != SDL_TEXTUREACCESS_STREAMING) {
return -1;
}
surface_colorspace = SDL_GetSurfaceColorspace(surface);
texture_colorspace = surface_colorspace;
if (surface_colorspace == SDL_COLORSPACE_SRGB_LINEAR ||
SDL_COLORSPACETRANSFER(surface_colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) {
if (SDL_ISPIXELFORMAT_FLOAT(tex_format)) {
texture_colorspace = SDL_COLORSPACE_SRGB_LINEAR;
} else if (SDL_ISPIXELFORMAT_10BIT(tex_format)) {
texture_colorspace = SDL_COLORSPACE_HDR10;
} else {
texture_colorspace = SDL_COLORSPACE_SRGB;
}
}
if (tex_format == surface->format && texture_colorspace == surface_colorspace) {
if (SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) {
/* Surface and Renderer formats are identical.
* Intermediate conversion is needed to convert color key to alpha (SDL_ConvertColorkeyToAlpha()). */
direct_update = SDL_FALSE;
} else {
/* Update Texture directly */
direct_update = SDL_TRUE;
}
} else {
/* Surface and Renderer formats are different, it needs an intermediate conversion. */
direct_update = SDL_FALSE;
}
if (direct_update) {
if (SDL_MUSTLOCK(surface)) {
SDL_LockSurface(surface);
SDL_UpdateTexture(texture, rect, surface->pixels, surface->pitch);
SDL_UnlockSurface(surface);
} else {
SDL_UpdateTexture(texture, rect, surface->pixels, surface->pitch);
}
} else {
SDL_Surface *temp = NULL;
/* Set up a destination surface for the texture update */
temp = SDL_ConvertSurfaceAndColorspace(surface, tex_format, NULL, texture_colorspace, surface_props);
if (temp) {
SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
SDL_DestroySurface(temp);
} else {
return -1;
}
}
{
Uint8 r, g, b, a;
SDL_BlendMode blendMode;
SDL_GetSurfaceColorMod(surface, &r, &g, &b);
SDL_SetTextureColorMod(texture, r, g, b);
SDL_GetSurfaceAlphaMod(surface, &a);
SDL_SetTextureAlphaMod(texture, a);
if (SDL_SurfaceHasColorKey(surface)) {
/* We converted to a texture with alpha format */
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
} else {
SDL_GetSurfaceBlendMode(surface, &blendMode);
SDL_SetTextureBlendMode(texture, blendMode);
}
}
return 0;
}
SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface)
{
SDL_bool needAlpha;
SDL_bool direct_update;
int i;
SDL_PixelFormat format = SDL_PIXELFORMAT_UNKNOWN;
SDL_Palette *palette;
@ -1605,20 +1706,6 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
}
}
if (format == surface->format && texture_colorspace == surface_colorspace) {
if (SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) {
/* Surface and Renderer formats are identical.
* Intermediate conversion is needed to convert color key to alpha (SDL_ConvertColorkeyToAlpha()). */
direct_update = SDL_FALSE;
} else {
/* Update Texture directly */
direct_update = SDL_TRUE;
}
} else {
/* Surface and Renderer formats are different, it needs an intermediate conversion. */
direct_update = SDL_FALSE;
}
props = SDL_CreateProperties();
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, texture_colorspace);
if (surface_colorspace == texture_colorspace) {
@ -1637,46 +1724,11 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
return NULL;
}
if (direct_update) {
if (SDL_MUSTLOCK(surface)) {
SDL_LockSurface(surface);
SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
SDL_UnlockSurface(surface);
} else {
SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
}
} else {
SDL_Surface *temp = NULL;
/* Set up a destination surface for the texture update */
temp = SDL_ConvertSurfaceAndColorspace(surface, format, NULL, texture_colorspace, surface->internal->props);
if (temp) {
SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
SDL_DestroySurface(temp);
} else {
SDL_DestroyTexture(texture);
return NULL;
}
if (SDL_UpdateTextureFromSurface(texture, NULL, surface) < 0) {
SDL_DestroyTexture(texture);
return NULL;
}
{
Uint8 r, g, b, a;
SDL_BlendMode blendMode;
SDL_GetSurfaceColorMod(surface, &r, &g, &b);
SDL_SetTextureColorMod(texture, r, g, b);
SDL_GetSurfaceAlphaMod(surface, &a);
SDL_SetTextureAlphaMod(texture, a);
if (SDL_SurfaceHasColorKey(surface)) {
/* We converted to a texture with alpha format */
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
} else {
SDL_GetSurfaceBlendMode(surface, &blendMode);
SDL_SetTextureBlendMode(texture, blendMode);
}
}
return texture;
}