Added SDL_SetRenderTextureAddressMode() and SDL_GetRenderTextureAddressMode()

Fixes https://github.com/libsdl-org/SDL/issues/4820
Fixes https://github.com/libsdl-org/SDL/issues/12610
This commit is contained in:
Sam Lantinga
2024-07-20 09:34:34 -07:00
parent eb918af3dc
commit 633b9f6fb1
20 changed files with 623 additions and 531 deletions

View File

@@ -50,16 +50,6 @@
/* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when
!!! FIXME: textures are needed. */
// Sampler types
typedef enum
{
D3D11_SAMPLER_NEAREST_CLAMP,
D3D11_SAMPLER_NEAREST_WRAP,
D3D11_SAMPLER_LINEAR_CLAMP,
D3D11_SAMPLER_LINEAR_WRAP,
D3D11_SAMPLER_COUNT
} D3D11_Sampler;
// Vertex shader, common values
typedef struct
{
@@ -178,7 +168,7 @@ typedef struct
ID3D11PixelShader *pixelShaders[NUM_SHADERS];
int blendModesCount;
D3D11_BlendMode *blendModes;
ID3D11SamplerState *samplers[D3D11_SAMPLER_COUNT];
ID3D11SamplerState *samplers[RENDER_SAMPLER_COUNT];
D3D_FEATURE_LEVEL featureLevel;
bool pixelSizeChanged;
@@ -538,7 +528,6 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
};
D3D11_BUFFER_DESC constantBufferDesc;
D3D11_SAMPLER_DESC samplerDesc;
D3D11_RASTERIZER_DESC rasterDesc;
// See if we need debug interfaces
@@ -727,38 +716,6 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
goto done;
}
// 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) == D3D11_SAMPLER_COUNT);
SDL_zero(samplerDesc);
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;
for (int i = 0; i < SDL_arraysize(samplerParams); ++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
SDL_zero(rasterDesc);
rasterDesc.AntialiasedLineEnable = FALSE;
@@ -2305,6 +2262,64 @@ static bool D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *
return true;
}
static ID3D11SamplerState *D3D11_GetSamplerState(D3D11_RenderData *data, SDL_ScaleMode scale_mode, SDL_TextureAddressMode address_u, SDL_TextureAddressMode address_v)
{
Uint32 key = RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v);
SDL_assert(key < SDL_arraysize(data->samplers));
if (!data->samplers[key]) {
D3D11_SAMPLER_DESC samplerDesc;
SDL_zero(samplerDesc);
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;
switch (scale_mode) {
case SDL_SCALEMODE_NEAREST:
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
break;
case SDL_SCALEMODE_PIXELART: // Uses linear sampling
case SDL_SCALEMODE_LINEAR:
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
break;
default:
SDL_SetError("Unknown scale mode: %d", scale_mode);
return NULL;
}
switch (address_u) {
case SDL_TEXTURE_ADDRESS_CLAMP:
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_u);
return NULL;
}
switch (address_v) {
case SDL_TEXTURE_ADDRESS_CLAMP:
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_v);
return NULL;
}
HRESULT result = ID3D11Device_CreateSamplerState(data->d3dDevice,
&samplerDesc,
&data->samplers[key]);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT("ID3D11Device::CreateSamplerState", result);
return NULL;
}
}
return data->samplers[key];
}
static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix)
{
SDL_Texture *texture = cmd->data.draw.texture;
@@ -2319,35 +2334,11 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
D3D11_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (cmd->data.draw.texture_scale_mode) {
case SDL_SCALEMODE_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[D3D11_SAMPLER_NEAREST_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = rendererData->samplers[D3D11_SAMPLER_NEAREST_WRAP];
break;
default:
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
case SDL_SCALEMODE_PIXELART: // Uses linear sampling
case SDL_SCALEMODE_LINEAR:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[D3D11_SAMPLER_LINEAR_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = rendererData->samplers[D3D11_SAMPLER_LINEAR_WRAP];
break;
default:
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
default:
return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
textureSampler = D3D11_GetSamplerState(rendererData, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
if (!textureSampler) {
return false;
}
#ifdef SDL_HAVE_YUV
if (textureData->yuv) {
ID3D11ShaderResourceView *shaderResources[3];