diff options
author | Boris Brezillon <boris.brezillon@collabora.com> | 2021-05-03 10:18:38 +0200 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@collabora.com> | 2021-05-17 09:48:34 +0200 |
commit | 075d43821a40eb65b20aa8ded271effe51ff4d95 (patch) | |
tree | 22f5820c75da3505ce26a863ae30e6124304ef02 | |
parent | 6b036d13502c8aff12b382af0bab5c7680ee24fd (diff) |
panfrost: Try to align scanout resource stride on 64 bytes
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Acked-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10423>
-rw-r--r-- | src/gallium/winsys/panfrost/drm/meson.build | 1 | ||||
-rw-r--r-- | src/gallium/winsys/panfrost/drm/panfrost_drm_winsys.c | 80 |
2 files changed, 81 insertions, 0 deletions
diff --git a/src/gallium/winsys/panfrost/drm/meson.build b/src/gallium/winsys/panfrost/drm/meson.build index 84aa9ba5602..71abfae1faf 100644 --- a/src/gallium/winsys/panfrost/drm/meson.build +++ b/src/gallium/winsys/panfrost/drm/meson.build @@ -26,4 +26,5 @@ libpanfrostwinsys = static_library( inc_gallium, inc_gallium_aux, inc_gallium_drivers, ], gnu_symbol_visibility : 'hidden', + dependencies: dep_libdrm, ) diff --git a/src/gallium/winsys/panfrost/drm/panfrost_drm_winsys.c b/src/gallium/winsys/panfrost/drm/panfrost_drm_winsys.c index ac47da455a0..082e816d99b 100644 --- a/src/gallium/winsys/panfrost/drm/panfrost_drm_winsys.c +++ b/src/gallium/winsys/panfrost/drm/panfrost_drm_winsys.c @@ -22,14 +22,93 @@ * IN THE SOFTWARE. */ +#include <errno.h> #include <unistd.h> #include <fcntl.h> +#include "util/format/u_format.h" #include "util/os_file.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "drm-uapi/drm.h" #include "renderonly/renderonly.h" #include "panfrost_drm_public.h" #include "panfrost/pan_public.h" +#include "xf86drm.h" + +static struct renderonly_scanout * +panfrost_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc, + struct renderonly *ro, + struct winsys_handle *out_handle) +{ + /* Find the smallest width alignment that gives us a 64byte aligned stride */ + unsigned blk_sz = util_format_get_blocksize(rsc->format); + + assert(blk_sz); + + unsigned align_w = 1; + for (unsigned i = 1; i <= blk_sz; i++) { + if (!((64 * i) % blk_sz)) { + align_w = (64 * i) / blk_sz; + break; + } + } + + struct drm_mode_create_dumb create_dumb = { + .width = ALIGN_NPOT(rsc->width0, align_w), + .height = rsc->height0, + .bpp = util_format_get_blocksizebits(rsc->format), + }; + struct drm_mode_destroy_dumb destroy_dumb = {0}; + + /* Align width to end up with a buffer that's aligned on 64 bytes. */ + + struct renderonly_scanout *scanout = CALLOC_STRUCT(renderonly_scanout); + if (!scanout) + return NULL; + + /* create dumb buffer at scanout GPU */ + int err = drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); + if (err < 0) { + fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n", + strerror(errno)); + goto free_scanout; + } + + if (create_dumb.pitch % 64) + goto free_dumb; + + scanout->handle = create_dumb.handle; + scanout->stride = create_dumb.pitch; + + if (!out_handle) + return scanout; + + /* fill in winsys handle */ + memset(out_handle, 0, sizeof(*out_handle)); + out_handle->type = WINSYS_HANDLE_TYPE_FD; + out_handle->stride = create_dumb.pitch; + + err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC, + (int *)&out_handle->handle); + if (err < 0) { + fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno)); + goto free_dumb; + } + + return scanout; + +free_dumb: + destroy_dumb.handle = scanout->handle; + drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); + +free_scanout: + FREE(scanout); + + return NULL; + +} struct pipe_screen * panfrost_drm_screen_create(int fd) @@ -40,5 +119,6 @@ panfrost_drm_screen_create(int fd) struct pipe_screen * panfrost_drm_screen_create_renderonly(struct renderonly *ro) { + ro->create_for_resource = panfrost_create_kms_dumb_buffer_for_resource; return panfrost_create_screen(os_dupfd_cloexec(ro->gpu_fd), ro); } |