blob: 6dc626462461c03acef4a963fcdaa4f9b29e9b20 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'common.dart';
void main() {
internalBootstrapBrowserTest(() => testMain);
}
class TestRasterizer extends Rasterizer {
Map<EngineFlutterView, TestViewRasterizer> viewRasterizers =
<EngineFlutterView, TestViewRasterizer>{};
@override
TestViewRasterizer createViewRasterizer(EngineFlutterView view) {
return viewRasterizers.putIfAbsent(view, () => TestViewRasterizer(view));
}
@override
void dispose() {
// Do nothing
}
@override
void setResourceCacheMaxBytes(int bytes) {
// Do nothing
}
List<LayerTree> treesRenderedInView(EngineFlutterView view) {
return viewRasterizers[view]!.treesRendered;
}
}
class TestViewRasterizer extends ViewRasterizer {
TestViewRasterizer(super.view);
List<LayerTree> treesRendered = <LayerTree>[];
@override
DisplayCanvasFactory<DisplayCanvas> get displayFactory =>
throw UnimplementedError();
@override
void prepareToDraw() {
// Do nothing
}
@override
Future<void> draw(LayerTree tree) async {
treesRendered.add(tree);
return Future<void>.value();
}
@override
Future<void> rasterizeToCanvas(
DisplayCanvas canvas, List<CkPicture> pictures) {
// No-op
return Future<void>.value();
}
}
void testMain() {
group('Renderer', () {
setUpCanvasKitTest();
test('always renders most recent picture and skips intermediate pictures',
() async {
final TestRasterizer testRasterizer = TestRasterizer();
CanvasKitRenderer.instance.debugOverrideRasterizer(testRasterizer);
// Create another view to render into to force the renderer to make
// a [ViewRasterizer] for it.
final EngineFlutterView testView = EngineFlutterView(
EnginePlatformDispatcher.instance, createDomElement('test-view'));
EnginePlatformDispatcher.instance.viewManager.registerView(testView);
final List<LayerTree> treesToRender = <LayerTree>[];
final List<Future<void>> renderFutures = <Future<void>>[];
for (int i = 1; i < 20; i++) {
final ui.PictureRecorder recorder = ui.PictureRecorder();
final ui.Canvas canvas = ui.Canvas(recorder);
canvas.drawRect(const ui.Rect.fromLTWH(0, 0, 50, 50),
ui.Paint()..color = const ui.Color(0xff00ff00));
final ui.Picture picture = recorder.endRecording();
final ui.SceneBuilder builder = ui.SceneBuilder();
builder.addPicture(ui.Offset.zero, picture);
final ui.Scene scene = builder.build();
treesToRender.add((scene as LayerScene).layerTree);
renderFutures
.add(CanvasKitRenderer.instance.renderScene(scene, testView));
}
await Future.wait(renderFutures);
// Should just render the first and last pictures and skip the one inbetween.
final List<LayerTree> treesRendered =
testRasterizer.treesRenderedInView(testView);
expect(treesRendered.length, 2);
expect(treesRendered.first, treesToRender.first);
expect(treesRendered.last, treesToRender.last);
});
test('can render multiple frames at once into multiple views', () async {
final TestRasterizer testRasterizer = TestRasterizer();
CanvasKitRenderer.instance.debugOverrideRasterizer(testRasterizer);
// Create another view to render into to force the renderer to make
// a [ViewRasterizer] for it.
final EngineFlutterView testView1 = EngineFlutterView(
EnginePlatformDispatcher.instance, createDomElement('test-view'));
EnginePlatformDispatcher.instance.viewManager.registerView(testView1);
final EngineFlutterView testView2 = EngineFlutterView(
EnginePlatformDispatcher.instance, createDomElement('test-view'));
EnginePlatformDispatcher.instance.viewManager.registerView(testView2);
final EngineFlutterView testView3 = EngineFlutterView(
EnginePlatformDispatcher.instance, createDomElement('test-view'));
EnginePlatformDispatcher.instance.viewManager.registerView(testView3);
final Map<EngineFlutterView, List<LayerTree>> treesToRender =
<EngineFlutterView, List<LayerTree>>{};
treesToRender[testView1] = <LayerTree>[];
treesToRender[testView2] = <LayerTree>[];
treesToRender[testView3] = <LayerTree>[];
final List<Future<void>> renderFutures = <Future<void>>[];
for (int i = 1; i < 20; i++) {
for (final EngineFlutterView testView in <EngineFlutterView>[
testView1,
testView2,
testView3,
]) {
final ui.PictureRecorder recorder = ui.PictureRecorder();
final ui.Canvas canvas = ui.Canvas(recorder);
canvas.drawRect(const ui.Rect.fromLTWH(0, 0, 50, 50),
ui.Paint()..color = const ui.Color(0xff00ff00));
final ui.Picture picture = recorder.endRecording();
final ui.SceneBuilder builder = ui.SceneBuilder();
builder.addPicture(ui.Offset.zero, picture);
final ui.Scene scene = builder.build();
treesToRender[testView]!.add((scene as LayerScene).layerTree);
renderFutures
.add(CanvasKitRenderer.instance.renderScene(scene, testView));
}
}
await Future.wait(renderFutures);
// Should just render the first and last pictures and skip the one inbetween.
final List<LayerTree> treesRenderedInView1 =
testRasterizer.treesRenderedInView(testView1);
final List<LayerTree> treesToRenderInView1 = treesToRender[testView1]!;
expect(treesRenderedInView1.length, 2);
expect(treesRenderedInView1.first, treesToRenderInView1.first);
expect(treesRenderedInView1.last, treesToRenderInView1.last);
final List<LayerTree> treesRenderedInView2 =
testRasterizer.treesRenderedInView(testView2);
final List<LayerTree> treesToRenderInView2 = treesToRender[testView2]!;
expect(treesRenderedInView2.length, 2);
expect(treesRenderedInView2.first, treesToRenderInView2.first);
expect(treesRenderedInView2.last, treesToRenderInView2.last);
final List<LayerTree> treesRenderedInView3 =
testRasterizer.treesRenderedInView(testView3);
final List<LayerTree> treesToRenderInView3 = treesToRender[testView3]!;
expect(treesRenderedInView3.length, 2);
expect(treesRenderedInView3.first, treesToRenderInView3.first);
expect(treesRenderedInView3.last, treesToRenderInView3.last);
});
});
}