Flutter Engine
 
Loading...
Searching...
No Matches
diff_context.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
9
10namespace flutter {
11
13 PaintRegionMap& this_frame_paint_region_map,
14 const PaintRegionMap& last_frame_paint_region_map,
15 bool has_raster_cache,
16 bool impeller_enabled)
17 : rects_(std::make_shared<std::vector<DlRect>>()),
18 frame_size_(frame_size),
19 this_frame_paint_region_map_(this_frame_paint_region_map),
20 last_frame_paint_region_map_(last_frame_paint_region_map),
21 has_raster_cache_(has_raster_cache),
22 impeller_enabled_(impeller_enabled) {}
23
25 state_stack_.push_back(state_);
26
27 bool had_integral_transform = state_.integral_transform;
28 state_.rect_index = rects_->size();
29 state_.has_filter_bounds_adjustment = false;
30 state_.has_texture = false;
31 state_.integral_transform = false;
32
33 if (had_integral_transform) {
34 MakeTransformIntegral(state_.matrix_clip);
35 }
36}
37
39 FML_DCHECK(!state_stack_.empty());
40 if (state_.has_filter_bounds_adjustment) {
41 filter_bounds_adjustment_stack_.pop_back();
42 }
43 state_ = state_stack_.back();
44 state_stack_.pop_back();
45}
46
47DiffContext::State::State() : matrix_clip(kGiantRect, DlMatrix()) {}
48
50 state_.matrix_clip.transform(transform);
51}
52
53void DiffContext::MakeTransformIntegral(
54 DisplayListMatrixClipState& matrix_clip) {
55 // TODO(knopp): This is duplicated from LayerStack. Maybe should be part of
56 // clip tracker?
57 DlMatrix integral;
59 &integral)) {
60 matrix_clip.setTransform(integral);
61 }
62}
63
65 const FilterBoundsAdjustment& filter) {
66 FML_DCHECK(state_.has_filter_bounds_adjustment == false);
67 state_.has_filter_bounds_adjustment = true;
68 filter_bounds_adjustment_stack_.push_back(filter);
69}
70
71DlRect DiffContext::ApplyFilterBoundsAdjustment(DlRect rect) const {
72 // Apply filter bounds adjustment in reverse order
73 for (auto i = filter_bounds_adjustment_stack_.rbegin();
74 i != filter_bounds_adjustment_stack_.rend(); ++i) {
75 rect = (*i)(rect);
76 }
77 return rect;
78}
79
80void DiffContext::AlignRect(DlIRect& rect,
81 int horizontal_alignment,
82 int vertical_alignment) const {
83 auto top = rect.GetTop();
84 auto left = rect.GetLeft();
85 auto right = rect.GetRight();
86 auto bottom = rect.GetBottom();
87 if (top % vertical_alignment != 0) {
88 top -= top % vertical_alignment;
89 }
90 if (left % horizontal_alignment != 0) {
91 left -= left % horizontal_alignment;
92 }
93 if (right % horizontal_alignment != 0) {
94 right += horizontal_alignment - right % horizontal_alignment;
95 }
96 if (bottom % vertical_alignment != 0) {
97 bottom += vertical_alignment - bottom % vertical_alignment;
98 }
99 right = std::min(right, frame_size_.width);
100 bottom = std::min(bottom, frame_size_.height);
101 rect = DlIRect::MakeLTRB(left, top, right, bottom);
102}
103
104Damage DiffContext::ComputeDamage(const DlIRect& accumulated_buffer_damage,
105 int horizontal_clip_alignment,
106 int vertical_clip_alignment) const {
107 DlRect buffer_damage = DlRect::Make(accumulated_buffer_damage).Union(damage_);
108 DlRect frame_damage(damage_);
109
110 for (const auto& r : readbacks_) {
111 DlRect paint_rect = DlRect::Make(r.paint_rect);
112 DlRect readback_rect = DlRect::Make(r.readback_rect);
113 // Changes either in readback or paint rect require repainting both readback
114 // and paint rect.
115 if (paint_rect.IntersectsWithRect(frame_damage) ||
116 readback_rect.IntersectsWithRect(frame_damage)) {
117 frame_damage = frame_damage.Union(readback_rect).Union(paint_rect);
118 buffer_damage = buffer_damage.Union(readback_rect).Union(paint_rect);
119 }
120 }
121
122 DlIRect frame_clip = DlIRect::MakeSize(frame_size_);
123
124 Damage res;
125 res.buffer_damage =
126 DlIRect::RoundOut(buffer_damage).IntersectionOrEmpty(frame_clip);
127 res.frame_damage =
128 DlIRect::RoundOut(frame_damage).IntersectionOrEmpty(frame_clip);
129
130 if (horizontal_clip_alignment > 1 || vertical_clip_alignment > 1) {
131 AlignRect(res.buffer_damage, horizontal_clip_alignment,
132 vertical_clip_alignment);
133 AlignRect(res.frame_damage, horizontal_clip_alignment,
134 vertical_clip_alignment);
135 }
136 return res;
137}
138
140 DlRect mapped_rect(rect);
141 state_.matrix_clip.mapRect(&mapped_rect);
142 return mapped_rect;
143}
144
146 state_.matrix_clip.clipRect(clip, DlClipOp::kIntersect, false);
147 return !state_.matrix_clip.is_cull_rect_empty();
148}
149
151 return state_.matrix_clip.matrix();
152}
153
155 return state_.matrix_clip.GetLocalCullCoverage();
156}
157
158void DiffContext::MarkSubtreeDirty(const PaintRegion& previous_paint_region) {
160 if (previous_paint_region.is_valid()) {
161 AddDamage(previous_paint_region);
162 }
163 state_.dirty = true;
164}
165
166void DiffContext::MarkSubtreeDirty(const DlRect& previous_paint_region) {
168 AddDamage(previous_paint_region);
169 state_.dirty = true;
170}
171
173 // During painting we cull based on non-overriden transform and then
174 // override the transform right before paint. Do the same thing here to get
175 // identical paint rect.
176 auto transformed_rect = ApplyFilterBoundsAdjustment(MapRect(rect));
177 if (transformed_rect.IntersectsWithRect(
178 state_.matrix_clip.GetDeviceCullCoverage())) {
179 if (state_.integral_transform) {
180 DisplayListMatrixClipState temp_state = state_.matrix_clip;
181 MakeTransformIntegral(temp_state);
182 temp_state.mapRect(rect, &transformed_rect);
183 transformed_rect = ApplyFilterBoundsAdjustment(transformed_rect);
184 }
185 rects_->push_back(transformed_rect);
186 if (IsSubtreeDirty()) {
187 AddDamage(transformed_rect);
188 }
189 }
190}
191
193 // Set the has_texture flag on current state and all parent states. That
194 // way we'll know that we can't skip diff for retained layers because
195 // they contain a TextureLayer.
196 for (auto& state : state_stack_) {
197 state.has_texture = true;
198 }
199 state_.has_texture = true;
200}
201
203 // Adding paint region for retained layer implies that current subtree is not
204 // dirty, so we know, for example, that the inherited transforms must match
206 if (region.is_valid()) {
207 rects_->insert(rects_->end(), region.begin(), region.end());
208 }
209}
210
212 const DlIRect& readback_rect) {
213 Readback readback;
214 readback.paint_rect = paint_rect;
215 readback.readback_rect = readback_rect;
216 readback.position = rects_->size();
217 // Push empty rect as a placeholder for position in current subtree
218 rects_->push_back(DlRect());
219 readbacks_.push_back(readback);
220}
221
223 bool has_readback = std::any_of(
224 readbacks_.begin(), readbacks_.end(),
225 [&](const Readback& r) { return r.position >= state_.rect_index; });
226 return PaintRegion(rects_, state_.rect_index, rects_->size(), has_readback,
227 state_.has_texture);
228}
229
231 FML_DCHECK(damage.is_valid());
232 for (const auto& r : damage) {
233 damage_ = damage_.Union(r);
234 }
235}
236
237void DiffContext::AddDamage(const DlRect& rect) {
238 damage_ = damage_.Union(rect);
239}
240
242 const PaintRegion& region) {
243 this_frame_paint_region_map_[layer->unique_id()] = region;
244}
245
247 auto i = last_frame_paint_region_map_.find(layer->unique_id());
248 if (i != last_frame_paint_region_map_.end()) {
249 return i->second;
250 } else {
251 // This is valid when Layer::PreservePaintRegion is called for retained
252 // layer with zero sized parent clip (these layers are not diffed)
253 return PaintRegion();
254 }
255}
256
258#if !FLUTTER_RELEASE
259 FML_TRACE_COUNTER("flutter", "DiffContext", reinterpret_cast<int64_t>(this),
260 "NewPictures", new_pictures_, "PicturesTooComplexToCompare",
261 pictures_too_complex_to_compare_, "DeepComparePictures",
262 deep_compare_pictures_, "SameInstancePictures",
263 same_instance_pictures_,
264 "DifferentInstanceButEqualPictures",
265 different_instance_but_equal_pictures_);
266#endif // !FLUTTER_RELEASE
267}
268
269} // namespace flutter
DlRect GetCullRect() const
std::function< DlRect(DlRect)> FilterBoundsAdjustment
DiffContext(DlISize frame_size, PaintRegionMap &this_frame_paint_region_map, const PaintRegionMap &last_frame_paint_region_map, bool has_raster_cache, bool impeller_enabled)
bool PushCullRect(const DlRect &clip)
DlRect MapRect(const DlRect &rect)
Damage ComputeDamage(const DlIRect &additional_damage, int horizontal_clip_alignment=0, int vertical_clip_alignment=0) const
void SetLayerPaintRegion(const Layer *layer, const PaintRegion &region)
void MarkSubtreeDirty(const PaintRegion &previous_paint_region=PaintRegion())
void AddReadbackRegion(const DlIRect &paint_rect, const DlIRect &readback_rect)
void AddDamage(const PaintRegion &damage)
PaintRegion CurrentSubtreeRegion() const
void AddExistingPaintRegion(const PaintRegion &region)
void PushFilterBoundsAdjustment(const FilterBoundsAdjustment &filter)
PaintRegion GetOldLayerPaintRegion(const Layer *layer) const
const DlMatrix & GetMatrix() const
bool IsSubtreeDirty() const
void AddLayerBounds(const DlRect &rect)
void PushTransform(const DlMatrix &transform)
void setTransform(const DlMatrix &matrix)
uint64_t unique_id() const
Definition layer.h:237
std::vector< DlRect >::const_iterator end() const
std::vector< DlRect >::const_iterator begin() const
bool is_valid() const
#define FML_DCHECK(condition)
Definition logging.h:122
std::map< uint64_t, PaintRegion > PaintRegionMap
impeller::Rect DlRect
impeller::IRect32 DlIRect
static constexpr DlRect kGiantRect
Definition layer.h:40
Definition ref_ptr.h:261
DlIRect buffer_damage
DlIRect frame_damage
static bool ComputeIntegralTransCTM(const SkMatrix &in, SkMatrix *out)
Snap the translation components of the |in| matrix to integers and store the snapped matrix in |out|.
A 4x4 matrix using column-major storage.
Definition matrix.h:37
constexpr auto GetTop() const
Definition rect.h:353
constexpr TRect Union(const TRect &o) const
Definition rect.h:513
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
Definition rect.h:157
constexpr bool IntersectsWithRect(const TRect &o) const
Definition rect.h:546
RoundOut(const TRect< U > &r)
Definition rect.h:679
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
constexpr TRect IntersectionOrEmpty(const TRect &o) const
Definition rect.h:542
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129
Type height
Definition size.h:29
Type width
Definition size.h:28
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)
Definition trace_event.h:85