diff --git a/src/gallium/frontends/va/context.c b/src/gallium/frontends/va/context.c index adb32703f28..b206d2a647d 100644 --- a/src/gallium/frontends/va/context.c +++ b/src/gallium/frontends/va/context.c @@ -400,6 +400,10 @@ vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id) vlVaSurface *surf = (vlVaSurface *)entry->key; assert(surf->ctx == context); surf->ctx = NULL; + if (surf->fence && context->decoder && context->decoder->destroy_fence) { + context->decoder->destroy_fence(context->decoder, surf->fence); + surf->fence = NULL; + } } _mesa_set_destroy(context->surfaces, NULL); diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c index 952560bb391..4fc6eeb7ff3 100644 --- a/src/gallium/frontends/va/picture.c +++ b/src/gallium/frontends/va/picture.c @@ -39,7 +39,7 @@ #include "va_private.h" static void -vlVaSetSurfaceContext(vlVaSurface *surf, vlVaContext *context) +vlVaSetSurfaceContext(vlVaDriver *drv, vlVaSurface *surf, vlVaContext *context) { if (surf->ctx == context) return; @@ -47,6 +47,23 @@ vlVaSetSurfaceContext(vlVaSurface *surf, vlVaContext *context) if (surf->ctx) { assert(_mesa_set_search(surf->ctx->surfaces, surf)); _mesa_set_remove_key(surf->ctx->surfaces, surf); + + /* Only drivers supporting PIPE_VIDEO_ENTRYPOINT_PROCESSING will create + * decoder for postproc context and thus be able to wait on and destroy + * the surface fence. On other drivers we need to destroy the fence here + * otherwise vaQuerySurfaceStatus/vaSyncSurface will fail and we'll also + * potentially leak the fence. + */ + if (surf->fence && !context->decoder && + context->templat.entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING && + surf->ctx->decoder && surf->ctx->decoder->destroy_fence && + !drv->pipe->screen->get_video_param(drv->pipe->screen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_PROCESSING, + PIPE_VIDEO_CAP_SUPPORTED)) { + surf->ctx->decoder->destroy_fence(surf->ctx->decoder, surf->fence); + surf->fence = NULL; + } } surf->ctx = context; @@ -85,7 +102,7 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende return VA_STATUS_ERROR_INVALID_SURFACE; context->target_id = render_target; - vlVaSetSurfaceContext(surf, context); + vlVaSetSurfaceContext(drv, surf, context); context->target = surf->buffer; context->mjpeg.sampling_factor = 0; @@ -993,7 +1010,7 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) } if (apply_av1_fg) { - vlVaSetSurfaceContext(surf, context); + vlVaSetSurfaceContext(drv, surf, context); *out_target = surf->buffer; } diff --git a/src/gallium/frontends/va/surface.c b/src/gallium/frontends/va/surface.c index 62f3adc3add..baddba39bbc 100644 --- a/src/gallium/frontends/va/surface.c +++ b/src/gallium/frontends/va/surface.c @@ -89,6 +89,8 @@ vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_sur if (surf->ctx) { assert(_mesa_set_search(surf->ctx->surfaces, surf)); _mesa_set_remove_key(surf->ctx->surfaces, surf); + if (surf->fence && surf->ctx->decoder && surf->ctx->decoder->destroy_fence) + surf->ctx->decoder->destroy_fence(surf->ctx->decoder, surf->fence); } util_dynarray_fini(&surf->subpics); FREE(surf); diff --git a/src/gallium/include/pipe/p_video_codec.h b/src/gallium/include/pipe/p_video_codec.h index 694302940d7..085dbae3f50 100644 --- a/src/gallium/include/pipe/p_video_codec.h +++ b/src/gallium/include/pipe/p_video_codec.h @@ -148,6 +148,12 @@ struct pipe_video_codec struct pipe_fence_handle *fence, uint64_t timeout); + /** + * Destroy fence. + */ + void (*destroy_fence)(struct pipe_video_codec *codec, + struct pipe_fence_handle *fence); + /** * Update target buffer address. *