frontends/va: Only use interlaced surfaces when progressive is not supported

There is no good reason to use interlaced surfaces when progressive
is supported and it only creates issues when exporting the surface
or trying to do transcoding.
This allows to remove all workarounds that handled reallocating
from interlaced to progressive because a given operation would not
work for interlaced.

Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32095>
This commit is contained in:
David Rosca 2024-11-12 16:16:43 +01:00 committed by Marge Bot
parent 2abbd361e2
commit c324364f39
3 changed files with 14 additions and 146 deletions

View file

@ -259,19 +259,6 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
unsigned stride = 0;
unsigned offset = 0;
/* This function is used by some programs to test for hardware decoding, but on
* AMD devices, the buffers default to interlaced, which causes this function to fail.
* Some programs expect this function to fail, while others, assume this means
* hardware acceleration is not available and give up without trying the fall-back
* vaCreateImage + vaPutImage
*/
const char *proc = util_get_process_name();
const char *derive_interlaced_allowlist[] = {
"vlc",
"h264encode",
"hevcencode"
};
if (!ctx)
return VA_STATUS_ERROR_INVALID_CONTEXT;
@ -294,22 +281,15 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
}
if (surf->buffer->interlaced) {
for (i = 0; i < ARRAY_SIZE(derive_interlaced_allowlist); i++)
if ((strcmp(derive_interlaced_allowlist[i], proc) == 0))
break;
status = VA_STATUS_ERROR_OPERATION_FAILED;
goto exit_on_error;
}
if (i >= ARRAY_SIZE(derive_interlaced_allowlist) ||
!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE)) {
status = VA_STATUS_ERROR_OPERATION_FAILED;
goto exit_on_error;
}
} else if (util_format_get_num_planes(surf->buffer->buffer_format) >= 2 &&
(!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP) ||
!surf->buffer->contiguous_planes)) {
if (util_format_get_num_planes(surf->buffer->buffer_format) >= 2 &&
(!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
PIPE_VIDEO_CAP_SUPPORTS_CONTIGUOUS_PLANES_MAP) ||
!surf->buffer->contiguous_planes)) {
status = VA_STATUS_ERROR_OPERATION_FAILED;
goto exit_on_error;
}
@ -397,54 +377,8 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
img->offsets[1] = 0;
}
if (surf->buffer->interlaced) {
struct u_rect src_rect, dst_rect;
struct pipe_video_buffer new_template;
new_template = surf->templat;
new_template.interlaced = false;
new_buffer = drv->pipe->create_video_buffer(drv->pipe, &new_template);
/* not all devices support non-interlaced buffers */
if (!new_buffer) {
status = VA_STATUS_ERROR_OPERATION_FAILED;
goto exit_on_error;
}
/* convert the interlaced to the progressive */
src_rect.x0 = dst_rect.x0 = 0;
src_rect.x1 = dst_rect.x1 = surf->templat.width;
src_rect.y0 = dst_rect.y0 = 0;
src_rect.y1 = dst_rect.y1 = surf->templat.height;
vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
surf->buffer, new_buffer,
&src_rect, &dst_rect,
VL_COMPOSITOR_WEAVE);
/* recalculate the values now that we have a new surface */
memset(buf_resources, 0, sizeof(buf_resources));
new_buffer->get_resources(new_buffer, buf_resources);
if (screen->resource_get_info) {
screen->resource_get_info(screen, buf_resources[0], &img->pitches[0],
&img->offsets[0]);
if (!img->pitches[0])
img->offsets[0] = 0;
screen->resource_get_info(screen, buf_resources[1], &img->pitches[1],
&img->offsets[1]);
if (!img->pitches[1])
img->offsets[1] = 0;
}
w = align(new_buffer->width, 2);
h = align(new_buffer->height, 2);
}
img->num_planes = 2;
if(screen->resource_get_info) {
/* Note this block might use h and w from the recalculated size if it entered
the interlaced branch above.*/
img->data_size = (img->pitches[0] * h) + (img->pitches[1] * h / 2);
} else {
/* Use stride = w as default if screen->resource_get_info was not available */

View file

@ -357,7 +357,6 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
struct pipe_surface **dst_surfaces;
struct u_rect src_rect;
struct u_rect dst_rect;
bool scale = false;
bool grab = false;
unsigned i, src_num_planes, dst_num_planes;
@ -375,29 +374,10 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
!src->interlaced)
grab = true;
if ((src->width != dst->width || src->height != dst->height) &&
(src->interlaced && dst->interlaced))
scale = true;
src_surfaces = src->get_surfaces(src);
if (!src_surfaces || !src_surfaces[0])
return VA_STATUS_ERROR_INVALID_SURFACE;
if (scale || (src->interlaced != dst->interlaced && dst->interlaced)) {
vlVaSurface *surf;
surf = handle_table_get(drv->htab, context->target_id);
if (!surf)
return VA_STATUS_ERROR_INVALID_SURFACE;
surf->templat.interlaced = false;
dst->destroy(dst);
if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
dst = context->target = surf->buffer;
}
dst_surfaces = dst->get_surfaces(dst);
if (!dst_surfaces || !dst_surfaces[0])
return VA_STATUS_ERROR_INVALID_SURFACE;
@ -433,15 +413,6 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
return VA_STATUS_SUCCESS;
}
if (src->interlaced != dst->interlaced) {
deinterlace = deinterlace ? deinterlace : VL_COMPOSITOR_WEAVE;
vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
src, dst, &src_rect, &dst_rect,
deinterlace);
return VA_STATUS_SUCCESS;
}
for (i = 0; i < VL_MAX_SURFACES; ++i) {
struct pipe_surface *from = src_surfaces[i];
struct pipe_blit_info blit;
@ -547,7 +518,7 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
VARectangle def_src_region, def_dst_region;
const VARectangle *src_region, *dst_region;
VAProcPipelineParameterBuffer *param;
struct pipe_video_buffer *src, *dst;
struct pipe_video_buffer *src;
vlVaSurface *src_surface, *dst_surface;
unsigned i;
struct pipe_screen *pscreen;
@ -618,21 +589,6 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
}
src = src_surface->buffer;
dst = dst_surface->buffer;
/* convert the destination buffer to progressive if we're deinterlacing
otherwise we might end up deinterlacing twice */
if (param->num_filters && dst->interlaced) {
vlVaSurface *surf;
surf = dst_surface;
surf->templat.interlaced = false;
dst->destroy(dst);
if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
dst = context->target = surf->buffer;
}
for (i = 0; i < param->num_filters; i++) {
vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]);

