Include TextureLayer in contents of toImageSync (#35608)
diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index de7573e..3b4907b 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc
@@ -171,7 +171,10 @@ } } -sk_sp<DisplayList> LayerTree::Flatten(const SkRect& bounds) { +sk_sp<DisplayList> LayerTree::Flatten( + const SkRect& bounds, + std::shared_ptr<TextureRegistry> texture_registry, + GrDirectContext* gr_context) { TRACE_EVENT0("flutter", "LayerTree::Flatten"); DisplayListCanvasRecorder builder(bounds); @@ -179,13 +182,14 @@ MutatorsStack unused_stack; const FixedRefreshRateStopwatch unused_stopwatch; SkMatrix root_surface_transformation; + // No root surface transformation. So assume identity. root_surface_transformation.reset(); PrerollContext preroll_context{ // clang-format off .raster_cache = nullptr, - .gr_context = nullptr, + .gr_context = gr_context, .view_embedder = nullptr, .mutators_stack = unused_stack, .dst_color_space = nullptr, @@ -193,7 +197,7 @@ .surface_needs_readback = false, .raster_time = unused_stopwatch, .ui_time = unused_stopwatch, - .texture_registry = nullptr, + .texture_registry = texture_registry, .checkerboard_offscreen_layers = false, .frame_device_pixel_ratio = device_pixel_ratio_ // clang-format on @@ -209,12 +213,12 @@ // clang-format off .internal_nodes_canvas = &internal_nodes_canvas, .leaf_nodes_canvas = &builder, - .gr_context = nullptr, + .gr_context = gr_context, .dst_color_space = nullptr, .view_embedder = nullptr, .raster_time = unused_stopwatch, .ui_time = unused_stopwatch, - .texture_registry = nullptr, + .texture_registry = texture_registry, .raster_cache = nullptr, .checkerboard_offscreen_layers = false, .frame_device_pixel_ratio = device_pixel_ratio_,
diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index c7daa5f..1675004 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h
@@ -8,6 +8,7 @@ #include <cstdint> #include <memory> +#include "flutter/common/graphics/texture.h" #include "flutter/flow/compositor_context.h" #include "flutter/flow/layers/layer.h" #include "flutter/flow/raster_cache.h" @@ -41,7 +42,10 @@ void Paint(CompositorContext::ScopedFrame& frame, bool ignore_raster_cache = false) const; - sk_sp<DisplayList> Flatten(const SkRect& bounds); + sk_sp<DisplayList> Flatten( + const SkRect& bounds, + std::shared_ptr<TextureRegistry> texture_registry = nullptr, + GrDirectContext* gr_context = nullptr); Layer* root_layer() const { return root_layer_.get(); }
diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index e38066a..843be96 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart
@@ -38,6 +38,7 @@ external String? _toImageSync(int width, int height, _Image outImage); /// Creates a raster image representation of the current state of the scene. + /// /// This is a slow operation that is performed on a background thread. /// /// Callers must dispose the [Image] when they are done with it. If the result
diff --git a/lib/ui/compositing/scene.cc b/lib/ui/compositing/scene.cc index 734a67e..5a8601b 100644 --- a/lib/ui/compositing/scene.cc +++ b/lib/ui/compositing/scene.cc
@@ -5,6 +5,7 @@ #include "flutter/lib/ui/compositing/scene.h" #include "flutter/fml/trace_event.h" +#include "flutter/lib/ui/painting/display_list_deferred_image_gpu.h" #include "flutter/lib/ui/painting/image.h" #include "flutter/lib/ui/painting/picture.h" #include "flutter/lib/ui/ui_dart_state.h" @@ -42,7 +43,7 @@ ->get_window(0) ->viewport_metrics(); - layer_tree_ = std::make_unique<LayerTree>( + layer_tree_ = std::make_shared<LayerTree>( SkISize::Make(viewport_metrics.physical_width, viewport_metrics.physical_height), static_cast<float>(viewport_metrics.device_pixel_ratio)); @@ -69,12 +70,7 @@ return tonic::ToDart("Scene did not contain a layer tree."); } - auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height)); - if (!picture) { - return tonic::ToDart("Could not flatten scene into a layer tree."); - } - - Picture::RasterizeToImageSync(picture, width, height, raw_image_handle); + Scene::RasterizeToImage(width, height, raw_image_handle); return Dart_Null(); } @@ -87,15 +83,32 @@ return tonic::ToDart("Scene did not contain a layer tree."); } - auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height)); - if (!picture) { - return tonic::ToDart("Could not flatten scene into a layer tree."); - } - - return Picture::RasterizeToImage(picture, width, height, raw_image_callback); + return Picture::RasterizeLayerTreeToImage(std::move(layer_tree_), width, + height, raw_image_callback); } -std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree() { +void Scene::RasterizeToImage(uint32_t width, + uint32_t height, + Dart_Handle raw_image_handle) { + auto* dart_state = UIDartState::Current(); + if (!dart_state) { + return; + } + auto unref_queue = dart_state->GetSkiaUnrefQueue(); + auto snapshot_delegate = dart_state->GetSnapshotDelegate(); + auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner(); + + auto image = CanvasImage::Create(); + const SkImageInfo image_info = SkImageInfo::Make( + width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType); + auto dl_image = DlDeferredImageGPU::MakeFromLayerTree( + image_info, std::move(layer_tree_), std::move(snapshot_delegate), + std::move(raster_task_runner), std::move(unref_queue)); + image->set_image(dl_image); + image->AssociateWithDartWrapper(raw_image_handle); +} + +std::shared_ptr<flutter::LayerTree> Scene::takeLayerTree() { return std::move(layer_tree_); }
diff --git a/lib/ui/compositing/scene.h b/lib/ui/compositing/scene.h index 1cf95aa..aca7978 100644 --- a/lib/ui/compositing/scene.h +++ b/lib/ui/compositing/scene.h
@@ -26,7 +26,7 @@ bool checkerboardRasterCacheImages, bool checkerboardOffscreenLayers); - std::unique_ptr<flutter::LayerTree> takeLayerTree(); + std::shared_ptr<flutter::LayerTree> takeLayerTree(); Dart_Handle toImageSync(uint32_t width, uint32_t height, @@ -34,17 +34,26 @@ Dart_Handle toImage(uint32_t width, uint32_t height, - Dart_Handle image_callback); + Dart_Handle raw_image_handle); void dispose(); private: - explicit Scene(std::shared_ptr<flutter::Layer> rootLayer, - uint32_t rasterizerTracingThreshold, - bool checkerboardRasterCacheImages, - bool checkerboardOffscreenLayers); + Scene(std::shared_ptr<flutter::Layer> rootLayer, + uint32_t rasterizerTracingThreshold, + bool checkerboardRasterCacheImages, + bool checkerboardOffscreenLayers); - std::unique_ptr<flutter::LayerTree> layer_tree_; + void RasterizeToImage(uint32_t width, + uint32_t height, + Dart_Handle raw_image_handle); + + // This is a shared_ptr to support flattening the layer tree from the UI + // thread onto the raster thread - allowing access to the texture registry + // required to render TextureLayers. + // + // No longer valid after calling `takeLayerTree`. + std::shared_ptr<flutter::LayerTree> layer_tree_; }; } // namespace flutter
diff --git a/lib/ui/painting/display_list_deferred_image_gpu.cc b/lib/ui/painting/display_list_deferred_image_gpu.cc index beeb0cc..14391c2 100644 --- a/lib/ui/painting/display_list_deferred_image_gpu.cc +++ b/lib/ui/painting/display_list_deferred_image_gpu.cc
@@ -22,6 +22,19 @@ raster_task_runner)); } +sk_sp<DlDeferredImageGPU> DlDeferredImageGPU::MakeFromLayerTree( + const SkImageInfo& image_info, + std::shared_ptr<LayerTree> layer_tree, + fml::WeakPtr<SnapshotDelegate> snapshot_delegate, + fml::RefPtr<fml::TaskRunner> raster_task_runner, + fml::RefPtr<SkiaUnrefQueue> unref_queue) { + return sk_sp<DlDeferredImageGPU>(new DlDeferredImageGPU( + ImageWrapper::MakeFromLayerTree( + image_info, std::move(layer_tree), std::move(snapshot_delegate), + raster_task_runner, std::move(unref_queue)), + raster_task_runner)); +} + DlDeferredImageGPU::DlDeferredImageGPU( std::shared_ptr<ImageWrapper> image_wrapper, fml::RefPtr<fml::TaskRunner> raster_task_runner) @@ -92,6 +105,20 @@ return wrapper; } +std::shared_ptr<DlDeferredImageGPU::ImageWrapper> +DlDeferredImageGPU::ImageWrapper::MakeFromLayerTree( + const SkImageInfo& image_info, + std::shared_ptr<LayerTree> layer_tree, + fml::WeakPtr<SnapshotDelegate> snapshot_delegate, + fml::RefPtr<fml::TaskRunner> raster_task_runner, + fml::RefPtr<SkiaUnrefQueue> unref_queue) { + auto wrapper = std::shared_ptr<ImageWrapper>( + new ImageWrapper(image_info, nullptr, std::move(snapshot_delegate), + std::move(raster_task_runner), std::move(unref_queue))); + wrapper->SnapshotDisplayList(std::move(layer_tree)); + return wrapper; +} + DlDeferredImageGPU::ImageWrapper::ImageWrapper( const SkImageInfo& image_info, sk_sp<DisplayList> display_list, @@ -131,9 +158,11 @@ return texture_.isValid(); } -void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList() { +void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList( + std::shared_ptr<LayerTree> layer_tree) { fml::TaskRunner::RunNowOrPostTask( - raster_task_runner_, [weak_this = weak_from_this()]() { + raster_task_runner_, + [weak_this = weak_from_this(), layer_tree = std::move(layer_tree)]() { auto wrapper = weak_this.lock(); if (!wrapper) { return; @@ -142,6 +171,14 @@ if (!snapshot_delegate) { return; } + if (layer_tree) { + auto display_list = + layer_tree->Flatten(SkRect::MakeWH(wrapper->image_info_.width(), + wrapper->image_info_.height()), + snapshot_delegate->GetTextureRegistry(), + snapshot_delegate->GetGrContext()); + wrapper->display_list_ = std::move(display_list); + } auto result = snapshot_delegate->MakeGpuImage(wrapper->display_list_, wrapper->image_info_); if (result->texture.isValid()) {
diff --git a/lib/ui/painting/display_list_deferred_image_gpu.h b/lib/ui/painting/display_list_deferred_image_gpu.h index 429dcd8..5f04eb2 100644 --- a/lib/ui/painting/display_list_deferred_image_gpu.h +++ b/lib/ui/painting/display_list_deferred_image_gpu.h
@@ -11,6 +11,7 @@ #include "flutter/common/graphics/texture.h" #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_image.h" +#include "flutter/flow/layers/layer_tree.h" #include "flutter/flow/skia_gpu_object.h" #include "flutter/fml/macros.h" #include "flutter/fml/memory/weak_ptr.h" @@ -28,6 +29,13 @@ fml::RefPtr<fml::TaskRunner> raster_task_runner, fml::RefPtr<SkiaUnrefQueue> unref_queue); + static sk_sp<DlDeferredImageGPU> MakeFromLayerTree( + const SkImageInfo& image_info, + std::shared_ptr<LayerTree> layer_tree, + fml::WeakPtr<SnapshotDelegate> snapshot_delegate, + fml::RefPtr<fml::TaskRunner> raster_task_runner, + fml::RefPtr<SkiaUnrefQueue> unref_queue); + // |DlImage| ~DlDeferredImageGPU() override; @@ -73,6 +81,13 @@ fml::RefPtr<fml::TaskRunner> raster_task_runner, fml::RefPtr<SkiaUnrefQueue> unref_queue); + static std::shared_ptr<ImageWrapper> MakeFromLayerTree( + const SkImageInfo& image_info, + std::shared_ptr<LayerTree> layer_tree, + fml::WeakPtr<SnapshotDelegate> snapshot_delegate, + fml::RefPtr<fml::TaskRunner> raster_task_runner, + fml::RefPtr<SkiaUnrefQueue> unref_queue); + const SkImageInfo image_info() const { return image_info_; } const GrBackendTexture& texture() const { return texture_; } bool isTextureBacked() const; @@ -103,7 +118,11 @@ fml::RefPtr<fml::TaskRunner> raster_task_runner, fml::RefPtr<SkiaUnrefQueue> unref_queue); - void SnapshotDisplayList(); + // If a layer tree is provided, it will be flattened during the raster + // thread task spwaned by this method. After being flattened into a display + // list, the image wrapper will be updated to hold this display list and the + // layer tree can be dropped. + void SnapshotDisplayList(std::shared_ptr<LayerTree> layer_tree = nullptr); // |ContextListener| void OnGrContextCreated() override;
diff --git a/lib/ui/painting/picture.cc b/lib/ui/painting/picture.cc index 4d5411d..c79c5c0 100644 --- a/lib/ui/painting/picture.cc +++ b/lib/ui/painting/picture.cc
@@ -95,11 +95,21 @@ Dart_Handle raw_image_callback) { return RasterizeToImage( [display_list](SkCanvas* canvas) { display_list->RenderTo(canvas); }, - width, height, raw_image_callback); + nullptr, width, height, raw_image_callback); +} + +Dart_Handle Picture::RasterizeLayerTreeToImage( + std::shared_ptr<LayerTree> layer_tree, + uint32_t width, + uint32_t height, + Dart_Handle raw_image_callback) { + return RasterizeToImage(nullptr, std::move(layer_tree), width, height, + raw_image_callback); } Dart_Handle Picture::RasterizeToImage( std::function<void(SkCanvas*)> draw_callback, + std::shared_ptr<LayerTree> layer_tree, uint32_t width, uint32_t height, Dart_Handle raw_image_callback) { @@ -158,10 +168,25 @@ // Kick things off on the raster rask runner. fml::TaskRunner::RunNowOrPostTask( - raster_task_runner, [ui_task_runner, snapshot_delegate, draw_callback, - picture_bounds, ui_task] { - sk_sp<SkImage> raster_image = snapshot_delegate->MakeRasterSnapshot( - draw_callback, picture_bounds); + raster_task_runner, + [ui_task_runner, snapshot_delegate, draw_callback, picture_bounds, + ui_task, layer_tree = std::move(layer_tree)] { + sk_sp<SkImage> raster_image; + if (layer_tree) { + auto display_list = layer_tree->Flatten( + SkRect::MakeWH(picture_bounds.width(), picture_bounds.height()), + snapshot_delegate->GetTextureRegistry(), + snapshot_delegate->GetGrContext()); + + raster_image = snapshot_delegate->MakeRasterSnapshot( + [display_list](SkCanvas* canvas) { + display_list->RenderTo(canvas); + }, + picture_bounds); + } else { + raster_image = snapshot_delegate->MakeRasterSnapshot(draw_callback, + picture_bounds); + } fml::TaskRunner::RunNowOrPostTask( ui_task_runner,
diff --git a/lib/ui/painting/picture.h b/lib/ui/painting/picture.h index 1cb390a..77fda55 100644 --- a/lib/ui/painting/picture.h +++ b/lib/ui/painting/picture.h
@@ -6,6 +6,7 @@ #define FLUTTER_LIB_UI_PAINTING_PICTURE_H_ #include "flutter/display_list/display_list.h" +#include "flutter/flow/layers/layer_tree.h" #include "flutter/flow/skia_gpu_object.h" #include "flutter/lib/ui/dart_wrapper.h" #include "flutter/lib/ui/painting/image.h" @@ -51,8 +52,19 @@ uint32_t height, Dart_Handle raw_image_callback); + static Dart_Handle RasterizeLayerTreeToImage( + std::shared_ptr<LayerTree> layer_tree, + uint32_t width, + uint32_t height, + Dart_Handle raw_image_callback); + + // Callers may provide either a draw_callback (which should reference a + // display list) or a layer tree. If a layer tree is provided, it will be + // flattened on the raster thread. In this case the draw callback will be + // ignored. static Dart_Handle RasterizeToImage( std::function<void(SkCanvas*)> draw_callback, + std::shared_ptr<LayerTree> layer_tree, uint32_t width, uint32_t height, Dart_Handle raw_image_callback);
diff --git a/lib/ui/snapshot_delegate.h b/lib/ui/snapshot_delegate.h index 4158d28..3b59ffe 100644 --- a/lib/ui/snapshot_delegate.h +++ b/lib/ui/snapshot_delegate.h
@@ -13,6 +13,7 @@ #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/core/SkPromiseImageTexture.h" #include "third_party/skia/include/gpu/GrContextThreadSafeProxy.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { @@ -52,6 +53,8 @@ /// virtual std::shared_ptr<TextureRegistry> GetTextureRegistry() = 0; + virtual GrDirectContext* GetGrContext() = 0; + virtual std::unique_ptr<GpuImageResult> MakeGpuImage( sk_sp<DisplayList> display_list, const SkImageInfo& image_info) = 0;
diff --git a/runtime/runtime_delegate.h b/runtime/runtime_delegate.h index 540e47d..ad68067 100644 --- a/runtime/runtime_delegate.h +++ b/runtime/runtime_delegate.h
@@ -24,7 +24,7 @@ virtual void ScheduleFrame(bool regenerate_layer_tree = true) = 0; - virtual void Render(std::unique_ptr<flutter::LayerTree> layer_tree) = 0; + virtual void Render(std::shared_ptr<flutter::LayerTree> layer_tree) = 0; virtual void UpdateSemantics(SemanticsNodeUpdates update, CustomAccessibilityActionUpdates actions) = 0;
diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 31bd0cd..d8614dc 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc
@@ -144,7 +144,7 @@ } } -void Animator::Render(std::unique_ptr<flutter::LayerTree> layer_tree) { +void Animator::Render(std::shared_ptr<flutter::LayerTree> layer_tree) { has_rendered_ = true; last_layer_tree_size_ = layer_tree->frame_size();
diff --git a/shell/common/animator.h b/shell/common/animator.h index d822935..6550452 100644 --- a/shell/common/animator.h +++ b/shell/common/animator.h
@@ -54,7 +54,7 @@ void RequestFrame(bool regenerate_layer_tree = true); - void Render(std::unique_ptr<flutter::LayerTree> layer_tree); + void Render(std::shared_ptr<flutter::LayerTree> layer_tree); const std::weak_ptr<VsyncWaiter> GetVsyncWaiter() const;
diff --git a/shell/common/animator_unittests.cc b/shell/common/animator_unittests.cc index 628d7eb..91c2bad 100644 --- a/shell/common/animator_unittests.cc +++ b/shell/common/animator_unittests.cc
@@ -157,7 +157,7 @@ [&] { ASSERT_FALSE(delegate.notify_idle_called_); auto layer_tree = - std::make_unique<LayerTree>(SkISize::Make(600, 800), 1.0); + std::make_shared<LayerTree>(SkISize::Make(600, 800), 1.0); animator->Render(std::move(layer_tree)); task_runners.GetPlatformTaskRunner()->PostTask(flush_vsync_task); }, @@ -240,7 +240,7 @@ PostTaskSync(task_runners.GetUITaskRunner(), [&] { auto layer_tree = - std::make_unique<LayerTree>(SkISize::Make(600, 800), 1.0); + std::make_shared<LayerTree>(SkISize::Make(600, 800), 1.0); animator->Render(std::move(layer_tree)); }); }
diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 9a0e5d0..c2cbc9f 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc
@@ -439,7 +439,7 @@ animator_->RequestFrame(regenerate_layer_tree); } -void Engine::Render(std::unique_ptr<flutter::LayerTree> layer_tree) { +void Engine::Render(std::shared_ptr<flutter::LayerTree> layer_tree) { if (!layer_tree) { return; }
diff --git a/shell/common/engine.h b/shell/common/engine.h index 491ec4f..04b968f 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h
@@ -879,7 +879,7 @@ std::string DefaultRouteName() override; // |RuntimeDelegate| - void Render(std::unique_ptr<flutter::LayerTree> layer_tree) override; + void Render(std::shared_ptr<flutter::LayerTree> layer_tree) override; // |RuntimeDelegate| void UpdateSemantics(SemanticsNodeUpdates update,
diff --git a/shell/common/engine_unittests.cc b/shell/common/engine_unittests.cc index 6267494..6dfc93c 100644 --- a/shell/common/engine_unittests.cc +++ b/shell/common/engine_unittests.cc
@@ -48,7 +48,7 @@ public: MOCK_METHOD0(DefaultRouteName, std::string()); MOCK_METHOD1(ScheduleFrame, void(bool)); - MOCK_METHOD1(Render, void(std::unique_ptr<flutter::LayerTree>)); + MOCK_METHOD1(Render, void(std::shared_ptr<flutter::LayerTree>)); MOCK_METHOD2(UpdateSemantics, void(SemanticsNodeUpdates, CustomAccessibilityActionUpdates)); MOCK_METHOD1(HandlePlatformMessage, void(std::unique_ptr<PlatformMessage>));
diff --git a/shell/common/pipeline.h b/shell/common/pipeline.h index 35f90f3..f9546d0 100644 --- a/shell/common/pipeline.h +++ b/shell/common/pipeline.h
@@ -222,11 +222,11 @@ }; struct LayerTreeItem { - LayerTreeItem(std::unique_ptr<LayerTree> layer_tree, + LayerTreeItem(std::shared_ptr<LayerTree> layer_tree, std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) : layer_tree(std::move(layer_tree)), frame_timings_recorder(std::move(frame_timings_recorder)) {} - std::unique_ptr<LayerTree> layer_tree; + std::shared_ptr<LayerTree> layer_tree; std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder; };
diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index d3ecb11..f9d10fd 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc
@@ -145,6 +145,10 @@ return compositor_context_->texture_registry(); } +GrDirectContext* Rasterizer::GetGrContext() { + return surface_ ? surface_->GetContext() : nullptr; +} + flutter::LayerTree* Rasterizer::GetLastLayerTree() { return last_layer_tree_.get(); } @@ -181,7 +185,7 @@ RasterStatus raster_status = RasterStatus::kFailed; LayerTreePipeline::Consumer consumer = [&](std::unique_ptr<LayerTreeItem> item) { - std::unique_ptr<LayerTree> layer_tree = std::move(item->layer_tree); + std::shared_ptr<LayerTree> layer_tree = std::move(item->layer_tree); std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder = std::move(item->frame_timings_recorder); if (discard_callback(*layer_tree.get())) { @@ -488,7 +492,7 @@ RasterStatus Rasterizer::DoDraw( std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder, - std::unique_ptr<flutter::LayerTree> layer_tree) { + std::shared_ptr<flutter::LayerTree> layer_tree) { TRACE_EVENT_WITH_FRAME_NUMBER(frame_timings_recorder, "flutter", "Rasterizer::DoDraw"); FML_DCHECK(delegate_.GetTaskRunners()
diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 2f90ed5..7052b66 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h
@@ -26,6 +26,7 @@ #include "flutter/shell/common/pipeline.h" #include "flutter/shell/common/snapshot_surface_producer.h" #include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" namespace flutter { @@ -213,6 +214,8 @@ std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder); // |SnapshotDelegate| + GrDirectContext* GetGrContext() override; + std::shared_ptr<flutter::TextureRegistry> GetTextureRegistry() override; using LayerTreeDiscardCallback = std::function<bool(flutter::LayerTree&)>; @@ -496,7 +499,7 @@ RasterStatus DoDraw( std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder, - std::unique_ptr<flutter::LayerTree> layer_tree); + std::shared_ptr<flutter::LayerTree> layer_tree); RasterStatus DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree); @@ -515,11 +518,11 @@ std::unique_ptr<SnapshotSurfaceProducer> snapshot_surface_producer_; std::unique_ptr<flutter::CompositorContext> compositor_context_; // This is the last successfully rasterized layer tree. - std::unique_ptr<flutter::LayerTree> last_layer_tree_; + std::shared_ptr<flutter::LayerTree> last_layer_tree_; // Set when we need attempt to rasterize the layer tree again. This layer_tree // has not successfully rasterized. This can happen due to the change in the // thread configuration. This will be inserted to the front of the pipeline. - std::unique_ptr<flutter::LayerTree> resubmitted_layer_tree_; + std::shared_ptr<flutter::LayerTree> resubmitted_layer_tree_; std::unique_ptr<FrameTimingsRecorder> resubmitted_recorder_; fml::closure next_frame_callback_; bool user_override_resource_cache_bytes_;
diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 4523284..af14fcc 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc
@@ -176,7 +176,7 @@ fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -238,7 +238,7 @@ fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -306,7 +306,7 @@ rasterizer->Setup(std::move(surface)); auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -376,7 +376,7 @@ rasterizer->Setup(std::move(surface)); auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -423,7 +423,7 @@ fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -476,7 +476,7 @@ fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -573,7 +573,7 @@ fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -627,7 +627,7 @@ fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -681,7 +681,7 @@ fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -734,7 +734,7 @@ fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder()); @@ -811,7 +811,7 @@ auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); for (int i = 0; i < 2; i++) { auto layer_tree = - std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder(timestamps[i])); @@ -972,7 +972,7 @@ auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); for (int i = 0; i < 2; i++) { auto layer_tree = - std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder(timestamps[i])); @@ -1045,7 +1045,7 @@ thread_host.raster_thread->GetTaskRunner()->PostTask([&] { rasterizer->Setup(std::move(surface)); auto pipeline = std::make_shared<LayerTreePipeline>(/*depth=*/10); - auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(), + auto layer_tree = std::make_shared<LayerTree>(/*frame_size=*/SkISize(), /*device_pixel_ratio=*/2.0f); auto layer_tree_item = std::make_unique<LayerTreeItem>( std::move(layer_tree), CreateFinishedBuildRecorder(first_timestamp));
diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index 27f6b0f..eca3450 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc
@@ -197,7 +197,7 @@ fml::WeakPtr<RuntimeDelegate> runtime_delegate = shell->weak_engine_; shell->GetTaskRunners().GetUITaskRunner()->PostTask( [&latch, runtime_delegate, &builder, viewport_metrics]() { - auto layer_tree = std::make_unique<LayerTree>( + auto layer_tree = std::make_shared<LayerTree>( SkISize::Make(viewport_metrics.physical_width, viewport_metrics.physical_height), static_cast<float>(viewport_metrics.device_pixel_ratio));
diff --git a/testing/dart/compositing_test.dart b/testing/dart/compositing_test.dart index 99c95cf..cb65eb0 100644 --- a/testing/dart/compositing_test.dart +++ b/testing/dart/compositing_test.dart
@@ -36,6 +36,28 @@ expect(data.buffer.asUint8List()[3], 0xFF); }); + test('Scene.toImageSync succeeds with texture layer', () async { + final SceneBuilder builder = SceneBuilder(); + builder.pushOffset(10, 10); + builder.addTexture(0, width: 10, height: 10); + + final Scene scene = builder.build(); + final Image image = scene.toImageSync(10, 10); + scene.dispose(); + + expect(image.width, 10); + expect(image.height, 10); + + final ByteData? data = await image.toByteData(); + + expect(data, isNotNull); + expect(data!.lengthInBytes, 10 * 10 * 4); + expect(data.buffer.asUint8List()[0], 0); + expect(data.buffer.asUint8List()[1], 0); + expect(data.buffer.asUint8List()[2], 0); + expect(data.buffer.asUint8List()[3], 0); + }); + test('addPicture with disposed picture does not crash', () { bool assertsEnabled = false; assert(() {