fix(web): add CropBounds to PasteKey — stale raster cache was corrupting transparency

This commit is contained in:
2026-09-08 13:28:42 -07:00
parent 5175c1c8c9
commit 081e4c1bf8
+8 -6
View File
@@ -19,11 +19,13 @@ public sealed class SceneCompositor
// chat/web/image layers are identical frame after frame. Same shape as OBS (the
// source surface is cached, the compositor blits): a scaled/round-clipped/mirrored
// layer rasterizes once and is pasted (row-copy/blend) on every later tick.
// Keyed by the SOURCE FRAME IDENTITY (array + Epoch) — producers hand out fresh
// immutable byte[], or recycled-ring arrays whose monotonic Epoch distinguishes
// each generation (screen capture, take-11 fix), so "same array+epoch + same
// target rect" ⇒ same raster. Bounds-checked eviction clears wholesale.
private sealed record PasteKey(byte[] Pixels, long Epoch, int SrcW, int SrcH, int DstW, int DstH, bool Round, bool Mirror);
// Keyed by the SOURCE FRAME IDENTITY (array + Epoch + CropBounds) — producers hand
// out fresh immutable byte[], or recycled-ring arrays whose monotonic Epoch distinguishes
// each generation (screen capture, take-11 fix). CropBounds must be in the key because
// the same frame (same Pixels/Epoch/Width/Height) can have different CropBounds as
// the element is resized — a stale cached raster with wrong crop pixels would corrupt
// the output. Bounds-checked eviction clears wholesale.
private sealed record PasteKey(byte[] Pixels, long Epoch, int SrcW, int SrcH, int DstW, int DstH, bool Round, bool Mirror, (int X, int Y, int W, int H)? CropBounds);
private static readonly Dictionary<PasteKey, VideoFrame> _pasteCache = new();
private static readonly Dictionary<SceneElement, VideoFrame> _elementRasters = new(ReferenceEqualityComparer.Instance);
private static readonly object _pasteGate = new();
@@ -286,7 +288,7 @@ public sealed class SceneCompositor
VideoFrame? raster = null;
lock (_pasteGate)
{
key = new PasteKey(frame.BgraPixels, frame.Epoch, frame.Width, frame.Height, dw, dh, isRound, mirror);
key = new PasteKey(frame.BgraPixels, frame.Epoch, frame.Width, frame.Height, dw, dh, isRound, mirror, frame.CropBounds);
_pasteCache.TryGetValue(key, out raster);
}