xbintsc 0.5.32 → 0.5.37

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 (222) hide show
  1. package/README.md +10 -7
  2. package/README.zh-CN.md +10 -8
  3. package/dist/scripts/check-version.d.ts +27 -0
  4. package/dist/scripts/check-version.js +71 -0
  5. package/dist/scripts/check-version.js.map +1 -0
  6. package/dist/scripts/package-platform.d.ts +58 -0
  7. package/dist/scripts/package-platform.js +142 -0
  8. package/dist/scripts/package-platform.js.map +1 -0
  9. package/dist/scripts/verify-platform-package.d.ts +34 -0
  10. package/dist/scripts/verify-platform-package.js +161 -0
  11. package/dist/scripts/verify-platform-package.js.map +1 -0
  12. package/dist/src/cli/help.d.ts +1 -1
  13. package/dist/src/cli/main.js +3 -1
  14. package/dist/src/cli/main.js.map +1 -1
  15. package/dist/src/driver/runtime-lib.d.ts +29 -4
  16. package/dist/src/driver/runtime-lib.js +68 -10
  17. package/dist/src/driver/runtime-lib.js.map +1 -1
  18. package/dist/src/driver/version.d.ts +1 -1
  19. package/dist/src/driver/version.js +1 -1
  20. package/dist/src/extensions/gui/index.js +18 -5
  21. package/dist/src/extensions/gui/index.js.map +1 -1
  22. package/dist/src/extensions/media/index.js +4 -3
  23. package/dist/src/extensions/media/index.js.map +1 -1
  24. package/dist/src/parser/context.d.ts +41 -0
  25. package/dist/src/parser/context.js +89 -4
  26. package/dist/src/parser/context.js.map +1 -1
  27. package/dist/src/parser/literals.js +6 -12
  28. package/dist/src/parser/literals.js.map +1 -1
  29. package/dist/tests/driver/platform-package.test.d.ts +1 -0
  30. package/dist/tests/driver/platform-package.test.js +49 -0
  31. package/dist/tests/driver/platform-package.test.js.map +1 -0
  32. package/dist/tests/driver/runtime-lib.test.js +51 -4
  33. package/dist/tests/driver/runtime-lib.test.js.map +1 -1
  34. package/dist/tests/e2e/gui-audio.test.d.ts +14 -0
  35. package/dist/tests/e2e/gui-audio.test.js +287 -0
  36. package/dist/tests/e2e/gui-audio.test.js.map +1 -0
  37. package/dist/tests/e2e/gui-browser.test.js +65 -0
  38. package/dist/tests/e2e/gui-browser.test.js.map +1 -1
  39. package/dist/tests/e2e/gui-canvas-args.test.d.ts +6 -0
  40. package/dist/tests/e2e/gui-canvas-args.test.js +217 -0
  41. package/dist/tests/e2e/gui-canvas-args.test.js.map +1 -0
  42. package/dist/tests/e2e/gui-canvas.test.js.map +1 -1
  43. package/dist/tests/e2e/gui-dom.test.js +215 -0
  44. package/dist/tests/e2e/gui-dom.test.js.map +1 -1
  45. package/dist/tests/e2e/gui-events.test.js +112 -0
  46. package/dist/tests/e2e/gui-events.test.js.map +1 -1
  47. package/dist/tests/e2e/gui-helpers.d.ts +7 -0
  48. package/dist/tests/e2e/gui-helpers.js +1 -0
  49. package/dist/tests/e2e/gui-helpers.js.map +1 -1
  50. package/dist/tests/e2e/gui-media.test.js +78 -0
  51. package/dist/tests/e2e/gui-media.test.js.map +1 -1
  52. package/dist/tests/e2e/gui-style.test.js +55 -0
  53. package/dist/tests/e2e/gui-style.test.js.map +1 -1
  54. package/dist/tests/e2e/gui-webgl.test.js +258 -0
  55. package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
  56. package/dist/tests/e2e/gui-webgl2-3d.test.d.ts +4 -0
  57. package/dist/tests/e2e/gui-webgl2-3d.test.js +264 -0
  58. package/dist/tests/e2e/gui-webgl2-3d.test.js.map +1 -0
  59. package/dist/tests/e2e/gui-webgl2-blit.test.d.ts +10 -0
  60. package/dist/tests/e2e/gui-webgl2-blit.test.js +262 -0
  61. package/dist/tests/e2e/gui-webgl2-blit.test.js.map +1 -0
  62. package/dist/tests/e2e/gui-webgl2-formats.test.d.ts +6 -0
  63. package/dist/tests/e2e/gui-webgl2-formats.test.js +395 -0
  64. package/dist/tests/e2e/gui-webgl2-formats.test.js.map +1 -0
  65. package/dist/tests/e2e/gui-webgl2-mrt.test.d.ts +4 -0
  66. package/dist/tests/e2e/gui-webgl2-mrt.test.js +105 -0
  67. package/dist/tests/e2e/gui-webgl2-mrt.test.js.map +1 -0
  68. package/dist/tests/e2e/gui-webgl2-ubo.test.d.ts +8 -0
  69. package/dist/tests/e2e/gui-webgl2-ubo.test.js +112 -0
  70. package/dist/tests/e2e/gui-webgl2-ubo.test.js.map +1 -0
  71. package/dist/tests/e2e/gui-webgl2.test.js +45 -1
  72. package/dist/tests/e2e/gui-webgl2.test.js.map +1 -1
  73. package/dist/tests/extensions/gui-index.test.js +1 -0
  74. package/dist/tests/extensions/gui-index.test.js.map +1 -1
  75. package/dist/tests/extensions/media.test.js +1 -0
  76. package/dist/tests/extensions/media.test.js.map +1 -1
  77. package/dist/tests/parser/expressions.test.js +30 -0
  78. package/dist/tests/parser/expressions.test.js.map +1 -1
  79. package/dist/tests/platform-tarball.test.d.ts +1 -0
  80. package/dist/tests/platform-tarball.test.js +111 -0
  81. package/dist/tests/platform-tarball.test.js.map +1 -0
  82. package/dist/tests/version.test.js +6 -0
  83. package/dist/tests/version.test.js.map +1 -1
  84. package/doc/ai/contributing.md +11 -0
  85. package/doc/ai/extensions.md +7 -4
  86. package/doc/ai/troubleshooting.md +7 -5
  87. package/doc/ai/zh-CN/contributing.md +9 -0
  88. package/doc/ai/zh-CN/extensions.md +4 -2
  89. package/doc/ai/zh-CN/troubleshooting.md +5 -3
  90. package/doc/gui/api.md +99 -22
  91. package/doc/gui/build.md +11 -4
  92. package/doc/gui/canvas.md +49 -18
  93. package/doc/gui/dom.md +57 -7
  94. package/doc/gui/media.md +4 -0
  95. package/doc/gui/webgl.md +105 -46
  96. package/doc/gui.md +7 -3
  97. package/doc/npm-package.md +55 -27
  98. package/doc/requirements.md +6 -2
  99. package/doc/zh-CN/gui/api.md +84 -14
  100. package/doc/zh-CN/gui/build.md +7 -2
  101. package/doc/zh-CN/gui/canvas.md +44 -19
  102. package/doc/zh-CN/gui/dom.md +48 -4
  103. package/doc/zh-CN/gui/media.md +3 -0
  104. package/doc/zh-CN/gui/webgl.md +22 -16
  105. package/doc/zh-CN/gui.md +3 -2
  106. package/doc/zh-CN/npm-package.md +44 -23
  107. package/doc/zh-CN/requirements.md +4 -1
  108. package/package.json +17 -1
  109. package/runtime/ext_gui/audio.cpp +365 -153
  110. package/runtime/ext_gui/audio_buffer.cpp +166 -0
  111. package/runtime/ext_gui/audio_buffer.h +37 -0
  112. package/runtime/ext_gui/audio_decode.cpp +219 -0
  113. package/runtime/ext_gui/audio_decode.h +39 -0
  114. package/runtime/ext_gui/audio_device.cpp +87 -0
  115. package/runtime/ext_gui/audio_effects.cpp +163 -0
  116. package/runtime/ext_gui/audio_effects.h +25 -0
  117. package/runtime/ext_gui/audio_internal.h +30 -0
  118. package/runtime/ext_gui/audio_mixer.cpp +494 -0
  119. package/runtime/ext_gui/audio_mixer.h +238 -0
  120. package/runtime/ext_gui/audio_param.cpp +104 -0
  121. package/runtime/ext_gui/audio_param_object.cpp +155 -0
  122. package/runtime/ext_gui/browser.cpp +45 -50
  123. package/runtime/ext_gui/browser_abort.cpp +249 -0
  124. package/runtime/ext_gui/browser_dialogs.cpp +76 -0
  125. package/runtime/ext_gui/browser_media.cpp +176 -0
  126. package/runtime/ext_gui/browser_navigation.cpp +130 -0
  127. package/runtime/ext_gui/canvas.cpp +88 -30
  128. package/runtime/ext_gui/canvas.h +74 -9
  129. package/runtime/ext_gui/canvas_image_data.cpp +143 -0
  130. package/runtime/ext_gui/canvas_internal.h +8 -5
  131. package/runtime/ext_gui/canvas_pattern.cpp +90 -0
  132. package/runtime/ext_gui/canvas_raster.cpp +31 -9
  133. package/runtime/ext_gui/canvas_style.cpp +4 -2
  134. package/runtime/ext_gui/css_selector.cpp +21 -3
  135. package/runtime/ext_gui/dom.h +4 -0
  136. package/runtime/ext_gui/dom_api.cpp +1 -0
  137. package/runtime/ext_gui/dom_api_canvas.cpp +120 -114
  138. package/runtime/ext_gui/dom_api_canvas_extra.cpp +57 -2
  139. package/runtime/ext_gui/dom_api_canvas_image.cpp +239 -0
  140. package/runtime/ext_gui/dom_api_canvas_paths.cpp +179 -0
  141. package/runtime/ext_gui/dom_api_computed_style.cpp +124 -0
  142. package/runtime/ext_gui/dom_api_dataset.cpp +154 -0
  143. package/runtime/ext_gui/dom_api_document.cpp +58 -5
  144. package/runtime/ext_gui/dom_api_events.cpp +93 -17
  145. package/runtime/ext_gui/dom_api_internal.h +71 -2
  146. package/runtime/ext_gui/dom_api_mutation.cpp +159 -0
  147. package/runtime/ext_gui/dom_api_node.cpp +40 -19
  148. package/runtime/ext_gui/dom_api_node_read.cpp +37 -1
  149. package/runtime/ext_gui/dom_api_path2d.cpp +358 -0
  150. package/runtime/ext_gui/dom_api_proto.cpp +35 -0
  151. package/runtime/ext_gui/dom_api_style.cpp +223 -13
  152. package/runtime/ext_gui/dom_api_webgl.cpp +7 -0
  153. package/runtime/ext_gui/dom_api_webgl2.cpp +151 -36
  154. package/runtime/ext_gui/dom_api_webgl2_draw.cpp +3 -3
  155. package/runtime/ext_gui/dom_api_webgl_buffer.cpp +6 -2
  156. package/runtime/ext_gui/dom_api_webgl_compressed.cpp +167 -0
  157. package/runtime/ext_gui/dom_api_webgl_framebuffer.cpp +160 -0
  158. package/runtime/ext_gui/dom_api_webgl_shader.cpp +4 -4
  159. package/runtime/ext_gui/dom_api_webgl_source.cpp +161 -0
  160. package/runtime/ext_gui/dom_api_webgl_state.cpp +169 -23
  161. package/runtime/ext_gui/dom_api_webgl_texture.cpp +276 -236
  162. package/runtime/ext_gui/dom_api_webgl_ubo.cpp +81 -0
  163. package/runtime/ext_gui/gui.cpp +103 -14
  164. package/runtime/ext_gui/gui_engine.h +56 -4
  165. package/runtime/ext_gui/gui_events.cpp +80 -9
  166. package/runtime/ext_gui/image_bitmap.cpp +28 -0
  167. package/runtime/ext_gui/image_bitmap.h +26 -0
  168. package/runtime/ext_gui/image_bitmap_browser.cpp +136 -0
  169. package/runtime/ext_gui/listener_options.h +43 -0
  170. package/runtime/ext_gui/media.cpp +32 -0
  171. package/runtime/ext_gui/media.h +13 -0
  172. package/runtime/ext_gui/media_api.h +23 -0
  173. package/runtime/ext_gui/paint.cpp +28 -0
  174. package/runtime/ext_gui/paint.h +4 -0
  175. package/runtime/ext_gui/webgl.h +152 -18
  176. package/runtime/ext_gui/webgl_blit.cpp +95 -0
  177. package/runtime/ext_gui/webgl_buffer.cpp +178 -263
  178. package/runtime/ext_gui/webgl_buffer_objects.cpp +270 -0
  179. package/runtime/ext_gui/webgl_clear.cpp +142 -0
  180. package/runtime/ext_gui/webgl_compressed.cpp +180 -0
  181. package/runtime/ext_gui/webgl_context.cpp +241 -156
  182. package/runtime/ext_gui/webgl_draw.cpp +68 -3
  183. package/runtime/ext_gui/webgl_draw_buffers.cpp +75 -0
  184. package/runtime/ext_gui/webgl_glsl.h +40 -0
  185. package/runtime/ext_gui/webgl_glsl_compile.cpp +6 -0
  186. package/runtime/ext_gui/webgl_glsl_rewrite.cpp +18 -0
  187. package/runtime/ext_gui/webgl_glsl_scan.cpp +20 -11
  188. package/runtime/ext_gui/webgl_glsl_scan_block.cpp +126 -0
  189. package/runtime/ext_gui/webgl_glsl_tokens.h +28 -0
  190. package/runtime/ext_gui/webgl_pipeline.cpp +71 -19
  191. package/runtime/ext_gui/webgl_program_blocks.cpp +58 -0
  192. package/runtime/ext_gui/webgl_program_internal.h +6 -0
  193. package/runtime/ext_gui/webgl_shader.cpp +13 -1
  194. package/runtime/ext_gui/webgl_state.cpp +228 -0
  195. package/runtime/ext_gui/webgl_texture.cpp +144 -17
  196. package/runtime/ext_gui/webgl_texture_3d.cpp +215 -0
  197. package/runtime/ext_gui/webgl_uniform_block.h +31 -0
  198. package/runtime/ext_gui/webgl_webgl2.cpp +58 -5
  199. package/runtime/ext_gui/window.cpp +14 -65
  200. package/runtime/ext_gui/window_events.cpp +125 -0
  201. package/runtime/ext_media/decode_audio.cpp +308 -0
  202. package/runtime/ext_media/media_bridge.c +2 -0
  203. package/runtime/rt.h +43 -0
  204. package/runtime/rt_internal.h +4 -0
  205. package/runtime/xt_array_buffer.c +30 -0
  206. package/runtime/xt_builtins.c +0 -21
  207. package/runtime/xt_containers/access.inc +94 -2
  208. package/runtime/xt_containers/objects.inc +29 -31
  209. package/runtime/xt_typed_array/elements.inc +13 -0
  210. package/scripts/build-media.ts +14 -6
  211. package/scripts/build-runtime.ts +21 -16
  212. package/scripts/check-version.ts +39 -9
  213. package/scripts/package-platform.ts +183 -0
  214. package/scripts/set-platform-version.ts +62 -0
  215. package/scripts/verify-platform-package.ts +182 -0
  216. package/src/cli/main.ts +5 -1
  217. package/src/driver/runtime-lib.ts +73 -9
  218. package/src/driver/version.ts +1 -1
  219. package/src/extensions/gui/index.ts +18 -5
  220. package/src/extensions/media/index.ts +4 -3
  221. package/src/parser/context.ts +99 -4
  222. package/src/parser/literals.ts +6 -12
