File: ca_renderer_layer_tree.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (332 lines) | stat: -rw-r--r-- 12,874 bytes parent folder | download | duplicates (2)
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_ACCELERATED_WIDGET_MAC_CA_RENDERER_LAYER_TREE_H_
#define UI_ACCELERATED_WIDGET_MAC_CA_RENDERER_LAYER_TREE_H_

#include <CoreVideo/CoreVideo.h>
#include <IOSurface/IOSurfaceRef.h>
#include <QuartzCore/QuartzCore.h>

#include <list>
#include <memory>
#include <optional>
#include <unordered_map>

#include "base/apple/scoped_cftyperef.h"
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac_export.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/rrect_f.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/hdr_metadata.h"
#include "ui/gfx/mac/io_surface.h"
#include "ui/gfx/video_types.h"

@class AVSampleBufferDisplayLayer;

namespace ui {

ACCELERATED_WIDGET_MAC_EXPORT BASE_DECLARE_FEATURE(
    kFullscreenLowPowerBackdropMac);

struct CARendererLayerParams;

enum class CALayerType {
  // A CALayer with contents set to an IOSurface by setContents.
  kDefault,
  // An AVSampleBufferDisplayLayer.
  kVideo,
  // A CAMetalLayer that copies half-float or 10-bit IOSurfaces.
  kHDRCopier,
};

// The CARendererLayerTree will construct a hierarchy of CALayers from a linear
// list provided by the CoreAnimation renderer using the algorithm and structure
// referenced described in
// https://docs.google.com/document/d/1DtSN9zzvCF44_FQPM7ie01UxGHagQ66zfF5L9HnigQY/edit?usp=sharing
class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
 public:
  CARendererLayerTree(bool allow_av_sample_buffer_display_layer,
                      bool allow_solid_color_layers,
                      id<MTLDevice> metal_device = nil);

  CARendererLayerTree(const CARendererLayerTree&) = delete;
  CARendererLayerTree& operator=(const CARendererLayerTree&) = delete;

  // This will remove all CALayers from this tree from their superlayer.
  ~CARendererLayerTree();

  // Append the description of a new CALayer to the tree. This will not
  // create any new CALayers until CommitScheduledCALayers is called. This
  // cannot be called anymore after CommitScheduledCALayers has been called.
  bool ScheduleCALayer(const CARendererLayerParams& params);

  void SetDisplayHDRHeadroom(float display_hdr_headroom) {
    display_hdr_headroom_ = display_hdr_headroom;
  }

  // Create a CALayer tree for the scheduled layers, and set |superlayer| to
  // have only this tree as its sublayers. If |old_tree| is non-null, then try
  // to re-use the CALayers of |old_tree| as much as possible. |old_tree| will
  // be destroyed at the end of the function, and any CALayers in it which were
  // not re-used by |this| will be removed from the CALayer hierarchy.
  void CommitScheduledCALayers(CALayer* superlayer,
                               std::unique_ptr<CARendererLayerTree> old_tree,
                               const gfx::Size& pixel_size,
                               float scale_factor);

  // Returns the contents used for a given solid color.
  id ContentsForSolidColorForTesting(SkColor4f color);

  // If there exists only a single content layer, return the IOSurface of that
  // layer.
  IOSurfaceRef GetContentIOSurface() const;

 private:
  class SolidColorContents;
  class RootLayer;
  class ClipAndSortingLayer;
  class TransformLayer;
  class ContentLayer;
  friend class ContentLayer;

  using CALayerMap =
      std::unordered_map<IOSurfaceRef, base::WeakPtr<ContentLayer>>;

  void MatchLayersToOldTree(CARendererLayerTree* old_tree);

  class RootLayer {
   public:
    RootLayer(CARendererLayerTree* tree);

    RootLayer(RootLayer&&) = delete;
    RootLayer(const RootLayer&) = delete;
    RootLayer& operator=(const RootLayer&) = delete;

    // This will remove |ca_layer| from its superlayer, if |ca_layer| is
    // non-nil.
    ~RootLayer();

    // Append a new content layer, without modifying the actual CALayer
    // structure.
    bool AddContentLayer(const CARendererLayerParams& params);

    // Downgrade all downgradeable AVSampleBufferDisplayLayers to be normal
    // CALayers.
    // https://crbug.com/923427, https://crbug.com/1143477
    void DowngradeAVLayersToCALayers();

