Browse Source

Made texture size and format public in the API

Also added refcount to textures so they can be retained by application code.
Sam Lantinga 10 months ago
parent
commit
1f3a0d12e6

+ 16 - 0
include/SDL3/SDL_render.h

@@ -118,11 +118,27 @@ typedef enum SDL_RendererLogicalPresentation
  */
  */
 typedef struct SDL_Renderer SDL_Renderer;
 typedef struct SDL_Renderer SDL_Renderer;
 
 
+#ifndef SDL_INTERNAL
 /**
 /**
  * An efficient driver-specific representation of pixel data
  * An efficient driver-specific representation of pixel data
  *
  *
  * \since This struct is available since SDL 3.0.0.
  * \since This struct is available since SDL 3.0.0.
+ *
+ * \sa SDL_CreateTexture
+ * \sa SDL_CreateTextureFromSurface
+ * \sa SDL_CreateTextureWithProperties
+ * \sa SDL_DestroyTexture
  */
  */
+struct SDL_Texture
+{
+    SDL_PixelFormat format;     /**< The format of the texture, read-only */
+    int w;                      /**< The width of the texture, read-only. */
+    int h;                      /**< The height of the texture, read-only. */
+
+    int refcount;               /**< Application reference count, used when freeing texture */
+};
+#endif /* !SDL_INTERNAL */
+
 typedef struct SDL_Texture SDL_Texture;
 typedef struct SDL_Texture SDL_Texture;
 
 
 /* Function prototypes */
 /* Function prototypes */

+ 3 - 0
src/SDL_internal.h

@@ -222,6 +222,9 @@
 #define SDL_EndThreadFunction NULL
 #define SDL_EndThreadFunction NULL
 #endif
 #endif
 
 
+/* Enable internal definitions in SDL API headers */
+#define SDL_INTERNAL
+
 #include <SDL3/SDL.h>
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_intrin.h>
 #include <SDL3/SDL_intrin.h>
 
 

+ 8 - 4
src/render/SDL_render.c

@@ -1362,6 +1362,7 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert
     if (!texture) {
     if (!texture) {
         return NULL;
         return NULL;
     }
     }
+    texture->refcount = 1;
     SDL_SetObjectValid(texture, SDL_OBJECT_TYPE_TEXTURE, true);
     SDL_SetObjectValid(texture, SDL_OBJECT_TYPE_TEXTURE, true);
     texture->colorspace = (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, default_colorspace);
     texture->colorspace = (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, default_colorspace);
     texture->format = format;
     texture->format = format;
@@ -4990,12 +4991,10 @@ bool SDL_RenderPresent(SDL_Renderer *renderer)
     return true;
     return true;
 }
 }
 
 
-static bool SDL_DestroyTextureInternal(SDL_Texture *texture, bool is_destroying)
+static void SDL_DestroyTextureInternal(SDL_Texture *texture, bool is_destroying)
 {
 {
     SDL_Renderer *renderer;
     SDL_Renderer *renderer;
 
 
-    CHECK_TEXTURE_MAGIC(texture, false);
-
     SDL_DestroyProperties(texture->props);
     SDL_DestroyProperties(texture->props);
 
 
     renderer = texture->renderer;
     renderer = texture->renderer;
@@ -5036,11 +5035,16 @@ static bool SDL_DestroyTextureInternal(SDL_Texture *texture, bool is_destroying)
     texture->locked_surface = NULL;
     texture->locked_surface = NULL;
 
 
     SDL_free(texture);
     SDL_free(texture);
-    return true;
 }
 }
 
 
 void SDL_DestroyTexture(SDL_Texture *texture)
 void SDL_DestroyTexture(SDL_Texture *texture)
 {
 {
+    CHECK_TEXTURE_MAGIC(texture, );
+
+    if (--texture->refcount > 0) {
+        return;
+    }
+
     SDL_DestroyTextureInternal(texture, false /* is_destroying */);
     SDL_DestroyTextureInternal(texture, false /* is_destroying */);
 }
 }
 
 

