Simple Directmedia Layer

SDL_SoftStretch() doesn't handle large pixel formats

Fixes https://github.com/libsdl-org/SDL/issues/11534

+65 -1
+2 -1
src/video/SDL_surface.c
··· 1254 1254 if (scaleMode == SDL_SCALEMODE_NEAREST) { 1255 1255 if (!(src->map.info.flags & complex_copy_flags) && 1256 1256 src->format == dst->format && 1257 - !SDL_ISPIXELFORMAT_INDEXED(src->format)) { 1257 + !SDL_ISPIXELFORMAT_INDEXED(src->format) && 1258 + SDL_BYTESPERPIXEL(src->format) <= 4) { 1258 1259 return SDL_SoftStretch(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST); 1259 1260 } else if (SDL_BITSPERPIXEL(src->format) < 8) { 1260 1261 // Scaling bitmap not yet supported, convert to RGBA for blit
+63
test/testautomation_surface.c
··· 1479 1479 } 1480 1480 1481 1481 1482 + static int SDLCALL surface_testScale(void *arg) 1483 + { 1484 + SDL_PixelFormat formats[] = { 1485 + SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_RGBA8888, 1486 + SDL_PIXELFORMAT_ARGB2101010, SDL_PIXELFORMAT_ABGR2101010, 1487 + SDL_PIXELFORMAT_ARGB64, SDL_PIXELFORMAT_RGBA64, 1488 + SDL_PIXELFORMAT_ARGB128_FLOAT, SDL_PIXELFORMAT_RGBA128_FLOAT, 1489 + }; 1490 + SDL_ScaleMode modes[] = { 1491 + SDL_SCALEMODE_NEAREST, SDL_SCALEMODE_LINEAR 1492 + }; 1493 + SDL_Surface *surface, *result; 1494 + SDL_PixelFormat format; 1495 + SDL_ScaleMode mode; 1496 + const float MAXIMUM_ERROR = 0.0001f; 1497 + float srcR = 10 / 255.0f, srcG = 128 / 255.0f, srcB = 240 / 255.0f, srcA = 170 / 255.0f; 1498 + float actualR, actualG, actualB, actualA; 1499 + float deltaR, deltaG, deltaB, deltaA; 1500 + int i, j, ret; 1501 + 1502 + for (i = 0; i < SDL_arraysize(formats); ++i) { 1503 + for (j = 0; j < SDL_arraysize(modes); ++j) { 1504 + format = formats[i]; 1505 + mode = modes[j]; 1506 + 1507 + surface = SDL_CreateSurface(1, 1, format); 1508 + SDLTest_AssertCheck(surface != NULL, "SDL_CreateSurface()"); 1509 + ret = SDL_SetSurfaceColorspace(surface, SDL_COLORSPACE_SRGB); 1510 + SDLTest_AssertCheck(ret == true, "SDL_SetSurfaceColorspace()"); 1511 + ret = SDL_ClearSurface(surface, srcR, srcG, srcB, srcA); 1512 + SDLTest_AssertCheck(ret == true, "SDL_ClearSurface()"); 1513 + result = SDL_ScaleSurface(surface, 2, 2, mode); 1514 + SDLTest_AssertCheck(ret == true, "SDL_PremultiplySurfaceAlpha()"); 1515 + ret = SDL_ReadSurfacePixelFloat(result, 1, 1, &actualR, &actualG, &actualB, &actualA); 1516 + SDLTest_AssertCheck(ret == true, "SDL_ReadSurfacePixelFloat()"); 1517 + deltaR = SDL_fabsf(actualR - srcR); 1518 + deltaG = SDL_fabsf(actualG - srcG); 1519 + deltaB = SDL_fabsf(actualB - srcB); 1520 + deltaA = SDL_fabsf(actualA - srcA); 1521 + SDLTest_AssertCheck( 1522 + deltaR <= MAXIMUM_ERROR && 1523 + deltaG <= MAXIMUM_ERROR && 1524 + deltaB <= MAXIMUM_ERROR && 1525 + deltaA <= MAXIMUM_ERROR, 1526 + "Checking %s %s scaling results, expected %.4f,%.4f,%.4f,%.4f got %.4f,%.4f,%.4f,%.4f", 1527 + SDL_GetPixelFormatName(format), 1528 + mode == SDL_SCALEMODE_NEAREST ? "nearest" : "linear", 1529 + srcR, srcG, srcB, srcA, actualR, actualG, actualB, actualA); 1530 + 1531 + SDL_DestroySurface(surface); 1532 + SDL_DestroySurface(result); 1533 + } 1534 + } 1535 + 1536 + return TEST_COMPLETED; 1537 + } 1538 + 1539 + 1482 1540 /* ================= Test References ================== */ 1483 1541 1484 1542 /* Surface test cases */ ··· 1574 1632 surface_testPremultiplyAlpha, "surface_testPremultiplyAlpha", "Test alpha premultiply operations.", TEST_ENABLED 1575 1633 }; 1576 1634 1635 + static const SDLTest_TestCaseReference surfaceTestScale = { 1636 + surface_testScale, "surface_testScale", "Test scaling operations.", TEST_ENABLED 1637 + }; 1638 + 1577 1639 /* Sequence of Surface test cases */ 1578 1640 static const SDLTest_TestCaseReference *surfaceTests[] = { 1579 1641 &surfaceTestSaveLoadBitmap, ··· 1599 1661 &surfaceTestPalettization, 1600 1662 &surfaceTestClearSurface, 1601 1663 &surfaceTestPremultiplyAlpha, 1664 + &surfaceTestScale, 1602 1665 NULL 1603 1666 }; 1604 1667