Make texture scale mode a part of the 2D renderer draw state

Also added texture addressing mode support to the PSP and Vita renderers (untested)

Fixes https://github.com/libsdl-org/SDL/issues/12461
This commit is contained in:
Sam Lantinga
2025-03-05 18:56:59 -08:00
parent 6e2d3c9b5d
commit cb099ebd4f
19 changed files with 477 additions and 302 deletions

View File

@@ -171,10 +171,6 @@ static void SW_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
}
static void SW_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
}
static bool SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
SW_RenderData *data = (SW_RenderData *)renderer->internal;
@@ -317,7 +313,7 @@ static bool Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *sur
static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Texture *texture,
const SDL_Rect *srcrect, const SDL_Rect *final_rect,
const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y)
const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y, const SDL_ScaleMode scaleMode)
{
SDL_Surface *src = (SDL_Surface *)texture->internal;
SDL_Rect tmp_rect;
@@ -412,7 +408,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
result = false;
} else {
SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE);
result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode);
result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, scaleMode);
SDL_DestroySurface(src_clone);
src_clone = src_scaled;
src_scaled = NULL;
@@ -429,7 +425,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, center,
&rect_dest, &cangle, &sangle);
src_rotated = SDLgfx_rotateSurface(src_clone, angle,
(texture->scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL,
(scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL,
&rect_dest, cangle, sangle, center);
if (!src_rotated) {
result = false;
@@ -460,7 +456,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
}
// Renderer scaling, if needed
result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, scaleMode);
} else {
/* The NONE blend mode requires three steps to get the pixels onto the destination surface.
* First, the area where the rotated pixels will be blitted to get set to zero.
@@ -470,7 +466,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
SDL_Rect mask_rect = tmp_rect;
SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE);
// Renderer scaling, if needed
result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, scaleMode);
if (result) {
/* The next step copies the alpha value. This is done with the BLEND blend mode and
* by modulating the source colors with 0. Since the destination is all zeros, this
@@ -479,7 +475,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
mask_rect = tmp_rect;
// Renderer scaling, if needed
result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, scaleMode);
if (result) {
/* The last step gets the color values in place. The ADD blend mode simply adds them to
* the destination (where the color values are all zero). However, because the ADD blend
@@ -492,7 +488,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te
} else {
SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
// Renderer scaling, if needed
result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, scaleMode);
SDL_DestroySurface(src_rotated_rgb);
}
}
@@ -858,7 +854,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
SDL_SetSurfaceColorMod(src, 255, 255, 255);
SDL_SetSurfaceAlphaMod(src, 255);
SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode);
SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, cmd->data.draw.texture_scale_mode);
SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod);
SDL_SetSurfaceAlphaMod(tmp, alphaMod);
@@ -869,7 +865,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
// No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy()
}
} else {
SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode);
SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, cmd->data.draw.texture_scale_mode);
}
}
break;
@@ -889,7 +885,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, &copydata->srcrect,
&copydata->dstrect, copydata->angle, &copydata->center, copydata->flip,
copydata->scale_x, copydata->scale_y);
copydata->scale_x, copydata->scale_y, cmd->data.draw.texture_scale_mode);
break;
}
@@ -1135,7 +1131,6 @@ bool SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, S
renderer->UpdateTexture = SW_UpdateTexture;
renderer->LockTexture = SW_LockTexture;
renderer->UnlockTexture = SW_UnlockTexture;
renderer->SetTextureScaleMode = SW_SetTextureScaleMode;
renderer->SetRenderTarget = SW_SetRenderTarget;
renderer->QueueSetViewport = SW_QueueNoOp;
renderer->QueueSetDrawColor = SW_QueueNoOp;