44
55#include " flutter/flow/compositor_context.h"
66
7+ #include < optional>
78#include " flutter/flow/layers/layer_tree.h"
89#include " third_party/skia/include/core/SkCanvas.h"
910
1011namespace flutter {
1112
13+ std::optional<SkRect> FrameDamage::ComputeClipRect (
14+ flutter::LayerTree& layer_tree) {
15+ if (layer_tree.root_layer ()) {
16+ PaintRegionMap empty_paint_region_map;
17+ DiffContext context (layer_tree.frame_size (),
18+ layer_tree.device_pixel_ratio (),
19+ layer_tree.paint_region_map (),
20+ prev_layer_tree_ ? prev_layer_tree_->paint_region_map ()
21+ : empty_paint_region_map);
22+ context.PushCullRect (SkRect::MakeIWH (layer_tree.frame_size ().width (),
23+ layer_tree.frame_size ().height ()));
24+ {
25+ DiffContext::AutoSubtreeRestore subtree (&context);
26+ const Layer* prev_root_layer = nullptr ;
27+ if (!prev_layer_tree_ ||
28+ prev_layer_tree_->frame_size () != layer_tree.frame_size ()) {
29+ // If there is no previous layer tree assume the entire frame must be
30+ // repainted.
31+ context.MarkSubtreeDirty (SkRect::MakeIWH (
32+ layer_tree.frame_size ().width (), layer_tree.frame_size ().height ()));
33+ } else {
34+ prev_root_layer = prev_layer_tree_->root_layer ();
35+ }
36+ layer_tree.root_layer ()->Diff (&context, prev_root_layer);
37+ }
38+
39+ damage_ = context.ComputeDamage (additional_damage_);
40+ return SkRect::Make (damage_->buffer_damage );
41+ } else {
42+ return std::nullopt ;
43+ }
44+ }
45+
1246CompositorContext::CompositorContext (fml::Milliseconds frame_budget)
1347 : raster_time_(frame_budget), ui_time_(frame_budget) {}
1448
@@ -68,9 +102,15 @@ CompositorContext::ScopedFrame::~ScopedFrame() {
68102
69103RasterStatus CompositorContext::ScopedFrame::Raster (
70104 flutter::LayerTree& layer_tree,
71- bool ignore_raster_cache) {
105+ bool ignore_raster_cache,
106+ FrameDamage* frame_damage) {
72107 TRACE_EVENT0 (" flutter" , " CompositorContext::ScopedFrame::Raster" );
73- bool root_needs_readback = layer_tree.Preroll (*this , ignore_raster_cache);
108+
109+ std::optional<SkRect> clip_rect =
110+ frame_damage ? frame_damage->ComputeClipRect (layer_tree) : std::nullopt ;
111+
112+ bool root_needs_readback = layer_tree.Preroll (
113+ *this , ignore_raster_cache, clip_rect ? *clip_rect : kGiantRect );
74114 bool needs_save_layer = root_needs_readback && !surface_supports_readback ();
75115 PostPrerollResult post_preroll_result = PostPrerollResult::kSuccess ;
76116 if (view_embedder_ && raster_thread_merger_) {
@@ -84,9 +124,16 @@ RasterStatus CompositorContext::ScopedFrame::Raster(
84124 if (post_preroll_result == PostPrerollResult::kSkipAndRetryFrame ) {
85125 return RasterStatus::kSkipAndRetry ;
86126 }
127+
128+ SkAutoCanvasRestore restore (canvas (), clip_rect.has_value ());
129+
87130 // Clearing canvas after preroll reduces one render target switch when preroll
88131 // paints some raster cache.
89132 if (canvas ()) {
133+ if (clip_rect) {
134+ canvas ()->clipRect (*clip_rect);
135+ }
136+
90137 if (needs_save_layer) {
91138 TRACE_EVENT0 (" flutter" , " Canvas::saveLayer" );
92139 SkRect bounds = SkRect::Make (layer_tree.frame_size ());
0 commit comments