View file

@ -1250,9 +1250,9 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
if (!modifiers)
templat.interlaced =
pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
PIPE_VIDEO_CAP_PREFERS_INTERLACED);
!pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE);
#ifndef _WIN32
if (expected_fourcc != VA_FOURCC_NV12 || memory_attribute || prime_desc)
@ -1650,30 +1650,8 @@ vlVaExportSurfaceHandle(VADriverContextP ctx,
}
if (surf->buffer->interlaced) {
struct pipe_video_buffer *interlaced = surf->buffer;
struct u_rect src_rect, dst_rect;
surf->templat.interlaced = false;
ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0);
if (ret != VA_STATUS_SUCCESS) {
mtx_unlock(&drv->mutex);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
src_rect.x0 = dst_rect.x0 = 0;
src_rect.y0 = dst_rect.y0 = 0;
src_rect.x1 = dst_rect.x1 = surf->templat.width;
src_rect.y1 = dst_rect.y1 = surf->templat.height;
vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
interlaced, surf->buffer,
&src_rect, &dst_rect,
VL_COMPOSITOR_WEAVE);
if (interlaced->codec && interlaced->codec->update_decoder_target)
interlaced->codec->update_decoder_target(interlaced->codec, interlaced, surf->buffer);
interlaced->destroy(interlaced);
mtx_unlock(&drv->mutex);
return VA_STATUS_ERROR_INVALID_SURFACE;
}
surfaces = surf->buffer->get_surfaces(surf->buffer);