[Mesa-dev] [PATCH 7/8] st/va: add NV12 -> NV12 post processing

Christian König deathsimple at vodafone.de
Fri Dec 11 04:33:51 PST 2015


From: Christian König <christian.koenig at amd.com>

Usefull for mpv and GStreamer.

Signed-off-by: Indrajit-kumar Das <Indrajit-kumar.Das at amd.com>
Signed-off-by: Christian König <christian.koenig at amd.com>
---
 src/gallium/state_trackers/va/picture.c  |  10 +-
 src/gallium/state_trackers/va/postproc.c | 152 ++++++++++++++++++++++++-------
 2 files changed, 125 insertions(+), 37 deletions(-)

diff --git a/src/gallium/state_trackers/va/picture.c b/src/gallium/state_trackers/va/picture.c
index 7b30bf8..b5e1ebc 100644
--- a/src/gallium/state_trackers/va/picture.c
+++ b/src/gallium/state_trackers/va/picture.c
@@ -63,11 +63,11 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende
    if (!context->decoder) {
       /* VPP */
       if (context->templat.profile == PIPE_VIDEO_PROFILE_UNKNOWN &&
-         ((context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM  &&
-           context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM  &&
-           context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM  &&
-           context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM) ||
-           context->target->interlaced))
+          context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM &&
+          context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM &&
+          context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM &&
+          context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM &&
+          context->target->buffer_format != PIPE_FORMAT_NV12)
          return VA_STATUS_ERROR_UNIMPLEMENTED;
 
       return VA_STATUS_SUCCESS;
diff --git a/src/gallium/state_trackers/va/postproc.c b/src/gallium/state_trackers/va/postproc.c
index 1ee3587..c6cfd3a 100644
--- a/src/gallium/state_trackers/va/postproc.c
+++ b/src/gallium/state_trackers/va/postproc.c
@@ -27,6 +27,8 @@
 
 #include "util/u_handle_table.h"
 
+#include "vl/vl_defines.h"
+
 #include "va_private.h"
 
 static const VARectangle *
@@ -44,43 +46,21 @@ vlVaRegionDefault(const VARectangle *region, struct pipe_video_buffer *buf,
    return def;
 }
 
-VAStatus
-vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
+static VAStatus
+vlVaPostProcCompositor(vlVaDriver *drv, vlVaContext *context,
+                       const VARectangle *src_region,
+                       const VARectangle *dst_region,
+                       struct pipe_video_buffer *src,
+                       struct pipe_video_buffer *dst)
 {
-   VARectangle def_src_region, def_dst_region;
-   const VARectangle *src_region, *dst_region;
+   struct pipe_surface **surfaces;
    struct u_rect src_rect;
    struct u_rect dst_rect;
-   vlVaSurface *src_surface;
-   VAProcPipelineParameterBuffer *pipeline_param;
-   struct pipe_surface **surfaces;
-   struct pipe_surface *psurf;
-
-   if (!drv || !context)
-      return VA_STATUS_ERROR_INVALID_CONTEXT;
-
-   if (!buf || !buf->data)
-      return VA_STATUS_ERROR_INVALID_BUFFER;
-
-   if (!context->target)
-      return VA_STATUS_ERROR_INVALID_SURFACE;
-
-   pipeline_param = (VAProcPipelineParameterBuffer *)buf->data;
-
-   src_surface = handle_table_get(drv->htab, pipeline_param->surface);
-   if (!src_surface || !src_surface->buffer)
-      return VA_STATUS_ERROR_INVALID_SURFACE;
-
-   surfaces = context->target->get_surfaces(context->target);
 
+   surfaces = dst->get_surfaces(dst);
    if (!surfaces || !surfaces[0])
       return VA_STATUS_ERROR_INVALID_SURFACE;
 
-   psurf = surfaces[0];
-
-   src_region = vlVaRegionDefault(pipeline_param->surface_region, src_surface->buffer, &def_src_region);
-   dst_region = vlVaRegionDefault(pipeline_param->output_region, context->target, &def_dst_region);
-
    src_rect.x0 = src_region->x;
    src_rect.y0 = src_region->y;
    src_rect.x1 = src_region->x + src_region->width;
@@ -92,11 +72,119 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
    dst_rect.y1 = dst_region->y + dst_region->height;
 
    vl_compositor_clear_layers(&drv->cstate);
-   vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src_surface->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE);
+   vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src,
+				  &src_rect, NULL, VL_COMPOSITOR_WEAVE);
    vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
