Skip to content

Commit

Permalink
Enable texture wrapping for SDL_RenderGeometry()
Browse files Browse the repository at this point in the history
  • Loading branch information
slouken committed Jul 20, 2024
1 parent f0a839b commit 38ee4ea
Show file tree
Hide file tree
Showing 11 changed files with 1,116 additions and 359 deletions.
29 changes: 21 additions & 8 deletions src/render/SDL_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
cmd->data.draw.color = *color;
cmd->data.draw.blend = blendMode;
cmd->data.draw.texture = texture;
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
}
}
return cmd;
Expand Down Expand Up @@ -715,12 +716,15 @@ static int 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)
float scale_x, float scale_y, SDL_bool wrap)
{
SDL_RenderCommand *cmd;
int retval = -1;
cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture);
if (cmd) {
if (wrap) {
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_WRAP;
}
retval = renderer->QueueGeometry(renderer, cmd, texture,
xy, xy_stride,
color, color_stride, uv, uv_stride,
Expand Down Expand Up @@ -3602,7 +3606,7 @@ int SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
retval = QueueCmdGeometry(renderer, NULL,
xy, xy_stride, &renderer->color, 0 /* color_stride */, NULL, 0,
num_vertices, indices, num_indices, size_indices,
1.0f, 1.0f);
1.0f, 1.0f, SDL_FALSE);
}

SDL_small_free(xy, isstack1);
Expand Down Expand Up @@ -3818,7 +3822,7 @@ int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FR
num_vertices,
indices, num_indices, size_indices,
renderer->view->scale.x,
renderer->view->scale.y);
renderer->view->scale.y, SDL_FALSE);
} else {

real_dstrect.x *= renderer->view->scale.x;
Expand Down Expand Up @@ -3976,7 +3980,7 @@ int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture,
num_vertices,
indices, num_indices, size_indices,
renderer->view->scale.x,
renderer->view->scale.y);
renderer->view->scale.y, SDL_FALSE);
} else {

retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip,
Expand Down Expand Up @@ -4340,7 +4344,7 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
xy, xy_stride, color, color_stride, uv, uv_stride,
num_vertices, prev, 3, 4,
renderer->view->scale.x,
renderer->view->scale.y);
renderer->view->scale.y, SDL_FALSE);
if (retval < 0) {
goto end;
}
Expand All @@ -4361,7 +4365,7 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
xy, xy_stride, color, color_stride, uv, uv_stride,
num_vertices, prev, 3, 4,
renderer->view->scale.x,
renderer->view->scale.y);
renderer->view->scale.y, SDL_FALSE);
if (retval < 0) {
goto end;
}
Expand All @@ -4386,6 +4390,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer,
{
int i;
int count = indices ? num_indices : num_vertices;
SDL_bool wrap = SDL_FALSE;

CHECK_RENDERER_MAGIC(renderer, -1);

Expand Down Expand Up @@ -4446,7 +4451,15 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer,
float u = uv_[0];
float v = uv_[1];
if (u < 0.0f || v < 0.0f || u > 1.0f || v > 1.0f) {
return SDL_SetError("Values of 'uv' out of bounds %f %f at %d/%d", u, v, i, num_vertices);
if (renderer->software) {
// Software renderer doesn't support UV wrapping yet
wrap = SDL_TRUE;
break;
return SDL_SetError("Values of 'uv' out of bounds %f %f at %d/%d", u, v, i, num_vertices);
} else {
wrap = SDL_TRUE;
break;
}
}
}
}
Expand Down Expand Up @@ -4485,7 +4498,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer,
num_vertices,
indices, num_indices, size_indices,
renderer->view->scale.x,
renderer->view->scale.y);
renderer->view->scale.y, wrap);
}

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

typedef enum SDL_TextureAddressMode
{
SDL_TEXTURE_ADDRESS_INVALID,
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 @@ -132,6 +139,7 @@ typedef struct SDL_RenderCommand
SDL_FColor color;
SDL_BlendMode blend;
SDL_Texture *texture;
SDL_TextureAddressMode texture_address_mode;
} draw;
struct
{
Expand Down
42 changes: 31 additions & 11 deletions src/render/direct3d/SDL_render_d3d.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ typedef struct
SDL_bool updateSize;
SDL_bool beginScene;
SDL_bool enableSeparateAlphaBlend;
D3DTEXTUREFILTERTYPE scaleMode[8];
D3DTEXTUREFILTERTYPE scaleMode[3];
SDL_TextureAddressMode addressMode[3];
IDirect3DSurface9 *defaultRenderTarget;
IDirect3DSurface9 *currentRenderTarget;
void *d3dxDLL;
Expand Down Expand Up @@ -277,6 +278,9 @@ static void D3D_InitRenderState(D3D_RenderData *data)
/* Reset our current scale mode */
SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));

/* Reset our current address mode */
SDL_zeroa(data->addressMode);

/* Start the render with beginScene */
data->beginScene = SDL_TRUE;
}
Expand Down Expand Up @@ -927,19 +931,32 @@ static int BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWO
static void UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
{
if (texturedata->scaleMode != data->scaleMode[index]) {
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER,
texturedata->scaleMode);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER,
texturedata->scaleMode);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU,
D3DTADDRESS_CLAMP);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV,
D3DTADDRESS_CLAMP);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, texturedata->scaleMode);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, texturedata->scaleMode);
data->scaleMode[index] = texturedata->scaleMode;
}
}

