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

@ -98,6 +98,21 @@ typedef enum SDL_TextureAccess
SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */ SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */
} SDL_TextureAccess; } SDL_TextureAccess;
/**
* The addressing mode for a texture when used in SDL_RenderGeometry().
*
* This affects how texture coordinates are interpreted outside of [0, 1]
*
* \since This enum is available since SDL 3.4.0.
*/
typedef enum SDL_TextureAddressMode
{
SDL_TEXTURE_ADDRESS_INVALID = -1,
SDL_TEXTURE_ADDRESS_AUTO, /**< Wrapping is enabled if texture coordinates are outside [0, 1], this is the default */
SDL_TEXTURE_ADDRESS_CLAMP, /**< Texture coordinates are clamped to the [0, 1] range */
SDL_TEXTURE_ADDRESS_WRAP, /**< The texture is repeated (tiled) */
} SDL_TextureAddressMode;
/** /**
* How the logical size is mapped to the output. * How the logical size is mapped to the output.
* *
@ -2294,6 +2309,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9GridTiled(SDL_Renderer *rende
* \since This function is available since SDL 3.2.0. * \since This function is available since SDL 3.2.0.
* *
* \sa SDL_RenderGeometryRaw * \sa SDL_RenderGeometryRaw
* \sa SDL_SetRenderTextureAddressMode
*/ */
extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
SDL_Texture *texture, SDL_Texture *texture,
@ -2326,6 +2342,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
* \since This function is available since SDL 3.2.0. * \since This function is available since SDL 3.2.0.
* *
* \sa SDL_RenderGeometry * \sa SDL_RenderGeometry
* \sa SDL_SetRenderTextureAddressMode
*/ */
extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
SDL_Texture *texture, SDL_Texture *texture,
@ -2335,6 +2352,38 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
int num_vertices, int num_vertices,
const void *indices, int num_indices, int size_indices); const void *indices, int num_indices, int size_indices);
/**
* Set the texture addressing mode used in SDL_RenderGeometry().
*
* \param renderer the rendering context.
* \param u_mode the SDL_TextureAddressMode to use for horizontal texture coordinates in SDL_RenderGeometry().
* \param v_mode the SDL_TextureAddressMode to use for vertical texture coordinates in SDL_RenderGeometry().
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_RenderGeometry
* \sa SDL_RenderGeometryRaw
* \sa SDL_GetRenderTextureAddressMode
*/
extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode u_mode, SDL_TextureAddressMode v_mode);
/**
* Get the texture addressing mode used in SDL_RenderGeometry().
*
* \param renderer the rendering context.
* \param u_mode a pointer filled in with the SDL_TextureAddressMode to use for horizontal texture coordinates in SDL_RenderGeometry(), may be NULL.
* \param v_mode a pointer filled in with the SDL_TextureAddressMode to use for vertical texture coordinates in SDL_RenderGeometry(), may be NULL.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
*
* \since This function is available since SDL 3.4.0.
*
* \sa SDL_SetRenderTextureAddressMode
*/
extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode *u_mode, SDL_TextureAddressMode *v_mode);
/** /**
* Read pixels from the current rendering target. * Read pixels from the current rendering target.
* *

View file

@ -1246,6 +1246,8 @@ SDL3_0.0.0 {
SDL_SetWindowProgressValue; SDL_SetWindowProgressValue;
SDL_GetWindowProgressState; SDL_GetWindowProgressState;
SDL_GetWindowProgressValue; SDL_GetWindowProgressValue;
SDL_SetRenderTextureAddressMode;
SDL_GetRenderTextureAddressMode;
# extra symbols go here (don't modify this line) # extra symbols go here (don't modify this line)
local: *; local: *;
}; };

View file

@ -1271,3 +1271,5 @@
#define SDL_SetWindowProgressValue SDL_SetWindowProgressValue_REAL #define SDL_SetWindowProgressValue SDL_SetWindowProgressValue_REAL
#define SDL_GetWindowProgressState SDL_GetWindowProgressState_REAL #define SDL_GetWindowProgressState SDL_GetWindowProgressState_REAL
#define SDL_GetWindowProgressValue SDL_GetWindowProgressValue_REAL #define SDL_GetWindowProgressValue SDL_GetWindowProgressValue_REAL
#define SDL_SetRenderTextureAddressMode SDL_SetRenderTextureAddressMode_REAL
#define SDL_GetRenderTextureAddressMode SDL_GetRenderTextureAddressMode_REAL

View file

@ -1279,3 +1279,5 @@ SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressState,(SDL_Window *a,SDL_ProgressState
SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressValue,(SDL_Window *a,float b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_SetWindowProgressValue,(SDL_Window *a,float b),(a,b),return)
SDL_DYNAPI_PROC(SDL_ProgressState,SDL_GetWindowProgressState,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_ProgressState,SDL_GetWindowProgressState,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(float,SDL_GetWindowProgressValue,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(float,SDL_GetWindowProgressValue,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_SetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode b,SDL_TextureAddressMode c),(a,b,c),return)
SDL_DYNAPI_PROC(bool,SDL_GetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode *b,SDL_TextureAddressMode *c),(a,b,c),return)

View file

@ -584,7 +584,8 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
if (texture) { if (texture) {
cmd->data.draw.texture_scale_mode = texture->scaleMode; cmd->data.draw.texture_scale_mode = texture->scaleMode;
} }
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP; cmd->data.draw.texture_address_mode_u = SDL_TEXTURE_ADDRESS_CLAMP;
cmd->data.draw.texture_address_mode_v = SDL_TEXTURE_ADDRESS_CLAMP;
cmd->data.draw.gpu_render_state = renderer->gpu_render_state; cmd->data.draw.gpu_render_state = renderer->gpu_render_state;
if (renderer->gpu_render_state) { if (renderer->gpu_render_state) {
renderer->gpu_render_state->last_command_generation = renderer->render_command_generation; renderer->gpu_render_state->last_command_generation = renderer->render_command_generation;
@ -727,13 +728,15 @@ static bool QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture,
const float *uv, int uv_stride, const float *uv, int uv_stride,
int num_vertices, int num_vertices,
const void *indices, int num_indices, int size_indices, const void *indices, int num_indices, int size_indices,
float scale_x, float scale_y, SDL_TextureAddressMode texture_address_mode) float scale_x, float scale_y,
SDL_TextureAddressMode texture_address_mode_u, SDL_TextureAddressMode texture_address_mode_v)
{ {
SDL_RenderCommand *cmd; SDL_RenderCommand *cmd;
bool result = false; bool result = false;
cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture); cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture);
if (cmd) { if (cmd) {
cmd->data.draw.texture_address_mode = texture_address_mode; cmd->data.draw.texture_address_mode_u = texture_address_mode_u;
cmd->data.draw.texture_address_mode_v = texture_address_mode_v;
result = renderer->QueueGeometry(renderer, cmd, texture, result = renderer->QueueGeometry(renderer, cmd, texture,
xy, xy_stride, xy, xy_stride,
color, color_stride, uv, uv_stride, color, color_stride, uv, uv_stride,
@ -3739,7 +3742,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
result = QueueCmdGeometry(renderer, NULL, result = QueueCmdGeometry(renderer, NULL,
xy, xy_stride, &renderer->color, 0 /* color_stride */, NULL, 0, xy, xy_stride, &renderer->color, 0 /* color_stride */, NULL, 0,
num_vertices, indices, num_indices, size_indices, num_vertices, indices, num_indices, size_indices,
1.0f, 1.0f, SDL_TEXTURE_ADDRESS_CLAMP); 1.0f, 1.0f, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
} }
SDL_small_free(xy, isstack1); SDL_small_free(xy, isstack1);
@ -3920,7 +3923,7 @@ static bool SDL_RenderTextureInternal(SDL_Renderer *renderer, SDL_Texture *textu
result = QueueCmdGeometry(renderer, texture, result = QueueCmdGeometry(renderer, texture,
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
num_vertices, indices, num_indices, size_indices, num_vertices, indices, num_indices, size_indices,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
} else { } else {
const SDL_FRect rect = { dstrect->x * scale_x, dstrect->y * scale_y, dstrect->w * scale_x, dstrect->h * scale_y }; const SDL_FRect rect = { dstrect->x * scale_x, dstrect->y * scale_y, dstrect->w * scale_x, dstrect->h * scale_y };
result = QueueCmdCopy(renderer, texture, srcrect, &rect); result = QueueCmdCopy(renderer, texture, srcrect, &rect);
@ -4083,7 +4086,7 @@ bool SDL_RenderTextureAffine(SDL_Renderer *renderer, SDL_Texture *texture,
&texture->color, 0 /* color_stride */, &texture->color, 0 /* color_stride */,
uv, uv_stride, uv, uv_stride,
num_vertices, indices, num_indices, size_indices, num_vertices, indices, num_indices, size_indices,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP
); );
} }
return result; return result;
@ -4233,7 +4236,7 @@ bool SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture,
result = QueueCmdGeometry(renderer, texture, result = QueueCmdGeometry(renderer, texture,
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
num_vertices, indices, num_indices, size_indices, num_vertices, indices, num_indices, size_indices,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
} else { } else {
result = QueueCmdCopyEx(renderer, texture, &real_srcrect, dstrect, angle, &real_center, flip, scale_x, scale_y); result = QueueCmdCopyEx(renderer, texture, &real_srcrect, dstrect, angle, &real_center, flip, scale_x, scale_y);
} }
@ -4285,7 +4288,8 @@ static bool SDL_RenderTextureTiled_Wrap(SDL_Renderer *renderer, SDL_Texture *tex
return QueueCmdGeometry(renderer, texture, return QueueCmdGeometry(renderer, texture,
xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride,
num_vertices, indices, num_indices, size_indices, num_vertices, indices, num_indices, size_indices,
view->current_scale.x, view->current_scale.y, SDL_TEXTURE_ADDRESS_WRAP); view->current_scale.x, view->current_scale.y,
SDL_TEXTURE_ADDRESS_WRAP, SDL_TEXTURE_ADDRESS_WRAP);
} }
static bool SDL_RenderTextureTiled_Iterate(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float scale, const SDL_FRect *dstrect) 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,
result = QueueCmdGeometry(renderer, texture, result = QueueCmdGeometry(renderer, texture,
xy, xy_stride, color, color_stride, uv, uv_stride, xy, xy_stride, color, color_stride, uv, uv_stride,
num_vertices, prev, 3, 4, num_vertices, prev, 3, 4,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
if (!result) { if (!result) {
goto end; goto end;
} }
@ -5052,7 +5056,7 @@ static bool SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer,
result = QueueCmdGeometry(renderer, texture, result = QueueCmdGeometry(renderer, texture,
xy, xy_stride, color, color_stride, uv, uv_stride, xy, xy_stride, color, color_stride, uv, uv_stride,
num_vertices, prev, 3, 4, num_vertices, prev, 3, 4,
scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP); scale_x, scale_y, SDL_TEXTURE_ADDRESS_CLAMP, SDL_TEXTURE_ADDRESS_CLAMP);
if (!result) { if (!result) {
goto end; goto end;
} }
@ -5077,7 +5081,8 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
{ {
int i; int i;
int count = indices ? num_indices : num_vertices; int count = indices ? num_indices : num_vertices;
SDL_TextureAddressMode texture_address_mode; SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
CHECK_RENDERER_MAGIC(renderer, false); CHECK_RENDERER_MAGIC(renderer, false);
@ -5132,19 +5137,39 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
texture = texture->native; texture = texture->native;
} }
texture_address_mode = renderer->texture_address_mode; texture_address_mode_u = renderer->texture_address_mode_u;
if (texture_address_mode == SDL_TEXTURE_ADDRESS_AUTO && texture) { texture_address_mode_v = renderer->texture_address_mode_v;
texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP; if (texture &&
(texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO ||
texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO)) {
for (i = 0; i < num_vertices; ++i) { for (i = 0; i < num_vertices; ++i) {
const float *uv_ = (const float *)((const char *)uv + i * uv_stride); const float *uv_ = (const float *)((const char *)uv + i * uv_stride);
float u = uv_[0]; float u = uv_[0];
float v = uv_[1]; float v = uv_[1];
if (u < 0.0f || v < 0.0f || u > 1.0f || v > 1.0f) { if (u < 0.0f || u > 1.0f) {
texture_address_mode = SDL_TEXTURE_ADDRESS_WRAP; if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO) {
texture_address_mode_u = SDL_TEXTURE_ADDRESS_WRAP;
if (texture_address_mode_v != SDL_TEXTURE_ADDRESS_AUTO) {
break; break;
} }
} }
} }
if (v < 0.0f || v > 1.0f) {
if (texture_address_mode_v == SDL_TEXTURE_ADDRESS_AUTO) {
texture_address_mode_v = SDL_TEXTURE_ADDRESS_WRAP;
if (texture_address_mode_u != SDL_TEXTURE_ADDRESS_AUTO) {
break;
}
}
}
}
if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_AUTO) {
texture_address_mode_u = SDL_TEXTURE_ADDRESS_CLAMP;
}
if (texture_address_mode_v == SDL_TEXTURE_ADDRESS_AUTO) {
texture_address_mode_v = SDL_TEXTURE_ADDRESS_CLAMP;
}
}
if (indices) { if (indices) {
for (i = 0; i < num_indices; ++i) { for (i = 0; i < num_indices; ++i) {
@ -5168,7 +5193,9 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
// For the software renderer, try to reinterpret triangles as SDL_Rect // For the software renderer, try to reinterpret triangles as SDL_Rect
#ifdef SDL_VIDEO_RENDER_SW #ifdef SDL_VIDEO_RENDER_SW
if (renderer->software && texture_address_mode == SDL_TEXTURE_ADDRESS_CLAMP) { if (renderer->software &&
texture_address_mode_u == SDL_TEXTURE_ADDRESS_CLAMP &&
texture_address_mode_v == SDL_TEXTURE_ADDRESS_CLAMP) {
return SDL_SW_RenderGeometryRaw(renderer, texture, return SDL_SW_RenderGeometryRaw(renderer, texture,
xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices,
indices, num_indices, size_indices); indices, num_indices, size_indices);
@ -5180,7 +5207,36 @@ bool SDL_RenderGeometryRaw(SDL_Renderer *renderer,
xy, xy_stride, color, color_stride, uv, uv_stride, xy, xy_stride, color, color_stride, uv, uv_stride,
num_vertices, indices, num_indices, size_indices, num_vertices, indices, num_indices, size_indices,
view->current_scale.x, view->current_scale.y, view->current_scale.x, view->current_scale.y,
texture_address_mode); texture_address_mode_u, texture_address_mode_v);
}
bool SDL_SetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode u_mode, SDL_TextureAddressMode v_mode)
{
CHECK_RENDERER_MAGIC(renderer, false);
renderer->texture_address_mode_u = u_mode;
renderer->texture_address_mode_v = v_mode;
return true;
}
bool SDL_GetRenderTextureAddressMode(SDL_Renderer *renderer, SDL_TextureAddressMode *u_mode, SDL_TextureAddressMode *v_mode)
{
if (u_mode) {
*u_mode = SDL_TEXTURE_ADDRESS_INVALID;
}
if (v_mode) {
*v_mode = SDL_TEXTURE_ADDRESS_INVALID;
}
CHECK_RENDERER_MAGIC(renderer, false);
if (u_mode) {
*u_mode = renderer->texture_address_mode_u;
}
if (v_mode) {
*v_mode = renderer->texture_address_mode_v;
}
return true;
} }
SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)

View file

@ -32,14 +32,6 @@
extern "C" { extern "C" {
#endif #endif
typedef enum SDL_TextureAddressMode
{
SDL_TEXTURE_ADDRESS_INVALID = -1,
SDL_TEXTURE_ADDRESS_AUTO,
SDL_TEXTURE_ADDRESS_CLAMP,
SDL_TEXTURE_ADDRESS_WRAP,
} SDL_TextureAddressMode;
/** /**
* A rectangle, with the origin at the upper left (double precision). * A rectangle, with the origin at the upper left (double precision).
*/ */
@ -187,7 +179,8 @@ typedef struct SDL_RenderCommand
SDL_BlendMode blend; SDL_BlendMode blend;
SDL_Texture *texture; SDL_Texture *texture;
SDL_ScaleMode texture_scale_mode; SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode; SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
SDL_GPURenderState *gpu_render_state; SDL_GPURenderState *gpu_render_state;
} draw; } draw;
struct struct
@ -312,7 +305,8 @@ struct SDL_Renderer
float color_scale; float color_scale;
SDL_FColor color; /**< Color for drawing operations values */ SDL_FColor color; /**< Color for drawing operations values */
SDL_BlendMode blendMode; /**< The drawing blend mode */ SDL_BlendMode blendMode; /**< The drawing blend mode */
SDL_TextureAddressMode texture_address_mode; SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
SDL_GPURenderState *gpu_render_state; SDL_GPURenderState *gpu_render_state;
SDL_RenderCommand *render_commands; SDL_RenderCommand *render_commands;
@ -373,6 +367,12 @@ extern SDL_RenderDriver GPU_RenderDriver;
// Clean up any renderers at shutdown // Clean up any renderers at shutdown
extern void SDL_QuitRender(void); extern void SDL_QuitRender(void);
#define RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v) \
(((scale_mode == SDL_SCALEMODE_NEAREST) << 0) | \
((address_u == SDL_TEXTURE_ADDRESS_WRAP) << 1) | \
((address_v == SDL_TEXTURE_ADDRESS_WRAP) << 2))
#define RENDER_SAMPLER_COUNT (((1 << 0) | (1 << 1) | (1 << 2)) + 1)
// Add a supported texture format to a renderer // Add a supported texture format to a renderer
extern bool SDL_AddSupportedTextureFormat(SDL_Renderer *renderer, SDL_PixelFormat format); extern bool SDL_AddSupportedTextureFormat(SDL_Renderer *renderer, SDL_PixelFormat format);

View file

@ -61,7 +61,8 @@ typedef struct
bool beginScene; bool beginScene;
bool enableSeparateAlphaBlend; bool enableSeparateAlphaBlend;
SDL_ScaleMode scaleMode[3]; SDL_ScaleMode scaleMode[3];
SDL_TextureAddressMode addressMode[3]; SDL_TextureAddressMode addressModeU[3];
SDL_TextureAddressMode addressModeV[3];
IDirect3DSurface9 *defaultRenderTarget; IDirect3DSurface9 *defaultRenderTarget;
IDirect3DSurface9 *currentRenderTarget; IDirect3DSurface9 *currentRenderTarget;
void *d3dxDLL; void *d3dxDLL;
@ -278,8 +279,11 @@ static void D3D_InitRenderState(D3D_RenderData *data)
} }
// Reset our current address mode // Reset our current address mode
for (int i = 0; i < SDL_arraysize(data->addressMode); ++i) { for (int i = 0; i < SDL_arraysize(data->addressModeU); ++i) {
data->addressMode[i] = SDL_TEXTURE_ADDRESS_INVALID; data->addressModeU[i] = SDL_TEXTURE_ADDRESS_INVALID;
}
for (int i = 0; i < SDL_arraysize(data->addressModeV); ++i) {
data->addressModeV[i] = SDL_TEXTURE_ADDRESS_INVALID;
} }
// Start the render with beginScene // Start the render with beginScene
@ -937,22 +941,28 @@ static void UpdateTextureScaleMode(D3D_RenderData *data, SDL_ScaleMode scaleMode
} }
} }
static void UpdateTextureAddressMode(D3D_RenderData *data, SDL_TextureAddressMode addressMode, unsigned index) static DWORD TranslateAddressMode(SDL_TextureAddressMode addressMode)
{ {
if (addressMode != data->addressMode[index]) {
switch (addressMode) { switch (addressMode) {
case SDL_TEXTURE_ADDRESS_CLAMP: case SDL_TEXTURE_ADDRESS_CLAMP:
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); return D3DTADDRESS_CLAMP;
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
break;
case SDL_TEXTURE_ADDRESS_WRAP: case SDL_TEXTURE_ADDRESS_WRAP:
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); return D3DTADDRESS_WRAP;
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
break;
default: default:
break; SDL_assert(!"Unknown texture address mode");
return D3DTADDRESS_CLAMP;
} }
data->addressMode[index] = addressMode; }
static void UpdateTextureAddressMode(D3D_RenderData *data, SDL_TextureAddressMode addressModeU, SDL_TextureAddressMode addressModeV, unsigned index)
{
if (addressModeU != data->addressModeU[index]) {
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, TranslateAddressMode(addressModeU));
data->addressModeU[index] = addressModeU;
}
if (addressModeV != data->addressModeV[index]) {
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, TranslateAddressMode(addressModeV));
data->addressModeV[index] = addressModeV;
} }
} }
@ -1047,15 +1057,15 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
if (texture) { if (texture) {
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 0); UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 0);
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 0); UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v, 0);
#ifdef SDL_HAVE_YUV #ifdef SDL_HAVE_YUV
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal; D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
if (texturedata && texturedata->yuv) { if (texturedata && texturedata->yuv) {
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 1); UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 1);
UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 2); UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 2);
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 1); UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v, 1);
UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 2); UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v, 2);
} }
#endif // SDL_HAVE_YUV #endif // SDL_HAVE_YUV
} }

View file

@ -50,16 +50,6 @@
/* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when /* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when
!!! FIXME: textures are needed. */ !!! 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 // Vertex shader, common values
typedef struct typedef struct
{ {
@ -178,7 +168,7 @@ typedef struct
ID3D11PixelShader *pixelShaders[NUM_SHADERS]; ID3D11PixelShader *pixelShaders[NUM_SHADERS];
int blendModesCount; int blendModesCount;
D3D11_BlendMode *blendModes; D3D11_BlendMode *blendModes;
ID3D11SamplerState *samplers[D3D11_SAMPLER_COUNT]; ID3D11SamplerState *samplers[RENDER_SAMPLER_COUNT];
D3D_FEATURE_LEVEL featureLevel; D3D_FEATURE_LEVEL featureLevel;
bool pixelSizeChanged; bool pixelSizeChanged;
@ -538,7 +528,6 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
}; };
D3D11_BUFFER_DESC constantBufferDesc; D3D11_BUFFER_DESC constantBufferDesc;
D3D11_SAMPLER_DESC samplerDesc;
D3D11_RASTERIZER_DESC rasterDesc; D3D11_RASTERIZER_DESC rasterDesc;
// See if we need debug interfaces // See if we need debug interfaces
@ -727,38 +716,6 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
goto done; 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 // Setup Direct3D rasterizer states
SDL_zero(rasterDesc); SDL_zero(rasterDesc);
rasterDesc.AntialiasedLineEnable = FALSE; rasterDesc.AntialiasedLineEnable = FALSE;
@ -2305,6 +2262,64 @@ static bool D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *
return true; 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) static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix)
{ {
SDL_Texture *texture = cmd->data.draw.texture; 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); D3D11_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (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);
case SDL_SCALEMODE_NEAREST: if (!textureSampler) {
switch (cmd->data.draw.texture_address_mode) { return false;
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);
} }
#ifdef SDL_HAVE_YUV #ifdef SDL_HAVE_YUV
if (textureData->yuv) { if (textureData->yuv) {
ID3D11ShaderResourceView *shaderResources[3]; ID3D11ShaderResourceView *shaderResources[3];

View file

@ -56,16 +56,6 @@ extern "C" {
/* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when /* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when
!!! FIXME: textures are needed. */ !!! FIXME: textures are needed. */
// Sampler types
typedef enum
{
D3D12_SAMPLER_NEAREST_CLAMP,
D3D12_SAMPLER_NEAREST_WRAP,
D3D12_SAMPLER_LINEAR_CLAMP,
D3D12_SAMPLER_LINEAR_WRAP,
D3D12_SAMPLER_COUNT
} D3D12_Sampler;
// Vertex shader, common values // Vertex shader, common values
typedef struct typedef struct
{ {
@ -231,7 +221,8 @@ typedef struct
D3D12_PipelineState *currentPipelineState; D3D12_PipelineState *currentPipelineState;
D3D12_VertexBuffer vertexBuffers[SDL_D3D12_NUM_VERTEX_BUFFERS]; D3D12_VertexBuffer vertexBuffers[SDL_D3D12_NUM_VERTEX_BUFFERS];
D3D12_CPU_DESCRIPTOR_HANDLE samplers[D3D12_SAMPLER_COUNT]; D3D12_CPU_DESCRIPTOR_HANDLE samplers[RENDER_SAMPLER_COUNT];
bool samplers_created[RENDER_SAMPLER_COUNT];
// Data for staging/allocating textures // Data for staging/allocating textures
ID3D12Resource *uploadBuffers[SDL_D3D12_NUM_UPLOAD_BUFFERS]; ID3D12Resource *uploadBuffers[SDL_D3D12_NUM_UPLOAD_BUFFERS];
@ -419,6 +410,7 @@ static void D3D12_ReleaseAll(SDL_Renderer *renderer)
D3D_SAFE_RELEASE(data->textureRTVDescriptorHeap); D3D_SAFE_RELEASE(data->textureRTVDescriptorHeap);
D3D_SAFE_RELEASE(data->srvDescriptorHeap); D3D_SAFE_RELEASE(data->srvDescriptorHeap);
D3D_SAFE_RELEASE(data->samplerDescriptorHeap); D3D_SAFE_RELEASE(data->samplerDescriptorHeap);
SDL_zeroa(data->samplers_created);
D3D_SAFE_RELEASE(data->fence); D3D_SAFE_RELEASE(data->fence);
for (i = 0; i < SDL_D3D12_NUM_BUFFERS; ++i) { for (i = 0; i < SDL_D3D12_NUM_BUFFERS; ++i) {
@ -796,7 +788,6 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
D3D12_COMMAND_QUEUE_DESC queueDesc; D3D12_COMMAND_QUEUE_DESC queueDesc;
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc; D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc;
D3D12_SAMPLER_DESC samplerDesc;
ID3D12DescriptorHeap *rootDescriptorHeaps[2]; ID3D12DescriptorHeap *rootDescriptorHeaps[2];
// See if we need debug interfaces // See if we need debug interfaces
@ -1114,31 +1105,9 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
} }
// Create samplers to use when drawing textures: // 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) == D3D12_SAMPLER_COUNT);
SDL_zero(samplerDesc);
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(data->samplerDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &data->samplers[0]); D3D_CALL_RET(data->samplerDescriptorHeap, GetCPUDescriptorHandleForHeapStart, &data->samplers[0]);
for (i = 0; i < SDL_arraysize(samplerParams); ++i) { for (i = 0; i < SDL_arraysize(data->samplers); ++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; data->samplers[i].ptr = data->samplers[0].ptr + i * data->samplerDescriptorSize;
ID3D12Device1_CreateSampler(data->d3dDevice, &samplerDesc, data->samplers[i]);
} }
// Initialize the pool allocator for SRVs // Initialize the pool allocator for SRVs
@ -2743,6 +2712,59 @@ static bool D3D12_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *
return true; return true;
} }
static D3D12_CPU_DESCRIPTOR_HANDLE *D3D12_GetSamplerState(D3D12_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_created[key]) {
D3D12_SAMPLER_DESC samplerDesc;
SDL_zero(samplerDesc);
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;
switch (scale_mode) {
case SDL_SCALEMODE_NEAREST:
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
break;
case SDL_SCALEMODE_PIXELART: // Uses linear sampling
case SDL_SCALEMODE_LINEAR:
samplerDesc.Filter = D3D12_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 = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_u);
return NULL;
}
switch (address_v) {
case SDL_TEXTURE_ADDRESS_CLAMP:
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_v);
return NULL;
}
ID3D12Device1_CreateSampler(data->d3dDevice, &samplerDesc, data->samplers[key]);
data->samplers_created[key] = true;
}
return &data->samplers[key];
}
static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix) static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix)
{ {
SDL_Texture *texture = cmd->data.draw.texture; SDL_Texture *texture = cmd->data.draw.texture;
@ -2757,35 +2779,11 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
D3D12_SetupShaderConstants(renderer, cmd, texture, &constants); D3D12_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (cmd->data.draw.texture_scale_mode) { textureSampler = D3D12_GetSamplerState(rendererData, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
case SDL_SCALEMODE_NEAREST: if (!textureSampler) {
switch (cmd->data.draw.texture_address_mode) { return false;
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = &rendererData->samplers[D3D12_SAMPLER_NEAREST_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = &rendererData->samplers[D3D12_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[D3D12_SAMPLER_LINEAR_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = &rendererData->samplers[D3D12_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);
} }
#ifdef SDL_HAVE_YUV #ifdef SDL_HAVE_YUV
if (textureData->yuv) { if (textureData->yuv) {
D3D12_CPU_DESCRIPTOR_HANDLE shaderResources[3]; D3D12_CPU_DESCRIPTOR_HANDLE shaderResources[3];

View file

@ -83,7 +83,7 @@ typedef struct GPU_RenderData
bool scissor_was_enabled; bool scissor_was_enabled;
} state; } state;
SDL_GPUSampler *samplers[3][2]; SDL_GPUSampler *samplers[RENDER_SAMPLER_COUNT];
} GPU_RenderData; } GPU_RenderData;
typedef struct GPU_TextureData typedef struct GPU_TextureData
@ -505,13 +505,6 @@ static void PushFragmentUniforms(GPU_RenderData *data, SDL_RenderCommand *cmd)
} }
} }
static SDL_GPUSampler **SamplerPointer(GPU_RenderData *data, SDL_TextureAddressMode address_mode, SDL_ScaleMode scale_mode)
{
SDL_assert(scale_mode < SDL_arraysize(data->samplers));
SDL_assert((address_mode - 1) < SDL_arraysize(data->samplers[0]));
return &data->samplers[scale_mode][address_mode - 1];
}
static void SetViewportAndScissor(GPU_RenderData *data) static void SetViewportAndScissor(GPU_RenderData *data)
{ {
SDL_SetGPUViewport(data->state.render_pass, &data->state.viewport); SDL_SetGPUViewport(data->state.render_pass, &data->state.viewport);
@ -530,6 +523,58 @@ static void SetViewportAndScissor(GPU_RenderData *data)
} }
} }
static SDL_GPUSampler *GetSampler(GPU_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]) {
SDL_GPUSamplerCreateInfo sci;
SDL_zero(sci);
switch (scale_mode) {
case SDL_SCALEMODE_NEAREST:
sci.min_filter = SDL_GPU_FILTER_NEAREST;
sci.mag_filter = SDL_GPU_FILTER_NEAREST;
sci.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
break;
case SDL_SCALEMODE_PIXELART: // Uses linear sampling
case SDL_SCALEMODE_LINEAR:
sci.min_filter = SDL_GPU_FILTER_LINEAR;
sci.mag_filter = SDL_GPU_FILTER_LINEAR;
sci.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
break;
default:
SDL_SetError("Unknown scale mode: %d", scale_mode);
return NULL;
}
switch (address_u) {
case SDL_TEXTURE_ADDRESS_CLAMP:
sci.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
sci.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_REPEAT;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_u);
return NULL;
}
switch (address_v) {
case SDL_TEXTURE_ADDRESS_CLAMP:
sci.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
sci.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_REPEAT;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_v);
return NULL;
}
sci.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
data->samplers[key] = SDL_CreateGPUSampler(data->device, &sci);
}
return data->samplers[key];
}
static void Draw( static void Draw(
GPU_RenderData *data, SDL_RenderCommand *cmd, GPU_RenderData *data, SDL_RenderCommand *cmd,
Uint32 num_verts, Uint32 num_verts,
@ -603,7 +648,7 @@ static void Draw(
GPU_TextureData *tdata = (GPU_TextureData *)cmd->data.draw.texture->internal; GPU_TextureData *tdata = (GPU_TextureData *)cmd->data.draw.texture->internal;
SDL_GPUTextureSamplerBinding sampler_bind; SDL_GPUTextureSamplerBinding sampler_bind;
SDL_zero(sampler_bind); SDL_zero(sampler_bind);
sampler_bind.sampler = *SamplerPointer(data, cmd->data.draw.texture_address_mode, cmd->data.draw.texture_scale_mode); sampler_bind.sampler = GetSampler(data, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
sampler_bind.texture = tdata->texture; sampler_bind.texture = tdata->texture;
SDL_BindGPUFragmentSamplers(pass, sampler_slot++, &sampler_bind, 1); SDL_BindGPUFragmentSamplers(pass, sampler_slot++, &sampler_bind, 1);
} }
@ -835,7 +880,8 @@ static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
SDL_Texture *thistexture = cmd->data.draw.texture; SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend; SDL_BlendMode thisblend = cmd->data.draw.blend;
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode; SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode; SDL_TextureAddressMode thisaddressmode_u = cmd->data.draw.texture_address_mode_u;
SDL_TextureAddressMode thisaddressmode_v = cmd->data.draw.texture_address_mode_v;
const SDL_RenderCommandType thiscmdtype = cmd->command; const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd; SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next; SDL_RenderCommand *nextcmd = cmd->next;
@ -848,7 +894,8 @@ static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
break; // can't go any further on this draw call, different render command up next. break; // can't go any further on this draw call, different render command up next.
} else if (nextcmd->data.draw.texture != thistexture || } else if (nextcmd->data.draw.texture != thistexture ||
nextcmd->data.draw.texture_scale_mode != thisscalemode || nextcmd->data.draw.texture_scale_mode != thisscalemode ||
nextcmd->data.draw.texture_address_mode != thisaddressmode || nextcmd->data.draw.texture_address_mode_u != thisaddressmode_u ||
nextcmd->data.draw.texture_address_mode_v != thisaddressmode_v ||
nextcmd->data.draw.blend != thisblend) { nextcmd->data.draw.blend != thisblend) {
// FIXME should we check address mode too? // FIXME should we check address mode too?
break; // can't go any further on this draw call, different texture/blendmode copy up next. break; // can't go any further on this draw call, different texture/blendmode copy up next.
@ -1080,8 +1127,8 @@ static void GPU_DestroyRenderer(SDL_Renderer *renderer)
data->state.command_buffer = NULL; data->state.command_buffer = NULL;
} }
for (Uint32 i = 0; i < sizeof(data->samplers) / sizeof(SDL_GPUSampler *); ++i) { for (Uint32 i = 0; i < SDL_arraysize(data->samplers); ++i) {
SDL_ReleaseGPUSampler(data->device, ((SDL_GPUSampler **)data->samplers)[i]); SDL_ReleaseGPUSampler(data->device, data->samplers[i]);
} }
if (data->backbuffer.texture) { if (data->backbuffer.texture) {
@ -1153,70 +1200,6 @@ static bool GPU_SetVSync(SDL_Renderer *renderer, const int vsync)
return true; return true;
} }
static bool InitSamplers(GPU_RenderData *data)
{
struct
{
struct
{
SDL_TextureAddressMode address_mode;
SDL_ScaleMode scale_mode;
} sdl;
struct
{
SDL_GPUSamplerAddressMode address_mode;
SDL_GPUFilter filter;
SDL_GPUSamplerMipmapMode mipmap_mode;
Uint32 anisotropy;
} gpu;
} configs[] = {
{
{ SDL_TEXTURE_ADDRESS_CLAMP, SDL_SCALEMODE_NEAREST },
{ SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_NEAREST, SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 0 },
},
{
{ SDL_TEXTURE_ADDRESS_CLAMP, SDL_SCALEMODE_LINEAR },
{ SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_LINEAR, SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 0 },
},
{
{ SDL_TEXTURE_ADDRESS_CLAMP, SDL_SCALEMODE_PIXELART },
{ SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_NEAREST, SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 0 },
},
{
{ SDL_TEXTURE_ADDRESS_WRAP, SDL_SCALEMODE_NEAREST },
{ SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_NEAREST, SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 0 },
},
{
{ SDL_TEXTURE_ADDRESS_WRAP, SDL_SCALEMODE_LINEAR },
{ SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_LINEAR, SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 0 },
},
{
{ SDL_TEXTURE_ADDRESS_WRAP, SDL_SCALEMODE_PIXELART },
{ SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_NEAREST, SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 0 },
},
};
for (Uint32 i = 0; i < SDL_arraysize(configs); ++i) {
SDL_GPUSamplerCreateInfo sci;
SDL_zero(sci);
sci.max_anisotropy = configs[i].gpu.anisotropy;
sci.enable_anisotropy = configs[i].gpu.anisotropy > 0;
sci.address_mode_u = sci.address_mode_v = sci.address_mode_w = configs[i].gpu.address_mode;
sci.min_filter = sci.mag_filter = configs[i].gpu.filter;
sci.mipmap_mode = configs[i].gpu.mipmap_mode;
SDL_GPUSampler *sampler = SDL_CreateGPUSampler(data->device, &sci);
if (sampler == NULL) {
return false;
}
*SamplerPointer(data, configs[i].sdl.address_mode, configs[i].sdl.scale_mode) = sampler;
}
return true;
}
static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props) static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
{ {
GPU_RenderData *data = NULL; GPU_RenderData *data = NULL;
@ -1285,10 +1268,6 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
return false; return false;
} }
if (!InitSamplers(data)) {
return false;
}
if (!SDL_ClaimWindowForGPUDevice(data->device, window)) { if (!SDL_ClaimWindowForGPUDevice(data->device, window)) {
return false; return false;
} }

View file

@ -79,16 +79,6 @@ 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_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; 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 typedef enum SDL_MetalVertexFunction
{ {
SDL_METAL_VERTEX_SOLID, SDL_METAL_VERTEX_SOLID,
@ -139,7 +129,7 @@ typedef struct METAL_ShaderPipelines
@property(nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder; @property(nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder;
@property(nonatomic, retain) id<MTLLibrary> mtllibrary; @property(nonatomic, retain) id<MTLLibrary> mtllibrary;
@property(nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer; @property(nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer;
@property(nonatomic, retain) NSMutableArray<id<MTLSamplerState>> *mtlsamplers; @property(nonatomic, retain) NSMutableDictionary<NSNumber *, id<MTLSamplerState>> *mtlsamplers;
@property(nonatomic, retain) id<MTLBuffer> mtlbufconstants; @property(nonatomic, retain) id<MTLBuffer> mtlbufconstants;
@property(nonatomic, retain) id<MTLBuffer> mtlbufquadindices; @property(nonatomic, retain) id<MTLBuffer> mtlbufquadindices;
@property(nonatomic, assign) SDL_MetalView mtlview; @property(nonatomic, assign) SDL_MetalView mtlview;
@ -1301,6 +1291,9 @@ typedef struct
__unsafe_unretained id<MTLBuffer> vertex_buffer; __unsafe_unretained id<MTLBuffer> vertex_buffer;
size_t constants_offset; size_t constants_offset;
SDL_Texture *texture; SDL_Texture *texture;
SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
bool cliprect_dirty; bool cliprect_dirty;
bool cliprect_enabled; bool cliprect_enabled;
SDL_Rect cliprect; SDL_Rect cliprect;
@ -1466,6 +1459,59 @@ static bool SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
return true; return true;
} }
static id<MTLSamplerState> GetSampler(SDL3METAL_RenderData *data, SDL_ScaleMode scale_mode, SDL_TextureAddressMode address_u, SDL_TextureAddressMode address_v)
{
NSNumber *key = [NSNumber numberWithInteger:RENDER_SAMPLER_HASHKEY(scale_mode, address_u, address_v)];
id<MTLSamplerState> mtlsampler = data.mtlsamplers[key];
if (mtlsampler == nil) {
MTLSamplerDescriptor *samplerdesc;
samplerdesc = [[MTLSamplerDescriptor alloc] init];
switch (scale_mode) {
case SDL_SCALEMODE_NEAREST:
samplerdesc.minFilter = MTLSamplerMinMagFilterNearest;
samplerdesc.magFilter = MTLSamplerMinMagFilterNearest;
break;
case SDL_SCALEMODE_PIXELART: // Uses linear sampling
case SDL_SCALEMODE_LINEAR:
samplerdesc.minFilter = MTLSamplerMinMagFilterLinear;
samplerdesc.magFilter = MTLSamplerMinMagFilterLinear;
break;
default:
SDL_SetError("Unknown scale mode: %d", scale_mode);
return nil;
}
switch (address_u) {
case SDL_TEXTURE_ADDRESS_CLAMP:
samplerdesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
samplerdesc.sAddressMode = MTLSamplerAddressModeRepeat;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_u);
return nil;
}
switch (address_v) {
case SDL_TEXTURE_ADDRESS_CLAMP:
samplerdesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
break;
case SDL_TEXTURE_ADDRESS_WRAP:
samplerdesc.tAddressMode = MTLSamplerAddressModeRepeat;
break;
default:
SDL_SetError("Unknown texture address mode: %d", address_v);
return nil;
}
mtlsampler = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc];
if (mtlsampler == nil) {
SDL_SetError("Couldn't create sampler");
return nil;
}
data.mtlsamplers[key] = mtlsampler;
}
return mtlsampler;
}
static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t constants_offset, static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t constants_offset,
id<MTLBuffer> mtlbufvertex, METAL_DrawStateCache *statecache) id<MTLBuffer> mtlbufvertex, METAL_DrawStateCache *statecache)
{ {
@ -1481,33 +1527,6 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
} }
if (texture != statecache->texture) { if (texture != statecache->texture) {
id<MTLSamplerState> mtlsampler;
if (cmd->data.draw.texture_scale_mode == 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", 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", cmd->data.draw.texture_address_mode);
}
}
[data.mtlcmdencoder setFragmentSamplerState:mtlsampler atIndex:0];
[data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0]; [data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0];
#ifdef SDL_HAVE_YUV #ifdef SDL_HAVE_YUV
if (texturedata.yuv || texturedata.nv12) { if (texturedata.yuv || texturedata.nv12) {
@ -1517,6 +1536,20 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
#endif #endif
statecache->texture = texture; statecache->texture = texture;
} }
if (cmd->data.draw.texture_scale_mode != statecache->texture_scale_mode ||
cmd->data.draw.texture_address_mode_u != statecache->texture_address_mode_u ||
cmd->data.draw.texture_address_mode_v != statecache->texture_address_mode_v) {
id<MTLSamplerState> mtlsampler = GetSampler(data, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
if (mtlsampler == nil) {
return false;
}
[data.mtlcmdencoder setFragmentSamplerState:mtlsampler atIndex:0];
statecache->texture_scale_mode = cmd->data.draw.texture_scale_mode;
statecache->texture_address_mode_u = cmd->data.draw.texture_address_mode_u;
statecache->texture_address_mode_v = cmd->data.draw.texture_address_mode_v;
}
return true; return true;
} }
@ -1537,6 +1570,9 @@ static bool METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
statecache.vertex_buffer = nil; statecache.vertex_buffer = nil;
statecache.constants_offset = CONSTANTS_OFFSET_INVALID; statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
statecache.texture = NULL; statecache.texture = NULL;
statecache.texture_scale_mode = SDL_SCALEMODE_INVALID;
statecache.texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID;
statecache.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID;
statecache.shader_constants_dirty = true; statecache.shader_constants_dirty = true;
statecache.cliprect_dirty = true; statecache.cliprect_dirty = true;
statecache.viewport_dirty = true; statecache.viewport_dirty = true;
@ -1897,7 +1933,6 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
int maxtexsize, quadcount = UINT16_MAX / 4; int maxtexsize, quadcount = UINT16_MAX / 4;
UInt16 *indexdata; UInt16 *indexdata;
size_t indicessize = sizeof(UInt16) * quadcount * 6; size_t indicessize = sizeof(UInt16) * quadcount * 6;
MTLSamplerDescriptor *samplerdesc;
id<MTLCommandQueue> mtlcmdqueue; id<MTLCommandQueue> mtlcmdqueue;
id<MTLLibrary> mtllibrary; id<MTLLibrary> mtllibrary;
id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices; id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices;
@ -2057,27 +2092,7 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
data.allpipelines = NULL; data.allpipelines = NULL;
ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm); ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm);
static struct data.mtlsamplers = [[NSMutableDictionary<NSNumber *, id<MTLSamplerState>> alloc] init];
{
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];
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]; mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];

View file

@ -149,7 +149,8 @@ typedef struct
bool vtexture_external; bool vtexture_external;
#endif #endif
SDL_ScaleMode texture_scale_mode; SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode; SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
GL_FBOList *fbo; GL_FBOList *fbo;
} GL_TextureData; } GL_TextureData;
@ -538,7 +539,8 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
data->format = format; data->format = format;
data->formattype = type; data->formattype = type;
data->texture_scale_mode = SDL_SCALEMODE_INVALID; data->texture_scale_mode = SDL_SCALEMODE_INVALID;
data->texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID; data->texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID;
data->texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID;
renderdata->glEnable(textype); renderdata->glEnable(textype);
renderdata->glBindTexture(textype, data->texture); renderdata->glBindTexture(textype, data->texture);
#ifdef SDL_PLATFORM_MACOS #ifdef SDL_PLATFORM_MACOS
@ -1099,21 +1101,23 @@ static bool SetTextureScaleMode(GL_RenderData *data, GLenum textype, SDL_ScaleMo
return true; return true;
} }
static bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode) static GLint TranslateAddressMode(SDL_TextureAddressMode addressMode)
{ {
switch (addressMode) { switch (addressMode) {
case SDL_TEXTURE_ADDRESS_CLAMP: case SDL_TEXTURE_ADDRESS_CLAMP:
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); return GL_CLAMP_TO_EDGE;
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
break;
case SDL_TEXTURE_ADDRESS_WRAP: case SDL_TEXTURE_ADDRESS_WRAP:
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_REPEAT); return GL_REPEAT;
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_REPEAT);
break;
default: default:
return SDL_SetError("Unknown texture address mode: %d", addressMode); SDL_assert(!"Unknown texture address mode");
return GL_CLAMP_TO_EDGE;
} }
return true; }
static void SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressModeU, SDL_TextureAddressMode addressModeV)
{
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, TranslateAddressMode(addressModeU));
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, TranslateAddressMode(addressModeV));
} }
static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd) static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
@ -1192,34 +1196,28 @@ static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
texturedata->texture_scale_mode = cmd->data.draw.texture_scale_mode; texturedata->texture_scale_mode = cmd->data.draw.texture_scale_mode;
} }
if (cmd->data.draw.texture_address_mode != texturedata->texture_address_mode) { if (cmd->data.draw.texture_address_mode_u != texturedata->texture_address_mode_u ||
cmd->data.draw.texture_address_mode_v != texturedata->texture_address_mode_v) {
#ifdef SDL_HAVE_YUV #ifdef SDL_HAVE_YUV
if (texturedata->yuv) { if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2); data->glActiveTextureARB(GL_TEXTURE2);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
return false;
}
data->glActiveTextureARB(GL_TEXTURE1); data->glActiveTextureARB(GL_TEXTURE1);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
return false;
}
data->glActiveTextureARB(GL_TEXTURE0_ARB); data->glActiveTextureARB(GL_TEXTURE0_ARB);
} else if (texturedata->nv12) { } else if (texturedata->nv12) {
data->glActiveTextureARB(GL_TEXTURE1); data->glActiveTextureARB(GL_TEXTURE1);
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
return false;
}
data->glActiveTextureARB(GL_TEXTURE0); data->glActiveTextureARB(GL_TEXTURE0);
} }
#endif #endif
if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
return false;
}
texturedata->texture_address_mode = cmd->data.draw.texture_address_mode; texturedata->texture_address_mode_u = cmd->data.draw.texture_address_mode_u;
texturedata->texture_address_mode_v = cmd->data.draw.texture_address_mode_v;
} }
return true; return true;
@ -1406,7 +1404,8 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
SDL_Texture *thistexture = cmd->data.draw.texture; SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend; SDL_BlendMode thisblend = cmd->data.draw.blend;
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode; SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode; SDL_TextureAddressMode thisaddressmode_u = cmd->data.draw.texture_address_mode_u;
SDL_TextureAddressMode thisaddressmode_v = cmd->data.draw.texture_address_mode_v;
const SDL_RenderCommandType thiscmdtype = cmd->command; const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd; SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next; SDL_RenderCommand *nextcmd = cmd->next;
@ -1418,7 +1417,8 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
break; // can't go any further on this draw call, different render command up next. break; // can't go any further on this draw call, different render command up next.
} else if (nextcmd->data.draw.texture != thistexture || } else if (nextcmd->data.draw.texture != thistexture ||
nextcmd->data.draw.texture_scale_mode != thisscalemode || nextcmd->data.draw.texture_scale_mode != thisscalemode ||
nextcmd->data.draw.texture_address_mode != thisaddressmode || nextcmd->data.draw.texture_address_mode_u != thisaddressmode_u ||
nextcmd->data.draw.texture_address_mode_v != thisaddressmode_v ||
nextcmd->data.draw.blend != thisblend) { nextcmd->data.draw.blend != thisblend) {
break; // can't go any further on this draw call, different texture/blendmode copy up next. break; // can't go any further on this draw call, different texture/blendmode copy up next.
} else { } else {

View file

@ -78,7 +78,8 @@ typedef struct GLES2_TextureData
#endif #endif
GLfloat texel_size[4]; GLfloat texel_size[4];
SDL_ScaleMode texture_scale_mode; SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode; SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
GLES2_FBOList *fbo; GLES2_FBOList *fbo;
} GLES2_TextureData; } GLES2_TextureData;
@ -1092,21 +1093,23 @@ static bool SetTextureScaleMode(GLES2_RenderData *data, GLenum textype, SDL_Scal
return true; return true;
} }
static bool SetTextureAddressMode(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode) static GLint TranslateAddressMode(SDL_TextureAddressMode addressMode)
{ {
switch (addressMode) { switch (addressMode) {
case SDL_TEXTURE_ADDRESS_CLAMP: case SDL_TEXTURE_ADDRESS_CLAMP:
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); return GL_CLAMP_TO_EDGE;
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
break;
case SDL_TEXTURE_ADDRESS_WRAP: case SDL_TEXTURE_ADDRESS_WRAP:
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_REPEAT); return GL_REPEAT;
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_REPEAT);
break;
default: default:
return SDL_SetError("Unknown texture address mode: %d", addressMode); SDL_assert(!"Unknown texture address mode");
return GL_CLAMP_TO_EDGE;
} }
return true; }
static void SetTextureAddressMode(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressModeU, SDL_TextureAddressMode addressModeV)
{
data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, TranslateAddressMode(addressModeU));
data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, TranslateAddressMode(addressModeV));
} }
static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, void *vertices) static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, void *vertices)
@ -1287,34 +1290,28 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
tdata->texture_scale_mode = cmd->data.draw.texture_scale_mode; tdata->texture_scale_mode = cmd->data.draw.texture_scale_mode;
} }
if (cmd->data.draw.texture_address_mode != tdata->texture_address_mode) { if (cmd->data.draw.texture_address_mode_u != tdata->texture_address_mode_u ||
cmd->data.draw.texture_address_mode_v != tdata->texture_address_mode_v) {
#ifdef SDL_HAVE_YUV #ifdef SDL_HAVE_YUV
if (tdata->yuv) { if (tdata->yuv) {
data->glActiveTexture(GL_TEXTURE2); data->glActiveTexture(GL_TEXTURE2);
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) { SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
return false;
}
data->glActiveTexture(GL_TEXTURE1); data->glActiveTexture(GL_TEXTURE1);
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) { SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
return false;
}
data->glActiveTexture(GL_TEXTURE0); data->glActiveTexture(GL_TEXTURE0);
} else if (tdata->nv12) { } else if (tdata->nv12) {
data->glActiveTexture(GL_TEXTURE1); data->glActiveTexture(GL_TEXTURE1);
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) { SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
return false;
}
data->glActiveTexture(GL_TEXTURE0); data->glActiveTexture(GL_TEXTURE0);
} }
#endif #endif
if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) { SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
return false;
}
tdata->texture_address_mode = cmd->data.draw.texture_address_mode; tdata->texture_address_mode_u = cmd->data.draw.texture_address_mode_u;
tdata->texture_address_mode_v = cmd->data.draw.texture_address_mode_v;
} }
return ret; return ret;
@ -1493,7 +1490,8 @@ static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
SDL_Texture *thistexture = cmd->data.draw.texture; SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend; SDL_BlendMode thisblend = cmd->data.draw.blend;
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode; SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode; SDL_TextureAddressMode thisaddressmode_u = cmd->data.draw.texture_address_mode_u;
SDL_TextureAddressMode thisaddressmode_v = cmd->data.draw.texture_address_mode_v;
const SDL_RenderCommandType thiscmdtype = cmd->command; const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd; SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next; SDL_RenderCommand *nextcmd = cmd->next;
@ -1505,7 +1503,8 @@ static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
break; // can't go any further on this draw call, different render command up next. break; // can't go any further on this draw call, different render command up next.
} else if (nextcmd->data.draw.texture != thistexture || } else if (nextcmd->data.draw.texture != thistexture ||
nextcmd->data.draw.texture_scale_mode != thisscalemode || nextcmd->data.draw.texture_scale_mode != thisscalemode ||
nextcmd->data.draw.texture_address_mode != thisaddressmode || nextcmd->data.draw.texture_address_mode_u != thisaddressmode_u ||
nextcmd->data.draw.texture_address_mode_v != thisaddressmode_v ||
nextcmd->data.draw.blend != thisblend) { nextcmd->data.draw.blend != thisblend) {
break; // can't go any further on this draw call, different texture/blendmode copy up next. break; // can't go any further on this draw call, different texture/blendmode copy up next.
} else { } else {
@ -1660,7 +1659,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
data->texture_v = 0; data->texture_v = 0;
#endif #endif
data->texture_scale_mode = SDL_SCALEMODE_INVALID; data->texture_scale_mode = SDL_SCALEMODE_INVALID;
data->texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID; data->texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID;
data->texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID;
// Allocate a blob for image renderdata // Allocate a blob for image renderdata
if (texture->access == SDL_TEXTUREACCESS_STREAMING) { if (texture->access == SDL_TEXTUREACCESS_STREAMING) {

View file

@ -76,7 +76,8 @@ typedef struct
int shadeModel; int shadeModel;
SDL_Texture *texture; SDL_Texture *texture;
SDL_ScaleMode texture_scale_mode; SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode; SDL_TextureAddressMode texture_address_mode_u;
SDL_TextureAddressMode texture_address_mode_v;
} PSP_BlendState; } PSP_BlendState;
typedef struct typedef struct
@ -540,20 +541,6 @@ static bool TextureShouldSwizzle(PSP_TextureData *psp_texture, SDL_Texture *text
return !((texture->access == SDL_TEXTUREACCESS_TARGET) && InVram(psp_texture->data)) && texture->access != SDL_TEXTUREACCESS_STREAMING && (texture->w >= 16 || texture->h >= 16); return !((texture->access == SDL_TEXTUREACCESS_TARGET) && InVram(psp_texture->data)) && texture->access != SDL_TEXTUREACCESS_STREAMING && (texture->w >= 16 || texture->h >= 16);
} }
static void SetTextureAddressMode(SDL_TextureAddressMode addressMode)
{
switch (addressMode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
sceGuTexWrap(GU_CLAMP, GU_CLAMP);
break;
case SDL_TEXTURE_ADDRESS_WRAP:
sceGuTexWrap(GU_REPEAT, GU_REPEAT);
break;
default:
break;
}
}
static void SetTextureScaleMode(SDL_ScaleMode scaleMode) static void SetTextureScaleMode(SDL_ScaleMode scaleMode)
{ {
switch (scaleMode) { switch (scaleMode) {
@ -569,6 +556,24 @@ static void SetTextureScaleMode(SDL_ScaleMode scaleMode)
} }
} }
static int TranslateAddressMode(SDL_TextureAddressMode mode)
{
switch (mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
return GU_CLAMP;
case SDL_TEXTURE_ADDRESS_WRAP:
return GU_REPEAT;
default:
SDL_assert(!"Unknown texture address mode");
return GU_CLAMP;
}
}
static void SetTextureAddressMode(SDL_TextureAddressMode addressModeU, SDL_TextureAddressMode addressModeV)
{
sceGuTexWrap(TranslateAddressMode(addressModeU), TranslateAddressMode(addressModeV));
}
static void TextureActivate(SDL_Texture *texture) static void TextureActivate(SDL_Texture *texture)
{ {
PSP_TextureData *psp_texture = (PSP_TextureData *)texture->internal; PSP_TextureData *psp_texture = (PSP_TextureData *)texture->internal;
@ -1058,7 +1063,7 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
if (state->texture) { if (state->texture) {
SetTextureScaleMode(state->texture_scale_mode); SetTextureScaleMode(state->texture_scale_mode);
SetTextureAddressMode(state->texture_address_mode); SetTextureAddressMode(state->texture_address_mode_u, state->texture_address_mode_v);
} }
*current = *state; *current = *state;
@ -1145,7 +1150,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
.color = drawstate.color, .color = drawstate.color,
.texture = NULL, .texture = NULL,
.texture_scale_mode = SDL_SCALEMODE_INVALID, .texture_scale_mode = SDL_SCALEMODE_INVALID,
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID, .texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID,
.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID,
.mode = cmd->data.draw.blend, .mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT .shadeModel = GU_FLAT
}; };
@ -1162,7 +1168,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
.color = drawstate.color, .color = drawstate.color,
.texture = NULL, .texture = NULL,
.texture_scale_mode = SDL_SCALEMODE_INVALID, .texture_scale_mode = SDL_SCALEMODE_INVALID,
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID, .texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID,
.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID,
.mode = cmd->data.draw.blend, .mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT .shadeModel = GU_FLAT
}; };
@ -1179,7 +1186,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
.color = drawstate.color, .color = drawstate.color,
.texture = NULL, .texture = NULL,
.texture_scale_mode = SDL_SCALEMODE_INVALID, .texture_scale_mode = SDL_SCALEMODE_INVALID,
.texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID, .texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID,
.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID,
.mode = cmd->data.draw.blend, .mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT .shadeModel = GU_FLAT
}; };
@ -1196,7 +1204,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
.color = drawstate.color, .color = drawstate.color,
.texture = cmd->data.draw.texture, .texture = cmd->data.draw.texture,
.texture_scale_mode = cmd->data.draw.texture_scale_mode, .texture_scale_mode = cmd->data.draw.texture_scale_mode,
.texture_address_mode = cmd->data.draw.texture_address_mode, .texture_address_mode_u = cmd->data.draw.texture_address_mode_u,
.texture_address_mode_v = cmd->data.draw.texture_address_mode_v,
.mode = cmd->data.draw.blend, .mode = cmd->data.draw.blend,
.shadeModel = GU_SMOOTH .shadeModel = GU_SMOOTH
}; };
@ -1212,7 +1221,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
.color = drawstate.color, .color = drawstate.color,
.texture = cmd->data.draw.texture, .texture = cmd->data.draw.texture,
.texture_scale_mode = cmd->data.draw.texture_scale_mode, .texture_scale_mode = cmd->data.draw.texture_scale_mode,
.texture_address_mode = cmd->data.draw.texture_address_mode, .texture_address_mode_u = cmd->data.draw.texture_address_mode_u,
.texture_address_mode_v = cmd->data.draw.texture_address_mode_v,
.mode = cmd->data.draw.blend, .mode = cmd->data.draw.blend,
.shadeModel = GU_SMOOTH .shadeModel = GU_SMOOTH
}; };
@ -1236,7 +1246,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
.color = drawstate.color, .color = drawstate.color,
.texture = cmd->data.draw.texture, .texture = cmd->data.draw.texture,
.texture_scale_mode = cmd->data.draw.texture_scale_mode, .texture_scale_mode = cmd->data.draw.texture_scale_mode,
.texture_address_mode = cmd->data.draw.texture_address_mode, .texture_address_mode_u = cmd->data.draw.texture_address_mode_u,
.texture_address_mode_v = cmd->data.draw.texture_address_mode_v,
.mode = cmd->data.draw.blend, .mode = cmd->data.draw.blend,
.shadeModel = GU_SMOOTH .shadeModel = GU_SMOOTH
}; };

