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_
|