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 <laa...@gmail.com>

> Signed-off-by: Lucas Stach <l.st...@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
> etna...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/etnaviv
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to