xbintsc 0.5.37 → 0.5.41
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/dist/src/cli/help.d.ts +1 -1
- package/dist/src/codegen/generator/module.js +23 -7
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +1 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +1 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/deferred.d.ts +63 -0
- package/dist/src/driver/bundler/deferred.js +279 -0
- package/dist/src/driver/bundler/deferred.js.map +1 -0
- package/dist/src/driver/bundler/merge.js +214 -2
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/runtime-objects.d.ts +1 -1
- package/dist/src/driver/runtime-objects.js +1 -0
- package/dist/src/driver/runtime-objects.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/html.js +98 -15
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +1 -0
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/gui/three.d.ts +4 -3
- package/dist/src/extensions/gui/three.js +4 -3
- package/dist/src/extensions/gui/three.js.map +1 -1
- package/dist/tests/codegen/closures.test.js +7 -0
- package/dist/tests/codegen/closures.test.js.map +1 -1
- package/dist/tests/e2e/compile-objects-classes.test.js +31 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/gui-canvas-state.test.d.ts +9 -0
- package/dist/tests/e2e/gui-canvas-state.test.js +297 -0
- package/dist/tests/e2e/gui-canvas-state.test.js.map +1 -0
- package/dist/tests/e2e/gui-draw-perf.test.d.ts +22 -0
- package/dist/tests/e2e/gui-draw-perf.test.js +405 -0
- package/dist/tests/e2e/gui-draw-perf.test.js.map +1 -0
- package/dist/tests/e2e/gui-perf.test.d.ts +23 -0
- package/dist/tests/e2e/gui-perf.test.js +283 -0
- package/dist/tests/e2e/gui-perf.test.js.map +1 -0
- package/dist/tests/e2e/gui-script-import-order.test.d.ts +10 -0
- package/dist/tests/e2e/gui-script-import-order.test.js +169 -0
- package/dist/tests/e2e/gui-script-import-order.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl.test.js +4 -4
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.d.ts +8 -0
- package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.js +336 -0
- package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.js +108 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.js.map +1 -0
- package/dist/tests/e2e/url.test.d.ts +6 -0
- package/dist/tests/e2e/url.test.js +114 -0
- package/dist/tests/e2e/url.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.js +45 -10
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/doc/gui/api.md +28 -2
- package/doc/gui/canvas.md +110 -27
- package/doc/gui/known-issues.md +32 -10
- package/doc/gui/rendering.md +77 -0
- package/doc/gui/runtime.md +18 -3
- package/doc/gui/webgl.md +58 -29
- package/doc/gui-scripts.md +19 -19
- package/doc/gui.md +43 -9
- package/doc/implemented/fetch.md +5 -0
- package/doc/implemented/modules.md +13 -0
- package/doc/implemented/stdlib.md +17 -0
- package/doc/unimplemented/deviations.md +1 -0
- package/doc/zh-CN/gui/api.md +25 -2
- package/doc/zh-CN/gui/canvas.md +95 -26
- package/doc/zh-CN/gui/known-issues.md +21 -4
- package/doc/zh-CN/gui/rendering.md +59 -0
- package/doc/zh-CN/gui/runtime.md +13 -3
- package/doc/zh-CN/gui/webgl.md +30 -8
- package/doc/zh-CN/gui-scripts.md +14 -13
- package/doc/zh-CN/gui.md +32 -8
- package/doc/zh-CN/implemented/fetch.md +4 -0
- package/doc/zh-CN/implemented/modules.md +10 -0
- package/doc/zh-CN/implemented/stdlib.md +15 -0
- package/doc/zh-CN/unimplemented/deviations.md +1 -0
- package/package.json +7 -7
- package/runtime/ext_gui/browser.cpp +3 -1
- package/runtime/ext_gui/canvas.cpp +135 -89
- package/runtime/ext_gui/canvas.h +116 -0
- package/runtime/ext_gui/canvas_clip.cpp +143 -0
- package/runtime/ext_gui/canvas_composite.cpp +241 -0
- package/runtime/ext_gui/canvas_coverage.cpp +241 -0
- package/runtime/ext_gui/canvas_gradient.cpp +41 -4
- package/runtime/ext_gui/canvas_image_data.cpp +4 -0
- package/runtime/ext_gui/canvas_internal.h +34 -9
- package/runtime/ext_gui/canvas_raster.cpp +207 -178
- package/runtime/ext_gui/canvas_shadow.cpp +161 -0
- package/runtime/ext_gui/canvas_stroke.cpp +37 -9
- package/runtime/ext_gui/canvas_style.cpp +59 -0
- package/runtime/ext_gui/canvas_text.cpp +140 -0
- package/runtime/ext_gui/css.h +7 -0
- package/runtime/ext_gui/css_sheet.cpp +22 -0
- package/runtime/ext_gui/document.cpp +25 -1
- package/runtime/ext_gui/document.h +8 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +16 -1
- package/runtime/ext_gui/dom_api_canvas_image.cpp +9 -0
- package/runtime/ext_gui/dom_api_canvas_state.cpp +217 -0
- package/runtime/ext_gui/dom_api_internal.h +36 -37
- package/runtime/ext_gui/dom_api_offscreen.cpp +213 -0
- package/runtime/ext_gui/dom_api_proto.cpp +18 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +29 -9
- package/runtime/ext_gui/dom_api_webgl2.cpp +33 -1
- package/runtime/ext_gui/dom_api_webgl_internal.h +58 -0
- package/runtime/ext_gui/dom_api_webgl_source.cpp +18 -0
- package/runtime/ext_gui/gradient_values.cpp +12 -1
- package/runtime/ext_gui/gui.cpp +5 -0
- package/runtime/ext_gui/gui_canvas.cpp +4 -0
- package/runtime/ext_gui/gui_engine.h +32 -0
- package/runtime/ext_gui/gui_events.cpp +182 -58
- package/runtime/ext_gui/gui_media.cpp +3 -0
- package/runtime/ext_gui/image.cpp +69 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +11 -0
- package/runtime/ext_gui/layout.cpp +4 -0
- package/runtime/ext_gui/paint.cpp +19 -0
- package/runtime/ext_gui/paint_background.cpp +18 -1
- package/runtime/ext_gui/perf.cpp +171 -0
- package/runtime/ext_gui/perf.h +127 -0
- package/runtime/ext_gui/renderer.cpp +109 -41
- package/runtime/ext_gui/renderer.h +33 -9
- package/runtime/ext_gui/renderer_image.cpp +135 -65
- package/runtime/ext_gui/renderer_internal.h +15 -3
- package/runtime/ext_gui/renderer_text.cpp +24 -12
- package/runtime/ext_gui/script.cpp +31 -0
- package/runtime/ext_gui/style.cpp +101 -30
- package/runtime/ext_gui/style.h +6 -3
- package/runtime/ext_gui/style_print.cpp +7 -1
- package/runtime/ext_gui/text.cpp +23 -4
- package/runtime/ext_gui/text.h +29 -0
- package/runtime/ext_gui/text_cache.cpp +118 -0
- package/runtime/ext_gui/text_glyph_cache.cpp +100 -0
- package/runtime/ext_gui/webgl.h +48 -146
- package/runtime/ext_gui/webgl_blit.cpp +12 -1
- package/runtime/ext_gui/webgl_blit_depth.cpp +270 -0
- package/runtime/ext_gui/webgl_buffer.cpp +59 -1
- package/runtime/ext_gui/webgl_buffer_objects.cpp +106 -9
- package/runtime/ext_gui/webgl_clear.cpp +3 -0
- package/runtime/ext_gui/webgl_context.cpp +29 -3
- package/runtime/ext_gui/webgl_draw.cpp +75 -270
- package/runtime/ext_gui/webgl_draw_buffers.cpp +1 -0
- package/runtime/ext_gui/webgl_draw_setup.cpp +321 -0
- package/runtime/ext_gui/webgl_draw_state.h +130 -0
- package/runtime/ext_gui/webgl_glsl.h +3 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +3 -8
- package/runtime/ext_gui/webgl_glsl_unroll.cpp +283 -0
- package/runtime/ext_gui/webgl_msl.cpp +4 -0
- package/runtime/ext_gui/webgl_objects.h +148 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +8 -8
- package/runtime/ext_gui/webgl_program_internal.h +35 -0
- package/runtime/ext_gui/webgl_shader.cpp +34 -36
- package/runtime/ext_gui/webgl_webgl2.cpp +36 -0
- package/runtime/ext_gui/window.cpp +56 -1
- package/runtime/rt.h +3 -0
- package/runtime/xt_fetch/async.inc +60 -0
- package/runtime/xt_url_object.c +463 -0
- package/src/codegen/generator/module.ts +22 -7
- package/src/codegen/generator/state.ts +1 -0
- package/src/codegen/generator/tables.ts +1 -0
- package/src/driver/bundler/deferred.ts +351 -0
- package/src/driver/bundler/merge.ts +219 -2
- package/src/driver/runtime-objects.ts +1 -0
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/html.ts +100 -17
- package/src/extensions/gui/index.ts +1 -0
- package/src/extensions/gui/three.ts +4 -3
package/runtime/ext_gui/webgl.h
CHANGED
|
@@ -32,15 +32,13 @@
|
|
|
32
32
|
|
|
33
33
|
#include "webgl_constants.h"
|
|
34
34
|
#include "webgl2_constants.h"
|
|
35
|
+
#include "webgl_draw_state.h"
|
|
35
36
|
#include "webgl_glsl.h"
|
|
37
|
+
#include "webgl_objects.h"
|
|
36
38
|
#include "webgl_uniform_block.h"
|
|
37
39
|
|
|
38
40
|
namespace xtgui {
|
|
39
41
|
|
|
40
|
-
constexpr int kWebGLMaxAttribs = 16;
|
|
41
|
-
constexpr int kWebGLMaxTextureUnits = 16;
|
|
42
|
-
constexpr int kWebGLMaxDrawBuffers = 4;
|
|
43
|
-
|
|
44
42
|
struct WebGLShader {
|
|
45
43
|
uint32_t id = 0;
|
|
46
44
|
int type = 0; // GL_VERTEX_SHADER / GL_FRAGMENT_SHADER
|
|
@@ -56,6 +54,10 @@ struct WebGLUniform {
|
|
|
56
54
|
std::string name;
|
|
57
55
|
GlslBlockMember layout;
|
|
58
56
|
bool sampler = false;
|
|
57
|
+
/** `sampler2DShadow`/`samplerCubeShadow`/`sampler2DArrayShadow`: SDL_GPU
|
|
58
|
+
* binds a comparison sampler, and the GLSL `texture()` call performs the
|
|
59
|
+
* hardware depth compare. */
|
|
60
|
+
bool compare = false;
|
|
59
61
|
int unit = -1;
|
|
60
62
|
};
|
|
61
63
|
|
|
@@ -68,6 +70,7 @@ struct WebGLProgram {
|
|
|
68
70
|
std::vector<WebGLUniform> uniforms;
|
|
69
71
|
std::vector<WebGLUniformBlock> blocks;
|
|
70
72
|
std::vector<GlslUniformDecl> attribs;
|
|
73
|
+
std::vector<WebGLDrawAttribPlan> draw_attribs;
|
|
71
74
|
std::unordered_map<std::string, int> attrib_locations; // name -> location
|
|
72
75
|
std::unordered_map<std::string, int> attrib_bindings; // bindAttribLocation overrides
|
|
73
76
|
std::unordered_map<std::string, int> uniform_index; // name -> uniforms[] index
|
|
@@ -81,145 +84,7 @@ struct WebGLProgram {
|
|
|
81
84
|
SDL_GPUShader *vs_shader = nullptr;
|
|
82
85
|
SDL_GPUShader *fs_shader = nullptr;
|
|
83
86
|
std::vector<SDL_GPUGraphicsPipeline *> pipelines;
|
|
84
|
-
std::unordered_map<
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
struct WebGLBuffer {
|
|
88
|
-
uint32_t id = 0;
|
|
89
|
-
std::vector<uint8_t> data;
|
|
90
|
-
SDL_GPUBuffer *gpu = nullptr;
|
|
91
|
-
uint32_t capacity = 0;
|
|
92
|
-
bool dirty = true;
|
|
93
|
-
/** `bufferData` usage hint, reported by `getBufferParameter`. */
|
|
94
|
-
int usage = GL_STATIC_DRAW;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
struct WebGLTexture {
|
|
98
|
-
uint32_t id = 0;
|
|
99
|
-
int width = 0;
|
|
100
|
-
int height = 0;
|
|
101
|
-
int levels = 1;
|
|
102
|
-
/** The binding target this texture was created for. */
|
|
103
|
-
int target = GL_TEXTURE_2D;
|
|
104
|
-
/** Layers for a cube/2D-array texture, depth for a 3D texture. */
|
|
105
|
-
int layers = 1;
|
|
106
|
-
SDL_GPUTexture *gpu = nullptr;
|
|
107
|
-
SDL_GPUTextureFormat format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
|
108
|
-
/** Depth(-stencil) formats can only be depth attachments. */
|
|
109
|
-
bool depth = false;
|
|
110
|
-
/** Block-compressed textures are sample-only, with one mip level. */
|
|
111
|
-
bool compressed = false;
|
|
112
|
-
/** Usage flags the current `gpu` texture was created with. */
|
|
113
|
-
uint32_t usage = 0;
|
|
114
|
-
bool as_target = false; // bound as a colour attachment
|
|
115
|
-
bool as_depth_target = false; // bound as a depth attachment
|
|
116
|
-
bool has_mipmaps = false;
|
|
117
|
-
int min_filter = 0;
|
|
118
|
-
int mag_filter = 0;
|
|
119
|
-
int wrap_s = 0;
|
|
120
|
-
int wrap_t = 0;
|
|
121
|
-
SDL_GPUSampler *sampler = nullptr;
|
|
122
|
-
bool dirty = false;
|
|
123
|
-
bool defined = false;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
struct WebGLRenderbuffer {
|
|
127
|
-
uint32_t id = 0;
|
|
128
|
-
int width = 0;
|
|
129
|
-
int height = 0;
|
|
130
|
-
bool stencil = false;
|
|
131
|
-
SDL_GPUTexture *depth = nullptr;
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
struct WebGLFramebuffer {
|
|
135
|
-
uint32_t id = 0;
|
|
136
|
-
uint32_t color_textures[kWebGLMaxDrawBuffers] = {};
|
|
137
|
-
/** Layer rendered to for an array/cube colour attachment. */
|
|
138
|
-
int color_layers[kWebGLMaxDrawBuffers] = {};
|
|
139
|
-
/** `COLOR_ATTACHMENTi` or `NONE` per draw-buffer slot. */
|
|
140
|
-
int draw_buffers[kWebGLMaxDrawBuffers] = {GL_COLOR_ATTACHMENT0, GL_NONE, GL_NONE, GL_NONE};
|
|
141
|
-
uint32_t depth_texture = 0;
|
|
142
|
-
uint32_t depth_renderbuffer = 0;
|
|
143
|
-
int width = 0;
|
|
144
|
-
int height = 0;
|
|
145
|
-
SDL_GPUTexture *depth = nullptr; // owned when no renderbuffer/texture supplies one
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
/** Per-attribute array state. */
|
|
149
|
-
struct WebGLAttribState {
|
|
150
|
-
bool enabled = false;
|
|
151
|
-
bool integer = false; // `vertexAttribIPointer` rather than `vertexAttribPointer`
|
|
152
|
-
uint32_t buffer = 0;
|
|
153
|
-
int size = 4;
|
|
154
|
-
int type = GL_FLOAT;
|
|
155
|
-
bool normalized = false;
|
|
156
|
-
int stride = 0;
|
|
157
|
-
int offset = 0;
|
|
158
|
-
int divisor = 0; // 0 = per vertex, 1 = per instance
|
|
159
|
-
float current[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
/** A WebGL 2 vertex-array object; binding one restores this state. */
|
|
163
|
-
struct WebGLVertexArray {
|
|
164
|
-
uint32_t id = 0;
|
|
165
|
-
WebGLAttribState attribs[kWebGLMaxAttribs];
|
|
166
|
-
uint32_t element_buffer = 0;
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
/** A WebGL 2 sampler object, bound to a texture unit with `bindSampler`. */
|
|
170
|
-
struct WebGLSampler {
|
|
171
|
-
uint32_t id = 0;
|
|
172
|
-
int min_filter = 0;
|
|
173
|
-
int mag_filter = 0;
|
|
174
|
-
int wrap_s = 0;
|
|
175
|
-
int wrap_t = 0;
|
|
176
|
-
SDL_GPUSampler *gpu = nullptr;
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
struct WebGLQuery {
|
|
180
|
-
uint32_t id = 0;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
struct WebGLSync {
|
|
184
|
-
uint32_t id = 0;
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
/** One face's stencil test and update state. */
|
|
188
|
-
struct WebGLStencilFace {
|
|
189
|
-
int func = GL_ALWAYS;
|
|
190
|
-
int ref = 0;
|
|
191
|
-
uint32_t value_mask = 0xFFFFFFFFu; // compare mask
|
|
192
|
-
uint32_t write_mask = 0xFFFFFFFFu;
|
|
193
|
-
int fail = GL_KEEP;
|
|
194
|
-
int zfail = GL_KEEP;
|
|
195
|
-
int zpass = GL_KEEP;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
/** The fixed-function state a pipeline depends on. */
|
|
199
|
-
struct WebGLDrawState {
|
|
200
|
-
bool blend = false;
|
|
201
|
-
int blend_src_rgb = GL_ONE;
|
|
202
|
-
int blend_dst_rgb = GL_ZERO;
|
|
203
|
-
int blend_src_alpha = GL_ONE;
|
|
204
|
-
int blend_dst_alpha = GL_ZERO;
|
|
205
|
-
int blend_eq_rgb = GL_FUNC_ADD;
|
|
206
|
-
int blend_eq_alpha = GL_FUNC_ADD;
|
|
207
|
-
bool depth_test = false;
|
|
208
|
-
bool depth_write = true;
|
|
209
|
-
int depth_func = GL_LESS;
|
|
210
|
-
bool stencil = false;
|
|
211
|
-
WebGLStencilFace stencil_front;
|
|
212
|
-
WebGLStencilFace stencil_back;
|
|
213
|
-
bool cull = false;
|
|
214
|
-
int cull_face = GL_BACK;
|
|
215
|
-
int front_face = GL_CCW;
|
|
216
|
-
bool color_mask[4] = {true, true, true, true};
|
|
217
|
-
/** Attachment formats of the bound target; pipelines are format-specific. */
|
|
218
|
-
int color_formats[kWebGLMaxDrawBuffers] = {
|
|
219
|
-
SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM,
|
|
220
|
-
SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM};
|
|
221
|
-
int color_target_count = 1;
|
|
222
|
-
int depth_format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
|
|
87
|
+
std::unordered_map<WebGLDrawKey, SDL_GPUGraphicsPipeline *, WebGLDrawKeyHash> pipeline_cache;
|
|
223
88
|
};
|
|
224
89
|
|
|
225
90
|
class WebGLContext {
|
|
@@ -416,6 +281,10 @@ class WebGLContext {
|
|
|
416
281
|
void bind_framebuffer(int target, uint32_t id);
|
|
417
282
|
uint32_t bound_read_framebuffer_id() const { return read_framebuffer_; }
|
|
418
283
|
bool blit_framebuffer(const int source[4], const int destination[4], int mask, int filter);
|
|
284
|
+
/** Copy the depth attachment with a sampling pass (SDL_GPU's blit only copies
|
|
285
|
+
* colour); stencil bits are not copied. */
|
|
286
|
+
bool blit_depth(uint32_t source_framebuffer, uint32_t destination_framebuffer,
|
|
287
|
+
const int source[4], const int destination[4]);
|
|
419
288
|
bool framebuffer_texture(uint32_t framebuffer, uint32_t texture,
|
|
420
289
|
int attachment = GL_COLOR_ATTACHMENT0);
|
|
421
290
|
bool framebuffer_texture_layer(uint32_t framebuffer, uint32_t texture, int attachment,
|
|
@@ -476,6 +345,7 @@ class WebGLContext {
|
|
|
476
345
|
/** The 1×1 texture a scissored colour clear blits from. */
|
|
477
346
|
SDL_GPUTexture *clear_color_texture();
|
|
478
347
|
SDL_GPUTexture *framebuffer_color(uint32_t id);
|
|
348
|
+
SDL_GPUTexture *framebuffer_depth(uint32_t id);
|
|
479
349
|
void framebuffer_size(uint32_t id, int *width, int *height);
|
|
480
350
|
/** Release every GPU handle this context owns, keeping the CPU-side object
|
|
481
351
|
* table. Used by the destructor and by `lose_context`. */
|
|
@@ -490,7 +360,19 @@ class WebGLContext {
|
|
|
490
360
|
int draw_color_layer(int slot);
|
|
491
361
|
SDL_GPUTexture *ensure_texture_gpu(WebGLTexture *texture, bool as_target);
|
|
492
362
|
SDL_GPUSampler *sampler_for(WebGLTexture *texture);
|
|
363
|
+
SDL_GPUSampler *sampler_for_compare(WebGLTexture *texture);
|
|
493
364
|
SDL_GPUBuffer *ensure_buffer_gpu(WebGLBuffer *buffer);
|
|
365
|
+
/** Upload `size` bytes at `offset` into an existing GPU buffer, ending the
|
|
366
|
+
* open render pass first (a copy pass cannot run inside one). */
|
|
367
|
+
bool upload_buffer_range(SDL_GPUBuffer *gpu, uint32_t offset, const void *bytes, uint32_t size);
|
|
368
|
+
/** The persistent GPU buffer for a disabled attribute's `current[]` value. */
|
|
369
|
+
SDL_GPUBuffer *constant_attrib_buffer(int index);
|
|
370
|
+
/** Hash the current fixed-function state into a draw key. */
|
|
371
|
+
void draw_state_hash(uint64_t *first, uint64_t *second) const;
|
|
372
|
+
/** The prepared pipeline/layout for `key`, building and caching it on miss. */
|
|
373
|
+
const WebGLDrawSetup *prepare_draw(const WebGLDrawKey &key);
|
|
374
|
+
/** Drop every prepared draw and pipeline key (state/layout changed shape). */
|
|
375
|
+
void clear_draw_cache();
|
|
494
376
|
void ensure_default_target();
|
|
495
377
|
void rebuild_default_target();
|
|
496
378
|
bool ensure_fallback();
|
|
@@ -502,11 +384,10 @@ class WebGLContext {
|
|
|
502
384
|
SDL_GPUSampler *sampler_gpu(WebGLSampler *sampler);
|
|
503
385
|
uint32_t buffer_for_target(int target) const;
|
|
504
386
|
void release_program_pipelines(WebGLProgram *program);
|
|
505
|
-
SDL_GPUGraphicsPipeline *create_pipeline(WebGLProgram *program, int mode,
|
|
387
|
+
SDL_GPUGraphicsPipeline *create_pipeline(WebGLProgram *program, int mode,
|
|
506
388
|
int attribute_count, int buffer_count,
|
|
507
389
|
const SDL_GPUVertexAttribute *attrs,
|
|
508
|
-
const SDL_GPUVertexBufferDescription *buffers
|
|
509
|
-
const std::string &key);
|
|
390
|
+
const SDL_GPUVertexBufferDescription *buffers);
|
|
510
391
|
|
|
511
392
|
uint64_t id_ = 0;
|
|
512
393
|
int width_ = 0;
|
|
@@ -518,6 +399,23 @@ class WebGLContext {
|
|
|
518
399
|
SDL_GPURenderPass *pass_ = nullptr;
|
|
519
400
|
bool pass_targets_default_ = true;
|
|
520
401
|
uint32_t pass_framebuffer_ = 0;
|
|
402
|
+
/** Bumped every time a render pass is actually opened: bindings recorded in
|
|
403
|
+
* a previous pass do not survive an intervening upload. */
|
|
404
|
+
uint64_t pass_serial_ = 0;
|
|
405
|
+
/** State-shape versions. A mutation that changes the vertex layout, the GPU
|
|
406
|
+
* buffer handles or the attachment formats bumps one of these, which
|
|
407
|
+
* invalidates every prepared draw. */
|
|
408
|
+
uint64_t attribs_version_ = 1;
|
|
409
|
+
uint64_t gpu_version_ = 1;
|
|
410
|
+
uint64_t framebuffer_version_ = 1;
|
|
411
|
+
std::unordered_map<WebGLDrawKey, WebGLDrawSetup, WebGLDrawKeyHash> draw_setups_;
|
|
412
|
+
SDL_GPUGraphicsPipeline *last_pipeline_ = nullptr;
|
|
413
|
+
const WebGLDrawSetup *last_setup_ = nullptr;
|
|
414
|
+
uint64_t last_setup_pass_ = 0;
|
|
415
|
+
/** Pipelines for internal helper draws (depth blit), keyed by their state. */
|
|
416
|
+
std::unordered_map<std::string, SDL_GPUGraphicsPipeline *> internal_pipelines_;
|
|
417
|
+
/** Scratch for the sampler bindings of one draw. */
|
|
418
|
+
std::vector<SDL_GPUTextureSamplerBinding> sampler_bindings_;
|
|
521
419
|
|
|
522
420
|
SDL_GPUTexture *color_ = nullptr;
|
|
523
421
|
SDL_GPUTexture *depth_ = nullptr;
|
|
@@ -528,6 +426,10 @@ class WebGLContext {
|
|
|
528
426
|
/** Internal program/buffer for a scissored depth/stencil clear. */
|
|
529
427
|
uint32_t clear_program_ = 0;
|
|
530
428
|
uint32_t clear_buffer_ = 0;
|
|
429
|
+
/** Internal program/buffer/sampler for a depth blit. */
|
|
430
|
+
uint32_t blit_program_ = 0;
|
|
431
|
+
uint32_t blit_buffer_ = 0;
|
|
432
|
+
SDL_GPUSampler *blit_sampler_ = nullptr;
|
|
531
433
|
|
|
532
434
|
float clear_color_[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
533
435
|
float clear_depth_ = 1.0f;
|
|
@@ -19,10 +19,21 @@ namespace xtgui {
|
|
|
19
19
|
|
|
20
20
|
bool WebGLContext::blit_framebuffer(const int source[4], const int destination[4], int mask,
|
|
21
21
|
int filter) {
|
|
22
|
-
|
|
22
|
+
const bool color_bit = (mask & GL_COLOR_BUFFER_BIT) != 0;
|
|
23
|
+
const bool depth_bit = (mask & GL_DEPTH_BUFFER_BIT) != 0;
|
|
24
|
+
if (!color_bit && !depth_bit) return true;
|
|
23
25
|
end_pass();
|
|
24
26
|
ensure_command();
|
|
25
27
|
if (cmd_ == nullptr) return false;
|
|
28
|
+
if (depth_bit) {
|
|
29
|
+
/* SDL_GPU's blit API is colour-only; the depth copy is a sampling pass that
|
|
30
|
+
* writes `gl_FragDepth`. Stencil bits have no sampleable representation and
|
|
31
|
+
* are left untouched. */
|
|
32
|
+
blit_depth(read_framebuffer_, bound_framebuffer_, source, destination);
|
|
33
|
+
end_pass();
|
|
34
|
+
ensure_command();
|
|
35
|
+
}
|
|
36
|
+
if (!color_bit) return true;
|
|
26
37
|
SDL_GPUTexture *source_texture = framebuffer_color(read_framebuffer_);
|
|
27
38
|
SDL_GPUTexture *destination_texture = framebuffer_color(bound_framebuffer_);
|
|
28
39
|
if (source_texture == nullptr || destination_texture == nullptr ||
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc GUI engine — `blitFramebuffer` depth copies.
|
|
3
|
+
*
|
|
4
|
+
* SDL_GPU's blit copies colour attachments only. A depth attachment can still
|
|
5
|
+
* be sampled as an ordinary texture, so a full-screen quad samples the source
|
|
6
|
+
* depth and writes it back with `gl_FragDepth` while colour writes are masked
|
|
7
|
+
* off. Stencil is not sampleable through SDL_GPU and is left untouched.
|
|
8
|
+
*
|
|
9
|
+
* The internal program, quad buffer and sampler are ordinary engine objects and
|
|
10
|
+
* live for the context's lifetime. The caller's GL state is saved/restored
|
|
11
|
+
* around the draw.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#include "webgl.h"
|
|
15
|
+
|
|
16
|
+
#include <algorithm>
|
|
17
|
+
#include <cstring>
|
|
18
|
+
#include <string>
|
|
19
|
+
|
|
20
|
+
#include "gui_internal.h"
|
|
21
|
+
|
|
22
|
+
namespace xtgui {
|
|
23
|
+
namespace {
|
|
24
|
+
|
|
25
|
+
const char *kBlitVertexShader =
|
|
26
|
+
"#version 300 es\n"
|
|
27
|
+
"uniform highp vec4 u_dst;\n"
|
|
28
|
+
"uniform highp vec4 u_uv;\n"
|
|
29
|
+
"in highp vec2 a_pos;\n"
|
|
30
|
+
"out highp vec2 v_uv;\n"
|
|
31
|
+
"void main() {\n"
|
|
32
|
+
" v_uv = mix(u_uv.xy, u_uv.zw, a_pos);\n"
|
|
33
|
+
" gl_Position = vec4(mix(u_dst.xy, u_dst.zw, a_pos), 0.0, 1.0);\n"
|
|
34
|
+
"}\n";
|
|
35
|
+
|
|
36
|
+
const char *kBlitFragmentShader =
|
|
37
|
+
"#version 300 es\n"
|
|
38
|
+
"precision highp float;\n"
|
|
39
|
+
"uniform highp vec4 u_dst;\n"
|
|
40
|
+
"uniform highp sampler2D u_depth;\n"
|
|
41
|
+
"in highp vec2 v_uv;\n"
|
|
42
|
+
"out highp vec4 fragColor;\n"
|
|
43
|
+
"void main() {\n"
|
|
44
|
+
" fragColor = vec4(1.0);\n"
|
|
45
|
+
" gl_FragDepth = texture(u_depth, v_uv).r;\n"
|
|
46
|
+
"}\n";
|
|
47
|
+
|
|
48
|
+
} // namespace
|
|
49
|
+
|
|
50
|
+
bool WebGLContext::blit_depth(uint32_t source_framebuffer, uint32_t destination_framebuffer,
|
|
51
|
+
const int source[4], const int destination[4]) {
|
|
52
|
+
if (guidev::g_device == nullptr) return false;
|
|
53
|
+
if (source_framebuffer == destination_framebuffer) return false;
|
|
54
|
+
/* A renderbuffer depth attachment is never created with SAMPLER usage. */
|
|
55
|
+
if (source_framebuffer != 0) {
|
|
56
|
+
WebGLFramebuffer *framebuffer = this->framebuffer(source_framebuffer);
|
|
57
|
+
if (framebuffer == nullptr || framebuffer->depth_texture == 0) return false;
|
|
58
|
+
}
|
|
59
|
+
if (destination_framebuffer != 0 && this->framebuffer(destination_framebuffer) == nullptr) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
int source_width = 0;
|
|
64
|
+
int source_height = 0;
|
|
65
|
+
int destination_width = 0;
|
|
66
|
+
int destination_height = 0;
|
|
67
|
+
framebuffer_size(source_framebuffer, &source_width, &source_height);
|
|
68
|
+
framebuffer_size(destination_framebuffer, &destination_width, &destination_height);
|
|
69
|
+
if (source_width <= 0 || source_height <= 0 || destination_width <= 0 ||
|
|
70
|
+
destination_height <= 0) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
int sx0 = source[0];
|
|
74
|
+
int sy0 = source[1];
|
|
75
|
+
int sx1 = source[2];
|
|
76
|
+
int sy1 = source[3];
|
|
77
|
+
int dx0 = destination[0];
|
|
78
|
+
int dy0 = destination[1];
|
|
79
|
+
int dx1 = destination[2];
|
|
80
|
+
int dy1 = destination[3];
|
|
81
|
+
if (sx1 < sx0) std::swap(sx0, sx1);
|
|
82
|
+
if (sy1 < sy0) std::swap(sy0, sy1);
|
|
83
|
+
if (dx1 < dx0) std::swap(dx0, dx1);
|
|
84
|
+
if (dy1 < dy0) std::swap(dy0, dy1);
|
|
85
|
+
sx0 = std::max(0, std::min(sx0, source_width));
|
|
86
|
+
sx1 = std::max(0, std::min(sx1, source_width));
|
|
87
|
+
sy0 = std::max(0, std::min(sy0, source_height));
|
|
88
|
+
sy1 = std::max(0, std::min(sy1, source_height));
|
|
89
|
+
dx0 = std::max(0, std::min(dx0, destination_width));
|
|
90
|
+
dx1 = std::max(0, std::min(dx1, destination_width));
|
|
91
|
+
dy0 = std::max(0, std::min(dy0, destination_height));
|
|
92
|
+
dy1 = std::max(0, std::min(dy1, destination_height));
|
|
93
|
+
if (sx1 <= sx0 || sy1 <= sy0 || dx1 <= dx0 || dy1 <= dy0) return true;
|
|
94
|
+
SDL_GPUTexture *source_depth = framebuffer_depth(source_framebuffer);
|
|
95
|
+
SDL_GPUTexture *destination_depth = framebuffer_depth(destination_framebuffer);
|
|
96
|
+
if (source_depth == nullptr || destination_depth == nullptr ||
|
|
97
|
+
source_depth == destination_depth) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Build the internal program/buffer on first use. */
|
|
102
|
+
if (blit_program_ == 0) {
|
|
103
|
+
const uint32_t vs = create_shader(GL_VERTEX_SHADER);
|
|
104
|
+
shader_source(vs, kBlitVertexShader);
|
|
105
|
+
const uint32_t fs = create_shader(GL_FRAGMENT_SHADER);
|
|
106
|
+
shader_source(fs, kBlitFragmentShader);
|
|
107
|
+
if (compile_shader(vs) && compile_shader(fs)) {
|
|
108
|
+
const uint32_t program_id = create_program();
|
|
109
|
+
attach_shader(program_id, vs);
|
|
110
|
+
attach_shader(program_id, fs);
|
|
111
|
+
bind_attrib_location(program_id, 0, "a_pos");
|
|
112
|
+
if (link_program(program_id)) {
|
|
113
|
+
blit_program_ = program_id;
|
|
114
|
+
} else {
|
|
115
|
+
delete_program(program_id);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (blit_program_ == 0) {
|
|
119
|
+
delete_shader(vs);
|
|
120
|
+
delete_shader(fs);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (blit_buffer_ == 0) {
|
|
125
|
+
blit_buffer_ = create_buffer();
|
|
126
|
+
bind_buffer(GL_ARRAY_BUFFER, blit_buffer_);
|
|
127
|
+
const float vertices[8] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
|
|
128
|
+
buffer_data(blit_buffer_, (const uint8_t *)vertices, (uint32_t)sizeof(vertices),
|
|
129
|
+
GL_STATIC_DRAW);
|
|
130
|
+
}
|
|
131
|
+
if (blit_sampler_ == nullptr) {
|
|
132
|
+
SDL_GPUSamplerCreateInfo sampler_info;
|
|
133
|
+
memset(&sampler_info, 0, sizeof(sampler_info));
|
|
134
|
+
sampler_info.min_filter = SDL_GPU_FILTER_NEAREST;
|
|
135
|
+
sampler_info.mag_filter = SDL_GPU_FILTER_NEAREST;
|
|
136
|
+
sampler_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
|
|
137
|
+
sampler_info.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
|
138
|
+
sampler_info.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
|
139
|
+
sampler_info.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
|
|
140
|
+
sampler_info.max_lod = 0.0f;
|
|
141
|
+
blit_sampler_ = SDL_CreateGPUSampler(guidev::g_device, &sampler_info);
|
|
142
|
+
}
|
|
143
|
+
WebGLProgram *program = this->program(blit_program_);
|
|
144
|
+
WebGLBuffer *quad_buffer = buffer(blit_buffer_);
|
|
145
|
+
SDL_GPUBuffer *quad_gpu = quad_buffer != nullptr ? ensure_buffer_gpu(quad_buffer) : nullptr;
|
|
146
|
+
if (program == nullptr || program->vs_shader == nullptr || program->fs_shader == nullptr ||
|
|
147
|
+
quad_gpu == nullptr || blit_sampler_ == nullptr) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* NDC rectangle and source UVs. Source V is flipped because GL's origin is
|
|
152
|
+
* bottom-left while SDL_GPU's render targets and uploads are top-down. */
|
|
153
|
+
double dst[4] = {(double)dx0 / (double)destination_width * 2.0 - 1.0,
|
|
154
|
+
(double)dy0 / (double)destination_height * 2.0 - 1.0,
|
|
155
|
+
(double)dx1 / (double)destination_width * 2.0 - 1.0,
|
|
156
|
+
(double)dy1 / (double)destination_height * 2.0 - 1.0};
|
|
157
|
+
double uv[4] = {(double)sx0 / (double)source_width,
|
|
158
|
+
1.0 - (double)sy0 / (double)source_height,
|
|
159
|
+
(double)sx1 / (double)source_width,
|
|
160
|
+
1.0 - (double)sy1 / (double)source_height};
|
|
161
|
+
|
|
162
|
+
const WebGLDrawState saved_state = state_;
|
|
163
|
+
const uint32_t saved_program = current_program_;
|
|
164
|
+
state_.blend = false;
|
|
165
|
+
state_.cull = false;
|
|
166
|
+
state_.stencil = false;
|
|
167
|
+
state_.depth_test = true;
|
|
168
|
+
state_.depth_write = true;
|
|
169
|
+
state_.depth_func = GL_ALWAYS;
|
|
170
|
+
for (bool &channel : state_.color_mask) channel = false;
|
|
171
|
+
state_.color_target_count = 0;
|
|
172
|
+
for (int slot = 0; slot < kWebGLMaxDrawBuffers; slot++) {
|
|
173
|
+
if (draw_color_texture(slot) == nullptr) continue;
|
|
174
|
+
state_.color_formats[state_.color_target_count++] = draw_color_format(slot);
|
|
175
|
+
}
|
|
176
|
+
if (state_.color_target_count == 0) state_.color_target_count = 1;
|
|
177
|
+
state_.depth_format = target_depth_format();
|
|
178
|
+
current_program_ = blit_program_;
|
|
179
|
+
|
|
180
|
+
std::string key = "blit-depth/";
|
|
181
|
+
for (int i = 0; i < state_.color_target_count; i++) {
|
|
182
|
+
key += std::to_string(state_.color_formats[i]) + ",";
|
|
183
|
+
}
|
|
184
|
+
key += std::to_string(state_.depth_format);
|
|
185
|
+
SDL_GPUVertexAttribute attribute;
|
|
186
|
+
memset(&attribute, 0, sizeof(attribute));
|
|
187
|
+
attribute.location = 0;
|
|
188
|
+
attribute.buffer_slot = 0;
|
|
189
|
+
attribute.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
|
|
190
|
+
attribute.offset = 0;
|
|
191
|
+
SDL_GPUVertexBufferDescription buffer_description;
|
|
192
|
+
memset(&buffer_description, 0, sizeof(buffer_description));
|
|
193
|
+
buffer_description.slot = 0;
|
|
194
|
+
buffer_description.pitch = 8;
|
|
195
|
+
buffer_description.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX;
|
|
196
|
+
SDL_GPUGraphicsPipeline *pipeline = nullptr;
|
|
197
|
+
auto cached = internal_pipelines_.find(key);
|
|
198
|
+
if (cached != internal_pipelines_.end()) {
|
|
199
|
+
pipeline = cached->second;
|
|
200
|
+
} else {
|
|
201
|
+
pipeline = create_pipeline(program, GL_TRIANGLE_STRIP, 1, 1, &attribute, &buffer_description);
|
|
202
|
+
if (pipeline != nullptr) internal_pipelines_[key] = pipeline;
|
|
203
|
+
}
|
|
204
|
+
bool ok = pipeline != nullptr;
|
|
205
|
+
if (ok) {
|
|
206
|
+
begin_pass(false, false, false);
|
|
207
|
+
ok = pass_ != nullptr;
|
|
208
|
+
}
|
|
209
|
+
if (ok) {
|
|
210
|
+
SDL_BindGPUGraphicsPipeline(pass_, pipeline);
|
|
211
|
+
SDL_GPUBufferBinding binding;
|
|
212
|
+
memset(&binding, 0, sizeof(binding));
|
|
213
|
+
binding.buffer = quad_gpu;
|
|
214
|
+
SDL_BindGPUVertexBuffers(pass_, 0, &binding, 1);
|
|
215
|
+
SDL_Rect scissor;
|
|
216
|
+
scissor.x = 0;
|
|
217
|
+
scissor.y = 0;
|
|
218
|
+
scissor.w = destination_width;
|
|
219
|
+
scissor.h = destination_height;
|
|
220
|
+
if (scissor_test_ && scissor_box_[2] > 0 && scissor_box_[3] > 0) {
|
|
221
|
+
scissor.x = scissor_box_[0];
|
|
222
|
+
scissor.y = destination_height - (scissor_box_[1] + scissor_box_[3]);
|
|
223
|
+
scissor.w = scissor_box_[2];
|
|
224
|
+
scissor.h = scissor_box_[3];
|
|
225
|
+
}
|
|
226
|
+
if (scissor.x < 0) {
|
|
227
|
+
scissor.w += scissor.x;
|
|
228
|
+
scissor.x = 0;
|
|
229
|
+
}
|
|
230
|
+
if (scissor.y < 0) {
|
|
231
|
+
scissor.h += scissor.y;
|
|
232
|
+
scissor.y = 0;
|
|
233
|
+
}
|
|
234
|
+
if (scissor.x + scissor.w > destination_width) scissor.w = destination_width - scissor.x;
|
|
235
|
+
if (scissor.y + scissor.h > destination_height) scissor.h = destination_height - scissor.y;
|
|
236
|
+
if (scissor.w < 0) scissor.w = 0;
|
|
237
|
+
if (scissor.h < 0) scissor.h = 0;
|
|
238
|
+
SDL_SetGPUScissor(pass_, &scissor);
|
|
239
|
+
|
|
240
|
+
const int dst_location = uniform_location(blit_program_, "u_dst");
|
|
241
|
+
const int uv_location = uniform_location(blit_program_, "u_uv");
|
|
242
|
+
if (dst_location >= 0) uniform_floats(blit_program_, dst_location, 4, dst, 1);
|
|
243
|
+
if (uv_location >= 0) uniform_floats(blit_program_, uv_location, 4, uv, 1);
|
|
244
|
+
if (program->block_size > 0) {
|
|
245
|
+
if (program->vs_has_block) {
|
|
246
|
+
SDL_PushGPUVertexUniformData(cmd_, 0, program->block.data(),
|
|
247
|
+
(Uint32)program->block.size());
|
|
248
|
+
}
|
|
249
|
+
if (program->fs_has_block) {
|
|
250
|
+
SDL_PushGPUFragmentUniformData(cmd_, 0, program->block.data(),
|
|
251
|
+
(Uint32)program->block.size());
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
SDL_GPUTextureSamplerBinding sampler_binding;
|
|
255
|
+
sampler_binding.texture = source_depth;
|
|
256
|
+
sampler_binding.sampler = blit_sampler_;
|
|
257
|
+
SDL_BindGPUFragmentSamplers(pass_, 0, &sampler_binding, 1);
|
|
258
|
+
SDL_DrawGPUPrimitives(pass_, 4, 1, 0, 0);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
state_ = saved_state;
|
|
262
|
+
current_program_ = saved_program;
|
|
263
|
+
/* This pass bound the blit pipeline directly, outside the prepared-draw
|
|
264
|
+
* cache; a later draw in the same pass must bind its own pipeline again. */
|
|
265
|
+
last_setup_ = nullptr;
|
|
266
|
+
last_pipeline_ = nullptr;
|
|
267
|
+
return ok;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
} // namespace xtgui
|
|
@@ -58,6 +58,27 @@ SDL_GPUSamplerAddressMode address_of(int wrap) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
SDL_GPUCompareOp compare_of(int func) {
|
|
62
|
+
switch (func) {
|
|
63
|
+
case GL_NEVER:
|
|
64
|
+
return SDL_GPU_COMPAREOP_NEVER;
|
|
65
|
+
case GL_LESS:
|
|
66
|
+
return SDL_GPU_COMPAREOP_LESS;
|
|
67
|
+
case GL_EQUAL:
|
|
68
|
+
return SDL_GPU_COMPAREOP_EQUAL;
|
|
69
|
+
case GL_LEQUAL:
|
|
70
|
+
return SDL_GPU_COMPAREOP_LESS_OR_EQUAL;
|
|
71
|
+
case GL_GREATER:
|
|
72
|
+
return SDL_GPU_COMPAREOP_GREATER;
|
|
73
|
+
case GL_NOTEQUAL:
|
|
74
|
+
return SDL_GPU_COMPAREOP_NOT_EQUAL;
|
|
75
|
+
case GL_GEQUAL:
|
|
76
|
+
return SDL_GPU_COMPAREOP_GREATER_OR_EQUAL;
|
|
77
|
+
default:
|
|
78
|
+
return SDL_GPU_COMPAREOP_ALWAYS;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
61
82
|
} // namespace
|
|
62
83
|
|
|
63
84
|
/* -- textures ------------------------------------------------------------ */
|
|
@@ -111,6 +132,9 @@ void WebGLContext::delete_texture(uint32_t id) {
|
|
|
111
132
|
if (found->second->sampler != nullptr) {
|
|
112
133
|
SDL_ReleaseGPUSampler(guidev::g_device, found->second->sampler);
|
|
113
134
|
}
|
|
135
|
+
if (found->second->compare_sampler != nullptr) {
|
|
136
|
+
SDL_ReleaseGPUSampler(guidev::g_device, found->second->compare_sampler);
|
|
137
|
+
}
|
|
114
138
|
}
|
|
115
139
|
textures_.erase(found);
|
|
116
140
|
}
|
|
@@ -159,17 +183,29 @@ bool WebGLContext::tex_parameter(uint32_t id, int pname, int value) {
|
|
|
159
183
|
else if (pname == GL_TEXTURE_MAG_FILTER) record->mag_filter = value;
|
|
160
184
|
else if (pname == GL_TEXTURE_WRAP_S) record->wrap_s = value;
|
|
161
185
|
else if (pname == GL_TEXTURE_WRAP_T) record->wrap_t = value;
|
|
162
|
-
else
|
|
186
|
+
else if (pname == GL_TEXTURE_COMPARE_MODE) {
|
|
187
|
+
record->compare_mode = value == GL_COMPARE_REF_TO_TEXTURE;
|
|
188
|
+
} else if (pname == GL_TEXTURE_COMPARE_FUNC) {
|
|
189
|
+
record->compare_func = value;
|
|
190
|
+
} else return true; // other parameters are accepted and ignored
|
|
163
191
|
if (record->sampler != nullptr && guidev::g_device != nullptr) {
|
|
164
192
|
SDL_ReleaseGPUSampler(guidev::g_device, record->sampler);
|
|
165
193
|
record->sampler = nullptr;
|
|
166
194
|
}
|
|
195
|
+
if (record->compare_sampler != nullptr && guidev::g_device != nullptr) {
|
|
196
|
+
SDL_ReleaseGPUSampler(guidev::g_device, record->compare_sampler);
|
|
197
|
+
record->compare_sampler = nullptr;
|
|
198
|
+
}
|
|
167
199
|
return true;
|
|
168
200
|
}
|
|
169
201
|
|
|
170
202
|
int WebGLContext::tex_parameter_value(uint32_t id, int pname) {
|
|
171
203
|
WebGLTexture *record = texture(id);
|
|
172
204
|
if (record == nullptr) return 0;
|
|
205
|
+
if (pname == GL_TEXTURE_COMPARE_MODE) {
|
|
206
|
+
return record->compare_mode ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
|
|
207
|
+
}
|
|
208
|
+
if (pname == GL_TEXTURE_COMPARE_FUNC) return record->compare_func;
|
|
173
209
|
if (pname == GL_TEXTURE_MIN_FILTER) return record->min_filter;
|
|
174
210
|
if (pname == GL_TEXTURE_MAG_FILTER) return record->mag_filter;
|
|
175
211
|
if (pname == GL_TEXTURE_WRAP_S) return record->wrap_s;
|
|
@@ -269,6 +305,25 @@ SDL_GPUSampler *WebGLContext::sampler_for(WebGLTexture *record) {
|
|
|
269
305
|
return record->sampler;
|
|
270
306
|
}
|
|
271
307
|
|
|
308
|
+
SDL_GPUSampler *WebGLContext::sampler_for_compare(WebGLTexture *record) {
|
|
309
|
+
if (record == nullptr || guidev::g_device == nullptr) return nullptr;
|
|
310
|
+
if (record->compare_sampler != nullptr) return record->compare_sampler;
|
|
311
|
+
SDL_GPUSamplerCreateInfo info;
|
|
312
|
+
memset(&info, 0, sizeof(info));
|
|
313
|
+
info.min_filter = SDL_GPU_FILTER_LINEAR;
|
|
314
|
+
info.mag_filter = SDL_GPU_FILTER_LINEAR;
|
|
315
|
+
info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
|
|
316
|
+
info.address_mode_u = address_of(record->wrap_s);
|
|
317
|
+
info.address_mode_v = address_of(record->wrap_t);
|
|
318
|
+
info.address_mode_w = address_of(record->wrap_t);
|
|
319
|
+
info.min_lod = 0.0f;
|
|
320
|
+
info.max_lod = record->has_mipmaps ? 1000.0f : 0.0f;
|
|
321
|
+
info.enable_compare = true;
|
|
322
|
+
info.compare_op = compare_of(record->compare_func);
|
|
323
|
+
record->compare_sampler = SDL_CreateGPUSampler(guidev::g_device, &info);
|
|
324
|
+
return record->compare_sampler;
|
|
325
|
+
}
|
|
326
|
+
|
|
272
327
|
int WebGLContext::texture_width(uint32_t id) {
|
|
273
328
|
WebGLTexture *record = texture(id);
|
|
274
329
|
return record != nullptr ? record->width : 0;
|
|
@@ -317,12 +372,14 @@ void WebGLContext::bind_framebuffer(int target, uint32_t id) {
|
|
|
317
372
|
if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER) return;
|
|
318
373
|
if (id != bound_framebuffer_) end_pass();
|
|
319
374
|
bound_framebuffer_ = id;
|
|
375
|
+
framebuffer_version_ += 1;
|
|
320
376
|
if (target == GL_FRAMEBUFFER) read_framebuffer_ = id;
|
|
321
377
|
read_buffer_ = id == 0 ? GL_BACK : GL_COLOR_ATTACHMENT0;
|
|
322
378
|
}
|
|
323
379
|
|
|
324
380
|
bool WebGLContext::framebuffer_texture(uint32_t framebuffer_id, uint32_t texture_id,
|
|
325
381
|
int attachment) {
|
|
382
|
+
framebuffer_version_ += 1;
|
|
326
383
|
WebGLFramebuffer *record_framebuffer = framebuffer(framebuffer_id);
|
|
327
384
|
WebGLTexture *record = texture(texture_id);
|
|
328
385
|
if (record_framebuffer == nullptr) return false;
|
|
@@ -436,6 +493,7 @@ bool WebGLContext::renderbuffer_storage(uint32_t id, int width, int height, bool
|
|
|
436
493
|
}
|
|
437
494
|
|
|
438
495
|
bool WebGLContext::framebuffer_renderbuffer(uint32_t framebuffer_id, uint32_t renderbuffer_id) {
|
|
496
|
+
framebuffer_version_ += 1;
|
|
439
497
|
WebGLFramebuffer *framebuffer_ = framebuffer(framebuffer_id);
|
|
440
498
|
WebGLRenderbuffer *record = renderbuffer(renderbuffer_id);
|
|
441
499
|
if (framebuffer_ == nullptr) return false;
|