[Mesa-dev] [PATCH 1/8] etnaviv: create optional 2d pipe in screen

Philipp Zabel p.zabel at pengutronix.de
Mon Apr 15 10:17:14 UTC 2019


On Fri, 2019-04-12 at 19:38 +0200, Lucas Stach wrote:
> The 2D pipe is useful to implement fast planar and interleaved YUV buffer
> imports. Not all systems have a 2D capable core, so this is strictly
> optional.
> 
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
> ---
>  src/gallium/drivers/etnaviv/etnaviv_context.c |  6 ++
>  src/gallium/drivers/etnaviv/etnaviv_context.h |  1 +
>  src/gallium/drivers/etnaviv/etnaviv_screen.c  | 68 +++++++++++++++++++
>  src/gallium/drivers/etnaviv/etnaviv_screen.h  |  6 ++
>  4 files changed, 81 insertions(+)
> 
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
> index a59338490b62..631f551d0ad4 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_context.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
> @@ -78,6 +78,9 @@ etna_context_destroy(struct pipe_context *pctx)
>     if (ctx->stream)
>        etna_cmd_stream_del(ctx->stream);
>  
> +   if (ctx->stream2d)
> +      etna_cmd_stream_del(ctx->stream2d);
> +
>     slab_destroy_child(&ctx->transfer_pool);
>  
>     if (ctx->in_fence_fd != -1)
> @@ -434,6 +437,9 @@ etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
>     if (ctx->stream == NULL)
>        goto fail;
>  
> +   if (screen->pipe2d)
> +      ctx->stream2d = etna_cmd_stream_new(screen->pipe2d, 0x1000, NULL, NULL);
> +
>     /* context ctxate setup */
>     ctx->specs = screen->specs;
>     ctx->screen = screen;
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h
> index a79d739100d9..2c6e5d6c3db1 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_context.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_context.h
> @@ -110,6 +110,7 @@ struct etna_context {
>     struct etna_specs specs;
>     struct etna_screen *screen;
>     struct etna_cmd_stream *stream;
> +   struct etna_cmd_stream *stream2d;
>  
>     /* which state objects need to be re-emit'd: */
>     enum {
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c
> index 62b6f1c80fae..0dea6056c75a 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c
> @@ -95,6 +95,12 @@ etna_screen_destroy(struct pipe_screen *pscreen)
>     if (screen->gpu)
>        etna_gpu_del(screen->gpu);
>  
> +   if (screen->pipe2d)
> +      etna_pipe_del(screen->pipe2d);
> +
> +   if (screen->gpu2d)
> +      etna_gpu_del(screen->gpu2d);
> +
>     if (screen->ro)
>        FREE(screen->ro);
>  
> @@ -891,6 +897,66 @@ etna_screen_bo_from_handle(struct pipe_screen *pscreen,
>     return bo;
>  }
>  
> +static void etna_screen_init_2d(struct etna_screen *screen)
> +{
> +   struct etna_gpu *gpu2d = NULL;
> +   uint64_t val;
> +   int ret, i;
> +
> +   /* If the current GPU is a combined 2d/3D core, use it as 2D engine */
                                           ^ 2D

> +   if (screen->features[0] & chipFeatures_PIPE_2D)
> +      gpu2d = screen->gpu;

If the GPU is a combined 2D/3D core, is screen->gpu2d set anywhere?
I assume it isn't on purpose, so it can be used to check whether
etna_gpu_del(screen->gpu2d) must be called in etna_screen_destroy().

> +
> +   /* otherwise search for a 2D capable core */
> +   if (!gpu2d) {

This could just be

   else {
      /* otherwise search for a 2D capable core */

> +      for (i = 0;; i++) {
> +         gpu2d = etna_gpu_new(screen->dev, i);
> +         if (!gpu2d)
> +            return;
> +
> +         ret = etna_gpu_get_param(gpu2d, ETNA_GPU_FEATURES_0, &val);
> +         if (!ret && (val & chipFeatures_PIPE_2D)) {
> +            screen->gpu2d = gpu2d;
> +            break;
> +         }
> +
> +         etna_gpu_del(gpu2d);
> +      }
> +   }
> +
> +   if (etna_gpu_get_param(screen->gpu2d, ETNA_GPU_FEATURES_0, &val))

If the GPU is a combined 2D/3D core, and screen->gpu2d == NULL at this
point, won't this fail trying to dereference the gpu NULL pointer in
etna_gpu_get_param()? I suppose these should be using the local gpu2d
variable instead of screen->gpu2d.

Further, if the GPU is a combined 2D/3D core, we have already queried
GPU features just before etna_screen_init_2d() was called,
in etna_screen_create(). We could just copy features to features2d.

Nitpick: if the gpu2d is 2D-only, the only way we can arrive here is
from the break in the loop above, just after val was already set to the
ETNA_GPU_FEATURES_0 value. In that case the first call to
etna_gpu_get_parm() is superfluous.

> +      return;
> +   screen->features2d[0] = val;
> +
> +   if (etna_gpu_get_param(screen->gpu2d, ETNA_GPU_FEATURES_1, &val))
> +      return;
> +   screen->features2d[1] = val;
> +
> +   if (etna_gpu_get_param(screen->gpu2d, ETNA_GPU_FEATURES_2, &val))
> +      return;
> +   screen->features2d[2] = val;
> +
> +   if (etna_gpu_get_param(screen->gpu2d, ETNA_GPU_FEATURES_3, &val))
> +      return;
> +   screen->features2d[3] = val;
> +
> +   if (etna_gpu_get_param(screen->gpu2d, ETNA_GPU_FEATURES_4, &val))
> +      return;
> +   screen->features2d[4] = val;
> +
> +   if (etna_gpu_get_param(screen->gpu2d, ETNA_GPU_FEATURES_5, &val))
> +      return;
> +   screen->features2d[5] = val;
> +
> +   if (etna_gpu_get_param(screen->gpu2d, ETNA_GPU_FEATURES_6, &val))
> +      return;
> +   screen->features2d[6] = val;
> +
> +   screen->pipe2d = etna_pipe_new(gpu2d, ETNA_PIPE_2D);
> +   if (!screen->pipe2d)
> +      DBG("could not create 2d pipe");
> +}
> +
>  struct pipe_screen *
>  etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu,
>                     struct renderonly *ro)
> @@ -984,6 +1050,8 @@ etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu,
>     }
>     screen->features[6] = val;
>  
> +   etna_screen_init_2d(screen);
> +
>     if (!etna_get_specs(screen))
>        goto fail;
>  
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.h b/src/gallium/drivers/etnaviv/etnaviv_screen.h
> index 9757985526ec..82733a379430 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_screen.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.h
> @@ -60,6 +60,9 @@ enum viv_features_word {
>  #define VIV_FEATURE(screen, word, feature) \
>     ((screen->features[viv_ ## word] & (word ## _ ## feature)) != 0)
>  
> +#define VIV_2D_FEATURE(screen, word, feature) \
> +   ((screen->features2d[viv_ ## word] & (word ## _ ## feature)) != 0)
> +
>  struct etna_screen {
>     struct pipe_screen base;
>  
> @@ -68,7 +71,9 @@ struct etna_screen {
>  
>     struct etna_device *dev;
>     struct etna_gpu *gpu;
> +   struct etna_gpu *gpu2d;
>     struct etna_pipe *pipe;
> +   struct etna_pipe *pipe2d;
>     struct etna_perfmon *perfmon;
>     struct renderonly *ro;
>  
> @@ -78,6 +83,7 @@ struct etna_screen {
>     uint32_t model;
>     uint32_t revision;
>     uint32_t features[VIV_FEATURES_WORD_COUNT];
> +   uint32_t features2d[VIV_FEATURES_WORD_COUNT];
>  
>     struct etna_specs specs;
>  

regards
Philipp


More information about the mesa-dev mailing list