Skip to content

Added SDL_SetRenderTextureAddressMode() and SDL_GetRenderTextureAddressMode() #10328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions include/SDL3/SDL_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ typedef enum SDL_TextureAccess
SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */
} SDL_TextureAccess;

/**
* The addressing mode for a texture when used in SDL_RenderGeometry().
*
* This affects how texture coordinates are interpreted outside of [0, 1]
*
* \since This enum is available since SDL 3.4.0.
*/
typedef enum SDL_TextureAddressMode
{
SDL_TEXTURE_ADDRESS_INVALID = -1,
SDL_TEXTURE_ADDRESS_AUTO, /**< Wrapping is enabled if texture coordinates are outside [0, 1], this is the default */
SDL_TEXTURE_ADDRESS_CLAMP, /**< Texture coordinates are clamped to the [0, 1] range */
SDL_TEXTURE_ADDRESS_WRAP, /**< The texture is repeated (tiled) */
} SDL_TextureAddressMode;

/**
* How the logical size is mapped to the output.
*
Expand Down Expand Up @@ -2294,6 +2309,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9GridTiled(SDL_Renderer *rende
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_RenderGeometryRaw
* \sa SDL_SetRenderTextureAddressMode
*/
extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
SDL_Texture *texture,
Expand Down Expand Up @@ -2326,6 +2342,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
* \since This function is available since SDL 3.2.0.
*
* \sa SDL_RenderGeometry
* \sa SDL_SetRenderTextureAddressMode
*/
extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
SDL_Texture *texture,
Expand All @@ -2335,6 +2352,38 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
int num_vertices,
const void *indices, int num_indices, int size_indices);

/**
* Set the texture addressing mode used in SDL_RenderGeometry().
*
* \param renderer the rendering context.
* \param u_mode the SDL_TextureAddressMode to use for horizontal texture coordinates in SDL_RenderGeometry().
* \param v_mode the SDL_TextureAddressMode to use for vertical texture coordinates in SDL_RenderGeometry().
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_RenderGeometry
* \sa SDL_RenderGeometryRaw
* \sa SDL_GetRenderTextureAddressMode
*/
extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode u_mode, SDL_TextureAddressMode v_mode);

/**
* Get the texture addressing mode used in SDL_RenderGeometry().
*
* \param renderer the rendering context.
* \param u_mode a pointer filled in with the SDL_TextureAddressMode to use for horizontal texture coordinates in SDL_RenderGeometry(), may be NULL.
* \param v_mode a pointer filled in with the SDL_TextureAddressMode to use for vertical texture coordinates in SDL_RenderGeometry(), may be NULL.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_SetRenderTextureAddressMode
*/
extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode *u_mode, SDL_TextureAddressMode *v_mode);

/**
* Read pixels from the current rendering target.
*
Expand Down
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi.sym
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,8 @@ SDL3_0.0.0 {
SDL_SetWindowProgressValue;
SDL_GetWindowProgressState;
SDL_GetWindowProgressValue;
SDL_SetRenderTextureAddressMode;
SDL_GetRenderTextureAddressMode;
# extra symbols go here (don't modify this line)
local: *;
};
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -1271,3 +1271,5 @@
#define SDL_SetWindowProgressValue SDL_SetWindowProgressValue_REAL
#define SDL_GetWindowProgressState SDL_GetWindowProgressState_REAL
#define SDL_GetWindowProgressValue SDL_GetWindowProgressValue_REAL
#define SDL_SetRenderTextureAddressMode SDL_SetRenderTextureAddressMode_REAL
#define SDL_GetRenderTextureAddressMode SDL_GetRenderTextureAddressMode_REAL
2 changes: 2 additions & 0 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1279,3 +1279,5 @@ SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressState,(SDL_Window *a,SDL_ProgressState
SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressValue,(SDL_Window *a,float b),(a,b),return)
SDL_DYNAPI_PROC(SDL_ProgressState,SDL_GetWindowProgressState,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(float,SDL_GetWindowProgressValue,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_SetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode b,SDL_TextureAddressMode c),(a,b,c),return)
SDL_DYNAPI_PROC(bool,SDL_GetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode *b,SDL_TextureAddressMode *c),(a,b,c),return)
94 changes: 75 additions & 19 deletions src/render/SDL_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,8 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
if (texture) {
cmd->data.draw.texture_scale_mode = texture->scaleMode;
}
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
cmd->data.draw.texture_address_mode_u = SDL_TEXTURE_ADDRESS_CLAMP;
cmd->data.draw.texture_address_mode_v = SDL_TEXTURE_ADDRESS_CLAMP;
cmd->data.draw.gpu_render_state = renderer->gpu_render_state;
if (renderer->gpu_render_state) {
renderer->gpu_render_state->last_command_generation = renderer->render_command_generation;
Expand Down Expand Up @@ -727,13 +728,15 @@ static bool QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture,
const float *uv, int uv_stride,
int num_vertices,
const void *indices, int num_indices, int size_indices,
float scale_x, float scale_y, SDL_TextureAddressMode texture_address_mode)
float scale_x, float scale_y,
SDL_TextureAddressMode texture_address_mode_u, SDL_TextureAddressMode texture_address_mode_v)
{
SDL_RenderCommand *cmd;
bool result = false;
cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture);
if (cmd) {
cmd->data.draw.texture_address_mode = texture_address_mode;
cmd->data.draw.texture_address_mode_u = texture_address_mode_u;
cmd->data.draw.texture_address_mode_v = texture_address_mode_v;
result = renderer->QueueGeometry(renderer, cmd, texture,
xy, xy_stride,
color, color_stride, uv, uv_stride,
Expand Down Expand Up @@ -3739,7 +3742,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
result = QueueCmdGeometry(renderer, NULL,
xy, xy_stride, &renderer->color, 0 /* color_stride */, NULL, 0,
num_vertices, indices, num_indices, size_indices,
1.0f, 1.0f, SDL_TEXTURE_ADDRESS_CLAMP);
1.0f, 1.0f, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
}

