On Fri, Jun 23, 2017 at 05:50:27PM +0200, Lucas Stach wrote:
> This allows to create buffers with a specific tiling layout, which is 
> primarily
> used by GBM to allocate the EGL back buffers with the correct tiling/modifier
> for use with the scanout engines.
> 
> Signed-off-by: Lucas Stach <l.st...@pengutronix.de>
> ---
>  src/gallium/drivers/etnaviv/etnaviv_resource.c | 97 
> ++++++++++++++++++++++++--
>  src/gallium/drivers/etnaviv/etnaviv_resource.h |  2 +-
>  src/gallium/drivers/etnaviv/etnaviv_texture.c  |  2 +-
>  src/gallium/drivers/etnaviv/etnaviv_transfer.c |  2 +-
>  4 files changed, 96 insertions(+), 7 deletions(-)
> 
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c 
> b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> index df5a5700bc19..8462012b9d5f 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> @@ -161,7 +161,7 @@ setup_miptree(struct etna_resource *rsc, unsigned 
> paddingX, unsigned paddingY,
>  /* Create a new resource object, using the given template info */
>  struct pipe_resource *
>  etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
> -                    const struct pipe_resource *templat)
> +                    uint64_t modifier, const struct pipe_resource *templat)
>  {
>     struct etna_screen *screen = etna_screen(pscreen);
>     struct etna_resource *rsc;
> @@ -217,8 +217,13 @@ etna_resource_alloc(struct pipe_screen *pscreen, 
> unsigned layout,
>        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;
> +      if (modifier != DRM_FORMAT_MOD_LINEAR) {
> +         padX = paddingX;
> +         padY = paddingY;
> +      } else {
> +         padX = ETNA_RS_WIDTH_MASK + 1;
> +         padY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;

We repeat `4 * screen->specs.pixel_pipes`, or in this case
`(ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes` in many places.

Maybe this 'minimum padding for RS' computation logic could factored
out for more readable code.

> +      }
>        scanout_templat.width0 = align(scanout_templat.width0, padX);
>        scanout_templat.height0 = align(scanout_templat.height0, padY);
>  
> @@ -227,6 +232,7 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned 
> layout,
>        if (!scanout)
>           return NULL;
>  
> +      handle.modifier = modifier;
>        rsc = etna_resource(pscreen->resource_from_handle(pscreen, templat,
>                                                          &handle,
>                                                          
> PIPE_HANDLE_USAGE_WRITE));
> @@ -331,7 +337,89 @@ etna_resource_create(struct pipe_screen *pscreen,
>     if (templat->target == PIPE_TEXTURE_3D)
>        layout = ETNA_LAYOUT_LINEAR;
>  
> -   return etna_resource_alloc(pscreen, layout, templat);
> +   /* modifier is only used for scanout surfaces, so safe to use LINEAR here 
> */
> +   return etna_resource_alloc(pscreen, layout, DRM_FORMAT_MOD_LINEAR, 
> templat);
> +}
> +
> +enum modifier_priority {
> +   MODIFIER_PRIORITY_INVALID = 0,
> +   MODIFIER_PRIORITY_LINEAR,
> +   MODIFIER_PRIORITY_SPLIT_TILED,
> +   MODIFIER_PRIORITY_SPLIT_SUPER_TILED,
> +   MODIFIER_PRIORITY_TILED,
> +   MODIFIER_PRIORITY_SUPER_TILED,
> +};
> +
> +const uint64_t priority_to_modifier[] = {
> +   [MODIFIER_PRIORITY_INVALID] = DRM_FORMAT_MOD_INVALID,
> +   [MODIFIER_PRIORITY_LINEAR] = DRM_FORMAT_MOD_LINEAR,
> +   [MODIFIER_PRIORITY_SPLIT_TILED] = DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED,
> +   [MODIFIER_PRIORITY_SPLIT_SUPER_TILED] = 
> DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED,
> +   [MODIFIER_PRIORITY_TILED] = DRM_FORMAT_MOD_VIVANTE_TILED,
> +   [MODIFIER_PRIORITY_SUPER_TILED] = DRM_FORMAT_MOD_VIVANTE_SUPER_TILED,
> +};
> +
> +static uint64_t
> +select_best_modifier(const struct etna_screen * screen,
> +                     const uint64_t *modifiers, const unsigned count)
> +{
> +   enum modifier_priority prio = MODIFIER_PRIORITY_INVALID;
> +
> +   for (int i = 0; i < count; i++) {
> +      switch (modifiers[i]) {
> +      case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
> +         if ((screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer) 
> ||
> +             !screen->specs.can_supertile)
> +            break;
> +         prio = MAX2(prio, MODIFIER_PRIORITY_SUPER_TILED);
> +         break;
> +      case DRM_FORMAT_MOD_VIVANTE_TILED:
> +         if (screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer)
> +            break;
> +         prio = MAX2(prio, MODIFIER_PRIORITY_TILED);
> +         break;
> +      case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
> +         if ((screen->specs.pixel_pipes < 2) || !screen->specs.can_supertile)
> +            break;
> +         prio = MAX2(prio, MODIFIER_PRIORITY_SPLIT_SUPER_TILED);
> +         break;
> +      case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
> +         if (screen->specs.pixel_pipes < 2)
> +            break;
> +         prio = MAX2(prio, MODIFIER_PRIORITY_SPLIT_TILED);
> +         break;
> +      case DRM_FORMAT_MOD_LINEAR:
> +         prio = MAX2(prio, MODIFIER_PRIORITY_LINEAR);
> +         break;
> +      case DRM_FORMAT_MOD_INVALID:
> +      default:
> +         break;
> +      }
> +   }
> +
> +   return priority_to_modifier[prio];
> +}
> +
> +static struct pipe_resource *
> +etna_resource_create_modifiers(struct pipe_screen *pscreen,
> +                               const struct pipe_resource *templat,
> +                               const uint64_t *modifiers, int count)
> +{
> +   struct etna_screen *screen = etna_screen(pscreen);
> +   struct pipe_resource tmpl = *templat;
> +   uint64_t modifier = select_best_modifier(screen, modifiers, count);
> +
> +   if (modifier == DRM_FORMAT_MOD_INVALID)
> +      return NULL;
> +
> +   /*
> +    * We currently assume that all buffers allocated through this interface
> +    * should be scanout enabled.
> +    */
> +   tmpl.bind |= PIPE_BIND_SCANOUT;
> +
> +   return etna_resource_alloc(pscreen, modifier_to_layout(modifier),
> +                              modifier, &tmpl);
>  }
>  
>  static void
> @@ -543,6 +631,7 @@ etna_resource_screen_init(struct pipe_screen *pscreen)
>  {
>     pscreen->can_create_resource = etna_screen_can_create_resource;
>     pscreen->resource_create = etna_resource_create;
> +   pscreen->resource_create_with_modifiers = etna_resource_create_modifiers;
>     pscreen->resource_from_handle = etna_resource_from_handle;
>     pscreen->resource_get_handle = etna_resource_get_handle;
>     pscreen->resource_changed = etna_resource_changed;
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h 
> b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> index 5f563c06adcf..0b135e2373b6 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> @@ -151,7 +151,7 @@ etna_screen_resource_alloc_ts(struct pipe_screen *pscreen,
>  
>  struct pipe_resource *
>  etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
> -                    const struct pipe_resource *templat);
> +                    uint64_t modifier, const struct pipe_resource *templat);
>  
>  void
>  etna_resource_screen_init(struct pipe_screen *pscreen);
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c 
> b/src/gallium/drivers/etnaviv/etnaviv_texture.c
> index b7e424f89bba..204c31d33b1e 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_texture.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c
> @@ -181,7 +181,7 @@ etna_create_sampler_view(struct pipe_context *pctx, 
> struct pipe_resource *prsc,
>           templat.bind &= ~(PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET 
> |
>                             PIPE_BIND_BLENDABLE);
>           res->texture =
> -            etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED, &templat);
> +            etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED, 0, 
> &templat);
>        }
>  
>        if (!res->texture) {
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c 
> b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> index 27e1be19579a..3795c7839081 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
> @@ -203,7 +203,7 @@ etna_transfer_map(struct pipe_context *pctx, struct 
> pipe_resource *prsc,
>        templ.nr_samples = 0;
>        templ.bind = PIPE_BIND_RENDER_TARGET;
>  
> -      trans->rsc = etna_resource_alloc(pctx->screen, ETNA_LAYOUT_LINEAR, 
> &templ);
> +      trans->rsc = etna_resource_alloc(pctx->screen, ETNA_LAYOUT_LINEAR, 0, 
> &templ);
>        if (!trans->rsc) {
>           slab_free(&ctx->transfer_pool, trans);
>           return NULL;
> -- 
> 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