@perspective-dev/viewer-charts 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +193 -0
- package/dist/cdn/perspective-viewer-charts.js +3 -0
- package/dist/cdn/perspective-viewer-charts.js.map +7 -0
- package/dist/esm/axis/axis-primitives.d.ts +24 -0
- package/dist/esm/axis/bar-axis.d.ts +51 -0
- package/dist/esm/axis/canvas.d.ts +24 -0
- package/dist/esm/axis/categorical-axis-core.d.ts +42 -0
- package/dist/esm/axis/categorical-axis.d.ts +27 -0
- package/dist/esm/axis/facet-chrome.d.ts +13 -0
- package/dist/esm/axis/label-geometry.d.ts +41 -0
- package/dist/esm/axis/legend.d.ts +44 -0
- package/dist/esm/axis/numeric-axis.d.ts +20 -0
- package/dist/esm/charts/candlestick/candlestick-build.d.ts +129 -0
- package/dist/esm/charts/candlestick/candlestick-interact.d.ts +10 -0
- package/dist/esm/charts/candlestick/candlestick-render.d.ts +24 -0
- package/dist/esm/charts/candlestick/candlestick.d.ts +144 -0
- package/dist/esm/charts/candlestick/glyphs/draw-candlesticks.d.ts +36 -0
- package/dist/esm/charts/candlestick/glyphs/draw-ohlc.d.ts +33 -0
- package/dist/esm/charts/canvas-types.d.ts +15 -0
- package/dist/esm/charts/cartesian/cartesian-build.d.ts +14 -0
- package/dist/esm/charts/cartesian/cartesian-interact.d.ts +20 -0
- package/dist/esm/charts/cartesian/cartesian-render.d.ts +26 -0
- package/dist/esm/charts/cartesian/cartesian.d.ts +239 -0
- package/dist/esm/charts/cartesian/glyph.d.ts +53 -0
- package/dist/esm/charts/cartesian/glyphs/density.d.ts +142 -0
- package/dist/esm/charts/cartesian/glyphs/lines.d.ts +23 -0
- package/dist/esm/charts/cartesian/glyphs/points.d.ts +24 -0
- package/dist/esm/charts/cartesian/label-interner.d.ts +21 -0
- package/dist/esm/charts/cartesian/tooltip-lines.d.ts +11 -0
- package/dist/esm/charts/chart-base.d.ts +402 -0
- package/dist/esm/charts/chart.d.ts +338 -0
- package/dist/esm/charts/common/band-layout.d.ts +32 -0
- package/dist/esm/charts/common/categorical-y-chart.d.ts +53 -0
- package/dist/esm/charts/common/category-axis-resolver.d.ts +90 -0
- package/dist/esm/charts/common/chrome-cache.d.ts +18 -0
- package/dist/esm/charts/common/draw-tooltip-box.d.ts +9 -0
- package/dist/esm/charts/common/leaf-color.d.ts +33 -0
- package/dist/esm/charts/common/node-store.d.ts +81 -0
- package/dist/esm/charts/common/tree-chart.d.ts +48 -0
- package/dist/esm/charts/common/tree-chrome.d.ts +31 -0
- package/dist/esm/charts/common/tree-data.d.ts +54 -0
- package/dist/esm/charts/common/visible-extent.d.ts +51 -0
- package/dist/esm/charts/heatmap/heatmap-build.d.ts +86 -0
- package/dist/esm/charts/heatmap/heatmap-interact.d.ts +19 -0
- package/dist/esm/charts/heatmap/heatmap-render.d.ts +19 -0
- package/dist/esm/charts/heatmap/heatmap-y-axis.d.ts +46 -0
- package/dist/esm/charts/heatmap/heatmap.d.ts +117 -0
- package/dist/esm/charts/map/map.d.ts +67 -0
- package/dist/esm/charts/registry.d.ts +14 -0
- package/dist/esm/charts/series/glyphs/draw-areas.d.ts +30 -0
- package/dist/esm/charts/series/glyphs/draw-bars.d.ts +15 -0
- package/dist/esm/charts/series/glyphs/draw-lines.d.ts +34 -0
- package/dist/esm/charts/series/glyphs/draw-scatter.d.ts +33 -0
- package/dist/esm/charts/series/series-build.d.ts +228 -0
- package/dist/esm/charts/series/series-interact.d.ts +35 -0
- package/dist/esm/charts/series/series-render.d.ts +41 -0
- package/dist/esm/charts/series/series-type.d.ts +49 -0
- package/dist/esm/charts/series/series.d.ts +317 -0
- package/dist/esm/charts/sunburst/sunburst-interact.d.ts +7 -0
- package/dist/esm/charts/sunburst/sunburst-layout.d.ts +33 -0
- package/dist/esm/charts/sunburst/sunburst-render.d.ts +22 -0
- package/dist/esm/charts/sunburst/sunburst.d.ts +85 -0
- package/dist/esm/charts/treemap/treemap-interact.d.ts +12 -0
- package/dist/esm/charts/treemap/treemap-layout.d.ts +28 -0
- package/dist/esm/charts/treemap/treemap-render.d.ts +18 -0
- package/dist/esm/charts/treemap/treemap.d.ts +74 -0
- package/dist/esm/config.d.ts +27 -0
- package/dist/esm/data/lazy-row.d.ts +32 -0
- package/dist/esm/data/split-groups.d.ts +20 -0
- package/dist/esm/data/view-reader.d.ts +35 -0
- package/dist/esm/event-detail.d.ts +28 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/interaction/hit-test.d.ts +30 -0
- package/dist/esm/interaction/host-sink-dom.d.ts +19 -0
- package/dist/esm/interaction/host-sink-message.d.ts +46 -0
- package/dist/esm/interaction/lazy-tooltip.d.ts +61 -0
- package/dist/esm/interaction/raw-event-forwarder.d.ts +27 -0
- package/dist/esm/interaction/spatial-grid.d.ts +15 -0
- package/dist/esm/interaction/tooltip-controller.d.ts +193 -0
- package/dist/esm/interaction/zoom-controller.d.ts +106 -0
- package/dist/esm/interaction/zoom-router.d.ts +48 -0
- package/dist/esm/layout/facet-grid.d.ts +126 -0
- package/dist/esm/layout/plot-layout.d.ts +104 -0
- package/dist/esm/layout/ticks.d.ts +17 -0
- package/dist/esm/map/mercator.d.ts +102 -0
- package/dist/esm/map/tile-cache.d.ts +38 -0
- package/dist/esm/map/tile-layer.d.ts +66 -0
- package/dist/esm/map/tile-loader.d.ts +52 -0
- package/dist/esm/map/tile-source.d.ts +66 -0
- package/dist/esm/perspective-viewer-charts.js +3 -0
- package/dist/esm/perspective-viewer-charts.js.map +7 -0
- package/dist/esm/plugin/charts.d.ts +40 -0
- package/dist/esm/plugin/plugin.d.ts +95 -0
- package/dist/esm/render/scheduler.d.ts +41 -0
- package/dist/esm/theme/gradient.d.ts +48 -0
- package/dist/esm/theme/palette.d.ts +13 -0
- package/dist/esm/theme/theme-snapshot.d.ts +7 -0
- package/dist/esm/theme/theme.d.ts +53 -0
- package/dist/esm/transport/protocol.d.ts +430 -0
- package/dist/esm/transport/renderer-transport.d.ts +201 -0
- package/dist/esm/utils/css.d.ts +1 -0
- package/dist/esm/utils/font-snapshot.d.ts +50 -0
- package/dist/esm/webgl/buffer-pool.d.ts +62 -0
- package/dist/esm/webgl/context-manager.d.ts +184 -0
- package/dist/esm/webgl/gradient-texture.d.ts +17 -0
- package/dist/esm/webgl/instanced-attrs.d.ts +44 -0
- package/dist/esm/webgl/plot-frame.d.ts +39 -0
- package/dist/esm/webgl/program-cache.d.ts +13 -0
- package/dist/esm/webgl/shader-manifest.d.ts +53 -0
- package/dist/esm/webgl/shader-registry.d.ts +22 -0
- package/dist/esm/worker/boot.d.ts +0 -0
- package/dist/esm/worker/dispatch.d.ts +9 -0
- package/dist/esm/worker/font-loader.d.ts +2 -0
- package/dist/esm/worker/renderer.worker.d.ts +115 -0
- package/dist/esm/worker/session-host.d.ts +26 -0
- package/package.json +47 -0
- package/src/css/perspective-viewer-charts.css +95 -0
- package/src/ts/axis/axis-primitives.ts +125 -0
- package/src/ts/axis/bar-axis.ts +345 -0
- package/src/ts/axis/canvas.ts +64 -0
- package/src/ts/axis/categorical-axis-core.ts +125 -0
- package/src/ts/axis/categorical-axis.ts +716 -0
- package/src/ts/axis/facet-chrome.ts +42 -0
- package/src/ts/axis/label-geometry.ts +188 -0
- package/src/ts/axis/legend.ts +218 -0
- package/src/ts/axis/numeric-axis.ts +353 -0
- package/src/ts/charts/candlestick/candlestick-build.ts +516 -0
- package/src/ts/charts/candlestick/candlestick-interact.ts +256 -0
- package/src/ts/charts/candlestick/candlestick-render.ts +387 -0
- package/src/ts/charts/candlestick/candlestick.ts +367 -0
- package/src/ts/charts/candlestick/glyphs/draw-candlesticks.ts +432 -0
- package/src/ts/charts/candlestick/glyphs/draw-ohlc.ts +317 -0
- package/src/ts/charts/canvas-types.ts +30 -0
- package/src/ts/charts/cartesian/cartesian-build.ts +616 -0
- package/src/ts/charts/cartesian/cartesian-interact.ts +355 -0
- package/src/ts/charts/cartesian/cartesian-render.ts +948 -0
- package/src/ts/charts/cartesian/cartesian.ts +469 -0
- package/src/ts/charts/cartesian/glyph.ts +81 -0
- package/src/ts/charts/cartesian/glyphs/density.ts +1263 -0
- package/src/ts/charts/cartesian/glyphs/lines.ts +320 -0
- package/src/ts/charts/cartesian/glyphs/points.ts +239 -0
- package/src/ts/charts/cartesian/label-interner.ts +56 -0
- package/src/ts/charts/cartesian/tooltip-lines.ts +80 -0
- package/src/ts/charts/chart-base.ts +840 -0
- package/src/ts/charts/chart.ts +427 -0
- package/src/ts/charts/common/band-layout.ts +63 -0
- package/src/ts/charts/common/categorical-y-chart.ts +81 -0
- package/src/ts/charts/common/category-axis-resolver.ts +314 -0
- package/src/ts/charts/common/chrome-cache.ts +79 -0
- package/src/ts/charts/common/draw-tooltip-box.ts +84 -0
- package/src/ts/charts/common/leaf-color.ts +92 -0
- package/src/ts/charts/common/node-store.ts +235 -0
- package/src/ts/charts/common/tree-chart.ts +76 -0
- package/src/ts/charts/common/tree-chrome.ts +123 -0
- package/src/ts/charts/common/tree-data.ts +623 -0
- package/src/ts/charts/common/visible-extent.ts +112 -0
- package/src/ts/charts/heatmap/heatmap-build.ts +426 -0
- package/src/ts/charts/heatmap/heatmap-interact.ts +274 -0
- package/src/ts/charts/heatmap/heatmap-render.ts +815 -0
- package/src/ts/charts/heatmap/heatmap-y-axis.ts +351 -0
- package/src/ts/charts/heatmap/heatmap.ts +368 -0
- package/src/ts/charts/map/map.ts +201 -0
- package/src/ts/charts/registry.ts +65 -0
- package/src/ts/charts/series/glyphs/draw-areas.ts +331 -0
- package/src/ts/charts/series/glyphs/draw-bars.ts +113 -0
- package/src/ts/charts/series/glyphs/draw-lines.ts +320 -0
- package/src/ts/charts/series/glyphs/draw-scatter.ts +328 -0
- package/src/ts/charts/series/series-build.ts +848 -0
- package/src/ts/charts/series/series-interact.ts +604 -0
- package/src/ts/charts/series/series-render.ts +1109 -0
- package/src/ts/charts/series/series-type.ts +99 -0
- package/src/ts/charts/series/series.ts +794 -0
- package/src/ts/charts/sunburst/sunburst-interact.ts +460 -0
- package/src/ts/charts/sunburst/sunburst-layout.ts +238 -0
- package/src/ts/charts/sunburst/sunburst-render.ts +887 -0
- package/src/ts/charts/sunburst/sunburst.ts +248 -0
- package/src/ts/charts/treemap/treemap-interact.ts +445 -0
- package/src/ts/charts/treemap/treemap-layout.ts +328 -0
- package/src/ts/charts/treemap/treemap-render.ts +886 -0
- package/src/ts/charts/treemap/treemap.ts +247 -0
- package/src/ts/config.ts +41 -0
- package/src/ts/data/lazy-row.ts +140 -0
- package/src/ts/data/split-groups.ts +97 -0
- package/src/ts/data/view-reader.ts +107 -0
- package/src/ts/event-detail.ts +44 -0
- package/src/ts/index.ts +53 -0
- package/src/ts/interaction/hit-test.ts +106 -0
- package/src/ts/interaction/host-sink-dom.ts +85 -0
- package/src/ts/interaction/host-sink-message.ts +75 -0
- package/src/ts/interaction/lazy-tooltip.ts +102 -0
- package/src/ts/interaction/raw-event-forwarder.ts +175 -0
- package/src/ts/interaction/spatial-grid.ts +100 -0
- package/src/ts/interaction/tooltip-controller.ts +407 -0
- package/src/ts/interaction/zoom-controller.ts +468 -0
- package/src/ts/interaction/zoom-router.ts +230 -0
- package/src/ts/layout/facet-grid.ts +346 -0
- package/src/ts/layout/plot-layout.ts +277 -0
- package/src/ts/layout/ticks.ts +168 -0
- package/src/ts/map/mercator.ts +204 -0
- package/src/ts/map/tile-cache.ts +96 -0
- package/src/ts/map/tile-layer.ts +382 -0
- package/src/ts/map/tile-loader.ts +143 -0
- package/src/ts/map/tile-source.ts +156 -0
- package/src/ts/plugin/charts.ts +286 -0
- package/src/ts/plugin/plugin.ts +668 -0
- package/src/ts/render/scheduler.ts +339 -0
- package/src/ts/shaders/area.frag.glsl +20 -0
- package/src/ts/shaders/area.vert.glsl +19 -0
- package/src/ts/shaders/bar.frag.glsl +25 -0
- package/src/ts/shaders/bar.vert.glsl +60 -0
- package/src/ts/shaders/candlestick-body.frag.glsl +19 -0
- package/src/ts/shaders/candlestick-body.vert.glsl +34 -0
- package/src/ts/shaders/density-extreme.frag.glsl +30 -0
- package/src/ts/shaders/density-mrt.frag.glsl +44 -0
- package/src/ts/shaders/density-mrt.vert.glsl +48 -0
- package/src/ts/shaders/density-resolve.frag.glsl +89 -0
- package/src/ts/shaders/density-resolve.vert.glsl +23 -0
- package/src/ts/shaders/density-splat.frag.glsl +34 -0
- package/src/ts/shaders/density-splat.vert.glsl +52 -0
- package/src/ts/shaders/gridline.frag.glsl +18 -0
- package/src/ts/shaders/gridline.vert.glsl +18 -0
- package/src/ts/shaders/heatmap.frag.glsl +23 -0
- package/src/ts/shaders/heatmap.vert.glsl +42 -0
- package/src/ts/shaders/line-uniform.frag.glsl +26 -0
- package/src/ts/shaders/line-uniform.vert.glsl +54 -0
- package/src/ts/shaders/line.frag.glsl +28 -0
- package/src/ts/shaders/line.vert.glsl +87 -0
- package/src/ts/shaders/scatter.frag.glsl +39 -0
- package/src/ts/shaders/scatter.vert.glsl +67 -0
- package/src/ts/shaders/sunburst-arc.frag.glsl +19 -0
- package/src/ts/shaders/sunburst-arc.vert.glsl +79 -0
- package/src/ts/shaders/tile.frag.glsl +27 -0
- package/src/ts/shaders/tile.vert.glsl +35 -0
- package/src/ts/shaders/treemap.frag.glsl +19 -0
- package/src/ts/shaders/treemap.vert.glsl +25 -0
- package/src/ts/shaders/y-scatter.frag.glsl +30 -0
- package/src/ts/shaders/y-scatter.vert.glsl +31 -0
- package/src/ts/theme/gradient.ts +312 -0
- package/src/ts/theme/palette.ts +64 -0
- package/src/ts/theme/theme-snapshot.ts +66 -0
- package/src/ts/theme/theme.ts +166 -0
- package/src/ts/transport/protocol.ts +497 -0
- package/src/ts/transport/renderer-transport.ts +788 -0
- package/src/ts/utils/css.ts +36 -0
- package/src/ts/utils/font-snapshot.ts +159 -0
- package/src/ts/webgl/buffer-pool.ts +163 -0
- package/src/ts/webgl/context-manager.ts +414 -0
- package/src/ts/webgl/gradient-texture.ts +84 -0
- package/src/ts/webgl/instanced-attrs.ts +139 -0
- package/src/ts/webgl/plot-frame.ts +91 -0
- package/src/ts/webgl/program-cache.ts +46 -0
- package/src/ts/webgl/shader-manifest.ts +148 -0
- package/src/ts/webgl/shader-registry.ts +97 -0
- package/src/ts/worker/boot.ts +22 -0
- package/src/ts/worker/dispatch.ts +99 -0
- package/src/ts/worker/font-loader.ts +89 -0
- package/src/ts/worker/renderer.worker.ts +734 -0
- package/src/ts/worker/session-host.ts +118 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
type GL = WebGL2RenderingContext | WebGLRenderingContext;
|
|
2
|
+
export interface ManagedBuffer {
|
|
3
|
+
buffer: WebGLBuffer;
|
|
4
|
+
byteCapacity: number;
|
|
5
|
+
}
|
|
6
|
+
export declare class BufferPool {
|
|
7
|
+
private _gl;
|
|
8
|
+
private _buffers;
|
|
9
|
+
private _totalCapacity;
|
|
10
|
+
private _maxCapacity;
|
|
11
|
+
constructor(gl: GL);
|
|
12
|
+
get totalCapacity(): number;
|
|
13
|
+
get maxCapacity(): number;
|
|
14
|
+
set maxCapacity(cap: number);
|
|
15
|
+
ensureCapacity(totalRows: number): void;
|
|
16
|
+
/**
|
|
17
|
+
* Read-only lookup by name. Returns the existing managed buffer, or
|
|
18
|
+
* `undefined` if no buffer has been allocated under that name yet.
|
|
19
|
+
*
|
|
20
|
+
* Render-path callers that bind buffers for `drawArrays` /
|
|
21
|
+
* `drawArraysInstanced` MUST use this rather than `getOrCreate`:
|
|
22
|
+
* the latter recreates (zero-initialized) when `_totalCapacity` has
|
|
23
|
+
* grown past the current `byteCapacity`. That recreate is desired
|
|
24
|
+
* during `upload` (where `bufferSubData` immediately writes the
|
|
25
|
+
* actual data) but catastrophic during render — it wipes the
|
|
26
|
+
* previous draw's vertex data, leaving `drawArrays` to issue
|
|
27
|
+
* against zeros and produce no visible glyphs (a one-frame blank
|
|
28
|
+
* plot area while gridlines/chrome remain correct).
|
|
29
|
+
*
|
|
30
|
+
* Specifically, `ensureBufferCapacity(totalRows)` from a pending
|
|
31
|
+
* draw updates `_totalCapacity` *before* its matching `uploadChunk`
|
|
32
|
+
* has run; a pan/zoom-induced render landing in that window would
|
|
33
|
+
* otherwise see `requiredBytes > byteCapacity` and recreate.
|
|
34
|
+
*/
|
|
35
|
+
peek(name: string): ManagedBuffer | undefined;
|
|
36
|
+
getOrCreate(name: string, componentsPerVertex: number, bytesPerElement: number): ManagedBuffer;
|
|
37
|
+
/**
|
|
38
|
+
* Upload `data` into the named GPU buffer at `byteOffset`. The
|
|
39
|
+
* buffer is sized lazily by `getOrCreate` to
|
|
40
|
+
* `_totalCapacity × componentsPerVertex × data.BYTES_PER_ELEMENT`.
|
|
41
|
+
* Callers MUST keep `byteOffset + data.byteLength` within that
|
|
42
|
+
* capacity — `bufferSubData` raises `INVALID_VALUE` on overflow
|
|
43
|
+
* and the upload is silently dropped at the GL layer.
|
|
44
|
+
*
|
|
45
|
+
* Common pitfall: passing a module-level scratch typed array whose
|
|
46
|
+
* `length` exceeds the current frame's valid-data count. Scratch
|
|
47
|
+
* buffers in chart impls grow monotonically across frames; the
|
|
48
|
+
* GPU buffer is sized to the *current* `_totalCapacity`. After a
|
|
49
|
+
* renderer-session reset (e.g. plugin disconnect/reconnect) the
|
|
50
|
+
* GPU buffer is fresh while the scratch retains its historical-
|
|
51
|
+
* peak length, and the upload writes past the buffer end. Always
|
|
52
|
+
* pass `data.subarray(0, n × componentsPerVertex)` when uploading
|
|
53
|
+
* from a scratch.
|
|
54
|
+
*
|
|
55
|
+
* Set `BUFFER_POOL_STRICT = true` in `config.ts` to convert
|
|
56
|
+
* overflows from opaque GL errors into descriptive throws at the
|
|
57
|
+
* offending stack frame.
|
|
58
|
+
*/
|
|
59
|
+
upload(name: string, data: Float32Array | Int32Array, byteOffset: number, componentsPerVertex?: number): WebGLBuffer;
|
|
60
|
+
releaseAll(): void;
|
|
61
|
+
}
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { ShaderRegistry } from "./shader-registry";
|
|
2
|
+
import { BufferPool } from "./buffer-pool";
|
|
3
|
+
export type WebGLCanvas = HTMLCanvasElement | OffscreenCanvas;
|
|
4
|
+
export interface WebGLContextManagerOptions {
|
|
5
|
+
/**
|
|
6
|
+
* If `true`, compile + link every shader in `SHADER_MANIFEST`
|
|
7
|
+
* during construction (and again after a context-loss/restore
|
|
8
|
+
* cycle). Trades ~30-100ms of init time for elimination of the
|
|
9
|
+
* compile/link cost on the first-frame path of every chart type
|
|
10
|
+
* that ends up rendered. Default `false` keeps the original
|
|
11
|
+
* lazy-compile behavior — programs are compiled on first
|
|
12
|
+
* `getOrCreate(name, ...)` call from a glyph's render path.
|
|
13
|
+
*/
|
|
14
|
+
precompile?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare class WebGLContextManager {
|
|
17
|
+
private _canvas;
|
|
18
|
+
private _gl;
|
|
19
|
+
private _isWebGL2;
|
|
20
|
+
private _shaders;
|
|
21
|
+
private _buffers;
|
|
22
|
+
private _uploadedCount;
|
|
23
|
+
private _cssWidth;
|
|
24
|
+
private _cssHeight;
|
|
25
|
+
private _dpr;
|
|
26
|
+
private _precompile;
|
|
27
|
+
private _frameCallback;
|
|
28
|
+
/**
|
|
29
|
+
* Per-instance `MessageChannel` used by `_yieldToTask` to resume a
|
|
30
|
+
* polling `awaitGpuFence` loop on the next task. Allocated lazily —
|
|
31
|
+
* the polling path is rarely hit when the GPU is idle, and many
|
|
32
|
+
* `WebGLContextManager` instances never need one.
|
|
33
|
+
*
|
|
34
|
+
* Must be per-instance: a module-level singleton races when two
|
|
35
|
+
* managers poll concurrently. Both call sites assign
|
|
36
|
+
* `port1.onmessage = resolve`, the second assignment overwrites the
|
|
37
|
+
* first, and the first poll's promise never settles — leaving its
|
|
38
|
+
* `awaitGpuFence` hung. The hang propagates up through the render
|
|
39
|
+
* scheduler's `present` → `uploadAndRender` → the worker's
|
|
40
|
+
* `uploadChunkAck` → the host's `with_typed_arrays` callback,
|
|
41
|
+
* stalling `draw()` indefinitely. (Now that fence waits across
|
|
42
|
+
* different `WebGLContextManager`s run in parallel inside one
|
|
43
|
+
* scheduler drain, the per-instance discipline matters even
|
|
44
|
+
* more — concurrent poll loops are the common case, not the
|
|
45
|
+
* exception.)
|
|
46
|
+
*
|
|
47
|
+
* Cost of per-instance allocation: one extra `MessageChannel` (two
|
|
48
|
+
* `MessagePort`s, ~negligible bytes, zero idle CPU) per chart on
|
|
49
|
+
* top of the per-chart proxy channel that the transport already
|
|
50
|
+
* holds. Bounded by chart count; safe even for pathological pages
|
|
51
|
+
* with hundreds of charts. The alternative — allocating a fresh
|
|
52
|
+
* channel on every `_yieldToTask` call — would churn ports on every
|
|
53
|
+
* fence poll (potentially many per frame on slow GPUs), which is
|
|
54
|
+
* far worse for the structured-clone subsystem than holding one
|
|
55
|
+
* port pair for the manager's lifetime.
|
|
56
|
+
*/
|
|
57
|
+
private _yieldChannel;
|
|
58
|
+
constructor(canvas: WebGLCanvas, options?: WebGLContextManagerOptions);
|
|
59
|
+
get gl(): WebGL2RenderingContext | WebGLRenderingContext;
|
|
60
|
+
get isWebGL2(): boolean;
|
|
61
|
+
get shaders(): ShaderRegistry;
|
|
62
|
+
get bufferPool(): BufferPool;
|
|
63
|
+
get uploadedCount(): number;
|
|
64
|
+
set uploadedCount(count: number);
|
|
65
|
+
/**
|
|
66
|
+
* Resize the GL canvas's bitmap to match the host's CSS layout. The
|
|
67
|
+
* Host is responsible for measuring the DOM element (or otherwise
|
|
68
|
+
* deciding the target CSS size) and the device pixel ratio — the
|
|
69
|
+
* manager itself does not touch DOM, so the same code path works
|
|
70
|
+
* whether the canvas is an `HTMLCanvasElement` (in-process) or an
|
|
71
|
+
* `OffscreenCanvas` (in-process via transfer, or in a worker).
|
|
72
|
+
*/
|
|
73
|
+
resize(cssWidth: number, cssHeight: number, dpr: number): void;
|
|
74
|
+
/**
|
|
75
|
+
* Pending dimensions to apply at the start of the next render.
|
|
76
|
+
* `null` when no resize is queued. See {@link requestResize} /
|
|
77
|
+
* {@link applyPendingResize}.
|
|
78
|
+
*/
|
|
79
|
+
private _pendingResize;
|
|
80
|
+
/**
|
|
81
|
+
* Record a dimension change to be applied at the start of the
|
|
82
|
+
* next render's Phase 1, *before* `_fullRender` runs. The actual
|
|
83
|
+
* `canvas.width = N` assignment (which clears the drawing buffer
|
|
84
|
+
* per the WebGL spec) happens inside `applyPendingResize()`,
|
|
85
|
+
* paired in the same synchronous task as the paint that fills
|
|
86
|
+
* the new buffer.
|
|
87
|
+
*
|
|
88
|
+
* Why split the dimension change off from the existing
|
|
89
|
+
* {@link resize} method: in direct / in-process modes the
|
|
90
|
+
* GL canvas IS the host's visible canvas, and `canvas.width = N`
|
|
91
|
+
* is immediately observable to the browser's compositor as a
|
|
92
|
+
* cleared buffer. If the resize lands in the message handler
|
|
93
|
+
* (one task) but the matching `_fullRender` lands in the next
|
|
94
|
+
* RAF (a later task), the compositor cycles between them and
|
|
95
|
+
* presents one full frame of empty canvas — visible flicker.
|
|
96
|
+
* Deferring the dimension change to the same RAF as the paint
|
|
97
|
+
* eliminates the inter-frame gap; both happen inside Phase 1's
|
|
98
|
+
* un-yielded loop.
|
|
99
|
+
*
|
|
100
|
+
* Multiple `requestResize` calls before the next render coalesce
|
|
101
|
+
* to last-write-wins — five rapid width changes from a window
|
|
102
|
+
* drag produce one resize+paint, not five.
|
|
103
|
+
*/
|
|
104
|
+
requestResize(cssWidth: number, cssHeight: number, dpr: number): void;
|
|
105
|
+
/**
|
|
106
|
+
* Apply any pending dimension change recorded by
|
|
107
|
+
* {@link requestResize}. Called by the scheduler's Phase 1
|
|
108
|
+
* (immediately before each entry's `fullRender`) and by the
|
|
109
|
+
* `snapshotPng` bypass path. Returns `true` when a resize was
|
|
110
|
+
* applied, `false` when there was nothing pending — useful for
|
|
111
|
+
* callers that want to skip a no-op render.
|
|
112
|
+
*/
|
|
113
|
+
applyPendingResize(): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Last CSS width passed to `resize()`.
|
|
116
|
+
*/
|
|
117
|
+
get cssWidth(): number;
|
|
118
|
+
/**
|
|
119
|
+
* Last CSS height passed to `resize()`.
|
|
120
|
+
*/
|
|
121
|
+
get cssHeight(): number;
|
|
122
|
+
/**
|
|
123
|
+
* Last device pixel ratio passed to `resize()`.
|
|
124
|
+
*/
|
|
125
|
+
get dpr(): number;
|
|
126
|
+
clear(): void;
|
|
127
|
+
/**
|
|
128
|
+
* Register a per-frame hook invoked at the end of each render. In
|
|
129
|
+
* blit-mode rendering, the worker installs a callback that
|
|
130
|
+
* transfers an `ImageBitmap` from `_canvas` (an `OffscreenCanvas`)
|
|
131
|
+
* back to the host so the visible display canvas can `drawImage`
|
|
132
|
+
* it. In direct mode the callback is left null and `endFrame` is a
|
|
133
|
+
* no-op.
|
|
134
|
+
*
|
|
135
|
+
* Pass `null` to detach.
|
|
136
|
+
*/
|
|
137
|
+
setFrameCallback(cb: ((bitmap: ImageBitmap) => void) | null): void;
|
|
138
|
+
/**
|
|
139
|
+
* Called by chart impls at the bottom of `_fullRender` (and any
|
|
140
|
+
* other path that produces a complete frame). When a frame
|
|
141
|
+
* callback is registered AND the GL surface is an
|
|
142
|
+
* `OffscreenCanvas`, ship its current contents as an
|
|
143
|
+
* `ImageBitmap` to the host. Otherwise no-op — direct-mode
|
|
144
|
+
* rendering has nothing to ship; the visible canvas already holds
|
|
145
|
+
* the drawing buffer.
|
|
146
|
+
*/
|
|
147
|
+
endFrame(): void;
|
|
148
|
+
/**
|
|
149
|
+
* Resolve when every GL command submitted up to this call has been
|
|
150
|
+
* executed by the GPU.
|
|
151
|
+
*
|
|
152
|
+
* On WebGL2 this issues a `fenceSync(SYNC_GPU_COMMANDS_COMPLETE)`
|
|
153
|
+
* and polls `clientWaitSync` with a zero timeout, yielding to the
|
|
154
|
+
* task queue between polls. The first poll passes
|
|
155
|
+
* `SYNC_FLUSH_COMMANDS_BIT` so the fence becomes reachable without
|
|
156
|
+
* a separate `gl.flush()`.
|
|
157
|
+
*
|
|
158
|
+
* On WebGL1 there is no fenceSync; we fall back to the blocking
|
|
159
|
+
* `gl.finish()`. This is acceptable in a worker — never call this
|
|
160
|
+
* from the main thread on a heavy frame.
|
|
161
|
+
*
|
|
162
|
+
* Used as a per-frame "GPU is idle" barrier so callers can serialize
|
|
163
|
+
* follow-on work (`endFrame` snapshot, present roundtrip, the next
|
|
164
|
+
* chunk upload) against actual GPU completion instead of the
|
|
165
|
+
* implicit, implementation-defined timing of `transferToImageBitmap`.
|
|
166
|
+
*/
|
|
167
|
+
awaitGpuFence(): Promise<void>;
|
|
168
|
+
ensureBufferCapacity(totalRows: number): void;
|
|
169
|
+
/**
|
|
170
|
+
* Yield to the task queue between fence polls. We avoid
|
|
171
|
+
* `setTimeout(0)` because Chromium clamps nested `setTimeout` to
|
|
172
|
+
* ~4ms in workers, which would inflate the measured cost of
|
|
173
|
+
* `awaitGpuFence`. A reused per-instance `MessageChannel` lands the
|
|
174
|
+
* resume in the next task with sub-ms latency.
|
|
175
|
+
*
|
|
176
|
+
* `addEventListener(..., { once: true })` is used over
|
|
177
|
+
* `port1.onmessage = ...` so concurrent in-flight resumes (should
|
|
178
|
+
* any path ever introduce them) cannot clobber each other's
|
|
179
|
+
* resolvers — the previous module-level singleton lost a resolver
|
|
180
|
+
* on every overlap and hung one chart's `draw()` indefinitely.
|
|
181
|
+
*/
|
|
182
|
+
private _yieldToTask;
|
|
183
|
+
destroy(): void;
|
|
184
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type GradientStop } from "../theme/gradient";
|
|
2
|
+
import type { WebGLContextManager } from "./context-manager";
|
|
3
|
+
export interface GradientTextureCache {
|
|
4
|
+
texture: WebGLTexture;
|
|
5
|
+
lastStops: GradientStop[] | null;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Allocate a 256×1 RGBA8 texture (once) and re-upload the LUT only when
|
|
9
|
+
* `stops` has changed since the last call. Typical render path: zero
|
|
10
|
+
* GPU work beyond binding an already-uploaded texture.
|
|
11
|
+
*/
|
|
12
|
+
export declare function ensureGradientTexture(glManager: WebGLContextManager, cache: GradientTextureCache | null, stops: GradientStop[]): GradientTextureCache;
|
|
13
|
+
/**
|
|
14
|
+
* Bind `texture` to a texture unit and set the sampler uniform. Call after
|
|
15
|
+
* `useProgram`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function bindGradientTexture(glManager: WebGLContextManager, texture: WebGLTexture, samplerLoc: WebGLUniformLocation | null, unit?: number): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { WebGLContextManager } from "./context-manager";
|
|
2
|
+
type GL = WebGL2RenderingContext | WebGLRenderingContext;
|
|
3
|
+
export interface Instancing {
|
|
4
|
+
setDivisor(location: number, divisor: number): void;
|
|
5
|
+
drawArraysInstanced(mode: number, first: number, count: number, instances: number): void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Return an Instancing helper for the given GL context. On WebGL2, native
|
|
9
|
+
* `vertexAttribDivisor`/`drawArraysInstanced` are used; on WebGL1 the
|
|
10
|
+
* ANGLE_instanced_arrays extension is looked up and cached by caller.
|
|
11
|
+
* Negative attribute locations (optimized-out attributes) are tolerated by
|
|
12
|
+
* `setDivisor` and ignored.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getInstancing(glManager: WebGLContextManager): Instancing;
|
|
15
|
+
/**
|
|
16
|
+
* Allocate the static `[0, 1, 2, 3]` line-strip corner buffer used by
|
|
17
|
+
* every instanced line/wick glyph: each corner index is multiplied by
|
|
18
|
+
* `LINE_WIDTH_PX` in the shader to expand a 2-vertex segment into a
|
|
19
|
+
* `TRIANGLE_STRIP` quad. Identical contents across all callers; one
|
|
20
|
+
* helper avoids the four-way `createBuffer` / `bufferData` boilerplate.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createLineCornerBuffer(gl: GL): WebGLBuffer;
|
|
23
|
+
/**
|
|
24
|
+
* Allocate the static `[(0,0), (1,0), (0,1), (1,1)]` quad-strip corner
|
|
25
|
+
* buffer used by instanced rect glyphs (candlestick body). Used as a
|
|
26
|
+
* `vec2 a_corner` attribute that the shader scales by per-instance
|
|
27
|
+
* width/height to expand into a `TRIANGLE_STRIP` rect.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createQuadCornerBuffer(gl: GL): WebGLBuffer;
|
|
30
|
+
/**
|
|
31
|
+
* Bind a per-instance float attribute from a named buffer in the buffer
|
|
32
|
+
* pool. Returns `true` when the bind happened, `false` when the buffer
|
|
33
|
+
* has not yet been allocated (caller should skip the draw rather than
|
|
34
|
+
* paint zero data). No-op return `true` when `attr` is negative
|
|
35
|
+
* (optimized-out attribute — drawing the rest is still valid).
|
|
36
|
+
*
|
|
37
|
+
* Render-path uses `peek`, never `getOrCreate`: the latter recreates
|
|
38
|
+
* with zero-initialized contents when `_totalCapacity` has grown past
|
|
39
|
+
* the current buffer, which would wipe the previous draw's vertex
|
|
40
|
+
* data and leave `drawArraysInstanced` to render zeros. See
|
|
41
|
+
* {@link BufferPool#peek} for the full rationale.
|
|
42
|
+
*/
|
|
43
|
+
export declare function bindInstancedFloatAttr(glManager: WebGLContextManager, instancing: Instancing, attr: number, name: string, components: number): boolean;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PlotLayout } from "../layout/plot-layout";
|
|
2
|
+
type GL = WebGL2RenderingContext | WebGLRenderingContext;
|
|
3
|
+
/**
|
|
4
|
+
* Return CSS-pixel dimensions of the GL canvas.
|
|
5
|
+
*/
|
|
6
|
+
export declare function cssSize(gl: GL, dpr: number): {
|
|
7
|
+
cssWidth: number;
|
|
8
|
+
cssHeight: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Clear the framebuffer + enable alpha blending. Call once per frame,
|
|
12
|
+
* before any per-plot-rect {@link withScissor} invocations. Faceted
|
|
13
|
+
* renderers call this once and then loop {@link withScissor} per cell
|
|
14
|
+
* so the inter-facet clears don't wipe each other's pixels.
|
|
15
|
+
*/
|
|
16
|
+
export declare function clearAndSetupFrame(gl: GL): void;
|
|
17
|
+
/**
|
|
18
|
+
* Scissor-constrain `draw` to `layout.plotRect`. Caller handles
|
|
19
|
+
* projection / uniforms / VBO bindings inside `draw`; this helper only
|
|
20
|
+
* manages the scissor enable/disable bracket.
|
|
21
|
+
*
|
|
22
|
+
* Unlike {@link renderInPlotFrame}, this does *not* clear the
|
|
23
|
+
* framebuffer — so it's safe to call repeatedly per frame (one per
|
|
24
|
+
* facet). Pair with {@link clearAndSetupFrame} at the start of each
|
|
25
|
+
* frame.
|
|
26
|
+
*/
|
|
27
|
+
export declare function withScissor(gl: GL, layout: PlotLayout, dpr: number, draw: () => void): void;
|
|
28
|
+
/**
|
|
29
|
+
* One-shot convenience: clear + setup blend + scissor + draw. Used by
|
|
30
|
+
* single-plot callers (bar / heatmap / candlestick / scatter-without-
|
|
31
|
+
* splits) that only draw into one plot rect per frame.
|
|
32
|
+
*
|
|
33
|
+
* Faceted callers must use {@link clearAndSetupFrame} +
|
|
34
|
+
* {@link withScissor} instead; calling this helper in a per-facet loop
|
|
35
|
+
* would clear the framebuffer on each invocation and wipe out every
|
|
36
|
+
* previously-drawn facet.
|
|
37
|
+
*/
|
|
38
|
+
export declare function renderInPlotFrame(gl: GL, layout: PlotLayout, dpr: number, draw: () => void): void;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { WebGLContextManager } from "./context-manager";
|
|
2
|
+
/**
|
|
3
|
+
* Compile (or fetch from the shader registry) a program and resolve a
|
|
4
|
+
* flat record of uniform + attribute locations keyed by name. Uniforms
|
|
5
|
+
* resolve to `WebGLUniformLocation | null`; attribs resolve to `number`.
|
|
6
|
+
*
|
|
7
|
+
* Each glyph drawer used to repeat ~10 lines of `gl.getUniformLocation`
|
|
8
|
+
* / `gl.getAttribLocation` calls — replacing those with one
|
|
9
|
+
* `compileProgram(...)` call shrinks the worker bundle by ~80 bytes per
|
|
10
|
+
* site (uniform/attrib name strings still ship — WebGL needs them
|
|
11
|
+
* verbatim — but the per-call wrapper goes away).
|
|
12
|
+
*/
|
|
13
|
+
export declare function compileProgram<C>(glManager: WebGLContextManager, key: string, vert: string, frag: string, uniforms: readonly string[], attrs: readonly string[]): C;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import barVert from "../shaders/bar.vert.glsl";
|
|
2
|
+
import barFrag from "../shaders/bar.frag.glsl";
|
|
3
|
+
import lineVert from "../shaders/line.vert.glsl";
|
|
4
|
+
import lineFrag from "../shaders/line.frag.glsl";
|
|
5
|
+
import scatterVert from "../shaders/scatter.vert.glsl";
|
|
6
|
+
import scatterFrag from "../shaders/scatter.frag.glsl";
|
|
7
|
+
import areaVert from "../shaders/area.vert.glsl";
|
|
8
|
+
import areaFrag from "../shaders/area.frag.glsl";
|
|
9
|
+
import lineUniformVert from "../shaders/line-uniform.vert.glsl";
|
|
10
|
+
import lineUniformFrag from "../shaders/line-uniform.frag.glsl";
|
|
11
|
+
import yScatterVert from "../shaders/y-scatter.vert.glsl";
|
|
12
|
+
import yScatterFrag from "../shaders/y-scatter.frag.glsl";
|
|
13
|
+
import candlestickBodyVert from "../shaders/candlestick-body.vert.glsl";
|
|
14
|
+
import candlestickBodyFrag from "../shaders/candlestick-body.frag.glsl";
|
|
15
|
+
import heatmapVert from "../shaders/heatmap.vert.glsl";
|
|
16
|
+
import heatmapFrag from "../shaders/heatmap.frag.glsl";
|
|
17
|
+
import sunburstArcVert from "../shaders/sunburst-arc.vert.glsl";
|
|
18
|
+
import sunburstArcFrag from "../shaders/sunburst-arc.frag.glsl";
|
|
19
|
+
import treemapVert from "../shaders/treemap.vert.glsl";
|
|
20
|
+
import treemapFrag from "../shaders/treemap.frag.glsl";
|
|
21
|
+
import densitySplatVert from "../shaders/density-splat.vert.glsl";
|
|
22
|
+
import densitySplatFrag from "../shaders/density-splat.frag.glsl";
|
|
23
|
+
import densityExtremeFrag from "../shaders/density-extreme.frag.glsl";
|
|
24
|
+
import densityMrtVert from "../shaders/density-mrt.vert.glsl";
|
|
25
|
+
import densityMrtFrag from "../shaders/density-mrt.frag.glsl";
|
|
26
|
+
import densityResolveVert from "../shaders/density-resolve.vert.glsl";
|
|
27
|
+
import densityResolveFrag from "../shaders/density-resolve.frag.glsl";
|
|
28
|
+
import tileVert from "../shaders/tile.vert.glsl";
|
|
29
|
+
import tileFrag from "../shaders/tile.frag.glsl";
|
|
30
|
+
/**
|
|
31
|
+
* One shader program in the build's static manifest. The `name` is the
|
|
32
|
+
* cache key consumed by `ShaderRegistry.getOrCreate(name, ...)` —
|
|
33
|
+
* call sites must pass the same name (and the same vert/frag source)
|
|
34
|
+
* for the cache to hit. The single source of truth for both fields is
|
|
35
|
+
* this file; glyph code re-imports from here so the manifest and the
|
|
36
|
+
* call sites can never drift.
|
|
37
|
+
*/
|
|
38
|
+
export interface ShaderSpec {
|
|
39
|
+
name: string;
|
|
40
|
+
vert: string;
|
|
41
|
+
frag: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Every WebGL program the build ships, keyed by cache name. Used by
|
|
45
|
+
* `ShaderRegistry.precompile(SHADER_MANIFEST)` to compile + link all
|
|
46
|
+
* programs eagerly during renderer construction so the first-frame
|
|
47
|
+
* path doesn't pay the compile cost inline.
|
|
48
|
+
*
|
|
49
|
+
* Names mirror the existing `getOrCreate` keys at each call site —
|
|
50
|
+
* the lazy path stays valid; precompile just primes the cache early.
|
|
51
|
+
*/
|
|
52
|
+
export declare const SHADER_MANIFEST: readonly ShaderSpec[];
|
|
53
|
+
export { barVert, barFrag, lineVert, lineFrag, scatterVert, scatterFrag, areaVert, areaFrag, lineUniformVert, lineUniformFrag, yScatterVert, yScatterFrag, candlestickBodyVert, candlestickBodyFrag, heatmapVert, heatmapFrag, sunburstArcVert, sunburstArcFrag, treemapVert, treemapFrag, densitySplatVert, densitySplatFrag, densityExtremeFrag, densityMrtVert, densityMrtFrag, densityResolveVert, densityResolveFrag, tileVert, tileFrag, };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ShaderSpec } from "./shader-manifest";
|
|
2
|
+
type GL = WebGL2RenderingContext | WebGLRenderingContext;
|
|
3
|
+
export declare class ShaderRegistry {
|
|
4
|
+
private _gl;
|
|
5
|
+
private _programs;
|
|
6
|
+
constructor(gl: GL);
|
|
7
|
+
/**
|
|
8
|
+
* Compile + link every program in `specs` eagerly. Used by
|
|
9
|
+
* `WebGLContextManager` when constructed with `precompile: true`
|
|
10
|
+
* so the first-frame path doesn't pay the compile cost inline.
|
|
11
|
+
*
|
|
12
|
+
* Compilation is synchronous and serial — single-digit ms per
|
|
13
|
+
* program on a modern GPU. With `KHR_parallel_shader_compile`
|
|
14
|
+
* (browser-supported but not yet wired here) the work could be
|
|
15
|
+
* dispatched to driver threads; today we accept the wall-time
|
|
16
|
+
* cost in exchange for simpler code and a deterministic init.
|
|
17
|
+
*/
|
|
18
|
+
precompile(specs: readonly ShaderSpec[]): void;
|
|
19
|
+
getOrCreate(name: string, vertSrc: string, fragSrc: string): WebGLProgram;
|
|
20
|
+
releaseAll(): void;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ControlMsg } from "../transport/protocol";
|
|
2
|
+
import type { WorkerRenderer } from "./renderer.worker";
|
|
3
|
+
/**
|
|
4
|
+
* Stateless control-message dispatcher. The renderer instance is
|
|
5
|
+
* supplied by the caller so worker mode (one global instance) and
|
|
6
|
+
* in-process mode (one instance per host element) share the same
|
|
7
|
+
* routing logic.
|
|
8
|
+
*/
|
|
9
|
+
export declare function dispatch(r: WorkerRenderer, msg: ControlMsg): void;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import "./boot";
|
|
2
|
+
import type { Client, Table, View } from "@perspective-dev/client";
|
|
3
|
+
import { WebGLContextManager } from "../webgl/context-manager";
|
|
4
|
+
import { ChartImplementation } from "../charts/chart";
|
|
5
|
+
import { ZoomController } from "../interaction/zoom-controller";
|
|
6
|
+
import type { InitMsg, InteractionEvent, LoadAndRenderMsg, WorkerMsg } from "../transport/protocol";
|
|
7
|
+
export declare class WorkerRenderer {
|
|
8
|
+
chartImpl: ChartImplementation;
|
|
9
|
+
glManager: WebGLContextManager;
|
|
10
|
+
zoomController: ZoomController | null;
|
|
11
|
+
gridlines: OffscreenCanvas;
|
|
12
|
+
chrome: OffscreenCanvas;
|
|
13
|
+
cssWidth: number;
|
|
14
|
+
cssHeight: number;
|
|
15
|
+
dpr: number;
|
|
16
|
+
client: Client;
|
|
17
|
+
view: View;
|
|
18
|
+
/**
|
|
19
|
+
* Source `Table` opened once at bootstrap from the host-supplied
|
|
20
|
+
* `tableName`. Used by `loadAndRender` to fetch the source schema
|
|
21
|
+
* for group-by level types — the worker resolves it itself so the
|
|
22
|
+
* host's render path makes zero `Client`/`Table`/`View` awaits.
|
|
23
|
+
* Null when the host had no table loaded at init time.
|
|
24
|
+
*/
|
|
25
|
+
table: Table | null;
|
|
26
|
+
controlPort: MessagePort;
|
|
27
|
+
/**
|
|
28
|
+
* Monotonic counter bumped by every `loadAndRender` entry. Captured
|
|
29
|
+
* locally as `myGen` and re-checked after each await — a stale
|
|
30
|
+
* value means a newer call has superseded this one and we must
|
|
31
|
+
* bail (throwing inside the `with_typed_arrays` callback so the
|
|
32
|
+
* wasm Arrow buffer release runs cleanly).
|
|
33
|
+
*/
|
|
34
|
+
private _renderGen;
|
|
35
|
+
/**
|
|
36
|
+
* Active drag state. `pointerdown` resolves a target via the
|
|
37
|
+
* facet grid and stores it; `pointermove` consults this until
|
|
38
|
+
* `pointerup` clears it. Pointer capture itself is host-side.
|
|
39
|
+
*/
|
|
40
|
+
private _dragTarget;
|
|
41
|
+
private _lastDragX;
|
|
42
|
+
private _lastDragY;
|
|
43
|
+
constructor(msg: InitMsg, client: Client, view: View, table: Table | null, controlPort: MessagePort, ImplClass: new () => ChartImplementation);
|
|
44
|
+
setViewByName(name: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Full data-fetch + render pipeline. Owns every `Client`/`Table`/
|
|
47
|
+
* `View` await on the render path:
|
|
48
|
+
*
|
|
49
|
+
* 1. Resolve metadata (`view.num_rows`, `view.schema`,
|
|
50
|
+
* `view.expression_schema`, `table.schema`) in parallel.
|
|
51
|
+
* 2. Apply schema + viewer-config to the chart impl (replaces the
|
|
52
|
+
* individual `setColumnTypes` / `setGroupByTypes` /
|
|
53
|
+
* `setViewPivots` / `setColumnSlots` setters that used to
|
|
54
|
+
* stream from the host).
|
|
55
|
+
* 3. Compute `totalRows` from `bufferPool.maxCapacity / numCols`
|
|
56
|
+
* and grow the buffer pool to fit.
|
|
57
|
+
* 4. Run `view.with_typed_arrays`; the inner callback hands the
|
|
58
|
+
* resulting `ColumnDataMap` straight to
|
|
59
|
+
* `chartImpl.uploadAndRender` — no `postMessage`, no transfer.
|
|
60
|
+
*
|
|
61
|
+
* Mid-flight cancellation: each entry bumps `_renderGen` and
|
|
62
|
+
* captures `myGen`. After the metadata await we re-check; if a
|
|
63
|
+
* newer call has superseded this one, ack-and-return so the host
|
|
64
|
+
* promise resolves cleanly. Inside the `with_typed_arrays`
|
|
65
|
+
* callback the same check throws `StaleGenerationError` so the
|
|
66
|
+
* wasm Arrow buffer release path runs (callback's promise must
|
|
67
|
+
* reject for `with_typed_arrays` to unwind) before the next call
|
|
68
|
+
* proceeds — caught and swallowed here.
|
|
69
|
+
*
|
|
70
|
+
* Always sends `loadAndRenderAck` (even on stale drop) per the
|
|
71
|
+
* "resolve on stale" host contract.
|
|
72
|
+
*/
|
|
73
|
+
loadAndRender(msg: LoadAndRenderMsg): Promise<void>;
|
|
74
|
+
redraw(): void;
|
|
75
|
+
resize(cssWidth: number, cssHeight: number, dpr: number): void;
|
|
76
|
+
clear(): void;
|
|
77
|
+
saveZoom(): any;
|
|
78
|
+
restoreZoom(state: any): void;
|
|
79
|
+
allZoomsDefault(): boolean;
|
|
80
|
+
resetAllZooms(): void;
|
|
81
|
+
resetExpandedDomain(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Hit-test the cursor against the chart's facet grid (in faceted
|
|
84
|
+
* mode) or its current layout (single-plot). Mirrors the resolver
|
|
85
|
+
* `_setupZoomRouter` builds on the host for in-process mode — the
|
|
86
|
+
* worker owns the facet grid and controllers, so the resolution
|
|
87
|
+
* runs here.
|
|
88
|
+
*/
|
|
89
|
+
private _resolveTarget;
|
|
90
|
+
onInteraction(event: InteractionEvent): void;
|
|
91
|
+
/**
|
|
92
|
+
* Read the chart impl's `TooltipController`. Charts that don't use
|
|
93
|
+
* one (no `attachTooltip` override) yield `null` and the
|
|
94
|
+
* mouse-event branches fall through.
|
|
95
|
+
*/
|
|
96
|
+
private _tooltip;
|
|
97
|
+
/**
|
|
98
|
+
* Composite the three layers into a single PNG `Blob`.
|
|
99
|
+
*/
|
|
100
|
+
snapshotPng(): Promise<Blob>;
|
|
101
|
+
destroy(): void;
|
|
102
|
+
post(msg: WorkerMsg, transfer?: Transferable[]): void;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* In-process bootstrap. Used when the host loads this same module via
|
|
106
|
+
* `await import(workerURL)` to run the renderer on the main thread —
|
|
107
|
+
* skips the wasm / font / proxy-port plumbing because the host already
|
|
108
|
+
* owns a live `Client` and the document's `FontFaceSet` is the active
|
|
109
|
+
* one.
|
|
110
|
+
*/
|
|
111
|
+
export declare function bootstrapInProcess(opts: {
|
|
112
|
+
msg: InitMsg;
|
|
113
|
+
client: Client;
|
|
114
|
+
controlPort: MessagePort;
|
|
115
|
+
}): Promise<WorkerRenderer>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { InitMsg } from "../transport/protocol";
|
|
2
|
+
import type { WorkerRenderer } from "./renderer.worker";
|
|
3
|
+
/**
|
|
4
|
+
* Adapter that satisfies the `MessagePort` shape `WorkerRenderer`
|
|
5
|
+
* expects (it only ever calls `.postMessage` on it). Outgoing posts
|
|
6
|
+
* get session-tagged on the way out so the host can route them to
|
|
7
|
+
* the right `RendererTransport` instance.
|
|
8
|
+
*
|
|
9
|
+
* The receive direction is handled exclusively by the worker-scope
|
|
10
|
+
* `self.addEventListener("message", …)` installed by `installSessionHost`;
|
|
11
|
+
* this adapter does not own a real port pair.
|
|
12
|
+
*/
|
|
13
|
+
export declare function makeSessionPort(sessionId: number): MessagePort;
|
|
14
|
+
/**
|
|
15
|
+
* Install the shared message handler on the worker scope. One worker
|
|
16
|
+
* process hosts many `WorkerRenderer` instances, one per `sessionId`
|
|
17
|
+
* allocated by the host's `RendererTransport`; this listener
|
|
18
|
+
* demultiplexes incoming `ControlEnvelope`s and routes them to the
|
|
19
|
+
* matching renderer.
|
|
20
|
+
*
|
|
21
|
+
* The `bootstrap` callback constructs a `WorkerRenderer` from an
|
|
22
|
+
* `InitMsg` and a session-tagged port. It's injected so this module
|
|
23
|
+
* doesn't need to import `renderer.worker` for runtime bindings (avoids
|
|
24
|
+
* a runtime cycle — `renderer.worker` imports this module).
|
|
25
|
+
*/
|
|
26
|
+
export declare function installSessionHost(bootstrap: (msg: InitMsg, port: MessagePort) => Promise<WorkerRenderer>): void;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@perspective-dev/viewer-charts",
|
|
3
|
+
"version": "4.3.0",
|
|
4
|
+
"description": "Perspective.js WebGL Plugin",
|
|
5
|
+
"unpkg": "./dist/cdn/perspective-viewer-charts.js",
|
|
6
|
+
"jsdelivr": "./dist/cdn/perspective-viewer-charts.js",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/esm/index.d.ts",
|
|
11
|
+
"default": "./dist/esm/perspective-viewer-charts.js"
|
|
12
|
+
},
|
|
13
|
+
"./src/*": "./src/*",
|
|
14
|
+
"./dist/*": "./dist/*",
|
|
15
|
+
"./cdn/": "./dist/cdn/",
|
|
16
|
+
"./esm/": "./dist/esm/",
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist/**/*",
|
|
21
|
+
"src/**/*"
|
|
22
|
+
],
|
|
23
|
+
"types": "dist/esm/index.d.ts",
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/perspective-dev/perspective"
|
|
30
|
+
},
|
|
31
|
+
"author": "",
|
|
32
|
+
"license": "Apache-2.0",
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@perspective-dev/client": "",
|
|
35
|
+
"@perspective-dev/viewer": "",
|
|
36
|
+
"@perspective-dev/esbuild-plugin": "",
|
|
37
|
+
"@perspective-dev/test": "",
|
|
38
|
+
"@types/node": ">=22",
|
|
39
|
+
"lightningcss": "^1.29.0",
|
|
40
|
+
"typescript": ">=5 <6",
|
|
41
|
+
"webpack-glsl-minify": "1.5.0"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "node ./build.mjs",
|
|
45
|
+
"clean": "node ./clean.mjs"
|
|
46
|
+
}
|
|
47
|
+
}
|