static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Shader *shader, const float **shader_params)
static void UpdateTextureAddressMode(D3D_RenderData *data, SDL_TextureAddressMode addressMode, unsigned index)
{
if (addressMode != data->addressMode[index]) {
switch (addressMode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
break;
case SDL_TEXTURE_ADDRESS_WRAP:
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
break;
default:
break;
}
data->addressMode[index] = addressMode;
}
}

static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_TextureAddressMode addressMode, D3D9_Shader *shader, const float **shader_params)
{
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;

Expand All @@ -948,6 +965,7 @@ static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Sh
}

UpdateTextureScaleMode(data, texturedata, 0);
UpdateTextureAddressMode(data, addressMode, 0);

*shader = texturedata->shader;
*shader_params = texturedata->shader_params;
Expand All @@ -959,6 +977,8 @@ static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Sh
if (texturedata->yuv) {
UpdateTextureScaleMode(data, texturedata, 1);
UpdateTextureScaleMode(data, texturedata, 2);
UpdateTextureAddressMode(data, addressMode, 1);
UpdateTextureAddressMode(data, addressMode, 2);

if (BindTextureRep(data->device, &texturedata->utexture, 1) < 0) {
return -1;
Expand Down Expand Up @@ -994,7 +1014,7 @@ static int SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
IDirect3DDevice9_SetTexture(data->device, 2, NULL);
}
#endif
if (texture && SetupTextureState(data, texture, &shader, &shader_params) < 0) {
if (texture && SetupTextureState(data, texture, cmd->data.draw.texture_address_mode, &shader, &shader_params) < 0) {
return -1;
}

Expand Down
80 changes: 56 additions & 24 deletions src/render/direct3d11/SDL_render_d3d11.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ extern ISwapChainBackgroundPanelNative *WINRT_GlobalSwapChainBackgroundPanelNati
/* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when
!!! FIXME: textures are needed. */

/* Sampler types */
typedef enum
{
SDL_D3D11_SAMPLER_NEAREST_CLAMP,
SDL_D3D11_SAMPLER_NEAREST_WRAP,
SDL_D3D11_SAMPLER_LINEAR_CLAMP,
SDL_D3D11_SAMPLER_LINEAR_WRAP,
SDL_NUM_D3D11_SAMPLERS
} SDL_D3D11_sampler_type;

/* Vertex shader, common values */
typedef struct
{
Expand Down Expand Up @@ -181,8 +191,7 @@ typedef struct
ID3D11PixelShader *pixelShaders[NUM_SHADERS];
int blendModesCount;
D3D11_BlendMode *blendModes;
ID3D11SamplerState *nearestPixelSampler;
ID3D11SamplerState *linearSampler;
ID3D11SamplerState *samplers[SDL_NUM_D3D11_SAMPLERS];
D3D_FEATURE_LEVEL featureLevel;
SDL_bool pixelSizeChanged;

Expand Down Expand Up @@ -346,8 +355,9 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer)
SAFE_RELEASE(data->vertexShaderConstants);
SAFE_RELEASE(data->clippedRasterizer);
SAFE_RELEASE(data->mainRasterizer);
SAFE_RELEASE(data->linearSampler);
SAFE_RELEASE(data->nearestPixelSampler);
for (i = 0; i < SDL_arraysize(data->samplers[i]); ++i) {
SAFE_RELEASE(data->samplers[i]);
}

if (data->blendModesCount > 0) {
for (i = 0; i < data->blendModesCount; ++i) {
Expand Down Expand Up @@ -734,31 +744,35 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
}

/* Create samplers to use when drawing textures: */
static struct
{
D3D11_FILTER filter;
D3D11_TEXTURE_ADDRESS_MODE address;
} samplerParams[] = {
{ D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_CLAMP },
{ D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_WRAP },
{ D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP },
{ D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_WRAP },
};
SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_NUM_D3D11_SAMPLERS);
SDL_zero(samplerDesc);
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.MinLOD = 0.0f;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
result = ID3D11Device_CreateSamplerState(data->d3dDevice,
&samplerDesc,
&data->nearestPixelSampler);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [nearest-pixel filter]"), result);
goto done;
}

samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
result = ID3D11Device_CreateSamplerState(data->d3dDevice,
&samplerDesc,
&data->linearSampler);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [linear filter]"), result);
goto done;
for (int i = 0; i < SDL_arraysize(data->samplers); ++i) {
samplerDesc.Filter = samplerParams[i].filter;
samplerDesc.AddressU = samplerParams[i].address;
samplerDesc.AddressV = samplerParams[i].address;
result = ID3D11Device_CreateSamplerState(data->d3dDevice,
&samplerDesc,
&data->samplers[i]);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [nearest-pixel filter]"), result);
goto done;
}
}

/* Setup Direct3D rasterizer states */
Expand Down Expand Up @@ -2426,10 +2440,28 @@ static int D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c

switch (textureData->scaleMode) {
case D3D11_FILTER_MIN_MAG_MIP_POINT:
textureSampler = rendererData->nearestPixelSampler;
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[SDL_D3D11_SAMPLER_NEAREST_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = rendererData->samplers[SDL_D3D11_SAMPLER_NEAREST_WRAP];
break;
default:
return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode);
}
break;
case D3D11_FILTER_MIN_MAG_MIP_LINEAR:
textureSampler = rendererData->linearSampler;
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[SDL_D3D11_SAMPLER_LINEAR_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = rendererData->samplers[SDL_D3D11_SAMPLER_LINEAR_WRAP];
break;
default:
return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode);
}
break;
default:
return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode);
Expand Down
Loading

0 comments on commit 38ee4ea

Please sign in to comment.