[vlc-devel] [PATCH v2 2/2] vaapi: add support for DRM modifiers

Lionel Landwerlin lionel.g.landwerlin at intel.com
Mon May 11 13:21:52 CEST 2020


On 11/05/2020 14:05, Thomas Guillem wrote:
> Hello,
>
> On Sun, May 10, 2020, at 23:01, Lionel Landwerlin wrote:
>> DRM modifiers communicate a description of the data layout in the
>> buffers exported/imported through various API.
>>
>> On Intel HW this exports tiling information as well as potential
>> compression.
>>
>> v2: Make modifier usage conditional to the appropriate vaapi version
>>
>> v3: Don't touch configure.ac
>>      Use VA_CHECK_VERSION()
>> ---
>>   modules/hw/vaapi/vlc_vaapi.c                | 15 ++++
>>   modules/hw/vaapi/vlc_vaapi.h                | 10 +++
>>   modules/video_output/opengl/interop_vaapi.c | 91 +++++++++++++++++++--
>>   3 files changed, 108 insertions(+), 8 deletions(-)
>>
>> diff --git a/modules/hw/vaapi/vlc_vaapi.c b/modules/hw/vaapi/vlc_vaapi.c
>> index 8a4dc6023d..31304fd6c3 100644
>> --- a/modules/hw/vaapi/vlc_vaapi.c
>> +++ b/modules/hw/vaapi/vlc_vaapi.c
>> @@ -589,3 +589,18 @@ vlc_vaapi_PicGetDisplay(picture_t *pic)
>>       struct vaapi_pic_context *pic_ctx = (struct vaapi_pic_context
>> *)pic->context;
>>       return pic_ctx->va_dpy;
>>   }
>> +
>> +#if VA_CHECK_VERSION(1, 1, 0)
>> +int
>> +vlc_vaapi_ExportSurfaceHandle(vlc_object_t *o,
>> +                              VADisplay dpy,
>> +                              VASurfaceID surface,
>> +                              uint32_t mem_type,
>> +                              uint32_t flags,
>> +                              void *descriptor)
>> +{
>> +    VA_CALL(o, vaExportSurfaceHandle, dpy, surface, mem_type, flags,
>> descriptor);
>> +    return VLC_SUCCESS;
>> +error: return VLC_EGENERIC;
>> +}
>> +#endif
>> diff --git a/modules/hw/vaapi/vlc_vaapi.h b/modules/hw/vaapi/vlc_vaapi.h
>> index ffcf68205f..95de6f07c7 100644
>> --- a/modules/hw/vaapi/vlc_vaapi.h
>> +++ b/modules/hw/vaapi/vlc_vaapi.h
>> @@ -199,6 +199,16 @@ vlc_vaapi_IsChromaOpaque(int i_vlc_chroma)
>>   
>>   void vlc_chroma_to_vaapi(int i_vlc_chroma, unsigned *va_rt_format, int
>> *va_fourcc);
>>   
>> +#ifdef VA_CHECK_VERSION(1, 1, 0)
> Typo here, It should be #if VA_CHECK_VERSION(1, 1, 0)
>
>> +int
>> +vlc_vaapi_ExportSurfaceHandle(vlc_object_t *o,
>> +                              VADisplay dpy,
>> +                              VASurfaceID surface,
>> +                              uint32_t mem_type,
>> +                              uint32_t flags,
>> +                              void *descriptor);
>> +#endif
>> +
>>   /* This macro is designed to wrap any VA call, and in case of failure,
>>      display the VA error string then goto the 'error' label (which you
>> must
>>      define). */
>> diff --git a/modules/video_output/opengl/interop_vaapi.c
>> b/modules/video_output/opengl/interop_vaapi.c
>> index 27d9e0ec2d..1f79ccc431 100644
>> --- a/modules/video_output/opengl/interop_vaapi.c
>> +++ b/modules/video_output/opengl/interop_vaapi.c
>> @@ -46,6 +46,15 @@ typedef void *GLeglImageOES;
>>   typedef void (*PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum target,
>> GLeglImageOES image);
>>   #endif
>>   
>> +#define DRM_FORMAT_MOD_VENDOR_NONE    0
>> +#define DRM_FORMAT_RESERVED           ((1ULL << 56) - 1)
>> +
>> +#define fourcc_mod_code(vendor, val) \
>> +        ((((EGLuint64KHR)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) |
>> ((val) & 0x00ffffffffffffffULL))
>> +
>> +#define DRM_FORMAT_MOD_INVALID  fourcc_mod_code(NONE,
>> DRM_FORMAT_RESERVED)
>> +
>> +
>>   struct priv
>>   {
>>       VADisplay vadpy;
>> @@ -56,16 +65,23 @@ struct priv
>>       EGLint drm_fourccs[3];
>>   
>>       struct {
>> -        picture_t *  pic;
>> -        VAImage      va_image;
>> -        VABufferInfo va_buffer_info;
>> -        void *       egl_images[3];
>> +        picture_t *                 pic;
>> +#if VA_CHECK_VERSION(1, 1, 0)
>> +        /* VADRMPRIMESurfaceDescriptor carries modifier information
>> +         * (GPU tiling, compression, etc...) */
>> +        VADRMPRIMESurfaceDescriptor va_surface_descriptor;
>> +#else
>> +        VABufferInfo                va_buffer_info;
>> +#endif
>> +        VAImage                     va_image;
>> +        void *                      egl_images[3];
>>       } last;
>>   };
>>   
>>   static EGLImageKHR
>>   vaegl_image_create(const struct vlc_gl_interop *interop, EGLint w,
>> EGLint h,
>> -                   EGLint fourcc, EGLint fd, EGLint offset, EGLint
>> pitch)
>> +                   EGLint fourcc, EGLint fd, EGLint offset, EGLint
>> pitch,
>> +                   EGLuint64KHR modifier)
>>   {
>>       EGLint attribs[] = {
>>           EGL_WIDTH, w,
>> @@ -74,6 +90,8 @@ vaegl_image_create(const struct vlc_gl_interop
>> *interop, EGLint w, EGLint h,
>>           EGL_DMA_BUF_PLANE0_FD_EXT, fd,
>>           EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset,
>>           EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch,
>> +        EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, modifier & 0xffffffff,
>> +        EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, modifier >> 32,
>>           EGL_NONE
>>       };
>>   
>> @@ -95,7 +113,12 @@ vaegl_release_last_pic(const struct vlc_gl_interop
>> *interop, struct priv *priv)
>>       for (unsigned i = 0; i < priv->last.va_image.num_planes; ++i)
>>           vaegl_image_destroy(interop, priv->last.egl_images[i]);
>>   
>> +#if VA_CHECK_VERSION(1, 1, 0)
>> +    for (unsigned i = 0; i < priv->last.va_surface_descriptor.num_objects; ++i)
>> +        close(priv->last.va_surface_descriptor.objects[i].fd);
>> +#else
>>       vlc_vaapi_ReleaseBufferHandle(o, priv->vadpy, priv->last.va_image.buf);
>> +#endif
>>   
>>       vlc_vaapi_DestroyImage(o, priv->vadpy, priv->last.va_image.image_id);
>>   
>> @@ -157,14 +180,18 @@ tc_vaegl_update(const struct vlc_gl_interop
>> *interop, GLuint *textures,
>>       struct priv *priv = interop->priv;
>>       vlc_object_t *o = VLC_OBJECT(interop->gl);
>>       VAImage va_image;
>> +#if VA_CHECK_VERSION(1, 1, 0)
>> +    VADRMPRIMESurfaceDescriptor va_surface_descriptor;
>> +#else
>>       VABufferInfo va_buffer_info;
>> +#endif
>>       EGLImageKHR egl_images[3] = { };
>>       bool release_image = false, release_buffer_info = false;
>>   
>>       if (pic == priv->last.pic)
>>       {
>>           va_image = priv->last.va_image;
>> -        va_buffer_info = priv->last.va_buffer_info;
>> +        va_surface_descriptor = priv->last.va_surface_descriptor;
>>           for (unsigned i = 0; i < priv->last.va_image.num_planes; ++i)
>>               egl_images[i] = priv->last.egl_images[i];
>>       }
>> @@ -177,21 +204,55 @@ tc_vaegl_update(const struct vlc_gl_interop
>> *interop, GLuint *textures,
>>   
>>           assert(va_image.format.fourcc == priv->fourcc);
>>   
>> +#if VA_CHECK_VERSION(1, 1, 0)
>> +        if (vlc_vaapi_ExportSurfaceHandle(o, priv->vadpy,
>> vlc_vaapi_PicGetSurface(pic),
>> +
>> VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, 0,
>> +                                          &va_surface_descriptor))
>> +            goto error;
>> +#else
>>           va_buffer_info = (VABufferInfo) {
>>               .mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
>>           };
>>           if (vlc_vaapi_AcquireBufferHandle(o, priv->vadpy, va_image.buf,
>>                                             &va_buffer_info))
>>               goto error;
>> +#endif
>>           release_buffer_info = true;
>>       }
>>   
>> +#if VA_CHECK_VERSION(1, 1, 0)
>> +    for (unsigned i = 0; i < va_surface_descriptor.num_layers; ++i)
>> +    {
>> +        unsigned obj_idx =
>> va_surface_descriptor.layers[i].object_index[0];
>> +
>> +        /* Since we don't ask for composite object through
>> +         * vaExportSurfaceHandle, we shouldn't get any multiplane
>> +         * layer. */
>> +        if (va_surface_descriptor.layers[i].num_planes > 1)
>> +          goto error;
>> +
>> +        egl_images[i] =
>> +            vaegl_image_create(interop, tex_width[i], tex_height[i],
>> +                               priv->drm_fourccs[i],
>> +
>> va_surface_descriptor.objects[obj_idx].fd,
>> +
>> va_surface_descriptor.layers[i].offset[0],
>> +
>> va_surface_descriptor.layers[i].pitch[0],
>> +
>> va_surface_descriptor.objects[obj_idx].drm_format_modifier);
>> +        if (egl_images[i] == NULL)
>> +            goto error;
>> +
>> +        interop->vt->BindTexture(interop->tex_target, textures[i]);
>> +
>> +        priv->glEGLImageTargetTexture2DOES(interop->tex_target,
>> egl_images[i]);
>> +    }
>> +#else
>>       for (unsigned i = 0; i < va_image.num_planes; ++i)
>>       {
>>           egl_images[i] =
>>               vaegl_image_create(interop, tex_width[i], tex_height[i],
>>                                  priv->drm_fourccs[i],
>> va_buffer_info.handle,
>> -                               va_image.offsets[i],
>> va_image.pitches[i]);
>> +                               va_image.offsets[i],
>> va_image.pitches[i],
>> +                               DRM_FORMAT_MOD_INVALID);
>>           if (egl_images[i] == NULL)
>>               goto error;
>>   
>> @@ -199,6 +260,7 @@ tc_vaegl_update(const struct vlc_gl_interop
>> *interop, GLuint *textures,
>>   
>>           priv->glEGLImageTargetTexture2DOES(interop->tex_target, egl_images[i]);
>>       }
>> +#endif
>>   
>>       if (pic != priv->last.pic)
>>       {
>> @@ -206,7 +268,12 @@ tc_vaegl_update(const struct vlc_gl_interop
>> *interop, GLuint *textures,
>>               vaegl_release_last_pic(interop, priv);
>>           priv->last.pic = picture_Hold(pic);
>>           priv->last.va_image = va_image;
>> +#if VA_CHECK_VERSION(1, 1, 0)
>> +        priv->last.va_surface_descriptor = va_surface_descriptor;
>> +#else
>>           priv->last.va_buffer_info = va_buffer_info;
>> +#endif
>> +
>>           for (unsigned i = 0; i < va_image.num_planes; ++i)
>>               priv->last.egl_images[i] = egl_images[i];
>>       }
>> @@ -217,7 +284,14 @@ error:
>>       if (release_image)
>>       {
>>           if (release_buffer_info)
>> +        {
>> +#if VA_CHECK_VERSION(1, 1, 0)
>> +            for (unsigned i = 0; i <
>> va_surface_descriptor.num_objects; ++i)
>> +                close(va_surface_descriptor.objects[i].fd);
>> +#else
>>               vlc_vaapi_ReleaseBufferHandle(o, priv->vadpy,
>> va_image.buf);
>> +#endif
>> +        }
>>   
>>           for (unsigned i = 0; i < 3 && egl_images[i] != NULL; ++i)
>>               vaegl_image_destroy(interop, egl_images[i]);
>> @@ -313,7 +387,8 @@ tc_va_check_derive_image(const struct
>> vlc_gl_interop *interop)
>>           EGLint h = (va_image.height * image_desc->p[i].h.num) /
>> image_desc->p[i].h.den;
>>           EGLImageKHR egl_image =
>>               vaegl_image_create(interop, w, h, priv->drm_fourccs[i],
>> va_buffer_info.handle,
>> -                               va_image.offsets[i],
>> va_image.pitches[i]);
>> +                               va_image.offsets[i],
>> va_image.pitches[i],
>> +                               DRM_FORMAT_MOD_INVALID);
>>           if (egl_image == NULL)
>>           {
>>               msg_Warn(o, "Can't create Image KHR: kernel too old ?");
>> -- 
>> 2.26.2
> Thanks for your work, I tested it on my side. Ready to merge it tomorrow.
>
> (you don't have to resend a patch for the typo, I fixed it on my side).


Thanks a bunch, and thanks for fixing the typo.


Cheers,


-Lionel


>
>> _______________________________________________
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel




More information about the vlc-devel mailing list