fix(canvas): report retained backing failures
- Warn once with the rejected surface dimensions and original CanvasKit error - Disable repeated cache allocation attempts until the renderer surface is replaced - Keep direct scene rendering as the visible fallback
This commit is contained in:
parent
c4df0c0257
commit
afc5305e8c
|
|
@ -122,6 +122,7 @@ export class SkiaRenderer {
|
|||
} | null = null
|
||||
sceneBackingPreviewUntil = 0
|
||||
sceneBackingNeedsCrispRender = false
|
||||
sceneBackingAllocationFailed = false
|
||||
sceneBackingBuild: {
|
||||
surface: Surface
|
||||
graph: SceneGraph
|
||||
|
|
@ -451,6 +452,7 @@ export class SkiaRenderer {
|
|||
replaceSurface(surface: Surface): void {
|
||||
this.surface.delete()
|
||||
this.surface = surface
|
||||
this.sceneBackingAllocationFailed = false
|
||||
this.invalidateScenePicture()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,15 +187,22 @@ function sceneBackingGeometry(r: SkiaRenderer) {
|
|||
}
|
||||
|
||||
function createSceneBackingSurface(r: SkiaRenderer, width: number, height: number): Surface | null {
|
||||
if (r.sceneBackingAllocationFailed) return null
|
||||
const info = {
|
||||
width: Math.ceil(width * r.dpr),
|
||||
height: Math.ceil(height * r.dpr),
|
||||
colorType: r.ck.ColorType.RGBA_8888,
|
||||
alphaType: r.ck.AlphaType.Premul,
|
||||
colorSpace: r.ck.ColorSpace.SRGB
|
||||
}
|
||||
try {
|
||||
return r.surface.makeSurface({
|
||||
width: Math.ceil(width * r.dpr),
|
||||
height: Math.ceil(height * r.dpr),
|
||||
colorType: r.ck.ColorType.RGBA_8888,
|
||||
alphaType: r.ck.AlphaType.Premul,
|
||||
colorSpace: r.ck.ColorSpace.SRGB
|
||||
})
|
||||
} catch {
|
||||
return r.surface.makeSurface(info)
|
||||
} catch (error) {
|
||||
r.sceneBackingAllocationFailed = true
|
||||
console.warn(
|
||||
`Disabling retained scene backing after CanvasKit failed to allocate ${info.width}×${info.height}`,
|
||||
error
|
||||
)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
@ -452,6 +459,7 @@ export function renderSceneBacking(
|
|||
graph: SceneGraph,
|
||||
sceneVersion: number
|
||||
): boolean {
|
||||
if (r.sceneBackingAllocationFailed) return false
|
||||
const positionPreviewVersion = graph.positionPreviewVersion
|
||||
const allowStaleZoom = now() < r.sceneBackingPreviewUntil
|
||||
const hasCoverage = backingCoverageContainsLiveViewport(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { expect, mock, test } from 'bun:test'
|
||||
import { expect, mock, spyOn, test } from 'bun:test'
|
||||
|
||||
import type { Canvas, Image as CKImage, ImageInfo, Surface } from 'canvaskit-wasm'
|
||||
|
||||
|
|
@ -39,6 +39,7 @@ function createRenderer(surfaceFactory: (info: ImageInfo) => Surface | null) {
|
|||
pageId: 'page',
|
||||
sceneBacking: null,
|
||||
sceneBackingBuild: null,
|
||||
sceneBackingAllocationFailed: false,
|
||||
sceneBackingNeedsCrispRender: false,
|
||||
sceneBackingPreviewUntil: 0,
|
||||
sceneBackingAverageRecordMs: 40,
|
||||
|
|
@ -124,15 +125,27 @@ test('retained scene backing preserves the full margin when it fits the allocati
|
|||
expect(requests[0]).toMatchObject({ width: 2400, height: 1800 })
|
||||
})
|
||||
|
||||
test('retained scene backing falls back when CanvasKit throws during allocation', () => {
|
||||
test('retained scene backing reports a throwing allocation and disables further attempts', () => {
|
||||
const error = new TypeError("Cannot set properties of null (setting 'be')")
|
||||
const r = createRenderer(() => {
|
||||
throw new TypeError("Cannot set properties of null (setting 'be')")
|
||||
throw error
|
||||
})
|
||||
const canvas = createCanvas()
|
||||
const warn = spyOn(console, 'warn').mockImplementation(() => undefined)
|
||||
|
||||
expect(() => renderSceneBacking(r, canvas, createGraph(), 1)).not.toThrow()
|
||||
expect(renderSceneBacking(r, canvas, createGraph(), 1)).toBe(false)
|
||||
|
||||
expect(r.sceneBackingAllocationFailed).toBe(true)
|
||||
expect(r.surface.makeSurface).toHaveBeenCalledTimes(1)
|
||||
expect(warn).toHaveBeenCalledTimes(1)
|
||||
expect(warn).toHaveBeenCalledWith(
|
||||
'Disabling retained scene backing after CanvasKit failed to allocate 300×300',
|
||||
error
|
||||
)
|
||||
expect(r.sceneBacking).toBeNull()
|
||||
expect(canvas.drawImageRectOptions).not.toHaveBeenCalled()
|
||||
warn.mockRestore()
|
||||
})
|
||||
|
||||
test('retained scene backing filters cross-zoom previews instead of falling back to live rendering', () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue