Mesa (master): gallium, va: add support for VASurfaceAttribDRMFormatModifiers

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 22 16:17:46 UTC 2021


Module: Mesa
Branch: master
Commit: 5f101e8096f719a97528c8d15b6ea8fd3a7eae4e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5f101e8096f719a97528c8d15b6ea8fd3a7eae4e

Author: Simon Ser <contact at emersion.fr>
Date:   Fri Apr  9 10:25:11 2021 +0200

gallium, va: add support for VASurfaceAttribDRMFormatModifiers

This new surface attribute can be supplied by the client to indicate
a list of modifiers that the driver can choose from for buffer
allocation. This is useful to make sure the buffers allocated via libva
are compatible with the intended usage (e.g. can be scanned out via KMS
or can be imported to EGL).

Introduce a new Gallium pipe_context.create_video_buffer_with_modifiers
hook that drivers can implement if they are modifiers-aware. Add a
modifiers argument to vlVaHandleSurfaceAllocate so that the
user-supplied list of modifiers can be passed down from vaCreateSurfaces
to the Gallium driver.

Signed-off-by: Simon Ser <contact at emersion.fr>
Reviewed-by: Leo Liu <leo.liu at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10237>

---

 meson.build                           |  4 +++
 src/gallium/frontends/va/picture.c    |  2 +-
 src/gallium/frontends/va/postproc.c   |  4 +--
 src/gallium/frontends/va/surface.c    | 62 +++++++++++++++++++++++++++++------
 src/gallium/frontends/va/va_private.h |  3 +-
 src/gallium/include/pipe/p_context.h  |  8 +++++
 6 files changed, 69 insertions(+), 14 deletions(-)

diff --git a/meson.build b/meson.build
index ff432eb9a41..d99c4565f4b 100644
--- a/meson.build
+++ b/meson.build
@@ -731,6 +731,10 @@ if _va != 'disabled'
   if dep_va.found()
     dep_va_headers = dep_va.partial_dependency(compile_args : true)
     with_gallium_va = true
+    if cc.has_header_symbol('va/va.h', 'VASurfaceAttribDRMFormatModifiers',
+                            dependencies: dep_va_headers)
+      pre_args += '-DHAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS'
+    endif
   endif
 endif
 
diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c
index 32d8b925036..d3953b1d36c 100644
--- a/src/gallium/frontends/va/picture.c
+++ b/src/gallium/frontends/va/picture.c
@@ -710,7 +710,7 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
    if (realloc) {
       struct pipe_video_buffer *old_buf = surf->buffer;
 
-      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) {
+      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS) {
          mtx_unlock(&drv->mutex);
          return VA_STATUS_ERROR_ALLOCATION_FAILED;
       }
diff --git a/src/gallium/frontends/va/postproc.c b/src/gallium/frontends/va/postproc.c
index 7ab56b5f4c2..162994d88fd 100644
--- a/src/gallium/frontends/va/postproc.c
+++ b/src/gallium/frontends/va/postproc.c
@@ -145,7 +145,7 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
       surf->templat.interlaced = false;
       dst->destroy(dst);
 
-      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS)
+      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
          return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
       dst = context->target = surf->buffer;
@@ -317,7 +317,7 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
       surf->templat.interlaced = false;
       dst->destroy(dst);
 
-      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS)
+      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
          return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
       dst = context->target = surf->buffer;
diff --git a/src/gallium/frontends/va/surface.c b/src/gallium/frontends/va/surface.c
index d226575dc08..1110f3eaa9f 100644
--- a/src/gallium/frontends/va/surface.c
+++ b/src/gallium/frontends/va/surface.c
@@ -512,6 +512,16 @@ vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id,
    attribs[i].value.value.p = NULL; /* ignore */
    i++;
 
+#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS
+   if (drv->pipe->create_video_buffer_with_modifiers) {
+      attribs[i].type = VASurfaceAttribDRMFormatModifiers;
+      attribs[i].value.type = VAGenericValueTypePointer;
+      attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;
+      attribs[i].value.value.p = NULL; /* ignore */
+      i++;
+   }
+#endif
+
    if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_UNKNOWN) {
       attribs[i].type = VASurfaceAttribMaxWidth;
       attribs[i].value.type = VAGenericValueTypeInteger;
@@ -641,12 +651,23 @@ fail:
 
 VAStatus
 vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface,
-                          struct pipe_video_buffer *templat)
+                          struct pipe_video_buffer *templat,
+                          const uint64_t *modifiers,
+                          unsigned int modifiers_count)
 {
    struct pipe_surface **surfaces;
    unsigned i;
 
-   surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat);
+   if (modifiers_count > 0) {
+      if (!drv->pipe->create_video_buffer_with_modifiers)
+         return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
+      surface->buffer =
+         drv->pipe->create_video_buffer_with_modifiers(drv->pipe, templat,
+                                                       modifiers,
+                                                       modifiers_count);
+   } else {
+      surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat);
+   }
    if (!surface->buffer)
       return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
@@ -677,6 +698,9 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
 {
    vlVaDriver *drv;
    VASurfaceAttribExternalBuffers *memory_attribute;
+#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS
+   const VADRMFormatModifierList *modifier_list;
+#endif
    struct pipe_video_buffer templat;
    struct pipe_screen *pscreen;
    int i;
@@ -685,6 +709,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
    VAStatus vaStatus;
    vlVaSurface *surf;
    bool protected;
+   const uint64_t *modifiers;
+   unsigned int modifiers_count;
 
    if (!ctx)
       return VA_STATUS_ERROR_INVALID_CONTEXT;
@@ -706,6 +732,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
    memory_attribute = NULL;
    memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
    expected_fourcc = 0;
+   modifiers = NULL;
+   modifiers_count = 0;
 
    for (i = 0; i < num_attribs && attrib_list; i++) {
       if (!(attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE))
@@ -735,6 +763,15 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
             return VA_STATUS_ERROR_INVALID_PARAMETER;
          memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
          break;
+#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS
+      case VASurfaceAttribDRMFormatModifiers:
+         if (attrib_list[i].value.type != VAGenericValueTypePointer)
+            return VA_STATUS_ERROR_INVALID_PARAMETER;
+         modifier_list = attrib_list[i].value.value.p;
+         modifiers = modifier_list->modifiers;
+         modifiers_count = modifier_list->num_modifiers;
+         break;
+#endif
       default:
          return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
       }
@@ -757,6 +794,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
    case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
       if (!memory_attribute)
          return VA_STATUS_ERROR_INVALID_PARAMETER;
+      if (modifiers)
+         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
       expected_fourcc = memory_attribute->pixel_format;
       break;
@@ -772,12 +811,14 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
       PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
       PIPE_VIDEO_CAP_PREFERED_FORMAT
    );
-   templat.interlaced = pscreen->get_video_param(
-      pscreen,
-      PIPE_VIDEO_PROFILE_UNKNOWN,
-      PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
-      PIPE_VIDEO_CAP_PREFERS_INTERLACED
-   );
+
+   if (modifiers)
+      templat.interlaced = false;
+   else
+      templat.interlaced =
+         pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+                                  PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+                                  PIPE_VIDEO_CAP_PREFERS_INTERLACED);
 
    if (expected_fourcc) {
       enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc);
@@ -815,7 +856,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
              !(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING))
             templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED;
 
-	 vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat);
+	 vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat, modifiers,
+                                              modifiers_count);
          if (vaStatus != VA_STATUS_SUCCESS)
             goto free_surf;
          break;
@@ -1043,7 +1085,7 @@ vlVaExportSurfaceHandle(VADriverContextP ctx,
 
       surf->templat.interlaced = false;
 
-      ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat);
+      ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0);
       if (ret != VA_STATUS_SUCCESS) {
          mtx_unlock(&drv->mutex);
          return VA_STATUS_ERROR_ALLOCATION_FAILED;
diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h
index 17bd024c1a7..a25e24592a1 100644
--- a/src/gallium/frontends/va/va_private.h
+++ b/src/gallium/frontends/va/va_private.h
@@ -427,7 +427,8 @@ VAStatus vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID contex
 
 // internal functions
 VAStatus vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf);
-VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, struct pipe_video_buffer *templat);
+VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, struct pipe_video_buffer *templat,
+                                   const uint64_t *modifiers, unsigned int modifiers_count);
 void vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, struct pipe_video_buffer **ref_frame);
 void vlVaHandlePictureParameterBufferMPEG12(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf);
 void vlVaHandleIQMatrixBufferMPEG12(vlVaContext *context, vlVaBuffer *buf);
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 13e704de0fb..4ce0e569c89 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -1101,6 +1101,14 @@ struct pipe_context {
    void (*set_context_param)(struct pipe_context *ctx,
                              enum pipe_context_param param,
                              unsigned value);
+
+   /**
+    * Creates a video buffer as decoding target, with modifiers.
+    */
+   struct pipe_video_buffer *(*create_video_buffer_with_modifiers)(struct pipe_context *context,
+                                                                   const struct pipe_video_buffer *templat,
+                                                                   const uint64_t *modifiers,
+                                                                   unsigned int modifiers_count);
 };
 
 



More information about the mesa-commit mailing list