Open Plant WSI
Engine

Single render loop + isolated draw overlay

Tiles and points are composited in WebGL2. ROI interaction runs in a separate overlay canvas to keep input handling deterministic and simple.

Runtime layout

React
 └─ WsiViewerCanvas
    ├─ WebGL Canvas (WsiTileRenderer: pan/zoom/rotate)
    │  ├─ Tile pass
    │  └─ Point pass
    └─ DrawLayer Canvas (ROI input + preview + labels)

Tile pipeline

Tier selection: tier = floor(maxTierZoom + log2(zoom)).
Visible set: intersect viewport bounds with tile grid at the selected tier.
Fallback first: draw cached overlapping tiles before new-tier tiles are ready.
Tile-only color correction: brightness/contrast/saturation uniforms are applied in tile fragment shader only.
Async fetch/upload: fetch bitmap, upload texture, schedule new frame.
LRU trim: evict least-used textures when cache exceeds budget.

Runtime resilience (WS-7)

Context loss: renderer pauses frame loop, drag state, and tile scheduler on webglcontextlost.
Safe recovery: on webglcontextrestored, shader programs and GPU buffers/textures are recreated.
Point replay: last point buffers and palette are re-uploaded automatically after restore.
Network degrade: retry/backoff + fallback tile rendering keep viewport continuity during tile failures.
Hooks: onContextLost, onContextRestored, onTileError expose runtime fault signals to host apps.

Point pipeline

External parsing: point loading/decoding (e.g. zstd+MVT) is the caller's responsibility.
Input contract: accepts Float32Array positions + Uint16Array palette indices, plus optional fillModes/drawIndices.
GPU upload: positions and palette index buffers.
Shader render: palette-based point fragments in ring/solid mode via fillModes.
ROI filter: optional polygon clip before upload/render via clipMode.
ROI stats: optional per-ROI term aggregation via computeRoiPointGroups / onRoiPointGroups.

ROI acceleration modes

`sync`

Main-thread polygon filtering. Useful for debugging and baseline checks.

`worker`

Dedicated worker thread ROI filtering to avoid UI stalls. Current recommended default.

`hybrid-webgpu`

Experimental path: WebGPU bbox prefilter + exact polygon test, then draw-bridge via drawIndices for indexed point rendering.

Observability

onStats/onClipStats plus built-in debugOverlay provide runtime profiling signals and fast regression checks.

Draw pipeline

Camera input: pan + wheel zoom + Ctrl/Cmd + drag rotate (rotationDeg).
Pointer capture: draw layer captures active pointer in draw mode.
Preview: freehand/rectangle/circle preview polygon or brush cursor+stroke.
Finalize: close ring and emit DrawResult (intent: "roi" | "patch" | "brush").
Region interaction: cursor-mode region hit test is contour + label only (interior fill excluded).
Persist: region outlines and labels remain visible across camera changes.

WebGPU expansion path (compute-focused)

ROI culling

Started with bbox prefilter compute pass, then exact polygon phase.

LOD aggregation

Low-zoom density aggregation and binning on GPU.

Term histogram

ROI-level term counts and positivity stats in parallel.

Interop

Pack compute output for direct WebGL buffer upload.

The current WebGPU route is marked experimental and designed as opt-in. Keep worker as the production-safe default until measured wins are confirmed.

Open-source docs contract

Behavior first: every runtime mode must define default, fallback, and failure behavior.
Versioned API: docs and src/index.ts exports are updated in the same PR.
Measured claims: performance guidance must reference reproducible stats paths (onStats, onClipStats).
Bilingual parity: EN/KO pages must be kept equivalent for engine users.