blob: ee1fb9bec7b060fab91301c5c5fe9a87ffc6b0fb [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 'dart:html' as html;
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);
}
void testMain() {
group('CanvasKit', () {
setUpCanvasKitTest();
test('Surface allocates canvases efficiently', () {
final Surface surface = Surface(HtmlViewEmbedder());
final CkSurface original = surface.acquireFrame(ui.Size(9, 19)).skiaSurface;
// Expect exact requested dimensions.
expect(original.width(), 9);
expect(original.height(), 19);
expect(surface.htmlCanvas!.style.width, '9px');
expect(surface.htmlCanvas!.style.height, '19px');
// Shrinking reuses the existing surface straight-up.
final CkSurface shrunk = surface.acquireFrame(ui.Size(5, 15)).skiaSurface;
expect(shrunk, same(original));
expect(surface.htmlCanvas!.style.width, '9px');
expect(surface.htmlCanvas!.style.height, '19px');
// The first increase will allocate a new surface, but will overallocate
// by 40% to accommodate future increases.
final CkSurface firstIncrease = surface.acquireFrame(ui.Size(10, 20)).skiaSurface;
expect(firstIncrease, isNot(same(original)));
// Expect overallocated dimensions
expect(firstIncrease.width(), 14);
expect(firstIncrease.height(), 28);
expect(surface.htmlCanvas!.style.width, '14px');
expect(surface.htmlCanvas!.style.height, '28px');
// Subsequent increases within 40% reuse the old surface.
final CkSurface secondIncrease = surface.acquireFrame(ui.Size(11, 22)).skiaSurface;
expect(secondIncrease, same(firstIncrease));
// Increases beyond the 40% limit will cause a new allocation.
final CkSurface huge = surface.acquireFrame(ui.Size(20, 40)).skiaSurface;
expect(huge, isNot(same(firstIncrease)));
// Also over-allocated
expect(huge.width(), 28);
expect(huge.height(), 56);
expect(surface.htmlCanvas!.style.width, '28px');
expect(surface.htmlCanvas!.style.height, '56px');
// Shrink again. Reuse the last allocated surface.
final CkSurface shrunk2 = surface.acquireFrame(ui.Size(5, 15)).skiaSurface;
expect(shrunk2, same(huge));
});
test(
'Surface creates new context when WebGL context is lost',
() async {
final Surface surface = Surface(HtmlViewEmbedder());
expect(surface.debugForceNewContext, isTrue);
final CkSurface before = surface.acquireFrame(ui.Size(9, 19)).skiaSurface;
expect(surface.debugForceNewContext, isFalse);
// Pump a timer to flush any microtasks.
await Future<void>.delayed(Duration.zero);
final CkSurface afterAcquireFrame = surface.acquireFrame(ui.Size(9, 19)).skiaSurface;
// Existing context is reused.
expect(afterAcquireFrame, same(before));
// Emulate WebGL context loss.
final html.CanvasElement canvas = surface.htmlElement.children.single as html.CanvasElement;
final dynamic ctx = canvas.getContext('webgl2');
final dynamic loseContextExtension = ctx.getExtension('WEBGL_lose_context');
loseContextExtension.loseContext();
// Pump a timer to allow the "lose context" event to propagate.
await Future<void>.delayed(Duration.zero);
expect(surface.debugForceNewContext, isTrue);
final CkSurface afterContextLost = surface.acquireFrame(ui.Size(9, 19)).skiaSurface;
// A new cotext is created.
expect(afterContextLost, isNot(same(before)));
},
// Firefox doesn't have the WEBGL_lose_context extension.
skip: isFirefox || isIosSafari,
);
// Regression test for https://github.com/flutter/flutter/issues/75286
test('updates canvas logical size when device-pixel ratio changes', () {
final Surface surface = Surface(HtmlViewEmbedder());
final CkSurface original = surface.acquireFrame(ui.Size(10, 16)).skiaSurface;
expect(original.width(), 10);
expect(original.height(), 16);
expect(surface.htmlCanvas!.style.width, '10px');
expect(surface.htmlCanvas!.style.height, '16px');
// Increase device-pixel ratio: this makes CSS pixels bigger, so we need
// fewer of them to cover the browser window.
window.debugOverrideDevicePixelRatio(2.0);
final CkSurface highDpr = surface.acquireFrame(ui.Size(10, 16)).skiaSurface;
expect(highDpr.width(), 10);
expect(highDpr.height(), 16);
expect(surface.htmlCanvas!.style.width, '5px');
expect(surface.htmlCanvas!.style.height, '8px');
// Decrease device-pixel ratio: this makes CSS pixels smaller, so we need
// more of them to cover the browser window.
window.debugOverrideDevicePixelRatio(0.5);
final CkSurface lowDpr = surface.acquireFrame(ui.Size(10, 16)).skiaSurface;
expect(lowDpr.width(), 10);
expect(lowDpr.height(), 16);
expect(surface.htmlCanvas!.style.width, '20px');
expect(surface.htmlCanvas!.style.height, '32px');
});
}, skip: isIosSafari);
}