From c92613bc491ed902c686e307221958d200ac747b Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Thu, 17 Oct 2019 14:07:51 -0700 Subject: [PATCH] Re-land "Custom compositor layers must take into account the device pixel ratio." This reverts commit 6c2381da6070f9e96825841e77e9ffeb376d6aa9 and applies iOS fixes. --- flow/embedded_views.h | 4 +- flow/layers/layer_tree.h | 7 + shell/common/engine.cc | 1 + shell/common/rasterizer.cc | 3 +- shell/platform/darwin/ios/ios_surface_gl.h | 2 +- shell/platform/darwin/ios/ios_surface_gl.mm | 2 +- shell/platform/darwin/ios/ios_surface_metal.h | 2 +- .../platform/darwin/ios/ios_surface_metal.mm | 4 +- .../darwin/ios/ios_surface_software.h | 2 +- .../darwin/ios/ios_surface_software.mm | 4 +- shell/platform/embedder/embedder.cc | 6 + .../embedder_external_view_embedder.cc | 42 ++-- .../embedder_external_view_embedder.h | 5 +- shell/platform/embedder/fixtures/main.dart | 13 ++ .../embedder/tests/embedder_unittests.cc | 198 +++++++++++++++++- 15 files changed, 273 insertions(+), 22 deletions(-) diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 8a9d2fdc5..7f59c005c 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -208,7 +208,9 @@ class ExternalViewEmbedder { // sets the stage for the next pre-roll. virtual void CancelFrame() = 0; - virtual void BeginFrame(SkISize frame_size, GrContext* context) = 0; + virtual void BeginFrame(SkISize frame_size, + GrContext* context, + double device_pixel_ratio) = 0; virtual void PrerollCompositeEmbeddedView( int view_id, diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index e61f48b97..124b8a85d 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -71,8 +71,15 @@ class LayerTree { checkerboard_offscreen_layers_ = checkerboard; } + void set_device_pixel_ratio(double device_pixel_ratio) { + device_pixel_ratio_ = device_pixel_ratio; + } + + double device_pixel_ratio() const { return device_pixel_ratio_; } + private: SkISize frame_size_ = SkISize::MakeEmpty(); // Physical pixels. + double device_pixel_ratio_ = 1.0; std::shared_ptr root_layer_; fml::TimePoint build_start_; fml::TimePoint build_finish_; diff --git a/shell/common/engine.cc b/shell/common/engine.cc index b3c889d6b..fd424a369 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -438,6 +438,7 @@ void Engine::Render(std::unique_ptr layer_tree) { return; layer_tree->set_frame_size(frame_size); + layer_tree->set_device_pixel_ratio(viewport_metrics_.device_pixel_ratio); animator_->Render(std::move(layer_tree)); } diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index b52a8abdb..930cc6850 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -230,7 +230,8 @@ RasterStatus Rasterizer::DrawToSurface(flutter::LayerTree& layer_tree) { if (external_view_embedder != nullptr) { external_view_embedder->BeginFrame(layer_tree.frame_size(), - surface_->GetContext()); + surface_->GetContext(), + layer_tree.device_pixel_ratio()); embedder_root_surface = external_view_embedder->GetRootSurface(); } diff --git a/shell/platform/darwin/ios/ios_surface_gl.h b/shell/platform/darwin/ios/ios_surface_gl.h index 964cc7adb..95350aefc 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.h +++ b/shell/platform/darwin/ios/ios_surface_gl.h @@ -60,7 +60,7 @@ class IOSSurfaceGL final : public IOSSurface, void CancelFrame() override; // |ExternalViewEmbedder| - void BeginFrame(SkISize frame_size, GrContext* context) override; + void BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) override; // |ExternalViewEmbedder| void PrerollCompositeEmbeddedView(int view_id, diff --git a/shell/platform/darwin/ios/ios_surface_gl.mm b/shell/platform/darwin/ios/ios_surface_gl.mm index 9e838e200..11e83fe35 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.mm +++ b/shell/platform/darwin/ios/ios_surface_gl.mm @@ -100,7 +100,7 @@ void IOSSurfaceGL::CancelFrame() { } // |ExternalViewEmbedder| -void IOSSurfaceGL::BeginFrame(SkISize frame_size, GrContext* context) { +void IOSSurfaceGL::BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) { FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); FML_CHECK(platform_views_controller != nullptr); platform_views_controller->SetFrameSize(frame_size); diff --git a/shell/platform/darwin/ios/ios_surface_metal.h b/shell/platform/darwin/ios/ios_surface_metal.h index f43cada80..230bd5b4b 100644 --- a/shell/platform/darwin/ios/ios_surface_metal.h +++ b/shell/platform/darwin/ios/ios_surface_metal.h @@ -48,7 +48,7 @@ class IOSSurfaceMetal final : public IOSSurface, void CancelFrame() override; // |ExternalViewEmbedder| - void BeginFrame(SkISize frame_size, GrContext* context) override; + void BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) override; // |ExternalViewEmbedder| void PrerollCompositeEmbeddedView(int view_id, diff --git a/shell/platform/darwin/ios/ios_surface_metal.mm b/shell/platform/darwin/ios/ios_surface_metal.mm index eb129c96e..0a75c3ec5 100644 --- a/shell/platform/darwin/ios/ios_surface_metal.mm +++ b/shell/platform/darwin/ios/ios_surface_metal.mm @@ -61,7 +61,9 @@ void IOSSurfaceMetal::CancelFrame() { [CATransaction commit]; } -void IOSSurfaceMetal::BeginFrame(SkISize frame_size, GrContext* context) { +void IOSSurfaceMetal::BeginFrame(SkISize frame_size, + GrContext* context, + double device_pixel_ratio) { FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); FML_CHECK(platform_views_controller != nullptr); platform_views_controller->SetFrameSize(frame_size); diff --git a/shell/platform/darwin/ios/ios_surface_software.h b/shell/platform/darwin/ios/ios_surface_software.h index d2ff61efd..3b4fa2aa9 100644 --- a/shell/platform/darwin/ios/ios_surface_software.h +++ b/shell/platform/darwin/ios/ios_surface_software.h @@ -52,7 +52,7 @@ class IOSSurfaceSoftware final : public IOSSurface, void CancelFrame() override; // |ExternalViewEmbedder| - void BeginFrame(SkISize frame_size, GrContext* context) override; + void BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) override; // |ExternalViewEmbedder| void PrerollCompositeEmbeddedView(int view_id, diff --git a/shell/platform/darwin/ios/ios_surface_software.mm b/shell/platform/darwin/ios/ios_surface_software.mm index 4566bbf3f..efc19cbc1 100644 --- a/shell/platform/darwin/ios/ios_surface_software.mm +++ b/shell/platform/darwin/ios/ios_surface_software.mm @@ -150,7 +150,9 @@ void IOSSurfaceSoftware::CancelFrame() { } // |ExternalViewEmbedder| -void IOSSurfaceSoftware::BeginFrame(SkISize frame_size, GrContext* context) { +void IOSSurfaceSoftware::BeginFrame(SkISize frame_size, + GrContext* context, + double device_pixel_ratio) { FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); FML_CHECK(platform_views_controller != nullptr); platform_views_controller->SetFrameSize(frame_size); diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index afbebe5d6..2dfc70201 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -984,6 +984,12 @@ FlutterEngineResult FlutterEngineSendWindowMetricsEvent( metrics.physical_height = SAFE_ACCESS(flutter_metrics, height, 0.0); metrics.device_pixel_ratio = SAFE_ACCESS(flutter_metrics, pixel_ratio, 1.0); + if (metrics.device_pixel_ratio <= 0.0) { + FML_LOG(ERROR) << "Device pixel ratio invalid: " + << metrics.device_pixel_ratio; + return LOG_EMBEDDER_ERROR(kInvalidArguments); + } + return reinterpret_cast(engine)->SetViewportMetrics( std::move(metrics)) ? kSuccess diff --git a/shell/platform/embedder/embedder_external_view_embedder.cc b/shell/platform/embedder/embedder_external_view_embedder.cc index 0ef658454..3232070a8 100644 --- a/shell/platform/embedder/embedder_external_view_embedder.cc +++ b/shell/platform/embedder/embedder_external_view_embedder.cc @@ -67,9 +67,12 @@ static SkISize TransformedSurfaceSize(const SkISize& size, // |ExternalViewEmbedder| void EmbedderExternalViewEmbedder::BeginFrame(SkISize frame_size, - GrContext* context) { + GrContext* context, + double device_pixel_ratio) { Reset(); + pending_frame_size_ = frame_size; + pending_device_pixel_ratio_ = device_pixel_ratio; pending_surface_transformation_ = GetSurfaceTransformation(); const auto surface_size = TransformedSurfaceSize( @@ -155,7 +158,8 @@ SkCanvas* EmbedderExternalViewEmbedder::CompositeEmbeddedView(int view_id) { static FlutterLayer MakeBackingStoreLayer( const SkISize& frame_size, const FlutterBackingStore* store, - const SkMatrix& surface_transformation) { + const SkMatrix& surface_transformation, + double device_pixel_ratio) { FlutterLayer layer = {}; layer.struct_size = sizeof(layer); @@ -166,7 +170,9 @@ static FlutterLayer MakeBackingStoreLayer( SkRect::MakeWH(frame_size.width(), frame_size.height()); const auto transformed_layer_bounds = - surface_transformation.mapRect(layer_bounds); + SkMatrix::Concat(surface_transformation, + SkMatrix::MakeScale(device_pixel_ratio)) + .mapRect(layer_bounds); layer.offset.x = transformed_layer_bounds.x(); layer.offset.y = transformed_layer_bounds.y(); @@ -190,7 +196,8 @@ static FlutterPlatformView MakePlatformView( static FlutterLayer MakePlatformViewLayer( const EmbeddedViewParams& params, const FlutterPlatformView& platform_view, - const SkMatrix& surface_transformation) { + const SkMatrix& surface_transformation, + double device_pixel_ratio) { FlutterLayer layer = {}; layer.struct_size = sizeof(layer); @@ -204,7 +211,9 @@ static FlutterLayer MakePlatformViewLayer( ); const auto transformed_layer_bounds = - surface_transformation.mapRect(layer_bounds); + SkMatrix::Concat(surface_transformation, + SkMatrix::MakeScale(device_pixel_ratio)) + .mapRect(layer_bounds); layer.offset.x = transformed_layer_bounds.x(); layer.offset.y = transformed_layer_bounds.y(); @@ -235,8 +244,11 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) { { // The root surface is expressed as a layer. presented_layers.push_back(MakeBackingStoreLayer( - pending_frame_size_, root_render_target_->GetBackingStore(), - pending_surface_transformation_)); + pending_frame_size_, // frame size + root_render_target_->GetBackingStore(), // backing store + pending_surface_transformation_, // surface transformation + pending_device_pixel_ratio_ // device pixel ratio + )); } const auto surface_size = TransformedSurfaceSize( @@ -262,9 +274,12 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) { // The layers presented to the embedder will contain a back pointer to this // struct. It is safe to deallocate when the embedder callback is done. presented_platform_views[view_id] = MakePlatformView(view_id); - presented_layers.push_back( - MakePlatformViewLayer(params, presented_platform_views.at(view_id), - pending_surface_transformation_)); + presented_layers.push_back(MakePlatformViewLayer( + params, // embedded view params + presented_platform_views.at(view_id), // platform view + pending_surface_transformation_, // surface transformation + pending_device_pixel_ratio_ // device pixel ratio + )); if (!pending_canvas_spies_.at(view_id)->DidDrawIntoCanvas()) { // Nothing was drawn into the overlay canvas, we don't need to composite @@ -312,8 +327,11 @@ bool EmbedderExternalViewEmbedder::SubmitFrame(GrContext* context) { // Indicate a layer for the backing store containing contents rendered by // Flutter. presented_layers.push_back(MakeBackingStoreLayer( - pending_frame_size_, render_target->GetBackingStore(), - pending_surface_transformation_)); + pending_frame_size_, // frame size + render_target->GetBackingStore(), // backing store + pending_surface_transformation_, // surface transformation + pending_device_pixel_ratio_ // device pixel ratio + )); } { diff --git a/shell/platform/embedder/embedder_external_view_embedder.h b/shell/platform/embedder/embedder_external_view_embedder.h index 65b001cee..042b17031 100644 --- a/shell/platform/embedder/embedder_external_view_embedder.h +++ b/shell/platform/embedder/embedder_external_view_embedder.h @@ -73,7 +73,9 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder { void CancelFrame() override; // |ExternalViewEmbedder| - void BeginFrame(SkISize frame_size, GrContext* context) override; + void BeginFrame(SkISize frame_size, + GrContext* context, + double device_pixel_ratio) override; // |ExternalViewEmbedder| void PrerollCompositeEmbeddedView( @@ -127,6 +129,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder { RegistryKey::Equal>; SkISize pending_frame_size_ = SkISize::Make(0, 0); + double pending_device_pixel_ratio_ = 1.0; SkMatrix pending_surface_transformation_; std::map> pending_recorders_; diff --git a/shell/platform/embedder/fixtures/main.dart b/shell/platform/embedder/fixtures/main.dart index 045d69cbd..67a546ad4 100644 --- a/shell/platform/embedder/fixtures/main.dart +++ b/shell/platform/embedder/fixtures/main.dart @@ -430,3 +430,16 @@ void verify_b141980393() { }; window.scheduleFrame(); } + +@pragma('vm:entry-point') +void can_display_platform_view_with_pixel_ratio() { + window.onBeginFrame = (Duration duration) { + SceneBuilder builder = SceneBuilder(); + builder.pushOffset(0.0, 20.0); + builder.addPlatformView(42, width: 400.0, height: 280.0); + builder.addPicture(Offset(0.0, 0.0), CreateSimplePicture()); + builder.pop(); + window.render(builder.build()); + }; + window.scheduleFrame(); +} diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index ad6a80d1e..a6a1d291a 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -652,6 +652,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToOpenGLFramebuffer) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -743,6 +744,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToOpenGLTexture) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -834,6 +836,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderToSoftwareBuffer) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -1125,6 +1128,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderKnownScene) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -1302,6 +1306,7 @@ TEST_F(EmbedderTest, event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -1422,6 +1427,7 @@ TEST_F(EmbedderTest, CustomCompositorMustWorkWithCustomTaskRunner) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -1500,6 +1506,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderWithRootLayerOnly) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -1612,6 +1619,7 @@ TEST_F(EmbedderTest, CompositorMustBeAbleToRenderWithPlatformLayerOnBottom) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -1795,6 +1803,7 @@ TEST_F(EmbedderTest, // Flutter still thinks it is 800 x 600. Only the root surface is rotated. event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -1829,6 +1838,7 @@ TEST_F(EmbedderTest, CanRenderSceneWithoutCustomCompositor) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -1871,6 +1881,7 @@ TEST_F(EmbedderTest, CanRenderSceneWithoutCustomCompositorWithTransformation) { // Flutter still thinks it is 800 x 600. event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -1905,6 +1916,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithoutCompositor) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -1947,6 +1959,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithoutCompositorWithXform) { // Flutter still thinks it is 800 x 600. event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -1981,6 +1994,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositor) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -2024,6 +2038,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositorWithXform) { // Flutter still thinks it is 800 x 600. event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -2134,6 +2149,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositorOnNonRootLayer) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -2253,6 +2269,7 @@ TEST_F(EmbedderTest, CanRenderGradientWithCompositorOnNonRootLayerWithXform) { // Flutter still thinks it is 800 x 600. event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); @@ -2372,7 +2389,7 @@ TEST_F(EmbedderTest, VerifyB141980393) { // achieved via a root surface transformation. event.width = flutter_application_rect.width(); event.height = flutter_application_rect.height(); - + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); ASSERT_TRUE(engine.is_valid()); @@ -2425,6 +2442,7 @@ TEST_F(EmbedderTest, CaDeinitializeAnEngine) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kInvalidArguments); engine.reset(); @@ -2466,6 +2484,7 @@ TEST_F(EmbedderTest, CanCreateEmbedderWithCustomRenderTaskRunner) { event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); task_latch.Wait(); @@ -2525,6 +2544,7 @@ TEST_F(EmbedderTest, event.struct_size = sizeof(event); event.width = 800; event.height = 600; + event.pixel_ratio = 1.0; ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), kSuccess); }); @@ -2555,5 +2575,181 @@ TEST_F(EmbedderTest, } } +TEST_F(EmbedderTest, + CompositorMustBeAbleToRenderKnownScenePixelRatioOnSurface) { + auto& context = GetEmbedderContext(); + + EmbedderConfigBuilder builder(context); + builder.SetOpenGLRendererConfig(SkISize::Make(800, 600)); + builder.SetCompositor(); + builder.SetDartEntrypoint("can_display_platform_view_with_pixel_ratio"); + + context.GetCompositor().SetRenderTargetType( + EmbedderTestCompositor::RenderTargetType::kOpenGLTexture); + + fml::AutoResetWaitableEvent latch; + context.GetCompositor().SetNextPresentCallback( + [&](const FlutterLayer** layers, size_t layers_count) { + ASSERT_EQ(layers_count, 3u); + + // Layer 0 (Root) + { + FlutterBackingStore backing_store = *layers[0]->backing_store; + backing_store.type = kFlutterBackingStoreTypeOpenGL; + backing_store.did_update = true; + backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture; + + FlutterLayer layer = {}; + layer.struct_size = sizeof(layer); + layer.type = kFlutterLayerContentTypeBackingStore; + layer.backing_store = &backing_store; + layer.size = FlutterSizeMake(800.0, 600.0); + layer.offset = FlutterPointMake(0.0, 0.0); + + ASSERT_EQ(*layers[0], layer); + } + + // Layer 1 + { + FlutterPlatformView platform_view = {}; + platform_view.struct_size = sizeof(platform_view); + platform_view.identifier = 42; + + FlutterLayer layer = {}; + layer.struct_size = sizeof(layer); + layer.type = kFlutterLayerContentTypePlatformView; + layer.platform_view = &platform_view; + layer.size = FlutterSizeMake(800.0, 560.0); + layer.offset = FlutterPointMake(0.0, 40.0); + + ASSERT_EQ(*layers[1], layer); + } + + // Layer 2 + { + FlutterBackingStore backing_store = *layers[2]->backing_store; + backing_store.type = kFlutterBackingStoreTypeOpenGL; + backing_store.did_update = true; + backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture; + + FlutterLayer layer = {}; + layer.struct_size = sizeof(layer); + layer.type = kFlutterLayerContentTypeBackingStore; + layer.backing_store = &backing_store; + layer.size = FlutterSizeMake(800.0, 600.0); + layer.offset = FlutterPointMake(0.0, 0.0); + + ASSERT_EQ(*layers[2], layer); + } + + latch.Signal(); + }); + + auto engine = builder.LaunchEngine(); + + // Send a window metrics events so frames may be scheduled. + FlutterWindowMetricsEvent event = {}; + event.struct_size = sizeof(event); + event.width = 400; + event.height = 300; + event.pixel_ratio = 2.0; + ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), + kSuccess); + ASSERT_TRUE(engine.is_valid()); + + latch.Wait(); +} + +TEST_F( + EmbedderTest, + CompositorMustBeAbleToRenderKnownScenePixelRatioOnSurfaceWithRootSurfaceXformation) { + auto& context = GetEmbedderContext(); + + EmbedderConfigBuilder builder(context); + builder.SetOpenGLRendererConfig(SkISize::Make(600, 800)); + builder.SetCompositor(); + builder.SetDartEntrypoint("can_display_platform_view_with_pixel_ratio"); + + context.GetCompositor().SetRenderTargetType( + EmbedderTestCompositor::RenderTargetType::kOpenGLTexture); + + const auto root_surface_transformation = + SkMatrix().preTranslate(0, 800).preRotate(-90, 0, 0); + + context.SetRootSurfaceTransformation(root_surface_transformation); + + fml::AutoResetWaitableEvent latch; + context.GetCompositor().SetNextPresentCallback( + [&](const FlutterLayer** layers, size_t layers_count) { + ASSERT_EQ(layers_count, 3u); + + // Layer 0 (Root) + { + FlutterBackingStore backing_store = *layers[0]->backing_store; + backing_store.type = kFlutterBackingStoreTypeOpenGL; + backing_store.did_update = true; + backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture; + + FlutterLayer layer = {}; + layer.struct_size = sizeof(layer); + layer.type = kFlutterLayerContentTypeBackingStore; + layer.backing_store = &backing_store; + layer.size = FlutterSizeMake(600.0, 800.0); + layer.offset = FlutterPointMake(0.0, 0.0); + + ASSERT_EQ(*layers[0], layer); + } + + // Layer 1 + { + FlutterPlatformView platform_view = {}; + platform_view.struct_size = sizeof(platform_view); + platform_view.identifier = 42; + + FlutterLayer layer = {}; + layer.struct_size = sizeof(layer); + layer.type = kFlutterLayerContentTypePlatformView; + layer.platform_view = &platform_view; + layer.size = FlutterSizeMake(560.0, 800.0); + layer.offset = FlutterPointMake(40.0, 0.0); + + ASSERT_EQ(*layers[1], layer); + } + + // Layer 2 + { + FlutterBackingStore backing_store = *layers[2]->backing_store; + backing_store.type = kFlutterBackingStoreTypeOpenGL; + backing_store.did_update = true; + backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture; + + FlutterLayer layer = {}; + layer.struct_size = sizeof(layer); + layer.type = kFlutterLayerContentTypeBackingStore; + layer.backing_store = &backing_store; + layer.size = FlutterSizeMake(600.0, 800.0); + layer.offset = FlutterPointMake(0.0, 0.0); + + ASSERT_EQ(*layers[2], layer); + } + + latch.Signal(); + }); + + auto engine = builder.LaunchEngine(); + + // Send a window metrics events so frames may be scheduled. + FlutterWindowMetricsEvent event = {}; + event.struct_size = sizeof(event); + event.width = 400; + event.height = 300; + event.pixel_ratio = 2.0; + ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), + kSuccess); + ASSERT_TRUE(engine.is_valid()); + + latch.Wait(); +} + } // namespace testing } // namespace flutter -- GitLab