frontends: va: fix vaQuerySurfaceStatus and vaSyncSurface for decode
Use the new get_decoder_fence vfunc to implement vaQuerySurfaceStatus and vaSyncSurface in the va state tracker. A pointer to the surface's fence is passed to the codecs before the end_frame vfunc and the codec is responsible for allocating a fence on command stream submission. This fence is then queried on vaQuerySurfaceStatus and waited on in vaSyncSurface. Notably both functions were not implemented as per the VA-API docs for PIPE_VIDEO_ENTRYPOINT_BITSTREAM. Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> Reviewed-by: Sil Vilerino <sivileri@microsoft.com> Reviewed-by: Leo Liu <leo.liu@amd.com> Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20133>
This commit is contained in:
committed by
Marge Bot
parent
3a0d1f9fdc
commit
4246bcfc7a
@@ -1024,6 +1024,8 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
|
||||
surf->feedback = feedback;
|
||||
surf->coded_buf = coded_buf;
|
||||
coded_buf->associated_encode_input_surf = context->target_id;
|
||||
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
|
||||
context->desc.base.fence = &surf->fence;
|
||||
}
|
||||
|
||||
context->decoder->end_frame(context->decoder, context->target, &context->desc.base);
|
||||
|
||||
@@ -114,8 +114,14 @@ vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)
|
||||
return VA_STATUS_ERROR_INVALID_SURFACE;
|
||||
}
|
||||
|
||||
if (!surf->feedback) {
|
||||
// No outstanding operation: nothing to do.
|
||||
/* This is checked before getting the context below as
|
||||
* surf->ctx is only set in begin_frame
|
||||
* and not when the surface is created
|
||||
* Some apps try to sync/map the surface right after creation and
|
||||
* would get VA_STATUS_ERROR_INVALID_CONTEXT
|
||||
*/
|
||||
if ((!surf->feedback) && (!surf->fence)) {
|
||||
// No outstanding encode/decode operation: nothing to do.
|
||||
mtx_unlock(&drv->mutex);
|
||||
return VA_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -126,7 +132,18 @@ vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)
|
||||
return VA_STATUS_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
|
||||
if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
|
||||
int ret = 0;
|
||||
|
||||
if (context->decoder->get_decoder_fence)
|
||||
ret = context->decoder->get_decoder_fence(context->decoder,
|
||||
surf->fence,
|
||||
PIPE_DEFAULT_DECODER_FEEDBACK_TIMEOUT_NS);
|
||||
|
||||
mtx_unlock(&drv->mutex);
|
||||
// Assume that the GPU has hung otherwise.
|
||||
return ret ? VA_STATUS_SUCCESS : VA_STATUS_ERROR_TIMEDOUT;
|
||||
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
|
||||
if (!drv->pipe->screen->get_video_param(drv->pipe->screen,
|
||||
context->decoder->profile,
|
||||
context->decoder->entrypoint,
|
||||
@@ -176,6 +193,19 @@ vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfac
|
||||
return VA_STATUS_ERROR_INVALID_SURFACE;
|
||||
}
|
||||
|
||||
/* This is checked before getting the context below as
|
||||
* surf->ctx is only set in begin_frame
|
||||
* and not when the surface is created
|
||||
* Some apps try to sync/map the surface right after creation and
|
||||
* would get VA_STATUS_ERROR_INVALID_CONTEXT
|
||||
*/
|
||||
if ((!surf->feedback) && (!surf->fence)) {
|
||||
// No outstanding encode/decode operation: nothing to do.
|
||||
*status = VASurfaceReady;
|
||||
mtx_unlock(&drv->mutex);
|
||||
return VA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
context = handle_table_get(drv->htab, surf->ctx);
|
||||
if (!context) {
|
||||
mtx_unlock(&drv->mutex);
|
||||
@@ -187,6 +217,25 @@ vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfac
|
||||
*status=VASurfaceReady;
|
||||
else
|
||||
*status=VASurfaceRendering;
|
||||
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
|
||||
int ret = 0;
|
||||
|
||||
if (context->decoder->get_decoder_fence)
|
||||
ret = context->decoder->get_decoder_fence(context->decoder,
|
||||
surf->fence, 0);
|
||||
|
||||
if (ret)
|
||||
*status = VASurfaceReady;
|
||||
else
|
||||
/* An approach could be to just tell the client that this is not
|
||||
* implemented, but this breaks other code. Compromise by at least
|
||||
* conservatively setting the status to VASurfaceRendering if we can't
|
||||
* query the hardware. Note that we _must_ set the status here, otherwise
|
||||
* it comes out of the function unchanged. As we are returning
|
||||
* VA_STATUS_SUCCESS, the client would be within his/her rights to use a
|
||||
* potentially uninitialized/invalid status value unknowingly.
|
||||
*/
|
||||
*status = VASurfaceRendering;
|
||||
}
|
||||
|
||||
mtx_unlock(&drv->mutex);
|
||||
|
||||
@@ -374,6 +374,7 @@ typedef struct {
|
||||
bool force_flushed;
|
||||
struct pipe_video_buffer *obsolete_buf;
|
||||
enum pipe_format encoder_format;
|
||||
struct pipe_fence_handle *fence;
|
||||
} vlVaSurface;
|
||||
|
||||
typedef struct {
|
||||
|
||||
Reference in New Issue
Block a user