fix(wayland): support DMA-BUF modifiers for wlroots capture (#5132)
This commit is contained in:
@@ -176,6 +176,10 @@ namespace wl {
|
|||||||
listener {
|
listener {
|
||||||
&CLASS_CALL(interface_t, add_interface),
|
&CLASS_CALL(interface_t, add_interface),
|
||||||
&CLASS_CALL(interface_t, del_interface)
|
&CLASS_CALL(interface_t, del_interface)
|
||||||
|
},
|
||||||
|
dmabuf_listener {
|
||||||
|
&CLASS_CALL(interface_t, dmabuf_format),
|
||||||
|
&CLASS_CALL(interface_t, dmabuf_modifier)
|
||||||
} {
|
} {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,6 +187,14 @@ namespace wl {
|
|||||||
wl_registry_add_listener(registry, &listener, this);
|
wl_registry_add_listener(registry, &listener, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void interface_t::dmabuf_format(zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void interface_t::dmabuf_modifier(zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo) {
|
||||||
|
uint64_t modifier = ((uint64_t) modifier_hi << 32) | modifier_lo;
|
||||||
|
supported_modifiers[format].push_back(modifier);
|
||||||
|
}
|
||||||
|
|
||||||
void interface_t::add_interface(
|
void interface_t::add_interface(
|
||||||
wl_registry *registry,
|
wl_registry *registry,
|
||||||
std::uint32_t id,
|
std::uint32_t id,
|
||||||
@@ -210,7 +222,8 @@ namespace wl {
|
|||||||
this->interface[WLR_EXPORT_DMABUF] = true;
|
this->interface[WLR_EXPORT_DMABUF] = true;
|
||||||
} else if (!std::strcmp(interface, zwp_linux_dmabuf_v1_interface.name)) {
|
} else if (!std::strcmp(interface, zwp_linux_dmabuf_v1_interface.name)) {
|
||||||
BOOST_LOG(info) << "[wayland] Found interface: "sv << interface << '(' << id << ") version "sv << version;
|
BOOST_LOG(info) << "[wayland] Found interface: "sv << interface << '(' << id << ") version "sv << version;
|
||||||
dmabuf_interface = (zwp_linux_dmabuf_v1 *) wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, version);
|
dmabuf_interface = (zwp_linux_dmabuf_v1 *) wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, std::min(version, 3u));
|
||||||
|
zwp_linux_dmabuf_v1_add_listener(dmabuf_interface, &dmabuf_listener, this);
|
||||||
|
|
||||||
this->interface[LINUX_DMABUF] = true;
|
this->interface[LINUX_DMABUF] = true;
|
||||||
}
|
}
|
||||||
@@ -275,10 +288,12 @@ namespace wl {
|
|||||||
void dmabuf_t::listen(
|
void dmabuf_t::listen(
|
||||||
zwlr_screencopy_manager_v1 *screencopy_manager,
|
zwlr_screencopy_manager_v1 *screencopy_manager,
|
||||||
zwp_linux_dmabuf_v1 *dmabuf_interface,
|
zwp_linux_dmabuf_v1 *dmabuf_interface,
|
||||||
|
const std::map<std::uint32_t, std::vector<std::uint64_t>> *supported_modifiers,
|
||||||
wl_output *output,
|
wl_output *output,
|
||||||
bool blend_cursor
|
bool blend_cursor
|
||||||
) {
|
) {
|
||||||
this->dmabuf_interface = dmabuf_interface;
|
this->dmabuf_interface = dmabuf_interface;
|
||||||
|
this->supported_modifiers = supported_modifiers;
|
||||||
// Reset state
|
// Reset state
|
||||||
shm_info.supported = false;
|
shm_info.supported = false;
|
||||||
dmabuf_info.supported = false;
|
dmabuf_info.supported = false;
|
||||||
@@ -357,7 +372,17 @@ namespace wl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create GBM buffer
|
// Create GBM buffer
|
||||||
current_bo = gbm_bo_create(gbm_device, dmabuf_info.width, dmabuf_info.height, dmabuf_info.format, GBM_BO_USE_RENDERING);
|
if (supported_modifiers) {
|
||||||
|
auto it = supported_modifiers->find(dmabuf_info.format);
|
||||||
|
if (it != supported_modifiers->end() && !it->second.empty()) {
|
||||||
|
current_bo = gbm_bo_create_with_modifiers(gbm_device, dmabuf_info.width, dmabuf_info.height, dmabuf_info.format, it->second.data(), it->second.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current_bo) {
|
||||||
|
current_bo = gbm_bo_create(gbm_device, dmabuf_info.width, dmabuf_info.height, dmabuf_info.format, GBM_BO_USE_RENDERING);
|
||||||
|
}
|
||||||
|
|
||||||
if (!current_bo) {
|
if (!current_bo) {
|
||||||
BOOST_LOG(error) << "Failed to create GBM buffer"sv;
|
BOOST_LOG(error) << "Failed to create GBM buffer"sv;
|
||||||
zwlr_screencopy_frame_v1_destroy(frame);
|
zwlr_screencopy_frame_v1_destroy(frame);
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
// standard includes
|
// standard includes
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#ifdef SUNSHINE_BUILD_WAYLAND
|
#ifdef SUNSHINE_BUILD_WAYLAND
|
||||||
#include <linux-dmabuf-unstable-v1.h>
|
#include <linux-dmabuf-unstable-v1.h>
|
||||||
@@ -50,7 +53,7 @@ namespace wl {
|
|||||||
dmabuf_t &operator=(const dmabuf_t &) = delete;
|
dmabuf_t &operator=(const dmabuf_t &) = delete;
|
||||||
dmabuf_t &operator=(dmabuf_t &&) = delete;
|
dmabuf_t &operator=(dmabuf_t &&) = delete;
|
||||||
|
|
||||||
void listen(zwlr_screencopy_manager_v1 *screencopy_manager, zwp_linux_dmabuf_v1 *dmabuf_interface, wl_output *output, bool blend_cursor = false);
|
void listen(zwlr_screencopy_manager_v1 *screencopy_manager, zwp_linux_dmabuf_v1 *dmabuf_interface, const std::map<std::uint32_t, std::vector<std::uint64_t>> *supported_modifiers, wl_output *output, bool blend_cursor = false);
|
||||||
static void buffer_params_created(void *data, struct zwp_linux_buffer_params_v1 *params, struct wl_buffer *wl_buffer);
|
static void buffer_params_created(void *data, struct zwp_linux_buffer_params_v1 *params, struct wl_buffer *wl_buffer);
|
||||||
static void buffer_params_failed(void *data, struct zwp_linux_buffer_params_v1 *params);
|
static void buffer_params_failed(void *data, struct zwp_linux_buffer_params_v1 *params);
|
||||||
void buffer(zwlr_screencopy_frame_v1 *frame, std::uint32_t format, std::uint32_t width, std::uint32_t height, std::uint32_t stride);
|
void buffer(zwlr_screencopy_frame_v1 *frame, std::uint32_t format, std::uint32_t width, std::uint32_t height, std::uint32_t stride);
|
||||||
@@ -76,6 +79,7 @@ namespace wl {
|
|||||||
void create_and_copy_dmabuf(zwlr_screencopy_frame_v1 *frame);
|
void create_and_copy_dmabuf(zwlr_screencopy_frame_v1 *frame);
|
||||||
|
|
||||||
zwp_linux_dmabuf_v1 *dmabuf_interface {nullptr};
|
zwp_linux_dmabuf_v1 *dmabuf_interface {nullptr};
|
||||||
|
const std::map<std::uint32_t, std::vector<std::uint64_t>> *supported_modifiers {nullptr};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool supported {false};
|
bool supported {false};
|
||||||
@@ -158,7 +162,11 @@ namespace wl {
|
|||||||
return interface[bit];
|
return interface[bit];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dmabuf_format(zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format);
|
||||||
|
void dmabuf_modifier(zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo);
|
||||||
|
|
||||||
std::vector<std::unique_ptr<monitor_t>> monitors;
|
std::vector<std::unique_ptr<monitor_t>> monitors;
|
||||||
|
std::map<std::uint32_t, std::vector<std::uint64_t>> supported_modifiers;
|
||||||
zwlr_screencopy_manager_v1 *screencopy_manager {nullptr};
|
zwlr_screencopy_manager_v1 *screencopy_manager {nullptr};
|
||||||
zwp_linux_dmabuf_v1 *dmabuf_interface {nullptr};
|
zwp_linux_dmabuf_v1 *dmabuf_interface {nullptr};
|
||||||
zxdg_output_manager_v1 *output_manager {nullptr};
|
zxdg_output_manager_v1 *output_manager {nullptr};
|
||||||
@@ -169,6 +177,7 @@ namespace wl {
|
|||||||
|
|
||||||
std::bitset<MAX_INTERFACES> interface;
|
std::bitset<MAX_INTERFACES> interface;
|
||||||
wl_registry_listener listener;
|
wl_registry_listener listener;
|
||||||
|
zwp_linux_dmabuf_v1_listener dmabuf_listener;
|
||||||
};
|
};
|
||||||
|
|
||||||
class display_t {
|
class display_t {
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ namespace wl {
|
|||||||
auto to = std::chrono::steady_clock::now() + timeout;
|
auto to = std::chrono::steady_clock::now() + timeout;
|
||||||
|
|
||||||
// Dispatch events until we get a new frame or the timeout expires
|
// Dispatch events until we get a new frame or the timeout expires
|
||||||
dmabuf.listen(interface.screencopy_manager, interface.dmabuf_interface, output, cursor);
|
dmabuf.listen(interface.screencopy_manager, interface.dmabuf_interface, &interface.supported_modifiers, output, cursor);
|
||||||
do {
|
do {
|
||||||
auto remaining_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(to - std::chrono::steady_clock::now());
|
auto remaining_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(to - std::chrono::steady_clock::now());
|
||||||
if (remaining_time_ms.count() < 0 || !display.dispatch(remaining_time_ms)) {
|
if (remaining_time_ms.count() < 0 || !display.dispatch(remaining_time_ms)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user