From c4ed39f85b1ebd062eaa51880fcc79cfbcb4e5c3 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 1 Oct 2017 18:40:45 +0100 Subject: st/va: Implement vaExportSurfaceHandle() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. v2: Convert surfaces to progressive before exporting them (Christian). v3: Set destination rectangle to match source when converting (Leo). Add guards to allow building with libva1. Signed-off-by: Mark Thompson Acked-by: Christian König Acked-and-Tested-by: Leo Liu --- src/gallium/state_trackers/va/context.c | 5 +- src/gallium/state_trackers/va/surface.c | 148 +++++++++++++++++++++++++++++ src/gallium/state_trackers/va/va_private.h | 1 + 3 files changed, 153 insertions(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/va') diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c index f2cb37aa22a..1207499a788 100644 --- a/src/gallium/state_trackers/va/context.c +++ b/src/gallium/state_trackers/va/context.c @@ -88,7 +88,10 @@ static struct VADriverVTable vtable = &vlVaCreateSurfaces2, &vlVaQuerySurfaceAttributes, &vlVaAcquireBufferHandle, - &vlVaReleaseBufferHandle + &vlVaReleaseBufferHandle, +#if VA_CHECK_VERSION(1, 0, 0) + &vlVaExportSurfaceHandle, +#endif }; static struct VADriverVTableVPP vtable_vpp = diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c index 4c2f4b5452a..76e562717a6 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 +#include static const enum pipe_format vpp_surface_formats[] = { PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM, @@ -901,3 +902,150 @@ vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, return VA_STATUS_SUCCESS; } + +#if VA_CHECK_VERSION(1, 0, 0) +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; + } + + 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); + 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); + + interlaced->destroy(interlaced); + } + + 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); + desc->width = surf->buffer->width; + desc->height = surf->buffer->height; + + 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; +} +#endif diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h index 61712ce913e..46f6ba66f2a 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); -- cgit v1.2.3