@@ -0,0 +1,228 @@
1
+ /*
2
+ * xbintsc GUI engine — WebGL fixed-function state.
3
+ *
4
+ * SDL_GPU bakes blend/depth/stencil/rasterisation into a pipeline, so these
5
+ * setters only record the values; `webgl_draw.cpp` hashes them into the
6
+ * pipeline cache key and `webgl_pipeline.cpp` builds the matching state.
7
+ */
8
+
9
+ #include "webgl.h"
10
+
11
+ #include <algorithm>
12
+ #include <cstring>
13
+
14
+ #include "gui_internal.h"
15
+
16
+ namespace xtgui {
17
+
18
+ /* -- state --------------------------------------------------------------- */
19
+
20
+ void WebGLContext::enable(int cap) {
21
+ if (cap == GL_BLEND) state_.blend = true;
22
+ if (cap == GL_DEPTH_TEST) state_.depth_test = true;
23
+ if (cap == GL_CULL_FACE) state_.cull = true;
24
+ if (cap == GL_SCISSOR_TEST) scissor_test_ = true;
25
+ if (cap == GL_STENCIL_TEST) state_.stencil = true;
26
+ }
27
+
28
+ void WebGLContext::disable(int cap) {
29
+ if (cap == GL_BLEND) state_.blend = false;
30
+ if (cap == GL_DEPTH_TEST) state_.depth_test = false;
31
+ if (cap == GL_CULL_FACE) state_.cull = false;
32
+ if (cap == GL_SCISSOR_TEST) scissor_test_ = false;
33
+ if (cap == GL_STENCIL_TEST) state_.stencil = false;
34
+ }
35
+
36
+ bool WebGLContext::is_enabled(int cap) const {
37
+ if (cap == GL_BLEND) return state_.blend;
38
+ if (cap == GL_DEPTH_TEST) return state_.depth_test;
39
+ if (cap == GL_CULL_FACE) return state_.cull;
40
+ if (cap == GL_SCISSOR_TEST) return scissor_test_;
41
+ if (cap == GL_STENCIL_TEST) return state_.stencil;
42
+ return false;
43
+ }
44
+
45
+ void WebGLContext::clear_color(float r, float g, float b, float a) {
46
+ clear_color_[0] = r;
47
+ clear_color_[1] = g;
48
+ clear_color_[2] = b;
49
+ clear_color_[3] = a;
50
+ }
51
+
52
+ void WebGLContext::color_mask(bool r, bool g, bool b, bool a) {
53
+ state_.color_mask[0] = r;
54
+ state_.color_mask[1] = g;
55
+ state_.color_mask[2] = b;
56
+ state_.color_mask[3] = a;
57
+ }
58
+
59
+ void WebGLContext::blend_func(int src, int dst) {
60
+ state_.blend_src_rgb = src;
61
+ state_.blend_dst_rgb = dst;
62
+ state_.blend_src_alpha = src;
63
+ state_.blend_dst_alpha = dst;
64
+ }
65
+
66
+ void WebGLContext::blend_func_separate(int src_rgb, int dst_rgb, int src_alpha, int dst_alpha) {
67
+ state_.blend_src_rgb = src_rgb;
68
+ state_.blend_dst_rgb = dst_rgb;
69
+ state_.blend_src_alpha = src_alpha;
70
+ state_.blend_dst_alpha = dst_alpha;
71
+ }
72
+
73
+ void WebGLContext::blend_equation(int mode) {
74
+ state_.blend_eq_rgb = mode;
75
+ state_.blend_eq_alpha = mode;
76
+ }
77
+
78
+ void WebGLContext::blend_equation_separate(int rgb, int alpha) {
79
+ state_.blend_eq_rgb = rgb;
80
+ state_.blend_eq_alpha = alpha;
81
+ }
82
+
83
+ void WebGLContext::blend_color(float r, float g, float b, float a) {
84
+ blend_color_[0] = r;
85
+ blend_color_[1] = g;
86
+ blend_color_[2] = b;
87
+ blend_color_[3] = a;
88
+ }
89
+
90
+ void WebGLContext::blend_color_value(float out[4]) const {
91
+ for (int i = 0; i < 4; i++) out[i] = blend_color_[i];
92
+ }
93
+
94
+ void WebGLContext::cull_face(int mode) { state_.cull_face = mode; }
95
+
96
+ void WebGLContext::front_face(int mode) { state_.front_face = mode; }
97
+
98
+ void WebGLContext::stencil_func(int func, int ref, uint32_t mask) {
99
+ stencil_func_separate(GL_FRONT_AND_BACK, func, ref, mask);
100
+ }
101
+
102
+ void WebGLContext::stencil_func_separate(int face, int func, int ref, uint32_t mask) {
103
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
104
+ state_.stencil_front.func = func;
105
+ state_.stencil_front.ref = ref;
106
+ state_.stencil_front.value_mask = mask;
107
+ }
108
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
109
+ state_.stencil_back.func = func;
110
+ state_.stencil_back.ref = ref;
111
+ state_.stencil_back.value_mask = mask;
112
+ }
113
+ }
114
+
115
+ void WebGLContext::stencil_op(int fail, int zfail, int zpass) {
116
+ stencil_op_separate(GL_FRONT_AND_BACK, fail, zfail, zpass);
117
+ }
118
+
119
+ void WebGLContext::stencil_op_separate(int face, int fail, int zfail, int zpass) {
120
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
121
+ state_.stencil_front.fail = fail;
122
+ state_.stencil_front.zfail = zfail;
123
+ state_.stencil_front.zpass = zpass;
124
+ }
125
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
126
+ state_.stencil_back.fail = fail;
127
+ state_.stencil_back.zfail = zfail;
128
+ state_.stencil_back.zpass = zpass;
129
+ }
130
+ }
131
+
132
+ void WebGLContext::stencil_mask(uint32_t mask) {
133
+ stencil_mask_separate(GL_FRONT_AND_BACK, mask);
134
+ }
135
+
136
+ void WebGLContext::stencil_mask_separate(int face, uint32_t mask) {
137
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK) state_.stencil_front.write_mask = mask;
138
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK) state_.stencil_back.write_mask = mask;
139
+ }
140
+
141
+ const WebGLStencilFace &WebGLContext::stencil_face(int face) const {
142
+ return face == GL_FRONT ? state_.stencil_front : state_.stencil_back;
143
+ }
144
+
145
+ int WebGLContext::stencil_reference() const {
146
+ /* SDL_GPU has one stencil reference for a draw; the front value is the
147
+ * WebGL default for both faces. */
148
+ return state_.stencil_front.ref;
149
+ }
150
+
151
+ void WebGLContext::viewport(int x, int y, int w, int h) {
152
+ viewport_[0] = x;
153
+ viewport_[1] = y;
154
+ viewport_[2] = w;
155
+ viewport_[3] = h;
156
+ }
157
+
158
+ void WebGLContext::scissor(int x, int y, int w, int h) {
159
+ scissor_box_[0] = x;
160
+ scissor_box_[1] = y;
161
+ scissor_box_[2] = w;
162
+ scissor_box_[3] = h;
163
+ }
164
+
165
+ void WebGLContext::clear(int mask) {
166
+ if (guidev::g_device == nullptr) return;
167
+ const bool color_bit = (mask & GL_COLOR_BUFFER_BIT) != 0;
168
+ const bool depth_bit = (mask & GL_DEPTH_BUFFER_BIT) != 0;
169
+ const bool stencil_bit = (mask & GL_STENCIL_BUFFER_BIT) != 0;
170
+ const bool scissored = scissor_test_ && scissor_box_[2] > 0 && scissor_box_[3] > 0;
171
+ if (!scissored) {
172
+ begin_pass(color_bit, depth_bit, stencil_bit);
173
+ return;
174
+ }
175
+ if (color_bit) {
176
+ SDL_GPUTexture *source = clear_color_texture();
177
+ SDL_GPUTexture *destination = target_color();
178
+ int target_width = 0;
179
+ int target_height = 0;
180
+ framebuffer_size(bound_framebuffer_, &target_width, &target_height);
181
+ if (source != nullptr && destination != nullptr && target_width > 0 && target_height > 0) {
182
+ end_pass();
183
+ ensure_command();
184
+ if (cmd_ != nullptr) {
185
+ int x = std::max(0, scissor_box_[0]);
186
+ int y = std::max(0, scissor_box_[1]);
187
+ int w = scissor_box_[2];
188
+ int h = scissor_box_[3];
189
+ if (x + w > target_width) w = target_width - x;
190
+ if (y + h > target_height) h = target_height - y;
191
+ if (w > 0 && h > 0) {
192
+ SDL_GPUBlitRegion source_region;
193
+ memset(&source_region, 0, sizeof(source_region));
194
+ source_region.texture = source;
195
+ source_region.w = 1;
196
+ source_region.h = 1;
197
+ SDL_GPUBlitRegion destination_region;
198
+ memset(&destination_region, 0, sizeof(destination_region));
199
+ destination_region.texture = destination;
200
+ destination_region.x = (Uint32)x;
201
+ destination_region.y = (Uint32)(target_height - (y + h));
202
+ destination_region.w = (Uint32)w;
203
+ destination_region.h = (Uint32)h;
204
+ SDL_GPUBlitInfo info;
205
+ memset(&info, 0, sizeof(info));
206
+ info.source = source_region;
207
+ info.destination = destination_region;
208
+ /* The pixels outside the scissor rectangle must survive the clear, so
209
+ * the blit has to load the destination. DONT_CARE maps to Metal's
210
+ * MTLLoadActionDontCare, which discards the whole attachment before
211
+ * the blit writes its region and leaves the rest undefined (Vulkan
212
+ * happened to preserve it, which hid this in CI on Linux). */
213
+ info.load_op = SDL_GPU_LOADOP_LOAD;
214
+ info.filter = SDL_GPU_FILTER_NEAREST;
215
+ SDL_BlitGPUTexture(cmd_, &info);
216
+ }
217
+ }
218
+ }
219
+ }
220
+ if (depth_bit || stencil_bit) scissored_clear(mask);
221
+ }
222
+
223
+ void WebGLContext::finish() {
224
+ submit();
225
+ if (guidev::g_device != nullptr) SDL_WaitForGPUIdle(guidev::g_device);
226
+ }
227
+
228
+ } // namespace xtgui
@@ -12,16 +12,31 @@
12
12
  namespace xtgui {
13
13
  namespace {
14
14
 
15
- /** Upload an RGBA8 rectangle into level 0 of `gpu`. `rgba` may be null, which
16
- * uploads transparent black. */
15
+ bool depth_texture_format(SDL_GPUTextureFormat format) {
16
+ return format == SDL_GPU_TEXTUREFORMAT_D16_UNORM ||
17
+ format == SDL_GPU_TEXTUREFORMAT_D24_UNORM ||
18
+ format == SDL_GPU_TEXTUREFORMAT_D32_FLOAT ||
19
+ format == SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT ||
20
+ format == SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
21
+ }
22
+
23
+ int texel_bytes(SDL_GPUTextureFormat format) {
24
+ if (format == SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT) return 8;
25
+ if (format == SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT) return 16;
26
+ return 4;
27
+ }
28
+
29
+ /** Upload a rectangle of tightly packed texels into level 0 of `gpu`. `pixels`
30
+ * may be null, which uploads zeros. */
17
31
  bool upload_region(SDL_GPUDevice *device, SDL_GPUCommandBuffer *cmd, SDL_GPUTexture *gpu, int x,
18
- int y, int width, int height, const uint8_t *rgba) {
19
- const uint32_t bytes = (uint32_t)(width * height * 4);
32
+ int y, int width, int height, const uint8_t *pixels, int bytes_per_texel,
33
+ int layer = 0) {
34
+ const uint32_t bytes = (uint32_t)(width * height * bytes_per_texel);
20
35
  if (bytes == 0) return true;
21
36
  std::vector<uint8_t> zeros;
22
- if (rgba == nullptr) {
37
+ if (pixels == nullptr) {
23
38
  zeros.assign(bytes, 0);
24
- rgba = zeros.data();
39
+ pixels = zeros.data();
25
40
  }
26
41
  SDL_GPUTransferBufferCreateInfo info;
27
42
  memset(&info, 0, sizeof(info));
@@ -34,7 +49,7 @@ bool upload_region(SDL_GPUDevice *device, SDL_GPUCommandBuffer *cmd, SDL_GPUText
34
49
  SDL_ReleaseGPUTransferBuffer(device, transfer);
35
50
  return false;
36
51
  }
37
- memcpy(mapped, rgba, bytes);
52
+ memcpy(mapped, pixels, bytes);
38
53
  SDL_UnmapGPUTransferBuffer(device, transfer);
39
54
  SDL_GPUTextureTransferInfo source;
40
55
  memset(&source, 0, sizeof(source));
@@ -46,6 +61,7 @@ bool upload_region(SDL_GPUDevice *device, SDL_GPUCommandBuffer *cmd, SDL_GPUText
46
61
  region.texture = gpu;
47
62
  region.x = (Uint32)x;
48
63
  region.y = (Uint32)y;
64
+ region.layer = (Uint32)layer;
49
65
  region.w = (Uint32)width;
50
66
  region.h = (Uint32)height;
51
67
  region.d = 1;
@@ -58,7 +74,44 @@ bool upload_region(SDL_GPUDevice *device, SDL_GPUCommandBuffer *cmd, SDL_GPUText
58
74
 
59
75
  } // namespace
60
76
 
61
- bool WebGLContext::tex_image_rgba(uint32_t id, int width, int height, const uint8_t *rgba) {
77
+ SDL_GPUTexture *WebGLContext::clear_color_texture() {
78
+ if (guidev::g_device == nullptr) return nullptr;
79
+ if (clear_texture_ == nullptr) {
80
+ end_pass();
81
+ ensure_command();
82
+ SDL_GPUTextureCreateInfo info;
83
+ memset(&info, 0, sizeof(info));
84
+ info.type = SDL_GPU_TEXTURETYPE_2D;
85
+ info.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
86
+ info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
87
+ info.width = 1;
88
+ info.height = 1;
89
+ info.layer_count_or_depth = 1;
90
+ info.num_levels = 1;
91
+ info.sample_count = SDL_GPU_SAMPLECOUNT_1;
92
+ clear_texture_ = SDL_CreateGPUTexture(guidev::g_device, &info);
93
+ if (clear_texture_ == nullptr) {
94
+ set_error(GL_OUT_OF_MEMORY);
95
+ return nullptr;
96
+ }
97
+ }
98
+ end_pass();
99
+ ensure_command();
100
+ if (cmd_ == nullptr) return clear_texture_;
101
+ uint8_t rgba[4];
102
+ for (int i = 0; i < 4; i++) {
103
+ float value = clear_color_[i];
104
+ if (value < 0.0f) value = 0.0f;
105
+ if (value > 1.0f) value = 1.0f;
106
+ rgba[i] = (uint8_t)(value * 255.0f + 0.5f);
107
+ }
108
+ upload_region(guidev::g_device, cmd_, clear_texture_, 0, 0, 1, 1, rgba, 4);
109
+ return clear_texture_;
110
+ }
111
+
112
+ bool WebGLContext::tex_image_format(uint32_t id, int width, int height,
113
+ SDL_GPUTextureFormat format, const uint8_t *pixels,
114
+ int layer) {
62
115
  WebGLTexture *record = texture(id);
63
116
  if (record == nullptr || width <= 0 || height <= 0) {
64
117
  set_error(GL_INVALID_VALUE);
@@ -67,27 +120,43 @@ bool WebGLContext::tex_image_rgba(uint32_t id, int width, int height, const uint
67
120
  end_pass();
68
121
  ensure_command();
69
122
  if (cmd_ == nullptr) return false;
70
- if (record->width != width || record->height != height) {
123
+ if (record->width != width || record->height != height || record->format != format) {
71
124
  if (record->gpu != nullptr) {
72
125
  SDL_WaitForGPUIdle(guidev::g_device);
73
126
  SDL_ReleaseGPUTexture(guidev::g_device, record->gpu);
74
127
  record->gpu = nullptr;
128
+ record->usage = 0;
75
129
  }
76
130
  record->width = width;
77
131
  record->height = height;
132
+ record->format = format;
133
+ record->layers = 1;
134
+ record->target = layer >= 0 ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
135
+ record->compressed = false;
78
136
  record->has_mipmaps = false;
79
137
  if (record->sampler != nullptr) {
80
138
  SDL_ReleaseGPUSampler(guidev::g_device, record->sampler);
81
139
  record->sampler = nullptr;
82
140
  }
83
141
  }
84
- if (ensure_texture_gpu(record, record->as_target) == nullptr) return false;
142
+ if (ensure_texture_gpu(record, record->as_target || record->as_depth_target) == nullptr) {
143
+ return false;
144
+ }
85
145
  record->defined = true;
86
- return upload_region(guidev::g_device, cmd_, record->gpu, 0, 0, width, height, rgba);
146
+ if (layer >= 0) {
147
+ record->target = GL_TEXTURE_CUBE_MAP;
148
+ record->layers = 6;
149
+ }
150
+ return upload_region(guidev::g_device, cmd_, record->gpu, 0, 0, width, height, pixels,
151
+ texel_bytes(format), layer >= 0 ? layer : 0);
87
152
  }
88
153
 
89
- bool WebGLContext::tex_sub_image_rgba(uint32_t id, int x, int y, int width, int height,
90
- const uint8_t *rgba) {
154
+ bool WebGLContext::tex_image_rgba(uint32_t id, int width, int height, const uint8_t *rgba) {
155
+ return tex_image_format(id, width, height, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, rgba);
156
+ }
157
+
158
+ bool WebGLContext::tex_sub_image_format(uint32_t id, int x, int y, int width, int height,
159
+ const uint8_t *pixels, int layer) {
91
160
  WebGLTexture *record = texture(id);
92
161
  if (record == nullptr || !record->defined || record->gpu == nullptr) {
93
162
  set_error(GL_INVALID_OPERATION);
@@ -101,7 +170,13 @@ bool WebGLContext::tex_sub_image_rgba(uint32_t id, int x, int y, int width, int
101
170
  end_pass();
102
171
  ensure_command();
103
172
  if (cmd_ == nullptr) return false;
104
- return upload_region(guidev::g_device, cmd_, record->gpu, x, y, width, height, rgba);
173
+ return upload_region(guidev::g_device, cmd_, record->gpu, x, y, width, height, pixels,
174
+ texel_bytes(record->format), layer);
175
+ }
176
+
177
+ bool WebGLContext::tex_sub_image_rgba(uint32_t id, int x, int y, int width, int height,
178
+ const uint8_t *rgba) {
179
+ return tex_sub_image_format(id, x, y, width, height, rgba);
105
180
  }
106
181
 
107
182
  bool WebGLContext::generate_mipmap(uint32_t id) {
@@ -110,6 +185,11 @@ bool WebGLContext::generate_mipmap(uint32_t id) {
110
185
  set_error(GL_INVALID_OPERATION);
111
186
  return false;
112
187
  }
188
+ if (record->depth) {
189
+ /* Depth textures have no mip chain in this backend. */
190
+ set_error(GL_INVALID_OPERATION);
191
+ return false;
192
+ }
113
193
  end_pass();
114
194
  ensure_command();
115
195
  if (cmd_ == nullptr || record->levels <= 1) return false;
@@ -124,7 +204,25 @@ bool WebGLContext::generate_mipmap(uint32_t id) {
124
204
 
125
205
  bool WebGLContext::read_pixels(int x, int y, int width, int height, uint8_t *out) {
126
206
  if (out == nullptr || width <= 0 || height <= 0) return false;
207
+ if (target_color_format() != (int)SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM) {
208
+ /* The only readback this surface offers is RGBA8; a float/half colour
209
+ * target is read by rendering it into an RGBA8 target instead. */
210
+ set_error(GL_INVALID_OPERATION);
211
+ return false;
212
+ }
127
213
  SDL_GPUTexture *target = target_color();
214
+ if (bound_framebuffer_ != 0) {
215
+ WebGLFramebuffer *framebuffer = this->framebuffer(bound_framebuffer_);
216
+ if (framebuffer != nullptr) {
217
+ int index = read_buffer_ - GL_COLOR_ATTACHMENT0;
218
+ if (index < 0 || index >= kWebGLMaxDrawBuffers ||
219
+ framebuffer->color_textures[index] == 0) {
220
+ index = 0;
221
+ }
222
+ WebGLTexture *read_texture = texture(framebuffer->color_textures[index]);
223
+ target = read_texture != nullptr ? ensure_texture_gpu(read_texture, true) : nullptr;
224
+ }
225
+ }
128
226
  int target_width = bound_framebuffer_ == 0 ? width_ : 0;
129
227
  int target_height = bound_framebuffer_ == 0 ? height_ : 0;
130
228
  if (bound_framebuffer_ != 0) {
@@ -196,7 +294,8 @@ bool WebGLContext::read_pixels(int x, int y, int width, int height, uint8_t *out
196
294
  return true;
197
295
  }
198
296
 
199
- bool WebGLContext::tex_storage_2d(uint32_t id, int levels, int width, int height) {
297
+ bool WebGLContext::tex_storage_format(uint32_t id, int levels, int width, int height,
298
+ SDL_GPUTextureFormat format) {
200
299
  (void)levels; // the backend always allocates the full mip chain
201
300
  WebGLTexture *record = texture(id);
202
301
  if (record == nullptr || width <= 0 || height <= 0) {
@@ -210,20 +309,29 @@ bool WebGLContext::tex_storage_2d(uint32_t id, int levels, int width, int height
210
309
  SDL_WaitForGPUIdle(guidev::g_device);
211
310
  SDL_ReleaseGPUTexture(guidev::g_device, record->gpu);
212
311
  record->gpu = nullptr;
312
+ record->usage = 0;
213
313
  }
214
314
  record->width = width;
215
315
  record->height = height;
316
+ record->format = format;
317
+ record->layers = 1;
318
+ record->target = GL_TEXTURE_2D;
319
+ record->compressed = false;
216
320
  record->has_mipmaps = false;
217
321
  if (record->sampler != nullptr && guidev::g_device != nullptr) {
218
322
  SDL_ReleaseGPUSampler(guidev::g_device, record->sampler);
219
323
  record->sampler = nullptr;
220
324
  }
221
325
  record->defined = true;
222
- return ensure_texture_gpu(record, record->as_target) != nullptr;
326
+ return ensure_texture_gpu(record, record->as_target || record->as_depth_target) != nullptr;
223
327
  }
224
328
 
225
- /* -- WebGL 2 clearBuffer* ------------------------------------------------ */
329
+ bool WebGLContext::tex_storage_2d(uint32_t id, int levels, int width, int height) {
330
+ return tex_storage_format(id, levels, width, height,
331
+ SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM);
332
+ }
226
333
 
334
+ /* -- WebGL 2 clearBuffer* ------------------------------------------------ */
227
335
  void WebGLContext::clear_buffer_float(int buffer, int drawbuffer, const float *values,
228
336
  int count) {
229
337
  if (buffer == GL_COLOR) {
@@ -290,4 +398,23 @@ void WebGLContext::clear_buffer_fi(int buffer, int drawbuffer, float depth, int
290
398
  }
291
399
  }
292
400
 
401
+ SDL_GPUTextureFormat webgl_storage_format(int internalformat) {
402
+ if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_DEPTH_COMPONENT24 ||
403
+ internalformat == GL_DEPTH_COMPONENT32F) {
404
+ return SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
405
+ }
406
+ if (internalformat == GL_DEPTH_STENCIL || internalformat == GL_DEPTH24_STENCIL8) {
407
+ return SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
408
+ }
409
+ if (internalformat == GL_RGBA32F || internalformat == GL_RGB32F ||
410
+ internalformat == GL_RG32F || internalformat == GL_R32F) {
411
+ return SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT;
412
+ }
413
+ if (internalformat == GL_RGBA16F || internalformat == GL_RGB16F ||
414
+ internalformat == GL_RG16F || internalformat == GL_R16F) {
415
+ return SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT;
416
+ }
417
+ return SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
418
+ }
419
+
293
420
  } // namespace xtgui