forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
diff_context.h
281 lines (219 loc) · 9.93 KB
/
diff_context.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FLOW_DIFF_CONTEXT_H_
#define FLUTTER_FLOW_DIFF_CONTEXT_H_
#include <functional>
#include <map>
#include <optional>
#include <vector>
#include "display_list/utils/dl_matrix_clip_tracker.h"
#include "flutter/flow/paint_region.h"
#include "flutter/fml/macros.h"
#include "third_party/skia/include/core/SkM44.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkRect.h"
namespace flutter {
class Layer;
// Represents area that needs to be updated in front buffer (frame_damage) and
// area that is going to be painted to in back buffer (buffer_damage).
struct Damage {
// This is the damage between current and previous frame;
// If embedder supports partial update, this is the region that needs to be
// repainted.
// Corresponds to "surface damage" from EGL_KHR_partial_update.
SkIRect frame_damage;
// Reflects actual change to target framebuffer; This is frame_damage +
// damage previously acumulated for target framebuffer.
// All drawing will be clipped to this region. Knowing the affected area
// upfront may be useful for tile based GPUs.
// Corresponds to "buffer damage" from EGL_KHR_partial_update.
SkIRect buffer_damage;
};
// Layer Unique Id to PaintRegion
using PaintRegionMap = std::map<uint64_t, PaintRegion>;
// Tracks state during tree diffing process and computes resulting damage
class DiffContext {
public:
explicit DiffContext(SkISize frame_size,
PaintRegionMap& this_frame_paint_region_map,
const PaintRegionMap& last_frame_paint_region_map,
bool has_raster_cache,
bool impeller_enabled);
// Starts a new subtree.
void BeginSubtree();
// Ends current subtree; All modifications to state (transform, cullrect,
// dirty) will be restored
void EndSubtree();
// Creates subtree in current scope and closes it on scope exit
class AutoSubtreeRestore {
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(AutoSubtreeRestore);
public:
explicit AutoSubtreeRestore(DiffContext* context) : context_(context) {
context->BeginSubtree();
}
~AutoSubtreeRestore() { context_->EndSubtree(); }
private:
DiffContext* context_;
};
// Pushes additional transform for current subtree
void PushTransform(const SkMatrix& transform);
void PushTransform(const SkM44& transform);
// Pushes cull rect for current subtree
bool PushCullRect(const SkRect& clip);
// Function that adjusts layer bounds (in device coordinates) depending
// on filter.
using FilterBoundsAdjustment = std::function<SkRect(SkRect)>;
// Pushes filter bounds adjustment to current subtree. Every layer in this
// subtree will have bounds adjusted by this function.
void PushFilterBoundsAdjustment(const FilterBoundsAdjustment& filter);
// Instruct DiffContext that current layer will paint with integral transform.
void WillPaintWithIntegralTransform() { state_.integral_transform = true; }
// Returns current transform as SkMatrix.
SkMatrix GetTransform3x3() const;
// Return cull rect for current subtree (in local coordinates).
SkRect GetCullRect() const;
// Sets the dirty flag on current subtree.
//
// previous_paint_region, which should represent region of previous subtree
// at this level will be added to damage area.
//
// Each paint region added to dirty subtree (through AddPaintRegion) is also
// added to damage.
void MarkSubtreeDirty(
const PaintRegion& previous_paint_region = PaintRegion());
void MarkSubtreeDirty(const SkRect& previous_paint_region);
bool IsSubtreeDirty() const { return state_.dirty; }
// Marks that current subtree contains a TextureLayer. This is needed to
// ensure that we'll Diff the TextureLayer even if inside retained layer.
void MarkSubtreeHasTextureLayer();
// Add layer bounds to current paint region; rect is in "local" (layer)
// coordinates.
void AddLayerBounds(const SkRect& rect);
// Add entire paint region of retained layer for current subtree. This can
// only be used in subtrees that are not dirty, otherwise ancestor transforms
// or clips may result in different paint region.
void AddExistingPaintRegion(const PaintRegion& region);
// The idea of readback region is that if any part of the readback region
// needs to be repainted, then the whole readback region must be repainted;
//
// paint_rect - rectangle where the filter paints contents (in screen
// coordinates)
// readback_rect - rectangle where the filter samples from (in screen
// coordinates)
void AddReadbackRegion(const SkIRect& paint_rect,
const SkIRect& readback_rect);
// Returns the paint region for current subtree; Each rect in paint region is
// in screen coordinates; Once a layer accumulates the paint regions of its
// children, this PaintRegion value can be associated with the current layer
// using DiffContext::SetLayerPaintRegion.
PaintRegion CurrentSubtreeRegion() const;
// Computes final damage
//
// additional_damage is the previously accumulated frame_damage for
// current framebuffer
//
// clip_alignment controls the alignment of resulting frame and surface
// damage.
Damage ComputeDamage(const SkIRect& additional_damage,
int horizontal_clip_alignment = 0,
int vertical_clip_alignment = 0) const;
// Adds the region to current damage. Used for removed layers, where instead
// of diffing the layer its paint region is direcly added to damage.
void AddDamage(const PaintRegion& damage);
// Associates the paint region with specified layer and current layer tree.
// The paint region can not be stored directly in layer itself, because same
// retained layer instance can possibly paint in different locations depending
// on ancestor layers.
void SetLayerPaintRegion(const Layer* layer, const PaintRegion& region);
// Retrieves the paint region associated with specified layer and previous
// frame layer tree.
PaintRegion GetOldLayerPaintRegion(const Layer* layer) const;
// Whether or not a raster cache is being used. If so, we must snap
// all transformations to physical pixels if the layer may be raster
// cached.
bool has_raster_cache() const { return has_raster_cache_; }
bool impeller_enabled() const { return impeller_enabled_; }
class Statistics {
public:
// Picture replaced by different picture
void AddNewPicture() { ++new_pictures_; }
// Picture that would require deep comparison but was considered too complex
// to serialize and thus was treated as new picture
void AddPictureTooComplexToCompare() { ++pictures_too_complex_to_compare_; }
// Picture that has identical instance between frames
void AddSameInstancePicture() { ++same_instance_pictures_; };
// Picture that had to be serialized to compare for equality
void AddDeepComparePicture() { ++deep_compare_pictures_; }
// Picture that had to be serialized to compare (different instances),
// but were equal
void AddDifferentInstanceButEqualPicture() {
++different_instance_but_equal_pictures_;
};
// Logs the statistics to trace counter
void LogStatistics();
private:
int new_pictures_ = 0;
int pictures_too_complex_to_compare_ = 0;
int same_instance_pictures_ = 0;
int deep_compare_pictures_ = 0;
int different_instance_but_equal_pictures_ = 0;
};
Statistics& statistics() { return statistics_; }
SkRect MapRect(const SkRect& rect);
private:
struct State {
State();
bool dirty = false;
size_t rect_index = 0;
// In order to replicate paint process closely, DiffContext needs to take
// into account that some layers are painted with transform translation
// snapped to integral coordinates.
//
// It's not possible to simply snap the transform itself, because culling
// needs to happen with original (unsnapped) transform, just like it does
// during paint. This means the integral coordinates must be applied after
// culling before painting the layer content (either the layer itself, or
// when starting subtree to paint layer children).
bool integral_transform = false;
// Used to restoring clip tracker when popping state.
int clip_tracker_save_count = 0;
// Whether this subtree has filter bounds adjustment function. If so,
// it will need to be removed from stack when subtree is closed.
bool has_filter_bounds_adjustment = false;
// Whether there is a texture layer in this subtree.
bool has_texture = false;
};
void MakeCurrentTransformIntegral();
DisplayListMatrixClipTracker clip_tracker_;
std::shared_ptr<std::vector<SkRect>> rects_;
State state_;
SkISize frame_size_;
std::vector<State> state_stack_;
std::vector<FilterBoundsAdjustment> filter_bounds_adjustment_stack_;
// Applies the filter bounds adjustment stack on provided rect.
// Rect must be in device coordinates.
SkRect ApplyFilterBoundsAdjustment(SkRect rect) const;
SkRect damage_ = SkRect::MakeEmpty();
PaintRegionMap& this_frame_paint_region_map_;
const PaintRegionMap& last_frame_paint_region_map_;
bool has_raster_cache_;
bool impeller_enabled_;
void AddDamage(const SkRect& rect);
void AlignRect(SkIRect& rect,
int horizontal_alignment,
int vertical_clip_alignment) const;
struct Readback {
// Index of rects_ entry that this readback belongs to. Used to
// determine if subtree has any readback
size_t position;
// Paint region of the filter performing readback, in screen coordinates.
SkIRect paint_rect;
// Readback area of the filter, in screen coordinates.
SkIRect readback_rect;
};
std::vector<Readback> readbacks_;
Statistics statistics_;
};
} // namespace flutter
#endif // FLUTTER_FLOW_DIFF_CONTEXT_H_