@solidtv/renderer 1.2.9 → 1.3.0
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 +7 -0
- package/dist/src/core/CoreNode.js +30 -9
- package/dist/src/core/CoreNode.js.map +1 -1
- package/dist/src/core/CoreTextNode.js +3 -1
- package/dist/src/core/CoreTextNode.js.map +1 -1
- package/dist/src/core/CoreTextureManager.d.ts +10 -0
- package/dist/src/core/CoreTextureManager.js +38 -5
- package/dist/src/core/CoreTextureManager.js.map +1 -1
- package/dist/src/core/Stage.d.ts +19 -0
- package/dist/src/core/Stage.js +28 -1
- package/dist/src/core/Stage.js.map +1 -1
- package/dist/src/core/lib/ImageWorker.js +22 -6
- package/dist/src/core/lib/ImageWorker.js.map +1 -1
- package/dist/src/core/lib/textureSvg.js +4 -1
- package/dist/src/core/lib/textureSvg.js.map +1 -1
- package/dist/src/core/lib/validateImageBitmap.d.ts +18 -0
- package/dist/src/core/lib/validateImageBitmap.js +66 -0
- package/dist/src/core/lib/validateImageBitmap.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/WebGlCtxTexture.js +5 -1
- package/dist/src/core/renderers/webgl/WebGlCtxTexture.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/core/textures/ImageTexture.js +21 -7
- package/dist/src/core/textures/ImageTexture.js.map +1 -1
- package/dist/src/main-api/Renderer.d.ts +41 -0
- package/dist/src/main-api/Renderer.js +8 -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 +66 -0
- package/src/core/CoreNode.ts +32 -9
- package/src/core/CoreTextNode.test.ts +145 -0
- package/src/core/CoreTextNode.ts +3 -1
- package/src/core/CoreTextureManager.ts +61 -8
- package/src/core/Stage.contextLoss.test.ts +45 -0
- package/src/core/Stage.ts +30 -0
- package/src/core/lib/ImageWorker.ts +30 -6
- package/src/core/lib/textureSvg.ts +4 -1
- package/src/core/lib/validateImageBitmap.test.ts +119 -0
- package/src/core/lib/validateImageBitmap.ts +89 -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/WebGlCtxTexture.ts +5 -1
- package/src/core/renderers/webgl/WebGlRenderer.ts +28 -0
- package/src/core/textures/ImageTexture.ts +25 -7
- package/src/main-api/Renderer.ts +50 -0
|
@@ -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) {
|
|
@@ -192,6 +192,18 @@ export class ImageTexture extends Texture {
|
|
|
192
192
|
const hasAlphaChannel = premultiplyAlpha ?? blob.type.includes('image/png');
|
|
193
193
|
const imageBitmapSupported = this.txManager.imageBitmapSupported;
|
|
194
194
|
|
|
195
|
+
// When the device does NOT honor the createImageBitmap premultiply option
|
|
196
|
+
// (e.g. older Safari), request a straight ('none') bitmap and let WebGL
|
|
197
|
+
// premultiply on upload instead. `premultiplyAlpha` in the returned
|
|
198
|
+
// TextureData means "WebGL should premultiply this source on upload".
|
|
199
|
+
const useGlPremultiply =
|
|
200
|
+
hasAlphaChannel === true &&
|
|
201
|
+
imageBitmapSupported.premultiplyHonored === false;
|
|
202
|
+
const bitmapMode: 'premultiply' | 'none' =
|
|
203
|
+
hasAlphaChannel === true && useGlPremultiply === false
|
|
204
|
+
? 'premultiply'
|
|
205
|
+
: 'none';
|
|
206
|
+
|
|
195
207
|
if (imageBitmapSupported.full === true && sw !== null && sh !== null) {
|
|
196
208
|
// createImageBitmap with crop
|
|
197
209
|
const bitmap = await this.platform.createImageBitmap(
|
|
@@ -201,28 +213,29 @@ export class ImageTexture extends Texture {
|
|
|
201
213
|
sw,
|
|
202
214
|
sh,
|
|
203
215
|
{
|
|
204
|
-
premultiplyAlpha:
|
|
216
|
+
premultiplyAlpha: bitmapMode,
|
|
205
217
|
colorSpaceConversion: 'none',
|
|
206
218
|
imageOrientation: 'none',
|
|
207
219
|
},
|
|
208
220
|
);
|
|
209
|
-
return { data: bitmap, premultiplyAlpha:
|
|
221
|
+
return { data: bitmap, premultiplyAlpha: useGlPremultiply };
|
|
210
222
|
} else if (imageBitmapSupported.basic === true) {
|
|
211
223
|
// basic createImageBitmap without options or crop
|
|
212
|
-
// this is supported for Chrome v50 to v52/54 that doesn't support options
|
|
224
|
+
// this is supported for Chrome v50 to v52/54 that doesn't support options.
|
|
225
|
+
// The browser default premultiplies, so WebGL must not premultiply again.
|
|
213
226
|
return {
|
|
214
227
|
data: await this.platform.createImageBitmap(blob),
|
|
215
|
-
premultiplyAlpha:
|
|
228
|
+
premultiplyAlpha: false,
|
|
216
229
|
};
|
|
217
230
|
}
|
|
218
231
|
|
|
219
232
|
// default createImageBitmap without crop but with options
|
|
220
233
|
const bitmap = await this.platform.createImageBitmap(blob, {
|
|
221
|
-
premultiplyAlpha:
|
|
234
|
+
premultiplyAlpha: bitmapMode,
|
|
222
235
|
colorSpaceConversion: 'none',
|
|
223
236
|
imageOrientation: 'none',
|
|
224
237
|
});
|
|
225
|
-
return { data: bitmap, premultiplyAlpha:
|
|
238
|
+
return { data: bitmap, premultiplyAlpha: useGlPremultiply };
|
|
226
239
|
}
|
|
227
240
|
|
|
228
241
|
async loadImage(src: string) {
|
|
@@ -274,9 +287,14 @@ export class ImageTexture extends Texture {
|
|
|
274
287
|
};
|
|
275
288
|
}
|
|
276
289
|
|
|
290
|
+
// The loader computes whether WebGL should premultiply this source on
|
|
291
|
+
// upload (it depends on the source type and on whether createImageBitmap
|
|
292
|
+
// honored the premultiply option). Preserve it; fall back to the prop only
|
|
293
|
+
// when the loader didn't decide.
|
|
277
294
|
return {
|
|
278
295
|
data: resp.data,
|
|
279
|
-
premultiplyAlpha:
|
|
296
|
+
premultiplyAlpha:
|
|
297
|
+
resp.premultiplyAlpha ?? this.props.premultiplyAlpha ?? true,
|
|
280
298
|
};
|
|
281
299
|
}
|
|
282
300
|
|
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
|
*/
|
|
@@ -436,6 +458,25 @@ export type RendererMainSettings = RendererRuntimeSettings & {
|
|
|
436
458
|
*/
|
|
437
459
|
createImageBitmapSupport: 'auto' | 'basic' | 'options' | 'full';
|
|
438
460
|
|
|
461
|
+
/**
|
|
462
|
+
* Override for whether `createImageBitmap(..., { premultiplyAlpha: 'premultiply' })`
|
|
463
|
+
* is actually honored by the target device.
|
|
464
|
+
*
|
|
465
|
+
* @remarks
|
|
466
|
+
* Some older browsers (notably older Safari/WebKit) accept the
|
|
467
|
+
* `premultiplyAlpha: 'premultiply'` option without throwing but silently
|
|
468
|
+
* ignore it, returning straight (non-premultiplied) alpha. This causes edge
|
|
469
|
+
* "ghosting" on images with transparency.
|
|
470
|
+
*
|
|
471
|
+
* Set to `'auto'` to detect via a cheap startup probe (one 1×1 texture
|
|
472
|
+
* upload + framebuffer readback). Set to a boolean to force the value. Leave
|
|
473
|
+
* unset to assume the option is honored — the default, which preserves
|
|
474
|
+
* existing behavior with no probe overhead.
|
|
475
|
+
*
|
|
476
|
+
* @defaultValue `true` (assume honored; no probe)
|
|
477
|
+
*/
|
|
478
|
+
premultiplyAlphaHonored?: boolean | 'auto';
|
|
479
|
+
|
|
439
480
|
/**
|
|
440
481
|
* Provide an alternative platform abstraction layer
|
|
441
482
|
*
|
|
@@ -506,6 +547,7 @@ export type RendererMainSettings = RendererRuntimeSettings & {
|
|
|
506
547
|
* @see {@link RendererMainIdleEvent}
|
|
507
548
|
* @see {@link RendererMainCriticalCleanupEvent}
|
|
508
549
|
* @see {@link RendererMainCriticalCleanupFailedEvent}
|
|
550
|
+
* @see {@link RendererMainContextLostEvent}
|
|
509
551
|
*
|
|
510
552
|
* @fires RendererMain#fpsUpdate
|
|
511
553
|
* @fires RendererMain#frameTick
|
|
@@ -513,6 +555,7 @@ export type RendererMainSettings = RendererRuntimeSettings & {
|
|
|
513
555
|
* @fires RendererMain#idle
|
|
514
556
|
* @fires RendererMain#criticalCleanup
|
|
515
557
|
* @fires RendererMain#criticalCleanupFailed
|
|
558
|
+
* @fires RendererMain#contextLost
|
|
516
559
|
*/
|
|
517
560
|
export class RendererMain extends EventEmitter {
|
|
518
561
|
readonly root: INode;
|
|
@@ -562,6 +605,12 @@ export class RendererMain extends EventEmitter {
|
|
|
562
605
|
textureProcessingTimeLimit: settings.textureProcessingTimeLimit || 10,
|
|
563
606
|
canvas: settings.canvas,
|
|
564
607
|
createImageBitmapSupport: settings.createImageBitmapSupport || 'full',
|
|
608
|
+
// undefined -> true (assume honored, no probe); 'auto' -> probe;
|
|
609
|
+
// explicit boolean -> force the value.
|
|
610
|
+
premultiplyAlphaHonored:
|
|
611
|
+
settings.premultiplyAlphaHonored === undefined
|
|
612
|
+
? true
|
|
613
|
+
: settings.premultiplyAlphaHonored,
|
|
565
614
|
platform: settings.platform || null,
|
|
566
615
|
maxRetryCount: settings.maxRetryCount ?? 5,
|
|
567
616
|
};
|
|
@@ -622,6 +671,7 @@ export class RendererMain extends EventEmitter {
|
|
|
622
671
|
targetFPS: settings.targetFPS!,
|
|
623
672
|
textureProcessingTimeLimit: settings.textureProcessingTimeLimit!,
|
|
624
673
|
createImageBitmapSupport: settings.createImageBitmapSupport!,
|
|
674
|
+
premultiplyAlphaHonored: settings.premultiplyAlphaHonored,
|
|
625
675
|
platform,
|
|
626
676
|
maxRetryCount: settings.maxRetryCount ?? 5,
|
|
627
677
|
});
|