@codexo/exojs 0.6.2 → 0.6.4

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +585 -499
  2. package/README.md +156 -156
  3. package/dist/esm/core/Application.d.ts +8 -0
  4. package/dist/esm/core/Application.js +17 -0
  5. package/dist/esm/core/Application.js.map +1 -1
  6. package/dist/esm/core/capabilities.d.ts +38 -0
  7. package/dist/esm/core/capabilities.js +198 -0
  8. package/dist/esm/core/capabilities.js.map +1 -0
  9. package/dist/esm/core/index.d.ts +1 -0
  10. package/dist/esm/index.js +1 -0
  11. package/dist/esm/index.js.map +1 -1
  12. package/dist/esm/rendering/webgl2/glsl/mask-compose.frag.js +1 -1
  13. package/dist/esm/rendering/webgl2/glsl/mask-compose.vert.js +1 -1
  14. package/dist/esm/rendering/webgl2/glsl/particle.frag.js +1 -1
  15. package/dist/esm/rendering/webgl2/glsl/primitive.frag.js +1 -1
  16. package/dist/esm/rendering/webgl2/glsl/primitive.vert.js +1 -1
  17. package/dist/esm/rendering/webgl2/glsl/sprite.frag.js +1 -1
  18. package/dist/esm/rendering/webgpu/WebGpuBackend.js +41 -41
  19. package/dist/esm/rendering/webgpu/WebGpuBackend.js.map +1 -1
  20. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js +44 -44
  21. package/dist/esm/rendering/webgpu/WebGpuMaskCompositor.js.map +1 -1
  22. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js +65 -65
  23. package/dist/esm/rendering/webgpu/WebGpuParticleRenderer.js.map +1 -1
  24. package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.js +25 -25
  25. package/dist/esm/rendering/webgpu/WebGpuPrimitiveRenderer.js.map +1 -1
  26. package/dist/esm/vendor/webgl-debug.js +1156 -1156
  27. package/dist/esm/vendor/webgl-debug.js.map +1 -1
  28. package/dist/exo.esm.js +1550 -1338
  29. package/dist/exo.esm.js.map +1 -1
  30. package/package.json +105 -105
package/dist/exo.esm.js CHANGED
@@ -372,6 +372,202 @@ const canvasSourceToDataUrl = (source) => {
372
372
  return canvasElement.toDataURL();
373
373
  };
374
374
 
375
+ /// <reference types="@webgpu/types" />
376
+ // Browser-environment feature detection. Construction is private; the
377
+ // only public entry is `Capabilities.ready`, a lazy-cached `Promise<Capabilities>`
378
+ // that fires the (mostly) async probes on first access and returns the
379
+ // same Promise for every subsequent call. Once it resolves, the returned
380
+ // instance is frozen — every property is read once and never mutates.
381
+ //
382
+ // Synchronous callsites should keep the resolved instance in scope (e.g.,
383
+ // `app.capabilities` after `await app.start(...)`); there is no global
384
+ // sync mirror, by design.
385
+ const hasWindow = typeof window !== 'undefined';
386
+ const hasDocument = typeof document !== 'undefined';
387
+ const hasNavigator = typeof navigator !== 'undefined';
388
+ class Capabilities {
389
+ static _readyPromise = null;
390
+ /**
391
+ * Lazy-cached Promise that resolves to a frozen Capabilities instance.
392
+ *
393
+ * The first read kicks off the async probes (currently just the WebGPU
394
+ * adapter request); every subsequent read returns the same Promise.
395
+ * Concurrent callers share the in-flight detection — no double work.
396
+ *
397
+ * Early-warmup pattern for callers who want to overlap detection with
398
+ * other startup work:
399
+ *
400
+ * ```ts
401
+ * void Capabilities.ready; // fire-and-forget; starts probes now
402
+ * // ... unrelated bootstrap ...
403
+ * const caps = await Capabilities.ready; // typically already resolved
404
+ * ```
405
+ */
406
+ static get ready() {
407
+ if (Capabilities._readyPromise === null) {
408
+ Capabilities._readyPromise = Capabilities._detect();
409
+ }
410
+ return Capabilities._readyPromise;
411
+ }
412
+ webgl2;
413
+ webgpu;
414
+ webgpuAdapter;
415
+ webgpuVendor;
416
+ webgpuArchitecture;
417
+ pointer;
418
+ keyboard;
419
+ gamepad;
420
+ touch;
421
+ maxTouchPoints;
422
+ audio;
423
+ fullscreen;
424
+ vibration;
425
+ offscreenCanvas;
426
+ webWorkers;
427
+ devicePixelRatio;
428
+ constructor(values) {
429
+ this.webgl2 = values.webgl2;
430
+ this.webgpu = values.webgpu;
431
+ this.webgpuAdapter = values.webgpuAdapter;
432
+ this.webgpuVendor = values.webgpuVendor;
433
+ this.webgpuArchitecture = values.webgpuArchitecture;
434
+ this.pointer = values.pointer;
435
+ this.keyboard = values.keyboard;
436
+ this.gamepad = values.gamepad;
437
+ this.touch = values.touch;
438
+ this.maxTouchPoints = values.maxTouchPoints;
439
+ this.audio = values.audio;
440
+ this.fullscreen = values.fullscreen;
441
+ this.vibration = values.vibration;
442
+ this.offscreenCanvas = values.offscreenCanvas;
443
+ this.webWorkers = values.webWorkers;
444
+ this.devicePixelRatio = values.devicePixelRatio;
445
+ Object.freeze(this);
446
+ }
447
+ static async _detect() {
448
+ const [webgpuAdapter, webgpuInfo] = await probeWebGpu();
449
+ return new Capabilities({
450
+ webgl2: probeWebGl2(),
451
+ webgpu: probeWebGpuApiSurface(),
452
+ webgpuAdapter,
453
+ webgpuVendor: webgpuInfo?.vendor ?? null,
454
+ webgpuArchitecture: webgpuInfo?.architecture ?? null,
455
+ pointer: probePointer(),
456
+ keyboard: probeKeyboard(),
457
+ gamepad: probeGamepad(),
458
+ touch: probeTouchSupported(),
459
+ maxTouchPoints: probeMaxTouchPoints(),
460
+ audio: probeAudio(),
461
+ fullscreen: probeFullscreen(),
462
+ vibration: probeVibration(),
463
+ offscreenCanvas: probeOffscreenCanvas(),
464
+ webWorkers: probeWebWorkers(),
465
+ devicePixelRatio: hasWindow ? window.devicePixelRatio : 1,
466
+ });
467
+ }
468
+ }
469
+ // --- probes ---------------------------------------------------------------
470
+ function probeWebGl2() {
471
+ if (!hasDocument)
472
+ return false;
473
+ try {
474
+ const canvas = document.createElement('canvas');
475
+ const gl = canvas.getContext('webgl2');
476
+ return gl !== null;
477
+ }
478
+ catch {
479
+ return false;
480
+ }
481
+ }
482
+ function probeWebGpuApiSurface() {
483
+ return hasNavigator && 'gpu' in navigator;
484
+ }
485
+ async function probeWebGpu() {
486
+ if (!probeWebGpuApiSurface())
487
+ return [null, null];
488
+ const gpu = navigator.gpu;
489
+ if (!gpu || typeof gpu.requestAdapter !== 'function')
490
+ return [null, null];
491
+ try {
492
+ const adapter = await gpu.requestAdapter();
493
+ if (!adapter)
494
+ return [null, null];
495
+ // Modern path: GPUAdapter.info is a sync property (Chrome 116+,
496
+ // Safari 18+). Older browsers exposed a deprecated async
497
+ // requestAdapterInfo() instead. Try the modern path first, fall
498
+ // back if needed.
499
+ const adapterAny = adapter;
500
+ if (adapterAny.info) {
501
+ return [adapter, adapterAny.info];
502
+ }
503
+ if (typeof adapterAny.requestAdapterInfo === 'function') {
504
+ try {
505
+ return [adapter, await adapterAny.requestAdapterInfo()];
506
+ }
507
+ catch {
508
+ return [adapter, null];
509
+ }
510
+ }
511
+ return [adapter, null];
512
+ }
513
+ catch {
514
+ return [null, null];
515
+ }
516
+ }
517
+ function probePointer() {
518
+ return hasWindow && 'PointerEvent' in window;
519
+ }
520
+ function probeKeyboard() {
521
+ return hasWindow && 'KeyboardEvent' in window;
522
+ }
523
+ function probeGamepad() {
524
+ return hasNavigator && typeof navigator.getGamepads === 'function';
525
+ }
526
+ function probeTouchSupported() {
527
+ if (!hasWindow)
528
+ return false;
529
+ if ('ontouchstart' in window)
530
+ return true;
531
+ if (probeMaxTouchPoints() > 0)
532
+ return true;
533
+ return false;
534
+ }
535
+ function probeMaxTouchPoints() {
536
+ if (!hasNavigator)
537
+ return 0;
538
+ const points = navigator.maxTouchPoints;
539
+ return typeof points === 'number' ? points : 0;
540
+ }
541
+ function probeAudio() {
542
+ if (!hasWindow)
543
+ return false;
544
+ const w = window;
545
+ return typeof w.AudioContext !== 'undefined' || typeof w.webkitAudioContext !== 'undefined';
546
+ }
547
+ function probeFullscreen() {
548
+ if (!hasDocument)
549
+ return false;
550
+ const el = document.documentElement;
551
+ return typeof el.requestFullscreen === 'function' || typeof el.webkitRequestFullscreen === 'function';
552
+ }
553
+ function probeVibration() {
554
+ return hasNavigator && typeof navigator.vibrate === 'function';
555
+ }
556
+ function probeOffscreenCanvas() {
557
+ // The browser global is verbatim `OffscreenCanvas`; eslint's
558
+ // strict-camelCase rule rejects the property name even though we
559
+ // can't rename a web standard.
560
+ // eslint-disable-next-line @typescript-eslint/naming-convention
561
+ return hasWindow && typeof window.OffscreenCanvas !== 'undefined';
562
+ }
563
+ function probeWebWorkers() {
564
+ // The browser global is verbatim `Worker`; eslint's strict-camelCase
565
+ // rule rejects the property name even though we can't rename a web
566
+ // standard.
567
+ // eslint-disable-next-line @typescript-eslint/naming-convention
568
+ return hasWindow && typeof window.Worker === 'function';
569
+ }
570
+
375
571
  class Clock {
376
572
  _startTime;
377
573
  _elapsedTime = new Time(0);
@@ -3870,1162 +4066,1162 @@ class SceneManager {
3870
4066
  }
3871
4067
  }
3872
4068
 
