diff options
Diffstat (limited to 'src/gallium/state_trackers/va/buffer.c')
-rw-r--r-- | src/gallium/state_trackers/va/buffer.c | 136 |
1 files changed, 135 insertions, 1 deletions
diff --git a/src/gallium/state_trackers/va/buffer.c b/src/gallium/state_trackers/va/buffer.c index d3a7c5d6dc4..71a65037757 100644 --- a/src/gallium/state_trackers/va/buffer.c +++ b/src/gallium/state_trackers/va/buffer.c @@ -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; +} |