[Mesa-dev] [PATCH v4 8/9] st/va: implement VaDeriveImage

Christian König deathsimple at vodafone.de
Fri Oct 30 04:57:02 PDT 2015


On 29.10.2015 18:40, Julien Isorce wrote:
> And apply relatives change to:
> vlVaBufferSetNumElements
> vlVaCreateBuffer
> vlVaMapBuffer
> vlVaUnmapBuffer
> vlVaDestroyBuffer
> vlVaPutImage
>
> It is unfortunate that there is no proper va buffer type and struct
> for this. Only possible to use VAImageBufferType which is normally
> used for normal user data array.
> On of the consequences is that it is only possible VaDeriveImage
> is only useful on surfaces backed with contiguous planes.
> Implementation inspired from cgit.freedesktop.org/vaapi/intel-driver
>
> Signed-off-by: Julien Isorce <j.isorce at samsung.com>

Reviewed-by: Christian König <christian.koenig at amd.com>

> ---
>   src/gallium/state_trackers/va/buffer.c     | 43 ++++++++++++--
>   src/gallium/state_trackers/va/image.c      | 92 +++++++++++++++++++++++++++++-
>   src/gallium/state_trackers/va/va_private.h |  5 ++
>   3 files changed, 135 insertions(+), 5 deletions(-)
>
> diff --git a/src/gallium/state_trackers/va/buffer.c b/src/gallium/state_trackers/va/buffer.c
> index 8f9ba44..6e32541 100644
> --- a/src/gallium/state_trackers/va/buffer.c
> +++ b/src/gallium/state_trackers/va/buffer.c
> @@ -26,8 +26,11 @@
>    *
>    **************************************************************************/
>   
> +#include "pipe/p_screen.h"
>   #include "util/u_memory.h"
>   #include "util/u_handle_table.h"
> +#include "util/u_transfer.h"
> +#include "vl/vl_winsys.h"
>   
>   #include "va_private.h"
>   
> @@ -73,6 +76,10 @@ vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id,
>         return VA_STATUS_ERROR_INVALID_CONTEXT;
>   
>      buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
> +
> +   if (!buf || buf->derived_surface.resource)
> +      return VA_STATUS_ERROR_INVALID_BUFFER;
> +
>      buf->data = REALLOC(buf->data, buf->size * buf->num_elements,
>                          buf->size * num_elements);
>      buf->num_elements = num_elements;
> @@ -86,16 +93,32 @@ vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id,
>   VAStatus
>   vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)
>   {
> +   vlVaDriver *drv;
>      vlVaBuffer *buf;
>   
>      if (!ctx)
>         return VA_STATUS_ERROR_INVALID_CONTEXT;
>   
> -   buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
> +   if (!pbuff)
> +      return VA_STATUS_ERROR_INVALID_BUFFER;
> +
> +   drv = VL_VA_DRIVER(ctx);
> +
> +   buf = handle_table_get(drv->htab, buf_id);
>      if (!buf)
>         return VA_STATUS_ERROR_INVALID_BUFFER;
>   
> -   *pbuff = buf->data;
> +   if (buf->derived_surface.resource) {
> +      *pbuff = pipe_buffer_map(drv->pipe, buf->derived_surface.resource,
> +                               PIPE_TRANSFER_WRITE,
> +                               &buf->derived_surface.transfer);
> +
> +      if (!buf->derived_surface.transfer || !*pbuff)
> +         return VA_STATUS_ERROR_INVALID_BUFFER;
> +
> +   } else {
> +      *pbuff = buf->data;
> +   }
>   
>      return VA_STATUS_SUCCESS;
>   }
> @@ -103,16 +126,25 @@ vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)
>   VAStatus
>   vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
>   {
> +   vlVaDriver *drv;
>      vlVaBuffer *buf;
>   
>      if (!ctx)
>         return VA_STATUS_ERROR_INVALID_CONTEXT;
>   
> -   buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
> +   drv = VL_VA_DRIVER(ctx);
> +
> +   buf = handle_table_get(drv->htab, buf_id);
>      if (!buf)
>         return VA_STATUS_ERROR_INVALID_BUFFER;
>   
> -   /* Nothing to do here */
> +   if (buf->derived_surface.resource) {
> +     if (!buf->derived_surface.transfer)
> +        return VA_STATUS_ERROR_INVALID_BUFFER;
> +
> +     pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer);
> +     buf->derived_surface.transfer = NULL;
> +   }
>   
>      return VA_STATUS_SUCCESS;
>   }
> @@ -129,6 +161,9 @@ vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
>      if (!buf)
>         return VA_STATUS_ERROR_INVALID_BUFFER;
>   
> +   if (buf->derived_surface.resource)
> +     pipe_resource_reference(&buf->derived_surface.resource, NULL);
> +
>      FREE(buf->data);
>      FREE(buf);
>      handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);
> diff --git a/src/gallium/state_trackers/va/image.c b/src/gallium/state_trackers/va/image.c
> index 8e64673..f266ce8 100644
> --- a/src/gallium/state_trackers/va/image.c
> +++ b/src/gallium/state_trackers/va/image.c
> @@ -184,10 +184,95 @@ vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int heig
>   VAStatus
>   vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
>   {
> +   vlVaDriver *drv;
> +   vlVaSurface *surf;
> +   vlVaBuffer *img_buf;
> +   VAImage *img;
> +   struct pipe_surface **surfaces;
> +   int w;
> +   int h;
> +   int i;
> +
>      if (!ctx)
>         return VA_STATUS_ERROR_INVALID_CONTEXT;
>   
> -   return VA_STATUS_ERROR_UNIMPLEMENTED;
> +   drv = VL_VA_DRIVER(ctx);
> +
> +   if (!drv)
> +      return VA_STATUS_ERROR_INVALID_CONTEXT;
> +
> +   surf = handle_table_get(drv->htab, surface);
> +
> +   if (!surf || !surf->buffer || surf->buffer->interlaced)
> +      return VA_STATUS_ERROR_INVALID_SURFACE;
> +
> +   surfaces = surf->buffer->get_surfaces(surf->buffer);
> +   if (!surfaces || !surfaces[0]->texture)
> +      return VA_STATUS_ERROR_ALLOCATION_FAILED;
> +
> +   img = CALLOC(1, sizeof(VAImage));
> +   if (!img)
> +      return VA_STATUS_ERROR_ALLOCATION_FAILED;
> +
> +   img->format.fourcc = PipeToYCbCr(surf->buffer->buffer_format);
> +   img->buf = VA_INVALID_ID;
> +   img->width = surf->buffer->width;
> +   img->height = surf->buffer->height;
> +   img->num_palette_entries = 0;
> +   img->entry_bytes = 0;
> +   w = align(surf->buffer->width, 2);
> +   h = align(surf->buffer->height, 2);
> +
> +   for (i = 0; i < ARRAY_SIZE(formats); ++i) {
> +      if (img->format.fourcc == formats[i].fourcc)
> +         img->format = formats[i];
> +   }
> +
> +   switch (img->format.fourcc) {
> +   case VA_FOURCC('U','Y','V','Y'):
> +   case VA_FOURCC('Y','U','Y','V'):
> +      img->num_planes = 1;
> +      img->pitches[0] = w * 2;
> +      img->offsets[0] = 0;
> +      img->data_size  = w * h * 2;
> +      break;
> +
> +   case VA_FOURCC('B','G','R','A'):
> +   case VA_FOURCC('R','G','B','A'):
> +   case VA_FOURCC('B','G','R','X'):
> +   case VA_FOURCC('R','G','B','X'):
> +      img->num_planes = 1;
> +      img->pitches[0] = w * 4;
> +      img->offsets[0] = 0;
> +      img->data_size  = w * h * 4;
> +      break;
> +
> +   default:
> +      /* VaDeriveImage is designed for contiguous planes. */
> +      FREE(img);
> +      return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
> +   }
> +
> +   img_buf = CALLOC(1, sizeof(vlVaBuffer));
> +   if (!img_buf) {
> +      FREE(img);
> +      return VA_STATUS_ERROR_ALLOCATION_FAILED;
> +   }
> +
> +   img->image_id = handle_table_add(drv->htab, img);
> +
> +   img_buf->type = VAImageBufferType;
> +   img_buf->size = image->data_size;
> +   img_buf->num_elements = 1;
> +   img_buf->derived_surface.fence = surf->fence;
> +
> +   pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture);
> +
> +   img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf);
> +
> +   *image = *img;
> +
> +   return VA_STATUS_SUCCESS;
>   }
>   
>   VAStatus
> @@ -342,6 +427,11 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
>      if (!img_buf)
>         return VA_STATUS_ERROR_INVALID_BUFFER;
>   
> +   if (img_buf->derived_surface.resource) {
> +      /* Attempting to transfer derived image to surface */
> +      return VA_STATUS_ERROR_UNIMPLEMENTED;
> +   }
> +
>      format = YCbCrToPipe(vaimage->format.fourcc);
>      if (format == PIPE_FORMAT_NONE)
>         return VA_STATUS_ERROR_OPERATION_FAILED;
> diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h
> index b062357..40363b3 100644
> --- a/src/gallium/state_trackers/va/va_private.h
> +++ b/src/gallium/state_trackers/va/va_private.h
> @@ -236,6 +236,11 @@ typedef struct {
>      unsigned int size;
>      unsigned int num_elements;
>      void *data;
> +   struct {
> +      struct pipe_resource *resource;
> +      struct pipe_transfer *transfer;
> +      struct pipe_fence_handle *fence;
> +   } derived_surface;
>   } vlVaBuffer;
>   
>   typedef struct {



More information about the mesa-dev mailing list