From 1ce5d757d04ab91423d757811c712ab098a35ccc Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 21 Jan 2019 10:50:13 -0500 Subject: [PATCH] freedreno: core buffer modifier support Split out of a patch from Fritz Koenig to decouple from a6xx UBWC enablement, and added fd_resource_create_with_modifiers(). --- .../drivers/freedreno/freedreno_resource.c | 87 ++++++++++++++++++- .../drivers/freedreno/freedreno_screen.h | 1 + 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 14751074ace..ccd4f7f118d 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -43,6 +43,7 @@ #include "freedreno_query_hw.h" #include "freedreno_util.h" +#include #include /* XXX this should go away, needed for 'struct winsys_handle' */ @@ -810,12 +811,26 @@ has_depth(enum pipe_format format) } } +static bool +find_modifier(uint64_t needle, const uint64_t *haystack, int count) +{ + int i; + + for (i = 0; i < count; i++) { + if (haystack[i] == needle) + return true; + } + + return false; +} + /** * Create a new texture object, using the given template info. */ static struct pipe_resource * -fd_resource_create(struct pipe_screen *pscreen, - const struct pipe_resource *tmpl) +fd_resource_create_with_modifiers(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl, + const uint64_t *modifiers, int count) { struct fd_screen *screen = fd_screen(pscreen); struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); @@ -840,10 +855,25 @@ fd_resource_create(struct pipe_screen *pscreen, PIPE_BIND_LINEAR | \ PIPE_BIND_DISPLAY_TARGET) + bool linear = find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count); + if (tmpl->bind & LINEAR) + linear = true; + + /* Normally, for non-shared buffers, allow buffer compression if + * not shared, otherwise only allow if QCOM_COMPRESSED modifier + * is requested: + * + * TODO we should probably also limit tiled in a similar way, + * except we don't have a format modifier for tiled. (We probably + * should.) + */ + bool allow_ubwc = find_modifier(DRM_FORMAT_MOD_INVALID, modifiers, count); + if (tmpl->bind & PIPE_BIND_SHARED) + allow_ubwc = find_modifier(DRM_FORMAT_MOD_QCOM_COMPRESSED, modifiers, count); + if (screen->tile_mode && (tmpl->target != PIPE_BUFFER) && - (tmpl->bind & PIPE_BIND_SAMPLER_VIEW) && - !(tmpl->bind & LINEAR)) { + !linear) { rsc->tile_mode = screen->tile_mode(tmpl); } @@ -888,6 +918,9 @@ fd_resource_create(struct pipe_screen *pscreen, size = screen->setup_slices(rsc); + if (allow_ubwc && screen->fill_ubwc_buffer_sizes && rsc->tile_mode) + size += screen->fill_ubwc_buffer_sizes(rsc); + /* special case for hw-query buffer, which we need to allocate before we * know the size: */ @@ -912,6 +945,34 @@ fail: return NULL; } +static struct pipe_resource * +fd_resource_create(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl) +{ + const uint64_t mod = DRM_FORMAT_MOD_INVALID; + return fd_resource_create_with_modifiers(pscreen, tmpl, &mod, 1); +} + +static bool +is_supported_modifier(struct pipe_screen *pscreen, enum pipe_format pfmt, + uint64_t mod) +{ + int count; + + /* Get the count of supported modifiers: */ + pscreen->query_dmabuf_modifiers(pscreen, pfmt, 0, NULL, NULL, &count); + + /* Get the supported modifiers: */ + uint64_t modifiers[count]; + pscreen->query_dmabuf_modifiers(pscreen, pfmt, 0, modifiers, NULL, &count); + + for (int i = 0; i < count; i++) + if (modifiers[i] == mod) + return true; + + return false; +} + /** * Create a texture from a winsys_handle. The handle is often created in * another process by first creating a pipe texture and then calling @@ -922,6 +983,7 @@ fd_resource_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *tmpl, struct winsys_handle *handle, unsigned usage) { + struct fd_screen *screen = fd_screen(pscreen); struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); struct fd_resource_slice *slice = &rsc->slices[0]; struct pipe_resource *prsc = &rsc->base; @@ -960,6 +1022,19 @@ fd_resource_from_handle(struct pipe_screen *pscreen, (slice->pitch & (pitchalign - 1))) goto fail; + if (handle->modifier == DRM_FORMAT_MOD_QCOM_COMPRESSED) { + if (!is_supported_modifier(pscreen, tmpl->format, + DRM_FORMAT_MOD_QCOM_COMPRESSED)) { + DBG("bad modifier: %lx", handle->modifier); + goto fail; + } + debug_assert(screen->fill_ubwc_buffer_sizes); + screen->fill_ubwc_buffer_sizes(rsc); + } else if (handle->modifier && + (handle->modifier != DRM_FORMAT_MOD_INVALID)) { + goto fail; + } + assert(rsc->cpp); return prsc; @@ -1131,6 +1206,10 @@ fd_resource_screen_init(struct pipe_screen *pscreen) bool fake_rgtc = screen->gpu_id < 400; pscreen->resource_create = u_transfer_helper_resource_create; + /* NOTE: u_transfer_helper does not yet support the _with_modifiers() + * variant: + */ + pscreen->resource_create_with_modifiers = fd_resource_create_with_modifiers; pscreen->resource_from_handle = fd_resource_from_handle; pscreen->resource_get_handle = fd_resource_get_handle; pscreen->resource_destroy = u_transfer_helper_resource_destroy; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h index 243770ffd90..1060f4609f6 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.h +++ b/src/gallium/drivers/freedreno/freedreno_screen.h @@ -87,6 +87,7 @@ struct fd_screen { */ struct fd_pipe *pipe; + uint32_t (*fill_ubwc_buffer_sizes)(struct fd_resource *rsc); uint32_t (*setup_slices)(struct fd_resource *rsc); unsigned (*tile_mode)(const struct pipe_resource *prsc); -- 2.30.2