using AcDream.App.Rendering.Gpu;
namespace AcDream.App.Rendering;
///
/// Campaign V slice V6d: the encoding the retained UI passes textures around
/// with — a ONE-BASED index into the device's global texture table, where 0
/// means "no texture".
///
/// Why an encoding rather than the slot itself. Until this slice
/// the UI's currency was a raw GL texture name: TextureCache handed one
/// out, sixty-odd widget call sites carried it, and TextRenderer.DrawSprite
/// bound it to texture unit 0. That name means nothing on Vulkan, so the
/// currency has to become a . But
/// is internal to the pinned RHI contract while
/// UiRenderContext.DrawSprite, TextureCache.GetOrUploadRenderSurface
/// and a dozen widget properties are public, so the slot cannot itself travel
/// through those signatures without either publishing a contract type or
/// converting the whole retained-UI surface to internal. Both were out of scope
/// for this slice, and the second is explicitly forbidden by the campaign's
/// rule against visibility sweeps.
///
/// Why one-based. The old currency already had the property that
/// zero means nothing — GL texture name 0 is "no texture" — and every widget in
/// the tree guards on it (if (tex == 0) return;). Slot 0 is a perfectly
/// valid table index, so handing out raw slot indices would turn every one of
/// those guards into a silent false negative. Shifting by one preserves the
/// guard exactly, needs no call-site change, and keeps the sentinel loud rather
/// than aliasing onto a real texture.
///
/// Retired when the retained UI's public surface can name a
/// directly.
///
internal static class UiTextureTableHandle
{
/// No texture. What every widget's tex == 0 guard tests for.
public const uint None = 0;
/// Encodes a registered slot. An unassigned slot encodes to .
public static uint FromSlot(GpuTextureSlot slot) =>
slot.IsAssigned ? slot.Index + 1 : None;
///
/// Decodes a handle. decodes to
/// , which the retained UI's shader
/// reads as "draw the vertex colour" rather than sampling anything.
///
public static GpuTextureSlot ToSlot(uint handle) =>
handle == None ? GpuTextureSlot.Unassigned : new GpuTextureSlot(handle - 1);
}