    // Allocate CALayers for this layer and its children, and set their
    // properties appropriately. Re-use the CALayers from |old_layer| if
    // possible. If re-using a CALayer from |old_layer|, reset its |ca_layer|
    // to nil, so that its destructor will not remove an active CALayer.
    void CommitToCA(CALayer* superlayer, const gfx::Size& pixel_size);

    void CALayerFallBack();

    // Return true if the CALayer tree is just a video layer on a black or
    // transparent background, false otherwise.
    bool WantsFullscreenLowPowerBackdrop() const;

    // Tree that owns `this`.
    const raw_ptr<CARendererLayerTree> tree_;

    std::list<ClipAndSortingLayer> clip_and_sorting_layers_;
    CALayer* __strong ca_layer_;

    // Weak pointer to the layer in the old CARendererLayerTree that will be
    // reused by this layer, and the weak factory used to make that pointer.
    base::WeakPtr<RootLayer> old_layer_;
    base::WeakPtrFactory<RootLayer> weak_factory_for_new_layer_{this};
  };
  class ClipAndSortingLayer {
   public:
    ClipAndSortingLayer(RootLayer* root_layer,
                        bool is_clipped,
                        gfx::Rect clip_rect,
                        gfx::RRectF rounded_corner_bounds,
                        unsigned sorting_context_id,
                        bool is_singleton_sorting_context);

    ClipAndSortingLayer(ClipAndSortingLayer&& layer) = delete;
    ClipAndSortingLayer(const ClipAndSortingLayer&) = delete;
    ClipAndSortingLayer& operator=(const ClipAndSortingLayer&) = delete;

    // See the behavior of RootLayer for the effects of these functions on the
    // |ca_layer| member and |old_layer| argument.
    ~ClipAndSortingLayer();
    void AddContentLayer(const CARendererLayerParams& params);

    void CommitToCA(CALayer* last_committed_clip_ca_layer);
    void CALayerFallBack();

    CARendererLayerTree* tree() { return parent_layer_->tree_; }

    // Parent layer that owns `this`, and child layers that `this` owns.
    // RAW_PTR_EXCLUSION: Performance reasons (based on analysis of MotionMark).
    RAW_PTR_EXCLUSION RootLayer* const parent_layer_ = nullptr;
    std::list<TransformLayer> transform_layers_;

    bool is_clipped_ = false;
    gfx::Rect clip_rect_;
    gfx::RRectF rounded_corner_bounds_;
    unsigned sorting_context_id_ = 0;
    bool is_singleton_sorting_context_ = false;
    CALayer* __strong clipping_ca_layer_;
    CALayer* __strong rounded_corner_ca_layer_;

    // The status when used as an old layer.
    bool ca_layer_used_ = false;

    // Weak pointer to the layer in the old CARendererLayerTree that will be
    // reused by this layer, and the weak factory used to make that pointer.
    base::WeakPtr<ClipAndSortingLayer> old_layer_;
    base::WeakPtrFactory<ClipAndSortingLayer> weak_factory_for_new_layer_{this};
  };
  class TransformLayer {
   public:
    TransformLayer(ClipAndSortingLayer* parent_layer,
                   const gfx::Transform& transform);

    TransformLayer(TransformLayer&& layer) = delete;
    TransformLayer(const TransformLayer&) = delete;
    TransformLayer& operator=(const TransformLayer&) = delete;

    // See the behavior of RootLayer for the effects of these functions on the
    // |ca_layer| member and |old_layer| argument.
    ~TransformLayer();
    void AddContentLayer(const CARendererLayerParams& params);
    void CommitToCA(CALayer* last_committed_transform_ca_layer);

    void CALayerFallBack();

    CARendererLayerTree* tree() { return parent_layer_->tree(); }

    // Parent layer that owns `this`, and child layers that `this` owns.
    // RAW_PTR_EXCLUSION: Performance reasons (based on analysis of MotionMark).
    RAW_PTR_EXCLUSION ClipAndSortingLayer* const parent_layer_ = nullptr;
    std::list<ContentLayer> content_layers_;

    gfx::Transform transform_;
    CALayer* __strong ca_layer_;

    // The ca layer status when used as an old layer.
    bool ca_layer_used_ = false;

