backend-drm: Move fb -> buffer reference to plane state

Currently each drm_fb takes a reference on a client buffer it wraps.
This prevents us from being able to reuse a drm_fb in multiple places
(e.g. two views of the same client buffer) simultaneously, or even back
to back.

Move the buffer reference to the plane state, as preparation for
allowing drm_fb to be cached inside the weston_buffer.

Signed-off-by: Daniel Stone <daniels@collabora.com>
dev
Daniel Stone 3 years ago
parent 267f6cc6a1
commit 2ecc38b042
  1. 6
      libweston/backend-drm/drm-internal.h
  2. 2
      libweston/backend-drm/fb.c
  3. 17
      libweston/backend-drm/state-helpers.c
  4. 9
      libweston/backend-drm/state-propose.c

@ -340,8 +340,6 @@ struct drm_fb {
uint64_t modifier;
int width, height;
int fd;
struct weston_buffer_reference buffer_ref;
struct weston_buffer_release_reference buffer_release_ref;
/* Used by gbm fbs */
struct gbm_bo *bo;
@ -411,6 +409,10 @@ struct drm_plane_state {
struct drm_output_state *output_state;
struct drm_fb *fb;
struct {
struct weston_buffer_reference buffer;
struct weston_buffer_release_reference release;
} fb_ref;
struct weston_view *ev; /**< maintained for drm_assign_planes only */

@ -48,8 +48,6 @@ drm_fb_destroy(struct drm_fb *fb)
{
if (fb->fb_id != 0)
drmModeRmFB(fb->fd, fb->fb_id);
weston_buffer_reference(&fb->buffer_ref, NULL);
weston_buffer_release_reference(&fb->buffer_release_ref, NULL);
free(fb);
}

@ -93,6 +93,8 @@ drm_plane_state_free(struct drm_plane_state *state, bool force)
if (force || state != state->plane->state_cur) {
drm_fb_unref(state->fb);
weston_buffer_reference(&state->fb_ref.buffer, NULL);
weston_buffer_release_reference(&state->fb_ref.release, NULL);
free(state);
}
}
@ -128,8 +130,21 @@ drm_plane_state_duplicate(struct drm_output_state *state_output,
}
wl_list_insert(&state_output->plane_list, &dst->link);
if (src->fb)
/* Take a reference on the src framebuffer; if it wraps a client
* buffer, then we must also transfer the reference on the client
* buffer. */
if (src->fb) {
dst->fb = drm_fb_ref(src->fb);
memset(&dst->fb_ref, 0, sizeof(dst->fb_ref));
weston_buffer_reference(&dst->fb_ref.buffer,
src->fb_ref.buffer.buffer);
weston_buffer_release_reference(&dst->fb_ref.release,
src->fb_ref.release.buffer_release);
} else {
assert(!src->fb_ref.buffer.buffer);
assert(!src->fb_ref.release.buffer_release);
}
dst->output_state = state_output;
dst->complete = false;

@ -607,14 +607,15 @@ out:
/* Take a reference on the buffer so that we don't release it
* back to the client until we're done with it; cursor buffers
* don't require a reference since we copy them. */
assert(fb->buffer_ref.buffer == NULL);
assert(fb->buffer_release_ref.buffer_release == NULL);
assert(ps->fb_ref.buffer.buffer == NULL);
assert(ps->fb_ref.release.buffer_release == NULL);
if (ps->plane->type == WDRM_PLANE_TYPE_CURSOR) {
assert(ps->fb->type == BUFFER_CURSOR);
} else if (fb->type == BUFFER_CLIENT || fb->type == BUFFER_DMABUF) {
assert(ps->fb == fb);
weston_buffer_reference(&fb->buffer_ref, surface->buffer_ref.buffer);
weston_buffer_release_reference(&fb->buffer_release_ref,
weston_buffer_reference(&ps->fb_ref.buffer,
surface->buffer_ref.buffer);
weston_buffer_release_reference(&ps->fb_ref.release,
surface->buffer_release_ref.buffer_release);
}
break;

Loading…
Cancel
Save