@luma.gl/webgl 9.1.0-alpha.15 → 9.1.0-alpha.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/converters/device-parameters.d.ts +3 -3
- package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
- package/dist/adapter/converters/sampler-parameters.js +6 -4
- package/dist/adapter/converters/texture-formats.d.ts +49 -11
- package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
- package/dist/adapter/converters/texture-formats.js +150 -160
- package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
- package/dist/adapter/helpers/format-utils.js +6 -0
- package/dist/adapter/helpers/webgl-texture-utils.d.ts +34 -30
- package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
- package/dist/adapter/helpers/webgl-texture-utils.js +52 -256
- package/dist/adapter/resources/webgl-command-buffer.d.ts +59 -2
- package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-command-buffer.js +87 -31
- package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-command-encoder.js +3 -0
- package/dist/adapter/resources/webgl-external-texture.js +14 -0
- package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-framebuffer.js +1 -2
- package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pass.js +38 -20
- package/dist/adapter/resources/webgl-render-pipeline.d.ts +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.js +30 -16
- package/dist/adapter/resources/webgl-shader.d.ts +1 -0
- package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-shader.js +7 -5
- package/dist/adapter/resources/webgl-texture.d.ts +8 -14
- package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-texture.js +119 -208
- package/dist/adapter/webgl-adapter.d.ts.map +1 -1
- package/dist/adapter/webgl-adapter.js +4 -10
- package/dist/adapter/webgl-device.d.ts +8 -3
- package/dist/adapter/webgl-device.d.ts.map +1 -1
- package/dist/adapter/webgl-device.js +53 -22
- package/dist/context/debug/spector-types.js +1 -1
- package/dist/context/debug/spector.d.ts +5 -5
- package/dist/context/debug/spector.d.ts.map +1 -1
- package/dist/context/debug/spector.js +6 -6
- package/dist/context/debug/webgl-developer-tools.d.ts +2 -3
- package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
- package/dist/context/debug/webgl-developer-tools.js +6 -19
- package/dist/context/helpers/create-browser-context.d.ts +6 -22
- package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
- package/dist/context/helpers/create-browser-context.js +40 -32
- package/dist/dist.dev.js +366 -400
- package/dist/dist.min.js +2 -2
- package/dist/index.cjs +341 -384
- package/dist/index.cjs.map +3 -3
- package/package.json +4 -4
- package/src/adapter/converters/device-parameters.ts +3 -3
- package/src/adapter/converters/sampler-parameters.ts +6 -4
- package/src/adapter/converters/texture-formats.ts +171 -177
- package/src/adapter/helpers/format-utils.ts +6 -0
- package/src/adapter/helpers/webgl-texture-utils.ts +99 -75
- package/src/adapter/resources/webgl-command-buffer.ts +124 -40
- package/src/adapter/resources/webgl-command-encoder.ts +6 -0
- package/src/adapter/resources/webgl-external-texture.ts +14 -0
- package/src/adapter/resources/webgl-framebuffer.ts +1 -2
- package/src/adapter/resources/webgl-render-pass.ts +44 -23
- package/src/adapter/resources/webgl-render-pipeline.ts +32 -16
- package/src/adapter/resources/webgl-shader.ts +8 -6
- package/src/adapter/resources/webgl-texture.ts +126 -235
- package/src/adapter/webgl-adapter.ts +4 -12
- package/src/adapter/webgl-device.ts +88 -48
- package/src/context/debug/spector-types.ts +1 -1
- package/src/context/debug/spector.ts +11 -11
- package/src/context/debug/webgl-developer-tools.ts +8 -31
- package/src/context/helpers/create-browser-context.ts +53 -63
|
@@ -6,24 +6,24 @@
|
|
|
6
6
|
// WebGL... the texture API from hell... hopefully made simpler
|
|
7
7
|
//
|
|
8
8
|
|
|
9
|
+
import {TypedArray} from '@math.gl/types';
|
|
9
10
|
import type {ExternalImage} from '@luma.gl/core';
|
|
10
11
|
import {Buffer, Texture, Framebuffer, FramebufferProps} from '@luma.gl/core';
|
|
11
|
-
|
|
12
12
|
import {
|
|
13
13
|
GL,
|
|
14
14
|
GLTextureTarget,
|
|
15
15
|
GLTextureCubeMapTarget,
|
|
16
16
|
GLTexelDataFormat,
|
|
17
|
-
GLPixelType
|
|
17
|
+
GLPixelType,
|
|
18
|
+
GLDataType
|
|
18
19
|
} from '@luma.gl/constants';
|
|
19
20
|
|
|
20
|
-
import {TypedArray} from '@math.gl/types';
|
|
21
|
-
|
|
22
21
|
import {WEBGLFramebuffer} from '../resources/webgl-framebuffer';
|
|
23
22
|
import {getGLTypeFromTypedArray, getTypedArrayFromGLType} from './typed-array-utils';
|
|
24
23
|
import {glFormatToComponents, glTypeToBytes} from './format-utils';
|
|
25
24
|
import {WEBGLBuffer} from '../resources/webgl-buffer';
|
|
26
25
|
import {WEBGLTexture} from '../resources/webgl-texture';
|
|
26
|
+
import {withGLParameters} from '../../context/state-tracker/with-parameters';
|
|
27
27
|
|
|
28
28
|
/** A "border" parameter is required in many WebGL texture APIs, but must always be 0... */
|
|
29
29
|
const BORDER = 0;
|
|
@@ -120,7 +120,7 @@ export function copyExternalImageToMipLevel(
|
|
|
120
120
|
gl: WebGL2RenderingContext,
|
|
121
121
|
handle: WebGLTexture,
|
|
122
122
|
image: ExternalImage,
|
|
123
|
-
options: WebGLCopyTextureOptions
|
|
123
|
+
options: WebGLCopyTextureOptions & {flipY?: boolean}
|
|
124
124
|
): void {
|
|
125
125
|
const {width, height} = options;
|
|
126
126
|
const {dimension, depth = 0, mipLevel = 0} = options;
|
|
@@ -129,26 +129,29 @@ export function copyExternalImageToMipLevel(
|
|
|
129
129
|
|
|
130
130
|
const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
|
|
131
131
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
132
|
+
const glParameters = options.flipY ? {[GL.UNPACK_FLIP_Y_WEBGL]: true} : {};
|
|
133
|
+
withGLParameters(gl, glParameters, () => {
|
|
134
|
+
switch (dimension) {
|
|
135
|
+
case '2d-array':
|
|
136
|
+
case '3d':
|
|
137
|
+
gl.bindTexture(glTarget, handle);
|
|
138
|
+
// prettier-ignore
|
|
139
|
+
gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
|
|
140
|
+
gl.bindTexture(glTarget, null);
|
|
141
|
+
break;
|
|
140
142
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
143
|
+
case '2d':
|
|
144
|
+
case 'cube':
|
|
145
|
+
gl.bindTexture(glTarget, handle);
|
|
146
|
+
// prettier-ignore
|
|
147
|
+
gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
|
|
148
|
+
gl.bindTexture(glTarget, null);
|
|
149
|
+
break;
|
|
148
150
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
default:
|
|
152
|
+
throw new Error(dimension);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
152
155
|
}
|
|
153
156
|
|
|
154
157
|
/**
|
|
@@ -278,7 +281,7 @@ export function getWebGLCubeFaceTarget(
|
|
|
278
281
|
* Wrapper for the messy WebGL texture API
|
|
279
282
|
*
|
|
280
283
|
export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextureOptions): void {
|
|
281
|
-
const {dimension, width, height, depth = 0,
|
|
284
|
+
const {dimension, width, height, depth = 0, mipLevel = 0} = options;
|
|
282
285
|
const {glInternalFormat, glFormat, glType, compressed} = options;
|
|
283
286
|
const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
|
|
284
287
|
|
|
@@ -287,10 +290,10 @@ export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextu
|
|
|
287
290
|
case '3d':
|
|
288
291
|
if (compressed) {
|
|
289
292
|
// prettier-ignore
|
|
290
|
-
gl.compressedTexImage3D(glTarget,
|
|
293
|
+
gl.compressedTexImage3D(glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, null);
|
|
291
294
|
} else {
|
|
292
295
|
// prettier-ignore
|
|
293
|
-
gl.texImage3D( glTarget,
|
|
296
|
+
gl.texImage3D( glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, glFormat, glType, null);
|
|
294
297
|
}
|
|
295
298
|
break;
|
|
296
299
|
|
|
@@ -298,10 +301,10 @@ export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextu
|
|
|
298
301
|
case 'cube':
|
|
299
302
|
if (compressed) {
|
|
300
303
|
// prettier-ignore
|
|
301
|
-
gl.compressedTexImage2D(glTarget,
|
|
304
|
+
gl.compressedTexImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, null);
|
|
302
305
|
} else {
|
|
303
306
|
// prettier-ignore
|
|
304
|
-
gl.texImage2D(glTarget,
|
|
307
|
+
gl.texImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, glFormat, glType, null);
|
|
305
308
|
}
|
|
306
309
|
break;
|
|
307
310
|
|
|
@@ -309,6 +312,7 @@ export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextu
|
|
|
309
312
|
throw new Error(dimension);
|
|
310
313
|
}
|
|
311
314
|
}
|
|
315
|
+
*/
|
|
312
316
|
|
|
313
317
|
/**
|
|
314
318
|
* Set a texture mip level to the contents of an external image.
|
|
@@ -490,6 +494,30 @@ export function setMipLevelFromGPUBuffer(
|
|
|
490
494
|
gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, null);
|
|
491
495
|
}
|
|
492
496
|
*/
|
|
497
|
+
export type ReadPixelsToArrayOptions = {
|
|
498
|
+
sourceX?: number;
|
|
499
|
+
sourceY?: number;
|
|
500
|
+
sourceFormat?: number;
|
|
501
|
+
sourceAttachment?: number;
|
|
502
|
+
target?: Uint8Array | Uint16Array | Float32Array;
|
|
503
|
+
// following parameters are auto deduced if not provided
|
|
504
|
+
sourceWidth?: number;
|
|
505
|
+
sourceHeight?: number;
|
|
506
|
+
sourceDepth?: number;
|
|
507
|
+
sourceType?: number;
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
export type ReadPixelsToBufferOptions = {
|
|
511
|
+
sourceX?: number;
|
|
512
|
+
sourceY?: number;
|
|
513
|
+
sourceFormat?: number;
|
|
514
|
+
target?: Buffer; // A new Buffer object is created when not provided.
|
|
515
|
+
targetByteOffset?: number; // byte offset in buffer object
|
|
516
|
+
// following parameters are auto deduced if not provided
|
|
517
|
+
sourceWidth?: number;
|
|
518
|
+
sourceHeight?: number;
|
|
519
|
+
sourceType?: number;
|
|
520
|
+
};
|
|
493
521
|
|
|
494
522
|
/**
|
|
495
523
|
* Copies data from a type or a Texture object into ArrayBuffer object.
|
|
@@ -504,23 +532,12 @@ export function setMipLevelFromGPUBuffer(
|
|
|
504
532
|
*/
|
|
505
533
|
export function readPixelsToArray(
|
|
506
534
|
source: Framebuffer | Texture,
|
|
507
|
-
options?:
|
|
508
|
-
sourceX?: number;
|
|
509
|
-
sourceY?: number;
|
|
510
|
-
sourceFormat?: number;
|
|
511
|
-
sourceAttachment?: number;
|
|
512
|
-
target?: Uint8Array | Uint16Array | Float32Array;
|
|
513
|
-
// following parameters are auto deduced if not provided
|
|
514
|
-
sourceWidth?: number;
|
|
515
|
-
sourceHeight?: number;
|
|
516
|
-
sourceDepth?: number;
|
|
517
|
-
sourceType?: number;
|
|
518
|
-
}
|
|
535
|
+
options?: ReadPixelsToArrayOptions
|
|
519
536
|
): Uint8Array | Uint16Array | Float32Array {
|
|
520
537
|
const {
|
|
521
538
|
sourceX = 0,
|
|
522
539
|
sourceY = 0,
|
|
523
|
-
sourceAttachment =
|
|
540
|
+
sourceAttachment = 0 // TODO - support gl.readBuffer
|
|
524
541
|
} = options || {};
|
|
525
542
|
let {
|
|
526
543
|
target = null,
|
|
@@ -535,21 +552,19 @@ export function readPixelsToArray(
|
|
|
535
552
|
const {framebuffer, deleteFramebuffer} = getFramebuffer(source);
|
|
536
553
|
// assert(framebuffer);
|
|
537
554
|
const {gl, handle} = framebuffer;
|
|
538
|
-
const attachment = sourceAttachment - GL.COLOR_ATTACHMENT0;
|
|
539
555
|
|
|
540
556
|
sourceWidth ||= framebuffer.width;
|
|
541
557
|
sourceHeight ||= framebuffer.height;
|
|
542
558
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
sourceDepth = framebuffer.colorAttachments[attachment]?.texture?.depth || 1;
|
|
559
|
+
const texture = framebuffer.colorAttachments[sourceAttachment]?.texture;
|
|
560
|
+
if (!texture) {
|
|
561
|
+
throw new Error(`Invalid framebuffer attachment ${sourceAttachment}`);
|
|
562
|
+
}
|
|
563
|
+
sourceDepth = texture?.depth || 1;
|
|
549
564
|
|
|
550
|
-
sourceFormat ||=
|
|
565
|
+
sourceFormat ||= texture?.glFormat || GL.RGBA;
|
|
551
566
|
// Deduce the type from color attachment if not provided.
|
|
552
|
-
sourceType ||=
|
|
567
|
+
sourceType ||= texture?.glType || GL.UNSIGNED_BYTE;
|
|
553
568
|
|
|
554
569
|
// Deduce type and allocated pixelArray if needed
|
|
555
570
|
target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
|
|
@@ -557,13 +572,31 @@ export function readPixelsToArray(
|
|
|
557
572
|
// Pixel array available, if necessary, deduce type from it.
|
|
558
573
|
sourceType = sourceType || getGLTypeFromTypedArray(target);
|
|
559
574
|
|
|
560
|
-
|
|
575
|
+
// Note: luma.gl overrides bindFramebuffer so that we can reliably restore the previous framebuffer (this is the only function for which we do that)
|
|
576
|
+
const prevHandle = gl.bindFramebuffer(
|
|
577
|
+
GL.FRAMEBUFFER,
|
|
578
|
+
handle
|
|
579
|
+
) as unknown as WebGLFramebuffer | null;
|
|
580
|
+
|
|
581
|
+
// Select the color attachment to read from
|
|
582
|
+
gl.readBuffer(gl.COLOR_ATTACHMENT0 + sourceAttachment);
|
|
583
|
+
|
|
584
|
+
// There is a lot of hedging in the WebGL2 spec about what formats are guaranteed to be readable
|
|
585
|
+
// (It should always be possible to read RGBA/UNSIGNED_BYTE, but most other combinations are not guaranteed)
|
|
586
|
+
// Querying is possible but expensive:
|
|
587
|
+
// const {device} = framebuffer;
|
|
588
|
+
// texture.glReadFormat ||= gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
|
|
589
|
+
// texture.glReadType ||= gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
|
|
590
|
+
// console.log('params', device.getGLKey(texture.glReadFormat), device.getGLKey(texture.glReadType));
|
|
591
|
+
|
|
561
592
|
gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target);
|
|
562
|
-
|
|
593
|
+
gl.readBuffer(gl.COLOR_ATTACHMENT0);
|
|
563
594
|
gl.bindFramebuffer(GL.FRAMEBUFFER, prevHandle || null);
|
|
595
|
+
|
|
564
596
|
if (deleteFramebuffer) {
|
|
565
597
|
framebuffer.destroy();
|
|
566
598
|
}
|
|
599
|
+
|
|
567
600
|
return target;
|
|
568
601
|
}
|
|
569
602
|
|
|
@@ -576,17 +609,7 @@ export function readPixelsToArray(
|
|
|
576
609
|
*/
|
|
577
610
|
export function readPixelsToBuffer(
|
|
578
611
|
source: Framebuffer | Texture,
|
|
579
|
-
options?:
|
|
580
|
-
sourceX?: number;
|
|
581
|
-
sourceY?: number;
|
|
582
|
-
sourceFormat?: number;
|
|
583
|
-
target?: Buffer; // A new Buffer object is created when not provided.
|
|
584
|
-
targetByteOffset?: number; // byte offset in buffer object
|
|
585
|
-
// following parameters are auto deduced if not provided
|
|
586
|
-
sourceWidth?: number;
|
|
587
|
-
sourceHeight?: number;
|
|
588
|
-
sourceType?: number;
|
|
589
|
-
}
|
|
612
|
+
options?: ReadPixelsToBufferOptions
|
|
590
613
|
): WEBGLBuffer {
|
|
591
614
|
const {
|
|
592
615
|
target,
|
|
@@ -620,11 +643,11 @@ export function readPixelsToBuffer(
|
|
|
620
643
|
// TODO(donmccurdy): Do we have tests to confirm this is working?
|
|
621
644
|
const commandEncoder = source.device.createCommandEncoder();
|
|
622
645
|
commandEncoder.copyTextureToBuffer({
|
|
623
|
-
|
|
646
|
+
sourceTexture: source as Texture,
|
|
624
647
|
width: sourceWidth,
|
|
625
648
|
height: sourceHeight,
|
|
626
649
|
origin: [sourceX, sourceY],
|
|
627
|
-
|
|
650
|
+
destinationBuffer: webglBufferTarget,
|
|
628
651
|
byteOffset: targetByteOffset
|
|
629
652
|
});
|
|
630
653
|
commandEncoder.destroy();
|
|
@@ -642,8 +665,8 @@ export function readPixelsToBuffer(
|
|
|
642
665
|
*/
|
|
643
666
|
// eslint-disable-next-line complexity, max-statements
|
|
644
667
|
export function copyToTexture(
|
|
645
|
-
|
|
646
|
-
|
|
668
|
+
sourceTexture: Framebuffer | Texture,
|
|
669
|
+
destinationTexture: Texture | GL,
|
|
647
670
|
options?: {
|
|
648
671
|
sourceX?: number;
|
|
649
672
|
sourceY?: number;
|
|
@@ -673,7 +696,7 @@ export function copyToTexture(
|
|
|
673
696
|
height // defaults to target height
|
|
674
697
|
} = options || {};
|
|
675
698
|
|
|
676
|
-
const {framebuffer, deleteFramebuffer} = getFramebuffer(
|
|
699
|
+
const {framebuffer, deleteFramebuffer} = getFramebuffer(sourceTexture);
|
|
677
700
|
// assert(framebuffer);
|
|
678
701
|
const webglFramebuffer = framebuffer;
|
|
679
702
|
const {device, handle} = webglFramebuffer;
|
|
@@ -690,8 +713,8 @@ export function copyToTexture(
|
|
|
690
713
|
// assert(target);
|
|
691
714
|
let texture: WEBGLTexture | null = null;
|
|
692
715
|
let textureTarget: GL;
|
|
693
|
-
if (
|
|
694
|
-
texture =
|
|
716
|
+
if (destinationTexture instanceof WEBGLTexture) {
|
|
717
|
+
texture = destinationTexture;
|
|
695
718
|
width = Number.isFinite(width) ? width : texture.width;
|
|
696
719
|
height = Number.isFinite(height) ? height : texture.height;
|
|
697
720
|
texture?.bind(0);
|
|
@@ -785,8 +808,8 @@ export function toFramebuffer(texture: Texture, props?: FramebufferProps): WEBGL
|
|
|
785
808
|
// eslint-disable-next-line max-params
|
|
786
809
|
function getPixelArray(
|
|
787
810
|
pixelArray,
|
|
788
|
-
|
|
789
|
-
|
|
811
|
+
glType: GLDataType | GLPixelType,
|
|
812
|
+
glFormat: GL,
|
|
790
813
|
width: number,
|
|
791
814
|
height: number,
|
|
792
815
|
depth?: number
|
|
@@ -794,10 +817,11 @@ function getPixelArray(
|
|
|
794
817
|
if (pixelArray) {
|
|
795
818
|
return pixelArray;
|
|
796
819
|
}
|
|
820
|
+
// const formatInfo = decodeTextureFormat(format);
|
|
797
821
|
// Allocate pixel array if not already available, using supplied type
|
|
798
|
-
|
|
799
|
-
const ArrayType = getTypedArrayFromGLType(
|
|
800
|
-
const components = glFormatToComponents(
|
|
822
|
+
glType ||= GL.UNSIGNED_BYTE;
|
|
823
|
+
const ArrayType = getTypedArrayFromGLType(glType, {clamped: false});
|
|
824
|
+
const components = glFormatToComponents(glFormat);
|
|
801
825
|
// TODO - check for composite type (components = 1).
|
|
802
826
|
return new ArrayType(width * height * components) as Uint8Array | Uint16Array | Float32Array;
|
|
803
827
|
}
|
|
@@ -7,9 +7,18 @@ import type {
|
|
|
7
7
|
CopyBufferToTextureOptions,
|
|
8
8
|
CopyTextureToBufferOptions,
|
|
9
9
|
CopyTextureToTextureOptions
|
|
10
|
+
// ClearTextureOptions,
|
|
11
|
+
// ReadTextureOptions
|
|
10
12
|
} from '@luma.gl/core';
|
|
11
13
|
import {CommandBuffer, Texture, Framebuffer} from '@luma.gl/core';
|
|
12
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
GL,
|
|
16
|
+
GLTextureTarget,
|
|
17
|
+
GLTextureCubeMapTarget
|
|
18
|
+
// GLTexelDataFormat,
|
|
19
|
+
// GLPixelType,
|
|
20
|
+
// GLDataType
|
|
21
|
+
} from '@luma.gl/constants';
|
|
13
22
|
|
|
14
23
|
import {WebGLDevice} from '../webgl-device';
|
|
15
24
|
import {WEBGLBuffer} from './webgl-buffer';
|
|
@@ -37,11 +46,23 @@ type CopyTextureToTextureCommand = {
|
|
|
37
46
|
options: CopyTextureToTextureOptions;
|
|
38
47
|
};
|
|
39
48
|
|
|
49
|
+
type ClearTextureCommand = {
|
|
50
|
+
name: 'clear-texture';
|
|
51
|
+
options: {}; // ClearTextureOptions;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type ReadTextureCommand = {
|
|
55
|
+
name: 'read-texture';
|
|
56
|
+
options: {}; // ReadTextureOptions;
|
|
57
|
+
};
|
|
58
|
+
|
|
40
59
|
type Command =
|
|
41
60
|
| CopyBufferToBufferCommand
|
|
42
61
|
| CopyBufferToTextureCommand
|
|
43
62
|
| CopyTextureToBufferCommand
|
|
44
|
-
| CopyTextureToTextureCommand
|
|
63
|
+
| CopyTextureToTextureCommand
|
|
64
|
+
| ClearTextureCommand
|
|
65
|
+
| ReadTextureCommand;
|
|
45
66
|
|
|
46
67
|
export class WEBGLCommandBuffer extends CommandBuffer {
|
|
47
68
|
device: WebGLDevice;
|
|
@@ -67,14 +88,19 @@ export class WEBGLCommandBuffer extends CommandBuffer {
|
|
|
67
88
|
case 'copy-texture-to-texture':
|
|
68
89
|
_copyTextureToTexture(this.device, command.options);
|
|
69
90
|
break;
|
|
91
|
+
// case 'clear-texture':
|
|
92
|
+
// _clearTexture(this.device, command.options);
|
|
93
|
+
// break;
|
|
94
|
+
default:
|
|
95
|
+
throw new Error(command.name);
|
|
70
96
|
}
|
|
71
97
|
}
|
|
72
98
|
}
|
|
73
99
|
}
|
|
74
100
|
|
|
75
101
|
function _copyBufferToBuffer(device: WebGLDevice, options: CopyBufferToBufferOptions): void {
|
|
76
|
-
const source = options.
|
|
77
|
-
const destination = options.
|
|
102
|
+
const source = options.sourceBuffer as WEBGLBuffer;
|
|
103
|
+
const destination = options.destinationBuffer as WEBGLBuffer;
|
|
78
104
|
|
|
79
105
|
// {In WebGL2 we can p}erform the copy on the GPU
|
|
80
106
|
// Use GL.COPY_READ_BUFFER+GL.COPY_WRITE_BUFFER avoid disturbing other targets and locking type
|
|
@@ -106,22 +132,22 @@ function _copyBufferToTexture(device: WebGLDevice, options: CopyBufferToTextureO
|
|
|
106
132
|
function _copyTextureToBuffer(device: WebGLDevice, options: CopyTextureToBufferOptions): void {
|
|
107
133
|
const {
|
|
108
134
|
/** Texture to copy to/from. */
|
|
109
|
-
|
|
135
|
+
sourceTexture,
|
|
110
136
|
/** Mip-map level of the texture to copy to/from. (Default 0) */
|
|
111
137
|
mipLevel = 0,
|
|
112
138
|
/** Defines which aspects of the texture to copy to/from. */
|
|
113
139
|
aspect = 'all',
|
|
114
140
|
|
|
115
141
|
/** Width to copy */
|
|
116
|
-
width = options.
|
|
142
|
+
width = options.sourceTexture.width,
|
|
117
143
|
/** Height to copy */
|
|
118
|
-
height = options.
|
|
144
|
+
height = options.sourceTexture.height,
|
|
119
145
|
depthOrArrayLayers = 0,
|
|
120
146
|
/** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
|
|
121
147
|
origin = [0, 0],
|
|
122
148
|
|
|
123
149
|
/** Destination buffer */
|
|
124
|
-
|
|
150
|
+
destinationBuffer,
|
|
125
151
|
/** Offset, in bytes, from the beginning of the buffer to the start of the image data (default 0) */
|
|
126
152
|
byteOffset = 0,
|
|
127
153
|
/**
|
|
@@ -139,7 +165,7 @@ function _copyTextureToBuffer(device: WebGLDevice, options: CopyTextureToBufferO
|
|
|
139
165
|
|
|
140
166
|
// TODO - Not possible to read just stencil or depth part in WebGL?
|
|
141
167
|
if (aspect !== 'all') {
|
|
142
|
-
throw new Error('not supported');
|
|
168
|
+
throw new Error('aspect not supported in WebGL');
|
|
143
169
|
}
|
|
144
170
|
|
|
145
171
|
// TODO - mipLevels are set when attaching texture to framebuffer
|
|
@@ -148,10 +174,10 @@ function _copyTextureToBuffer(device: WebGLDevice, options: CopyTextureToBufferO
|
|
|
148
174
|
}
|
|
149
175
|
|
|
150
176
|
// Asynchronous read (PIXEL_PACK_BUFFER) is WebGL2 only feature
|
|
151
|
-
const {framebuffer, destroyFramebuffer} = getFramebuffer(
|
|
177
|
+
const {framebuffer, destroyFramebuffer} = getFramebuffer(sourceTexture);
|
|
152
178
|
let prevHandle: WebGLFramebuffer | null | undefined;
|
|
153
179
|
try {
|
|
154
|
-
const webglBuffer =
|
|
180
|
+
const webglBuffer = destinationBuffer as WEBGLBuffer;
|
|
155
181
|
const sourceWidth = width || framebuffer.width;
|
|
156
182
|
const sourceHeight = height || framebuffer.height;
|
|
157
183
|
const sourceParams = getTextureFormatWebGL(
|
|
@@ -220,7 +246,7 @@ export function readPixelsToBuffer(
|
|
|
220
246
|
function _copyTextureToTexture(device: WebGLDevice, options: CopyTextureToTextureOptions): void {
|
|
221
247
|
const {
|
|
222
248
|
/** Texture to copy to/from. */
|
|
223
|
-
|
|
249
|
+
sourceTexture,
|
|
224
250
|
/** Mip-map level of the texture to copy to (Default 0) */
|
|
225
251
|
destinationMipLevel = 0,
|
|
226
252
|
/** Defines which aspects of the texture to copy to/from. */
|
|
@@ -232,7 +258,7 @@ function _copyTextureToTexture(device: WebGLDevice, options: CopyTextureToTextur
|
|
|
232
258
|
destinationOrigin = [0, 0],
|
|
233
259
|
|
|
234
260
|
/** Texture to copy to/from. */
|
|
235
|
-
|
|
261
|
+
destinationTexture
|
|
236
262
|
/** Mip-map level of the texture to copy to/from. (Default 0) */
|
|
237
263
|
// destinationMipLevel = options.mipLevel,
|
|
238
264
|
/** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
|
|
@@ -242,12 +268,12 @@ function _copyTextureToTexture(device: WebGLDevice, options: CopyTextureToTextur
|
|
|
242
268
|
} = options;
|
|
243
269
|
|
|
244
270
|
let {
|
|
245
|
-
width = options.
|
|
246
|
-
height = options.
|
|
271
|
+
width = options.destinationTexture.width,
|
|
272
|
+
height = options.destinationTexture.height
|
|
247
273
|
// depthOrArrayLayers = 0
|
|
248
274
|
} = options;
|
|
249
275
|
|
|
250
|
-
const {framebuffer, destroyFramebuffer} = getFramebuffer(
|
|
276
|
+
const {framebuffer, destroyFramebuffer} = getFramebuffer(sourceTexture);
|
|
251
277
|
const [sourceX, sourceY] = origin;
|
|
252
278
|
const [destinationX, destinationY, destinationZ] = destinationOrigin;
|
|
253
279
|
|
|
@@ -261,8 +287,8 @@ function _copyTextureToTexture(device: WebGLDevice, options: CopyTextureToTextur
|
|
|
261
287
|
|
|
262
288
|
let texture: WEBGLTexture = null;
|
|
263
289
|
let textureTarget: GL;
|
|
264
|
-
if (
|
|
265
|
-
texture =
|
|
290
|
+
if (destinationTexture instanceof WEBGLTexture) {
|
|
291
|
+
texture = destinationTexture;
|
|
266
292
|
width = Number.isFinite(width) ? width : texture.width;
|
|
267
293
|
height = Number.isFinite(height) ? height : texture.height;
|
|
268
294
|
texture.bind(0);
|
|
@@ -311,7 +337,82 @@ function _copyTextureToTexture(device: WebGLDevice, options: CopyTextureToTextur
|
|
|
311
337
|
}
|
|
312
338
|
}
|
|
313
339
|
|
|
314
|
-
|
|
340
|
+
/** Clear one mip level of a texture *
|
|
341
|
+
function _clearTexture(device: WebGLDevice, options: ClearTextureOptions) {
|
|
342
|
+
const BORDER = 0;
|
|
343
|
+
const {dimension, width, height, depth = 0, mipLevel = 0} = options;
|
|
344
|
+
const {glInternalFormat, glFormat, glType, compressed} = options;
|
|
345
|
+
const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
|
|
346
|
+
|
|
347
|
+
switch (dimension) {
|
|
348
|
+
case '2d-array':
|
|
349
|
+
case '3d':
|
|
350
|
+
if (compressed) {
|
|
351
|
+
// prettier-ignore
|
|
352
|
+
device.gl.compressedTexImage3D(glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, null);
|
|
353
|
+
} else {
|
|
354
|
+
// prettier-ignore
|
|
355
|
+
device.gl.texImage3D( glTarget, mipLevel, glInternalFormat, width, height, depth, BORDER, glFormat, glType, null);
|
|
356
|
+
}
|
|
357
|
+
break;
|
|
358
|
+
|
|
359
|
+
case '2d':
|
|
360
|
+
case 'cube':
|
|
361
|
+
if (compressed) {
|
|
362
|
+
// prettier-ignore
|
|
363
|
+
device.gl.compressedTexImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, null);
|
|
364
|
+
} else {
|
|
365
|
+
// prettier-ignore
|
|
366
|
+
device.gl.texImage2D(glTarget, mipLevel, glInternalFormat, width, height, BORDER, glFormat, glType, null);
|
|
367
|
+
}
|
|
368
|
+
break;
|
|
369
|
+
|
|
370
|
+
default:
|
|
371
|
+
throw new Error(dimension);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
// function _readTexture(device: WebGLDevice, options: CopyTextureToBufferOptions) {}
|
|
377
|
+
|
|
378
|
+
// HELPERS
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* In WebGL, cube maps specify faces by overriding target instead of using the depth parameter.
|
|
382
|
+
* @note We still bind the texture using GL.TEXTURE_CUBE_MAP, but we need to use the face-specific target when setting mip levels.
|
|
383
|
+
* @returns glTarget unchanged, if dimension !== 'cube'.
|
|
384
|
+
*/
|
|
385
|
+
export function getWebGLCubeFaceTarget(
|
|
386
|
+
glTarget: GLTextureTarget,
|
|
387
|
+
dimension: '1d' | '2d' | '2d-array' | 'cube' | 'cube-array' | '3d',
|
|
388
|
+
level: number
|
|
389
|
+
): GLTextureTarget | GLTextureCubeMapTarget {
|
|
390
|
+
return dimension === 'cube' ? GL.TEXTURE_CUBE_MAP_POSITIVE_X + level : glTarget;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/** Wrap a texture in a framebuffer so that we can use WebGL APIs that work on framebuffers */
|
|
394
|
+
function getFramebuffer(source: Texture | Framebuffer): {
|
|
395
|
+
framebuffer: WEBGLFramebuffer;
|
|
396
|
+
destroyFramebuffer: boolean;
|
|
397
|
+
} {
|
|
398
|
+
if (source instanceof Texture) {
|
|
399
|
+
const {width, height, id} = source;
|
|
400
|
+
const framebuffer = source.device.createFramebuffer({
|
|
401
|
+
id: `framebuffer-for-${id}`,
|
|
402
|
+
width,
|
|
403
|
+
height,
|
|
404
|
+
colorAttachments: [source]
|
|
405
|
+
}) as unknown as WEBGLFramebuffer;
|
|
406
|
+
|
|
407
|
+
return {framebuffer, destroyFramebuffer: true};
|
|
408
|
+
}
|
|
409
|
+
return {framebuffer: source as unknown as WEBGLFramebuffer, destroyFramebuffer: false};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Returns number of components in a specific readPixels WebGL format
|
|
414
|
+
* @todo use shadertypes utils instead?
|
|
415
|
+
*/
|
|
315
416
|
export function glFormatToComponents(format): 1 | 2 | 3 | 4 {
|
|
316
417
|
switch (format) {
|
|
317
418
|
case GL.ALPHA:
|
|
@@ -333,7 +434,10 @@ export function glFormatToComponents(format): 1 | 2 | 3 | 4 {
|
|
|
333
434
|
}
|
|
334
435
|
}
|
|
335
436
|
|
|
336
|
-
|
|
437
|
+
/**
|
|
438
|
+
* Return byte count for given readPixels WebGL type
|
|
439
|
+
* @todo use shadertypes utils instead?
|
|
440
|
+
*/
|
|
337
441
|
export function glTypeToBytes(type: GL): 1 | 2 | 4 {
|
|
338
442
|
switch (type) {
|
|
339
443
|
case GL.UNSIGNED_BYTE:
|
|
@@ -349,23 +453,3 @@ export function glTypeToBytes(type: GL): 1 | 2 | 4 {
|
|
|
349
453
|
throw new Error('GLType');
|
|
350
454
|
}
|
|
351
455
|
}
|
|
352
|
-
|
|
353
|
-
// Helper methods
|
|
354
|
-
|
|
355
|
-
function getFramebuffer(source: Texture | Framebuffer): {
|
|
356
|
-
framebuffer: WEBGLFramebuffer;
|
|
357
|
-
destroyFramebuffer: boolean;
|
|
358
|
-
} {
|
|
359
|
-
if (source instanceof Texture) {
|
|
360
|
-
const {width, height, id} = source;
|
|
361
|
-
const framebuffer = source.device.createFramebuffer({
|
|
362
|
-
id: `framebuffer-for-${id}`,
|
|
363
|
-
width,
|
|
364
|
-
height,
|
|
365
|
-
colorAttachments: [source]
|
|
366
|
-
}) as unknown as WEBGLFramebuffer;
|
|
367
|
-
|
|
368
|
-
return {framebuffer, destroyFramebuffer: true};
|
|
369
|
-
}
|
|
370
|
-
return {framebuffer: source as unknown as WEBGLFramebuffer, destroyFramebuffer: false};
|
|
371
|
-
}
|
|
@@ -8,6 +8,8 @@ import type {
|
|
|
8
8
|
CopyBufferToTextureOptions,
|
|
9
9
|
CopyTextureToBufferOptions,
|
|
10
10
|
CopyTextureToTextureOptions,
|
|
11
|
+
// ClearTextureOptions,
|
|
12
|
+
// ReadTextureOptions,
|
|
11
13
|
QuerySet,
|
|
12
14
|
Buffer
|
|
13
15
|
} from '@luma.gl/core';
|
|
@@ -52,6 +54,10 @@ export class WEBGLCommandEncoder extends CommandEncoder {
|
|
|
52
54
|
this.commandBuffer.commands.push({name: 'copy-texture-to-texture', options});
|
|
53
55
|
}
|
|
54
56
|
|
|
57
|
+
// clearTexture(options: ClearTextureOptions): void {
|
|
58
|
+
// this.commandBuffer.commands.push({name: 'copy-texture-to-texture', options});
|
|
59
|
+
// }
|
|
60
|
+
|
|
55
61
|
override pushDebugGroup(groupLabel: string): void {}
|
|
56
62
|
override popDebugGroup() {}
|
|
57
63
|
|
|
@@ -72,6 +72,20 @@ export class WEBGLExternalTexture extends WEBGLTexture {
|
|
|
72
72
|
data.addEventListener('loadeddata', () => this.initialize(props));
|
|
73
73
|
return this;
|
|
74
74
|
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
initialize() {
|
|
78
|
+
// TODO - Video handling, move to ExternalTexture?
|
|
79
|
+
// if (isVideo) {
|
|
80
|
+
// this._video = {
|
|
81
|
+
// video: data,
|
|
82
|
+
// // TODO - should we be using the sampler parameters here?
|
|
83
|
+
// parameters: {},
|
|
84
|
+
// // @ts-expect-error HTMLVideoElement.HAVE_CURRENT_DATA is not declared
|
|
85
|
+
// lastTime: data.readyState >= HTMLVideoElement.HAVE_CURRENT_DATA ? data.currentTime : -1
|
|
86
|
+
// };
|
|
87
|
+
// }
|
|
88
|
+
}
|
|
75
89
|
|
|
76
90
|
update(): this {
|
|
77
91
|
if (this._video) {
|
|
@@ -77,8 +77,7 @@ export class WEBGLFramebuffer extends Framebuffer {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/** Check the status */
|
|
80
|
-
|
|
81
|
-
if (this.props.check !== false) {
|
|
80
|
+
if (this.device.props.debug) {
|
|
82
81
|
const status = this.gl.checkFramebufferStatus(GL.FRAMEBUFFER) as GL;
|
|
83
82
|
if (status !== GL.FRAMEBUFFER_COMPLETE) {
|
|
84
83
|
throw new Error(`Framebuffer ${_getFrameBufferStatus(status)}`);
|