perf(texture): cap and downscale theme images on load
Theme images were decoded straight to RGBA at their full source size and uploaded to a GPU texture as-is. A large or over-sized image wasted VRAM and could exceed the GL maximum texture size, and each code path also hand-managed the decoded pixel buffer with its own free calls. - Loading from file and from memory now goes through the shared size-aware decoder with a 2048-pixel cap on the long side. An image larger than that is downscaled with its aspect ratio kept; an image whose area is absurd is rejected; a small image is left untouched. - The decoder owns the pixel buffer for the life of the upload, so the manual free calls are gone. Tests cover downscaling a wide image to a 2048 long side with the aspect kept, rejecting an over-area image, and leaving an under-cap image as-is, plus the fit-dims math at the theme-art cap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -9678,6 +9678,8 @@ void testImageDecodePolicy()
|
||||
EXPECT_EQ(dw, 250); EXPECT_EQ(dh, 125);
|
||||
util::FitImageDims(100, 50, 250, &dw, &dh); // already small: unchanged
|
||||
EXPECT_EQ(dw, 100); EXPECT_EQ(dh, 50);
|
||||
util::FitImageDims(5000, 100, 2048, &dw, &dh); // theme-art cap
|
||||
EXPECT_EQ(dw, 2048); EXPECT_EQ(dh, 40); // truncating arithmetic (40.96)
|
||||
|
||||
const util::ImageLimits lim;
|
||||
EXPECT_TRUE(util::DimsWithinLimits(4000, 3000, false, lim)); // 12 MP photo
|
||||
@@ -9772,6 +9774,20 @@ void testImageDecodeCore()
|
||||
EXPECT_EQ(af.w, 3); EXPECT_EQ(af.h, 2);
|
||||
EXPECT_FALSE(af.animated);
|
||||
}
|
||||
// Theme-art cap (texture_loader): a >2048 still downscales to a 2048 long side with aspect kept; over-area is rejected.
|
||||
{
|
||||
util::ImageLimits tl; tl.stillMax = 2048; tl.animMax = 2048;
|
||||
auto wide = imgTestBmp(5000, 100, true);
|
||||
EXPECT_TRUE(util::DecodeAnimatedFromMemory(wide.data(), wide.size(), 1, tl, nullptr, af) == util::ImageStatus::Ok);
|
||||
EXPECT_EQ(af.w, 2048);
|
||||
EXPECT_TRUE(std::abs(af.h - (int)(100.0 * 2048 / 5000)) <= 1);
|
||||
EXPECT_EQ(af.frames.size(), (std::size_t)1);
|
||||
auto huge = imgTestBmp(20000, 20000, false);
|
||||
EXPECT_TRUE(util::DecodeAnimatedFromMemory(huge.data(), huge.size(), 1, tl, nullptr, af) == util::ImageStatus::TooLarge);
|
||||
auto small = imgTestBmp(300, 200, true); // under the cap: untouched
|
||||
EXPECT_TRUE(util::DecodeAnimatedFromMemory(small.data(), small.size(), 1, tl, nullptr, af) == util::ImageStatus::Ok);
|
||||
EXPECT_EQ(af.w, 300); EXPECT_EQ(af.h, 200);
|
||||
}
|
||||
// Garbage and cancellation.
|
||||
{
|
||||
const unsigned char junk[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
|
||||
|
||||
Reference in New Issue
Block a user