Mesa (main): va: Add support for VPP rotation, flip, alpha blend, crop, scaling
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu Jul 21 23:05:21 UTC 2022
Module: Mesa
Branch: main
Commit: 345fd9209267ba5bd205cd87153c74c159d2e51d
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=345fd9209267ba5bd205cd87153c74c159d2e51d
Author: Sil Vilerino <sivileri at microsoft.com>
Date: Fri Jul 15 08:01:41 2022 -0400
va: Add support for VPP rotation, flip, alpha blend, crop, scaling
Reviewed-by: Ruijing Dong <ruijing.dong at amd.com>
Reviewed-by: Jesse Natalie <jenatali at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17557>
---
src/gallium/frontends/va/context.c | 5 +-
src/gallium/frontends/va/picture.c | 14 ++++++
src/gallium/frontends/va/postproc.c | 88 +++++++++++++++++++++++++++++++++++
src/gallium/frontends/va/surface.c | 67 +++++++++++++++++++++++++-
src/gallium/frontends/va/va_private.h | 2 +
5 files changed, 174 insertions(+), 2 deletions(-)
diff --git a/src/gallium/frontends/va/context.c b/src/gallium/frontends/va/context.c
index f59276e9c53..b205d173ba0 100644
--- a/src/gallium/frontends/va/context.c
+++ b/src/gallium/frontends/va/context.c
@@ -249,7 +249,10 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width,
if (!context)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
- if (is_vpp) {
+ if (is_vpp && !drv->vscreen->pscreen->get_video_param(drv->vscreen->pscreen,
+ PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_SUPPORTED)) {
context->decoder = NULL;
} else {
if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c
index 6c13217e285..bcd23b3ae8a 100644
--- a/src/gallium/frontends/va/picture.c
+++ b/src/gallium/frontends/va/picture.c
@@ -86,6 +86,14 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende
context->target->buffer_format != PIPE_FORMAT_P016)
return VA_STATUS_ERROR_UNIMPLEMENTED;
+ if (drv->pipe->screen->get_video_param(drv->pipe->screen,
+ PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_SUPPORTED)) {
+ context->needs_begin_frame = true;
+ context->vpp_needs_flush_on_endpic = true;
+ }
+
return VA_STATUS_SUCCESS;
}
@@ -822,6 +830,12 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE &&
u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC)
context->desc.h265enc.frame_num++;
+ else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING &&
+ context->vpp_needs_flush_on_endpic) {
+ context->decoder->flush(context->decoder);
+ context->vpp_needs_flush_on_endpic = false;
+ }
+
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 44c35886f76..17513df4d2b 100644
--- a/src/gallium/frontends/va/postproc.c
+++ b/src/gallium/frontends/va/postproc.c
@@ -111,6 +111,74 @@ static void vlVaGetBox(struct pipe_video_buffer *buf, unsigned idx,
box->height = height;
}
+static VAStatus vlVaVidEngineBlit(vlVaDriver *drv, vlVaContext *context,
+ const VARectangle *src_region,
+ const VARectangle *dst_region,
+ struct pipe_video_buffer *src,
+ struct pipe_video_buffer *dst,
+ enum vl_compositor_deinterlace deinterlace,
+ VAProcPipelineParameterBuffer* param)
+{
+ if (deinterlace != VL_COMPOSITOR_NONE)
+ return VA_STATUS_ERROR_UNIMPLEMENTED;
+
+ if (src->buffer_format != PIPE_FORMAT_NV12 ||
+ dst->buffer_format != PIPE_FORMAT_NV12)
+ return VA_STATUS_ERROR_UNIMPLEMENTED;
+
+ struct u_rect src_rect;
+ struct u_rect dst_rect;
+
+ src_rect.x0 = src_region->x;
+ src_rect.y0 = src_region->y;
+ src_rect.x1 = src_region->x + src_region->width;
+ src_rect.y1 = src_region->y + src_region->height;
+
+ dst_rect.x0 = dst_region->x;
+ dst_rect.y0 = dst_region->y;
+ dst_rect.x1 = dst_region->x + dst_region->width;
+ dst_rect.y1 = dst_region->y + dst_region->height;
+
+ context->desc.vidproc.base.input_format = src->buffer_format;
+ context->desc.vidproc.base.output_format = dst->buffer_format;
+
+ context->desc.vidproc.src_region = src_rect;
+ context->desc.vidproc.dst_region = dst_rect;
+
+ if (param->rotation_state == VA_ROTATION_NONE)
+ context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ORIENTATION_DEFAULT;
+ else if (param->rotation_state == VA_ROTATION_90)
+ context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_90;
+ else if (param->rotation_state == VA_ROTATION_180)
+ context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_180;
+ else if (param->rotation_state == VA_ROTATION_270)
+ context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_270;
+
+ if (param->mirror_state == VA_MIRROR_HORIZONTAL)
+ context->desc.vidproc.orientation |= PIPE_VIDEO_VPP_FLIP_HORIZONTAL;
+ if (param->mirror_state == VA_MIRROR_VERTICAL)
+ context->desc.vidproc.orientation |= PIPE_VIDEO_VPP_FLIP_VERTICAL;
+
+ memset(&context->desc.vidproc.blend, 0, sizeof(context->desc.vidproc.blend));
+ context->desc.vidproc.blend.mode = PIPE_VIDEO_VPP_BLEND_MODE_NONE;
+ if (param->blend_state != NULL) {
+ if (param->blend_state->flags & VA_BLEND_GLOBAL_ALPHA) {
+ context->desc.vidproc.blend.mode = PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA;
+ context->desc.vidproc.blend.global_alpha = param->blend_state->global_alpha;
+ }
+ }
+
+ if (context->needs_begin_frame) {
+ context->decoder->begin_frame(context->decoder, dst,
+ &context->desc.base);
+ context->needs_begin_frame = false;
+ }
+ context->decoder->process_frame(context->decoder, src, &context->desc.vidproc);
+ context->vpp_needs_flush_on_endpic = true;
+
+ return VA_STATUS_SUCCESS;
+}
+
static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
const VARectangle *src_region,
const VARectangle *dst_region,
@@ -402,6 +470,26 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region);
dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region);
+ /* If the driver supports video engine post proc, attempt to do that
+ * if it fails, fallback to the other existing implementations below
+ */
+ if (pscreen->get_video_param(pscreen,
+ PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_SUPPORTED)) {
+ if (!context->decoder) {
+ context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat);
+ if (!context->decoder)
+ return VA_STATUS_ERROR_ALLOCATION_FAILED;
+ }
+
+ /* Perform VPBlit, if fail, fallback to other implementations below */
+ if (VA_STATUS_SUCCESS == vlVaVidEngineBlit(drv, context, src_region, dst_region,
+ src, context->target, deinterlace, param))
+ return VA_STATUS_SUCCESS;
+ }
+
+ /* Try other post proc implementations */
if (context->target->buffer_format != PIPE_FORMAT_NV12 &&
context->target->buffer_format != PIPE_FORMAT_P010 &&
context->target->buffer_format != PIPE_FORMAT_P016)
diff --git a/src/gallium/frontends/va/surface.c b/src/gallium/frontends/va/surface.c
index 47e916652ca..4441c0b1908 100755
--- a/src/gallium/frontends/va/surface.c
+++ b/src/gallium/frontends/va/surface.c
@@ -523,7 +523,12 @@ vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id,
}
#endif
- if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
+ /* If VPP supported entry, use the max dimensions cap values, if not fallback to this below */
+ if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_PROCESSING ||
+ pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_SUPPORTED))
+ {
attribs[i].type = VASurfaceAttribMaxWidth;
attribs[i].value.type = VAGenericValueTypeInteger;
attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
@@ -1146,6 +1151,66 @@ vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context,
pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards);
pipeline_cap->output_color_standards = vpp_output_color_standards;
+ struct pipe_screen *pscreen = VL_VA_PSCREEN(ctx);
+ uint32_t pipe_orientation_flags = pscreen->get_video_param(pscreen,
+ PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_ORIENTATION_MODES);
+
+ pipeline_cap->rotation_flags = VA_ROTATION_NONE;
+ if(pipe_orientation_flags & PIPE_VIDEO_VPP_ROTATION_90)
+ pipeline_cap->rotation_flags |= (1 << VA_ROTATION_90);
+ if(pipe_orientation_flags & PIPE_VIDEO_VPP_ROTATION_180)
+ pipeline_cap->rotation_flags |= (1 << VA_ROTATION_180);
+ if(pipe_orientation_flags & PIPE_VIDEO_VPP_ROTATION_270)
+ pipeline_cap->rotation_flags |= (1 << VA_ROTATION_270);
+
+ pipeline_cap->mirror_flags = VA_MIRROR_NONE;
+ if(pipe_orientation_flags & PIPE_VIDEO_VPP_FLIP_HORIZONTAL)
+ pipeline_cap->mirror_flags |= VA_MIRROR_HORIZONTAL;
+ if(pipe_orientation_flags & PIPE_VIDEO_VPP_FLIP_VERTICAL)
+ pipeline_cap->mirror_flags |= VA_MIRROR_VERTICAL;
+
+ pipeline_cap->max_input_width = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_MAX_INPUT_WIDTH);
+
+ pipeline_cap->max_input_height = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_MAX_INPUT_HEIGHT);
+
+ pipeline_cap->min_input_width = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_MIN_INPUT_WIDTH);
+
+ pipeline_cap->min_input_height = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_MIN_INPUT_HEIGHT);
+
+ pipeline_cap->max_output_width = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_WIDTH);
+
+ pipeline_cap->max_output_height = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_MAX_OUTPUT_HEIGHT);
+
+ pipeline_cap->min_output_width = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_WIDTH);
+
+ pipeline_cap->min_output_height = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_MIN_OUTPUT_HEIGHT);
+
+ uint32_t pipe_blend_modes = pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+ PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+ PIPE_VIDEO_CAP_VPP_BLEND_MODES);
+
+ pipeline_cap->blend_flags = 0;
+ if (pipe_blend_modes & PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA)
+ pipeline_cap->blend_flags |= VA_BLEND_GLOBAL_ALPHA;
+
for (i = 0; i < num_filters; i++) {
vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]);
VAProcFilterParameterBufferBase *filter;
diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h
index 149cfa2d961..15222ac4d73 100755
--- a/src/gallium/frontends/va/va_private.h
+++ b/src/gallium/frontends/va/va_private.h
@@ -293,6 +293,7 @@ typedef struct {
struct pipe_av1_picture_desc av1;
struct pipe_h264_enc_picture_desc h264enc;
struct pipe_h265_enc_picture_desc h265enc;
+ struct pipe_vpp_desc vidproc;
} desc;
struct {
@@ -317,6 +318,7 @@ typedef struct {
bool first_single_submitted;
int gop_coeff;
bool needs_begin_frame;
+ bool vpp_needs_flush_on_endpic;
void *blit_cs;
int packed_header_type;
} vlVaContext;
More information about the mesa-commit
mailing list