[Mesa-dev] [PATCH 2/3] st/va: Implement vaExportSurfaceHandle()

Mark Thompson sw at jkqxz.net
Thu Sep 28 22:12:56 UTC 2017


This is a new interface in libva2 to support wider use-cases of passing
surfaces to external APIs.  In particular, this allows export of NV12 and
P010 surfaces.

Signed-off-by: Mark Thompson <sw at jkqxz.net>
---
On 22/09/17 10:17, Christian König wrote:
> Am 21.09.2017 um 21:00 schrieb Mark Thompson:
>> On 20/09/17 09:14, Christian König wrote:
>>> Am 20.09.2017 um 00:01 schrieb Mark Thompson:
>>>> Still unsure on what to do about size and interlacing.  I'll have a look at the postproc code just posted soon, though I think it's pretty much entirely orthogonal to this.
>>> Probably best to convert the interlaced representation into the progressive form before exporting.
>> I'd prefer not to do that, because a use-case of this is to be able to modify surfaces in-place.  (E.g. decode, scale, export, blend something else onto the surface, fence, encode.)
> 
> My suggesting is to change the backing store of the surface while it is exported. So in place modifications should work and if the surface is then reused for decoding it will directly decode to the progressive format.

This works nicely.  Thanks for the suggestion!

The libva side of this is updated in <https://github.com/01org/libva/pull/125>.

Thanks,

- Mark


 src/gallium/state_trackers/va/context.c    |   3 +-
 src/gallium/state_trackers/va/surface.c    | 145 +++++++++++++++++++++++++++++
 src/gallium/state_trackers/va/va_private.h |   1 +
 3 files changed, 148 insertions(+), 1 deletion(-)

diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c
index f2cb37aa22..2794e5c733 100644
--- a/src/gallium/state_trackers/va/context.c
+++ b/src/gallium/state_trackers/va/context.c
@@ -88,7 +88,8 @@ static struct VADriverVTable vtable =
    &vlVaCreateSurfaces2,
    &vlVaQuerySurfaceAttributes,
    &vlVaAcquireBufferHandle,
-   &vlVaReleaseBufferHandle
+   &vlVaReleaseBufferHandle,
+   &vlVaExportSurfaceHandle
 };
 
 static struct VADriverVTableVPP vtable_vpp =
diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c
index 643cdcd54a..e63d552c7d 100644
--- a/src/gallium/state_trackers/va/surface.c
+++ b/src/gallium/state_trackers/va/surface.c
@@ -44,6 +44,7 @@
 #include "va_private.h"
 
 #include <va/va_drmcommon.h>
+#include <drm-uapi/drm_fourcc.h>
 
 static const enum pipe_format vpp_surface_formats[] = {
    PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM,
@@ -889,3 +890,147 @@ vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context,
 
    return VA_STATUS_SUCCESS;
 }
