diff options
author | Leandro Ribeiro <leandro.ribeiro@collabora.com> | 2022-01-24 18:35:03 -0300 |
---|---|---|
committer | Marius Vlad <marius.vlad@collabora.com> | 2022-05-24 22:11:23 +0300 |
commit | d2d5c666a3926d2e7924b597546942e364189c97 (patch) | |
tree | bd3221ab125596f50534d2d6fcf19d554ab73bb5 | |
parent | f573612d379503c85f106a2f19924bf8f21a11cf (diff) | |
download | weston-d2d5c666a3926d2e7924b597546942e364189c97.tar.gz |
clients/simple-dmabuf-feedback: do not use buffer before compositor's response
This fixes an issue when running simple-dmabuf-feedback:
"wl_display@1: error 1: invalid arguments for wl_surface@3.attach".
As we are not using create_immed request from zwp_linux_dmabuf_v1, we
can't start to use a dma-buf buffer before we process compositor's event
telling us that the creation succeeded.
This was causing problems in the following scenario:
1. buffer is marked to be recreated (because of dma-buf feedback);
2. in buffer_release() event, we destroy the buffer and recreate it;
3. after we recreate it, roundtrip is not called, as we don't want to
block during the drawing loop;
4. buffer status is not being properly tracked, so we are trying to
use a buffer before receiving the event from the compositor telling
us that the creation succeeded.
To fix this, this patch improves buffer status tracking. Now we only
pick a buffer in the drawing loop when it is available. Also, if we have
no buffers available we perform a roundtrip and try again, as we may
have recreated all of them but still didn't have the chance to process
compositor's events telling us that creation succeeded.
Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
(cherry picked from commit 7724c5ea380da617883ce8f644276e75f7e5bb7f)
-rw-r--r-- | clients/simple-dmabuf-feedback.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/clients/simple-dmabuf-feedback.c b/clients/simple-dmabuf-feedback.c index dd2e64a5..94d734b9 100644 --- a/clients/simple-dmabuf-feedback.c +++ b/clients/simple-dmabuf-feedback.c @@ -140,7 +140,11 @@ struct display { struct buffer { struct window *window; struct wl_buffer *buffer; - bool busy; + enum { + NOT_CREATED, + IN_USE, + AVAILABLE + } status; bool recreate; int dmabuf_fds[4]; struct gbm_bo *bo; @@ -469,7 +473,7 @@ buffer_release(void *data, struct wl_buffer *buffer) { struct buffer *buf = data; - buf->busy = false; + buf->status = AVAILABLE; if (buf->recreate) buffer_recreate(buf); @@ -485,6 +489,7 @@ create_succeeded(void *data, struct zwp_linux_buffer_params_v1 *params, { struct buffer *buf = data; + buf->status = AVAILABLE; buf->buffer = new_buffer; wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); zwp_linux_buffer_params_v1_destroy(params); @@ -516,6 +521,7 @@ create_dmabuf_buffer(struct window *window, struct buffer *buf, uint32_t width, struct zwp_linux_buffer_params_v1 *params; int i; + buf->status = NOT_CREATED; buf->window = window; buf->width = width; buf->height = height; @@ -573,8 +579,22 @@ window_next_buffer(struct window *window) unsigned int i; for (i = 0; i < NUM_BUFFERS; i++) - if (!window->buffers[i].busy) + if (window->buffers[i].status == AVAILABLE) return &window->buffers[i]; + + /* In this client, we sometimes have to recreate the buffers. As we are + * not using the create_immed request from zwp_linux_dmabuf_v1, we need + * to wait an event from the server (what leads to create_succeeded() + * being called in this client). So if all buffers are busy, it may be + * the case in which all the buffers were recreated but the server still + * didn't send the events. This is very unlikely to happen, but a + * roundtrip() guarantees that we receive and process the events. */ + wl_display_roundtrip(window->display->display); + + for (i = 0; i < NUM_BUFFERS; i++) + if (window->buffers[i].status == AVAILABLE) + return &window->buffers[i]; + return NULL; } @@ -639,7 +659,7 @@ redraw(void *data, struct wl_callback *callback, uint32_t time) window->callback = wl_surface_frame(window->surface); wl_callback_add_listener(window->callback, &frame_listener, window); wl_surface_commit(window->surface); - buf->busy = true; + buf->status = IN_USE; region = wl_compositor_create_region(window->display->compositor); wl_region_add(region, 0, 0, window->display->output.width, |