Commit 30be1cfe authored by Maksim Sisov's avatar Maksim Sisov Committed by Commit Bot

[ozone/wayland] Factor out zwp linux dmabuf from the manager.

This change is a prerequisite for having buffer manager
to handle frame callbacks.

Also, each window will be backed with own buffer manager,
which is needed to ease handling of the frame callbacks.

Now, zwp_linux_dmabuf Wayland factory is wrapped around
WaylandZwpLinuxDmabuf and receives requests to create
buffers backed by dmabuf file descriptor. Returns
a wl_buffer on success via a provided callback. If
failed, nullptr is returned.

Bug: 943096
Change-Id: I85cff3ad7a12e26a4380b87d2933af377c436e4d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1539700
Commit-Queue: Maksim Sisov <msisov@igalia.com>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Cr-Commit-Position: refs/heads/master@{#644728}
parent bd7a43fd
...@@ -70,6 +70,8 @@ source_set("wayland") { ...@@ -70,6 +70,8 @@ source_set("wayland") {
"wayland_util.h", "wayland_util.h",
"wayland_window.cc", "wayland_window.cc",
"wayland_window.h", "wayland_window.h",
"wayland_zwp_linux_dmabuf.cc",
"wayland_zwp_linux_dmabuf.h",
"xdg_popup_wrapper.h", "xdg_popup_wrapper.h",
"xdg_popup_wrapper_v5.cc", "xdg_popup_wrapper_v5.cc",
"xdg_popup_wrapper_v5.h", "xdg_popup_wrapper_v5.h",
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
#include "ui/ozone/platform/wayland/wayland_buffer_manager.h" #include "ui/ozone/platform/wayland/wayland_buffer_manager.h"
#include <drm_fourcc.h>
#include <linux-dmabuf-unstable-v1-client-protocol.h>
#include <presentation-time-client-protocol.h> #include <presentation-time-client-protocol.h>
#include <memory> #include <memory>
...@@ -13,6 +11,7 @@ ...@@ -13,6 +11,7 @@
#include "ui/ozone/common/linux/drm_util_linux.h" #include "ui/ozone/common/linux/drm_util_linux.h"
#include "ui/ozone/platform/wayland/wayland_connection.h" #include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_window.h" #include "ui/ozone/platform/wayland/wayland_window.h"
#include "ui/ozone/platform/wayland/wayland_zwp_linux_dmabuf.h"
namespace ui { namespace ui {
...@@ -44,27 +43,12 @@ base::TimeTicks GetPresentationFeedbackTimeStamp(uint32_t tv_sec_hi, ...@@ -44,27 +43,12 @@ base::TimeTicks GetPresentationFeedbackTimeStamp(uint32_t tv_sec_hi,
} // namespace } // namespace
WaylandBufferManager::Buffer::Buffer() = default; WaylandBufferManager::Buffer::Buffer() = default;
WaylandBufferManager::Buffer::Buffer(uint32_t id, WaylandBufferManager::Buffer::Buffer(const gfx::Size& buffer_size)
zwp_linux_buffer_params_v1* zwp_params, : size(buffer_size) {}
const gfx::Size& buffer_size)
: buffer_id(id), size(buffer_size), params(zwp_params) {}
WaylandBufferManager::Buffer::~Buffer() = default; WaylandBufferManager::Buffer::~Buffer() = default;
WaylandBufferManager::WaylandBufferManager( WaylandBufferManager::WaylandBufferManager(WaylandConnection* connection)
zwp_linux_dmabuf_v1* zwp_linux_dmabuf, : connection_(connection), weak_factory_(this) {}
WaylandConnection* connection)
: zwp_linux_dmabuf_(zwp_linux_dmabuf), connection_(connection) {
static const zwp_linux_dmabuf_v1_listener dmabuf_listener = {
&WaylandBufferManager::Format,
&WaylandBufferManager::Modifiers,
};
zwp_linux_dmabuf_v1_add_listener(zwp_linux_dmabuf_.get(), &dmabuf_listener,
this);
// A roundtrip after binding guarantees that the client has received all
// supported formats.
wl_display_roundtrip(connection->display());
}
WaylandBufferManager::~WaylandBufferManager() { WaylandBufferManager::~WaylandBufferManager() {
DCHECK(buffers_.empty()); DCHECK(buffers_.empty());
...@@ -82,9 +66,6 @@ bool WaylandBufferManager::CreateBuffer(base::File file, ...@@ -82,9 +66,6 @@ bool WaylandBufferManager::CreateBuffer(base::File file,
TRACE_EVENT2("wayland", "WaylandBufferManager::CreateZwpLinuxDmabuf", TRACE_EVENT2("wayland", "WaylandBufferManager::CreateZwpLinuxDmabuf",
"Format", format, "Buffer id", buffer_id); "Format", format, "Buffer id", buffer_id);
static const struct zwp_linux_buffer_params_v1_listener params_listener = {
WaylandBufferManager::CreateSucceeded,
WaylandBufferManager::CreateFailed};
if (!ValidateDataFromGpu(file, width, height, strides, offsets, format, if (!ValidateDataFromGpu(file, width, height, strides, offsets, format,
modifiers, planes_count, buffer_id)) { modifiers, planes_count, buffer_id)) {
// base::File::Close() has an assertion that checks if blocking operations // base::File::Close() has an assertion that checks if blocking operations
...@@ -93,36 +74,15 @@ bool WaylandBufferManager::CreateBuffer(base::File file, ...@@ -93,36 +74,15 @@ bool WaylandBufferManager::CreateBuffer(base::File file,
return false; return false;
} }
base::ScopedFD fd(file.TakePlatformFile()); std::unique_ptr<Buffer> buffer =
std::make_unique<Buffer>(gfx::Size(width, height));
// Store |params| connected to |buffer_id| to track buffer creation and buffers_.insert(std::make_pair(buffer_id, std::move(buffer)));
// identify, which buffer a client wants to use.
DCHECK(zwp_linux_dmabuf_);
struct zwp_linux_buffer_params_v1* params =
zwp_linux_dmabuf_v1_create_params(zwp_linux_dmabuf_.get());
buffers_.insert(std::pair<uint32_t, std::unique_ptr<Buffer>>(
buffer_id,
std::make_unique<Buffer>(buffer_id, params, gfx::Size(width, height))));
for (size_t i = 0; i < planes_count; i++) {
uint32_t modifier_lo = 0;
uint32_t modifier_hi = 0;
if (modifiers[i] != DRM_FORMAT_MOD_INVALID) {
modifier_lo = modifiers[i] & UINT32_MAX;
modifier_hi = modifiers[i] >> 32;
} else {
DCHECK_EQ(planes_count, 1u) << "Invalid modifier may be passed only in "
"case of single plane format being used";
}
zwp_linux_buffer_params_v1_add(params, fd.get(), i /* plane id */,
offsets[i], strides[i], modifier_hi,
modifier_lo);
}
zwp_linux_buffer_params_v1_add_listener(params, &params_listener, this);
zwp_linux_buffer_params_v1_create(params, width, height, format, 0);
connection_->ScheduleFlush(); auto callback = base::BindOnce(&WaylandBufferManager::OnCreateBufferComplete,
weak_factory_.GetWeakPtr(), buffer_id);
connection_->zwp_dmabuf()->CreateBuffer(
std::move(file), gfx::Size(width, height), strides, offsets, modifiers,
format, planes_count, std::move(callback));
return true; return true;
} }
...@@ -131,7 +91,7 @@ bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget, ...@@ -131,7 +91,7 @@ bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
uint32_t buffer_id, uint32_t buffer_id,
const gfx::Rect& damage_region, const gfx::Rect& damage_region,
wl::BufferSwapCallback callback) { wl::BufferSwapCallback callback) {
TRACE_EVENT1("wayland", "WaylandBufferManager::ScheduleSwapBuffer", TRACE_EVENT1("wayland", "WaylandBufferManager::ScheduleBufferSwap",
"Buffer id", buffer_id); "Buffer id", buffer_id);
if (!ValidateDataFromGpu(widget, buffer_id)) if (!ValidateDataFromGpu(widget, buffer_id))
...@@ -191,9 +151,6 @@ void WaylandBufferManager::ClearState() { ...@@ -191,9 +151,6 @@ void WaylandBufferManager::ClearState() {
// TODO(msisov): handle buffer swap failure or success. // TODO(msisov): handle buffer swap failure or success.
bool WaylandBufferManager::SwapBuffer(Buffer* buffer) { bool WaylandBufferManager::SwapBuffer(Buffer* buffer) {
TRACE_EVENT1("wayland", "WaylandBufferManager::SwapBuffer", "Buffer id",
buffer->buffer_id);
WaylandWindow* window = connection_->GetWindow(buffer->widget); WaylandWindow* window = connection_->GetWindow(buffer->widget);
if (!window) { if (!window) {
error_message_ = "A WaylandWindow with current widget does not exist"; error_message_ = "A WaylandWindow with current widget does not exist";
...@@ -310,27 +267,17 @@ bool WaylandBufferManager::ValidateDataFromGpu( ...@@ -310,27 +267,17 @@ bool WaylandBufferManager::ValidateDataFromGpu(
return true; return true;
} }
void WaylandBufferManager::CreateSucceededInternal( void WaylandBufferManager::OnCreateBufferComplete(
struct zwp_linux_buffer_params_v1* params, uint32_t buffer_id,
struct wl_buffer* new_buffer) { wl::Object<struct wl_buffer> new_buffer) {
// Find which buffer id |params| belong to and store wl_buffer auto it = buffers_.find(buffer_id);
// with that id.
Buffer* buffer = nullptr;
for (auto& item : buffers_) {
if (item.second.get()->params == params) {
buffer = item.second.get();
break;
}
}
// It can happen that buffer was destroyed by a client while the Wayland // It can happen that buffer was destroyed by a client while the Wayland
// compositor was processing a request to create a wl_buffer. // compositor was processing a request to create a wl_buffer.
if (!buffer) if (it == buffers_.end())
return; return;
buffer->wl_buffer.reset(new_buffer); Buffer* buffer = it->second.get();
buffer->params = nullptr; buffer->wl_buffer = std::move(new_buffer);
zwp_linux_buffer_params_v1_destroy(params);
if (buffer->widget != gfx::kNullAcceleratedWidget) if (buffer->widget != gfx::kNullAcceleratedWidget)
SwapBuffer(buffer); SwapBuffer(buffer);
...@@ -342,60 +289,6 @@ void WaylandBufferManager::OnBufferSwapped(Buffer* buffer) { ...@@ -342,60 +289,6 @@ void WaylandBufferManager::OnBufferSwapped(Buffer* buffer) {
.Run(buffer->swap_result, std::move(buffer->feedback)); .Run(buffer->swap_result, std::move(buffer->feedback));
} }
void WaylandBufferManager::AddSupportedFourCCFormat(uint32_t fourcc_format) {
// Return on not the supported fourcc format.
if (!IsValidBufferFormat(fourcc_format))
return;
// It can happen that ::Format or ::Modifiers call can have already added such
// a format. Thus, we can ignore that format.
gfx::BufferFormat format = GetBufferFormatFromFourCCFormat(fourcc_format);
auto it = std::find(supported_buffer_formats_.begin(),
supported_buffer_formats_.end(), format);
if (it != supported_buffer_formats_.end())
return;
supported_buffer_formats_.push_back(format);
}
// static
void WaylandBufferManager::Modifiers(
void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
uint32_t format,
uint32_t modifier_hi,
uint32_t modifier_lo) {
WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
if (self)
self->AddSupportedFourCCFormat(format);
}
// static
void WaylandBufferManager::Format(void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
uint32_t format) {
WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
if (self)
self->AddSupportedFourCCFormat(format);
}
// static
void WaylandBufferManager::CreateSucceeded(
void* data,
struct zwp_linux_buffer_params_v1* params,
struct wl_buffer* new_buffer) {
WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
DCHECK(self);
self->CreateSucceededInternal(params, new_buffer);
}
// static
void WaylandBufferManager::CreateFailed(
void* data,
struct zwp_linux_buffer_params_v1* params) {
zwp_linux_buffer_params_v1_destroy(params);
LOG(FATAL) << "zwp_linux_buffer_params.create failed";
}
// static // static
void WaylandBufferManager::FrameCallbackDone(void* data, void WaylandBufferManager::FrameCallbackDone(void* data,
wl_callback* callback, wl_callback* callback,
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/files/file.h" #include "base/files/file.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/gfx/presentation_feedback.h" #include "ui/gfx/presentation_feedback.h"
...@@ -20,14 +21,8 @@ ...@@ -20,14 +21,8 @@
#include "ui/ozone/platform/wayland/wayland_object.h" #include "ui/ozone/platform/wayland/wayland_object.h"
#include "ui/ozone/platform/wayland/wayland_util.h" #include "ui/ozone/platform/wayland/wayland_util.h"
struct zwp_linux_dmabuf_v1;
struct zwp_linux_buffer_params_v1;
struct wp_presentation_feedback; struct wp_presentation_feedback;
namespace gfx {
enum class BufferFormat;
} // namespace gfx
namespace ui { namespace ui {
class WaylandConnection; class WaylandConnection;
...@@ -36,16 +31,11 @@ class WaylandConnection; ...@@ -36,16 +31,11 @@ class WaylandConnection;
// dmabuf buffers. Only used when GPU runs in own process. // dmabuf buffers. Only used when GPU runs in own process.
class WaylandBufferManager { class WaylandBufferManager {
public: public:
WaylandBufferManager(zwp_linux_dmabuf_v1* zwp_linux_dmabuf, explicit WaylandBufferManager(WaylandConnection* connection);
WaylandConnection* connection);
~WaylandBufferManager(); ~WaylandBufferManager();
std::string error_message() { return std::move(error_message_); } std::string error_message() { return std::move(error_message_); }
std::vector<gfx::BufferFormat> supported_buffer_formats() {
return supported_buffer_formats_;
}
// Creates a wl_buffer based on the dmabuf |file| descriptor. On error, false // Creates a wl_buffer based on the dmabuf |file| descriptor. On error, false
// is returned and |error_message_| is set. // is returned and |error_message_| is set.
bool CreateBuffer(base::File file, bool CreateBuffer(base::File file,
...@@ -86,14 +76,9 @@ class WaylandBufferManager { ...@@ -86,14 +76,9 @@ class WaylandBufferManager {
// to this Buffer object on run-time. // to this Buffer object on run-time.
struct Buffer { struct Buffer {
Buffer(); Buffer();
Buffer(uint32_t id, explicit Buffer(const gfx::Size& buffer_size);
zwp_linux_buffer_params_v1* zwp_params,
const gfx::Size& buffer_size);
~Buffer(); ~Buffer();
// GPU GbmPixmapWayland corresponding buffer id.
uint32_t buffer_id = 0;
// Actual buffer size. // Actual buffer size.
const gfx::Size size; const gfx::Size size;
...@@ -112,9 +97,6 @@ class WaylandBufferManager { ...@@ -112,9 +97,6 @@ class WaylandBufferManager {
// supported. // supported.
gfx::PresentationFeedback feedback; gfx::PresentationFeedback feedback;
// Params that are used to create a wl_buffer.
zwp_linux_buffer_params_v1* params = nullptr;
// A wl_buffer backed by a dmabuf created on the GPU side. // A wl_buffer backed by a dmabuf created on the GPU side.
wl::Object<struct wl_buffer> wl_buffer; wl::Object<struct wl_buffer> wl_buffer;
...@@ -150,30 +132,13 @@ class WaylandBufferManager { ...@@ -150,30 +132,13 @@ class WaylandBufferManager {
bool ValidateDataFromGpu(const gfx::AcceleratedWidget& widget, bool ValidateDataFromGpu(const gfx::AcceleratedWidget& widget,
uint32_t buffer_id); uint32_t buffer_id);
void CreateSucceededInternal(struct zwp_linux_buffer_params_v1* params, // Callback method. Receives a result for the request to create a wl_buffer
struct wl_buffer* new_buffer); // backend by dmabuf file descriptor from ::CreateBuffer call.
void OnCreateBufferComplete(uint32_t buffer_id,
wl::Object<struct wl_buffer> new_buffer);
void OnBufferSwapped(Buffer* buffer); void OnBufferSwapped(Buffer* buffer);
void AddSupportedFourCCFormat(uint32_t fourcc_format);
// zwp_linux_dmabuf_v1_listener
static void Modifiers(void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
uint32_t format,
uint32_t modifier_hi,
uint32_t modifier_lo);
static void Format(void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
uint32_t format);
// zwp_linux_buffer_params_v1_listener
static void CreateSucceeded(void* data,
struct zwp_linux_buffer_params_v1* params,
struct wl_buffer* new_buffer);
static void CreateFailed(void* data,
struct zwp_linux_buffer_params_v1* params);
// wl_callback_listener // wl_callback_listener
static void FrameCallbackDone(void* data, static void FrameCallbackDone(void* data,
wl_callback* callback, wl_callback* callback,
...@@ -198,19 +163,18 @@ class WaylandBufferManager { ...@@ -198,19 +163,18 @@ class WaylandBufferManager {
void* data, void* data,
struct wp_presentation_feedback* wp_presentation_feedback); struct wp_presentation_feedback* wp_presentation_feedback);
// Stores announced buffer formats supported by the compositor.
std::vector<gfx::BufferFormat> supported_buffer_formats_;
// A container of created buffers. // A container of created buffers.
base::flat_map<uint32_t, std::unique_ptr<Buffer>> buffers_; base::flat_map<uint32_t, std::unique_ptr<Buffer>> buffers_;
// Set when invalid data is received from the GPU process. // Set when invalid data is received from the GPU process.
std::string error_message_; std::string error_message_;
wl::Object<zwp_linux_dmabuf_v1> zwp_linux_dmabuf_;
// Non-owned pointer to the main connection. // Non-owned pointer to the main connection.
WaylandConnection* connection_ = nullptr; WaylandConnection* const connection_;
base::WeakPtrFactory<WaylandBufferManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WaylandBufferManager);
}; };
} // namespace ui } // namespace ui
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "ui/ozone/platform/wayland/wayland_output_manager.h" #include "ui/ozone/platform/wayland/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/wayland_shared_memory_buffer_manager.h" #include "ui/ozone/platform/wayland/wayland_shared_memory_buffer_manager.h"
#include "ui/ozone/platform/wayland/wayland_window.h" #include "ui/ozone/platform/wayland/wayland_window.h"
#include "ui/ozone/platform/wayland/wayland_zwp_linux_dmabuf.h"
static_assert(XDG_SHELL_VERSION_CURRENT == 5, "Unsupported xdg-shell version"); static_assert(XDG_SHELL_VERSION_CURRENT == 5, "Unsupported xdg-shell version");
...@@ -287,17 +288,15 @@ void WaylandConnection::SetSequenceNumberUpdateCb( ...@@ -287,17 +288,15 @@ void WaylandConnection::SetSequenceNumberUpdateCb(
} }
ozone::mojom::WaylandConnectionPtr WaylandConnection::BindInterface() { ozone::mojom::WaylandConnectionPtr WaylandConnection::BindInterface() {
// This mustn't be called twice or when the zwp_linux_dmabuf interface is not DCHECK(!binding_.is_bound());
// available.
DCHECK(!binding_.is_bound() || buffer_manager_);
ozone::mojom::WaylandConnectionPtr ptr; ozone::mojom::WaylandConnectionPtr ptr;
binding_.Bind(MakeRequest(&ptr)); binding_.Bind(MakeRequest(&ptr));
return ptr; return ptr;
} }
std::vector<gfx::BufferFormat> WaylandConnection::GetSupportedBufferFormats() { std::vector<gfx::BufferFormat> WaylandConnection::GetSupportedBufferFormats() {
if (buffer_manager_) if (zwp_dmabuf_)
return buffer_manager_->supported_buffer_formats(); return zwp_dmabuf_->supported_buffer_formats();
return std::vector<gfx::BufferFormat>(); return std::vector<gfx::BufferFormat>();
} }
...@@ -510,13 +509,15 @@ void WaylandConnection::Global(void* data, ...@@ -510,13 +509,15 @@ void WaylandConnection::Global(void* data,
connection->data_device_manager_.reset(new WaylandDataDeviceManager( connection->data_device_manager_.reset(new WaylandDataDeviceManager(
data_device_manager.release(), connection)); data_device_manager.release(), connection));
connection->EnsureDataDevice(); connection->EnsureDataDevice();
} else if (!connection->buffer_manager_ && } else if (!connection->zwp_dmabuf_ &&
(strcmp(interface, "zwp_linux_dmabuf_v1") == 0)) { (strcmp(interface, "zwp_linux_dmabuf_v1") == 0)) {
wl::Object<zwp_linux_dmabuf_v1> zwp_linux_dmabuf = wl::Object<zwp_linux_dmabuf_v1> zwp_linux_dmabuf =
wl::Bind<zwp_linux_dmabuf_v1>( wl::Bind<zwp_linux_dmabuf_v1>(
registry, name, std::min(version, kMaxLinuxDmabufVersion)); registry, name, std::min(version, kMaxLinuxDmabufVersion));
connection->buffer_manager_.reset( connection->zwp_dmabuf_ = std::make_unique<WaylandZwpLinuxDmabuf>(
new WaylandBufferManager(zwp_linux_dmabuf.release(), connection)); zwp_linux_dmabuf.release(), connection);
connection->buffer_manager_ =
std::make_unique<WaylandBufferManager>(connection);
} else if (!connection->presentation_ && } else if (!connection->presentation_ &&
(strcmp(interface, "wp_presentation") == 0)) { (strcmp(interface, "wp_presentation") == 0)) {
connection->presentation_ = connection->presentation_ =
......
...@@ -34,6 +34,7 @@ class WaylandBufferManager; ...@@ -34,6 +34,7 @@ class WaylandBufferManager;
class WaylandShmBufferManager; class WaylandShmBufferManager;
class WaylandOutputManager; class WaylandOutputManager;
class WaylandWindow; class WaylandWindow;
class WaylandZwpLinuxDmabuf;
// TODO(crbug.com/942203): factor out PlatformClipboard to a separate class. // TODO(crbug.com/942203): factor out PlatformClipboard to a separate class.
class WaylandConnection : public PlatformEventSource, class WaylandConnection : public PlatformEventSource,
...@@ -131,6 +132,8 @@ class WaylandConnection : public PlatformEventSource, ...@@ -131,6 +132,8 @@ class WaylandConnection : public PlatformEventSource,
WaylandBufferManager* buffer_manager() const { return buffer_manager_.get(); } WaylandBufferManager* buffer_manager() const { return buffer_manager_.get(); }
WaylandZwpLinuxDmabuf* zwp_dmabuf() const { return zwp_dmabuf_.get(); }
// Clipboard implementation. // Clipboard implementation.
PlatformClipboard* GetPlatformClipboard(); PlatformClipboard* GetPlatformClipboard();
void DataSourceCancelled(); void DataSourceCancelled();
...@@ -248,6 +251,7 @@ class WaylandConnection : public PlatformEventSource, ...@@ -248,6 +251,7 @@ class WaylandConnection : public PlatformEventSource,
std::unique_ptr<WaylandTouch> touch_; std::unique_ptr<WaylandTouch> touch_;
std::unique_ptr<WaylandCursorPosition> wayland_cursor_position_; std::unique_ptr<WaylandCursorPosition> wayland_cursor_position_;
std::unique_ptr<WaylandShmBufferManager> shm_buffer_manager_; std::unique_ptr<WaylandShmBufferManager> shm_buffer_manager_;
std::unique_ptr<WaylandZwpLinuxDmabuf> zwp_dmabuf_;
// Objects that are using when GPU runs in own process. // Objects that are using when GPU runs in own process.
std::unique_ptr<WaylandBufferManager> buffer_manager_; std::unique_ptr<WaylandBufferManager> buffer_manager_;
......
...@@ -85,7 +85,7 @@ void WaylandConnectionConnector::OnWaylandConnectionPtrBinded( ...@@ -85,7 +85,7 @@ void WaylandConnectionConnector::OnWaylandConnectionPtrBinded(
wcp_ptr->SetWaylandConnection(std::move(wc_ptr)); wcp_ptr->SetWaylandConnection(std::move(wc_ptr));
#if defined(WAYLAND_GBM) #if defined(WAYLAND_GBM)
if (!connection_->buffer_manager()) { if (!connection_->zwp_dmabuf()) {
LOG(WARNING) << "zwp_linux_dmabuf is not available."; LOG(WARNING) << "zwp_linux_dmabuf is not available.";
wcp_ptr->ResetGbmDevice(); wcp_ptr->ResetGbmDevice();
} }
......
...@@ -37,6 +37,9 @@ using BufferSwapCallback = ...@@ -37,6 +37,9 @@ using BufferSwapCallback =
using RequestSizeCallback = base::OnceCallback<void(const gfx::Size&)>; using RequestSizeCallback = base::OnceCallback<void(const gfx::Size&)>;
using OnRequestBufferCallback =
base::OnceCallback<void(wl::Object<struct wl_buffer>)>;
wl_buffer* CreateSHMBuffer(const gfx::Size& size, wl_buffer* CreateSHMBuffer(const gfx::Size& size,
base::SharedMemory* shared_memory, base::SharedMemory* shared_memory,
wl_shm* shm); wl_shm* shm);
......
// Copyright 2019 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.
#include "ui/ozone/platform/wayland/wayland_zwp_linux_dmabuf.h"
#include <drm_fourcc.h>
#include <linux-dmabuf-unstable-v1-client-protocol.h>
#include "ui/ozone/common/linux/drm_util_linux.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
namespace ui {
WaylandZwpLinuxDmabuf::WaylandZwpLinuxDmabuf(
zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
WaylandConnection* connection)
: zwp_linux_dmabuf_(zwp_linux_dmabuf), connection_(connection) {
static const zwp_linux_dmabuf_v1_listener dmabuf_listener = {
&WaylandZwpLinuxDmabuf::Format,
&WaylandZwpLinuxDmabuf::Modifiers,
};
zwp_linux_dmabuf_v1_add_listener(zwp_linux_dmabuf_.get(), &dmabuf_listener,
this);
// A roundtrip after binding guarantees that the client has received all
// supported formats.
wl_display_roundtrip(connection_->display());
}
WaylandZwpLinuxDmabuf::~WaylandZwpLinuxDmabuf() = default;
void WaylandZwpLinuxDmabuf::CreateBuffer(base::File file,
const gfx::Size& size,
const std::vector<uint32_t>& strides,
const std::vector<uint32_t>& offsets,
const std::vector<uint64_t>& modifiers,
uint32_t format,
uint32_t planes_count,
wl::OnRequestBufferCallback callback) {
static const struct zwp_linux_buffer_params_v1_listener params_listener = {
&WaylandZwpLinuxDmabuf::CreateSucceeded,
&WaylandZwpLinuxDmabuf::CreateFailed};
struct zwp_linux_buffer_params_v1* params =
zwp_linux_dmabuf_v1_create_params(zwp_linux_dmabuf_.get());
// Store the |params| with the corresponding |callback| to identify newly
// created buffer and notify the client about it via the |callback|.
pending_params_.insert(std::make_pair(params, std::move(callback)));
base::ScopedFD fd(file.TakePlatformFile());
for (size_t i = 0; i < planes_count; i++) {
uint32_t modifier_lo = 0;
uint32_t modifier_hi = 0;
if (modifiers[i] != DRM_FORMAT_MOD_INVALID) {
modifier_lo = modifiers[i] & UINT32_MAX;
modifier_hi = modifiers[i] >> 32;
} else {
DCHECK_EQ(planes_count, 1u) << "Invalid modifier may be passed only in "
"case of single plane format being used";
}
zwp_linux_buffer_params_v1_add(params, fd.get(), i /* plane id */,
offsets[i], strides[i], modifier_hi,
modifier_lo);
}
zwp_linux_buffer_params_v1_add_listener(params, &params_listener, this);
zwp_linux_buffer_params_v1_create(params, size.width(), size.height(), format,
0);
connection_->ScheduleFlush();
}
void WaylandZwpLinuxDmabuf::AddSupportedFourCCFormat(uint32_t fourcc_format) {
// Return on not the supported fourcc format.
if (!IsValidBufferFormat(fourcc_format))
return;
// It can happen that ::Format or ::Modifiers call can have already added
// such a format. Thus, we can ignore that format.
gfx::BufferFormat format = GetBufferFormatFromFourCCFormat(fourcc_format);
auto it = std::find(supported_buffer_formats_.begin(),
supported_buffer_formats_.end(), format);
if (it != supported_buffer_formats_.end())
return;
supported_buffer_formats_.push_back(format);
}
void WaylandZwpLinuxDmabuf::NotifyRequestCreateBufferDone(
struct zwp_linux_buffer_params_v1* params,
struct wl_buffer* new_buffer) {
auto it = pending_params_.find(params);
DCHECK(it != pending_params_.end());
std::move(it->second).Run(wl::Object<struct wl_buffer>(new_buffer));
pending_params_.erase(it);
zwp_linux_buffer_params_v1_destroy(params);
connection_->ScheduleFlush();
}
// static
void WaylandZwpLinuxDmabuf::Modifiers(
void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
uint32_t format,
uint32_t modifier_hi,
uint32_t modifier_lo) {
WaylandZwpLinuxDmabuf* self = static_cast<WaylandZwpLinuxDmabuf*>(data);
if (self)
self->AddSupportedFourCCFormat(format);
}
// static
void WaylandZwpLinuxDmabuf::Format(void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
uint32_t format) {
WaylandZwpLinuxDmabuf* self = static_cast<WaylandZwpLinuxDmabuf*>(data);
if (self)
self->AddSupportedFourCCFormat(format);
}
// static
void WaylandZwpLinuxDmabuf::CreateSucceeded(
void* data,
struct zwp_linux_buffer_params_v1* params,
struct wl_buffer* new_buffer) {
WaylandZwpLinuxDmabuf* self = static_cast<WaylandZwpLinuxDmabuf*>(data);
if (self)
self->NotifyRequestCreateBufferDone(params, new_buffer);
}
// static
void WaylandZwpLinuxDmabuf::CreateFailed(
void* data,
struct zwp_linux_buffer_params_v1* params) {
WaylandZwpLinuxDmabuf* self = static_cast<WaylandZwpLinuxDmabuf*>(data);
if (self)
self->NotifyRequestCreateBufferDone(params, nullptr);
}
} // namespace ui
// Copyright 2019 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_WAYLAND_ZWP_LINUX_DMABUF_H_
#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_ZWP_LINUX_DMABUF_H_
#include <vector>
#include "base/containers/flat_map.h"
#include "base/files/file.h"
#include "base/macros.h"
#include "ui/ozone/platform/wayland/wayland_object.h"
#include "ui/ozone/platform/wayland/wayland_util.h"
struct zwp_linux_dmabuf_v1;
struct zwp_linux_buffer_params_v1;
namespace gfx {
enum class BufferFormat;
class Size;
} // namespace gfx
namespace ui {
class WaylandConnection;
// Wrapper around |zwp_linux_dmabuf_v1| Wayland factory, which creates
// |wl_buffer|s backed by dmabuf |file| descriptor.
class WaylandZwpLinuxDmabuf {
public:
WaylandZwpLinuxDmabuf(zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
WaylandConnection* connection);
~WaylandZwpLinuxDmabuf();
// Requests to create a wl_buffer backed by the |file| descriptor. The result
// is sent back via the |callback|. If buffer creation failed, nullptr is sent
// back via the callback. Otherwise, a pointer to the |wl_buffer| is sent.
void CreateBuffer(base::File file,
const gfx::Size& size,
const std::vector<uint32_t>& strides,
const std::vector<uint32_t>& offsets,
const std::vector<uint64_t>& modifiers,
uint32_t format,
uint32_t planes_count,
wl::OnRequestBufferCallback callback);
// Returns supported buffer formats received from the Wayland compositor.
std::vector<gfx::BufferFormat> supported_buffer_formats() const {
return supported_buffer_formats_;
}
private:
// Receives supported |fourcc_format| from either ::Modifers or ::Format call
// (depending on the protocol version), and stores it as gfx::BufferFormat to
// the |supported_buffer_formats_| container.
void AddSupportedFourCCFormat(uint32_t fourcc_format);
// Finds the stored callback corresponding to the |params| created in the
// RequestBufferAsync call, and passes the wl_buffer to the client. The
// |new_buffer| can be null.
void NotifyRequestCreateBufferDone(struct zwp_linux_buffer_params_v1* params,
struct wl_buffer* new_buffer);
// zwp_linux_dmabuf_v1_listener
static void Modifiers(void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
uint32_t format,
uint32_t modifier_hi,
uint32_t modifier_lo);
static void Format(void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
uint32_t format);
// zwp_linux_buffer_params_v1_listener
static void CreateSucceeded(void* data,
struct zwp_linux_buffer_params_v1* params,
struct wl_buffer* new_buffer);
static void CreateFailed(void* data,
struct zwp_linux_buffer_params_v1* params);
// Holds pointer to the zwp_linux_dmabuf_v1 Wayland factory.
const wl::Object<zwp_linux_dmabuf_v1> zwp_linux_dmabuf_;
// Non-owned.
WaylandConnection* const connection_;
// Holds supported DRM formats translated to gfx::BufferFormat.
std::vector<gfx::BufferFormat> supported_buffer_formats_;
// Contains callbacks for requests to create |wl_buffer|s using
// |zwp_linux_dmabuf_| factory.
base::flat_map<struct zwp_linux_buffer_params_v1*,
wl::OnRequestBufferCallback>
pending_params_;
DISALLOW_COPY_AND_ASSIGN(WaylandZwpLinuxDmabuf);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_ZWP_LINUX_DMABUF_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment