Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit cfa1b8e

Browse files
authored
Add DiffContext (#21824)
1 parent 6e7ac9b commit cfa1b8e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1882
-55
lines changed

BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ config("config") {
2828
if (is_fuchsia && flutter_enable_legacy_fuchsia_embedder) {
2929
defines = [ "LEGACY_FUCHSIA_EMBEDDER" ]
3030
}
31+
32+
if (is_debug) {
33+
defines = [ "FLUTTER_ENABLE_DIFF_CONTEXT" ]
34+
}
3135
}
3236

3337
config("export_dynamic_symbols") {

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ FILE: ../../../flutter/common/task_runners.cc
3434
FILE: ../../../flutter/common/task_runners.h
3535
FILE: ../../../flutter/flow/compositor_context.cc
3636
FILE: ../../../flutter/flow/compositor_context.h
37+
FILE: ../../../flutter/flow/diff_context.cc
38+
FILE: ../../../flutter/flow/diff_context.h
3739
FILE: ../../../flutter/flow/embedded_view_params_unittests.cc
3840
FILE: ../../../flutter/flow/embedded_views.cc
3941
FILE: ../../../flutter/flow/embedded_views.h
@@ -101,6 +103,8 @@ FILE: ../../../flutter/flow/matrix_decomposition.cc
101103
FILE: ../../../flutter/flow/matrix_decomposition.h
102104
FILE: ../../../flutter/flow/matrix_decomposition_unittests.cc
103105
FILE: ../../../flutter/flow/mutators_stack_unittests.cc
106+
FILE: ../../../flutter/flow/paint_region.cc
107+
FILE: ../../../flutter/flow/paint_region.h
104108
FILE: ../../../flutter/flow/paint_utils.cc
105109
FILE: ../../../flutter/flow/paint_utils.h
106110
FILE: ../../../flutter/flow/raster_cache.cc

common/graphics/persistent_cache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
#include "flutter/fml/unique_fd.h"
1616
#include "third_party/skia/include/gpu/GrContextOptions.h"
1717

18+
namespace flutter {
19+
1820
namespace testing {
1921
class ShellTest;
2022
}
2123

22-
namespace flutter {
23-
2424
/// A cache of SkData that gets stored to disk.
2525
///
2626
/// This is mainly used for Shaders but is also written to by Dart. It is

flow/BUILD.gn

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ source_set("flow") {
1010
sources = [
1111
"compositor_context.cc",
1212
"compositor_context.h",
13+
"diff_context.cc",
14+
"diff_context.h",
1315
"embedded_views.cc",
1416
"embedded_views.h",
1517
"instrumentation.cc",
@@ -50,6 +52,8 @@ source_set("flow") {
5052
"layers/transform_layer.h",
5153
"matrix_decomposition.cc",
5254
"matrix_decomposition.h",
55+
"paint_region.cc",
56+
"paint_region.h",
5357
"paint_utils.cc",
5458
"paint_utils.h",
5559
"raster_cache.cc",
@@ -103,6 +107,8 @@ if (enable_unittests) {
103107
testonly = true
104108

105109
sources = [
110+
"testing/diff_context_test.cc",
111+
"testing/diff_context_test.h",
106112
"testing/gl_context_switch_test.cc",
107113
"testing/gl_context_switch_test.h",
108114
"testing/layer_test.h",

flow/diff_context.cc

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#include "flutter/flow/diff_context.h"
2+
#include "flutter/flow/layers/layer.h"
3+
4+
namespace flutter {
5+
6+
#ifdef FLUTTER_ENABLE_DIFF_CONTEXT
7+
8+
DiffContext::DiffContext(SkISize frame_size,
9+
double frame_device_pixel_ratio,
10+
PaintRegionMap& this_frame_paint_region_map,
11+
const PaintRegionMap& last_frame_paint_region_map)
12+
: rects_(std::make_shared<std::vector<SkRect>>()),
13+
frame_size_(frame_size),
14+
frame_device_pixel_ratio_(frame_device_pixel_ratio),
15+
this_frame_paint_region_map_(this_frame_paint_region_map),
16+
last_frame_paint_region_map_(last_frame_paint_region_map) {}
17+
18+
void DiffContext::BeginSubtree() {
19+
state_stack_.push_back(state_);
20+
state_.rect_index_ = rects_->size();
21+
}
22+
23+
void DiffContext::EndSubtree() {
24+
FML_DCHECK(!state_stack_.empty());
25+
state_ = std::move(state_stack_.back());
26+
state_stack_.pop_back();
27+
}
28+
29+
DiffContext::State::State()
30+
: dirty(false), cull_rect(kGiantRect), rect_index_(0) {}
31+
32+
void DiffContext::PushTransform(const SkMatrix& transform) {
33+
state_.transform.preConcat(transform);
34+
SkMatrix inverse_transform;
35+
// Perspective projections don't produce rectangles that are useful for
36+
// culling for some reason.
37+
if (!transform.hasPerspective() && transform.invert(&inverse_transform)) {
38+
inverse_transform.mapRect(&state_.cull_rect);
39+
} else {
40+
state_.cull_rect = kGiantRect;
41+
}
42+
}
43+
44+
Damage DiffContext::ComputeDamage(
45+
const SkIRect& accumulated_buffer_damage) const {
46+
SkRect buffer_damage = SkRect::Make(accumulated_buffer_damage);
47+
buffer_damage.join(damage_);
48+
SkRect frame_damage(damage_);
49+
50+
for (const auto& r : readbacks_) {
51+
SkRect rect = SkRect::Make(r.rect);
52+
if (rect.intersects(frame_damage)) {
53+
frame_damage.join(rect);
54+
}
55+
if (rect.intersects(buffer_damage)) {
56+
buffer_damage.join(rect);
57+
}
58+
}
59+
60+
Damage res;
61+
buffer_damage.roundOut(&res.buffer_damage);
62+
frame_damage.roundOut(&res.frame_damage);
63+
64+
SkIRect frame_clip = SkIRect::MakeSize(frame_size_);
65+
res.buffer_damage.intersect(frame_clip);
66+
res.frame_damage.intersect(frame_clip);
67+
return res;
68+
}
69+
70+
bool DiffContext::PushCullRect(const SkRect& clip) {
71+
return state_.cull_rect.intersect(clip);
72+
}
73+
74+
void DiffContext::MarkSubtreeDirty(const PaintRegion& previous_paint_region) {
75+
FML_DCHECK(!IsSubtreeDirty());
76+
if (previous_paint_region.is_valid()) {
77+
AddDamage(previous_paint_region);
78+
}
79+
state_.dirty = true;
80+
}
81+
82+
void DiffContext::AddLayerBounds(const SkRect& rect) {
83+
SkRect r(rect);
84+
if (r.intersect(state_.cull_rect)) {
85+
state_.transform.mapRect(&r);
86+
if (!r.isEmpty()) {
87+
rects_->push_back(r);
88+
if (IsSubtreeDirty()) {
89+
AddDamage(r);
90+
}
91+
}
92+
}
93+
}
94+
95+
void DiffContext::AddExistingPaintRegion(const PaintRegion& region) {
96+
// Adding paint region for retained layer implies that current subtree is not
97+
// dirty, so we know, for example, that the inherited transforms must match
98+
FML_DCHECK(!IsSubtreeDirty());
99+
if (region.is_valid()) {
100+
rects_->insert(rects_->end(), region.begin(), region.end());
101+
}
102+
}
103+
104+
void DiffContext::AddReadbackRegion(const SkIRect& rect) {
105+
Readback readback;
106+
readback.rect = rect;
107+
readback.position = rects_->size();
108+
// Push empty rect as a placeholder for position in current subtree
109+
rects_->push_back(SkRect::MakeEmpty());
110+
readbacks_.push_back(std::move(readback));
111+
}
112+
113+
PaintRegion DiffContext::CurrentSubtreeRegion() const {
114+
bool has_readback = std::any_of(
115+
readbacks_.begin(), readbacks_.end(),
116+
[&](const Readback& r) { return r.position >= state_.rect_index_; });
117+
return PaintRegion(rects_, state_.rect_index_, rects_->size(), has_readback);
118+
}
119+
120+
void DiffContext::AddDamage(const PaintRegion& damage) {
121+
FML_DCHECK(damage.is_valid());
122+
for (const auto& r : damage) {
123+
damage_.join(r);
124+
}
125+
}
126+
127+
void DiffContext::AddDamage(const SkRect& rect) {
128+
damage_.join(rect);
129+
}
130+
131+
void DiffContext::SetLayerPaintRegion(const Layer* layer,
132+
const PaintRegion& region) {
133+
this_frame_paint_region_map_[layer->unique_id()] = region;
134+
}
135+
136+
PaintRegion DiffContext::GetOldLayerPaintRegion(const Layer* layer) const {
137+
auto i = last_frame_paint_region_map_.find(layer->unique_id());
138+
if (i != last_frame_paint_region_map_.end()) {
139+
return i->second;
140+
} else {
141+
// This is valid when Layer::PreservePaintRegion is called for retained
142+
// layer with zero sized parent clip (these layers are not diffed)
143+
return PaintRegion();
144+
}
145+
}
146+
147+
void DiffContext::Statistics::LogStatistics() {
148+
#if !FLUTTER_RELEASE
149+
FML_TRACE_COUNTER("flutter", "DiffContext", reinterpret_cast<int64_t>(this),
150+
"NewPictures", new_pictures_, "PicturesTooComplexToCompare",
151+
pictures_too_complex_to_compare_, "DeepComparePictures",
152+
deep_compare_pictures_, "SameInstancePictures",
153+
same_instance_pictures_,
154+
"DifferentInstanceButEqualPictures",
155+
different_instance_but_equal_pictures_);
156+
#endif // !FLUTTER_RELEASE
157+
}
158+
159+
#endif // FLUTTER_ENABLE_DIFF_CONTEXT
160+
161+
} // namespace flutter

0 commit comments

Comments
 (0)