Skip to content

Commit 3d91658

Browse files
committed
Added SDL_SetRenderTextureAddressMode() and SDL_GetRenderTextureAddressMode()
Fixes #4820 Fixes #12610
1 parent eed94cb commit 3d91658

20 files changed

+626
-484
lines changed

include/SDL3/SDL_render.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,21 @@ typedef enum SDL_TextureAccess
9898
SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */
9999
} SDL_TextureAccess;
100100

101+
/**
102+
* The addressing mode for a texture when used in SDL_RenderGeometry().
103+
*
104+
* This affects how texture coordinates are interpreted outside of [0, 1]
105+
*
106+
* \since This enum is available since SDL 3.4.0.
107+
*/
108+
typedef enum SDL_TextureAddressMode
109+
{
110+
SDL_TEXTURE_ADDRESS_INVALID = -1,
111+
SDL_TEXTURE_ADDRESS_AUTO, /**< Wrapping is enabled if texture coordinates are outside [0, 1], this is the default */
112+
SDL_TEXTURE_ADDRESS_CLAMP, /**< Texture coordinates are clamped to the [0, 1] range */
113+
SDL_TEXTURE_ADDRESS_WRAP, /**< The texture is repeated (tiled) */
114+
} SDL_TextureAddressMode;
115+
101116
/**
102117
* How the logical size is mapped to the output.
103118
*
@@ -2294,6 +2309,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9GridTiled(SDL_Renderer *rende
22942309
* \since This function is available since SDL 3.2.0.
22952310
*
22962311
* \sa SDL_RenderGeometryRaw
2312+
* \sa SDL_SetRenderTextureAddressMode
22972313
*/
22982314
extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
22992315
SDL_Texture *texture,
@@ -2326,6 +2342,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
23262342
* \since This function is available since SDL 3.2.0.
23272343
*
23282344
* \sa SDL_RenderGeometry
2345+
* \sa SDL_SetRenderTextureAddressMode
23292346
*/
23302347
extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
23312348
SDL_Texture *texture,
@@ -2335,6 +2352,38 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
23352352
int num_vertices,
23362353
const void *indices, int num_indices, int size_indices);
23372354

2355+
/**
2356+
* Set the texture addressing mode used in SDL_RenderGeometry().
2357+
*
2358+
* \param renderer the rendering context.
2359+
* \param mode_u the SDL_TextureAddressMode to use for horizontal texture coordinates in SDL_RenderGeometry().
2360+
* \param mode_v the SDL_TextureAddressMode to use for vertical texture coordinates in SDL_RenderGeometry().
2361+
* \returns true on success or false on failure; call SDL_GetError() for more
2362+
* information.
2363+
*
2364+
* \since This function is available since SDL 3.4.0.
2365+
*
2366+
* \sa SDL_RenderGeometry
2367+
* \sa SDL_RenderGeometryRaw
2368+
* \sa SDL_GetRenderTextureAddressMode
2369+
*/
2370+
extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode mode_u, SDL_TextureAddressMode mode_v);
2371+
2372+
/**
2373+
* Get the texture addressing mode used in SDL_RenderGeometry().
2374+
*
2375+
* \param renderer the rendering context.
2376+
* \param mode_u a pointer filled in with the SDL_TextureAddressMode to use for horizontal texture coordinates in SDL_RenderGeometry(), may be NULL.
2377+
* \param mode_v a pointer filled in with the SDL_TextureAddressMode to use for vertical texture coordinates in SDL_RenderGeometry(), may be NULL.
2378+
* \returns true on success or false on failure; call SDL_GetError() for more
2379+
* information.
2380+
*
2381+
* \since This function is available since SDL 3.4.0.
2382+
*
2383+
* \sa SDL_SetRenderTextureAddressMode
2384+
*/
2385+
extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode *mode_u, SDL_TextureAddressMode *mode_v);
2386+
23382387
/**
23392388
* Read pixels from the current rendering target.
23402389
*

src/dynapi/SDL_dynapi.sym

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,8 @@ SDL3_0.0.0 {
12461246
SDL_SetWindowProgressValue;
12471247
SDL_GetWindowProgressState;
12481248
SDL_GetWindowProgressValue;
1249+
SDL_SetRenderTextureAddressMode;
1250+
SDL_GetRenderTextureAddressMode;
12491251
# extra symbols go here (don't modify this line)
12501252
local: *;
12511253
};

src/dynapi/SDL_dynapi_overrides.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,3 +1271,5 @@
12711271
#define SDL_SetWindowProgressValue SDL_SetWindowProgressValue_REAL
12721272
#define SDL_GetWindowProgressState SDL_GetWindowProgressState_REAL
12731273
#define SDL_GetWindowProgressValue SDL_GetWindowProgressValue_REAL
1274+
#define SDL_SetRenderTextureAddressMode SDL_SetRenderTextureAddressMode_REAL
1275+
#define SDL_GetRenderTextureAddressMode SDL_GetRenderTextureAddressMode_REAL

src/dynapi/SDL_dynapi_procs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,3 +1279,5 @@ SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressState,(SDL_Window *a,SDL_ProgressState
12791279
SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressValue,(SDL_Window *a,float b),(a,b),return)
12801280
SDL_DYNAPI_PROC(SDL_ProgressState,SDL_GetWindowProgressState,(SDL_Window *a),(a),return)
12811281
SDL_DYNAPI_PROC(float,SDL_GetWindowProgressValue,(SDL_Window *a),(a),return)
1282+
SDL_DYNAPI_PROC(bool,SDL_SetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode b,SDL_TextureAddressMode c),(a,b,c),return)
1283+
SDL_DYNAPI_PROC(bool,SDL_GetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode *b,SDL_TextureAddressMode *c),(a,b,c),return)

src/render/SDL_render.c

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,8 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
584584
if (texture) {
585585
cmd->data.draw.texture_scale_mode = texture->scaleMode;
586586
}
587-
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
587+
cmd->data.draw.texture_address_mode_u = SDL_TEXTURE_ADDRESS_CLAMP;
588+
cmd->data.draw.texture_address_mode_v = SDL_TEXTURE_ADDRESS_CLAMP;
588589
cmd->data.draw.gpu_render_state = renderer->gpu_render_state;
589590
if (renderer->gpu_render_state) {
590591
renderer->gpu_render_state->last_command_generation = renderer->render_command_generation;
@@ -727,13 +728,15 @@ static bool QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture,
727728
const float *uv, int uv_stride,
728729
int num_vertices,
729730
const void *indices, int num_indices, int size_indices,
730-
float scale_x, float scale_y, SDL_TextureAddressMode texture_address_mode)
731+
float scale_x, float scale_y,
732+
SDL_TextureAddressMode texture_address_mode_u, SDL_TextureAddressMode texture_address_mode_v)
731733
{
732734
SDL_RenderCommand *cmd;
733735
bool result = false;
734736
cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture);
735737
if (cmd) {
736-
cmd->data.draw.texture_address_mode = texture_address_mode;
738+
cmd->data.draw.texture_address_mode_u = texture_address_mode_u;
739+
cmd->data.draw.texture_address_mode_v = texture_address_mode_v;
737740
result = renderer->QueueGeometry(renderer, cmd, texture,
738741
xy, xy_stride,
739742
color, color_stride, uv, uv_stride,
@@ -3739,7 +3742,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
37393742
result = QueueCmdGeometry(renderer, NULL,
37403743
xy, xy_stride, &renderer->color, 0 /* color_stride */, NULL, 0,
37413744
num_vertices, indices, num_indices, size_indices,
3742-
1.0f, 1.0f, SDL_TEXTURE_ADDRESS_CLAMP);
3745+
1.0f, 1.0f, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
37433746
}
37443747

37453748
SDL_small_free(xy, isstack1);
@@ -3920,7 +3923,7 @@ static bool SDL_RenderTextureInternal(SDL_Renderer *renderer, SDL_Texture *textu
39203923
result = QueueCmdGeometry(renderer, texture,
39213924
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
39223925
num_vertices, indices, num_indices, size_indices,
3923-
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP);
3926+
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
39243927
} else {
39253928
const SDL_FRect rect = { dstrect->x * scale_x, dstrect->y * scale_y, dstrect->w * scale_x, dstrect->h * scale_y };
39263929
result = QueueCmdCopy(renderer, texture, srcrect, &rect);
@@ -4083,7 +4086,7 @@ bool SDL_RenderTextureAffine(SDL_Renderer *renderer, SDL_Texture *texture,
40834086
&texture->color, 0 /* color_stride */,
40844087
uv, uv_stride,
40854088
num_vertices, indices, num_indices, size_indices,
4086-
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP
4089+
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP
40874090
);
40884091
}
40894092
return result;
@@ -4233,7 +4236,7 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture,
42334236
result = QueueCmdGeometry(renderer, texture,
42344237
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
42354238
num_vertices, indices, num_indices, size_indices,
4236-
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP);
4239+
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
42374240
} else {
42384241
result = QueueCmdCopyEx(renderer, texture, &real_srcrect, dstrect, angle, &real_center, flip, scale_x, scale_y);
42394242
}
@@ -4285,7 +4288,8 @@ static bool SDL_RenderTextureTiled_Wrap(SDL_Renderer *renderer, SDL_Texture *tex
42854288
return QueueCmdGeometry(renderer, texture,
42864289
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
42874290
num_vertices, indices, num_indices, size_indices,
4288-
view->current_scale.x, view->current_scale.y, SDL_TEXTURE_ADDRESS_WRAP);
4291+
view->current_scale.x, view->current_scale.y,
4292+
SDL_TEXTURE_ADDRESS_WRAP, SDL_TEXTURE_ADDRESS_WRAP);
42894293
}
42904294

42914295
static bool SDL_RenderTextureTiled_Iterate(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float scale, const SDL_FRect *dstrect)
@@ -5032,7 +5036,7 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
50325036
result = QueueCmdGeometry(renderer, texture,
50335037
xy, xy_stride, color, color_stride, uv, uv_stride,
50345038
num_vertices, prev, 3, 4,
5035-
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP);
5039+
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
50365040
if (!result) {
50375041
goto end;
50385042
}
@@ -5052,7 +5056,7 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
50525056
result = QueueCmdGeometry(renderer, texture,
50535057
xy, xy_stride, color, color_stride, uv, uv_stride,
50545058
num_vertices, prev, 3, 4,
5055-
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP);
5059+
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
50565060
if (!result) {
50575061
goto end;
50585062
}
@@ -5077,7 +5081,8 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
50775081
{
50785082
int i;
50795083
int count = indices ? num_indices : num_vertices;
5080-
SDL_TextureAddressMode texture_address_mode;
5084+
SDL_TextureAddressMode texture_address_mode_u;
5085+
SDL_TextureAddressMode texture_address_mode_v;
50815086

50825087
CHECK_RENDERER_MAGIC(renderer, false);
50835088

@@ -5132,18 +5137,38 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
51325137
texture = texture->native;
51335138
}
51345139

5135-
texture_address_mode = renderer->texture_address_mode;
5136-
if (texture_address_mode == SDL_TEXTURE_ADDRESS_AUTO && texture) {
5137-
texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
5140+
texture_address_mode_u = renderer->texture_address_mode_u;
5141+
texture_address_mode_v = renderer->texture_address_mode_v;
5142+
if (texture &&
5143+
(texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO ||
5144+
texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO)) {
51385145
for (i = 0; i < num_vertices; ++i) {
51395146
const float *uv_ = (const float *)((const char *)uv + i * uv_stride);
51405147
float u = uv_[0];
51415148
float v = uv_[1];
5142-
if (u < 0.0f || v < 0.0f || u > 1.0f || v > 1.0f) {
5143-
texture_address_mode = SDL_TEXTURE_ADDRESS_WRAP;
5144-
break;
5149+
if (u < 0.0f || u > 1.0f) {
5150+
if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO) {
5151+
texture_address_mode_u = SDL_TEXTURE_ADDRESS_WRAP;
5152+
if (texture_address_mode_v != SDL_TEXTURE_ADDRESS_AUTO) {
5153+
break;
5154+
}
5155+
}
5156+
}
5157+
if (v < 0.0f || v > 1.0f) {
5158+
if (texture_address_mode_v == SDL_TEXTURE_ADDRESS_AUTO) {
5159+
texture_address_mode_v = SDL_TEXTURE_ADDRESS_WRAP;
5160+
if (texture_address_mode_u != SDL_TEXTURE_ADDRESS_AUTO) {
5161+
break;
5162+
}
5163+
}
51455164
}
51465165
}
5166+
if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO) {
5167+
texture_address_mode_u = SDL_TEXTURE_ADDRESS_CLAMP;
5168+
}
5169+
if (texture_address_mode_v == SDL_TEXTURE_ADDRESS_AUTO) {
5170+
texture_address_mode_v = SDL_TEXTURE_ADDRESS_CLAMP;
5171+
}
51475172
}
51485173

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

51695194
// For the software renderer, try to reinterpret triangles as SDL_Rect
51705195
#ifdef SDL_VIDEO_RENDER_SW
5171-
if (renderer->software && texture_address_mode == SDL_TEXTURE_ADDRESS_CLAMP) {
5196+
if (renderer->software &&
5197+
texture_address_mode_u == SDL_TEXTURE_ADDRESS_CLAMP &&
5198+
texture_address_mode_v == SDL_TEXTURE_ADDRESS_CLAMP) {
51725199
return SDL_SW_RenderGeometryRaw(renderer, texture,
51735200
xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices,
51745201
indices, num_indices, size_indices);
@@ -5180,7 +5207,36 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
51805207
xy, xy_stride, color, color_stride, uv, uv_stride,
51815208
num_vertices, indices, num_indices, size_indices,
51825209
view->current_scale.x, view->current_scale.y,
5183-
texture_address_mode);
5210+
texture_address_mode_u, texture_address_mode_v);
5211+
}
5212+
5213+
bool SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode mode_u, SDL_TextureAddressMode mode_v)
5214+
{
5215+
CHECK_RENDERER_MAGIC(renderer, false);
5216+
5217+
renderer->texture_address_mode_u = mode_u;
5218+
renderer->texture_address_mode_v = mode_v;
5219+
return true;
5220+
}
5221+
5222+
bool SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode *mode_u, SDL_TextureAddressMode *mode_v)
5223+
{
5224+
if (mode_u) {
5225+
*mode_u = SDL_TEXTURE_ADDRESS_INVALID;
5226+
}
5227+
if (mode_v) {
5228+
*mode_v = SDL_TEXTURE_ADDRESS_INVALID;
5229+
}
5230+
5231+
CHECK_RENDERER_MAGIC(renderer, false);
5232+
5233+
if (mode_u) {
5234+
*mode_u = renderer->texture_address_mode_u;
5235+
}
5236+
if (mode_v) {
5237+
*mode_v = renderer->texture_address_mode_v;
5238+
}
5239+
return true;
51845240
}
51855241

51865242
SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)

src/render/SDL_sysrender.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@
3232
extern "C" {
3333
#endif
3434

35-
typedef enum SDL_TextureAddressMode
36-
{
37-
SDL_TEXTURE_ADDRESS_INVALID = -1,
38-
SDL_TEXTURE_ADDRESS_AUTO,
39-
SDL_TEXTURE_ADDRESS_CLAMP,
40-
SDL_TEXTURE_ADDRESS_WRAP,
41-
} SDL_TextureAddressMode;
42-
4335
/**
4436
* A rectangle, with the origin at the upper left (double precision).
4537
*/
@@ -187,7 +179,8 @@ typedef struct SDL_RenderCommand
187179
SDL_BlendMode blend;
188180
SDL_Texture *texture;
189181
SDL_ScaleMode texture_scale_mode;
190-
SDL_TextureAddressMode texture_address_mode;
182+
SDL_TextureAddressMode texture_address_mode_u;
183+
SDL_TextureAddressMode texture_address_mode_v;
191184
SDL_GPURenderState *gpu_render_state;
192185
} draw;
193186
struct
@@ -312,7 +305,8 @@ struct SDL_Renderer
312305
float color_scale;
313306
SDL_FColor color; /**< Color for drawing operations values */
314307
SDL_BlendMode blendMode; /**< The drawing blend mode */
315-
SDL_TextureAddressMode texture_address_mode;
308+
SDL_TextureAddressMode texture_address_mode_u;
309+
SDL_TextureAddressMode texture_address_mode_v;
316310
SDL_GPURenderState *gpu_render_state;
317311

318312
SDL_RenderCommand *render_commands;
@@ -373,6 +367,12 @@ extern SDL_RenderDriver GPU_RenderDriver;
373367
// Clean up any renderers at shutdown
374368
extern void SDL_QuitRender(void);
375369

370+
#define SAMPLER_HASHKEY(scale_mode, address_u, address_v) \
371+
(((scale_mode == SDL_SCALEMODE_NEAREST) << 0) | \
372+
((address_u == SDL_TEXTURE_ADDRESS_WRAP) << 1) | \
373+
((address_v == SDL_TEXTURE_ADDRESS_WRAP) << 2))
374+
#define SAMPLER_COUNT (((1 << 0) | (1 << 1) | (1 << 2)) + 1)
375+
376376
// Add a supported texture format to a renderer
377377
extern bool SDL_AddSupportedTextureFormat(SDL_Renderer *renderer, SDL_PixelFormat format);
378378

0 commit comments

Comments
 (0)