backend/drm: re-use FBs
Instead of importing buffers to GBM and KMS at each frame, cache them and re-use them while the wlr_buffer is alive. This is the same as [1] and [2] but for the DRM backend. [1]: https://github.com/swaywm/wlroots/pull/2538 [2]: https://github.com/swaywm/wlroots/pull/2539
This commit is contained in:
parent
91cb0fc443
commit
d9bbc416a6
|
@ -42,6 +42,11 @@ static void backend_destroy(struct wlr_backend *backend) {
|
||||||
|
|
||||||
wlr_signal_emit_safe(&backend->events.destroy, backend);
|
wlr_signal_emit_safe(&backend->events.destroy, backend);
|
||||||
|
|
||||||
|
struct wlr_drm_fb *fb, *fb_tmp;
|
||||||
|
wl_list_for_each_safe(fb, fb_tmp, &drm->fbs, link) {
|
||||||
|
drm_fb_destroy(fb);
|
||||||
|
}
|
||||||
|
|
||||||
wl_list_remove(&drm->display_destroy.link);
|
wl_list_remove(&drm->display_destroy.link);
|
||||||
wl_list_remove(&drm->session_destroy.link);
|
wl_list_remove(&drm->session_destroy.link);
|
||||||
wl_list_remove(&drm->session_active.link);
|
wl_list_remove(&drm->session_active.link);
|
||||||
|
@ -147,6 +152,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
|
||||||
wlr_backend_init(&drm->backend, &backend_impl);
|
wlr_backend_init(&drm->backend, &backend_impl);
|
||||||
|
|
||||||
drm->session = session;
|
drm->session = session;
|
||||||
|
wl_list_init(&drm->fbs);
|
||||||
wl_list_init(&drm->outputs);
|
wl_list_init(&drm->outputs);
|
||||||
|
|
||||||
drm->dev = dev;
|
drm->dev = dev;
|
||||||
|
|
|
@ -297,15 +297,7 @@ void drm_fb_clear(struct wlr_drm_fb **fb_ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_drm_fb *fb = *fb_ptr;
|
struct wlr_drm_fb *fb = *fb_ptr;
|
||||||
|
wlr_buffer_unlock(fb->wlr_buf); // may destroy the buffer
|
||||||
struct gbm_device *gbm = gbm_bo_get_device(fb->bo);
|
|
||||||
if (drmModeRmFB(gbm_device_get_fd(gbm), fb->id) != 0) {
|
|
||||||
wlr_log(WLR_ERROR, "drmModeRmFB failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
gbm_bo_destroy(fb->bo);
|
|
||||||
wlr_buffer_unlock(fb->wlr_buf);
|
|
||||||
free(fb);
|
|
||||||
|
|
||||||
*fb_ptr = NULL;
|
*fb_ptr = NULL;
|
||||||
}
|
}
|
||||||
|
@ -362,6 +354,12 @@ static struct gbm_bo *get_bo_for_dmabuf(struct gbm_device *gbm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drm_fb_handle_wlr_buf_destroy(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct wlr_drm_fb *fb = wl_container_of(listener, fb, wlr_buf_destroy);
|
||||||
|
drm_fb_destroy(fb);
|
||||||
|
}
|
||||||
|
|
||||||
static struct wlr_drm_fb *drm_fb_create(struct wlr_drm_backend *drm,
|
static struct wlr_drm_fb *drm_fb_create(struct wlr_drm_backend *drm,
|
||||||
struct wlr_buffer *buf, const struct wlr_drm_format_set *formats) {
|
struct wlr_buffer *buf, const struct wlr_drm_format_set *formats) {
|
||||||
struct wlr_drm_fb *fb = calloc(1, sizeof(*fb));
|
struct wlr_drm_fb *fb = calloc(1, sizeof(*fb));
|
||||||
|
@ -369,8 +367,6 @@ static struct wlr_drm_fb *drm_fb_create(struct wlr_drm_backend *drm,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fb->wlr_buf = wlr_buffer_lock(buf);
|
|
||||||
|
|
||||||
struct wlr_dmabuf_attributes attribs;
|
struct wlr_dmabuf_attributes attribs;
|
||||||
if (!wlr_buffer_get_dmabuf(buf, &attribs)) {
|
if (!wlr_buffer_get_dmabuf(buf, &attribs)) {
|
||||||
wlr_log(WLR_ERROR, "Failed to get DMA-BUF from buffer");
|
wlr_log(WLR_ERROR, "Failed to get DMA-BUF from buffer");
|
||||||
|
@ -403,16 +399,46 @@ static struct wlr_drm_fb *drm_fb_create(struct wlr_drm_backend *drm,
|
||||||
goto error_get_fb_for_bo;
|
goto error_get_fb_for_bo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fb->wlr_buf = buf;
|
||||||
|
|
||||||
|
fb->wlr_buf_destroy.notify = drm_fb_handle_wlr_buf_destroy;
|
||||||
|
wl_signal_add(&buf->events.destroy, &fb->wlr_buf_destroy);
|
||||||
|
|
||||||
|
wl_list_insert(&drm->fbs, &fb->link);
|
||||||
|
|
||||||
return fb;
|
return fb;
|
||||||
|
|
||||||
error_get_fb_for_bo:
|
error_get_fb_for_bo:
|
||||||
gbm_bo_destroy(fb->bo);
|
gbm_bo_destroy(fb->bo);
|
||||||
error_get_dmabuf:
|
error_get_dmabuf:
|
||||||
wlr_buffer_unlock(fb->wlr_buf);
|
|
||||||
free(fb);
|
free(fb);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drm_fb_destroy(struct wlr_drm_fb *fb) {
|
||||||
|
wl_list_remove(&fb->link);
|
||||||
|
wl_list_remove(&fb->wlr_buf_destroy.link);
|
||||||
|
|
||||||
|
struct gbm_device *gbm = gbm_bo_get_device(fb->bo);
|
||||||
|
if (drmModeRmFB(gbm_device_get_fd(gbm), fb->id) != 0) {
|
||||||
|
wlr_log(WLR_ERROR, "drmModeRmFB failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
gbm_bo_destroy(fb->bo);
|
||||||
|
free(fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wlr_drm_fb *drm_fb_get(struct wlr_drm_backend *drm,
|
||||||
|
struct wlr_buffer *local_buf) {
|
||||||
|
struct wlr_drm_fb *fb;
|
||||||
|
wl_list_for_each(fb, &drm->fbs, link) {
|
||||||
|
if (fb->wlr_buf == local_buf) {
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool drm_fb_import(struct wlr_drm_fb **fb_ptr, struct wlr_drm_backend *drm,
|
bool drm_fb_import(struct wlr_drm_fb **fb_ptr, struct wlr_drm_backend *drm,
|
||||||
struct wlr_buffer *buf, struct wlr_drm_surface *mgpu,
|
struct wlr_buffer *buf, struct wlr_drm_surface *mgpu,
|
||||||
const struct wlr_drm_format_set *formats) {
|
const struct wlr_drm_format_set *formats) {
|
||||||
|
@ -428,10 +454,13 @@ bool drm_fb_import(struct wlr_drm_fb **fb_ptr, struct wlr_drm_backend *drm,
|
||||||
local_buf = wlr_buffer_lock(buf);
|
local_buf = wlr_buffer_lock(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_drm_fb *fb = drm_fb_create(drm, local_buf, formats);
|
struct wlr_drm_fb *fb = drm_fb_get(drm, local_buf);
|
||||||
wlr_buffer_unlock(local_buf);
|
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
return false;
|
fb = drm_fb_create(drm, local_buf, formats);
|
||||||
|
if (!fb) {
|
||||||
|
wlr_buffer_unlock(local_buf);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drm_fb_move(fb_ptr, &fb);
|
drm_fb_move(fb_ptr, &fb);
|
||||||
|
|
|
@ -86,6 +86,7 @@ struct wlr_drm_backend {
|
||||||
struct wl_listener session_active;
|
struct wl_listener session_active;
|
||||||
struct wl_listener dev_change;
|
struct wl_listener dev_change;
|
||||||
|
|
||||||
|
struct wl_list fbs; // wlr_drm_fb.link
|
||||||
struct wl_list outputs;
|
struct wl_list outputs;
|
||||||
|
|
||||||
struct wlr_drm_renderer renderer;
|
struct wlr_drm_renderer renderer;
|
||||||
|
|
|
@ -31,8 +31,12 @@ struct wlr_drm_surface {
|
||||||
|
|
||||||
struct wlr_drm_fb {
|
struct wlr_drm_fb {
|
||||||
struct wlr_buffer *wlr_buf;
|
struct wlr_buffer *wlr_buf;
|
||||||
|
struct wl_list link; // wlr_drm_backend.fbs
|
||||||
|
|
||||||
struct gbm_bo *bo;
|
struct gbm_bo *bo;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
|
struct wl_listener wlr_buf_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool init_drm_renderer(struct wlr_drm_backend *drm,
|
bool init_drm_renderer(struct wlr_drm_backend *drm,
|
||||||
|
@ -47,6 +51,7 @@ bool drm_fb_lock_surface(struct wlr_drm_fb **fb, struct wlr_drm_backend *drm,
|
||||||
bool drm_fb_import(struct wlr_drm_fb **fb, struct wlr_drm_backend *drm,
|
bool drm_fb_import(struct wlr_drm_fb **fb, struct wlr_drm_backend *drm,
|
||||||
struct wlr_buffer *buf, struct wlr_drm_surface *mgpu,
|
struct wlr_buffer *buf, struct wlr_drm_surface *mgpu,
|
||||||
const struct wlr_drm_format_set *formats);
|
const struct wlr_drm_format_set *formats);
|
||||||
|
void drm_fb_destroy(struct wlr_drm_fb *fb);
|
||||||
|
|
||||||
void drm_fb_clear(struct wlr_drm_fb **fb);
|
void drm_fb_clear(struct wlr_drm_fb **fb);
|
||||||
void drm_fb_move(struct wlr_drm_fb **new, struct wlr_drm_fb **old);
|
void drm_fb_move(struct wlr_drm_fb **new, struct wlr_drm_fb **old);
|
||||||
|
|
Loading…
Reference in New Issue