[PATCH v2 06/10] etnaviv: implement resource import with modifier
Christian Gmeiner
christian.gmeiner at gmail.com
Sun Jul 9 14:02:03 UTC 2017
2017-07-04 17:45 GMT+02:00 Lucas Stach <l.stach at pengutronix.de>:
> This implements resource import with modifier, deriving the correct
> internal layout from the modifier and constructing a render compatible
> base resource if needed.
>
> This removes the special cases for DDX and renderonly scanout allocated
> buffers, as the linear modifier is enough to trigger correct handling
> of those buffers.
>
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> Reviewed-by: Wladimir J. van der Laan <laanwj at gmail.com>
Reviewed-by: Christian Gmeiner <christian.gmeiner at gmail.com>
> ---
> src/gallium/drivers/etnaviv/etnaviv_resource.c | 109 +++++++++++++++++--------
> 1 file changed, 77 insertions(+), 32 deletions(-)
>
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> index 69eecf224dc5..fb68a876215f 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> @@ -36,6 +36,29 @@
> #include "util/u_inlines.h"
> #include "util/u_memory.h"
>
> +#include <drm_fourcc.h>
> +
> +#ifndef DRM_FORMAT_MOD_INVALID
> +#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
> +#endif
> +
> +static enum etna_surface_layout modifier_to_layout(uint64_t modifier)
> +{
> + switch (modifier) {
> + case DRM_FORMAT_MOD_VIVANTE_TILED:
> + return ETNA_LAYOUT_TILED;
> + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
> + return ETNA_LAYOUT_SUPER_TILED;
> + case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
> + return ETNA_LAYOUT_MULTI_TILED;
> + case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
> + return ETNA_LAYOUT_MULTI_SUPERTILED;
> + case DRM_FORMAT_MOD_LINEAR:
> + default:
> + return ETNA_LAYOUT_LINEAR;
> + }
> +}
> +
> /* A tile is 4x4 pixels, having 'screen->specs.bits_per_tile' of tile status.
> * So, in a buffer of N pixels, there are N / (4 * 4) tiles.
> * We need N * screen->specs.bits_per_tile / (4 * 4) bits of tile status, or
> @@ -141,6 +164,7 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
> const struct pipe_resource *templat)
> {
> struct etna_screen *screen = etna_screen(pscreen);
> + struct etna_resource *rsc;
> unsigned size;
>
> DBG_F(ETNA_DBG_RESOURCE_MSGS,
> @@ -183,8 +207,34 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
> if (templat->target != PIPE_BUFFER)
> etna_adjust_rs_align(screen->specs.pixel_pipes, NULL, &paddingY);
>
> - struct etna_resource *rsc = CALLOC_STRUCT(etna_resource);
> + if (templat->bind & PIPE_BIND_SCANOUT) {
> + struct pipe_resource scanout_templat = *templat;
> + struct renderonly_scanout *scanout;
> + struct winsys_handle handle;
> +
> + /* pad scanout buffer size to be compatible with the RS */
> + etna_adjust_rs_align(screen->specs.pixel_pipes,
> + &scanout_templat.width0, &scanout_templat.height0);
>
> + scanout = renderonly_scanout_for_resource(&scanout_templat,
> + screen->ro, &handle);
> + if (!scanout)
> + return NULL;
> +
> + assert(handle.type == DRM_API_HANDLE_TYPE_FD);
> + rsc = etna_resource(pscreen->resource_from_handle(pscreen, templat,
> + &handle,
> + PIPE_HANDLE_USAGE_WRITE));
> + close(handle.handle);
> + if (!rsc)
> + return NULL;
> +
> + rsc->scanout = scanout;
> +
> + return &rsc->base;
> + }
> +
> + rsc = CALLOC_STRUCT(etna_resource);
> if (!rsc)
> return NULL;
>
> @@ -211,27 +261,6 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
> rsc->bo = bo;
> rsc->ts_bo = 0; /* TS is only created when first bound to surface */
>
> - if (templat->bind & PIPE_BIND_SCANOUT) {
> - struct pipe_resource scanout_templat = *templat;
> - struct winsys_handle handle;
> -
> - /* pad scanout buffer size to be compatible with the RS */
> - etna_adjust_rs_align(screen->specs.pixel_pipes,
> - &scanout_templat.width0, &scanout_templat.height0);
> -
> - rsc->scanout = renderonly_scanout_for_resource(&scanout_templat,
> - screen->ro, &handle);
> - if (!rsc->scanout)
> - goto free_rsc;
> -
> - rsc->external = pscreen->resource_from_handle(pscreen, &rsc->base,
> - &handle,
> - PIPE_HANDLE_USAGE_WRITE);
> - close(handle.handle);
> - if (!rsc->external)
> - goto free_rsc;
> - }
> -
> if (DBG_ENABLED(ETNA_DBG_ZERO)) {
> void *map = etna_bo_map(bo);
> memset(map, 0, size);
> @@ -364,15 +393,22 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
> goto fail;
>
> rsc->seqno = 1;
> + rsc->layout = modifier_to_layout(handle->modifier);
> + rsc->halign = TEXTURE_HALIGN_FOUR;
> +
>
> level->width = tmpl->width0;
> level->height = tmpl->height0;
>
> - /* We will be using the RS to copy with this resource, so we must
> - * ensure that it is appropriately aligned for the RS requirements. */
> - level->padded_width = level->width;
> - level->padded_height = level->height;
> - etna_adjust_rs_align(&level->padded_width, &level->padded_height);
> + /* Determine padding of the imported resource. */
> + unsigned paddingX = 0, paddingY = 0;
> + etna_layout_multiple(rsc->layout, screen->specs.pixel_pipes,
> + VIV_FEATURE(screen, chipMinorFeatures1, TEXTURE_HALIGN),
> + &paddingX, &paddingY, &rsc->halign);
> +
> + etna_adjust_rs_align(screen->specs.pixel_pipes, NULL, &paddingY);
> + level->padded_width = align(level->width, paddingX);
> + level->padded_height = align(level->height, paddingY);
>
> level->layer_stride = level->stride * util_format_get_nblocksy(prsc->format,
> level->padded_height);
> @@ -389,12 +425,21 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
> goto fail;
> }
>
> - if (handle->type == DRM_API_HANDLE_TYPE_SHARED && tmpl->bind & PIPE_BIND_RENDER_TARGET) {
> - /* Render targets are linear in Xorg but must be tiled
> - * here. It would be nice if dri_drawable_get_format()
> - * set scanout for these buffers too. */
> + if (rsc->layout == ETNA_LAYOUT_LINEAR) {
> + /*
> + * Both sampler and pixel pipes can't handle linear, create a compatible
> + * base resource, where we can attach the imported buffer as an external
> + * resource.
> + */
> + struct pipe_resource tiled_templat = *tmpl;
> +
> + /*
> + * Remove BIND_SCANOUT to avoid recursion, as etna_resource_create uses
> + * this function to import the scanout buffer and get a tiled resource.
> + */
> + tiled_templat.bind &= ~PIPE_BIND_SCANOUT;
>
> - ptiled = etna_resource_create(pscreen, tmpl);
> + ptiled = etna_resource_create(pscreen, &tiled_templat);
> if (!ptiled)
> goto fail;
>
> --
> 2.11.0
>
greets
--
Christian Gmeiner, MSc
https://christian-gmeiner.info
More information about the etnaviv
mailing list