diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 71fa9ceb07..f6e4f5e252 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -1254,7 +1254,8 @@ bool SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, S if (scaleMode == SDL_SCALEMODE_NEAREST) { if (!(src->map.info.flags & complex_copy_flags) && src->format == dst->format && - !SDL_ISPIXELFORMAT_INDEXED(src->format)) { + !SDL_ISPIXELFORMAT_INDEXED(src->format) && + SDL_BYTESPERPIXEL(src->format) <= 4) { return SDL_SoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST); } else if (SDL_BITSPERPIXEL(src->format) < 8) { // Scaling bitmap not yet supported, convert to RGBA for blit diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index 7ba11caac4..c1d641eef6 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -1479,6 +1479,64 @@ static int SDLCALL surface_testPremultiplyAlpha(void *arg) } +static int SDLCALL surface_testScale(void *arg) +{ + SDL_PixelFormat formats[] = { + SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_RGBA8888, + SDL_PIXELFORMAT_ARGB2101010, SDL_PIXELFORMAT_ABGR2101010, + SDL_PIXELFORMAT_ARGB64, SDL_PIXELFORMAT_RGBA64, + SDL_PIXELFORMAT_ARGB128_FLOAT, SDL_PIXELFORMAT_RGBA128_FLOAT, + }; + SDL_ScaleMode modes[] = { + SDL_SCALEMODE_NEAREST, SDL_SCALEMODE_LINEAR + }; + SDL_Surface *surface, *result; + SDL_PixelFormat format; + SDL_ScaleMode mode; + const float MAXIMUM_ERROR = 0.0001f; + float srcR = 10 / 255.0f, srcG = 128 / 255.0f, srcB = 240 / 255.0f, srcA = 170 / 255.0f; + float actualR, actualG, actualB, actualA; + float deltaR, deltaG, deltaB, deltaA; + int i, j, ret; + + for (i = 0; i < SDL_arraysize(formats); ++i) { + for (j = 0; j < SDL_arraysize(modes); ++j) { + format = formats[i]; + mode = modes[j]; + + surface = SDL_CreateSurface(1, 1, format); + SDLTest_AssertCheck(surface != NULL, "SDL_CreateSurface()"); + ret = SDL_SetSurfaceColorspace(surface, SDL_COLORSPACE_SRGB); + SDLTest_AssertCheck(ret == true, "SDL_SetSurfaceColorspace()"); + ret = SDL_ClearSurface(surface, srcR, srcG, srcB, srcA); + SDLTest_AssertCheck(ret == true, "SDL_ClearSurface()"); + result = SDL_ScaleSurface(surface, 2, 2, mode); + SDLTest_AssertCheck(ret == true, "SDL_PremultiplySurfaceAlpha()"); + ret = SDL_ReadSurfacePixelFloat(result, 1, 1, &actualR, &actualG, &actualB, &actualA); + SDLTest_AssertCheck(ret == true, "SDL_ReadSurfacePixelFloat()"); + deltaR = SDL_fabsf(actualR - srcR); + deltaG = SDL_fabsf(actualG - srcG); + deltaB = SDL_fabsf(actualB - srcB); + deltaA = SDL_fabsf(actualA - srcA); + SDLTest_AssertCheck( + deltaR <= MAXIMUM_ERROR && + deltaG <= MAXIMUM_ERROR && + deltaB <= MAXIMUM_ERROR && + deltaA <= MAXIMUM_ERROR, + "Checking %s %s scaling results, expected %.4f,%.4f,%.4f,%.4f got %.4f,%.4f,%.4f,%.4f", + SDL_GetPixelFormatName(format), + mode == SDL_SCALEMODE_NEAREST ? "nearest" : "linear", + srcR, srcG, srcB, srcA, actualR, actualG, actualB, actualA); + + SDL_DestroySurface(surface); + SDL_DestroySurface(result); + } + } + + return TEST_COMPLETED; +} + + /* ================= Test References ================== */ /* Surface test cases */ @@ -1574,6 +1632,10 @@ static const SDLTest_TestCaseReference surfaceTestPremultiplyAlpha = { surface_testPremultiplyAlpha, "surface_testPremultiplyAlpha", "Test alpha premultiply operations.", TEST_ENABLED }; +static const SDLTest_TestCaseReference surfaceTestScale = { + surface_testScale, "surface_testScale", "Test scaling operations.", TEST_ENABLED +}; + /* Sequence of Surface test cases */ static const SDLTest_TestCaseReference *surfaceTests[] = { &surfaceTestSaveLoadBitmap, @@ -1599,6 +1661,7 @@ static const SDLTest_TestCaseReference *surfaceTests[] = { &surfaceTestPalettization, &surfaceTestClearSurface, &surfaceTestPremultiplyAlpha, + &surfaceTestScale, NULL };