+ 18 - 13
src/render/SDL_sysrender.h

@@ -71,17 +71,22 @@ typedef struct SDL_RenderViewState
 // Define the SDL texture structure
 // Define the SDL texture structure
 struct SDL_Texture
 struct SDL_Texture
 {
 {
-    SDL_Colorspace colorspace;  /**< The colorspace of the texture */
-    float SDR_white_point;      /**< The SDR white point for this content */
-    float HDR_headroom;         /**< The HDR headroom needed by this content */
-    SDL_PixelFormat format;     /**< The pixel format of the texture */
-    SDL_TextureAccess access;   /**< The texture access mode */
-    int w;                      /**< The width of the texture */
-    int h;                      /**< The height of the texture */
-    SDL_BlendMode blendMode;    /**< The texture blend mode */
-    SDL_ScaleMode scaleMode;    /**< The texture scale mode */
-    SDL_FColor color;           /**< Texture modulation values */
-    SDL_RenderViewState view;   /**< Target texture view state */
+    // Public API definition
+    SDL_PixelFormat format;     /**< The format of the texture, read-only */
+    int w;                      /**< The width of the texture, read-only. */
+    int h;                      /**< The height of the texture, read-only. */
+
+    int refcount;               /**< Application reference count, used when freeing texture */
+
+    // Private API definition
+    SDL_Colorspace colorspace;  // The colorspace of the texture
+    float SDR_white_point;      // The SDR white point for this content
+    float HDR_headroom;         // The HDR headroom needed by this content
+    SDL_TextureAccess access;   // The texture access mode
+    SDL_BlendMode blendMode;    // The texture blend mode
+    SDL_ScaleMode scaleMode;    // The texture scale mode
+    SDL_FColor color;           // Texture modulation values
+    SDL_RenderViewState view;   // Target texture view state
 
 
     SDL_Renderer *renderer;
     SDL_Renderer *renderer;
 
 
@@ -91,13 +96,13 @@ struct SDL_Texture
     void *pixels;
     void *pixels;
     int pitch;
     int pitch;
     SDL_Rect locked_rect;
     SDL_Rect locked_rect;
-    SDL_Surface *locked_surface; /**< Locked region exposed as a SDL surface */
+    SDL_Surface *locked_surface; // Locked region exposed as a SDL surface
 
 
     Uint32 last_command_generation; // last command queue generation this texture was in.
     Uint32 last_command_generation; // last command queue generation this texture was in.
 
 
     SDL_PropertiesID props;
     SDL_PropertiesID props;
 
 
-    void *internal; /**< Driver specific texture representation */
+    void *internal;             // Driver specific texture representation
 
 
     SDL_Texture *prev;
     SDL_Texture *prev;
     SDL_Texture *next;
     SDL_Texture *next;

+ 15 - 21
test/testautomation_render.c

@@ -239,8 +239,7 @@ static int SDLCALL render_testBlit(void *arg)
     SDL_FRect rect;
     SDL_FRect rect;
     SDL_Texture *tface;
     SDL_Texture *tface;
     SDL_Surface *referenceSurface = NULL;
     SDL_Surface *referenceSurface = NULL;
-    float tw, th;
-    float i, j, ni, nj;
+    int i, j, ni, nj;
     int checkFailCount1;
     int checkFailCount1;
 
 
     /* Clear surface. */
     /* Clear surface. */
@@ -257,19 +256,18 @@ static int SDLCALL render_testBlit(void *arg)
     }
     }
 
 
     /* Constant values. */
     /* Constant values. */
