feat(D.5.1): IconComposer — CPU alpha-over icon composite + cache

Adds IconComposer (AcDream.App.UI) which mirrors retail IconData::RenderIcons
(decomp 407524): decodes each RenderSurface layer directly via SurfaceDecoder,
composites them bottom-to-top with Porter-Duff alpha-over, and uploads the
result to a GL texture via TextureCache. Composited handles are keyed by the
(iconId, underlayId, overlayId) tuple so each unique combo is uploaded once.

Adds a public TextureCache.UploadRgba8(byte[], int, int, bool) wrapper — a
thin shell around the existing private overload — so IconComposer can upload
its CPU-side composite without duplicating any GL state logic.

Pure Compose() path is covered by 2 unit tests (opaque top wins; transparent
top preserves bottom). Dat-decode + GL-upload exercised by the visual gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-16 22:09:41 +02:00
parent 6c485c2f06
commit 6e82807863
3 changed files with 129 additions and 0 deletions

View file

@ -542,6 +542,11 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
return composed;
}
/// <summary>Uploads a raw RGBA8 byte array as a Texture2D. Used by
/// <see cref="AcDream.App.UI.IconComposer"/> to upload CPU-composited icon layers.</summary>
public uint UploadRgba8(byte[] rgba, int width, int height, bool nearest = false)
=> UploadRgba8(new DecodedTexture(rgba, width, height), nearest);
private uint UploadRgba8(DecodedTexture decoded, bool nearest = false)
{
uint tex = _gl.GenTexture();