summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/va
diff options
context:
space:
mode:
authorMark Thompson <[email protected]>2017-10-01 18:40:45 +0100
committerLeo Liu <[email protected]>2017-10-07 10:15:14 -0400
commitc4ed39f85b1ebd062eaa51880fcc79cfbcb4e5c3 (patch)
tree1c6afdcf2bda376e0325b6b71efe9804f7c4b666 /src/gallium/state_trackers/va
parent52b73caaf40e79c90a105ec6d349abb3398e3c6b (diff)
st/va: Implement vaExportSurfaceHandle()
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 <[email protected]> Acked-by: Christian König <[email protected]> Acked-and-Tested-by: Leo Liu <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers/va')
-rw-r--r--src/gallium/state_trackers/va/context.c5
-rw-r--r--src/gallium/state_trackers/va/surface.c148
-rw-r--r--src/gallium/state_trackers/va/va_private.h1
3 files changed, 153 insertions, 1 deletions
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 <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,
@@ -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);