frontends/va: Fix locking in vlVaDeriveImage

The mutex needs to be locked before accessing the handle table.
After 64ca0fd2f2 ("frontends/va: Allocate surface buffers on demand")
the issue is now much more likely to happen and can be reproduced when
transcoding using ffmpeg.

Cc: mesa-stable
Reviewed-By: Sil Vilerino <sivileri@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30935>
This commit is contained in:
David Rosca
2024-08-30 09:33:49 +02:00
committed by Marge Bot
parent 5879eaac18
commit fccf31c231

View File

@@ -248,7 +248,7 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
vlVaDriver *drv; vlVaDriver *drv;
vlVaSurface *surf; vlVaSurface *surf;
vlVaBuffer *img_buf; vlVaBuffer *img_buf;
VAImage *img; VAImage *img = NULL;
VAStatus status; VAStatus status;
struct pipe_screen *screen; struct pipe_screen *screen;
struct pipe_resource *buf_resources[VL_NUM_COMPONENTS]; struct pipe_resource *buf_resources[VL_NUM_COMPONENTS];
@@ -285,10 +285,13 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
if (!screen) if (!screen)
return VA_STATUS_ERROR_INVALID_CONTEXT; return VA_STATUS_ERROR_INVALID_CONTEXT;
mtx_lock(&drv->mutex);
surf = handle_table_get(drv->htab, surface); surf = handle_table_get(drv->htab, surface);
vlVaGetSurfaceBuffer(drv, surf); vlVaGetSurfaceBuffer(drv, surf);
if (!surf || !surf->buffer) if (!surf || !surf->buffer) {
return VA_STATUS_ERROR_INVALID_SURFACE; status = VA_STATUS_ERROR_INVALID_SURFACE;
goto exit_on_error;
}
if (surf->buffer->interlaced) { if (surf->buffer->interlaced) {
for (i = 0; i < ARRAY_SIZE(derive_interlaced_allowlist); i++) for (i = 0; i < ARRAY_SIZE(derive_interlaced_allowlist); i++)
@@ -298,25 +301,32 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
if (i >= ARRAY_SIZE(derive_interlaced_allowlist) || if (i >= ARRAY_SIZE(derive_interlaced_allowlist) ||
!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN, !screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE)) PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE)) {
return VA_STATUS_ERROR_OPERATION_FAILED; status = VA_STATUS_ERROR_OPERATION_FAILED;
goto exit_on_error;
}
} else if (util_format_get_num_planes(surf->buffer->buffer_format) >= 2 && } else if (util_format_get_num_planes(surf->buffer->buffer_format) >= 2 &&
(!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN, (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP) || PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP) ||
!surf->buffer->contiguous_planes)) { !surf->buffer->contiguous_planes)) {
return VA_STATUS_ERROR_OPERATION_FAILED; status = VA_STATUS_ERROR_OPERATION_FAILED;
goto exit_on_error;
} }
memset(buf_resources, 0, sizeof(buf_resources)); memset(buf_resources, 0, sizeof(buf_resources));
surf->buffer->get_resources(surf->buffer, buf_resources); surf->buffer->get_resources(surf->buffer, buf_resources);
if (!buf_resources[0]) if (!buf_resources[0]) {
return VA_STATUS_ERROR_ALLOCATION_FAILED; status = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto exit_on_error;
}
img = CALLOC(1, sizeof(VAImage)); img = CALLOC(1, sizeof(VAImage));
if (!img) if (!img) {
return VA_STATUS_ERROR_ALLOCATION_FAILED; status = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto exit_on_error;
}
img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format);
img->buf = VA_INVALID_ID; img->buf = VA_INVALID_ID;
@@ -336,7 +346,6 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
} }
} }
mtx_lock(&drv->mutex);
if (screen->resource_get_info) { if (screen->resource_get_info) {
screen->resource_get_info(screen, buf_resources[0], &stride, screen->resource_get_info(screen, buf_resources[0], &stride,
&offset); &offset);