@solidtv/renderer 1.2.8 → 1.2.10
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/src/common/EventEmitter.d.ts +6 -0
- package/dist/src/common/EventEmitter.js +29 -11
- package/dist/src/common/EventEmitter.js.map +1 -1
- package/dist/src/core/CoreNode.d.ts +14 -3
- package/dist/src/core/CoreNode.js +60 -16
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/Stage.d.ts +19 -0
- package/dist/src/core/Stage.js +25 -0
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/platforms/web/WebPlatform.js +6 -0
- package/dist/src/core/platforms/web/WebPlatform.js.map +1 -1
- package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +15 -0
- package/dist/src/core/renderers/webgl/WebGlRenderer.js +24 -0
- package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
- package/dist/src/main-api/Renderer.d.ts +23 -0
- package/dist/src/main-api/Renderer.js +2 -0
- package/dist/src/main-api/Renderer.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
- package/src/common/EventEmitter.ts +29 -11
- package/src/core/CoreNode.test.ts +209 -0
- package/src/core/CoreNode.ts +76 -19
- package/src/core/Stage.contextLoss.test.ts +45 -0
- package/src/core/Stage.ts +27 -0
- package/src/core/platforms/web/WebPlatform.contextLoss.test.ts +80 -0
- package/src/core/platforms/web/WebPlatform.ts +7 -0
- package/src/core/renderers/webgl/WebGlRenderer.ts +28 -0
- package/src/main-api/Renderer.ts +24 -0
package/src/core/CoreNode.ts
CHANGED
|
@@ -295,6 +295,10 @@ export interface CoreNodeProps {
|
|
|
295
295
|
* its descendants from overflowing outside of the Node's x/y/width/height
|
|
296
296
|
* bounds.
|
|
297
297
|
*
|
|
298
|
+
* Pass `true` to clip exactly to the Node's bounds, or pass a
|
|
299
|
+
* `[top, right, bottom, left]` tuple to expand the clip rectangle outward
|
|
300
|
+
* by the given pixel amounts on each side (negative values inset it).
|
|
301
|
+
*
|
|
298
302
|
* For WebGL, clipping is implemented using the high-performance WebGL
|
|
299
303
|
* operation scissor. As a consequence, clipping does not work for
|
|
300
304
|
* non-rectangular areas. So, if the element is rotated
|
|
@@ -305,7 +309,7 @@ export interface CoreNodeProps {
|
|
|
305
309
|
*
|
|
306
310
|
* @default `false`
|
|
307
311
|
*/
|
|
308
|
-
clipping: boolean;
|
|
312
|
+
clipping: boolean | [number, number, number, number];
|
|
309
313
|
/**
|
|
310
314
|
* The color of the Node.
|
|
311
315
|
*
|
|
@@ -804,13 +808,14 @@ export class CoreNode extends EventEmitter {
|
|
|
804
808
|
public renderBound?: Bound;
|
|
805
809
|
public strictBound?: Bound;
|
|
806
810
|
public preloadBound?: Bound;
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
811
|
+
/**
|
|
812
|
+
* Points at the shared `NO_CLIPPING_RECT` until this node actually
|
|
813
|
+
* participates in clipping (either it clips, or an ancestor's clip rect
|
|
814
|
+
* propagates down). Clipping is rare across the scene graph, so most nodes
|
|
815
|
+
* never allocate their own rect — `calculateClippingRect` swaps in a private
|
|
816
|
+
* object lazily the first time one is needed.
|
|
817
|
+
*/
|
|
818
|
+
public clippingRect: RectWithValid = NO_CLIPPING_RECT;
|
|
814
819
|
public textureCoords?: TextureCoords;
|
|
815
820
|
public updateShaderUniforms: boolean = false;
|
|
816
821
|
public isRenderable = false;
|
|
@@ -1366,7 +1371,7 @@ export class CoreNode extends EventEmitter {
|
|
|
1366
1371
|
childUpdateType |= UpdateType.Global;
|
|
1367
1372
|
}
|
|
1368
1373
|
|
|
1369
|
-
if (this.clipping
|
|
1374
|
+
if (this.props.clipping !== false) {
|
|
1370
1375
|
updateType |= UpdateType.Clipping | UpdateType.RenderBounds;
|
|
1371
1376
|
childUpdateType |= UpdateType.RenderBounds;
|
|
1372
1377
|
}
|
|
@@ -1669,14 +1674,31 @@ export class CoreNode extends EventEmitter {
|
|
|
1669
1674
|
}
|
|
1670
1675
|
|
|
1671
1676
|
// clipping is enabled and we are in bounds create our own bounds
|
|
1672
|
-
const { x, y, w, h } = this.props;
|
|
1677
|
+
const { x, y, w, h, clipping } = this.props;
|
|
1673
1678
|
|
|
1674
1679
|
// Pick the global transform if available, otherwise use the local transform
|
|
1675
1680
|
// global transform is only available if the node in an RTT chain
|
|
1676
1681
|
const { tx, ty } = this.sceneGlobalTransform || this.globalTransform || {};
|
|
1677
1682
|
const _x = tx ?? x;
|
|
1678
1683
|
const _y = ty ?? y;
|
|
1679
|
-
|
|
1684
|
+
|
|
1685
|
+
let mT = 0;
|
|
1686
|
+
let mR = 0;
|
|
1687
|
+
let mB = 0;
|
|
1688
|
+
let mL = 0;
|
|
1689
|
+
if (Array.isArray(clipping) === true) {
|
|
1690
|
+
mT = clipping[0];
|
|
1691
|
+
mR = clipping[1];
|
|
1692
|
+
mB = clipping[2];
|
|
1693
|
+
mL = clipping[3];
|
|
1694
|
+
}
|
|
1695
|
+
this.strictBound = createBound(
|
|
1696
|
+
_x - mL,
|
|
1697
|
+
_y - mT,
|
|
1698
|
+
_x + w + mR,
|
|
1699
|
+
_y + h + mB,
|
|
1700
|
+
this.strictBound,
|
|
1701
|
+
);
|
|
1680
1702
|
|
|
1681
1703
|
this.preloadBound = createPreloadBounds(
|
|
1682
1704
|
this.strictBound,
|
|
@@ -1912,15 +1934,47 @@ export class CoreNode extends EventEmitter {
|
|
|
1912
1934
|
* Finally, the node's parentClippingRect and clippingRect properties are updated.
|
|
1913
1935
|
*/
|
|
1914
1936
|
calculateClippingRect(parentClippingRect: RectWithValid) {
|
|
1915
|
-
const {
|
|
1937
|
+
const { props, globalTransform: gt } = this;
|
|
1916
1938
|
const { clipping } = props;
|
|
1917
1939
|
const isRotated = gt!.tb !== 0 || gt!.tc !== 0;
|
|
1940
|
+
const nodeClips = clipping !== false && isRotated === false;
|
|
1918
1941
|
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
clippingRect
|
|
1942
|
+
// Common case: this node doesn't clip and no ancestor clip rect needs to
|
|
1943
|
+
// propagate. No node-owned rect is required, so point at the shared
|
|
1944
|
+
// invalid default and skip the allocation entirely.
|
|
1945
|
+
if (nodeClips === false && parentClippingRect.valid === false) {
|
|
1946
|
+
this.clippingRect = NO_CLIPPING_RECT;
|
|
1947
|
+
return;
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
// A node-owned, mutable rect is needed. Allocate one lazily the first time
|
|
1951
|
+
// (the default shares NO_CLIPPING_RECT, which must never be written to).
|
|
1952
|
+
let clippingRect = this.clippingRect;
|
|
1953
|
+
if (clippingRect === NO_CLIPPING_RECT) {
|
|
1954
|
+
clippingRect = this.clippingRect = {
|
|
1955
|
+
x: 0,
|
|
1956
|
+
y: 0,
|
|
1957
|
+
w: 0,
|
|
1958
|
+
h: 0,
|
|
1959
|
+
valid: false,
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
if (nodeClips === true) {
|
|
1964
|
+
let mT = 0;
|
|
1965
|
+
let mR = 0;
|
|
1966
|
+
let mB = 0;
|
|
1967
|
+
let mL = 0;
|
|
1968
|
+
if (Array.isArray(clipping) === true) {
|
|
1969
|
+
mT = clipping[0];
|
|
1970
|
+
mR = clipping[1];
|
|
1971
|
+
mB = clipping[2];
|
|
1972
|
+
mL = clipping[3];
|
|
1973
|
+
}
|
|
1974
|
+
clippingRect.x = gt!.tx - mL;
|
|
1975
|
+
clippingRect.y = gt!.ty - mT;
|
|
1976
|
+
clippingRect.w = this.props.w * gt!.ta + mL + mR;
|
|
1977
|
+
clippingRect.h = this.props.h * gt!.td + mT + mB;
|
|
1924
1978
|
clippingRect.valid = true;
|
|
1925
1979
|
} else {
|
|
1926
1980
|
clippingRect.valid = false;
|
|
@@ -2421,11 +2475,14 @@ export class CoreNode extends EventEmitter {
|
|
|
2421
2475
|
this.setUpdateType(UpdateType.RenderBounds);
|
|
2422
2476
|
}
|
|
2423
2477
|
|
|
2424
|
-
get clipping(): boolean {
|
|
2478
|
+
get clipping(): boolean | [number, number, number, number] {
|
|
2425
2479
|
return this.props.clipping;
|
|
2426
2480
|
}
|
|
2427
2481
|
|
|
2428
|
-
set clipping(value: boolean) {
|
|
2482
|
+
set clipping(value: boolean | [number, number, number, number]) {
|
|
2483
|
+
if (this.props.clipping === value) {
|
|
2484
|
+
return;
|
|
2485
|
+
}
|
|
2429
2486
|
this.props.clipping = value;
|
|
2430
2487
|
this.setUpdateType(
|
|
2431
2488
|
UpdateType.Clipping | UpdateType.RenderBounds | UpdateType.Children,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for WebGL context-loss handling on the Stage.
|
|
3
|
+
*
|
|
4
|
+
* Covers the pragmatic core support added for low-RAM devices (Chromium 123+
|
|
5
|
+
* drops the GPU context when backgrounded). On loss we stop the render loop
|
|
6
|
+
* and emit a `contextLost` event so consumers can reload; the engine does not
|
|
7
|
+
* rebuild GL resources in place, so there is no restore path.
|
|
8
|
+
*/
|
|
9
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
10
|
+
import { Stage } from './Stage.js';
|
|
11
|
+
import { EventEmitter } from '../common/EventEmitter.js';
|
|
12
|
+
|
|
13
|
+
// Build a minimal Stage-like object that exercises the context-loss methods
|
|
14
|
+
// without standing up the full GL-backed constructor.
|
|
15
|
+
function makeStage() {
|
|
16
|
+
const eventBus = new EventEmitter();
|
|
17
|
+
const stage = Object.create(Stage.prototype) as Stage;
|
|
18
|
+
(stage as unknown as { eventBus: EventEmitter }).eventBus = eventBus;
|
|
19
|
+
stage.isContextLost = false;
|
|
20
|
+
return { stage, eventBus };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('Stage.setContextLost', () => {
|
|
24
|
+
it('sets the flag and emits contextLost', () => {
|
|
25
|
+
const { stage, eventBus } = makeStage();
|
|
26
|
+
const onLost = vi.fn();
|
|
27
|
+
eventBus.on('contextLost', onLost);
|
|
28
|
+
|
|
29
|
+
stage.setContextLost();
|
|
30
|
+
|
|
31
|
+
expect(stage.isContextLost).toBe(true);
|
|
32
|
+
expect(onLost).toHaveBeenCalledTimes(1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('is idempotent — does not re-emit when already lost', () => {
|
|
36
|
+
const { stage, eventBus } = makeStage();
|
|
37
|
+
const onLost = vi.fn();
|
|
38
|
+
eventBus.on('contextLost', onLost);
|
|
39
|
+
|
|
40
|
+
stage.setContextLost();
|
|
41
|
+
stage.setContextLost();
|
|
42
|
+
|
|
43
|
+
expect(onLost).toHaveBeenCalledTimes(1);
|
|
44
|
+
});
|
|
45
|
+
});
|
package/src/core/Stage.ts
CHANGED
|
@@ -119,6 +119,18 @@ export class Stage {
|
|
|
119
119
|
*/
|
|
120
120
|
public readonly eventBus: EventEmitter;
|
|
121
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Whether the underlying WebGL context has been lost.
|
|
124
|
+
*
|
|
125
|
+
* @remarks
|
|
126
|
+
* Set by the renderer's `webglcontextlost` listener. Once true it stays true:
|
|
127
|
+
* the engine does not rebuild GPU resources in-place, so the render loop
|
|
128
|
+
* stops and the supported recovery is to reload the app (see the `contextLost`
|
|
129
|
+
* event). This avoids issuing GL calls against a dead context, which return
|
|
130
|
+
* null/throw on low-RAM devices (e.g. Chromium 123+ backgrounding behaviour).
|
|
131
|
+
*/
|
|
132
|
+
public isContextLost = false;
|
|
133
|
+
|
|
122
134
|
/// State
|
|
123
135
|
startTime = 0;
|
|
124
136
|
deltaTime = 0;
|
|
@@ -429,6 +441,21 @@ export class Stage {
|
|
|
429
441
|
});
|
|
430
442
|
}
|
|
431
443
|
|
|
444
|
+
/**
|
|
445
|
+
* Mark the WebGL context as lost. Stops GL work and notifies consumers.
|
|
446
|
+
*
|
|
447
|
+
* @remarks
|
|
448
|
+
* The engine does not rebuild GPU resources in-place; consumers are expected
|
|
449
|
+
* to reload the app in response to the `contextLost` event.
|
|
450
|
+
*/
|
|
451
|
+
setContextLost() {
|
|
452
|
+
if (this.isContextLost === true) {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
this.isContextLost = true;
|
|
456
|
+
this.eventBus.emit('contextLost');
|
|
457
|
+
}
|
|
458
|
+
|
|
432
459
|
/**
|
|
433
460
|
* Create default PixelTexture
|
|
434
461
|
*/
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests that the render loop stops doing GL work once the WebGL context is
|
|
3
|
+
* lost.
|
|
4
|
+
*
|
|
5
|
+
* When `stage.isContextLost === true`, `runLoop` must issue no GL-touching
|
|
6
|
+
* calls and must not reschedule itself — the engine does not rebuild GL
|
|
7
|
+
* resources, so recovery is via app reload.
|
|
8
|
+
*/
|
|
9
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
10
|
+
import { WebPlatform } from './WebPlatform.js';
|
|
11
|
+
import type { Stage } from '../../Stage.js';
|
|
12
|
+
|
|
13
|
+
function makeFakeStage(isContextLost: boolean) {
|
|
14
|
+
return {
|
|
15
|
+
isContextLost,
|
|
16
|
+
targetFrameTime: 0,
|
|
17
|
+
updateFrameTime: vi.fn(),
|
|
18
|
+
updateAnimations: vi.fn(() => false),
|
|
19
|
+
hasSceneUpdates: vi.fn(() => true),
|
|
20
|
+
drawFrame: vi.fn(),
|
|
21
|
+
flushFrameEvents: vi.fn(),
|
|
22
|
+
calculateFps: vi.fn(),
|
|
23
|
+
} as unknown as Stage;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('WebPlatform render loop context-loss guard', () => {
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
vi.unstubAllGlobals();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('skips all GL work and does not reschedule while context is lost', () => {
|
|
32
|
+
let capturedLoop: ((t?: number) => void) | null = null;
|
|
33
|
+
const raf = vi.fn((cb: (t?: number) => void) => {
|
|
34
|
+
capturedLoop = cb;
|
|
35
|
+
return 1;
|
|
36
|
+
});
|
|
37
|
+
const setTimeoutSpy = vi.fn(
|
|
38
|
+
(_cb: () => void, _ms?: number) =>
|
|
39
|
+
1 as unknown as ReturnType<typeof setTimeout>,
|
|
40
|
+
);
|
|
41
|
+
vi.stubGlobal('requestAnimationFrame', raf);
|
|
42
|
+
vi.stubGlobal('setTimeout', setTimeoutSpy);
|
|
43
|
+
|
|
44
|
+
const stage = makeFakeStage(true);
|
|
45
|
+
new WebPlatform().startLoop(stage);
|
|
46
|
+
|
|
47
|
+
// startLoop kicks off the first frame via requestAnimationFrame
|
|
48
|
+
expect(capturedLoop).not.toBeNull();
|
|
49
|
+
expect(raf).toHaveBeenCalledTimes(1);
|
|
50
|
+
|
|
51
|
+
// Run one iteration with the context lost
|
|
52
|
+
capturedLoop!(0);
|
|
53
|
+
|
|
54
|
+
// No GL-touching frame work happened
|
|
55
|
+
expect(stage.updateFrameTime).not.toHaveBeenCalled();
|
|
56
|
+
expect(stage.drawFrame).not.toHaveBeenCalled();
|
|
57
|
+
expect(stage.hasSceneUpdates).not.toHaveBeenCalled();
|
|
58
|
+
|
|
59
|
+
// The loop did not reschedule itself (neither RAF nor setTimeout)
|
|
60
|
+
expect(raf).toHaveBeenCalledTimes(1);
|
|
61
|
+
expect(setTimeoutSpy).not.toHaveBeenCalled();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('runs frame work when the context is healthy', () => {
|
|
65
|
+
let capturedLoop: ((t?: number) => void) | null = null;
|
|
66
|
+
const raf = vi.fn((cb: (t?: number) => void) => {
|
|
67
|
+
capturedLoop = cb;
|
|
68
|
+
return 1;
|
|
69
|
+
});
|
|
70
|
+
vi.stubGlobal('requestAnimationFrame', raf);
|
|
71
|
+
|
|
72
|
+
const stage = makeFakeStage(false);
|
|
73
|
+
new WebPlatform().startLoop(stage);
|
|
74
|
+
|
|
75
|
+
capturedLoop!(0);
|
|
76
|
+
|
|
77
|
+
expect(stage.updateFrameTime).toHaveBeenCalledTimes(1);
|
|
78
|
+
expect(stage.drawFrame).toHaveBeenCalledTimes(1);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -32,6 +32,13 @@ export class WebPlatform extends Platform {
|
|
|
32
32
|
const buffer = 4;
|
|
33
33
|
|
|
34
34
|
const runLoop = (currentTime: number = 0) => {
|
|
35
|
+
// The GL context is lost and the engine does not rebuild it in place.
|
|
36
|
+
// Stop the loop entirely (no reschedule) so we issue no GL calls against
|
|
37
|
+
// a dead context. Recovery is via app reload (see the `contextLost` event).
|
|
38
|
+
if (stage.isContextLost === true) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
35
42
|
const targetFrameTime = stage.targetFrameTime;
|
|
36
43
|
|
|
37
44
|
// Frame Limiting logic
|
|
@@ -174,6 +174,8 @@ export class WebGlRenderer extends CoreRenderer {
|
|
|
174
174
|
const glw = (this.glw = new WebGlContextWrapper(gl));
|
|
175
175
|
glw.viewport(0, 0, options.canvas.width, options.canvas.height);
|
|
176
176
|
|
|
177
|
+
this.attachContextLossListeners(options.canvas);
|
|
178
|
+
|
|
177
179
|
this.updateClearColor(this.stage.clearColor);
|
|
178
180
|
|
|
179
181
|
glw.setBlend(true);
|
|
@@ -300,6 +302,32 @@ export class WebGlRenderer extends CoreRenderer {
|
|
|
300
302
|
]);
|
|
301
303
|
}
|
|
302
304
|
|
|
305
|
+
/**
|
|
306
|
+
* Listen for WebGL context loss on the canvas.
|
|
307
|
+
*
|
|
308
|
+
* @remarks
|
|
309
|
+
* On low-RAM devices (e.g. Chromium 123+ after backgrounding) the GPU
|
|
310
|
+
* context is dropped, after which `gl.createTexture()` and friends return
|
|
311
|
+
* null and the engine would crash. We pause the render loop via the Stage
|
|
312
|
+
* flag and surface a `contextLost` event so consumers can react.
|
|
313
|
+
*
|
|
314
|
+
* We intentionally do NOT call `event.preventDefault()` (which would ask the
|
|
315
|
+
* browser to restore the context) and do NOT listen for
|
|
316
|
+
* `webglcontextrestored`: the engine cannot rebuild its GPU resources
|
|
317
|
+
* in-place, so the supported recovery is to reload the app. See BROWSERS.md.
|
|
318
|
+
*/
|
|
319
|
+
private attachContextLossListeners(
|
|
320
|
+
canvas: HTMLCanvasElement | OffscreenCanvas,
|
|
321
|
+
): void {
|
|
322
|
+
if ('addEventListener' in canvas === false) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const target = canvas as HTMLCanvasElement;
|
|
326
|
+
target.addEventListener('webglcontextlost', () => {
|
|
327
|
+
this.stage.setContextLost();
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
303
331
|
reset() {
|
|
304
332
|
const { glw } = this;
|
|
305
333
|
if (DIRTY_QUAD_BUFFER) {
|
package/src/main-api/Renderer.ts
CHANGED
|
@@ -145,6 +145,28 @@ export interface RendererMainCriticalCleanupFailedEvent {
|
|
|
145
145
|
criticalThreshold: number;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
/**
|
|
149
|
+
* WebGL Context Lost Event Data
|
|
150
|
+
*
|
|
151
|
+
* @remarks
|
|
152
|
+
* Fired when the underlying WebGL context is lost (e.g. on low-RAM devices
|
|
153
|
+
* running Chromium 123+ after the app has been backgrounded). The render loop
|
|
154
|
+
* stops; in-engine GL resources are NOT rebuilt, so the supported handling is
|
|
155
|
+
* to reload the app.
|
|
156
|
+
*
|
|
157
|
+
* @category Events
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* renderer.on('contextLost', () => {
|
|
161
|
+
* window.location.reload();
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
export interface RendererMainContextLostEvent {
|
|
166
|
+
/** This event has no payload - listen without parameters */
|
|
167
|
+
readonly __eventHasNoPayload?: never;
|
|
168
|
+
}
|
|
169
|
+
|
|
148
170
|
/**
|
|
149
171
|
* Settings for the Renderer that can be updated during runtime.
|
|
150
172
|
*/
|
|
@@ -506,6 +528,7 @@ export type RendererMainSettings = RendererRuntimeSettings & {
|
|
|
506
528
|
* @see {@link RendererMainIdleEvent}
|
|
507
529
|
* @see {@link RendererMainCriticalCleanupEvent}
|
|
508
530
|
* @see {@link RendererMainCriticalCleanupFailedEvent}
|
|
531
|
+
* @see {@link RendererMainContextLostEvent}
|
|
509
532
|
*
|
|
510
533
|
* @fires RendererMain#fpsUpdate
|
|
511
534
|
* @fires RendererMain#frameTick
|
|
@@ -513,6 +536,7 @@ export type RendererMainSettings = RendererRuntimeSettings & {
|
|
|
513
536
|
* @fires RendererMain#idle
|
|
514
537
|
* @fires RendererMain#criticalCleanup
|
|
515
538
|
* @fires RendererMain#criticalCleanupFailed
|
|
539
|
+
* @fires RendererMain#contextLost
|
|
516
540
|
*/
|
|
517
541
|
export class RendererMain extends EventEmitter {
|
|
518
542
|
readonly root: INode;
|