frontends/va: Skip processing buffers already converted with EFC
authorDavid Rosca <nowrep@gmail.com>
Sat, 15 Jul 2023 12:46:53 +0000 (14:46 +0200)
committerMarge Bot <emma+marge@anholt.net>
Tue, 18 Jul 2023 20:09:42 +0000 (20:09 +0000)
Since the EFC conversion reallocates the dst buffer with new format,
any subsequent VA postproc calls on the same surface will fall back
to vl_compositor conversion.

This is the case in ffmpeg where the postproc filter output
buffers are reused instead of allocated for each frame.

Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24170>

src/gallium/frontends/va/postproc.c

index 5a4ad0f..ccb290f 100644 (file)
@@ -368,6 +368,27 @@ vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
    return context->deint->video_buffer;
 }
 
+static bool can_convert_with_efc(vlVaSurface *src, vlVaSurface *dst)
+{
+   enum pipe_format src_format, dst_format;
+
+   if (src->buffer->interlaced)
+      return false;
+
+   src_format = src->buffer->buffer_format;
+
+   if (src_format != PIPE_FORMAT_B8G8R8A8_UNORM &&
+       src_format != PIPE_FORMAT_R8G8B8A8_UNORM &&
+       src_format != PIPE_FORMAT_B8G8R8X8_UNORM &&
+       src_format != PIPE_FORMAT_R8G8B8X8_UNORM)
+      return false;
+
+   dst_format = dst->encoder_format != PIPE_FORMAT_NONE ?
+      dst->encoder_format : dst->buffer->buffer_format;
+
+   return dst_format == PIPE_FORMAT_NV12;
+}
+
 VAStatus
 vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
 {
@@ -400,28 +421,25 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
 
    pscreen = drv->vscreen->pscreen;
 
-   if (src_surface->buffer->buffer_format != dst_surface->buffer->buffer_format &&
-       !src_surface->buffer->interlaced &&
-       (dst_surface->buffer->buffer_format == PIPE_FORMAT_NV12 ||
-        dst_surface->buffer->buffer_format == PIPE_FORMAT_P010 ||
-        dst_surface->buffer->buffer_format == PIPE_FORMAT_P016) &&
+   if (can_convert_with_efc(src_surface, dst_surface) &&
        pscreen->get_video_param(pscreen,
                                 PIPE_VIDEO_PROFILE_UNKNOWN,
                                 PIPE_VIDEO_ENTRYPOINT_ENCODE,
                                 PIPE_VIDEO_CAP_EFC_SUPPORTED)) {
 
-      // EFC will convert the buffer to a format the encoder accepts
-      dst_surface->encoder_format = dst_surface->buffer->buffer_format;
+      vlVaSurface *surf = dst_surface;
 
-      vlVaSurface *surf;
+      // EFC will convert the buffer to a format the encoder accepts
+      if (src_surface->buffer->buffer_format != surf->buffer->buffer_format) {
+         surf->encoder_format = surf->buffer->buffer_format;
 
-      surf = handle_table_get(drv->htab, context->target_id);
-      surf->templat.interlaced = src_surface->templat.interlaced;
-      surf->templat.buffer_format = src_surface->templat.buffer_format;
-      surf->buffer->destroy(surf->buffer);
+         surf->templat.interlaced = src_surface->templat.interlaced;
+         surf->templat.buffer_format = src_surface->templat.buffer_format;
+         surf->buffer->destroy(surf->buffer);
 
-      if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
-         return VA_STATUS_ERROR_ALLOCATION_FAILED;
+         if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
+      }
 
       pipe_resource_reference(&(((struct vl_video_buffer *)(surf->buffer))->resources[0]), ((struct vl_video_buffer *)(src_surface->buffer))->resources[0]);
       context->target = surf->buffer;