diff options
Diffstat (limited to 'backend/drm')
-rw-r--r-- | backend/drm/backend.c | 2 | ||||
-rw-r--r-- | backend/drm/bo_handle_table.c | 43 | ||||
-rw-r--r-- | backend/drm/legacy.c | 20 | ||||
-rw-r--r-- | backend/drm/meson.build | 1 | ||||
-rw-r--r-- | backend/drm/renderer.c | 77 | ||||
-rw-r--r-- | backend/drm/util.c | 11 |
6 files changed, 57 insertions, 97 deletions
diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 9ae4dbf0..5e01eddf 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -52,8 +52,6 @@ static void backend_destroy(struct wlr_backend *backend) { wl_list_remove(&drm->dev_change.link); wl_list_remove(&drm->dev_remove.link); - drm_bo_handle_table_finish(&drm->bo_handles); - if (drm->parent) { finish_drm_renderer(&drm->mgpu_renderer); } diff --git a/backend/drm/bo_handle_table.c b/backend/drm/bo_handle_table.c deleted file mode 100644 index 479168b4..00000000 --- a/backend/drm/bo_handle_table.c +++ /dev/null @@ -1,43 +0,0 @@ -#include <assert.h> -#include <stdint.h> -#include <stdlib.h> -#include <wlr/util/log.h> -#include "backend/drm/bo_handle_table.h" - -static size_t align(size_t val, size_t align) { - size_t mask = align - 1; - return (val + mask) & ~mask; -} - -void drm_bo_handle_table_finish(struct wlr_drm_bo_handle_table *table) { - free(table->nrefs); -} - -bool drm_bo_handle_table_ref(struct wlr_drm_bo_handle_table *table, - uint32_t handle) { - assert(handle != 0); - - if (handle > table->len) { - // Grow linearly, because we don't expect the number of BOs to explode - size_t len = align(handle + 1, 512); - size_t *nrefs = realloc(table->nrefs, len * sizeof(size_t)); - if (nrefs == NULL) { - wlr_log_errno(WLR_ERROR, "realloc failed"); - return false; - } - memset(&nrefs[table->len], 0, (len - table->len) * sizeof(size_t)); - table->len = len; - table->nrefs = nrefs; - } - - table->nrefs[handle]++; - return true; -} - -size_t drm_bo_handle_table_unref(struct wlr_drm_bo_handle_table *table, - uint32_t handle) { - assert(handle < table->len); - assert(table->nrefs[handle] > 0); - table->nrefs[handle]--; - return table->nrefs[handle]; -} diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index 7a711590..cb672023 100644 --- a/backend/drm/legacy.c +++ b/backend/drm/legacy.c @@ -138,11 +138,21 @@ static bool legacy_crtc_commit(struct wlr_drm_connector *conn, return false; } - uint32_t cursor_handle = cursor_fb->handles[0]; - uint32_t cursor_width = cursor_fb->wlr_buf->width; - uint32_t cursor_height = cursor_fb->wlr_buf->height; - if (drmModeSetCursor(drm->fd, crtc->id, cursor_handle, - cursor_width, cursor_height)) { + drmModeFB *drm_fb = drmModeGetFB(drm->fd, cursor_fb->id); + if (drm_fb == NULL) { + wlr_drm_conn_log_errno(conn, WLR_DEBUG, "Failed to get cursor " + "BO handle: drmModeGetFB failed"); + return false; + } + uint32_t cursor_handle = drm_fb->handle; + uint32_t cursor_width = drm_fb->width; + uint32_t cursor_height = drm_fb->height; + drmModeFreeFB(drm_fb); + + int ret = drmModeSetCursor(drm->fd, crtc->id, cursor_handle, + cursor_width, cursor_height); + close_bo_handle(drm->fd, cursor_handle); + if (ret != 0) { wlr_drm_conn_log_errno(conn, WLR_DEBUG, "drmModeSetCursor failed"); return false; } diff --git a/backend/drm/meson.build b/backend/drm/meson.build index 8f78b74e..b076b472 100644 --- a/backend/drm/meson.build +++ b/backend/drm/meson.build @@ -1,7 +1,6 @@ wlr_files += files( 'atomic.c', 'backend.c', - 'bo_handle_table.c', 'cvt.c', 'drm.c', 'legacy.c', diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 2d81ccd5..40e068cd 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -204,42 +204,6 @@ static const struct wlr_addon_interface fb_addon_impl = { .destroy = drm_fb_handle_destroy, }; -static uint32_t get_bo_handle_for_fd(struct wlr_drm_backend *drm, - int dmabuf_fd) { - uint32_t handle = 0; - int ret = drmPrimeFDToHandle(drm->fd, dmabuf_fd, &handle); - if (ret != 0) { - wlr_log_errno(WLR_DEBUG, "drmPrimeFDToHandle failed"); - return 0; - } - - if (!drm_bo_handle_table_ref(&drm->bo_handles, handle)) { - // If that failed, the handle wasn't ref'ed in the table previously, - // so safe to delete - struct drm_gem_close args = { .handle = handle }; - drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args); - return 0; - } - - return handle; -} - -static void close_bo_handle(struct wlr_drm_backend *drm, uint32_t handle) { - if (handle == 0) { - return; - } - - size_t nrefs = drm_bo_handle_table_unref(&drm->bo_handles, handle); - if (nrefs > 0) { - return; - } - - struct drm_gem_close args = { .handle = handle }; - if (drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args) != 0) { - wlr_log_errno(WLR_ERROR, "drmIoctl(GEM_CLOSE) failed"); - } -} - static uint32_t get_fb_for_bo(struct wlr_drm_backend *drm, struct wlr_dmabuf_attributes *dmabuf, uint32_t handles[static 4]) { uint64_t modifiers[4] = {0}; @@ -281,6 +245,29 @@ static uint32_t get_fb_for_bo(struct wlr_drm_backend *drm, return id; } +static void close_all_bo_handles(struct wlr_drm_backend *drm, + uint32_t handles[static 4]) { + for (int i = 0; i < 4; ++i) { + if (handles[i] == 0) { + continue; + } + + // If multiple planes share the same BO handle, avoid double-closing it + bool already_closed = false; + for (int j = 0; j < i; ++j) { + if (handles[i] == handles[j]) { + already_closed = true; + break; + } + } + if (already_closed) { + continue; + } + + close_bo_handle(drm->fd, handles[i]); + } +} + 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_drm_fb *fb = calloc(1, sizeof(*fb)); @@ -318,19 +305,23 @@ static struct wlr_drm_fb *drm_fb_create(struct wlr_drm_backend *drm, } } + uint32_t handles[4] = {0}; for (int i = 0; i < attribs.n_planes; ++i) { - fb->handles[i] = get_bo_handle_for_fd(drm, attribs.fd[i]); - if (fb->handles[i] == 0) { + int ret = drmPrimeFDToHandle(drm->fd, attribs.fd[i], &handles[i]); + if (ret != 0) { + wlr_log_errno(WLR_DEBUG, "drmPrimeFDToHandle failed"); goto error_bo_handle; } } - fb->id = get_fb_for_bo(drm, &attribs, fb->handles); + fb->id = get_fb_for_bo(drm, &attribs, handles); if (!fb->id) { wlr_log(WLR_DEBUG, "Failed to import BO in KMS"); goto error_bo_handle; } + close_all_bo_handles(drm, handles); + fb->backend = drm; fb->wlr_buf = buf; @@ -340,9 +331,7 @@ static struct wlr_drm_fb *drm_fb_create(struct wlr_drm_backend *drm, return fb; error_bo_handle: - for (int i = 0; i < attribs.n_planes; ++i) { - close_bo_handle(drm, fb->handles[i]); - } + close_all_bo_handles(drm, handles); error_get_dmabuf: free(fb); return NULL; @@ -358,10 +347,6 @@ void drm_fb_destroy(struct wlr_drm_fb *fb) { wlr_log(WLR_ERROR, "drmModeRmFB failed"); } - for (size_t i = 0; i < sizeof(fb->handles) / sizeof(fb->handles[0]); ++i) { - close_bo_handle(drm, fb->handles[i]); - } - free(fb); } diff --git a/backend/drm/util.c b/backend/drm/util.c index 3cf656fb..407c19a5 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -320,3 +320,14 @@ size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num_objs], match_obj_(&st, 0, 0, 0, 0); return st.score; } + +void close_bo_handle(int drm_fd, uint32_t handle) { + if (handle == 0) { + return; + } + + struct drm_gem_close args = { .handle = handle }; + if (drmIoctl(drm_fd, DRM_IOCTL_GEM_CLOSE, &args) != 0) { + wlr_log_errno(WLR_ERROR, "drmIoctl(GEM_CLOSE) failed"); + } +} |