SDL_small_free(xy, isstack1);
Expand Down Expand Up @@ -3920,7 +3923,7 @@ static bool SDL_RenderTextureInternal(SDL_Renderer *renderer, SDL_Texture *textu
result = QueueCmdGeometry(renderer, texture,
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
num_vertices, indices, num_indices, size_indices,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP);
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
} else {
const SDL_FRect rect = { dstrect->x * scale_x, dstrect->y * scale_y, dstrect->w * scale_x, dstrect->h * scale_y };
result = QueueCmdCopy(renderer, texture, srcrect, &rect);
Expand Down Expand Up @@ -4083,7 +4086,7 @@ bool SDL_RenderTextureAffine(SDL_Renderer *renderer, SDL_Texture *texture,
&texture->color, 0 /* color_stride */,
uv, uv_stride,
num_vertices, indices, num_indices, size_indices,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP
);
}
return result;
Expand Down Expand Up @@ -4233,7 +4236,7 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture,
result = QueueCmdGeometry(renderer, texture,
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
num_vertices, indices, num_indices, size_indices,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP);
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
} else {
result = QueueCmdCopyEx(renderer, texture, &real_srcrect, dstrect, angle, &real_center, flip, scale_x, scale_y);
}
Expand Down Expand Up @@ -4285,7 +4288,8 @@ static bool SDL_RenderTextureTiled_Wrap(SDL_Renderer *renderer, SDL_Texture *tex
return QueueCmdGeometry(renderer, texture,
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
num_vertices, indices, num_indices, size_indices,
view->current_scale.x, view->current_scale.y, SDL_TEXTURE_ADDRESS_WRAP);
view->current_scale.x, view->current_scale.y,
SDL_TEXTURE_ADDRESS_WRAP, SDL_TEXTURE_ADDRESS_WRAP);
}

static bool SDL_RenderTextureTiled_Iterate(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float scale, const SDL_FRect *dstrect)
Expand Down Expand Up @@ -5032,7 +5036,7 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
result = QueueCmdGeometry(renderer, texture,
xy, xy_stride, color, color_stride, uv, uv_stride,
num_vertices, prev, 3, 4,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP);
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
if (!result) {
goto end;
}
Expand All @@ -5052,7 +5056,7 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
result = QueueCmdGeometry(renderer, texture,
xy, xy_stride, color, color_stride, uv, uv_stride,
num_vertices, prev, 3, 4,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP);
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
if (!result) {
goto end;
}
Expand All @@ -5077,7 +5081,8 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
{
int i;
int count = indices ? num_indices : num_vertices;
SDL_TextureAddressMode texture_address_mode;
SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;

CHECK_RENDERER_MAGIC(renderer, false);

Expand Down Expand Up @@ -5132,18 +5137,38 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
texture = texture->native;
}

