@geastack/native-webgl-angle 0.1.16 → 0.1.18

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.
@@ -349,42 +349,86 @@ export function isUniformNumberArray( value ) {
349
349
 
350
350
  }
351
351
 
352
- /** @param {NativeUniformValue} value @return {value is Vector2[]} */
353
- function isVector2Array( value ) {
352
+ /**
353
+ * One element of a uniform array whose first element is the given kind. Read
354
+ * through \`Array.isArray\` and \`instanceof\` on the element itself rather than
355
+ * through the value narrowed to that array type: the value is stored as the
356
+ * uniform union, and claiming one array arm for it is an array-to-array
357
+ * conversion with no runtime form.
358
+ */
359
+
360
+ /** @param {NativeUniformValue} value @param {number} index @return {Vector2} */
361
+ function vector2ArrayElement( value, index ) {
362
+
363
+ \tif ( Array.isArray( value ) ) {
364
+
365
+ \t\tconst element = value[ index ];
366
+
367
+ \t\tif ( element instanceof Vector2 ) return element;
368
+
369
+ \t}
354
370
 
355
- \treturn Array.isArray( value ) && value.length > 0 && value[ 0 ] instanceof Vector2;
371
+ \tthrow new Error( 'THREE.UniformsUtils: a uniform array mixes Vector2 with other values.' );
356
372
 
357
373
  }
358
374
 
359
- /** @param {NativeUniformValue} value @return {value is Vector3[]} */
360
- function isVector3Array( value ) {
375
+ /** @param {NativeUniformValue} value @param {number} index @return {Vector3} */
376
+ function vector3ArrayElement( value, index ) {
377
+
378
+ \tif ( Array.isArray( value ) ) {
361
379
 
362
- \treturn Array.isArray( value ) && value.length > 0 && value[ 0 ] instanceof Vector3;
380
+ \t\tconst element = value[ index ];
381
+
382
+ \t\tif ( element instanceof Vector3 ) return element;
383
+
384
+ \t}
385
+
386
+ \tthrow new Error( 'THREE.UniformsUtils: a uniform array mixes Vector3 with other values.' );
363
387
 
364
388
  }
365
389
 
366
- /** @param {NativeUniformValue} value @return {value is Vector4[]} */
367
- function isVector4Array( value ) {
390
+ /** @param {NativeUniformValue} value @param {number} index @return {Vector4} */
391
+ function vector4ArrayElement( value, index ) {
392
+
393
+ \tif ( Array.isArray( value ) ) {
368
394
 
369
- \treturn Array.isArray( value ) && value.length > 0 && value[ 0 ] instanceof Vector4;
395
+ \t\tconst element = value[ index ];
396
+
397
+ \t\tif ( element instanceof Vector4 ) return element;
398
+
399
+ \t}
400
+
401
+ \tthrow new Error( 'THREE.UniformsUtils: a uniform array mixes Vector4 with other values.' );
370
402
 
371
403
  }
372
404
 
373
- /** @param {NativeUniformValue} value @return {value is Matrix4[]} */
374
- function isMatrix4Array( value ) {
405
+ /** @param {NativeUniformValue} value @param {number} index @return {Matrix4} */
406
+ function matrix4ArrayElement( value, index ) {
407
+
408
+ \tif ( Array.isArray( value ) ) {
409
+
410
+ \t\tconst element = value[ index ];
411
+
412
+ \t\tif ( element instanceof Matrix4 ) return element;
375
413
 
376
- \treturn Array.isArray( value ) && value.length > 0 && value[ 0 ] instanceof Matrix4;
414
+ \t}
415
+
416
+ \tthrow new Error( 'THREE.UniformsUtils: a uniform array mixes Matrix4 with other values.' );
377
417
 
378
418
  }
379
419
 
380
- /** @param {NativeUniformValue} value @return {value is Array<Texture|null>} */
381
- export function isUniformTextureArray( value ) {
420
+ /** @param {NativeUniformValue} value @param {number} index @return {Texture|null} */
421
+ function textureArrayElement( value, index ) {
382
422
 
383
- \tif ( ! Array.isArray( value ) || value.length === 0 ) return false;
423
+ \tif ( Array.isArray( value ) ) {
384
424
 
385
- \tconst first = value[ 0 ];
425
+ \t\tconst element = value[ index ];
386
426
 
387
- \treturn first === null || first instanceof Texture;
427
+ \t\tif ( element === null || element instanceof Texture ) return element;
428
+
429
+ \t}
430
+
431
+ \tthrow new Error( 'THREE.UniformsUtils: a uniform array mixes textures with other values.' );
388
432
 
389
433
  }
390
434
 
@@ -423,63 +467,70 @@ export function cloneUniformValue( value ) {
423
467
 
424
468
  \tif ( isUniformNumberArray( value ) ) return value.slice();
425
469
 
426
- \tif ( isVector2Array( value ) ) {
470
+ \tif ( Array.isArray( value ) && value.length > 0 ) {
427
471
 
428
- \t\t/** @type {Vector2[]} */
429
- \t\tconst cloned = [];
472
+ \t\tconst first = value[ 0 ];
473
+ \t\tconst length = value.length;
430
474
 
431
- \t\tfor ( let i = 0, l = value.length; i < l; i ++ ) cloned.push( value[ i ].clone() );
475
+ \t\tif ( first instanceof Vector2 ) {
432
476
 
433
- \t\treturn cloned;
477
+ \t\t\t/** @type {Vector2[]} */
478
+ \t\t\tconst cloned = [];
434
479
 
435
- \t}
480
+ \t\t\tfor ( let i = 0; i < length; i ++ ) cloned.push( vector2ArrayElement( value, i ).clone() );
481
+
482
+ \t\t\treturn cloned;
436
483
 
437
- \tif ( isVector3Array( value ) ) {
484
+ \t\t}
438
485
 
439
- \t\t/** @type {Vector3[]} */
440
- \t\tconst cloned = [];
486
+ \t\tif ( first instanceof Vector3 ) {
441
487
 
442
- \t\tfor ( let i = 0, l = value.length; i < l; i ++ ) cloned.push( value[ i ].clone() );
488
+ \t\t\t/** @type {Vector3[]} */
489
+ \t\t\tconst cloned = [];
443
490
 
444
- \t\treturn cloned;
491
+ \t\t\tfor ( let i = 0; i < length; i ++ ) cloned.push( vector3ArrayElement( value, i ).clone() );
445
492
 
446
- \t}
493
+ \t\t\treturn cloned;
447
494
 
448
- \tif ( isVector4Array( value ) ) {
495
+ \t\t}
449
496
 
450
- \t\t/** @type {Vector4[]} */
451
- \t\tconst cloned = [];
497
+ \t\tif ( first instanceof Vector4 ) {
452
498
 
453
- \t\tfor ( let i = 0, l = value.length; i < l; i ++ ) cloned.push( value[ i ].clone() );
499
+ \t\t\t/** @type {Vector4[]} */
500
+ \t\t\tconst cloned = [];
454
501
 
455
- \t\treturn cloned;
502
+ \t\t\tfor ( let i = 0; i < length; i ++ ) cloned.push( vector4ArrayElement( value, i ).clone() );
456
503
 
457
- \t}
504
+ \t\t\treturn cloned;
458
505
 
459
- \tif ( isMatrix4Array( value ) ) {
506
+ \t\t}
460
507
 
461
- \t\t/** @type {Matrix4[]} */
462
- \t\tconst cloned = [];
508
+ \t\tif ( first instanceof Matrix4 ) {
463
509
 
464
- \t\tfor ( let i = 0, l = value.length; i < l; i ++ ) cloned.push( value[ i ].clone() );
510
+ \t\t\t/** @type {Matrix4[]} */
511
+ \t\t\tconst cloned = [];
465
512
 
466
- \t\treturn cloned;
513
+ \t\t\tfor ( let i = 0; i < length; i ++ ) cloned.push( matrix4ArrayElement( value, i ).clone() );
467
514
 
468
- \t}
515
+ \t\t\treturn cloned;
516
+
517
+ \t\t}
469
518
 
470
- \tif ( isUniformTextureArray( value ) ) {
519
+ \t\tif ( first === null || first instanceof Texture ) {
471
520
 
472
- \t\t/** @type {Array<Texture|null>} */
473
- \t\tconst cloned = [];
521
+ \t\t\t/** @type {Array<Texture|null>} */
522
+ \t\t\tconst cloned = [];
474
523
 
475
- \t\tfor ( let i = 0, l = value.length; i < l; i ++ ) {
524
+ \t\t\tfor ( let i = 0; i < length; i ++ ) {
476
525
 
477
- \t\t\tconst texture = value[ i ];
478
- \t\t\tcloned.push( texture === null ? null : texture.clone() );
526
+ \t\t\t\tconst texture = textureArrayElement( value, i );
527
+ \t\t\t\tcloned.push( texture === null ? null : texture.clone() );
479
528
 
480
- \t\t}
529
+ \t\t\t}
481
530
 
482
- \t\treturn cloned;
531
+ \t\t\treturn cloned;
532
+
533
+ \t\t}
483
534
 
484
535
  \t}
485
536
 
@@ -856,8 +907,7 @@ function ${name}( gl, v, textures ) {
856
907
 
857
908
  \t}
858
909
 
859
- \tconst list = requireTextureArray( v );
860
- \tconst n = list.length;
910
+ \tconst n = requireTextureArrayLength( v );
861
911
 
862
912
  \tconst units = allocTexUnits( manager, n );
863
913
 
@@ -887,7 +937,7 @@ ${
887
937
  }
888
938
  \tfor ( let i = 0; i !== n; ++ i ) {
889
939
 
890
- \t\tconst texture = list[ i ];
940
+ \t\tconst texture = textureArrayElement( v, i );
891
941
  \t\tmanager.${setter}( texture === null ? ${shadowAware ? 'emptyTexture2D' : empty} : texture, units[ i ] );
892
942
 
893
943
  \t}
@@ -1033,7 +1083,7 @@ import { Matrix4 } from '../../math/Matrix4.js';
1033
1083
  import { Vector2 } from '../../math/Vector2.js';
1034
1084
  import { Vector3 } from '../../math/Vector3.js';
1035
1085
  import { Vector4 } from '../../math/Vector4.js';
1036
- import { isUniformNumberArray, isUniformTextureArray } from '../shaders/UniformsUtils.js';
1086
+ import { isUniformNumberArray } from '../shaders/UniformsUtils.js';
1037
1087
  import {
1038
1088
  ${nativeLightUniformClassNames.map((name) => `\t${name},`).join('\n')}
1039
1089
  } from '../shaders/UniformsLib.js';
@@ -1124,10 +1174,39 @@ function requireUintUniformArray( value ) {
1124
1174
 
1125
1175
  }
1126
1176
 
1127
- /** @param {NativeUniformValue} value @return {Array<Texture|null>} */
1128
- function requireTextureArray( value ) {
1177
+ /**
1178
+ * A sampler array value is read element by element, never returned as a
1179
+ * narrowed \`Array<Texture|null>\`: a call site can hand the setter a value whose
1180
+ * static carrier is another array arm (a \`number[]\` passed to \`setValue\` by
1181
+ * name), and claiming that array for the texture arm is an array-to-array
1182
+ * conversion with no runtime form. Validated up front, as before, so a value
1183
+ * that is not a texture array throws before any texture unit is allocated.
1184
+ * @param {NativeUniformValue} value @return {number}
1185
+ */
1186
+ function requireTextureArrayLength( value ) {
1187
+
1188
+ \tif ( Array.isArray( value ) && value.length > 0 ) {
1189
+
1190
+ \t\tconst first = value[ 0 ];
1191
+
1192
+ \t\tif ( first === null || first instanceof Texture ) return value.length;
1193
+
1194
+ \t}
1195
+
1196
+ \tthrow new Error( 'THREE.WebGLUniforms: sampler array uniform value must be an array of textures.' );
1197
+
1198
+ }
1199
+
1200
+ /** @param {NativeUniformValue} value @param {number} index @return {Texture|null} */
1201
+ function textureArrayElement( value, index ) {
1202
+
1203
+ \tif ( Array.isArray( value ) ) {
1129
1204
 
1130
- \tif ( isUniformTextureArray( value ) ) return value;
1205
+ \t\tconst element = value[ index ];
1206
+
1207
+ \t\tif ( element === null || element instanceof Texture ) return element;
1208
+
1209
+ \t}
1131
1210
 
1132
1211
  \tthrow new Error( 'THREE.WebGLUniforms: sampler array uniform value must be an array of textures.' );
1133
1212
 
@@ -16,6 +16,9 @@ export const nativeUploadFunctions = [
16
16
  ['threeWebGLTexImage3D', 'gea_three_webgl_tex_image_3d_native', ['target', 'level', 'internalFormat', 'width', 'height', 'depth', 'format', 'type'], 'gea_three_webgl_tex_image_3d_bytes', ['target', 'level', 'internalFormat', 'width', 'height', 'depth', 'format', 'type'], textureElementKind],
17
17
  ['threeWebGLTexSubImage3D', 'gea_three_webgl_tex_sub_image_3d_native', ['target', 'level', 'xoffset', 'yoffset', 'zoffset', 'width', 'height', 'depth', 'format', 'type'], 'gea_three_webgl_tex_sub_image_3d_bytes', ['target', 'level', 'xoffset', 'yoffset', 'zoffset', 'width', 'height', 'depth', 'format', 'type'], textureElementKind],
18
18
  ['threeWebGLTexSubImage2D', 'gea_three_webgl_tex_sub_image_2d_native', ['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format', 'type'], 'gea_three_webgl_tex_sub_image_2d_bytes', ['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format', 'type'], textureElementKind],
19
+ // Compressed blocks are opaque bytes.
20
+ ['threeWebGLCompressedTexImage2D', 'gea_three_webgl_compressed_tex_image_2d_native', ['target', 'level', 'internalFormat', 'width', 'height'], 'gea_three_webgl_compressed_tex_image_2d_bytes', ['target', 'level', 'internalFormat', 'width', 'height'], '4'],
21
+ ['threeWebGLCompressedTexSubImage2D', 'gea_three_webgl_compressed_tex_sub_image_2d_native', ['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format'], 'gea_three_webgl_compressed_tex_sub_image_2d_bytes', ['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format'], '4'],
19
22
  ].map(([name, binding, parameters, raw, rawParameters, kind, range]) => {
20
23
  const declaration = `extern "C" void ${raw}(${rawParameters.map(p => `double ${p}`).join(', ')}, const void* bytes, double byteLength);
21
24
  template <typename Source> inline void ${binding}(${parameters.map(p => `double ${p}`).join(', ')}, const Source& values${range ? ', double sourceOffset, double length' : ''}) {
package/geatsc-plugin.mjs CHANGED
@@ -138,6 +138,18 @@ inline double gea_three_resource_read_native(std::string name, const gea::Ref<ge
138
138
  ['threeWebGLTimerEnd','gea_three_webgl_timer_end','void','extern "C" void gea_three_webgl_timer_end();'],
139
139
  ['threeWebGLTimerResult','gea_three_webgl_timer_result','double','extern "C" double gea_three_webgl_timer_result(double);'],
140
140
  ['threeWebGLRenderbufferStorageMultisample','gea_three_webgl_renderbuffer_storage_multisample','void','extern "C" void gea_three_webgl_renderbuffer_storage_multisample(double,double,double,double,double);'],
141
+ [
142
+ "threeWebGLPushDebugGroup",
143
+ "gea_three_webgl_push_debug_group",
144
+ "void",
145
+ 'extern "C" void gea_three_webgl_push_debug_group(std::string label);',
146
+ ],
147
+ [
148
+ "threeWebGLPopDebugGroup",
149
+ "gea_three_webgl_pop_debug_group",
150
+ "void",
151
+ 'extern "C" void gea_three_webgl_pop_debug_group();',
152
+ ],
141
153
  [
142
154
  "threeNativeProfilePhase",
143
155
  "gea_three_native_profile_phase",
@@ -666,7 +678,7 @@ inline double gea_three_resource_read_native(std::string name, const gea::Ref<ge
666
678
  "threeWebGLDrawBuffers",
667
679
  "gea_three_webgl_draw_buffers",
668
680
  "void",
669
- 'extern "C" void gea_three_webgl_draw_buffers(double attachment);',
681
+ 'extern "C" void gea_three_webgl_draw_buffers(double count, double a0, double a1, double a2, double a3, double a4, double a5, double a6, double a7);',
670
682
  ],
671
683
 
672
684
  [
@@ -2123,8 +2135,29 @@ const transformSource = ({ fileName, text }) => {
2123
2135
  if (normalized.endsWith("/three/src/renderers/WebGLRenderer.js")) {
2124
2136
  transformed =
2125
2137
  // Forward slashes: a Windows path's backslashes would be escapes in this literal.
2126
- `import { nativeProfilePhase } from '${fileURLToPath(new URL("./src/nativeWebGLHost.ts", import.meta.url)).replaceAll("\\", "/")}';\n` +
2138
+ `import { nativeProfilePhase, nativePushDebugGroup, nativePopDebugGroup } from '${fileURLToPath(new URL("./src/nativeWebGLHost.ts", import.meta.url)).replaceAll("\\", "/")}';\n` +
2127
2139
  transformed;
2140
+ transformed = replaceOne(
2141
+ transformed,
2142
+ "\t\t\tif ( _isContextLost === true ) return;\n",
2143
+ "\t\t\tif ( _isContextLost === true ) return;\n\n\t\t\tnativePushDebugGroup( scene.name !== '' ? scene.name : ( camera.name !== '' ? camera.name : scene.type ) );\n",
2144
+ fileName,
2145
+ "WebGLRenderer render debug group begin",
2146
+ );
2147
+ transformed = replaceOne(
2148
+ transformed,
2149
+ "\t\t\t\t_nodesHandler.renderEnd();\n\n\t\t\t}\n\n\t\t};",
2150
+ "\t\t\t\t_nodesHandler.renderEnd();\n\n\t\t\t}\n\n\t\t\tnativePopDebugGroup();\n\n\t\t};",
2151
+ fileName,
2152
+ "WebGLRenderer render debug group end",
2153
+ );
2154
+ transformed = replaceOne(
2155
+ transformed,
2156
+ "\t\t\tif ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );\n\t\t\tif ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera );\n\t\t\tif ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );\n",
2157
+ "\t\t\tif ( opaqueObjects.length > 0 ) {\n\n\t\t\t\tnativePushDebugGroup( 'opaque' );\n\t\t\t\trenderObjects( opaqueObjects, scene, camera );\n\t\t\t\tnativePopDebugGroup();\n\n\t\t\t}\n\n\t\t\tif ( transmissiveObjects.length > 0 ) {\n\n\t\t\t\tnativePushDebugGroup( 'transmissive' );\n\t\t\t\trenderObjects( transmissiveObjects, scene, camera );\n\t\t\t\tnativePopDebugGroup();\n\n\t\t\t}\n\n\t\t\tif ( transparentObjects.length > 0 ) {\n\n\t\t\t\tnativePushDebugGroup( 'transparent' );\n\t\t\t\trenderObjects( transparentObjects, scene, camera );\n\t\t\t\tnativePopDebugGroup();\n\n\t\t\t}\n",
2158
+ fileName,
2159
+ "WebGLRenderer render list debug groups",
2160
+ );
2128
2161
  transformed = replaceOne(
2129
2162
  transformed,
2130
2163
  "if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();",
@@ -6426,6 +6459,23 @@ ${wiringText.replace(/\t\t\t\t/g, "\t\t\t\t")}
6426
6459
  );
6427
6460
  }
6428
6461
  if (normalized.endsWith("/three/src/renderers/webgl/WebGLShadowMap.js")) {
6462
+ transformed =
6463
+ `import { nativePushDebugGroup, nativePopDebugGroup } from '${fileURLToPath(new URL("./src/nativeWebGLHost.ts", import.meta.url)).replaceAll("\\", "/")}';\n` +
6464
+ transformed;
6465
+ transformed = replaceOne(
6466
+ transformed,
6467
+ "\t\tif ( lights.length === 0 ) return;\n",
6468
+ "\t\tif ( lights.length === 0 ) return;\n\n\t\tnativePushDebugGroup( 'shadow map' );\n",
6469
+ fileName,
6470
+ "WebGLShadowMap debug group begin",
6471
+ );
6472
+ transformed = replaceOne(
6473
+ transformed,
6474
+ "\t\tscope.needsUpdate = false;\n\n\t\trenderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );\n",
6475
+ "\t\tscope.needsUpdate = false;\n\n\t\trenderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );\n\n\t\tnativePopDebugGroup();\n",
6476
+ fileName,
6477
+ "WebGLShadowMap debug group end",
6478
+ );
6429
6479
  // An app that replaces `shadowMap.render` (the browser's cached sun shadow)
6430
6480
  // cannot do so natively: the field holds a `this`-bound function expression
6431
6481
  // no app function converts to. This hook is an ordinary function-typed
@@ -433,6 +433,8 @@ using PFNGLTEXSUBIMAGE3DPROC = void (*)(GLenum, GLint, GLint, GLint, GLint, GLsi
433
433
  using PFNGLTEXSTORAGE3DPROC = void (*)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei);
434
434
  using PFNGLFRAMEBUFFERTEXTURELAYERPROC = void (*)(GLenum, GLenum, GLuint, GLint, GLint);
435
435
  using PFNGLTEXSTORAGE2DPROC = void (*)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
436
+ using PFNGLCOMPRESSEDTEXIMAGE2DPROC = void (*)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void *);
437
+ using PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC = void (*)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *);
436
438
  using PFNGLUNIFORM1FPROC = void (*)(GLint, GLfloat);
437
439
  using PFNGLUNIFORM1FVPROC = void (*)(GLint, GLsizei, const GLfloat *);
438
440
  using PFNGLUNIFORM1IPROC = void (*)(GLint, GLint);
@@ -503,6 +505,8 @@ struct AngleWebGLState {
503
505
  PFNGLBINDBUFFERRANGEPROC glBindBufferRange = nullptr;
504
506
  PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = nullptr;
505
507
  PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = nullptr;
508
+ void (*glPushGroupMarkerEXT)(GLsizei, const GLchar *) = nullptr;
509
+ void (*glPopGroupMarkerEXT)() = nullptr;
506
510
  PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
507
511
  PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr;
508
512
  PFNGLBINDTEXTUREPROC glBindTexture = nullptr;
@@ -587,6 +591,9 @@ struct AngleWebGLState {
587
591
  PFNGLTEXPARAMETERIPROC glTexParameteri = nullptr;
588
592
  PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D = nullptr;
589
593
  PFNGLTEXSTORAGE2DPROC glTexStorage2D = nullptr;
594
+ // Compressed uploads are optional too: a GLES without them drops the call.
595
+ PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D = nullptr;
596
+ PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D = nullptr;
590
597
  // Array/3D entry points are optional: a GLES without them still starts,
591
598
  // and uploads to those targets report GL_INVALID_OPERATION in the log.
592
599
  PFNGLTEXIMAGE3DPROC glTexImage3D = nullptr;
@@ -1038,10 +1045,15 @@ static bool loadGlSymbols() {
1038
1045
  LOAD_GL(glActiveTexture, PFNGLACTIVETEXTUREPROC)
1039
1046
  LOAD_GL(glAttachShader, PFNGLATTACHSHADERPROC)
1040
1047
  LOAD_GL(glBindBuffer, PFNGLBINDBUFFERPROC)
1041
- LOAD_GL(glBindBufferBase, PFNGLBINDBUFFERBASEPROC)
1042
- LOAD_GL(glBindBufferRange, PFNGLBINDBUFFERRANGEPROC)
1043
- LOAD_GL(glGetUniformBlockIndex, PFNGLGETUNIFORMBLOCKINDEXPROC)
1044
- LOAD_GL(glUniformBlockBinding, PFNGLUNIFORMBLOCKBINDINGPROC)
1048
+ // Uniform-buffer entry points are optional like the array/3D ones: a GLES
1049
+ // without them (threejs-rendozer exports none) still starts, and only a
1050
+ // program that uses uniform groups loses them, with a log line per call.
1051
+ gWebGL.glBindBufferBase = loadGl<PFNGLBINDBUFFERBASEPROC>("glBindBufferBase");
1052
+ gWebGL.glBindBufferRange = loadGl<PFNGLBINDBUFFERRANGEPROC>("glBindBufferRange");
1053
+ gWebGL.glGetUniformBlockIndex = loadGl<PFNGLGETUNIFORMBLOCKINDEXPROC>("glGetUniformBlockIndex");
1054
+ gWebGL.glUniformBlockBinding = loadGl<PFNGLUNIFORMBLOCKBINDINGPROC>("glUniformBlockBinding");
1055
+ gWebGL.glPushGroupMarkerEXT = loadGl<decltype(gWebGL.glPushGroupMarkerEXT)>("glPushGroupMarkerEXT");
1056
+ gWebGL.glPopGroupMarkerEXT = loadGl<decltype(gWebGL.glPopGroupMarkerEXT)>("glPopGroupMarkerEXT");
1045
1057
  LOAD_GL(glBindFramebuffer, PFNGLBINDFRAMEBUFFERPROC)
1046
1058
  LOAD_GL(glBindRenderbuffer, PFNGLBINDRENDERBUFFERPROC)
1047
1059
  LOAD_GL(glBindTexture, PFNGLBINDTEXTUREPROC)
@@ -1129,6 +1141,8 @@ static bool loadGlSymbols() {
1129
1141
  LOAD_GL(glTexParameteri, PFNGLTEXPARAMETERIPROC)
1130
1142
  LOAD_GL(glTexSubImage2D, PFNGLTEXSUBIMAGE2DPROC)
1131
1143
  LOAD_GL(glTexStorage2D, PFNGLTEXSTORAGE2DPROC)
1144
+ gWebGL.glCompressedTexImage2D = loadGl<PFNGLCOMPRESSEDTEXIMAGE2DPROC>("glCompressedTexImage2D");
1145
+ gWebGL.glCompressedTexSubImage2D = loadGl<PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC>("glCompressedTexSubImage2D");
1132
1146
  gWebGL.glTexImage3D = loadGl<PFNGLTEXIMAGE3DPROC>("glTexImage3D");
1133
1147
  gWebGL.glTexSubImage3D = loadGl<PFNGLTEXSUBIMAGE3DPROC>("glTexSubImage3D");
1134
1148
  gWebGL.glTexStorage3D = loadGl<PFNGLTEXSTORAGE3DPROC>("glTexStorage3D");
@@ -2313,8 +2327,11 @@ extern "C" void gea_three_webgl_renderbuffer_storage(double target, double inter
2313
2327
  geaTrapCheck("gea_three_webgl_renderbuffer_storage"); GEA_WEBGL_VOID("renderbufferStorage"); gWebGL.glRenderbufferStorage(asGLenum(target), asGLenum(internalFormat), asGLsizei(width), asGLsizei(height)); }
2314
2328
  extern "C" void gea_three_webgl_framebuffer_renderbuffer(double target, double attachment, double renderbuffertarget, double renderbuffer) {
2315
2329
  geaTrapCheck("gea_three_webgl_framebuffer_renderbuffer"); GEA_WEBGL_VOID("framebufferRenderbuffer"); gWebGL.glFramebufferRenderbuffer(asGLenum(target), asGLenum(attachment), asGLenum(renderbuffertarget), asGLuint(renderbuffer)); }
2316
- extern "C" void gea_three_webgl_draw_buffers(double attachment) {
2317
- geaTrapCheck("gea_three_webgl_draw_buffers"); GEA_WEBGL_VOID("drawBuffers"); const GLenum glAttachment = asGLenum(attachment); gWebGL.glDrawBuffers(1, &glAttachment); }
2330
+ extern "C" void gea_three_webgl_draw_buffers(double count, double a0, double a1, double a2, double a3, double a4, double a5, double a6, double a7) {
2331
+ geaTrapCheck("gea_three_webgl_draw_buffers"); GEA_WEBGL_VOID("drawBuffers");
2332
+ const GLenum attachments[8] = {asGLenum(a0), asGLenum(a1), asGLenum(a2), asGLenum(a3), asGLenum(a4), asGLenum(a5), asGLenum(a6), asGLenum(a7)};
2333
+ const GLsizei n = std::max<GLsizei>(0, std::min<GLsizei>(asGLsizei(count), 8));
2334
+ gWebGL.glDrawBuffers(n, attachments); }
2318
2335
 
2319
2336
  extern "C" void gea_three_webgl_clear_color(double r, double g, double b, double a) {
2320
2337
  geaTrapCheck("gea_three_webgl_clear_color"); GEA_WEBGL_VOID("clearColor");
@@ -2414,23 +2431,35 @@ extern "C" void gea_three_webgl_draw_arrays(double mode, double first, double co
2414
2431
  extern "C" void gea_three_webgl_vertex_attrib_divisor(double index, double divisor) {
2415
2432
  geaTrapCheck("gea_three_webgl_vertex_attrib_divisor"); GEA_WEBGL_VOID("vertexAttribDivisor");
2416
2433
  gWebGL.glVertexAttribDivisor(asGLuint(index), asGLuint(divisor)); }
2434
+ static bool requireGl(const void *fn, const char *name);
2417
2435
  // Indexed binds also set the target's generic binding. The host shadows only the
2418
2436
  // ARRAY_BUFFER and COPY_READ/WRITE bindings (bindNativeBuffer), and the uniform
2419
2437
  // staging path queries UNIFORM_BUFFER_BINDING instead of shadowing it, so neither
2420
2438
  // call needs to update a shadow.
2421
2439
  extern "C" void gea_three_webgl_bind_buffer_base(double target, double index, double buffer) {
2422
2440
  geaTrapCheck("gea_three_webgl_bind_buffer_base"); GEA_WEBGL_VOID("bindBufferBase");
2441
+ if (!requireGl(reinterpret_cast<const void *>(gWebGL.glBindBufferBase), "glBindBufferBase")) return;
2423
2442
  gWebGL.glBindBufferBase(asGLenum(target), asGLuint(index), asGLuint(buffer)); }
2424
2443
  extern "C" void gea_three_webgl_bind_buffer_range(double target, double index, double buffer, double offset, double size) {
2425
2444
  geaTrapCheck("gea_three_webgl_bind_buffer_range"); GEA_WEBGL_VOID("bindBufferRange");
2445
+ if (!requireGl(reinterpret_cast<const void *>(gWebGL.glBindBufferRange), "glBindBufferRange")) return;
2426
2446
  gWebGL.glBindBufferRange(asGLenum(target), asGLuint(index), asGLuint(buffer),
2427
2447
  static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size)); }
2428
2448
  extern "C" double gea_three_webgl_get_uniform_block_index(double program, std::string name) {
2429
2449
  geaTrapCheck("gea_three_webgl_get_uniform_block_index"); GEA_WEBGL_DOUBLE("getUniformBlockIndex");
2450
+ // GL_INVALID_INDEX: the block is reported as absent.
2451
+ if (!requireGl(reinterpret_cast<const void *>(gWebGL.glGetUniformBlockIndex), "glGetUniformBlockIndex")) return 4294967295.0;
2430
2452
  return gWebGL.glGetUniformBlockIndex(asGLuint(program), name.c_str()); }
2431
2453
  extern "C" void gea_three_webgl_uniform_block_binding(double program, double blockIndex, double binding) {
2432
2454
  geaTrapCheck("gea_three_webgl_uniform_block_binding"); GEA_WEBGL_VOID("uniformBlockBinding");
2455
+ if (!requireGl(reinterpret_cast<const void *>(gWebGL.glUniformBlockBinding), "glUniformBlockBinding")) return;
2433
2456
  gWebGL.glUniformBlockBinding(asGLuint(program), asGLuint(blockIndex), asGLuint(binding)); }
2457
+ extern "C" void gea_three_webgl_push_debug_group(std::string label) {
2458
+ geaTrapCheck("gea_three_webgl_push_debug_group"); GEA_WEBGL_VOID("pushDebugGroup");
2459
+ if (gWebGL.glPushGroupMarkerEXT) gWebGL.glPushGroupMarkerEXT(static_cast<GLsizei>(label.size()), label.c_str()); }
2460
+ extern "C" void gea_three_webgl_pop_debug_group() {
2461
+ geaTrapCheck("gea_three_webgl_pop_debug_group"); GEA_WEBGL_VOID("popDebugGroup");
2462
+ if (gWebGL.glPopGroupMarkerEXT) gWebGL.glPopGroupMarkerEXT(); }
2434
2463
  extern "C" void gea_three_webgl_draw_elements_instanced(double mode, double count, double type, double offset, double instanceCount) {
2435
2464
  geaTrapCheck("gea_three_webgl_draw_elements_instanced"); GEA_WEBGL_VOID("drawElementsInstanced");
2436
2465
  gWebGL.glDrawElementsInstanced(asGLenum(mode), asGLsizei(count), asGLenum(type),
@@ -2679,6 +2708,18 @@ extern "C" void gea_three_webgl_tex_sub_image_3d_bytes(double target, double lev
2679
2708
  gWebGL.glTexSubImage3D(asGLenum(target), asGLint(level), asGLint(xoffset), asGLint(yoffset), asGLint(zoffset), asGLsizei(width), asGLsizei(height), asGLsizei(depth), asGLenum(format), asGLenum(type), bytes);
2680
2709
  }
2681
2710
 
2711
+ extern "C" void gea_three_webgl_compressed_tex_image_2d_bytes(double target, double level, double internalFormat, double width, double height, const void* bytes, double byteLength) {
2712
+ GEA_WEBGL_VOID("compressedTexImage2DBytes");
2713
+ if (!requireGl(reinterpret_cast<const void *>(gWebGL.glCompressedTexImage2D), "glCompressedTexImage2D")) return;
2714
+ gWebGL.glCompressedTexImage2D(asGLenum(target), asGLint(level), asGLenum(internalFormat), asGLsizei(width), asGLsizei(height), 0, asGLsizei(byteLength), bytes);
2715
+ }
2716
+
2717
+ extern "C" void gea_three_webgl_compressed_tex_sub_image_2d_bytes(double target, double level, double xoffset, double yoffset, double width, double height, double format, const void* bytes, double byteLength) {
2718
+ GEA_WEBGL_VOID("compressedTexSubImage2DBytes");
2719
+ if (!requireGl(reinterpret_cast<const void *>(gWebGL.glCompressedTexSubImage2D), "glCompressedTexSubImage2D")) return;
2720
+ gWebGL.glCompressedTexSubImage2D(asGLenum(target), asGLint(level), asGLint(xoffset), asGLint(yoffset), asGLsizei(width), asGLsizei(height), asGLenum(format), asGLsizei(byteLength), bytes);
2721
+ }
2722
+
2682
2723
  extern "C" void gea_three_webgl_tex_storage_3d(double target, double levels, double internalFormat, double width, double height, double depth) {
2683
2724
  GEA_WEBGL_VOID("texStorage3D");
2684
2725
  if (!requireGl(reinterpret_cast<const void *>(gWebGL.glTexStorage3D), "glTexStorage3D")) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geastack/native-webgl-angle",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Typed native WebGL compatibility layer backed by ANGLE/Metal",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -277,6 +277,10 @@ declare function threeWebGLTexImage2D(target: number, level: number, internalFor
277
277
  /** @gea-host-inert Reads its arguments, writes GL state only; never calls back into script. */
278
278
  declare function threeWebGLTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, type: number, values: BufferSourceLike): void
279
279
  /** @gea-host-inert Reads its arguments, writes GL state only; never calls back into script. */
280
+ declare function threeWebGLCompressedTexImage2D(target: number, level: number, internalFormat: number, width: number, height: number, values: BufferSourceLike): void
281
+ /** @gea-host-inert Reads its arguments, writes GL state only; never calls back into script. */
282
+ declare function threeWebGLCompressedTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, values: BufferSourceLike): void
283
+ /** @gea-host-inert Reads its arguments, writes GL state only; never calls back into script. */
280
284
  declare function threeWebGLTexStorage2D(target: number, levels: number, internalFormat: number, width: number, height: number): void
281
285
  /** @gea-host-inert Reads its arguments, writes GL state only; never calls back into script. */
282
286
  declare function threeWebGLTexImage3D(target: number, level: number, internalFormat: number, width: number, height: number, depth: number, format: number, type: number, values: BufferSourceLike): void
@@ -943,7 +947,10 @@ export class NativeWebGL2RenderingContext {
943
947
  }
944
948
 
945
949
  isContextLost(): boolean { return false }
946
- getSupportedExtensions(): string[] { return ['EXT_texture_filter_anisotropic', 'OES_texture_float_linear', 'EXT_color_buffer_float'] }
950
+ getSupportedExtensions(): string[] {
951
+ return ['EXT_texture_filter_anisotropic', 'OES_texture_float_linear', 'EXT_color_buffer_float', 'WEBGL_compressed_texture_s3tc',
952
+ 'WEBGL_compressed_texture_s3tc_srgb', 'EXT_texture_compression_rgtc', 'EXT_texture_compression_bptc']
953
+ }
947
954
 
948
955
  getExtension(name: string): WebGLExtension | null {
949
956
  // One shared shape for every supported name -- see `WebGLExtension`. The
@@ -955,7 +962,11 @@ export class NativeWebGL2RenderingContext {
955
962
  name === 'WEBGL_debug_renderer_info' ||
956
963
  name === 'OES_texture_float_linear' ||
957
964
  name === 'EXT_color_buffer_float' ||
958
- name === 'EXT_color_buffer_half_float'
965
+ name === 'EXT_color_buffer_half_float' ||
966
+ name === 'WEBGL_compressed_texture_s3tc' ||
967
+ name === 'WEBGL_compressed_texture_s3tc_srgb' ||
968
+ name === 'EXT_texture_compression_rgtc' ||
969
+ name === 'EXT_texture_compression_bptc'
959
970
  ) {
960
971
  return new WebGLExtension()
961
972
  }
@@ -1154,8 +1165,12 @@ export class NativeWebGL2RenderingContext {
1154
1165
  texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, type: number, pixels: BufferSourceLike): void {
1155
1166
  threeWebGLTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels)
1156
1167
  }
1157
- compressedTexImage2D(_target: number, _level: number, _internalFormat: number, _width: number, _height: number, _border: number, _data: BufferSourceLike): void {}
1158
- compressedTexSubImage2D(_target: number, _level: number, _xoffset: number, _yoffset: number, _width: number, _height: number, _format: number, _data: BufferSourceLike): void {}
1168
+ compressedTexImage2D(target: number, level: number, internalFormat: number, width: number, height: number, _border: number, data: BufferSourceLike): void {
1169
+ threeWebGLCompressedTexImage2D(target, level, internalFormat, width, height, data)
1170
+ }
1171
+ compressedTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, data: BufferSourceLike): void {
1172
+ threeWebGLCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, data)
1173
+ }
1159
1174
  compressedTexImage3D(_target: number, _level: number, _internalFormat: number, _width: number, _height: number, _depth: number, _border: number, _data: BufferSourceLike): void {}
1160
1175
  compressedTexSubImage3D(_target: number, _level: number, _xoffset: number, _yoffset: number, _zoffset: number, _width: number, _height: number, _depth: number, _format: number, _data: BufferSourceLike): void {}
1161
1176
  texStorage2D(target: number, levels: number, internalFormat: number, width: number, height: number): void {
@@ -1198,7 +1213,12 @@ export class NativeWebGL2RenderingContext {
1198
1213
  framebufferTextureLayer(target: number, attachment: number, texture: NativeHandle | null, level: number, layer: number): void {
1199
1214
  threeWebGLFramebufferTextureLayer(target, attachment, nullableNativeHandle(texture), level, layer)
1200
1215
  }
1201
- drawBuffers(buffers: number[]): void { nativeWebGLDrawBuffers(buffers[0] ?? this.COLOR_ATTACHMENT0) }
1216
+ /** Every listed buffer reaches GL (up to 8, the MRT limit the host passes), so multiple render targets write all their attachments. */
1217
+ drawBuffers(buffers: number[]): void {
1218
+ const count = Math.min(buffers.length, 8)
1219
+ const at = (index: number): number => index < count ? buffers[index] : this.NONE
1220
+ nativeWebGLDrawBuffers(count, at(0), at(1), at(2), at(3), at(4), at(5), at(6), at(7))
1221
+ }
1202
1222
 
1203
1223
  clearColor(r: number, g: number, b: number, a: number): void { nativeWebGLClearColor(r, g, b, a) }
1204
1224
  clear(mask: number): void { nativeWebGLClear(mask) }
@@ -148,7 +148,7 @@ export function nativeWebGLBindRenderbuffer(target: number, renderbuffer: number
148
148
  export function nativeWebGLDeleteRenderbuffer(renderbuffer: number): void { threeWebGLDeleteRenderbuffer(renderbuffer) }
149
149
  export function nativeWebGLRenderbufferStorage(target: number, internalFormat: number, width: number, height: number): void { threeWebGLRenderbufferStorage(target, internalFormat, width, height) }
150
150
  export function nativeWebGLFramebufferRenderbuffer(target: number, attachment: number, renderbuffertarget: number, renderbuffer: number): void { threeWebGLFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) }
151
- export function nativeWebGLDrawBuffers(attachment: number): void { threeWebGLDrawBuffers(attachment) }
151
+ export function nativeWebGLDrawBuffers(count: number, a0: number, a1: number, a2: number, a3: number, a4: number, a5: number, a6: number, a7: number): void { threeWebGLDrawBuffers(count, a0, a1, a2, a3, a4, a5, a6, a7) }
152
152
 
153
153
  export function nativeWebGLClearColor(r: number, g: number, b: number, a: number): void { threeWebGLClearColor(r, g, b, a) }
154
154
  export function nativeWebGLClear(mask: number): void { threeWebGLClear(mask) }
@@ -303,7 +303,7 @@ declare function threeWebGLRenderbufferStorage(target: number, internalFormat: n
303
303
  /** @gea-host-inert Native state only; retains no script references and invokes no script. */
304
304
  declare function threeWebGLFramebufferRenderbuffer(target: number, attachment: number, renderbuffertarget: number, renderbuffer: number): void
305
305
  /** @gea-host-inert Native state only; retains no script references and invokes no script. */
306
- declare function threeWebGLDrawBuffers(attachment: number): void
306
+ declare function threeWebGLDrawBuffers(count: number, a0: number, a1: number, a2: number, a3: number, a4: number, a5: number, a6: number, a7: number): void
307
307
  /** @gea-host-inert Copies scalar arguments into GL state; retains no script references and invokes no script. */
308
308
  declare function threeWebGLClearColor(r: number, g: number, b: number, a: number): void
309
309
  /** @gea-host-inert Native state only; retains no script references and invokes no script. */
@@ -366,6 +366,13 @@ declare function threeWebGLGetError(): number
366
366
  declare function threeNativeProfilePhase(phase: number): void
367
367
  export function nativeProfilePhase(phase: number): void { threeNativeProfilePhase(phase) }
368
368
 
369
+ export function nativePushDebugGroup(label: string): void { threeWebGLPushDebugGroup(label) }
370
+ /** @gea-host-inert Native state only; retains no script references and invokes no script. */
371
+ declare function threeWebGLPushDebugGroup(label: string): void
372
+ export function nativePopDebugGroup(): void { threeWebGLPopDebugGroup() }
373
+ /** @gea-host-inert Native state only; retains no script references and invokes no script. */
374
+ declare function threeWebGLPopDebugGroup(): void
375
+
369
376
  export function nativeWebGLBindBufferBase(target: number, index: number, buffer: number): void { threeWebGLBindBufferBase(target, index, buffer) }
370
377
  /** @gea-host-inert Native state only; retains no script references and invokes no script. */
371
378
  declare function threeWebGLBindBufferBase(target: number, index: number, buffer: number): void