Better scaling fallbacks for the SW renderer (bug 5313)
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
diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c
index fa21932..bf66baf 100644
--- a/src/video/SDL_surface.c
+++ b/src/video/SDL_surface.c
@@ -944,33 +944,73 @@ SDL_PrivateLowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
/* fast path */
return SDL_SoftStretchLinear(src, srcrect, dst, dstrect);
} else {
- /* Use an intermediate surface */
- SDL_Surface *tmp;
+ /* Use intermediate surface(s) */
+ SDL_Surface *tmp1 = NULL;
int ret;
- SDL_Rect tmprect;
+ SDL_Rect srcrect2;
+ int is_complex_copy_flags = (src->map->info.flags & complex_copy_flags);
+
+ Uint32 flags;
Uint8 r, g, b;
Uint8 alpha;
SDL_BlendMode blendMode;
- tmp = SDL_CreateRGBSurfaceWithFormat(src->flags, dstrect->w, dstrect->h, 0, src->format->format);
-
+ /* Save source infos */
+ flags = src->flags;
SDL_GetSurfaceColorMod(src, &r, &g, &b);
SDL_GetSurfaceAlphaMod(src, &alpha);
SDL_GetSurfaceBlendMode(src, &blendMode);
+ srcrect2.x = srcrect->x;
+ srcrect2.y = srcrect->y;
+ srcrect2.w = srcrect->w;
+ srcrect2.h = srcrect->h;
+
+ /* Change source format if not appropriate for scaling */
+ if (src->format->BytesPerPixel != 4 || src->format->format == SDL_PIXELFORMAT_ARGB2101010) {
+ SDL_Rect tmprect;
+ int fmt;
+ tmprect.x = 0;
+ tmprect.y = 0;
+ tmprect.w = src->w;
+ tmprect.h = src->h;
+ if (dst->format->BytesPerPixel == 4 && dst->format->format != SDL_PIXELFORMAT_ARGB2101010) {
+ fmt = dst->format->format;
+ } else {
+ fmt = SDL_PIXELFORMAT_ARGB8888;
+ }
+ tmp1 = SDL_CreateRGBSurfaceWithFormat(flags, src->w, src->h, 0, fmt);
+ SDL_LowerBlit(src, srcrect, tmp1, &tmprect);
+
+ srcrect2.x = 0;
+ srcrect2.y = 0;
+ SDL_SetSurfaceColorMod(tmp1, r, g, b);
+ SDL_SetSurfaceAlphaMod(tmp1, alpha);
+ SDL_SetSurfaceBlendMode(tmp1, blendMode);
+
+ src = tmp1;
+ }
- SDL_SoftStretchLinear(src, srcrect, tmp, NULL);
-
- SDL_SetSurfaceColorMod(tmp, r, g, b);
- SDL_SetSurfaceAlphaMod(tmp, alpha);
- SDL_SetSurfaceBlendMode(tmp, blendMode);
-
- tmprect.x = 0;
- tmprect.y = 0;
- tmprect.w = dstrect->w;
- tmprect.h = dstrect->h;
- ret = SDL_LowerBlit(tmp, &tmprect, dst, dstrect);
-
- SDL_FreeSurface(tmp);
+ /* Intermediate scaling */
+ if (is_complex_copy_flags || src->format->format != dst->format->format) {
+ SDL_Rect tmprect;
+ SDL_Surface *tmp2 = SDL_CreateRGBSurfaceWithFormat(flags, dstrect->w, dstrect->h, 0, src->format->format);
+ SDL_SoftStretchLinear(src, &srcrect2, tmp2, NULL);
+
+ SDL_SetSurfaceColorMod(tmp2, r, g, b);
+ SDL_SetSurfaceAlphaMod(tmp2, alpha);
+ SDL_SetSurfaceBlendMode(tmp2, blendMode);
+
+ tmprect.x = 0;
+ tmprect.y = 0;
+ tmprect.w = dstrect->w;
+ tmprect.h = dstrect->h;
+ ret = SDL_LowerBlit(tmp2, &tmprect, dst, dstrect);
+ SDL_FreeSurface(tmp2);
+ } else {
+ ret = SDL_SoftStretchLinear(src, &srcrect2, dst, dstrect);
+ }
+
+ SDL_FreeSurface(tmp1);
return ret;
}
}