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

Commit 69c29fb

Browse files
authored
Reland: Partial repaint platform views (#54231)
Relands #54219 reverted in #54230. The tracked area of `PlatformViewLayer` now covers entire frame ensuring full repaint when platform view is removed. Added `FullRepaintAfterRemovingLayer` test. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
1 parent a912045 commit 69c29fb

File tree

9 files changed

+81
-26
lines changed

9 files changed

+81
-26
lines changed

flow/diff_context.cc

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void DiffContext::BeginSubtree() {
2727
bool had_integral_transform = state_.integral_transform;
2828
state_.rect_index = rects_->size();
2929
state_.has_filter_bounds_adjustment = false;
30-
state_.has_texture = false;
30+
state_.has_volatile_layer = false;
3131
state_.integral_transform = false;
3232

3333
if (had_integral_transform) {
@@ -203,14 +203,20 @@ void DiffContext::AddLayerBounds(const SkRect& rect) {
203203
}
204204
}
205205

206-
void DiffContext::MarkSubtreeHasTextureLayer() {
206+
void DiffContext::RepaintEntireFrame() {
207+
auto frame_rect = SkRect::MakeIWH(frame_size_.width(), frame_size_.height());
208+
rects_->push_back(frame_rect);
209+
AddDamage(frame_rect);
210+
}
211+
212+
void DiffContext::MarkSubtreeHasVolatileLayer() {
207213
// Set the has_texture flag on current state and all parent states. That
208214
// way we'll know that we can't skip diff for retained layers because
209215
// they contain a TextureLayer.
210216
for (auto& state : state_stack_) {
211-
state.has_texture = true;
217+
state.has_volatile_layer = true;
212218
}
213-
state_.has_texture = true;
219+
state_.has_volatile_layer = true;
214220
}
215221

216222
void DiffContext::AddExistingPaintRegion(const PaintRegion& region) {
@@ -238,7 +244,7 @@ PaintRegion DiffContext::CurrentSubtreeRegion() const {
238244
readbacks_.begin(), readbacks_.end(),
239245
[&](const Readback& r) { return r.position >= state_.rect_index; });
240246
return PaintRegion(rects_, state_.rect_index, rects_->size(), has_readback,
241-
state_.has_texture);
247+
state_.has_volatile_layer);
242248
}
243249

244250
void DiffContext::AddDamage(const PaintRegion& damage) {

flow/diff_context.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,18 @@ class DiffContext {
107107

108108
bool IsSubtreeDirty() const { return state_.dirty; }
109109

110-
// Marks that current subtree contains a TextureLayer. This is needed to
111-
// ensure that we'll Diff the TextureLayer even if inside retained layer.
112-
void MarkSubtreeHasTextureLayer();
110+
// Marks that current subtree contains a volatile layer. A volatile layer will
111+
// do diffing even if it is a retained subtree. Necessary for TextureLayer
112+
// and PlatformViewLayer.
113+
void MarkSubtreeHasVolatileLayer();
113114

114115
// Add layer bounds to current paint region; rect is in "local" (layer)
115116
// coordinates.
116117
void AddLayerBounds(const SkRect& rect);
117118

119+
// Marks entire frame as dirty.
120+
void RepaintEntireFrame();
121+
118122
// Add entire paint region of retained layer for current subtree. This can
119123
// only be used in subtrees that are not dirty, otherwise ancestor transforms
120124
// or clips may result in different paint region.
@@ -231,7 +235,7 @@ class DiffContext {
231235
bool has_filter_bounds_adjustment = false;
232236

233237
// Whether there is a texture layer in this subtree.
234-
bool has_texture = false;
238+
bool has_volatile_layer = false;
235239
};
236240

237241
void MakeTransformIntegral(DisplayListMatrixClipState& matrix_clip);

flow/layers/container_layer.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ void ContainerLayer::DiffChildren(DiffContext* context,
7878
auto prev_layer = prev_layers[i_prev];
7979
auto paint_region = context->GetOldLayerPaintRegion(prev_layer.get());
8080
if (layer == prev_layer && !paint_region.has_readback() &&
81-
!paint_region.has_texture()) {
81+
!paint_region.has_volatile_layer()) {
8282
// for retained layers, stop processing the subtree and add existing
8383
// region; We know current subtree is not dirty (every ancestor up to
8484
// here matches) so the retained subtree will render identically to

flow/layers/platform_view_layer.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ PlatformViewLayer::PlatformViewLayer(const SkPoint& offset,
1313
int64_t view_id)
1414
: offset_(offset), size_(size), view_id_(view_id) {}
1515

16+
void PlatformViewLayer::Diff(DiffContext* context, const Layer* old_layer) {
17+
DiffContext::AutoSubtreeRestore subtree(context);
18+
// Ensure that Diff is called again even if this layer is in retained subtree.
19+
context->MarkSubtreeHasVolatileLayer();
20+
// Partial repaint is disabled when platform view is present. This will also
21+
// set whole frame as the layer paint region, which will ensure full repaint
22+
// when the layer is removed.
23+
context->RepaintEntireFrame();
24+
context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion());
25+
}
26+
1627
void PlatformViewLayer::Preroll(PrerollContext* context) {
1728
set_paint_bounds(SkRect::MakeXYWH(offset_.x(), offset_.y(), size_.width(),
1829
size_.height()));

flow/layers/platform_view_layer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class PlatformViewLayer : public Layer {
1616
public:
1717
PlatformViewLayer(const SkPoint& offset, const SkSize& size, int64_t view_id);
1818

19+
void Diff(DiffContext* context, const Layer* old_layer) override;
1920
void Preroll(PrerollContext* context) override;
2021
void Paint(PaintContext& context) const override;
2122

flow/layers/platform_view_layer_unittests.cc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "flutter/flow/layers/platform_view_layer.h"
77
#include "flutter/flow/layers/transform_layer.h"
88

9+
#include "flutter/flow/testing/diff_context_test.h"
910
#include "flutter/flow/testing/layer_test.h"
1011
#include "flutter/flow/testing/mock_embedder.h"
1112
#include "flutter/flow/testing/mock_layer.h"
@@ -139,5 +140,45 @@ TEST_F(PlatformViewLayerTest, StateTransfer) {
139140
transform_layer1->Paint(paint_ctx);
140141
}
141142

143+
using PlatformViewLayerDiffTest = DiffContextTest;
144+
145+
TEST_F(PlatformViewLayerDiffTest, PlatformViewRetainedLayer) {
146+
MockLayerTree tree1(SkISize::Make(800, 600));
147+
auto container = std::make_shared<ContainerLayer>();
148+
tree1.root()->Add(container);
149+
auto layer = std::make_shared<PlatformViewLayer>(SkPoint::Make(100, 100),
150+
SkSize::Make(100, 100), 0);
151+
container->Add(layer);
152+
153+
MockLayerTree tree2(SkISize::Make(800, 600));
154+
tree2.root()->Add(container); // retained layer
155+
156+
auto damage = DiffLayerTree(tree1, MockLayerTree(SkISize::Make(800, 600)));
157+
EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 800, 600));
158+
159+
damage = DiffLayerTree(tree2, tree1);
160+
EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 800, 600));
161+
}
162+
163+
TEST_F(PlatformViewLayerDiffTest, FullRepaintAfterRemovingLayer) {
164+
MockLayerTree tree1(SkISize::Make(800, 600));
165+
auto container = std::make_shared<ContainerLayer>();
166+
tree1.root()->Add(container);
167+
auto layer = std::make_shared<PlatformViewLayer>(SkPoint::Make(100, 100),
168+
SkSize::Make(100, 100), 0);
169+
container->Add(layer);
170+
171+
auto damage = DiffLayerTree(tree1, MockLayerTree(SkISize::Make(800, 600)));
172+
EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 800, 600));
173+
174+
// Second layer tree with the PlatformViewLayer removed.
175+
MockLayerTree tree2(SkISize::Make(800, 600));
176+
auto container2 = std::make_shared<ContainerLayer>();
177+
tree2.root()->Add(container2);
178+
179+
damage = DiffLayerTree(tree2, tree1);
180+
EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 800, 600));
181+
}
182+
142183
} // namespace testing
143184
} // namespace flutter

