[vlc-commits] [Git][videolan/vlc][master] opengl: vaapi: check surfaces via the export path
Steve Lhomme (@robUx4)
gitlab at videolan.org
Sun Aug 30 06:02:15 UTC 2026
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
706fe761 by Charles Turner at 2026-08-30T05:50:10+00:00
opengl: vaapi: check surfaces via the export path
tc_vaegl_update imports with vaExportSurfaceHandle and the surface's
real drm_format_modifier, but tc_va_check_derive_image validated with
vaDeriveImage and DRM_FORMAT_MOD_INVALID - stricter than the path it
guards. On radeonsi, tiled P010 surfaces at widths that are not a
multiple of 256 are rejected (element pitch vs byte pitch), so the
interop was refused and 10-bit playback silently fell back to software.
NV12 is unaffected (R8, bpe == 1).
Also reject multiplane layers, matching update.
Not codec-specific: any 10-bit 4:2:0 (P010) content at such a width
triggers it - HEVC Main10, VP9 Profile 2, AV1 10-bit. Generate a
reproducer (1920 is not a multiple of 256) and play it via VAAPI:
ffmpeg -f lavfi -i testsrc2=size=1920x1080:rate=30:duration=3 \
-pix_fmt yuv420p10le -c:v libvpx-vp9 -profile:v 2 -b:v 2M out.mkv
vlc -vv --dec-dev decdev_vaapi_wl --vout=gl out.mkv
glinterop_vaapi gl warning: Can't create Image KHR: kernel too old ?
gl gl error: Could not create interop
main video output error: video output display creation failed
after which decoding continues in software. With this change the
interop is accepted and rendering is hardware-accelerated.
Verified on a Radeon 860M (gfx1151, mesa 26.0.8, libva 1.24) with
glinterop_vaapi on native Wayland (xdg_shell), with both HEVC Main10
and VP9 Profile 2.
- - - - -
1 changed file:
- modules/video_output/opengl/interop_vaapi.c
Changes:
=====================================
modules/video_output/opengl/interop_vaapi.c
=====================================
@@ -366,9 +366,55 @@ tc_va_check_derive_image(const struct vlc_gl_interop *interop)
if (!pool)
return VLC_EGENERIC;
+ int ret;
+
+#if VA_CHECK_VERSION(1, 1, 0)
+ VADRMPRIMESurfaceDescriptor desc;
+
+ ret = vlc_vaapi_ExportSurfaceHandle(o, priv->vadpy, va_surface_ids[0],
+ VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
+ VA_EXPORT_SURFACE_READ_ONLY |
+ VA_EXPORT_SURFACE_SEPARATE_LAYERS,
+ &desc);
+ if (ret != VLC_SUCCESS)
+ goto done;
+
+ for (unsigned i = 0; i < desc.num_layers; ++i)
+ {
+ unsigned obj_idx = desc.layers[i].object_index[0];
+
+ if (desc.layers[i].num_planes > 1)
+ {
+ ret = VLC_EGENERIC;
+ goto done_desc;
+ }
+
+ EGLint w = (desc.width * interop->texs[i].w.num) / interop->texs[i].w.den;
+ EGLint h = (desc.height * interop->texs[i].h.num) / interop->texs[i].h.den;
+ EGLImageKHR egl_image =
+ vaegl_image_create(interop, w, h, priv->drm_fourccs[i],
+ desc.objects[obj_idx].fd,
+ desc.layers[i].offset[0], desc.layers[i].pitch[0],
+ desc.objects[obj_idx].drm_format_modifier);
+ if (egl_image == NULL)
+ {
+ msg_Warn(o, "Can't create Image KHR: kernel too old ?");
+ ret = VLC_EGENERIC;
+ goto done_desc;
+ }
+ vaegl_image_destroy(interop, egl_image);
+ }
+
+ ret = VLC_SUCCESS;
+
+done_desc:
+ for (unsigned i = 0; i < desc.num_objects; ++i)
+ close(desc.objects[i].fd);
+ goto done;
+#else
VAImage va_image = { .image_id = VA_INVALID_ID };
- int ret = vlc_vaapi_DeriveImage(o, priv->vadpy, va_surface_ids[0],
- &va_image);
+ ret = vlc_vaapi_DeriveImage(o, priv->vadpy, va_surface_ids[0],
+ &va_image);
if (ret != VLC_SUCCESS)
goto done;
assert(va_image.format.fourcc == priv->fourcc);
@@ -376,10 +422,10 @@ tc_va_check_derive_image(const struct vlc_gl_interop *interop)
VABufferInfo va_buffer_info = (VABufferInfo) {
.mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
};
- ret = vlc_vaapi_AcquireBufferHandle(o ,priv->vadpy, va_image.buf,
+ ret = vlc_vaapi_AcquireBufferHandle(o, priv->vadpy, va_image.buf,
&va_buffer_info);
if (ret != VLC_SUCCESS)
- goto done;
+ goto done_derive;
for (unsigned i = 0; i < interop->tex_count; ++i)
{
@@ -393,19 +439,23 @@ tc_va_check_derive_image(const struct vlc_gl_interop *interop)
{
msg_Warn(o, "Can't create Image KHR: kernel too old ?");
ret = VLC_EGENERIC;
- goto done;
+ goto done_derive;
}
vaegl_image_destroy(interop, egl_image);
}
-done:
+ ret = VLC_SUCCESS;
+
+done_derive:
if (va_image.image_id != VA_INVALID_ID)
{
if (va_image.buf != VA_INVALID_ID)
vlc_vaapi_ReleaseBufferHandle(o, priv->vadpy, va_image.buf);
vlc_vaapi_DestroyImage(o, priv->vadpy, va_image.image_id);
}
+#endif
+done:
picture_pool_Release(pool);
return ret;
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/706fe761898e111c97f917b4957e1809497432c1
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/706fe761898e111c97f917b4957e1809497432c1
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list