Driver layer onAdd — adopt the main context. A prior capture re-uploads next frame.
Publish null without disabling (empty drape set / capture failure).
Driver layer onRemove (style reload / teardown) — the texture dies with the layer.
Full teardown — clears every receiver and frees the texture.
Register a receiver — it gets the CURRENT shared drape immediately (if any).
Master switch — off publishes null (byte-identical rendering); on re-publishes.
Global opacity multiplier — republishes without a re-capture.
The capture side's mailbox: newest seq wins, and a SAME-seq re-grab (crisper pixels of the same view) replaces + re-uploads; consumed by uploadIfDirty.
Unregister a receiver — its drape is cleared; others are untouched.
Driver prerender hook: upload the newest capture (at most once per submission),
then publish the refreshed SharedDrape. All UNPACK state + bindings we
touch are snapshotted and restored — MapLibre's own uploads must be unaffected.
The drape's main-context half: it owns the atlas texture, the set of registered DrapeReceivers, and the mailbox captures are posted into. A grab arrives via
submitCapture; the driver layer'sprerendercallsuploadIfDirty, which uploads the newest grab at most once and publishes the refreshedSharedDrapeto every receiver (nullwhile the drape is disabled, cleared, or detached). It needs a WebGL2 context and never touches the map —DrapeCoordinatorLayerhands it the context and the render-loop slot, so the coordinator does nothing until that layer is on the map.enableVectorDrape wires the coordinator, the driver layer, and the hidden capture map in one call; that is what an app normally wants. Construct one directly when you are producing the atlas yourself — your own renderer, an offline tile, a canvas the SDK did not draw — and want the SDK's 3D layers to sample it.
Example
See
DrapeCapturePayload for what a capture must supply.