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:
committed by
Christian König
parent
802ba6f865
commit
e7ed3963ed
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user