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

Mark Thompson sw at jkqxz.net
Sun Oct 15 11:23:27 UTC 2017


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

v2: Convert surfaces to progressive before exporting them (Christian).

v3: Set destination rectangle to match source when converting (Leo).
    Add guards to allow building with libva1.

v4: Adjust target version - this is no longer in libva 2.0.

Signed-off-by: Mark Thompson <sw at jkqxz.net>
---
(Testing only for now, not to be applied yet.)


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

diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c
index f2cb37aa22..8ba0af11ea 100644
--- a/src/gallium/state_trackers/va/context.c
+++ b/src/gallium/state_trackers/va/context.c
@@ -88,7 +88,10 @@ static struct VADriverVTable vtable =
    &vlVaCreateSurfaces2,
    &vlVaQuerySurfaceAttributes,
    &vlVaAcquireBufferHandle,
-   &vlVaReleaseBufferHandle
+   &vlVaReleaseBufferHandle,
+#if VA_CHECK_VERSION(1, 0, 1)
+   &vlVaExportSurfaceHandle,
+#endif
 };
 
 static struct VADriverVTableVPP vtable_vpp =
diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c
index 4c2f4b5452..013914ac0e 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,
@@ -901,3 +902,150 @@ vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context,
 
    return VA_STATUS_SUCCESS;
 }
+
+#if VA_CHECK_VERSION(1, 0, 1)
+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, dst_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 = dst_rect.x0 = 0;
+      src_rect.y0 = dst_rect.y0 = 0;
+      src_rect.x1 = dst_rect.x1 = surf->templat.width;
+      src_rect.y1 = dst_rect.y1 = surf->templat.height;
+
+      vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
+                                   interlaced, surf->buffer,
+                                   &src_rect, &dst_rect,
+                                   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;
+}
+#endif
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