xbintsc 0.5.32 → 0.5.36
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 +10 -7
- package/README.zh-CN.md +10 -8
- package/dist/scripts/check-version.d.ts +27 -0
- package/dist/scripts/check-version.js +71 -0
- package/dist/scripts/check-version.js.map +1 -0
- package/dist/scripts/package-platform.d.ts +58 -0
- package/dist/scripts/package-platform.js +142 -0
- package/dist/scripts/package-platform.js.map +1 -0
- package/dist/scripts/verify-platform-package.d.ts +34 -0
- package/dist/scripts/verify-platform-package.js +161 -0
- package/dist/scripts/verify-platform-package.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/cli/main.js +3 -1
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +29 -4
- package/dist/src/driver/runtime-lib.js +68 -10
- package/dist/src/driver/runtime-lib.js.map +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/gui/index.js +6 -5
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/media/index.js +4 -3
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/src/parser/context.d.ts +41 -0
- package/dist/src/parser/context.js +89 -4
- package/dist/src/parser/context.js.map +1 -1
- package/dist/src/parser/literals.js +6 -12
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/driver/platform-package.test.d.ts +1 -0
- package/dist/tests/driver/platform-package.test.js +49 -0
- package/dist/tests/driver/platform-package.test.js.map +1 -0
- package/dist/tests/driver/runtime-lib.test.js +51 -4
- package/dist/tests/driver/runtime-lib.test.js.map +1 -1
- package/dist/tests/e2e/gui-audio.test.d.ts +14 -0
- package/dist/tests/e2e/gui-audio.test.js +287 -0
- package/dist/tests/e2e/gui-audio.test.js.map +1 -0
- package/dist/tests/e2e/gui-helpers.d.ts +7 -0
- package/dist/tests/e2e/gui-helpers.js +1 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +78 -0
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-style.test.js +55 -0
- package/dist/tests/e2e/gui-style.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.js +258 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl2-3d.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js +264 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js +262 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.d.ts +6 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js +395 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js +105 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.d.ts +8 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js +112 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.js +45 -1
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -1
- package/dist/tests/extensions/gui-index.test.js +1 -0
- package/dist/tests/extensions/gui-index.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +1 -0
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +30 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/platform-tarball.test.d.ts +1 -0
- package/dist/tests/platform-tarball.test.js +111 -0
- package/dist/tests/platform-tarball.test.js.map +1 -0
- package/dist/tests/version.test.js +6 -0
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/contributing.md +11 -0
- package/doc/ai/extensions.md +7 -4
- package/doc/ai/troubleshooting.md +7 -5
- package/doc/ai/zh-CN/contributing.md +9 -0
- package/doc/ai/zh-CN/extensions.md +4 -2
- package/doc/ai/zh-CN/troubleshooting.md +5 -3
- package/doc/gui/api.md +61 -13
- package/doc/gui/build.md +11 -4
- package/doc/gui/dom.md +6 -3
- package/doc/gui/media.md +4 -0
- package/doc/gui/webgl.md +105 -46
- package/doc/gui.md +7 -3
- package/doc/npm-package.md +55 -27
- package/doc/requirements.md +6 -2
- package/doc/zh-CN/gui/api.md +51 -10
- package/doc/zh-CN/gui/build.md +7 -2
- package/doc/zh-CN/gui/dom.md +3 -1
- package/doc/zh-CN/gui/media.md +3 -0
- package/doc/zh-CN/gui/webgl.md +22 -16
- package/doc/zh-CN/gui.md +3 -2
- package/doc/zh-CN/npm-package.md +44 -23
- package/doc/zh-CN/requirements.md +4 -1
- package/package.json +17 -1
- package/runtime/ext_gui/audio.cpp +365 -153
- package/runtime/ext_gui/audio_buffer.cpp +166 -0
- package/runtime/ext_gui/audio_buffer.h +37 -0
- package/runtime/ext_gui/audio_decode.cpp +219 -0
- package/runtime/ext_gui/audio_decode.h +39 -0
- package/runtime/ext_gui/audio_device.cpp +87 -0
- package/runtime/ext_gui/audio_effects.cpp +163 -0
- package/runtime/ext_gui/audio_effects.h +25 -0
- package/runtime/ext_gui/audio_internal.h +30 -0
- package/runtime/ext_gui/audio_mixer.cpp +494 -0
- package/runtime/ext_gui/audio_mixer.h +238 -0
- package/runtime/ext_gui/audio_param.cpp +104 -0
- package/runtime/ext_gui/audio_param_object.cpp +155 -0
- package/runtime/ext_gui/browser.cpp +11 -1
- package/runtime/ext_gui/css_selector.cpp +21 -3
- package/runtime/ext_gui/dom_api_internal.h +16 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +7 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +151 -36
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +3 -3
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +6 -2
- package/runtime/ext_gui/dom_api_webgl_compressed.cpp +167 -0
- package/runtime/ext_gui/dom_api_webgl_framebuffer.cpp +160 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +4 -4
- package/runtime/ext_gui/dom_api_webgl_source.cpp +161 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +169 -23
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +276 -236
- package/runtime/ext_gui/dom_api_webgl_ubo.cpp +81 -0
- package/runtime/ext_gui/gui.cpp +44 -9
- package/runtime/ext_gui/gui_engine.h +9 -4
- package/runtime/ext_gui/image_bitmap.cpp +28 -0
- package/runtime/ext_gui/image_bitmap.h +26 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +136 -0
- package/runtime/ext_gui/media.cpp +32 -0
- package/runtime/ext_gui/media.h +13 -0
- package/runtime/ext_gui/media_api.h +23 -0
- package/runtime/ext_gui/webgl.h +152 -18
- package/runtime/ext_gui/webgl_blit.cpp +95 -0
- package/runtime/ext_gui/webgl_buffer.cpp +178 -263
- package/runtime/ext_gui/webgl_buffer_objects.cpp +270 -0
- package/runtime/ext_gui/webgl_clear.cpp +142 -0
- package/runtime/ext_gui/webgl_compressed.cpp +180 -0
- package/runtime/ext_gui/webgl_context.cpp +241 -156
- package/runtime/ext_gui/webgl_draw.cpp +68 -3
- package/runtime/ext_gui/webgl_draw_buffers.cpp +75 -0
- package/runtime/ext_gui/webgl_glsl.h +40 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +6 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +18 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +20 -11
- package/runtime/ext_gui/webgl_glsl_scan_block.cpp +126 -0
- package/runtime/ext_gui/webgl_glsl_tokens.h +28 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +71 -19
- package/runtime/ext_gui/webgl_program_blocks.cpp +58 -0
- package/runtime/ext_gui/webgl_program_internal.h +6 -0
- package/runtime/ext_gui/webgl_shader.cpp +13 -1
- package/runtime/ext_gui/webgl_state.cpp +228 -0
- package/runtime/ext_gui/webgl_texture.cpp +144 -17
- package/runtime/ext_gui/webgl_texture_3d.cpp +215 -0
- package/runtime/ext_gui/webgl_uniform_block.h +31 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +58 -5
- package/runtime/ext_media/decode_audio.cpp +308 -0
- package/runtime/ext_media/media_bridge.c +2 -0
- package/runtime/rt.h +17 -0
- package/runtime/xt_array_buffer.c +30 -0
- package/runtime/xt_typed_array/elements.inc +13 -0
- package/scripts/build-media.ts +14 -6
- package/scripts/build-runtime.ts +21 -16
- package/scripts/check-version.ts +39 -9
- package/scripts/package-platform.ts +183 -0
- package/scripts/set-platform-version.ts +62 -0
- package/scripts/verify-platform-package.ts +182 -0
- package/src/cli/main.ts +5 -1
- package/src/driver/runtime-lib.ts +73 -9
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/index.ts +6 -5
- package/src/extensions/media/index.ts +4 -3
- package/src/parser/context.ts +99 -4
- package/src/parser/literals.ts +6 -12
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc GUI engine — WebGL pixel sources.
|
|
3
|
+
*
|
|
4
|
+
* Decodes the things `texImage2D` accepts (`<img>`, `<canvas>`, `<video>`,
|
|
5
|
+
* `ImageData` and `ImageBitmap`) into tightly packed RGBA8, and converts the
|
|
6
|
+
* RGBA/RGB/LUMINANCE families to that layout.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#include "dom_api_internal.h"
|
|
10
|
+
|
|
11
|
+
#include <cstring>
|
|
12
|
+
#include <string>
|
|
13
|
+
#include <vector>
|
|
14
|
+
|
|
15
|
+
#include "dom_api_webgl_rt.h"
|
|
16
|
+
#include "image.h"
|
|
17
|
+
#include "image_bitmap.h"
|
|
18
|
+
#include "webgl.h"
|
|
19
|
+
|
|
20
|
+
namespace domapi {
|
|
21
|
+
namespace {
|
|
22
|
+
|
|
23
|
+
void flip_rows(std::vector<uint8_t> *pixels, int width, int height) {
|
|
24
|
+
const size_t stride = (size_t)width * 4;
|
|
25
|
+
std::vector<uint8_t> row(stride);
|
|
26
|
+
for (int y = 0; y < height / 2; y++) {
|
|
27
|
+
uint8_t *top = pixels->data() + (size_t)y * stride;
|
|
28
|
+
uint8_t *bottom = pixels->data() + (size_t)(height - 1 - y) * stride;
|
|
29
|
+
memcpy(row.data(), top, stride);
|
|
30
|
+
memcpy(top, bottom, stride);
|
|
31
|
+
memcpy(bottom, row.data(), stride);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
} // namespace
|
|
36
|
+
|
|
37
|
+
void webgl_convert_pixels(const uint8_t *source, int count, int format, bool premultiply,
|
|
38
|
+
std::vector<uint8_t> *out) {
|
|
39
|
+
out->assign((size_t)count * 4, 255);
|
|
40
|
+
for (int i = 0; i < count; i++) {
|
|
41
|
+
uint8_t r = 0;
|
|
42
|
+
uint8_t g = 0;
|
|
43
|
+
uint8_t b = 0;
|
|
44
|
+
uint8_t a = 255;
|
|
45
|
+
switch (format) {
|
|
46
|
+
case GL_RGBA:
|
|
47
|
+
r = source[i * 4 + 0];
|
|
48
|
+
g = source[i * 4 + 1];
|
|
49
|
+
b = source[i * 4 + 2];
|
|
50
|
+
a = source[i * 4 + 3];
|
|
51
|
+
break;
|
|
52
|
+
case GL_RGB:
|
|
53
|
+
r = source[i * 3 + 0];
|
|
54
|
+
g = source[i * 3 + 1];
|
|
55
|
+
b = source[i * 3 + 2];
|
|
56
|
+
break;
|
|
57
|
+
case GL_LUMINANCE_ALPHA:
|
|
58
|
+
r = g = b = source[i * 2 + 0];
|
|
59
|
+
a = source[i * 2 + 1];
|
|
60
|
+
break;
|
|
61
|
+
case GL_ALPHA:
|
|
62
|
+
a = source[i];
|
|
63
|
+
r = g = b = 0;
|
|
64
|
+
break;
|
|
65
|
+
case GL_LUMINANCE:
|
|
66
|
+
default:
|
|
67
|
+
r = g = b = source[i];
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
if (premultiply) {
|
|
71
|
+
r = (uint8_t)((r * a + 127) / 255);
|
|
72
|
+
g = (uint8_t)((g * a + 127) / 255);
|
|
73
|
+
b = (uint8_t)((b * a + 127) / 255);
|
|
74
|
+
}
|
|
75
|
+
(*out)[(size_t)i * 4 + 0] = r;
|
|
76
|
+
(*out)[(size_t)i * 4 + 1] = g;
|
|
77
|
+
(*out)[(size_t)i * 4 + 2] = b;
|
|
78
|
+
(*out)[(size_t)i * 4 + 3] = a;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
/** Decode a DOM source into top-down RGBA8. */
|
|
84
|
+
bool webgl_read_source(xt_value source, int *width, int *height, std::vector<uint8_t> *rgba,
|
|
85
|
+
bool premultiply) {
|
|
86
|
+
if (XT_IS_OBJECT(source)) {
|
|
87
|
+
xt_value bitmap_id = xt_object_get_cstr(source, "__xt_bitmap");
|
|
88
|
+
if (XT_IS_NUMBER(bitmap_id)) {
|
|
89
|
+
const xtgui::Image *bitmap =
|
|
90
|
+
xtgui::xt_image_bitmap_get((uint64_t)xt_to_number(bitmap_id));
|
|
91
|
+
if (bitmap == nullptr || bitmap->width <= 0 || bitmap->height <= 0) return false;
|
|
92
|
+
*width = bitmap->width;
|
|
93
|
+
*height = bitmap->height;
|
|
94
|
+
if (premultiply) {
|
|
95
|
+
webgl_convert_pixels(bitmap->pixels.data(), bitmap->width * bitmap->height, GL_RGBA, true,
|
|
96
|
+
rgba);
|
|
97
|
+
} else {
|
|
98
|
+
*rgba = bitmap->pixels;
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
XtGuiWindow *win = nullptr;
|
|
104
|
+
xtgui::Node *node = resolve_node(source, &win);
|
|
105
|
+
const xtgui::Image *image = nullptr;
|
|
106
|
+
std::vector<uint8_t> owned;
|
|
107
|
+
if (node != nullptr && node->isElement() && node->isTag("img")) {
|
|
108
|
+
const std::string *src = node->attr("src");
|
|
109
|
+
if (src != nullptr) image = xtgui::xt_image_load(*src);
|
|
110
|
+
} else if (node != nullptr && node->isElement() && node->isTag("video")) {
|
|
111
|
+
xtgui::MediaPlayer *player = xt_gui_media_player(win, node);
|
|
112
|
+
if (player != nullptr) image = player->frame();
|
|
113
|
+
} else if (node != nullptr && node->isElement() && node->isTag("canvas")) {
|
|
114
|
+
if (xtgui::Canvas2D *canvas = xt_gui_canvas_find(win, node)) {
|
|
115
|
+
image = &canvas->image();
|
|
116
|
+
} else if (xtgui::WebGLContext *context = xt_gui_webgl_find(win, node)) {
|
|
117
|
+
owned.resize((size_t)context->width() * context->height() * 4);
|
|
118
|
+
if (!context->read_pixels(0, 0, context->width(), context->height(), owned.data())) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
/* `readPixels` is GL-ordered (bottom-up); textures are stored top-down. */
|
|
122
|
+
flip_rows(&owned, context->width(), context->height());
|
|
123
|
+
*width = context->width();
|
|
124
|
+
*height = context->height();
|
|
125
|
+
rgba->swap(owned);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
} else if (XT_IS_OBJECT(source) && !xt_is_array_buffer(source)) {
|
|
129
|
+
xt_value data = xt_object_get_cstr(source, "data");
|
|
130
|
+
xt_value width_value = xt_object_get_cstr(source, "width");
|
|
131
|
+
xt_value height_value = xt_object_get_cstr(source, "height");
|
|
132
|
+
if (XT_IS_OBJECT(data) && XT_IS_NUMBER(width_value) && XT_IS_NUMBER(height_value)) {
|
|
133
|
+
const int w = (int)xt_to_number(width_value);
|
|
134
|
+
const int h = (int)xt_to_number(height_value);
|
|
135
|
+
const std::vector<uint8_t> bytes = webgl_bytes(data);
|
|
136
|
+
if (w <= 0 || h <= 0 || bytes.size() < (size_t)w * h * 4) return false;
|
|
137
|
+
webgl_convert_pixels(bytes.data(), w * h, GL_RGBA, premultiply, rgba);
|
|
138
|
+
*width = w;
|
|
139
|
+
*height = h;
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
/* `new Image()` is a plain object with a `src`. */
|
|
143
|
+
xt_value src = xt_object_get_cstr(source, "src");
|
|
144
|
+
if (XT_IS_STRING(src)) {
|
|
145
|
+
const char *path = xt_string_data(xt_to_string(src));
|
|
146
|
+
if (path != nullptr && path[0] != '\0') image = xtgui::xt_image_load(path);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (image == nullptr || image->width <= 0 || image->height <= 0) return false;
|
|
150
|
+
*width = image->width;
|
|
151
|
+
*height = image->height;
|
|
152
|
+
if (premultiply) {
|
|
153
|
+
webgl_convert_pixels(image->pixels.data(), image->width * image->height, GL_RGBA, true, rgba);
|
|
154
|
+
} else {
|
|
155
|
+
*rgba = image->pixels;
|
|
156
|
+
}
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
} // namespace domapi
|
|
@@ -14,7 +14,16 @@
|
|
|
14
14
|
namespace domapi {
|
|
15
15
|
namespace {
|
|
16
16
|
|
|
17
|
-
xtgui::WebGLContext *context_of(xt_value self) { return
|
|
17
|
+
xtgui::WebGLContext *context_of(xt_value self) { return webgl_live_context(self); }
|
|
18
|
+
|
|
19
|
+
/** Fire a `webglcontextlost`/`webglcontextrestored` event on the canvas that
|
|
20
|
+
* owns the context. `self` is the context or extension handle. */
|
|
21
|
+
void dispatch_context_event(xt_value self, const char *type) {
|
|
22
|
+
XtGuiWindow *win = nullptr;
|
|
23
|
+
xtgui::Node *node =
|
|
24
|
+
resolve_node(xt_object_get_cstr(self, "__xt_gl_node"), &win);
|
|
25
|
+
if (win != nullptr && node != nullptr) xt_gui_dispatch_to_node(win, node, type);
|
|
26
|
+
}
|
|
18
27
|
|
|
19
28
|
xt_value number_array(const double *values, int count) {
|
|
20
29
|
xt_value array = xt_array_new(0, nullptr);
|
|
@@ -28,6 +37,9 @@ xt_value object_for(xt_value self, uint32_t id, const char *key, const char *kin
|
|
|
28
37
|
|
|
29
38
|
} // namespace
|
|
30
39
|
|
|
40
|
+
METHOD(webgl_lose_context);
|
|
41
|
+
METHOD(webgl_restore_context);
|
|
42
|
+
|
|
31
43
|
void webgl_unpack_flags(xt_value context, bool *flip_y, bool *premultiply) {
|
|
32
44
|
*flip_y = value_truthy(xt_object_get_cstr(context, "__xt_unpack_flip_y"));
|
|
33
45
|
*premultiply = value_truthy(xt_object_get_cstr(context, "__xt_unpack_premultiply"));
|
|
@@ -121,8 +133,13 @@ METHOD(webgl_depth_range) {
|
|
|
121
133
|
|
|
122
134
|
METHOD(webgl_blend_color) {
|
|
123
135
|
(void)env;
|
|
124
|
-
(
|
|
125
|
-
(
|
|
136
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
137
|
+
if (context != nullptr) {
|
|
138
|
+
context->blend_color((float)webgl_number(argc, argv, 0, 0.0),
|
|
139
|
+
(float)webgl_number(argc, argv, 1, 0.0),
|
|
140
|
+
(float)webgl_number(argc, argv, 2, 0.0),
|
|
141
|
+
(float)webgl_number(argc, argv, 3, 0.0));
|
|
142
|
+
}
|
|
126
143
|
return XT_UNDEFINED;
|
|
127
144
|
}
|
|
128
145
|
|
|
@@ -258,7 +275,8 @@ METHOD(webgl_get_error) {
|
|
|
258
275
|
(void)env;
|
|
259
276
|
(void)argc;
|
|
260
277
|
(void)argv;
|
|
261
|
-
xtgui::WebGLContext *context =
|
|
278
|
+
xtgui::WebGLContext *context = webgl_from_context(self);
|
|
279
|
+
if (context != nullptr && context->lost()) return xt_number(GL_CONTEXT_LOST_WEBGL);
|
|
262
280
|
return xt_number(context != nullptr ? context->error() : GL_NO_ERROR);
|
|
263
281
|
}
|
|
264
282
|
|
|
@@ -280,6 +298,34 @@ METHOD(webgl_get_parameter) {
|
|
|
280
298
|
const double values[4] = {(double)box[0], (double)box[1], (double)box[2], (double)box[3]};
|
|
281
299
|
return number_array(values, 4);
|
|
282
300
|
}
|
|
301
|
+
case GL_STENCIL_FUNC:
|
|
302
|
+
return xt_number(context->stencil_face(GL_FRONT).func);
|
|
303
|
+
case GL_STENCIL_REF:
|
|
304
|
+
return xt_number(context->stencil_face(GL_FRONT).ref);
|
|
305
|
+
case GL_STENCIL_VALUE_MASK:
|
|
306
|
+
return xt_number((double)context->stencil_face(GL_FRONT).value_mask);
|
|
307
|
+
case GL_STENCIL_WRITEMASK:
|
|
308
|
+
return xt_number((double)context->stencil_face(GL_FRONT).write_mask);
|
|
309
|
+
case GL_STENCIL_FAIL:
|
|
310
|
+
return xt_number(context->stencil_face(GL_FRONT).fail);
|
|
311
|
+
case GL_STENCIL_PASS_DEPTH_FAIL:
|
|
312
|
+
return xt_number(context->stencil_face(GL_FRONT).zfail);
|
|
313
|
+
case GL_STENCIL_PASS_DEPTH_PASS:
|
|
314
|
+
return xt_number(context->stencil_face(GL_FRONT).zpass);
|
|
315
|
+
case GL_STENCIL_BACK_FUNC:
|
|
316
|
+
return xt_number(context->stencil_face(GL_BACK).func);
|
|
317
|
+
case GL_STENCIL_BACK_REF:
|
|
318
|
+
return xt_number(context->stencil_face(GL_BACK).ref);
|
|
319
|
+
case GL_STENCIL_BACK_VALUE_MASK:
|
|
320
|
+
return xt_number((double)context->stencil_face(GL_BACK).value_mask);
|
|
321
|
+
case GL_STENCIL_BACK_WRITEMASK:
|
|
322
|
+
return xt_number((double)context->stencil_face(GL_BACK).write_mask);
|
|
323
|
+
case GL_STENCIL_BACK_FAIL:
|
|
324
|
+
return xt_number(context->stencil_face(GL_BACK).fail);
|
|
325
|
+
case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
|
|
326
|
+
return xt_number(context->stencil_face(GL_BACK).zfail);
|
|
327
|
+
case GL_STENCIL_BACK_PASS_DEPTH_PASS:
|
|
328
|
+
return xt_number(context->stencil_face(GL_BACK).zpass);
|
|
283
329
|
case GL_COLOR_CLEAR_VALUE: {
|
|
284
330
|
const double values[4] = {0, 0, 0, 0};
|
|
285
331
|
return number_array(values, 4);
|
|
@@ -289,8 +335,10 @@ METHOD(webgl_get_parameter) {
|
|
|
289
335
|
return number_array(values, 2);
|
|
290
336
|
}
|
|
291
337
|
case GL_BLEND_COLOR: {
|
|
292
|
-
|
|
293
|
-
|
|
338
|
+
float values[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
339
|
+
context->blend_color_value(values);
|
|
340
|
+
const double out[4] = {values[0], values[1], values[2], values[3]};
|
|
341
|
+
return number_array(out, 4);
|
|
294
342
|
}
|
|
295
343
|
case GL_ALIASED_LINE_WIDTH_RANGE:
|
|
296
344
|
case GL_ALIASED_POINT_SIZE_RANGE: {
|
|
@@ -318,12 +366,36 @@ METHOD(webgl_get_parameter) {
|
|
|
318
366
|
? webgl_make_object(self, "__xt_gl_texture", texture, "texture")
|
|
319
367
|
: XT_NULL;
|
|
320
368
|
}
|
|
369
|
+
case GL_TEXTURE_BINDING_CUBE_MAP: {
|
|
370
|
+
const uint32_t texture = context->bound_cube_texture(0);
|
|
371
|
+
return texture != 0
|
|
372
|
+
? webgl_make_object(self, "__xt_gl_texture", texture, "texture")
|
|
373
|
+
: XT_NULL;
|
|
374
|
+
}
|
|
375
|
+
case GL_TEXTURE_BINDING_2D_ARRAY: {
|
|
376
|
+
const uint32_t texture = context->bound_array_texture(0);
|
|
377
|
+
return texture != 0
|
|
378
|
+
? webgl_make_object(self, "__xt_gl_texture", texture, "texture")
|
|
379
|
+
: XT_NULL;
|
|
380
|
+
}
|
|
381
|
+
case GL_TEXTURE_BINDING_3D: {
|
|
382
|
+
const uint32_t texture = context->bound_3d_texture(0);
|
|
383
|
+
return texture != 0
|
|
384
|
+
? webgl_make_object(self, "__xt_gl_texture", texture, "texture")
|
|
385
|
+
: XT_NULL;
|
|
386
|
+
}
|
|
321
387
|
case GL_FRAMEBUFFER_BINDING: {
|
|
322
388
|
const uint32_t framebuffer = context->bound_framebuffer_id();
|
|
323
389
|
return framebuffer != 0
|
|
324
390
|
? webgl_make_object(self, "__xt_gl_framebuffer", framebuffer, "framebuffer")
|
|
325
391
|
: XT_NULL;
|
|
326
392
|
}
|
|
393
|
+
case GL_READ_FRAMEBUFFER_BINDING: {
|
|
394
|
+
const uint32_t framebuffer = context->bound_read_framebuffer_id();
|
|
395
|
+
return framebuffer != 0
|
|
396
|
+
? webgl_make_object(self, "__xt_gl_framebuffer", framebuffer, "framebuffer")
|
|
397
|
+
: XT_NULL;
|
|
398
|
+
}
|
|
327
399
|
case GL_RENDERBUFFER_BINDING: {
|
|
328
400
|
const uint32_t renderbuffer = context->bound_renderbuffer_id();
|
|
329
401
|
return renderbuffer != 0
|
|
@@ -351,22 +423,50 @@ METHOD(webgl_get_supported_extensions) {
|
|
|
351
423
|
xt_value list = xt_array_new(0, nullptr);
|
|
352
424
|
xt_array_push(list, xt_string_from_cstr("OES_element_index_uint"));
|
|
353
425
|
xt_array_push(list, xt_string_from_cstr("OES_standard_derivatives"));
|
|
426
|
+
xt_array_push(list, xt_string_from_cstr("OES_texture_float"));
|
|
427
|
+
xt_array_push(list, xt_string_from_cstr("OES_texture_half_float"));
|
|
428
|
+
xt_array_push(list, xt_string_from_cstr("WEBGL_depth_texture"));
|
|
429
|
+
xt_array_push(list, xt_string_from_cstr("EXT_color_buffer_float"));
|
|
430
|
+
xt_array_push(list, xt_string_from_cstr("EXT_color_buffer_half_float"));
|
|
354
431
|
xt_array_push(list, xt_string_from_cstr("WEBGL_lose_context"));
|
|
432
|
+
xtgui::WebGLContext *context = webgl_from_context(self);
|
|
433
|
+
if (context != nullptr && context->supports_texture_format(0x83F1)) {
|
|
434
|
+
xt_array_push(list, xt_string_from_cstr("WEBGL_compressed_texture_s3tc"));
|
|
435
|
+
}
|
|
436
|
+
if (context != nullptr && context->supports_texture_format(0x8C4D)) {
|
|
437
|
+
xt_array_push(list, xt_string_from_cstr("WEBGL_compressed_texture_s3tc_srgb"));
|
|
438
|
+
}
|
|
439
|
+
if (context != nullptr && context->supports_texture_format(0x93B0)) {
|
|
440
|
+
xt_array_push(list, xt_string_from_cstr("WEBGL_compressed_texture_astc"));
|
|
441
|
+
}
|
|
355
442
|
return list;
|
|
356
443
|
}
|
|
357
444
|
|
|
358
445
|
METHOD(webgl_get_extension) {
|
|
359
446
|
(void)env;
|
|
360
447
|
const std::string name = webgl_string(argc, argv, 0);
|
|
361
|
-
if (name
|
|
448
|
+
if (name.rfind("WEBGL_compressed_texture_", 0) == 0) {
|
|
449
|
+
xt_value extension = webgl_compressed_extension(name, webgl_from_context(self));
|
|
450
|
+
if (!XT_IS_UNDEFINED(extension)) return extension;
|
|
451
|
+
}
|
|
452
|
+
if (name == "OES_element_index_uint" || name == "OES_standard_derivatives" ||
|
|
453
|
+
name == "OES_texture_float" || name == "OES_texture_half_float" ||
|
|
454
|
+
name == "WEBGL_depth_texture" || name == "EXT_color_buffer_float" ||
|
|
455
|
+
name == "EXT_color_buffer_half_float") {
|
|
362
456
|
return xt_object_new();
|
|
363
457
|
}
|
|
364
458
|
if (name == "WEBGL_lose_context") {
|
|
365
459
|
xt_value object = xt_object_new();
|
|
460
|
+
/* The closures receive this object as `this`, so carry the context id and
|
|
461
|
+
* the canvas handle over from the context that produced the extension. */
|
|
462
|
+
xt_object_set(object, xt_string_from_cstr("__xt_gl_context"),
|
|
463
|
+
xt_object_get_cstr(self, "__xt_gl_context"));
|
|
464
|
+
xt_object_set(object, xt_string_from_cstr("__xt_gl_node"),
|
|
465
|
+
xt_object_get_cstr(self, "__xt_gl_node"));
|
|
366
466
|
xt_object_set(object, xt_string_from_cstr("loseContext"),
|
|
367
|
-
xt_closure_new((void *)
|
|
467
|
+
xt_closure_new((void *)webgl_lose_context, 0, nullptr));
|
|
368
468
|
xt_object_set(object, xt_string_from_cstr("restoreContext"),
|
|
369
|
-
xt_closure_new((void *)
|
|
469
|
+
xt_closure_new((void *)webgl_restore_context, 0, nullptr));
|
|
370
470
|
return object;
|
|
371
471
|
}
|
|
372
472
|
return XT_NULL;
|
|
@@ -379,7 +479,7 @@ METHOD(webgl_get_context_attributes) {
|
|
|
379
479
|
xt_value attributes = xt_object_new();
|
|
380
480
|
xt_object_set(attributes, xt_string_from_cstr("alpha"), XT_TRUE);
|
|
381
481
|
xt_object_set(attributes, xt_string_from_cstr("depth"), XT_TRUE);
|
|
382
|
-
xt_object_set(attributes, xt_string_from_cstr("stencil"),
|
|
482
|
+
xt_object_set(attributes, xt_string_from_cstr("stencil"), XT_TRUE);
|
|
383
483
|
xt_object_set(attributes, xt_string_from_cstr("antialias"), XT_FALSE);
|
|
384
484
|
xt_object_set(attributes, xt_string_from_cstr("premultipliedAlpha"), XT_TRUE);
|
|
385
485
|
xt_object_set(attributes, xt_string_from_cstr("preserveDrawingBuffer"), XT_TRUE);
|
|
@@ -393,51 +493,97 @@ METHOD(webgl_is_context_lost) {
|
|
|
393
493
|
(void)env;
|
|
394
494
|
(void)argc;
|
|
395
495
|
(void)argv;
|
|
396
|
-
xtgui::WebGLContext *context =
|
|
496
|
+
xtgui::WebGLContext *context = webgl_from_context(self);
|
|
397
497
|
return xt_bool(context == nullptr || context->lost());
|
|
398
498
|
}
|
|
399
499
|
|
|
400
|
-
/*
|
|
401
|
-
*
|
|
402
|
-
|
|
500
|
+
/* `WEBGL_lose_context.loseContext()` / `restoreContext()`: the simulator drops
|
|
501
|
+
* every object and reports `CONTEXT_LOST_WEBGL` until the restore, so a page
|
|
502
|
+
* exercises the same loss/restore path it would take on a real GPU reset. */
|
|
503
|
+
METHOD(webgl_lose_context) {
|
|
403
504
|
(void)env;
|
|
404
505
|
(void)argc;
|
|
405
506
|
(void)argv;
|
|
507
|
+
xtgui::WebGLContext *context = webgl_from_context(self);
|
|
508
|
+
if (context == nullptr || context->lost()) return XT_UNDEFINED;
|
|
509
|
+
context->lose_context();
|
|
510
|
+
dispatch_context_event(self, "webglcontextlost");
|
|
406
511
|
return XT_UNDEFINED;
|
|
407
512
|
}
|
|
408
513
|
|
|
409
|
-
METHOD(
|
|
514
|
+
METHOD(webgl_restore_context) {
|
|
410
515
|
(void)env;
|
|
411
516
|
(void)argc;
|
|
412
517
|
(void)argv;
|
|
518
|
+
xtgui::WebGLContext *context = webgl_from_context(self);
|
|
519
|
+
if (context == nullptr || !context->lost()) return XT_UNDEFINED;
|
|
520
|
+
context->restore_context();
|
|
521
|
+
if (!context->lost()) dispatch_context_event(self, "webglcontextrestored");
|
|
522
|
+
return XT_UNDEFINED;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/* Stencil test/update state. SDL_GPU has one stencil reference per draw and no
|
|
526
|
+
* per-pipeline compare/write masks; the entry points store WebGL's state, the
|
|
527
|
+
* pipeline carries the compare function and ops, and `SDL_SetGPUStencilReference`
|
|
528
|
+
* supplies the reference. A write mask of 0 is emulated as KEEP. */
|
|
529
|
+
METHOD(webgl_stencil_func) {
|
|
530
|
+
(void)env;
|
|
531
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
532
|
+
if (context != nullptr) {
|
|
533
|
+
context->stencil_func(webgl_int(argc, argv, 0, GL_ALWAYS), webgl_int(argc, argv, 1, 0),
|
|
534
|
+
(uint32_t)webgl_number(argc, argv, 2, 0xFFFFFFFF));
|
|
535
|
+
}
|
|
536
|
+
return XT_UNDEFINED;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
METHOD(webgl_stencil_func_separate) {
|
|
540
|
+
(void)env;
|
|
541
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
542
|
+
if (context != nullptr) {
|
|
543
|
+
const int face = webgl_int(argc, argv, 0, GL_FRONT_AND_BACK);
|
|
544
|
+
context->stencil_func_separate(face, webgl_int(argc, argv, 1, GL_ALWAYS),
|
|
545
|
+
webgl_int(argc, argv, 2, 0),
|
|
546
|
+
(uint32_t)webgl_number(argc, argv, 3, 0xFFFFFFFF));
|
|
547
|
+
}
|
|
413
548
|
return XT_UNDEFINED;
|
|
414
549
|
}
|
|
415
550
|
|
|
416
551
|
METHOD(webgl_stencil_op) {
|
|
417
552
|
(void)env;
|
|
418
|
-
(
|
|
419
|
-
(
|
|
553
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
554
|
+
if (context != nullptr) {
|
|
555
|
+
context->stencil_op(webgl_int(argc, argv, 0, GL_KEEP), webgl_int(argc, argv, 1, GL_KEEP),
|
|
556
|
+
webgl_int(argc, argv, 2, GL_KEEP));
|
|
557
|
+
}
|
|
420
558
|
return XT_UNDEFINED;
|
|
421
559
|
}
|
|
422
560
|
|
|
423
561
|
METHOD(webgl_stencil_op_separate) {
|
|
424
562
|
(void)env;
|
|
425
|
-
(
|
|
426
|
-
(
|
|
563
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
564
|
+
if (context != nullptr) {
|
|
565
|
+
const int face = webgl_int(argc, argv, 0, GL_FRONT_AND_BACK);
|
|
566
|
+
context->stencil_op_separate(face, webgl_int(argc, argv, 1, GL_KEEP),
|
|
567
|
+
webgl_int(argc, argv, 2, GL_KEEP),
|
|
568
|
+
webgl_int(argc, argv, 3, GL_KEEP));
|
|
569
|
+
}
|
|
427
570
|
return XT_UNDEFINED;
|
|
428
571
|
}
|
|
429
572
|
|
|
430
573
|
METHOD(webgl_stencil_mask) {
|
|
431
574
|
(void)env;
|
|
432
|
-
(
|
|
433
|
-
(
|
|
575
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
576
|
+
if (context != nullptr) context->stencil_mask((uint32_t)webgl_number(argc, argv, 0, 0xFFFFFFFF));
|
|
434
577
|
return XT_UNDEFINED;
|
|
435
578
|
}
|
|
436
579
|
|
|
437
580
|
METHOD(webgl_stencil_mask_separate) {
|
|
438
581
|
(void)env;
|
|
439
|
-
(
|
|
440
|
-
(
|
|
582
|
+
xtgui::WebGLContext *context = context_of(self);
|
|
583
|
+
if (context != nullptr) {
|
|
584
|
+
context->stencil_mask_separate(webgl_int(argc, argv, 0, GL_FRONT_AND_BACK),
|
|
585
|
+
(uint32_t)webgl_number(argc, argv, 1, 0xFFFFFFFF));
|
|
586
|
+
}
|
|
441
587
|
return XT_UNDEFINED;
|
|
442
588
|
}
|
|
443
589
|
|