xbintsc 0.5.31 → 0.5.32

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.
Files changed (181) hide show
  1. package/README.md +16 -10
  2. package/dist/src/binder/references.js +14 -1
  3. package/dist/src/binder/references.js.map +1 -1
  4. package/dist/src/cli/help.d.ts +1 -1
  5. package/dist/src/codegen/generator/module.d.ts +1 -0
  6. package/dist/src/codegen/generator/module.js +54 -0
  7. package/dist/src/codegen/generator/module.js.map +1 -1
  8. package/dist/src/codegen/generator/statements/variables.js +6 -4
  9. package/dist/src/codegen/generator/statements/variables.js.map +1 -1
  10. package/dist/src/driver/version.d.ts +1 -1
  11. package/dist/src/driver/version.js +1 -1
  12. package/dist/src/extensions/gui/css.d.ts +26 -0
  13. package/dist/src/extensions/gui/css.js +100 -0
  14. package/dist/src/extensions/gui/css.js.map +1 -0
  15. package/dist/src/extensions/gui/html.js +9 -2
  16. package/dist/src/extensions/gui/html.js.map +1 -1
  17. package/dist/src/extensions/gui/index.js +16 -2
  18. package/dist/src/extensions/gui/index.js.map +1 -1
  19. package/dist/src/extensions/gui/three.d.ts +16 -0
  20. package/dist/src/extensions/gui/three.js +22 -0
  21. package/dist/src/extensions/gui/three.js.map +1 -0
  22. package/dist/src/extensions/media/index.d.ts +6 -5
  23. package/dist/src/extensions/media/index.js +12 -14
  24. package/dist/src/extensions/media/index.js.map +1 -1
  25. package/dist/tests/e2e/compile-builtins.test.js +24 -0
  26. package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
  27. package/dist/tests/e2e/compile-objects-classes.test.js +23 -0
  28. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
  29. package/dist/tests/e2e/gui-browser.test.js +1 -1
  30. package/dist/tests/e2e/gui-browser.test.js.map +1 -1
  31. package/dist/tests/e2e/gui-effects.test.d.ts +6 -0
  32. package/dist/tests/e2e/gui-effects.test.js +262 -0
  33. package/dist/tests/e2e/gui-effects.test.js.map +1 -0
  34. package/dist/tests/e2e/gui-example-webgl.test.d.ts +10 -0
  35. package/dist/tests/e2e/gui-example-webgl.test.js +75 -0
  36. package/dist/tests/e2e/gui-example-webgl.test.js.map +1 -0
  37. package/dist/tests/e2e/gui-example-webgl2.test.d.ts +8 -0
  38. package/dist/tests/e2e/gui-example-webgl2.test.js +72 -0
  39. package/dist/tests/e2e/gui-example-webgl2.test.js.map +1 -0
  40. package/dist/tests/e2e/gui-layout.test.js +48 -0
  41. package/dist/tests/e2e/gui-layout.test.js.map +1 -1
  42. package/dist/tests/e2e/gui-media.test.js +5 -4
  43. package/dist/tests/e2e/gui-media.test.js.map +1 -1
  44. package/dist/tests/e2e/gui-webgl.test.d.ts +11 -0
  45. package/dist/tests/e2e/gui-webgl.test.js +179 -0
  46. package/dist/tests/e2e/gui-webgl.test.js.map +1 -0
  47. package/dist/tests/e2e/gui-webgl2.test.d.ts +10 -0
  48. package/dist/tests/e2e/gui-webgl2.test.js +238 -0
  49. package/dist/tests/e2e/gui-webgl2.test.js.map +1 -0
  50. package/dist/tests/extensions/gui.test.js +41 -0
  51. package/dist/tests/extensions/gui.test.js.map +1 -1
  52. package/dist/tests/extensions/media.test.js +7 -3
  53. package/dist/tests/extensions/media.test.js.map +1 -1
  54. package/doc/ai/extensions.md +29 -9
  55. package/doc/ai/troubleshooting.md +12 -8
  56. package/doc/ai/zh-CN/extensions.md +26 -8
  57. package/doc/ai/zh-CN/troubleshooting.md +10 -6
  58. package/doc/gui/api.md +3 -2
  59. package/doc/gui/build.md +72 -16
  60. package/doc/gui/canvas.md +11 -3
  61. package/doc/gui/dom.md +33 -18
  62. package/doc/gui/known-issues.md +57 -24
  63. package/doc/gui/layout.md +18 -0
  64. package/doc/gui/media.md +17 -13
  65. package/doc/gui/rendering.md +50 -3
  66. package/doc/gui/webgl.md +256 -0
  67. package/doc/gui.md +108 -17
  68. package/doc/npm-package.md +6 -4
  69. package/doc/requirements.md +18 -9
  70. package/doc/zh-CN/gui/api.md +3 -2
  71. package/doc/zh-CN/gui/build.md +64 -15
  72. package/doc/zh-CN/gui/canvas.md +9 -2
  73. package/doc/zh-CN/gui/dom.md +20 -7
  74. package/doc/zh-CN/gui/known-issues.md +45 -19
  75. package/doc/zh-CN/gui/layout.md +14 -0
  76. package/doc/zh-CN/gui/media.md +15 -11
  77. package/doc/zh-CN/gui/rendering.md +41 -4
  78. package/doc/zh-CN/gui/webgl.md +115 -0
  79. package/doc/zh-CN/gui.md +89 -14
  80. package/doc/zh-CN/npm-package.md +9 -6
  81. package/doc/zh-CN/requirements.md +12 -6
  82. package/llms.txt +2 -0
  83. package/package.json +1 -1
  84. package/runtime/ext_gui/browser.cpp +39 -13
  85. package/runtime/ext_gui/canvas.cpp +3 -18
  86. package/runtime/ext_gui/canvas_internal.h +10 -0
  87. package/runtime/ext_gui/canvas_raster.cpp +60 -0
  88. package/runtime/ext_gui/clip_values.cpp +246 -0
  89. package/runtime/ext_gui/css.cpp +94 -0
  90. package/runtime/ext_gui/css.h +22 -1
  91. package/runtime/ext_gui/css_match.cpp +3 -0
  92. package/runtime/ext_gui/css_selector.cpp +9 -0
  93. package/runtime/ext_gui/css_sheet.cpp +89 -45
  94. package/runtime/ext_gui/document.cpp +4 -1
  95. package/runtime/ext_gui/document.h +2 -0
  96. package/runtime/ext_gui/dom.h +16 -0
  97. package/runtime/ext_gui/dom_api.cpp +1 -0
  98. package/runtime/ext_gui/dom_api_canvas.cpp +17 -80
  99. package/runtime/ext_gui/dom_api_canvas_extra.cpp +130 -1
  100. package/runtime/ext_gui/dom_api_canvas_pending.cpp +41 -0
  101. package/runtime/ext_gui/dom_api_internal.h +259 -0
  102. package/runtime/ext_gui/dom_api_webgl.cpp +376 -0
  103. package/runtime/ext_gui/dom_api_webgl2.cpp +434 -0
  104. package/runtime/ext_gui/dom_api_webgl2_draw.cpp +269 -0
  105. package/runtime/ext_gui/dom_api_webgl_buffer.cpp +212 -0
  106. package/runtime/ext_gui/dom_api_webgl_rt.h +30 -0
  107. package/runtime/ext_gui/dom_api_webgl_shader.cpp +443 -0
  108. package/runtime/ext_gui/dom_api_webgl_state.cpp +444 -0
  109. package/runtime/ext_gui/dom_api_webgl_texture.cpp +445 -0
  110. package/runtime/ext_gui/effect_values.cpp +312 -0
  111. package/runtime/ext_gui/gradient_values.cpp +476 -0
  112. package/runtime/ext_gui/grid_values.cpp +230 -0
  113. package/runtime/ext_gui/gui_canvas.cpp +50 -2
  114. package/runtime/ext_gui/gui_engine.h +27 -0
  115. package/runtime/ext_gui/gui_events.cpp +4 -1
  116. package/runtime/ext_gui/gui_media.cpp +1 -1
  117. package/runtime/ext_gui/gui_webgl.cpp +83 -0
  118. package/runtime/ext_gui/layout.cpp +21 -0
  119. package/runtime/ext_gui/layout_flow.cpp +81 -4
  120. package/runtime/ext_gui/layout_flow_internal.h +31 -0
  121. package/runtime/ext_gui/layout_grid.cpp +374 -0
  122. package/runtime/ext_gui/media.h +1 -1
  123. package/runtime/ext_gui/media_api.h +2 -2
  124. package/runtime/ext_gui/media_query.cpp +211 -0
  125. package/runtime/ext_gui/paint.cpp +111 -77
  126. package/runtime/ext_gui/paint.h +33 -3
  127. package/runtime/ext_gui/paint_background.cpp +229 -0
  128. package/runtime/ext_gui/paint_clip.cpp +268 -0
  129. package/runtime/ext_gui/paint_effects.cpp +324 -0
  130. package/runtime/ext_gui/paint_internal.h +85 -0
  131. package/runtime/ext_gui/renderer.cpp +8 -31
  132. package/runtime/ext_gui/renderer_clip.cpp +196 -0
  133. package/runtime/ext_gui/renderer_image.cpp +13 -8
  134. package/runtime/ext_gui/renderer_internal.h +15 -8
  135. package/runtime/ext_gui/renderer_text.cpp +6 -31
  136. package/runtime/ext_gui/style.cpp +343 -20
  137. package/runtime/ext_gui/style.h +144 -3
  138. package/runtime/ext_gui/style_print.cpp +134 -1
  139. package/runtime/ext_gui/style_values.cpp +152 -126
  140. package/runtime/ext_gui/style_values_internal.h +35 -0
  141. package/runtime/ext_gui/webgl.h +466 -0
  142. package/runtime/ext_gui/webgl2_constants.h +274 -0
  143. package/runtime/ext_gui/webgl_buffer.cpp +565 -0
  144. package/runtime/ext_gui/webgl_constants.h +317 -0
  145. package/runtime/ext_gui/webgl_context.cpp +466 -0
  146. package/runtime/ext_gui/webgl_draw.cpp +495 -0
  147. package/runtime/ext_gui/webgl_glsl.h +125 -0
  148. package/runtime/ext_gui/webgl_glsl_compile.cpp +431 -0
  149. package/runtime/ext_gui/webgl_glsl_rewrite.cpp +349 -0
  150. package/runtime/ext_gui/webgl_glsl_scan.cpp +581 -0
  151. package/runtime/ext_gui/webgl_msl.cpp +62 -0
  152. package/runtime/ext_gui/webgl_msl.h +33 -0
  153. package/runtime/ext_gui/webgl_pipeline.cpp +274 -0
  154. package/runtime/ext_gui/webgl_program_internal.h +18 -0
  155. package/runtime/ext_gui/webgl_shader.cpp +582 -0
  156. package/runtime/ext_gui/webgl_texture.cpp +293 -0
  157. package/runtime/ext_gui/webgl_uniform.cpp +167 -0
  158. package/runtime/ext_gui/webgl_webgl2.cpp +224 -0
  159. package/runtime/ext_media/media.cpp +1 -1
  160. package/runtime/ext_media/media_bridge.c +9 -3
  161. package/runtime/rt_internal.h +1 -0
  162. package/runtime/xt_containers/access.inc +8 -0
  163. package/runtime/xt_regex/api.inc +2 -0
  164. package/runtime/xt_regex/matcher.inc +16 -3
  165. package/runtime/xt_regex/parser.inc +8 -2
  166. package/runtime/xt_regex/types.inc +3 -0
  167. package/runtime/xt_stdlib2/regexp-match.inc +60 -21
  168. package/runtime/xt_stdlib2/regexp.inc +1 -0
  169. package/runtime/xt_typed_array.c +1 -1
  170. package/scripts/build-gui.ts +90 -3
  171. package/scripts/build-media.ts +323 -58
  172. package/scripts/setup-vs-toolchain.ps1 +152 -0
  173. package/src/binder/references.ts +13 -1
  174. package/src/codegen/generator/module.ts +50 -0
  175. package/src/codegen/generator/statements/variables.ts +6 -3
  176. package/src/driver/version.ts +1 -1
  177. package/src/extensions/gui/css.ts +113 -0
  178. package/src/extensions/gui/html.ts +9 -2
  179. package/src/extensions/gui/index.ts +16 -2
  180. package/src/extensions/gui/three.ts +25 -0
  181. package/src/extensions/media/index.ts +13 -16
