mirror of https://github.com/libsdl-org/SDL
Enable texture wrapping for SDL_RenderGeometry()
Currently wrapping is based on whether texture coordinates are outside of [0,1], but the code is structured so it's easy to add an API to set it and add additional wrapping modes if we want. Fixes https://github.com/libsdl-org/SDL/issues/9238 Closes https://github.com/libsdl-org/SDL/pull/5369
This commit is contained in:
parent
6a74ade73d
commit
03bb2c17ed
|
@ -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;
|
||||
|
@ -715,12 +716,14 @@ 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_TextureAddressMode texture_address_mode)
|
||||
{
|
||||
SDL_RenderCommand *cmd;
|
||||
int retval = -1;
|
||||
cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture);
|
||||
if (cmd) {
|
||||
cmd->data.draw.texture_address_mode = texture_address_mode;
|
||||
|
||||
retval = renderer->QueueGeometry(renderer, cmd, texture,
|
||||
xy, xy_stride,
|
||||
color, color_stride, uv, uv_stride,
|
||||
|
@ -3602,7 +3605,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_TEXTURE_ADDRESS_CLAMP);
|
||||
}
|
||||
|
||||
SDL_small_free(xy, isstack1);
|
||||
|
@ -3818,7 +3821,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_TEXTURE_ADDRESS_CLAMP);
|
||||
} else {
|
||||
|
||||
real_dstrect.x *= renderer->view->scale.x;
|
||||
|
@ -3976,7 +3979,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_TEXTURE_ADDRESS_CLAMP);
|
||||
} else {
|
||||
|
||||
retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip,
|
||||
|
@ -4340,7 +4343,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_TEXTURE_ADDRESS_CLAMP);
|
||||
if (retval < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
@ -4361,7 +4364,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_TEXTURE_ADDRESS_CLAMP);
|
||||
if (retval < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
@ -4386,6 +4389,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer,
|
|||
{
|
||||
int i;
|
||||
int count = indices ? num_indices : num_vertices;
|
||||
SDL_TextureAddressMode texture_address_mode;
|
||||
|
||||
CHECK_RENDERER_MAGIC(renderer, -1);
|
||||
|
||||
|
@ -4440,13 +4444,16 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer,
|
|||
texture = texture->native;
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
texture_address_mode = renderer->texture_address_mode;
|
||||
if (texture_address_mode == SDL_TEXTURE_ADDRESS_AUTO && texture) {
|
||||
texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
|
||||
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) {
|
||||
return SDL_SetError("Values of 'uv' out of bounds %f %f at %d/%d", u, v, i, num_vertices);
|
||||
texture_address_mode = SDL_TEXTURE_ADDRESS_WRAP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4473,7 +4480,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer,
|
|||
|
||||
/* For the software renderer, try to reinterpret triangles as SDL_Rect */
|
||||
#if SDL_VIDEO_RENDER_SW
|
||||
if (renderer->software) {
|
||||
if (renderer->software && texture_address_mode == 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);
|
||||
|
@ -4485,7 +4492,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, texture_address_mode);
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
|
||||
|
|
|
@ -30,6 +30,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum SDL_TextureAddressMode
|
||||
{
|
||||
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).
|
||||
*/
|
||||
|
@ -132,6 +139,7 @@ typedef struct SDL_RenderCommand
|
|||
SDL_FColor color;
|
||||
SDL_BlendMode blend;
|
||||
SDL_Texture *texture;
|
||||
SDL_TextureAddressMode texture_address_mode;
|
||||
} draw;
|
||||
struct
|
||||
{
|
||||
|
@ -262,6 +270,7 @@ 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_RenderCommand *render_commands;
|
||||
SDL_RenderCommand *render_commands_tail;
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
SAFE_RELEASE(data->samplers[i]);
|
||||
}
|
||||
|
||||
if (data->blendModesCount > 0) {
|
||||
for (i = 0; i < data->blendModesCount; ++i) {
|
||||
|
@ -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(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 */
|
||||
|
@ -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);
|
||||
|
|
|
@ -134,6 +134,16 @@ extern "C" {
|
|||
/* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when
|
||||
!!! FIXME: textures are needed. */
|
||||
|
||||
/* Sampler types */
|
||||
typedef enum
|
||||
{
|
||||
SDL_D3D12_SAMPLER_NEAREST_CLAMP,
|
||||
SDL_D3D12_SAMPLER_NEAREST_WRAP,
|
||||
SDL_D3D12_SAMPLER_LINEAR_CLAMP,
|
||||
SDL_D3D12_SAMPLER_LINEAR_WRAP,
|
||||
SDL_D3D12_NUM_SAMPLERS
|
||||
} SDL_D3D12_sampler_type;
|
||||
|
||||
/* Vertex shader, common values */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -294,8 +304,7 @@ typedef struct
|
|||
D3D12_PipelineState *currentPipelineState;
|
||||
|
||||
D3D12_VertexBuffer vertexBuffers[SDL_D3D12_NUM_VERTEX_BUFFERS];
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE nearestPixelSampler;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE linearSampler;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE samplers[SDL_D3D12_NUM_SAMPLERS];
|
||||
|
||||
/* Data for staging/allocating textures */
|
||||
ID3D12Resource *uploadBuffers[SDL_D3D12_NUM_UPLOAD_BUFFERS];
|
||||
|
@ -1057,7 +1066,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
|
|||
data->srvDescriptorSize = D3D_CALL(d3dDevice, GetDescriptorHandleIncrementSize, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
|
||||
SDL_zero(descriptorHeapDesc);
|
||||
descriptorHeapDesc.NumDescriptors = 2;
|
||||
descriptorHeapDesc.NumDescriptors = 4;
|
||||
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
result = D3D_CALL(data->d3dDevice, CreateDescriptorHeap,
|
||||
|
@ -1165,22 +1174,32 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
|
|||
}
|
||||
|
||||
/* Create samplers to use when drawing textures: */
|
||||
static struct
|
||||
{
|
||||
D3D12_FILTER filter;
|
||||
D3D12_TEXTURE_ADDRESS_MODE address;
|
||||
} samplerParams[] = {
|
||||
{ D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_CLAMP },
|
||||
{ D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_WRAP },
|
||||
{ D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_CLAMP },
|
||||
{ D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_WRAP },
|
||||
};
|
||||
SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_D3D12_NUM_SAMPLERS);
|
||||
SDL_zero(samplerDesc);
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
samplerDesc.MipLODBias = 0.0f;
|
||||
samplerDesc.MaxAnisotropy = 1;
|
||||
samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
samplerDesc.MinLOD = 0.0f;
|
||||
samplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
|
||||
D3D_CALL_RET_ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(data->samplerDescriptorHeap, &data->nearestPixelSampler);
|
||||
D3D_CALL(data->d3dDevice, CreateSampler, &samplerDesc, data->nearestPixelSampler);
|
||||
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
data->linearSampler.ptr = data->nearestPixelSampler.ptr + data->samplerDescriptorSize;
|
||||
D3D_CALL(data->d3dDevice, CreateSampler, &samplerDesc, data->linearSampler);
|
||||
D3D_CALL_RET_ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(data->samplerDescriptorHeap, &data->samplers[0]);
|
||||
for (i = 0; i < SDL_arraysize(samplerParams); ++i) {
|
||||
samplerDesc.Filter = samplerParams[i].filter;
|
||||
samplerDesc.AddressU = samplerParams[i].address;
|
||||
samplerDesc.AddressV = samplerParams[i].address;
|
||||
data->samplers[i].ptr = data->samplers[0].ptr + i * data->samplerDescriptorSize;
|
||||
D3D_CALL(data->d3dDevice, CreateSampler, &samplerDesc, data->samplers[i]);
|
||||
}
|
||||
|
||||
/* Initialize the pool allocator for SRVs */
|
||||
for (i = 0; i < SDL_D3D12_MAX_NUM_TEXTURES; ++i) {
|
||||
|
@ -2797,10 +2816,28 @@ static int D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
|
||||
switch (textureData->scaleMode) {
|
||||
case D3D12_FILTER_MIN_MAG_MIP_POINT:
|
||||
textureSampler = &rendererData->nearestPixelSampler;
|
||||
switch (cmd->data.draw.texture_address_mode) {
|
||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||
textureSampler = &rendererData->samplers[SDL_D3D12_SAMPLER_NEAREST_CLAMP];
|
||||
break;
|
||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||
textureSampler = &rendererData->samplers[SDL_D3D12_SAMPLER_NEAREST_WRAP];
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode);
|
||||
}
|
||||
break;
|
||||
case D3D12_FILTER_MIN_MAG_MIP_LINEAR:
|
||||
textureSampler = &rendererData->linearSampler;
|
||||
switch (cmd->data.draw.texture_address_mode) {
|
||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||
textureSampler = &rendererData->samplers[SDL_D3D12_SAMPLER_LINEAR_CLAMP];
|
||||
break;
|
||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||
textureSampler = &rendererData->samplers[SDL_D3D12_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);
|
||||
|
|
|
@ -80,6 +80,16 @@ static const size_t CONSTANTS_OFFSET_DECODE_BT2020_LIMITED = ALIGN_CONSTANTS(16,
|
|||
static const size_t CONSTANTS_OFFSET_DECODE_BT2020_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT2020_LIMITED + sizeof(float) * 4 * 4);
|
||||
static const size_t CONSTANTS_LENGTH = CONSTANTS_OFFSET_DECODE_BT2020_FULL + sizeof(float) * 4 * 4;
|
||||
|
||||
/* Sampler types */
|
||||
typedef enum
|
||||
{
|
||||
SDL_METAL_SAMPLER_NEAREST_CLAMP,
|
||||
SDL_METAL_SAMPLER_NEAREST_WRAP,
|
||||
SDL_METAL_SAMPLER_LINEAR_CLAMP,
|
||||
SDL_METAL_SAMPLER_LINEAR_WRAP,
|
||||
SDL_NUM_METAL_SAMPLERS
|
||||
} SDL_METAL_sampler_type;
|
||||
|
||||
typedef enum SDL_MetalVertexFunction
|
||||
{
|
||||
SDL_METAL_VERTEX_SOLID,
|
||||
|
@ -130,8 +140,7 @@ typedef struct METAL_ShaderPipelines
|
|||
@property(nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
|
||||
@property(nonatomic, retain) id<MTLLibrary> mtllibrary;
|
||||
@property(nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
|
||||
@property(nonatomic, retain) id<MTLSamplerState> mtlsamplernearest;
|
||||
@property(nonatomic, retain) id<MTLSamplerState> mtlsamplerlinear;
|
||||
@property(nonatomic, retain) NSMutableArray<id<MTLSamplerState>> *mtlsamplers;
|
||||
@property(nonatomic, retain) id<MTLBuffer> mtlbufconstants;
|
||||
@property(nonatomic, retain) id<MTLBuffer> mtlbufquadindices;
|
||||
@property(nonatomic, assign) SDL_MetalView mtlview;
|
||||
|
@ -148,7 +157,6 @@ typedef struct METAL_ShaderPipelines
|
|||
@interface METAL_TextureData : NSObject
|
||||
@property(nonatomic, retain) id<MTLTexture> mtltexture;
|
||||
@property(nonatomic, retain) id<MTLTexture> mtltextureUv;
|
||||
@property(nonatomic, retain) id<MTLSamplerState> mtlsampler;
|
||||
@property(nonatomic, assign) SDL_MetalFragmentFunction fragmentFunction;
|
||||
#if SDL_HAVE_YUV
|
||||
@property(nonatomic, assign) BOOL yuv;
|
||||
|
@ -739,11 +747,6 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
|||
}
|
||||
#endif /* SDL_HAVE_YUV */
|
||||
texturedata = [[METAL_TextureData alloc] init];
|
||||
if (texture->scaleMode == SDL_SCALEMODE_NEAREST) {
|
||||
texturedata.mtlsampler = data.mtlsamplernearest;
|
||||
} else {
|
||||
texturedata.mtlsampler = data.mtlsamplerlinear;
|
||||
}
|
||||
if (SDL_COLORSPACETRANSFER(texture->colorspace) == SDL_TRANSFER_CHARACTERISTICS_SRGB) {
|
||||
texturedata.fragmentFunction = SDL_METAL_FRAGMENT_COPY;
|
||||
#if SDL_HAVE_YUV
|
||||
|
@ -1094,16 +1097,6 @@ static void METAL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
|
||||
static void METAL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
||||
{
|
||||
@autoreleasepool {
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *)renderer->internal;
|
||||
METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->internal;
|
||||
|
||||
if (scaleMode == SDL_SCALEMODE_NEAREST) {
|
||||
texturedata.mtlsampler = data.mtlsamplernearest;
|
||||
} else {
|
||||
texturedata.mtlsampler = data.mtlsamplerlinear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int METAL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
|
@ -1503,13 +1496,32 @@ static SDL_bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cm
|
|||
}
|
||||
|
||||
if (texture != statecache->texture) {
|
||||
METAL_TextureData *oldtexturedata = NULL;
|
||||
if (statecache->texture) {
|
||||
oldtexturedata = (__bridge METAL_TextureData *)statecache->texture->internal;
|
||||
}
|
||||
if (!oldtexturedata || (texturedata.mtlsampler != oldtexturedata.mtlsampler)) {
|
||||
[data.mtlcmdencoder setFragmentSamplerState:texturedata.mtlsampler atIndex:0];
|
||||
id<MTLSamplerState> mtlsampler;
|
||||
|
||||
if (texture->scaleMode == SDL_SCALEMODE_NEAREST) {
|
||||
switch (cmd->data.draw.texture_address_mode) {
|
||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_CLAMP];
|
||||
break;
|
||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_WRAP];
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode);
|
||||
}
|
||||
} else {
|
||||
switch (cmd->data.draw.texture_address_mode) {
|
||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_LINEAR_CLAMP];
|
||||
break;
|
||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_LINEAR_WRAP];
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode);
|
||||
}
|
||||
}
|
||||
[data.mtlcmdencoder setFragmentSamplerState:mtlsampler atIndex:0];
|
||||
|
||||
[data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0];
|
||||
#if SDL_HAVE_YUV
|
||||
|
@ -1904,7 +1916,6 @@ static int METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_
|
|||
MTLSamplerDescriptor *samplerdesc;
|
||||
id<MTLCommandQueue> mtlcmdqueue;
|
||||
id<MTLLibrary> mtllibrary;
|
||||
id<MTLSamplerState> mtlsamplernearest, mtlsamplerlinear;
|
||||
id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices;
|
||||
id<MTLCommandBuffer> cmdbuffer;
|
||||
id<MTLBlitCommandEncoder> blitcmd;
|
||||
|
@ -2066,17 +2077,27 @@ static int METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_
|
|||
data.allpipelines = NULL;
|
||||
ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm);
|
||||
|
||||
static struct
|
||||
{
|
||||
MTLSamplerMinMagFilter filter;
|
||||
MTLSamplerAddressMode address;
|
||||
} samplerParams[] = {
|
||||
{ MTLSamplerMinMagFilterNearest, MTLSamplerAddressModeClampToEdge },
|
||||
{ MTLSamplerMinMagFilterNearest, MTLSamplerAddressModeRepeat },
|
||||
{ MTLSamplerMinMagFilterLinear, MTLSamplerAddressModeClampToEdge },
|
||||
{ MTLSamplerMinMagFilterLinear, MTLSamplerAddressModeRepeat },
|
||||
};
|
||||
SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_NUM_METAL_SAMPLERS);
|
||||
|
||||
data.mtlsamplers = [[NSMutableArray<id<MTLSamplerState>> alloc] init];
|
||||
samplerdesc = [[MTLSamplerDescriptor alloc] init];
|
||||
|
||||
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
|
||||
mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||
data.mtlsamplernearest = mtlsamplernearest;
|
||||
|
||||
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
|
||||
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
|
||||
mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
|
||||
data.mtlsamplerlinear = mtlsamplerlinear;
|
||||
for (int i = 0; i < SDL_arraysize(samplerParams); ++i) {
|
||||
samplerdesc.minFilter = samplerParams[i].filter;
|
||||
samplerdesc.magFilter = samplerParams[i].filter;
|
||||
samplerdesc.sAddressMode = samplerParams[i].address;
|
||||
samplerdesc.tAddressMode = samplerParams[i].address;
|
||||
[data.mtlsamplers addObject:[data.mtldevice newSamplerStateWithDescriptor:samplerdesc]];
|
||||
}
|
||||
|
||||
mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
|
||||
|
||||
|
|
|
@ -541,15 +541,6 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr
|
|||
renderdata->glBindTexture(textype, data->texture);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, scaleMode);
|
||||
/* According to the spec, CLAMP_TO_EDGE is the default for TEXTURE_RECTANGLE
|
||||
and setting it causes an INVALID_ENUM error in the latest NVidia drivers.
|
||||
*/
|
||||
if (textype != GL_TEXTURE_RECTANGLE_ARB) {
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
|
||||
#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
|
||||
|
@ -609,10 +600,6 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr
|
|||
scaleMode);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
|
||||
scaleMode);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
|
||||
(texture_h + 1) / 2, 0, format, type, NULL);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture);
|
||||
|
@ -622,10 +609,6 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr
|
|||
scaleMode);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
|
||||
scaleMode);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
|
||||
(texture_h + 1) / 2, 0, format, type, NULL);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
|
||||
|
@ -646,10 +629,6 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr
|
|||
scaleMode);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
|
||||
scaleMode);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2,
|
||||
(texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture);
|
||||
|
@ -1141,6 +1120,23 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
|
||||
{
|
||||
switch (addressMode) {
|
||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
break;
|
||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unknown texture address mode: %d\n", addressMode);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
|
||||
{
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
|
@ -1157,16 +1153,28 @@ static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
|
|||
}
|
||||
data->glBindTexture(textype, texturedata->vtexture);
|
||||
|
||||
if (SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data->GL_ARB_multitexture_supported) {
|
||||
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
}
|
||||
data->glBindTexture(textype, texturedata->utexture);
|
||||
|
||||
if (SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (texturedata->nv12) {
|
||||
if (data->GL_ARB_multitexture_supported) {
|
||||
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
}
|
||||
data->glBindTexture(textype, texturedata->utexture);
|
||||
|
||||
if (SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (data->GL_ARB_multitexture_supported) {
|
||||
|
@ -1174,6 +1182,10 @@ static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
|
|||
}
|
||||
data->glBindTexture(textype, texturedata->texture);
|
||||
|
||||
if (SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->drawstate.texture = texture;
|
||||
}
|
||||
|
||||
|
|
|
@ -1030,6 +1030,23 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int SetTextureAddressMode(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
|
||||
{
|
||||
switch (addressMode) {
|
||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
break;
|
||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unknown texture address mode: %d\n", addressMode);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, void *vertices)
|
||||
{
|
||||
GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
|
||||
|
@ -1162,18 +1179,35 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo
|
|||
data->glActiveTexture(GL_TEXTURE2);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
|
||||
if (SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->glActiveTexture(GL_TEXTURE1);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
|
||||
if (SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
} else if (tdata->nv12) {
|
||||
data->glActiveTexture(GL_TEXTURE1);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
|
||||
if (SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
#endif
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
|
||||
if (SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->drawstate.texture = texture;
|
||||
}
|
||||
|
||||
|
@ -1552,8 +1586,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
|||
renderdata->glBindTexture(data->texture_type, data->texture_v);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
|
||||
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v);
|
||||
|
||||
|
@ -1570,8 +1602,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
|||
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
|
||||
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
|
||||
return -1;
|
||||
|
@ -1595,8 +1625,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
|||
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
|
||||
return -1;
|
||||
|
@ -1623,8 +1651,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
|||
renderdata->glBindTexture(data->texture_type, data->texture);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
|
||||
renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
|
||||
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
|
||||
|
|
|
@ -928,7 +928,8 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
|
|||
&(ptr[0].src), &(ptr[1].src), &(ptr[2].src),
|
||||
surface,
|
||||
&(ptr[0].dst), &(ptr[1].dst), &(ptr[2].dst),
|
||||
ptr[0].color, ptr[1].color, ptr[2].color);
|
||||
ptr[0].color, ptr[1].color, ptr[2].color,
|
||||
cmd->data.draw.texture_address_mode);
|
||||
}
|
||||
} else {
|
||||
GeometryFillData *ptr = (GeometryFillData *)verts;
|
||||
|
|
|
@ -42,7 +42,7 @@ static void SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
|
|||
SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2,
|
||||
int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x,
|
||||
int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row,
|
||||
SDL_Color c0, SDL_Color c1, SDL_Color c2, int is_uniform);
|
||||
SDL_Color c0, SDL_Color c1, SDL_Color c2, SDL_bool is_uniform, SDL_TextureAddressMode texture_address_mode);
|
||||
|
||||
#if 0
|
||||
int SDL_BlitTriangle(SDL_Surface *src, const SDL_Point srcpoints[3], SDL_Surface *dst, const SDL_Point dstpoints[3])
|
||||
|
@ -183,7 +183,17 @@ static void bounding_rect(const SDL_Point *a, const SDL_Point *b, const SDL_Poin
|
|||
/* Use 64 bits precision to prevent overflow when interpolating color / texture with wide triangles */
|
||||
#define TRIANGLE_GET_TEXTCOORD \
|
||||
int srcx = (int)(((Sint64)w0 * s2s0_x + (Sint64)w1 * s2s1_x + s2_x_area.x) / area); \
|
||||
int srcy = (int)(((Sint64)w0 * s2s0_y + (Sint64)w1 * s2s1_y + s2_x_area.y) / area);
|
||||
int srcy = (int)(((Sint64)w0 * s2s0_y + (Sint64)w1 * s2s1_y + s2_x_area.y) / area); \
|
||||
if (texture_address_mode == SDL_TEXTURE_ADDRESS_WRAP) { \
|
||||
srcx %= src_surface->w; \
|
||||
if (srcx < 0) { \
|
||||
srcx += (src_surface->w - 1); \
|
||||
} \
|
||||
srcy %= src_surface->h; \
|
||||
if (srcy < 0) { \
|
||||
srcy += (src_surface->h - 1); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define TRIANGLE_GET_MAPPED_COLOR \
|
||||
Uint8 r = (Uint8)(((Sint64)w0 * c0.r + (Sint64)w1 * c1.r + (Sint64)w2 * c2.r) / area); \
|
||||
|
@ -231,7 +241,7 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin
|
|||
Sint64 w0_row, w1_row, w2_row;
|
||||
int bias_w0, bias_w1, bias_w2;
|
||||
|
||||
int is_uniform;
|
||||
SDL_bool is_uniform;
|
||||
|
||||
SDL_Surface *tmp = NULL;
|
||||
|
||||
|
@ -454,8 +464,10 @@ int SDL_SW_BlitTriangle(
|
|||
SDL_Point *s0, SDL_Point *s1, SDL_Point *s2,
|
||||
SDL_Surface *dst,
|
||||
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2,
|
||||
SDL_Color c0, SDL_Color c1, SDL_Color c2)
|
||||
SDL_Color c0, SDL_Color c1, SDL_Color c2,
|
||||
SDL_TextureAddressMode texture_address_mode)
|
||||
{
|
||||
SDL_Surface *src_surface = src;
|
||||
int ret = 0;
|
||||
int src_locked = 0;
|
||||
int dst_locked = 0;
|
||||
|
@ -482,9 +494,9 @@ int SDL_SW_BlitTriangle(
|
|||
Sint64 w0_row, w1_row, w2_row;
|
||||
int bias_w0, bias_w1, bias_w2;
|
||||
|
||||
int is_uniform;
|
||||
SDL_bool is_uniform;
|
||||
|
||||
int has_modulation;
|
||||
SDL_bool has_modulation;
|
||||
|
||||
if (!SDL_SurfaceValid(src)) {
|
||||
return SDL_InvalidParamError("src");
|
||||
|
@ -527,7 +539,7 @@ int SDL_SW_BlitTriangle(
|
|||
SDL_GetSurfaceBlendMode(src, &blend);
|
||||
|
||||
/* TRIANGLE_GET_TEXTCOORD interpolates up to the max values included, so reduce by 1 */
|
||||
{
|
||||
if (texture_address_mode == SDL_TEXTURE_ADDRESS_CLAMP) {
|
||||
SDL_Rect srcrect;
|
||||
int maxx, maxy;
|
||||
bounding_rect(s0, s1, s2, &srcrect);
|
||||
|
@ -564,17 +576,6 @@ int SDL_SW_BlitTriangle(
|
|||
has_modulation = SDL_TRUE;
|
||||
}
|
||||
|
||||
{
|
||||
/* Clip triangle rect with surface rect */
|
||||
SDL_Rect rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.w = dst->w;
|
||||
rect.h = dst->h;
|
||||
|
||||
SDL_GetRectIntersection(&dstrect, &rect, &dstrect);
|
||||
}
|
||||
|
||||
{
|
||||
/* Clip triangle with surface clip rect */
|
||||
SDL_Rect rect;
|
||||
|
@ -695,6 +696,7 @@ int SDL_SW_BlitTriangle(
|
|||
tmp_info.colorkey = info->colorkey;
|
||||
|
||||
/* src */
|
||||
tmp_info.src_surface = src_surface;
|
||||
tmp_info.src = (Uint8 *)src_ptr;
|
||||
tmp_info.src_pitch = src_pitch;
|
||||
|
||||
|
@ -714,7 +716,7 @@ int SDL_SW_BlitTriangle(
|
|||
SDL_BlitTriangle_Slow(&tmp_info, s2_x_area, dstrect, (int)area, bias_w0, bias_w1, bias_w2,
|
||||
d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x,
|
||||
s2s0_x, s2s1_x, s2s0_y, s2s1_y, (int)w0_row, (int)w1_row, (int)w2_row,
|
||||
c0, c1, c2, is_uniform);
|
||||
c0, c1, c2, is_uniform, texture_address_mode);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
@ -786,8 +788,9 @@ static void SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
|
|||
SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2,
|
||||
int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x,
|
||||
int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row,
|
||||
SDL_Color c0, SDL_Color c1, SDL_Color c2, int is_uniform)
|
||||
SDL_Color c0, SDL_Color c1, SDL_Color c2, SDL_bool is_uniform, SDL_TextureAddressMode texture_address_mode)
|
||||
{
|
||||
SDL_Surface *src_surface = info->src_surface;
|
||||
const int flags = info->flags;
|
||||
Uint32 modulateR = info->r;
|
||||
Uint32 modulateG = info->g;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "../SDL_sysrender.h" // For SDL_TextureAddressMode
|
||||
|
||||
extern int SDL_SW_FillTriangle(SDL_Surface *dst,
|
||||
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2,
|
||||
SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2);
|
||||
|
@ -33,7 +35,8 @@ extern int SDL_SW_BlitTriangle(
|
|||
SDL_Point *s0, SDL_Point *s1, SDL_Point *s2,
|
||||
SDL_Surface *dst,
|
||||
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2,
|
||||
SDL_Color c0, SDL_Color c1, SDL_Color c2);
|
||||
SDL_Color c0, SDL_Color c1, SDL_Color c2,
|
||||
SDL_TextureAddressMode texture_address_mode);
|
||||
|
||||
extern void trianglepoint_2_fixedpoint(SDL_Point *a);
|
||||
|
||||
|
|
|
@ -158,9 +158,12 @@ typedef enum {
|
|||
} SDL_vulkan_renderpass_type;
|
||||
|
||||
/* Sampler types */
|
||||
typedef enum {
|
||||
SDL_VULKAN_SAMPLER_NEAREST = 0,
|
||||
SDL_VULKAN_SAMPLER_LINEAR = 1,
|
||||
typedef enum
|
||||
{
|
||||
SDL_VULKAN_SAMPLER_NEAREST_CLAMP,
|
||||
SDL_VULKAN_SAMPLER_NEAREST_WRAP,
|
||||
SDL_VULKAN_SAMPLER_LINEAR_CLAMP,
|
||||
SDL_VULKAN_SAMPLER_LINEAR_WRAP,
|
||||
SDL_VULKAN_NUM_SAMPLERS
|
||||
} SDL_vulkan_sampler_type;
|
||||
|
||||
|
@ -181,6 +184,15 @@ static const float INPUTTYPE_SRGB = 1;
|
|||
static const float INPUTTYPE_SCRGB = 2;
|
||||
static const float INPUTTYPE_HDR10 = 3;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SAMPLER_POINT_CLAMP,
|
||||
SAMPLER_POINT_WRAP,
|
||||
SAMPLER_LINEAR_CLAMP,
|
||||
SAMPLER_LINEAR_WRAP,
|
||||
NUM_SAMPLERS
|
||||
} Sampler;
|
||||
|
||||
/* Pixel shader constants, common values */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -1904,34 +1916,37 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
|
|||
|
||||
/* Create samplers */
|
||||
{
|
||||
static struct
|
||||
{
|
||||
VkFilter filter;
|
||||
VkSamplerAddressMode address;
|
||||
} samplerParams[] = {
|
||||
{ VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE },
|
||||
{ VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT },
|
||||
{ VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE },
|
||||
{ VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT },
|
||||
};
|
||||
SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_VULKAN_NUM_SAMPLERS);
|
||||
VkSamplerCreateInfo samplerCreateInfo = { 0 };
|
||||
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
|
||||
samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
|
||||
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.mipLodBias = 0.0f;
|
||||
samplerCreateInfo.anisotropyEnable = VK_FALSE;
|
||||
samplerCreateInfo.maxAnisotropy = 1.0f;
|
||||
samplerCreateInfo.minLod = 0.0f;
|
||||
samplerCreateInfo.maxLod = 1000.0f;
|
||||
result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[SDL_VULKAN_SAMPLER_NEAREST]);
|
||||
if (result != VK_SUCCESS) {
|
||||
VULKAN_DestroyAll(renderer);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSampler(): %s\n", SDL_Vulkan_GetResultString(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
|
||||
samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
|
||||
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[SDL_VULKAN_SAMPLER_LINEAR]);
|
||||
if (result != VK_SUCCESS) {
|
||||
VULKAN_DestroyAll(renderer);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSampler(): %s\n", SDL_Vulkan_GetResultString(result));
|
||||
return result;
|
||||
for (int i = 0; i < SDL_arraysize(samplerParams); ++i) {
|
||||
samplerCreateInfo.magFilter = samplerParams[i].filter;
|
||||
samplerCreateInfo.minFilter = samplerParams[i].filter;
|
||||
samplerCreateInfo.addressModeU = samplerParams[i].address;
|
||||
samplerCreateInfo.addressModeV = samplerParams[i].address;
|
||||
result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[i]);
|
||||
if (result != VK_SUCCESS) {
|
||||
VULKAN_DestroyAll(renderer);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSampler(): %s\n", SDL_Vulkan_GetResultString(result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2602,8 +2617,8 @@ static int VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
|||
samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
|
||||
samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
|
||||
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
samplerCreateInfo.mipLodBias = 0.0f;
|
||||
samplerCreateInfo.anisotropyEnable = VK_FALSE;
|
||||
|
@ -3627,10 +3642,28 @@ static SDL_bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderComm
|
|||
|
||||
switch (textureData->scaleMode) {
|
||||
case VK_FILTER_NEAREST:
|
||||
textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_NEAREST];
|
||||
switch (cmd->data.draw.texture_address_mode) {
|
||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||
textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_NEAREST_CLAMP];
|
||||
break;
|
||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||
textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_NEAREST_WRAP];
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode);
|
||||
}
|
||||
break;
|
||||
case VK_FILTER_LINEAR:
|
||||
textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_LINEAR];
|
||||
switch (cmd->data.draw.texture_address_mode) {
|
||||
case SDL_TEXTURE_ADDRESS_CLAMP:
|
||||
textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_LINEAR_CLAMP];
|
||||
break;
|
||||
case SDL_TEXTURE_ADDRESS_WRAP:
|
||||
textureSampler = rendererData->samplers[SDL_VULKAN_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", textureData->scaleMode);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,9 +23,10 @@ typedef struct SDLTest_SurfaceImage_s {
|
|||
} SDLTest_SurfaceImage_t;
|
||||
|
||||
/* Test images */
|
||||
SDL_Surface *SDLTest_ImageBlit(void);
|
||||
SDL_Surface *SDLTest_ImageBlitColor(void);
|
||||
SDL_Surface *SDLTest_ImageFace(void);
|
||||
SDL_Surface *SDLTest_ImagePrimitives(void);
|
||||
SDL_Surface *SDLTest_ImageBlendingBackground(void);
|
||||
SDL_Surface *SDLTest_ImageBlendingSprite(void);
|
||||
extern SDL_Surface *SDLTest_ImageBlit(void);
|
||||
extern SDL_Surface *SDLTest_ImageBlitColor(void);
|
||||
extern SDL_Surface *SDLTest_ImageFace(void);
|
||||
extern SDL_Surface *SDLTest_ImagePrimitives(void);
|
||||
extern SDL_Surface *SDLTest_ImageBlendingBackground(void);
|
||||
extern SDL_Surface *SDLTest_ImageBlendingSprite(void);
|
||||
extern SDL_Surface *SDLTest_ImageWrappingSprite(void);
|
||||
|
|
|
@ -1076,6 +1076,109 @@ clearScreen(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests geometry UV wrapping
|
||||
*/
|
||||
static int render_testUVWrapping(void *arg)
|
||||
{
|
||||
SDL_Vertex vertices[6];
|
||||
SDL_Vertex *verts = vertices;
|
||||
SDL_FColor color = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
float tw, th;
|
||||
SDL_FRect rect;
|
||||
float min_U = -0.5f;
|
||||
float max_U = 1.5f;
|
||||
float min_V = -0.5f;
|
||||
float max_V = 1.5f;
|
||||
SDL_Texture *tface;
|
||||
SDL_Surface *referenceSurface = NULL;
|
||||
|
||||
/* Clear surface. */
|
||||
clearScreen();
|
||||
|
||||
/* Create face surface. */
|
||||
tface = loadTestFace();
|
||||
SDLTest_AssertCheck(tface != NULL, "Verify loadTestFace() result");
|
||||
if (tface == NULL) {
|
||||
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;
|
||||
|
||||
/*
|
||||
* 0--1
|
||||
* | /|
|
||||
* |/ |
|
||||
* 3--2
|
||||
*
|
||||
* Draw sprite2 as triangles that can be recombined as rect by software renderer
|
||||
*/
|
||||
|
||||
/* 0 */
|
||||
verts->position.x = rect.x;
|
||||
verts->position.y = rect.y;
|
||||
verts->color = color;
|
||||
verts->tex_coord.x = min_U;
|
||||
verts->tex_coord.y = min_V;
|
||||
verts++;
|
||||
/* 1 */
|
||||
verts->position.x = rect.x + rect.w;
|
||||
verts->position.y = rect.y;
|
||||
verts->color = color;
|
||||
verts->tex_coord.x = max_U;
|
||||
verts->tex_coord.y = min_V;
|
||||
verts++;
|
||||
/* 2 */
|
||||
verts->position.x = rect.x + rect.w;
|
||||
verts->position.y = rect.y + rect.h;
|
||||
verts->color = color;
|
||||
verts->tex_coord.x = max_U;
|
||||
verts->tex_coord.y = max_V;
|
||||
verts++;
|
||||
/* 0 */
|
||||
verts->position.x = rect.x;
|
||||
verts->position.y = rect.y;
|
||||
verts->color = color;
|
||||
verts->tex_coord.x = min_U;
|
||||
verts->tex_coord.y = min_V;
|
||||
verts++;
|
||||
/* 2 */
|
||||
verts->position.x = rect.x + rect.w;
|
||||
verts->position.y = rect.y + rect.h;
|
||||
verts->color = color;
|
||||
verts->tex_coord.x = max_U;
|
||||
verts->tex_coord.y = max_V;
|
||||
verts++;
|
||||
/* 3 */
|
||||
verts->position.x = rect.x;
|
||||
verts->position.y = rect.y + rect.h;
|
||||
verts->color = color;
|
||||
verts->tex_coord.x = min_U;
|
||||
verts->tex_coord.y = max_V;
|
||||
verts++;
|
||||
|
||||
/* Blit sprites as triangles onto the screen */
|
||||
SDL_RenderGeometry(renderer, tface, vertices, 6, NULL, 0);
|
||||
|
||||
/* See if it's the same */
|
||||
referenceSurface = SDLTest_ImageWrappingSprite();
|
||||
compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
|
||||
|
||||
/* Make current */
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
/* Clean up. */
|
||||
SDL_DestroyTexture(tface);
|
||||
SDL_DestroySurface(referenceSurface);
|
||||
referenceSurface = NULL;
|
||||
|
||||
return TEST_COMPLETED;
|
||||
}
|
||||
|
||||
/* ================= Test References ================== */
|
||||
|
||||
/* Render test cases */
|
||||
|
@ -1115,11 +1218,15 @@ static const SDLTest_TestCaseReference renderTest9 = {
|
|||
(SDLTest_TestCaseFp)render_testLogicalSize, "render_testLogicalSize", "Tests logical size", TEST_ENABLED
|
||||
};
|
||||
|
||||
static const SDLTest_TestCaseReference renderTestUVWrapping = {
|
||||
(SDLTest_TestCaseFp)render_testUVWrapping, "render_testUVWrapping", "Tests geometry UV wrapping", TEST_ENABLED
|
||||
};
|
||||
|
||||
/* Sequence of Render test cases */
|
||||
static const SDLTest_TestCaseReference *renderTests[] = {
|
||||
&renderTest1, &renderTest2, &renderTest3, &renderTest4,
|
||||
&renderTest5, &renderTest6, &renderTest7, &renderTest8,
|
||||
&renderTest9, NULL
|
||||
&renderTest9, &renderTestUVWrapping, NULL
|
||||
};
|
||||
|
||||
/* Render test suite (global) */
|
||||
|
|
Loading…
Reference in New Issue