Path: blob/21.2-virgl/src/gallium/frontends/va/buffer.c
4561 views
/**************************************************************************1*2* Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.3* Copyright 2014 Advanced Micro Devices, Inc.4* All Rights Reserved.5*6* Permission is hereby granted, free of charge, to any person obtaining a7* copy of this software and associated documentation files (the8* "Software"), to deal in the Software without restriction, including9* without limitation the rights to use, copy, modify, merge, publish,10* distribute, sub license, and/or sell copies of the Software, and to11* permit persons to whom the Software is furnished to do so, subject to12* the following conditions:13*14* The above copyright notice and this permission notice (including the15* next paragraph) shall be included in all copies or substantial portions16* of the Software.17*18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS19* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF20* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.21* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR22* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,23* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE24* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.25*26**************************************************************************/2728#include "pipe/p_screen.h"29#include "frontend/drm_driver.h"30#include "util/u_memory.h"31#include "util/u_handle_table.h"32#include "util/u_transfer.h"33#include "vl/vl_winsys.h"3435#include "va_private.h"3637VAStatus38vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type,39unsigned int size, unsigned int num_elements, void *data,40VABufferID *buf_id)41{42vlVaDriver *drv;43vlVaBuffer *buf;4445if (!ctx)46return VA_STATUS_ERROR_INVALID_CONTEXT;4748buf = CALLOC(1, sizeof(vlVaBuffer));49if (!buf)50return VA_STATUS_ERROR_ALLOCATION_FAILED;5152buf->type = type;53buf->size = size;54buf->num_elements = num_elements;55buf->data = MALLOC(size * num_elements);5657if (!buf->data) {58FREE(buf);59return VA_STATUS_ERROR_ALLOCATION_FAILED;60}6162if (data)63memcpy(buf->data, data, size * num_elements);6465drv = VL_VA_DRIVER(ctx);66mtx_lock(&drv->mutex);67*buf_id = handle_table_add(drv->htab, buf);68mtx_unlock(&drv->mutex);6970return VA_STATUS_SUCCESS;71}7273VAStatus74vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id,75unsigned int num_elements)76{77vlVaDriver *drv;78vlVaBuffer *buf;7980if (!ctx)81return VA_STATUS_ERROR_INVALID_CONTEXT;8283drv = VL_VA_DRIVER(ctx);84mtx_lock(&drv->mutex);85buf = handle_table_get(drv->htab, buf_id);86mtx_unlock(&drv->mutex);87if (!buf)88return VA_STATUS_ERROR_INVALID_BUFFER;8990if (buf->derived_surface.resource)91return VA_STATUS_ERROR_INVALID_BUFFER;9293buf->data = REALLOC(buf->data, buf->size * buf->num_elements,94buf->size * num_elements);95buf->num_elements = num_elements;9697if (!buf->data)98return VA_STATUS_ERROR_ALLOCATION_FAILED;99100return VA_STATUS_SUCCESS;101}102103VAStatus104vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)105{106vlVaDriver *drv;107vlVaBuffer *buf;108109if (!ctx)110return VA_STATUS_ERROR_INVALID_CONTEXT;111112drv = VL_VA_DRIVER(ctx);113if (!drv)114return VA_STATUS_ERROR_INVALID_CONTEXT;115116if (!pbuff)117return VA_STATUS_ERROR_INVALID_PARAMETER;118119mtx_lock(&drv->mutex);120buf = handle_table_get(drv->htab, buf_id);121if (!buf || buf->export_refcount > 0) {122mtx_unlock(&drv->mutex);123return VA_STATUS_ERROR_INVALID_BUFFER;124}125126if (buf->derived_surface.resource) {127struct pipe_resource *resource;128struct pipe_box box = {};129130resource = buf->derived_surface.resource;131box.width = resource->width0;132box.height = resource->height0;133box.depth = resource->depth0;134*pbuff = drv->pipe->buffer_map(drv->pipe, resource, 0, PIPE_MAP_WRITE,135&box, &buf->derived_surface.transfer);136mtx_unlock(&drv->mutex);137138if (!buf->derived_surface.transfer || !*pbuff)139return VA_STATUS_ERROR_INVALID_BUFFER;140141if (buf->type == VAEncCodedBufferType) {142((VACodedBufferSegment*)buf->data)->buf = *pbuff;143((VACodedBufferSegment*)buf->data)->size = buf->coded_size;144((VACodedBufferSegment*)buf->data)->next = NULL;145*pbuff = buf->data;146}147} else {148mtx_unlock(&drv->mutex);149*pbuff = buf->data;150}151152return VA_STATUS_SUCCESS;153}154155VAStatus156vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)157{158vlVaDriver *drv;159vlVaBuffer *buf;160161if (!ctx)162return VA_STATUS_ERROR_INVALID_CONTEXT;163164drv = VL_VA_DRIVER(ctx);165if (!drv)166return VA_STATUS_ERROR_INVALID_CONTEXT;167168mtx_lock(&drv->mutex);169buf = handle_table_get(drv->htab, buf_id);170if (!buf || buf->export_refcount > 0) {171mtx_unlock(&drv->mutex);172return VA_STATUS_ERROR_INVALID_BUFFER;173}174175if (buf->derived_surface.resource) {176if (!buf->derived_surface.transfer) {177mtx_unlock(&drv->mutex);178return VA_STATUS_ERROR_INVALID_BUFFER;179}180181pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer);182buf->derived_surface.transfer = NULL;183}184mtx_unlock(&drv->mutex);185186return VA_STATUS_SUCCESS;187}188189VAStatus190vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)191{192vlVaDriver *drv;193vlVaBuffer *buf;194195if (!ctx)196return VA_STATUS_ERROR_INVALID_CONTEXT;197198drv = VL_VA_DRIVER(ctx);199mtx_lock(&drv->mutex);200buf = handle_table_get(drv->htab, buf_id);201if (!buf) {202mtx_unlock(&drv->mutex);203return VA_STATUS_ERROR_INVALID_BUFFER;204}205206if (buf->derived_surface.resource) {207pipe_resource_reference(&buf->derived_surface.resource, NULL);208209if (buf->derived_image_buffer)210buf->derived_image_buffer->destroy(buf->derived_image_buffer);211}212213FREE(buf->data);214FREE(buf);215handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);216mtx_unlock(&drv->mutex);217218return VA_STATUS_SUCCESS;219}220221VAStatus222vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type,223unsigned int *size, unsigned int *num_elements)224{225vlVaDriver *drv;226vlVaBuffer *buf;227228if (!ctx)229return VA_STATUS_ERROR_INVALID_CONTEXT;230231drv = VL_VA_DRIVER(ctx);232mtx_lock(&drv->mutex);233buf = handle_table_get(drv->htab, buf_id);234mtx_unlock(&drv->mutex);235if (!buf)236return VA_STATUS_ERROR_INVALID_BUFFER;237238*type = buf->type;239*size = buf->size;240*num_elements = buf->num_elements;241242return VA_STATUS_SUCCESS;243}244245VAStatus246vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,247VABufferInfo *out_buf_info)248{249vlVaDriver *drv;250uint32_t i;251uint32_t mem_type;252vlVaBuffer *buf ;253struct pipe_screen *screen;254255/* List of supported memory types, in preferred order. */256static const uint32_t mem_types[] = {257VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,2580259};260261if (!ctx)262return VA_STATUS_ERROR_INVALID_CONTEXT;263264drv = VL_VA_DRIVER(ctx);265screen = VL_VA_PSCREEN(ctx);266mtx_lock(&drv->mutex);267buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);268mtx_unlock(&drv->mutex);269270if (!buf)271return VA_STATUS_ERROR_INVALID_BUFFER;272273/* Only VA surface|image like buffers are supported for now .*/274if (buf->type != VAImageBufferType)275return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;276277if (!out_buf_info)278return VA_STATUS_ERROR_INVALID_PARAMETER;279280if (!out_buf_info->mem_type)281mem_type = mem_types[0];282else {283mem_type = 0;284for (i = 0; mem_types[i] != 0; i++) {285if (out_buf_info->mem_type & mem_types[i]) {286mem_type = out_buf_info->mem_type;287break;288}289}290if (!mem_type)291return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;292}293294if (!buf->derived_surface.resource)295return VA_STATUS_ERROR_INVALID_BUFFER;296297if (buf->export_refcount > 0) {298if (buf->export_state.mem_type != mem_type)299return VA_STATUS_ERROR_INVALID_PARAMETER;300} else {301VABufferInfo * const buf_info = &buf->export_state;302303switch (mem_type) {304case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {305struct winsys_handle whandle;306307mtx_lock(&drv->mutex);308drv->pipe->flush(drv->pipe, NULL, 0);309310memset(&whandle, 0, sizeof(whandle));311whandle.type = WINSYS_HANDLE_TYPE_FD;312313if (!screen->resource_get_handle(screen, drv->pipe,314buf->derived_surface.resource,315&whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) {316mtx_unlock(&drv->mutex);317return VA_STATUS_ERROR_INVALID_BUFFER;318}319320mtx_unlock(&drv->mutex);321322buf_info->handle = (intptr_t)whandle.handle;323break;324}325default:326return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;327}328329buf_info->type = buf->type;330buf_info->mem_type = mem_type;331buf_info->mem_size = buf->num_elements * buf->size;332}333334buf->export_refcount++;335336*out_buf_info = buf->export_state;337338return VA_STATUS_SUCCESS;339}340341VAStatus342vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)343{344vlVaDriver *drv;345vlVaBuffer *buf;346347if (!ctx)348return VA_STATUS_ERROR_INVALID_CONTEXT;349350drv = VL_VA_DRIVER(ctx);351mtx_lock(&drv->mutex);352buf = handle_table_get(drv->htab, buf_id);353mtx_unlock(&drv->mutex);354355if (!buf)356return VA_STATUS_ERROR_INVALID_BUFFER;357358if (buf->export_refcount == 0)359return VA_STATUS_ERROR_INVALID_BUFFER;360361if (--buf->export_refcount == 0) {362VABufferInfo * const buf_info = &buf->export_state;363364switch (buf_info->mem_type) {365case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:366close((intptr_t)buf_info->handle);367break;368default:369return VA_STATUS_ERROR_INVALID_BUFFER;370}371372buf_info->mem_type = 0;373}374375return VA_STATUS_SUCCESS;376}377378379