Commit a7638e9b authored by Thong Thai's avatar Thong Thai
Browse files

WIP: gallium: Derive image from interlaced buffers in certain cases

Only allow vaDriveImage to derive and convert interlaced buffers to progressive buffers in some cases (VLC media player) while keeping the existing functionality as a default (for programs such as Kodi)

Closes: mesa/mesa#1428
parent 4c35bc7e
Pipeline #120807 passed with stages
in 13 minutes and 48 seconds
......@@ -6,5 +6,6 @@ OPT_BOOL(debug_disassembly, false, "Report shader disassembly as part of driver
OPT_BOOL(halt_shaders, false, "Halt shaders at the start (will hang)")
OPT_BOOL(vs_fetch_always_opencode, false, "Always open code vertex fetches (less efficient, purely for testing)")
OPT_BOOL(prim_restart_tri_strips_only, false, "Only enable primitive restart for triangle strips")
OPT_BOOL(derive_image_interlaced, false, "Convert interlaced buffers to progressive in vaDriveImage")
#undef OPT_BOOL
......@@ -704,6 +704,8 @@ static int si_get_video_param(struct pipe_screen *screen,
default:
return 0;
}
case PIPE_VIDEO_CAP_DERIVE_INTERLACED:
return sscreen->options.derive_image_interlaced;
default:
return 0;
}
......
......@@ -86,7 +86,8 @@ enum pipe_video_cap
PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE = 6,
PIPE_VIDEO_CAP_SUPPORTS_INTERLACED = 7,
PIPE_VIDEO_CAP_MAX_LEVEL = 8,
PIPE_VIDEO_CAP_STACKED_FRAMES = 9
PIPE_VIDEO_CAP_STACKED_FRAMES = 9,
PIPE_VIDEO_CAP_DERIVE_INTERLACED = 10,
};
enum pipe_video_entrypoint
......
......@@ -206,6 +206,7 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
int i;
unsigned stride = 0;
unsigned offset = 0;
bool derive_interlaced = false;
if (!ctx)
return VA_STATUS_ERROR_INVALID_CONTEXT;
......@@ -220,12 +221,17 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
if (!screen)
return VA_STATUS_ERROR_INVALID_CONTEXT;
if (screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_UNKNOWN,
PIPE_VIDEO_CAP_DERIVE_INTERLACED))
derive_interlaced = true;
surf = handle_table_get(drv->htab, surface);
if (!surf || !surf->buffer)
return VA_STATUS_ERROR_INVALID_SURFACE;
if (surf->buffer->interlaced)
if (surf->buffer->interlaced && !derive_interlaced)
return VA_STATUS_ERROR_OPERATION_FAILED;
surfaces = surf->buffer->get_surfaces(surf->buffer);
......@@ -262,11 +268,15 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
offset = 0;
}
img->num_planes = 1;
img->offsets[0] = offset;
switch (img->format.fourcc) {
case VA_FOURCC('U','Y','V','Y'):
case VA_FOURCC('Y','U','Y','V'):
img->pitches[0] = stride > 0 ? stride : w * 2;
assert(img->pitches[0] >= (w * 2));
img->data_size = img->pitches[0] * h;
break;
case VA_FOURCC('B','G','R','A'):
......@@ -275,8 +285,49 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
case VA_FOURCC('R','G','B','X'):
img->pitches[0] = stride > 0 ? stride : w * 4;
assert(img->pitches[0] >= (w * 4));
img->data_size = img->pitches[0] * h;
break;
case VA_FOURCC('N','V','1','2'):
if (surf->buffer->interlaced) {
struct pipe_video_buffer *new_buffer;
struct u_rect src_rect, dst_rect;
surf->templat.interlaced = false;
new_buffer = drv->pipe->create_video_buffer(drv->pipe, &surf->templat);
/* 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);
surf->buffer->destroy(surf->buffer);
surf->buffer = new_buffer;
/* recalculate the values now that we have a new surface */
surfaces = surf->buffer->get_surfaces(surf->buffer);
if (screen->resource_get_info) {
screen->resource_get_info(screen, surfaces[0]->texture, &stride,
&offset);
if (!stride)
offset = 0;
}
w = align(surf->buffer->width, 2);
h = align(surf->buffer->height, 2);
}
img->num_planes = 2;
img->pitches[0] = stride > 0 ? stride : w;
img->pitches[1] = stride > 0 ? stride : w;
img->offsets[1] = (stride > 0 ? stride : w) * h;
img->data_size = (stride > 0 ? stride : w) * h * 3 / 2;
break;
default:
/* VaDeriveImage only supports contiguous planes. But there is now a
more generic api vlVaExportSurfaceHandle. */
......@@ -285,10 +336,6 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
return VA_STATUS_ERROR_OPERATION_FAILED;
}
img->num_planes = 1;
img->offsets[0] = offset;
img->data_size = img->pitches[0] * h;
img_buf = CALLOC(1, sizeof(vlVaBuffer));
if (!img_buf) {
FREE(img);
......
......@@ -560,6 +560,9 @@ TODO: document the other workarounds.
<!-- Helps offscreen tests -->
<option name="mesa_glthread" value="true"/>
</application>
<application name="VLC media player" executable="vlc">
<option name="radeonsi_derive_image_interlaced" value="true" />
</application>
</device>
<device driver="virtio_gpu">
<!-- Some Valve games do a final blit to a BRGA_sRGB surface. On a GLES
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment