Fixed bug #3070 - SDL_RenderCopyEx rotation and global scaling around the wrong way (software renderer)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index f9f01fb..09e216d 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -611,12 +611,12 @@ QueueCmdCopy(SDL_Renderer *renderer, SDL_Texture * texture, const SDL_Rect * src
static int
QueueCmdCopyEx(SDL_Renderer *renderer, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
- const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
+ const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, float scale_x, float scale_y)
{
SDL_RenderCommand *cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_COPY_EX, texture);
int retval = -1;
if (cmd != NULL) {
- retval = renderer->QueueCopyEx(renderer, cmd, texture, srcquad, dstrect, angle, center, flip);
+ retval = renderer->QueueCopyEx(renderer, cmd, texture, srcquad, dstrect, angle, center, flip, scale_x, scale_y);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
@@ -3734,15 +3734,7 @@ SDL_RenderCopyExF(SDL_Renderer * renderer, SDL_Texture * texture,
renderer->scale.x, renderer->scale.y);
} else {
- real_dstrect.x *= renderer->scale.x;
- real_dstrect.y *= renderer->scale.y;
- real_dstrect.w *= renderer->scale.x;
- real_dstrect.h *= renderer->scale.y;
-
- real_center.x *= renderer->scale.x;
- real_center.y *= renderer->scale.y;
-
- retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip);
+ retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip, renderer->scale.x, renderer->scale.y);
}
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index ff38ed0..5d92f6a 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -143,7 +143,7 @@ struct SDL_Renderer
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
int (*QueueCopyEx) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
- const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
+ const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, float scale_x, float scale_y);
int (*QueueGeometry) (SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride,
int num_vertices, const void *indices, int num_indices, int size_indices,
diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c
index 961aea2..4fabcee 100644
--- a/src/render/software/SDL_render_sw.c
+++ b/src/render/software/SDL_render_sw.c
@@ -273,12 +273,14 @@ typedef struct CopyExData
double angle;
SDL_FPoint center;
SDL_RendererFlip flip;
+ float scale_x;
+ float scale_y;
} CopyExData;
static int
SW_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
- const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
+ const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, float scale_x, float scale_y)
{
CopyExData *verts = (CopyExData *) SDL_AllocateRenderVertices(renderer, sizeof (CopyExData), 0, &cmd->data.draw.first);
@@ -297,14 +299,35 @@ SW_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * te
verts->angle = angle;
SDL_memcpy(&verts->center, center, sizeof (SDL_FPoint));
verts->flip = flip;
+ verts->scale_x = scale_x;
+ verts->scale_y = scale_y;
return 0;
}
static int
+Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *surface, SDL_Rect *dstrect,
+ float scale_x, float scale_y, SDL_ScaleMode scaleMode)
+{
+ int retval;
+ /* Renderer scaling, if needed */
+ if (scale_x != 1.0f || scale_y != 1.0f) {
+ SDL_Rect r;
+ r.x = (int)((float) dstrect->x * scale_x);
+ r.y = (int)((float) dstrect->y * scale_y);
+ r.w = (int)((float) dstrect->w * scale_x);
+ r.h = (int)((float) dstrect->h * scale_y);
+ retval = SDL_PrivateUpperBlitScaled(src, srcrect, surface, &r, scaleMode);
+ } else {
+ retval = SDL_BlitSurface(src, srcrect, surface, dstrect);
+ }
+ return retval;
+}
+
+static int
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_RendererFlip flip)
+ const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip, float scale_x, float scale_y)
{
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
SDL_Rect tmp_rect;
@@ -475,7 +498,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
SDL_SetSurfaceAlphaMod(src_rotated, alphaMod);
SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
}
- retval = SDL_BlitSurface(src_rotated, NULL, surface, &tmp_rect);
+ /* Renderer scaling, if needed */
+ retval = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, texture->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.
@@ -484,7 +508,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
*/
SDL_Rect mask_rect = tmp_rect;
SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE);
- retval = SDL_BlitSurface(mask_rotated, NULL, surface, &mask_rect);
+ /* Renderer scaling, if needed */
+ retval = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
if (!retval) {
/* 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
@@ -492,7 +517,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
*/
SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
mask_rect = tmp_rect;
- retval = SDL_BlitSurface(src_rotated, NULL, surface, &mask_rect);
+ /* Renderer scaling, if needed */
+ retval = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
if (!retval) {
/* 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
@@ -508,7 +534,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
retval = -1;
} else {
SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
- retval = SDL_BlitSurface(src_rotated_rgb, NULL, surface, &tmp_rect);
+ /* Renderer scaling, if needed */
+ retval = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
SDL_FreeSurface(src_rotated_rgb);
}
}
@@ -879,7 +906,8 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
}
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, ©data->srcrect,
- ©data->dstrect, copydata->angle, ©data->center, copydata->flip);
+ ©data->dstrect, copydata->angle, ©data->center, copydata->flip,
+ copydata->scale_x, copydata->scale_y);
break;
}