From 5ddcb61cc66a82bb2e96a43091578bd84aac7c88 Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Fri, 11 Sep 2020 18:54:05 +0200 Subject: [PATCH 1/2] Add optional DiscardCallback parameter to Rasterizer::Draw If this callback returns true for given layer tree, the layer tree will be discarded and not rasterized This is useful after the resize event, when layer tree with certain size is expected, but there is a tree with previous size still in pipeline --- shell/common/rasterizer.cc | 9 +++++++-- shell/common/rasterizer.h | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 36eee5e174d06..55bd1d2fd1782 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -156,7 +156,8 @@ void Rasterizer::DrawLastLayerTree() { DrawToSurface(*last_layer_tree_); } -void Rasterizer::Draw(fml::RefPtr> pipeline) { +void Rasterizer::Draw(fml::RefPtr> pipeline, + DiscardCallback discardCallback) { TRACE_EVENT0("flutter", "GPURasterizer::Draw"); if (raster_thread_merger_ && !raster_thread_merger_->IsOnRasterizingThread()) { @@ -170,7 +171,11 @@ void Rasterizer::Draw(fml::RefPtr> pipeline) { RasterStatus raster_status = RasterStatus::kFailed; Pipeline::Consumer consumer = [&](std::unique_ptr layer_tree) { - raster_status = DoDraw(std::move(layer_tree)); + if (discardCallback && discardCallback(*layer_tree.get())) { + raster_status = RasterStatus::kSuccess; + } else { + raster_status = DoDraw(std::move(layer_tree)); + } }; PipelineConsumeResult consume_result = pipeline->Consume(consumer); diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index e400ff16b2e23..0aee48dc6b39c 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -204,6 +204,8 @@ class Rasterizer final : public SnapshotDelegate { /// flutter::TextureRegistry* GetTextureRegistry(); + using DiscardCallback = std::function; + //---------------------------------------------------------------------------- /// @brief Takes the next item from the layer tree pipeline and executes /// the raster thread frame workload for that pipeline item to @@ -232,8 +234,11 @@ class Rasterizer final : public SnapshotDelegate { /// /// @param[in] pipeline The layer tree pipeline to take the next layer tree /// to render from. + /// @param[in] discardCallback if specified and returns true, the layer tree + // is discarded instead of being rendered /// - void Draw(fml::RefPtr> pipeline); + void Draw(fml::RefPtr> pipeline, + DiscardCallback discardCallback = nullptr); //---------------------------------------------------------------------------- /// @brief The type of the screenshot to obtain of the previously From 0b5d49999ed260396405ca6c30f82e4037fe713b Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Fri, 11 Sep 2020 19:11:00 +0200 Subject: [PATCH 2/2] Do not rasterzize wrong size layer tree after viewport metrics change --- shell/common/shell.cc | 28 ++++++++++++++++++---------- shell/common/shell.h | 4 ++++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/shell/common/shell.cc b/shell/common/shell.cc index ff576e4358c2b..e3eaac2fc1050 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -822,13 +822,8 @@ void Shell::OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) { // This is the formula Android uses. // https://android.googlesource.com/platform/frameworks/base/+/master/libs/hwui/renderthread/CacheManager.cpp#41 - size_t max_bytes = metrics.physical_width * metrics.physical_height * 12 * 4; - task_runners_.GetRasterTaskRunner()->PostTask( - [rasterizer = rasterizer_->GetWeakPtr(), max_bytes] { - if (rasterizer) { - rasterizer->SetResourceCacheMaxBytes(max_bytes, false); - } - }); + resource_cache_max_bytes_update_ = + metrics.physical_width * metrics.physical_height * 12 * 4; task_runners_.GetUITaskRunner()->PostTask( [engine = engine_->GetWeakPtr(), metrics]() { @@ -836,6 +831,10 @@ void Shell::OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) { engine->SetViewportMetrics(metrics); } }); + + std::scoped_lock lock(resize_mutex_); + expected_frame_size_ = + SkISize::Make(metrics.physical_width, metrics.physical_height); } // |PlatformView::Delegate| @@ -1025,13 +1024,22 @@ void Shell::OnAnimatorDraw(fml::RefPtr> pipeline, } } + size_t max_bytes = resource_cache_max_bytes_update_; + resource_cache_max_bytes_update_ = 0; + task_runners_.GetRasterTaskRunner()->PostTask( [&waiting_for_first_frame = waiting_for_first_frame_, &waiting_for_first_frame_condition = waiting_for_first_frame_condition_, - rasterizer = rasterizer_->GetWeakPtr(), - pipeline = std::move(pipeline)]() { + rasterizer = rasterizer_->GetWeakPtr(), max_bytes, + pipeline = std::move(pipeline), this]() { if (rasterizer) { - rasterizer->Draw(pipeline); + if (max_bytes != 0) { + rasterizer->SetResourceCacheMaxBytes(max_bytes, false); + } + rasterizer->Draw(pipeline, [this](flutter::LayerTree& tree) { + std::scoped_lock lock(resize_mutex_); + return tree.frame_size() != expected_frame_size_; + }); if (waiting_for_first_frame.load()) { waiting_for_first_frame.store(false); diff --git a/shell/common/shell.h b/shell/common/shell.h index c8dad14e02193..4f3722343f14c 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -425,6 +425,10 @@ class Shell final : public PlatformView::Delegate, // and read from the raster thread. std::atomic display_refresh_rate_ = 0.0f; + std::mutex resize_mutex_; + SkISize expected_frame_size_ = SkISize::MakeEmpty(); + size_t resource_cache_max_bytes_update_ = 0; + // How many frames have been timed since last report. size_t UnreportedFramesCount() const;