summaryrefslogtreecommitdiff
path: root/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
blob: 3917d70a33341e9d1d54dac486ba9f17707ed0fe (plain)
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
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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 <map>
#include <memory>

#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/threading/sequenced_task_runner_handle.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 "mojo/public/cpp/bindings/type_converter.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/public/mojom/wayland/wayland_buffer_manager.mojom.h"

#if defined(WAYLAND_GBM)
#include "ui/gfx/linux/gbm_device.h"  // nogncheck
#endif

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

namespace ui {

class WaylandConnection;
class WaylandSurfaceGpu;
class WaylandWindow;
struct OverlayPlane;

// 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();
  ~WaylandBufferManagerGpu() override;

  // 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) 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 buffer for swap.
  void OnSubmission(gfx::AcceleratedWidget widget,
                    uint32_t buffer_id,
                    gfx::SwapResult swap_result,
                    gfx::GpuFenceHandle release_fence_handle) override;
  void OnPresentation(gfx::AcceleratedWidget widget,
                      uint32_t buffer_id,
                      const gfx::PresentationFeedback& feedback) 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/public/mojom/wayland/wayland_connection.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 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 buffer_id,
                    const gfx::Rect& bounds_rect,
                    const gfx::Rect& damage_region);
  // Send overlay configurations for a frame to a WaylandWindow identified by
  // |widget|.
  void CommitOverlays(
      gfx::AcceleratedWidget widget,
      std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays);

  // Asks Wayland to destroy a wl_buffer.
  void DestroyBuffer(gfx::AcceleratedWidget widget, uint32_t buffer_id);

#if defined(WAYLAND_GBM)
  // Returns a gbm_device based on a DRM render node.
  GbmDevice* gbm_device() const { return gbm_device_.get(); }
  void set_gbm_device(std::unique_ptr<GbmDevice> gbm_device) {
    gbm_device_ = std::move(gbm_device);
  }
#endif

  bool supports_acquire_fence() const { return supports_acquire_fence_; }
  bool supports_viewporter() const { return supports_viewporter_; }

  // 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();

 private:
  void CreateDmabufBasedBufferInternal(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 CreateShmBasedBufferInternal(base::ScopedFD shm_fd,
                                    size_t length,
                                    gfx::Size size,
                                    uint32_t buffer_id);
  void CommitOverlaysInternal(
      gfx::AcceleratedWidget widget,
      std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays);
  void DestroyBufferInternal(gfx::AcceleratedWidget widget, uint32_t buffer_id);

  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 SubmitSwapResultOnOriginThread(gfx::AcceleratedWidget widget,
                                      uint32_t buffer_id,
                                      gfx::SwapResult swap_result,
                                      gfx::GpuFenceHandle release_fence);
  void SubmitPresentationOnOriginThread(
      gfx::AcceleratedWidget widget,
      uint32_t buffer_id,
      const gfx::PresentationFeedback& feedback);

#if defined(WAYLAND_GBM)
  // A DRM render node based gbm device.
  std::unique_ptr<GbmDevice> gbm_device_;
#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;

  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, WaylandSurfaceGpu*>
      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 GpuMainThread, but are rerouted to the IOChildThread 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 GpuMainThread, e.g.
  // WaylandCanvasSurface calls from the VizCompositorThread.
  // This map must only be accessed from the IO thread.
  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 IOChildThread. This is
  // needed to ensure mojo calls happen on a right sequence.
  scoped_refptr<base::SingleThreadTaskRunner> io_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;

  DISALLOW_COPY_AND_ASSIGN(WaylandBufferManagerGpu);
};

}  // namespace ui

// This is a specialization of mojo::TypeConverter and has to be in the mojo
// namespace.
namespace mojo {
template <>
struct TypeConverter<ui::ozone::mojom::WaylandOverlayConfigPtr,
                     ui::OverlayPlane> {
  static ui::ozone::mojom::WaylandOverlayConfigPtr Convert(
      const ui::OverlayPlane& input);
};
}  // namespace mojo

#endif  // UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_BUFFER_MANAGER_GPU_H_