View file

@ -925,7 +925,8 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
surface, surface,
&(ptr[0].dst), &(ptr[1].dst), &(ptr[2].dst), &(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); cmd->data.draw.texture_address_mode_u,
cmd->data.draw.texture_address_mode_v);
} }
} else { } else {
GeometryFillData *ptr = (GeometryFillData *)verts; GeometryFillData *ptr = (GeometryFillData *)verts;

View file

@ -42,7 +42,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, 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 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, 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, bool is_uniform, SDL_TextureAddressMode texture_address_mode); SDL_Color c0, SDL_Color c1, SDL_Color c2, bool is_uniform,
SDL_TextureAddressMode texture_address_mode_u,
SDL_TextureAddressMode texture_address_mode_v);
#if 0 #if 0
bool SDL_BlitTriangle(SDL_Surface *src, const SDL_Point srcpoints[3], SDL_Surface *dst, const SDL_Point dstpoints[3]) bool SDL_BlitTriangle(SDL_Surface *src, const SDL_Point srcpoints[3], SDL_Surface *dst, const SDL_Point dstpoints[3])
@ -184,11 +186,13 @@ static void bounding_rect(const SDL_Point *a, const SDL_Point *b, const SDL_Poin
#define TRIANGLE_GET_TEXTCOORD \ #define TRIANGLE_GET_TEXTCOORD \
int srcx = (int)(((Sint64)w0 * s2s0_x + (Sint64)w1 * s2s1_x + s2_x_area.x) / area); \ 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) { \ if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_WRAP) { \
srcx %= src_surface->w; \ srcx %= src_surface->w; \
if (srcx < 0) { \ if (srcx < 0) { \
srcx += (src_surface->w - 1); \ srcx += (src_surface->w - 1); \
} \ } \
} \
if (texture_address_mode_v == SDL_TEXTURE_ADDRESS_WRAP) { \
srcy %= src_surface->h; \ srcy %= src_surface->h; \
if (srcy < 0) { \ if (srcy < 0) { \
srcy += (src_surface->h - 1); \ srcy += (src_surface->h - 1); \
@ -465,7 +469,8 @@ bool SDL_SW_BlitTriangle(
SDL_Surface *dst, SDL_Surface *dst,
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, 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_TextureAddressMode texture_address_mode_u,
SDL_TextureAddressMode texture_address_mode_v)
{ {
bool result = true; bool result = true;
SDL_Surface *src_surface = src; SDL_Surface *src_surface = src;
@ -539,12 +544,12 @@ bool SDL_SW_BlitTriangle(
SDL_GetSurfaceBlendMode(src, &blend); SDL_GetSurfaceBlendMode(src, &blend);
// TRIANGLE_GET_TEXTCOORD interpolates up to the max values included, so reduce by 1 // TRIANGLE_GET_TEXTCOORD interpolates up to the max values included, so reduce by 1
if (texture_address_mode == SDL_TEXTURE_ADDRESS_CLAMP) { if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_CLAMP ||
texture_address_mode_v == SDL_TEXTURE_ADDRESS_CLAMP) {
SDL_Rect srcrect; SDL_Rect srcrect;
int maxx, maxy;
bounding_rect(s0, s1, s2, &srcrect); bounding_rect(s0, s1, s2, &srcrect);
maxx = srcrect.x + srcrect.w; if (texture_address_mode_u == SDL_TEXTURE_ADDRESS_CLAMP) {
maxy = srcrect.y + srcrect.h; int maxx = srcrect.x + srcrect.w;
if (srcrect.w > 0) { if (srcrect.w > 0) {
if (s0->x == maxx) { if (s0->x == maxx) {
s0->x--; s0->x--;
@ -556,6 +561,9 @@ bool SDL_SW_BlitTriangle(
s2->x--; s2->x--;
} }
} }
}
if (texture_address_mode_v == SDL_TEXTURE_ADDRESS_CLAMP) {
int maxy = srcrect.y + srcrect.h;
if (srcrect.h > 0) { if (srcrect.h > 0) {
if (s0->y == maxy) { if (s0->y == maxy) {
s0->y--; s0->y--;
@ -568,6 +576,7 @@ bool SDL_SW_BlitTriangle(
} }
} }
} }
}
if (is_uniform) { if (is_uniform) {
// SDL_GetSurfaceColorMod(src, &r, &g, &b); // SDL_GetSurfaceColorMod(src, &r, &g, &b);
@ -716,7 +725,7 @@ bool SDL_SW_BlitTriangle(
SDL_BlitTriangle_Slow(&tmp_info, s2_x_area, dstrect, (int)area, bias_w0, bias_w1, bias_w2, 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, 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, s2s0_x, s2s1_x, s2s0_y, s2s1_y, (int)w0_row, (int)w1_row, (int)w2_row,
c0, c1, c2, is_uniform, texture_address_mode); c0, c1, c2, is_uniform, texture_address_mode_u, texture_address_mode_v);
goto end; goto end;
} }
@ -788,7 +797,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, 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 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, 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, bool is_uniform, SDL_TextureAddressMode texture_address_mode) SDL_Color c0, SDL_Color c1, SDL_Color c2, bool is_uniform,
SDL_TextureAddressMode texture_address_mode_u,
SDL_TextureAddressMode texture_address_mode_v)
{ {
SDL_Surface *src_surface = info->src_surface; SDL_Surface *src_surface = info->src_surface;
const int flags = info->flags; const int flags = info->flags;

View file

@ -24,8 +24,6 @@
#include "SDL_internal.h" #include "SDL_internal.h"
#include "../SDL_sysrender.h" // For SDL_TextureAddressMode
extern bool SDL_SW_FillTriangle(SDL_Surface *dst, extern bool SDL_SW_FillTriangle(SDL_Surface *dst,
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, SDL_Point *d0, SDL_Point *d1, SDL_Point *d2,
SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2); SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2);
@ -35,7 +33,8 @@ extern bool SDL_SW_BlitTriangle(SDL_Surface *src,
SDL_Surface *dst, SDL_Surface *dst,
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, 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_TextureAddressMode texture_address_mode_u,
SDL_TextureAddressMode texture_address_mode_v);
extern void trianglepoint_2_fixedpoint(SDL_Point *a); extern void trianglepoint_2_fixedpoint(SDL_Point *a);

View file

@ -293,7 +293,8 @@ static bool VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
} }
vita_texture->scale_mode = SDL_SCALEMODE_INVALID; vita_texture->scale_mode = SDL_SCALEMODE_INVALID;
vita_texture->address_mode = SDL_TEXTURE_ADDRESS_INVALID; vita_texture->address_mode_u = SDL_TEXTURE_ADDRESS_INVALID;
vita_texture->address_mode_v = SDL_TEXTURE_ADDRESS_INVALID;
texture->internal = vita_texture; texture->internal = vita_texture;
@ -806,6 +807,19 @@ static bool VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
return true; return true;
} }
static SceGxmTextureAddrMode TranslateAddressMode(SDL_TextureAddressMode mode)
{
switch (mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
return SCE_GXM_TEXTURE_ADDR_CLAMP;
case SDL_TEXTURE_ADDRESS_WRAP:
return SCE_GXM_TEXTURE_ADDR_REPEAT;
default:
SDL_assert(!"Unknown texture address mode");
return SCE_GXM_TEXTURE_ADDR_CLAMP;
}
}
static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd) static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
{ {
SDL_Texture *texture = cmd->data.draw.texture; SDL_Texture *texture = cmd->data.draw.texture;
@ -906,18 +920,13 @@ static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd
vita_texture->scale_mode = cmd->data.draw.texture_scale_mode; vita_texture->scale_mode = cmd->data.draw.texture_scale_mode;
} }
if (cmd->data.draw.texture_address_mode != vita_texture->address_mode) { if (cmd->data.draw.texture_address_mode_u != vita_texture->address_mode_u ||
switch (cmd->data.draw.texture_address_mode) { cmd->data.draw.texture_address_mode_v != vita_texture->address_mode_v) {
case SDL_TEXTURE_ADDRESS_CLAMP: SceGxmTextureAddrMode mode_u = TranslateAddressMode(cmd->data.draw.texture_address_mode_u);
gxm_texture_set_address_mode(vita_texture->tex, SCE_GXM_TEXTURE_ADDR_CLAMP, SCE_GXM_TEXTURE_ADDR_CLAMP); SceGxmTextureAddrMode mode_v = TranslateAddressMode(cmd->data.draw.texture_address_mode_v);
break; gxm_texture_set_address_mode(vita_texture->tex, mode_u, mode_v);
case SDL_TEXTURE_ADDRESS_WRAP: vita_texture->address_mode_u = cmd->data.draw.texture_address_mode_u;
gxm_texture_set_address_mode(vita_texture->tex, SCE_GXM_TEXTURE_ADDR_REPEAT, SCE_GXM_TEXTURE_ADDR_REPEAT); vita_texture->address_mode_v = cmd->data.draw.texture_address_mode_v;
break;
default:
break;
}
vita_texture->address_mode = cmd->data.draw.texture_address_mode;
} }
} }