texture_address_mode = renderer->texture_address_mode;
if (texture_address_mode == SDL_TEXTURE_ADDRESS_AUTO && texture) {
texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
texture_address_mode_u = renderer->texture_address_mode_u;
texture_address_mode_v = renderer->texture_address_mode_v;
if (texture &&
(texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO ||
texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO)) {
for (i = 0; i < num_vertices; ++i) {
const float *uv_ = (const float *)((const char *)uv + i * uv_stride);
float u = uv_[0];
float v = uv_[1];
if (u < 0.0f || v < 0.0f || u > 1.0f || v > 1.0f) {
texture_address_mode = SDL_TEXTURE_ADDRESS_WRAP;
break;
if (u < 0.0f || u > 1.0f) {
if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO) {
texture_address_mode_u = SDL_TEXTURE_ADDRESS_WRAP;
if (texture_address_mode_v != SDL_TEXTURE_ADDRESS_AUTO) {
break;
}
}
}
if (v < 0.0f || v > 1.0f) {
if (texture_address_mode_v == SDL_TEXTURE_ADDRESS_AUTO) {
texture_address_mode_v = SDL_TEXTURE_ADDRESS_WRAP;
if (texture_address_mode_u != SDL_TEXTURE_ADDRESS_AUTO) {
break;
}
}
}
}
if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO) {
texture_address_mode_u = SDL_TEXTURE_ADDRESS_CLAMP;
}
if (texture_address_mode_v == SDL_TEXTURE_ADDRESS_AUTO) {
texture_address_mode_v = SDL_TEXTURE_ADDRESS_CLAMP;
}
}

if (indices) {
Expand All @@ -5168,7 +5193,9 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,

// For the software renderer, try to reinterpret triangles as SDL_Rect
#ifdef SDL_VIDEO_RENDER_SW
if (renderer->software && texture_address_mode == SDL_TEXTURE_ADDRESS_CLAMP) {
if (renderer->software &&
texture_address_mode_u == SDL_TEXTURE_ADDRESS_CLAMP &&
texture_address_mode_v == SDL_TEXTURE_ADDRESS_CLAMP) {
return SDL_SW_RenderGeometryRaw(renderer, texture,
xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices,
indices, num_indices, size_indices);
Expand All @@ -5180,7 +5207,36 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
xy, xy_stride, color, color_stride, uv, uv_stride,
num_vertices, indices, num_indices, size_indices,
view->current_scale.x, view->current_scale.y,
texture_address_mode);
texture_address_mode_u, texture_address_mode_v);
}

bool SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode u_mode, SDL_TextureAddressMode v_mode)
{
CHECK_RENDERER_MAGIC(renderer, false);

renderer->texture_address_mode_u = u_mode;
renderer->texture_address_mode_v = v_mode;
return true;
}

bool SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode *u_mode, SDL_TextureAddressMode *v_mode)
{
if (u_mode) {
*u_mode = SDL_TEXTURE_ADDRESS_INVALID;
}
if (v_mode) {
*v_mode = SDL_TEXTURE_ADDRESS_INVALID;
}

CHECK_RENDERER_MAGIC(renderer, false);

if (u_mode) {
*u_mode = renderer->texture_address_mode_u;
}
if (v_mode) {
*v_mode = renderer->texture_address_mode_v;
}
return true;
}

SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
Expand Down
20 changes: 10 additions & 10 deletions src/render/SDL_sysrender.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,6 @@
extern "C" {
#endif

typedef enum SDL_TextureAddressMode
{
SDL_TEXTURE_ADDRESS_INVALID = -1,
SDL_TEXTURE_ADDRESS_AUTO,
SDL_TEXTURE_ADDRESS_CLAMP,
SDL_TEXTURE_ADDRESS_WRAP,
} SDL_TextureAddressMode;

/**
* A rectangle, with the origin at the upper left (double precision).
*/
Expand Down Expand Up @@ -187,7 +179,8 @@ typedef struct SDL_RenderCommand
SDL_BlendMode blend;
SDL_Texture *texture;
SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode;
SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
SDL_GPURenderState *gpu_render_state;
} draw;
struct
Expand Down Expand Up @@ -312,7 +305,8 @@ struct SDL_Renderer
float color_scale;
SDL_FColor color; /**< Color for drawing operations values */
SDL_BlendMode blendMode; /**< The drawing blend mode */
SDL_TextureAddressMode texture_address_mode;
SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
SDL_GPURenderState *gpu_render_state;

SDL_RenderCommand *render_commands;
Expand Down Expand Up @@ -373,6 +367,12 @@ extern SDL_RenderDriver GPU_RenderDriver;
// Clean up any renderers at shutdown
extern void SDL_QuitRender(void);

#define RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v) \
(((scale_mode == SDL_SCALEMODE_NEAREST) << 0) | \
((address_u == SDL_TEXTURE_ADDRESS_WRAP) << 1) | \
((address_v == SDL_TEXTURE_ADDRESS_WRAP) << 2))
#define RENDER_SAMPLER_COUNT (((1 << 0) | (1 << 1) | (1 << 2)) + 1)

// Add a supported texture format to a renderer
extern bool SDL_AddSupportedTextureFormat(SDL_Renderer *renderer, SDL_PixelFormat format);

Expand Down
Loading
Loading