diff --git a/src/gallium/frontends/va/image.c b/src/gallium/frontends/va/image.c index 39768a030b7..22713776d10 100644 --- a/src/gallium/frontends/va/image.c +++ b/src/gallium/frontends/va/image.c @@ -548,6 +548,7 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, ret = vlVaPostProcCompositor(drv, &src_rect, &dst_rect, surf->buffer, tmp_surf.buffer, VL_COMPOSITOR_NONE, &proc); + drv->pipe->flush(drv->pipe, NULL, 0); if (ret != VA_STATUS_SUCCESS) { tmp_surf.buffer->destroy(tmp_surf.buffer); mtx_unlock(&drv->mutex); @@ -715,14 +716,14 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, ret = vlVaPostProcCompositor(drv, &src_rect, &dst_rect, tmp_surf.buffer, surf->buffer, VL_COMPOSITOR_NONE, &proc); + vlVaSurfaceFlush(drv, surf); tmp_surf.buffer->destroy(tmp_surf.buffer); mtx_unlock(&drv->mutex); return ret; } vlVaUploadImage(drv, surf, img_buf, vaimage); - - drv->pipe->flush(drv->pipe, NULL, 0); + vlVaSurfaceFlush(drv, surf); mtx_unlock(&drv->mutex); return VA_STATUS_SUCCESS; diff --git a/src/gallium/frontends/va/postproc.c b/src/gallium/frontends/va/postproc.c index b9802213fbb..9ff64fd4476 100644 --- a/src/gallium/frontends/va/postproc.c +++ b/src/gallium/frontends/va/postproc.c @@ -232,7 +232,6 @@ vlVaPostProcCompositor(vlVaDriver *drv, drv->cstate.chroma_location = VL_COMPOSITOR_LOCATION_NONE; - drv->pipe->flush(drv->pipe, NULL, 0); return VA_STATUS_SUCCESS; } @@ -572,6 +571,8 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex return VA_STATUS_SUCCESS; } - return vlVaPostProcCompositor(drv, src_region, dst_region, - src, context->target, deinterlace, param); + VAStatus ret = vlVaPostProcCompositor(drv, src_region, dst_region, + src, context->target, deinterlace, param); + vlVaSurfaceFlush(drv, dst_surface); + return ret; } diff --git a/src/gallium/frontends/va/surface.c b/src/gallium/frontends/va/surface.c index 006421537f5..f93e4f0660c 100644 --- a/src/gallium/frontends/va/surface.c +++ b/src/gallium/frontends/va/surface.c @@ -119,6 +119,8 @@ vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_sur } if (surf->buffer) surf->buffer->destroy(surf->buffer); + if (surf->pipe_fence) + drv->pipe->screen->fence_reference(drv->pipe->screen, &surf->pipe_fence, NULL); if (surf->ctx) { assert(_mesa_set_search(surf->ctx->surfaces, surf)); _mesa_set_remove_key(surf->ctx->surfaces, surf); @@ -176,13 +178,22 @@ _vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target, uint64_t timeo fence = surf->fence; } + if (surf->pipe_fence) { + struct pipe_screen *pscreen = drv->pipe->screen; + if (!pscreen->fence_finish(pscreen, NULL, surf->pipe_fence, timeout_ns)) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_TIMEDOUT; + } + pscreen->fence_reference(pscreen, &surf->pipe_fence, NULL); + } + /* 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->buffer || !fence) { + if (!surf->fence) { // No outstanding encode/decode operation: nothing to do. mtx_unlock(&drv->mutex); return VA_STATUS_SUCCESS; @@ -441,7 +452,7 @@ vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short s /* flush before calling flush_frontbuffer so that rendering is flushed * to back buffer so the texture can be copied in flush_frontbuffer */ - drv->pipe->flush(drv->pipe, NULL, 0); + vlVaSurfaceFlush(drv, surf); screen->flush_frontbuffer(screen, drv->pipe, tex, 0, 0, vscreen->get_private(vscreen), 0, NULL); @@ -996,7 +1007,7 @@ vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, surfaces[i]->width, surfaces[i]->height, false); } - drv->pipe->flush(drv->pipe, NULL, 0); + vlVaSurfaceFlush(drv, surface); } return VA_STATUS_SUCCESS; @@ -1013,6 +1024,13 @@ vlVaGetSurfaceBuffer(vlVaDriver *drv, vlVaSurface *surface) return surface->buffer; } +void +vlVaSurfaceFlush(vlVaDriver *drv, vlVaSurface *surf) +{ + drv->pipe->flush(drv->pipe, &surf->pipe_fence, + drv->has_external_handles ? 0 : PIPE_FLUSH_ASYNC); +} + static int rt_format_to_fourcc(uint32_t format) { diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h index 6eb09b1248e..c163318dc2d 100644 --- a/src/gallium/frontends/va/va_private.h +++ b/src/gallium/frontends/va/va_private.h @@ -448,7 +448,8 @@ typedef struct vlVaSurface { vlVaContext *ctx; vlVaBuffer *coded_buf; bool full_range; - struct pipe_fence_handle *fence; + struct pipe_fence_handle *fence; /* pipe_video_codec fence */ + struct pipe_fence_handle *pipe_fence; /* pipe_context fence */ struct vlVaSurface *efc_surface; /* input surface for EFC */ bool is_dpb; } vlVaSurface; @@ -569,6 +570,7 @@ VAStatus vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContex VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, struct pipe_video_buffer *templat, const uint64_t *modifiers, unsigned int modifiers_count); struct pipe_video_buffer *vlVaGetSurfaceBuffer(vlVaDriver *drv, vlVaSurface *surface); +void vlVaSurfaceFlush(vlVaDriver *drv, vlVaSurface *surf); void vlVaAddRawHeader(struct util_dynarray *headers, uint8_t type, uint32_t size, uint8_t *buf, bool is_slice, uint32_t emulation_bytes_start); void vlVaGetBufferFeedback(vlVaBuffer *buf);