3873
- /*
3874
- ** Copyright (c) 2012 The Khronos Group Inc.
3875
- **
3876
- ** Permission is hereby granted, free of charge, to any person obtaining a
3877
- ** copy of this software and/or associated documentation files (the
3878
- ** "Materials"), to deal in the Materials without restriction, including
3879
- ** without limitation the rights to use, copy, modify, merge, publish,
3880
- ** distribute, sublicense, and/or sell copies of the Materials, and to
3881
- ** permit persons to whom the Materials are furnished to do so, subject to
3882
- ** the following conditions:
3883
- **
3884
- ** The above copyright notice and this permission notice shall be included
3885
- ** in all copies or substantial portions of the Materials.
3886
- **
3887
- ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3888
- ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3889
- ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3890
- ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
3891
- ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
3892
- ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
3893
- ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
3894
- */
3895
-
3896
- // Various functions for helping debug WebGL apps.
3897
-
3898
- const WebGLDebugUtils = function() {
3899
-
3900
- /**
3901
- * Wrapped logging function.
3902
- * @param {string} msg Message to log.
3903
- */
3904
- var log = function(msg) {
3905
- if (window.console && window.console.log) {
3906
- window.console.log(msg);
3907
- }
3908
- };
3909
-
3910
- /**
3911
- * Wrapped error logging function.
3912
- * @param {string} msg Message to log.
3913
- */
3914
- var error = function(msg) {
3915
- if (window.console && window.console.error) {
3916
- window.console.error(msg);
3917
- } else {
3918
- log(msg);
3919
- }
3920
- };
3921
-
3922
-
3923
- /**
3924
- * Which arguments are enums based on the number of arguments to the function.
3925
- * So
3926
- * 'texImage2D': {
3927
- * 9: { 0:true, 2:true, 6:true, 7:true },
3928
- * 6: { 0:true, 2:true, 3:true, 4:true },
3929
- * },
3930
- *
3931
- * means if there are 9 arguments then 6 and 7 are enums, if there are 6
3932
- * arguments 3 and 4 are enums
3933
- *
3934
- * @type {!Object.<number, !Object.<number, string>}
3935
- */
3936
- var glValidEnumContexts = {
3937
- // Generic setters and getters
3938
-
3939
- 'enable': {1: { 0:true }},
3940
- 'disable': {1: { 0:true }},
3941
- 'getParameter': {1: { 0:true }},
3942
-
3943
- // Rendering
3944
-
3945
- 'drawArrays': {3:{ 0:true }},
3946
- 'drawElements': {4:{ 0:true, 2:true }},
3947
-
3948
- // Shaders
3949
-
3950
- 'createShader': {1: { 0:true }},
3951
- 'getShaderParameter': {2: { 1:true }},
3952
- 'getProgramParameter': {2: { 1:true }},
3953
- 'getShaderPrecisionFormat': {2: { 0: true, 1:true }},
3954
-
3955
- // Vertex attributes
3956
-
3957
- 'getVertexAttrib': {2: { 1:true }},
3958
- 'vertexAttribPointer': {6: { 2:true }},
3959
-
3960
- // Textures
3961
-
3962
- 'bindTexture': {2: { 0:true }},
3963
- 'activeTexture': {1: { 0:true }},
3964
- 'getTexParameter': {2: { 0:true, 1:true }},
3965
- 'texParameterf': {3: { 0:true, 1:true }},
3966
- 'texParameteri': {3: { 0:true, 1:true, 2:true }},
3967
- // texImage2D and texSubImage2D are defined below with WebGL 2 entrypoints
3968
- 'copyTexImage2D': {8: { 0:true, 2:true }},
3969
- 'copyTexSubImage2D': {8: { 0:true }},
3970
- 'generateMipmap': {1: { 0:true }},
3971
- // compressedTexImage2D and compressedTexSubImage2D are defined below with WebGL 2 entrypoints
3972
-
3973
- // Buffer objects
3974
-
3975
- 'bindBuffer': {2: { 0:true }},
3976
- // bufferData and bufferSubData are defined below with WebGL 2 entrypoints
3977
- 'getBufferParameter': {2: { 0:true, 1:true }},
3978
-
3979
- // Renderbuffers and framebuffers
3980
-
3981
- 'pixelStorei': {2: { 0:true, 1:true }},
3982
- // readPixels is defined below with WebGL 2 entrypoints
3983
- 'bindRenderbuffer': {2: { 0:true }},
3984
- 'bindFramebuffer': {2: { 0:true }},
3985
- 'checkFramebufferStatus': {1: { 0:true }},
3986
- 'framebufferRenderbuffer': {4: { 0:true, 1:true, 2:true }},
3987
- 'framebufferTexture2D': {5: { 0:true, 1:true, 2:true }},
3988
- 'getFramebufferAttachmentParameter': {3: { 0:true, 1:true, 2:true }},
3989
- 'getRenderbufferParameter': {2: { 0:true, 1:true }},
3990
- 'renderbufferStorage': {4: { 0:true, 1:true }},
3991
-
3992
- // Frame buffer operations (clear, blend, depth test, stencil)
3993
-
3994
- 'clear': {1: { 0: { 'enumBitwiseOr': ['COLOR_BUFFER_BIT', 'DEPTH_BUFFER_BIT', 'STENCIL_BUFFER_BIT'] }}},
3995
- 'depthFunc': {1: { 0:true }},
3996
- 'blendFunc': {2: { 0:true, 1:true }},
3997
- 'blendFuncSeparate': {4: { 0:true, 1:true, 2:true, 3:true }},
3998
- 'blendEquation': {1: { 0:true }},
3999
- 'blendEquationSeparate': {2: { 0:true, 1:true }},
4000
- 'stencilFunc': {3: { 0:true }},
4001
- 'stencilFuncSeparate': {4: { 0:true, 1:true }},
4002
- 'stencilMaskSeparate': {2: { 0:true }},
4003
- 'stencilOp': {3: { 0:true, 1:true, 2:true }},
4004
- 'stencilOpSeparate': {4: { 0:true, 1:true, 2:true, 3:true }},
4005
-
4006
- // Culling
4007
-
4008
- 'cullFace': {1: { 0:true }},
4009
- 'frontFace': {1: { 0:true }},
4010
-
4011
- // ANGLE_instanced_arrays extension
4012
-
4013
- 'drawArraysInstancedANGLE': {4: { 0:true }},
4014
- 'drawElementsInstancedANGLE': {5: { 0:true, 2:true }},
4015
-
4016
- // EXT_blend_minmax extension
4017
-
4018
- 'blendEquationEXT': {1: { 0:true }},
4019
-
4020
- // WebGL 2 Buffer objects
4021
-
4022
- 'bufferData': {
4023
- 3: { 0:true, 2:true }, // WebGL 1
4024
- 4: { 0:true, 2:true }, // WebGL 2
4025
- 5: { 0:true, 2:true } // WebGL 2
4026
- },
4027
- 'bufferSubData': {
4028
- 3: { 0:true }, // WebGL 1
4029
- 4: { 0:true }, // WebGL 2
4030
- 5: { 0:true } // WebGL 2
4031
- },
4032
- 'copyBufferSubData': {5: { 0:true, 1:true }},
4033
- 'getBufferSubData': {3: { 0:true }, 4: { 0:true }, 5: { 0:true }},
4034
-
4035
- // WebGL 2 Framebuffer objects
4036
-
4037
- 'blitFramebuffer': {10: { 8: { 'enumBitwiseOr': ['COLOR_BUFFER_BIT', 'DEPTH_BUFFER_BIT', 'STENCIL_BUFFER_BIT'] }, 9:true }},
4038
- 'framebufferTextureLayer': {5: { 0:true, 1:true }},
4039
- 'invalidateFramebuffer': {2: { 0:true }},
4040
- 'invalidateSubFramebuffer': {6: { 0:true }},
4041
- 'readBuffer': {1: { 0:true }},
4042
-
4043
- // WebGL 2 Renderbuffer objects
4044
-
4045
- 'getInternalformatParameter': {3: { 0:true, 1:true, 2:true }},
4046
- 'renderbufferStorageMultisample': {5: { 0:true, 2:true }},
4047
-
4048
- // WebGL 2 Texture objects
4049
-
4050
- 'texStorage2D': {5: { 0:true, 2:true }},
4051
- 'texStorage3D': {6: { 0:true, 2:true }},
4052
- 'texImage2D': {
4053
- 9: { 0:true, 2:true, 6:true, 7:true }, // WebGL 1 & 2
4054
- 6: { 0:true, 2:true, 3:true, 4:true }, // WebGL 1
4055
- 10: { 0:true, 2:true, 6:true, 7:true } // WebGL 2
4056
- },
4057
- 'texImage3D': {
4058
- 10: { 0:true, 2:true, 7:true, 8:true },
4059
- 11: { 0:true, 2:true, 7:true, 8:true }
4060
- },
4061
- 'texSubImage2D': {
4062
- 9: { 0:true, 6:true, 7:true }, // WebGL 1 & 2
4063
- 7: { 0:true, 4:true, 5:true }, // WebGL 1
4064
- 10: { 0:true, 6:true, 7:true } // WebGL 2
4065
- },
4066
- 'texSubImage3D': {
4067
- 11: { 0:true, 8:true, 9:true },
4068
- 12: { 0:true, 8:true, 9:true }
4069
- },
4070
- 'copyTexSubImage3D': {9: { 0:true }},
4071
- 'compressedTexImage2D': {
4072
- 7: { 0: true, 2:true }, // WebGL 1 & 2
4073
- 8: { 0: true, 2:true }, // WebGL 2
4074
- 9: { 0: true, 2:true } // WebGL 2
4075
- },
4076
- 'compressedTexImage3D': {
4077
- 8: { 0: true, 2:true },
4078
- 9: { 0: true, 2:true },
4079
- 10: { 0: true, 2:true }
4080
- },
4081
- 'compressedTexSubImage2D': {
4082
- 8: { 0: true, 6:true }, // WebGL 1 & 2
4083
- 9: { 0: true, 6:true }, // WebGL 2
4084
- 10: { 0: true, 6:true } // WebGL 2
4085
- },
4086
- 'compressedTexSubImage3D': {
4087
- 10: { 0: true, 8:true },
4088
- 11: { 0: true, 8:true },
4089
- 12: { 0: true, 8:true }
4090
- },
4091
-
4092
- // WebGL 2 Vertex attribs
4093
-
4094
- 'vertexAttribIPointer': {5: { 2:true }},
4095
-
4096
- // WebGL 2 Writing to the drawing buffer
4097
-
4098
- 'drawArraysInstanced': {4: { 0:true }},
4099
- 'drawElementsInstanced': {5: { 0:true, 2:true }},
4100
- 'drawRangeElements': {6: { 0:true, 4:true }},
4101
-
4102
- // WebGL 2 Reading back pixels
4103
-
4104
- 'readPixels': {
4105
- 7: { 4:true, 5:true }, // WebGL 1 & 2
4106
- 8: { 4:true, 5:true } // WebGL 2
4107
- },
4108
-
4109
- // WebGL 2 Multiple Render Targets
4110
-
4111
- 'clearBufferfv': {3: { 0:true }, 4: { 0:true }},
4112
- 'clearBufferiv': {3: { 0:true }, 4: { 0:true }},
4113
- 'clearBufferuiv': {3: { 0:true }, 4: { 0:true }},
4114
- 'clearBufferfi': {4: { 0:true }},
4115
-
4116
- // WebGL 2 Query objects
4117
-
4118
- 'beginQuery': {2: { 0:true }},
4119
- 'endQuery': {1: { 0:true }},
4120
- 'getQuery': {2: { 0:true, 1:true }},
4121
- 'getQueryParameter': {2: { 1:true }},
4122
-
4123
- // WebGL 2 Sampler objects
4124
-
4125
- 'samplerParameteri': {3: { 1:true, 2:true }},
4126
- 'samplerParameterf': {3: { 1:true }},
4127
- 'getSamplerParameter': {2: { 1:true }},
4128
-
4129
- // WebGL 2 Sync objects
4130
-
4131
- 'fenceSync': {2: { 0:true, 1: { 'enumBitwiseOr': [] } }},
4132
- 'clientWaitSync': {3: { 1: { 'enumBitwiseOr': ['SYNC_FLUSH_COMMANDS_BIT'] } }},
4133
- 'waitSync': {3: { 1: { 'enumBitwiseOr': [] } }},
4134
- 'getSyncParameter': {2: { 1:true }},
4135
-
4136
- // WebGL 2 Transform Feedback
4137
-
4138
- 'bindTransformFeedback': {2: { 0:true }},
4139
- 'beginTransformFeedback': {1: { 0:true }},
4140
- 'transformFeedbackVaryings': {3: { 2:true }},
4141
-
4142
- // WebGL2 Uniform Buffer Objects and Transform Feedback Buffers
4143
-
4144
- 'bindBufferBase': {3: { 0:true }},
4145
- 'bindBufferRange': {5: { 0:true }},
4146
- 'getIndexedParameter': {2: { 0:true }},
4147
- 'getActiveUniforms': {3: { 2:true }},
4148
- 'getActiveUniformBlockParameter': {3: { 2:true }}
4149
- };
4150
-
4151
- /**
4152
- * Map of numbers to names.
4153
- * @type {Object}
4154
- */
4155
- var glEnums = null;
4156
-
4157
- /**
4158
- * Map of names to numbers.
4159
- * @type {Object}
4160
- */
4161
- var enumStringToValue = null;
4162
-
4163
- /**
4164
- * Initializes this module. Safe to call more than once.
4165
- * @param {!WebGLRenderingContext} ctx A WebGL context. If
4166
- * you have more than one context it doesn't matter which one
4167
- * you pass in, it is only used to pull out constants.
4168
- */
4169
- function init(ctx) {
4170
- if (glEnums == null) {
4171
- glEnums = { };
4172
- enumStringToValue = { };
4173
- for (var propertyName in ctx) {
4174
- if (typeof ctx[propertyName] == 'number') {
4175
- glEnums[ctx[propertyName]] = propertyName;
4176
- enumStringToValue[propertyName] = ctx[propertyName];
4177
- }
4178
- }
4179
- }
4180
- }
4181
-
4182
- /**
4183
- * Checks the utils have been initialized.
4184
- */
4185
- function checkInit() {
4186
- if (glEnums == null) {
4187
- throw 'WebGLDebugUtils.init(ctx) not called';
4188
- }
4189
- }
4190
-
4191
- /**
4192
- * Returns true or false if value matches any WebGL enum
4193
- * @param {*} value Value to check if it might be an enum.
4194
- * @return {boolean} True if value matches one of the WebGL defined enums
4195
- */
4196
- function mightBeEnum(value) {
4197
- checkInit();
4198
- return (glEnums[value] !== undefined);
4199
- }
4200
-
4201
- /**
4202
- * Gets an string version of an WebGL enum.
4203
- *
4204
- * Example:
4205
- * var str = WebGLDebugUtil.glEnumToString(ctx.getError());
4206
- *
4207
- * @param {number} value Value to return an enum for
4208
- * @return {string} The string version of the enum.
4209
- */
4210
- function glEnumToString(value) {
4211
- checkInit();
4212
- var name = glEnums[value];
4213
- return (name !== undefined) ? ("gl." + name) :
4214
- ("/*UNKNOWN WebGL ENUM*/ 0x" + value.toString(16) + "");
4215
- }
4216
-
4217
- /**
4218
- * Returns the string version of a WebGL argument.
4219
- * Attempts to convert enum arguments to strings.
4220
- * @param {string} functionName the name of the WebGL function.
4221
- * @param {number} numArgs the number of arguments passed to the function.
4222
- * @param {number} argumentIndx the index of the argument.
4223
- * @param {*} value The value of the argument.
4224
- * @return {string} The value as a string.
4225
- */
4226
- function glFunctionArgToString(functionName, numArgs, argumentIndex, value) {
4227
- var funcInfo = glValidEnumContexts[functionName];
4228
- if (funcInfo !== undefined) {
4229
- var funcInfo = funcInfo[numArgs];
4230
- if (funcInfo !== undefined) {
4231
- if (funcInfo[argumentIndex]) {
4232
- if (typeof funcInfo[argumentIndex] === 'object' &&
4233
- funcInfo[argumentIndex]['enumBitwiseOr'] !== undefined) {
4234
- var enums = funcInfo[argumentIndex]['enumBitwiseOr'];
4235
- var orResult = 0;
4236
- var orEnums = [];
4237
- for (var i = 0; i < enums.length; ++i) {
4238
- var enumValue = enumStringToValue[enums[i]];
4239
- if ((value & enumValue) !== 0) {
4240
- orResult |= enumValue;
4241
- orEnums.push(glEnumToString(enumValue));
4242
- }
4243
- }
4244
- if (orResult === value) {
4245
- return orEnums.join(' | ');
4246
- } else {
4247
- return glEnumToString(value);
4248
- }
4249
- } else {
4250
- return glEnumToString(value);
4251
- }
4252
- }
4253
- }
4254
- }
4255
- if (value === null) {
4256
- return "null";
4257
- } else if (value === undefined) {
4258
- return "undefined";
4259
- } else {
4260
- return value.toString();
4261
- }
4262
- }
4263
-
4264
- /**
4265
- * Converts the arguments of a WebGL function to a string.
4266
- * Attempts to convert enum arguments to strings.
4267
- *
4268
- * @param {string} functionName the name of the WebGL function.
4269
- * @param {Array<*>} args The arguments.
4270
- * @return {string} The arguments as a string.
4271
- */
4272
- function glFunctionArgsToString(functionName, args) {
4273
- // apparently we can't do args.join(",");
4274
- var argStr = "";
4275
- var numArgs = args.length;
4276
- for (var ii = 0; ii < numArgs; ++ii) {
4277
- argStr += ((ii == 0) ? '' : ', ') +
4278
- glFunctionArgToString(functionName, numArgs, ii, args[ii]);
4279
- }
4280
- return argStr;
4281
- }
4282
-
4283
- function makePropertyWrapper(wrapper, original, propertyName) {
4284
- //log("wrap prop: " + propertyName);
4285
- wrapper.__defineGetter__(propertyName, function() {
4286
- return original[propertyName];
4287
- });
4288
- // TODO(gmane): this needs to handle properties that take more than
4289
- // one value?
4290
- wrapper.__defineSetter__(propertyName, function(value) {
4291
- //log("set: " + propertyName);
4292
- original[propertyName] = value;
4293
- });
4294
- }
4295
-
4296
- /**
4297
- * Given a WebGL context returns a wrapped context that calls
4298
- * gl.getError after every command and calls a function if the
4299
- * result is not gl.NO_ERROR.
4300
- *
4301
- * @param {!WebGLRenderingContext} ctx The webgl context to
4302
- * wrap.
4303
- * @param {!function(err, funcName, args): void} opt_onErrorFunc
4304
- * The function to call when gl.getError returns an
4305
- * error. If not specified the default function calls
4306
- * console.log with a message.
4307
- * @param {!function(funcName, args): void} opt_onFunc The
4308
- * function to call when each webgl function is called.
4309
- * You can use this to log all calls for example.
4310
- * @param {!WebGLRenderingContext} opt_err_ctx The webgl context
4311
- * to call getError on if different than ctx.
4312
- */
4313
- function makeDebugContext(ctx, opt_onErrorFunc, opt_onFunc, opt_err_ctx) {
4314
- opt_err_ctx = opt_err_ctx || ctx;
4315
- init(ctx);
4316
- opt_onErrorFunc = opt_onErrorFunc || function(err, functionName, args) {
4317
- // apparently we can't do args.join(",");
4318
- var argStr = "";
4319
- var numArgs = args.length;
4320
- for (var ii = 0; ii < numArgs; ++ii) {
4321
- argStr += ((ii == 0) ? '' : ', ') +
4322
- glFunctionArgToString(functionName, numArgs, ii, args[ii]);
4323
- }
4324
- error("WebGL error "+ glEnumToString(err) + " in "+ functionName +
4325
- "(" + argStr + ")");
4326
- };
4327
-
4328
- // Holds booleans for each GL error so after we get the error ourselves
4329
- // we can still return it to the client app.
4330
- var glErrorShadow = { };
4331
-
4332
- // Makes a function that calls a WebGL function and then calls getError.
4333
- function makeErrorWrapper(ctx, functionName) {
4334
- return function() {
4335
- if (opt_onFunc) {
4336
- opt_onFunc(functionName, arguments);
4337
- }
4338
- var result = ctx[functionName].apply(ctx, arguments);
4339
- var err = opt_err_ctx.getError();
4340
- if (err != 0) {
4341
- glErrorShadow[err] = true;
4342
- opt_onErrorFunc(err, functionName, arguments);
4343
- }
4344
- return result;
4345
- };
4346
- }
4347
-
4348
- // Make a an object that has a copy of every property of the WebGL context
4349
- // but wraps all functions.
4350
- var wrapper = {};
4351
- for (var propertyName in ctx) {
4352
- if (typeof ctx[propertyName] == 'function') {
4353
- if (propertyName != 'getExtension') {
4354
- wrapper[propertyName] = makeErrorWrapper(ctx, propertyName);
4355
- } else {
4356
- var wrapped = makeErrorWrapper(ctx, propertyName);
4357
- wrapper[propertyName] = function () {
4358
- var result = wrapped.apply(ctx, arguments);
4359
- if (!result) {
4360
- return null;
4361
- }
4362
- return makeDebugContext(result, opt_onErrorFunc, opt_onFunc, opt_err_ctx);
4363
- };
4364
- }
4365
- } else {
4366
- makePropertyWrapper(wrapper, ctx, propertyName);
4367
- }
4368
- }
4369
-
4370
- // Override the getError function with one that returns our saved results.
4371
- wrapper.getError = function() {
4372
- for (var err in glErrorShadow) {
4373
- if (glErrorShadow.hasOwnProperty(err)) {
4374
- if (glErrorShadow[err]) {
4375
- glErrorShadow[err] = false;
4376
- return err;
4377
- }
4378
- }
4379
- }
4380
- return ctx.NO_ERROR;
4381
- };
4382
-
4383
- return wrapper;
4384
- }
4385
-
4386
- function resetToInitialState(ctx) {
4387
- var isWebGL2RenderingContext = !!ctx.createTransformFeedback;
4388
-
4389
- if (isWebGL2RenderingContext) {
4390
- ctx.bindVertexArray(null);
4391
- }
4392
-
4393
- var numAttribs = ctx.getParameter(ctx.MAX_VERTEX_ATTRIBS);
4394
- var tmp = ctx.createBuffer();
4395
- ctx.bindBuffer(ctx.ARRAY_BUFFER, tmp);
4396
- for (var ii = 0; ii < numAttribs; ++ii) {
4397
- ctx.disableVertexAttribArray(ii);
4398
- ctx.vertexAttribPointer(ii, 4, ctx.FLOAT, false, 0, 0);
4399
- ctx.vertexAttrib1f(ii, 0);
4400
- if (isWebGL2RenderingContext) {
4401
- ctx.vertexAttribDivisor(ii, 0);
4402
- }
4403
- }
4404
- ctx.deleteBuffer(tmp);
4405
-
4406
- var numTextureUnits = ctx.getParameter(ctx.MAX_TEXTURE_IMAGE_UNITS);
4407
- for (var ii = 0; ii < numTextureUnits; ++ii) {
4408
- ctx.activeTexture(ctx.TEXTURE0 + ii);
4409
- ctx.bindTexture(ctx.TEXTURE_CUBE_MAP, null);
4410
- ctx.bindTexture(ctx.TEXTURE_2D, null);
4411
- if (isWebGL2RenderingContext) {
4412
- ctx.bindTexture(ctx.TEXTURE_2D_ARRAY, null);
4413
- ctx.bindTexture(ctx.TEXTURE_3D, null);
4414
- ctx.bindSampler(ii, null);
4415
- }
4416
- }
4417
-
4418
- ctx.activeTexture(ctx.TEXTURE0);
4419
- ctx.useProgram(null);
4420
- ctx.bindBuffer(ctx.ARRAY_BUFFER, null);
4421
- ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null);
4422
- ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
4423
- ctx.bindRenderbuffer(ctx.RENDERBUFFER, null);
4424
- ctx.disable(ctx.BLEND);
4425
- ctx.disable(ctx.CULL_FACE);
4426
- ctx.disable(ctx.DEPTH_TEST);
4427
- ctx.disable(ctx.DITHER);
4428
- ctx.disable(ctx.SCISSOR_TEST);
4429
- ctx.blendColor(0, 0, 0, 0);
4430
- ctx.blendEquation(ctx.FUNC_ADD);
4431
- ctx.blendFunc(ctx.ONE, ctx.ZERO);
4432
- ctx.clearColor(0, 0, 0, 0);
4433
- ctx.clearDepth(1);
4434
- ctx.clearStencil(-1);
4435
- ctx.colorMask(true, true, true, true);
4436
- ctx.cullFace(ctx.BACK);
4437
- ctx.depthFunc(ctx.LESS);
4438
- ctx.depthMask(true);
4439
- ctx.depthRange(0, 1);
4440
- ctx.frontFace(ctx.CCW);
4441
- ctx.hint(ctx.GENERATE_MIPMAP_HINT, ctx.DONT_CARE);
4442
- ctx.lineWidth(1);
4443
- ctx.pixelStorei(ctx.PACK_ALIGNMENT, 4);
4444
- ctx.pixelStorei(ctx.UNPACK_ALIGNMENT, 4);
4445
- ctx.pixelStorei(ctx.UNPACK_FLIP_Y_WEBGL, false);
4446
- ctx.pixelStorei(ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
4447
- // TODO: Delete this IF.
4448
- if (ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL) {
4449
- ctx.pixelStorei(ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL, ctx.BROWSER_DEFAULT_WEBGL);
4450
- }
4451
- ctx.polygonOffset(0, 0);
4452
- ctx.sampleCoverage(1, false);
4453
- ctx.scissor(0, 0, ctx.canvas.width, ctx.canvas.height);
4454
- ctx.stencilFunc(ctx.ALWAYS, 0, 0xFFFFFFFF);
4455
- ctx.stencilMask(0xFFFFFFFF);
4456
- ctx.stencilOp(ctx.KEEP, ctx.KEEP, ctx.KEEP);
4457
- ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
4458
- ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT | ctx.STENCIL_BUFFER_BIT);
4459
-
4460
- if (isWebGL2RenderingContext) {
4461
- ctx.drawBuffers([ctx.BACK]);
4462
- ctx.readBuffer(ctx.BACK);
4463
- ctx.bindBuffer(ctx.COPY_READ_BUFFER, null);
4464
- ctx.bindBuffer(ctx.COPY_WRITE_BUFFER, null);
4465
- ctx.bindBuffer(ctx.PIXEL_PACK_BUFFER, null);
4466
- ctx.bindBuffer(ctx.PIXEL_UNPACK_BUFFER, null);
4467
- var numTransformFeedbacks = ctx.getParameter(ctx.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
4468
- for (var ii = 0; ii < numTransformFeedbacks; ++ii) {
4469
- ctx.bindBufferBase(ctx.TRANSFORM_FEEDBACK_BUFFER, ii, null);
4470
- }
4471
- var numUBOs = ctx.getParameter(ctx.MAX_UNIFORM_BUFFER_BINDINGS);
4472
- for (var ii = 0; ii < numUBOs; ++ii) {
4473
- ctx.bindBufferBase(ctx.UNIFORM_BUFFER, ii, null);
4474
- }
4475
- ctx.disable(ctx.RASTERIZER_DISCARD);
4476
- ctx.pixelStorei(ctx.UNPACK_IMAGE_HEIGHT, 0);
4477
- ctx.pixelStorei(ctx.UNPACK_SKIP_IMAGES, 0);
4478
- ctx.pixelStorei(ctx.UNPACK_ROW_LENGTH, 0);
4479
- ctx.pixelStorei(ctx.UNPACK_SKIP_ROWS, 0);
4480
- ctx.pixelStorei(ctx.UNPACK_SKIP_PIXELS, 0);
4481
- ctx.pixelStorei(ctx.PACK_ROW_LENGTH, 0);
4482
- ctx.pixelStorei(ctx.PACK_SKIP_ROWS, 0);
4483
- ctx.pixelStorei(ctx.PACK_SKIP_PIXELS, 0);
4484
- ctx.hint(ctx.FRAGMENT_SHADER_DERIVATIVE_HINT, ctx.DONT_CARE);
4485
- }
4486
-
4487
- // TODO: This should NOT be needed but Firefox fails with 'hint'
4488
- while(ctx.getError());
4489
- }
4490
-
4491
- function makeLostContextSimulatingCanvas(canvas) {
4492
- var unwrappedContext_;
4493
- var wrappedContext_;
4494
- var onLost_ = [];
4495
- var onRestored_ = [];
4496
- var wrappedContext_ = {};
4497
- var contextId_ = 1;
4498
- var contextLost_ = false;
4499
- var resourceDb_ = [];
4500
- var numCallsToLoseContext_ = 0;
4501
- var numCalls_ = 0;
4502
- var canRestore_ = false;
4503
- var restoreTimeout_ = 0;
4504
- var isWebGL2RenderingContext;
4505
-
4506
- // Holds booleans for each GL error so can simulate errors.
4507
- var glErrorShadow_ = { };
4508
-
4509
- canvas.getContext = function(f) {
4510
- return function() {
4511
- var ctx = f.apply(canvas, arguments);
4512
- // Did we get a context and is it a WebGL context?
4513
- if ((ctx instanceof WebGLRenderingContext) || (window.WebGL2RenderingContext && (ctx instanceof WebGL2RenderingContext))) {
4514
- if (ctx != unwrappedContext_) {
4515
- if (unwrappedContext_) {
4516
- throw "got different context"
4517
- }
4518
- isWebGL2RenderingContext = window.WebGL2RenderingContext && (ctx instanceof WebGL2RenderingContext);
4519
- unwrappedContext_ = ctx;
4520
- wrappedContext_ = makeLostContextSimulatingContext(unwrappedContext_);
4521
- }
4522
- return wrappedContext_;
4523
- }
4524
- return ctx;
4525
- }
4526
- }(canvas.getContext);
4527
-
4528
- function wrapEvent(listener) {
4529
- if (typeof(listener) == "function") {
4530
- return listener;
4531
- } else {
4532
- return function(info) {
4533
- listener.handleEvent(info);
4534
- }
4535
- }
4536
- }
4537
-
4538
- var addOnContextLostListener = function(listener) {
4539
- onLost_.push(wrapEvent(listener));
4540
- };
4541
-
4542
- var addOnContextRestoredListener = function(listener) {
4543
- onRestored_.push(wrapEvent(listener));
4544
- };
4545
-
4546
-
4547
- function wrapAddEventListener(canvas) {
4548
- var f = canvas.addEventListener;
4549
- canvas.addEventListener = function(type, listener, bubble) {
4550
- switch (type) {
4551
- case 'webglcontextlost':
4552
- addOnContextLostListener(listener);
4553
- break;
4554
- case 'webglcontextrestored':
4555
- addOnContextRestoredListener(listener);
4556
- break;
4557
- default:
4558
- f.apply(canvas, arguments);
4559
- }
4560
- };
4561
- }
4562
-
4563
- wrapAddEventListener(canvas);
4564
-
4565
- canvas.loseContext = function() {
4566
- if (!contextLost_) {
4567
- contextLost_ = true;
4568
- numCallsToLoseContext_ = 0;
4569
- ++contextId_;
4570
- while (unwrappedContext_.getError());
4571
- clearErrors();
4572
- glErrorShadow_[unwrappedContext_.CONTEXT_LOST_WEBGL] = true;
4573
- var event = makeWebGLContextEvent("context lost");
4574
- var callbacks = onLost_.slice();
4575
- setTimeout(function() {
4576
- //log("numCallbacks:" + callbacks.length);
4577
- for (var ii = 0; ii < callbacks.length; ++ii) {
4578
- //log("calling callback:" + ii);
4579
- callbacks[ii](event);
4580
- }
4581
- if (restoreTimeout_ >= 0) {
4582
- setTimeout(function() {
4583
- canvas.restoreContext();
4584
- }, restoreTimeout_);
4585
- }
4586
- }, 0);
4587
- }
4588
- };
4589
-
4590
- canvas.restoreContext = function() {
4591
- if (contextLost_) {
4592
- if (onRestored_.length) {
4593
- setTimeout(function() {
4594
- if (!canRestore_) {
4595
- throw "can not restore. webglcontestlost listener did not call event.preventDefault";
4596
- }
4597
- freeResources();
4598
- resetToInitialState(unwrappedContext_);
4599
- contextLost_ = false;
4600
- numCalls_ = 0;
4601
- canRestore_ = false;
4602
- var callbacks = onRestored_.slice();
4603
- var event = makeWebGLContextEvent("context restored");
4604
- for (var ii = 0; ii < callbacks.length; ++ii) {
4605
- callbacks[ii](event);
4606
- }
4607
- }, 0);
4608
- }
4609
- }
4610
- };
4611
-
4612
- canvas.loseContextInNCalls = function(numCalls) {
4613
- if (contextLost_) {
4614
- throw "You can not ask a lost contet to be lost";
4615
- }
4616
- numCallsToLoseContext_ = numCalls_ + numCalls;
4617
- };
4618
-
4619
- canvas.getNumCalls = function() {
4620
- return numCalls_;
4621
- };
4622
-
4623
- canvas.setRestoreTimeout = function(timeout) {
4624
- restoreTimeout_ = timeout;
4625
- };
4626
-
4627
- function clearErrors() {
4628
- var k = Object.keys(glErrorShadow_);
4629
- for (var ii = 0; ii < k.length; ++ii) {
4630
- delete glErrorShadow_[k[ii]];
4631
- }
4632
- }
4633
-
4634
- function loseContextIfTime() {
4635
- ++numCalls_;
4636
- if (!contextLost_) {
4637
- if (numCallsToLoseContext_ == numCalls_) {
4638
- canvas.loseContext();
4639
- }
4640
- }
4641
- }
4642
-
4643
- // Makes a function that simulates WebGL when out of context.
4644
- function makeLostContextFunctionWrapper(ctx, functionName) {
4645
- var f = ctx[functionName];
4646
- return function() {
4647
- // log("calling:" + functionName);
4648
- // Only call the functions if the context is not lost.
4649
- loseContextIfTime();
4650
- if (!contextLost_) {
4651
- //if (!checkResources(arguments)) {
4652
- // glErrorShadow_[wrappedContext_.INVALID_OPERATION] = true;
4653
- // return;
4654
- //}
4655
- var result = f.apply(ctx, arguments);
4656
- return result;
4657
- }
4658
- };
4659
- }
4660
-
4661
- function freeResources() {
4662
- for (var ii = 0; ii < resourceDb_.length; ++ii) {
4663
- var resource = resourceDb_[ii];
4664
- if (resource instanceof WebGLBuffer) {
4665
- unwrappedContext_.deleteBuffer(resource);
4666
- } else if (resource instanceof WebGLFramebuffer) {
4667
- unwrappedContext_.deleteFramebuffer(resource);
4668
- } else if (resource instanceof WebGLProgram) {
4669
- unwrappedContext_.deleteProgram(resource);
4670
- } else if (resource instanceof WebGLRenderbuffer) {
4671
- unwrappedContext_.deleteRenderbuffer(resource);
4672
- } else if (resource instanceof WebGLShader) {
4673
- unwrappedContext_.deleteShader(resource);
4674
- } else if (resource instanceof WebGLTexture) {
4675
- unwrappedContext_.deleteTexture(resource);
4676
- }
4677
- else if (isWebGL2RenderingContext) {
4678
- if (resource instanceof WebGLQuery) {
4679
- unwrappedContext_.deleteQuery(resource);
4680
- } else if (resource instanceof WebGLSampler) {
4681
- unwrappedContext_.deleteSampler(resource);
4682
- } else if (resource instanceof WebGLSync) {
4683
- unwrappedContext_.deleteSync(resource);
4684
- } else if (resource instanceof WebGLTransformFeedback) {
4685
- unwrappedContext_.deleteTransformFeedback(resource);
4686
- } else if (resource instanceof WebGLVertexArrayObject) {
4687
- unwrappedContext_.deleteVertexArray(resource);
4688
- }
4689
- }
4690
- }
4691
- }
4692
-
4693
- function makeWebGLContextEvent(statusMessage) {
4694
- return {
4695
- statusMessage: statusMessage,
4696
- preventDefault: function() {
4697
- canRestore_ = true;
4698
- }
4699
- };
4700
- }
4701
-
4702
- return canvas;
4703
-
4704
- function makeLostContextSimulatingContext(ctx) {
4705
- // copy all functions and properties to wrapper
4706
- for (var propertyName in ctx) {
4707
- if (typeof ctx[propertyName] == 'function') {
4708
- wrappedContext_[propertyName] = makeLostContextFunctionWrapper(
4709
- ctx, propertyName);
4710
- } else {
4711
- makePropertyWrapper(wrappedContext_, ctx, propertyName);
4712
- }
4713
- }
4714
-
4715
- // Wrap a few functions specially.
4716
- wrappedContext_.getError = function() {
4717
- loseContextIfTime();
4718
- if (!contextLost_) {
4719
- var err;
4720
- while (err = unwrappedContext_.getError()) {
4721
- glErrorShadow_[err] = true;
4722
- }
4723
- }
4724
- for (var err in glErrorShadow_) {
4725
- if (glErrorShadow_[err]) {
4726
- delete glErrorShadow_[err];
4727
- return err;
4728
- }
4729
- }
4730
- return wrappedContext_.NO_ERROR;
4731
- };
4732
-
4733
- var creationFunctions = [
4734
- "createBuffer",
4735
- "createFramebuffer",
4736
- "createProgram",
4737
- "createRenderbuffer",
4738
- "createShader",
4739
- "createTexture"
4740
- ];
4741
- if (isWebGL2RenderingContext) {
4742
- creationFunctions.push(
4743
- "createQuery",
4744
- "createSampler",
4745
- "fenceSync",
4746
- "createTransformFeedback",
4747
- "createVertexArray"
4748
- );
4749
- }
4750
- for (var ii = 0; ii < creationFunctions.length; ++ii) {
4751
- var functionName = creationFunctions[ii];
4752
- wrappedContext_[functionName] = function(f) {
4753
- return function() {
4754
- loseContextIfTime();
4755
- if (contextLost_) {
4756
- return null;
4757
- }
4758
- var obj = f.apply(ctx, arguments);
4759
- obj.__webglDebugContextLostId__ = contextId_;
4760
- resourceDb_.push(obj);
4761
- return obj;
4762
- };
4763
- }(ctx[functionName]);
4764
- }
4765
-
4766
- var functionsThatShouldReturnNull = [
4767
- "getActiveAttrib",
4768
- "getActiveUniform",
4769
- "getBufferParameter",
4770
- "getContextAttributes",
4771
- "getAttachedShaders",
4772
- "getFramebufferAttachmentParameter",
4773
- "getParameter",
4774
- "getProgramParameter",
4775
- "getProgramInfoLog",
4776
- "getRenderbufferParameter",
4777
- "getShaderParameter",
4778
- "getShaderInfoLog",
4779
- "getShaderSource",
4780
- "getTexParameter",
4781
- "getUniform",
4782
- "getUniformLocation",
4783
- "getVertexAttrib"
4784
- ];
4785
- if (isWebGL2RenderingContext) {
4786
- functionsThatShouldReturnNull.push(
4787
- "getInternalformatParameter",
4788
- "getQuery",
4789
- "getQueryParameter",
4790
- "getSamplerParameter",
4791
- "getSyncParameter",
4792
- "getTransformFeedbackVarying",
4793
- "getIndexedParameter",
4794
- "getUniformIndices",
4795
- "getActiveUniforms",
4796
- "getActiveUniformBlockParameter",
4797
- "getActiveUniformBlockName"
4798
- );
4799
- }
4800
- for (var ii = 0; ii < functionsThatShouldReturnNull.length; ++ii) {
4801
- var functionName = functionsThatShouldReturnNull[ii];
4802
- wrappedContext_[functionName] = function(f) {
4803
- return function() {
4804
- loseContextIfTime();
4805
- if (contextLost_) {
4806
- return null;
4807
- }
4808
- return f.apply(ctx, arguments);
4809
- }
4810
- }(wrappedContext_[functionName]);
4811
- }
4812
-
4813
- var isFunctions = [
4814
- "isBuffer",
4815
- "isEnabled",
4816
- "isFramebuffer",
4817
- "isProgram",
4818
- "isRenderbuffer",
4819
- "isShader",
4820
- "isTexture"
4821
- ];
4822
- if (isWebGL2RenderingContext) {
4823
- isFunctions.push(
4824
- "isQuery",
4825
- "isSampler",
4826
- "isSync",
4827
- "isTransformFeedback",
4828
- "isVertexArray"
4829
- );
4830
- }
4831
- for (var ii = 0; ii < isFunctions.length; ++ii) {
4832
- var functionName = isFunctions[ii];
4833
- wrappedContext_[functionName] = function(f) {
4834
- return function() {
4835
- loseContextIfTime();
4836
- if (contextLost_) {
4837
- return false;
4838
- }
4839
- return f.apply(ctx, arguments);
4840
- }
4841
- }(wrappedContext_[functionName]);
4842
- }
4843
-
4844
- wrappedContext_.checkFramebufferStatus = function(f) {
4845
- return function() {
4846
- loseContextIfTime();
4847
- if (contextLost_) {
4848
- return wrappedContext_.FRAMEBUFFER_UNSUPPORTED;
4849
- }
4850
- return f.apply(ctx, arguments);
4851
- };
4852
- }(wrappedContext_.checkFramebufferStatus);
4853
-
4854
- wrappedContext_.getAttribLocation = function(f) {
4855
- return function() {
4856
- loseContextIfTime();
4857
- if (contextLost_) {
4858
- return -1;
4859
- }
4860
- return f.apply(ctx, arguments);
4861
- };
4862
- }(wrappedContext_.getAttribLocation);
4863
-
4864
- wrappedContext_.getVertexAttribOffset = function(f) {
4865
- return function() {
4866
- loseContextIfTime();
4867
- if (contextLost_) {
4868
- return 0;
4869
- }
4870
- return f.apply(ctx, arguments);
4871
- };
4872
- }(wrappedContext_.getVertexAttribOffset);
4873
-
4874
- wrappedContext_.isContextLost = function() {
4875
- return contextLost_;
4876
- };
4877
-
4878
- if (isWebGL2RenderingContext) {
4879
- wrappedContext_.getFragDataLocation = function(f) {
4880
- return function() {
4881
- loseContextIfTime();
4882
- if (contextLost_) {
4883
- return -1;
4884
- }
4885
- return f.apply(ctx, arguments);
4886
- };
4887
- }(wrappedContext_.getFragDataLocation);
4888
-
4889
- wrappedContext_.clientWaitSync = function(f) {
4890
- return function() {
4891
- loseContextIfTime();
4892
- if (contextLost_) {
4893
- return wrappedContext_.WAIT_FAILED;
4894
- }
4895
- return f.apply(ctx, arguments);
4896
- };
4897
- }(wrappedContext_.clientWaitSync);
4898
-
4899
- wrappedContext_.getUniformBlockIndex = function(f) {
4900
- return function() {
4901
- loseContextIfTime();
4902
- if (contextLost_) {
4903
- return wrappedContext_.INVALID_INDEX;
4904
- }
4905
- return f.apply(ctx, arguments);
4906
- };
4907
- }(wrappedContext_.getUniformBlockIndex);
4908
- }
4909
-
4910
- return wrappedContext_;
4911
- }
4912
- }
4913
-
4914
- return {
4915
- /**
4916
- * Initializes this module. Safe to call more than once.
4917
- * @param {!WebGLRenderingContext} ctx A WebGL context. If
4918
- * you have more than one context it doesn't matter which one
4919
- * you pass in, it is only used to pull out constants.
4920
- */
4921
- 'init': init,
4922
-
4923
- /**
4924
- * Returns true or false if value matches any WebGL enum
4925
- * @param {*} value Value to check if it might be an enum.
4926
- * @return {boolean} True if value matches one of the WebGL defined enums
4927
- */
4928
- 'mightBeEnum': mightBeEnum,
4929
-
4930
- /**
4931
- * Gets an string version of an WebGL enum.
4932
- *
4933
- * Example:
4934
- * WebGLDebugUtil.init(ctx);
4935
- * var str = WebGLDebugUtil.glEnumToString(ctx.getError());
4936
- *
4937
- * @param {number} value Value to return an enum for
4938
- * @return {string} The string version of the enum.
4939
- */
4940
- 'glEnumToString': glEnumToString,
4941
-
4942
- /**
4943
- * Converts the argument of a WebGL function to a string.
4944
- * Attempts to convert enum arguments to strings.
4945
- *
4946
- * Example:
4947
- * WebGLDebugUtil.init(ctx);
4948
- * var str = WebGLDebugUtil.glFunctionArgToString('bindTexture', 2, 0, gl.TEXTURE_2D);
4949
- *
4950
- * would return 'TEXTURE_2D'
4951
- *
4952
- * @param {string} functionName the name of the WebGL function.
4953
- * @param {number} numArgs The number of arguments
4954
- * @param {number} argumentIndx the index of the argument.
4955
- * @param {*} value The value of the argument.
4956
- * @return {string} The value as a string.
4957
- */
4958
- 'glFunctionArgToString': glFunctionArgToString,
4959
-
4960
- /**
4961
- * Converts the arguments of a WebGL function to a string.
4962
- * Attempts to convert enum arguments to strings.
4963
- *
4964
- * @param {string} functionName the name of the WebGL function.
4965
- * @param {number} args The arguments.
4966
- * @return {string} The arguments as a string.
4967
- */
4968
- 'glFunctionArgsToString': glFunctionArgsToString,
4969
-
4970
- /**
4971
- * Given a WebGL context returns a wrapped context that calls
4972
- * gl.getError after every command and calls a function if the
4973
- * result is not NO_ERROR.
4974
- *
4975
- * You can supply your own function if you want. For example, if you'd like
4976
- * an exception thrown on any GL error you could do this
4977
- *
4978
- * function throwOnGLError(err, funcName, args) {
4979
- * throw WebGLDebugUtils.glEnumToString(err) +
4980
- * " was caused by call to " + funcName;
4981
- * };
4982
- *
4983
- * ctx = WebGLDebugUtils.makeDebugContext(
4984
- * canvas.getContext("webgl"), throwOnGLError);
4985
- *
4986
- * @param {!WebGLRenderingContext} ctx The webgl context to wrap.
4987
- * @param {!function(err, funcName, args): void} opt_onErrorFunc The function
4988
- * to call when gl.getError returns an error. If not specified the default
4989
- * function calls console.log with a message.
4990
- * @param {!function(funcName, args): void} opt_onFunc The
4991
- * function to call when each webgl function is called. You
4992
- * can use this to log all calls for example.
4993
- */
4994
- 'makeDebugContext': makeDebugContext,
4995
-
4996
- /**
4997
- * Given a canvas element returns a wrapped canvas element that will
4998
- * simulate lost context. The canvas returned adds the following functions.
4999
- *
5000
- * loseContext:
5001
- * simulates a lost context event.
5002
- *
5003
- * restoreContext:
5004
- * simulates the context being restored.
5005
- *
5006
- * lostContextInNCalls:
5007
- * loses the context after N gl calls.
5008
- *
5009
- * getNumCalls:
5010
- * tells you how many gl calls there have been so far.
5011
- *
5012
- * setRestoreTimeout:
5013
- * sets the number of milliseconds until the context is restored
5014
- * after it has been lost. Defaults to 0. Pass -1 to prevent
5015
- * automatic restoring.
5016
- *
5017
- * @param {!Canvas} canvas The canvas element to wrap.
5018
- */
5019
- 'makeLostContextSimulatingCanvas': makeLostContextSimulatingCanvas,
5020
-
5021
- /**
5022
- * Resets a context to the initial state.
5023
- * @param {!WebGLRenderingContext} ctx The webgl context to
5024
- * reset.
5025
- */
5026
- 'resetToInitialState': resetToInitialState
5027
- };
5028
-
4069
+ /*
4070
+ ** Copyright (c) 2012 The Khronos Group Inc.
4071
+ **
4072
+ ** Permission is hereby granted, free of charge, to any person obtaining a
4073
+ ** copy of this software and/or associated documentation files (the
4074
+ ** "Materials"), to deal in the Materials without restriction, including
4075
+ ** without limitation the rights to use, copy, modify, merge, publish,
4076
+ ** distribute, sublicense, and/or sell copies of the Materials, and to
4077
+ ** permit persons to whom the Materials are furnished to do so, subject to
4078
+ ** the following conditions:
4079
+ **
4080
+ ** The above copyright notice and this permission notice shall be included
4081
+ ** in all copies or substantial portions of the Materials.
4082
+ **
4083
+ ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4084
+ ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4085
+ ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
4086
+ ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
4087
+ ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
4088
+ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
4089
+ ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
4090
+ */
4091
+
4092
+ // Various functions for helping debug WebGL apps.
4093
+
4094
+ const WebGLDebugUtils = function() {
4095
+
4096
+ /**
4097
+ * Wrapped logging function.
4098
+ * @param {string} msg Message to log.
4099
+ */
4100
+ var log = function(msg) {
4101
+ if (window.console && window.console.log) {
4102
+ window.console.log(msg);
4103
+ }
4104
+ };
4105
+
4106
+ /**
4107
+ * Wrapped error logging function.
4108
+ * @param {string} msg Message to log.
4109
+ */
4110
+ var error = function(msg) {
4111
+ if (window.console && window.console.error) {
4112
+ window.console.error(msg);
4113
+ } else {
4114
+ log(msg);
4115
+ }
4116
+ };
4117
+
4118
+
4119
+ /**
4120
+ * Which arguments are enums based on the number of arguments to the function.
4121
+ * So
4122
+ * 'texImage2D': {
4123
+ * 9: { 0:true, 2:true, 6:true, 7:true },
4124
+ * 6: { 0:true, 2:true, 3:true, 4:true },
4125
+ * },
4126
+ *
4127
+ * means if there are 9 arguments then 6 and 7 are enums, if there are 6
4128
+ * arguments 3 and 4 are enums
4129
+ *
4130
+ * @type {!Object.<number, !Object.<number, string>}
4131
+ */
4132
+ var glValidEnumContexts = {
4133
+ // Generic setters and getters
4134
+
4135
+ 'enable': {1: { 0:true }},
4136
+ 'disable': {1: { 0:true }},
4137
+ 'getParameter': {1: { 0:true }},
4138
+
4139
+ // Rendering
4140
+
4141
+ 'drawArrays': {3:{ 0:true }},
4142
+ 'drawElements': {4:{ 0:true, 2:true }},
4143
+
4144
+ // Shaders
4145
+
4146
+ 'createShader': {1: { 0:true }},
4147
+ 'getShaderParameter': {2: { 1:true }},
4148
+ 'getProgramParameter': {2: { 1:true }},
4149
+ 'getShaderPrecisionFormat': {2: { 0: true, 1:true }},
4150
+
4151
+ // Vertex attributes
4152
+
4153
+ 'getVertexAttrib': {2: { 1:true }},
4154
+ 'vertexAttribPointer': {6: { 2:true }},
4155
+
4156
+ // Textures
4157
+
4158
+ 'bindTexture': {2: { 0:true }},
4159
+ 'activeTexture': {1: { 0:true }},
4160
+ 'getTexParameter': {2: { 0:true, 1:true }},
4161
+ 'texParameterf': {3: { 0:true, 1:true }},
4162
+ 'texParameteri': {3: { 0:true, 1:true, 2:true }},
4163
+ // texImage2D and texSubImage2D are defined below with WebGL 2 entrypoints
4164
+ 'copyTexImage2D': {8: { 0:true, 2:true }},
4165
+ 'copyTexSubImage2D': {8: { 0:true }},
4166
+ 'generateMipmap': {1: { 0:true }},
4167
+ // compressedTexImage2D and compressedTexSubImage2D are defined below with WebGL 2 entrypoints
4168
+
4169
+ // Buffer objects
4170
+
4171
+ 'bindBuffer': {2: { 0:true }},
4172
+ // bufferData and bufferSubData are defined below with WebGL 2 entrypoints
4173
+ 'getBufferParameter': {2: { 0:true, 1:true }},
4174
+
4175
+ // Renderbuffers and framebuffers
4176
+
4177
+ 'pixelStorei': {2: { 0:true, 1:true }},
4178
+ // readPixels is defined below with WebGL 2 entrypoints
4179
+ 'bindRenderbuffer': {2: { 0:true }},
4180
+ 'bindFramebuffer': {2: { 0:true }},
4181
+ 'checkFramebufferStatus': {1: { 0:true }},
4182
+ 'framebufferRenderbuffer': {4: { 0:true, 1:true, 2:true }},
4183
+ 'framebufferTexture2D': {5: { 0:true, 1:true, 2:true }},
4184
+ 'getFramebufferAttachmentParameter': {3: { 0:true, 1:true, 2:true }},
4185
+ 'getRenderbufferParameter': {2: { 0:true, 1:true }},
4186
+ 'renderbufferStorage': {4: { 0:true, 1:true }},
4187
+
4188
+ // Frame buffer operations (clear, blend, depth test, stencil)
4189
+
4190
+ 'clear': {1: { 0: { 'enumBitwiseOr': ['COLOR_BUFFER_BIT', 'DEPTH_BUFFER_BIT', 'STENCIL_BUFFER_BIT'] }}},
4191
+ 'depthFunc': {1: { 0:true }},
4192
+ 'blendFunc': {2: { 0:true, 1:true }},
4193
+ 'blendFuncSeparate': {4: { 0:true, 1:true, 2:true, 3:true }},
4194
+ 'blendEquation': {1: { 0:true }},
4195
+ 'blendEquationSeparate': {2: { 0:true, 1:true }},
4196
+ 'stencilFunc': {3: { 0:true }},
4197
+ 'stencilFuncSeparate': {4: { 0:true, 1:true }},
4198
+ 'stencilMaskSeparate': {2: { 0:true }},
4199
+ 'stencilOp': {3: { 0:true, 1:true, 2:true }},
4200
+ 'stencilOpSeparate': {4: { 0:true, 1:true, 2:true, 3:true }},
4201
+
4202
+ // Culling
4203
+
4204
+ 'cullFace': {1: { 0:true }},
4205
+ 'frontFace': {1: { 0:true }},
4206
+
4207
+ // ANGLE_instanced_arrays extension
4208
+
4209
+ 'drawArraysInstancedANGLE': {4: { 0:true }},
4210
+ 'drawElementsInstancedANGLE': {5: { 0:true, 2:true }},
4211
+
4212
+ // EXT_blend_minmax extension
4213
+
4214
+ 'blendEquationEXT': {1: { 0:true }},
4215
+
4216
+ // WebGL 2 Buffer objects
4217
+
4218
+ 'bufferData': {
4219
+ 3: { 0:true, 2:true }, // WebGL 1
4220
+ 4: { 0:true, 2:true }, // WebGL 2
4221
+ 5: { 0:true, 2:true } // WebGL 2
4222
+ },
4223
+ 'bufferSubData': {
4224
+ 3: { 0:true }, // WebGL 1
4225
+ 4: { 0:true }, // WebGL 2
4226
+ 5: { 0:true } // WebGL 2
4227
+ },
4228
+ 'copyBufferSubData': {5: { 0:true, 1:true }},
4229
+ 'getBufferSubData': {3: { 0:true }, 4: { 0:true }, 5: { 0:true }},
4230
+
4231
+ // WebGL 2 Framebuffer objects
4232
+
4233
+ 'blitFramebuffer': {10: { 8: { 'enumBitwiseOr': ['COLOR_BUFFER_BIT', 'DEPTH_BUFFER_BIT', 'STENCIL_BUFFER_BIT'] }, 9:true }},
4234
+ 'framebufferTextureLayer': {5: { 0:true, 1:true }},
4235
+ 'invalidateFramebuffer': {2: { 0:true }},
4236
+ 'invalidateSubFramebuffer': {6: { 0:true }},
4237
+ 'readBuffer': {1: { 0:true }},
4238
+
4239
+ // WebGL 2 Renderbuffer objects
4240
+
4241
+ 'getInternalformatParameter': {3: { 0:true, 1:true, 2:true }},
4242
+ 'renderbufferStorageMultisample': {5: { 0:true, 2:true }},
4243
+
4244
+ // WebGL 2 Texture objects
4245
+
4246
+ 'texStorage2D': {5: { 0:true, 2:true }},
4247
+ 'texStorage3D': {6: { 0:true, 2:true }},
4248
+ 'texImage2D': {
4249
+ 9: { 0:true, 2:true, 6:true, 7:true }, // WebGL 1 & 2
4250
+ 6: { 0:true, 2:true, 3:true, 4:true }, // WebGL 1
4251
+ 10: { 0:true, 2:true, 6:true, 7:true } // WebGL 2
4252
+ },
4253
+ 'texImage3D': {
4254
+ 10: { 0:true, 2:true, 7:true, 8:true },
4255
+ 11: { 0:true, 2:true, 7:true, 8:true }
4256
+ },
4257
+ 'texSubImage2D': {
4258
+ 9: { 0:true, 6:true, 7:true }, // WebGL 1 & 2
4259
+ 7: { 0:true, 4:true, 5:true }, // WebGL 1
4260
+ 10: { 0:true, 6:true, 7:true } // WebGL 2
4261
+ },
4262
+ 'texSubImage3D': {
4263
+ 11: { 0:true, 8:true, 9:true },
4264
+ 12: { 0:true, 8:true, 9:true }
4265
+ },
4266
+ 'copyTexSubImage3D': {9: { 0:true }},
4267
+ 'compressedTexImage2D': {
4268
+ 7: { 0: true, 2:true }, // WebGL 1 & 2
4269
+ 8: { 0: true, 2:true }, // WebGL 2
4270
+ 9: { 0: true, 2:true } // WebGL 2
4271
+ },
4272
+ 'compressedTexImage3D': {
4273
+ 8: { 0: true, 2:true },
4274
+ 9: { 0: true, 2:true },
4275
+ 10: { 0: true, 2:true }
4276
+ },
4277
+ 'compressedTexSubImage2D': {
4278
+ 8: { 0: true, 6:true }, // WebGL 1 & 2
4279
+ 9: { 0: true, 6:true }, // WebGL 2
4280
+ 10: { 0: true, 6:true } // WebGL 2
4281
+ },
4282
+ 'compressedTexSubImage3D': {
4283
+ 10: { 0: true, 8:true },
4284
+ 11: { 0: true, 8:true },
4285
+ 12: { 0: true, 8:true }
4286
+ },
4287
+
4288
+ // WebGL 2 Vertex attribs
4289
+
4290
+ 'vertexAttribIPointer': {5: { 2:true }},
4291
+
4292
+ // WebGL 2 Writing to the drawing buffer
4293
+
4294
+ 'drawArraysInstanced': {4: { 0:true }},
4295
+ 'drawElementsInstanced': {5: { 0:true, 2:true }},
4296
+ 'drawRangeElements': {6: { 0:true, 4:true }},
4297
+
4298
+ // WebGL 2 Reading back pixels
4299
+
4300
+ 'readPixels': {
4301
+ 7: { 4:true, 5:true }, // WebGL 1 & 2
4302
+ 8: { 4:true, 5:true } // WebGL 2
4303
+ },
4304
+
4305
+ // WebGL 2 Multiple Render Targets
4306
+
4307
+ 'clearBufferfv': {3: { 0:true }, 4: { 0:true }},
4308
+ 'clearBufferiv': {3: { 0:true }, 4: { 0:true }},
4309
+ 'clearBufferuiv': {3: { 0:true }, 4: { 0:true }},
4310
+ 'clearBufferfi': {4: { 0:true }},
4311
+
4312
+ // WebGL 2 Query objects
4313
+
4314
+ 'beginQuery': {2: { 0:true }},
4315
+ 'endQuery': {1: { 0:true }},
4316
+ 'getQuery': {2: { 0:true, 1:true }},
4317
+ 'getQueryParameter': {2: { 1:true }},
4318
+
4319
+ // WebGL 2 Sampler objects
4320
+
4321
+ 'samplerParameteri': {3: { 1:true, 2:true }},
4322
+ 'samplerParameterf': {3: { 1:true }},
4323
+ 'getSamplerParameter': {2: { 1:true }},
4324
+
4325
+ // WebGL 2 Sync objects
4326
+
4327
+ 'fenceSync': {2: { 0:true, 1: { 'enumBitwiseOr': [] } }},
4328
+ 'clientWaitSync': {3: { 1: { 'enumBitwiseOr': ['SYNC_FLUSH_COMMANDS_BIT'] } }},
4329
+ 'waitSync': {3: { 1: { 'enumBitwiseOr': [] } }},
4330
+ 'getSyncParameter': {2: { 1:true }},
4331
+
4332
+ // WebGL 2 Transform Feedback
4333
+
4334
+ 'bindTransformFeedback': {2: { 0:true }},
4335
+ 'beginTransformFeedback': {1: { 0:true }},
4336
+ 'transformFeedbackVaryings': {3: { 2:true }},
4337
+
4338
+ // WebGL2 Uniform Buffer Objects and Transform Feedback Buffers
4339
+
4340
+ 'bindBufferBase': {3: { 0:true }},
4341
+ 'bindBufferRange': {5: { 0:true }},
4342
+ 'getIndexedParameter': {2: { 0:true }},
4343
+ 'getActiveUniforms': {3: { 2:true }},
4344
+ 'getActiveUniformBlockParameter': {3: { 2:true }}
4345
+ };
4346
+
4347
+ /**
4348
+ * Map of numbers to names.
4349
+ * @type {Object}
4350
+ */
4351
+ var glEnums = null;
4352
+
4353
+ /**
4354
+ * Map of names to numbers.
4355
+ * @type {Object}
4356
+ */
4357
+ var enumStringToValue = null;
4358
+
4359
+ /**
4360
+ * Initializes this module. Safe to call more than once.
4361
+ * @param {!WebGLRenderingContext} ctx A WebGL context. If
4362
+ * you have more than one context it doesn't matter which one
4363
+ * you pass in, it is only used to pull out constants.
4364
+ */
4365
+ function init(ctx) {
4366
+ if (glEnums == null) {
4367
+ glEnums = { };
4368
+ enumStringToValue = { };
4369
+ for (var propertyName in ctx) {
4370
+ if (typeof ctx[propertyName] == 'number') {
4371
+ glEnums[ctx[propertyName]] = propertyName;
4372
+ enumStringToValue[propertyName] = ctx[propertyName];
4373
+ }
4374
+ }
4375
+ }
4376
+ }
4377
+
4378
+ /**
4379
+ * Checks the utils have been initialized.
4380
+ */
4381
+ function checkInit() {
4382
+ if (glEnums == null) {
4383
+ throw 'WebGLDebugUtils.init(ctx) not called';
4384
+ }
4385
+ }
4386
+
4387
+ /**
4388
+ * Returns true or false if value matches any WebGL enum
4389
+ * @param {*} value Value to check if it might be an enum.
4390
+ * @return {boolean} True if value matches one of the WebGL defined enums
4391
+ */
4392
+ function mightBeEnum(value) {
4393
+ checkInit();
4394
+ return (glEnums[value] !== undefined);
4395
+ }
4396
+
4397
+ /**
4398
+ * Gets an string version of an WebGL enum.
4399
+ *
4400
+ * Example:
4401
+ * var str = WebGLDebugUtil.glEnumToString(ctx.getError());
4402
+ *
4403
+ * @param {number} value Value to return an enum for
4404
+ * @return {string} The string version of the enum.
4405
+ */
4406
+ function glEnumToString(value) {
4407
+ checkInit();
4408
+ var name = glEnums[value];
4409
+ return (name !== undefined) ? ("gl." + name) :
4410
+ ("/*UNKNOWN WebGL ENUM*/ 0x" + value.toString(16) + "");
4411
+ }
4412
+
4413
+ /**
4414
+ * Returns the string version of a WebGL argument.
4415
+ * Attempts to convert enum arguments to strings.
4416
+ * @param {string} functionName the name of the WebGL function.
4417
+ * @param {number} numArgs the number of arguments passed to the function.
4418
+ * @param {number} argumentIndx the index of the argument.
4419
+ * @param {*} value The value of the argument.
4420
+ * @return {string} The value as a string.
4421
+ */
4422
+ function glFunctionArgToString(functionName, numArgs, argumentIndex, value) {
4423
+ var funcInfo = glValidEnumContexts[functionName];
4424
+ if (funcInfo !== undefined) {
4425
+ var funcInfo = funcInfo[numArgs];
4426
+ if (funcInfo !== undefined) {
4427
+ if (funcInfo[argumentIndex]) {
4428
+ if (typeof funcInfo[argumentIndex] === 'object' &&
4429
+ funcInfo[argumentIndex]['enumBitwiseOr'] !== undefined) {
4430
+ var enums = funcInfo[argumentIndex]['enumBitwiseOr'];
4431
+ var orResult = 0;
4432
+ var orEnums = [];
4433
+ for (var i = 0; i < enums.length; ++i) {
4434
+ var enumValue = enumStringToValue[enums[i]];
4435
+ if ((value & enumValue) !== 0) {
4436
+ orResult |= enumValue;
4437
+ orEnums.push(glEnumToString(enumValue));
4438
+ }
4439
+ }
4440
+ if (orResult === value) {
4441
+ return orEnums.join(' | ');
4442
+ } else {
4443
+ return glEnumToString(value);
4444
+ }
4445
+ } else {
4446
+ return glEnumToString(value);
4447
+ }
4448
+ }
4449
+ }
4450
+ }
4451
+ if (value === null) {
4452
+ return "null";
4453
+ } else if (value === undefined) {
4454
+ return "undefined";
4455
+ } else {
4456
+ return value.toString();
4457
+ }
4458
+ }
4459
+
4460
+ /**
4461
+ * Converts the arguments of a WebGL function to a string.
4462
+ * Attempts to convert enum arguments to strings.
4463
+ *
4464
+ * @param {string} functionName the name of the WebGL function.
4465
+ * @param {Array<*>} args The arguments.
4466
+ * @return {string} The arguments as a string.
4467
+ */
4468
+ function glFunctionArgsToString(functionName, args) {
4469
+ // apparently we can't do args.join(",");
4470
+ var argStr = "";
4471
+ var numArgs = args.length;
4472
+ for (var ii = 0; ii < numArgs; ++ii) {
4473
+ argStr += ((ii == 0) ? '' : ', ') +
4474
+ glFunctionArgToString(functionName, numArgs, ii, args[ii]);
4475
+ }
4476
+ return argStr;
4477
+ }
4478
+
4479
+ function makePropertyWrapper(wrapper, original, propertyName) {
4480
+ //log("wrap prop: " + propertyName);
4481
+ wrapper.__defineGetter__(propertyName, function() {
4482
+ return original[propertyName];
4483
+ });
4484
+ // TODO(gmane): this needs to handle properties that take more than
4485
+ // one value?
4486
+ wrapper.__defineSetter__(propertyName, function(value) {
4487
+ //log("set: " + propertyName);
4488
+ original[propertyName] = value;
4489
+ });
4490
+ }
4491
+
4492
+ /**
4493
+ * Given a WebGL context returns a wrapped context that calls
4494
+ * gl.getError after every command and calls a function if the
4495
+ * result is not gl.NO_ERROR.
4496
+ *
4497
+ * @param {!WebGLRenderingContext} ctx The webgl context to
4498
+ * wrap.
4499
+ * @param {!function(err, funcName, args): void} opt_onErrorFunc
4500
+ * The function to call when gl.getError returns an
4501
+ * error. If not specified the default function calls
4502
+ * console.log with a message.
4503
+ * @param {!function(funcName, args): void} opt_onFunc The
4504
+ * function to call when each webgl function is called.
4505
+ * You can use this to log all calls for example.
4506
+ * @param {!WebGLRenderingContext} opt_err_ctx The webgl context
4507
+ * to call getError on if different than ctx.
4508
+ */
4509
+ function makeDebugContext(ctx, opt_onErrorFunc, opt_onFunc, opt_err_ctx) {
4510
+ opt_err_ctx = opt_err_ctx || ctx;
4511
+ init(ctx);
4512
+ opt_onErrorFunc = opt_onErrorFunc || function(err, functionName, args) {
4513
+ // apparently we can't do args.join(",");
4514
+ var argStr = "";
4515
+ var numArgs = args.length;
4516
+ for (var ii = 0; ii < numArgs; ++ii) {
4517
+ argStr += ((ii == 0) ? '' : ', ') +
4518
+ glFunctionArgToString(functionName, numArgs, ii, args[ii]);
4519
+ }
4520
+ error("WebGL error "+ glEnumToString(err) + " in "+ functionName +
4521
+ "(" + argStr + ")");
4522
+ };
4523
+
4524
+ // Holds booleans for each GL error so after we get the error ourselves
4525
+ // we can still return it to the client app.
4526
+ var glErrorShadow = { };
4527
+
4528
+ // Makes a function that calls a WebGL function and then calls getError.
4529
+ function makeErrorWrapper(ctx, functionName) {
4530
+ return function() {
4531
+ if (opt_onFunc) {
4532
+ opt_onFunc(functionName, arguments);
4533
+ }
4534
+ var result = ctx[functionName].apply(ctx, arguments);
4535
+ var err = opt_err_ctx.getError();
4536
+ if (err != 0) {
4537
+ glErrorShadow[err] = true;
4538
+ opt_onErrorFunc(err, functionName, arguments);
4539
+ }
4540
+ return result;
4541
+ };
4542
+ }
4543
+
4544
+ // Make a an object that has a copy of every property of the WebGL context
4545
+ // but wraps all functions.
4546
+ var wrapper = {};
4547
+ for (var propertyName in ctx) {
4548
+ if (typeof ctx[propertyName] == 'function') {
4549
+ if (propertyName != 'getExtension') {
4550
+ wrapper[propertyName] = makeErrorWrapper(ctx, propertyName);
4551
+ } else {
4552
+ var wrapped = makeErrorWrapper(ctx, propertyName);
4553
+ wrapper[propertyName] = function () {
4554
+ var result = wrapped.apply(ctx, arguments);
4555
+ if (!result) {
4556
+ return null;
4557
+ }
4558
+ return makeDebugContext(result, opt_onErrorFunc, opt_onFunc, opt_err_ctx);
4559
+ };
4560
+ }
4561
+ } else {
4562
+ makePropertyWrapper(wrapper, ctx, propertyName);
4563
+ }
4564
+ }
4565
+
4566
+ // Override the getError function with one that returns our saved results.
4567
+ wrapper.getError = function() {
4568
+ for (var err in glErrorShadow) {
4569
+ if (glErrorShadow.hasOwnProperty(err)) {
4570
+ if (glErrorShadow[err]) {
4571
+ glErrorShadow[err] = false;
4572
+ return err;
4573
+ }
4574
+ }
4575
+ }
4576
+ return ctx.NO_ERROR;
4577
+ };
4578
+
4579
+ return wrapper;
4580
+ }
4581
+
4582
+ function resetToInitialState(ctx) {
4583
+ var isWebGL2RenderingContext = !!ctx.createTransformFeedback;
4584
+
4585
+ if (isWebGL2RenderingContext) {
4586
+ ctx.bindVertexArray(null);
4587
+ }
4588
+
4589
+ var numAttribs = ctx.getParameter(ctx.MAX_VERTEX_ATTRIBS);
4590
+ var tmp = ctx.createBuffer();
4591
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, tmp);
4592
+ for (var ii = 0; ii < numAttribs; ++ii) {
4593
+ ctx.disableVertexAttribArray(ii);
4594
+ ctx.vertexAttribPointer(ii, 4, ctx.FLOAT, false, 0, 0);
4595
+ ctx.vertexAttrib1f(ii, 0);
4596
+ if (isWebGL2RenderingContext) {
4597
+ ctx.vertexAttribDivisor(ii, 0);
4598
+ }
4599
+ }
4600
+ ctx.deleteBuffer(tmp);
4601
+
4602
+ var numTextureUnits = ctx.getParameter(ctx.MAX_TEXTURE_IMAGE_UNITS);
4603
+ for (var ii = 0; ii < numTextureUnits; ++ii) {
4604
+ ctx.activeTexture(ctx.TEXTURE0 + ii);
4605
+ ctx.bindTexture(ctx.TEXTURE_CUBE_MAP, null);
4606
+ ctx.bindTexture(ctx.TEXTURE_2D, null);
4607
+ if (isWebGL2RenderingContext) {
4608
+ ctx.bindTexture(ctx.TEXTURE_2D_ARRAY, null);
4609
+ ctx.bindTexture(ctx.TEXTURE_3D, null);
4610
+ ctx.bindSampler(ii, null);
4611
+ }
4612
+ }
4613
+
4614
+ ctx.activeTexture(ctx.TEXTURE0);
4615
+ ctx.useProgram(null);
4616
+ ctx.bindBuffer(ctx.ARRAY_BUFFER, null);
4617
+ ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null);
4618
+ ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
4619
+ ctx.bindRenderbuffer(ctx.RENDERBUFFER, null);
4620
+ ctx.disable(ctx.BLEND);
4621
+ ctx.disable(ctx.CULL_FACE);
4622
+ ctx.disable(ctx.DEPTH_TEST);
4623
+ ctx.disable(ctx.DITHER);
4624
+ ctx.disable(ctx.SCISSOR_TEST);
4625
+ ctx.blendColor(0, 0, 0, 0);
4626
+ ctx.blendEquation(ctx.FUNC_ADD);
4627
+ ctx.blendFunc(ctx.ONE, ctx.ZERO);
4628
+ ctx.clearColor(0, 0, 0, 0);
4629
+ ctx.clearDepth(1);
4630
+ ctx.clearStencil(-1);
4631
+ ctx.colorMask(true, true, true, true);
4632
+ ctx.cullFace(ctx.BACK);
4633
+ ctx.depthFunc(ctx.LESS);
4634
+ ctx.depthMask(true);
4635
+ ctx.depthRange(0, 1);
4636
+ ctx.frontFace(ctx.CCW);
4637
+ ctx.hint(ctx.GENERATE_MIPMAP_HINT, ctx.DONT_CARE);
4638
+ ctx.lineWidth(1);
4639
+ ctx.pixelStorei(ctx.PACK_ALIGNMENT, 4);
4640
+ ctx.pixelStorei(ctx.UNPACK_ALIGNMENT, 4);
4641
+ ctx.pixelStorei(ctx.UNPACK_FLIP_Y_WEBGL, false);
4642
+ ctx.pixelStorei(ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
4643
+ // TODO: Delete this IF.
4644
+ if (ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL) {
4645
+ ctx.pixelStorei(ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL, ctx.BROWSER_DEFAULT_WEBGL);
4646
+ }
4647
+ ctx.polygonOffset(0, 0);
4648
+ ctx.sampleCoverage(1, false);
4649
+ ctx.scissor(0, 0, ctx.canvas.width, ctx.canvas.height);
4650
+ ctx.stencilFunc(ctx.ALWAYS, 0, 0xFFFFFFFF);
4651
+ ctx.stencilMask(0xFFFFFFFF);
4652
+ ctx.stencilOp(ctx.KEEP, ctx.KEEP, ctx.KEEP);
4653
+ ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
4654
+ ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT | ctx.STENCIL_BUFFER_BIT);
4655
+
4656
+ if (isWebGL2RenderingContext) {
4657
+ ctx.drawBuffers([ctx.BACK]);
4658
+ ctx.readBuffer(ctx.BACK);
4659
+ ctx.bindBuffer(ctx.COPY_READ_BUFFER, null);
4660
+ ctx.bindBuffer(ctx.COPY_WRITE_BUFFER, null);
4661
+ ctx.bindBuffer(ctx.PIXEL_PACK_BUFFER, null);
4662
+ ctx.bindBuffer(ctx.PIXEL_UNPACK_BUFFER, null);
4663
+ var numTransformFeedbacks = ctx.getParameter(ctx.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
4664
+ for (var ii = 0; ii < numTransformFeedbacks; ++ii) {
4665
+ ctx.bindBufferBase(ctx.TRANSFORM_FEEDBACK_BUFFER, ii, null);
4666
+ }
4667
+ var numUBOs = ctx.getParameter(ctx.MAX_UNIFORM_BUFFER_BINDINGS);
4668
+ for (var ii = 0; ii < numUBOs; ++ii) {
4669
+ ctx.bindBufferBase(ctx.UNIFORM_BUFFER, ii, null);
4670
+ }
4671
+ ctx.disable(ctx.RASTERIZER_DISCARD);
4672
+ ctx.pixelStorei(ctx.UNPACK_IMAGE_HEIGHT, 0);
4673
+ ctx.pixelStorei(ctx.UNPACK_SKIP_IMAGES, 0);
4674
+ ctx.pixelStorei(ctx.UNPACK_ROW_LENGTH, 0);
4675
+ ctx.pixelStorei(ctx.UNPACK_SKIP_ROWS, 0);
4676
+ ctx.pixelStorei(ctx.UNPACK_SKIP_PIXELS, 0);
4677
+ ctx.pixelStorei(ctx.PACK_ROW_LENGTH, 0);
4678
+ ctx.pixelStorei(ctx.PACK_SKIP_ROWS, 0);
4679
+ ctx.pixelStorei(ctx.PACK_SKIP_PIXELS, 0);
4680
+ ctx.hint(ctx.FRAGMENT_SHADER_DERIVATIVE_HINT, ctx.DONT_CARE);
4681
+ }
4682
+
4683
+ // TODO: This should NOT be needed but Firefox fails with 'hint'
4684
+ while(ctx.getError());
4685
+ }
4686
+
4687
+ function makeLostContextSimulatingCanvas(canvas) {
4688
+ var unwrappedContext_;
4689
+ var wrappedContext_;
4690
+ var onLost_ = [];
4691
+ var onRestored_ = [];
4692
+ var wrappedContext_ = {};
4693
+ var contextId_ = 1;
4694
+ var contextLost_ = false;
4695
+ var resourceDb_ = [];
4696
+ var numCallsToLoseContext_ = 0;
4697
+ var numCalls_ = 0;
4698
+ var canRestore_ = false;
4699
+ var restoreTimeout_ = 0;
4700
+ var isWebGL2RenderingContext;
4701
+
4702
+ // Holds booleans for each GL error so can simulate errors.
4703
+ var glErrorShadow_ = { };
4704
+
4705
+ canvas.getContext = function(f) {
4706
+ return function() {
4707
+ var ctx = f.apply(canvas, arguments);
4708
+ // Did we get a context and is it a WebGL context?
4709
+ if ((ctx instanceof WebGLRenderingContext) || (window.WebGL2RenderingContext && (ctx instanceof WebGL2RenderingContext))) {
4710
+ if (ctx != unwrappedContext_) {
4711
+ if (unwrappedContext_) {
4712
+ throw "got different context"
4713
+ }
4714
+ isWebGL2RenderingContext = window.WebGL2RenderingContext && (ctx instanceof WebGL2RenderingContext);
4715
+ unwrappedContext_ = ctx;
4716
+ wrappedContext_ = makeLostContextSimulatingContext(unwrappedContext_);
4717
+ }
4718
+ return wrappedContext_;
4719
+ }
4720
+ return ctx;
4721
+ }
4722
+ }(canvas.getContext);
4723
+
4724
+ function wrapEvent(listener) {
4725
+ if (typeof(listener) == "function") {
4726
+ return listener;
4727
+ } else {
4728
+ return function(info) {
4729
+ listener.handleEvent(info);
4730
+ }
4731
+ }
4732
+ }
4733
+
4734
+ var addOnContextLostListener = function(listener) {
4735
+ onLost_.push(wrapEvent(listener));
4736
+ };
4737
+
4738
+ var addOnContextRestoredListener = function(listener) {
4739
+ onRestored_.push(wrapEvent(listener));
4740
+ };
4741
+
4742
+
4743
+ function wrapAddEventListener(canvas) {
4744
+ var f = canvas.addEventListener;
4745
+ canvas.addEventListener = function(type, listener, bubble) {
4746
+ switch (type) {
4747
+ case 'webglcontextlost':
4748
+ addOnContextLostListener(listener);
4749
+ break;
4750
+ case 'webglcontextrestored':
4751
+ addOnContextRestoredListener(listener);
4752
+ break;
4753
+ default:
4754
+ f.apply(canvas, arguments);
4755
+ }
4756
+ };
4757
+ }
4758
+
4759
+ wrapAddEventListener(canvas);
4760
+
4761
+ canvas.loseContext = function() {
4762
+ if (!contextLost_) {
4763
+ contextLost_ = true;
4764
+ numCallsToLoseContext_ = 0;
4765
+ ++contextId_;
4766
+ while (unwrappedContext_.getError());
4767
+ clearErrors();
4768
+ glErrorShadow_[unwrappedContext_.CONTEXT_LOST_WEBGL] = true;
4769
+ var event = makeWebGLContextEvent("context lost");
4770
+ var callbacks = onLost_.slice();
4771
+ setTimeout(function() {
4772
+ //log("numCallbacks:" + callbacks.length);
4773
+ for (var ii = 0; ii < callbacks.length; ++ii) {
4774
+ //log("calling callback:" + ii);
4775
+ callbacks[ii](event);
4776
+ }
4777
+ if (restoreTimeout_ >= 0) {
4778
+ setTimeout(function() {
4779
+ canvas.restoreContext();
4780
+ }, restoreTimeout_);
4781
+ }
4782
+ }, 0);
4783
+ }
4784
+ };
4785
+
4786
+ canvas.restoreContext = function() {
4787
+ if (contextLost_) {
4788
+ if (onRestored_.length) {
4789
+ setTimeout(function() {
4790
+ if (!canRestore_) {
4791
+ throw "can not restore. webglcontestlost listener did not call event.preventDefault";
4792
+ }
4793
+ freeResources();
4794
+ resetToInitialState(unwrappedContext_);
4795
+ contextLost_ = false;
4796
+ numCalls_ = 0;
4797
+ canRestore_ = false;
4798
+ var callbacks = onRestored_.slice();
4799
+ var event = makeWebGLContextEvent("context restored");
4800
+ for (var ii = 0; ii < callbacks.length; ++ii) {
4801
+ callbacks[ii](event);
4802
+ }
4803
+ }, 0);
4804
+ }
4805
+ }
4806
+ };
4807
+
4808
+ canvas.loseContextInNCalls = function(numCalls) {
4809
+ if (contextLost_) {
4810
+ throw "You can not ask a lost contet to be lost";
4811
+ }
4812
+ numCallsToLoseContext_ = numCalls_ + numCalls;
4813
+ };
4814
+
4815
+ canvas.getNumCalls = function() {
4816
+ return numCalls_;
4817
+ };
4818
+
4819
+ canvas.setRestoreTimeout = function(timeout) {
4820
+ restoreTimeout_ = timeout;
4821
+ };
4822
+
4823
+ function clearErrors() {
4824
+ var k = Object.keys(glErrorShadow_);
4825
+ for (var ii = 0; ii < k.length; ++ii) {
4826
+ delete glErrorShadow_[k[ii]];
4827
+ }
4828
+ }
4829
+
4830
+ function loseContextIfTime() {
4831
+ ++numCalls_;
4832
+ if (!contextLost_) {
4833
+ if (numCallsToLoseContext_ == numCalls_) {
4834
+ canvas.loseContext();
4835
+ }
4836
+ }
4837
+ }
4838
+
4839
+ // Makes a function that simulates WebGL when out of context.
4840
+ function makeLostContextFunctionWrapper(ctx, functionName) {
4841
+ var f = ctx[functionName];
4842
+ return function() {
4843
+ // log("calling:" + functionName);
4844
+ // Only call the functions if the context is not lost.
4845
+ loseContextIfTime();
4846
+ if (!contextLost_) {
4847
+ //if (!checkResources(arguments)) {
4848
+ // glErrorShadow_[wrappedContext_.INVALID_OPERATION] = true;
4849
+ // return;
4850
+ //}
4851
+ var result = f.apply(ctx, arguments);
4852
+ return result;
4853
+ }
4854
+ };
4855
+ }
4856
+
4857
+ function freeResources() {
4858
+ for (var ii = 0; ii < resourceDb_.length; ++ii) {
4859
+ var resource = resourceDb_[ii];
4860
+ if (resource instanceof WebGLBuffer) {
4861
+ unwrappedContext_.deleteBuffer(resource);
4862
+ } else if (resource instanceof WebGLFramebuffer) {
4863
+ unwrappedContext_.deleteFramebuffer(resource);
4864
+ } else if (resource instanceof WebGLProgram) {
4865
+ unwrappedContext_.deleteProgram(resource);
4866
+ } else if (resource instanceof WebGLRenderbuffer) {
4867
+ unwrappedContext_.deleteRenderbuffer(resource);
4868
+ } else if (resource instanceof WebGLShader) {
4869
+ unwrappedContext_.deleteShader(resource);
4870
+ } else if (resource instanceof WebGLTexture) {
4871
+ unwrappedContext_.deleteTexture(resource);
4872
+ }
4873
+ else if (isWebGL2RenderingContext) {
4874
+ if (resource instanceof WebGLQuery) {
4875
+ unwrappedContext_.deleteQuery(resource);
4876
+ } else if (resource instanceof WebGLSampler) {
4877
+ unwrappedContext_.deleteSampler(resource);
4878
+ } else if (resource instanceof WebGLSync) {
4879
+ unwrappedContext_.deleteSync(resource);
4880
+ } else if (resource instanceof WebGLTransformFeedback) {
4881
+ unwrappedContext_.deleteTransformFeedback(resource);
4882
+ } else if (resource instanceof WebGLVertexArrayObject) {
4883
+ unwrappedContext_.deleteVertexArray(resource);
4884
+ }
4885
+ }
4886
+ }
4887
+ }
4888
+
4889
+ function makeWebGLContextEvent(statusMessage) {
4890
+ return {
4891
+ statusMessage: statusMessage,
4892
+ preventDefault: function() {
4893
+ canRestore_ = true;
4894
+ }
4895
+ };
4896
+ }
4897
+
4898
+ return canvas;
4899
+
4900
+ function makeLostContextSimulatingContext(ctx) {
4901
+ // copy all functions and properties to wrapper
4902
+ for (var propertyName in ctx) {
4903
+ if (typeof ctx[propertyName] == 'function') {
4904
+ wrappedContext_[propertyName] = makeLostContextFunctionWrapper(
4905
+ ctx, propertyName);
4906
+ } else {
4907
+ makePropertyWrapper(wrappedContext_, ctx, propertyName);
4908
+ }
4909
+ }
4910
+
4911
+ // Wrap a few functions specially.
4912
+ wrappedContext_.getError = function() {
4913
+ loseContextIfTime();
4914
+ if (!contextLost_) {
4915
+ var err;
4916
+ while (err = unwrappedContext_.getError()) {
4917
+ glErrorShadow_[err] = true;
4918
+ }
4919
+ }
4920
+ for (var err in glErrorShadow_) {
4921
+ if (glErrorShadow_[err]) {
4922
+ delete glErrorShadow_[err];
4923
+ return err;
4924
+ }
4925
+ }
4926
+ return wrappedContext_.NO_ERROR;
4927
+ };
4928
+
4929
+ var creationFunctions = [
4930
+ "createBuffer",
4931
+ "createFramebuffer",
4932
+ "createProgram",
4933
+ "createRenderbuffer",
4934
+ "createShader",
4935
+ "createTexture"
4936
+ ];
4937
+ if (isWebGL2RenderingContext) {
4938
+ creationFunctions.push(
4939
+ "createQuery",
4940
+ "createSampler",
4941
+ "fenceSync",
4942
+ "createTransformFeedback",
4943
+ "createVertexArray"
4944
+ );
4945
+ }
4946
+ for (var ii = 0; ii < creationFunctions.length; ++ii) {
4947
+ var functionName = creationFunctions[ii];
4948
+ wrappedContext_[functionName] = function(f) {
4949
+ return function() {
4950
+ loseContextIfTime();
4951
+ if (contextLost_) {
4952
+ return null;
4953
+ }
4954
+ var obj = f.apply(ctx, arguments);
4955
+ obj.__webglDebugContextLostId__ = contextId_;
4956
+ resourceDb_.push(obj);
4957
+ return obj;
4958
+ };
4959
+ }(ctx[functionName]);
4960
+ }
4961
+
4962
+ var functionsThatShouldReturnNull = [
4963
+ "getActiveAttrib",
4964
+ "getActiveUniform",
4965
+ "getBufferParameter",
4966
+ "getContextAttributes",
4967
+ "getAttachedShaders",
4968
+ "getFramebufferAttachmentParameter",
4969
+ "getParameter",
4970
+ "getProgramParameter",
4971
+ "getProgramInfoLog",
4972
+ "getRenderbufferParameter",
4973
+ "getShaderParameter",
4974
+ "getShaderInfoLog",
4975
+ "getShaderSource",
4976
+ "getTexParameter",
4977
+ "getUniform",
4978
+ "getUniformLocation",
4979
+ "getVertexAttrib"
4980
+ ];
4981
+ if (isWebGL2RenderingContext) {
4982
+ functionsThatShouldReturnNull.push(
4983
+ "getInternalformatParameter",
4984
+ "getQuery",
4985
+ "getQueryParameter",
4986
+ "getSamplerParameter",
4987
+ "getSyncParameter",
4988
+ "getTransformFeedbackVarying",
4989
+ "getIndexedParameter",
4990
+ "getUniformIndices",
4991
+ "getActiveUniforms",
4992
+ "getActiveUniformBlockParameter",
4993
+ "getActiveUniformBlockName"
4994
+ );
4995
+ }
4996
+ for (var ii = 0; ii < functionsThatShouldReturnNull.length; ++ii) {
4997
+ var functionName = functionsThatShouldReturnNull[ii];
4998
+ wrappedContext_[functionName] = function(f) {
4999
+ return function() {
5000
+ loseContextIfTime();
5001
+ if (contextLost_) {
5002
+ return null;
5003
+ }
5004
+ return f.apply(ctx, arguments);
5005
+ }
5006
+ }(wrappedContext_[functionName]);
5007
+ }
5008
+
5009
+ var isFunctions = [
5010
+ "isBuffer",
5011
+ "isEnabled",
5012
+ "isFramebuffer",
5013
+ "isProgram",
5014
+ "isRenderbuffer",
5015
+ "isShader",
5016
+ "isTexture"
5017
+ ];
5018
+ if (isWebGL2RenderingContext) {
5019
+ isFunctions.push(
5020
+ "isQuery",
5021
+ "isSampler",
5022
+ "isSync",
5023
+ "isTransformFeedback",
5024
+ "isVertexArray"
5025
+ );
5026
+ }
5027
+ for (var ii = 0; ii < isFunctions.length; ++ii) {
5028
+ var functionName = isFunctions[ii];
5029
+ wrappedContext_[functionName] = function(f) {
5030
+ return function() {
5031
+ loseContextIfTime();
5032
+ if (contextLost_) {
5033
+ return false;
5034
+ }
5035
+ return f.apply(ctx, arguments);
5036
+ }
5037
+ }(wrappedContext_[functionName]);
5038
+ }
5039
+
5040
+ wrappedContext_.checkFramebufferStatus = function(f) {
5041
+ return function() {
5042
+ loseContextIfTime();
5043
+ if (contextLost_) {
5044
+ return wrappedContext_.FRAMEBUFFER_UNSUPPORTED;
5045
+ }
5046
+ return f.apply(ctx, arguments);
5047
+ };
5048
+ }(wrappedContext_.checkFramebufferStatus);
5049
+
5050
+ wrappedContext_.getAttribLocation = function(f) {
5051
+ return function() {
5052
+ loseContextIfTime();
5053
+ if (contextLost_) {
5054
+ return -1;
5055
+ }
5056
+ return f.apply(ctx, arguments);
5057
+ };
5058
+ }(wrappedContext_.getAttribLocation);
5059
+
5060
+ wrappedContext_.getVertexAttribOffset = function(f) {
5061
+ return function() {
5062
+ loseContextIfTime();
5063
+ if (contextLost_) {
5064
+ return 0;
5065
+ }
5066
+ return f.apply(ctx, arguments);
5067
+ };
5068
+ }(wrappedContext_.getVertexAttribOffset);
5069
+
5070
+ wrappedContext_.isContextLost = function() {
5071
+ return contextLost_;
5072
+ };
5073
+
5074
+ if (isWebGL2RenderingContext) {
5075
+ wrappedContext_.getFragDataLocation = function(f) {
5076
+ return function() {
5077
+ loseContextIfTime();
5078
+ if (contextLost_) {
5079
+ return -1;
5080
+ }
5081
+ return f.apply(ctx, arguments);
5082
+ };
5083
+ }(wrappedContext_.getFragDataLocation);
5084
+
5085
+ wrappedContext_.clientWaitSync = function(f) {
5086
+ return function() {
5087
+ loseContextIfTime();
5088
+ if (contextLost_) {
5089
+ return wrappedContext_.WAIT_FAILED;
5090
+ }
5091
+ return f.apply(ctx, arguments);
5092
+ };
5093
+ }(wrappedContext_.clientWaitSync);
5094
+
5095
+ wrappedContext_.getUniformBlockIndex = function(f) {
5096
+ return function() {
5097
+ loseContextIfTime();
5098
+ if (contextLost_) {
5099
+ return wrappedContext_.INVALID_INDEX;
5100
+ }
5101
+ return f.apply(ctx, arguments);
5102
+ };
5103
+ }(wrappedContext_.getUniformBlockIndex);
5104
+ }
5105
+
5106
+ return wrappedContext_;
5107
+ }
5108
+ }
5109
+
5110
+ return {
5111
+ /**
5112
+ * Initializes this module. Safe to call more than once.
5113
+ * @param {!WebGLRenderingContext} ctx A WebGL context. If
5114
+ * you have more than one context it doesn't matter which one
5115
+ * you pass in, it is only used to pull out constants.
5116
+ */
5117
+ 'init': init,
5118
+
5119
+ /**
5120
+ * Returns true or false if value matches any WebGL enum
5121
+ * @param {*} value Value to check if it might be an enum.
5122
+ * @return {boolean} True if value matches one of the WebGL defined enums
5123
+ */
5124
+ 'mightBeEnum': mightBeEnum,
5125
+
5126
+ /**
5127
+ * Gets an string version of an WebGL enum.
5128
+ *
5129
+ * Example:
5130
+ * WebGLDebugUtil.init(ctx);
5131
+ * var str = WebGLDebugUtil.glEnumToString(ctx.getError());
5132
+ *
5133
+ * @param {number} value Value to return an enum for
5134
+ * @return {string} The string version of the enum.
5135
+ */
5136
+ 'glEnumToString': glEnumToString,
5137
+
5138
+ /**
5139
+ * Converts the argument of a WebGL function to a string.
5140
+ * Attempts to convert enum arguments to strings.
5141
+ *
5142
+ * Example:
5143
+ * WebGLDebugUtil.init(ctx);
5144
+ * var str = WebGLDebugUtil.glFunctionArgToString('bindTexture', 2, 0, gl.TEXTURE_2D);
5145
+ *
5146
+ * would return 'TEXTURE_2D'
5147
+ *
5148
+ * @param {string} functionName the name of the WebGL function.
5149
+ * @param {number} numArgs The number of arguments
5150
+ * @param {number} argumentIndx the index of the argument.
5151
+ * @param {*} value The value of the argument.
5152
+ * @return {string} The value as a string.
5153
+ */
5154
+ 'glFunctionArgToString': glFunctionArgToString,
5155
+
5156
+ /**
5157
+ * Converts the arguments of a WebGL function to a string.
5158
+ * Attempts to convert enum arguments to strings.
5159
+ *
5160
+ * @param {string} functionName the name of the WebGL function.
5161
+ * @param {number} args The arguments.
5162
+ * @return {string} The arguments as a string.
5163
+ */
5164
+ 'glFunctionArgsToString': glFunctionArgsToString,
5165
+
5166
+ /**
5167
+ * Given a WebGL context returns a wrapped context that calls
5168
+ * gl.getError after every command and calls a function if the
5169
+ * result is not NO_ERROR.
5170
+ *
5171
+ * You can supply your own function if you want. For example, if you'd like
5172
+ * an exception thrown on any GL error you could do this
5173
+ *
5174
+ * function throwOnGLError(err, funcName, args) {
5175
+ * throw WebGLDebugUtils.glEnumToString(err) +
5176
+ * " was caused by call to " + funcName;
5177
+ * };
5178
+ *
5179
+ * ctx = WebGLDebugUtils.makeDebugContext(
5180
+ * canvas.getContext("webgl"), throwOnGLError);
5181
+ *
5182
+ * @param {!WebGLRenderingContext} ctx The webgl context to wrap.
5183
+ * @param {!function(err, funcName, args): void} opt_onErrorFunc The function
5184
+ * to call when gl.getError returns an error. If not specified the default
5185
+ * function calls console.log with a message.
5186
+ * @param {!function(funcName, args): void} opt_onFunc The
5187
+ * function to call when each webgl function is called. You
5188
+ * can use this to log all calls for example.
5189
+ */
5190
+ 'makeDebugContext': makeDebugContext,
5191
+
5192
+ /**
5193
+ * Given a canvas element returns a wrapped canvas element that will
5194
+ * simulate lost context. The canvas returned adds the following functions.
5195
+ *
5196
+ * loseContext:
5197
+ * simulates a lost context event.
5198
+ *
5199
+ * restoreContext:
5200
+ * simulates the context being restored.
5201
+ *
5202
+ * lostContextInNCalls:
5203
+ * loses the context after N gl calls.
5204
+ *
5205
+ * getNumCalls:
5206
+ * tells you how many gl calls there have been so far.
5207
+ *
5208
+ * setRestoreTimeout:
5209
+ * sets the number of milliseconds until the context is restored
5210
+ * after it has been lost. Defaults to 0. Pass -1 to prevent
5211
+ * automatic restoring.
5212
+ *
5213
+ * @param {!Canvas} canvas The canvas element to wrap.
5214
+ */
5215
+ 'makeLostContextSimulatingCanvas': makeLostContextSimulatingCanvas,
5216
+
5217
+ /**
5218
+ * Resets a context to the initial state.
5219
+ * @param {!WebGLRenderingContext} ctx The webgl context to
5220
+ * reset.
5221
+ */
5222
+ 'resetToInitialState': resetToInitialState
5223
+ };
5224
+
5029
5225
  }();
