Home | History | Annotate | Download | only in va
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 Thomas Balling Srensen & Orasanu Lucian.
      4  * Copyright 2014 Advanced Micro Devices, Inc.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sub license, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial portions
     17  * of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     22  * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
     23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  **************************************************************************/
     28 
     29 #include "pipe/p_screen.h"
     30 #include "state_tracker/drm_driver.h"
     31 #include "util/u_memory.h"
     32 #include "util/u_handle_table.h"
     33 #include "util/u_transfer.h"
     34 #include "vl/vl_winsys.h"
     35 
     36 #include "va_private.h"
     37 
     38 VAStatus
     39 vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type,
     40                  unsigned int size, unsigned int num_elements, void *data,
     41                  VABufferID *buf_id)
     42 {
     43    vlVaDriver *drv;
     44    vlVaBuffer *buf;
     45 
     46    if (!ctx)
     47       return VA_STATUS_ERROR_INVALID_CONTEXT;
     48 
     49    buf = CALLOC(1, sizeof(vlVaBuffer));
     50    if (!buf)
     51       return VA_STATUS_ERROR_ALLOCATION_FAILED;
     52 
     53    buf->type = type;
     54    buf->size = size;
     55    buf->num_elements = num_elements;
     56    buf->data = MALLOC(size * num_elements);
     57 
     58    if (!buf->data) {
     59       FREE(buf);
     60       return VA_STATUS_ERROR_ALLOCATION_FAILED;
     61    }
     62 
     63    if (data)
     64       memcpy(buf->data, data, size * num_elements);
     65 
     66    drv = VL_VA_DRIVER(ctx);
     67    mtx_lock(&drv->mutex);
     68    *buf_id = handle_table_add(drv->htab, buf);
     69    mtx_unlock(&drv->mutex);
     70 
     71    return VA_STATUS_SUCCESS;
     72 }
     73 
     74 VAStatus
     75 vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id,
     76                          unsigned int num_elements)
     77 {
     78    vlVaDriver *drv;
     79    vlVaBuffer *buf;
     80 
     81    if (!ctx)
     82       return VA_STATUS_ERROR_INVALID_CONTEXT;
     83 
     84    drv = VL_VA_DRIVER(ctx);
     85    mtx_lock(&drv->mutex);
     86    buf = handle_table_get(drv->htab, buf_id);
     87    mtx_unlock(&drv->mutex);
     88    if (!buf)
     89       return VA_STATUS_ERROR_INVALID_BUFFER;
     90 
     91    if (buf->derived_surface.resource)
     92       return VA_STATUS_ERROR_INVALID_BUFFER;
     93 
     94    buf->data = REALLOC(buf->data, buf->size * buf->num_elements,
     95                        buf->size * num_elements);
     96    buf->num_elements = num_elements;
     97 
     98    if (!buf->data)
     99       return VA_STATUS_ERROR_ALLOCATION_FAILED;
    100 
    101    return VA_STATUS_SUCCESS;
    102 }
    103 
    104 VAStatus
    105 vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)
    106 {
    107    vlVaDriver *drv;
    108    vlVaBuffer *buf;
    109 
    110    if (!ctx)
    111       return VA_STATUS_ERROR_INVALID_CONTEXT;
    112 
    113    drv = VL_VA_DRIVER(ctx);
    114    if (!drv)
    115       return VA_STATUS_ERROR_INVALID_CONTEXT;
    116 
    117    if (!pbuff)
    118       return VA_STATUS_ERROR_INVALID_PARAMETER;
    119 
    120    mtx_lock(&drv->mutex);
    121    buf = handle_table_get(drv->htab, buf_id);
    122    if (!buf || buf->export_refcount > 0) {
    123       mtx_unlock(&drv->mutex);
    124       return VA_STATUS_ERROR_INVALID_BUFFER;
    125    }
    126 
    127    if (buf->derived_surface.resource) {
    128       struct pipe_resource *resource;
    129       struct pipe_box box = {};
    130 
    131       resource = buf->derived_surface.resource;
    132       box.width = resource->width0;
    133       box.height = resource->height0;
    134       box.depth = resource->depth0;
    135       *pbuff = drv->pipe->transfer_map(drv->pipe, resource, 0, PIPE_TRANSFER_WRITE,
    136                                        &box, &buf->derived_surface.transfer);
    137       mtx_unlock(&drv->mutex);
    138 
    139       if (!buf->derived_surface.transfer || !*pbuff)
    140          return VA_STATUS_ERROR_INVALID_BUFFER;
    141 
    142       if (buf->type == VAEncCodedBufferType) {
    143          ((VACodedBufferSegment*)buf->data)->buf = *pbuff;
    144          ((VACodedBufferSegment*)buf->data)->size = buf->coded_size;
    145          ((VACodedBufferSegment*)buf->data)->next = NULL;
    146          *pbuff = buf->data;
    147       }
    148    } else {
    149       mtx_unlock(&drv->mutex);
    150       *pbuff = buf->data;
    151    }
    152 
    153    return VA_STATUS_SUCCESS;
    154 }
    155 
    156 VAStatus
    157 vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
    158 {
    159    vlVaDriver *drv;
    160    vlVaBuffer *buf;
    161 
    162    if (!ctx)
    163       return VA_STATUS_ERROR_INVALID_CONTEXT;
    164 
    165    drv = VL_VA_DRIVER(ctx);
    166    if (!drv)
    167       return VA_STATUS_ERROR_INVALID_CONTEXT;
    168 
    169    mtx_lock(&drv->mutex);
    170    buf = handle_table_get(drv->htab, buf_id);
    171    if (!buf || buf->export_refcount > 0) {
    172       mtx_unlock(&drv->mutex);
    173       return VA_STATUS_ERROR_INVALID_BUFFER;
    174    }
    175 
    176    if (buf->derived_surface.resource) {
    177       if (!buf->derived_surface.transfer) {
    178          mtx_unlock(&drv->mutex);
    179          return VA_STATUS_ERROR_INVALID_BUFFER;
    180       }
    181 
    182       pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer);
    183       buf->derived_surface.transfer = NULL;
    184    }
    185    mtx_unlock(&drv->mutex);
    186 
    187    return VA_STATUS_SUCCESS;
    188 }
    189 
    190 VAStatus
    191 vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
    192 {
    193    vlVaDriver *drv;
    194    vlVaBuffer *buf;
    195 
    196    if (!ctx)
    197       return VA_STATUS_ERROR_INVALID_CONTEXT;
    198 
    199    drv = VL_VA_DRIVER(ctx);
    200    mtx_lock(&drv->mutex);
    201    buf = handle_table_get(drv->htab, buf_id);
    202    if (!buf) {
    203       mtx_unlock(&drv->mutex);
    204       return VA_STATUS_ERROR_INVALID_BUFFER;
    205    }
    206 
    207    if (buf->derived_surface.resource)
    208       pipe_resource_reference(&buf->derived_surface.resource, NULL);
    209 
    210    FREE(buf->data);
    211    FREE(buf);
    212    handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);
    213    mtx_unlock(&drv->mutex);
    214 
    215    return VA_STATUS_SUCCESS;
    216 }
    217 
    218 VAStatus
    219 vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type,
    220                unsigned int *size, unsigned int *num_elements)
    221 {
    222    vlVaDriver *drv;
    223    vlVaBuffer *buf;
    224 
    225    if (!ctx)
    226       return VA_STATUS_ERROR_INVALID_CONTEXT;
    227 
    228    drv = VL_VA_DRIVER(ctx);
    229    mtx_lock(&drv->mutex);
    230    buf = handle_table_get(drv->htab, buf_id);
    231    mtx_unlock(&drv->mutex);
    232    if (!buf)
    233       return VA_STATUS_ERROR_INVALID_BUFFER;
    234 
    235    *type = buf->type;
    236    *size = buf->size;
    237    *num_elements = buf->num_elements;
    238 
    239    return VA_STATUS_SUCCESS;
    240 }
    241 
    242 VAStatus
    243 vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
    244                         VABufferInfo *out_buf_info)
    245 {
    246    vlVaDriver *drv;
    247    uint32_t i;
    248    uint32_t mem_type;
    249    vlVaBuffer *buf ;
    250    struct pipe_screen *screen;
    251 
    252    /* List of supported memory types, in preferred order. */
    253    static const uint32_t mem_types[] = {
    254       VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
    255       0
    256    };
    257 
    258    if (!ctx)
    259       return VA_STATUS_ERROR_INVALID_CONTEXT;
    260 
    261    drv = VL_VA_DRIVER(ctx);
    262    screen = VL_VA_PSCREEN(ctx);
    263    mtx_lock(&drv->mutex);
    264    buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
    265    mtx_unlock(&drv->mutex);
    266 
    267    if (!buf)
    268       return VA_STATUS_ERROR_INVALID_BUFFER;
    269 
    270    /* Only VA surface|image like buffers are supported for now .*/
    271    if (buf->type != VAImageBufferType)
    272       return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
    273 
    274    if (!out_buf_info)
    275       return VA_STATUS_ERROR_INVALID_PARAMETER;
    276 
    277    if (!out_buf_info->mem_type)
    278       mem_type = mem_types[0];
    279    else {
    280       mem_type = 0;
    281       for (i = 0; mem_types[i] != 0; i++) {
    282          if (out_buf_info->mem_type & mem_types[i]) {
    283             mem_type = out_buf_info->mem_type;
    284             break;
    285          }
    286       }
    287       if (!mem_type)
    288          return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
    289    }
    290 
    291    if (!buf->derived_surface.resource)
    292       return VA_STATUS_ERROR_INVALID_BUFFER;
    293 
    294    if (buf->export_refcount > 0) {
    295       if (buf->export_state.mem_type != mem_type)
    296          return VA_STATUS_ERROR_INVALID_PARAMETER;
    297    } else {
    298       VABufferInfo * const buf_info = &buf->export_state;
    299 
    300       switch (mem_type) {
    301       case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
    302          struct winsys_handle whandle;
    303 
    304          mtx_lock(&drv->mutex);
    305          drv->pipe->flush(drv->pipe, NULL, 0);
    306 
    307          memset(&whandle, 0, sizeof(whandle));
    308          whandle.type = DRM_API_HANDLE_TYPE_FD;
    309 
    310          if (!screen->resource_get_handle(screen, drv->pipe,
    311                                           buf->derived_surface.resource,
    312                                           &whandle, PIPE_HANDLE_USAGE_READ_WRITE)) {
    313             mtx_unlock(&drv->mutex);
    314             return VA_STATUS_ERROR_INVALID_BUFFER;
    315          }
    316 
    317          mtx_unlock(&drv->mutex);
    318 
    319          buf_info->handle = (intptr_t)whandle.handle;
    320          break;
    321       }
    322       default:
    323          return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
    324       }
    325 
    326       buf_info->type = buf->type;
    327       buf_info->mem_type = mem_type;
    328       buf_info->mem_size = buf->num_elements * buf->size;
    329    }
    330 
    331    buf->export_refcount++;
    332 
    333    *out_buf_info = buf->export_state;
    334 
    335    return VA_STATUS_SUCCESS;
    336 }
    337 
    338 VAStatus
    339 vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
    340 {
    341    vlVaDriver *drv;
    342    vlVaBuffer *buf;
    343 
    344    if (!ctx)
    345       return VA_STATUS_ERROR_INVALID_CONTEXT;
    346 
    347    drv = VL_VA_DRIVER(ctx);
    348    mtx_lock(&drv->mutex);
    349    buf = handle_table_get(drv->htab, buf_id);
    350    mtx_unlock(&drv->mutex);
    351 
    352    if (!buf)
    353       return VA_STATUS_ERROR_INVALID_BUFFER;
    354 
    355    if (buf->export_refcount == 0)
    356       return VA_STATUS_ERROR_INVALID_BUFFER;
    357 
    358    if (--buf->export_refcount == 0) {
    359       VABufferInfo * const buf_info = &buf->export_state;
    360 
    361       switch (buf_info->mem_type) {
    362       case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
    363          close((intptr_t)buf_info->handle);
    364          break;
    365       default:
    366          return VA_STATUS_ERROR_INVALID_BUFFER;
    367       }
    368 
    369       buf_info->mem_type = 0;
    370    }
    371 
    372    return VA_STATUS_SUCCESS;
    373 }
    374