@geastack/native-webgl-angle 0.1.11 → 0.1.13
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/geatsc-plugin-readback.mjs +46 -0
- package/geatsc-plugin-uniforms.mjs +214 -59
- package/geatsc-plugin-uploads.mjs +7 -2
- package/geatsc-plugin.mjs +919 -68
- package/native/angle_webgl_host.mm +267 -23
- package/native/webgl_readback.h +29 -0
- package/package.json +9 -7
- package/src/inflate.ts +252 -0
- package/src/nativeWebGL.ts +88 -17
- package/src/nativeWebGLHost.ts +28 -2
- package/src/text/atlas-sans.ts +19 -178
- package/src/text/atlas-serif-italic.ts +26 -178
- package/src/text/atlas-serif.ts +22 -178
- package/src/text/native-text-types.ts +28 -0
- package/src/text/native-text.ts +154 -50
- package/src/troika-three-text.ts +49 -4
- package/NOTICE +0 -4
|
@@ -1,15 +1,22 @@
|
|
|
1
|
+
#include "webgl_readback.h"
|
|
2
|
+
// GEA_WEBGL_STATIC_GLES: EGL/GLES are statically linked into the program, so
|
|
3
|
+
// nothing is loaded and entry points resolve through eglGetProcAddress.
|
|
1
4
|
#if defined(_WIN32)
|
|
2
5
|
#ifndef NOMINMAX
|
|
3
6
|
#define NOMINMAX
|
|
4
7
|
#endif
|
|
5
8
|
#include <windows.h>
|
|
6
|
-
|
|
9
|
+
// Legacy Win16 macros are not C++ identifiers and must not leak into the runtime.
|
|
10
|
+
#undef near
|
|
11
|
+
#undef far
|
|
12
|
+
#elif defined(__APPLE__)
|
|
7
13
|
#include "gea/apple/native_bridge.h"
|
|
8
14
|
|
|
9
15
|
#import <AppKit/AppKit.h>
|
|
10
16
|
#import <QuartzCore/QuartzCore.h>
|
|
11
17
|
#import <dispatch/dispatch.h>
|
|
12
|
-
|
|
18
|
+
#endif
|
|
19
|
+
#if !defined(_WIN32) && !defined(GEA_WEBGL_STATIC_GLES)
|
|
13
20
|
#include <dlfcn.h>
|
|
14
21
|
#endif
|
|
15
22
|
// Typed uniform arguments use the compiler runtime on both native platforms.
|
|
@@ -168,7 +175,7 @@ extern "C" bool gea_three_key_pressed(double code) {
|
|
|
168
175
|
return gGeaKeyState[c];
|
|
169
176
|
}
|
|
170
177
|
|
|
171
|
-
#if defined(
|
|
178
|
+
#if !defined(__APPLE__)
|
|
172
179
|
// The Win32 window procedure owns input on Windows; it reports into the same
|
|
173
180
|
// tables the AppKit host view fills on macOS (keys as macOS virtual key codes).
|
|
174
181
|
extern "C" void gea_three_set_key_state(int code, bool down) {
|
|
@@ -185,7 +192,7 @@ extern "C" void gea_three_set_pointer_state(double x, double y, double width, do
|
|
|
185
192
|
}
|
|
186
193
|
#endif
|
|
187
194
|
|
|
188
|
-
#if
|
|
195
|
+
#if defined(__APPLE__)
|
|
189
196
|
@interface GeaAngleWebGLHostView : NSView
|
|
190
197
|
@end
|
|
191
198
|
|
|
@@ -406,6 +413,10 @@ using PFNGLTEXIMAGE2DPROC = void (*)(GLenum, GLint, GLint, GLsizei, GLsizei, GLi
|
|
|
406
413
|
using PFNGLTEXPARAMETERFPROC = void (*)(GLenum, GLenum, GLfloat);
|
|
407
414
|
using PFNGLTEXPARAMETERIPROC = void (*)(GLenum, GLenum, GLint);
|
|
408
415
|
using PFNGLTEXSUBIMAGE2DPROC = void (*)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *);
|
|
416
|
+
using PFNGLTEXIMAGE3DPROC = void (*)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *);
|
|
417
|
+
using PFNGLTEXSUBIMAGE3DPROC = void (*)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *);
|
|
418
|
+
using PFNGLTEXSTORAGE3DPROC = void (*)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei);
|
|
419
|
+
using PFNGLFRAMEBUFFERTEXTURELAYERPROC = void (*)(GLenum, GLenum, GLuint, GLint, GLint);
|
|
409
420
|
using PFNGLTEXSTORAGE2DPROC = void (*)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
|
|
410
421
|
using PFNGLUNIFORM1FPROC = void (*)(GLint, GLfloat);
|
|
411
422
|
using PFNGLUNIFORM1FVPROC = void (*)(GLint, GLsizei, const GLfloat *);
|
|
@@ -439,7 +450,22 @@ using PFNGLVERTEXATTRIBDIVISORPROC = void (*)(GLuint, GLuint);
|
|
|
439
450
|
using PFNGLVERTEXATTRIBPOINTERPROC = void (*)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *);
|
|
440
451
|
using PFNGLVIEWPORTPROC = void (*)(GLint, GLint, GLsizei, GLsizei);
|
|
441
452
|
|
|
453
|
+
using PFNGLCOPYTEXIMAGE2DPROC=void(*)(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint);
|
|
454
|
+
using PFNGLCOPYTEXSUBIMAGE2DPROC=void(*)(GLenum,GLint,GLint,GLint,GLint,GLint,GLsizei,GLsizei);
|
|
455
|
+
using PFNGLBLITFRAMEBUFFERPROC = void (*)(GLint,GLint,GLint,GLint,GLint,GLint,GLint,GLint,GLbitfield,GLenum);
|
|
456
|
+
using PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC = void (*)(GLenum,GLsizei,GLenum,GLsizei,GLsizei);
|
|
457
|
+
using GLuint64 = std::uint64_t;
|
|
458
|
+
using GLsync = struct __GLsync *;
|
|
459
|
+
using PFNGLMAPBUFFERRANGEPROC = void *(*)(GLenum, GLintptr, GLsizeiptr, GLbitfield);
|
|
460
|
+
using PFNGLUNMAPBUFFERPROC = GLboolean (*)(GLenum);
|
|
461
|
+
using PFNGLFENCESYNCPROC = GLsync (*)(GLenum, GLbitfield);
|
|
462
|
+
using PFNGLCLIENTWAITSYNCPROC = GLenum (*)(GLsync, GLbitfield, GLuint64);
|
|
463
|
+
using PFNGLDELETESYNCPROC = void (*)(GLsync);
|
|
442
464
|
struct AngleWebGLState {
|
|
465
|
+
PFNGLCOPYTEXIMAGE2DPROC glCopyTexImage2D=nullptr;
|
|
466
|
+
PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D=nullptr;
|
|
467
|
+
PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = nullptr;
|
|
468
|
+
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = nullptr;
|
|
443
469
|
void *egl = nullptr;
|
|
444
470
|
void *gles = nullptr;
|
|
445
471
|
EGLDisplay display = EGL_NO_DISPLAY;
|
|
@@ -521,6 +547,12 @@ struct AngleWebGLState {
|
|
|
521
547
|
PFNGLPIXELSTOREIPROC glPixelStorei = nullptr;
|
|
522
548
|
PFNGLPOLYGONOFFSETPROC glPolygonOffset = nullptr;
|
|
523
549
|
PFNGLREADPIXELSPROC glReadPixels = nullptr;
|
|
550
|
+
// WebGL2 asynchronous readback: PIXEL_PACK_BUFFER reads, sync objects and read-mapping.
|
|
551
|
+
PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr;
|
|
552
|
+
PFNGLUNMAPBUFFERPROC glUnmapBuffer = nullptr;
|
|
553
|
+
PFNGLFENCESYNCPROC glFenceSync = nullptr;
|
|
554
|
+
PFNGLCLIENTWAITSYNCPROC glClientWaitSync = nullptr;
|
|
555
|
+
PFNGLDELETESYNCPROC glDeleteSync = nullptr;
|
|
524
556
|
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr;
|
|
525
557
|
PFNGLSCISSORPROC glScissor = nullptr;
|
|
526
558
|
PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
|
|
@@ -535,6 +567,12 @@ struct AngleWebGLState {
|
|
|
535
567
|
PFNGLTEXPARAMETERIPROC glTexParameteri = nullptr;
|
|
536
568
|
PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D = nullptr;
|
|
537
569
|
PFNGLTEXSTORAGE2DPROC glTexStorage2D = nullptr;
|
|
570
|
+
// Array/3D entry points are optional: a GLES without them still starts,
|
|
571
|
+
// and uploads to those targets report GL_INVALID_OPERATION in the log.
|
|
572
|
+
PFNGLTEXIMAGE3DPROC glTexImage3D = nullptr;
|
|
573
|
+
PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D = nullptr;
|
|
574
|
+
PFNGLTEXSTORAGE3DPROC glTexStorage3D = nullptr;
|
|
575
|
+
PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = nullptr;
|
|
538
576
|
PFNGLUNIFORM1FPROC glUniform1f = nullptr;
|
|
539
577
|
PFNGLUNIFORM1FVPROC glUniform1fv = nullptr;
|
|
540
578
|
PFNGLUNIFORM1IPROC glUniform1i = nullptr;
|
|
@@ -567,7 +605,7 @@ struct AngleWebGLState {
|
|
|
567
605
|
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
|
|
568
606
|
PFNGLVIEWPORTPROC glViewport = nullptr;
|
|
569
607
|
|
|
570
|
-
#if defined(
|
|
608
|
+
#if !defined(__APPLE__)
|
|
571
609
|
void *nativeWindow = nullptr;
|
|
572
610
|
#else
|
|
573
611
|
NSView *hostView = nil;
|
|
@@ -580,6 +618,7 @@ struct AngleWebGLState {
|
|
|
580
618
|
};
|
|
581
619
|
|
|
582
620
|
static AngleWebGLState gWebGL;
|
|
621
|
+
static GLenum hostReadbackError = 0;
|
|
583
622
|
static std::chrono::steady_clock::time_point gProfileSizeSync;
|
|
584
623
|
static bool gProfileSizeSyncPending = false;
|
|
585
624
|
static bool nativeFrameProfileEnabled() {
|
|
@@ -604,7 +643,7 @@ static bool nativeShadowColorAuditEnabled() {
|
|
|
604
643
|
}
|
|
605
644
|
|
|
606
645
|
static void smokeLog(const char *format, ...) {
|
|
607
|
-
char message[
|
|
646
|
+
char message[16384] = {};
|
|
608
647
|
va_list args;
|
|
609
648
|
va_start(args, format);
|
|
610
649
|
std::vsnprintf(message, sizeof(message), format, args);
|
|
@@ -618,8 +657,13 @@ static void smokeLog(const char *format, ...) {
|
|
|
618
657
|
std::fprintf(stderr, "%s\n", message);
|
|
619
658
|
return;
|
|
620
659
|
}
|
|
621
|
-
#
|
|
660
|
+
#elif defined(__APPLE__)
|
|
622
661
|
if (!path || path[0] == '\0') path = "/tmp/three-angle-metal-smoke.log";
|
|
662
|
+
#else
|
|
663
|
+
if (!path || path[0] == '\0') {
|
|
664
|
+
std::fprintf(stderr, "%s\n", message);
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
623
667
|
#endif
|
|
624
668
|
if (FILE *file = std::fopen(path, "a")) {
|
|
625
669
|
std::fprintf(file, "%s\n", message);
|
|
@@ -640,7 +684,7 @@ extern "C" void gea_three_angle_smoke_log(std::string message) {
|
|
|
640
684
|
// handler records the position in the host view's coordinate space with the
|
|
641
685
|
// same top-left-origin flip the per-view path used. Returning the event
|
|
642
686
|
// unmodified keeps normal dispatch (clicks, first responder) intact.
|
|
643
|
-
#if
|
|
687
|
+
#if defined(__APPLE__)
|
|
644
688
|
static id gGeaPointerMonitor = nil;
|
|
645
689
|
static void geaInstallPointerMonitor(void) {
|
|
646
690
|
if (gGeaPointerMonitor) return;
|
|
@@ -683,9 +727,16 @@ static void *openFirst(const char *envName, const char *const *paths) {
|
|
|
683
727
|
|
|
684
728
|
#endif
|
|
685
729
|
|
|
730
|
+
#if defined(GEA_WEBGL_STATIC_GLES)
|
|
731
|
+
extern "C" void *eglGetProcAddress(const char *name);
|
|
732
|
+
#endif
|
|
686
733
|
template <typename Fn>
|
|
687
734
|
static Fn loadSymbol(void *library, const char *name) {
|
|
688
|
-
#if defined(
|
|
735
|
+
#if defined(GEA_WEBGL_STATIC_GLES)
|
|
736
|
+
(void)library;
|
|
737
|
+
if (std::strcmp(name, "eglGetProcAddress") == 0) return reinterpret_cast<Fn>(&eglGetProcAddress);
|
|
738
|
+
return reinterpret_cast<Fn>(eglGetProcAddress(name));
|
|
739
|
+
#elif defined(_WIN32)
|
|
689
740
|
return reinterpret_cast<Fn>(GetProcAddress(static_cast<HMODULE>(library), name));
|
|
690
741
|
#else
|
|
691
742
|
return reinterpret_cast<Fn>(dlsym(library, name));
|
|
@@ -784,7 +835,7 @@ static void logEglFailure(const char *step) {
|
|
|
784
835
|
std::fprintf(stderr, "[three-angle-metal] %s failed, EGL error 0x%04x\n", step, lastEglError());
|
|
785
836
|
}
|
|
786
837
|
|
|
787
|
-
#if
|
|
838
|
+
#if defined(__APPLE__)
|
|
788
839
|
static CGFloat backingScaleForHostView(NSView *nativeView) {
|
|
789
840
|
CGFloat scale = nativeView.window ? nativeView.window.backingScaleFactor : 0.0;
|
|
790
841
|
if (scale <= 0.0 && nativeView.window.screen) scale = nativeView.window.screen.backingScaleFactor;
|
|
@@ -857,13 +908,13 @@ extern "C" void gea_three_webgl_update_size_uwp(double width, double height, dou
|
|
|
857
908
|
}
|
|
858
909
|
#endif
|
|
859
910
|
|
|
860
|
-
#if defined(
|
|
911
|
+
#if !defined(__APPLE__)
|
|
861
912
|
// The UWP frame driver owns its EGL context exclusively until it returns to
|
|
862
913
|
// CoreWindow event dispatch. Other hosts retain per-call binding semantics.
|
|
863
914
|
static thread_local bool gUwpFrameContextCurrent = false;
|
|
864
915
|
#endif
|
|
865
916
|
static bool makeCurrent(const char *label) {
|
|
866
|
-
#if defined(
|
|
917
|
+
#if !defined(__APPLE__)
|
|
867
918
|
if (gUwpFrameContextCurrent) return true;
|
|
868
919
|
#endif
|
|
869
920
|
if (!gWebGL.ready && gWebGL.context == EGL_NO_CONTEXT) return false;
|
|
@@ -894,7 +945,7 @@ static bool makeCurrent(const char *label) {
|
|
|
894
945
|
return true;
|
|
895
946
|
}
|
|
896
947
|
|
|
897
|
-
#if defined(
|
|
948
|
+
#if !defined(__APPLE__)
|
|
898
949
|
extern "C" bool gea_three_webgl_begin_frame_uwp() {
|
|
899
950
|
// Always rebind after the dispatcher, where arbitrary platform callbacks
|
|
900
951
|
// may have used a different context. No such callbacks run within the frame.
|
|
@@ -908,7 +959,7 @@ extern "C" void gea_three_webgl_end_frame_uwp() {
|
|
|
908
959
|
}
|
|
909
960
|
#endif
|
|
910
961
|
|
|
911
|
-
#if
|
|
962
|
+
#if defined(__APPLE__)
|
|
912
963
|
static bool rebuildWindowSurface(const char *label) {
|
|
913
964
|
if (!gWebGL.eglCreateWindowSurface || !gWebGL.eglDestroySurface || !gWebGL.eglMakeCurrent ||
|
|
914
965
|
!gWebGL.metalLayer || !gWebGL.config || gWebGL.context == EGL_NO_CONTEXT) {
|
|
@@ -1016,6 +1067,15 @@ static bool loadGlSymbols() {
|
|
|
1016
1067
|
LOAD_GL(glPixelStorei, PFNGLPIXELSTOREIPROC)
|
|
1017
1068
|
LOAD_GL(glPolygonOffset, PFNGLPOLYGONOFFSETPROC)
|
|
1018
1069
|
LOAD_GL(glReadPixels, PFNGLREADPIXELSPROC)
|
|
1070
|
+
LOAD_GL(glMapBufferRange, PFNGLMAPBUFFERRANGEPROC)
|
|
1071
|
+
LOAD_GL(glUnmapBuffer, PFNGLUNMAPBUFFERPROC)
|
|
1072
|
+
LOAD_GL(glFenceSync, PFNGLFENCESYNCPROC)
|
|
1073
|
+
LOAD_GL(glClientWaitSync, PFNGLCLIENTWAITSYNCPROC)
|
|
1074
|
+
LOAD_GL(glDeleteSync, PFNGLDELETESYNCPROC)
|
|
1075
|
+
LOAD_GL(glCopyTexImage2D,PFNGLCOPYTEXIMAGE2DPROC)
|
|
1076
|
+
LOAD_GL(glCopyTexSubImage2D,PFNGLCOPYTEXSUBIMAGE2DPROC)
|
|
1077
|
+
LOAD_GL(glBlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC)
|
|
1078
|
+
LOAD_GL(glRenderbufferStorageMultisample, PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)
|
|
1019
1079
|
LOAD_GL(glRenderbufferStorage, PFNGLRENDERBUFFERSTORAGEPROC)
|
|
1020
1080
|
LOAD_GL(glScissor, PFNGLSCISSORPROC)
|
|
1021
1081
|
LOAD_GL(glShaderSource, PFNGLSHADERSOURCEPROC)
|
|
@@ -1030,6 +1090,10 @@ static bool loadGlSymbols() {
|
|
|
1030
1090
|
LOAD_GL(glTexParameteri, PFNGLTEXPARAMETERIPROC)
|
|
1031
1091
|
LOAD_GL(glTexSubImage2D, PFNGLTEXSUBIMAGE2DPROC)
|
|
1032
1092
|
LOAD_GL(glTexStorage2D, PFNGLTEXSTORAGE2DPROC)
|
|
1093
|
+
gWebGL.glTexImage3D = loadGl<PFNGLTEXIMAGE3DPROC>("glTexImage3D");
|
|
1094
|
+
gWebGL.glTexSubImage3D = loadGl<PFNGLTEXSUBIMAGE3DPROC>("glTexSubImage3D");
|
|
1095
|
+
gWebGL.glTexStorage3D = loadGl<PFNGLTEXSTORAGE3DPROC>("glTexStorage3D");
|
|
1096
|
+
gWebGL.glFramebufferTextureLayer = loadGl<PFNGLFRAMEBUFFERTEXTURELAYERPROC>("glFramebufferTextureLayer");
|
|
1033
1097
|
LOAD_GL(glUniform1f, PFNGLUNIFORM1FPROC)
|
|
1034
1098
|
LOAD_GL(glUniform1fv, PFNGLUNIFORM1FVPROC)
|
|
1035
1099
|
LOAD_GL(glUniform1i, PFNGLUNIFORM1IPROC)
|
|
@@ -1065,7 +1129,7 @@ static bool loadGlSymbols() {
|
|
|
1065
1129
|
return true;
|
|
1066
1130
|
}
|
|
1067
1131
|
|
|
1068
|
-
#if defined(
|
|
1132
|
+
#if !defined(__APPLE__)
|
|
1069
1133
|
extern "C" bool gea_three_webgl_attach_uwp(
|
|
1070
1134
|
void *nativeWindow,
|
|
1071
1135
|
#else
|
|
@@ -1080,7 +1144,13 @@ extern "C" bool gea_three_webgl_attach(
|
|
|
1080
1144
|
smokeLog("[three-angle-metal] WebGL host attach requested");
|
|
1081
1145
|
if (gWebGL.ready) return true;
|
|
1082
1146
|
|
|
1083
|
-
#if defined(
|
|
1147
|
+
#if defined(GEA_WEBGL_STATIC_GLES)
|
|
1148
|
+
// Linked into the program: nothing to load; loadSymbol resolves through
|
|
1149
|
+
// eglGetProcAddress. The handles only need to be non-null.
|
|
1150
|
+
static int staticGles;
|
|
1151
|
+
gWebGL.egl = &staticGles;
|
|
1152
|
+
gWebGL.gles = &staticGles;
|
|
1153
|
+
#elif defined(_WIN32)
|
|
1084
1154
|
// An override (e.g. threejs-rendozer's GeaRendozerGLES.dll) first, then the
|
|
1085
1155
|
// packaged ANGLE of a UWP app, then a plain desktop load next to the exe.
|
|
1086
1156
|
auto openWin32 = [](const wchar_t *overrideEnv, const wchar_t *name) -> HMODULE {
|
|
@@ -1097,7 +1167,7 @@ extern "C" bool gea_three_webgl_attach(
|
|
|
1097
1167
|
};
|
|
1098
1168
|
gWebGL.egl = openWin32(L"GEA_ANGLE_EGL_DYLIB", L"libEGL.dll");
|
|
1099
1169
|
gWebGL.gles = openWin32(L"GEA_ANGLE_GLES_DYLIB", L"libGLESv2.dll");
|
|
1100
|
-
#
|
|
1170
|
+
#elif defined(__APPLE__)
|
|
1101
1171
|
static const char *const eglPaths[] = {
|
|
1102
1172
|
"/Applications/Visual Studio Code.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libEGL.dylib",
|
|
1103
1173
|
"/Applications/Cursor.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libEGL.dylib",
|
|
@@ -1115,6 +1185,8 @@ extern "C" bool gea_three_webgl_attach(
|
|
|
1115
1185
|
|
|
1116
1186
|
gWebGL.egl = openFirst("GEA_ANGLE_EGL_DYLIB", eglPaths);
|
|
1117
1187
|
gWebGL.gles = openFirst("GEA_ANGLE_GLES_DYLIB", glesPaths);
|
|
1188
|
+
#else
|
|
1189
|
+
#error "load libEGL/libGLESv2 for this platform, or build with GEA_WEBGL_STATIC_GLES"
|
|
1118
1190
|
#endif
|
|
1119
1191
|
if (!gWebGL.egl || !gWebGL.gles) {
|
|
1120
1192
|
smokeLog("[three-angle-metal] ANGLE libEGL/libGLESv2 were not found");
|
|
@@ -1192,7 +1264,7 @@ extern "C" bool gea_three_webgl_attach(
|
|
|
1192
1264
|
}
|
|
1193
1265
|
gWebGL.config = config;
|
|
1194
1266
|
|
|
1195
|
-
#if defined(
|
|
1267
|
+
#if !defined(__APPLE__)
|
|
1196
1268
|
gWebGL.nativeWindow = nativeWindow;
|
|
1197
1269
|
gea_three_webgl_update_size_uwp(width, height, devicePixelRatio);
|
|
1198
1270
|
if (gWebGL.eglCreateWindowSurface) {
|
|
@@ -1258,7 +1330,7 @@ extern "C" bool gea_three_webgl_attach(
|
|
|
1258
1330
|
|
|
1259
1331
|
gWebGL.ready = true;
|
|
1260
1332
|
gWebGL.glViewport(0, 0, gWebGL.widthPx, gWebGL.heightPx);
|
|
1261
|
-
#if
|
|
1333
|
+
#if defined(__APPLE__)
|
|
1262
1334
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
1263
1335
|
if (gWebGL.ready && rebuildWindowSurface("eglCreateWindowSurface(deferred)")) {
|
|
1264
1336
|
smokeLog("[three-angle-metal] WebGL EGL surface rebound at %dx%d", gWebGL.widthPx, gWebGL.heightPx);
|
|
@@ -1374,7 +1446,7 @@ extern "C" void gea_three_webgl_swap() {
|
|
|
1374
1446
|
// TEMP-DIAG: GEA_THREE_VIEW_DUMP=1 — at frame 60, log the window's full
|
|
1375
1447
|
// subview tree and a hit-test grid so overlay views that would swallow
|
|
1376
1448
|
// mouse events are visible without Accessibility permission.
|
|
1377
|
-
#if
|
|
1449
|
+
#if defined(__APPLE__)
|
|
1378
1450
|
if (std::getenv("GEA_THREE_VIEW_DUMP")) {
|
|
1379
1451
|
static int viewDumpCount = 0;
|
|
1380
1452
|
if (++viewDumpCount == 60) {
|
|
@@ -1407,6 +1479,16 @@ extern "C" void gea_three_webgl_swap() {
|
|
|
1407
1479
|
}
|
|
1408
1480
|
}
|
|
1409
1481
|
#endif
|
|
1482
|
+
// The debug dump and recording read the window into client memory. A PIXEL_PACK_BUFFER the app left
|
|
1483
|
+
// bound (WebGL2 asynchronous readback) would make the pointer a buffer offset instead, so the read
|
|
1484
|
+
// runs with it unbound and the binding is restored afterwards.
|
|
1485
|
+
const auto readWindowRgba = [](int w, int h, unsigned char *rgba) {
|
|
1486
|
+
GLint packBuffer = 0;
|
|
1487
|
+
if (gWebGL.glGetIntegerv) gWebGL.glGetIntegerv(0x88ED /* PIXEL_PACK_BUFFER_BINDING */, &packBuffer);
|
|
1488
|
+
if (packBuffer) gWebGL.glBindBuffer(0x88EB /* PIXEL_PACK_BUFFER */, 0);
|
|
1489
|
+
gWebGL.glReadPixels(0, 0, w, h, GL_RGBA_VALUE, GL_UNSIGNED_BYTE, rgba);
|
|
1490
|
+
if (packBuffer) gWebGL.glBindBuffer(0x88EB, static_cast<GLuint>(packBuffer));
|
|
1491
|
+
};
|
|
1410
1492
|
// Debug frame dump: GEA_WEBGL_DUMP_FRAME=<path-prefix> writes the full
|
|
1411
1493
|
// framebuffer of frames 90/180/300 as PPM (P6) — visual ground truth for
|
|
1412
1494
|
// native-vs-browser comparisons without needing a window screenshot.
|
|
@@ -1417,7 +1499,7 @@ extern "C" void gea_three_webgl_swap() {
|
|
|
1417
1499
|
const int w = gWebGL.widthPx;
|
|
1418
1500
|
const int h = gWebGL.heightPx;
|
|
1419
1501
|
std::vector<unsigned char> rgba(static_cast<size_t>(w) * h * 4);
|
|
1420
|
-
|
|
1502
|
+
readWindowRgba(w, h, rgba.data());
|
|
1421
1503
|
char path[512];
|
|
1422
1504
|
std::snprintf(path, sizeof path, "%s-f%d.ppm", dumpPrefix, dumpCount);
|
|
1423
1505
|
if (FILE *file = std::fopen(path, "wb")) {
|
|
@@ -1466,7 +1548,7 @@ extern "C" void gea_three_webgl_swap() {
|
|
|
1466
1548
|
if (due > recordWritten && gWebGL.widthPx == recordW && gWebGL.heightPx == recordH) {
|
|
1467
1549
|
std::vector<unsigned char> rgba(static_cast<size_t>(recordW) * recordH * 4);
|
|
1468
1550
|
std::vector<unsigned char> rgb(static_cast<size_t>(recordW) * recordH * 3);
|
|
1469
|
-
|
|
1551
|
+
readWindowRgba(recordW, recordH, rgba.data());
|
|
1470
1552
|
for (int y = 0; y < recordH; ++y) {
|
|
1471
1553
|
const unsigned char *src = rgba.data() + static_cast<size_t>(recordH - 1 - y) * recordW * 4;
|
|
1472
1554
|
unsigned char *dst = rgb.data() + static_cast<size_t>(y) * recordW * 3;
|
|
@@ -2259,7 +2341,7 @@ extern "C" void gea_three_webgl_draw_arrays_instanced(double mode, double first,
|
|
|
2259
2341
|
geaTrapCheck("gea_three_webgl_draw_arrays_instanced"); GEA_WEBGL_VOID("drawArraysInstanced");
|
|
2260
2342
|
gWebGL.glDrawArraysInstanced(asGLenum(mode), asGLint(first), asGLsizei(count), asGLsizei(instanceCount)); }
|
|
2261
2343
|
extern "C" double gea_three_webgl_get_error() {
|
|
2262
|
-
geaTrapCheck("gea_three_webgl_get_error"); GEA_WEBGL_DOUBLE("getError"); return gWebGL.glGetError(); }
|
|
2344
|
+
geaTrapCheck("gea_three_webgl_get_error"); GEA_WEBGL_DOUBLE("getError"); if (hostReadbackError) { const GLenum e = hostReadbackError; hostReadbackError = 0; return e; } return gWebGL.glGetError(); }
|
|
2263
2345
|
|
|
2264
2346
|
extern "C" double gea_three_webgl_call(
|
|
2265
2347
|
double opValue,
|
|
@@ -2481,6 +2563,36 @@ extern "C" void gea_three_webgl_tex_image_2d_bytes(double target, double level,
|
|
|
2481
2563
|
gWebGL.glTexImage2D(asGLenum(target), asGLint(level), asGLint(internalFormat), asGLsizei(width), asGLsizei(height), 0, asGLenum(format), asGLenum(type), bytes);
|
|
2482
2564
|
}
|
|
2483
2565
|
|
|
2566
|
+
static bool requireGl(const void *fn, const char *name) {
|
|
2567
|
+
if (fn) return true;
|
|
2568
|
+
smokeLog("[native-webgl] %s is not provided by this GLES; the call is dropped", name);
|
|
2569
|
+
return false;
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
extern "C" void gea_three_webgl_tex_image_3d_bytes(double target, double level, double internalFormat, double width, double height, double depth, double format, double type, const void* bytes, double) {
|
|
2573
|
+
GEA_WEBGL_VOID("texImage3DBytes");
|
|
2574
|
+
if (!requireGl(reinterpret_cast<const void *>(gWebGL.glTexImage3D), "glTexImage3D")) return;
|
|
2575
|
+
gWebGL.glTexImage3D(asGLenum(target), asGLint(level), asGLint(internalFormat), asGLsizei(width), asGLsizei(height), asGLsizei(depth), 0, asGLenum(format), asGLenum(type), bytes);
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
extern "C" void gea_three_webgl_tex_sub_image_3d_bytes(double target, double level, double xoffset, double yoffset, double zoffset, double width, double height, double depth, double format, double type, const void* bytes, double) {
|
|
2579
|
+
GEA_WEBGL_VOID("texSubImage3DBytes");
|
|
2580
|
+
if (!requireGl(reinterpret_cast<const void *>(gWebGL.glTexSubImage3D), "glTexSubImage3D")) return;
|
|
2581
|
+
gWebGL.glTexSubImage3D(asGLenum(target), asGLint(level), asGLint(xoffset), asGLint(yoffset), asGLint(zoffset), asGLsizei(width), asGLsizei(height), asGLsizei(depth), asGLenum(format), asGLenum(type), bytes);
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
extern "C" void gea_three_webgl_tex_storage_3d(double target, double levels, double internalFormat, double width, double height, double depth) {
|
|
2585
|
+
GEA_WEBGL_VOID("texStorage3D");
|
|
2586
|
+
if (!requireGl(reinterpret_cast<const void *>(gWebGL.glTexStorage3D), "glTexStorage3D")) return;
|
|
2587
|
+
gWebGL.glTexStorage3D(asGLenum(target), asGLsizei(std::max(1.0, levels)), asGLenum(internalFormat), asGLsizei(width), asGLsizei(height), asGLsizei(depth));
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
extern "C" void gea_three_webgl_framebuffer_texture_layer(double target, double attachment, double texture, double level, double layer) {
|
|
2591
|
+
GEA_WEBGL_VOID("framebufferTextureLayer");
|
|
2592
|
+
if (!requireGl(reinterpret_cast<const void *>(gWebGL.glFramebufferTextureLayer), "glFramebufferTextureLayer")) return;
|
|
2593
|
+
gWebGL.glFramebufferTextureLayer(asGLenum(target), asGLenum(attachment), asGLuint(texture), asGLint(level), asGLint(layer));
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2484
2596
|
extern "C" void gea_three_webgl_tex_sub_image_2d_bytes(double target, double level, double xoffset, double yoffset, double width, double height, double format, double type, const void* bytes, double) {
|
|
2485
2597
|
GEA_WEBGL_VOID("texSubImage2DBytes");
|
|
2486
2598
|
gWebGL.glTexSubImage2D(asGLenum(target), asGLint(level), asGLint(xoffset), asGLint(yoffset), asGLsizei(width), asGLsizei(height), asGLenum(format), asGLenum(type), bytes);
|
|
@@ -2771,3 +2883,135 @@ extern "C" double gea_three_webgl_call_f32(
|
|
|
2771
2883
|
}
|
|
2772
2884
|
return 0.0;
|
|
2773
2885
|
}
|
|
2886
|
+
|
|
2887
|
+
extern "C" void gea_three_webgl_read_pixels_bytes(double x, double y, double width, double height,
|
|
2888
|
+
double format, double type, void* bytes, double byteLength, double elementType) {
|
|
2889
|
+
GEA_WEBGL_VOID("readPixels");
|
|
2890
|
+
GLint alignment = 4, rowLength = 0, skipRows = 0, skipPixels = 0, packBuffer = 0;
|
|
2891
|
+
gWebGL.glGetIntegerv(0x0D05, &alignment);
|
|
2892
|
+
gWebGL.glGetIntegerv(0x0D02, &rowLength);
|
|
2893
|
+
gWebGL.glGetIntegerv(0x0D03, &skipRows);
|
|
2894
|
+
gWebGL.glGetIntegerv(0x0D04, &skipPixels);
|
|
2895
|
+
gWebGL.glGetIntegerv(0x88ED, &packBuffer);
|
|
2896
|
+
GLenum error = gea_webgl::validateReadPixels(width,height,format,type,byteLength,elementType,alignment,rowLength,skipRows,skipPixels);
|
|
2897
|
+
if (packBuffer || (!bytes && width > 0 && height > 0)) error = 0x0502;
|
|
2898
|
+
if (!std::isfinite(x) || !std::isfinite(y) || x < INT32_MIN || x > INT32_MAX || y < INT32_MIN || y > INT32_MAX) error = 0x0501;
|
|
2899
|
+
if (error) { if (!hostReadbackError) hostReadbackError = error; return; }
|
|
2900
|
+
gWebGL.glReadPixels(asGLint(x),asGLint(y),asGLsizei(width),asGLsizei(height),asGLenum(format),asGLenum(type),bytes);
|
|
2901
|
+
}
|
|
2902
|
+
|
|
2903
|
+
// WebGL2 asynchronous readback (three's readRenderTargetPixelsAsync): readPixels into the bound
|
|
2904
|
+
// PIXEL_PACK_BUFFER at a byte offset, a fence, polling, then getBufferSubData through a read mapping.
|
|
2905
|
+
extern "C" void gea_three_webgl_read_pixels_pack(double x, double y, double width, double height, double format, double type, double offset) {
|
|
2906
|
+
GEA_WEBGL_VOID("readPixels");
|
|
2907
|
+
GLint packBuffer = 0;
|
|
2908
|
+
gWebGL.glGetIntegerv(0x88ED, &packBuffer);
|
|
2909
|
+
if (!packBuffer || !std::isfinite(offset) || offset < 0 || std::floor(offset) != offset) { if (!hostReadbackError) hostReadbackError = 0x0502; return; }
|
|
2910
|
+
gWebGL.glReadPixels(asGLint(x), asGLint(y), asGLsizei(width), asGLsizei(height), asGLenum(format), asGLenum(type),
|
|
2911
|
+
reinterpret_cast<void *>(static_cast<std::uintptr_t>(offset)));
|
|
2912
|
+
}
|
|
2913
|
+
static std::unordered_map<std::uint32_t, GLsync> gWebGLSyncs;
|
|
2914
|
+
static std::uint32_t gWebGLNextSync = 1;
|
|
2915
|
+
extern "C" double gea_three_webgl_fence_sync() {
|
|
2916
|
+
GEA_WEBGL_DOUBLE("fenceSync");
|
|
2917
|
+
GLsync sync = gWebGL.glFenceSync(0x9117 /* SYNC_GPU_COMMANDS_COMPLETE */, 0);
|
|
2918
|
+
if (!sync) return 0.0;
|
|
2919
|
+
const std::uint32_t id = gWebGLNextSync++;
|
|
2920
|
+
gWebGLSyncs[id] = sync;
|
|
2921
|
+
return static_cast<double>(id);
|
|
2922
|
+
}
|
|
2923
|
+
extern "C" double gea_three_webgl_client_wait_sync(double sync, double flags, double timeout) {
|
|
2924
|
+
GEA_WEBGL_DOUBLE("clientWaitSync");
|
|
2925
|
+
auto it = gWebGLSyncs.find(static_cast<std::uint32_t>(sync));
|
|
2926
|
+
if (it == gWebGLSyncs.end()) return 0x911D; // WAIT_FAILED
|
|
2927
|
+
return static_cast<double>(gWebGL.glClientWaitSync(it->second, static_cast<GLbitfield>(flags), static_cast<GLuint64>(std::max(0.0, timeout))));
|
|
2928
|
+
}
|
|
2929
|
+
extern "C" void gea_three_webgl_delete_sync(double sync) {
|
|
2930
|
+
GEA_WEBGL_VOID("deleteSync");
|
|
2931
|
+
auto it = gWebGLSyncs.find(static_cast<std::uint32_t>(sync));
|
|
2932
|
+
if (it == gWebGLSyncs.end()) return;
|
|
2933
|
+
gWebGL.glDeleteSync(it->second);
|
|
2934
|
+
gWebGLSyncs.erase(it);
|
|
2935
|
+
}
|
|
2936
|
+
// GPU timers for the app's frame profiler, on GL_EXT_disjoint_timer_query.
|
|
2937
|
+
struct HostGpuTimers {
|
|
2938
|
+
bool initialized = false, supported = false;
|
|
2939
|
+
void (*gen)(GLsizei, GLuint *) = nullptr;
|
|
2940
|
+
void (*remove)(GLsizei, const GLuint *) = nullptr;
|
|
2941
|
+
void (*begin)(GLenum, GLuint) = nullptr;
|
|
2942
|
+
void (*end)(GLenum) = nullptr;
|
|
2943
|
+
void (*available)(GLuint, GLenum, GLuint *) = nullptr;
|
|
2944
|
+
void (*result)(GLuint, GLenum, std::uint64_t *) = nullptr;
|
|
2945
|
+
bool open = false;
|
|
2946
|
+
bool ensure() {
|
|
2947
|
+
if (initialized) return supported;
|
|
2948
|
+
initialized = true;
|
|
2949
|
+
const auto extensions = reinterpret_cast<const char *>(gWebGL.glGetString(0x1F03));
|
|
2950
|
+
const std::string list = " " + std::string(extensions ? extensions : "") + " ";
|
|
2951
|
+
if (list.find(" GL_EXT_disjoint_timer_query ") == std::string::npos) return false;
|
|
2952
|
+
gen = loadGl<decltype(gen)>("glGenQueriesEXT");
|
|
2953
|
+
remove = loadGl<decltype(remove)>("glDeleteQueriesEXT");
|
|
2954
|
+
begin = loadGl<decltype(begin)>("glBeginQueryEXT");
|
|
2955
|
+
end = loadGl<decltype(end)>("glEndQueryEXT");
|
|
2956
|
+
available = loadGl<decltype(available)>("glGetQueryObjectuivEXT");
|
|
2957
|
+
result = loadGl<decltype(result)>("glGetQueryObjectui64vEXT");
|
|
2958
|
+
supported = gen && remove && begin && end && available && result;
|
|
2959
|
+
return supported;
|
|
2960
|
+
}
|
|
2961
|
+
};
|
|
2962
|
+
static HostGpuTimers gHostGpuTimers;
|
|
2963
|
+
extern "C" double gea_three_webgl_timer_begin() {
|
|
2964
|
+
GEA_WEBGL_DOUBLE("timerBegin");
|
|
2965
|
+
auto &t = gHostGpuTimers;
|
|
2966
|
+
if (!t.ensure() || t.open) return 0.0;
|
|
2967
|
+
GLuint query = 0;
|
|
2968
|
+
t.gen(1, &query);
|
|
2969
|
+
if (!query) return 0.0;
|
|
2970
|
+
t.begin(0x88BF /* TIME_ELAPSED_EXT */, query);
|
|
2971
|
+
t.open = true;
|
|
2972
|
+
return static_cast<double>(query);
|
|
2973
|
+
}
|
|
2974
|
+
extern "C" void gea_three_webgl_timer_end() {
|
|
2975
|
+
GEA_WEBGL_VOID("timerEnd");
|
|
2976
|
+
auto &t = gHostGpuTimers;
|
|
2977
|
+
if (!t.supported || !t.open) return;
|
|
2978
|
+
t.end(0x88BF);
|
|
2979
|
+
t.open = false;
|
|
2980
|
+
}
|
|
2981
|
+
extern "C" double gea_three_webgl_timer_result(double timer) {
|
|
2982
|
+
GEA_WEBGL_DOUBLE("timerResult");
|
|
2983
|
+
auto &t = gHostGpuTimers;
|
|
2984
|
+
const GLuint query = static_cast<GLuint>(timer);
|
|
2985
|
+
if (!t.supported || !query) return 0.0;
|
|
2986
|
+
GLuint ready = 0;
|
|
2987
|
+
t.available(query, 0x8867 /* QUERY_RESULT_AVAILABLE */, &ready);
|
|
2988
|
+
if (!ready) return -1.0;
|
|
2989
|
+
std::uint64_t ns = 0;
|
|
2990
|
+
t.result(query, 0x8866 /* QUERY_RESULT */, &ns);
|
|
2991
|
+
t.remove(1, &query);
|
|
2992
|
+
return static_cast<double>(ns);
|
|
2993
|
+
}
|
|
2994
|
+
extern "C" void gea_three_webgl_get_buffer_sub_data_bytes(double target, double srcOffset, void *bytes, double byteLength) {
|
|
2995
|
+
GEA_WEBGL_VOID("getBufferSubData");
|
|
2996
|
+
if (!bytes || !(byteLength > 0) || !(srcOffset >= 0)) { if (!hostReadbackError) hostReadbackError = 0x0501; return; }
|
|
2997
|
+
void *mapped = gWebGL.glMapBufferRange(asGLenum(target), static_cast<GLintptr>(srcOffset), static_cast<GLsizeiptr>(byteLength), 0x0001 /* MAP_READ_BIT */);
|
|
2998
|
+
if (!mapped) { if (!hostReadbackError) hostReadbackError = 0x0502; return; }
|
|
2999
|
+
std::memcpy(bytes, mapped, static_cast<std::size_t>(byteLength));
|
|
3000
|
+
gWebGL.glUnmapBuffer(asGLenum(target));
|
|
3001
|
+
}
|
|
3002
|
+
|
|
3003
|
+
extern "C" void gea_three_webgl_blit_framebuffer(double sx0,double sy0,double sx1,double sy1,double dx0,double dy0,double dx1,double dy1,double mask,double filter) {
|
|
3004
|
+
GEA_WEBGL_VOID("blitFramebuffer");
|
|
3005
|
+
gWebGL.glBlitFramebuffer(asGLint(sx0),asGLint(sy0),asGLint(sx1),asGLint(sy1),asGLint(dx0),asGLint(dy0),asGLint(dx1),asGLint(dy1),asGLenum(mask),asGLenum(filter));
|
|
3006
|
+
}
|
|
3007
|
+
extern "C" void gea_three_webgl_renderbuffer_storage_multisample(double target,double samples,double format,double width,double height) {
|
|
3008
|
+
GEA_WEBGL_VOID("renderbufferStorageMultisample");
|
|
3009
|
+
gWebGL.glRenderbufferStorageMultisample(asGLenum(target),asGLsizei(samples),asGLenum(format),asGLsizei(width),asGLsizei(height));
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
extern "C" void gea_three_webgl_copy_tex_image_2d(double target,double level,double format,double x,double y,double w,double h,double border){
|
|
3013
|
+
GEA_WEBGL_VOID("copyTexImage2D");gWebGL.glCopyTexImage2D(asGLenum(target),asGLint(level),asGLenum(format),asGLint(x),asGLint(y),asGLsizei(w),asGLsizei(h),asGLint(border));
|
|
3014
|
+
}
|
|
3015
|
+
extern "C" void gea_three_webgl_copy_tex_sub_image_2d(double target,double level,double xo,double yo,double x,double y,double w,double h){
|
|
3016
|
+
GEA_WEBGL_VOID("copyTexSubImage2D");gWebGL.glCopyTexSubImage2D(asGLenum(target),asGLint(level),asGLint(xo),asGLint(yo),asGLint(x),asGLint(y),asGLsizei(w),asGLsizei(h));
|
|
3017
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <cmath>
|
|
3
|
+
#include <cstdint>
|
|
4
|
+
#include <limits>
|
|
5
|
+
|
|
6
|
+
namespace gea_webgl {
|
|
7
|
+
// Calculate the complete destination window, including WebGL2 pack layout.
|
|
8
|
+
// Return a GL error before the driver can touch an undersized typed array.
|
|
9
|
+
inline unsigned validateReadPixels(double width, double height, double format, double type,
|
|
10
|
+
double bytes, double elementType, int alignment, int rowLength, int skipRows, int skipPixels) {
|
|
11
|
+
if (!std::isfinite(width) || !std::isfinite(height) || width < 0 || height < 0 ||
|
|
12
|
+
width > INT32_MAX || height > INT32_MAX || std::floor(width) != width || std::floor(height) != height) return 0x0501;
|
|
13
|
+
if (format != 0x1908 || (type != 0x1401 && type != 0x1406 && type != 0x140B)) return 0x0502;
|
|
14
|
+
if (elementType != type && !(type == 0x140B && elementType == 0x1403)) return 0x0502;
|
|
15
|
+
if (bytes < 0 || !std::isfinite(bytes)) return 0x0501;
|
|
16
|
+
if (width == 0 || height == 0) return 0;
|
|
17
|
+
if (alignment != 1 && alignment != 2 && alignment != 4 && alignment != 8) return 0x0502;
|
|
18
|
+
if (rowLength < 0 || skipRows < 0 || skipPixels < 0) return 0x0502;
|
|
19
|
+
const uint64_t pixel = type == 0x1406 ? 16 : type == 0x140B ? 8 : 4;
|
|
20
|
+
const uint64_t row = rowLength ? rowLength : static_cast<uint64_t>(width);
|
|
21
|
+
if (row < static_cast<uint64_t>(width) + skipPixels) return 0x0502;
|
|
22
|
+
const uint64_t pitch = (row*pixel + alignment-1)/alignment*alignment;
|
|
23
|
+
const uint64_t rows = static_cast<uint64_t>(height)-1+skipRows;
|
|
24
|
+
if (rows && pitch > UINT64_MAX/rows) return 0x0502;
|
|
25
|
+
const uint64_t tail = (static_cast<uint64_t>(skipPixels)+static_cast<uint64_t>(width))*pixel;
|
|
26
|
+
if (rows*pitch > UINT64_MAX-tail) return 0x0502;
|
|
27
|
+
return static_cast<long double>(rows*pitch+tail) <= bytes ? 0 : 0x0502;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geastack/native-webgl-angle",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Typed native WebGL compatibility layer backed by ANGLE/Metal",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"./nativeThreeUtils": "./src/nativeThreeUtils.ts",
|
|
21
21
|
"./nativeWebXRManager": "./src/nativeWebXRManager.ts",
|
|
22
22
|
"./troika-three-text": "./src/troika-three-text.ts",
|
|
23
|
+
"./inflate": "./src/inflate.ts",
|
|
23
24
|
"./geatsc-plugin": "./geatsc-plugin.mjs",
|
|
24
25
|
"./native/*": "./native/*",
|
|
25
26
|
"./package.json": "./package.json",
|
|
@@ -38,7 +39,8 @@
|
|
|
38
39
|
"geatsc-plugin-instancing.mjs",
|
|
39
40
|
"geatsc-plugin-batched-probe.mjs",
|
|
40
41
|
"test/batched-render-scene.ts",
|
|
41
|
-
"test/auto-instanced-render-scene.ts"
|
|
42
|
+
"test/auto-instanced-render-scene.ts",
|
|
43
|
+
"geatsc-plugin-readback.mjs"
|
|
42
44
|
],
|
|
43
45
|
"publishConfig": {
|
|
44
46
|
"access": "public",
|
|
@@ -53,16 +55,16 @@
|
|
|
53
55
|
"test:package": "node --experimental-vm-modules test/package.test.mjs"
|
|
54
56
|
},
|
|
55
57
|
"dependencies": {
|
|
56
|
-
"@geastack/apple": "^0.2.
|
|
58
|
+
"@geastack/apple": "^0.2.15"
|
|
57
59
|
},
|
|
58
60
|
"peerDependencies": {
|
|
59
61
|
"three": "^0.185.0",
|
|
60
|
-
"@geastack/compiler": "^1.0.
|
|
62
|
+
"@geastack/compiler": "^1.0.29"
|
|
61
63
|
},
|
|
62
64
|
"devDependencies": {
|
|
63
|
-
"@geastack/compiler": "^1.0.
|
|
64
|
-
"@geastack/core": "^0.1.
|
|
65
|
-
"@geastack/engine": "^0.1.
|
|
65
|
+
"@geastack/compiler": "^1.0.29",
|
|
66
|
+
"@geastack/core": "^0.1.40",
|
|
67
|
+
"@geastack/engine": "^0.1.16",
|
|
66
68
|
"@types/three": "^0.185.0",
|
|
67
69
|
"three": "^0.185.0",
|
|
68
70
|
"troika-three-text": "^0.52.4",
|