Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
rasterizer_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define FML_USED_ON_EMBEDDER
6
7#include "flutter/shell/common/rasterizer.h"
8
9#include <memory>
10#include <optional>
11
12#include "flutter/flow/frame_timings.h"
13#include "flutter/fml/synchronization/count_down_latch.h"
14#include "flutter/fml/time/time_point.h"
15#include "flutter/shell/common/thread_host.h"
16#include "flutter/testing/testing.h"
17
22
23#include "gmock/gmock.h"
24
25using testing::_;
26using testing::ByMove;
27using testing::NiceMock;
28using testing::Return;
29using testing::ReturnRef;
30
31namespace flutter {
32namespace {
33
34constexpr float kDevicePixelRatio = 2.0f;
35constexpr int64_t kImplicitViewId = 0;
36
37std::vector<std::unique_ptr<LayerTreeTask>> SingleLayerTreeList(
38 int64_t view_id,
39 std::unique_ptr<LayerTree> layer_tree,
40 float pixel_ratio) {
41 std::vector<std::unique_ptr<LayerTreeTask>> tasks;
42 tasks.push_back(std::make_unique<LayerTreeTask>(
43 view_id, std::move(layer_tree), pixel_ratio));
44 return tasks;
45}
46
47class MockDelegate : public Rasterizer::Delegate {
48 public:
49 MOCK_METHOD(void,
50 OnFrameRasterized,
51 (const FrameTiming& frame_timing),
52 (override));
53 MOCK_METHOD(fml::Milliseconds, GetFrameBudget, (), (override));
54 MOCK_METHOD(fml::TimePoint, GetLatestFrameTargetTime, (), (const, override));
55 MOCK_METHOD(const TaskRunners&, GetTaskRunners, (), (const, override));
57 GetParentRasterThreadMerger,
58 (),
59 (const, override));
60 MOCK_METHOD(std::shared_ptr<const fml::SyncSwitch>,
61 GetIsGpuDisabledSyncSwitch,
62 (),
63 (const, override));
64 MOCK_METHOD(const Settings&, GetSettings, (), (const, override));
65 MOCK_METHOD(bool,
66 ShouldDiscardLayerTree,
67 (int64_t, const flutter::LayerTree&),
68 (override));
69};
70
71class MockSurface : public Surface {
72 public:
73 MOCK_METHOD(bool, IsValid, (), (override));
74 MOCK_METHOD(std::unique_ptr<SurfaceFrame>,
75 AcquireFrame,
76 (const SkISize& size),
77 (override));
78 MOCK_METHOD(SkMatrix, GetRootTransformation, (), (const, override));
79 MOCK_METHOD(GrDirectContext*, GetContext, (), (override));
80 MOCK_METHOD(std::unique_ptr<GLContextResult>,
81 MakeRenderContextCurrent,
82 (),
83 (override));
84 MOCK_METHOD(bool, ClearRenderContext, (), (override));
85 MOCK_METHOD(bool, AllowsDrawingWhenGpuDisabled, (), (const, override));
86};
87
88class MockExternalViewEmbedder : public ExternalViewEmbedder {
89 public:
90 MOCK_METHOD(DlCanvas*, GetRootCanvas, (), (override));
91 MOCK_METHOD(void, CancelFrame, (), (override));
92 MOCK_METHOD(
93 void,
94 BeginFrame,
95 (GrDirectContext * context,
96 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger),
97 (override));
98 MOCK_METHOD(void,
99 PrepareFlutterView,
100 (SkISize frame_size, double device_pixel_ratio),
101 (override));
102 MOCK_METHOD(void,
103 PrerollCompositeEmbeddedView,
104 (int64_t view_id, std::unique_ptr<EmbeddedViewParams> params),
105 (override));
106 MOCK_METHOD(
108 PostPrerollAction,
109 (const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger),
110 (override));
111 MOCK_METHOD(DlCanvas*, CompositeEmbeddedView, (int64_t view_id), (override));
112 MOCK_METHOD(void,
113 SubmitFlutterView,
114 (int64_t flutter_view_id,
115 GrDirectContext* context,
116 const std::shared_ptr<impeller::AiksContext>& aiks_context,
117 std::unique_ptr<SurfaceFrame> frame),
118 (override));
119 MOCK_METHOD(
120 void,
121 EndFrame,
122 (bool should_resubmit_frame,
123 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger),
124 (override));
125 MOCK_METHOD(bool, SupportsDynamicThreadMerging, (), (override));
126};
127} // namespace
128
129TEST(RasterizerTest, create) {
130 NiceMock<MockDelegate> delegate;
131 Settings settings;
132 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
133 auto rasterizer = std::make_unique<Rasterizer>(delegate);
134 EXPECT_TRUE(rasterizer != nullptr);
135}
136
137static std::unique_ptr<FrameTimingsRecorder> CreateFinishedBuildRecorder(
138 fml::TimePoint timestamp) {
139 std::unique_ptr<FrameTimingsRecorder> recorder =
140 std::make_unique<FrameTimingsRecorder>();
141 recorder->RecordVsync(timestamp, timestamp);
142 recorder->RecordBuildStart(timestamp);
143 recorder->RecordBuildEnd(timestamp);
144 return recorder;
145}
146
147static std::unique_ptr<FrameTimingsRecorder> CreateFinishedBuildRecorder() {
149}
150
151TEST(RasterizerTest, drawEmptyPipeline) {
152 std::string test_name =
153 ::testing::UnitTest::GetInstance()->current_test_info()->name();
154 ThreadHost thread_host("io.flutter.test." + test_name + ".",
158 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
159 thread_host.raster_thread->GetTaskRunner(),
160 thread_host.ui_thread->GetTaskRunner(),
161 thread_host.io_thread->GetTaskRunner());
162 NiceMock<MockDelegate> delegate;
163 Settings settings;
164 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
165 ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
166 auto rasterizer = std::make_unique<Rasterizer>(delegate);
167 auto surface = std::make_unique<NiceMock<MockSurface>>();
168 EXPECT_CALL(*surface, MakeRenderContextCurrent())
169 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
170 rasterizer->Setup(std::move(surface));
172 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
173 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
174 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
175 rasterizer->Draw(pipeline);
176 latch.Signal();
177 });
178 latch.Wait();
179}
180
181TEST(RasterizerTest,
182 drawWithExternalViewEmbedderExternalViewEmbedderSubmitFrameCalled) {
183 std::string test_name =
184 ::testing::UnitTest::GetInstance()->current_test_info()->name();
185 ThreadHost thread_host("io.flutter.test." + test_name + ".",
189 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
190 thread_host.raster_thread->GetTaskRunner(),
191 thread_host.ui_thread->GetTaskRunner(),
192 thread_host.io_thread->GetTaskRunner());
193 NiceMock<MockDelegate> delegate;
194 Settings settings;
195 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
196 EXPECT_CALL(delegate, GetTaskRunners())
197 .WillRepeatedly(ReturnRef(task_runners));
198 EXPECT_CALL(delegate, OnFrameRasterized(_));
199 auto rasterizer = std::make_unique<Rasterizer>(delegate);
200 auto surface = std::make_unique<NiceMock<MockSurface>>();
201
202 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
203 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
204 rasterizer->SetExternalViewEmbedder(external_view_embedder);
205
206 SurfaceFrame::FramebufferInfo framebuffer_info;
207 framebuffer_info.supports_readback = true;
208
209 auto surface_frame = std::make_unique<SurfaceFrame>(
210 /*surface=*/
211 nullptr, framebuffer_info,
212 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
213 /*frame_size=*/SkISize::Make(800, 600));
214 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(true));
215 EXPECT_CALL(*surface, AcquireFrame(SkISize()))
216 .WillOnce(Return(ByMove(std::move(surface_frame))));
217 EXPECT_CALL(*surface, MakeRenderContextCurrent())
218 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
219
220 EXPECT_CALL(*external_view_embedder,
221 BeginFrame(/*context=*/nullptr,
222 /*raster_thread_merger=*/
224 .Times(1);
225 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
226 /*frame_size=*/SkISize(),
227 /*device_pixel_ratio=*/2.0))
228 .Times(1);
229 EXPECT_CALL(*external_view_embedder,
230 SubmitFlutterView(/*flutter_view_id=*/kImplicitViewId, _, _, _))
231 .Times(1);
232 EXPECT_CALL(
233 *external_view_embedder,
234 EndFrame(/*should_resubmit_frame=*/false,
235 /*raster_thread_merger=*/fml::RefPtr<fml::RasterThreadMerger>(
236 nullptr)))
237 .Times(1);
238
239 rasterizer->Setup(std::move(surface));
241 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
242 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
243 auto layer_tree =
244 std::make_unique<LayerTree>(/*config=*/LayerTree::Config(),
245 /*frame_size=*/SkISize());
246 auto layer_tree_item = std::make_unique<FrameItem>(
247 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
248 kDevicePixelRatio),
251 pipeline->Produce().Complete(std::move(layer_tree_item));
252 EXPECT_TRUE(result.success);
253 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
254 rasterizer->Draw(pipeline);
255 latch.Signal();
256 });
257 latch.Wait();
258}
259
261 RasterizerTest,
262 drawWithExternalViewEmbedderAndThreadMergerNotMergedExternalViewEmbedderSubmitFrameNotCalled) {
263 std::string test_name =
264 ::testing::UnitTest::GetInstance()->current_test_info()->name();
265 ThreadHost thread_host("io.flutter.test." + test_name + ".",
269 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
270 thread_host.raster_thread->GetTaskRunner(),
271 thread_host.ui_thread->GetTaskRunner(),
272 thread_host.io_thread->GetTaskRunner());
273 NiceMock<MockDelegate> delegate;
274 Settings settings;
275 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
276 EXPECT_CALL(delegate, GetTaskRunners())
277 .WillRepeatedly(ReturnRef(task_runners));
278 EXPECT_CALL(delegate, OnFrameRasterized(_));
279 auto rasterizer = std::make_unique<Rasterizer>(delegate);
280 auto surface = std::make_unique<NiceMock<MockSurface>>();
281 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
282 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
283 rasterizer->SetExternalViewEmbedder(external_view_embedder);
284 EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
285 .WillRepeatedly(Return(true));
286 SurfaceFrame::FramebufferInfo framebuffer_info;
287 framebuffer_info.supports_readback = true;
288 auto surface_frame = std::make_unique<SurfaceFrame>(
289 /*surface=*/
290 nullptr, framebuffer_info,
291 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
292 /*frame_size=*/SkISize::Make(800, 600));
293 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(true));
294 EXPECT_CALL(*surface, AcquireFrame(SkISize()))
295 .WillOnce(Return(ByMove(std::move(surface_frame))));
296 EXPECT_CALL(*surface, MakeRenderContextCurrent())
297 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
298
299 EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
300 /*raster_thread_merger=*/_))
301 .Times(1);
302 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
303 /*frame_size=*/SkISize(),
304 /*device_pixel_ratio=*/2.0))
305 .Times(1);
306 EXPECT_CALL(*external_view_embedder,
307 SubmitFlutterView(/*flutter_view_id=*/kImplicitViewId, _, _, _))
308 .Times(0);
309 EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
310 /*raster_thread_merger=*/_))
311 .Times(1);
312
313 rasterizer->Setup(std::move(surface));
315 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
316 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
317 auto layer_tree = std::make_unique<LayerTree>(
318 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
319 auto layer_tree_item = std::make_unique<FrameItem>(
320 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
321 kDevicePixelRatio),
324 pipeline->Produce().Complete(std::move(layer_tree_item));
325 EXPECT_TRUE(result.success);
326 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
327 rasterizer->Draw(pipeline);
328 latch.Signal();
329 });
330 latch.Wait();
331}
332
334 RasterizerTest,
335 drawWithExternalViewEmbedderAndThreadsMergedExternalViewEmbedderSubmitFrameCalled) {
336 std::string test_name =
337 ::testing::UnitTest::GetInstance()->current_test_info()->name();
338 ThreadHost thread_host("io.flutter.test." + test_name + ".",
343 TaskRunners task_runners("test",
344 fml::MessageLoop::GetCurrent().GetTaskRunner(),
345 fml::MessageLoop::GetCurrent().GetTaskRunner(),
346 thread_host.ui_thread->GetTaskRunner(),
347 thread_host.io_thread->GetTaskRunner());
348
349 NiceMock<MockDelegate> delegate;
350 Settings settings;
351 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
352 EXPECT_CALL(delegate, GetTaskRunners())
353 .WillRepeatedly(ReturnRef(task_runners));
354 EXPECT_CALL(delegate, OnFrameRasterized(_));
355
356 auto rasterizer = std::make_unique<Rasterizer>(delegate);
357 auto surface = std::make_unique<NiceMock<MockSurface>>();
358
359 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
360 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
361 rasterizer->SetExternalViewEmbedder(external_view_embedder);
362
363 SurfaceFrame::FramebufferInfo framebuffer_info;
364 framebuffer_info.supports_readback = true;
365
366 auto surface_frame = std::make_unique<SurfaceFrame>(
367 /*surface=*/
368 nullptr, framebuffer_info,
369 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
370 /*frame_size=*/SkISize::Make(800, 600));
371 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(true));
372 EXPECT_CALL(*surface, AcquireFrame(SkISize()))
373 .WillOnce(Return(ByMove(std::move(surface_frame))));
374 EXPECT_CALL(*surface, MakeRenderContextCurrent())
375 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
376 EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
377 .WillRepeatedly(Return(true));
378
379 EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
380 /*raster_thread_merger=*/_))
381 .Times(1);
382 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
383 /*frame_size=*/SkISize(),
384 /*device_pixel_ratio=*/2.0))
385 .Times(1);
386 EXPECT_CALL(*external_view_embedder,
387 SubmitFlutterView(/*flutter_view_id=*/kImplicitViewId, _, _, _))
388 .Times(1);
389 EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
390 /*raster_thread_merger=*/_))
391 .Times(1);
392
393 rasterizer->Setup(std::move(surface));
394
395 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
396 auto layer_tree = std::make_unique<LayerTree>(/*config=*/LayerTree::Config(),
397 /*frame_size=*/SkISize());
398 auto layer_tree_item = std::make_unique<FrameItem>(
399 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
400 kDevicePixelRatio),
403 pipeline->Produce().Complete(std::move(layer_tree_item));
404 EXPECT_TRUE(result.success);
405 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
406 rasterizer->Draw(pipeline);
407}
408
409TEST(RasterizerTest,
410 drawLastLayerTreeWithThreadsMergedExternalViewEmbedderAndEndFrameCalled) {
411 std::string test_name =
412 ::testing::UnitTest::GetInstance()->current_test_info()->name();
413 ThreadHost thread_host("io.flutter.test." + test_name + ".",
418 TaskRunners task_runners("test",
419 fml::MessageLoop::GetCurrent().GetTaskRunner(),
420 fml::MessageLoop::GetCurrent().GetTaskRunner(),
421 thread_host.ui_thread->GetTaskRunner(),
422 thread_host.io_thread->GetTaskRunner());
423
424 NiceMock<MockDelegate> delegate;
425 Settings settings;
426 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
427 EXPECT_CALL(delegate, GetTaskRunners())
428 .WillRepeatedly(ReturnRef(task_runners));
429 EXPECT_CALL(delegate, OnFrameRasterized(_));
430
431 auto rasterizer = std::make_unique<Rasterizer>(delegate);
432 auto surface = std::make_unique<NiceMock<MockSurface>>();
433
434 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
435 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
436 rasterizer->SetExternalViewEmbedder(external_view_embedder);
437
438 SurfaceFrame::FramebufferInfo framebuffer_info;
439 framebuffer_info.supports_readback = true;
440
441 auto surface_frame1 = std::make_unique<SurfaceFrame>(
442 /*surface=*/
443 nullptr, framebuffer_info,
444 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
445 /*frame_size=*/SkISize::Make(800, 600));
446 auto surface_frame2 = std::make_unique<SurfaceFrame>(
447 /*surface=*/
448 nullptr, framebuffer_info,
449 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
450 /*frame_size=*/SkISize::Make(800, 600));
451 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled())
452 .WillRepeatedly(Return(true));
453 // Prepare two frames for Draw() and DrawLastLayerTrees().
454 EXPECT_CALL(*surface, AcquireFrame(SkISize()))
455 .WillOnce(Return(ByMove(std::move(surface_frame1))))
456 .WillOnce(Return(ByMove(std::move(surface_frame2))));
457 EXPECT_CALL(*surface, MakeRenderContextCurrent())
458 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
459 EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
460 .WillRepeatedly(Return(true));
461
462 EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
463 /*raster_thread_merger=*/_))
464 .Times(2);
465 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
466 /*frame_size=*/SkISize(),
467 /*device_pixel_ratio=*/2.0))
468 .Times(2);
469 EXPECT_CALL(*external_view_embedder,
470 SubmitFlutterView(/*flutter_view_id=*/kImplicitViewId, _, _, _))
471 .Times(2);
472 EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
473 /*raster_thread_merger=*/_))
474 .Times(2);
475
476 rasterizer->Setup(std::move(surface));
477
478 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
479 auto layer_tree = std::make_unique<LayerTree>(/*config=*/LayerTree::Config(),
480 /*frame_size=*/SkISize());
481 auto layer_tree_item = std::make_unique<FrameItem>(
482 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
483 kDevicePixelRatio),
486 pipeline->Produce().Complete(std::move(layer_tree_item));
487 EXPECT_TRUE(result.success);
488
489 // The Draw() will respectively call BeginFrame(), SubmitFlutterView() and
490 // EndFrame() one time.
491 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
492 rasterizer->Draw(pipeline);
493
494 // The DrawLastLayerTrees() will respectively call BeginFrame(),
495 // SubmitFlutterView() and EndFrame() one more time, totally 2 times.
496 rasterizer->DrawLastLayerTrees(CreateFinishedBuildRecorder());
497}
498
499TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) {
500 std::string test_name =
501 ::testing::UnitTest::GetInstance()->current_test_info()->name();
502 ThreadHost thread_host("io.flutter.test." + test_name + ".",
506 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
507 thread_host.raster_thread->GetTaskRunner(),
508 thread_host.ui_thread->GetTaskRunner(),
509 thread_host.io_thread->GetTaskRunner());
510 NiceMock<MockDelegate> delegate;
511 Settings settings;
512 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
513 EXPECT_CALL(delegate, GetTaskRunners())
514 .WillRepeatedly(ReturnRef(task_runners));
515 auto rasterizer = std::make_unique<Rasterizer>(delegate);
516
517 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
518 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
519 rasterizer->SetExternalViewEmbedder(external_view_embedder);
520
521 EXPECT_CALL(
522 *external_view_embedder,
523 EndFrame(/*should_resubmit_frame=*/false,
524 /*raster_thread_merger=*/fml::RefPtr<fml::RasterThreadMerger>(
525 nullptr)))
526 .Times(0);
527
529 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
530 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
531 auto layer_tree = std::make_unique<LayerTree>(
532 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
533 auto layer_tree_item = std::make_unique<FrameItem>(
534 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
535 kDevicePixelRatio),
538 pipeline->Produce().Complete(std::move(layer_tree_item));
539 EXPECT_TRUE(result.success);
540 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
541 rasterizer->Draw(pipeline);
542 latch.Signal();
543 });
544 latch.Wait();
545}
546
547TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) {
548 std::string test_name =
549 ::testing::UnitTest::GetInstance()->current_test_info()->name();
550 ThreadHost thread_host("io.flutter.test." + test_name + ".",
554 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
555 thread_host.raster_thread->GetTaskRunner(),
556 thread_host.ui_thread->GetTaskRunner(),
557 thread_host.io_thread->GetTaskRunner());
558 NiceMock<MockDelegate> delegate;
559 Settings settings;
560 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
561 EXPECT_CALL(delegate, GetTaskRunners())
562 .WillRepeatedly(ReturnRef(task_runners));
563 auto is_gpu_disabled_sync_switch =
564 std::make_shared<const fml::SyncSwitch>(false);
565 ON_CALL(delegate, GetIsGpuDisabledSyncSwitch())
566 .WillByDefault(Return(is_gpu_disabled_sync_switch));
567
568 auto rasterizer = std::make_unique<Rasterizer>(delegate);
569 auto surface = std::make_unique<NiceMock<MockSurface>>();
570 EXPECT_CALL(*surface, MakeRenderContextCurrent())
571 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
572
573 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
574 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
575 rasterizer->SetExternalViewEmbedder(external_view_embedder);
576 rasterizer->Setup(std::move(surface));
577
578 EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
579 /*raster_thread_merger=*/_))
580 .Times(0);
581 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
582 /*frame_size=*/SkISize(),
583 /*device_pixel_ratio=*/2.0))
584 .Times(0);
585 EXPECT_CALL(
586 *external_view_embedder,
587 EndFrame(/*should_resubmit_frame=*/false,
588 /*raster_thread_merger=*/fml::RefPtr<fml::RasterThreadMerger>(
589 nullptr)))
590 .Times(0);
591
593 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
594 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
595 auto layer_tree = std::make_unique<LayerTree>(
596 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
597 auto layer_tree_item = std::make_unique<FrameItem>(
598 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
599 kDevicePixelRatio),
602 pipeline->Produce().Complete(std::move(layer_tree_item));
603 EXPECT_TRUE(result.success);
604 // Always discard the layer tree.
605 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(true));
606 DrawStatus status = rasterizer->Draw(pipeline);
607 EXPECT_EQ(status, DrawStatus::kDone);
608 EXPECT_EQ(rasterizer->GetLastDrawStatus(kImplicitViewId),
610 latch.Signal();
611 });
612 latch.Wait();
613}
614
615TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) {
616 std::string test_name =
617 ::testing::UnitTest::GetInstance()->current_test_info()->name();
618 ThreadHost thread_host("io.flutter.test." + test_name + ".",
622 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
623 thread_host.raster_thread->GetTaskRunner(),
624 thread_host.ui_thread->GetTaskRunner(),
625 thread_host.io_thread->GetTaskRunner());
626 NiceMock<MockDelegate> delegate;
627 Settings settings;
628 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
629 EXPECT_CALL(delegate, GetTaskRunners())
630 .WillRepeatedly(ReturnRef(task_runners));
631
632 auto rasterizer = std::make_unique<Rasterizer>(delegate);
633 auto surface = std::make_unique<NiceMock<MockSurface>>();
634 EXPECT_CALL(*surface, MakeRenderContextCurrent())
635 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
636
637 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
638 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
639 rasterizer->SetExternalViewEmbedder(external_view_embedder);
640 rasterizer->Setup(std::move(surface));
641
642 EXPECT_CALL(
643 *external_view_embedder,
644 EndFrame(/*should_resubmit_frame=*/false,
645 /*raster_thread_merger=*/fml::RefPtr<fml::RasterThreadMerger>(
646 nullptr)))
647 .Times(0);
648
650 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
651 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
652 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
653 DrawStatus status = rasterizer->Draw(pipeline);
654 EXPECT_EQ(status, DrawStatus::kPipelineEmpty);
655 latch.Signal();
656 });
657 latch.Wait();
658}
659
660TEST(RasterizerTest, drawMultipleViewsWithExternalViewEmbedder) {
661 std::string test_name =
662 ::testing::UnitTest::GetInstance()->current_test_info()->name();
663 ThreadHost thread_host("io.flutter.test." + test_name + ".",
667 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
668 thread_host.raster_thread->GetTaskRunner(),
669 thread_host.ui_thread->GetTaskRunner(),
670 thread_host.io_thread->GetTaskRunner());
671 NiceMock<MockDelegate> delegate;
672 Settings settings;
673 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
674 EXPECT_CALL(delegate, GetTaskRunners())
675 .WillRepeatedly(ReturnRef(task_runners));
676 EXPECT_CALL(delegate, OnFrameRasterized(_));
677 auto rasterizer = std::make_unique<Rasterizer>(delegate);
678 auto surface = std::make_unique<NiceMock<MockSurface>>();
679 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
680 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
681 rasterizer->SetExternalViewEmbedder(external_view_embedder);
682 EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
683 .WillRepeatedly(Return(false));
684 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(true));
685 EXPECT_CALL(*surface, AcquireFrame(SkISize())).Times(2);
686 ON_CALL(*surface, AcquireFrame).WillByDefault([](const SkISize& size) {
687 SurfaceFrame::FramebufferInfo framebuffer_info;
688 framebuffer_info.supports_readback = true;
689 return std::make_unique<SurfaceFrame>(
690 /*surface=*/
691 nullptr, framebuffer_info,
692 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
693 /*frame_size=*/SkISize::Make(800, 600));
694 });
695 EXPECT_CALL(*surface, MakeRenderContextCurrent())
696 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
697
698 EXPECT_CALL(*external_view_embedder, BeginFrame(/*context=*/nullptr,
699 /*raster_thread_merger=*/_))
700 .Times(1);
701 EXPECT_CALL(*external_view_embedder,
702 PrepareFlutterView(/*frame_size=*/SkISize(),
703 /*device_pixel_ratio=*/1.5))
704 .Times(1);
705 EXPECT_CALL(*external_view_embedder,
706 SubmitFlutterView(/*flutter_view_id=*/0, _, _, _))
707 .Times(1);
708 EXPECT_CALL(*external_view_embedder,
709 PrepareFlutterView(/*frame_size=*/SkISize(),
710 /*device_pixel_ratio=*/2.0))
711 .Times(1);
712 EXPECT_CALL(*external_view_embedder,
713 SubmitFlutterView(/*flutter_view_id=*/1, _, _, _))
714 .Times(1);
715 EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
716 /*raster_thread_merger=*/_))
717 .Times(1);
718
719 rasterizer->Setup(std::move(surface));
721 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
722 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
723 std::vector<std::unique_ptr<LayerTreeTask>> tasks;
724 tasks.push_back(std::make_unique<LayerTreeTask>(
725 0, std::make_unique<LayerTree>(LayerTree::Config(), SkISize()), 1.5));
726 tasks.push_back(std::make_unique<LayerTreeTask>(
727 1, std::make_unique<LayerTree>(LayerTree::Config(), SkISize()), 2.0));
728 auto layer_tree_item = std::make_unique<FrameItem>(
729 std::move(tasks), CreateFinishedBuildRecorder());
731 pipeline->Produce().Complete(std::move(layer_tree_item));
732 EXPECT_TRUE(result.success);
733 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
734 rasterizer->Draw(pipeline);
735 latch.Signal();
736 });
737 latch.Wait();
738}
739
740TEST(RasterizerTest,
741 drawWithGpuEnabledAndSurfaceAllowsDrawingWhenGpuDisabledDoesAcquireFrame) {
742 std::string test_name =
743 ::testing::UnitTest::GetInstance()->current_test_info()->name();
744 ThreadHost thread_host("io.flutter.test." + test_name + ".",
748 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
749 thread_host.raster_thread->GetTaskRunner(),
750 thread_host.ui_thread->GetTaskRunner(),
751 thread_host.io_thread->GetTaskRunner());
752 NiceMock<MockDelegate> delegate;
753 Settings settings;
754 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
755 EXPECT_CALL(delegate, GetTaskRunners())
756 .WillRepeatedly(ReturnRef(task_runners));
757 EXPECT_CALL(delegate, OnFrameRasterized(_));
758
759 auto rasterizer = std::make_unique<Rasterizer>(delegate);
760 auto surface = std::make_unique<NiceMock<MockSurface>>();
761 auto is_gpu_disabled_sync_switch =
762 std::make_shared<const fml::SyncSwitch>(false);
763
764 SurfaceFrame::FramebufferInfo framebuffer_info;
765 framebuffer_info.supports_readback = true;
766 auto surface_frame = std::make_unique<SurfaceFrame>(
767 /*surface=*/
768 nullptr, /*framebuffer_info=*/framebuffer_info,
769 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
770 /*frame_size=*/SkISize::Make(800, 600));
771 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(true));
772 ON_CALL(delegate, GetIsGpuDisabledSyncSwitch())
773 .WillByDefault(Return(is_gpu_disabled_sync_switch));
774 EXPECT_CALL(delegate, GetIsGpuDisabledSyncSwitch()).Times(0);
775 EXPECT_CALL(*surface, AcquireFrame(SkISize()))
776 .WillOnce(Return(ByMove(std::move(surface_frame))));
777 EXPECT_CALL(*surface, MakeRenderContextCurrent())
778 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
779
780 rasterizer->Setup(std::move(surface));
782 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
783 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
784 auto layer_tree = std::make_unique<LayerTree>(
785 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
786 auto layer_tree_item = std::make_unique<FrameItem>(
787 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
788 kDevicePixelRatio),
791 pipeline->Produce().Complete(std::move(layer_tree_item));
792 EXPECT_TRUE(result.success);
793 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
794 rasterizer->Draw(pipeline);
795 latch.Signal();
796 });
797 latch.Wait();
798}
799
801 RasterizerTest,
802 drawWithGpuDisabledAndSurfaceAllowsDrawingWhenGpuDisabledDoesAcquireFrame) {
803 std::string test_name =
804 ::testing::UnitTest::GetInstance()->current_test_info()->name();
805 ThreadHost thread_host("io.flutter.test." + test_name + ".",
809 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
810 thread_host.raster_thread->GetTaskRunner(),
811 thread_host.ui_thread->GetTaskRunner(),
812 thread_host.io_thread->GetTaskRunner());
813 NiceMock<MockDelegate> delegate;
814 Settings settings;
815 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
816 EXPECT_CALL(delegate, GetTaskRunners())
817 .WillRepeatedly(ReturnRef(task_runners));
818 EXPECT_CALL(delegate, OnFrameRasterized(_));
819 auto rasterizer = std::make_unique<Rasterizer>(delegate);
820 auto surface = std::make_unique<NiceMock<MockSurface>>();
821 auto is_gpu_disabled_sync_switch =
822 std::make_shared<const fml::SyncSwitch>(true);
823
824 SurfaceFrame::FramebufferInfo framebuffer_info;
825 framebuffer_info.supports_readback = true;
826
827 auto surface_frame = std::make_unique<SurfaceFrame>(
828 /*surface=*/
829 nullptr, /*framebuffer_info=*/framebuffer_info,
830 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
831 /*frame_size=*/SkISize::Make(800, 600));
832 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(true));
833 ON_CALL(delegate, GetIsGpuDisabledSyncSwitch())
834 .WillByDefault(Return(is_gpu_disabled_sync_switch));
835 EXPECT_CALL(delegate, GetIsGpuDisabledSyncSwitch()).Times(0);
836 EXPECT_CALL(*surface, AcquireFrame(SkISize()))
837 .WillOnce(Return(ByMove(std::move(surface_frame))));
838 EXPECT_CALL(*surface, MakeRenderContextCurrent())
839 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
840
841 rasterizer->Setup(std::move(surface));
843 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
844 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
845 auto layer_tree = std::make_unique<LayerTree>(
846 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
847 auto layer_tree_item = std::make_unique<FrameItem>(
848 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
849 kDevicePixelRatio),
852 pipeline->Produce().Complete(std::move(layer_tree_item));
853 EXPECT_TRUE(result.success);
854 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
855 DrawStatus status = rasterizer->Draw(pipeline);
856 EXPECT_EQ(status, DrawStatus::kDone);
857 latch.Signal();
858 });
859 latch.Wait();
860}
861
863 RasterizerTest,
864 drawWithGpuEnabledAndSurfaceDisallowsDrawingWhenGpuDisabledDoesAcquireFrame) {
865 std::string test_name =
866 ::testing::UnitTest::GetInstance()->current_test_info()->name();
867 ThreadHost thread_host("io.flutter.test." + test_name + ".",
871 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
872 thread_host.raster_thread->GetTaskRunner(),
873 thread_host.ui_thread->GetTaskRunner(),
874 thread_host.io_thread->GetTaskRunner());
875 NiceMock<MockDelegate> delegate;
876 Settings settings;
877 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
878 EXPECT_CALL(delegate, GetTaskRunners())
879 .WillRepeatedly(ReturnRef(task_runners));
880 EXPECT_CALL(delegate, OnFrameRasterized(_));
881 auto rasterizer = std::make_unique<Rasterizer>(delegate);
882 auto surface = std::make_unique<NiceMock<MockSurface>>();
883 auto is_gpu_disabled_sync_switch =
884 std::make_shared<const fml::SyncSwitch>(false);
885
886 SurfaceFrame::FramebufferInfo framebuffer_info;
887 framebuffer_info.supports_readback = true;
888
889 auto surface_frame = std::make_unique<SurfaceFrame>(
890 /*surface=*/
891 nullptr, /*framebuffer_info=*/framebuffer_info,
892 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
893 /*frame_size=*/SkISize::Make(800, 600));
894 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(false));
895 EXPECT_CALL(delegate, GetIsGpuDisabledSyncSwitch())
896 .WillOnce(Return(is_gpu_disabled_sync_switch));
897 EXPECT_CALL(*surface, AcquireFrame(SkISize()))
898 .WillOnce(Return(ByMove(std::move(surface_frame))));
899 EXPECT_CALL(*surface, MakeRenderContextCurrent())
900 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
901
902 rasterizer->Setup(std::move(surface));
904 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
905 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
906 auto layer_tree = std::make_unique<LayerTree>(
907 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
908 auto layer_tree_item = std::make_unique<FrameItem>(
909 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
910 kDevicePixelRatio),
913 pipeline->Produce().Complete(std::move(layer_tree_item));
914 EXPECT_TRUE(result.success);
915 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
916 DrawStatus status = rasterizer->Draw(pipeline);
917 EXPECT_EQ(status, DrawStatus::kDone);
918 latch.Signal();
919 });
920 latch.Wait();
921}
922
924 RasterizerTest,
925 drawWithGpuDisabledAndSurfaceDisallowsDrawingWhenGpuDisabledDoesntAcquireFrame) {
926 std::string test_name =
927 ::testing::UnitTest::GetInstance()->current_test_info()->name();
928 ThreadHost thread_host("io.flutter.test." + test_name + ".",
932 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
933 thread_host.raster_thread->GetTaskRunner(),
934 thread_host.ui_thread->GetTaskRunner(),
935 thread_host.io_thread->GetTaskRunner());
936 NiceMock<MockDelegate> delegate;
937 Settings settings;
938 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
939 EXPECT_CALL(delegate, GetTaskRunners())
940 .WillRepeatedly(ReturnRef(task_runners));
941 EXPECT_CALL(delegate, OnFrameRasterized(_)).Times(0);
942 auto rasterizer = std::make_unique<Rasterizer>(delegate);
943 auto surface = std::make_unique<NiceMock<MockSurface>>();
944 auto is_gpu_disabled_sync_switch =
945 std::make_shared<const fml::SyncSwitch>(true);
946
947 SurfaceFrame::FramebufferInfo framebuffer_info;
948 framebuffer_info.supports_readback = true;
949
950 auto surface_frame = std::make_unique<SurfaceFrame>(
951 /*surface=*/
952 nullptr, /*framebuffer_info=*/framebuffer_info,
953 /*submit_callback=*/[](const SurfaceFrame&, DlCanvas*) { return true; },
954 /*frame_size=*/SkISize::Make(800, 600));
955 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(false));
956 EXPECT_CALL(delegate, GetIsGpuDisabledSyncSwitch())
957 .WillOnce(Return(is_gpu_disabled_sync_switch));
958 EXPECT_CALL(*surface, AcquireFrame(SkISize())).Times(0);
959 EXPECT_CALL(*surface, MakeRenderContextCurrent())
960 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
961
962 rasterizer->Setup(std::move(surface));
964 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
965 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
966 auto layer_tree = std::make_unique<LayerTree>(
967 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
968 auto layer_tree_item = std::make_unique<FrameItem>(
969 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
970 kDevicePixelRatio),
973 pipeline->Produce().Complete(std::move(layer_tree_item));
974 EXPECT_TRUE(result.success);
975 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
976 DrawStatus status = rasterizer->Draw(pipeline);
977 EXPECT_EQ(status, DrawStatus::kGpuUnavailable);
978 latch.Signal();
979 });
980 latch.Wait();
981}
982
984 RasterizerTest,
985 FrameTimingRecorderShouldStartRecordingRasterTimeBeforeSurfaceAcquireFrame) {
986 std::string test_name =
987 ::testing::UnitTest::GetInstance()->current_test_info()->name();
988 ThreadHost thread_host("io.flutter.test." + test_name + ".",
992 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
993 thread_host.raster_thread->GetTaskRunner(),
994 thread_host.ui_thread->GetTaskRunner(),
995 thread_host.io_thread->GetTaskRunner());
996 NiceMock<MockDelegate> delegate;
997 Settings settings;
998 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
999 EXPECT_CALL(delegate, GetTaskRunners())
1000 .WillRepeatedly(ReturnRef(task_runners));
1001 EXPECT_CALL(delegate, OnFrameRasterized(_))
1002 .WillOnce([&](const FrameTiming& frame_timing) {
1004 fml::TimePoint raster_start =
1005 frame_timing.Get(FrameTiming::kRasterStart);
1006 EXPECT_TRUE(now - raster_start < fml::TimeDelta::FromSecondsF(1));
1007 });
1008
1009 auto rasterizer = std::make_unique<Rasterizer>(delegate);
1010 auto surface = std::make_unique<NiceMock<MockSurface>>();
1011 auto is_gpu_disabled_sync_switch =
1012 std::make_shared<const fml::SyncSwitch>(false);
1013 ON_CALL(delegate, GetIsGpuDisabledSyncSwitch())
1014 .WillByDefault(Return(is_gpu_disabled_sync_switch));
1015 ON_CALL(*surface, AcquireFrame(SkISize()))
1016 .WillByDefault(::testing::Invoke([] { return nullptr; }));
1017 EXPECT_CALL(*surface, AcquireFrame(SkISize()));
1018 EXPECT_CALL(*surface, MakeRenderContextCurrent())
1019 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
1020 rasterizer->Setup(std::move(surface));
1022 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1023 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
1024 auto layer_tree = std::make_unique<LayerTree>(
1025 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
1026 auto layer_tree_item = std::make_unique<FrameItem>(
1027 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
1028 kDevicePixelRatio),
1031 pipeline->Produce().Complete(std::move(layer_tree_item));
1032 EXPECT_TRUE(result.success);
1033 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
1034 DrawStatus status = rasterizer->Draw(pipeline);
1035 EXPECT_EQ(status, DrawStatus::kDone);
1036 EXPECT_EQ(rasterizer->GetLastDrawStatus(kImplicitViewId),
1038 latch.Signal();
1039 });
1040 latch.Wait();
1041}
1042
1043TEST(RasterizerTest,
1044 drawLayerTreeWithCorrectFrameTimingWhenPipelineIsMoreAvailable) {
1045 std::string test_name =
1046 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1047 ThreadHost thread_host("io.flutter.test." + test_name + ".",
1051 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
1052 thread_host.raster_thread->GetTaskRunner(),
1053 thread_host.ui_thread->GetTaskRunner(),
1054 thread_host.io_thread->GetTaskRunner());
1055 NiceMock<MockDelegate> delegate;
1056 Settings settings;
1057 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
1058 ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
1059
1061 std::unique_ptr<Rasterizer> rasterizer;
1062 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1063 rasterizer = std::make_unique<Rasterizer>(delegate);
1064 latch.Signal();
1065 });
1066 latch.Wait();
1067
1068 auto surface = std::make_unique<NiceMock<MockSurface>>();
1069 EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled())
1070 .WillRepeatedly(Return(true));
1071 ON_CALL(*surface, AcquireFrame(SkISize()))
1072 .WillByDefault(::testing::Invoke([] {
1073 SurfaceFrame::FramebufferInfo framebuffer_info;
1074 framebuffer_info.supports_readback = true;
1075 return std::make_unique<SurfaceFrame>(
1076 /*surface=*/
1077 nullptr, framebuffer_info,
1078 /*submit_callback=*/
1079 [](const SurfaceFrame& frame, DlCanvas*) { return true; },
1080 /*frame_size=*/SkISize::Make(800, 600));
1081 }));
1082 ON_CALL(*surface, MakeRenderContextCurrent())
1083 .WillByDefault(::testing::Invoke(
1084 [] { return std::make_unique<GLContextDefaultResult>(true); }));
1085
1086 fml::CountDownLatch count_down_latch(2);
1087 auto first_timestamp = fml::TimePoint::Now();
1088 auto second_timestamp = first_timestamp + fml::TimeDelta::FromMilliseconds(8);
1089 std::vector<fml::TimePoint> timestamps = {first_timestamp, second_timestamp};
1090 int frame_rasterized_count = 0;
1091 EXPECT_CALL(delegate, OnFrameRasterized(_))
1092 .Times(2)
1093 .WillRepeatedly([&](const FrameTiming& frame_timing) {
1094 EXPECT_EQ(timestamps[frame_rasterized_count],
1095 frame_timing.Get(FrameTiming::kVsyncStart));
1096 EXPECT_EQ(timestamps[frame_rasterized_count],
1097 frame_timing.Get(FrameTiming::kBuildStart));
1098 EXPECT_EQ(timestamps[frame_rasterized_count],
1099 frame_timing.Get(FrameTiming::kBuildFinish));
1100 frame_rasterized_count++;
1101 count_down_latch.CountDown();
1102 });
1103
1104 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1105 rasterizer->Setup(std::move(surface));
1106 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
1107 for (int i = 0; i < 2; i++) {
1108 auto layer_tree = std::make_unique<LayerTree>(
1109 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
1110 auto layer_tree_item = std::make_unique<FrameItem>(
1111 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
1112 kDevicePixelRatio),
1113 CreateFinishedBuildRecorder(timestamps[i]));
1115 pipeline->Produce().Complete(std::move(layer_tree_item));
1116 EXPECT_TRUE(result.success);
1117 EXPECT_EQ(result.is_first_item, i == 0);
1118 }
1119 // Although we only call 'Rasterizer::Draw' once, it will be called twice
1120 // finally because there are two items in the pipeline.
1121 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
1122 rasterizer->Draw(pipeline);
1123 });
1124 count_down_latch.Wait();
1125 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1126 rasterizer.reset();
1127 latch.Signal();
1128 });
1129 latch.Wait();
1130}
1131
1132TEST(RasterizerTest, TeardownFreesResourceCache) {
1133 std::string test_name =
1134 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1135 ThreadHost thread_host("io.flutter.test." + test_name + ".",
1139 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
1140 thread_host.raster_thread->GetTaskRunner(),
1141 thread_host.ui_thread->GetTaskRunner(),
1142 thread_host.io_thread->GetTaskRunner());
1143
1144 NiceMock<MockDelegate> delegate;
1145 Settings settings;
1146 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
1147 EXPECT_CALL(delegate, GetTaskRunners())
1148 .WillRepeatedly(ReturnRef(task_runners));
1149
1150 auto rasterizer = std::make_unique<Rasterizer>(delegate);
1151 auto surface = std::make_unique<NiceMock<MockSurface>>();
1152 auto context = GrDirectContext::MakeMock(nullptr);
1153 context->setResourceCacheLimit(0);
1154
1155 EXPECT_CALL(*surface, MakeRenderContextCurrent())
1156 .WillRepeatedly([]() -> std::unique_ptr<GLContextResult> {
1157 return std::make_unique<GLContextDefaultResult>(true);
1158 });
1159 EXPECT_CALL(*surface, GetContext()).WillRepeatedly(Return(context.get()));
1160
1161 rasterizer->Setup(std::move(surface));
1162 EXPECT_EQ(context->getResourceCacheLimit(), 0ul);
1163
1164 rasterizer->SetResourceCacheMaxBytes(10000000, false);
1165 EXPECT_EQ(context->getResourceCacheLimit(), 10000000ul);
1166 EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
1167
1168 int count = 0;
1169 size_t bytes = 0;
1170 context->getResourceCacheUsage(&count, &bytes);
1171 EXPECT_EQ(bytes, 0ul);
1172
1173 auto image_info =
1175 auto sk_surface = SkSurfaces::RenderTarget(context.get(),
1176 skgpu::Budgeted::kYes, image_info);
1177 EXPECT_TRUE(sk_surface);
1178
1179 SkPaint paint;
1180 sk_surface->getCanvas()->drawPaint(paint);
1181 context->flushAndSubmit(GrSyncCpu::kYes);
1182
1183 EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
1184
1185 sk_surface.reset();
1186
1187 context->getResourceCacheUsage(&count, &bytes);
1188 EXPECT_GT(bytes, 0ul);
1189 EXPECT_GT(context->getResourceCachePurgeableBytes(), 0ul);
1190
1191 rasterizer->Teardown();
1192 EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
1193}
1194
1195TEST(RasterizerTest, TeardownNoSurface) {
1196 std::string test_name =
1197 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1198 ThreadHost thread_host("io.flutter.test." + test_name + ".",
1202 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
1203 thread_host.raster_thread->GetTaskRunner(),
1204 thread_host.ui_thread->GetTaskRunner(),
1205 thread_host.io_thread->GetTaskRunner());
1206
1207 NiceMock<MockDelegate> delegate;
1208 Settings settings;
1209 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
1210 EXPECT_CALL(delegate, GetTaskRunners())
1211 .WillRepeatedly(ReturnRef(task_runners));
1212
1213 auto rasterizer = std::make_unique<Rasterizer>(delegate);
1214
1215 EXPECT_TRUE(rasterizer);
1216 rasterizer->Teardown();
1217}
1218
1219TEST(RasterizerTest, presentationTimeSetWhenVsyncTargetInFuture) {
1220 GTEST_SKIP() << "eglPresentationTime is disabled due to "
1221 "https://github.com/flutter/flutter/issues/112503";
1222#if false
1223 std::string test_name =
1224 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1225 ThreadHost thread_host("io.flutter.test." + test_name + ".",
1228 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
1229 thread_host.raster_thread->GetTaskRunner(),
1230 thread_host.ui_thread->GetTaskRunner(),
1231 thread_host.io_thread->GetTaskRunner());
1232
1233 NiceMock<MockDelegate> delegate;
1234 Settings settings;
1235 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
1236 ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
1237
1239 std::unique_ptr<Rasterizer> rasterizer;
1240 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1241 rasterizer = std::make_unique<Rasterizer>(delegate);
1242 latch.Signal();
1243 });
1244 latch.Wait();
1245
1246 const auto millis_16 = fml::TimeDelta::FromMilliseconds(16);
1247 const auto first_timestamp = fml::TimePoint::Now() + millis_16;
1248 auto second_timestamp = first_timestamp + millis_16;
1249 std::vector<fml::TimePoint> timestamps = {first_timestamp, second_timestamp};
1250
1251 int frames_submitted = 0;
1252 fml::CountDownLatch submit_latch(2);
1253 auto surface = std::make_unique<MockSurface>();
1254 ON_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillByDefault(Return(true));
1255 ON_CALL(*surface, AcquireFrame(SkISize()))
1256 .WillByDefault(::testing::Invoke([&] {
1257 SurfaceFrame::FramebufferInfo framebuffer_info;
1258 framebuffer_info.supports_readback = true;
1259 return std::make_unique<SurfaceFrame>(
1260 /*surface=*/nullptr, framebuffer_info,
1261 /*submit_callback=*/
1262 [&](const SurfaceFrame& frame, DlCanvas*) {
1263 const auto pres_time = *frame.submit_info().presentation_time;
1264 const auto diff = pres_time - first_timestamp;
1265 int num_frames_submitted = frames_submitted++;
1266 EXPECT_EQ(diff.ToMilliseconds(),
1267 num_frames_submitted * millis_16.ToMilliseconds());
1268 submit_latch.CountDown();
1269 return true;
1270 },
1271 /*frame_size=*/SkISize::Make(800, 600));
1272 }));
1273
1274 ON_CALL(*surface, MakeRenderContextCurrent())
1275 .WillByDefault(::testing::Invoke(
1276 [] { return std::make_unique<GLContextDefaultResult>(true); }));
1277
1278 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1279 rasterizer->Setup(std::move(surface));
1280 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
1281 for (int i = 0; i < 2; i++) {
1282 auto layer_tree = std::make_unique<LayerTree>(
1283 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
1284 auto layer_tree_item = std::make_unique<FrameItem>(
1285 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
1286 kDevicePixelRatio),
1287 CreateFinishedBuildRecorder(timestamps[i]));
1289 pipeline->Produce().Complete(std::move(layer_tree_item));
1290 EXPECT_TRUE(result.success);
1291 EXPECT_EQ(result.is_first_item, i == 0);
1292 }
1293 // Although we only call 'Rasterizer::Draw' once, it will be called twice
1294 // finally because there are two items in the pipeline.
1295 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
1296 rasterizer->Draw(pipeline);
1297 });
1298
1299 submit_latch.Wait();
1300 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1301 rasterizer.reset();
1302 latch.Signal();
1303 });
1304 latch.Wait();
1305#endif // false
1306}
1307
1308TEST(RasterizerTest, presentationTimeNotSetWhenVsyncTargetInPast) {
1309 GTEST_SKIP() << "eglPresentationTime is disabled due to "
1310 "https://github.com/flutter/flutter/issues/112503";
1311#if false
1312 std::string test_name =
1313 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1314 ThreadHost thread_host("io.flutter.test." + test_name + ".",
1317 TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
1318 thread_host.raster_thread->GetTaskRunner(),
1319 thread_host.ui_thread->GetTaskRunner(),
1320 thread_host.io_thread->GetTaskRunner());
1321
1322 NiceMock<MockDelegate> delegate;
1323 Settings settings;
1324 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings));
1325 ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
1326
1328 std::unique_ptr<Rasterizer> rasterizer;
1329 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1330 rasterizer = std::make_unique<Rasterizer>(delegate);
1331 latch.Signal();
1332 });
1333 latch.Wait();
1334
1335 const auto millis_16 = fml::TimeDelta::FromMilliseconds(16);
1336 const auto first_timestamp = fml::TimePoint::Now() - millis_16;
1337
1338 fml::CountDownLatch submit_latch(1);
1339 auto surface = std::make_unique<MockSurface>();
1340 ON_CALL(*surface, AllowsDrawingWhenGpuDisabled()).WillByDefault(Return(true));
1341 ON_CALL(*surface, AcquireFrame(SkISize()))
1342 .WillByDefault(::testing::Invoke([&] {
1343 SurfaceFrame::FramebufferInfo framebuffer_info;
1344 framebuffer_info.supports_readback = true;
1345 return std::make_unique<SurfaceFrame>(
1346 /*surface=*/nullptr, framebuffer_info,
1347 /*submit_callback=*/
1348 [&](const SurfaceFrame& frame, DlCanvas*) {
1349 const std::optional<fml::TimePoint> pres_time =
1350 frame.submit_info().presentation_time;
1351 EXPECT_EQ(pres_time, std::nullopt);
1352 submit_latch.CountDown();
1353 return true;
1354 },
1355 /*frame_size=*/SkISize::Make(800, 600));
1356 }));
1357
1358 ON_CALL(*surface, MakeRenderContextCurrent())
1359 .WillByDefault(::testing::Invoke(
1360 [] { return std::make_unique<GLContextDefaultResult>(true); }));
1361
1362 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1363 rasterizer->Setup(std::move(surface));
1364 auto pipeline = std::make_shared<FramePipeline>(/*depth=*/10);
1365 auto layer_tree = std::make_unique<LayerTree>(
1366 /*config=*/LayerTree::Config(), /*frame_size=*/SkISize());
1367 auto layer_tree_item = std::make_unique<FrameItem>(
1368 SingleLayerTreeList(kImplicitViewId, std::move(layer_tree),
1369 kDevicePixelRatio),
1370 CreateFinishedBuildRecorder(first_timestamp));
1372 pipeline->Produce().Complete(std::move(layer_tree_item));
1373 EXPECT_TRUE(result.success);
1374 EXPECT_EQ(result.is_first_item, true);
1375 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false));
1376 rasterizer->Draw(pipeline);
1377 });
1378
1379 submit_latch.Wait();
1380 thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
1381 rasterizer.reset();
1382 latch.Signal();
1383 });
1384 latch.Wait();
1385#endif // false
1386}
1387
1388} // namespace flutter
#define TEST(S, s, D, expected)
int count
static sk_sp< GrDirectContext > MakeMock(const GrMockOptions *, const GrContextOptions &)
static sk_sp< SkColorSpace > MakeSRGB()
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:37
fml::TimePoint Get(Phase phase) const
Definition settings.h:51
static void EnsureInitializedForCurrentThread()
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
static constexpr TimeDelta FromSecondsF(double seconds)
Definition time_delta.h:53
static constexpr TimeDelta FromMilliseconds(int64_t millis)
Definition time_delta.h:46
static TimePoint Now()
Definition time_point.cc:49
const Paint & paint
const EmbeddedViewParams * params
VkSurfaceKHR surface
Definition main.cc:49
double frame
Definition examples.cpp:31
GAsyncResult * result
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
static std::unique_ptr< FrameTimingsRecorder > CreateFinishedBuildRecorder()
constexpr FlutterViewId kImplicitViewId
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
std::chrono::duration< double, std::milli > Milliseconds
Definition time_delta.h:18
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
static SkImageInfo MakeN32Premul(int width, int height)
The collection of all the threads used by the engine.
Definition thread_host.h:21
std::unique_ptr< fml::Thread > io_thread
Definition thread_host.h:86
std::unique_ptr< fml::Thread > platform_thread
Definition thread_host.h:83
std::unique_ptr< fml::Thread > raster_thread
Definition thread_host.h:85
std::unique_ptr< fml::Thread > ui_thread
Definition thread_host.h:84
#define EXPECT_TRUE(handle)
Definition unit_test.h:685