    // Weak pointer to the layer in the old CARendererLayerTree that will be
    // reused by this layer, and the weak factory used to make that pointer.
    base::WeakPtr<TransformLayer> old_layer_;
    base::WeakPtrFactory<TransformLayer> weak_factory_for_new_layer_{this};
  };
  class ContentLayer {
   public:
    ContentLayer(TransformLayer* parent_layer,
                 base::apple::ScopedCFTypeRef<IOSurfaceRef> io_surface,
                 base::apple::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer,
                 const gfx::RectF& contents_rect,
                 const gfx::Rect& rect,
                 SkColor4f background_color,
                 const gfx::ColorSpace& color_space,
                 unsigned edge_aa_mask,
                 float opacity,
                 bool nearest_neighbor_filter,
                 const gfx::HDRMetadata& hdr_metadata,
                 gfx::ProtectedVideoType protected_video_type,
                 bool is_render_pass_draw_quad);

    ContentLayer(ContentLayer&& layer) = delete;
    ContentLayer(const ContentLayer&) = delete;
    ContentLayer& operator=(const ContentLayer&) = delete;

    // See the behavior of RootLayer for the effects of these functions.
    ~ContentLayer();
    void CommitToCA(CALayer* last_committed_ca_layer);

    CARendererLayerTree* tree() { return parent_layer_->tree(); }
    void UpdateMapAndMatchOldLayers(CALayerMap& old_ca_layer_map,
                                    int& layer_order,
                                    int& last_old_layer_order);

    // Parent layer that owns `this`.
    // RAW_PTR_EXCLUSION: Performance reasons (based on analysis of MotionMark).
    RAW_PTR_EXCLUSION TransformLayer* const parent_layer_ = nullptr;

    // Ensure that the IOSurface be marked as in-use as soon as it is received.
    // When they are committed to the window server, that will also increment
    // their use count.
    const gfx::ScopedInUseIOSurface io_surface_;
    const base::apple::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer_;
    scoped_refptr<SolidColorContents> solid_color_contents_;
    gfx::RectF contents_rect_;
    gfx::RectF rect_;
    SkColor4f background_color_ = SkColors::kTransparent;
    // The color space of |io_surface|. Used for HDR tonemapping.
    gfx::ColorSpace io_surface_color_space_;
    // Note that the CoreAnimation edge antialiasing mask is not the same as
    // the edge antialiasing mask passed to the constructor.
    CAEdgeAntialiasingMask ca_edge_aa_mask_ = 0;
    float opacity_ = 1;
    NSString* const ca_filter_ = nil;

    CALayerType type_ = CALayerType::kDefault;

    // If |type| is CALayerType::kVideo and |video_type_can_downgrade| then
    // |type| can be downgraded to kDefault. This can be set to false for
    // HDR video (that cannot be displayed by a regular CALayer) or for
    // protected content (see https://crbug.com/1026703).
    bool video_type_can_downgrade_ = true;

    gfx::HDRMetadata hdr_metadata_;

    gfx::ProtectedVideoType protected_video_type_ =
        gfx::ProtectedVideoType::kClear;

    CALayer* __strong ca_layer_;

    // If this layer's contents can be represented as an
    // AVSampleBufferDisplayLayer, then |ca_layer| will point to |av_layer|.
    AVSampleBufferDisplayLayer* __strong av_layer_;

    // Layer used to colorize content when it updates, if borders are
    // enabled.
    CALayer* __strong update_indicator_layer_;

    // Indicate the content layer order in the whole layer tree.
    int layer_order_ = 0;

    // The status when used as an old layer.
    bool ca_layer_used_ = false;

    bool is_render_pass_draw_quad_ = false;

    // Weak pointer to the layer in the old CARendererLayerTree that will be
    // reused by this layer, and the weak factory used to make that pointer.
    base::WeakPtr<ContentLayer> old_layer_;
    base::WeakPtrFactory<ContentLayer> weak_factory_for_new_layer_{this};
  };

  RootLayer root_layer_{this};
  float scale_factor_ = 1;
  bool has_committed_ = false;
  const bool allow_av_sample_buffer_display_layer_ = true;
  const bool allow_solid_color_layers_ = true;
  float display_hdr_headroom_ = 1.f;

  // This is needed to ensure synchronization between the display compositor and
  // the HDRCopierLayer. See https://crbug.com/1372898
  id<MTLDevice> __strong metal_device_;

  // Map of content IOSurface.
  CALayerMap ca_layer_map_;
};

}  // namespace ui

#endif  // UI_ACCELERATED_WIDGET_MAC_CA_RENDERER_LAYER_TREE_H_