Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
view_slicer.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
6
7#include <unordered_map>
9#include "fml/logging.h"
10
11namespace flutter {
12
13std::unordered_map<int64_t, DlRect> SliceViews(
14 DlCanvas* background_canvas,
15 const std::vector<int64_t>& composition_order,
16 const std::unordered_map<int64_t, std::unique_ptr<EmbedderViewSlice>>&
17 slices,
18 const std::unordered_map<int64_t, DlRect>& view_rects,
19 const std::unordered_set<int64_t>& views_with_underlay_preserved) {
20 std::unordered_map<int64_t, DlRect> overlay_layers;
21
22 auto current_frame_view_count = composition_order.size();
23
24 // Restore the clip context after exiting this method since it's changed
25 // below.
26 DlAutoCanvasRestore save(background_canvas, /*do_save=*/true);
27
28 for (size_t i = 0; i < current_frame_view_count; i++) {
29 int64_t view_id = composition_order[i];
30 EmbedderViewSlice* slice = slices.at(view_id).get();
31 if (slice->canvas() == nullptr) {
32 continue;
33 }
34
35 slice->end_recording();
36
37 DlRect full_joined_rect;
38
39 // Determinate if Flutter UI intersects with any of the previous
40 // platform views stacked by z position.
41 //
42 // This is done by querying the r-tree that holds the records for the
43 // picture recorder corresponding to the flow layers added after a platform
44 // view layer.
45 for (int j = i; j >= 0; j--) {
46 int64_t current_view_id = composition_order[j];
47 auto maybe_rect = view_rects.find(current_view_id);
48 FML_DCHECK(maybe_rect != view_rects.end());
49 if (maybe_rect == view_rects.end()) {
50 continue;
51 }
52
53 const DlRect current_view_rect = maybe_rect->second;
54 const DlIRect rounded_in_platform_view_rect =
55 DlIRect::RoundIn(current_view_rect);
56 const DlRect rounded_out_platform_view_rect =
57 DlRect::RoundOut(current_view_rect);
58
59 // Each rect corresponds to a native view that renders Flutter UI.
60 std::vector<DlIRect> intersection_rects =
61 slice->region(current_view_rect).getRects();
62
63 // Ignore intersections of single width/height on the edge of the platform
64 // view.
65 // This is to address the following performance issue when interleaving
66 // adjacent platform views and layers: Since we `roundOut` both platform
67 // view rects and the layer rects, as long as the coordinate is
68 // fractional, there will be an intersection of a single pixel width (or
69 // height) after rounding out, even if they do not intersect before
70 // rounding out. We have to round out both platform view rect and the
71 // layer rect. Rounding in platform view rect will result in missing pixel
72 // on the intersection edge. Rounding in layer rect will result in missing
73 // pixel on the edge of the layer on top of the platform view.
74 for (auto it = intersection_rects.begin(); it != intersection_rects.end();
75 /*no-op*/) {
76 // If intersection_rect does not intersect with the *rounded in*
77 // platform view rect, then the intersection must be a single pixel
78 // width (or height) on edge.
79 if (!it->IntersectsWithRect(rounded_in_platform_view_rect)) {
80 it = intersection_rects.erase(it);
81 } else {
82 ++it;
83 }
84 }
85
86 // Limit the number of native views, so it doesn't grow forever.
87 //
88 // In this case, the rects are merged into a single one that is the union
89 // of all the rects.
90 DlRect partial_joined_rect;
91 for (const DlIRect& rect : intersection_rects) {
92 partial_joined_rect = partial_joined_rect.Union(DlRect::Make(rect));
93 }
94
95 // Get the intersection rect with the `current_view_rect`,
96 if (partial_joined_rect.IntersectsWithRect(
97 rounded_out_platform_view_rect)) {
98 // Join the `partial_joined_rect` into `full_joined_rect` to get the
99 // rect above the current `slice`, only if it intersects the indicated
100 // view. This should always be the case because we just deleted any
101 // rects that don't intersect the "rounded-in" view, so they must
102 // all intersect the "rounded-out" view (or the partial join could
103 // be empty in which case this would be a NOP). Either way, the
104 // penalty for not checking the return value of the intersect method
105 // would be to join a non-overlapping rectangle into the overlay
106 // bounds - if the above implementation ever changes - so we check it.
107 full_joined_rect = full_joined_rect.Union(partial_joined_rect);
108 }
109 }
110
111 if (!full_joined_rect.IsEmpty()) {
112 overlay_layers.insert({view_id, full_joined_rect});
113
114 // If overlay has a non-rect clip, we need to preserve the underlay in
115 // that area to show correctly after overlay is clipped behind the
116 // platform view
117 const bool preserve_underlay =
118 views_with_underlay_preserved.find(view_id) !=
119 views_with_underlay_preserved.end();
120 if (!preserve_underlay) {
121 // Clip the background canvas, so it doesn't contain any of the pixels
122 // drawn on the overlay layer.
123 background_canvas->ClipRect(full_joined_rect, DlClipOp::kDifference);
124 }
125 }
126 slice->render_into(background_canvas);
127 }
128
129 // Manually trigger the DlAutoCanvasRestore before we submit the frame
130 save.Restore();
131
132 return overlay_layers;
133}
134
135} // namespace flutter
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
virtual void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
std::vector< DlIRect > getRects(bool deband=true) const
Definition dl_region.cc:560
DlRegion region(const DlRect &query) const
virtual void render_into(DlCanvas *canvas)=0
virtual DlCanvas * canvas()=0
virtual void end_recording()=0
G_BEGIN_DECLS FlutterViewId view_id
#define FML_DCHECK(condition)
Definition logging.h:122
std::unordered_map< int64_t, DlRect > SliceViews(DlCanvas *background_canvas, const std::vector< int64_t > &composition_order, const std::unordered_map< int64_t, std::unique_ptr< EmbedderViewSlice > > &slices, const std::unordered_map< int64_t, DlRect > &view_rects, const std::unordered_set< int64_t > &views_with_underlay_preserved)
Compute the required overlay layers and clip the view slices according to the size and position of th...
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition rect.h:331
constexpr TRect Union(const TRect &o) const
Definition rect.h:547
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
Definition rect.h:181
constexpr bool IntersectsWithRect(const TRect &o) const
Definition rect.h:580
RoundIn(const TRect< U > &r)
Definition rect.h:721
RoundOut(const TRect< U > &r)
Definition rect.h:713