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

Commit 63a45e2

Browse files
committed
Reduce number of surfaces when presenting platform views
1 parent 97292b1 commit 63a45e2

File tree

11 files changed

+323
-227
lines changed

11 files changed

+323
-227
lines changed

flow/embedded_views.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ void DisplayListEmbedderViewSlice::end_recording() {
2121
builder_ = nullptr;
2222
}
2323

24-
std::list<SkRect> DisplayListEmbedderViewSlice::searchNonOverlappingDrawnRects(
25-
const SkRect& query) const {
26-
return display_list_->rtree()->searchAndConsolidateRects(query);
24+
const DlRegion& DisplayListEmbedderViewSlice::getRegion() const {
25+
return display_list_->rtree()->region();
2726
}
2827

2928
void DisplayListEmbedderViewSlice::render_into(DlCanvas* canvas) {

flow/embedded_views.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,20 +337,23 @@ class EmbedderViewSlice {
337337
virtual ~EmbedderViewSlice() = default;
338338
virtual DlCanvas* canvas() = 0;
339339
virtual void end_recording() = 0;
340-
virtual std::list<SkRect> searchNonOverlappingDrawnRects(
341-
const SkRect& query) const = 0;
340+
virtual const DlRegion& getRegion() const = 0;
341+
DlRegion region(const SkRect& query) const {
342+
return DlRegion::MakeIntersection(getRegion(), DlRegion(query.roundOut()));
343+
}
344+
342345
virtual void render_into(DlCanvas* canvas) = 0;
343346
};
344347

345348
class DisplayListEmbedderViewSlice : public EmbedderViewSlice {
346349
public:
347-
DisplayListEmbedderViewSlice(SkRect view_bounds);
350+
explicit DisplayListEmbedderViewSlice(SkRect view_bounds);
348351
~DisplayListEmbedderViewSlice() override = default;
349352

350353
DlCanvas* canvas() override;
351354
void end_recording() override;
352-
std::list<SkRect> searchNonOverlappingDrawnRects(
353-
const SkRect& query) const override;
355+
const DlRegion& getRegion() const override;
356+
354357
void render_into(DlCanvas* canvas) override;
355358
void dispatch(DlOpReceiver& receiver);
356359
bool is_empty();

shell/platform/android/external_view_embedder/external_view_embedder.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,15 @@ void AndroidExternalViewEmbedder::SubmitFrame(
104104
// The rect above the `current_view_rect`
105105
SkRect partial_joined_rect = SkRect::MakeEmpty();
106106
// Each rect corresponds to a native view that renders Flutter UI.
107-
std::list<SkRect> intersection_rects =
108-
slice->searchNonOverlappingDrawnRects(current_view_rect);
107+
std::vector<SkIRect> intersection_rects =
108+
slice->region(current_view_rect).getRects();
109109

110110
// Limit the number of native views, so it doesn't grow forever.
111111
//
112112
// In this case, the rects are merged into a single one that is the union
113113
// of all the rects.
114-
for (const SkRect& rect : intersection_rects) {
115-
partial_joined_rect.join(rect);
114+
for (const SkIRect& rect : intersection_rects) {
115+
partial_joined_rect.join(SkRect::Make(rect));
116116
}
117117
// Get the intersection rect with the `current_view_rect`,
118118
partial_joined_rect.intersect(current_view_rect);

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -694,8 +694,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
694694
for (size_t j = i + 1; j > 0; j--) {
695695
int64_t current_platform_view_id = composition_order_[j - 1];
696696
SkRect platform_view_rect = GetPlatformViewRect(current_platform_view_id);
697-
std::list<SkRect> intersection_rects =
698-
slice->searchNonOverlappingDrawnRects(platform_view_rect);
697+
std::vector<SkIRect> intersection_rects = slice->region(platform_view_rect).getRects();
699698
auto allocation_size = intersection_rects.size();
700699

701700
// For testing purposes, the overlay id is used to find the overlay view.
@@ -708,27 +707,22 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
708707
// TODO(egarciad): Consider making this configurable.
709708
// https://github.com/flutter/flutter/issues/52510
710709
if (allocation_size > kMaxLayerAllocations) {
711-
SkRect joined_rect = SkRect::MakeEmpty();
712-
for (const SkRect& rect : intersection_rects) {
710+
SkIRect joined_rect = SkIRect::MakeEmpty();
711+
for (const SkIRect& rect : intersection_rects) {
713712
joined_rect.join(rect);
714713
}
715714
// Replace the rects in the intersection rects list for a single rect that is
716715
// the union of all the rects in the list.
717716
intersection_rects.clear();
718717
intersection_rects.push_back(joined_rect);
719718
}
720-
for (SkRect& joined_rect : intersection_rects) {
719+
for (SkIRect& joined_rect : intersection_rects) {
721720
// Get the intersection rect between the current rect
722721
// and the platform view rect.
723-
joined_rect.intersect(platform_view_rect);
724-
// Subpixels in the platform may not align with the canvas subpixels.
725-
// To workaround it, round the floating point bounds and make the rect slightly larger.
726-
// For example, {0.3, 0.5, 3.1, 4.7} becomes {0, 0, 4, 5}.
727-
joined_rect.setLTRB(std::floor(joined_rect.left()), std::floor(joined_rect.top()),
728-
std::ceil(joined_rect.right()), std::ceil(joined_rect.bottom()));
722+
joined_rect.intersect(platform_view_rect.roundOut());
729723
// Clip the background canvas, so it doesn't contain any of the pixels drawn
730724
// on the overlay layer.
731-
background_canvas->ClipRect(joined_rect, DlCanvas::ClipOp::kDifference);
725+
background_canvas->ClipRect(SkRect::Make(joined_rect), DlCanvas::ClipOp::kDifference);
732726
// Get a new host layer.
733727
std::shared_ptr<FlutterPlatformViewLayer> layer = GetLayer(gr_context, //
734728
ios_context, //
@@ -804,7 +798,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
804798
GrDirectContext* gr_context,
805799
const std::shared_ptr<IOSContext>& ios_context,
806800
EmbedderViewSlice* slice,
807-
SkRect rect,
801+
SkIRect rect,
808802
int64_t view_id,
809803
int64_t overlay_id) {
810804
FML_DCHECK(flutter_view_);
@@ -837,7 +831,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
837831
DlCanvas* overlay_canvas = frame->Canvas();
838832
int restore_count = overlay_canvas->GetSaveCount();
839833
overlay_canvas->Save();
840-
overlay_canvas->ClipRect(rect);
834+
overlay_canvas->ClipRect(SkRect::Make(rect));
841835
overlay_canvas->Clear(DlColor::kTransparent());
842836
slice->render_into(overlay_canvas);
843837
overlay_canvas->RestoreToCount(restore_count);

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ class FlutterPlatformViewsController {
310310
std::shared_ptr<FlutterPlatformViewLayer> GetLayer(GrDirectContext* gr_context,
311311
const std::shared_ptr<IOSContext>& ios_context,
312312
EmbedderViewSlice* slice,
313-
SkRect rect,
313+
SkIRect rect,
314314
int64_t view_id,
315315
int64_t overlay_id);
316316
// Removes overlay views and platform views that aren't needed in the current frame.

shell/platform/embedder/embedder_external_view.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ EmbedderExternalView::~EmbedderExternalView() = default;
4343

4444
EmbedderExternalView::RenderTargetDescriptor
4545
EmbedderExternalView::CreateRenderTargetDescriptor() const {
46-
return {view_identifier_, render_surface_size_};
46+
return RenderTargetDescriptor(render_surface_size_);
4747
}
4848

4949
DlCanvas* EmbedderExternalView::GetCanvas() {
@@ -62,9 +62,8 @@ bool EmbedderExternalView::HasPlatformView() const {
6262
return view_identifier_.platform_view_id.has_value();
6363
}
6464

65-
std::list<SkRect> EmbedderExternalView::GetEngineRenderedContentsRegion(
66-
const SkRect& query) const {
67-
return slice_->searchNonOverlappingDrawnRects(query);
65+
const DlRegion& EmbedderExternalView::GetDlRegion() const {
66+
return slice_->getRegion();
6867
}
6968

7069
bool EmbedderExternalView::HasEngineRenderedContents() {
@@ -87,7 +86,8 @@ const EmbeddedViewParams* EmbedderExternalView::GetEmbeddedViewParams() const {
8786
return embedded_view_params_.get();
8887
}
8988

90-
bool EmbedderExternalView::Render(const EmbedderRenderTarget& render_target) {
89+
bool EmbedderExternalView::Render(const EmbedderRenderTarget& render_target,
90+
bool clear_surface) {
9191
TRACE_EVENT0("flutter", "EmbedderExternalView::Render");
9292
TryEndRecording();
9393
FML_DCHECK(HasEngineRenderedContents())
@@ -124,7 +124,9 @@ bool EmbedderExternalView::Render(const EmbedderRenderTarget& render_target) {
124124
DlSkCanvasAdapter dl_canvas(canvas);
125125
int restore_count = dl_canvas.GetSaveCount();
126126
dl_canvas.SetTransform(surface_transformation_);
127-
dl_canvas.Clear(DlColor::kTransparent());
127+
if (clear_surface) {
128+
dl_canvas.Clear(DlColor::kTransparent());
129+
}
128130
slice_->render_into(&dl_canvas);
129131
dl_canvas.RestoreToCount(restore_count);
130132
dl_canvas.Flush();

shell/platform/embedder/embedder_external_view.h

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,28 +46,23 @@ class EmbedderExternalView {
4646
};
4747

4848
struct RenderTargetDescriptor {
49-
ViewIdentifier view_identifier;
5049
SkISize surface_size;
5150

52-
RenderTargetDescriptor(ViewIdentifier p_view_identifier,
53-
SkISize p_surface_size)
54-
: view_identifier(p_view_identifier), surface_size(p_surface_size) {}
51+
explicit RenderTargetDescriptor(const SkISize& p_surface_size)
52+
: surface_size(p_surface_size) {}
5553

5654
struct Hash {
5755
constexpr std::size_t operator()(
5856
const RenderTargetDescriptor& desc) const {
5957
return fml::HashCombine(desc.surface_size.width(),
60-
desc.surface_size.height(),
61-
ViewIdentifier::Hash{}(desc.view_identifier));
58+
desc.surface_size.height());
6259
}
6360
};
6461

6562
struct Equal {
6663
bool operator()(const RenderTargetDescriptor& lhs,
6764
const RenderTargetDescriptor& rhs) const {
68-
return lhs.surface_size == rhs.surface_size &&
69-
ViewIdentifier::Equal{}(lhs.view_identifier,
70-
rhs.view_identifier);
65+
return lhs.surface_size == rhs.surface_size;
7166
}
7267
};
7368
};
@@ -107,9 +102,10 @@ class EmbedderExternalView {
107102

108103
SkISize GetRenderSurfaceSize() const;
109104

110-
bool Render(const EmbedderRenderTarget& render_target);
105+
bool Render(const EmbedderRenderTarget& render_target,
106+
bool clear_surface = true);
111107

112-
std::list<SkRect> GetEngineRenderedContentsRegion(const SkRect& query) const;
108+
const DlRegion& GetDlRegion() const;
113109

114110
private:
115111
// End the recording of the slice.

0 commit comments

Comments
 (0)