mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-14 08:22:25 -04:00
linux_dmabuf_v1: Introduce main device
Introduce properties for the main renderer and allocator the compositor wants wlroots to use when it needs to blit to a staging buffer during multigpu. We need to perform an additional blit if the modifier is not compatible with the target GPU.
This commit is contained in:
parent
5eb9a2ea10
commit
b0e8e6eae7
3 changed files with 107 additions and 5 deletions
|
|
@ -17,6 +17,8 @@
|
|||
#include <wlr/render/drm_format_set.h>
|
||||
|
||||
struct wlr_surface;
|
||||
struct wlr_renderer;
|
||||
struct wlr_allocator;
|
||||
|
||||
struct wlr_dmabuf_v1_buffer {
|
||||
struct wlr_buffer base;
|
||||
|
|
@ -27,6 +29,8 @@ struct wlr_dmabuf_v1_buffer {
|
|||
// private state
|
||||
|
||||
struct wl_listener release;
|
||||
|
||||
struct wlr_linux_dmabuf_v1 *linux_dmabuf_v1;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -63,7 +67,13 @@ struct wlr_linux_dmabuf_v1 {
|
|||
|
||||
int main_device_fd; // to sanity check FDs sent by clients, -1 if unavailable
|
||||
|
||||
// used for multigpu
|
||||
struct wlr_renderer *main_renderer;
|
||||
struct wlr_allocator *main_allocator;
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
struct wl_listener main_renderer_destroy;
|
||||
struct wl_listener main_allocator_destroy;
|
||||
|
||||
bool (*check_dmabuf_callback)(struct wlr_dmabuf_attributes *attribs, void *data);
|
||||
void *check_dmabuf_callback_data;
|
||||
|
|
@ -78,6 +88,23 @@ struct wlr_linux_dmabuf_v1 {
|
|||
struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_create(struct wl_display *display,
|
||||
uint32_t version, const struct wlr_linux_dmabuf_feedback_v1 *default_feedback);
|
||||
|
||||
/**
|
||||
* Returns the associated dmabuf object from a generic buffer. Returnns
|
||||
* NULL if the generic buffer is not a dmabuf.
|
||||
*/
|
||||
struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_try_from_buffer(
|
||||
struct wlr_buffer *buffer);
|
||||
|
||||
/**
|
||||
* Sets the main blit device used for multigpu. With multigpu, dmabufs with
|
||||
* implicit modifiers or just modifiers that aren't supported by other GPUs
|
||||
* might need to be blitted into a staging buffer with correct modifiers. This
|
||||
* will be done with this allocator (to allocate the staging buffer) and renderer
|
||||
* to render into the staging buffer.
|
||||
*/
|
||||
void wlr_linux_dmabuf_v1_set_main_blit_device(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
|
||||
struct wlr_renderer *renderer, struct wlr_allocator *allocator);
|
||||
|
||||
/**
|
||||
* Create the linux-dmabuf-v1 global.
|
||||
*
|
||||
|
|
@ -120,6 +147,9 @@ void wlr_linux_dmabuf_feedback_v1_finish(struct wlr_linux_dmabuf_feedback_v1 *fe
|
|||
struct wlr_linux_dmabuf_feedback_v1_init_options {
|
||||
// Main renderer used by the compositor
|
||||
struct wlr_renderer *main_renderer;
|
||||
// Optional allocator created for the primary GPU used by the default feedback.
|
||||
// This is used for multi gpu for allocating staging buffers.
|
||||
struct wlr_allocator *main_allocator;
|
||||
// Output on which direct scan-out is possible on the primary plane, or NULL
|
||||
struct wlr_output *scanout_primary_output;
|
||||
// Output layer feedback event, or NULL
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <wlr/backend.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/interfaces/wlr_buffer.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
|
|
@ -92,16 +93,19 @@ struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_try_from_buffer_resource(
|
|||
|
||||
static const struct wlr_buffer_impl buffer_impl;
|
||||
|
||||
static struct wlr_dmabuf_v1_buffer *dmabuf_v1_buffer_from_buffer(
|
||||
struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_try_from_buffer(
|
||||
struct wlr_buffer *wlr_buffer) {
|
||||
assert(wlr_buffer->impl == &buffer_impl);
|
||||
if (wlr_buffer->impl != &buffer_impl) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_dmabuf_v1_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
||||
struct wlr_dmabuf_v1_buffer *buffer =
|
||||
dmabuf_v1_buffer_from_buffer(wlr_buffer);
|
||||
wlr_dmabuf_v1_buffer_try_from_buffer(wlr_buffer);
|
||||
if (buffer->resource != NULL) {
|
||||
wl_resource_set_user_data(buffer->resource, NULL);
|
||||
}
|
||||
|
|
@ -113,7 +117,7 @@ static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
|||
static bool buffer_get_dmabuf(struct wlr_buffer *wlr_buffer,
|
||||
struct wlr_dmabuf_attributes *attribs) {
|
||||
struct wlr_dmabuf_v1_buffer *buffer =
|
||||
dmabuf_v1_buffer_from_buffer(wlr_buffer);
|
||||
wlr_dmabuf_v1_buffer_try_from_buffer(wlr_buffer);
|
||||
*attribs = buffer->attributes;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -368,6 +372,7 @@ static void params_create_common(struct wl_resource *params_resource,
|
|||
&wl_buffer_impl, buffer, buffer_handle_resource_destroy);
|
||||
|
||||
buffer->attributes = attribs;
|
||||
buffer->linux_dmabuf_v1 = linux_dmabuf;
|
||||
|
||||
buffer->release.notify = buffer_handle_release;
|
||||
wl_signal_add(&buffer->base.events.release, &buffer->release);
|
||||
|
|
@ -872,6 +877,8 @@ static void linux_dmabuf_v1_destroy(struct wlr_linux_dmabuf_v1 *linux_dmabuf) {
|
|||
}
|
||||
|
||||
wl_list_remove(&linux_dmabuf->display_destroy.link);
|
||||
wl_list_remove(&linux_dmabuf->main_renderer_destroy.link);
|
||||
wl_list_remove(&linux_dmabuf->main_allocator_destroy.link);
|
||||
|
||||
wl_global_destroy(linux_dmabuf->global);
|
||||
free(linux_dmabuf);
|
||||
|
|
@ -959,6 +966,8 @@ struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_create(struct wl_display *displa
|
|||
linux_dmabuf->main_device_fd = -1;
|
||||
|
||||
wl_list_init(&linux_dmabuf->surfaces);
|
||||
wl_list_init(&linux_dmabuf->main_renderer_destroy.link);
|
||||
wl_list_init(&linux_dmabuf->main_allocator_destroy.link);
|
||||
wl_signal_init(&linux_dmabuf->events.destroy);
|
||||
|
||||
linux_dmabuf->global = wl_global_create(display, &zwp_linux_dmabuf_v1_interface,
|
||||
|
|
@ -1161,3 +1170,42 @@ error:
|
|||
wlr_linux_dmabuf_feedback_v1_finish(feedback);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void linux_dmabuf_unregister_main_blit_device(struct wlr_linux_dmabuf_v1 *linux_dmabuf) {
|
||||
wl_list_remove(&linux_dmabuf->main_renderer_destroy.link);
|
||||
wl_list_remove(&linux_dmabuf->main_allocator_destroy.link);
|
||||
wl_list_init(&linux_dmabuf->main_renderer_destroy.link);
|
||||
wl_list_init(&linux_dmabuf->main_allocator_destroy.link);
|
||||
|
||||
linux_dmabuf->main_renderer = NULL;
|
||||
linux_dmabuf->main_allocator = NULL;
|
||||
}
|
||||
|
||||
static void linux_dmabuf_handle_main_renderer_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_linux_dmabuf_v1 *linux_dmabuf = wl_container_of(
|
||||
listener, linux_dmabuf, main_renderer_destroy);
|
||||
linux_dmabuf_unregister_main_blit_device(linux_dmabuf);
|
||||
}
|
||||
|
||||
static void linux_dmabuf_handle_main_allocator_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_linux_dmabuf_v1 *linux_dmabuf = wl_container_of(
|
||||
listener, linux_dmabuf, main_allocator_destroy);
|
||||
linux_dmabuf_unregister_main_blit_device(linux_dmabuf);
|
||||
}
|
||||
|
||||
void wlr_linux_dmabuf_v1_set_main_blit_device(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
|
||||
struct wlr_renderer *renderer, struct wlr_allocator *allocator) {
|
||||
assert(renderer != NULL && allocator != NULL);
|
||||
|
||||
wl_list_remove(&linux_dmabuf->main_renderer_destroy.link);
|
||||
wl_list_remove(&linux_dmabuf->main_allocator_destroy.link);
|
||||
|
||||
linux_dmabuf->main_renderer_destroy.notify = linux_dmabuf_handle_main_renderer_destroy;
|
||||
wl_signal_add(&renderer->events.destroy, &linux_dmabuf->main_renderer_destroy);
|
||||
|
||||
linux_dmabuf->main_allocator_destroy.notify = linux_dmabuf_handle_main_allocator_destroy;
|
||||
wl_signal_add(&allocator->events.destroy, &linux_dmabuf->main_allocator_destroy);
|
||||
|
||||
linux_dmabuf->main_renderer = renderer;
|
||||
linux_dmabuf->main_allocator = allocator;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
#include <wlr/render/wlr_texture.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
|
||||
#include <wlr/types/wlr_matrix.h>
|
||||
#include <wlr/types/wlr_raster.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
#include <wlr/render/wlr_texture.h>
|
||||
|
|
@ -368,6 +368,30 @@ struct wlr_texture *wlr_raster_obtain_texture_with_allocator(struct wlr_raster *
|
|||
return texture;
|
||||
}
|
||||
|
||||
// if this is a linux_dmabuf_v1 buffer, then we can try to use the
|
||||
// main device for blitting which should support all the modifiers we
|
||||
// advertise.
|
||||
if (raster->buffer) {
|
||||
struct wlr_dmabuf_v1_buffer *dmabuf_buffer =
|
||||
wlr_dmabuf_v1_buffer_try_from_buffer(raster->buffer);
|
||||
if (dmabuf_buffer && dmabuf_buffer->linux_dmabuf_v1->main_renderer) {
|
||||
struct wlr_linux_dmabuf_v1 *linux_dmabuf = dmabuf_buffer->linux_dmabuf_v1;
|
||||
struct wlr_texture *texture = wlr_texture_from_buffer(
|
||||
linux_dmabuf->main_renderer, raster->buffer);
|
||||
if (texture) {
|
||||
wlr_raster_attach_with_allocator(raster, texture,
|
||||
linux_dmabuf->main_allocator);
|
||||
|
||||
// try to create a blit but this time through the primary device
|
||||
texture = raster_try_texture_from_blit(raster, renderer);
|
||||
if (texture) {
|
||||
wlr_raster_attach_with_allocator(raster, texture, allocator);
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// as a last resort we need to do a copy through the CPU
|
||||
texture = raster_try_cpu_copy(raster, renderer);
|
||||
if (texture) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue