Created
September 28, 2018 01:46
-
-
Save chinmaygarde/482cc515e918c9017c431dc0a0097cce to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc | |
| index 29f9c93b5..80eda152d 100644 | |
| --- a/flow/layers/layer_tree.cc | |
| +++ b/flow/layers/layer_tree.cc | |
| @@ -6,7 +6,9 @@ | |
| #include "flutter/flow/layers/layer.h" | |
| #include "flutter/fml/trace_event.h" | |
| +#include "third_party/skia/include/core/SkImageInfo.h" | |
| #include "third_party/skia/include/core/SkPictureRecorder.h" | |
| +#include "third_party/skia/include/core/SkSurface.h" | |
| namespace flow { | |
| @@ -74,16 +76,40 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame) const { | |
| root_layer_->Paint(context); | |
| } | |
| -sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) { | |
| - TRACE_EVENT0("flutter", "LayerTree::Flatten"); | |
| +sk_sp<SkImage> LayerTree::ToRasterImage(GrContext* context, | |
| + const SkISize& image_size) const { | |
| + TRACE_EVENT0("flutter", "LayerTree::ToRasterImage"); | |
| - SkPictureRecorder recorder; | |
| - auto canvas = recorder.beginRecording(bounds); | |
| + // Step 1: Allocate the render target. If there is valid GrContext, it must | |
| + // not be a raster context as that will not have access to texture backed | |
| + // images referenced in the layer tree hierarchy. | |
| + | |
| + auto image_info = SkImageInfo::MakeN32Premul(image_size); | |
| + | |
| + sk_sp<SkSurface> surface; | |
| + | |
| + if (context) { | |
| + surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, image_info); | |
| + } | |
| + | |
| + if (!surface) { | |
| + // This should only happen on test contexts. In such cases, there aren't | |
| + // going to be texture backed images anyway. | |
| + surface = SkSurface::MakeRaster(image_info); | |
| + } | |
| + | |
| + if (!surface) { | |
| + return nullptr; | |
| + } | |
| + | |
| + auto canvas = surface->getCanvas(); | |
| if (!canvas) { | |
| return nullptr; | |
| } | |
| + // Step 2: Write into the render target. | |
| + | |
| Layer::PrerollContext preroll_context{ | |
| nullptr, // raster_cache (don't consult the cache) | |
| nullptr, // gr_context (used for the raster cache) | |
| @@ -94,6 +120,7 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) { | |
| const Stopwatch unused_stopwatch; | |
| TextureRegistry unused_texture_registry; | |
| SkMatrix root_surface_transformation; | |
| + | |
| // No root surface transformation. So assume identity. | |
| root_surface_transformation.reset(); | |
| @@ -115,7 +142,16 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) { | |
| } | |
| } | |
| - return recorder.finishRecordingAsPicture(); | |
| + // Step 3: Snapshot the render target and transfer the device snapshot to the | |
| + // host for a raster image. | |
| + | |
| + auto snapshot = surface->makeImageSnapshot(); | |
| + | |
| + if (!snapshot) { | |
| + return nullptr; | |
| + } | |
| + | |
| + return snapshot->makeRasterImage(); | |
| } | |
| } // namespace flow | |
| diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h | |
| index bae883ca2..d5af8f85d 100644 | |
| --- a/flow/layers/layer_tree.h | |
| +++ b/flow/layers/layer_tree.h | |
| @@ -34,7 +34,8 @@ class LayerTree { | |
| void Paint(CompositorContext::ScopedFrame& frame) const; | |
| - sk_sp<SkPicture> Flatten(const SkRect& bounds); | |
| + sk_sp<SkImage> ToRasterImage(GrContext* context, | |
| + const SkISize& image_size) const; | |
| Layer* root_layer() const { return root_layer_.get(); } | |
| diff --git a/lib/ui/compositing/scene.cc b/lib/ui/compositing/scene.cc | |
| index 2863f5307..d05bceba1 100644 | |
| --- a/lib/ui/compositing/scene.cc | |
| +++ b/lib/ui/compositing/scene.cc | |
| @@ -7,8 +7,6 @@ | |
| #include "flutter/fml/make_copyable.h" | |
| #include "flutter/fml/trace_event.h" | |
| #include "flutter/lib/ui/painting/image.h" | |
| -#include "third_party/skia/include/core/SkImageInfo.h" | |
| -#include "third_party/skia/include/core/SkSurface.h" | |
| #include "third_party/tonic/converter/dart_converter.h" | |
| #include "third_party/tonic/dart_args.h" | |
| #include "third_party/tonic/dart_binding_macros.h" | |
| @@ -38,13 +36,16 @@ fml::RefPtr<Scene> Scene::create(std::unique_ptr<flow::Layer> rootLayer, | |
| Scene::Scene(std::unique_ptr<flow::Layer> rootLayer, | |
| uint32_t rasterizerTracingThreshold, | |
| bool checkerboardRasterCacheImages, | |
| - bool checkerboardOffscreenLayers) | |
| - : m_layerTree(new flow::LayerTree()) { | |
| - m_layerTree->set_root_layer(std::move(rootLayer)); | |
| - m_layerTree->set_rasterizer_tracing_threshold(rasterizerTracingThreshold); | |
| - m_layerTree->set_checkerboard_raster_cache_images( | |
| + bool checkerboardOffscreenLayers) { | |
| + auto layer_tree = std::make_unique<flow::LayerTree>(); | |
| + | |
| + layer_tree->set_root_layer(std::move(rootLayer)); | |
| + layer_tree->set_rasterizer_tracing_threshold(rasterizerTracingThreshold); | |
| + layer_tree->set_checkerboard_raster_cache_images( | |
| checkerboardRasterCacheImages); | |
| - m_layerTree->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers); | |
| + layer_tree->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers); | |
| + | |
| + m_layerTree = std::move(layer_tree); | |
| } | |
| Scene::~Scene() {} | |
| @@ -53,50 +54,9 @@ void Scene::dispose() { | |
| ClearDartWrapper(); | |
| } | |
| -static sk_sp<SkImage> CreateSceneSnapshot(GrContext* context, | |
| - sk_sp<SkPicture> picture, | |
| - const SkSize& size) { | |
| - TRACE_EVENT0("flutter", "CreateSceneSnapshot"); | |
| - auto image_info = | |
| - SkImageInfo::MakeN32Premul(SkISize::Make(size.width(), size.height())); | |
| - | |
| - sk_sp<SkSurface> surface; | |
| - | |
| - if (context) { | |
| - surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, image_info); | |
| - } | |
| - | |
| - if (!surface) { | |
| - surface = SkSurface::MakeRaster(image_info); | |
| - } | |
| - | |
| - if (!surface) { | |
| - return nullptr; | |
| - } | |
| - | |
| - auto canvas = surface->getCanvas(); | |
| - | |
| - if (!canvas) { | |
| - return nullptr; | |
| - } | |
| - | |
| - if (picture) { | |
| - canvas->drawPicture(picture.get()); | |
| - } | |
| - | |
| - auto snapshot = surface->makeImageSnapshot(); | |
| - | |
| - if (!snapshot) { | |
| - return nullptr; | |
| - } | |
| - | |
| - return snapshot->makeRasterImage(); | |
| -} | |
| - | |
| Dart_Handle Scene::toImage(uint32_t width, | |
| uint32_t height, | |
| Dart_Handle raw_image_callback) { | |
| - TRACE_EVENT0("flutter", "Scene::toImage"); | |
| if (Dart_IsNull(raw_image_callback) || !Dart_IsClosure(raw_image_callback)) { | |
| return tonic::ToDart("Image callback was invalid"); | |
| } | |
| @@ -109,40 +69,37 @@ Dart_Handle Scene::toImage(uint32_t width, | |
| return tonic::ToDart("Image dimensions for scene were invalid."); | |
| } | |
| - auto dart_state = UIDartState::Current(); | |
| - | |
| - auto image_callback = std::make_unique<tonic::DartPersistentValue>( | |
| - dart_state, raw_image_callback); | |
| + auto layer_tree = accessLayerTree(); | |
| - // We can't create an image on this task runner because we don't have a | |
| - // graphics context. Even if we did, it would be slow anyway. Also, this | |
| - // thread owns the sole reference to the layer tree. So we flatten the layer | |
| - // tree into a picture and use that as the thread transport mechanism. | |
| - | |
| - auto bounds_size = SkSize::Make(width, height); | |
| - auto picture = m_layerTree->Flatten(SkRect::MakeSize(bounds_size)); | |
| - if (!picture) { | |
| + if (!layer_tree) { | |
| // Already in Dart scope. | |
| - return tonic::ToDart("Could not flatten scene into a layer tree."); | |
| + return tonic::ToDart("Could not access the layer tree."); | |
| } | |
| + auto dart_state = UIDartState::Current(); | |
| + | |
| + auto image_callback = std::make_unique<tonic::DartPersistentValue>( | |
| + dart_state, raw_image_callback); | |
| + auto bounds_size = SkISize::Make(width, height); | |
| auto resource_context = dart_state->GetResourceContext(); | |
| auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner(); | |
| auto unref_queue = dart_state->GetSkiaUnrefQueue(); | |
| - // The picture has been prepared on the UI thread. | |
| + // This call is made on the UI thread. We need to hop to the IO thread (which | |
| + // has a GrContext) to snapshot the image before hopping back to the UI thread | |
| + // to complete the callback. | |
| dart_state->GetTaskRunners().GetIOTaskRunner()->PostTask( | |
| - fml::MakeCopyable([picture = std::move(picture), // | |
| + fml::MakeCopyable([layer_tree = std::move(layer_tree), // | |
| bounds_size, // | |
| resource_context = std::move(resource_context), // | |
| ui_task_runner = std::move(ui_task_runner), // | |
| image_callback = std::move(image_callback), // | |
| unref_queue = std::move(unref_queue) // | |
| ]() mutable { | |
| - // Snapshot the picture on the IO thread that contains an optional | |
| + // Rasterizer the layer tree on the IO thread that contains an optional | |
| // GrContext. | |
| - auto image = CreateSceneSnapshot(resource_context.get(), | |
| - std::move(picture), bounds_size); | |
| + auto image = | |
| + layer_tree->ToRasterImage(resource_context.get(), bounds_size); | |
| // Send the image back to the UI thread for submission back to the | |
| // framework. | |
| @@ -175,8 +132,8 @@ Dart_Handle Scene::toImage(uint32_t width, | |
| return Dart_Null(); | |
| } | |
| -std::unique_ptr<flow::LayerTree> Scene::takeLayerTree() { | |
| - return std::move(m_layerTree); | |
| +std::shared_ptr<flow::LayerTree> Scene::accessLayerTree() const { | |
| + return m_layerTree; | |
| } | |
| } // namespace blink | |
| diff --git a/lib/ui/compositing/scene.h b/lib/ui/compositing/scene.h | |
| index 09f6a3e0d..a166f5526 100644 | |
| --- a/lib/ui/compositing/scene.h | |
| +++ b/lib/ui/compositing/scene.h | |
| @@ -29,7 +29,7 @@ class Scene : public RefCountedDartWrappable<Scene> { | |
| bool checkerboardRasterCacheImages, | |
| bool checkerboardOffscreenLayers); | |
| - std::unique_ptr<flow::LayerTree> takeLayerTree(); | |
| + std::shared_ptr<flow::LayerTree> accessLayerTree() const; | |
| Dart_Handle toImage(uint32_t width, | |
| uint32_t height, | |
| @@ -45,7 +45,7 @@ class Scene : public RefCountedDartWrappable<Scene> { | |
| bool checkerboardRasterCacheImages, | |
| bool checkerboardOffscreenLayers); | |
| - std::unique_ptr<flow::LayerTree> m_layerTree; | |
| + std::shared_ptr<flow::LayerTree> m_layerTree; | |
| }; | |
| } // namespace blink | |
| diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc | |
| index d3509ed08..f66bc3774 100644 | |
| --- a/runtime/runtime_controller.cc | |
| +++ b/runtime/runtime_controller.cc | |
| @@ -252,7 +252,7 @@ void RuntimeController::ScheduleFrame() { | |
| } | |
| void RuntimeController::Render(Scene* scene) { | |
| - client_.Render(scene->takeLayerTree()); | |
| + client_.Render(scene->accessLayerTree()); | |
| } | |
| void RuntimeController::UpdateSemantics(SemanticsUpdate* update) { | |
| diff --git a/runtime/runtime_delegate.h b/runtime/runtime_delegate.h | |
| index 2a9bded0a..a13f09844 100644 | |
| --- a/runtime/runtime_delegate.h | |
| +++ b/runtime/runtime_delegate.h | |
| @@ -23,7 +23,7 @@ class RuntimeDelegate { | |
| virtual void ScheduleFrame(bool regenerate_layer_tree = true) = 0; | |
| - virtual void Render(std::unique_ptr<flow::LayerTree> layer_tree) = 0; | |
| + virtual void Render(std::shared_ptr<flow::LayerTree> layer_tree) = 0; | |
| virtual void UpdateSemantics( | |
| blink::SemanticsNodeUpdates update, | |
| diff --git a/shell/common/animator.cc b/shell/common/animator.cc | |
| index 727d521b7..f3c7b7ba5 100644 | |
| --- a/shell/common/animator.cc | |
| +++ b/shell/common/animator.cc | |
| @@ -132,7 +132,7 @@ void Animator::BeginFrame(fml::TimePoint frame_start_time, | |
| } | |
| } | |
| -void Animator::Render(std::unique_ptr<flow::LayerTree> layer_tree) { | |
| +void Animator::Render(std::shared_ptr<flow::LayerTree> layer_tree) { | |
| if (dimension_change_pending_ && | |
| layer_tree->frame_size() != last_layer_tree_size_) { | |
| dimension_change_pending_ = false; | |
| @@ -146,7 +146,7 @@ void Animator::Render(std::unique_ptr<flow::LayerTree> layer_tree) { | |
| } | |
| // Commit the pending continuation. | |
| - producer_continuation_.Complete(std::move(layer_tree)); | |
| + producer_continuation_.Complete(layer_tree); | |
| delegate_.OnAnimatorDraw(layer_tree_pipeline_); | |
| } | |
| diff --git a/shell/common/animator.h b/shell/common/animator.h | |
| index 470f04b54..ab11ac5aa 100644 | |
| --- a/shell/common/animator.h | |
| +++ b/shell/common/animator.h | |
| @@ -38,7 +38,7 @@ class Animator final { | |
| void RequestFrame(bool regenerate_layer_tree = true); | |
| - void Render(std::unique_ptr<flow::LayerTree> layer_tree); | |
| + void Render(std::shared_ptr<flow::LayerTree> layer_tree); | |
| void Start(); | |
| diff --git a/shell/common/engine.cc b/shell/common/engine.cc | |
| index 2a9ee3f2c..254495624 100644 | |
| --- a/shell/common/engine.cc | |
| +++ b/shell/common/engine.cc | |
| @@ -379,7 +379,7 @@ void Engine::ScheduleFrame(bool regenerate_layer_tree) { | |
| animator_->RequestFrame(regenerate_layer_tree); | |
| } | |
| -void Engine::Render(std::unique_ptr<flow::LayerTree> layer_tree) { | |
| +void Engine::Render(std::shared_ptr<flow::LayerTree> layer_tree) { | |
| if (!layer_tree) | |
| return; | |
| diff --git a/shell/common/engine.h b/shell/common/engine.h | |
| index 06436ce36..f55a1c31e 100644 | |
| --- a/shell/common/engine.h | |
| +++ b/shell/common/engine.h | |
| @@ -129,7 +129,7 @@ class Engine final : public blink::RuntimeDelegate { | |
| std::string DefaultRouteName() override; | |
| // |blink::RuntimeDelegate| | |
| - void Render(std::unique_ptr<flow::LayerTree> layer_tree) override; | |
| + void Render(std::shared_ptr<flow::LayerTree> layer_tree) override; | |
| // |blink::RuntimeDelegate| | |
| void UpdateSemantics( | |
| diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc | |
| index 6f08b2afd..21a1b1547 100644 | |
| --- a/shell/common/rasterizer.cc | |
| +++ b/shell/common/rasterizer.cc | |
| @@ -89,7 +89,7 @@ void Rasterizer::Draw( | |
| } | |
| } | |
| -void Rasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) { | |
| +void Rasterizer::DoDraw(std::shared_ptr<flow::LayerTree> layer_tree) { | |
| if (!layer_tree || !surface_) { | |
| return; | |
| } | |
| diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h | |
| index 1d3c03d89..08d8a108c 100644 | |
| --- a/shell/common/rasterizer.h | |
| +++ b/shell/common/rasterizer.h | |
| @@ -71,11 +71,11 @@ class Rasterizer final { | |
| blink::TaskRunners task_runners_; | |
| std::unique_ptr<Surface> surface_; | |
| std::unique_ptr<flow::CompositorContext> compositor_context_; | |
| - std::unique_ptr<flow::LayerTree> last_layer_tree_; | |
| + std::shared_ptr<flow::LayerTree> last_layer_tree_; | |
| fml::closure next_frame_callback_; | |
| fml::WeakPtrFactory<Rasterizer> weak_factory_; | |
| - void DoDraw(std::unique_ptr<flow::LayerTree> layer_tree); | |
| + void DoDraw(std::shared_ptr<flow::LayerTree> layer_tree); | |
| bool DrawToSurface(flow::LayerTree& layer_tree); | |
| diff --git a/synchronization/pipeline.h b/synchronization/pipeline.h | |
| index 726adf64d..d8f4dfa1e 100644 | |
| --- a/synchronization/pipeline.h | |
| +++ b/synchronization/pipeline.h | |
| @@ -29,7 +29,7 @@ template <class R> | |
| class Pipeline : public fml::RefCountedThreadSafe<Pipeline<R>> { | |
| public: | |
| using Resource = R; | |
| - using ResourcePtr = std::unique_ptr<Resource>; | |
| + using ResourcePtr = std::shared_ptr<Resource>; | |
| /// Denotes a spot in the pipeline reserved for the producer to finish | |
| /// preparing a completed pipeline resource. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment