File: wayland_buffer_manager_gpu.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 (327 lines) | stat: -rw-r--r-- 14,444 bytes parent folder | download | duplicates (3)
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
// Copyright 2018 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_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_BUFFER_MANAGER_GPU_H_
#define UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_BUFFER_MANAGER_GPU_H_

#include <cstdint>
#include <map>
#include <memory>

#include "base/files/file_path.h"
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/frame_data.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/mojom/wayland_buffer_manager.mojom.h"
#include "ui/ozone/public/drm_modifiers_filter.h"

namespace gfx {
enum class SwapResult;
}  // namespace gfx

namespace ui {

class GbmDevice;
class WaylandConnection;
class WaylandSurfaceGpu;
class WaylandWindow;

// Forwards calls through an associated mojo connection to WaylandBufferManager
// on the browser process side.
//
// It's guaranteed that WaylandBufferManagerGpu makes mojo calls on the right
// sequence.
class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
 public:
  WaylandBufferManagerGpu();
  explicit WaylandBufferManagerGpu(const base::FilePath& drm_node_path);
  WaylandBufferManagerGpu(const WaylandBufferManagerGpu&) = delete;
  WaylandBufferManagerGpu& operator=(const WaylandBufferManagerGpu&) = delete;

  ~WaylandBufferManagerGpu() override;

  scoped_refptr<base::SingleThreadTaskRunner> gpu_thread_runner() const {
    return gpu_thread_runner_;
  }

  // WaylandBufferManagerGpu overrides:
  void Initialize(
      mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host,
      const base::flat_map<::gfx::BufferFormat, std::vector<uint64_t>>&
          buffer_formats_with_modifiers,
      bool supports_dma_buf,
      bool supports_viewporter,
      bool supports_acquire_fence,
      bool supports_overlays,
      bool supports_single_pixel_buffer) override;

  // These two calls get the surface, which backs the |widget| and notifies it
  // about the submission and the presentation. After the surface receives the
  // OnSubmission call, it can schedule a new frame for swap.
  void OnSubmission(gfx::AcceleratedWidget widget,
                    uint32_t frame_id,
                    gfx::SwapResult swap_result,
                    gfx::GpuFenceHandle release_fence_handle,
                    const std::vector<wl::WaylandPresentationInfo>&
                        presentation_infos) override;

  void OnPresentation(gfx::AcceleratedWidget widget,
                      const std::vector<wl::WaylandPresentationInfo>&
                          presentation_infos) override;

  // If the client, which uses this manager and implements WaylandSurfaceGpu,
  // wants to receive OnSubmission and OnPresentation callbacks and know the
  // result of the below operations, they must register themselves with the
  // below APIs.
  void RegisterSurface(gfx::AcceleratedWidget widget,
                       WaylandSurfaceGpu* surface);
  void UnregisterSurface(gfx::AcceleratedWidget widget);
  WaylandSurfaceGpu* GetSurface(gfx::AcceleratedWidget widget);

  // Methods, which can be used when in both in-process-gpu and out of process
  // modes. These calls are forwarded to the browser process through the
  // WaylandConnection mojo interface. See more in
  // ui/ozone/platform/wayland/mojom/wayland_buffer_manager.mojom.
  //
  // Asks Wayland to create generic dmabuf-based wl_buffer.
  void CreateDmabufBasedBuffer(base::ScopedFD dmabuf_fd,
                               gfx::Size size,
                               const std::vector<uint32_t>& strides,
                               const std::vector<uint32_t>& offsets,
                               const std::vector<uint64_t>& modifiers,
                               uint32_t current_format,
                               uint32_t planes_count,
                               uint32_t buffer_id);

  // Asks Wayland to create a shared memory based wl_buffer.
  void CreateShmBasedBuffer(base::ScopedFD shm_fd,
                            size_t length,
                            gfx::Size size,
                            uint32_t buffer_id);

  // Asks Wayland to create a single pixel wl_buffer that is not backed by
  // anything on the gpu side. Requires single pixel buffer protocol.
  void CreateSinglePixelBuffer(SkColor4f color, uint32_t buf_id);

  // Asks Wayland to find a wl_buffer with the |buffer_id| and attach the
  // buffer to the WaylandWindow's surface, which backs the following |widget|.
  // Once the buffer is submitted and presented, the OnSubmission and
  // OnPresentation are called. Note, it's not guaranteed the OnPresentation
  // will follow the OnSubmission immediately, but the OnPresentation must never
  // be called before the OnSubmission is called for that particular buffer.
  // This logic must be checked by the client, though the host ensures this
  // logic as well. This call must not be done twice for the same |widget| until
  // the OnSubmission is called (which actually means the client can continue
  // sending buffer swap requests).
  //
  // CommitBuffer() calls CommitOverlays() to commit only a primary plane
  // buffer.
  void CommitBuffer(gfx::AcceleratedWidget widget,
                    uint32_t frame_id,
                    uint32_t buffer_id,
                    gfx::FrameData data,
                    const gfx::Rect& bounds_rect,
                    bool enable_blend,
                    const gfx::RoundedCornersF& corners,
                    float surface_scale_factor,
                    const gfx::Rect& damage_region);
  // Send overlay configurations for a frame to a WaylandWindow identified by
  // |widget|.
  void CommitOverlays(gfx::AcceleratedWidget widget,
                      uint32_t frame_id,
                      gfx::FrameData data,
                      std::vector<wl::WaylandOverlayConfig> overlays);

  // Asks Wayland to destroy a wl_buffer.
  void DestroyBuffer(uint32_t buffer_id);

#if defined(WAYLAND_GBM)
  // Returns a gbm_device based on a DRM render node.
  GbmDevice* GetGbmDevice();
#endif

  bool supports_acquire_fence() const { return supports_acquire_fence_; }
  bool supports_viewporter() const { return supports_viewporter_; }
  bool supports_overlays() const { return supports_overlays_; }
  bool supports_single_pixel_buffer() const {
    return supports_single_pixel_buffer_;
  }
  void set_drm_modifiers_filter(
      std::unique_ptr<DrmModifiersFilter> drm_modifiers_filter) {
    drm_modifiers_filter_ = std::move(drm_modifiers_filter);
  }

  // Adds a WaylandBufferManagerGpu binding.
  void AddBindingWaylandBufferManagerGpu(
      mojo::PendingReceiver<ozone::mojom::WaylandBufferManagerGpu> receiver);

  // Returns supported modifiers for the supplied |buffer_format|.
  const std::vector<uint64_t> GetModifiersForBufferFormat(
      gfx::BufferFormat buffer_format) const;

  // Allocates a unique buffer ID.
  uint32_t AllocateBufferID();

  // Returns if a format is supported by current Wayland implementation.
  bool SupportsFormat(gfx::BufferFormat buffer_format) const;

 private:
  FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryTest, CreateSurfaceCheckGbm);
  FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryTest,
                           GbmSurfacelessWaylandCommitOverlaysCallbacksTest);
  FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryTest,
                           GbmSurfacelessWaylandGroupOnSubmissionCallbacksTest);
  FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryCompositorV3,
                           SurfaceDamageTest);
  FRIEND_TEST_ALL_PREFIXES(WaylandBufferManagerTest,
                           ExecutesTasksAfterInitialization);
  FRIEND_TEST_ALL_PREFIXES(WaylandOverlayManagerTest,
                           SupportsNonIntegerDisplayRect);

  void BindHostInterface(
      mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host);

  void SaveTaskRunnerForWidgetOnIOThread(
      gfx::AcceleratedWidget widget,
      scoped_refptr<base::SingleThreadTaskRunner> origin_runner);
  void ForgetTaskRunnerForWidgetOnIOThread(gfx::AcceleratedWidget widget);

  // Provides the WaylandSurfaceGpu, which backs the |widget|, with swap and
  // presentation results.
  void HandleSubmissionOnOriginThread(
      gfx::AcceleratedWidget widget,
      uint32_t frame_id,
      gfx::SwapResult swap_result,
      gfx::GpuFenceHandle release_fence,
      const std::vector<wl::WaylandPresentationInfo>& presentation_infos);
  void HandlePresentationOnOriginThread(
      gfx::AcceleratedWidget widget,
      const std::vector<wl::WaylandPresentationInfo>& presentation_infos);

  void OnHostDisconnected();

  // Executes the |task| immediately if the pipe has been bound. Otherwise, the
  // tasks are stored and executed after the remote pipe becomes bound.
  void RunOrQueueTask(base::OnceClosure task);
  // Called when the manager is initialized and the remote host is bound. Runs
  // pending tasks.
  void ProcessPendingTasks();

  // Internal methods that do calls to the |remote_host|.
  void CreateDmabufBasedBufferTask(base::ScopedFD dmabuf_fd,
                                   gfx::Size size,
                                   const std::vector<uint32_t>& strides,
                                   const std::vector<uint32_t>& offsets,
                                   const std::vector<uint64_t>& modifiers,
                                   uint32_t current_format,
                                   uint32_t planes_count,
                                   uint32_t buffer_id);
  void CreateShmBasedBufferTask(base::ScopedFD shm_fd,
                                size_t length,
                                gfx::Size size,
                                uint32_t buffer_id);
  void CreateSinglePixelBufferTask(SkColor4f color, uint32_t buf_id);
  void CommitOverlaysTask(gfx::AcceleratedWidget widget,
                          uint32_t frame_id,
                          gfx::FrameData data,
                          std::vector<wl::WaylandOverlayConfig> overlays);
  void DestroyBufferTask(uint32_t buffer_id);

#if defined(WAYLAND_GBM)
  // Uses |drm_node_path| to open the handle and store it into
  // |drm_render_node_fd|.
  void OpenAndStoreDrmRenderNodeFd(const base::FilePath& drm_node_path);
  // Used by the gbm_device for self creation.
  base::ScopedFD drm_render_node_fd_;
  // A DRM render node based gbm device.
  std::unique_ptr<GbmDevice> gbm_device_;
  // When set, avoids creating a real gbm_device. Instead, tests that set
  // this variable to true must set own instance of the GbmDevice. See the
  // CreateSurfaceCheckGbm for example.
  bool use_fake_gbm_device_for_test_ = false;
#endif
  // Whether Wayland server allows buffer submission with acquire fence.
  bool supports_acquire_fence_ = false;

  // Whether Wayland server implements wp_viewporter extension to support
  // cropping and scaling buffers.
  bool supports_viewporter_ = false;

  // Whether delegated overlays should be used for this Wayland server.
  bool supports_overlays_ = false;

  // Determines whether single pixel buffer are supported via a wayland
  // protocol.
  bool supports_single_pixel_buffer_ = false;

  // Determines whether Wayland server supports Wayland protocols that allow to
  // export wl_buffers backed by dmabuf.
  bool supports_dmabuf_ = true;

  // A DRM modifiers filter to ensure we don't allocate buffers with modifiers
  // not supported by Vulkan.
  std::unique_ptr<DrmModifiersFilter> drm_modifiers_filter_;

  mojo::ReceiverSet<ozone::mojom::WaylandBufferManagerGpu> receiver_set_;

  // A pointer to a WaylandBufferManagerHost object, which always lives on a
  // browser process side. It's used for a multi-process mode.
  mojo::Remote<ozone::mojom::WaylandBufferManagerHost> remote_host_;

  mojo::AssociatedReceiver<ozone::mojom::WaylandBufferManagerGpu>
      associated_receiver_{this};

  std::map<gfx::AcceleratedWidget, raw_ptr<WaylandSurfaceGpu, CtnExperimental>>
      widget_to_surface_map_;  // Guarded by |lock_|.

  // Supported buffer formats and modifiers sent by the Wayland compositor to
  // the client. Corresponds to the map stored in WaylandZwpLinuxDmabuf and
  // passed from it during initialization of this gpu host.
  base::flat_map<gfx::BufferFormat, std::vector<uint64_t>>
      supported_buffer_formats_with_modifiers_;

  // These task runners can be used to pass messages back to the same thread,
  // where the commit buffer request came from. For example, swap requests can
  // come from the Viz thread, but are rerouted to the GpuMainThread and then
  // mojo calls happen. However, when the manager receives mojo calls, it has to
  // reroute calls back to the same thread where the calls came from to ensure
  // correct sequence. Note that not all calls come from the Viz thread, e.g.
  // GbmPixmapWayland may call from either the GpuMainThread or IOChildThread.
  // This map must only be accessed from the GpuMainThread.
  base::small_map<std::map<gfx::AcceleratedWidget,
                           scoped_refptr<base::SingleThreadTaskRunner>>>
      commit_thread_runners_;

  // A task runner, which is initialized in a multi-process mode. It is used to
  // ensure all the methods of this class are run on GpuMainThread. This is
  // needed to ensure mojo calls happen on a right sequence.
  scoped_refptr<base::SingleThreadTaskRunner> gpu_thread_runner_;

  // Protects access to |widget_to_surface_map_| and |commit_thread_runners_|.
  base::Lock lock_;

  // Keeps track of the next unique buffer ID.
  uint32_t next_buffer_id_ = 0;

  // The tasks that are blocked on a remote_host pipe becoming bound.
  std::vector<base::OnceClosure> pending_tasks_;

  // All calls must happen on the correct sequence. See comments in the
  // constructor for more details.
  SEQUENCE_CHECKER(gpu_sequence_checker_);
};

}  // namespace ui

#endif  // UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_BUFFER_MANAGER_GPU_H_