@flighthq/render-gl 0.5.1-next.1069.554a2ac → 0.5.1-next.1201.9b49dee
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/README.md +2 -2
- package/dist/contract.d.ts +1 -3
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +1 -3
- package/dist/contract.js.map +1 -1
- package/dist/enableGlRenderStateGuards.js +2 -2
- package/dist/enableGlRenderStateGuards.js.map +1 -1
- package/dist/glCubeRenderTarget.d.ts +5 -5
- package/dist/glCubeRenderTarget.d.ts.map +1 -1
- package/dist/glCubeRenderTarget.js +16 -13
- package/dist/glCubeRenderTarget.js.map +1 -1
- package/dist/glFullscreenPass.d.ts +4 -3
- package/dist/glFullscreenPass.d.ts.map +1 -1
- package/dist/glFullscreenPass.js +152 -23
- package/dist/glFullscreenPass.js.map +1 -1
- package/dist/glLinearToSrgbPass.d.ts +2 -2
- package/dist/glLinearToSrgbPass.d.ts.map +1 -1
- package/dist/glLinearToSrgbPass.js.map +1 -1
- package/dist/glPresentRenderTarget.d.ts +2 -2
- package/dist/glPresentRenderTarget.d.ts.map +1 -1
- package/dist/glPresentRenderTarget.js.map +1 -1
- package/dist/glReadback.d.ts +2 -2
- package/dist/glReadback.d.ts.map +1 -1
- package/dist/glReadback.js +1 -1
- package/dist/glReadback.js.map +1 -1
- package/dist/glRenderPass.d.ts +6 -3
- package/dist/glRenderPass.d.ts.map +1 -1
- package/dist/glRenderPass.js +105 -86
- package/dist/glRenderPass.js.map +1 -1
- package/dist/glRenderState.d.ts +1 -2
- package/dist/glRenderState.d.ts.map +1 -1
- package/dist/glRenderState.js +53 -46
- package/dist/glRenderState.js.map +1 -1
- package/dist/glRenderTarget.d.ts +17 -16
- package/dist/glRenderTarget.d.ts.map +1 -1
- package/dist/glRenderTarget.js +38 -26
- package/dist/glRenderTarget.js.map +1 -1
- package/dist/glRenderTargetPool.d.ts +9 -9
- package/dist/glRenderTargetPool.d.ts.map +1 -1
- package/dist/glRenderTargetPool.js +10 -12
- package/dist/glRenderTargetPool.js.map +1 -1
- package/dist/glRenderTexture.d.ts +2 -2
- package/dist/glRenderTexture.d.ts.map +1 -1
- package/dist/glRenderTexture.js +11 -13
- package/dist/glRenderTexture.js.map +1 -1
- package/dist/glRenderTexturePool.js +3 -5
- package/dist/glRenderTexturePool.js.map +1 -1
- package/dist/glSkinPaletteTexture.js +8 -2
- package/dist/glSkinPaletteTexture.js.map +1 -1
- package/dist/glTestHelper.d.ts +0 -1
- package/dist/glTestHelper.d.ts.map +1 -1
- package/dist/glTestHelper.js +0 -1
- package/dist/glTestHelper.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
- package/src/enableGlRenderStateGuards.test.ts +2 -4
- package/src/glContext.test.ts +3 -52
- package/src/glCubeRenderTarget.test.ts +10 -8
- package/src/glDraw.test.ts +4 -16
- package/src/glFullscreenPass.test.ts +145 -41
- package/src/glLinearToSrgbPass.test.ts +8 -5
- package/src/glPresentRenderTarget.test.ts +3 -5
- package/src/glReadback.test.ts +3 -3
- package/src/glRenderPass.test.ts +228 -55
- package/src/glRenderState.test.ts +106 -165
- package/src/glRenderTarget.test.ts +134 -99
- package/src/glRenderTargetPool.test.ts +69 -76
- package/src/glRenderTexture.test.ts +58 -31
- package/src/glSkinPaletteTexture.test.ts +9 -0
- package/src/glTextureResolver.test.ts +5 -1
- package/dist/glBackground.d.ts +0 -3
- package/dist/glBackground.d.ts.map +0 -1
- package/dist/glBackground.js +0 -19
- package/dist/glBackground.js.map +0 -1
- package/dist/glContext.d.ts +0 -3
- package/dist/glContext.d.ts.map +0 -1
- package/dist/glContext.js +0 -16
- package/dist/glContext.js.map +0 -1
- package/src/glBackground.test.ts +0 -68
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
acquireGlTextureRenderTarget,
|
|
3
|
+
createGlTextureRenderTargetPool,
|
|
4
|
+
destroyGlTextureRenderTargetPool,
|
|
5
|
+
initializeGlTextureRenderTargetPool,
|
|
6
|
+
releaseGlTextureRenderTarget,
|
|
7
7
|
} from './glRenderTargetPool';
|
|
8
8
|
import { createGlState } from './glTestHelper';
|
|
9
9
|
|
|
10
|
-
describe('
|
|
10
|
+
describe('acquireGlTextureRenderTarget', () => {
|
|
11
11
|
it('allocates a new target when the pool is empty', () => {
|
|
12
12
|
const { state } = createGlState();
|
|
13
|
-
const pool =
|
|
14
|
-
const target =
|
|
13
|
+
const pool = createGlTextureRenderTargetPool();
|
|
14
|
+
const target = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48 });
|
|
15
15
|
expect(target.width).toBe(64);
|
|
16
16
|
expect(target.height).toBe(48);
|
|
17
17
|
expect(pool.free.length).toBe(0);
|
|
@@ -19,39 +19,39 @@ describe('acquireGlRenderTarget', () => {
|
|
|
19
19
|
|
|
20
20
|
it('reuses a matching released target instead of allocating', () => {
|
|
21
21
|
const { state } = createGlState();
|
|
22
|
-
const pool =
|
|
23
|
-
const first =
|
|
24
|
-
|
|
22
|
+
const pool = createGlTextureRenderTargetPool();
|
|
23
|
+
const first = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48 });
|
|
24
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
25
25
|
|
|
26
|
-
const reused =
|
|
26
|
+
const reused = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48 });
|
|
27
27
|
expect(reused).toBe(first);
|
|
28
28
|
expect(pool.free.length).toBe(0);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it('does not reuse a target with a different color space', () => {
|
|
32
32
|
const { state } = createGlState();
|
|
33
|
-
const pool =
|
|
34
|
-
const first =
|
|
33
|
+
const pool = createGlTextureRenderTargetPool();
|
|
34
|
+
const first = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, colorSpace: 'linear' });
|
|
35
35
|
expect(first.colorSpace).toBe('linear');
|
|
36
|
-
|
|
36
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
37
37
|
|
|
38
|
-
const other =
|
|
38
|
+
const other = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, colorSpace: 'srgb' });
|
|
39
39
|
expect(other).not.toBe(first);
|
|
40
40
|
expect(pool.free).toContain(first);
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
it('does not reuse a target with different heterogeneous color formats', () => {
|
|
44
44
|
const { state } = createGlState();
|
|
45
|
-
const pool =
|
|
46
|
-
const first =
|
|
45
|
+
const pool = createGlTextureRenderTargetPool();
|
|
46
|
+
const first = acquireGlTextureRenderTarget(state, pool, {
|
|
47
47
|
width: 64,
|
|
48
48
|
height: 48,
|
|
49
49
|
colorAttachments: 2,
|
|
50
50
|
colorFormats: ['rgba8', 'rgba8'],
|
|
51
51
|
});
|
|
52
|
-
|
|
52
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
53
53
|
|
|
54
|
-
const other =
|
|
54
|
+
const other = acquireGlTextureRenderTarget(state, pool, {
|
|
55
55
|
width: 64,
|
|
56
56
|
height: 48,
|
|
57
57
|
colorAttachments: 2,
|
|
@@ -64,11 +64,11 @@ describe('acquireGlRenderTarget', () => {
|
|
|
64
64
|
it('reuses the effective rgba8 target when a preferred float format is unsupported', () => {
|
|
65
65
|
const { state, gl } = createGlState();
|
|
66
66
|
vi.spyOn(gl, 'getExtension').mockReturnValue(null);
|
|
67
|
-
const pool =
|
|
68
|
-
const first =
|
|
69
|
-
|
|
67
|
+
const pool = createGlTextureRenderTargetPool();
|
|
68
|
+
const first = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, format: 'rgba8' });
|
|
69
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
70
70
|
|
|
71
|
-
const reused =
|
|
71
|
+
const reused = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, format: 'rgba32f' }, 'preferred');
|
|
72
72
|
expect(reused).toBe(first);
|
|
73
73
|
expect(reused.format).toBe('rgba8');
|
|
74
74
|
expect(reused.requestedAxes.format).toBe('rgba32f');
|
|
@@ -78,15 +78,15 @@ describe('acquireGlRenderTarget', () => {
|
|
|
78
78
|
it('refuses an unsupported required float format without consuming a fallback target', () => {
|
|
79
79
|
const { state, gl } = createGlState();
|
|
80
80
|
vi.spyOn(gl, 'getExtension').mockReturnValue(null);
|
|
81
|
-
const pool =
|
|
82
|
-
const fallback =
|
|
83
|
-
|
|
81
|
+
const pool = createGlTextureRenderTargetPool();
|
|
82
|
+
const fallback = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, format: 'rgba8' });
|
|
83
|
+
releaseGlTextureRenderTarget(pool, fallback);
|
|
84
84
|
const createFramebufferSpy = vi.spyOn(gl, 'createFramebuffer');
|
|
85
85
|
const clearSpy = vi.spyOn(gl, 'clear');
|
|
86
86
|
createFramebufferSpy.mockClear();
|
|
87
87
|
clearSpy.mockClear();
|
|
88
88
|
|
|
89
|
-
const refused =
|
|
89
|
+
const refused = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, format: 'rgba32f' }, 'required');
|
|
90
90
|
expect(refused).toBeNull();
|
|
91
91
|
expect(pool.free).toEqual([fallback]);
|
|
92
92
|
expect(createFramebufferSpy).not.toHaveBeenCalled();
|
|
@@ -96,9 +96,9 @@ describe('acquireGlRenderTarget', () => {
|
|
|
96
96
|
it('allocates a supported required float format', () => {
|
|
97
97
|
const { state, gl } = createGlState();
|
|
98
98
|
vi.spyOn(gl, 'getExtension').mockReturnValue({} as never);
|
|
99
|
-
const pool =
|
|
99
|
+
const pool = createGlTextureRenderTargetPool();
|
|
100
100
|
|
|
101
|
-
const target =
|
|
101
|
+
const target = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, format: 'rgba16f' }, 'required');
|
|
102
102
|
expect(target).not.toBeNull();
|
|
103
103
|
expect(target?.format).toBe('rgba16f');
|
|
104
104
|
expect(target?.requestedAxes.format).toBe('rgba16f');
|
|
@@ -106,35 +106,29 @@ describe('acquireGlRenderTarget', () => {
|
|
|
106
106
|
|
|
107
107
|
it('does not reuse a target with a different depth mode', () => {
|
|
108
108
|
const { state } = createGlState();
|
|
109
|
-
const pool =
|
|
110
|
-
const first =
|
|
111
|
-
|
|
109
|
+
const pool = createGlTextureRenderTargetPool();
|
|
110
|
+
const first = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, depth: 'none' });
|
|
111
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
112
112
|
|
|
113
|
-
const other =
|
|
113
|
+
const other = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48, depth: 'depth-stencil' });
|
|
114
114
|
expect(other).not.toBe(first);
|
|
115
115
|
expect(pool.free).toContain(first);
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
it('re-stamps
|
|
118
|
+
it('re-stamps requested axes on a compatible target', () => {
|
|
119
119
|
const { state } = createGlState();
|
|
120
|
-
const pool =
|
|
121
|
-
const first =
|
|
120
|
+
const pool = createGlTextureRenderTargetPool();
|
|
121
|
+
const first = acquireGlTextureRenderTarget(state, pool, {
|
|
122
122
|
width: 64,
|
|
123
123
|
height: 48,
|
|
124
|
-
clearColors: [0xff0000ff],
|
|
125
|
-
clearDepth: 0.25,
|
|
126
124
|
});
|
|
127
|
-
|
|
125
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
128
126
|
|
|
129
|
-
const reused =
|
|
127
|
+
const reused = acquireGlTextureRenderTarget(state, pool, {
|
|
130
128
|
width: 64,
|
|
131
129
|
height: 48,
|
|
132
|
-
clearColors: [0x00ff00ff],
|
|
133
|
-
clearDepth: 0.75,
|
|
134
130
|
});
|
|
135
131
|
expect(reused).toBe(first);
|
|
136
|
-
expect(reused.clearColors).toEqual([0x00ff00ff]);
|
|
137
|
-
expect(reused.clearDepth).toBe(0.75);
|
|
138
132
|
expect(reused.requestedAxes).toEqual({
|
|
139
133
|
width: 64,
|
|
140
134
|
height: 48,
|
|
@@ -149,11 +143,11 @@ describe('acquireGlRenderTarget', () => {
|
|
|
149
143
|
|
|
150
144
|
it('allocates a new target when the free target has different dimensions', () => {
|
|
151
145
|
const { state } = createGlState();
|
|
152
|
-
const pool =
|
|
153
|
-
const first =
|
|
154
|
-
|
|
146
|
+
const pool = createGlTextureRenderTargetPool();
|
|
147
|
+
const first = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48 });
|
|
148
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
155
149
|
|
|
156
|
-
const other =
|
|
150
|
+
const other = acquireGlTextureRenderTarget(state, pool, { width: 128, height: 48 });
|
|
157
151
|
expect(other).not.toBe(first);
|
|
158
152
|
// The mismatched target stays parked in the free list.
|
|
159
153
|
expect(pool.free).toContain(first);
|
|
@@ -161,47 +155,46 @@ describe('acquireGlRenderTarget', () => {
|
|
|
161
155
|
|
|
162
156
|
it('matches the ceiled, clamped descriptor dimensions', () => {
|
|
163
157
|
const { state } = createGlState();
|
|
164
|
-
const pool =
|
|
165
|
-
const first =
|
|
166
|
-
|
|
158
|
+
const pool = createGlTextureRenderTargetPool();
|
|
159
|
+
const first = acquireGlTextureRenderTarget(state, pool, { width: 10.2, height: 0 });
|
|
160
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
167
161
|
|
|
168
162
|
// 10.2 -> 11, 0 -> 1; an equivalent descriptor must hit the same parked target.
|
|
169
|
-
const reused =
|
|
163
|
+
const reused = acquireGlTextureRenderTarget(state, pool, { width: 10.9, height: 0.4 });
|
|
170
164
|
expect(reused).toBe(first);
|
|
171
165
|
});
|
|
172
166
|
|
|
173
167
|
it('clears a reused target so it is handed back clean', () => {
|
|
174
168
|
const { state, gl } = createGlState();
|
|
175
|
-
const pool =
|
|
176
|
-
const first =
|
|
177
|
-
|
|
169
|
+
const pool = createGlTextureRenderTargetPool();
|
|
170
|
+
const first = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48 });
|
|
171
|
+
releaseGlTextureRenderTarget(pool, first);
|
|
178
172
|
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
const reused = acquireGlRenderTarget(state, pool, { width: 64, height: 48 });
|
|
173
|
+
const clearSpy = vi.spyOn(gl, 'clearBufferfv');
|
|
174
|
+
const reused = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 48 });
|
|
182
175
|
expect(reused).toBe(first);
|
|
183
176
|
expect(clearSpy).toHaveBeenCalled();
|
|
184
177
|
});
|
|
185
178
|
});
|
|
186
179
|
|
|
187
|
-
describe('
|
|
180
|
+
describe('createGlTextureRenderTargetPool', () => {
|
|
188
181
|
it('returns a pool with an empty free list', () => {
|
|
189
|
-
const pool =
|
|
182
|
+
const pool = createGlTextureRenderTargetPool();
|
|
190
183
|
expect(pool.free).toEqual([]);
|
|
191
184
|
});
|
|
192
185
|
});
|
|
193
186
|
|
|
194
|
-
describe('
|
|
187
|
+
describe('destroyGlTextureRenderTargetPool', () => {
|
|
195
188
|
it('destroys every parked target and empties the free list', () => {
|
|
196
189
|
const { state, gl } = createGlState();
|
|
197
|
-
const pool =
|
|
198
|
-
const a =
|
|
199
|
-
const b =
|
|
200
|
-
|
|
201
|
-
|
|
190
|
+
const pool = createGlTextureRenderTargetPool();
|
|
191
|
+
const a = acquireGlTextureRenderTarget(state, pool, { width: 32, height: 32 });
|
|
192
|
+
const b = acquireGlTextureRenderTarget(state, pool, { width: 16, height: 16 });
|
|
193
|
+
releaseGlTextureRenderTarget(pool, a);
|
|
194
|
+
releaseGlTextureRenderTarget(pool, b);
|
|
202
195
|
|
|
203
196
|
const deleteSpy = vi.spyOn(gl, 'deleteFramebuffer');
|
|
204
|
-
|
|
197
|
+
destroyGlTextureRenderTargetPool(pool);
|
|
205
198
|
|
|
206
199
|
expect(deleteSpy).toHaveBeenCalledWith(a.framebuffer);
|
|
207
200
|
expect(deleteSpy).toHaveBeenCalledWith(b.framebuffer);
|
|
@@ -210,24 +203,24 @@ describe('destroyGlRenderTargetPool', () => {
|
|
|
210
203
|
|
|
211
204
|
it('is a no-op on an empty pool', () => {
|
|
212
205
|
const { state } = createGlState();
|
|
213
|
-
const pool =
|
|
214
|
-
expect(() =>
|
|
206
|
+
const pool = createGlTextureRenderTargetPool();
|
|
207
|
+
expect(() => destroyGlTextureRenderTargetPool(pool)).not.toThrow();
|
|
215
208
|
});
|
|
216
209
|
});
|
|
217
210
|
|
|
218
|
-
describe('
|
|
211
|
+
describe('initializeGlTextureRenderTargetPool', () => {
|
|
219
212
|
it('is the construction initializer of createGlRenderTargetPool', () => {
|
|
220
|
-
expect(typeof
|
|
213
|
+
expect(typeof initializeGlTextureRenderTargetPool).toBe('function');
|
|
221
214
|
});
|
|
222
215
|
});
|
|
223
|
-
describe('
|
|
216
|
+
describe('releaseGlTextureRenderTarget', () => {
|
|
224
217
|
it('returns the target to the free list without destroying it', () => {
|
|
225
218
|
const { state, gl } = createGlState();
|
|
226
|
-
const pool =
|
|
227
|
-
const target =
|
|
219
|
+
const pool = createGlTextureRenderTargetPool();
|
|
220
|
+
const target = acquireGlTextureRenderTarget(state, pool, { width: 64, height: 64 });
|
|
228
221
|
|
|
229
222
|
const deleteSpy = vi.spyOn(gl, 'deleteFramebuffer');
|
|
230
|
-
|
|
223
|
+
releaseGlTextureRenderTarget(pool, target);
|
|
231
224
|
|
|
232
225
|
expect(pool.free).toContain(target);
|
|
233
226
|
expect(deleteSpy).not.toHaveBeenCalled();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { addLogSink, createMemoryLogSink, getMemoryLogSinkEntries, removeLogSink } from '@flighthq/log/contract';
|
|
2
|
-
import type { RenderTexture } from '@flighthq/types/contract';
|
|
2
|
+
import type { RenderTargetClear, RenderTexture } from '@flighthq/types/contract';
|
|
3
3
|
import { RenderTargetTextureSourceKind } from '@flighthq/types/contract';
|
|
4
4
|
|
|
5
5
|
import { enableGlRenderTextureGuards } from './enableGlRenderTextureGuards';
|
|
@@ -23,7 +23,7 @@ describe('bindGlRenderTexture', () => {
|
|
|
23
23
|
it('binds the existing target texture without uploading pixels', () => {
|
|
24
24
|
const { state, gl } = createRenderTextureState();
|
|
25
25
|
const renderTexture = createRenderTexture({ height: 8, width: 8 });
|
|
26
|
-
renderIntoGlRenderTexture(state, renderTexture, () => {});
|
|
26
|
+
renderIntoGlRenderTexture(state, renderTexture, () => {}, TRANSPARENT_CLEAR);
|
|
27
27
|
const uploads = vi.mocked(gl.texImage2D).mock.calls.length;
|
|
28
28
|
|
|
29
29
|
const texture = bindGlRenderTexture(state, renderTexture);
|
|
@@ -47,7 +47,7 @@ describe('clearGlRenderTexture', () => {
|
|
|
47
47
|
|
|
48
48
|
clearGlRenderTexture(state, renderTexture);
|
|
49
49
|
|
|
50
|
-
expect(gl.
|
|
50
|
+
expect(gl.clearBufferfv).toHaveBeenCalledWith(gl.COLOR, 0, expect.anything());
|
|
51
51
|
expect(isGlRenderTextureReady(state, renderTexture)).toBe(true);
|
|
52
52
|
expect(renderTexture.version).toBe(1);
|
|
53
53
|
});
|
|
@@ -57,7 +57,7 @@ describe('destroyGlRenderTexture', () => {
|
|
|
57
57
|
it('deletes the hidden target and returns the source to unrendered state', () => {
|
|
58
58
|
const { state, gl } = createRenderTextureState();
|
|
59
59
|
const renderTexture = createRenderTexture({ height: 8, width: 8 });
|
|
60
|
-
renderIntoGlRenderTexture(state, renderTexture, () => {});
|
|
60
|
+
renderIntoGlRenderTexture(state, renderTexture, () => {}, TRANSPARENT_CLEAR);
|
|
61
61
|
|
|
62
62
|
destroyGlRenderTexture(state, renderTexture);
|
|
63
63
|
|
|
@@ -76,9 +76,14 @@ describe('enableGlRenderTextureGuards', () => {
|
|
|
76
76
|
enableGlRenderTextureGuards(state);
|
|
77
77
|
try {
|
|
78
78
|
bindGlRenderTexture(state, unrendered);
|
|
79
|
-
renderIntoGlRenderTexture(
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
renderIntoGlRenderTexture(
|
|
80
|
+
state,
|
|
81
|
+
writing,
|
|
82
|
+
() => {
|
|
83
|
+
bindGlRenderTexture(state, writing);
|
|
84
|
+
},
|
|
85
|
+
TRANSPARENT_CLEAR,
|
|
86
|
+
);
|
|
82
87
|
|
|
83
88
|
const entries = getMemoryLogSinkEntries(sink);
|
|
84
89
|
expect(entries).toHaveLength(2);
|
|
@@ -108,7 +113,7 @@ describe('getGlRenderTextureColorSpace', () => {
|
|
|
108
113
|
const renderTexture = createRenderTexture({ height: 8, width: 8 });
|
|
109
114
|
|
|
110
115
|
expect(getGlRenderTextureColorSpace(state, renderTexture)).toBe('linear');
|
|
111
|
-
renderIntoGlRenderTexture(state, renderTexture, () => {});
|
|
116
|
+
renderIntoGlRenderTexture(state, renderTexture, () => {}, TRANSPARENT_CLEAR);
|
|
112
117
|
expect(getGlRenderTextureColorSpace(state, renderTexture)).toBe('linear');
|
|
113
118
|
});
|
|
114
119
|
});
|
|
@@ -145,7 +150,7 @@ describe('isGlRenderTextureReady', () => {
|
|
|
145
150
|
const renderTexture = createRenderTexture({ height: 8, width: 8 });
|
|
146
151
|
|
|
147
152
|
expect(isGlRenderTextureReady(state, renderTexture)).toBe(false);
|
|
148
|
-
renderIntoGlRenderTexture(state, renderTexture, () => {});
|
|
153
|
+
renderIntoGlRenderTexture(state, renderTexture, () => {}, TRANSPARENT_CLEAR);
|
|
149
154
|
expect(isGlRenderTextureReady(state, renderTexture)).toBe(true);
|
|
150
155
|
});
|
|
151
156
|
});
|
|
@@ -154,8 +159,8 @@ describe('renderIntoGlRenderTexture', () => {
|
|
|
154
159
|
it('lazily creates a target and marks it ready after the callback completes', () => {
|
|
155
160
|
const { state } = createRenderTextureState();
|
|
156
161
|
const renderTexture = createRenderTexture({ depth: true, height: 24, width: 32 });
|
|
157
|
-
const callback = vi.fn((
|
|
158
|
-
expect(
|
|
162
|
+
const callback = vi.fn((pass) => {
|
|
163
|
+
expect(pass.state).toBe(state);
|
|
159
164
|
expect(explainGlRenderTexture(state, renderTexture).status).toBe('writing');
|
|
160
165
|
});
|
|
161
166
|
|
|
@@ -166,7 +171,7 @@ describe('renderIntoGlRenderTexture', () => {
|
|
|
166
171
|
});
|
|
167
172
|
expect(renderTexture.version).toBe(0);
|
|
168
173
|
|
|
169
|
-
renderIntoGlRenderTexture(state, renderTexture, callback);
|
|
174
|
+
renderIntoGlRenderTexture(state, renderTexture, callback, TRANSPARENT_CLEAR);
|
|
170
175
|
|
|
171
176
|
expect(callback).toHaveBeenCalledOnce();
|
|
172
177
|
expect(renderTexture.version).toBe(1);
|
|
@@ -183,9 +188,14 @@ describe('renderIntoGlRenderTexture', () => {
|
|
|
183
188
|
const renderTexture = createRenderTexture({ height: 8, width: 8 });
|
|
184
189
|
|
|
185
190
|
expect(() =>
|
|
186
|
-
renderIntoGlRenderTexture(
|
|
187
|
-
|
|
188
|
-
|
|
191
|
+
renderIntoGlRenderTexture(
|
|
192
|
+
state,
|
|
193
|
+
renderTexture,
|
|
194
|
+
() => {
|
|
195
|
+
throw new Error('producer failed');
|
|
196
|
+
},
|
|
197
|
+
TRANSPARENT_CLEAR,
|
|
198
|
+
),
|
|
189
199
|
).toThrow('producer failed');
|
|
190
200
|
|
|
191
201
|
expect(explainGlRenderTexture(state, renderTexture).status).toBe('unrendered');
|
|
@@ -195,12 +205,17 @@ describe('renderIntoGlRenderTexture', () => {
|
|
|
195
205
|
it('invalidates a previously-ready target when a replacement render throws', () => {
|
|
196
206
|
const { state } = createRenderTextureState();
|
|
197
207
|
const renderTexture = createRenderTexture({ height: 8, width: 8 });
|
|
198
|
-
renderIntoGlRenderTexture(state, renderTexture, () => {});
|
|
208
|
+
renderIntoGlRenderTexture(state, renderTexture, () => {}, TRANSPARENT_CLEAR);
|
|
199
209
|
|
|
200
210
|
expect(() =>
|
|
201
|
-
renderIntoGlRenderTexture(
|
|
202
|
-
|
|
203
|
-
|
|
211
|
+
renderIntoGlRenderTexture(
|
|
212
|
+
state,
|
|
213
|
+
renderTexture,
|
|
214
|
+
() => {
|
|
215
|
+
throw new Error('replacement failed');
|
|
216
|
+
},
|
|
217
|
+
TRANSPARENT_CLEAR,
|
|
218
|
+
),
|
|
204
219
|
).toThrow('replacement failed');
|
|
205
220
|
|
|
206
221
|
expect(explainGlRenderTexture(state, renderTexture).status).toBe('unrendered');
|
|
@@ -211,14 +226,19 @@ describe('renderIntoGlRenderTexture', () => {
|
|
|
211
226
|
const { state } = createRenderTextureState();
|
|
212
227
|
const renderTexture = createRenderTexture({ height: 8, width: 8 });
|
|
213
228
|
|
|
214
|
-
renderIntoGlRenderTexture(
|
|
215
|
-
|
|
229
|
+
renderIntoGlRenderTexture(
|
|
230
|
+
state,
|
|
231
|
+
renderTexture,
|
|
232
|
+
() => {
|
|
233
|
+
getGlRenderStateRuntime(state).currentMaskDepth = 1;
|
|
216
234
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
235
|
+
expect(() => renderIntoGlRenderTexture(state, renderTexture, () => {}, TRANSPARENT_CLEAR)).toThrow(
|
|
236
|
+
'cannot nest the active framebuffer while a contour clip is live',
|
|
237
|
+
);
|
|
238
|
+
expect(explainGlRenderTexture(state, renderTexture).status).toBe('writing');
|
|
239
|
+
},
|
|
240
|
+
TRANSPARENT_CLEAR,
|
|
241
|
+
);
|
|
222
242
|
|
|
223
243
|
expect(explainGlRenderTexture(state, renderTexture).status).toBe('ready');
|
|
224
244
|
});
|
|
@@ -226,11 +246,11 @@ describe('renderIntoGlRenderTexture', () => {
|
|
|
226
246
|
it('resizes the retained target when the source dimensions change', () => {
|
|
227
247
|
const { state } = createRenderTextureState();
|
|
228
248
|
const renderTexture = createRenderTexture({ height: 16, width: 32 });
|
|
229
|
-
renderIntoGlRenderTexture(state, renderTexture, () => {});
|
|
249
|
+
renderIntoGlRenderTexture(state, renderTexture, () => {}, TRANSPARENT_CLEAR);
|
|
230
250
|
|
|
231
251
|
renderTexture.source.width = 12;
|
|
232
252
|
renderTexture.source.height = 10;
|
|
233
|
-
renderIntoGlRenderTexture(state, renderTexture, () => {});
|
|
253
|
+
renderIntoGlRenderTexture(state, renderTexture, () => {}, TRANSPARENT_CLEAR);
|
|
234
254
|
|
|
235
255
|
expect(explainGlRenderTexture(state, renderTexture)).toEqual({
|
|
236
256
|
height: 10,
|
|
@@ -244,9 +264,14 @@ describe('renderIntoGlRenderTexture', () => {
|
|
|
244
264
|
const renderTexture = createRenderTexture({ height: 8, width: 8 });
|
|
245
265
|
let whileWriting: WebGLTexture | null = {} as WebGLTexture;
|
|
246
266
|
|
|
247
|
-
renderIntoGlRenderTexture(
|
|
248
|
-
|
|
249
|
-
|
|
267
|
+
renderIntoGlRenderTexture(
|
|
268
|
+
state,
|
|
269
|
+
renderTexture,
|
|
270
|
+
() => {
|
|
271
|
+
whileWriting = bindGlRenderTexture(state, renderTexture);
|
|
272
|
+
},
|
|
273
|
+
TRANSPARENT_CLEAR,
|
|
274
|
+
);
|
|
250
275
|
|
|
251
276
|
expect(whileWriting).toBeNull();
|
|
252
277
|
expect(bindGlRenderTexture(state, renderTexture)).not.toBeNull();
|
|
@@ -324,3 +349,5 @@ function createRenderTexture(options: { depth?: boolean; height: number; width:
|
|
|
324
349
|
version: 0,
|
|
325
350
|
} as unknown as RenderTexture;
|
|
326
351
|
}
|
|
352
|
+
|
|
353
|
+
const TRANSPARENT_CLEAR: Readonly<RenderTargetClear> = { color: [0, 0, 0, 0], depth: 1.0, stencil: 0 };
|
|
@@ -159,6 +159,15 @@ describe('uploadGlSkinPaletteTexture', () => {
|
|
|
159
159
|
expect(palette.jointCapacity).toBe(6);
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
+
it('throws when MAX_TEXTURE_SIZE is not positive', () => {
|
|
163
|
+
const { gl } = makeGl(0);
|
|
164
|
+
const palette = createGlSkinPaletteTexture(gl);
|
|
165
|
+
|
|
166
|
+
expect(() => uploadGlSkinPaletteTexture(gl, palette, makePalette(1), 1)).toThrow(
|
|
167
|
+
'WebGL MAX_TEXTURE_SIZE must be greater than zero',
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
|
|
162
171
|
it('wraps into multiple rows when totalTexels exceeds MAX_TEXTURE_SIZE', () => {
|
|
163
172
|
const { gl, calls } = makeGl(16);
|
|
164
173
|
const palette = createGlSkinPaletteTexture(gl);
|
|
@@ -206,7 +206,11 @@ describe('registerGlRenderTextureResolver', () => {
|
|
|
206
206
|
return previous?.(parameter);
|
|
207
207
|
});
|
|
208
208
|
const texture = textureWithTarget();
|
|
209
|
-
renderIntoGlRenderTexture(state, texture as RenderTexture, () => {}
|
|
209
|
+
renderIntoGlRenderTexture(state, texture as RenderTexture, () => {}, {
|
|
210
|
+
color: [0, 0, 0, 0],
|
|
211
|
+
depth: 1.0,
|
|
212
|
+
stencil: 0,
|
|
213
|
+
});
|
|
210
214
|
registerGlRenderTextureResolver(state);
|
|
211
215
|
const uploads = vi.mocked(gl.texImage2D).mock.calls.length;
|
|
212
216
|
|
package/dist/glBackground.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"glBackground.d.ts","sourceRoot":"","sources":["../src/glBackground.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAI9D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAwB7D"}
|
package/dist/glBackground.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { srgbChannelToLinear } from '@flighthq/color/contract';
|
|
2
|
-
import { getGlRenderStateRuntime } from './glRenderState';
|
|
3
|
-
export function renderGlBackground(state) {
|
|
4
|
-
const runtime = getGlRenderStateRuntime(state);
|
|
5
|
-
const gl = state.gl;
|
|
6
|
-
const viewport = runtime.renderTargetViewport;
|
|
7
|
-
gl.viewport(viewport?.x ?? 0, viewport?.y ?? 0, viewport?.width ?? gl.drawingBufferWidth, viewport?.height ?? gl.drawingBufferHeight);
|
|
8
|
-
const rgba = state.backgroundColorRgba;
|
|
9
|
-
if (rgba.length >= 4 && rgba[3] > 0) {
|
|
10
|
-
const linear = runtime.currentRenderTarget?.colorSpace === 'linear';
|
|
11
|
-
gl.clearColor(linear ? srgbChannelToLinear(rgba[0]) : rgba[0], linear ? srgbChannelToLinear(rgba[1]) : rgba[1], linear ? srgbChannelToLinear(rgba[2]) : rgba[2], rgba[3]);
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
gl.clearColor(0, 0, 0, 0);
|
|
15
|
-
}
|
|
16
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
17
|
-
runtime.context.currentBlendSignature = null;
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=glBackground.js.map
|
package/dist/glBackground.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"glBackground.js","sourceRoot":"","sources":["../src/glBackground.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,UAAU,kBAAkB,CAAC,KAAoB;IACrD,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;IACpB,MAAM,QAAQ,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAC9C,EAAE,CAAC,QAAQ,CACT,QAAQ,EAAE,CAAC,IAAI,CAAC,EAChB,QAAQ,EAAE,CAAC,IAAI,CAAC,EAChB,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,kBAAkB,EACxC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAC,mBAAmB,CAC3C,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,CAAC,mBAAmB,CAAC;IACvC,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,UAAU,KAAK,QAAQ,CAAC;QACpE,EAAE,CAAC,UAAU,CACX,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAC/C,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAC/C,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAC/C,IAAI,CAAC,CAAC,CAAC,CACR,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAC9B,OAAO,CAAC,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;AAC/C,CAAC"}
|
package/dist/glContext.d.ts
DELETED
package/dist/glContext.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"glContext.d.ts","sourceRoot":"","sources":["../src/glContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI5E,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,QAAQ,CAAC,gBAAgB,CAAM,GACvC,SAAS,CAWX"}
|
package/dist/glContext.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// Web-only acquisition constructor. Context-first/native callers do not import this module, keeping
|
|
2
|
-
// HTMLCanvasElement.getContext out of their bundles.
|
|
3
|
-
export function createGlContextFromCanvasElement(canvas, options = {}) {
|
|
4
|
-
const contextAttributes = {
|
|
5
|
-
alpha: true,
|
|
6
|
-
antialias: options.antialias ?? true,
|
|
7
|
-
powerPreference: options.powerPreference ?? 'default',
|
|
8
|
-
stencil: true,
|
|
9
|
-
...options.contextAttributes,
|
|
10
|
-
};
|
|
11
|
-
const context = canvas.getContext('webgl2', contextAttributes);
|
|
12
|
-
if (context === null)
|
|
13
|
-
throw new Error('Failed to get WebGL2 context.');
|
|
14
|
-
return context;
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=glContext.js.map
|
package/dist/glContext.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"glContext.js","sourceRoot":"","sources":["../src/glContext.ts"],"names":[],"mappings":"AAEA,oGAAoG;AACpG,qDAAqD;AACrD,MAAM,UAAU,gCAAgC,CAC9C,MAAyB,EACzB,UAAsC,EAAE;IAExC,MAAM,iBAAiB,GAA2B;QAChD,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;QACpC,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,SAAS;QACrD,OAAO,EAAE,IAAI;QACb,GAAG,OAAO,CAAC,iBAAiB;KAC7B,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAC/D,IAAI,OAAO,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACvE,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/src/glBackground.test.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { srgbChannelToLinear } from '@flighthq/color/contract';
|
|
2
|
-
|
|
3
|
-
import { renderGlBackground } from './glBackground';
|
|
4
|
-
import { getGlRenderStateRuntime } from './glRenderState';
|
|
5
|
-
import { createGlState } from './glTestHelper';
|
|
6
|
-
|
|
7
|
-
describe('renderGlBackground', () => {
|
|
8
|
-
it('calls clearColor with zeros when background alpha is 0', () => {
|
|
9
|
-
const { state, gl } = createGlState({ backgroundColorRgba: [0, 0, 0, 0] });
|
|
10
|
-
renderGlBackground(state);
|
|
11
|
-
expect(gl.clearColor).toHaveBeenCalledWith(0, 0, 0, 0);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('calls clearColor with the RGBA values when background is non-transparent', () => {
|
|
15
|
-
const { state, gl } = createGlState({ backgroundColorRgba: [1, 0, 0, 1] });
|
|
16
|
-
renderGlBackground(state);
|
|
17
|
-
expect(gl.clearColor).toHaveBeenCalledWith(1, 0, 0, 1);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('calls clearColor with zeros when RGBA array has fewer than 4 elements', () => {
|
|
21
|
-
const { state, gl } = createGlState({ backgroundColorRgba: [] });
|
|
22
|
-
renderGlBackground(state);
|
|
23
|
-
expect(gl.clearColor).toHaveBeenCalledWith(0, 0, 0, 0);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('always calls gl.clear with COLOR_BUFFER_BIT', () => {
|
|
27
|
-
const { state, gl } = createGlState();
|
|
28
|
-
renderGlBackground(state);
|
|
29
|
-
expect(gl.clear).toHaveBeenCalledWith((gl as unknown as { COLOR_BUFFER_BIT: number }).COLOR_BUFFER_BIT);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('preserves an active partial-target viewport origin', () => {
|
|
33
|
-
const { state, gl } = createGlState();
|
|
34
|
-
getGlRenderStateRuntime(state).renderTargetViewport = { height: 40, width: 30, x: 10, y: 20 };
|
|
35
|
-
|
|
36
|
-
renderGlBackground(state);
|
|
37
|
-
|
|
38
|
-
expect(gl.viewport).toHaveBeenLastCalledWith(10, 20, 30, 40);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('invalidates currentBlendSignature', () => {
|
|
42
|
-
const { state } = createGlState();
|
|
43
|
-
const runtime = getGlRenderStateRuntime(state);
|
|
44
|
-
runtime.context.currentBlendSignature = { dst: 0, equation: 0, src: 0 };
|
|
45
|
-
renderGlBackground(state);
|
|
46
|
-
expect(runtime.context.currentBlendSignature).toBeNull();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('passes fractional RGBA values through unchanged', () => {
|
|
50
|
-
const { state, gl } = createGlState({ backgroundColorRgba: [0.5, 0.25, 0.75, 0.8] });
|
|
51
|
-
renderGlBackground(state);
|
|
52
|
-
expect(gl.clearColor).toHaveBeenCalledWith(0.5, 0.25, 0.75, 0.8);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('decodes an sRGB background when the active target stores linear scene color', () => {
|
|
56
|
-
const { state, gl } = createGlState({ backgroundColorRgba: [0.5, 0.25, 0.75, 0.8] });
|
|
57
|
-
getGlRenderStateRuntime(state).currentRenderTarget = { colorSpace: 'linear' } as never;
|
|
58
|
-
|
|
59
|
-
renderGlBackground(state);
|
|
60
|
-
|
|
61
|
-
expect(gl.clearColor).toHaveBeenCalledWith(
|
|
62
|
-
srgbChannelToLinear(0.5),
|
|
63
|
-
srgbChannelToLinear(0.25),
|
|
64
|
-
srgbChannelToLinear(0.75),
|
|
65
|
-
0.8,
|
|
66
|
-
);
|
|
67
|
-
});
|
|
68
|
-
});
|