mirror of
https://github.com/storytold/photocraft.git
synced 2026-11-10 18:20:31 -06:00
Surface::translated, under every layer move and the Move drag preview, allocated every target tile that a moved source tile reached. For a move that isn't a whole number of tiles, the transparent margins of a layer's edge tiles landed on target tiles of their own, and those were stored though they hold only the default pixel (256 KB each at 8-bit RGBA). #4414's shared uniform tiles were also stored when their value was the default. Moving two 300 px blocks by (100, 56) left 10 of 18 stored tiles empty; nudging back and forth kept adding more. A target that ends up holding only the default pixel is no longer stored, as prune() would drop it. A copied tile is compared row by row with a row of the default pixel after the copy (one memcmp per row; a tile with content stops at its first row), and a shared uniform tile of the default value is skipped. Moves by whole tiles still re-share the existing tiles unchanged. Release, 24 cores, cargo xtask perf --quick (perf_scenarios, p50, HEAD vs this, two runs each): move layer on 16-bit 15000x10000 + refresh 5.3 -> 3.9 ms; move layer on 32-bit 20 layers + refresh 11.9 -> 5.9 ms; the other Move rows within noise. translated() alone on 36 MP: full layer unchanged (27.0 -> 27.6 ms RGBA8); 40 sparse blocks 11.8 -> 10.6 ms RGBA8, 44.0 -> 39 ms RGBA16, 308 -> 190 tiles. The new test covers RGBA8, RGBA16, RGBA32F and GRAY8 over a zero and a non-zero default pixel, and both paths; it fails on the old code. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>