+
+VAStatus
+vlVaExportSurfaceHandle(VADriverContextP ctx,
+                        VASurfaceID surface_id,
+                        uint32_t mem_type,
+                        uint32_t flags,
+                        void *descriptor)
+{
+   vlVaDriver *drv;
+   vlVaSurface *surf;
+   struct pipe_surface **surfaces;
+   struct pipe_screen *screen;
+   VAStatus ret;
+   unsigned int usage;
+   int i, p;
+
+   VADRMPRIMESurfaceDescriptor *desc = descriptor;
+
+   if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
+      return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
+   if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS)
+      return VA_STATUS_ERROR_INVALID_SURFACE;
+
+   drv    = VL_VA_DRIVER(ctx);
+   screen = VL_VA_PSCREEN(ctx);
+   mtx_lock(&drv->mutex);
+
+   surf = handle_table_get(drv->htab, surface_id);
+   if (!surf || !surf->buffer) {
+      mtx_unlock(&drv->mutex);
+      return VA_STATUS_ERROR_INVALID_SURFACE;
+   }
+
+   if (surf->buffer->interlaced) {
+      struct pipe_video_buffer *interlaced = surf->buffer;
+      struct u_rect src_rect;
+
+      surf->templat.interlaced = false;
+
+      ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat);
+      if (ret != VA_STATUS_SUCCESS) {
+         mtx_unlock(&drv->mutex);
+         return VA_STATUS_ERROR_ALLOCATION_FAILED;
+      }
+
+      src_rect.x0 = 0;
+      src_rect.y0 = 0;
+      src_rect.x1 = surf->templat.width;
+      src_rect.y1 = surf->templat.height;
+
+      vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
+                                   interlaced, surf->buffer,
+                                   &src_rect, NULL, VL_COMPOSITOR_WEAVE);
+
+      interlaced->destroy(interlaced);
+   }
+
+   surfaces = surf->buffer->get_surfaces(surf->buffer);
+
+   usage = 0;
+   if (flags & VA_EXPORT_SURFACE_READ_ONLY)
+      usage |= PIPE_HANDLE_USAGE_READ;
+   if (flags & VA_EXPORT_SURFACE_WRITE_ONLY)
+      usage |= PIPE_HANDLE_USAGE_WRITE;
+
+   desc->fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format);
+   desc->width  = surf->buffer->width;
+   desc->height = surf->buffer->height;
+
+   for (p = 0; p < VL_MAX_SURFACES; p++) {
+      struct winsys_handle whandle;
+      struct pipe_resource *resource;
+      uint32_t drm_format;
+
+      if (!surfaces[p])
+         break;
+
+      resource = surfaces[p]->texture;
+
+      switch (resource->format) {
+      case PIPE_FORMAT_R8_UNORM:
+         drm_format = DRM_FORMAT_R8;
+         break;
+      case PIPE_FORMAT_R8G8_UNORM:
+         drm_format = DRM_FORMAT_GR88;
+         break;
+      case PIPE_FORMAT_R16_UNORM:
+         drm_format = DRM_FORMAT_R16;
+         break;
+      case PIPE_FORMAT_R16G16_UNORM:
+         drm_format = DRM_FORMAT_GR1616;
+         break;
+      case PIPE_FORMAT_B8G8R8A8_UNORM:
+         drm_format = DRM_FORMAT_ARGB8888;
+         break;
+      case PIPE_FORMAT_R8G8B8A8_UNORM:
+         drm_format = DRM_FORMAT_ABGR8888;
+         break;
+      case PIPE_FORMAT_B8G8R8X8_UNORM:
+         drm_format = DRM_FORMAT_XRGB8888;
+         break;
+      case PIPE_FORMAT_R8G8B8X8_UNORM:
+         drm_format = DRM_FORMAT_XBGR8888;
+         break;
+      default:
+         ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
+         goto fail;
+      }
+
+      memset(&whandle, 0, sizeof(whandle));
+      whandle.type = DRM_API_HANDLE_TYPE_FD;
+
+      if (!screen->resource_get_handle(screen, drv->pipe, resource,
+                                       &whandle, usage)) {
+         ret = VA_STATUS_ERROR_INVALID_SURFACE;
+         goto fail;
+      }
+
+      desc->objects[p].fd   = (int)whandle.handle;
+      desc->objects[p].size = 0;
+      desc->objects[p].drm_format_modifier = whandle.modifier;
+
+      desc->layers[p].drm_format      = drm_format;
+      desc->layers[p].num_planes      = 1;
+      desc->layers[p].object_index[0] = p;
+      desc->layers[p].offset[0]       = whandle.offset;
+      desc->layers[p].pitch[0]        = whandle.stride;
+   }
+
+   desc->num_objects = p;
+   desc->num_layers  = p;
+
+   mtx_unlock(&drv->mutex);
+
+   return VA_STATUS_SUCCESS;
+
+fail:
+   for (i = 0; i < p; i++)
+      close(desc->objects[i].fd);
+
+   mtx_unlock(&drv->mutex);
+
+   return ret;
+}
diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h
index 61712ce913..46f6ba66f2 100644
--- a/src/gallium/state_trackers/va/va_private.h
+++ b/src/gallium/state_trackers/va/va_private.h
@@ -394,6 +394,7 @@ VAStatus vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config, VAS
 
 VAStatus vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, VABufferInfo *out_buf_info);
 VAStatus vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id);
+VAStatus vlVaExportSurfaceHandle(VADriverContextP ctx, VASurfaceID surface_id, uint32_t mem_type, uint32_t flags, void *descriptor);
 
 VAStatus vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, VAProcFilterType *filters,
                                    unsigned int *num_filters);
-- 
2.11.0


More information about the mesa-dev mailing list