mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-17 06:46:39 -04:00
start using texture sets
There are really two main uses of texture sets: checking if a dmabuf is importable, and actually importing it for the client buffer's texture
This commit is contained in:
parent
a446e1801f
commit
0925a529ab
6 changed files with 54 additions and 19 deletions
|
|
@ -142,7 +142,7 @@ struct wlr_client_buffer {
|
||||||
* The buffer's texture, if any. A buffer will not have a texture if the
|
* The buffer's texture, if any. A buffer will not have a texture if the
|
||||||
* client destroys the buffer before it has been released.
|
* client destroys the buffer before it has been released.
|
||||||
*/
|
*/
|
||||||
struct wlr_texture *texture;
|
struct wlr_texture_set *texture_set;
|
||||||
/**
|
/**
|
||||||
* The buffer this client buffer was created from. NULL if destroyed.
|
* The buffer this client buffer was created from. NULL if destroyed.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,9 @@ struct wlr_linux_dmabuf_v1 {
|
||||||
|
|
||||||
int main_device_fd; // to sanity check FDs sent by clients, -1 if unavailable
|
int main_device_fd; // to sanity check FDs sent by clients, -1 if unavailable
|
||||||
|
|
||||||
|
// This is only set when the compositor isn't providing a custom renderer.
|
||||||
|
struct wlr_renderer *main_renderer;
|
||||||
|
|
||||||
struct wl_listener display_destroy;
|
struct wl_listener display_destroy;
|
||||||
|
|
||||||
bool (*check_dmabuf_callback)(struct wlr_dmabuf_attributes *attribs, void *data);
|
bool (*check_dmabuf_callback)(struct wlr_dmabuf_attributes *attribs, void *data);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ static struct wlr_client_buffer *client_buffer_from_buffer(
|
||||||
static void client_buffer_destroy(struct wlr_buffer *buffer) {
|
static void client_buffer_destroy(struct wlr_buffer *buffer) {
|
||||||
struct wlr_client_buffer *client_buffer = client_buffer_from_buffer(buffer);
|
struct wlr_client_buffer *client_buffer = client_buffer_from_buffer(buffer);
|
||||||
wl_list_remove(&client_buffer->source_destroy.link);
|
wl_list_remove(&client_buffer->source_destroy.link);
|
||||||
wlr_texture_destroy(client_buffer->texture);
|
wlr_texture_set_destroy(client_buffer->texture_set);
|
||||||
free(client_buffer);
|
free(client_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,21 +56,21 @@ static void client_buffer_handle_source_destroy(struct wl_listener *listener,
|
||||||
|
|
||||||
struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer,
|
struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer,
|
||||||
struct wlr_renderer *renderer) {
|
struct wlr_renderer *renderer) {
|
||||||
struct wlr_texture *texture = wlr_texture_from_buffer(renderer, buffer);
|
struct wlr_texture_set *texture_set = wlr_texture_set_from_buffer(renderer, buffer);
|
||||||
if (texture == NULL) {
|
if (texture_set == NULL) {
|
||||||
wlr_log(WLR_ERROR, "Failed to create texture");
|
wlr_log(WLR_ERROR, "Failed to create texture");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_client_buffer *client_buffer = calloc(1, sizeof(*client_buffer));
|
struct wlr_client_buffer *client_buffer = calloc(1, sizeof(*client_buffer));
|
||||||
if (client_buffer == NULL) {
|
if (client_buffer == NULL) {
|
||||||
wlr_texture_destroy(texture);
|
wlr_texture_set_destroy(texture_set);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
wlr_buffer_init(&client_buffer->base, &client_buffer_impl,
|
wlr_buffer_init(&client_buffer->base, &client_buffer_impl,
|
||||||
texture->width, texture->height);
|
buffer->width, buffer->height);
|
||||||
client_buffer->source = buffer;
|
client_buffer->source = buffer;
|
||||||
client_buffer->texture = texture;
|
client_buffer->texture_set = texture_set;
|
||||||
|
|
||||||
wl_signal_add(&buffer->events.destroy, &client_buffer->source_destroy);
|
wl_signal_add(&buffer->events.destroy, &client_buffer->source_destroy);
|
||||||
client_buffer->source_destroy.notify = client_buffer_handle_source_destroy;
|
client_buffer->source_destroy.notify = client_buffer_handle_source_destroy;
|
||||||
|
|
@ -89,5 +89,5 @@ bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wlr_texture_update_from_buffer(client_buffer->texture, next, damage);
|
return wlr_texture_set_update_from_buffer(client_buffer->texture_set, next, damage);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -878,7 +878,8 @@ static struct wlr_texture *scene_buffer_get_texture(
|
||||||
struct wlr_client_buffer *client_buffer =
|
struct wlr_client_buffer *client_buffer =
|
||||||
wlr_client_buffer_get(scene_buffer->buffer);
|
wlr_client_buffer_get(scene_buffer->buffer);
|
||||||
if (client_buffer != NULL) {
|
if (client_buffer != NULL) {
|
||||||
return client_buffer->texture;
|
return wlr_texture_set_get_tex_for_renderer(client_buffer->texture_set,
|
||||||
|
renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
scene_buffer->texture =
|
scene_buffer->texture =
|
||||||
|
|
|
||||||
|
|
@ -445,7 +445,11 @@ static void surface_apply_damage(struct wlr_surface *surface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_update_opaque_region(struct wlr_surface *surface) {
|
static void surface_update_opaque_region(struct wlr_surface *surface) {
|
||||||
if (!wlr_surface_has_buffer(surface)) {
|
/*
|
||||||
|
* The surface's client_buffer may not have a texture imported yet,
|
||||||
|
* but if it has a texture set it is tracking a valid buffer.
|
||||||
|
*/
|
||||||
|
if (!wlr_surface_has_buffer(surface) || !surface->buffer->texture_set) {
|
||||||
pixman_region32_clear(&surface->opaque_region);
|
pixman_region32_clear(&surface->opaque_region);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -817,7 +821,8 @@ struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface) {
|
||||||
if (surface->buffer == NULL) {
|
if (surface->buffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return surface->buffer->texture;
|
return wlr_texture_set_get_tex_for_renderer(surface->buffer->texture_set,
|
||||||
|
surface->renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_surface_has_buffer(struct wlr_surface *surface) {
|
bool wlr_surface_has_buffer(struct wlr_surface *surface) {
|
||||||
|
|
|
||||||
|
|
@ -211,16 +211,39 @@ static bool check_import_dmabuf(struct wlr_dmabuf_attributes *attribs, void *dat
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check number of planes
|
/*
|
||||||
for (int i = 0; i < attribs->n_planes; i++) {
|
* Some compositors will be using this linux dmabuf manager with custom renderers,
|
||||||
uint32_t handle = 0;
|
* while others will use a wlroots-managed wlr_renderer. When checking if a dmabuf
|
||||||
if (drmPrimeFDToHandle(linux_dmabuf->main_device_fd, attribs->fd[i], &handle) != 0) {
|
* is valid for import we should treat these differently. In the first case we just
|
||||||
wlr_log_errno(WLR_DEBUG, "Failed to import DMA-BUF FD");
|
* need to check if the dmabuf is importable into the DRM device, in the wlroots-managed
|
||||||
|
* renderer case we should check if this dmabuf can be imported into the renderer.
|
||||||
|
*
|
||||||
|
* In the case where we have a wlr_renderer we need to check if a texture set can
|
||||||
|
* be created in order to handle multi-gpu systems. The texture set will handle ensuring
|
||||||
|
* that the dmabuf is importable on one GPU in the system, instead of only checking
|
||||||
|
* the main device.
|
||||||
|
*/
|
||||||
|
if (linux_dmabuf->main_renderer) {
|
||||||
|
struct wlr_texture_set *set=
|
||||||
|
wlr_texture_set_from_dmabuf(linux_dmabuf->main_renderer, attribs);
|
||||||
|
if (!set) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (drmCloseBufferHandle(linux_dmabuf->main_device_fd, handle) != 0) {
|
// We can import the image, good. No need to keep it since wlr_surface will
|
||||||
wlr_log_errno(WLR_ERROR, "Failed to close buffer handle");
|
// import it again on commit.
|
||||||
return false;
|
wlr_texture_set_destroy(set);
|
||||||
|
} else {
|
||||||
|
// TODO: check number of planes
|
||||||
|
for (int i = 0; i < attribs->n_planes; i++) {
|
||||||
|
uint32_t handle = 0;
|
||||||
|
if (drmPrimeFDToHandle(linux_dmabuf->main_device_fd, attribs->fd[i], &handle) != 0) {
|
||||||
|
wlr_log_errno(WLR_DEBUG, "Failed to import DMA-BUF FD");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (drmCloseBufferHandle(linux_dmabuf->main_device_fd, handle) != 0) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "Failed to close buffer handle");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1001,6 +1024,9 @@ struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_create_with_renderer(struct wl_d
|
||||||
struct wlr_linux_dmabuf_v1 *linux_dmabuf =
|
struct wlr_linux_dmabuf_v1 *linux_dmabuf =
|
||||||
wlr_linux_dmabuf_v1_create(display, version, &feedback);
|
wlr_linux_dmabuf_v1_create(display, version, &feedback);
|
||||||
wlr_linux_dmabuf_feedback_v1_finish(&feedback);
|
wlr_linux_dmabuf_feedback_v1_finish(&feedback);
|
||||||
|
|
||||||
|
linux_dmabuf->main_renderer = renderer;
|
||||||
|
|
||||||
return linux_dmabuf;
|
return linux_dmabuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue