Implement query_dmabuf_modifiers and resource_create_with_modifiers so Wayland clients can share AFBC buffers with the compositor.
For now this is guarded behind the PAN_MESA_DEBUG=modifiers env var because implementing those callbacks causes Weston to try to pass modifiers to the Rockchip KMS driver, which currently doesn't support modifiers, thus failing the modeset. This has been fixed in Weston 6.0, so we can enable unconditionally once we are confident that most people testing panfrost have upgraded. This lays the ground for scanning out AFBC buffers, if the KMS driver supports it. Signed-off-by: Tomeu Vizoso <tomeu.viz...@collabora.com> --- src/gallium/drivers/panfrost/pan_drm.c | 1 + src/gallium/drivers/panfrost/pan_resource.c | 74 ++++++++++++++++++--- src/gallium/drivers/panfrost/pan_screen.c | 37 +++++++++++ src/gallium/drivers/panfrost/pan_util.h | 7 ++ 4 files changed, 108 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_drm.c b/src/gallium/drivers/panfrost/pan_drm.c index 9648ac1d452d..623793a84411 100644 --- a/src/gallium/drivers/panfrost/pan_drm.c +++ b/src/gallium/drivers/panfrost/pan_drm.c @@ -26,6 +26,7 @@ #include <fcntl.h> #include <xf86drm.h> +#include "drm-uapi/drm_fourcc.h" #include "drm-uapi/panfrost_drm.h" #include "util/u_memory.h" diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 54497d3de2bb..d901d43168fb 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -34,6 +34,7 @@ #include "drm-uapi/drm_fourcc.h" #include "state_tracker/winsys_handle.h" +#include "util/u_drm.h" #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_surface.h" @@ -91,6 +92,18 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, rsc->bo = panfrost_drm_import_bo(screen, whandle->handle); + switch(whandle->modifier) { + case DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP): + rsc->layout = PAN_AFBC; + break; + case DRM_FORMAT_MOD_LINEAR: + rsc->layout = PAN_LINEAR; + break; + default: + fprintf(stderr, "unknown modifier: 0x%"PRIx64"\n", whandle->modifier); + assert(0); + } + size_t bo_size; panfrost_setup_slices(rsc, &bo_size); assert(bo_size == rsc->bo->size); @@ -106,6 +119,21 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, return prsc; } +static uint64_t +panfrost_resource_modifier(struct panfrost_resource *rsrc) +{ + switch (rsrc->layout) { + case PAN_AFBC: + return DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP); + case PAN_TILED: + return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; + case PAN_LINEAR: + return DRM_FORMAT_MOD_LINEAR; + default: + return DRM_FORMAT_MOD_INVALID; + } +} + static boolean panfrost_resource_get_handle(struct pipe_screen *pscreen, struct pipe_context *ctx, @@ -117,7 +145,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen, struct panfrost_resource *rsrc = (struct panfrost_resource *) pt; struct renderonly_scanout *scanout = rsrc->scanout; - handle->modifier = DRM_FORMAT_MOD_INVALID; + handle->modifier = panfrost_resource_modifier(rsrc); if (handle->type == WINSYS_HANDLE_TYPE_SHARED) { return FALSE; @@ -341,7 +369,9 @@ panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size) } static void -panfrost_resource_create_bo(struct panfrost_screen *screen, struct panfrost_resource *pres) +panfrost_resource_create_bo(struct panfrost_screen *screen, + struct panfrost_resource *pres, + const uint64_t *modifiers, int count) { struct pipe_resource *res = &pres->base; @@ -362,14 +392,19 @@ panfrost_resource_create_bo(struct panfrost_screen *screen, struct panfrost_reso /* Tiling textures is almost always faster, unless we only use it once */ + bool can_afbc = panfrost_format_supports_afbc(res->format); + bool want_afbc = drm_find_modifier(DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP), modifiers, count); + bool want_linear = drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count); + #define SCANOUT (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET) bool is_scanout = (res->bind & SCANOUT); bool is_texture = (res->bind & PIPE_BIND_SAMPLER_VIEW); + bool is_renderable = (res->bind & PIPE_BIND_RENDER_TARGET); bool is_2d = res->depth0 == 1 && res->array_size == 1; bool is_streaming = (res->usage == PIPE_USAGE_STREAM); - bool should_tile = !is_streaming && is_texture && is_2d && !is_scanout; + bool should_tile = !is_streaming && is_texture && is_2d && !want_linear && !is_scanout; /* Depth/stencil can't be tiled, only linear or AFBC */ should_tile &= !(res->bind & PIPE_BIND_DEPTH_STENCIL); @@ -381,17 +416,20 @@ panfrost_resource_create_bo(struct panfrost_screen *screen, struct panfrost_reso pres->checksummed = can_checksum && should_checksum; /* Set the layout appropriately */ - pres->layout = should_tile ? PAN_TILED : PAN_LINEAR; + if (want_afbc || (is_renderable && can_afbc && !is_texture)) + pres->layout = PAN_AFBC; + else + pres->layout = should_tile ? PAN_TILED : PAN_LINEAR; size_t bo_size; - panfrost_setup_slices(pres, &bo_size); pres->bo = panfrost_drm_create_bo(screen, bo_size, 0); } static struct pipe_resource * -panfrost_resource_create(struct pipe_screen *screen, - const struct pipe_resource *template) +panfrost_resource_create_with_modifiers(struct pipe_screen *screen, + const struct pipe_resource *template, + const uint64_t *modifiers, int count) { /* Make sure we're familiar */ switch (template->target) { @@ -418,13 +456,16 @@ panfrost_resource_create(struct pipe_screen *screen, util_range_init(&so->valid_buffer_range); - panfrost_resource_create_bo(pscreen, so); + panfrost_resource_create_bo(pscreen, so, modifiers, count); /* Set up the "scanout resource" (the dmabuf export of our buffer to * the KMS handle) if the buffer might ever have * resource_get_handle(WINSYS_HANDLE_TYPE_KMS) called on it. + * create_with_modifiers() doesn't give us usage flags, so we have to + * assume that all calls with modifiers are scanout-possible. */ - if (template->bind & PIPE_BIND_SCANOUT) { + if (((template->bind & PIPE_BIND_SCANOUT) || + !(count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID))) { so->scanout = renderonly_scanout_for_resource(&so->base, pscreen->ro, NULL); if (!so->scanout) { @@ -436,6 +477,14 @@ panfrost_resource_create(struct pipe_screen *screen, return (struct pipe_resource *)so; } +static struct pipe_resource * +panfrost_resource_create(struct pipe_screen *screen, + const struct pipe_resource *template) +{ + const uint64_t mod = DRM_FORMAT_MOD_INVALID; + return panfrost_resource_create_with_modifiers(screen, template, &mod, 1); +} + void panfrost_bo_reference(struct panfrost_bo *bo) { @@ -779,8 +828,11 @@ static const struct u_transfer_vtbl transfer_vtbl = { void panfrost_resource_screen_init(struct panfrost_screen *pscreen) { - //pscreen->base.resource_create_with_modifiers = - // panfrost_resource_create_with_modifiers; + if (pan_debug & PAN_DBG_MODIFIERS) { + pscreen->base.resource_create_with_modifiers = + panfrost_resource_create_with_modifiers; + } + pscreen->base.resource_create = u_transfer_helper_resource_create; pscreen->base.resource_destroy = u_transfer_helper_resource_destroy; pscreen->base.resource_from_handle = panfrost_resource_from_handle; diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index d53a906838eb..02b65e068c30 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -57,6 +57,7 @@ static const struct debug_named_value debug_options[] = { {"msgs", PAN_DBG_MSGS, "Print debug messages"}, {"trace", PAN_DBG_TRACE, "Trace the command stream"}, + {"modifiers", PAN_DBG_MODIFIERS,"Enable modifiers support"}, DEBUG_NAMED_VALUE_END }; @@ -559,6 +560,38 @@ panfrost_screen_get_compiler_options(struct pipe_screen *pscreen, return &midgard_nir_options; } +const uint64_t supported_modifiers[] = { + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP), + DRM_FORMAT_MOD_LINEAR, +}; + +static void +panfrost_query_dmabuf_modifiers(struct pipe_screen *pscreen, + enum pipe_format format, int max, + uint64_t *modifiers, + unsigned int *external_only, int *count) +{ + int i, num_modifiers = 0; + + if (max > ARRAY_SIZE(supported_modifiers)) + max = ARRAY_SIZE(supported_modifiers); + + if (!max) { + modifiers = NULL; + max = ARRAY_SIZE(supported_modifiers); + } + + for (i = 0; num_modifiers < max; i++) { + if (modifiers) + modifiers[num_modifiers] = supported_modifiers[i]; + if (external_only) + external_only[num_modifiers] = util_format_is_yuv(format) ? 1 : 0; + num_modifiers++; + } + + *count = num_modifiers; +} + struct pipe_screen * panfrost_create_screen(int fd, struct renderonly *ro) { @@ -599,6 +632,10 @@ panfrost_create_screen(int fd, struct renderonly *ro) screen->base.fence_reference = panfrost_fence_reference; screen->base.fence_finish = panfrost_fence_finish; + if (pan_debug & PAN_DBG_MODIFIERS) { + screen->base.query_dmabuf_modifiers = panfrost_query_dmabuf_modifiers; + } + screen->last_fragment_flushed = true; screen->last_job = NULL; diff --git a/src/gallium/drivers/panfrost/pan_util.h b/src/gallium/drivers/panfrost/pan_util.h index 8fd41420a486..a3a7ec3067e6 100644 --- a/src/gallium/drivers/panfrost/pan_util.h +++ b/src/gallium/drivers/panfrost/pan_util.h @@ -30,6 +30,7 @@ #define PAN_DBG_MSGS 0x0001 #define PAN_DBG_TRACE 0x0002 +#define PAN_DBG_MODIFIERS 0x0004 extern int pan_debug; @@ -38,4 +39,10 @@ extern int pan_debug; fprintf(stderr, "%s:%d: "fmt, \ __FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0) +/* TODO: Pick these two up from kernel header */ +#define AFBC_FORMAT_MOD_ROCKCHIP (1ULL << 20) + +#define DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED \ + fourcc_mod_code(ARM, ((1ULL << 55) | 1)) + #endif /* PAN_UTIL_H */ -- 2.20.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev