tu: Implement fallback linear staging blit for CopyImage
[mesa.git] / src / gallium / state_trackers / va / postproc.c
index d3eafe9b53b85c36ab9f1dc04917e6b4887935eb..1845883284468747cfe6132805e1df6d17b7c037 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "util/u_handle_table.h"
 #include "util/u_memory.h"
+#include "util/u_compute.h"
 
 #include "vl/vl_defines.h"
 #include "vl/vl_video_buffer.h"
@@ -96,9 +97,11 @@ static void vlVaGetBox(struct pipe_video_buffer *buf, unsigned idx,
    width = region->width;
    height = region->height;
 
-   vl_video_buffer_adjust_size(&x, &y, plane, buf->chroma_format,
+   vl_video_buffer_adjust_size(&x, &y, plane,
+                               pipe_format_to_chroma_format(buf->buffer_format),
                                buf->interlaced);
-   vl_video_buffer_adjust_size(&width, &height, plane, buf->chroma_format,
+   vl_video_buffer_adjust_size(&width, &height, plane,
+                               pipe_format_to_chroma_format(buf->buffer_format),
                                buf->interlaced);
 
    box->x = region->x < 0 ? -x : x;
@@ -119,10 +122,13 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
    struct u_rect src_rect;
    struct u_rect dst_rect;
    bool scale = false;
+   bool grab = false;
    unsigned i;
 
-   if (src->interlaced != dst->interlaced && dst->interlaced)
-      return VA_STATUS_ERROR_INVALID_SURFACE;
+   if ((src->buffer_format == PIPE_FORMAT_B8G8R8A8_UNORM ||
+        src->buffer_format == PIPE_FORMAT_B8G8R8X8_UNORM) &&
+       !src->interlaced)
+      grab = true;
 
    if ((src->width != dst->width || src->height != dst->height) &&
        (src->interlaced && dst->interlaced))
@@ -132,7 +138,7 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
    if (!src_surfaces || !src_surfaces[0])
       return VA_STATUS_ERROR_INVALID_SURFACE;
 
-   if (scale) {
+   if (scale || (src->interlaced != dst->interlaced && dst->interlaced)) {
       vlVaSurface *surf;
 
       surf = handle_table_get(drv->htab, context->target_id);
@@ -159,6 +165,14 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
    dst_rect.x1 = dst_region->x + dst_region->width;
    dst_rect.y1 = dst_region->y + dst_region->height;
 
+   if (grab) {
+      vl_compositor_convert_rgb_to_yuv(&drv->cstate, &drv->compositor, 0,
+                                       ((struct vl_video_buffer *)src)->resources[0],
+                                       dst, &src_rect, &dst_rect);
+
+      return VA_STATUS_SUCCESS;
+   }
+
    if (src->interlaced != dst->interlaced) {
       vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
                                    src, dst, &src_rect, &dst_rect,
@@ -206,7 +220,11 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
       blit.mask = PIPE_MASK_RGBA;
       blit.filter = PIPE_TEX_MIPFILTER_LINEAR;
 
-      drv->pipe->blit(drv->pipe, &blit);
+      if (drv->pipe->screen->get_param(drv->pipe->screen,
+                                       PIPE_CAP_PREFER_COMPUTE_FOR_MULTIMEDIA))
+         util_compute_blit(drv->pipe, &blit, &context->blit_cs);
+      else
+         drv->pipe->blit(drv->pipe, &blit);
    }
 
    // TODO: figure out why this is necessary for DMA-buf sharing
@@ -334,6 +352,7 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
    dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region);
 
    if (context->target->buffer_format != PIPE_FORMAT_NV12 &&
+       context->target->buffer_format != PIPE_FORMAT_P010 &&
        context->target->buffer_format != PIPE_FORMAT_P016)
       return vlVaPostProcCompositor(drv, context, src_region, dst_region,
                                     src, context->target, deinterlace);