// DOM-mode port of inverse-circle.comp.glsl. Inverts RGB inside each
// user-supplied circle; passes through every other pixel so the
// ping-pong carries the prior dispatch's scene forward.
//
// Bind-group contract (mirrors :WebGPUComputeShader.cppm):
//   group 0 binding 0 — uniform UIDispatchHeader (auto-injected)
//   group 1 binding 0 — texture_storage_2d<rgba8unorm, write> out (auto)
//   group 1 binding 1 — texture_2d<f32>                      prev (auto)
//   group 2 binding 0 — items SSBO declared by the C++ side via
//                       UICustomBinding { group=2, binding=0,
//                       kind=Buffer, pushOffset=offsetof(hdr.itemBuffer) }

struct UIDispatchHeader {
    outImage:   u32,
    itemBuffer: u32,
    surfaceW:   u32,
    surfaceH:   u32,
    clipX:      f32,
    clipY:      f32,
    clipW:      f32,
    clipH:      f32,
    itemCount:  u32,
    frameIdx:   u32,
    flags:      u32,
    _pad:       u32,
};
@group(0) @binding(0) var<uniform> hdr : UIDispatchHeader;
@group(1) @binding(0) var outTex  : texture_storage_2d<rgba8unorm, write>;
@group(1) @binding(1) var prevTex : texture_2d<f32>;

struct InverseCircleItem {
    centerRadius: vec4<f32>,
};
@group(2) @binding(0) var<storage, read> items : array<InverseCircleItem>;

@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
    if (gid.x >= hdr.surfaceW || gid.y >= hdr.surfaceH) { return; }
    let coord = vec2<i32>(i32(gid.x), i32(gid.y));
    let sp = vec2<f32>(f32(gid.x) + 0.5, f32(gid.y) + 0.5);

    // Max-coverage over all items, so overlapping circles don't
    // double-invert back to the original.
    var coverage: f32 = 0.0;
    for (var i: u32 = 0u; i < hdr.itemCount; i = i + 1u) {
        let it = items[i];
        let c = it.centerRadius.xy;
        let r = it.centerRadius.z;
        let d = length(sp - c) - r;
        coverage = max(coverage, clamp(0.5 - d, 0.0, 1.0));
    }

    var dst = textureLoad(prevTex, coord, 0);
    if (coverage > 0.0) {
        dst = vec4<f32>(mix(dst.rgb, vec3<f32>(1.0) - dst.rgb, coverage), dst.a);
    }
    textureStore(outTex, coord, dst);
}
