From a57c566988e1611f83dd16ff1081cfcf17d600c1 Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Wed, 7 Aug 2024 10:22:57 +0200
Subject: [PATCH] Add internal SDL_UpdateTextureFromSurface(), making
SDL_CreateTextureFromSurface() lighter
---
src/render/SDL_render.c | 158 ++++++++++++++++++++++++++--------------
1 file changed, 105 insertions(+), 53 deletions(-)
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 5886a286ec5c7..68682c274bf4e 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -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;
}