export interface PooledFramebuffer { readonly fb: WebGLFramebuffer; readonly tex: WebGLTexture; readonly width: number; readonly height: number; } export interface EnsureOptions { /** * Allocate `RGBA16F` colour attachments instead of `RGBA8`. Required * for multi-pass effects that produce intermediate values outside * [0, 1] — bright-pass / bloom / glow / any HDR composite. * * Requires the `EXT_color_buffer_float` extension. When unavailable, * the pool silently falls back to LDR; check `isHdrActive` if * correctness matters. */ hdr?: boolean; } export interface FramebufferPoolOptions { /** * Maximum number of distinct `(width, height, hdr)` slots the pool * holds simultaneously. Each slot owns the FBO `count` requested by * the last `ensure()` for that key. When the pool is at capacity * and a new key is requested, the least-recently-used slot is * disposed. * * Default: `4`. Resident GL objects ≤ `capacity × count_per_slot`. * * Set to `1` to preserve pre-0.5.0 behaviour: a single slot that * reallocates whenever any of `(count, width, height, hdr)` changes * — no LRU, no per-size persistence. * * Raise above 4 if your application renders into more than 4 * distinct sizes per frame (e.g. per-element effects on a canvas * with many heterogeneously-sized elements). Cost is roughly * `2 × (capacity - 4)` additional GL textures held resident. */ capacity?: number; } /** * Reusable ping-pong framebuffer allocator. Holds an LRU of slots * keyed by `(width, height, hdr)`; each slot owns a fixed count of * framebuffers at that size and format. * * Default capacity (4) covers the common case where most content * clusters into a handful of sizes (full-frame backgrounds, fit-to- * canvas media, captions at a couple of sizes). Per-frame size * alternations between cached sizes are O(1); sizes that fall outside * the LRU window evict the least-recently-used slot. * * **Important call-site pattern:** `ensure()` creates textures by * binding them to `gl.TEXTURE_2D` on the currently-active texture * unit. If you bind a source texture first and THEN call `ensure()`, * the source's unit will be clobbered. Always call `ensure()` BEFORE * any `activeTexture` / `bindTexture` for sampler inputs. */ export declare class FramebufferPool { private gl; /** Slots in LRU order: index 0 = most recently used. */ private slots; private readonly capacity; private hdrExtensionChecked; private hdrExtensionAvailable; /** * @param gl Owning WebGL2 context. The pool's allocations are tied to * this context's lifetime; on context loss + restore call * `resetContextState()` before the next `ensure()`. * @param options Pool configuration; see `FramebufferPoolOptions`. */ constructor(gl: WebGL2RenderingContext, options?: FramebufferPoolOptions); /** * Return at least `count` framebuffers sized `width × height` with the * requested format. Matching slot is moved to most-recently-used and * returned. On miss, a fresh slot is allocated; if the pool is at * capacity, the least-recently-used slot is disposed first. * * Requesting the same `(width, height, hdr)` with a `count` larger * than the slot currently holds reallocates *that slot only*; other * slots are untouched. * * **Bind order matters:** `ensure()` creates new textures by binding * them to `gl.TEXTURE_2D` on the active unit. If you have a source * texture bound and then call `ensure()`, that unit gets clobbered. * Always call `ensure()` BEFORE binding sampler inputs. * * @throws Error if texture or framebuffer allocation fails (e.g. an * incomplete framebuffer status — usually a sign of an unsupported * format combination). */ ensure(count: number, width: number, height: number, options?: EnsureOptions): readonly PooledFramebuffer[]; /** * `true` when the most-recently-touched slot was allocated with HDR * (`RGBA16F`) attachments. `false` when HDR was requested but * `EXT_color_buffer_float` is unavailable — in which case * `ensure({ hdr: true })` silently fell back to LDR (`RGBA8`). * * Reflects the *last* `ensure()` call, not pool-wide state — under * the LRU, distinct HDR and LDR slots can coexist; this getter * answers "did my last call get HDR?". */ get isHdrActive(): boolean; /** * Total number of framebuffers across all live slots. Useful for * test assertions and resource accounting; not a per-slot count. */ get count(): number; /** Free every framebuffer + colour attachment owned by the pool. */ dispose(): void; /** * Reset HDR extension state and drop all slot bookkeeping — call * after a context-loss + restore so the pool re-queries the * extension rather than trusting a stale flag, and so it doesn't * try to delete framebuffers/textures from the lost context (those * are gone with the context). */ resetContextState(): void; private freeSlot; private ensureHdrExtension; private createTexture; private createFramebuffer; } //# sourceMappingURL=framebuffer-pool.d.ts.map