-    CHECK_FUNC(SDL_GetTextureSize, (tface, &tw, &th))
-    rect.w = tw;
-    rect.h = th;
-    ni = TESTRENDER_SCREEN_W - tw;
-    nj = TESTRENDER_SCREEN_H - th;
+    rect.w = (float)tface->w;
+    rect.h = (float)tface->h;
+    ni = TESTRENDER_SCREEN_W - tface->w;
+    nj = TESTRENDER_SCREEN_H - tface->h;
 
 
     /* Loop blit. */
     /* Loop blit. */
     checkFailCount1 = 0;
     checkFailCount1 = 0;
     for (j = 0; j <= nj; j += 4) {
     for (j = 0; j <= nj; j += 4) {
         for (i = 0; i <= ni; i += 4) {
         for (i = 0; i <= ni; i += 4) {
             /* Blitting. */
             /* Blitting. */
-            rect.x = i;
-            rect.y = j;
+            rect.x = (float)i;
+            rect.y = (float)j;
             ret = SDL_RenderTexture(renderer, tface, NULL, &rect);
             ret = SDL_RenderTexture(renderer, tface, NULL, &rect);
             if (!ret) {
             if (!ret) {
                 checkFailCount1++;
                 checkFailCount1++;
@@ -631,7 +629,6 @@ static int SDLCALL render_testBlitColor(void *arg)
     SDL_FRect rect;
     SDL_FRect rect;
     SDL_Texture *tface;
     SDL_Texture *tface;
     SDL_Surface *referenceSurface = NULL;
     SDL_Surface *referenceSurface = NULL;
-    float tw, th;
     int i, j, ni, nj;
     int i, j, ni, nj;
     int checkFailCount1;
     int checkFailCount1;
     int checkFailCount2;
     int checkFailCount2;
@@ -647,11 +644,10 @@ static int SDLCALL render_testBlitColor(void *arg)
     }
     }
 
 
     /* Constant values. */
     /* Constant values. */
-    CHECK_FUNC(SDL_GetTextureSize, (tface, &tw, &th))
-    rect.w = tw;
-    rect.h = th;
-    ni = TESTRENDER_SCREEN_W - (int)tw;
-    nj = TESTRENDER_SCREEN_H - (int)th;
+    rect.w = (float)tface->w;
+    rect.h = (float)tface->h;
+    ni = TESTRENDER_SCREEN_W - tface->w;
+    nj = TESTRENDER_SCREEN_H - tface->h;
 
 
     /* Test blitting with color mod. */
     /* Test blitting with color mod. */
     checkFailCount1 = 0;
     checkFailCount1 = 0;
@@ -1423,7 +1419,6 @@ static int SDLCALL render_testUVWrapping(void *arg)
     SDL_Vertex vertices[6];
     SDL_Vertex vertices[6];
     SDL_Vertex *verts = vertices;
     SDL_Vertex *verts = vertices;
     SDL_FColor color = { 1.0f, 1.0f, 1.0f, 1.0f };
     SDL_FColor color = { 1.0f, 1.0f, 1.0f, 1.0f };
-    float tw, th;
     SDL_FRect rect;
     SDL_FRect rect;
     float min_U = -0.5f;
     float min_U = -0.5f;
     float max_U = 1.5f;
     float max_U = 1.5f;
@@ -1442,11 +1437,10 @@ static int SDLCALL render_testUVWrapping(void *arg)
         return TEST_ABORTED;
         return TEST_ABORTED;
     }
     }
 
 
-    CHECK_FUNC(SDL_GetTextureSize, (tface, &tw, &th))
-    rect.w = tw * 2;
-    rect.h = th * 2;
-    rect.x = (TESTRENDER_SCREEN_W - rect.w) / 2;
-    rect.y = (TESTRENDER_SCREEN_H - rect.h) / 2;
+    rect.w = (float)tface->w * 2;
+    rect.h = (float)tface->h * 2;
+    rect.x = (float)(TESTRENDER_SCREEN_W - rect.w) / 2;
+    rect.y = (float)(TESTRENDER_SCREEN_H - rect.h) / 2;
 
 
     /*
     /*
      *   0--1
      *   0--1

+ 5 - 8
test/testcamera.c

@@ -278,7 +278,6 @@ SDL_AppResult SDL_AppIterate(void *appstate)
     SDL_RenderClear(renderer);
     SDL_RenderClear(renderer);
 
 
     int win_w, win_h;
     int win_w, win_h;
-    float tw, th;
     SDL_FRect d;
     SDL_FRect d;
     Uint64 timestampNS = 0;
     Uint64 timestampNS = 0;
     SDL_Surface *frame_next = camera ? SDL_AcquireCameraFrame(camera, &timestampNS) : NULL;
     SDL_Surface *frame_next = camera ? SDL_AcquireCameraFrame(camera, &timestampNS) : NULL;
@@ -305,8 +304,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
 
 
     if (frame_current) {
     if (frame_current) {
         if (!texture ||
         if (!texture ||
-            !SDL_GetTextureSize(texture, &tw, &th) ||
-            (int)tw != frame_current->w || (int)th != frame_current->h) {
+            texture->w != frame_current->w || texture->h != frame_current->h) {
             /* Resize the window to match */
             /* Resize the window to match */
             SDL_SetWindowSize(window, frame_current->w, frame_current->h);
             SDL_SetWindowSize(window, frame_current->w, frame_current->h);
 
 
@@ -337,12 +335,11 @@ SDL_AppResult SDL_AppIterate(void *appstate)
             texture_updated = true;
             texture_updated = true;
         }
         }
 
 
