xbintsc 0.3.25 → 0.3.46
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 +39 -3
- package/dist/src/cli/main.js +124 -30
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.js +8 -1
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/module.js +10 -0
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +24 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +6 -0
- package/dist/src/codegen/generator/tables.js +38 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/commonjs.d.ts +52 -0
- package/dist/src/driver/bundler/commonjs.js +493 -0
- package/dist/src/driver/bundler/commonjs.js.map +1 -0
- package/dist/src/driver/bundler/graph.js +14 -0
- package/dist/src/driver/bundler/graph.js.map +1 -1
- package/dist/src/driver/bundler/merge.js +14 -0
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/bundler/types.d.ts +8 -0
- package/dist/src/driver/compiler.d.ts +8 -1
- package/dist/src/driver/compiler.js +73 -5
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/config.d.ts +53 -0
- package/dist/src/driver/config.js +141 -0
- package/dist/src/driver/config.js.map +1 -0
- package/dist/src/driver/icon.d.ts +62 -0
- package/dist/src/driver/icon.js +151 -0
- package/dist/src/driver/icon.js.map +1 -0
- package/dist/src/driver/index.d.ts +4 -0
- package/dist/src/driver/index.js +4 -0
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/mac-bundle.d.ts +41 -0
- package/dist/src/driver/mac-bundle.js +123 -0
- package/dist/src/driver/mac-bundle.js.map +1 -0
- package/dist/src/driver/win-icon.d.ts +27 -0
- package/dist/src/driver/win-icon.js +80 -0
- package/dist/src/driver/win-icon.js.map +1 -0
- package/dist/src/parser/statements.js +17 -4
- package/dist/src/parser/statements.js.map +1 -1
- package/dist/tests/cli/main.test.js +46 -1
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/driver/config.test.d.ts +1 -0
- package/dist/tests/driver/config.test.js +124 -0
- package/dist/tests/driver/config.test.js.map +1 -0
- package/dist/tests/driver/icon.test.d.ts +1 -0
- package/dist/tests/driver/icon.test.js +421 -0
- package/dist/tests/driver/icon.test.js.map +1 -0
- package/dist/tests/driver/modules.test.js +109 -0
- package/dist/tests/driver/modules.test.js.map +1 -1
- package/dist/tests/e2e/fetch.test.d.ts +12 -0
- package/dist/tests/e2e/fetch.test.js +272 -0
- package/dist/tests/e2e/fetch.test.js.map +1 -0
- package/dist/tests/e2e/gc.test.d.ts +1 -0
- package/dist/tests/e2e/gc.test.js +168 -0
- package/dist/tests/e2e/gc.test.js.map +1 -0
- package/dist/tests/e2e/gui-dom.test.d.ts +5 -0
- package/dist/tests/e2e/gui-dom.test.js +102 -0
- package/dist/tests/e2e/gui-dom.test.js.map +1 -0
- package/dist/tests/e2e/gui-events.test.d.ts +5 -0
- package/dist/tests/e2e/gui-events.test.js +60 -0
- package/dist/tests/e2e/gui-events.test.js.map +1 -0
- package/dist/tests/e2e/gui-helpers.d.ts +31 -0
- package/dist/tests/e2e/gui-helpers.js +74 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -0
- package/dist/tests/e2e/gui-layout.test.d.ts +4 -0
- package/dist/tests/e2e/gui-layout.test.js +88 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -0
- package/dist/tests/e2e/gui-lifecycle.test.d.ts +5 -0
- package/dist/tests/e2e/gui-lifecycle.test.js +58 -0
- package/dist/tests/e2e/gui-lifecycle.test.js.map +1 -0
- package/dist/tests/e2e/gui-paint.test.d.ts +5 -0
- package/dist/tests/e2e/gui-paint.test.js +111 -0
- package/dist/tests/e2e/gui-paint.test.js.map +1 -0
- package/dist/tests/e2e/gui-script.test.d.ts +5 -0
- package/dist/tests/e2e/gui-script.test.js +78 -0
- package/dist/tests/e2e/gui-script.test.js.map +1 -0
- package/dist/tests/e2e/gui-style.test.d.ts +5 -0
- package/dist/tests/e2e/gui-style.test.js +175 -0
- package/dist/tests/e2e/gui-style.test.js.map +1 -0
- package/dist/tests/e2e/harness.d.ts +2 -0
- package/dist/tests/e2e/harness.js +1 -0
- package/dist/tests/e2e/harness.js.map +1 -1
- package/dist/tests/e2e/icon.test.d.ts +7 -0
- package/dist/tests/e2e/icon.test.js +80 -0
- package/dist/tests/e2e/icon.test.js.map +1 -0
- package/dist/tests/e2e/npm-modules.test.d.ts +4 -1
- package/dist/tests/e2e/npm-modules.test.js +47 -1
- package/dist/tests/e2e/npm-modules.test.js.map +1 -1
- package/dist/tests/e2e/runtime-coverage-typed-array.test.d.ts +9 -0
- package/dist/tests/e2e/runtime-coverage-typed-array.test.js +140 -0
- package/dist/tests/e2e/runtime-coverage-typed-array.test.js.map +1 -0
- package/dist/tests/parser/statements.test.js +11 -0
- package/dist/tests/parser/statements.test.js.map +1 -1
- package/package.json +3 -2
- package/runtime/ext_gui/css.cpp +4 -517
- package/runtime/ext_gui/css_internal.h +27 -0
- package/runtime/ext_gui/css_match.cpp +195 -0
- package/runtime/ext_gui/css_selector.cpp +207 -0
- package/runtime/ext_gui/css_sheet.cpp +129 -0
- package/runtime/ext_gui/dom.cpp +7 -403
- package/runtime/ext_gui/dom_api.cpp +63 -1146
- package/runtime/ext_gui/dom_api_document.cpp +96 -0
- package/runtime/ext_gui/dom_api_events.cpp +123 -0
- package/runtime/ext_gui/dom_api_internal.h +135 -0
- package/runtime/ext_gui/dom_api_node.cpp +329 -0
- package/runtime/ext_gui/dom_api_node_read.cpp +294 -0
- package/runtime/ext_gui/dom_api_proto.cpp +135 -0
- package/runtime/ext_gui/dom_api_style.cpp +192 -0
- package/runtime/ext_gui/dom_internal.h +39 -0
- package/runtime/ext_gui/dom_parse.cpp +348 -0
- package/runtime/ext_gui/dom_serialize.cpp +54 -0
- package/runtime/ext_gui/gui.cpp +56 -286
- package/runtime/ext_gui/gui_events.cpp +294 -0
- package/runtime/ext_gui/gui_internal.h +29 -0
- package/runtime/ext_gui/layout.cpp +6 -597
- package/runtime/ext_gui/layout_flex.cpp +200 -0
- package/runtime/ext_gui/layout_flow.cpp +191 -0
- package/runtime/ext_gui/layout_flow_internal.h +149 -0
- package/runtime/ext_gui/layout_inline.cpp +181 -0
- package/runtime/ext_gui/layout_internal.h +20 -0
- package/runtime/ext_gui/renderer.cpp +15 -679
- package/runtime/ext_gui/renderer_image.cpp +233 -0
- package/runtime/ext_gui/renderer_internal.h +112 -0
- package/runtime/ext_gui/renderer_shaders.h +108 -0
- package/runtime/ext_gui/renderer_text.cpp +342 -0
- package/runtime/ext_gui/style.cpp +12 -660
- package/runtime/ext_gui/style_internal.h +33 -0
- package/runtime/ext_gui/style_print.cpp +113 -0
- package/runtime/ext_gui/style_ua.cpp +98 -0
- package/runtime/ext_gui/style_values.cpp +468 -0
- package/runtime/ext_gui/window.cpp +1 -0
- package/runtime/ext_node/buffer/parts/prototype.inc +1 -0
- package/runtime/ext_node/dgram/dgram.c +1 -0
- package/runtime/ext_node/events/events.c +1 -0
- package/runtime/ext_node/fs/fs_ops.c +10 -25
- package/runtime/ext_node/fs/glob.c +13 -30
- package/runtime/ext_node/fs/promises.c +1 -0
- package/runtime/ext_node/http/parts/prototypes.inc +5 -0
- package/runtime/ext_node/net/parts/prototypes.inc +2 -0
- package/runtime/ext_node/process/process.c +9 -7
- package/runtime/ext_node/stream/stream.c +1 -0
- package/runtime/ext_node/util/util.c +6 -6
- package/runtime/rt.h +16 -0
- package/runtime/rt_internal.h +67 -2
- package/runtime/xt_alloc.c +442 -5
- package/runtime/xt_builtins.c +1 -0
- package/runtime/xt_containers/access.inc +32 -1
- package/runtime/xt_fetch/buffer.inc +64 -0
- package/runtime/xt_fetch/headers.inc +312 -0
- package/runtime/xt_fetch/request.inc +386 -0
- package/runtime/xt_fetch/response.inc +107 -0
- package/runtime/xt_fetch/socket.inc +72 -0
- package/runtime/xt_fetch/url.inc +108 -0
- package/runtime/xt_fetch.c +39 -0
- package/runtime/xt_generator.c +95 -1
- package/runtime/xt_loop.c +35 -1
- package/runtime/xt_promise.c +46 -0
- package/runtime/xt_stdlib2/error.inc +1 -0
- package/runtime/xt_stdlib2/regexp-match.inc +8 -7
- package/runtime/xt_stdlib2/set.inc +1 -1
- package/runtime/xt_symbol.c +2 -0
- package/runtime/xt_typed_array/construction.inc +142 -0
- package/runtime/xt_typed_array/elements.inc +92 -0
- package/runtime/xt_typed_array/methods.inc +329 -0
- package/runtime/xt_typed_array.c +72 -0
- package/runtime/xt_values/number-format.inc +26 -0
- package/scripts/check-file-length.ts +85 -0
- package/src/cli/main.ts +137 -29
- package/src/codegen/generator/calls/access.ts +9 -1
- package/src/codegen/generator/module.ts +10 -0
- package/src/codegen/generator/state.ts +24 -0
- package/src/codegen/generator/tables.ts +40 -0
- package/src/driver/bundler/commonjs.ts +553 -0
- package/src/driver/bundler/graph.ts +14 -0
- package/src/driver/bundler/merge.ts +15 -0
- package/src/driver/bundler/types.ts +8 -0
- package/src/driver/compiler.ts +83 -5
- package/src/driver/config.ts +173 -0
- package/src/driver/icon.ts +184 -0
- package/src/driver/index.ts +30 -0
- package/src/driver/mac-bundle.ts +156 -0
- package/src/driver/win-icon.ts +96 -0
- package/src/parser/statements.ts +17 -4
- package/dist/tests/e2e/gui.test.d.ts +0 -12
- package/dist/tests/e2e/gui.test.js +0 -702
- package/dist/tests/e2e/gui.test.js.map +0 -1
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc GUI engine — SDL_GPU 2D renderer: image textures and geometry.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
#include "renderer_internal.h"
|
|
6
|
+
|
|
7
|
+
#include <cstddef>
|
|
8
|
+
#include <cstdint>
|
|
9
|
+
#include <cstdio>
|
|
10
|
+
#include <cstring>
|
|
11
|
+
|
|
12
|
+
#include "image.h"
|
|
13
|
+
|
|
14
|
+
#include "renderer_shaders.h"
|
|
15
|
+
|
|
16
|
+
namespace xtgui {
|
|
17
|
+
namespace renderer_detail {
|
|
18
|
+
|
|
19
|
+
SDL_GPUGraphicsPipeline *createImagePipeline(SDL_GPUDevice *device, SDL_Window *reference) {
|
|
20
|
+
SDL_GPUShaderCreateInfo vs_info;
|
|
21
|
+
memset(&vs_info, 0, sizeof(vs_info));
|
|
22
|
+
vs_info.code_size = strlen(kTextMSL);
|
|
23
|
+
vs_info.code = (const Uint8 *)kTextMSL;
|
|
24
|
+
vs_info.entrypoint = "vs_text";
|
|
25
|
+
vs_info.format = SDL_GPU_SHADERFORMAT_MSL;
|
|
26
|
+
vs_info.stage = SDL_GPU_SHADERSTAGE_VERTEX;
|
|
27
|
+
vs_info.num_uniform_buffers = 1;
|
|
28
|
+
SDL_GPUShader *vs = SDL_CreateGPUShader(device, &vs_info);
|
|
29
|
+
|
|
30
|
+
SDL_GPUShaderCreateInfo fs_info;
|
|
31
|
+
memset(&fs_info, 0, sizeof(fs_info));
|
|
32
|
+
fs_info.code_size = strlen(kTextMSL);
|
|
33
|
+
fs_info.code = (const Uint8 *)kTextMSL;
|
|
34
|
+
fs_info.entrypoint = "fs_image";
|
|
35
|
+
fs_info.format = SDL_GPU_SHADERFORMAT_MSL;
|
|
36
|
+
fs_info.stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
|
|
37
|
+
fs_info.num_samplers = 1;
|
|
38
|
+
SDL_GPUShader *fs = SDL_CreateGPUShader(device, &fs_info);
|
|
39
|
+
|
|
40
|
+
if (vs == nullptr || fs == nullptr) {
|
|
41
|
+
fprintf(stderr, "xt_gui: image shader creation failed: %s\n", SDL_GetError());
|
|
42
|
+
if (vs != nullptr) SDL_ReleaseGPUShader(device, vs);
|
|
43
|
+
if (fs != nullptr) SDL_ReleaseGPUShader(device, fs);
|
|
44
|
+
return nullptr;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
SDL_GPUVertexBufferDescription vb_desc;
|
|
48
|
+
memset(&vb_desc, 0, sizeof(vb_desc));
|
|
49
|
+
vb_desc.slot = 0;
|
|
50
|
+
vb_desc.pitch = sizeof(TextVertex);
|
|
51
|
+
vb_desc.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX;
|
|
52
|
+
|
|
53
|
+
SDL_GPUVertexAttribute attrs[3];
|
|
54
|
+
memset(attrs, 0, sizeof(attrs));
|
|
55
|
+
attrs[0] = {0, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, (Uint32)offsetof(TextVertex, x)};
|
|
56
|
+
attrs[1] = {1, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, (Uint32)offsetof(TextVertex, u)};
|
|
57
|
+
attrs[2] = {2, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4, (Uint32)offsetof(TextVertex, r)};
|
|
58
|
+
|
|
59
|
+
SDL_GPUColorTargetDescription color_target;
|
|
60
|
+
memset(&color_target, 0, sizeof(color_target));
|
|
61
|
+
color_target.format = SDL_GetGPUSwapchainTextureFormat(device, reference);
|
|
62
|
+
color_target.blend_state.enable_blend = true;
|
|
63
|
+
color_target.blend_state.src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA;
|
|
64
|
+
color_target.blend_state.dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
|
|
65
|
+
color_target.blend_state.color_blend_op = SDL_GPU_BLENDOP_ADD;
|
|
66
|
+
color_target.blend_state.src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE;
|
|
67
|
+
color_target.blend_state.dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
|
|
68
|
+
color_target.blend_state.alpha_blend_op = SDL_GPU_BLENDOP_ADD;
|
|
69
|
+
|
|
70
|
+
SDL_GPUGraphicsPipelineCreateInfo info;
|
|
71
|
+
memset(&info, 0, sizeof(info));
|
|
72
|
+
info.vertex_shader = vs;
|
|
73
|
+
info.fragment_shader = fs;
|
|
74
|
+
info.vertex_input_state.vertex_buffer_descriptions = &vb_desc;
|
|
75
|
+
info.vertex_input_state.num_vertex_buffers = 1;
|
|
76
|
+
info.vertex_input_state.vertex_attributes = attrs;
|
|
77
|
+
info.vertex_input_state.num_vertex_attributes = 3;
|
|
78
|
+
info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
|
|
79
|
+
info.rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL;
|
|
80
|
+
info.rasterizer_state.cull_mode = SDL_GPU_CULLMODE_NONE;
|
|
81
|
+
info.rasterizer_state.front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE;
|
|
82
|
+
info.multisample_state.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
|
83
|
+
info.target_info.color_target_descriptions = &color_target;
|
|
84
|
+
info.target_info.num_color_targets = 1;
|
|
85
|
+
|
|
86
|
+
SDL_GPUGraphicsPipeline *pipeline = SDL_CreateGPUGraphicsPipeline(device, &info);
|
|
87
|
+
SDL_ReleaseGPUShader(device, vs);
|
|
88
|
+
SDL_ReleaseGPUShader(device, fs);
|
|
89
|
+
if (pipeline == nullptr) {
|
|
90
|
+
fprintf(stderr, "xt_gui: image pipeline creation failed: %s\n", SDL_GetError());
|
|
91
|
+
}
|
|
92
|
+
return pipeline;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Decode `src` (cached) and upload it as an RGBA texture (cached by path). */
|
|
96
|
+
SDL_GPUTexture *ensureImageTexture(SDL_GPUDevice *device, const std::string &src) {
|
|
97
|
+
auto found = g_image_textures.find(src);
|
|
98
|
+
if (found != g_image_textures.end()) return found->second;
|
|
99
|
+
|
|
100
|
+
const xtgui::Image *image = xtgui::xt_image_load(src);
|
|
101
|
+
if (image == nullptr || image->width <= 0 || image->height <= 0) {
|
|
102
|
+
fprintf(stderr, "xt_gui: could not decode image '%s'\n", src.c_str());
|
|
103
|
+
g_image_textures.emplace(src, nullptr);
|
|
104
|
+
return nullptr;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
SDL_GPUTextureCreateInfo info;
|
|
108
|
+
memset(&info, 0, sizeof(info));
|
|
109
|
+
info.type = SDL_GPU_TEXTURETYPE_2D;
|
|
110
|
+
info.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
|
111
|
+
info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
|
112
|
+
info.width = (Uint32)image->width;
|
|
113
|
+
info.height = (Uint32)image->height;
|
|
114
|
+
info.layer_count_or_depth = 1;
|
|
115
|
+
info.num_levels = 1;
|
|
116
|
+
info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
|
117
|
+
SDL_GPUTexture *texture = SDL_CreateGPUTexture(device, &info);
|
|
118
|
+
if (texture == nullptr) {
|
|
119
|
+
fprintf(stderr, "xt_gui: image texture creation failed: %s\n", SDL_GetError());
|
|
120
|
+
g_image_textures.emplace(src, nullptr);
|
|
121
|
+
return nullptr;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
uint32_t bytes = (uint32_t)(image->pixels.size());
|
|
125
|
+
SDL_GPUTransferBufferCreateInfo transfer_info;
|
|
126
|
+
memset(&transfer_info, 0, sizeof(transfer_info));
|
|
127
|
+
transfer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
|
128
|
+
transfer_info.size = bytes;
|
|
129
|
+
SDL_GPUTransferBuffer *transfer = SDL_CreateGPUTransferBuffer(device, &transfer_info);
|
|
130
|
+
if (transfer == nullptr) {
|
|
131
|
+
SDL_ReleaseGPUTexture(device, texture);
|
|
132
|
+
g_image_textures.emplace(src, nullptr);
|
|
133
|
+
return nullptr;
|
|
134
|
+
}
|
|
135
|
+
void *mapped = SDL_MapGPUTransferBuffer(device, transfer, false);
|
|
136
|
+
std::memcpy(mapped, image->pixels.data(), bytes);
|
|
137
|
+
SDL_UnmapGPUTransferBuffer(device, transfer);
|
|
138
|
+
|
|
139
|
+
SDL_GPUCommandBuffer *cmd = SDL_AcquireGPUCommandBuffer(device);
|
|
140
|
+
if (cmd == nullptr) {
|
|
141
|
+
SDL_ReleaseGPUTransferBuffer(device, transfer);
|
|
142
|
+
SDL_ReleaseGPUTexture(device, texture);
|
|
143
|
+
g_image_textures.emplace(src, nullptr);
|
|
144
|
+
return nullptr;
|
|
145
|
+
}
|
|
146
|
+
SDL_GPUTextureTransferInfo source;
|
|
147
|
+
memset(&source, 0, sizeof(source));
|
|
148
|
+
source.transfer_buffer = transfer;
|
|
149
|
+
source.offset = 0;
|
|
150
|
+
source.pixels_per_row = (Uint32)image->width;
|
|
151
|
+
source.rows_per_layer = (Uint32)image->height;
|
|
152
|
+
SDL_GPUTextureRegion destination;
|
|
153
|
+
memset(&destination, 0, sizeof(destination));
|
|
154
|
+
destination.texture = texture;
|
|
155
|
+
destination.mip_level = 0;
|
|
156
|
+
destination.layer = 0;
|
|
157
|
+
destination.x = 0;
|
|
158
|
+
destination.y = 0;
|
|
159
|
+
destination.z = 0;
|
|
160
|
+
destination.w = (Uint32)image->width;
|
|
161
|
+
destination.h = (Uint32)image->height;
|
|
162
|
+
destination.d = 1;
|
|
163
|
+
SDL_GPUCopyPass *copy = SDL_BeginGPUCopyPass(cmd);
|
|
164
|
+
SDL_UploadToGPUTexture(copy, &source, &destination, false);
|
|
165
|
+
SDL_EndGPUCopyPass(copy);
|
|
166
|
+
SDL_SubmitGPUCommandBuffer(cmd);
|
|
167
|
+
SDL_ReleaseGPUTransferBuffer(device, transfer);
|
|
168
|
+
|
|
169
|
+
g_image_textures.emplace(src, texture);
|
|
170
|
+
return texture;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
} // namespace renderer_detail
|
|
174
|
+
} // namespace xtgui
|
|
175
|
+
|
|
176
|
+
void xt_gui_image_upload(SDL_GPUDevice *device, XtGuiGeometry *geometry,
|
|
177
|
+
const xtgui::DisplayList &list) {
|
|
178
|
+
using namespace xtgui::renderer_detail;
|
|
179
|
+
g_image_batches.clear();
|
|
180
|
+
if (g_image_pipeline == nullptr) {
|
|
181
|
+
geometry->vertex_count = 0;
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
std::vector<TextVertex> verts;
|
|
185
|
+
verts.reserve(list.images.size() * 6);
|
|
186
|
+
xtgui::Color white{1.0f, 1.0f, 1.0f, 1.0f};
|
|
187
|
+
GlyphEntry full;
|
|
188
|
+
full.u0 = 0.0f;
|
|
189
|
+
full.v0 = 0.0f;
|
|
190
|
+
full.u1 = 1.0f;
|
|
191
|
+
full.v1 = 1.0f;
|
|
192
|
+
for (const xtgui::PaintImage &image : list.images) {
|
|
193
|
+
if (image.width <= 0.0f || image.height <= 0.0f) continue;
|
|
194
|
+
SDL_GPUTexture *texture = ensureImageTexture(device, image.src);
|
|
195
|
+
if (texture == nullptr) continue;
|
|
196
|
+
uint32_t first = (uint32_t)verts.size();
|
|
197
|
+
pushGlyph(verts, image.x, image.y, image.width, image.height, full, white);
|
|
198
|
+
g_image_batches.push_back(ImageBatch{texture, first, 6});
|
|
199
|
+
}
|
|
200
|
+
uploadVertices(device, geometry, verts.data(), (uint32_t)verts.size(), sizeof(TextVertex));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
void xt_gui_image_draw(SDL_GPUCommandBuffer *cmd, SDL_GPURenderPass *pass, XtGuiGeometry *geometry,
|
|
204
|
+
float viewport_width, float viewport_height) {
|
|
205
|
+
using namespace xtgui::renderer_detail;
|
|
206
|
+
if (g_image_pipeline == nullptr || g_sampler == nullptr) return;
|
|
207
|
+
if (geometry->buffer == nullptr || geometry->vertex_count == 0 || g_image_batches.empty()) return;
|
|
208
|
+
if (viewport_width <= 0.0f || viewport_height <= 0.0f) return;
|
|
209
|
+
SDL_BindGPUGraphicsPipeline(pass, g_image_pipeline);
|
|
210
|
+
SDL_GPUBufferBinding binding;
|
|
211
|
+
binding.buffer = geometry->buffer;
|
|
212
|
+
binding.offset = 0;
|
|
213
|
+
SDL_BindGPUVertexBuffers(pass, 0, &binding, 1);
|
|
214
|
+
float viewport[2] = {viewport_width, viewport_height};
|
|
215
|
+
SDL_PushGPUVertexUniformData(cmd, 0, viewport, sizeof(viewport));
|
|
216
|
+
for (const ImageBatch &batch : g_image_batches) {
|
|
217
|
+
if (batch.texture == nullptr) continue;
|
|
218
|
+
SDL_GPUTextureSamplerBinding texture_binding;
|
|
219
|
+
texture_binding.texture = batch.texture;
|
|
220
|
+
texture_binding.sampler = g_sampler;
|
|
221
|
+
SDL_BindGPUFragmentSamplers(pass, 0, &texture_binding, 1);
|
|
222
|
+
SDL_DrawGPUPrimitives(pass, batch.count, 1, batch.first, 0);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
void xt_gui_image_textures_destroy(SDL_GPUDevice *device) {
|
|
227
|
+
using namespace xtgui::renderer_detail;
|
|
228
|
+
for (auto &entry : g_image_textures) {
|
|
229
|
+
if (entry.second != nullptr) SDL_ReleaseGPUTexture(device, entry.second);
|
|
230
|
+
}
|
|
231
|
+
g_image_textures.clear();
|
|
232
|
+
g_image_batches.clear();
|
|
233
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc GUI engine — shared declarations for the renderer translation units
|
|
3
|
+
* (`renderer.cpp`, `renderer_text.cpp`, `renderer_image.cpp`).
|
|
4
|
+
*
|
|
5
|
+
* The GPU state lives in `xtgui::renderer_detail` with external linkage so the
|
|
6
|
+
* three translation units can share it (it used to be an anonymous namespace).
|
|
7
|
+
*/
|
|
8
|
+
#ifndef XT_GUI_RENDERER_INTERNAL_H
|
|
9
|
+
#define XT_GUI_RENDERER_INTERNAL_H
|
|
10
|
+
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
#include <functional>
|
|
13
|
+
#include <string>
|
|
14
|
+
#include <unordered_map>
|
|
15
|
+
#include <vector>
|
|
16
|
+
|
|
17
|
+
#include "paint.h"
|
|
18
|
+
#include "renderer.h"
|
|
19
|
+
|
|
20
|
+
namespace xtgui {
|
|
21
|
+
namespace renderer_detail {
|
|
22
|
+
|
|
23
|
+
struct Vertex {
|
|
24
|
+
float x, y;
|
|
25
|
+
float lx, ly;
|
|
26
|
+
float hx, hy;
|
|
27
|
+
float radius;
|
|
28
|
+
float r, g, b, a;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
struct TextVertex {
|
|
32
|
+
float x, y;
|
|
33
|
+
float u, v;
|
|
34
|
+
float r, g, b, a;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/* Image quads are batched by texture; textures are cached by source path. */
|
|
38
|
+
struct ImageBatch {
|
|
39
|
+
SDL_GPUTexture *texture = nullptr;
|
|
40
|
+
uint32_t first = 0;
|
|
41
|
+
uint32_t count = 0;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
extern SDL_GPUGraphicsPipeline *g_pipeline;
|
|
45
|
+
extern SDL_GPUGraphicsPipeline *g_text_pipeline;
|
|
46
|
+
extern SDL_GPUGraphicsPipeline *g_image_pipeline;
|
|
47
|
+
extern SDL_GPUSampler *g_sampler;
|
|
48
|
+
extern int g_renderer_failed;
|
|
49
|
+
extern bool g_text_ok;
|
|
50
|
+
extern std::vector<ImageBatch> g_image_batches;
|
|
51
|
+
extern std::unordered_map<std::string, SDL_GPUTexture *> g_image_textures;
|
|
52
|
+
|
|
53
|
+
/* -- glyph atlas ---------------------------------------------------------- */
|
|
54
|
+
|
|
55
|
+
constexpr int kAtlasSize = 2048;
|
|
56
|
+
|
|
57
|
+
struct GlyphEntry {
|
|
58
|
+
float u0 = 0, v0 = 0, u1 = 0, v1 = 0;
|
|
59
|
+
int width = 0, height = 0, left = 0, top = 0;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
struct GlyphKey {
|
|
63
|
+
const void *font = nullptr;
|
|
64
|
+
uint32_t glyph = 0;
|
|
65
|
+
bool operator==(const GlyphKey &other) const {
|
|
66
|
+
return font == other.font && glyph == other.glyph;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
struct GlyphKeyHash {
|
|
71
|
+
size_t operator()(const GlyphKey &key) const {
|
|
72
|
+
return std::hash<const void *>()(key.font) * 1099511628211ull ^
|
|
73
|
+
(size_t)(key.glyph * 2654435761u);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
extern SDL_GPUTexture *g_atlas_texture;
|
|
78
|
+
extern std::vector<unsigned char> g_atlas_mirror;
|
|
79
|
+
extern std::unordered_map<GlyphKey, GlyphEntry, GlyphKeyHash> g_glyphs;
|
|
80
|
+
extern int g_atlas_x;
|
|
81
|
+
extern int g_atlas_y;
|
|
82
|
+
extern int g_atlas_row_height;
|
|
83
|
+
extern bool g_atlas_dirty;
|
|
84
|
+
extern int g_atlas_dirty_x0, g_atlas_dirty_y0, g_atlas_dirty_x1, g_atlas_dirty_y1;
|
|
85
|
+
extern bool g_atlas_full_logged;
|
|
86
|
+
|
|
87
|
+
/* -- geometry helpers ----------------------------------------------------- */
|
|
88
|
+
|
|
89
|
+
void pushRect(std::vector<Vertex> &verts, const xtgui::PaintRect &rect);
|
|
90
|
+
void pushGlyph(std::vector<TextVertex> &verts, float x, float y, float width, float height,
|
|
91
|
+
const GlyphEntry &entry, const xtgui::Color &color);
|
|
92
|
+
void uploadVertices(SDL_GPUDevice *device, XtGuiGeometry *geometry, const void *data,
|
|
93
|
+
uint32_t count, uint32_t stride);
|
|
94
|
+
|
|
95
|
+
/* -- text ----------------------------------------------------------------- */
|
|
96
|
+
|
|
97
|
+
bool ensureAtlasTexture(SDL_GPUDevice *device);
|
|
98
|
+
void markAtlasDirty(int x, int y, int width, int height);
|
|
99
|
+
bool ensureGlyph(SDL_GPUDevice *device, xtgui::Font *font, uint32_t glyph, GlyphEntry &out);
|
|
100
|
+
void flushAtlas(SDL_GPUDevice *device);
|
|
101
|
+
SDL_GPUGraphicsPipeline *createTextPipeline(SDL_GPUDevice *device, SDL_Window *reference);
|
|
102
|
+
SDL_GPUSampler *createSampler(SDL_GPUDevice *device);
|
|
103
|
+
|
|
104
|
+
/* -- images --------------------------------------------------------------- */
|
|
105
|
+
|
|
106
|
+
SDL_GPUGraphicsPipeline *createImagePipeline(SDL_GPUDevice *device, SDL_Window *reference);
|
|
107
|
+
SDL_GPUTexture *ensureImageTexture(SDL_GPUDevice *device, const std::string &src);
|
|
108
|
+
|
|
109
|
+
} // namespace renderer_detail
|
|
110
|
+
} // namespace xtgui
|
|
111
|
+
|
|
112
|
+
#endif /* XT_GUI_RENDERER_INTERNAL_H */
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc GUI engine — SDL_GPU Metal (MSL) shader sources.
|
|
3
|
+
*
|
|
4
|
+
* Shared by `renderer.cpp` (fills), `renderer_text.cpp` (glyphs) and
|
|
5
|
+
* `renderer_image.cpp` (images). Text and image quads reuse `kTextMSL`; only
|
|
6
|
+
* the fragment entry point differs (`fs_text` vs `fs_image`).
|
|
7
|
+
*/
|
|
8
|
+
#ifndef XT_GUI_RENDERER_SHADERS_H
|
|
9
|
+
#define XT_GUI_RENDERER_SHADERS_H
|
|
10
|
+
|
|
11
|
+
/* Rounded-rectangle fill. Vertex attributes (matching SDL_GPUVertexAttribute):
|
|
12
|
+
* 0 -> position (pixels, viewport-relative)
|
|
13
|
+
* 1 -> local (pixels, relative to the rectangle centre)
|
|
14
|
+
* 2 -> half (rectangle half extents, pixels)
|
|
15
|
+
* 3 -> radius (pixels)
|
|
16
|
+
* 4 -> colour
|
|
17
|
+
* The push constant is the viewport size in logical pixels. */
|
|
18
|
+
inline constexpr const char *kFillMSL = R"MSL(
|
|
19
|
+
#include <metal_stdlib>
|
|
20
|
+
using namespace metal;
|
|
21
|
+
|
|
22
|
+
struct FillIn {
|
|
23
|
+
float2 position [[attribute(0)]];
|
|
24
|
+
float2 local [[attribute(1)]];
|
|
25
|
+
float2 halfsize [[attribute(2)]];
|
|
26
|
+
float radius [[attribute(3)]];
|
|
27
|
+
float4 color [[attribute(4)]];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
struct FillOut {
|
|
31
|
+
float4 position [[position]];
|
|
32
|
+
float2 local;
|
|
33
|
+
float2 halfsize;
|
|
34
|
+
float radius;
|
|
35
|
+
float4 color;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
vertex FillOut vs_main(FillIn in [[stage_in]],
|
|
39
|
+
constant float2 &viewport [[buffer(0)]]) {
|
|
40
|
+
FillOut out;
|
|
41
|
+
float2 ndc = float2(in.position.x / viewport.x * 2.0 - 1.0,
|
|
42
|
+
1.0 - in.position.y / viewport.y * 2.0);
|
|
43
|
+
out.position = float4(ndc, 0.0, 1.0);
|
|
44
|
+
out.local = in.local;
|
|
45
|
+
out.halfsize = in.halfsize;
|
|
46
|
+
out.radius = in.radius;
|
|
47
|
+
out.color = in.color;
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fragment float4 fs_main(FillOut in [[stage_in]]) {
|
|
52
|
+
float2 d = abs(in.local) - in.halfsize + in.radius;
|
|
53
|
+
float dist = min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - in.radius;
|
|
54
|
+
float aa = max(fwidth(dist), 0.0001);
|
|
55
|
+
float alpha = clamp(0.5 - dist / aa, 0.0, 1.0);
|
|
56
|
+
return float4(in.color.rgb, in.color.a * alpha);
|
|
57
|
+
}
|
|
58
|
+
)MSL";
|
|
59
|
+
|
|
60
|
+
/* Glyph quads. Attributes:
|
|
61
|
+
* 0 -> position (pixels, viewport-relative)
|
|
62
|
+
* 1 -> uv (atlas coordinates in [0,1])
|
|
63
|
+
* 2 -> colour
|
|
64
|
+
* The fragment shader samples the single-channel atlas and modulates alpha. */
|
|
65
|
+
inline constexpr const char *kTextMSL = R"MSL(
|
|
66
|
+
#include <metal_stdlib>
|
|
67
|
+
using namespace metal;
|
|
68
|
+
|
|
69
|
+
struct TextIn {
|
|
70
|
+
float2 position [[attribute(0)]];
|
|
71
|
+
float2 uv [[attribute(1)]];
|
|
72
|
+
float4 color [[attribute(2)]];
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
struct TextOut {
|
|
76
|
+
float4 position [[position]];
|
|
77
|
+
float2 uv;
|
|
78
|
+
float4 color;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
vertex TextOut vs_text(TextIn in [[stage_in]],
|
|
82
|
+
constant float2 &viewport [[buffer(0)]]) {
|
|
83
|
+
TextOut out;
|
|
84
|
+
float2 ndc = float2(in.position.x / viewport.x * 2.0 - 1.0,
|
|
85
|
+
1.0 - in.position.y / viewport.y * 2.0);
|
|
86
|
+
out.position = float4(ndc, 0.0, 1.0);
|
|
87
|
+
out.uv = in.uv;
|
|
88
|
+
out.color = in.color;
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fragment float4 fs_text(TextOut in [[stage_in]],
|
|
93
|
+
texture2d<float> atlas [[texture(0)]],
|
|
94
|
+
sampler samp [[sampler(0)]]) {
|
|
95
|
+
float coverage = atlas.sample(samp, in.uv).r;
|
|
96
|
+
return float4(in.color.rgb, in.color.a * coverage);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Image quads reuse the text vertex layout but sample an RGBA texture. */
|
|
100
|
+
fragment float4 fs_image(TextOut in [[stage_in]],
|
|
101
|
+
texture2d<float> tex [[texture(0)]],
|
|
102
|
+
sampler samp [[sampler(0)]]) {
|
|
103
|
+
float4 c = tex.sample(samp, in.uv);
|
|
104
|
+
return float4(c.rgb * in.color.rgb, c.a * in.color.a);
|
|
105
|
+
}
|
|
106
|
+
)MSL";
|
|
107
|
+
|
|
108
|
+
#endif /* XT_GUI_RENDERER_SHADERS_H */
|