Flutter Engine
 
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 std::unordered_map<int64_t, DlRect> overlay_layers;
20
21 auto current_frame_view_count = composition_order.size();
22
23 // Restore the clip context after exiting this method since it's changed
24 // below.
25 DlAutoCanvasRestore save(background_canvas, /*do_save=*/true);
26
27 for (size_t i = 0; i < current_frame_view_count; i++) {
28 int64_t view_id = composition_order[i];
29 EmbedderViewSlice* slice = slices.at(view_id).get();
30 if (slice->canvas() == nullptr) {
31 continue;
32 }
33
34 slice->end_recording();
35
36 DlRect full_joined_rect;
37
38 // Determinate if Flutter UI intersects with any of the previous
39 // platform views stacked by z position.
40 //
41 // This is done by querying the r-tree that holds the records for the
42 // picture recorder corresponding to the flow layers added after a platform
43 // view layer.
44 for (int j = i; j >= 0; j--) {
45 int64_t current_view_id = composition_order[j];
46 auto maybe_rect = view_rects.find(current_view_id);
47 FML_DCHECK(maybe_rect != view_rects.end());
48 if (maybe_rect == view_rects.end()) {
49 continue;
50 }
51
52 const DlRect current_view_rect = maybe_rect->second;
53 const DlIRect rounded_in_platform_view_rect =
54 DlIRect::RoundIn(current_view_rect);
55 const DlRect rounded_out_platform_view_rect =
56 DlRect::RoundOut(current_view_rect);
57
58 // Each rect corresponds to a native view that renders Flutter UI.
59 std::vector<DlIRect> intersection_rects =
60 slice->region(current_view_rect).getRects();
61
62 // Ignore intersections of single width/height on the edge of the platform
63 // view.
64 // This is to address the following performance issue when interleaving
65 // adjacent platform views and layers: Since we `roundOut` both platform
66 // view rects and the layer rects, as long as the coordinate is
67 // fractional, there will be an intersection of a single pixel width (or
68 // height) after rounding out, even if they do not intersect before
69 // rounding out. We have to round out both platform view rect and the
70 // layer rect. Rounding in platform view rect will result in missing pixel
71 // on the intersection edge. Rounding in layer rect will result in missing
72 // pixel on the edge of the layer on top of the platform view.
73 for (auto it = intersection_rects.begin(); it != intersection_rects.end();
74 /*no-op*/) {
75 // If intersection_rect does not intersect with the *rounded in*
76 // platform view rect, then the intersection must be a single pixel
77 // width (or height) on edge.
78 if (!it->IntersectsWithRect(rounded_in_platform_view_rect)) {
79 it = intersection_rects.erase(it);
80 } else {
81 ++it;
82 }
83 }
84
85 // Limit the number of native views, so it doesn't grow forever.
86 //
87 // In this case, the rects are merged into a single one that is the union
88 // of all the rects.
89 DlRect partial_joined_rect;
90 for (const DlIRect& rect : intersection_rects) {
91 partial_joined_rect = partial_joined_rect.Union(DlRect::Make(rect));
92 }
93
94 // Get the intersection rect with the `current_view_rect`,
95 if (partial_joined_rect.IntersectsWithRect(
96 rounded_out_platform_view_rect)) {
97 // Join the `partial_joined_rect` into `full_joined_rect` to get the
98 // rect above the current `slice`, only if it intersects the indicated
99 // view. This should always be the case because we just deleted any
100 // rects that don't intersect the "rounded-in" view, so they must
101 // all intersect the "rounded-out" view (or the partial join could
102 // be empty in which case this would be a NOP). Either way, the
103 // penalty for not checking the return value of the intersect method
104 // would be to join a non-overlapping rectangle into the overlay
105 // bounds - if the above implementation ever changes - so we check it.
106 full_joined_rect = full_joined_rect.Union(partial_joined_rect);
107 }
108 }
109
110 if (!full_joined_rect.IsEmpty()) {
111 overlay_layers.insert({view_id, full_joined_rect});
112
113 // Clip the background canvas, so it doesn't contain any of the pixels
114 // drawn on the overlay layer.
115 background_canvas->ClipRect(full_joined_rect, DlClipOp::kDifference);
116 }
117 slice->render_into(background_canvas);
118 }
119
120 // Manually trigger the DlAutoCanvasRestore before we submit the frame
121 save.Restore();
122
123 return overlay_layers;
124}
125
126} // 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)
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:297
constexpr TRect Union(const TRect &o) const
Definition rect.h:513
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
Definition rect.h:157
constexpr bool IntersectsWithRect(const TRect &o) const
Definition rect.h:546
RoundIn(const TRect< U > &r)
Definition rect.h:687
RoundOut(const TRect< U > &r)
Definition rect.h:679