@@ -0,0 +1,256 @@
1
+ # WebGL (a `<canvas>` drawn on the GPU)
2
+
3
+ > Part of the [GUI extension](../gui.md); the engine overview, locked
4
+ > decisions and roadmap live there.
5
+
6
+ A `<canvas>` can ask for a WebGL context instead of the 2D one:
7
+
8
+ ```ts
9
+ const canvas: any = document.getElementById("scene");
10
+ const gl: any = canvas.getContext("webgl2"); // or "webgl" / "experimental-webgl"
11
+ if (gl == null) {
12
+ // no GPU backend that can consume WebGL's shaders on this platform
13
+ }
14
+ ```
15
+
16
+ Unlike the 2D context, which rasterises into a CPU bitmap and uploads it as a
17
+ texture, a WebGL context **renders on the GPU**: vertex transform, lighting,
18
+ texture sampling, depth testing and blending all execute in the SDL_GPU
19
+ pipeline (Vulkan on Windows/Linux, Metal on macOS). The page composites the
20
+ context's colour texture directly, so no pixels are read back to the CPU for
21
+ display.
22
+
23
+ Both **WebGL 1.0** and **WebGL 2.0** are available. A canvas keeps the first
24
+ context kind it asks for: after `getContext("webgl2")` a later
25
+ `getContext("webgl")` answers `null`, and the other way round. A WebGL 2 context
26
+ also satisfies `instanceof WebGLRenderingContext` (its prototype inherits the
27
+ WebGL 1 one) and adds the WebGL 2 constants and methods.
28
+
29
+ ## How a frame reaches the screen
30
+
31
+ - Each context owns one offscreen `R8G8B8A8_UNORM` colour texture (the drawing
32
+ buffer) and a `D32_FLOAT` depth texture, sized from the canvas's `width` /
33
+ `height` attributes. `canvas.width = …` recreates them and discards the
34
+ contents, like the DOM rule.
35
+ - The context records into its own SDL_GPU command buffer. `clear`/`draw*`
36
+ keep a render pass open; a buffer/texture upload or a framebuffer change ends
37
+ it and starts a new pass with `LOAD`, so the drawing buffer persists between
38
+ draws just like WebGL's.
39
+ - Once per frame, before the page's own render pass, the engine submits every
40
+ WebGL command buffer. The image pipeline then samples the colour texture as
41
+ an ordinary `PaintImage`, with no CPU copy.
42
+ - WebGL's origin is bottom-left while SDL_GPU render targets are top-left, so
43
+ the framebuffer is stored top-down: `viewport`/`scissor` are converted,
44
+ `readPixels` flips rows back, and the compositor sees an upright texture.
45
+ - A fixed-function state change (`blendFunc`, `depthFunc`, `cullFace`,
46
+ `colorMask`, …) changes which `SDL_GPUGraphicsPipeline` is needed, so
47
+ pipelines are created lazily per (program, vertex layout, state) and cached on
48
+ the program.
49
+
50
+ ## Shaders: GLSL ES to SPIR-V (and on to MSL)
51
+
52
+ SDL_GPU cannot compile GLSL at run time, and each backend consumes its own
53
+ format, so the engine ships two statically linked translators:
54
+
55
+ - **glslang** compiles the rewritten GLSL to SPIR-V, which the Vulkan backend
56
+ consumes directly;
57
+ - **SPIRV-Cross** cross-compiles that same SPIR-V to Metal Shading Language text,
58
+ which the Metal backend compiles at run time.
59
+
60
+ Both live in `gui.a` / `gui.lib`; the Metal path reuses the SPIR-V module rather
61
+ than growing a second GLSL front end, so both backends accept exactly the same
62
+ shader subset. The path is:
63
+
64
+ 1. `shaderSource` stores the GLSL ES text; `compileShader` translates it once
65
+ for `COMPILE_STATUS` / `getShaderInfoLog`.
66
+ 2. `linkProgram` translates both stages again with one shared attribute and
67
+ varying location map, compiles them with glslang, and then creates the
68
+ `SDL_GPUShader` objects: from the SPIR-V on Vulkan, or from the MSL text
69
+ SPIRV-Cross produced on Metal.
70
+ 3. The generated SPIR-V is reflected to obtain the exact std140 offsets, array
71
+ strides and matrix strides of the uniform block — the shader text may size an
72
+ array with a macro, but glslang has already resolved it. SPIRV-Cross keeps
73
+ those offsets in the MSL struct, so one uniform layout serves both backends.
74
+
75
+ The translator (`runtime/ext_gui/webgl_glsl*.cpp`) handles GLSL ES 1.00 and
76
+ 3.00 sources:
77
+
78
+ | WebGL spelling | Rewritten to |
79
+ | --- | --- |
80
+ | `attribute vec3 a_pos` | `layout(location = N) in vec3 a_pos` |
81
+ | `varying vec2 v_uv` | `layout(location = N) out/in vec2 v_uv` (one shared name → location map) |
82
+ | `gl_FragColor` | `layout(location = 0) out highp vec4 xt_FragColor` |
83
+ | `texture2D`, `textureCube`, `texture2DProj` | `texture`, `texture`, `textureProj` |
84
+ | `texture2DLodEXT` / `textureCubeLodEXT` | `textureLod` |
85
+ | non-sampler uniforms | one `layout(std140) uniform XtUniforms { … }` block |
86
+ | `uniform sampler2D u_tex` | `layout(set = 2, binding = N) uniform sampler2D u_tex` (fragment) or set 0 (vertex) |
87
+ | `gl_FragData[0]` | `xt_FragColor` |
88
+ | a missing `#version` / `#version 100` | `#version 310 es` |
89
+
90
+ Non-sampler uniforms are merged across both stages and emitted as one block in
91
+ each stage (set 1 for the vertex shader, set 3 for the fragment shader), which
92
+ matches SDL_GPU's Vulkan descriptor layout. On Metal the same declarations
93
+ become `[[buffer(0)]]` and `[[texture(N)]]`/`[[sampler(N)]]`, the slots SDL_GPU's
94
+ Metal backend binds. `uniformMatrix4fv` writes column-major floats into the
95
+ reflected offsets; `uniform1i` on a sampler stores the texture unit. The block
96
+ is pushed with the dynamic uniform-buffer API on every draw.
97
+
98
+ Limits of the translator: struct-typed uniforms, user uniform blocks, uniform
99
+ arrays whose size is not resolved by the preprocessor, sampler arrays and cube
100
+ maps are rejected (the link/shader info log says so). Shader code inside
101
+ `#ifdef` is fine; non-sampler uniform declarations are moved to the enclosing
102
+ top-level position so the block stays unconditional.
103
+
104
+ ### GLSL ES 3.00 (WebGL 2)
105
+
106
+ A `#version 300 es` source is accepted as-is apart from the version bump:
107
+ top-level `in`/`out` declarations become attributes/varyings, a named fragment
108
+ output (`out vec4 fragColor;`) becomes an `xt_FragColor`-style output, and
109
+ `texture()` / `textureLod()` already match the Vulkan dialect. Multiple fragment
110
+ outputs are given sequential locations, but the render pass has one colour
111
+ target, so only the first is written. `gl_VertexID` and `gl_InstanceID` are
112
+ available from GLSL ES 3.00, which is what the instanced example uses.
113
+
114
+ ## Supported API
115
+
116
+ - **Context**: `getContext("webgl")`, `canvas`, `drawingBufferWidth/Height`,
117
+ `getParameter`, `getError`, `getSupportedExtensions`, `getExtension`,
118
+ `getContextAttributes`, `isContextLost`, `getShaderPrecisionFormat`, and the
119
+ stencil entry points (accepted; the depth target has no stencil attachment).
120
+ - **Shaders and programs**: `createShader`, `shaderSource`, `compileShader`,
121
+ `getShaderParameter`, `getShaderInfoLog`, `getShaderSource`, `deleteShader`,
122
+ `createProgram`, `attachShader`, `detachShader`, `linkProgram`,
123
+ `getProgramParameter`, `getProgramInfoLog`, `getAttachedShaders`,
124
+ `validateProgram`, `deleteProgram`, `useProgram`,
125
+ `getActiveUniform`/`getActiveAttrib`, `getUniformLocation`,
126
+ `getAttribLocation`, `bindAttribLocation`.
127
+ - **Uniforms**: `uniform1f`…`uniform4f`, `uniform1i`…`uniform4i`,
128
+ `uniform1fv`…`uniform4fv`, `uniform1iv`…`uniform4iv`,
129
+ `uniformMatrix2fv`/`3fv`/`4fv`, `getUniform`.
130
+ - **Buffers and attributes**: `createBuffer`, `bindBuffer`, `bufferData`,
131
+ `bufferSubData`, `deleteBuffer`, `getBufferParameter`,
132
+ `enableVertexAttribArray`, `disableVertexAttribArray`,
133
+ `vertexAttribPointer`, `vertexAttrib1f`…`4f` / `1fv`…`4fv`,
134
+ `getVertexAttrib`.
135
+ - **Drawing**: `drawArrays`, `drawElements` (UNSIGNED_BYTE, UNSIGNED_SHORT,
136
+ UNSIGNED_INT; `TRIANGLE_FAN` and `LINE_LOOP` are expanded to lists).
137
+ `POINTS`, `LINES`, `LINE_STRIP`, `TRIANGLES` and `TRIANGLE_STRIP` map to the
138
+ matching SDL primitive.
139
+ - **Textures**: `createTexture`, `bindTexture`, `activeTexture`,
140
+ `texParameteri`/`texParameterf`, `getTexParameter`, `texImage2D` (raw pixels,
141
+ `<img>`, `<canvas>` and `ImageData` sources), `texSubImage2D`,
142
+ `generateMipmap`, `deleteTexture`. `UNPACK_FLIP_Y_WEBGL` and
143
+ `UNPACK_PREMULTIPLY_ALPHA_WEBGL` are honoured. Everything is converted to
144
+ RGBA8; `RGBA`, `RGB`, `LUMINANCE`, `ALPHA` and `LUMINANCE_ALPHA` with
145
+ `UNSIGNED_BYTE` are accepted.
146
+ - **Framebuffers**: `createFramebuffer`, `bindFramebuffer`,
147
+ `framebufferTexture2D` (colour attachment), `checkFramebufferStatus`,
148
+ `createRenderbuffer`, `bindRenderbuffer`, `renderbufferStorage` (depth),
149
+ `framebufferRenderbuffer`, `delete*`. This is enough for render-to-texture,
150
+ shadow maps and post-processing passes.
151
+ - **State**: `enable`/`disable`/`isEnabled` for `BLEND`, `DEPTH_TEST`,
152
+ `CULL_FACE`, `SCISSOR_TEST` (stencil accepted but not applied),
153
+ `clearColor`/`clearDepth`/`clearStencil`, `clear`, `blendFunc`/
154
+ `blendFuncSeparate`, `blendEquation`/`blendEquationSeparate`, `depthFunc`,
155
+ `depthMask`, `colorMask`, `cullFace`, `frontFace`, `viewport`, `scissor`,
156
+ `pixelStorei`, `finish`.
157
+ - **Readback**: `readPixels` (RGBA/UNSIGNED_BYTE) from the default framebuffer
158
+ or a bound framebuffer. It blocks until the GPU finishes; use it for tests and
159
+ screenshots, not per frame.
160
+
161
+ WebGL 2 adds:
162
+
163
+ - **Vertex-array objects**: `createVertexArray`, `bindVertexArray`,
164
+ `deleteVertexArray`, `isVertexArray`. SDL_GPU has no VAO, so binding one
165
+ restores a saved copy of the attribute table and its element buffer.
166
+ - **Instancing**: `drawArraysInstanced`, `drawElementsInstanced`,
167
+ `drawRangeElements`, `vertexAttribDivisor`. A divisor of 1 maps to SDL's
168
+ per-instance vertex input rate; SDL 3.2 reserves larger step rates, so a
169
+ divisor above 1 is clamped to 1.
170
+ - **Integer attributes and uniforms**: `vertexAttribIPointer`, the
171
+ `vertexAttribI4*` family, `uniform1ui`…`uniform4ui`.
172
+ - **Sampler objects**: `createSampler`, `bindSampler`, `deleteSampler`,
173
+ `samplerParameteri/f`, `getSamplerParameter`; a bound sampler overrides the
174
+ texture's own filter/wrap state for that unit.
175
+ - **Immutable textures and buffer copies**: `texStorage2D` (the backend always
176
+ allocates the full mip chain), `copyBufferSubData`, `getBufferSubData`.
177
+ - **Clears**: `clearBufferfv`, `clearBufferiv`, `clearBufferuiv`,
178
+ `clearBufferfi`.
179
+ - **Queries and fences**: the objects and entry points exist
180
+ (`createQuery`/`beginQuery`/`endQuery`/`getQueryParameter`,
181
+ `fenceSync`/`clientWaitSync`/`waitSync`/`getSyncParameter`) and degrade
182
+ gracefully: a fence reports `ALREADY_SIGNALED` and query results are 0.
183
+ - **Uniform blocks**: `getUniformBlockIndex` answers `INVALID_INDEX` so a
184
+ library falls back to individual uniforms; the block entry points are no-ops.
185
+ - **Transform feedback, 3D textures and compressed formats**: the entry points
186
+ are present as no-ops so feature-probing libraries do not throw.
187
+
188
+ Textures are created with a full mip chain; sampling clamps to level 0 until
189
+ `generateMipmap` runs. Matrix vertex attributes consume the right number of
190
+ consecutive locations and read one column per location. A disabled attribute
191
+ is supplied from the last `vertexAttrib*f` value through a small constant
192
+ buffer.
193
+
194
+ ## Not implemented
195
+
196
+ Uniform buffer objects in shader source, transform feedback (the entry points
197
+ are no-ops), cube maps, 3D/array textures, float/half textures, depth textures,
198
+ compressed textures, multiple render targets (only the first fragment output is
199
+ written), `blitFramebuffer`, MSAA/sample buffers, stencil operations (state is
200
+ accepted, the stencil buffer is not written), constant blend colours,
201
+ `drawingBufferStorage`, context loss, `bufferData` with a `usage` other than
202
+ static/dynamic (the hint is ignored), `texImage2D` for
203
+ `HTMLVideoElement`/`ImageBitmap` and scissored `clear` (a clear clears the whole
204
+ attachment). Shaders that use built-in blocks, user uniform blocks or
205
+ `gl_FragDepth` beyond the supported subset are rejected with a compile/link log.
206
+
207
+ The engine advertises zero vertex texture units, so a well-behaved WebGL 1
208
+ program will not try to sample a texture in a vertex shader.
209
+
210
+ ## Platform
211
+
212
+ The pipeline is created with the shader format the SDL_GPU device accepts:
213
+ **SPIR-V** (`SDL_GPU_SHADERFORMAT_SPIRV`) on Vulkan, which is what Windows and
214
+ Linux select, or **MSL** (`SDL_GPU_SHADERFORMAT_MSL`) on Metal, which macOS
215
+ selects. Both backends go through the same GLSL front end, so a shader that
216
+ compiles on one compiles on the other. On a device whose backend accepts neither
217
+ format — Direct3D 12, which would need DXIL — `getContext("webgl")` and
218
+ `getContext("webgl2")` both answer `null`; the 2D canvas and the rest of the page
219
+ still work.
220
+
221
+ glslang and SPIRV-Cross are fetched and built by `npm run gui` and merged into
222
+ `gui.a` / `gui.lib` (see [Packaging and build](./build.md)); a program that only
223
+ uses the 2D canvas or the DOM pays no run-time cost beyond the archive size.
224
+
225
+ ## Testing
226
+
227
+ - `tests/e2e/gui-webgl.test.ts` compiles GLSL, draws a textured and a
228
+ depth-tested quad, checks face culling and reads the pixels back.
229
+ - `tests/e2e/gui-webgl2.test.ts` covers the WebGL 2 additions: `#version 300 es`
230
+ shaders, a VAO round trip, instanced draws with a divisor, `texStorage2D`,
231
+ `clearBufferfv`, buffer copies, sampler objects and struct-uniform fields.
232
+ - `examples/gui/webgl-cube` is a spinning, lit, textured cube; it runs in a
233
+ browser unchanged and is covered by
234
+ `tests/e2e/gui-example-webgl.test.ts`.
235
+ - `examples/gui/webgl2-cubes` draws 64 instanced cubes with one draw call,
236
+ `#version 300 es` and a VAO; covered by
237
+ `tests/e2e/gui-example-webgl2.test.ts`.
238
+
239
+ These suites run against whichever backend the host selects: Vulkan on Linux
240
+ (and Windows), Metal on macOS, so the SPIRV-Cross -> MSL path is covered by the
241
+ same assertions as the SPIR-V one.
242
+
243
+ ## three.js
244
+
245
+ The `.js` asset loader only patches three.js's shader unroller; `WebGLRenderer`
246
+ runs unchanged on this engine's real WebGL 2 backend, so **no Canvas2D fallback
247
+ is bundled any more**. Verified with three.js r160 through SDL_GPU:
248
+ `MeshBasicMaterial`, `MeshStandardMaterial` and `MeshPhongMaterial`,
249
+ `CanvasTexture`, linear fog, ambient/directional/point/spot/hemisphere lights,
250
+ `Sprite`, `Line`, `Points` and `InstancedMesh`.
251
+
252
+ Features outside this engine's subset still cannot be emulated: shadow maps
253
+ (depth textures), cube textures/environment maps, HDR/float render targets,
254
+ multiple render targets, transform feedback and compressed textures. A scene
255
+ that needs one of those will not render correctly; everything the previous
256
+ Canvas2D fallback could show now goes through the GPU.
package/doc/gui.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # xbintsc GUI extension (self-hosted HTML/CSS renderer)
2
2
 