-   vl_compositor_render(&drv->cstate, &drv->compositor, psurf, NULL, false);
+   vl_compositor_render(&drv->cstate, &drv->compositor, surfaces[0], NULL, false);
+
+   return VA_STATUS_SUCCESS;
+}
+
+static void vlVaBoxAdjust(struct pipe_video_buffer *buf, unsigned idx,
+                          struct pipe_box *box)
+{
+   if (buf->interlaced) {
+      box->y /= 2;
+      box->height /= 2;
+   }
+   if (idx > buf->interlaced) {
+      /* we assume chroma format 420 here */
+      box->x /= 2;
+      box->y /= 2;
+      box->width /= 2;
+      box->height /= 2;
+   }
+}
+
+static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
+                                 const VARectangle *src_region,
+                                 const VARectangle *dst_region,
+                                 struct pipe_video_buffer *src,
+                                 struct pipe_video_buffer *dst)
+{
+   struct pipe_surface **src_surfaces;
+   struct pipe_surface **dst_surfaces;
+   unsigned i;
+
+   if (src->interlaced != dst->interlaced)
+      return VA_STATUS_ERROR_INVALID_SURFACE;
+
+   src_surfaces = src->get_surfaces(src);
+   if (!src_surfaces || !src_surfaces[0])
+      return VA_STATUS_ERROR_INVALID_SURFACE;
+
+   dst_surfaces = dst->get_surfaces(dst);
+   if (!dst_surfaces || !dst_surfaces[0])
+      return VA_STATUS_ERROR_INVALID_SURFACE;
+
+   for (i = 0; i < VL_MAX_SURFACES; ++i) {
+      struct pipe_blit_info blit;
+
+      if (!src_surfaces[i] || !dst_surfaces[i])
+         continue;
+
+      memset(&blit, 0, sizeof(blit));
+      blit.src.resource = src_surfaces[i]->texture;
+      blit.src.format = src_surfaces[i]->format;
+      blit.src.level = 0;
+      blit.src.box.x = src_region->x;
+      blit.src.box.y = src_region->y;
+      blit.src.box.z = src_surfaces[i]->u.tex.first_layer;
+      blit.src.box.width = src_region->width;
+      blit.src.box.height = src_region->height;
+      blit.src.box.depth = 1;
+      vlVaBoxAdjust(src, i, &blit.src.box);
+
+      blit.dst.resource = dst_surfaces[i]->texture;
+      blit.dst.format = dst_surfaces[i]->format;
+      blit.dst.level = 0;
+      blit.dst.box.x = dst_region->x;
+      blit.dst.box.y = dst_region->y;
+      blit.dst.box.z = dst_surfaces[i]->u.tex.first_layer;
+      blit.dst.box.width = dst_region->width;
+      blit.dst.box.height = dst_region->height;
+      blit.dst.box.depth = 1;
+      vlVaBoxAdjust(dst, i, &blit.dst.box);
+
+      blit.mask = PIPE_MASK_RGBA;
+      blit.filter = PIPE_TEX_MIPFILTER_LINEAR;
+
+      drv->pipe->blit(drv->pipe, &blit);
+   }
 
    return VA_STATUS_SUCCESS;
 }
 
+VAStatus
+vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
+{
+   VARectangle def_src_region, def_dst_region;
+   const VARectangle *src_region, *dst_region;
+   VAProcPipelineParameterBuffer *param;
+   vlVaSurface *src_surface;
+
+   if (!drv || !context)
+      return VA_STATUS_ERROR_INVALID_CONTEXT;
+
+   if (!buf || !buf->data)
+      return VA_STATUS_ERROR_INVALID_BUFFER;
 
+   if (!context->target)
+      return VA_STATUS_ERROR_INVALID_SURFACE;
+
+   param = buf->data;
+
+   src_surface = handle_table_get(drv->htab, param->surface);
+   if (!src_surface || !src_surface->buffer)
+      return VA_STATUS_ERROR_INVALID_SURFACE;
+
+   src_region = vlVaRegionDefault(param->surface_region, src_surface->buffer, &def_src_region);
+   dst_region = vlVaRegionDefault(param->output_region, context->target, &def_dst_region);
+
+   if (context->target->buffer_format != PIPE_FORMAT_NV12)
+      return vlVaPostProcCompositor(drv, context, src_region, dst_region,
+                                    src_surface->buffer, context->target);
+   else
+      return vlVaPostProcBlit(drv, context, src_region, dst_region,
+                              src_surface->buffer, context->target);
+}
-- 
2.5.0



More information about the mesa-dev mailing list