-        SDL_GetTextureSize(texture, &tw, &th);
         SDL_GetRenderOutputSize(renderer, &win_w, &win_h);
         SDL_GetRenderOutputSize(renderer, &win_w, &win_h);
-        d.x = ((win_w - tw) / 2);
-        d.y = ((win_h - th) / 2);
-        d.w = tw;
-        d.h = th;
+        d.x = ((win_w - texture->w) / 2.0f);
+        d.y = ((win_h - texture->h) / 2.0f);
+        d.w = (float)texture->w;
+        d.h = (float)texture->h;
         SDL_RenderTexture(renderer, texture, NULL, &d);
         SDL_RenderTexture(renderer, texture, NULL, &d);
     }
     }
 
 

+ 6 - 10
test/testnative.c

@@ -63,14 +63,12 @@ quit(int rc)
 
 
 static void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite)
 static void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite)
 {
 {
-    float sprite_w, sprite_h;
     int i;
     int i;
     SDL_Rect viewport;
     SDL_Rect viewport;
     SDL_FRect *position, *velocity;
     SDL_FRect *position, *velocity;
 
 
     /* Query the sizes */
     /* Query the sizes */
     SDL_GetRenderViewport(renderer, &viewport);
     SDL_GetRenderViewport(renderer, &viewport);
-    SDL_GetTextureSize(sprite, &sprite_w, &sprite_h);
 
 
     /* Draw a gray background */
     /* Draw a gray background */
     SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
     SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
@@ -81,12 +79,12 @@ static void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite)
         position = &positions[i];
         position = &positions[i];
         velocity = &velocities[i];
         velocity = &velocities[i];
         position->x += velocity->x;
         position->x += velocity->x;
-        if ((position->x < 0) || (position->x >= (viewport.w - sprite_w))) {
+        if ((position->x < 0) || (position->x >= (viewport.w - sprite->w))) {
             velocity->x = -velocity->x;
             velocity->x = -velocity->x;
             position->x += velocity->x;
             position->x += velocity->x;
         }
         }
         position->y += velocity->y;
         position->y += velocity->y;
-        if ((position->y < 0) || (position->y >= (viewport.h - sprite_h))) {
+        if ((position->y < 0) || (position->y >= (viewport.h - sprite->h))) {
             velocity->y = -velocity->y;
             velocity->y = -velocity->y;
             position->y += velocity->y;
             position->y += velocity->y;
         }
         }
@@ -108,7 +106,6 @@ int main(int argc, char *argv[])
     SDL_Renderer *renderer;
     SDL_Renderer *renderer;
     SDL_Texture *sprite;
     SDL_Texture *sprite;
     int window_w, window_h;
     int window_w, window_h;
-    float sprite_w, sprite_h;
     SDL_Event event;
     SDL_Event event;
 
 
     /* Initialize test framework */
     /* Initialize test framework */
@@ -178,7 +175,6 @@ int main(int argc, char *argv[])
 
 
     /* Allocate memory for the sprite info */
     /* Allocate memory for the sprite info */
     SDL_GetWindowSize(window, &window_w, &window_h);
     SDL_GetWindowSize(window, &window_w, &window_h);
-    SDL_GetTextureSize(sprite, &sprite_w, &sprite_h);
     positions = (SDL_FRect *)SDL_malloc(NUM_SPRITES * sizeof(*positions));
     positions = (SDL_FRect *)SDL_malloc(NUM_SPRITES * sizeof(*positions));
     velocities = (SDL_FRect *)SDL_malloc(NUM_SPRITES * sizeof(*velocities));
     velocities = (SDL_FRect *)SDL_malloc(NUM_SPRITES * sizeof(*velocities));
     if (!positions || !velocities) {
     if (!positions || !velocities) {
@@ -186,10 +182,10 @@ int main(int argc, char *argv[])
         quit(2);
         quit(2);
     }
     }
     for (i = 0; i < NUM_SPRITES; ++i) {
     for (i = 0; i < NUM_SPRITES; ++i) {
-        positions[i].x = (float)(SDL_rand(window_w - (int)sprite_w));
-        positions[i].y = (float)(SDL_rand(window_h - (int)sprite_h));
-        positions[i].w = sprite_w;
-        positions[i].h = sprite_h;
+        positions[i].x = (float)SDL_rand(window_w - sprite->w);
+        positions[i].y = (float)SDL_rand(window_h - sprite->h);
+        positions[i].w = (float)sprite->w;
+        positions[i].h = (float)sprite->h;
         velocities[i].x = 0.0f;
         velocities[i].x = 0.0f;
         velocities[i].y = 0.0f;
         velocities[i].y = 0.0f;
         while (velocities[i].x == 0.f && velocities[i].y == 0.f) {
         while (velocities[i].x == 0.f && velocities[i].y == 0.f) {

+ 5 - 10
test/testviewport.c

@@ -48,7 +48,6 @@ static void DrawOnViewport(SDL_Renderer *renderer)
 {
 {
     SDL_FRect rect;
     SDL_FRect rect;
     SDL_Rect cliprect;
     SDL_Rect cliprect;
-    float w, h;
 
 
     /* Set the viewport */
     /* Set the viewport */
     SDL_SetRenderViewport(renderer, &viewport);
     SDL_SetRenderViewport(renderer, &viewport);
@@ -91,15 +90,11 @@ static void DrawOnViewport(SDL_Renderer *renderer)
     SDL_RenderFillRect(renderer, &rect);
     SDL_RenderFillRect(renderer, &rect);
 
 
     /* Add a clip rect and fill it with the sprite */
     /* Add a clip rect and fill it with the sprite */
-    SDL_GetTextureSize(sprite, &w, &h);
-    rect.x = (viewport.w - w) / 2;
-    rect.y = (viewport.h - h) / 2;
-    rect.w = w;
-    rect.h = h;
-    cliprect.x = (int)rect.x;
-    cliprect.y = (int)rect.y;
-    cliprect.w = (int)rect.w;
-    cliprect.h = (int)rect.h;
+    cliprect.x = (viewport.w - sprite->w) / 2;
+    cliprect.y = (viewport.h - sprite->h) / 2;
+    cliprect.w = sprite->w;
+    cliprect.h = sprite->h;
+    SDL_RectToFRect(&cliprect, &rect);
     SDL_SetRenderClipRect(renderer, &cliprect);
     SDL_SetRenderClipRect(renderer, &cliprect);
     SDL_RenderTexture(renderer, sprite, NULL, &rect);
     SDL_RenderTexture(renderer, sprite, NULL, &rect);
     SDL_SetRenderClipRect(renderer, NULL);
     SDL_SetRenderClipRect(renderer, NULL);