3
- Status: **M16** — features (M1–M15) are complete: HTML parsing, CSS selector
3
+ Status: **M19** — features (M1–M15) are complete: HTML parsing, CSS selector
4
4
  matching, the cascade, computed styles and layout (block, inline, Flexbox and
5
5
  CSS positioning) are
6
6
  in place, and the engine *paints*: it builds a display list of rectangles, images
@@ -35,6 +35,12 @@ them) can be translated, scaled and rotated without reflowing anything — and
35
35
  `transition: transform`, so those poses animate. See
36
36
  [Layout](./gui/layout.md#transforms-m15) and
37
37
  [Animation](./gui/animation.md#css-transforms-m15).
38
+ **M17** adds real **WebGL 1.0**, and **M18** adds **WebGL 2.0**: `<canvas>.getContext("webgl2")` accepts `#version 300 es` shaders, vertex-array objects, instanced draws and sampler objects, all compiled to SPIR-V by the bundled glslang (and to MSL by the bundled SPIRV-Cross on Metal) and rendered through SDL_GPU. Geometry, lighting, texture sampling and blending run on the GPU and the page composites the colour texture without a readback — see [WebGL](./gui/webgl.md).
39
+ **M19** fills in the decorative CSS layer: `@media` queries, generated content
40
+ (`::before`/`::after`), multi-layer linear/radial backgrounds, `text-shadow`,
41
+ `clip-path` and the `filter` colour/shadow effects. `backdrop-filter` and true
42
+ group blur need an offscreen compositor and remain documented approximations or
43
+ unsupported — see [Rendering](./gui/rendering.md#backgrounds-generated-content-and-effects-m19).
38
44
  This overview records the locked decisions, the architecture, the milestone plan
39
45
  and the current progress; the engine itself is documented by function in the
40
46
  pages above.
@@ -174,21 +180,27 @@ engine were Rust.
174
180
  - **M6b — transitions/animations** ✅ `transition` shorthand + longhands,
175
181
  animated `background-color`/`color`/`border-color`/`border-radius`, retargeting
176
182
  and `win.advance(ms)`. `@keyframes` remain.
177
- 7. **M7 — CI & releases** ✅ (Linux/macOS build) / 🚧 (run + Windows)
183
+ 7. **M7 — CI & releases** ✅ (Linux/macOS/Windows x64 build) / 🚧 (run + Windows arm64)
178
184
  - `compile-examples` builds `gui.a` and `media.a` on Linux and macOS
179
185
  (required), then runs the examples and `tests/e2e/gui-*.test.ts` under
180
186
  Xvfb + lavapipe on Linux (required). The macOS run is provisional until a
181
187
  WindowServer is confirmed; it is guarded so a failure is logged without
182
188
  annotating the run.
183
- - The `package` job builds `gui.a` and `media.a` before assembling the
184
- release, so both ship inside the existing runtime archive
185
- (`package-release` copies all of `runtime/`).
186
- - `vendor/` (SDL3/FreeType/HarfBuzz for `gui.a`, FFmpeg for `media.a`) is
187
- cached per OS/arch, keyed by `scripts/build-gui.ts` / `scripts/build-media.ts`.
188
- - Windows (build + run) stays provisional in CI: the MSVC-compatible
189
- `gui.lib` builds and runs locally through SDL_GPU's Vulkan backend, but the
190
- hosted runners have no GPU/Vulkan driver. A failure is logged without
191
- annotating the run (see [Open questions](./gui/known-issues.md#open-questions)).
189
+ - The `package` job builds `gui.a`/`gui.lib` and `media.a`/`media.lib` before
190
+ assembling the release, so both ship inside the existing runtime archive
191
+ (`package-release` copies all of `runtime/`). Windows x64 is included;
192
+ Windows arm64 still skips them.
193
+ - `vendor/` (SDL3/FreeType/HarfBuzz for the GUI archive, FFmpeg for `media`)
194
+ is cached per OS/arch, keyed by `scripts/build-gui.ts` /
195
+ `scripts/build-media.ts`. Windows x64 gets its own source cache plus the
196
+ installed `vendor/ffmpeg-build-msvc/dist` prefix.
197
+ - Windows x64 builds both archives in CI and links a `gui,media` program,
198
+ using the same Visual Studio `vcvarsall` + bundled LLVM toolchain as a
199
+ local build (`.github/actions/vs-toolchain`); the host has no GPU/Vulkan
200
+ driver, so *running* the GUI/media examples there remains provisional (a
201
+ failure is logged without annotating the run). The Windows arm64 job still
202
+ skips both archives (see
203
+ [Open questions](./gui/known-issues.md#open-questions)).
192
204
  8. **M8 — interactive DOM** ✅
193
205
  - Element/document handles with stable identity, read/write properties via
194
206
  runtime accessors, traversal/attributes/queries, mutation with lazy
@@ -277,6 +289,54 @@ engine were Rust.
277
289
  NanoSVG cache as an SVG file (`svg.{h,cpp}`); the markup cache is bounded
278
290
  and a DOM mutation re-serializes on the next layout. e2e in
279
291
  `tests/e2e/gui-inline-svg.test.ts`.
292
+ 17. **M17 — WebGL** ✅
293
+ - `canvas.getContext("webgl")` creates a real GPU context
294
+ (`webgl.{h,cpp}`): an offscreen RGBA8 colour texture plus a depth texture,
295
+ its own SDL_GPU command buffer, and pipelines created lazily from the
296
+ program, vertex layout and fixed-function state. The page composites the
297
+ colour texture through the existing image path, with no CPU readback.
298
+ - `webgl_glsl*.cpp` rewrites GLSL ES 1.00/3.00 to Vulkan GLSL ES 3.10
299
+ (attribute/varying locations, `gl_FragColor`, `texture2D`, one std140
300
+ uniform block per stage, explicit sampler bindings), compiles it with a
301
+ statically bundled glslang, reflects the SPIR-V for uniform offsets, and
302
+ on Metal cross-compiles that same module to MSL with the bundled
303
+ SPIRV-Cross (`webgl_msl.cpp`).
304
+ - `dom_api_webgl*.cpp` exposes the WebGL 1.0 surface, including textures,
305
+ mipmaps, render-to-texture framebuffers and `readPixels`. See
306
+ [WebGL](./gui/webgl.md); e2e in `tests/e2e/gui-webgl.test.ts` and
307
+ `tests/e2e/gui-example-webgl.test.ts`, demo in
308
+ `examples/gui/webgl-cube`.
309
+ 18. **M18 — WebGL 2** ✅
310
+ - `canvas.getContext("webgl2")` returns a context whose prototype extends
311
+ the WebGL 1 one, with the WebGL 2 constants and methods.
312
+ - GLSL ES 3.00 sources (`#version 300 es`, `in`/`out`, named fragment
313
+ outputs, `gl_InstanceID`) compile through the same rewriter.
314
+ - Vertex-array objects save/restore the attribute table, instanced draws use
315
+ SDL's per-instance input rate, and sampler objects override a texture
316
+ unit's filter/wrap state. `texStorage2D`, `copyBufferSubData`,
317
+ `getBufferSubData` and `clearBuffer*` are implemented; query/fence/UBO and
318
+ transform-feedback entry points exist and degrade gracefully. See
319
+ [WebGL](./gui/webgl.md); e2e in `tests/e2e/gui-webgl2.test.ts` and
320
+ `tests/e2e/gui-example-webgl2.test.ts`, demo in
321
+ `examples/gui/webgl2-cubes`.
322
+ 19. **M19 — decorative CSS** ✅
323
+ - `@media` blocks are parsed recursively and evaluated against the viewport
324
+ (width/height ranges, orientation, hover/pointer and preference features);
325
+ `matchMedia()` uses the same evaluator.
326
+ - Generated content: `::before`/`::after` selectors, inherited pseudo styles,
327
+ `content` strings/escapes/`attr()`, and synthetic layout boxes that never
328
+ leak into DOM traversal.
329
+ - Multi-layer `background-image` with linear and radial gradients, painted
330
+ bottom-up as solid bands (18 strips / 32 concentric ellipses).
331
+ - `text-shadow` as shadow text runs, including a nine-tap blur approximate.
332
+ - `clip-path` polygons (`inset`/`circle`/`ellipse`/`polygon`) resolved to
333
+ device space, ear-clipped and intersected with shape geometry in
334
+ `renderer_clip.cpp` — no stencil/shader change.
335
+ - `filter` colour functions, nine-tap `blur()` and silhouette
336
+ `drop-shadow()`; `backdrop-filter` parses and cascades but needs an
337
+ offscreen backdrop pass (see [Known issues](./gui/known-issues.md)).
338
+ - E2E coverage in `tests/e2e/gui-effects.test.ts`; see
339
+ [Rendering](./gui/rendering.md#backgrounds-generated-content-and-effects-m19).
280
340
 
281
341
  ## Progress log
282
342
 
@@ -306,11 +366,12 @@ engine were Rust.
306
366
  pixel size and cached by that size, so scaling and HiDPI stay crisp.
307
367
  - **M6b** ✅ CSS transitions (parsing in `style.*`, an animation clock and
308
368
  transition state in `document.*`, `advance`/`advance(ms)` hooks, e2e coverage).
309
- - **M7** ✅ builds `gui.a` (and the optional `media.a`) in CI on Linux and macOS
310
- (required) and runs the example plus the GUI e2e suite under Xvfb on Linux;
311
- `package` ships both archives, `vendor/` is cached, and the `ar -M` merge
312
- works on GNU/Linux and macOS. macOS runs and all of Windows remain provisional
313
- in CI.
369
+ - **M7** ✅ builds `gui.a`/`gui.lib` and `media.a`/`media.lib` in CI on Linux,
370
+ macOS and Windows x64 (required) and runs the example plus the GUI e2e suite
371
+ under Xvfb on Linux; `package` ships the archives (Windows x64 included),
372
+ `vendor/` is cached, and the `ar -M` merge works on GNU/Linux, macOS and
373
+ COFF/Windows. macOS runs, the Windows example *run* and Windows arm64 remain
374
+ provisional in CI.
314
375
  - **M8** ✅ element/document handles (`dom_api.*`), DOM mutation with lazy
315
376
  restyle/relayout (`document.*`, `xt_gui_flush_dom`), element event dispatch
316
377
  with capture/bubble and `stopPropagation` (`dom_api.*`, `gui.cpp`), and e2e
@@ -347,7 +408,8 @@ engine were Rust.
347
408
  every frame now runs in constant memory (see [Memory & GC](./gui/runtime.md#memory--gc)).
348
409
  - **M13** ✅ `<video>` / `<audio>` support. The optional `media` extension
349
410
  vendors and builds a minimal static FFmpeg (`scripts/build-media.ts`) and
350
- merges it into `media.a`; `runtime/ext_media/media.cpp` decodes video to RGBA
411
+ merges it into `media.a` (or `media.lib` from clang-cl/MSVC objects on
412
+ Windows); `runtime/ext_media/media.cpp` decodes video to RGBA
351
413
  frames and audio to 48 kHz stereo PCM on the main thread,
352
414
  `runtime/ext_gui/gui_media.cpp` owns the players, implements the SDL audio
353
415
  sink and pumps the media clock and events each frame,
@@ -393,4 +455,33 @@ engine were Rust.
393
455
  NanoSVG cache (`svg.{h,cpp}`, bounded LRU for markup). The `win.inlineSvg`
394
456
  diagnostic exposes the serialized document, and `tests/e2e/gui-inline-svg.test.ts`
395
457
  pins sizing, hit testing, gradients, CSS box styling and mutation.
458
+ - **M17** ✅ WebGL. `xtgui::WebGLContext` (`webgl.{h,cpp}`) owns the offscreen
459
+ colour/depth targets and the command buffer, `webgl_buffer/texture/draw/shader`
460
+ implement the GL object model, `webgl_glsl*.cpp` translate GLSL ES to SPIR-V
461
+ with the bundled glslang (`webgl_msl.cpp`/SPIRV-Cross turn that module into
462
+ MSL on Metal), and `dom_api_webgl*.cpp` bind the WebGL 1.0 API.
463
+ `renderer_image.cpp` returns the context's colour texture for a canvas id, so
464
+ the page composites GPU output directly. Demo: `examples/gui/webgl-cube`;
465
+ e2e: `tests/e2e/gui-webgl.test.ts`, `tests/e2e/gui-example-webgl.test.ts`.
466
+ - **M18** ✅ WebGL 2. `webgl2_proto()` extends the WebGL 1 prototype with the
467
+ WebGL 2 constants/methods; `webgl_webgl2.cpp` implements vertex-array objects
468
+ and sampler/query/sync handles, `webgl_draw.cpp` adds instanced draws (input
469
+ rate from `vertexAttribDivisor`) and integer attributes, and
470
+ `webgl_texture.cpp` adds `texStorage2D` and `clearBuffer*`. The shader
471
+ rewriter gives `#version 300 es` outputs sequential locations, and the block
472
+ reflection flattens struct fields for three.js lights. three.js r160 runs on
473
+ the real renderer (basic/standard/Phong materials, textures, lights, fog,
474
+ sprites, lines, points and instancing); the Canvas2D fallback was removed.
475
+ Demo: `examples/gui/webgl2-cubes` (64 cubes, one instanced draw call);
476
+ e2e: `tests/e2e/gui-webgl2.test.ts`, `tests/e2e/gui-example-webgl2.test.ts`.
477
+ - **M19** ✅ decorative CSS. `css_sheet.cpp` now parses nested `@media` blocks and
478
+ `media_query.cpp` evaluates them (and `matchMedia`) against the viewport;
479
+ `css_selector.cpp` understands `::before`/`::after`. `style.cpp` computes
480
+ pseudo styles into a per-restyle arena, resolves `content`, and layout inserts
481
+ their boxes before/after the DOM children. `gradient_values.cpp` models a
482
+ background layer list (linear/radial, shape/size/position/stops),
483
+ `paint_background.cpp` paints it, `paint_effects.cpp` applies filter colour
484
+ functions plus nine-tap blur/drop-shadow and emits `text-shadow` runs, and
485
+ `paint_clip.cpp`/`renderer_clip.cpp` clip geometry against triangulated
486
+ `clip-path` polygons. E2E: `tests/e2e/gui-effects.test.ts`.
396
487
 
@@ -358,8 +358,10 @@ jobs:
358
358
  cannot poison a new build.
359
359
  - xbintsc builds for the **host** platform. It is not a cross-compiler: use a CI
360
360
  matrix (one job per OS/arch) to produce artifacts for several platforms.
361
- - macOS runners already have Xcode Command Line Tools; Windows runners need
362
- LLVM and the MSVC build tools, and the binary is `build\main.exe`.
361
+ - macOS runners already have Xcode Command Line Tools; Windows runners need the
362
+ Visual Studio C++ build tools (MSVC + its bundled LLVM), and the binary is
363
+ `build\main.exe`. In a source checkout,
364
+ `pwsh -File scripts/setup-vs-toolchain.ps1` imports that toolchain explicitly.
363
365
 
364
366
  ## npm package or release archive?
365
367
 
@@ -367,7 +369,7 @@ jobs:
367
369
  | --- | --- | --- |
368
370
  | Needs Node.js | Yes, 22+ | No |
369
371
  | First build | Compiles the C runtime from source | Links the prebuilt runtime |
370
- | GUI / media extensions | Not included | Included in Linux/macOS archives |
372
+ | GUI / media extensions | Not included | Included in Linux/macOS and Windows x64 archives |
371
373
  | Installation | `npm install` + lockfile / provenance | Download, verify `.sha256`, unpack |
372
374
  | Programmatic API | Yes | No (CLI only) |
373
375
  | Cross-compiles | No — host only | No — host only |
@@ -409,7 +411,7 @@ the same file under `node_modules/xbintsc/doc/ai/`.
409
411
  | The first build takes a long time | Expected: the runtime C sources are compiled and cached. Later builds reuse `.xbintsc/`; `--time` confirms. Use a release archive if cold builds must be fast. |
410
412
  | Permission errors writing `.xbintsc/` | Set `xbintsc_CACHE_DIR` to a writable directory, or run from a writable working directory. |
411
413
  | `module 'fs' is provided by the 'node' extension` | Add `--ext node`, or `"extensions": ["node"]` in the config. |
412
- | `GUI native library not found` / `media native library not found` | The npm package does not ship `gui.a`/`media.a`; use a Linux/macOS release archive or build them from a source checkout. |
414
+ | `GUI native library not found` / `media native library not found` | The npm package does not ship `gui.a`/`gui.lib` or `media.a`/`media.lib`; use a Linux/macOS/Windows x64 release archive or build them from a source checkout. |
413
415
  | `require("xbintsc")` fails | The package is ESM-only; use `import` (or dynamic `import()`). |
414
416
  | Windows link errors about missing MSVC libraries | Run from a Native Tools prompt, install the VS C++ build tools, and check `npx xbintsc doctor`. |
415
417
  | `npm ci --omit=dev` then the build cannot find `xbintsc` | Install devDependencies for the build stage, or move `xbintsc` to `dependencies`. |
@@ -124,22 +124,26 @@ Verify with `clang --version`. If xbintsc uses the wrong linker, set
124
124
  `xbintsc_CLANG` to the clang you want and/or pass extra flags through
125
125
  `xbintsc_LINKER_ARGS` (for example `-fuse-ld=lld`).
126
126
 
127
- ## Windows — install the MSVC C++ build tools (and LLVM)
127
+ ## Windows — install the MSVC C++ build tools (with LLVM)
128
128
 
129
- xbintsc targets the **MSVC ABI** on Windows. Install the Visual Studio C++
130
- build tools plus LLVM with `winget`:
129
+ xbintsc targets the **MSVC ABI** on Windows. One `winget` command installs the
130
+ Visual Studio C++ workload, MSBuild and the Clang component that the local build
131
+ scripts and CI use:
131
132
 
132
133
  ```powershell
133
- winget install -e --id LLVM.LLVM
134
134
  winget install -e --id Microsoft.VisualStudio.2022.BuildTools `
135
- --override "--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
135
+ --override "--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --includeRecommended"
136
136
  ```
137
137
 
138
138
  The LLVM bundled with Visual Studio 2022
139
- (`VC\Tools\Llvm\x64\bin\clang.exe`, version 19.1.5 in current installs) is
140
- enough, and so is a standalone LLVM. Either way the compiler must target the
141
- MSVC ABI (`Target: *-windows-msvc`): clang built for another Windows ABI cannot
142
- link with the MSVC runtime, so `xbintsc` rejects it with an explicit error.
139
+ (`VC\Tools\Llvm\x64\bin\clang.exe`, version 19.1.5 in current installs) is what
140
+ `scripts/setup-vs-toolchain.ps1` selects. A standalone LLVM also works for
141
+ `xbintsc` itself (`winget install -e --id LLVM.LLVM`), but the GUI/media archive
142
+ builds and the CI setup use the Visual Studio one so one toolchain produces the
143
+ runtime, the archives and the final binary. Either way the compiler must target
144
+ the MSVC ABI (`Target: *-windows-msvc`): clang built for another Windows ABI
145
+ cannot link with the MSVC runtime, so `xbintsc` rejects it with an explicit
146
+ error.
143
147
 
144
148
  A developer prompt is normally **not** required: `xbintsc` resolves the Visual
145
149
  Studio LLVM by absolute path, and that clang locates the MSVC/SDK headers,
@@ -151,6 +155,11 @@ imported, run the build from an **x64 Native Tools Command Prompt for VS 2022**
151
155
  & "$env:ProgramFiles\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
152
156
  ```
153
157
 
158
+ In a source checkout, `pwsh -File scripts/setup-vs-toolchain.ps1` does the same
159
+ and also pins `xbintsc_CLANG` to the LLVM bundled with that Visual Studio
160
+ installation. CI calls the same script, so a local build, the release archives
161
+ and CI use one Visual Studio toolchain.
162
+
154
163
  Verify with `xbintsc doctor` (or `clang --version`); the report names the
155
164
  resolved compiler, its version and its target.
156
165
 
@@ -55,7 +55,8 @@ requestAnimationFrame(frame);
55
55
  | `localStorage` | 内存中的 `getItem` / `setItem` / `removeItem` / `clear` / `key` / `length` |
56
56
  | `AudioContext`、`webkitAudioContext` | Web Audio 图构建器(见下) |
57
57
  | `Event`、`CustomEvent`、`ProgressEvent` 等 | 事件构造器 |
58
- | `HTMLCanvasElement`、`HTMLImageElement`、`ImageBitmap`、`ImageData`、`OffscreenCanvas`、`WebGL*`、`XRWebGL*`、`Request`、`Headers`、`Response`、`ReadableStream`、`DOMParser` | `typeof` 探测返回 `"undefined"`(引擎没有 WebGL、XR、fetch 或流式后端),让页面走自己的“不支持”分支,而不是调用空壳 |
58
+ | `HTMLCanvasElement`、`HTMLImageElement`、`WebGLRenderingContext`、`WebGL2RenderingContext`、`WebGLBuffer`/`WebGLTexture`/`WebGLShader`/`WebGLProgram`/`WebGLFramebuffer`/`WebGLRenderbuffer`/`WebGLUniformLocation`/`WebGLActiveInfo`/`WebGLVertexArrayObject`/`WebGLSampler`/`WebGLQuery`/`WebGLSync`/`WebGLTransformFeedback` | 真实的构造函数值。`canvas.getContext("webgl")` 与 `getContext("webgl2")` 返回 GPU 上下文(见 [WebGL](./webgl.md))。 |
59
+ | `ImageBitmap`、`ImageData`、`OffscreenCanvas`、`XRWebGL*`、`Request`、`Headers`、`Response`、`ReadableStream`、`DOMParser` | `typeof` 探测返回 `"undefined"`(没有 XR/fetch/流式后端),让页面走自己的“不支持”分支,而不是调用空壳。Three.js 页面在本后端上使用真实渲染器(见[已知问题](./known-issues.md))。 |
59
60
  | `requestAnimationFrame` / `cancelAnimationFrame` | 排入窗口的动画帧列表,见[运行时集成](./runtime.md) |
60
61
  | `alert` / `confirm` / `prompt`、`matchMedia`、`getComputedStyle`、`escape` | 宿主实现(Annex B `escape` 按 UTF-16 码元编码,与 `decodeURIComponent(escape(bytes))` 一致) |
61
62
 
@@ -133,4 +134,4 @@ win.stats() // 引擎/运行时计数器(内存排
133
134
 
134
135
  多窗口由对象模型自然得出:`createWindow` 返回一个原生对象句柄;每个句柄
135
136
  拥有自己的 `SDL_Window`/GPU 表面与自己的 DOM 树。`run()` 驱动一个共享主循环,
136
- 它每帧 tick 所有窗口,并在最后一个窗口关闭时退出。
137
+ 它每帧 tick 所有窗口,并在最后一个窗口关闭时退出。