5#define FML_USED_ON_EMBEDDER
7#include "flutter/shell/common/rasterizer.h"
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"
23#include "gmock/gmock.h"
27using testing::NiceMock;
29using testing::ReturnRef;
34constexpr float kDevicePixelRatio = 2.0f;
37std::vector<std::unique_ptr<LayerTreeTask>> SingleLayerTreeList(
39 std::unique_ptr<LayerTree> layer_tree,
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));
47class MockDelegate :
public Rasterizer::Delegate {
51 (
const FrameTiming& frame_timing),
54 MOCK_METHOD(
fml::TimePoint, GetLatestFrameTargetTime, (), (
const,
override));
55 MOCK_METHOD(
const TaskRunners&, GetTaskRunners, (), (
const,
override));
57 GetParentRasterThreadMerger,
60 MOCK_METHOD(std::shared_ptr<const fml::SyncSwitch>,
61 GetIsGpuDisabledSyncSwitch,
64 MOCK_METHOD(
const Settings&, GetSettings, (), (
const,
override));
66 ShouldDiscardLayerTree,
73 MOCK_METHOD(
bool, IsValid, (), (
override));
74 MOCK_METHOD(std::unique_ptr<SurfaceFrame>,
78 MOCK_METHOD(
SkMatrix, GetRootTransformation, (), (
const,
override));
80 MOCK_METHOD(std::unique_ptr<GLContextResult>,
81 MakeRenderContextCurrent,
84 MOCK_METHOD(
bool, ClearRenderContext, (), (
override));
85 MOCK_METHOD(
bool, AllowsDrawingWhenGpuDisabled, (), (
const,
override));
88class MockExternalViewEmbedder :
public ExternalViewEmbedder {
90 MOCK_METHOD(
DlCanvas*, GetRootCanvas, (), (
override));
91 MOCK_METHOD(
void, CancelFrame, (), (
override));
100 (
SkISize frame_size,
double device_pixel_ratio),
103 PrerollCompositeEmbeddedView,
104 (int64_t view_id, std::unique_ptr<EmbeddedViewParams>
params),
111 MOCK_METHOD(
DlCanvas*, CompositeEmbeddedView, (int64_t view_id), (
override));
114 (int64_t flutter_view_id,
116 const std::shared_ptr<impeller::AiksContext>& aiks_context,
117 std::unique_ptr<SurfaceFrame>
frame),
122 (
bool should_resubmit_frame,
125 MOCK_METHOD(
bool, SupportsDynamicThreadMerging, (), (
override));
130 NiceMock<MockDelegate> delegate;
132 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
133 auto rasterizer = std::make_unique<Rasterizer>(delegate);
139 std::unique_ptr<FrameTimingsRecorder> recorder =
140 std::make_unique<FrameTimingsRecorder>();
141 recorder->RecordVsync(timestamp, timestamp);
142 recorder->RecordBuildStart(timestamp);
143 recorder->RecordBuildEnd(timestamp);
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 +
".",
155 ThreadHost::Type::kPlatform |
157 ThreadHost::Type::kUi);
162 NiceMock<MockDelegate> delegate;
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));
173 auto pipeline = std::make_shared<FramePipeline>(10);
174 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
175 rasterizer->Draw(pipeline);
182 drawWithExternalViewEmbedderExternalViewEmbedderSubmitFrameCalled) {
183 std::string test_name =
184 ::testing::UnitTest::GetInstance()->current_test_info()->name();
185 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
186 ThreadHost::Type::kPlatform |
188 ThreadHost::Type::kUi);
193 NiceMock<MockDelegate> delegate;
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>>();
202 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
203 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
204 rasterizer->SetExternalViewEmbedder(external_view_embedder);
209 auto surface_frame = std::make_unique<SurfaceFrame>(
211 nullptr, framebuffer_info,
214 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(
true));
216 .WillOnce(Return(ByMove(std::move(surface_frame))));
217 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
218 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
220 EXPECT_CALL(*external_view_embedder,
225 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
229 EXPECT_CALL(*external_view_embedder,
233 *external_view_embedder,
239 rasterizer->Setup(std::move(
surface));
242 auto pipeline = std::make_shared<FramePipeline>(10);
243 auto layer_tree = std::make_unique<LayerTree>(
nullptr,
245 auto layer_tree_item = std::make_unique<FrameItem>(
250 pipeline->Produce().Complete(std::move(layer_tree_item));
252 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
253 rasterizer->Draw(pipeline);
261 drawWithExternalViewEmbedderAndThreadMergerNotMergedExternalViewEmbedderSubmitFrameNotCalled) {
262 std::string test_name =
263 ::testing::UnitTest::GetInstance()->current_test_info()->name();
264 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
265 ThreadHost::Type::kPlatform |
267 ThreadHost::Type::kUi);
272 NiceMock<MockDelegate> delegate;
274 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
275 EXPECT_CALL(delegate, GetTaskRunners())
276 .WillRepeatedly(ReturnRef(task_runners));
277 EXPECT_CALL(delegate, OnFrameRasterized(_));
278 auto rasterizer = std::make_unique<Rasterizer>(delegate);
279 auto surface = std::make_unique<NiceMock<MockSurface>>();
280 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
281 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
282 rasterizer->SetExternalViewEmbedder(external_view_embedder);
283 EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
284 .WillRepeatedly(Return(
true));
287 auto surface_frame = std::make_unique<SurfaceFrame>(
289 nullptr, framebuffer_info,
292 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(
true));
294 .WillOnce(Return(ByMove(std::move(surface_frame))));
295 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
296 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
298 EXPECT_CALL(*external_view_embedder, BeginFrame(
nullptr,
301 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
305 EXPECT_CALL(*external_view_embedder,
308 EXPECT_CALL(*external_view_embedder, EndFrame(
false,
312 rasterizer->Setup(std::move(
surface));
315 auto pipeline = std::make_shared<FramePipeline>(10);
316 auto layer_tree = std::make_unique<LayerTree>(
318 auto layer_tree_item = std::make_unique<FrameItem>(
323 pipeline->Produce().Complete(std::move(layer_tree_item));
325 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
326 rasterizer->Draw(pipeline);
334 drawWithExternalViewEmbedderAndThreadsMergedExternalViewEmbedderSubmitFrameCalled) {
335 std::string test_name =
336 ::testing::UnitTest::GetInstance()->current_test_info()->name();
337 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
338 ThreadHost::Type::kPlatform |
340 ThreadHost::Type::kUi);
348 NiceMock<MockDelegate> delegate;
350 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
351 EXPECT_CALL(delegate, GetTaskRunners())
352 .WillRepeatedly(ReturnRef(task_runners));
353 EXPECT_CALL(delegate, OnFrameRasterized(_));
355 auto rasterizer = std::make_unique<Rasterizer>(delegate);
356 auto surface = std::make_unique<NiceMock<MockSurface>>();
358 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
359 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
360 rasterizer->SetExternalViewEmbedder(external_view_embedder);
365 auto surface_frame = std::make_unique<SurfaceFrame>(
367 nullptr, framebuffer_info,
370 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(
true));
372 .WillOnce(Return(ByMove(std::move(surface_frame))));
373 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
374 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
375 EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
376 .WillRepeatedly(Return(
true));
378 EXPECT_CALL(*external_view_embedder, BeginFrame(
nullptr,
381 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
385 EXPECT_CALL(*external_view_embedder,
388 EXPECT_CALL(*external_view_embedder, EndFrame(
false,
392 rasterizer->Setup(std::move(
surface));
394 auto pipeline = std::make_shared<FramePipeline>(10);
395 auto layer_tree = std::make_unique<LayerTree>(
nullptr,
397 auto layer_tree_item = std::make_unique<FrameItem>(
402 pipeline->Produce().Complete(std::move(layer_tree_item));
404 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
405 rasterizer->Draw(pipeline);
409 drawLastLayerTreeWithThreadsMergedExternalViewEmbedderAndEndFrameCalled) {
410 std::string test_name =
411 ::testing::UnitTest::GetInstance()->current_test_info()->name();
412 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
413 ThreadHost::Type::kPlatform |
415 ThreadHost::Type::kUi);
423 NiceMock<MockDelegate> delegate;
425 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
426 EXPECT_CALL(delegate, GetTaskRunners())
427 .WillRepeatedly(ReturnRef(task_runners));
428 EXPECT_CALL(delegate, OnFrameRasterized(_));
430 auto rasterizer = std::make_unique<Rasterizer>(delegate);
431 auto surface = std::make_unique<NiceMock<MockSurface>>();
433 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
434 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
435 rasterizer->SetExternalViewEmbedder(external_view_embedder);
440 auto surface_frame1 = std::make_unique<SurfaceFrame>(
442 nullptr, framebuffer_info,
445 auto surface_frame2 = std::make_unique<SurfaceFrame>(
447 nullptr, framebuffer_info,
450 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled())
451 .WillRepeatedly(Return(
true));
454 .WillOnce(Return(ByMove(std::move(surface_frame1))))
455 .WillOnce(Return(ByMove(std::move(surface_frame2))));
456 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
457 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
458 EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
459 .WillRepeatedly(Return(
true));
461 EXPECT_CALL(*external_view_embedder, BeginFrame(
nullptr,
464 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
468 EXPECT_CALL(*external_view_embedder,
471 EXPECT_CALL(*external_view_embedder, EndFrame(
false,
475 rasterizer->Setup(std::move(
surface));
477 auto pipeline = std::make_shared<FramePipeline>(10);
478 auto layer_tree = std::make_unique<LayerTree>(
nullptr,
480 auto layer_tree_item = std::make_unique<FrameItem>(
485 pipeline->Produce().Complete(std::move(layer_tree_item));
490 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
491 rasterizer->Draw(pipeline);
498TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) {
499 std::string test_name =
500 ::testing::UnitTest::GetInstance()->current_test_info()->name();
501 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
502 ThreadHost::Type::kPlatform |
504 ThreadHost::Type::kUi);
509 NiceMock<MockDelegate> delegate;
511 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
512 EXPECT_CALL(delegate, GetTaskRunners())
513 .WillRepeatedly(ReturnRef(task_runners));
514 auto rasterizer = std::make_unique<Rasterizer>(delegate);
516 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
517 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
518 rasterizer->SetExternalViewEmbedder(external_view_embedder);
521 *external_view_embedder,
529 auto pipeline = std::make_shared<FramePipeline>(10);
530 auto layer_tree = std::make_unique<LayerTree>(
532 auto layer_tree_item = std::make_unique<FrameItem>(
537 pipeline->Produce().Complete(std::move(layer_tree_item));
539 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
540 rasterizer->Draw(pipeline);
546TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) {
547 std::string test_name =
548 ::testing::UnitTest::GetInstance()->current_test_info()->name();
549 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
550 ThreadHost::Type::kPlatform |
552 ThreadHost::Type::kUi);
557 NiceMock<MockDelegate> delegate;
559 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
560 EXPECT_CALL(delegate, GetTaskRunners())
561 .WillRepeatedly(ReturnRef(task_runners));
562 auto is_gpu_disabled_sync_switch =
563 std::make_shared<const fml::SyncSwitch>(
false);
564 ON_CALL(delegate, GetIsGpuDisabledSyncSwitch())
565 .WillByDefault(Return(is_gpu_disabled_sync_switch));
567 auto rasterizer = std::make_unique<Rasterizer>(delegate);
568 auto surface = std::make_unique<NiceMock<MockSurface>>();
569 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
570 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
572 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
573 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
574 rasterizer->SetExternalViewEmbedder(external_view_embedder);
575 rasterizer->Setup(std::move(
surface));
577 EXPECT_CALL(*external_view_embedder, BeginFrame(
nullptr,
580 EXPECT_CALL(*external_view_embedder, PrepareFlutterView(
585 *external_view_embedder,
593 auto pipeline = std::make_shared<FramePipeline>(10);
594 auto layer_tree = std::make_unique<LayerTree>(
596 auto layer_tree_item = std::make_unique<FrameItem>(
601 pipeline->Produce().Complete(std::move(layer_tree_item));
604 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
true));
605 DrawStatus status = rasterizer->Draw(pipeline);
614TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) {
615 std::string test_name =
616 ::testing::UnitTest::GetInstance()->current_test_info()->name();
617 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
618 ThreadHost::Type::kPlatform |
620 ThreadHost::Type::kUi);
625 NiceMock<MockDelegate> delegate;
627 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
628 EXPECT_CALL(delegate, GetTaskRunners())
629 .WillRepeatedly(ReturnRef(task_runners));
631 auto rasterizer = std::make_unique<Rasterizer>(delegate);
632 auto surface = std::make_unique<NiceMock<MockSurface>>();
633 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
634 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
636 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
637 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
638 rasterizer->SetExternalViewEmbedder(external_view_embedder);
639 rasterizer->Setup(std::move(
surface));
642 *external_view_embedder,
650 auto pipeline = std::make_shared<FramePipeline>(10);
651 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
652 DrawStatus status = rasterizer->Draw(pipeline);
659TEST(RasterizerTest, drawMultipleViewsWithExternalViewEmbedder) {
660 std::string test_name =
661 ::testing::UnitTest::GetInstance()->current_test_info()->name();
662 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
663 ThreadHost::Type::kPlatform |
665 ThreadHost::Type::kUi);
670 NiceMock<MockDelegate> delegate;
672 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
673 EXPECT_CALL(delegate, GetTaskRunners())
674 .WillRepeatedly(ReturnRef(task_runners));
675 EXPECT_CALL(delegate, OnFrameRasterized(_));
676 auto rasterizer = std::make_unique<Rasterizer>(delegate);
677 auto surface = std::make_unique<NiceMock<MockSurface>>();
678 std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
679 std::make_shared<NiceMock<MockExternalViewEmbedder>>();
680 rasterizer->SetExternalViewEmbedder(external_view_embedder);
681 EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
682 .WillRepeatedly(Return(
false));
683 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(
true));
688 return std::make_unique<SurfaceFrame>(
690 nullptr, framebuffer_info,
694 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
695 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
697 EXPECT_CALL(*external_view_embedder, BeginFrame(
nullptr,
700 EXPECT_CALL(*external_view_embedder,
704 EXPECT_CALL(*external_view_embedder,
705 SubmitFlutterView(0, _, _, _))
707 EXPECT_CALL(*external_view_embedder,
711 EXPECT_CALL(*external_view_embedder,
712 SubmitFlutterView(1, _, _, _))
714 EXPECT_CALL(*external_view_embedder, EndFrame(
false,
718 rasterizer->Setup(std::move(
surface));
721 auto pipeline = std::make_shared<FramePipeline>(10);
722 std::vector<std::unique_ptr<LayerTreeTask>> tasks;
723 tasks.push_back(std::make_unique<LayerTreeTask>(
724 0, std::make_unique<LayerTree>(
nullptr,
SkISize()), 1.5));
725 tasks.push_back(std::make_unique<LayerTreeTask>(
726 1, std::make_unique<LayerTree>(
nullptr,
SkISize()), 2.0));
727 auto layer_tree_item = std::make_unique<FrameItem>(
730 pipeline->Produce().Complete(std::move(layer_tree_item));
732 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
733 rasterizer->Draw(pipeline);
740 drawWithGpuEnabledAndSurfaceAllowsDrawingWhenGpuDisabledDoesAcquireFrame) {
741 std::string test_name =
742 ::testing::UnitTest::GetInstance()->current_test_info()->name();
743 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
744 ThreadHost::Type::kPlatform |
746 ThreadHost::Type::kUi);
751 NiceMock<MockDelegate> delegate;
753 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
754 EXPECT_CALL(delegate, GetTaskRunners())
755 .WillRepeatedly(ReturnRef(task_runners));
756 EXPECT_CALL(delegate, OnFrameRasterized(_));
758 auto rasterizer = std::make_unique<Rasterizer>(delegate);
759 auto surface = std::make_unique<NiceMock<MockSurface>>();
760 auto is_gpu_disabled_sync_switch =
761 std::make_shared<const fml::SyncSwitch>(
false);
765 auto surface_frame = std::make_unique<SurfaceFrame>(
767 nullptr, framebuffer_info,
770 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(
true));
771 ON_CALL(delegate, GetIsGpuDisabledSyncSwitch())
772 .WillByDefault(Return(is_gpu_disabled_sync_switch));
773 EXPECT_CALL(delegate, GetIsGpuDisabledSyncSwitch()).Times(0);
775 .WillOnce(Return(ByMove(std::move(surface_frame))));
776 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
777 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
779 rasterizer->Setup(std::move(
surface));
782 auto pipeline = std::make_shared<FramePipeline>(10);
783 auto layer_tree = std::make_unique<LayerTree>(
785 auto layer_tree_item = std::make_unique<FrameItem>(
790 pipeline->Produce().Complete(std::move(layer_tree_item));
792 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
793 rasterizer->Draw(pipeline);
801 drawWithGpuDisabledAndSurfaceAllowsDrawingWhenGpuDisabledDoesAcquireFrame) {
802 std::string test_name =
803 ::testing::UnitTest::GetInstance()->current_test_info()->name();
804 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
805 ThreadHost::Type::kPlatform |
807 ThreadHost::Type::kUi);
812 NiceMock<MockDelegate> delegate;
814 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
815 EXPECT_CALL(delegate, GetTaskRunners())
816 .WillRepeatedly(ReturnRef(task_runners));
817 EXPECT_CALL(delegate, OnFrameRasterized(_));
818 auto rasterizer = std::make_unique<Rasterizer>(delegate);
819 auto surface = std::make_unique<NiceMock<MockSurface>>();
820 auto is_gpu_disabled_sync_switch =
821 std::make_shared<const fml::SyncSwitch>(
true);
826 auto surface_frame = std::make_unique<SurfaceFrame>(
828 nullptr, framebuffer_info,
831 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(
true));
832 ON_CALL(delegate, GetIsGpuDisabledSyncSwitch())
833 .WillByDefault(Return(is_gpu_disabled_sync_switch));
834 EXPECT_CALL(delegate, GetIsGpuDisabledSyncSwitch()).Times(0);
836 .WillOnce(Return(ByMove(std::move(surface_frame))));
837 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
838 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
840 rasterizer->Setup(std::move(
surface));
843 auto pipeline = std::make_shared<FramePipeline>(10);
844 auto layer_tree = std::make_unique<LayerTree>(
846 auto layer_tree_item = std::make_unique<FrameItem>(
851 pipeline->Produce().Complete(std::move(layer_tree_item));
853 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
854 DrawStatus status = rasterizer->Draw(pipeline);
863 drawWithGpuEnabledAndSurfaceDisallowsDrawingWhenGpuDisabledDoesAcquireFrame) {
864 std::string test_name =
865 ::testing::UnitTest::GetInstance()->current_test_info()->name();
866 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
867 ThreadHost::Type::kPlatform |
869 ThreadHost::Type::kUi);
874 NiceMock<MockDelegate> delegate;
876 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
877 EXPECT_CALL(delegate, GetTaskRunners())
878 .WillRepeatedly(ReturnRef(task_runners));
879 EXPECT_CALL(delegate, OnFrameRasterized(_));
880 auto rasterizer = std::make_unique<Rasterizer>(delegate);
881 auto surface = std::make_unique<NiceMock<MockSurface>>();
882 auto is_gpu_disabled_sync_switch =
883 std::make_shared<const fml::SyncSwitch>(
false);
888 auto surface_frame = std::make_unique<SurfaceFrame>(
890 nullptr, framebuffer_info,
893 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(
false));
894 EXPECT_CALL(delegate, GetIsGpuDisabledSyncSwitch())
895 .WillOnce(Return(is_gpu_disabled_sync_switch));
897 .WillOnce(Return(ByMove(std::move(surface_frame))));
898 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
899 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
901 rasterizer->Setup(std::move(
surface));
904 auto pipeline = std::make_shared<FramePipeline>(10);
905 auto layer_tree = std::make_unique<LayerTree>(
907 auto layer_tree_item = std::make_unique<FrameItem>(
912 pipeline->Produce().Complete(std::move(layer_tree_item));
914 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
915 DrawStatus status = rasterizer->Draw(pipeline);
924 drawWithGpuDisabledAndSurfaceDisallowsDrawingWhenGpuDisabledDoesntAcquireFrame) {
925 std::string test_name =
926 ::testing::UnitTest::GetInstance()->current_test_info()->name();
927 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
928 ThreadHost::Type::kPlatform |
930 ThreadHost::Type::kUi);
935 NiceMock<MockDelegate> delegate;
937 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
938 EXPECT_CALL(delegate, GetTaskRunners())
939 .WillRepeatedly(ReturnRef(task_runners));
940 EXPECT_CALL(delegate, OnFrameRasterized(_)).Times(0);
941 auto rasterizer = std::make_unique<Rasterizer>(delegate);
942 auto surface = std::make_unique<NiceMock<MockSurface>>();
943 auto is_gpu_disabled_sync_switch =
944 std::make_shared<const fml::SyncSwitch>(
true);
949 auto surface_frame = std::make_unique<SurfaceFrame>(
951 nullptr, framebuffer_info,
954 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillOnce(Return(
false));
955 EXPECT_CALL(delegate, GetIsGpuDisabledSyncSwitch())
956 .WillOnce(Return(is_gpu_disabled_sync_switch));
958 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
959 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
961 rasterizer->Setup(std::move(
surface));
964 auto pipeline = std::make_shared<FramePipeline>(10);
965 auto layer_tree = std::make_unique<LayerTree>(
967 auto layer_tree_item = std::make_unique<FrameItem>(
972 pipeline->Produce().Complete(std::move(layer_tree_item));
974 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
975 DrawStatus status = rasterizer->Draw(pipeline);
984 FrameTimingRecorderShouldStartRecordingRasterTimeBeforeSurfaceAcquireFrame) {
985 std::string test_name =
986 ::testing::UnitTest::GetInstance()->current_test_info()->name();
987 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
988 ThreadHost::Type::kPlatform |
990 ThreadHost::Type::kUi);
995 NiceMock<MockDelegate> delegate;
997 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
998 EXPECT_CALL(delegate, GetTaskRunners())
999 .WillRepeatedly(ReturnRef(task_runners));
1000 EXPECT_CALL(delegate, OnFrameRasterized(_))
1008 auto rasterizer = std::make_unique<Rasterizer>(delegate);
1009 auto surface = std::make_unique<NiceMock<MockSurface>>();
1010 auto is_gpu_disabled_sync_switch =
1011 std::make_shared<const fml::SyncSwitch>(
false);
1012 ON_CALL(delegate, GetIsGpuDisabledSyncSwitch())
1013 .WillByDefault(Return(is_gpu_disabled_sync_switch));
1017 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
1018 .WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(
true))));
1019 rasterizer->Setup(std::move(
surface));
1022 auto pipeline = std::make_shared<FramePipeline>(10);
1023 auto layer_tree = std::make_unique<LayerTree>(
1025 auto layer_tree_item = std::make_unique<FrameItem>(
1030 pipeline->Produce().Complete(std::move(layer_tree_item));
1032 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
1033 DrawStatus status = rasterizer->Draw(pipeline);
1043 drawLayerTreeWithCorrectFrameTimingWhenPipelineIsMoreAvailable) {
1044 std::string test_name =
1045 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1046 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
1047 ThreadHost::Type::kPlatform |
1049 ThreadHost::Type::kUi);
1053 thread_host.
io_thread->GetTaskRunner());
1054 NiceMock<MockDelegate> delegate;
1056 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
1057 ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
1060 std::unique_ptr<Rasterizer> rasterizer;
1062 rasterizer = std::make_unique<Rasterizer>(delegate);
1067 auto surface = std::make_unique<NiceMock<MockSurface>>();
1068 EXPECT_CALL(*
surface, AllowsDrawingWhenGpuDisabled())
1069 .WillRepeatedly(Return(
true));
1074 return std::make_unique<SurfaceFrame>(
1076 nullptr, framebuffer_info,
1081 ON_CALL(*
surface, MakeRenderContextCurrent())
1083 [] {
return std::make_unique<GLContextDefaultResult>(
true); }));
1088 std::vector<fml::TimePoint> timestamps = {first_timestamp, second_timestamp};
1089 int frame_rasterized_count = 0;
1090 EXPECT_CALL(delegate, OnFrameRasterized(_))
1092 .WillRepeatedly([&](
const FrameTiming& frame_timing) {
1093 EXPECT_EQ(timestamps[frame_rasterized_count],
1095 EXPECT_EQ(timestamps[frame_rasterized_count],
1097 EXPECT_EQ(timestamps[frame_rasterized_count],
1099 frame_rasterized_count++;
1104 rasterizer->Setup(std::move(
surface));
1105 auto pipeline = std::make_shared<FramePipeline>(10);
1106 for (
int i = 0;
i < 2;
i++) {
1107 auto layer_tree = std::make_unique<LayerTree>(
1109 auto layer_tree_item = std::make_unique<FrameItem>(
1114 pipeline->Produce().Complete(std::move(layer_tree_item));
1116 EXPECT_EQ(
result.is_first_item,
i == 0);
1120 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
1121 rasterizer->Draw(pipeline);
1123 count_down_latch.
Wait();
1131TEST(RasterizerTest, TeardownFreesResourceCache) {
1132 std::string test_name =
1133 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1134 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
1135 ThreadHost::Type::kPlatform |
1137 ThreadHost::Type::kUi);
1141 thread_host.
io_thread->GetTaskRunner());
1143 NiceMock<MockDelegate> delegate;
1145 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
1146 EXPECT_CALL(delegate, GetTaskRunners())
1147 .WillRepeatedly(ReturnRef(task_runners));
1149 auto rasterizer = std::make_unique<Rasterizer>(delegate);
1150 auto surface = std::make_unique<NiceMock<MockSurface>>();
1152 context->setResourceCacheLimit(0);
1154 EXPECT_CALL(*
surface, MakeRenderContextCurrent())
1155 .WillRepeatedly([]() -> std::unique_ptr<GLContextResult> {
1156 return std::make_unique<GLContextDefaultResult>(
true);
1160 rasterizer->Setup(std::move(
surface));
1161 EXPECT_EQ(context->getResourceCacheLimit(), 0ul);
1163 rasterizer->SetResourceCacheMaxBytes(10000000,
false);
1164 EXPECT_EQ(context->getResourceCacheLimit(), 10000000ul);
1165 EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
1169 context->getResourceCacheUsage(&
count, &bytes);
1170 EXPECT_EQ(bytes, 0ul);
1179 sk_surface->getCanvas()->drawPaint(
paint);
1182 EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
1186 context->getResourceCacheUsage(&
count, &bytes);
1187 EXPECT_GT(bytes, 0ul);
1188 EXPECT_GT(context->getResourceCachePurgeableBytes(), 0ul);
1190 rasterizer->Teardown();
1191 EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
1194TEST(RasterizerTest, TeardownNoSurface) {
1195 std::string test_name =
1196 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1197 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
1198 ThreadHost::Type::kPlatform |
1200 ThreadHost::Type::kUi);
1204 thread_host.
io_thread->GetTaskRunner());
1206 NiceMock<MockDelegate> delegate;
1208 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
1209 EXPECT_CALL(delegate, GetTaskRunners())
1210 .WillRepeatedly(ReturnRef(task_runners));
1212 auto rasterizer = std::make_unique<Rasterizer>(delegate);
1215 rasterizer->Teardown();
1218TEST(RasterizerTest, presentationTimeSetWhenVsyncTargetInFuture) {
1219 GTEST_SKIP() <<
"eglPresentationTime is disabled due to "
1220 "https://github.com/flutter/flutter/issues/112503";
1222 std::string test_name =
1223 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1224 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
1226 ThreadHost::Type::kIo | ThreadHost::Type::kUi);
1230 thread_host.
io_thread->GetTaskRunner());
1232 NiceMock<MockDelegate> delegate;
1234 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
1235 ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
1238 std::unique_ptr<Rasterizer> rasterizer;
1240 rasterizer = std::make_unique<Rasterizer>(delegate);
1247 auto second_timestamp = first_timestamp + millis_16;
1248 std::vector<fml::TimePoint> timestamps = {first_timestamp, second_timestamp};
1250 int frames_submitted = 0;
1252 auto surface = std::make_unique<MockSurface>();
1253 ON_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillByDefault(Return(
true));
1258 return std::make_unique<SurfaceFrame>(
1259 nullptr, framebuffer_info,
1262 const auto pres_time = *
frame.submit_info().presentation_time;
1263 const auto diff = pres_time - first_timestamp;
1264 int num_frames_submitted = frames_submitted++;
1265 EXPECT_EQ(diff.ToMilliseconds(),
1266 num_frames_submitted * millis_16.ToMilliseconds());
1273 ON_CALL(*
surface, MakeRenderContextCurrent())
1275 [] {
return std::make_unique<GLContextDefaultResult>(
true); }));
1278 rasterizer->Setup(std::move(
surface));
1279 auto pipeline = std::make_shared<FramePipeline>(10);
1280 for (
int i = 0;
i < 2;
i++) {
1281 auto layer_tree = std::make_unique<LayerTree>(
1283 auto layer_tree_item = std::make_unique<FrameItem>(
1288 pipeline->Produce().Complete(std::move(layer_tree_item));
1290 EXPECT_EQ(
result.is_first_item,
i == 0);
1294 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
1295 rasterizer->Draw(pipeline);
1298 submit_latch.
Wait();
1307TEST(RasterizerTest, presentationTimeNotSetWhenVsyncTargetInPast) {
1308 GTEST_SKIP() <<
"eglPresentationTime is disabled due to "
1309 "https://github.com/flutter/flutter/issues/112503";
1311 std::string test_name =
1312 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1313 ThreadHost thread_host(
"io.flutter.test." + test_name +
".",
1315 ThreadHost::Type::kIo | ThreadHost::Type::kUi);
1319 thread_host.
io_thread->GetTaskRunner());
1321 NiceMock<MockDelegate> delegate;
1323 ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(
settings));
1324 ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
1327 std::unique_ptr<Rasterizer> rasterizer;
1329 rasterizer = std::make_unique<Rasterizer>(delegate);
1338 auto surface = std::make_unique<MockSurface>();
1339 ON_CALL(*
surface, AllowsDrawingWhenGpuDisabled()).WillByDefault(Return(
true));
1344 return std::make_unique<SurfaceFrame>(
1345 nullptr, framebuffer_info,
1348 const std::optional<fml::TimePoint> pres_time =
1349 frame.submit_info().presentation_time;
1350 EXPECT_EQ(pres_time, std::nullopt);
1357 ON_CALL(*
surface, MakeRenderContextCurrent())
1359 [] {
return std::make_unique<GLContextDefaultResult>(
true); }));
1362 rasterizer->Setup(std::move(
surface));
1363 auto pipeline = std::make_shared<FramePipeline>(10);
1364 auto layer_tree = std::make_unique<LayerTree>(
1366 auto layer_tree_item = std::make_unique<FrameItem>(
1371 pipeline->Produce().Complete(std::move(layer_tree_item));
1373 EXPECT_EQ(
result.is_first_item,
true);
1374 ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(
false));
1375 rasterizer->Draw(pipeline);
1378 submit_latch.
Wait();
static sk_sp< GrDirectContext > MakeMock(const GrMockOptions *, const GrContextOptions &)
static sk_sp< SkColorSpace > MakeSRGB()
Developer-facing API for rendering anything within the engine.
fml::TimePoint Get(Phase phase) const
static void EnsureInitializedForCurrentThread()
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
static constexpr TimeDelta FromSecondsF(double seconds)
static constexpr TimeDelta FromMilliseconds(int64_t millis)
@ kRaster
Suitable for thread which raster data.
const EmbeddedViewParams * params
SK_API GrDirectContext * GetContext(const SkImage *src)
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)
ObjectPtr Invoke(const Library &lib, const char *name)
static std::unique_ptr< FrameTimingsRecorder > CreateFinishedBuildRecorder(fml::TimePoint timestamp)
TEST(FrameTimingsRecorderTest, RecordVsync)
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
std::chrono::duration< double, std::milli > Milliseconds
flutter::DlCanvas DlCanvas
static constexpr SkISize Make(int32_t w, int32_t h)
static SkImageInfo MakeN32Premul(int width, int height)
The collection of all the threads used by the engine.
std::unique_ptr< fml::Thread > io_thread
std::unique_ptr< fml::Thread > platform_thread
std::unique_ptr< fml::Thread > raster_thread
std::unique_ptr< fml::Thread > ui_thread
#define EXPECT_TRUE(handle)