Flutter Engine
The 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
5#include "flutter/flow/diff_context.h"
6#include "flutter/flow/layers/layer.h"
7
8namespace flutter {
9
11 PaintRegionMap& this_frame_paint_region_map,
12 const PaintRegionMap& last_frame_paint_region_map,
13 bool has_raster_cache,
14 bool impeller_enabled)
16 rects_(std::make_shared<std::vector<SkRect>>()),
17 frame_size_(frame_size),
18 this_frame_paint_region_map_(this_frame_paint_region_map),
19 last_frame_paint_region_map_(last_frame_paint_region_map),
20 has_raster_cache_(has_raster_cache),
21 impeller_enabled_(impeller_enabled) {}
22
24 state_stack_.push_back(state_);
25
26 bool had_integral_transform = state_.integral_transform;
27 state_.rect_index = rects_->size();
28 state_.has_filter_bounds_adjustment = false;
29 state_.has_texture = false;
30 state_.integral_transform = false;
31
32 state_.clip_tracker_save_count = clip_tracker_.getSaveCount();
33 clip_tracker_.save();
34
35 if (had_integral_transform) {
36 MakeCurrentTransformIntegral();
37 }
38}
39
41 FML_DCHECK(!state_stack_.empty());
42 if (state_.has_filter_bounds_adjustment) {
43 filter_bounds_adjustment_stack_.pop_back();
44 }
45 clip_tracker_.restoreToCount(state_.clip_tracker_save_count);
46 state_ = state_stack_.back();
47 state_stack_.pop_back();
48}
49
50DiffContext::State::State() {}
51
53 clip_tracker_.transform(transform);
54}
55
57 clip_tracker_.transform(transform);
58}
59
60void DiffContext::MakeCurrentTransformIntegral() {
61 // TODO(knopp): This is duplicated from LayerStack. Maybe should be part of
62 // clip tracker?
63 if (clip_tracker_.using_4x4_matrix()) {
64 SkM44 integral;
66 &integral)) {
67 clip_tracker_.setTransform(integral);
68 }
69 } else {
70 SkMatrix integral;
72 &integral)) {
73 clip_tracker_.setTransform(integral);
74 }
75 }
76}
77
79 const FilterBoundsAdjustment& filter) {
80 FML_DCHECK(state_.has_filter_bounds_adjustment == false);
81 state_.has_filter_bounds_adjustment = true;
82 filter_bounds_adjustment_stack_.push_back(filter);
83}
84
85SkRect DiffContext::ApplyFilterBoundsAdjustment(SkRect rect) const {
86 // Apply filter bounds adjustment in reverse order
87 for (auto i = filter_bounds_adjustment_stack_.rbegin();
88 i != filter_bounds_adjustment_stack_.rend(); ++i) {
89 rect = (*i)(rect);
90 }
91 return rect;
92}
93
94void DiffContext::AlignRect(SkIRect& rect,
95 int horizontal_alignment,
96 int vertical_alignment) const {
97 auto top = rect.top();
98 auto left = rect.left();
99 auto right = rect.right();
100 auto bottom = rect.bottom();
101 if (top % vertical_alignment != 0) {
102 top -= top % vertical_alignment;
103 }
104 if (left % horizontal_alignment != 0) {
105 left -= left % horizontal_alignment;
106 }
107 if (right % horizontal_alignment != 0) {
108 right += horizontal_alignment - right % horizontal_alignment;
109 }
110 if (bottom % vertical_alignment != 0) {
111 bottom += vertical_alignment - bottom % vertical_alignment;
112 }
113 right = std::min(right, frame_size_.width());
114 bottom = std::min(bottom, frame_size_.height());
115 rect = SkIRect::MakeLTRB(left, top, right, bottom);
116}
117
118Damage DiffContext::ComputeDamage(const SkIRect& accumulated_buffer_damage,
119 int horizontal_clip_alignment,
120 int vertical_clip_alignment) const {
121 SkRect buffer_damage = SkRect::Make(accumulated_buffer_damage);
122 buffer_damage.join(damage_);
123 SkRect frame_damage(damage_);
124
125 for (const auto& r : readbacks_) {
126 SkRect paint_rect = SkRect::Make(r.paint_rect);
127 SkRect readback_rect = SkRect::Make(r.readback_rect);
128 // Changes either in readback or paint rect require repainting both readback
129 // and paint rect.
130 if (paint_rect.intersects(frame_damage) ||
131 readback_rect.intersects(frame_damage)) {
132 frame_damage.join(readback_rect);
133 frame_damage.join(paint_rect);
134 buffer_damage.join(readback_rect);
135 buffer_damage.join(paint_rect);
136 }
137 }
138
139 Damage res;
140 buffer_damage.roundOut(&res.buffer_damage);
141 frame_damage.roundOut(&res.frame_damage);
142
143 SkIRect frame_clip = SkIRect::MakeSize(frame_size_);
144 res.buffer_damage.intersect(frame_clip);
145 res.frame_damage.intersect(frame_clip);
146
147 if (horizontal_clip_alignment > 1 || vertical_clip_alignment > 1) {
148 AlignRect(res.buffer_damage, horizontal_clip_alignment,
149 vertical_clip_alignment);
150 AlignRect(res.frame_damage, horizontal_clip_alignment,
151 vertical_clip_alignment);
152 }
153 return res;
154}
155
157 SkRect mapped_rect(rect);
158 clip_tracker_.mapRect(&mapped_rect);
159 return mapped_rect;
160}
161
163 clip_tracker_.clipRect(clip, DlCanvas::ClipOp::kIntersect, false);
164 return !clip_tracker_.device_cull_rect().isEmpty();
165}
166
168 return clip_tracker_.matrix_3x3();
169}
170
172 return clip_tracker_.local_cull_rect();
173}
174
175void DiffContext::MarkSubtreeDirty(const PaintRegion& previous_paint_region) {
177 if (previous_paint_region.is_valid()) {
178 AddDamage(previous_paint_region);
179 }
180 state_.dirty = true;
181}
182
183void DiffContext::MarkSubtreeDirty(const SkRect& previous_paint_region) {
185 AddDamage(previous_paint_region);
186 state_.dirty = true;
187}
188
190 // During painting we cull based on non-overriden transform and then
191 // override the transform right before paint. Do the same thing here to get
192 // identical paint rect.
193 auto transformed_rect = ApplyFilterBoundsAdjustment(MapRect(rect));
194 if (transformed_rect.intersects(clip_tracker_.device_cull_rect())) {
195 if (state_.integral_transform) {
196 clip_tracker_.save();
197 MakeCurrentTransformIntegral();
198 transformed_rect = ApplyFilterBoundsAdjustment(MapRect(rect));
199 clip_tracker_.restore();
200 }
201 rects_->push_back(transformed_rect);
202 if (IsSubtreeDirty()) {
203 AddDamage(transformed_rect);
204 }
205 }
206}
207
209 // Set the has_texture flag on current state and all parent states. That
210 // way we'll know that we can't skip diff for retained layers because
211 // they contain a TextureLayer.
212 for (auto& state : state_stack_) {
213 state.has_texture = true;
214 }
215 state_.has_texture = true;
216}
217
219 // Adding paint region for retained layer implies that current subtree is not
220 // dirty, so we know, for example, that the inherited transforms must match
222 if (region.is_valid()) {
223 rects_->insert(rects_->end(), region.begin(), region.end());
224 }
225}
226
228 const SkIRect& readback_rect) {
229 Readback readback;
230 readback.paint_rect = paint_rect;
231 readback.readback_rect = readback_rect;
232 readback.position = rects_->size();
233 // Push empty rect as a placeholder for position in current subtree
234 rects_->push_back(SkRect::MakeEmpty());
235 readbacks_.push_back(readback);
236}
237
239 bool has_readback = std::any_of(
240 readbacks_.begin(), readbacks_.end(),
241 [&](const Readback& r) { return r.position >= state_.rect_index; });
242 return PaintRegion(rects_, state_.rect_index, rects_->size(), has_readback,
243 state_.has_texture);
244}
245
247 FML_DCHECK(damage.is_valid());
248 for (const auto& r : damage) {
249 damage_.join(r);
250 }
251}
252
253void DiffContext::AddDamage(const SkRect& rect) {
254 damage_.join(rect);
255}
256
258 const PaintRegion& region) {
259 this_frame_paint_region_map_[layer->unique_id()] = region;
260}
261
263 auto i = last_frame_paint_region_map_.find(layer->unique_id());
264 if (i != last_frame_paint_region_map_.end()) {
265 return i->second;
266 } else {
267 // This is valid when Layer::PreservePaintRegion is called for retained
268 // layer with zero sized parent clip (these layers are not diffed)
269 return PaintRegion();
270 }
271}
272
274#if !FLUTTER_RELEASE
275 FML_TRACE_COUNTER("flutter", "DiffContext", reinterpret_cast<int64_t>(this),
276 "NewPictures", new_pictures_, "PicturesTooComplexToCompare",
277 pictures_too_complex_to_compare_, "DeepComparePictures",
278 deep_compare_pictures_, "SameInstancePictures",
279 same_instance_pictures_,
280 "DifferentInstanceButEqualPictures",
281 different_instance_but_equal_pictures_);
282#endif // !FLUTTER_RELEASE
283}
284
285} // namespace flutter
static void readback(const SkBitmap &src, int *result, int resultCount)
Definition BlurTest.cpp:264
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
Definition SkM44.h:150
SkMatrix GetTransform3x3() const
void PushTransform(const SkMatrix &transform)
void AddLayerBounds(const SkRect &rect)
void SetLayerPaintRegion(const Layer *layer, const PaintRegion &region)
void MarkSubtreeDirty(const PaintRegion &previous_paint_region=PaintRegion())
void AddDamage(const PaintRegion &damage)
PaintRegion CurrentSubtreeRegion() const
void AddExistingPaintRegion(const PaintRegion &region)
void PushFilterBoundsAdjustment(const FilterBoundsAdjustment &filter)
PaintRegion GetOldLayerPaintRegion(const Layer *layer) const
SkRect MapRect(const SkRect &rect)
bool PushCullRect(const SkRect &clip)
Damage ComputeDamage(const SkIRect &additional_damage, int horizontal_clip_alignment=0, int vertical_clip_alignment=0) const
bool IsSubtreeDirty() const
void AddReadbackRegion(const SkIRect &paint_rect, const SkIRect &readback_rect)
std::function< SkRect(SkRect)> FilterBoundsAdjustment
DiffContext(SkISize frame_size, PaintRegionMap &this_frame_paint_region_map, const PaintRegionMap &last_frame_paint_region_map, bool has_raster_cache, bool impeller_enabled)
SkRect GetCullRect() const
void clipRect(const DlRect &rect, ClipOp op, bool is_aa)
uint64_t unique_id() const
Definition layer.h:250
bool is_valid() const
AtkStateType state
#define FML_DCHECK(condition)
Definition logging.h:103
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
std::map< uint64_t, PaintRegion > PaintRegionMap
static constexpr SkRect kGiantRect
Definition layer.h:49
Definition ref_ptr.h:256
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47
Definition SkMD5.cpp:134
bool intersect(const SkIRect &r)
Definition SkRect.h:513
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition SkRect.h:91
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595
bool intersects(const SkRect &r) const
Definition SkRect.h:1121
void roundOut(SkIRect *dst) const
Definition SkRect.h:1241
bool isEmpty() const
Definition SkRect.h:693
void join(const SkRect &r)
Definition SkRect.cpp:126
SkIRect buffer_damage
SkIRect 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|.
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)
Definition trace_event.h:85