[PATCH 07/11] etnaviv: implement resource import with modifier
Wladimir J. van der Laan
laanwj at gmail.com
Wed Jun 28 17:35:11 UTC 2017
On Fri, Jun 23, 2017 at 05:50:24PM +0200, Lucas Stach wrote:
> 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.
Reviewed-by: Wladimir J. van der Laan <laanwj at gmail.com>
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> ---
> src/gallium/drivers/etnaviv/etnaviv_resource.c | 112 +++++++++++++++++--------
> 1 file changed, 78 insertions(+), 34 deletions(-)
>
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> index 43f63f8908a0..f006d24a1bba 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 unsigned int 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,
> @@ -186,8 +210,36 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
> paddingY = min_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;
> + unsigned padX, padY;
>
> + /* pad scanout buffer size to be compatible with the RS */
> + padX = ETNA_RS_WIDTH_MASK + 1;
> + padY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;
> + scanout_templat.width0 = align(scanout_templat.width0, padX);
> + scanout_templat.height0 = align(scanout_templat.height0, padY);
> +
> + scanout = renderonly_scanout_for_resource(&scanout_templat,
> + screen->ro, &handle);
> + if (!scanout)
> + return NULL;
> +
> + 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;
>
> @@ -214,30 +266,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;
> - unsigned padX, padY;
> -
> - /* pad scanout buffer size to be compatible with the RS */
> - padX = ETNA_RS_WIDTH_MASK + 1;
> - padY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;
> - scanout_templat.width0 = align(scanout_templat.width0, padX);
> - scanout_templat.height0 = align(scanout_templat.height0, padY);
> -
> - 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);
> @@ -370,14 +398,21 @@ 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. */
> - unsigned paddingX = ETNA_RS_WIDTH_MASK + 1;
> - unsigned paddingY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;
> + /* 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);
> +
> + if (paddingY < 4 * screen->specs.pixel_pipes)
> + paddingY = 4 * screen->specs.pixel_pipes;
>
> level->padded_width = align(level->width, paddingX);
> level->padded_height = align(level->height, paddingY);
> @@ -396,12 +431,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
>
> _______________________________________________
> etnaviv mailing list
> etnaviv at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/etnaviv
More information about the etnaviv
mailing list