diff --git a/engine/src/flutter/flow/layers/layer_tree.cc b/engine/src/flutter/flow/layers/layer_tree.cc index b031ebf8cb8..f0e37c9bed5 100644 --- a/engine/src/flutter/flow/layers/layer_tree.cc +++ b/engine/src/flutter/flow/layers/layer_tree.cc @@ -27,6 +27,12 @@ void LayerTree::RecordBuildTime(fml::TimePoint start) { void LayerTree::Preroll(CompositorContext::ScopedFrame& frame, bool ignore_raster_cache) { TRACE_EVENT0("flutter", "LayerTree::Preroll"); + + if (!root_layer_) { + FML_LOG(ERROR) << "The scene did not specify any layers."; + return; + } + SkColorSpace* color_space = frame.canvas() ? frame.canvas()->imageInfo().colorSpace() : nullptr; frame.context().raster_cache().SetCheckboardCacheImages( @@ -75,6 +81,12 @@ void LayerTree::UpdateScene(SceneUpdateContext& context, void LayerTree::Paint(CompositorContext::ScopedFrame& frame, bool ignore_raster_cache) const { TRACE_EVENT0("flutter", "LayerTree::Paint"); + + if (!root_layer_) { + FML_LOG(ERROR) << "The scene did not specify any layers to paint."; + return; + } + SkISize canvas_size = frame.canvas()->getBaseLayerSize(); SkNWayCanvas internal_nodes_canvas(canvas_size.width(), canvas_size.height()); internal_nodes_canvas.addCanvas(frame.canvas()); diff --git a/engine/src/flutter/shell/platform/embedder/fixtures/main.dart b/engine/src/flutter/shell/platform/embedder/fixtures/main.dart index 5e8b0e2c6dc..d7dd20d7295 100644 --- a/engine/src/flutter/shell/platform/embedder/fixtures/main.dart +++ b/engine/src/flutter/shell/platform/embedder/fixtures/main.dart @@ -600,3 +600,23 @@ void platform_view_mutators_with_pixel_ratio() { }; window.scheduleFrame(); } + +@pragma('vm:entry-point') +void empty_scene() { + window.onBeginFrame = (Duration duration) { + window.render(SceneBuilder().build()); + signalNativeTest(); + }; + window.scheduleFrame(); +} + +@pragma('vm:entry-point') +void scene_with_no_container() { + window.onBeginFrame = (Duration duration) { + SceneBuilder builder = SceneBuilder(); + builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(400.0, 300.0))); + window.render(builder.build()); + signalNativeTest(); + }; + window.scheduleFrame(); +} diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc b/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc index fddca5e997b..47f86c281e4 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc @@ -3499,5 +3499,57 @@ TEST_F(EmbedderTest, latch.Wait(); } +TEST_F(EmbedderTest, EmptySceneIsAcceptable) { + auto& context = GetEmbedderContext(); + + EmbedderConfigBuilder builder(context); + builder.SetOpenGLRendererConfig(SkISize::Make(800, 600)); + builder.SetCompositor(); + builder.SetDartEntrypoint("empty_scene"); + fml::AutoResetWaitableEvent latch; + context.AddNativeCallback( + "SignalNativeTest", + CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { latch.Signal(); })); + + auto engine = builder.LaunchEngine(); + + ASSERT_TRUE(engine.is_valid()); + + FlutterWindowMetricsEvent event = {}; + event.struct_size = sizeof(event); + event.width = 800; + event.height = 600; + event.pixel_ratio = 1.0; + ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), + kSuccess); + latch.Wait(); +} + +TEST_F(EmbedderTest, SceneWithNoRootContainerIsAcceptable) { + auto& context = GetEmbedderContext(); + + EmbedderConfigBuilder builder(context); + builder.SetOpenGLRendererConfig(SkISize::Make(800, 600)); + builder.SetCompositor(); + builder.SetDartEntrypoint("scene_with_no_container"); + fml::AutoResetWaitableEvent latch; + context.AddNativeCallback( + "SignalNativeTest", + CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { latch.Signal(); })); + + auto engine = builder.LaunchEngine(); + + ASSERT_TRUE(engine.is_valid()); + + FlutterWindowMetricsEvent event = {}; + event.struct_size = sizeof(event); + event.width = 800; + event.height = 600; + event.pixel_ratio = 1.0; + ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), + kSuccess); + latch.Wait(); +} + } // namespace testing } // namespace flutter