st/va: add support to export a surface as dmabuf

I.e. implements:
VaAcquireBufferHandle
VaReleaseBufferHandle
for memory of type VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME

And apply relatives change to:
vlVaMapBuffer
vlVaUnMapBuffer
vlVaDestroyBuffer

Implementation inspired from cgit.freedesktop.org/vaapi/intel-driver

Tested with gstreamer-vaapi with nouveau driver.

Signed-off-by: Julien Isorce <j.isorce@samsung.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
Julien Isorce
2015-10-30 11:42:53 +00:00
committed by Christian König
parent 802ba6f865
commit e7ed3963ed
3 changed files with 144 additions and 2 deletions
+135 -1
View File
@@ -27,6 +27,7 @@
**************************************************************************/
#include "pipe/p_screen.h"
#include "state_tracker/drm_driver.h"
#include "util/u_memory.h"
#include "util/u_handle_table.h"
#include "util/u_transfer.h"
@@ -112,6 +113,9 @@ vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)
if (!buf)
return VA_STATUS_ERROR_INVALID_BUFFER;
if (buf->export_refcount > 0)
return VA_STATUS_ERROR_INVALID_BUFFER;
if (buf->derived_surface.resource) {
*pbuff = pipe_buffer_map(drv->pipe, buf->derived_surface.resource,
PIPE_TRANSFER_WRITE,
@@ -144,6 +148,9 @@ vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
if (!buf)
return VA_STATUS_ERROR_INVALID_BUFFER;
if (buf->export_refcount > 0)
return VA_STATUS_ERROR_INVALID_BUFFER;
if (buf->derived_surface.resource) {
if (!buf->derived_surface.transfer)
return VA_STATUS_ERROR_INVALID_BUFFER;
@@ -167,8 +174,12 @@ vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
if (!buf)
return VA_STATUS_ERROR_INVALID_BUFFER;
if (buf->derived_surface.resource)
if (buf->derived_surface.resource) {
if (buf->export_refcount > 0)
return VA_STATUS_ERROR_INVALID_BUFFER;
pipe_resource_reference(&buf->derived_surface.resource, NULL);
}
FREE(buf->data);
FREE(buf);
@@ -196,3 +207,126 @@ vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type,
return VA_STATUS_SUCCESS;
}
VAStatus
vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
VABufferInfo *out_buf_info)
{
uint32_t i;
uint32_t mem_type;
vlVaBuffer *buf ;
struct pipe_screen *screen;
/* List of supported memory types, in preferred order. */
static const uint32_t mem_types[] = {
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
0
};
if (!ctx)
return VA_STATUS_ERROR_INVALID_CONTEXT;
buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
if (!buf)
return VA_STATUS_ERROR_INVALID_BUFFER;
/* Only VA surface|image like buffers are supported for now .*/
if (buf->type != VAImageBufferType)
return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
if (!out_buf_info)
return VA_STATUS_ERROR_INVALID_PARAMETER;
if (!out_buf_info->mem_type)
mem_type = mem_types[0];
else {
mem_type = 0;
for (i = 0; mem_types[i] != 0; i++) {
if (out_buf_info->mem_type & mem_types[i]) {
mem_type = out_buf_info->mem_type;
break;
}
}
if (!mem_type)
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
}
if (!buf->derived_surface.resource)
return VA_STATUS_ERROR_INVALID_BUFFER;
screen = VL_VA_PSCREEN(ctx);
if (buf->derived_surface.fence) {
screen->fence_finish(screen, buf->derived_surface.fence, PIPE_TIMEOUT_INFINITE);
screen->fence_reference(screen, &buf->derived_surface.fence, NULL);
}
if (buf->export_refcount > 0) {
if (buf->export_state.mem_type != mem_type)
return VA_STATUS_ERROR_INVALID_PARAMETER;
} else {
VABufferInfo * const buf_info = &buf->export_state;
switch (mem_type) {
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
struct winsys_handle whandle;
memset(&whandle, 0, sizeof(whandle));
whandle.type = DRM_API_HANDLE_TYPE_FD;
if (!screen->resource_get_handle(screen, buf->derived_surface.resource, &whandle))
return VA_STATUS_ERROR_INVALID_BUFFER;
buf_info->handle = (intptr_t)whandle.handle;
break;
default:
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
}
}
buf_info->type = buf->type;
buf_info->mem_type = mem_type;
buf_info->mem_size = buf->num_elements * buf->size;
}
buf->export_refcount++;
*out_buf_info = buf->export_state;
return VA_STATUS_SUCCESS;
}
VAStatus
vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
{
vlVaBuffer *buf;
if (!ctx)
return VA_STATUS_ERROR_INVALID_CONTEXT;
buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
if (!buf)
return VA_STATUS_ERROR_INVALID_BUFFER;
if (buf->export_refcount == 0)
return VA_STATUS_ERROR_INVALID_BUFFER;
if (--buf->export_refcount == 0) {
VABufferInfo * const buf_info = &buf->export_state;
switch (buf_info->mem_type) {
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
close((intptr_t)buf_info->handle);
break;
default:
return VA_STATUS_ERROR_INVALID_BUFFER;
}
buf_info->mem_type = 0;
}
return VA_STATUS_SUCCESS;
}
+3 -1
View File
@@ -87,7 +87,9 @@ static struct VADriverVTable vtable =
&vlVaUnlockSurface,
NULL, /* DEPRECATED VaGetSurfaceAttributes */
&vlVaCreateSurfaces2,
&vlVaQuerySurfaceAttributes
&vlVaQuerySurfaceAttributes,
&vlVaAcquireBufferHandle,
&vlVaReleaseBufferHandle
};
static struct VADriverVTableVPP vtable_vpp =
@@ -34,6 +34,7 @@
#include <va/va.h>
#include <va/va_backend.h>
#include <va/va_backend_vpp.h>
#include <va/va_drmcommon.h>
#include "pipe/p_video_enums.h"
#include "pipe/p_video_codec.h"
@@ -238,6 +239,8 @@ typedef struct {
struct pipe_transfer *transfer;
struct pipe_fence_handle *fence;
} derived_surface;
unsigned int export_refcount;
VABufferInfo export_state;
} vlVaBuffer;
typedef struct {
@@ -328,6 +331,9 @@ VAStatus vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, unsigned
VAStatus vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config, VASurfaceAttrib *attrib_list,
unsigned int *num_attribs);
VAStatus vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, VABufferInfo *out_buf_info);
VAStatus vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id);
VAStatus vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, VAProcFilterType *filters,
unsigned int *num_filters);
VAStatus vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, VAProcFilterType type,