flow/layers/texture_layer.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void TextureLayer::Diff(DiffContext* context, const Layer* old_layer) {
3434
// TextureLayer is inside retained layer.
3535
// See ContainerLayer::DiffChildren
3636
// https://github.com/flutter/flutter/issues/92925
37-
context->MarkSubtreeHasTextureLayer();
37+
context->MarkSubtreeHasVolatileLayer();
3838
context->AddLayerBounds(SkRect::MakeXYWH(offset_.x(), offset_.y(),
3939
size_.width(), size_.height()));
4040
context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion());

flow/paint_region.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ class PaintRegion {
3030
size_t from,
3131
size_t to,
3232
bool has_readback,
33-
bool has_texture)
33+
bool has_volatile_layer)
3434
: rects_(std::move(rects)),
3535
from_(from),
3636
to_(to),
3737
has_readback_(has_readback),
38-
has_texture_(has_texture) {}
38+
has_volatile_layer_(has_volatile_layer) {}
3939

4040
std::vector<SkRect>::const_iterator begin() const {
4141
FML_DCHECK(is_valid());
@@ -56,16 +56,16 @@ class PaintRegion {
5656
// that performs readback
5757
bool has_readback() const { return has_readback_; }
5858

59-
// Returns whether there is a TextureLayer in subtree represented by this
60-
// region.
61-
bool has_texture() const { return has_texture_; }
59+
// Returns whether there is a TextureLayer or PlatformViewLayer in subtree
60+
// represented by this region.
61+
bool has_volatile_layer() const { return has_volatile_layer_; }
6262

6363
private:
6464
std::shared_ptr<std::vector<SkRect>> rects_;
6565
size_t from_ = 0;
6666
size_t to_ = 0;
6767
bool has_readback_ = false;
68-
bool has_texture_ = false;
68+
bool has_volatile_layer_ = false;
6969
};
7070

7171
} // namespace flutter

shell/common/rasterizer.cc

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -743,17 +743,9 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe(
743743
// when leaf layer tracing is enabled we wish to repaint the whole frame
744744
// for accurate performance metrics.
745745
if (frame->framebuffer_info().supports_partial_repaint) {
746-
// Disable partial repaint if external_view_embedder_ SubmitFlutterView is
747-
// involved - ExternalViewEmbedder unconditionally clears the entire
748-
// surface and also partial repaint with platform view present is
749-
// something that still need to be figured out.
750-
bool force_full_repaint =
751-
external_view_embedder_ &&
752-
(!raster_thread_merger_ || raster_thread_merger_->IsMerged());
753-
754746
damage = std::make_unique<FrameDamage>();
755747
auto existing_damage = frame->framebuffer_info().existing_damage;
756-
if (existing_damage.has_value() && !force_full_repaint) {
748+
if (existing_damage.has_value()) {
757749
damage->SetPreviousLayerTree(GetLastLayerTree(view_id));
758750
damage->AddAdditionalDamage(existing_damage.value());
759751
damage->SetClipAlignment(

0 commit comments

Comments
 (0)