未验证 提交 6999c4d4 编写于 作者: F Ferhat 提交者: GitHub

When picture is updated and bitmapcanvas reused, clear element cache (#22072)

上级 9bddfc9b
......@@ -135,7 +135,7 @@ class BitmapCanvas extends EngineCanvas {
}
/// Setup cache for reusing DOM elements across frames.
void setElementCache(CrossFrameCache<html.HtmlElement> cache) {
void setElementCache(CrossFrameCache<html.HtmlElement>? cache) {
_elementCache = cache;
}
......
......@@ -52,6 +52,7 @@ List<_PaintRequest> _paintQueue = <_PaintRequest>[];
void _recycleCanvas(EngineCanvas? canvas) {
if (canvas is BitmapCanvas) {
canvas.setElementCache(null);
if (canvas.isReusable()) {
_recycledCanvases.add(canvas);
if (_recycledCanvases.length > _kCanvasCacheSize) {
......@@ -91,7 +92,7 @@ class PersistedPicture extends PersistedLeafSurface {
final int hints;
/// Cache for reusing elements such as images across picture updates.
CrossFrameCache<html.HtmlElement> _elementCache =
CrossFrameCache<html.HtmlElement>? _elementCache =
CrossFrameCache<html.HtmlElement>();
@override
......@@ -386,6 +387,7 @@ class PersistedPicture extends PersistedLeafSurface {
if (_debugShowCanvasReuseStats) {
DebugCanvasReuseOverlay.instance.keptCount++;
}
// Re-use old bitmap canvas.
oldCanvas.bounds = _optimalLocalCullRect!;
_canvas = oldCanvas;
oldCanvas.setElementCache(_elementCache);
......@@ -395,6 +397,10 @@ class PersistedPicture extends PersistedLeafSurface {
// We can't use the old canvas because the size has changed, so we put
// it in a cache for later reuse.
_recycleCanvas(oldCanvas);
if (_canvas is BitmapCanvas) {
(_canvas as BitmapCanvas).setElementCache(null);
}
_canvas = null;
// We cannot paint immediately because not all canvases that we may be
// able to reuse have been released yet. So instead we enqueue this
// picture to be painted after the update cycle is done syncing the layer
......@@ -403,8 +409,9 @@ class PersistedPicture extends PersistedLeafSurface {
canvasSize: _optimalLocalCullRect!.size,
paintCallback: () {
_canvas = _findOrCreateCanvas(_optimalLocalCullRect!);
assert(_canvas is BitmapCanvas &&
(_canvas as BitmapCanvas?)!._elementCache == _elementCache);
if (_canvas is BitmapCanvas) {
(_canvas as BitmapCanvas).setElementCache(_elementCache);
}
if (_debugExplainSurfaceStats) {
final BitmapCanvas bitmapCanvas = _canvas as BitmapCanvas;
_surfaceStatsFor(this).paintPixelCount +=
......@@ -518,6 +525,9 @@ class PersistedPicture extends PersistedLeafSurface {
super.update(oldSurface);
// Transfer element cache over.
_elementCache = oldSurface._elementCache;
if (oldSurface != this) {
oldSurface._elementCache = null;
}
if (dx != oldSurface.dx || dy != oldSurface.dy) {
_applyTranslate();
......
......@@ -258,6 +258,42 @@ void testMain() {
});
});
/// Verify elementCache is passed during update to reuse existing
/// image elements.
test('Should retain same image element', () async {
final SurfaceSceneBuilder builder = SurfaceSceneBuilder();
final Picture picture1 = _drawPathImagePath();
EngineLayer oldLayer = builder.pushClipRect(
const Rect.fromLTRB(10, 10, 300, 300),
);
builder.addPicture(Offset.zero, picture1);
builder.pop();
html.HtmlElement content = builder.build().webOnlyRootElement;
html.document.body.append(content);
List<html.ImageElement> list = content.querySelectorAll('img');
for (html.ImageElement image in list) {
image.alt = 'marked';
}
// Force update to scene which will utilize reuse code path.
final SurfaceSceneBuilder builder2 = SurfaceSceneBuilder();
builder2.pushClipRect(
const Rect.fromLTRB(5, 10, 300, 300),
oldLayer: oldLayer
);
final Picture picture2 = _drawPathImagePath();
builder2.addPicture(Offset.zero, picture2);
builder2.pop();
html.HtmlElement contentAfterReuse = builder2.build().webOnlyRootElement;
list = contentAfterReuse.querySelectorAll('img');
for (html.ImageElement image in list) {
expect(image.alt, 'marked');
}
expect(list.length, 1);
});
PersistedPicture findPictureSurfaceChild(PersistedContainerSurface parent) {
PersistedPicture pictureSurface;
parent.visitChildren((PersistedSurface child) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册