This is a new interface in libva2 to support wider use-cases of passing surfaces to external APIs. In particular, this allows export of NV12 and P010 surfaces.
Signed-off-by: Mark Thompson <s...@jkqxz.net> --- This implements a new interface I am proposing for libva2, which will allow export to work properly with Mesa - see <https://github.com/01org/libva/pull/85>. I have it working for GPU-only playback in mpv through EGL (previously this always required a download/upload step). See <https://github.com/fhvwy/mpv/commit/0a505f9ff5f43ecb40abb99096204d1efbe47346> for a tree containing changes to make this work. Some outstanding things to consider: * I've defined the API to include the size of each object. This is because some import APIs require it - libva itself does, though the more obvious case is Beignet (<https://cgit.freedesktop.org/beignet/tree/include/CL/cl_intel.h#n136>). I'm not currently filling it because I don't see any way to get the actual object size through existing interfaces. Thoughts? * I haven't implemented the composite-object export form at all. I don't currently know of any use case for it - the Intel use-case is for passing NV12 scanout buffers to KMS, but this doesn't appear to be a thing in amdgpu (scanout is 32-bit RGB only). * It interacts badly with the interlacing feature. It seems to work correctly for 10-bit but not for 8-bit video? I have reapplied the VAAPI_DISABLE_INTERLACE patch locally to make it work for me in all cases, though I believe there is more work in progress in this area which can hopefully clarify the issue. Thanks, - Mark src/gallium/state_trackers/va/context.c | 3 +- src/gallium/state_trackers/va/surface.c | 118 +++++++++++++++++++++++++++++ src/gallium/state_trackers/va/va_private.h | 1 + 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c index f2cb37aa22..2794e5c733 100644 --- a/src/gallium/state_trackers/va/context.c +++ b/src/gallium/state_trackers/va/context.c @@ -88,7 +88,8 @@ static struct VADriverVTable vtable = &vlVaCreateSurfaces2, &vlVaQuerySurfaceAttributes, &vlVaAcquireBufferHandle, - &vlVaReleaseBufferHandle + &vlVaReleaseBufferHandle, + &vlVaExportSurfaceHandle }; static struct VADriverVTableVPP vtable_vpp = diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c index 67773cf76a..0fb0180377 100644 --- a/src/gallium/state_trackers/va/surface.c +++ b/src/gallium/state_trackers/va/surface.c @@ -44,6 +44,7 @@ #include "va_private.h" #include <va/va_drmcommon.h> +#include <drm-uapi/drm_fourcc.h> static const enum pipe_format vpp_surface_formats[] = { PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM, @@ -892,3 +893,120 @@ vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, return VA_STATUS_SUCCESS; } + +VAStatus vlVaExportSurfaceHandle(VADriverContextP ctx, + VASurfaceID surface_id, + uint32_t mem_type, + uint32_t flags, + void *descriptor) +{ + vlVaDriver *drv; + vlVaSurface *surf; + struct pipe_surface **surfaces; + struct pipe_screen *screen; + VAStatus ret; + unsigned int usage; + int i, p; + + VADRMPRIMESurfaceDescriptor *desc = descriptor; + + if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) + return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; + if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) + return VA_STATUS_ERROR_INVALID_SURFACE; + + drv = VL_VA_DRIVER(ctx); + screen = VL_VA_PSCREEN(ctx); + mtx_lock(&drv->mutex); + + surf = handle_table_get(drv->htab, surface_id); + if (!surf || !surf->buffer) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_INVALID_SURFACE; + } + + surfaces = surf->buffer->get_surfaces(surf->buffer); + + usage = 0; + if (flags & VA_EXPORT_SURFACE_READ_ONLY) + usage |= PIPE_HANDLE_USAGE_READ; + if (flags & VA_EXPORT_SURFACE_WRITE_ONLY) + usage |= PIPE_HANDLE_USAGE_WRITE; + + desc->fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); + + for (p = 0; p < VL_MAX_SURFACES; p++) { + struct winsys_handle whandle; + struct pipe_resource *resource; + uint32_t drm_format; + + if (!surfaces[p]) + break; + + resource = surfaces[p]->texture; + + switch (resource->format) { + case PIPE_FORMAT_R8_UNORM: + drm_format = DRM_FORMAT_R8; + break; + case PIPE_FORMAT_R8G8_UNORM: + drm_format = DRM_FORMAT_GR88; + break; + case PIPE_FORMAT_R16_UNORM: + drm_format = DRM_FORMAT_R16; + break; + case PIPE_FORMAT_R16G16_UNORM: + drm_format = DRM_FORMAT_GR1616; + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + drm_format = DRM_FORMAT_ARGB8888; + break; + case PIPE_FORMAT_R8G8B8A8_UNORM: + drm_format = DRM_FORMAT_ABGR8888; + break; + case PIPE_FORMAT_B8G8R8X8_UNORM: + drm_format = DRM_FORMAT_XRGB8888; + break; + case PIPE_FORMAT_R8G8B8X8_UNORM: + drm_format = DRM_FORMAT_XBGR8888; + break; + default: + ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; + goto fail; + } + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_FD; + + if (!screen->resource_get_handle(screen, drv->pipe, resource, + &whandle, usage)) { + ret = VA_STATUS_ERROR_INVALID_SURFACE; + goto fail; + } + + desc->objects[p].fd = (int)whandle.handle; + desc->objects[p].size = 0; + desc->objects[p].drm_format_modifier = whandle.modifier; + + desc->layers[p].drm_format = drm_format; + desc->layers[p].num_planes = 1; + desc->layers[p].object_index[0] = p; + desc->layers[p].offset[0] = whandle.offset; + desc->layers[p].pitch[0] = whandle.stride; + } + + desc->num_objects = p; + desc->num_layers = p; + + mtx_unlock(&drv->mutex); + + return VA_STATUS_SUCCESS; + +fail: + for (i = 0; i < p; i++) + close(desc->objects[i].fd); + + mtx_unlock(&drv->mutex); + + return ret; +} diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h index 5b1b832bb0..4f447008a6 100644 --- a/src/gallium/state_trackers/va/va_private.h +++ b/src/gallium/state_trackers/va/va_private.h @@ -394,6 +394,7 @@ VAStatus vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config, VAS VAStatus vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, VABufferInfo *out_buf_info); VAStatus vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id); +VAStatus vlVaExportSurfaceHandle(VADriverContextP ctx, VASurfaceID surface_id, uint32_t mem_type, uint32_t flags, void *descriptor); VAStatus vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, VAProcFilterType *filters, unsigned int *num_filters); -- 2.11.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev