1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
cc / slim / layer_tree_impl.h [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_SLIM_LAYER_TREE_IMPL_H_
#define CC_SLIM_LAYER_TREE_IMPL_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/component_export.h"
#include "base/containers/circular_deque.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "cc/resources/ui_resource_client.h"
#include "cc/resources/ui_resource_manager.h"
#include "cc/slim/damage_data.h"
#include "cc/slim/frame_sink_impl_client.h"
#include "cc/slim/layer_tree.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/quads/offset_tag.h"
#include "components/viz/common/surfaces/child_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/surface_range.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/overlay_transform.h"
namespace cc {
class UIResourceManager;
} // namespace cc
namespace viz {
class ClientResourceProvider;
class CompositorRenderPass;
} // namespace viz
namespace cc::slim {
class FrameSinkImpl;
class TestLayerTreeImpl;
class SurfaceLayer;
struct FrameData;
// Slim implementation of LayerTree.
class COMPONENT_EXPORT(CC_SLIM) LayerTreeImpl : public LayerTree,
public FrameSinkImplClient {
public:
~LayerTreeImpl() override;
// LayerTree.
cc::UIResourceManager* GetUIResourceManager() override;
void SetViewportRectAndScale(
const gfx::Rect& device_viewport_rect,
float device_scale_factor,
const viz::LocalSurfaceId& local_surface_id) override;
void set_background_color(SkColor4f color) override;
void SetVisible(bool visible) override;
bool IsVisible() const override;
void RequestPresentationTimeForNextFrame(
PresentationCallback callback) override;
void RequestSuccessfulPresentationTimeForNextFrame(
SuccessfulCallback callback) override;
void set_display_transform_hint(gfx::OverlayTransform hint) override;
void RequestCopyOfOutput(
std::unique_ptr<viz::CopyOutputRequest> request) override;
base::OnceClosure DeferBeginFrame() override;
void SetNeedsAnimate() override;
void MaybeCompositeNow() override;
const scoped_refptr<Layer>& root() const override;
void SetRoot(scoped_refptr<Layer> root) override;
void SetFrameSink(std::unique_ptr<FrameSink> sink) override;
void ReleaseLayerTreeFrameSink() override;
std::unique_ptr<ScopedKeepSurfaceAlive> CreateScopedKeepSurfaceAlive(
const viz::SurfaceId& surface_id) override;
const SurfaceRangesAndCounts& GetSurfaceRangesForTesting() const override;
void SetNeedsRedrawForTesting() override;
// FrameSinkImplClient.
bool BeginFrame(const viz::BeginFrameArgs& args,
viz::CompositorFrame& out_frame,
base::flat_set<viz::ResourceId>& out_resource_ids,
viz::HitTestRegionList& out_hit_test_region_list) override;
void DidReceiveCompositorFrameAck() override;
void DidSubmitCompositorFrame() override;
void DidPresentCompositorFrame(
uint32_t frame_token,
const viz::FrameTimingDetails& details) override;
void DidLoseLayerTreeFrameSink() override;
// Internal methods called by Layers.
void NotifyTreeChanged();
viz::ClientResourceProvider* GetClientResourceProvider();
viz::ResourceId GetVizResourceId(cc::UIResourceId id);
bool IsUIResourceOpaque(int resource_id);
gfx::Size GetUIResourceSize(int resource_id);
void AddSurfaceRange(const viz::SurfaceRange& range);
void RemoveSurfaceRange(const viz::SurfaceRange& range);
void RegisterOffsetTag(const viz::OffsetTag& tag, SurfaceLayer* owner);
void UnregisterOffsetTag(const viz::OffsetTag& tag, SurfaceLayer* owner);
private:
friend class LayerTree;
friend class TestLayerTreeImpl;
struct PresentationCallbackInfo {
PresentationCallbackInfo(
uint32_t frame_token,
std::vector<PresentationCallback> presentation_callbacks,
std::vector<SuccessfulCallback> success_callbacks);
~PresentationCallbackInfo();
PresentationCallbackInfo(PresentationCallbackInfo&&);
PresentationCallbackInfo& operator=(PresentationCallbackInfo&&);
PresentationCallbackInfo(const PresentationCallbackInfo&) = delete;
PresentationCallbackInfo& operator=(const PresentationCallbackInfo&) =
delete;
uint32_t frame_token = 0u;
std::vector<PresentationCallback> presentation_callbacks;
std::vector<SuccessfulCallback> success_callbacks;
};
LayerTreeImpl(LayerTreeClient* client,
uint32_t num_unneeded_begin_frame_before_stop,
int min_occlusion_tracking_dimension);
// Request a new frame sink from the client if a new frame sink is needed and
// there isn't already a pending request.
void MaybeRequestFrameSink();
// Matches `DeferBeginFrame` that reduces number of outstanding requests to
// defer (ie stop) BeginFrames to the client.
void ReleaseDeferBeginFrame();
void UpdateNeedsBeginFrame();
void SetClientNeedsOneBeginFrame();
// Call this whenever there are tree or layer changes that needs to be
// submitted in a CompositorFrame.
void SetNeedsDraw();
bool NeedsDraw() const;
bool NeedsBeginFrames() const;
void GenerateCompositorFrame(
const viz::BeginFrameArgs& args,
viz::CompositorFrame& out_frame,
base::flat_set<viz::ResourceId>& out_resource_ids,
viz::HitTestRegionList& out_hit_test_region_list);
void Draw(Layer& layer,
viz::CompositorRenderPass& render_pass,
FrameData& data,
const gfx::Transform& parent_transform_to_root,
const gfx::Transform& parent_transform_to_target,
const gfx::RectF* parent_clip_in_target,
const gfx::RectF& clip_in_parent,
float opacity);
void DrawChildrenAndAppendQuads(Layer& layer,
viz::CompositorRenderPass& render_pass,
FrameData& data,
const gfx::Transform& transform_to_root,
const gfx::Transform& transform_to_target,
const gfx::RectF* clip_in_target,
const gfx::RectF& clip_in_layer,
float opacity);
// Updates the `FrameData::occlusion_in_target` field with the visible_rect.
// Return if layer's AppendQuads should happen. May reduce `visible_rect` if
// it's partially occluded.
bool UpdateOcclusionRect(Layer& layer,
FrameData& data,
const gfx::Transform& transform_to_target,
float opacity,
const gfx::RectF& visible_rectf_in_target,
gfx::RectF& visible_rect);
// Compute and update `damage_rect` and `has_damage_from_contributing_content`
// of `render_pass`. `data.render_pass_damage` should be the newly computed
// damage data of the frame being produced. Damage data from previous frame is
// retrieved from `damage_from_previous_frame_`. `data.render_pass_damage` is
// moved into `data.current_frame_data` and then cleared, to avoid copying
// data.
void ProcessDamageForRenderPass(viz::CompositorRenderPass& render_pass,
FrameData& data);
const raw_ptr<LayerTreeClient> client_;
const uint32_t num_unneeded_begin_frame_before_stop_;
const int min_occlusion_tracking_dimension_;
std::unique_ptr<FrameSinkImpl> frame_sink_;
cc::UIResourceManager ui_resource_manager_;
viz::ChildLocalSurfaceIdAllocator local_surface_id_allocator_;
bool frame_sink_request_pending_ = false;
// Indicates there is an `UpdateNeedsBeginFrame` call pending in the current
// task lower in the stack frame. This is to prevent unnecessary back and
// forth flips.
bool update_needs_begin_frame_pending_ = false;
// Set when client requests a begin frame viz `SetNeedsAnimate`.
bool client_needs_one_begin_frame_ = false;
// Set to indicate there are layer or tree changes that's not yet submitted
// in a CompositorFrame.
bool needs_draw_ = false;
bool visible_ = false;
uint32_t num_defer_begin_frame_ = 0u;
// Number of begin frames with no draw. Stop requesting begin frames after
// this reaches `num_unneeded_begin_frame_before_stop_`.
// TODO(boliu): Move this logic to DelayedScheduler.
uint32_t num_begin_frames_with_no_draw_ =
num_unneeded_begin_frame_before_stop_;
gfx::Rect device_viewport_rect_;
float device_scale_factor_ = 1.0f;
SkColor4f background_color_ = SkColors::kWhite;
SurfaceRangesAndCounts referenced_surfaces_;
// Tracks OffsetTags and which SurfaceLayer they were registered with.
base::flat_map<viz::OffsetTag, raw_ptr<SurfaceLayer>> registered_offset_tags_;
viz::FrameTokenGenerator next_frame_token_;
gfx::OverlayTransform display_transform_hint_ = gfx::OVERLAY_TRANSFORM_NONE;
std::vector<std::unique_ptr<viz::CopyOutputRequest>>
copy_requests_for_next_frame_;
// These are added to `pending_presentation_callbacks_` in the next frame.
std::vector<PresentationCallback> presentation_callback_for_next_frame_;
std::vector<SuccessfulCallback> success_callback_for_next_frame_;
FrameDamageData damage_from_previous_frame_;
base::circular_deque<PresentationCallbackInfo>
pending_presentation_callbacks_;
// Destroy Layers before other fields that might be accessed by Layers.
scoped_refptr<Layer> root_;
base::WeakPtrFactory<LayerTreeImpl> weak_factory_{this};
};
} // namespace cc::slim
#endif // CC_SLIM_LAYER_TREE_IMPL_H_