View file

@ -206,7 +206,8 @@ typedef struct
bool yuv; bool yuv;
bool nv12; bool nv12;
SDL_ScaleMode scale_mode; SDL_ScaleMode scale_mode;
SDL_TextureAddressMode address_mode; SDL_TextureAddressMode address_mode_u;
SDL_TextureAddressMode address_mode_v;
} VITA_GXM_TextureData; } VITA_GXM_TextureData;
#endif // SDL_RENDER_VITA_GXM_TYPES_H #endif // SDL_RENDER_VITA_GXM_TYPES_H

View file

@ -169,16 +169,6 @@ typedef enum {
VULKAN_RENDERPASS_COUNT VULKAN_RENDERPASS_COUNT
} VULKAN_RenderPass; } VULKAN_RenderPass;
// Sampler types
typedef enum
{
VULKAN_SAMPLER_NEAREST_CLAMP,
VULKAN_SAMPLER_NEAREST_WRAP,
VULKAN_SAMPLER_LINEAR_CLAMP,
VULKAN_SAMPLER_LINEAR_WRAP,
VULKAN_SAMPLER_COUNT
} VULKAN_Sampler;
// Vertex shader, common values // Vertex shader, common values
typedef struct typedef struct
{ {
@ -196,15 +186,6 @@ static const float INPUTTYPE_SRGB = 1;
static const float INPUTTYPE_SCRGB = 2; static const float INPUTTYPE_SCRGB = 2;
static const float INPUTTYPE_HDR10 = 3; 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 // Pixel shader constants, common values
typedef struct typedef struct
{ {
@ -347,7 +328,7 @@ typedef struct
uint32_t currentConstantBufferIndex; uint32_t currentConstantBufferIndex;
int32_t currentConstantBufferOffset; int32_t currentConstantBufferOffset;
VkSampler samplers[VULKAN_SAMPLER_COUNT]; VkSampler samplers[RENDER_SAMPLER_COUNT];
VkDescriptorPool **descriptorPools; VkDescriptorPool **descriptorPools;
uint32_t *numDescriptorPools; uint32_t *numDescriptorPools;
uint32_t currentDescriptorPoolIndex; uint32_t currentDescriptorPoolIndex;
@ -1950,42 +1931,6 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
VULKAN_CreateVertexBuffer(rendererData, i, SDL_VULKAN_VERTEX_BUFFER_DEFAULT_SIZE); VULKAN_CreateVertexBuffer(rendererData, i, SDL_VULKAN_VERTEX_BUFFER_DEFAULT_SIZE);
} }
// 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) == VULKAN_SAMPLER_COUNT);
VkSamplerCreateInfo samplerCreateInfo = { 0 };
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
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;
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);
SET_ERROR_CODE("vkCreateSampler()", result);
return result;
}
}
}
SDL_PropertiesID props = SDL_GetRendererProperties(renderer); SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER, rendererData->instance); SDL_SetPointerProperty(props, SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER, rendererData->instance);
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER, (Sint64)rendererData->surface); SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER, (Sint64)rendererData->surface);
@ -3762,6 +3707,42 @@ static bool VULKAN_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand
return true; return true;
} }
static VkSampler VULKAN_GetSampler(VULKAN_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]) {
VkSamplerCreateInfo samplerCreateInfo = { 0 };
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
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;
switch (scale_mode) {
case SDL_SCALEMODE_NEAREST:
samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
break;
case SDL_SCALEMODE_PIXELART: // Uses linear sampling
case SDL_SCALEMODE_LINEAR:
samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
break;
default:
SDL_SetError("Unknown scale mode: %d", scale_mode);
return VK_NULL_HANDLE;
}
VkResult result = vkCreateSampler(data->device, &samplerCreateInfo, NULL, &data->samplers[key]);
if (result != VK_SUCCESS) {
SET_ERROR_CODE("vkCreateSampler()", result);
return false;
}
}
return data->samplers[key];
}
static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix, VULKAN_DrawStateCache *stateCache) static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const Float4X4 *matrix, VULKAN_DrawStateCache *stateCache)
{ {
@ -3775,34 +3756,9 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants); VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (cmd->data.draw.texture_scale_mode) { textureSampler = VULKAN_GetSampler(rendererData, cmd->data.draw.texture_scale_mode, cmd->data.draw.texture_address_mode_u, cmd->data.draw.texture_address_mode_v);
case SDL_SCALEMODE_NEAREST: if (textureSampler == VK_NULL_HANDLE) {
switch (cmd->data.draw.texture_address_mode) { return false;
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_NEAREST_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = rendererData->samplers[VULKAN_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[VULKAN_SAMPLER_LINEAR_CLAMP];
break;
case SDL_TEXTURE_ADDRESS_WRAP:
textureSampler = rendererData->samplers[VULKAN_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);
} }
if (textureData->mainImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { if (textureData->mainImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {