@gjsify/webgl 0.26.1 → 0.27.1
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/README.md +40 -11
- package/lib/esm/html-canvas-element.js +1 -1
- package/lib/esm/html-canvas-element.spec.js +1 -0
- package/lib/esm/test.js +1 -1
- package/lib/esm/webgl-bridge.js +1 -1
- package/lib/types/html-canvas-element.d.ts +30 -4
- package/lib/types/webgl-bridge.d.ts +1 -1
- package/package.json +22 -13
- package/prebuilds/linux-arm64/Gwebgl-0.1.typelib +0 -0
- package/prebuilds/linux-arm64/libgwebgl.so +0 -0
- package/prebuilds/linux-ppc64/Gwebgl-0.1.typelib +0 -0
- package/prebuilds/linux-ppc64/libgwebgl.so +0 -0
- package/prebuilds/linux-riscv64/Gwebgl-0.1.typelib +0 -0
- package/prebuilds/linux-riscv64/libgwebgl.so +0 -0
- package/prebuilds/linux-s390x/Gwebgl-0.1.typelib +0 -0
- package/prebuilds/linux-s390x/libgwebgl.so +0 -0
- package/prebuilds/linux-x64/Gwebgl-0.1.typelib +0 -0
- package/prebuilds/linux-x64/libgwebgl.so +0 -0
package/README.md
CHANGED
|
@@ -113,9 +113,11 @@ yarn build:prebuilds
|
|
|
113
113
|
|
|
114
114
|
## Prebuilt binaries
|
|
115
115
|
|
|
116
|
-
Prebuilds for
|
|
116
|
+
Prebuilds for every target in `package.json#gjsify.platforms` are built automatically by CI
|
|
117
117
|
(`.github/workflows/prebuilds.yml`) when the Vala source changes and committed back
|
|
118
|
-
to the repository.
|
|
118
|
+
to the repository. Since ADR 0017 each one ships in its own
|
|
119
|
+
`@gjsify/webgl-<os>-<arch>` package, referenced from here as an `optionalDependency`, so a
|
|
120
|
+
consumer installs only the artifact that fits its platform.
|
|
119
121
|
|
|
120
122
|
## Inspirations and credits
|
|
121
123
|
|
|
@@ -130,17 +132,44 @@ to the repository. They are included in the npm package via the `files` field.
|
|
|
130
132
|
| `linux-x64` | ✅ `libgwebgl.so` + `Gwebgl-0.1.typelib` | native runner |
|
|
131
133
|
| `linux-arm64` | ✅ | native runner |
|
|
132
134
|
| `linux-ppc64`, `linux-s390x`, `linux-riscv64` | ✅ | QEMU emulation |
|
|
133
|
-
|
|
|
135
|
+
| `darwin-arm64` / `darwin-x64` | ✅ `libgwebgl.dylib` + `Gwebgl-0.1.typelib` | native runner — **WebGL1 only, see below** |
|
|
134
136
|
| Windows | ❌ | — no Vala/GI bridge in this repo targets Windows |
|
|
135
137
|
|
|
136
|
-
**macOS
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
**macOS renders — WebGL1 only.** Measured on macOS 15.7.8 / x86_64 with gtk 4.22 and
|
|
139
|
+
libepoxy 1.5.10: `Gtk.GLArea` realizes a `GdkMacosGLContext`, and this bridge draws real
|
|
140
|
+
pixels through it. That describes the GL stack once GTK is loaded — reaching it needed
|
|
141
|
+
`DYLD_LIBRARY_PATH=/usr/local/lib` exported by hand, because the `Gtk-4.0` typelib names a
|
|
142
|
+
bare `libgtk-4.1.dylib` leaf that a Homebrew prefix does not put on the loader's search path
|
|
143
|
+
for every host; that defect is tracked and fixed separately. Two further limits come from the
|
|
144
|
+
platform, not from the bridge:
|
|
145
|
+
|
|
146
|
+
- GTK4's macOS backend goes through **CGL, which offers desktop OpenGL only** — no GLES
|
|
147
|
+
profile at any version. A GLES-exclusive request (`gtk_gl_area_set_use_es(TRUE)`) fails
|
|
148
|
+
with *"Application does not support OpenGL API"*, so `WebGLBridge` declares
|
|
149
|
+
`set_allowed_apis(GL | GLES)` and lets GDK choose: GLES 3.2 where it exists, desktop
|
|
150
|
+
GL 4.1 on macOS.
|
|
151
|
+
- Desktop GL 4.1 has **no GLSL ES 3.00 compiler** (that needs `ARB_ES3_compatibility`, GL 4.3),
|
|
152
|
+
so `#version 300 es` shaders — i.e. all WebGL2 content, including three.js ≥ r163 and
|
|
153
|
+
Excalibur 0.32 — do not compile. `#version 100` (WebGL1) does, via `ARB_ES2_compatibility`.
|
|
154
|
+
Of the 219 GL entry points the library references, exactly two are absent from Apple's
|
|
155
|
+
`OpenGL.framework` (`glInvalidateFramebuffer`, `glInvalidateSubFramebuffer`, both GL 4.3);
|
|
156
|
+
they are gated on `epoxy_gl_version() >= 43` because libepoxy aborts rather than returning
|
|
157
|
+
null.
|
|
158
|
+
|
|
159
|
+
Remaining darwin gaps are tracked in [`status/open-todos.md`](../../../status/open-todos.md).
|
|
160
|
+
|
|
161
|
+
## Diagnosing a host
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
gjsify run packages/framework/webgl/scripts/probe-gl-host.js [--seconds N]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Configures a bare `Gtk.GLArea` exactly as `WebGLBridge` does and reports the negotiated GL API
|
|
168
|
+
and version, the widget scale factor, the logical allocation versus the device-pixel drawing
|
|
169
|
+
buffer, the GL vendor/renderer/GLSL strings and which shader dialects compile — then draws a
|
|
170
|
+
recognisable pattern using only `clearColor` + `scissor` + `clear`, so a blank window can never
|
|
171
|
+
be mistaken for a failed shader. Exits non-zero when the GLArea does not realize. It needs a
|
|
172
|
+
real display, which is why it is a script rather than a spec.
|
|
144
173
|
|
|
145
174
|
## License
|
|
146
175
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{WebGLRenderingContext as e}from"./webgl-rendering-context.js";import{WebGL2RenderingContext as t}from"./webgl2-rendering-context.js";import{HTMLCanvasElement as n}from"@gjsify/dom-elements";var HTMLCanvasElement=class extends n{constructor(e){super(),this.gtkGlArea=e}get width(){return this.gtkGlArea.get_allocated_width()}set width(e){}get height(){return this.gtkGlArea.get_allocated_height()}set height(e){}get clientWidth(){return this.
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{WebGLRenderingContext as e}from"./webgl-rendering-context.js";import{WebGL2RenderingContext as t}from"./webgl2-rendering-context.js";import{HTMLCanvasElement as n}from"@gjsify/dom-elements";var HTMLCanvasElement=class extends n{constructor(e){super(),this.gtkGlArea=e}get width(){return this.gtkGlArea.get_allocated_width()*this.scaleFactor}set width(e){}get height(){return this.gtkGlArea.get_allocated_height()*this.scaleFactor}set height(e){}get scaleFactor(){return this.gtkGlArea.get_scale_factor()||1}get clientWidth(){return this.gtkGlArea.get_allocated_width()}get clientHeight(){return this.gtkGlArea.get_allocated_height()}get offsetWidth(){return this.clientWidth}get offsetHeight(){return this.clientHeight}getGlArea(){return this.gtkGlArea}getContext(n,r){return n===`webgl`||n===`experimental-webgl`?(this._webgl||=(this.gtkGlArea.make_current(),new e(this,r)),this._webgl):n===`webgl2`?(this._webgl2||=(this.gtkGlArea.make_current(),new t(this,r)),this._webgl2):super.getContext(n,r)}};export{HTMLCanvasElement};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{__name as e}from"./_virtual/_rolldown/runtime.js";import{HTMLCanvasElement as t}from"./html-canvas-element.js";import{describe as n,expect as r,it as i}from"@gjsify/unit";function stubGlArea(e,t,n){return{get_allocated_width:()=>e,get_allocated_height:()=>t,get_scale_factor:()=>n}}var a=e(async()=>{await n(`HTMLCanvasElement (GLArea) — drawing buffer vs CSS size`,async()=>{await i(`reports the drawing buffer in DEVICE pixels on a HiDPI surface`,async()=>{let e=new t(stubGlArea(360,655,3));r(e.width).toBe(1080),r(e.height).toBe(1965)}),await i(`keeps the CSS layout size LOGICAL on the same surface`,async()=>{let e=new t(stubGlArea(360,655,3));r(e.clientWidth).toBe(360),r(e.clientHeight).toBe(655),r(e.offsetWidth).toBe(360),r(e.offsetHeight).toBe(655)}),await i(`CSS size × devicePixelRatio equals the drawing buffer`,async()=>{let e=new t(stubGlArea(800,600,2));r(e.clientWidth*e.scaleFactor).toBe(e.width),r(e.clientHeight*e.scaleFactor).toBe(e.height)}),await i(`is a no-op change at scale-factor 1 (every pre-HiDPI host)`,async()=>{let e=new t(stubGlArea(1024,768,1));r(e.width).toBe(1024),r(e.height).toBe(768),r(e.clientWidth).toBe(1024),r(e.clientHeight).toBe(768)}),await i(`treats an unrealized widget (scale 0) as scale 1, not as a 0×0 buffer`,async()=>{let e=new t(stubGlArea(640,480,0));r(e.scaleFactor).toBe(1),r(e.width).toBe(640),r(e.height).toBe(480)}),await i(`ignores width/height writes — GTK owns the allocation`,async()=>{let e=new t(stubGlArea(360,655,3));e.width=42,e.height=42,r(e.width).toBe(1080),r(e.height).toBe(1965)})})},`default`);export{a as default};
|
package/lib/esm/test.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import e from"./
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import e from"./html-canvas-element.spec.js";import t from"./register.spec.js";import n from"./webgl1.spec.js";import r from"./webgl2.spec.js";import{run as i}from"@gjsify/unit";i({testSuite:async()=>{await n(),await r(),await e()},registerSuite:t});
|
package/lib/esm/webgl-bridge.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{WebGLRenderingContext as e}from"./webgl-rendering-context.js";import{WebGL2RenderingContext as t}from"./webgl2-rendering-context.js";import{HTMLCanvasElement as n}from"./html-canvas-element.js";import{notifyElementResize as r}from"@gjsify/dom-elements";import i from"gi://GObject";import a from"gi://GLib?version=2.0";import
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{WebGLRenderingContext as e}from"./webgl-rendering-context.js";import{WebGL2RenderingContext as t}from"./webgl2-rendering-context.js";import{HTMLCanvasElement as n}from"./html-canvas-element.js";import{notifyElementResize as r}from"@gjsify/dom-elements";import i from"gi://GObject";import a from"gi://Gdk?version=4.0";import o from"gi://GLib?version=2.0";import s from"gi://Gtk?version=4.0";import{attachEventControllers as c}from"@gjsify/event-bridge";import{Event as l}from"@gjsify/dom-events";const u=i.registerClass({GTypeName:`GjsifyWebGLBridge`},class WebGLBridge extends s.GLArea{constructor(e){super(e),this._canvas=null,this._readyCallbacks=[],this._resizeCallbacks=[],this._renderTag=null,this._tickCallbackId=null,this._frameCallback=null,this._lastFrameCallback=null,this._lastFrameTime=0,this._replaying=!1,this._frameCallbackId=0,this._nextFrameId=1,this._timeOrigin=o.get_monotonic_time(),this.set_allowed_apis(a.GLAPI.GL|a.GLAPI.GLES),this.set_required_version(3,2),this.set_has_depth_buffer(!0),this.set_has_stencil_buffer(!0),c(this,()=>this._canvas,{captureKeys:!0}),this._tickCallbackId=this.add_tick_callback((e,t)=>(this._frameCallback!==null&&this.queue_render(),o.SOURCE_CONTINUE));let t=this.connect(`render`,()=>{this.disconnect(t),this.make_current(),this._canvas=new n(this);{let e=globalThis;e.document?.body&&e.document.body.appendChild(this._canvas)}this._canvas.getContext(`webgl2`);let e=this._canvas.getContext(`webgl`);if(e){for(let t of this._readyCallbacks)t(this._canvas,e);this._readyCallbacks=[]}return this._renderTag=this.connect(`render`,e=>{let t=(o.get_monotonic_time()-this._timeOrigin)/1e3;if(this._frameCallback!==null){globalThis.__GJSIFY_DEBUG_RAF===!0&&console.log(`[rAF] frame callback fires t=${t.toFixed(1)}`);let e=this._frameCallback;this._frameCallback=null,this._frameCallbackId=0,this._lastFrameCallback=e,this._lastFrameTime=t,e(t)}else if(this._lastFrameCallback!==null){this._replaying=!0;try{this._lastFrameCallback(this._lastFrameTime)}finally{this._replaying=!1}}return!0}),!0});this.connect(`resize`,()=>{let e=this.get_allocated_width(),t=this.get_allocated_height();this._canvas&&(this._canvas.dispatchEvent(new l(`resize`)),r(this._canvas,e,t));for(let n of this._resizeCallbacks)n(e,t);this._frameCallback&&this.requestAnimationFrame(this._frameCallback)}),this.connect(`unrealize`,()=>{this._renderTag!==null&&(this.disconnect(this._renderTag),this._renderTag=null),this._tickCallbackId!==null&&(this.remove_tick_callback(this._tickCallbackId),this._tickCallbackId=null),this._frameCallback=null,this._lastFrameCallback=null,this._lastFrameTime=0,this._replaying=!1,this._canvas=null})}get canvas(){return this._canvas}onReady(e){if(this._canvas){let t=this._canvas.getContext(`webgl`);if(t){e(this._canvas,t);return}}this._readyCallbacks.push(e)}onWebGLReady(e){this.onReady(e)}onResize(e){this._resizeCallbacks.push(e)}requestAnimationFrame(e){let t=this._nextFrameId++;return this._replaying?t:(this._frameCallback=e,this._frameCallbackId=t,this.queue_render(),t)}cancelAnimationFrame(e){e!==0&&e===this._frameCallbackId&&(this._frameCallback=null,this._frameCallbackId=0,this._lastFrameCallback=null,this._lastFrameTime=0)}installGlobals(){let n=globalThis;n.requestAnimationFrame=e=>this.requestAnimationFrame(e),n.cancelAnimationFrame=e=>this.cancelAnimationFrame(e),n.WebGLRenderingContext=e,n.WebGL2RenderingContext=t,Object.defineProperty(globalThis,"devicePixelRatio",{get:()=>this.get_scale_factor()||1,configurable:!0});let r=this._timeOrigin;n.performance={now:()=>(o.get_monotonic_time()-r)/1e3,timeOrigin:Date.now()}}});export{u as WebGLBridge};
|
|
@@ -7,17 +7,43 @@ export declare class HTMLCanvasElement extends BaseHTMLCanvasElement {
|
|
|
7
7
|
_webgl?: OurWebGLRenderingContext;
|
|
8
8
|
_webgl2?: OurWebGL2RenderingContext;
|
|
9
9
|
constructor(gtkGlArea: Gtk.GLArea);
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* DRAWING-BUFFER width, in DEVICE pixels (overrides the DOM attr-backed getter).
|
|
12
|
+
*
|
|
13
|
+
* GtkGLArea's framebuffer is `allocation × scale-factor`, and the GL viewport
|
|
14
|
+
* is raw device pixels — GTK does NOT apply the surface scale to GL the way
|
|
15
|
+
* it silently pre-scales a Cairo context for `Gtk.DrawingArea`. So on a
|
|
16
|
+
* scale-factor-3 display (a phone) a viewport computed from the ALLOCATION
|
|
17
|
+
* covers the bottom-left ninth of the framebuffer and the rest stays at the
|
|
18
|
+
* clear colour. Measured on a OnePlus 6T / postmarketOS, GNOME Mobile,
|
|
19
|
+
* 1080×2340 at scale 3: the three.js teapot and the Excalibur game each
|
|
20
|
+
* rendered into a 120×218 corner of a 360×655-logical widget.
|
|
21
|
+
*
|
|
22
|
+
* Reporting device pixels here is also what the browser contract means by
|
|
23
|
+
* `canvas.width` — the drawing buffer, which is exactly what
|
|
24
|
+
* `WebGLRenderingContextBase.drawingBufferWidth` re-exports. CSS layout size
|
|
25
|
+
* stays logical (`clientWidth`/`offsetWidth` below), so a consumer that
|
|
26
|
+
* multiplies a layout size by `devicePixelRatio` (`installGlobals()` exposes
|
|
27
|
+
* the live scale factor) lands on the same number.
|
|
28
|
+
*/
|
|
11
29
|
get width(): number;
|
|
12
30
|
set width(_width: number);
|
|
13
|
-
/**
|
|
31
|
+
/** DRAWING-BUFFER height, in DEVICE pixels. See `width` for why it is scaled. */
|
|
14
32
|
get height(): number;
|
|
15
33
|
set height(_height: number);
|
|
34
|
+
/**
|
|
35
|
+
* The widget's surface scale factor (1 on a standard display, 2–3 on HiDPI).
|
|
36
|
+
* Read live rather than cached: moving a window between monitors changes it,
|
|
37
|
+
* and GTK re-allocates the widget rather than recreating the canvas.
|
|
38
|
+
*/
|
|
39
|
+
get scaleFactor(): number;
|
|
40
|
+
/** CSS layout width — the GTK allocation, in LOGICAL pixels. */
|
|
16
41
|
get clientWidth(): number;
|
|
42
|
+
/** CSS layout height — the GTK allocation, in LOGICAL pixels. */
|
|
17
43
|
get clientHeight(): number;
|
|
18
|
-
/** CSS layout width — same as
|
|
44
|
+
/** CSS layout width — same as `clientWidth` for a border-less canvas. */
|
|
19
45
|
get offsetWidth(): number;
|
|
20
|
-
/** CSS layout height — same as
|
|
46
|
+
/** CSS layout height — same as `clientHeight` for a border-less canvas. */
|
|
21
47
|
get offsetHeight(): number;
|
|
22
48
|
/** Returns the underlying Gtk.GLArea. Used by WebGLRenderingContext for GLSL version detection. */
|
|
23
49
|
getGlArea(): Gtk.GLArea;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import GObject from 'gi://GObject';
|
|
2
|
-
import
|
|
2
|
+
import Gdk from 'gi://Gdk?version=4.0';
|
|
3
3
|
import GLib from 'gi://GLib?version=2.0';
|
|
4
4
|
import Gtk from 'gi://Gtk?version=4.0';
|
|
5
5
|
import { HTMLCanvasElement as OurHTMLCanvasElement } from './html-canvas-element.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/webgl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.1",
|
|
4
4
|
"description": "WebGL module for Gjs",
|
|
5
5
|
"module": "lib/esm/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
"./lib/esm/register.js"
|
|
20
20
|
],
|
|
21
21
|
"files": [
|
|
22
|
-
"lib"
|
|
23
|
-
"prebuilds"
|
|
22
|
+
"lib"
|
|
24
23
|
],
|
|
25
24
|
"gjsify": {
|
|
26
25
|
"platforms": [
|
|
@@ -28,9 +27,10 @@
|
|
|
28
27
|
"linux-arm64",
|
|
29
28
|
"linux-ppc64",
|
|
30
29
|
"linux-s390x",
|
|
31
|
-
"linux-riscv64"
|
|
30
|
+
"linux-riscv64",
|
|
31
|
+
"darwin-arm64",
|
|
32
|
+
"darwin-x64"
|
|
32
33
|
],
|
|
33
|
-
"prebuilds": "prebuilds",
|
|
34
34
|
"runtimes": {
|
|
35
35
|
"gjs": "polyfill",
|
|
36
36
|
"node": "none",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"tier": 1
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
|
-
"clear": "
|
|
43
|
+
"clear": "gjsify clear lib tmp build test.gjs.mjs tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo",
|
|
44
44
|
"check": "gjsify tsc --noEmit",
|
|
45
45
|
"init:meson": "meson setup build .",
|
|
46
46
|
"init:meson:wipe": "gjsify run init:meson --wipe",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"WebGL"
|
|
61
61
|
],
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@gjsify/cli": "^0.
|
|
64
|
-
"@gjsify/unit": "^0.
|
|
63
|
+
"@gjsify/cli": "^0.27.1",
|
|
64
|
+
"@gjsify/unit": "^0.27.1",
|
|
65
65
|
"@types/bit-twiddle": "^1.0.3",
|
|
66
66
|
"@types/node": "^25.9.2",
|
|
67
67
|
"typescript": "^6.0.3"
|
|
@@ -71,10 +71,10 @@
|
|
|
71
71
|
"@girs/gjs": "^4.1.0",
|
|
72
72
|
"@girs/gtk-4.0": "^4.1.0",
|
|
73
73
|
"@girs/gwebgl-0.1": "0.1.0-4.0.0-rc.5",
|
|
74
|
-
"@gjsify/dom-elements": "^0.
|
|
75
|
-
"@gjsify/dom-events": "^0.
|
|
76
|
-
"@gjsify/event-bridge": "^0.
|
|
77
|
-
"@gjsify/utils": "^0.
|
|
74
|
+
"@gjsify/dom-elements": "^0.27.1",
|
|
75
|
+
"@gjsify/dom-events": "^0.27.1",
|
|
76
|
+
"@gjsify/event-bridge": "^0.27.1",
|
|
77
|
+
"@gjsify/utils": "^0.27.1",
|
|
78
78
|
"bit-twiddle": "^1.0.2",
|
|
79
79
|
"glsl-tokenizer": "^2.1.5"
|
|
80
80
|
},
|
|
@@ -87,5 +87,14 @@
|
|
|
87
87
|
"bugs": {
|
|
88
88
|
"url": "https://github.com/gjsify/gjsify/issues"
|
|
89
89
|
},
|
|
90
|
-
"homepage": "https://github.com/gjsify/gjsify/tree/main/packages/framework/webgl#readme"
|
|
90
|
+
"homepage": "https://github.com/gjsify/gjsify/tree/main/packages/framework/webgl#readme",
|
|
91
|
+
"optionalDependencies": {
|
|
92
|
+
"@gjsify/webgl-darwin-arm64": "0.27.1",
|
|
93
|
+
"@gjsify/webgl-darwin-x64": "0.27.1",
|
|
94
|
+
"@gjsify/webgl-linux-arm64": "0.27.1",
|
|
95
|
+
"@gjsify/webgl-linux-ppc64": "0.27.1",
|
|
96
|
+
"@gjsify/webgl-linux-riscv64": "0.27.1",
|
|
97
|
+
"@gjsify/webgl-linux-s390x": "0.27.1",
|
|
98
|
+
"@gjsify/webgl-linux-x64": "0.27.1"
|
|
99
|
+
}
|
|
91
100
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|