@flighthq/render-gl 0.2.0 → 0.2.1-next.410.a23f189
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/glCompressedTexture.d.ts +8 -0
- package/dist/glCompressedTexture.d.ts.map +1 -0
- package/dist/glCompressedTexture.js +270 -0
- package/dist/glCompressedTexture.js.map +1 -0
- package/dist/glDraw.d.ts +4 -2
- package/dist/glDraw.d.ts.map +1 -1
- package/dist/glDraw.js +215 -20
- package/dist/glDraw.js.map +1 -1
- package/dist/glFullscreenPass.d.ts.map +1 -1
- package/dist/glFullscreenPass.js +32 -0
- package/dist/glFullscreenPass.js.map +1 -1
- package/dist/glLinearToSrgbPass.d.ts +4 -0
- package/dist/glLinearToSrgbPass.d.ts.map +1 -0
- package/dist/glLinearToSrgbPass.js +42 -0
- package/dist/glLinearToSrgbPass.js.map +1 -0
- package/dist/glPresentRenderTarget.d.ts +3 -0
- package/dist/glPresentRenderTarget.d.ts.map +1 -0
- package/dist/glPresentRenderTarget.js +35 -0
- package/dist/glPresentRenderTarget.js.map +1 -0
- package/dist/glRenderPass.d.ts +5 -0
- package/dist/glRenderPass.d.ts.map +1 -0
- package/dist/glRenderPass.js +130 -0
- package/dist/glRenderPass.js.map +1 -0
- package/dist/glRenderState.d.ts +1 -1
- package/dist/glRenderState.d.ts.map +1 -1
- package/dist/glRenderState.js +1 -0
- package/dist/glRenderState.js.map +1 -1
- package/dist/glRenderTarget.d.ts +2 -15
- package/dist/glRenderTarget.d.ts.map +1 -1
- package/dist/glRenderTarget.js +48 -57
- package/dist/glRenderTarget.js.map +1 -1
- package/dist/glRenderTargetPool.d.ts.map +1 -1
- package/dist/glRenderTargetPool.js +4 -0
- package/dist/glRenderTargetPool.js.map +1 -1
- package/dist/glSkinPaletteTexture.d.ts +5 -0
- package/dist/glSkinPaletteTexture.d.ts.map +1 -0
- package/dist/glSkinPaletteTexture.js +42 -0
- package/dist/glSkinPaletteTexture.js.map +1 -0
- package/dist/glTestHelper.d.ts.map +1 -1
- package/dist/glTestHelper.js +1 -0
- package/dist/glTestHelper.js.map +1 -1
- package/dist/glTextureUpload.d.ts +5 -0
- package/dist/glTextureUpload.d.ts.map +1 -0
- package/dist/glTextureUpload.js +27 -0
- package/dist/glTextureUpload.js.map +1 -0
- package/dist/glTextureVideoUpload.d.ts +3 -0
- package/dist/glTextureVideoUpload.d.ts.map +1 -0
- package/dist/glTextureVideoUpload.js +24 -0
- package/dist/glTextureVideoUpload.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/glCompressedTexture.test.ts +276 -0
- package/src/glDraw.test.ts +319 -36
- package/src/glFullscreenPass.test.ts +22 -1
- package/src/glLinearToSrgbPass.test.ts +75 -0
- package/src/glPresentRenderTarget.test.ts +62 -0
- package/src/glReadback.test.ts +1 -0
- package/src/glRenderPass.test.ts +170 -0
- package/src/glRenderTarget.test.ts +63 -98
- package/src/glRenderTargetPool.test.ts +14 -0
- package/src/glSkinPaletteTexture.test.ts +129 -0
- package/src/glTextureUpload.test.ts +49 -0
- package/src/glTextureVideoUpload.test.ts +53 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GlCompressedTextureDecoder, GlCompressedTextureSupport, GlRenderState, TextureContainer, TextureContainerFormat } from '@flighthq/types';
|
|
2
|
+
export declare function detectGlCompressedTextureSupport(gl: WebGL2RenderingContext): GlCompressedTextureSupport;
|
|
3
|
+
export declare function getGlCompressedTextureFormat(gl: WebGL2RenderingContext, format: TextureContainerFormat): number;
|
|
4
|
+
export declare function hasGlCompressedTextureFormat(support: Readonly<GlCompressedTextureSupport>, format: TextureContainerFormat): boolean;
|
|
5
|
+
export declare function registerGlCompressedTextureDecoder(state: GlRenderState, decode: GlCompressedTextureDecoder | null): void;
|
|
6
|
+
export declare function registerGlCompressedTextureUpload(state: GlRenderState, uploader?: null): void;
|
|
7
|
+
export declare function uploadGlCompressedTextureContainer(gl: WebGL2RenderingContext, container: Readonly<TextureContainer>, payload: Readonly<Uint8Array>, decode?: GlCompressedTextureDecoder): boolean;
|
|
8
|
+
//# sourceMappingURL=glCompressedTexture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glCompressedTexture.d.ts","sourceRoot":"","sources":["../src/glCompressedTexture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,aAAa,EAEb,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AAmBzB,wBAAgB,gCAAgC,CAAC,EAAE,EAAE,sBAAsB,GAAG,0BAA0B,CAWvG;AAQD,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,sBAAsB,EAAE,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAqG/G;AAKD,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,QAAQ,CAAC,0BAA0B,CAAC,EAC7C,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAuCT;AAOD,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,0BAA0B,GAAG,IAAI,GACxC,IAAI,CAEN;AASD,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAE7F;AAiBD,wBAAgB,kCAAkC,CAChD,EAAE,EAAE,sBAAsB,EAC1B,SAAS,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EACrC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC7B,MAAM,CAAC,EAAE,0BAA0B,GAClC,OAAO,CA0DT"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { getGlRenderStateRuntime } from './glRenderState';
|
|
2
|
+
// GPU-native block-compressed texture upload for WebGL2: hand a parsed TextureContainer (KTX2 / DDS /
|
|
3
|
+
// ATF) plus its byte payload and this pushes every mip level straight to the GPU with
|
|
4
|
+
// `compressedTexImage2D` — no CPU decode — when the device exposes the matching
|
|
5
|
+
// `WEBGL_compressed_texture_*` extension. When it does not, an optional RGBA decode seam turns each
|
|
6
|
+
// level into plain pixels the portable `texImage2D` path uploads, so an asset still renders on
|
|
7
|
+
// hardware missing that block format (desktop S3TC/BPTC vs mobile ETC2/ASTC).
|
|
8
|
+
//
|
|
9
|
+
// Detection is done once per context via `detectGlCompressedTextureSupport`; the format→GL-enum
|
|
10
|
+
// mapping reads the live extension objects, so the enum constants come from the browser, not a baked
|
|
11
|
+
// table. Basis intermediate formats (`etc1s`/`uastc`) are NOT uploaded here — they must be transcoded
|
|
12
|
+
// to a concrete BCn/ETC/ASTC format first (see the deferred `@flighthq/texture-transcode` seam).
|
|
13
|
+
// Probes which block-compressed families the WebGL2 context can upload natively, from its
|
|
14
|
+
// `WEBGL_compressed_texture_*` extensions. Call once per context and cache the result; each `getExtension`
|
|
15
|
+
// activates the extension so the enum constants become readable by `getGlCompressedTextureFormat`.
|
|
16
|
+
export function detectGlCompressedTextureSupport(gl) {
|
|
17
|
+
return {
|
|
18
|
+
astc: gl.getExtension('WEBGL_compressed_texture_astc') !== null,
|
|
19
|
+
bptc: gl.getExtension('EXT_texture_compression_bptc') !== null,
|
|
20
|
+
etc: gl.getExtension('WEBGL_compressed_texture_etc') !== null,
|
|
21
|
+
pvrtc: gl.getExtension('WEBGL_compressed_texture_pvrtc') !== null,
|
|
22
|
+
rgtc: gl.getExtension('EXT_texture_compression_rgtc') !== null,
|
|
23
|
+
s3tc: gl.getExtension('WEBGL_compressed_texture_s3tc') !== null &&
|
|
24
|
+
gl.getExtension('WEBGL_compressed_texture_s3tc_srgb') !== null,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Resolves the GL `internalformat` enum for a container format from the device's live compression
|
|
28
|
+
// extensions, or -1 when the device cannot upload that format natively (missing extension, or an
|
|
29
|
+
// uncompressed / Basis-intermediate format that is not a `compressedTexImage2D` target). The returned
|
|
30
|
+
// number is the exact enum `compressedTexImage2D` expects, read off the extension object so it matches
|
|
31
|
+
// the running browser. Requires the relevant extension to already be enabled (call
|
|
32
|
+
// `detectGlCompressedTextureSupport` first).
|
|
33
|
+
export function getGlCompressedTextureFormat(gl, format) {
|
|
34
|
+
const s3tc = gl.getExtension('WEBGL_compressed_texture_s3tc');
|
|
35
|
+
const s3tcSrgb = gl.getExtension('WEBGL_compressed_texture_s3tc_srgb');
|
|
36
|
+
const rgtc = gl.getExtension('EXT_texture_compression_rgtc');
|
|
37
|
+
const bptc = gl.getExtension('EXT_texture_compression_bptc');
|
|
38
|
+
const etc = gl.getExtension('WEBGL_compressed_texture_etc');
|
|
39
|
+
const astc = gl.getExtension('WEBGL_compressed_texture_astc');
|
|
40
|
+
const pvrtc = gl.getExtension('WEBGL_compressed_texture_pvrtc');
|
|
41
|
+
const enumFromExt = (ext, key) => typeof ext?.[key] === 'number' ? ext[key] : -1;
|
|
42
|
+
switch (format) {
|
|
43
|
+
case 'bc1':
|
|
44
|
+
return enumFromExt(s3tc, 'COMPRESSED_RGBA_S3TC_DXT1_EXT');
|
|
45
|
+
case 'bc1Srgb':
|
|
46
|
+
return enumFromExt(s3tcSrgb, 'COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT');
|
|
47
|
+
case 'bc2':
|
|
48
|
+
return enumFromExt(s3tc, 'COMPRESSED_RGBA_S3TC_DXT3_EXT');
|
|
49
|
+
case 'bc2Srgb':
|
|
50
|
+
return enumFromExt(s3tcSrgb, 'COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT');
|
|
51
|
+
case 'bc3':
|
|
52
|
+
return enumFromExt(s3tc, 'COMPRESSED_RGBA_S3TC_DXT5_EXT');
|
|
53
|
+
case 'bc3Srgb':
|
|
54
|
+
return enumFromExt(s3tcSrgb, 'COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT');
|
|
55
|
+
case 'bc4':
|
|
56
|
+
return enumFromExt(rgtc, 'COMPRESSED_RED_RGTC1_EXT');
|
|
57
|
+
case 'bc4Snorm':
|
|
58
|
+
return enumFromExt(rgtc, 'COMPRESSED_SIGNED_RED_RGTC1_EXT');
|
|
59
|
+
case 'bc5':
|
|
60
|
+
return enumFromExt(rgtc, 'COMPRESSED_RED_GREEN_RGTC2_EXT');
|
|
61
|
+
case 'bc5Snorm':
|
|
62
|
+
return enumFromExt(rgtc, 'COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT');
|
|
63
|
+
case 'bc6hUfloat':
|
|
64
|
+
return enumFromExt(bptc, 'COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT');
|
|
65
|
+
case 'bc6hSfloat':
|
|
66
|
+
return enumFromExt(bptc, 'COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT');
|
|
67
|
+
case 'bc7':
|
|
68
|
+
return enumFromExt(bptc, 'COMPRESSED_RGBA_BPTC_UNORM_EXT');
|
|
69
|
+
case 'bc7Srgb':
|
|
70
|
+
return enumFromExt(bptc, 'COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT');
|
|
71
|
+
case 'etc1':
|
|
72
|
+
case 'etc2Rgb':
|
|
73
|
+
return enumFromExt(etc, 'COMPRESSED_RGB8_ETC2');
|
|
74
|
+
case 'etc2RgbSrgb':
|
|
75
|
+
return enumFromExt(etc, 'COMPRESSED_SRGB8_ETC2');
|
|
76
|
+
case 'etc2Rgba':
|
|
77
|
+
return enumFromExt(etc, 'COMPRESSED_RGBA8_ETC2_EAC');
|
|
78
|
+
case 'etc2RgbaSrgb':
|
|
79
|
+
return enumFromExt(etc, 'COMPRESSED_SRGB8_ALPHA8_ETC2_EAC');
|
|
80
|
+
case 'etc2RgbA1':
|
|
81
|
+
return enumFromExt(etc, 'COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2');
|
|
82
|
+
case 'etc2RgbA1Srgb':
|
|
83
|
+
return enumFromExt(etc, 'COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2');
|
|
84
|
+
case 'eacR11':
|
|
85
|
+
return enumFromExt(etc, 'COMPRESSED_R11_EAC');
|
|
86
|
+
case 'eacR11Snorm':
|
|
87
|
+
return enumFromExt(etc, 'COMPRESSED_SIGNED_R11_EAC');
|
|
88
|
+
case 'eacRg11':
|
|
89
|
+
return enumFromExt(etc, 'COMPRESSED_RG11_EAC');
|
|
90
|
+
case 'eacRg11Snorm':
|
|
91
|
+
return enumFromExt(etc, 'COMPRESSED_SIGNED_RG11_EAC');
|
|
92
|
+
case 'pvrtc2bppRgb':
|
|
93
|
+
return enumFromExt(pvrtc, 'COMPRESSED_RGB_PVRTC_2BPPV1_IMG');
|
|
94
|
+
case 'pvrtc2bppRgba':
|
|
95
|
+
return enumFromExt(pvrtc, 'COMPRESSED_RGBA_PVRTC_2BPPV1_IMG');
|
|
96
|
+
case 'pvrtc4bppRgb':
|
|
97
|
+
return enumFromExt(pvrtc, 'COMPRESSED_RGB_PVRTC_4BPPV1_IMG');
|
|
98
|
+
case 'pvrtc4bppRgba':
|
|
99
|
+
return enumFromExt(pvrtc, 'COMPRESSED_RGBA_PVRTC_4BPPV1_IMG');
|
|
100
|
+
case 'astc4x4':
|
|
101
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_4x4_KHR');
|
|
102
|
+
case 'astc5x4':
|
|
103
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_5x4_KHR');
|
|
104
|
+
case 'astc5x5':
|
|
105
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_5x5_KHR');
|
|
106
|
+
case 'astc6x5':
|
|
107
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_6x5_KHR');
|
|
108
|
+
case 'astc6x6':
|
|
109
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_6x6_KHR');
|
|
110
|
+
case 'astc8x5':
|
|
111
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_8x5_KHR');
|
|
112
|
+
case 'astc8x6':
|
|
113
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_8x6_KHR');
|
|
114
|
+
case 'astc8x8':
|
|
115
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_8x8_KHR');
|
|
116
|
+
case 'astc10x5':
|
|
117
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_10x5_KHR');
|
|
118
|
+
case 'astc10x6':
|
|
119
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_10x6_KHR');
|
|
120
|
+
case 'astc10x8':
|
|
121
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_10x8_KHR');
|
|
122
|
+
case 'astc10x10':
|
|
123
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_10x10_KHR');
|
|
124
|
+
case 'astc12x10':
|
|
125
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_12x10_KHR');
|
|
126
|
+
case 'astc12x12':
|
|
127
|
+
return enumFromExt(astc, 'COMPRESSED_RGBA_ASTC_12x12_KHR');
|
|
128
|
+
default:
|
|
129
|
+
// Uncompressed and Basis-intermediate formats have no compressedTexImage2D enum.
|
|
130
|
+
return -1;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// True when the device's detected support covers a container format's family — the cheap, GL-free gate
|
|
134
|
+
// an asset pipeline uses to pick which of several shipped encodings to upload, without touching the
|
|
135
|
+
// context. `srgb` twins ride the same extension as their unorm base, so both report against one flag.
|
|
136
|
+
export function hasGlCompressedTextureFormat(support, format) {
|
|
137
|
+
switch (format) {
|
|
138
|
+
case 'bc1':
|
|
139
|
+
case 'bc1Srgb':
|
|
140
|
+
case 'bc2':
|
|
141
|
+
case 'bc2Srgb':
|
|
142
|
+
case 'bc3':
|
|
143
|
+
case 'bc3Srgb':
|
|
144
|
+
return support.s3tc;
|
|
145
|
+
case 'bc4':
|
|
146
|
+
case 'bc4Snorm':
|
|
147
|
+
case 'bc5':
|
|
148
|
+
case 'bc5Snorm':
|
|
149
|
+
return support.rgtc;
|
|
150
|
+
case 'bc6hUfloat':
|
|
151
|
+
case 'bc6hSfloat':
|
|
152
|
+
case 'bc7':
|
|
153
|
+
case 'bc7Srgb':
|
|
154
|
+
return support.bptc;
|
|
155
|
+
case 'etc1':
|
|
156
|
+
case 'etc2Rgb':
|
|
157
|
+
case 'etc2RgbSrgb':
|
|
158
|
+
case 'etc2Rgba':
|
|
159
|
+
case 'etc2RgbaSrgb':
|
|
160
|
+
case 'etc2RgbA1':
|
|
161
|
+
case 'etc2RgbA1Srgb':
|
|
162
|
+
case 'eacR11':
|
|
163
|
+
case 'eacR11Snorm':
|
|
164
|
+
case 'eacRg11':
|
|
165
|
+
case 'eacRg11Snorm':
|
|
166
|
+
return support.etc;
|
|
167
|
+
case 'pvrtc2bppRgb':
|
|
168
|
+
case 'pvrtc2bppRgba':
|
|
169
|
+
case 'pvrtc4bppRgb':
|
|
170
|
+
case 'pvrtc4bppRgba':
|
|
171
|
+
return support.pvrtc;
|
|
172
|
+
default:
|
|
173
|
+
return isAstcFormat(format) ? support.astc : false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Installs the RGBA fallback decoder used when the device cannot upload a compressed container's format
|
|
177
|
+
// natively — the seam that lets an S3TC/BPTC asset still render on mobile ETC2/ASTC hardware (and vice
|
|
178
|
+
// versa) by decoding each level to plain pixels. Opt-in and last-write-wins: a state that never draws a
|
|
179
|
+
// compressed texture the device lacks never installs one, so the decoder (and any WASM block-codec it
|
|
180
|
+
// wraps) tree-shakes out. Pass null to clear a previously installed decoder.
|
|
181
|
+
export function registerGlCompressedTextureDecoder(state, decode) {
|
|
182
|
+
getGlRenderStateRuntime(state).compressedTextureDecoder = decode;
|
|
183
|
+
}
|
|
184
|
+
// Installs the block-compressed upload seam on a render state, opting the ~40-format
|
|
185
|
+
// uploadGlCompressedTextureContainer path into the bundle only for a state that actually draws a
|
|
186
|
+
// compressed texture. The 2D display draw path (uploadGlDisplayTexture) reads the installed handler off
|
|
187
|
+
// the runtime and skips a compressed-only resource when none is registered, so a plain element/data
|
|
188
|
+
// bitmap never carries the compression enum table. Opt-in and last-write-wins; pass null to clear a
|
|
189
|
+
// previously installed uploader. The installed handler bridges a compressed ImageResource to
|
|
190
|
+
// uploadGlCompressedTextureContainer, threading through any registered RGBA decode fallback.
|
|
191
|
+
export function registerGlCompressedTextureUpload(state, uploader) {
|
|
192
|
+
getGlRenderStateRuntime(state).compressedTextureUpload = uploader === null ? null : uploadGlCompressedImageResource;
|
|
193
|
+
}
|
|
194
|
+
// Uploads every stored sub-image of a compressed container to the texture the caller has bound. Takes
|
|
195
|
+
// the GPU-native `compressedTexImage2D`/`compressedTexImage3D` path when the device supports the
|
|
196
|
+
// container's format; otherwise, if a `decode` seam is supplied, decompresses each 2D level to RGBA and
|
|
197
|
+
// uploads it through the portable pixel path. Returns `true` when the container was uploaded (either
|
|
198
|
+
// path), `false` when the format is neither natively supported nor decodable, or when the container is
|
|
199
|
+
// still supercompressed (`supercompression !== 'None'`) — a sentinel, not a throw, so a caller falls
|
|
200
|
+
// back to a different asset (or inflates/transcodes first). The caller owns creating/binding the
|
|
201
|
+
// texture (to gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP, or gl.TEXTURE_2D_ARRAY per the container's shape) and
|
|
202
|
+
// setting sampler/mip state; this uploads only the container's own sub-images.
|
|
203
|
+
//
|
|
204
|
+
// `container.levels` is the flat subresource list in `mip + (face + layer * faces) * mipLevels` order;
|
|
205
|
+
// each flat index is decoded back to (mip, face, layer) so a cubemap's six faces land on
|
|
206
|
+
// gl.TEXTURE_CUBE_MAP_POSITIVE_X + face and an array's layers slice into a gl.TEXTURE_2D_ARRAY. The
|
|
207
|
+
// RGBA decode fallback covers only the plain 2D case (faces === 1, layers === 1); a compressed cubemap
|
|
208
|
+
// or array with no native support reports failure rather than a partial 2D upload.
|
|
209
|
+
export function uploadGlCompressedTextureContainer(gl, container, payload, decode) {
|
|
210
|
+
// A still-wrapped supercompressed payload (Zstd/ZLIB deflate or BasisLZ transcode) is not block data;
|
|
211
|
+
// uploading it as if it were would push corrupt pixels. Fail the sentinel and let the caller inflate
|
|
212
|
+
// or transcode through the deferred seam first.
|
|
213
|
+
if (container.supercompression !== 'None')
|
|
214
|
+
return false;
|
|
215
|
+
const nativeFormat = getGlCompressedTextureFormat(gl, container.format);
|
|
216
|
+
const faces = container.faces;
|
|
217
|
+
const layers = container.layers;
|
|
218
|
+
const mipLevels = container.mipLevels;
|
|
219
|
+
if (nativeFormat !== -1) {
|
|
220
|
+
// An array texture is immutable storage: allocate the whole mip chain × depth once with
|
|
221
|
+
// texStorage3D, then blit each layer's slice into its depth slot (layers are non-contiguous in the
|
|
222
|
+
// layer-major flat list, so per-subresource upload is required; compressedTexImage3D cannot
|
|
223
|
+
// allocate a null store the way the 2D path does).
|
|
224
|
+
if (layers > 1) {
|
|
225
|
+
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, mipLevels, nativeFormat, container.width, container.height, layers);
|
|
226
|
+
}
|
|
227
|
+
for (let index = 0; index < container.levels.length; index += 1) {
|
|
228
|
+
const entry = container.levels[index];
|
|
229
|
+
const view = new Uint8Array(payload.buffer, payload.byteOffset + entry.byteOffset, entry.byteLength);
|
|
230
|
+
const mip = index % mipLevels;
|
|
231
|
+
const faceLayer = (index - mip) / mipLevels;
|
|
232
|
+
const face = faceLayer % faces;
|
|
233
|
+
const layer = (faceLayer - face) / faces;
|
|
234
|
+
if (layers > 1) {
|
|
235
|
+
gl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, mip, 0, 0, layer, entry.width, entry.height, 1, nativeFormat, view);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
const target = faces === 6 ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + face : gl.TEXTURE_2D;
|
|
239
|
+
gl.compressedTexImage2D(target, mip, nativeFormat, entry.width, entry.height, 0, view);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
// RGBA decode fallback: plain 2D only. A cubemap/array with no native block support is not decoded
|
|
245
|
+
// face-by-face here — report failure so the caller supplies a different encoding.
|
|
246
|
+
if (decode === undefined || faces !== 1 || layers !== 1)
|
|
247
|
+
return false;
|
|
248
|
+
for (let mip = 0; mip < container.levels.length; mip += 1) {
|
|
249
|
+
const entry = container.levels[mip];
|
|
250
|
+
const view = new Uint8Array(payload.buffer, payload.byteOffset + entry.byteOffset, entry.byteLength);
|
|
251
|
+
const rgba = decode(container.format, entry.width, entry.height, view);
|
|
252
|
+
if (rgba === null)
|
|
253
|
+
return false;
|
|
254
|
+
gl.texImage2D(gl.TEXTURE_2D, mip, gl.RGBA, entry.width, entry.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, rgba);
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
function isAstcFormat(format) {
|
|
259
|
+
return format.startsWith('astc');
|
|
260
|
+
}
|
|
261
|
+
// The installed GlCompressedTextureUploader: bridges a compressed ImageResource to the container upload,
|
|
262
|
+
// threading through any registered RGBA decode fallback. Returns false when the resource carries no
|
|
263
|
+
// compressed payload so the display path leaves the texture as-is rather than uploading garbage.
|
|
264
|
+
function uploadGlCompressedImageResource(gl, image, decode) {
|
|
265
|
+
const compressed = image.compressed;
|
|
266
|
+
if (compressed === null)
|
|
267
|
+
return false;
|
|
268
|
+
return uploadGlCompressedTextureContainer(gl, compressed.container, compressed.payload, decode ?? undefined);
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=glCompressedTexture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glCompressedTexture.js","sourceRoot":"","sources":["../src/glCompressedTexture.ts"],"names":[],"mappings":"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"}
|
package/dist/glDraw.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import type { GlBitmapShader, GlBlendRealization, GlRenderState } from '@flighthq/types';
|
|
1
|
+
import type { GlBitmapShader, GlBlendRealization, GlRenderState, ImageResource, SamplerLike, VideoTexture } from '@flighthq/types';
|
|
2
2
|
import { BlendMode } from '@flighthq/types';
|
|
3
3
|
export declare function applyGlBlendMode(state: GlRenderState, blendMode: BlendMode | null): void;
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function bindGlImageResourceTexture(state: GlRenderState, image: Readonly<ImageResource>, sampler?: Readonly<SamplerLike> | null): WebGLTexture;
|
|
5
|
+
export declare function bindGlTexture(state: GlRenderState, imageSource: CanvasImageSource, sampler?: Readonly<SamplerLike> | null): WebGLTexture;
|
|
6
|
+
export declare function bindGlVideoTexture(state: GlRenderState, videoTexture: Readonly<VideoTexture>, sampler?: Readonly<SamplerLike> | null): WebGLTexture;
|
|
5
7
|
export declare function createGlTexture(state: GlRenderState): WebGLTexture;
|
|
6
8
|
export declare function drawGlQuad(state: GlRenderState, x0: number, y0: number, x1: number, y1: number, u0: number, v0: number, u1: number, v1: number): void;
|
|
7
9
|
export declare function enableGlBlendModeSupport(state: GlRenderState): void;
|
package/dist/glDraw.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glDraw.d.ts","sourceRoot":"","sources":["../src/glDraw.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"glDraw.d.ts","sourceRoot":"","sources":["../src/glDraw.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,aAAa,EAEb,aAAa,EACb,WAAW,EAGX,YAAY,EACb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAY5C,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAQxF;AASD,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC9B,OAAO,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,GACrC,YAAY,CAiBd;AAWD,wBAAgB,aAAa,CAC3B,KAAK,EAAE,aAAa,EACpB,WAAW,EAAE,iBAAiB,EAC9B,OAAO,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,GACrC,YAAY,CA+Bd;AAWD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,EACpB,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,EACpC,OAAO,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,GACrC,YAAY,CAgBd;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAYlE;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,IAAI,CA0BN;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAGnE;AAKD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAExF;AAKD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAEtE;AAKD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,GAAG,IAAI,CAGrH;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,aAAa,EACpB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,IAAI,CAcN;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAe5G;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAShF"}
|
package/dist/glDraw.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { BlendMode } from '@flighthq/types';
|
|
2
2
|
import { getGlRenderStateRuntime } from './glRenderState';
|
|
3
3
|
import { setGlAttributes, setGlMatrixFromValues } from './glShader';
|
|
4
|
+
import { uploadGlTextureData, uploadGlTextureElement } from './glTextureUpload';
|
|
5
|
+
import { uploadGlTextureVideoFrame } from './glTextureVideoUpload';
|
|
4
6
|
// Applies the blend mode's registered fixed-function realization to the GL context, skipping the
|
|
5
7
|
// work when the mode is unchanged. A mode with no registered realization (an unregistered vendor
|
|
6
8
|
// mode, or a built-in with no fixed-function equivalent such as Overlay) degrades to normal
|
|
@@ -16,19 +18,48 @@ export function applyGlBlendMode(state, blendMode) {
|
|
|
16
18
|
gl.blendEquation(gl[realization.equation ?? 'FUNC_ADD']);
|
|
17
19
|
gl.blendFunc(gl[realization.src], gl[realization.dst]);
|
|
18
20
|
}
|
|
19
|
-
|
|
21
|
+
// Binds (uploading + caching on first use, re-uploading when the pixels change) the GL texture for an
|
|
22
|
+
// ImageResource — a bitmap, sprite atlas, or material map — and applies the sampler's full state. The
|
|
23
|
+
// resource-level sibling of bindGlTexture (which takes a raw element): it accepts an element-backed OR a
|
|
24
|
+
// data-only generated Surface (source-or-data upload via uploadGlDisplayTexture), and caches by the
|
|
25
|
+
// resource entity in imageResourceTextureCache, keyed with the uploaded `version` so an in-place Surface
|
|
26
|
+
// edit (which bumps version) re-uploads without the caller tracking it. Sampler state is re-applied every
|
|
27
|
+
// bind so a resource reused by two materials with different samplers follows the current draw.
|
|
28
|
+
export function bindGlImageResourceTexture(state, image, sampler) {
|
|
29
|
+
const runtime = getGlRenderStateRuntime(state);
|
|
30
|
+
const gl = state.gl;
|
|
31
|
+
const cache = runtime.imageResourceTextureCache;
|
|
32
|
+
let entry = cache.get(image);
|
|
33
|
+
if (entry === undefined) {
|
|
34
|
+
entry = { texture: gl.createTexture(), version: -1 };
|
|
35
|
+
cache.set(image, entry);
|
|
36
|
+
}
|
|
37
|
+
gl.bindTexture(gl.TEXTURE_2D, entry.texture);
|
|
38
|
+
runtime.currentTexture = entry.texture;
|
|
39
|
+
if (entry.version !== image.version) {
|
|
40
|
+
uploadGlDisplayTexture(state, image);
|
|
41
|
+
entry.version = image.version;
|
|
42
|
+
}
|
|
43
|
+
applyGlSamplerState(state, runtime, entry.texture, sampler ?? null);
|
|
44
|
+
return entry.texture;
|
|
45
|
+
}
|
|
46
|
+
// Binds (uploading + caching on first use) the GL texture for an image source and applies the given
|
|
47
|
+
// sampler's full sampling state — wrap, min/mag filter, anisotropy, and a generated mip chain — to
|
|
48
|
+
// the bound texture. Sampler state is re-applied on every bind, not baked at creation, because the GL
|
|
49
|
+
// texture is cached by image source alone: one image reused by two materials with different samplers
|
|
50
|
+
// (e.g. a map bound as both normal and metallic-roughness with different sampling) shares one GL
|
|
51
|
+
// texture, so its sampling must follow the current draw rather than whoever uploaded it first. WebGL2
|
|
52
|
+
// allows REPEAT and mipmaps on NPOT textures, so no power-of-two constraint applies. Callers without a
|
|
53
|
+
// sampler (2D bitmap/text/sprite) get the historical default: the state's allowSmoothing filter,
|
|
54
|
+
// clamp-to-edge, and no mip chain. See applyGlSamplerState.
|
|
55
|
+
export function bindGlTexture(state, imageSource, sampler) {
|
|
20
56
|
const runtime = getGlRenderStateRuntime(state);
|
|
21
57
|
const gl = state.gl;
|
|
22
58
|
const textureCache = runtime.textureCache;
|
|
23
59
|
let texture = textureCache.get(imageSource);
|
|
24
60
|
if (!texture) {
|
|
25
|
-
const filter = state.allowSmoothing ? gl.LINEAR : gl.NEAREST;
|
|
26
61
|
texture = gl.createTexture();
|
|
27
62
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
28
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
|
|
29
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
|
|
30
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
31
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
32
63
|
// Both image and canvas sources present straight (un-premultiplied) alpha to texImage2D, so
|
|
33
64
|
// premultiply on upload to match the premultiplied (ONE, ONE_MINUS_SRC_ALPHA) blend used
|
|
34
65
|
// everywhere — uploaded images, canvas-backed shapes/text, and render-target composites. (A
|
|
@@ -39,12 +70,47 @@ export function bindGlTexture(state, imageSource) {
|
|
|
39
70
|
textureCache.set(imageSource, texture);
|
|
40
71
|
runtime.currentTexture = texture;
|
|
41
72
|
}
|
|
42
|
-
else
|
|
73
|
+
else {
|
|
74
|
+
// Always rebind on a cache hit, never skip on runtime.currentTexture. That tracker is the last
|
|
75
|
+
// texture bound to whatever unit was active THEN, but callers change the active unit between binds
|
|
76
|
+
// (a material binds its maps to units 0..4 via gl.activeTexture). Binding one image source to two
|
|
77
|
+
// units — e.g. a map reused as both normal and metallic-roughness — would otherwise leave the
|
|
78
|
+
// second unit unbound. A rebind is one cheap GL call; the sprite batch binds once per batch, so the
|
|
79
|
+
// dropped skip costs nothing meaningful.
|
|
43
80
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
44
81
|
runtime.currentTexture = texture;
|
|
45
82
|
}
|
|
83
|
+
// texture is the active TEXTURE_2D binding in every path above; apply this draw's sampler state here
|
|
84
|
+
// so a cache hit picks it up instead of the first uploader's.
|
|
85
|
+
applyGlSamplerState(state, runtime, texture, sampler ?? null);
|
|
46
86
|
return texture;
|
|
47
87
|
}
|
|
88
|
+
// Binds the GL texture for a VideoTexture and re-uploads the backing element's current frame only when
|
|
89
|
+
// its `frameId` has advanced past the one last uploaded — the dynamic, per-frame sibling of
|
|
90
|
+
// bindGlImageResourceTexture (settled ImageResource) and bindGlTexture (raw element). The GL texture is
|
|
91
|
+
// cached by the VideoTexture entity in the runtime's videoTextureCache (lazily created), so it persists
|
|
92
|
+
// across frames while the frameId dirty-gate keeps a paused or stalled stream from re-uploading. Applies
|
|
93
|
+
// the VideoTexture's sampler every bind so a stream shared by two samplers follows the current draw.
|
|
94
|
+
// Leaves the texture bound at the active unit for the caller to sample. Callers advance `frameId` via
|
|
95
|
+
// advanceVideoTexture when the element reports a fresh decoded frame; this reads the current frame
|
|
96
|
+
// through uploadGlTextureElement's zero-copy element fast-path.
|
|
97
|
+
export function bindGlVideoTexture(state, videoTexture, sampler) {
|
|
98
|
+
const runtime = getGlRenderStateRuntime(state);
|
|
99
|
+
const gl = state.gl;
|
|
100
|
+
const cache = (runtime.videoTextureCache ??= new WeakMap());
|
|
101
|
+
let entry = cache.get(videoTexture);
|
|
102
|
+
if (entry === undefined) {
|
|
103
|
+
entry = { texture: gl.createTexture(), uploadedFrameId: -1 };
|
|
104
|
+
cache.set(videoTexture, entry);
|
|
105
|
+
}
|
|
106
|
+
gl.bindTexture(gl.TEXTURE_2D, entry.texture);
|
|
107
|
+
runtime.currentTexture = entry.texture;
|
|
108
|
+
// Straight-alpha element under premultiplied blend would blow out RGB; match the bitmap/element path.
|
|
109
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
110
|
+
entry.uploadedFrameId = uploadGlTextureVideoFrame(gl, videoTexture, entry.uploadedFrameId);
|
|
111
|
+
applyGlSamplerState(state, runtime, entry.texture, sampler ?? videoTexture.sampler ?? null);
|
|
112
|
+
return entry.texture;
|
|
113
|
+
}
|
|
48
114
|
export function createGlTexture(state) {
|
|
49
115
|
const runtime = getGlRenderStateRuntime(state);
|
|
50
116
|
const gl = state.gl;
|
|
@@ -116,14 +182,19 @@ export function setGlQuadMatrixFromOffset(state, a, b, c, d, tx, ty, dx, dy) {
|
|
|
116
182
|
export function updateGlTexture(state, texture, canvas) {
|
|
117
183
|
const runtime = getGlRenderStateRuntime(state);
|
|
118
184
|
const gl = state.gl;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
185
|
+
// Always rebind before uploading — runtime.currentTexture is unit-blind (see bindGlTexture), so a
|
|
186
|
+
// skip could upload into whatever is bound on the currently-active unit instead of `texture`.
|
|
187
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
188
|
+
runtime.currentTexture = texture;
|
|
123
189
|
// Browsers pass canvas pixel data to Gl as straight (unmultiplied) alpha.
|
|
124
190
|
// Premultiply on upload so the texture matches the (ONE, ONE_MINUS_SRC_ALPHA) blend mode.
|
|
125
191
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
126
192
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
|
|
193
|
+
// Refresh the mip chain if this texture carries one (a canvas/video that opted into mipmaps); the
|
|
194
|
+
// re-uploaded base level would otherwise leave stale lower mips. The 2D default has no chain, so
|
|
195
|
+
// the common per-frame canvas/video upload skips the cost.
|
|
196
|
+
if (runtime.mipmappedTextures?.has(texture))
|
|
197
|
+
gl.generateMipmap(gl.TEXTURE_2D);
|
|
127
198
|
}
|
|
128
199
|
export function useGlProgram(state, shader) {
|
|
129
200
|
const runtime = getGlRenderStateRuntime(state);
|
|
@@ -135,15 +206,144 @@ export function useGlProgram(state, shader) {
|
|
|
135
206
|
runtime.currentProgram = program;
|
|
136
207
|
}
|
|
137
208
|
}
|
|
209
|
+
// Uploads an ImageResource into the currently-bound texture for the 2D display pipeline. The element
|
|
210
|
+
// fast-path premultiplies via UNPACK_PREMULTIPLY_ALPHA_WEBGL (straight-alpha element under a premultiplied
|
|
211
|
+
// (ONE, ONE_MINUS_SRC_ALPHA) blend would otherwise blow a 40%-white shape to opaque white). That flag is
|
|
212
|
+
// ignored for raw-data (ArrayBufferView) uploads, so straight-alpha `data` is premultiplied on the CPU
|
|
213
|
+
// first; opaque data (alpha 255, e.g. a normal/roughness map) premultiplies to itself, so this is a no-op
|
|
214
|
+
// there. The data path is what makes a memory-generated Surface a first-class 2D texture. A resource that
|
|
215
|
+
// carries only a block-`compressed` payload (no element or data) uploads through the GPU-native compressed
|
|
216
|
+
// path — falling back to the state's registered RGBA decoder when the device lacks the block format.
|
|
217
|
+
function uploadGlDisplayTexture(state, image) {
|
|
218
|
+
const gl = state.gl;
|
|
219
|
+
if (image.source !== null) {
|
|
220
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
221
|
+
uploadGlTextureElement(gl, gl.TEXTURE_2D, image.source);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (image.data === null && image.compressed !== null) {
|
|
225
|
+
// The compressed-container upload path is an opt-in seam (registerGlCompressedTextureUpload), so a
|
|
226
|
+
// state that only draws element/data bitmaps never carries its ~40-format enum table. When unset,
|
|
227
|
+
// skip rather than upload garbage — the texture stays empty until an uploader is registered.
|
|
228
|
+
const runtime = getGlRenderStateRuntime(state);
|
|
229
|
+
runtime.compressedTextureUpload?.(gl, image, runtime.compressedTextureDecoder ?? null);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const data = image.alphaType === 'straight' ? premultiplyStraightRgba8(image.data) : image.data;
|
|
233
|
+
uploadGlTextureData(gl, gl.TEXTURE_2D, image.width, image.height, data);
|
|
234
|
+
}
|
|
235
|
+
// Returns a new premultiplied rgba8 buffer from a straight-alpha one (rgb *= a/255). Allocates, but runs
|
|
236
|
+
// only on a texture upload (cache miss or content change), never in the per-frame draw path.
|
|
237
|
+
function premultiplyStraightRgba8(data) {
|
|
238
|
+
const out = new Uint8ClampedArray(data.length);
|
|
239
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
240
|
+
const a = data[i + 3];
|
|
241
|
+
out[i] = (data[i] * a) / 255;
|
|
242
|
+
out[i + 1] = (data[i + 1] * a) / 255;
|
|
243
|
+
out[i + 2] = (data[i + 2] * a) / 255;
|
|
244
|
+
out[i + 3] = a;
|
|
245
|
+
}
|
|
246
|
+
return out;
|
|
247
|
+
}
|
|
248
|
+
// Applies a sampler's wrap, filtering, anisotropy, and mip chain to the currently-bound TEXTURE_2D.
|
|
249
|
+
// Without a sampler it falls back to the state's allowSmoothing flag with clamp-to-edge and no mips —
|
|
250
|
+
// the 2D bitmap/sprite default. With one, every field comes from the descriptor. The mip chain is
|
|
251
|
+
// generated once per texture (tracked in runtime.mipmappedTextures) the first time a mip-sampling
|
|
252
|
+
// filter asks for it, so a shared texture first bound without mips and later with them still generates
|
|
253
|
+
// its chain. Filtering and wrap are set every bind (cheap) so a texture shared across samplers follows
|
|
254
|
+
// the current draw; only the one-time mip generation is gated.
|
|
255
|
+
function applyGlSamplerState(state, runtime, texture, sampler) {
|
|
256
|
+
const gl = state.gl;
|
|
257
|
+
if (!sampler) {
|
|
258
|
+
const filter = state.allowSmoothing ? gl.LINEAR : gl.NEAREST;
|
|
259
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
|
|
260
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
|
|
261
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
262
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const useMips = sampler.mipmaps && isGlMipmapFilter(sampler.minFilter);
|
|
266
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, glMinFilterValue(gl, sampler.minFilter, useMips));
|
|
267
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glMagFilterValue(gl, sampler.magFilter));
|
|
268
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, glTextureWrapValue(gl, sampler.wrapU));
|
|
269
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, glTextureWrapValue(gl, sampler.wrapV));
|
|
270
|
+
const ext = ensureGlAnisotropyExt(state, runtime);
|
|
271
|
+
if (ext) {
|
|
272
|
+
// Clamp the requested level to [1, hardware max]; 1 disables anisotropy and also resets a texture
|
|
273
|
+
// that a previous anisotropic sampler left elevated.
|
|
274
|
+
const level = Math.max(1, Math.min(sampler.anisotropy, runtime.maxAnisotropy ?? 1));
|
|
275
|
+
gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, level);
|
|
276
|
+
}
|
|
277
|
+
if (useMips) {
|
|
278
|
+
const mipped = (runtime.mipmappedTextures ??= new WeakSet());
|
|
279
|
+
if (!mipped.has(texture)) {
|
|
280
|
+
gl.generateMipmap(gl.TEXTURE_2D);
|
|
281
|
+
mipped.add(texture);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Resolves and caches EXT_texture_filter_anisotropic on the runtime: anisotropyExt is undefined until
|
|
286
|
+
// first queried, then the extension object or null when unsupported, and maxAnisotropy caches the
|
|
287
|
+
// hardware cap. Returns null when anisotropic filtering is unavailable.
|
|
288
|
+
function ensureGlAnisotropyExt(state, runtime) {
|
|
289
|
+
let ext = runtime.anisotropyExt;
|
|
290
|
+
if (ext === undefined) {
|
|
291
|
+
ext = state.gl.getExtension('EXT_texture_filter_anisotropic');
|
|
292
|
+
runtime.anisotropyExt = ext;
|
|
293
|
+
runtime.maxAnisotropy = ext ? state.gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 1;
|
|
294
|
+
}
|
|
295
|
+
return ext;
|
|
296
|
+
}
|
|
297
|
+
// Maps a magnification TextureFilter to its WebGL2 constant. Magnification never samples mips, so the
|
|
298
|
+
// mip-variant names collapse to their base LINEAR/NEAREST.
|
|
299
|
+
function glMagFilterValue(gl, filter) {
|
|
300
|
+
return filter.startsWith('nearest') ? gl.NEAREST : gl.LINEAR;
|
|
301
|
+
}
|
|
302
|
+
// Maps a minification TextureFilter to its WebGL2 constant. When useMips is false (mipmaps disabled or
|
|
303
|
+
// a non-mip filter) the mip-variant names collapse to their base LINEAR/NEAREST, so a filter that
|
|
304
|
+
// names a mip level never selects an absent chain (which would render the texture black).
|
|
305
|
+
function glMinFilterValue(gl, filter, useMips) {
|
|
306
|
+
if (!useMips)
|
|
307
|
+
return filter.startsWith('nearest') ? gl.NEAREST : gl.LINEAR;
|
|
308
|
+
switch (filter) {
|
|
309
|
+
case 'linear-mipmap-linear':
|
|
310
|
+
return gl.LINEAR_MIPMAP_LINEAR;
|
|
311
|
+
case 'linear-mipmap-nearest':
|
|
312
|
+
return gl.LINEAR_MIPMAP_NEAREST;
|
|
313
|
+
case 'nearest-mipmap-linear':
|
|
314
|
+
return gl.NEAREST_MIPMAP_LINEAR;
|
|
315
|
+
case 'nearest-mipmap-nearest':
|
|
316
|
+
return gl.NEAREST_MIPMAP_NEAREST;
|
|
317
|
+
case 'nearest':
|
|
318
|
+
return gl.NEAREST;
|
|
319
|
+
default:
|
|
320
|
+
return gl.LINEAR;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// True for the mip-sampling minification filters; the two non-mip modes ('linear'/'nearest') sample
|
|
324
|
+
// only the base level and need no mip chain.
|
|
325
|
+
function isGlMipmapFilter(filter) {
|
|
326
|
+
return filter !== 'linear' && filter !== 'nearest';
|
|
327
|
+
}
|
|
328
|
+
// Maps a sampler wrap mode to its WebGL2 texture-wrap constant; clamp-to-edge is the fallback. REPEAT
|
|
329
|
+
// tiles the sampled uv, which is what makes setTextureUvScale / a repeat sampler actually tile.
|
|
330
|
+
function glTextureWrapValue(gl, wrap) {
|
|
331
|
+
if (wrap === 'repeat')
|
|
332
|
+
return gl.REPEAT;
|
|
333
|
+
if (wrap === 'mirror-repeat')
|
|
334
|
+
return gl.MIRRORED_REPEAT;
|
|
335
|
+
return gl.CLAMP_TO_EDGE;
|
|
336
|
+
}
|
|
138
337
|
const NORMAL_BLEND = { src: 'ONE', dst: 'ONE_MINUS_SRC_ALPHA' };
|
|
139
338
|
// The built-in blend modes registerDefaultGlBlendModes installs, each with its fixed-function
|
|
140
|
-
// realization
|
|
141
|
-
//
|
|
339
|
+
// realization — the cheap fixed-function set. The Porter-Duff coverage operators (Erase/Alpha/None/…) are
|
|
340
|
+
// a CompositeEffect, the destination-reading blends (Overlay/HardLight/…) a BlendEffect, and rare
|
|
341
|
+
// equations like Subtract are wired on demand via registerGlBlendMode — none belong in the node-property
|
|
342
|
+
// set. Darken/Lighten are exact only for an opaque backdrop (MIN/MAX cannot carry the coverage-restore
|
|
343
|
+
// term); realize them as a BlendEffect for transparent-edge correctness.
|
|
142
344
|
const DEFAULT_GL_BLEND_MODES = [
|
|
143
345
|
[BlendMode.Add, { src: 'ONE', dst: 'ONE' }],
|
|
144
346
|
[BlendMode.Darken, { src: 'ONE', dst: 'ONE', equation: 'MIN' }],
|
|
145
|
-
[BlendMode.Erase, { src: 'ZERO', dst: 'ONE_MINUS_SRC_ALPHA' }],
|
|
146
|
-
[BlendMode.Layer, NORMAL_BLEND],
|
|
147
347
|
[BlendMode.Lighten, { src: 'ONE', dst: 'ONE', equation: 'MAX' }],
|
|
148
348
|
// Premultiplied multiply: result = src.rgb*dst + dst*(1-src.a). The (1-src.a) term restores the
|
|
149
349
|
// destination where the source is transparent or partially covered (antialiased edges, the quad's
|
|
@@ -151,12 +351,7 @@ const DEFAULT_GL_BLEND_MODES = [
|
|
|
151
351
|
// toward black — the straight-alpha (DST_COLOR, ZERO) form fringes there because this pipeline
|
|
152
352
|
// uploads and shades premultiplied. Exact for an opaque backdrop.
|
|
153
353
|
[BlendMode.Multiply, { src: 'DST_COLOR', dst: 'ONE_MINUS_SRC_ALPHA' }],
|
|
154
|
-
// No blending: result = src (the premultiplied source replaces the destination). For opaque
|
|
155
|
-
// content this matches Normal; unlike Normal it does not composite, so semi-transparent source
|
|
156
|
-
// pixels overwrite the backdrop instead of blending over it.
|
|
157
|
-
[BlendMode.None, { src: 'ONE', dst: 'ZERO' }],
|
|
158
354
|
[BlendMode.Normal, NORMAL_BLEND],
|
|
159
355
|
[BlendMode.Screen, { src: 'ONE', dst: 'ONE_MINUS_SRC_COLOR' }],
|
|
160
|
-
[BlendMode.Subtract, { src: 'ONE', dst: 'ONE', equation: 'FUNC_REVERSE_SUBTRACT' }],
|
|
161
356
|
];
|
|
162
357
|
//# sourceMappingURL=glDraw.js.map
|