5030
5226
 
5031
5227
  var RenderBackendType;
@@ -5640,7 +5836,7 @@ class WebGl2VertexArrayObject {
5640
5836
 
5641
5837
  var vertexSource$4 = "#version 300 es\nprecision lowp float;\nprecision lowp int;\n\n// Per-instance attributes (divisor = 1). Each Sprite contributes one entry\n// to the per-instance buffer; gl_VertexID 0..3 selects which corner of the\n// quad this invocation is computing.\nlayout(location = 0) in vec4 a_localBounds; // left, top, right, bottom (local space)\nlayout(location = 1) in vec3 a_transformAB; // a, b, x — first row of 2D affine\nlayout(location = 2) in vec3 a_transformCD; // c, d, y — second row\nlayout(location = 3) in vec4 a_uvBounds; // uMin, vMin, uMax, vMax (normalised, already flipY-swapped)\nlayout(location = 4) in vec4 a_color; // RGBA tint\nlayout(location = 5) in uint a_textureSlot;\n\nuniform mat3 u_projection;\n\nout vec2 v_texcoord;\nout vec4 v_color;\nflat out uint v_textureSlot;\n\nvoid main(void) {\n // gl_VertexID 0..3 → corner: 0=TL, 1=TR, 2=BL, 3=BR (TRIANGLE_STRIP order)\n int vid = gl_VertexID;\n int cornerX = vid & 1;\n int cornerY = (vid >> 1) & 1;\n\n // Local-space corner: pick from the bounds rectangle.\n float localX = (cornerX == 0) ? a_localBounds.x : a_localBounds.z;\n float localY = (cornerY == 0) ? a_localBounds.y : a_localBounds.w;\n\n // Apply the per-instance affine transform: world = M * (localX, localY, 1)\n float worldX = (a_transformAB.x * localX) + (a_transformAB.y * localY) + a_transformAB.z;\n float worldY = (a_transformCD.x * localX) + (a_transformCD.y * localY) + a_transformCD.z;\n\n gl_Position = vec4((u_projection * vec3(worldX, worldY, 1.0)).xy, 0.0, 1.0);\n\n // UV: pick from the bounds rectangle. The CPU pre-swaps Y bounds when\n // the texture is flipY, so the shader doesn't have to know.\n float u = (cornerX == 0) ? a_uvBounds.x : a_uvBounds.z;\n float v = (cornerY == 0) ? a_uvBounds.y : a_uvBounds.w;\n v_texcoord = vec2(u, v);\n\n v_color = vec4(a_color.rgb * a_color.a, a_color.a);\n v_textureSlot = a_textureSlot;\n}\n";
5642
5838
 
5643
- var fragmentSource$4 = "#version 300 es\r\nprecision lowp float;\r\nprecision lowp int;\r\n\r\n// Multi-texture sprite batching: up to 8 textures bound per draw call,\r\n// each fragment selects its source via a flat-interpolated slot index.\r\n//\r\n// GLSL ES 3.0 forbids non-constant array-of-sampler indexing unless the\r\n// expression is dynamically uniform — which a per-vertex slot is not\r\n// once different triangles in the same batch carry different slots. The\r\n// if/else chain below dispatches statically and dodges that constraint.\r\n\r\nuniform sampler2D u_texture0;\r\nuniform sampler2D u_texture1;\r\nuniform sampler2D u_texture2;\r\nuniform sampler2D u_texture3;\r\nuniform sampler2D u_texture4;\r\nuniform sampler2D u_texture5;\r\nuniform sampler2D u_texture6;\r\nuniform sampler2D u_texture7;\r\n\r\nin vec2 v_texcoord;\r\nin vec4 v_color;\r\nflat in uint v_textureSlot;\r\n\r\nlayout(location = 0) out vec4 fragColor;\r\n\r\nvoid main(void) {\r\n vec4 sampleColor;\r\n\r\n if (v_textureSlot == 0u) {\r\n sampleColor = texture(u_texture0, v_texcoord);\r\n } else if (v_textureSlot == 1u) {\r\n sampleColor = texture(u_texture1, v_texcoord);\r\n } else if (v_textureSlot == 2u) {\r\n sampleColor = texture(u_texture2, v_texcoord);\r\n } else if (v_textureSlot == 3u) {\r\n sampleColor = texture(u_texture3, v_texcoord);\r\n } else if (v_textureSlot == 4u) {\r\n sampleColor = texture(u_texture4, v_texcoord);\r\n } else if (v_textureSlot == 5u) {\r\n sampleColor = texture(u_texture5, v_texcoord);\r\n } else if (v_textureSlot == 6u) {\r\n sampleColor = texture(u_texture6, v_texcoord);\r\n } else {\r\n sampleColor = texture(u_texture7, v_texcoord);\r\n }\r\n\r\n fragColor = sampleColor * v_color;\r\n}\r\n";
5839
+ var fragmentSource$4 = "#version 300 es\nprecision lowp float;\nprecision lowp int;\n\n// Multi-texture sprite batching: up to 8 textures bound per draw call,\n// each fragment selects its source via a flat-interpolated slot index.\n//\n// GLSL ES 3.0 forbids non-constant array-of-sampler indexing unless the\n// expression is dynamically uniform — which a per-vertex slot is not\n// once different triangles in the same batch carry different slots. The\n// if/else chain below dispatches statically and dodges that constraint.\n\nuniform sampler2D u_texture0;\nuniform sampler2D u_texture1;\nuniform sampler2D u_texture2;\nuniform sampler2D u_texture3;\nuniform sampler2D u_texture4;\nuniform sampler2D u_texture5;\nuniform sampler2D u_texture6;\nuniform sampler2D u_texture7;\n\nin vec2 v_texcoord;\nin vec4 v_color;\nflat in uint v_textureSlot;\n\nlayout(location = 0) out vec4 fragColor;\n\nvoid main(void) {\n vec4 sampleColor;\n\n if (v_textureSlot == 0u) {\n sampleColor = texture(u_texture0, v_texcoord);\n } else if (v_textureSlot == 1u) {\n sampleColor = texture(u_texture1, v_texcoord);\n } else if (v_textureSlot == 2u) {\n sampleColor = texture(u_texture2, v_texcoord);\n } else if (v_textureSlot == 3u) {\n sampleColor = texture(u_texture3, v_texcoord);\n } else if (v_textureSlot == 4u) {\n sampleColor = texture(u_texture4, v_texcoord);\n } else if (v_textureSlot == 5u) {\n sampleColor = texture(u_texture5, v_texcoord);\n } else if (v_textureSlot == 6u) {\n sampleColor = texture(u_texture6, v_texcoord);\n } else {\n sampleColor = texture(u_texture7, v_texcoord);\n }\n\n fragColor = sampleColor * v_color;\n}\n";
5644
5840
 
5645
5841
  /**
5646
5842
  * Instanced sprite renderer for WebGL2.
@@ -6349,7 +6545,7 @@ class WebGl2MeshRenderer extends AbstractWebGl2Renderer {
6349
6545
 
6350
6546
  var vertexSource$2 = "#version 300 es\nprecision lowp float;\nprecision lowp int;\n\n// Per-instance attributes (one entry per particle, 24 bytes total).\nlayout(location = 0) in vec2 a_translation; // particle position in system-local space\nlayout(location = 1) in vec2 a_scale; // particle scale\nlayout(location = 2) in float a_rotation; // particle rotation in degrees\nlayout(location = 3) in vec4 a_color; // RGBA tint\n\nuniform mat3 u_projection;\nuniform mat3 u_systemTransform;\nuniform vec4 u_localBounds; // left, top, right, bottom (system.vertices)\nuniform vec4 u_uvBounds; // uMin, vMin, uMax, vMax (flipY-swapped)\n\nout vec2 v_texcoord;\nout vec4 v_color;\n\nvoid main(void) {\n // Static index buffer is [0,1,2,0,2,3] (triangle-list), so gl_VertexID 0..3\n // maps to TL, TR, BR, BL via the same bit math the sprite renderer uses.\n int vid = gl_VertexID;\n int cornerX = ((vid + 1) >> 1) & 1;\n int cornerY = vid >> 1;\n\n float localX = (cornerX == 0) ? u_localBounds.x : u_localBounds.z;\n float localY = (cornerY == 0) ? u_localBounds.y : u_localBounds.w;\n\n // Per-particle scale + rotation.\n vec2 rotation = vec2(sin(radians(a_rotation)), cos(radians(a_rotation)));\n vec2 transformed = vec2(\n (localX * (a_scale.x * rotation.y)) + (localY * (a_scale.y * rotation.x)),\n (localX * (a_scale.x * -rotation.x)) + (localY * (a_scale.y * rotation.y))\n );\n\n vec3 worldPos = vec3(transformed + a_translation, 1.0);\n\n gl_Position = vec4((u_projection * u_systemTransform * worldPos).xy, 0.0, 1.0);\n\n float u = (cornerX == 0) ? u_uvBounds.x : u_uvBounds.z;\n float v = (cornerY == 0) ? u_uvBounds.y : u_uvBounds.w;\n v_texcoord = vec2(u, v);\n\n v_color = vec4(a_color.rgb * a_color.a, a_color.a);\n}\n";
6351
6547
 
6352
- var fragmentSource$2 = "#version 300 es\r\nprecision lowp float;\r\n\r\nuniform sampler2D u_texture;\r\n\r\nin vec2 v_texcoord;\r\nin vec4 v_color;\r\n\r\nlayout(location = 0) out vec4 fragColor;\r\n\r\nvoid main(void) {\r\n fragColor = texture(u_texture, v_texcoord) * v_color;\r\n}\r\n";
6548
+ var fragmentSource$2 = "#version 300 es\nprecision lowp float;\n\nuniform sampler2D u_texture;\n\nin vec2 v_texcoord;\nin vec4 v_color;\n\nlayout(location = 0) out vec4 fragColor;\n\nvoid main(void) {\n fragColor = texture(u_texture, v_texcoord) * v_color;\n}\n";
6353
6549
 
6354
6550
  /**
6355
6551
  * Instanced particle renderer for WebGL2.
@@ -6641,9 +6837,9 @@ class WebGl2ParticleRenderer extends AbstractWebGl2Renderer {
6641
6837
  }
6642
6838
  }
6643
6839
 
6644
- var vertexSource$1 = "#version 300 es\r\nprecision lowp float;\r\n\r\nlayout(location = 0) in vec2 a_position;\r\nlayout(location = 1) in vec4 a_color;\r\n\r\nuniform mat3 u_projection;\r\nuniform mat3 u_translation;\r\n\r\nout vec4 v_color;\r\n\r\nvoid main(void) {\r\n gl_Position = vec4((u_projection * u_translation * vec3(a_position, 1.0)).xy, 0.0, 1.0);\r\n v_color = vec4(a_color.rgb * a_color.a, a_color.a);\r\n}\r\n";
6840
+ var vertexSource$1 = "#version 300 es\nprecision lowp float;\n\nlayout(location = 0) in vec2 a_position;\nlayout(location = 1) in vec4 a_color;\n\nuniform mat3 u_projection;\nuniform mat3 u_translation;\n\nout vec4 v_color;\n\nvoid main(void) {\n gl_Position = vec4((u_projection * u_translation * vec3(a_position, 1.0)).xy, 0.0, 1.0);\n v_color = vec4(a_color.rgb * a_color.a, a_color.a);\n}\n";
6645
6841
 
6646
- var fragmentSource$1 = "#version 300 es\r\nprecision lowp float;\r\n\r\nlayout(location = 0) out vec4 fragColor;\r\n\r\nin vec4 v_color;\r\n\r\nvoid main(void) {\r\n fragColor = v_color;\r\n}\r\n";
6842
+ var fragmentSource$1 = "#version 300 es\nprecision lowp float;\n\nlayout(location = 0) out vec4 fragColor;\n\nin vec4 v_color;\n\nvoid main(void) {\n fragColor = v_color;\n}\n";
6647
6843
 
6648
6844
  const minBatchVertexSize = 4;
6649
6845
  const vertexStrideBytes$4 = 12;
@@ -6856,9 +7052,9 @@ class WebGl2PrimitiveRenderer extends AbstractWebGl2Renderer {
6856
7052
  }
6857
7053
  }
6858
7054
 
6859
- var vertexSource = "#version 300 es\r\nprecision lowp float;\r\n\r\nlayout(location = 0) in vec2 a_position;\r\nlayout(location = 1) in vec2 a_texcoord;\r\n\r\nuniform mat3 u_projection;\r\n\r\nout vec2 v_texcoord;\r\n\r\nvoid main(void) {\r\n gl_Position = vec4((u_projection * vec3(a_position, 1.0)).xy, 0.0, 1.0);\r\n v_texcoord = a_texcoord;\r\n}\r\n";
7055
+ var vertexSource = "#version 300 es\nprecision lowp float;\n\nlayout(location = 0) in vec2 a_position;\nlayout(location = 1) in vec2 a_texcoord;\n\nuniform mat3 u_projection;\n\nout vec2 v_texcoord;\n\nvoid main(void) {\n gl_Position = vec4((u_projection * vec3(a_position, 1.0)).xy, 0.0, 1.0);\n v_texcoord = a_texcoord;\n}\n";
6860
7056
 
6861
- var fragmentSource = "#version 300 es\r\nprecision lowp float;\r\n\r\nuniform sampler2D u_content;\r\nuniform sampler2D u_mask;\r\n\r\nin vec2 v_texcoord;\r\n\r\nlayout(location = 0) out vec4 fragColor;\r\n\r\nvoid main(void) {\r\n vec4 contentColor = texture(u_content, v_texcoord);\r\n float maskAlpha = texture(u_mask, v_texcoord).a;\r\n\r\n fragColor = vec4(contentColor.rgb * maskAlpha, contentColor.a * maskAlpha);\r\n}\r\n";
7057
+ var fragmentSource = "#version 300 es\nprecision lowp float;\n\nuniform sampler2D u_content;\nuniform sampler2D u_mask;\n\nin vec2 v_texcoord;\n\nlayout(location = 0) out vec4 fragColor;\n\nvoid main(void) {\n vec4 contentColor = texture(u_content, v_texcoord);\n float maskAlpha = texture(u_mask, v_texcoord).a;\n\n fragColor = vec4(contentColor.rgb * maskAlpha, contentColor.a * maskAlpha);\n}\n";
6862
7058
 
6863
7059
  // 4 floats per vertex: position(x, y) + texcoord(u, v).
6864
7060
  const vertexStrideBytes$3 = 16;
@@ -8424,31 +8620,31 @@ function getWebGpuBlendState(blendMode) {
8424
8620
  }
8425
8621
 
8426
8622
  /// <reference types="@webgpu/types" />
8427
- const primitiveShaderSource = `
8428
- struct VertexInput {
8429
- @location(0) position: vec4<f32>,
8430
- @location(1) color: vec4<f32>,
8431
- };
8432
-
8433
- struct VertexOutput {
8434
- @builtin(position) position: vec4<f32>,
8435
- @location(0) color: vec4<f32>,
8436
- };
8437
-
8438
- @vertex
8439
- fn vertexMain(input: VertexInput) -> VertexOutput {
8440
- var output: VertexOutput;
8441
-
8442
- output.position = input.position;
8443
- output.color = vec4<f32>(input.color.rgb * input.color.a, input.color.a);
8444
-
8445
- return output;
8446
- }
8447
-
8448
- @fragment
8449
- fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
8450
- return input.color;
8451
- }
8623
+ const primitiveShaderSource = `
8624
+ struct VertexInput {
8625
+ @location(0) position: vec4<f32>,
8626
+ @location(1) color: vec4<f32>,
8627
+ };
8628
+
8629
+ struct VertexOutput {
8630
+ @builtin(position) position: vec4<f32>,
8631
+ @location(0) color: vec4<f32>,
8632
+ };
8633
+
8634
+ @vertex
8635
+ fn vertexMain(input: VertexInput) -> VertexOutput {
8636
+ var output: VertexOutput;
8637
+
8638
+ output.position = input.position;
8639
+ output.color = vec4<f32>(input.color.rgb * input.color.a, input.color.a);
8640
+
8641
+ return output;
8642
+ }
8643
+
8644
+ @fragment
8645
+ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
8646
+ return input.color;
8647
+ }
8452
8648
  `;
8453
8649
  // 4 floats (pre-transformed clip-space position) + 1 u32 (color) = 20 bytes.
8454
8650
  // The CPU applies (view * shape.globalTransform) to each vertex before writing
@@ -9884,71 +10080,71 @@ class WebGpuMeshRenderer extends AbstractWebGpuRenderer {
9884
10080
  }
9885
10081
 
9886
10082
  /// <reference types="@webgpu/types" />
9887
- const particleShaderSource = `
9888
- struct ProjectionUniforms {
9889
- projection: mat4x4<f32>,
9890
- translation: mat4x4<f32>,
9891
- flags: vec4<f32>,
9892
- localBounds: vec4<f32>, // quadMin.xy, quadSize.xy
9893
- uvBounds: vec4<f32>, // uvMin.xy, uvMax.xy
9894
- };
9895
-
9896
- @group(0) @binding(0)
9897
- var<uniform> uniforms: ProjectionUniforms;
9898
-
9899
- @group(1) @binding(0)
9900
- var particleTexture: texture_2d<f32>;
9901
-
9902
- @group(1) @binding(1)
9903
- var particleSampler: sampler;
9904
-
9905
- // Per-instance attributes (one entry per particle, 24 bytes total).
9906
- struct VertexInput {
9907
- @location(0) unitPosition: vec2<f32>, // per-vertex (static unit quad)
9908
- @location(1) translation: vec2<f32>,
9909
- @location(2) scale: vec2<f32>,
9910
- @location(3) rotation: f32,
9911
- @location(4) color: vec4<f32>,
9912
- };
9913
-
9914
- struct VertexOutput {
9915
- @builtin(position) position: vec4<f32>,
9916
- @location(0) texcoord: vec2<f32>,
9917
- @location(1) color: vec4<f32>,
9918
- };
9919
-
9920
- @vertex
9921
- fn vertexMain(input: VertexInput) -> VertexOutput {
9922
- let quadMin = uniforms.localBounds.xy;
9923
- let quadSize = uniforms.localBounds.zw;
9924
- let uvMin = uniforms.uvBounds.xy;
9925
- let uvMax = uniforms.uvBounds.zw;
9926
-
9927
- let localPosition = quadMin + (input.unitPosition * quadSize);
9928
- let radians = radians(input.rotation);
9929
- let sinValue = sin(radians);
9930
- let cosValue = cos(radians);
9931
- let rotated = vec2<f32>(
9932
- (localPosition.x * (input.scale.x * cosValue)) + (localPosition.y * (input.scale.y * sinValue)) + input.translation.x,
9933
- (localPosition.x * (input.scale.x * -sinValue)) + (localPosition.y * (input.scale.y * cosValue)) + input.translation.y
9934
- );
9935
-
9936
- var output: VertexOutput;
9937
-
9938
- output.position = uniforms.projection * uniforms.translation * vec4<f32>(rotated, 0.0, 1.0);
9939
- output.texcoord = uvMin + ((uvMax - uvMin) * input.unitPosition);
9940
- output.color = vec4(input.color.rgb * input.color.a, input.color.a);
9941
-
9942
- return output;
9943
- }
9944
-
9945
- @fragment
9946
- fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
9947
- let sample = textureSample(particleTexture, particleSampler, input.texcoord);
9948
- let premultipliedSample = select(sample, vec4(sample.rgb * sample.a, sample.a), uniforms.flags.x > 0.5);
9949
-
9950
- return premultipliedSample * input.color;
9951
- }
10083
+ const particleShaderSource = `
10084
+ struct ProjectionUniforms {
10085
+ projection: mat4x4<f32>,
10086
+ translation: mat4x4<f32>,
10087
+ flags: vec4<f32>,
10088
+ localBounds: vec4<f32>, // quadMin.xy, quadSize.xy
10089
+ uvBounds: vec4<f32>, // uvMin.xy, uvMax.xy
10090
+ };
10091
+
10092
+ @group(0) @binding(0)
10093
+ var<uniform> uniforms: ProjectionUniforms;
10094
+
10095
+ @group(1) @binding(0)
10096
+ var particleTexture: texture_2d<f32>;
10097
+
10098
+ @group(1) @binding(1)
10099
+ var particleSampler: sampler;
10100
+
10101
+ // Per-instance attributes (one entry per particle, 24 bytes total).
10102
+ struct VertexInput {
10103
+ @location(0) unitPosition: vec2<f32>, // per-vertex (static unit quad)
10104
+ @location(1) translation: vec2<f32>,
10105
+ @location(2) scale: vec2<f32>,
10106
+ @location(3) rotation: f32,
10107
+ @location(4) color: vec4<f32>,
10108
+ };
10109
+
10110
+ struct VertexOutput {
10111
+ @builtin(position) position: vec4<f32>,
10112
+ @location(0) texcoord: vec2<f32>,
10113
+ @location(1) color: vec4<f32>,
10114
+ };
10115
+
10116
+ @vertex
10117
+ fn vertexMain(input: VertexInput) -> VertexOutput {
10118
+ let quadMin = uniforms.localBounds.xy;
10119
+ let quadSize = uniforms.localBounds.zw;
10120
+ let uvMin = uniforms.uvBounds.xy;
10121
+ let uvMax = uniforms.uvBounds.zw;
10122
+
10123
+ let localPosition = quadMin + (input.unitPosition * quadSize);
10124
+ let radians = radians(input.rotation);
10125
+ let sinValue = sin(radians);
10126
+ let cosValue = cos(radians);
10127
+ let rotated = vec2<f32>(
10128
+ (localPosition.x * (input.scale.x * cosValue)) + (localPosition.y * (input.scale.y * sinValue)) + input.translation.x,
10129
+ (localPosition.x * (input.scale.x * -sinValue)) + (localPosition.y * (input.scale.y * cosValue)) + input.translation.y
10130
+ );
10131
+
10132
+ var output: VertexOutput;
10133
+
10134
+ output.position = uniforms.projection * uniforms.translation * vec4<f32>(rotated, 0.0, 1.0);
10135
+ output.texcoord = uvMin + ((uvMax - uvMin) * input.unitPosition);
10136
+ output.color = vec4(input.color.rgb * input.color.a, input.color.a);
10137
+
10138
+ return output;
10139
+ }
10140
+
10141
+ @fragment
10142
+ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
10143
+ let sample = textureSample(particleTexture, particleSampler, input.texcoord);
10144
+ let premultipliedSample = select(sample, vec4(sample.rgb * sample.a, sample.a), uniforms.flags.x > 0.5);
10145
+
10146
+ return premultipliedSample * input.color;
10147
+ }
9952
10148
  `;
9953
10149
  const staticVertexStrideBytes = 8;
9954
10150
  const instanceWords = 6;
@@ -10304,50 +10500,50 @@ class WebGpuParticleRenderer extends AbstractWebGpuRenderer {
10304
10500
  }
10305
10501
 
10306
10502
  /// <reference types="@webgpu/types" />
10307
- const compositorShaderSource = `
10308
- struct ProjectionUniforms {
10309
- matrix: mat4x4<f32>,
10310
- };
10311
-
10312
- @group(0) @binding(0)
10313
- var<uniform> projection: ProjectionUniforms;
10314
-
10315
- @group(1) @binding(0)
10316
- var contentTexture: texture_2d<f32>;
10317
- @group(1) @binding(1)
10318
- var contentSampler: sampler;
10319
- @group(1) @binding(2)
10320
- var maskTexture: texture_2d<f32>;
10321
- @group(1) @binding(3)
10322
- var maskSampler: sampler;
10323
-
10324
- struct VertexInput {
10325
- @location(0) position: vec2<f32>,
10326
- @location(1) texcoord: vec2<f32>,
10327
- };
10328
-
10329
- struct VertexOutput {
10330
- @builtin(position) position: vec4<f32>,
10331
- @location(0) texcoord: vec2<f32>,
10332
- };
10333
-
10334
- @vertex
10335
- fn vertexMain(input: VertexInput) -> VertexOutput {
10336
- var output: VertexOutput;
10337
-
10338
- output.position = projection.matrix * vec4<f32>(input.position, 0.0, 1.0);
10339
- output.texcoord = input.texcoord;
10340
-
10341
- return output;
10342
- }
10343
-
10344
- @fragment
10345
- fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
10346
- let contentColor = textureSample(contentTexture, contentSampler, input.texcoord);
10347
- let maskAlpha = textureSample(maskTexture, maskSampler, input.texcoord).a;
10348
-
10349
- return vec4<f32>(contentColor.rgb * maskAlpha, contentColor.a * maskAlpha);
10350
- }
10503
+ const compositorShaderSource = `
10504
+ struct ProjectionUniforms {
10505
+ matrix: mat4x4<f32>,
10506
+ };
10507
+
10508
+ @group(0) @binding(0)
10509
+ var<uniform> projection: ProjectionUniforms;
10510
+
10511
+ @group(1) @binding(0)
10512
+ var contentTexture: texture_2d<f32>;
10513
+ @group(1) @binding(1)
10514
+ var contentSampler: sampler;
10515
+ @group(1) @binding(2)
10516
+ var maskTexture: texture_2d<f32>;
10517
+ @group(1) @binding(3)
10518
+ var maskSampler: sampler;
10519
+
10520
+ struct VertexInput {
10521
+ @location(0) position: vec2<f32>,
10522
+ @location(1) texcoord: vec2<f32>,
10523
+ };
10524
+
10525
+ struct VertexOutput {
10526
+ @builtin(position) position: vec4<f32>,
10527
+ @location(0) texcoord: vec2<f32>,
10528
+ };
10529
+
10530
+ @vertex
10531
+ fn vertexMain(input: VertexInput) -> VertexOutput {
10532
+ var output: VertexOutput;
10533
+
10534
+ output.position = projection.matrix * vec4<f32>(input.position, 0.0, 1.0);
10535
+ output.texcoord = input.texcoord;
10536
+
10537
+ return output;
10538
+ }
10539
+
10540
+ @fragment
10541
+ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
10542
+ let contentColor = textureSample(contentTexture, contentSampler, input.texcoord);
10543
+ let maskAlpha = textureSample(maskTexture, maskSampler, input.texcoord).a;
10544
+
10545
+ return vec4<f32>(contentColor.rgb * maskAlpha, contentColor.a * maskAlpha);
10546
+ }
10351
10547
  `;
10352
10548
  // 4 floats per vertex: position(x, y) + texcoord(u, v).
10353
10549
  const vertexStrideBytes = 16;
@@ -11278,47 +11474,47 @@ class WebGpuBackend {
11278
11474
  _getMipmapResources() {
11279
11475
  if (this._mipmapShaderModule === null || this._mipmapBindGroupLayout === null || this._mipmapPipelineLayout === null || this._mipmapPipeline === null || this._mipmapSampler === null) {
11280
11476
  this._mipmapShaderModule = this.device.createShaderModule({
11281
- code: `
11282
- struct VertexOutput {
11283
- @builtin(position) position: vec4<f32>,
11284
- @location(0) texcoord: vec2<f32>,
11285
- };
11286
-
11287
- @group(0) @binding(0)
11288
- var sourceTexture: texture_2d<f32>;
11289
- @group(0) @binding(1)
11290
- var sourceSampler: sampler;
11291
-
11292
- @vertex
11293
- fn vertexMain(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
11294
- var positions = array<vec2<f32>, 3>(
11295
- vec2<f32>(-1.0, -1.0),
11296
- vec2<f32>(3.0, -1.0),
11297
- vec2<f32>(-1.0, 3.0)
11298
- );
11299
- // Y is flipped vs the position array: NDC Y points up, but texture UV
11300
- // Y points down (UV (0,0) is the top-left of the source). Matching the
11301
- // two ensures that the output texture's top-left pixel samples from the
11302
- // source's top-left, so every mip level has the same orientation as the
11303
- // level above it. Prior to this, odd mip levels were rendered upside
11304
- // down, producing visible texture flips at view-size doublings.
11305
- var texcoords = array<vec2<f32>, 3>(
11306
- vec2<f32>(0.0, 1.0),
11307
- vec2<f32>(2.0, 1.0),
11308
- vec2<f32>(0.0, -1.0)
11309
- );
11310
- var output: VertexOutput;
11311
-
11312
- output.position = vec4<f32>(positions[vertexIndex], 0.0, 1.0);
11313
- output.texcoord = texcoords[vertexIndex];
11314
-
11315
- return output;
11316
- }
11317
-
11318
- @fragment
11319
- fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
11320
- return textureSample(sourceTexture, sourceSampler, input.texcoord);
11321
- }
11477
+ code: `
11478
+ struct VertexOutput {
11479
+ @builtin(position) position: vec4<f32>,
11480
+ @location(0) texcoord: vec2<f32>,
11481
+ };
11482
+
11483
+ @group(0) @binding(0)
11484
+ var sourceTexture: texture_2d<f32>;
11485
+ @group(0) @binding(1)
11486
+ var sourceSampler: sampler;
11487
+
11488
+ @vertex
11489
+ fn vertexMain(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
11490
+ var positions = array<vec2<f32>, 3>(
11491
+ vec2<f32>(-1.0, -1.0),
11492
+ vec2<f32>(3.0, -1.0),
11493
+ vec2<f32>(-1.0, 3.0)
11494
+ );
11495
+ // Y is flipped vs the position array: NDC Y points up, but texture UV
11496
+ // Y points down (UV (0,0) is the top-left of the source). Matching the
11497
+ // two ensures that the output texture's top-left pixel samples from the
11498
+ // source's top-left, so every mip level has the same orientation as the
11499
+ // level above it. Prior to this, odd mip levels were rendered upside
11500
+ // down, producing visible texture flips at view-size doublings.
11501
+ var texcoords = array<vec2<f32>, 3>(
11502
+ vec2<f32>(0.0, 1.0),
11503
+ vec2<f32>(2.0, 1.0),
11504
+ vec2<f32>(0.0, -1.0)
11505
+ );
11506
+ var output: VertexOutput;
11507
+
11508
+ output.position = vec4<f32>(positions[vertexIndex], 0.0, 1.0);
11509
+ output.texcoord = texcoords[vertexIndex];
11510
+
11511
+ return output;
11512
+ }
11513
+
11514
+ @fragment
11515
+ fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
11516
+ return textureSample(sourceTexture, sourceSampler, input.texcoord);
11517
+ }
11322
11518
  `,
11323
11519
  });
11324
11520
  this._mipmapBindGroupLayout = this.device.createBindGroupLayout({
@@ -14655,6 +14851,7 @@ class Application {
14655
14851
  _frameRequest = 0;
14656
14852
  _backendType;
14657
14853
  _backend;
14854
+ _capabilities = null;
14658
14855
  constructor(appSettings) {
14659
14856
  this.options = {
14660
14857
  canvas: appSettings?.canvas ?? createDefaultCanvas(),
@@ -14696,11 +14893,26 @@ class Application {
14696
14893
  get backend() {
14697
14894
  return this._backend;
14698
14895
  }
14896
+ /**
14897
+ * Resolved capabilities for the host browser. Available after
14898
+ * {@link Application.start} resolves; reading before that throws.
14899
+ * For pre-start access use {@link Capabilities.ready} directly.
14900
+ */
14901
+ get capabilities() {
14902
+ if (this._capabilities === null) {
14903
+ throw new Error('Application.capabilities is unavailable before start() resolves. Use `await Capabilities.ready` for pre-start checks.');
14904
+ }
14905
+ return this._capabilities;
14906
+ }
14699
14907
  async start(scene) {
14700
14908
  if (this._status === ApplicationStatus.Stopped) {
14701
14909
  this._status = ApplicationStatus.Loading;
14910
+ // Kick off capability detection in parallel with renderer init —
14911
+ // both are mostly-async startup work, no point serializing them.
14912
+ const capabilitiesPromise = Capabilities.ready;
14702
14913
  try {
14703
14914
  await this.initializeRenderManager();
14915
+ this._capabilities = await capabilitiesPromise;
14704
14916
  await this.sceneManager.setScene(scene);
14705
14917
  this._frameRequest = requestAnimationFrame(this._updateHandler);
14706
14918
  this._frameClock.restart();
@@ -18985,5 +19197,5 @@ const createRapierPhysicsWorld = async (options = {}) => {
18985
19197
  return await RapierPhysicsWorld.create(options);
18986
19198
  };
18987
19199
 
18988
- export { AbstractAssetFactory, AbstractMedia, AbstractWebGl2BatchedRenderer, AbstractWebGl2Renderer, AbstractWebGpuRenderer, AnimatedSprite, Application, ApplicationStatus, ArcadeStickGamepadMapping, AudioAnalyser, BinaryFactory, BlendModes, BlurFilter, Bounds, BufferTypes, BufferUsage, BundleLoadError, CacheFirstStrategy, CallbackRenderPass, ChannelOffset, ChannelSize, Circle, CircleGeometry, Clock, CollisionType, Color, ColorAffector, ColorFilter, Container, Drawable, DrawableShape, Ellipse, FactoryRegistry, Filter, Flags, FontFactory, ForceAffector, GameCubeGamepadMapping, Gamepad, GamepadChannel, GamepadControl, GamepadMapping, GamepadMappingFamily, GamepadPromptLayouts, GenericDualAnalogGamepadMapping, Geometry, Graphics, ImageFactory, IndexedDbDatabase, IndexedDbStore, Input, InputManager, Interval, JoyConLeftGamepadMapping, JoyConRightGamepadMapping, Json, JsonFactory, Keyboard, Line, Loader, Matrix, Mesh, Music, MusicFactory, NetworkOnlyStrategy, ObservableSize, ObservableVector, Particle, ParticleOptions, ParticleSystem, PlayStationGamepadMapping, Pointer, PointerState, PointerStateFlag, PolarVector, Polygon, Quadtree, Random, RapierPhysicsBinding, RapierPhysicsWorld, Rectangle, RenderBackendType, RenderNode, RenderTarget, RenderTargetPass, RenderTexture, RendererRegistry, RenderingPrimitives, Sampler, ScaleAffector, ScaleModes, Scene, SceneManager, SceneNode, Segment, Shader, ShaderAttribute, ShaderPrimitives, ShaderUniform, Signal, Size, Sound, SoundFactory, Sprite, SpriteFlags, Spritesheet, SteamControllerGamepadMapping, SvgAsset, SvgFactory, SwitchProGamepadMapping, Text, TextAsset, TextFactory, TextStyle, Texture, TextureFactory, Time, Timer, TorqueAffector, UniversalEmitter, Vector, Video, VideoFactory, View, ViewFlags, VoronoiRegion, VttAsset, VttFactory, WasmFactory, WebGl2Backend, WebGl2MeshRenderer, WebGl2ParticleRenderer, WebGl2PrimitiveRenderer, WebGl2RenderBuffer, WebGl2ShaderBlock, WebGl2SpriteRenderer, WebGl2VertexArrayObject, WebGpuBackend, WebGpuMeshRenderer, WebGpuParticleRenderer, WebGpuPrimitiveRenderer, WebGpuSpriteRenderer, WrapModes, XboxGamepadMapping, bezierCurveTo, buildCircle, buildEllipse, buildLine, buildPath, buildPolygon, buildRectangle, buildStar, builtInGamepadDefinitions, canvasSourceToDataUrl, clamp, createRapierPhysicsWorld, createRenderStats, createWebGl2ShaderProgram, decodeAudioData, defineAssetManifest, degreesPerRadian, degreesToRadians, determineMimeType, emptyArrayBuffer, getAudioContext, getCanvasSourceSize, getCollisionCircleCircle, getCollisionCircleRectangle, getCollisionPolygonCircle, getCollisionRectangleRectangle, getCollisionSat, getDistance, getOfflineAudioContext, getPreciseTime, getTextureSourceSize, getVoronoiRegion$1 as getVoronoiRegion, getWebGpuBlendState, hours, inRange, intersectionCircleCircle, intersectionCircleEllipse, intersectionCirclePoly, intersectionEllipseEllipse, intersectionEllipsePoly, intersectionLineCircle, intersectionLineEllipse, intersectionLineLine, intersectionLinePoly, intersectionLineRect, intersectionPointCircle, intersectionPointEllipse, intersectionPointLine, intersectionPointPoint, intersectionPointPoly, intersectionPointRect, intersectionPolyPoly, intersectionRectCircle, intersectionRectEllipse, intersectionRectPoly, intersectionRectRect, intersectionSat, isAudioContextReady, isPowerOfTwo, lerp, matchesIds, milliseconds, minutes, noop$1 as noop, normalizeIds, onAudioContextReady, parseGamepadDescriptor, quadraticCurveTo, radiansPerDegree, radiansToDegrees, rand, removeArrayItems, resetRenderStats, resolveDefinition, resolveGamepadDefinition, seconds, sign$1 as sign, stopEvent, supportsCodec, supportsEventOptions, supportsIndexedDb, supportsPointerEvents, supportsTouchEvents, supportsWebAudio, tau, trimRotation, webGl2PrimitiveArrayConstructors, webGl2PrimitiveByteSizeMapping, webGl2PrimitiveTypeNames };
19200
+ export { AbstractAssetFactory, AbstractMedia, AbstractWebGl2BatchedRenderer, AbstractWebGl2Renderer, AbstractWebGpuRenderer, AnimatedSprite, Application, ApplicationStatus, ArcadeStickGamepadMapping, AudioAnalyser, BinaryFactory, BlendModes, BlurFilter, Bounds, BufferTypes, BufferUsage, BundleLoadError, CacheFirstStrategy, CallbackRenderPass, Capabilities, ChannelOffset, ChannelSize, Circle, CircleGeometry, Clock, CollisionType, Color, ColorAffector, ColorFilter, Container, Drawable, DrawableShape, Ellipse, FactoryRegistry, Filter, Flags, FontFactory, ForceAffector, GameCubeGamepadMapping, Gamepad, GamepadChannel, GamepadControl, GamepadMapping, GamepadMappingFamily, GamepadPromptLayouts, GenericDualAnalogGamepadMapping, Geometry, Graphics, ImageFactory, IndexedDbDatabase, IndexedDbStore, Input, InputManager, Interval, JoyConLeftGamepadMapping, JoyConRightGamepadMapping, Json, JsonFactory, Keyboard, Line, Loader, Matrix, Mesh, Music, MusicFactory, NetworkOnlyStrategy, ObservableSize, ObservableVector, Particle, ParticleOptions, ParticleSystem, PlayStationGamepadMapping, Pointer, PointerState, PointerStateFlag, PolarVector, Polygon, Quadtree, Random, RapierPhysicsBinding, RapierPhysicsWorld, Rectangle, RenderBackendType, RenderNode, RenderTarget, RenderTargetPass, RenderTexture, RendererRegistry, RenderingPrimitives, Sampler, ScaleAffector, ScaleModes, Scene, SceneManager, SceneNode, Segment, Shader, ShaderAttribute, ShaderPrimitives, ShaderUniform, Signal, Size, Sound, SoundFactory, Sprite, SpriteFlags, Spritesheet, SteamControllerGamepadMapping, SvgAsset, SvgFactory, SwitchProGamepadMapping, Text, TextAsset, TextFactory, TextStyle, Texture, TextureFactory, Time, Timer, TorqueAffector, UniversalEmitter, Vector, Video, VideoFactory, View, ViewFlags, VoronoiRegion, VttAsset, VttFactory, WasmFactory, WebGl2Backend, WebGl2MeshRenderer, WebGl2ParticleRenderer, WebGl2PrimitiveRenderer, WebGl2RenderBuffer, WebGl2ShaderBlock, WebGl2SpriteRenderer, WebGl2VertexArrayObject, WebGpuBackend, WebGpuMeshRenderer, WebGpuParticleRenderer, WebGpuPrimitiveRenderer, WebGpuSpriteRenderer, WrapModes, XboxGamepadMapping, bezierCurveTo, buildCircle, buildEllipse, buildLine, buildPath, buildPolygon, buildRectangle, buildStar, builtInGamepadDefinitions, canvasSourceToDataUrl, clamp, createRapierPhysicsWorld, createRenderStats, createWebGl2ShaderProgram, decodeAudioData, defineAssetManifest, degreesPerRadian, degreesToRadians, determineMimeType, emptyArrayBuffer, getAudioContext, getCanvasSourceSize, getCollisionCircleCircle, getCollisionCircleRectangle, getCollisionPolygonCircle, getCollisionRectangleRectangle, getCollisionSat, getDistance, getOfflineAudioContext, getPreciseTime, getTextureSourceSize, getVoronoiRegion$1 as getVoronoiRegion, getWebGpuBlendState, hours, inRange, intersectionCircleCircle, intersectionCircleEllipse, intersectionCirclePoly, intersectionEllipseEllipse, intersectionEllipsePoly, intersectionLineCircle, intersectionLineEllipse, intersectionLineLine, intersectionLinePoly, intersectionLineRect, intersectionPointCircle, intersectionPointEllipse, intersectionPointLine, intersectionPointPoint, intersectionPointPoly, intersectionPointRect, intersectionPolyPoly, intersectionRectCircle, intersectionRectEllipse, intersectionRectPoly, intersectionRectRect, intersectionSat, isAudioContextReady, isPowerOfTwo, lerp, matchesIds, milliseconds, minutes, noop$1 as noop, normalizeIds, onAudioContextReady, parseGamepadDescriptor, quadraticCurveTo, radiansPerDegree, radiansToDegrees, rand, removeArrayItems, resetRenderStats, resolveDefinition, resolveGamepadDefinition, seconds, sign$1 as sign, stopEvent, supportsCodec, supportsEventOptions, supportsIndexedDb, supportsPointerEvents, supportsTouchEvents, supportsWebAudio, tau, trimRotation, webGl2PrimitiveArrayConstructors, webGl2PrimitiveByteSizeMapping, webGl2PrimitiveTypeNames };
18989
19201
  //# sourceMappingURL=exo.esm.js.map