17ec681f3Smrg/**************************************************************************
27ec681f3Smrg *
37ec681f3Smrg * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
47ec681f3Smrg * Copyright 2014 Advanced Micro Devices, Inc.
57ec681f3Smrg * All Rights Reserved.
67ec681f3Smrg *
77ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87ec681f3Smrg * copy of this software and associated documentation files (the
97ec681f3Smrg * "Software"), to deal in the Software without restriction, including
107ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish,
117ec681f3Smrg * distribute, sub license, and/or sell copies of the Software, and to
127ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to
137ec681f3Smrg * the following conditions:
147ec681f3Smrg *
157ec681f3Smrg * The above copyright notice and this permission notice (including the
167ec681f3Smrg * next paragraph) shall be included in all copies or substantial portions
177ec681f3Smrg * of the Software.
187ec681f3Smrg *
197ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
207ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
217ec681f3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
227ec681f3Smrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
237ec681f3Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
247ec681f3Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
257ec681f3Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
267ec681f3Smrg *
277ec681f3Smrg **************************************************************************/
287ec681f3Smrg
297ec681f3Smrg#include "pipe/p_screen.h"
307ec681f3Smrg#include "frontend/drm_driver.h"
317ec681f3Smrg#include "util/u_memory.h"
327ec681f3Smrg#include "util/u_handle_table.h"
337ec681f3Smrg#include "util/u_transfer.h"
347ec681f3Smrg#include "vl/vl_winsys.h"
357ec681f3Smrg
367ec681f3Smrg#include "va_private.h"
377ec681f3Smrg
387ec681f3SmrgVAStatus
397ec681f3SmrgvlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type,
407ec681f3Smrg                 unsigned int size, unsigned int num_elements, void *data,
417ec681f3Smrg                 VABufferID *buf_id)
427ec681f3Smrg{
437ec681f3Smrg   vlVaDriver *drv;
447ec681f3Smrg   vlVaBuffer *buf;
457ec681f3Smrg
467ec681f3Smrg   if (!ctx)
477ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
487ec681f3Smrg
497ec681f3Smrg   buf = CALLOC(1, sizeof(vlVaBuffer));
507ec681f3Smrg   if (!buf)
517ec681f3Smrg      return VA_STATUS_ERROR_ALLOCATION_FAILED;
527ec681f3Smrg
537ec681f3Smrg   buf->type = type;
547ec681f3Smrg   buf->size = size;
557ec681f3Smrg   buf->num_elements = num_elements;
567ec681f3Smrg   buf->data = MALLOC(size * num_elements);
577ec681f3Smrg
587ec681f3Smrg   if (!buf->data) {
597ec681f3Smrg      FREE(buf);
607ec681f3Smrg      return VA_STATUS_ERROR_ALLOCATION_FAILED;
617ec681f3Smrg   }
627ec681f3Smrg
637ec681f3Smrg   if (data)
647ec681f3Smrg      memcpy(buf->data, data, size * num_elements);
657ec681f3Smrg
667ec681f3Smrg   drv = VL_VA_DRIVER(ctx);
677ec681f3Smrg   mtx_lock(&drv->mutex);
687ec681f3Smrg   *buf_id = handle_table_add(drv->htab, buf);
697ec681f3Smrg   mtx_unlock(&drv->mutex);
707ec681f3Smrg
717ec681f3Smrg   return VA_STATUS_SUCCESS;
727ec681f3Smrg}
737ec681f3Smrg
747ec681f3SmrgVAStatus
757ec681f3SmrgvlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id,
767ec681f3Smrg                         unsigned int num_elements)
777ec681f3Smrg{
787ec681f3Smrg   vlVaDriver *drv;
797ec681f3Smrg   vlVaBuffer *buf;
807ec681f3Smrg
817ec681f3Smrg   if (!ctx)
827ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
837ec681f3Smrg
847ec681f3Smrg   drv = VL_VA_DRIVER(ctx);
857ec681f3Smrg   mtx_lock(&drv->mutex);
867ec681f3Smrg   buf = handle_table_get(drv->htab, buf_id);
877ec681f3Smrg   mtx_unlock(&drv->mutex);
887ec681f3Smrg   if (!buf)
897ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
907ec681f3Smrg
917ec681f3Smrg   if (buf->derived_surface.resource)
927ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
937ec681f3Smrg
947ec681f3Smrg   buf->data = REALLOC(buf->data, buf->size * buf->num_elements,
957ec681f3Smrg                       buf->size * num_elements);
967ec681f3Smrg   buf->num_elements = num_elements;
977ec681f3Smrg
987ec681f3Smrg   if (!buf->data)
997ec681f3Smrg      return VA_STATUS_ERROR_ALLOCATION_FAILED;
1007ec681f3Smrg
1017ec681f3Smrg   return VA_STATUS_SUCCESS;
1027ec681f3Smrg}
1037ec681f3Smrg
1047ec681f3SmrgVAStatus
1057ec681f3SmrgvlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)
1067ec681f3Smrg{
1077ec681f3Smrg   vlVaDriver *drv;
1087ec681f3Smrg   vlVaBuffer *buf;
1097ec681f3Smrg
1107ec681f3Smrg   if (!ctx)
1117ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
1127ec681f3Smrg
1137ec681f3Smrg   drv = VL_VA_DRIVER(ctx);
1147ec681f3Smrg   if (!drv)
1157ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
1167ec681f3Smrg
1177ec681f3Smrg   if (!pbuff)
1187ec681f3Smrg      return VA_STATUS_ERROR_INVALID_PARAMETER;
1197ec681f3Smrg
1207ec681f3Smrg   mtx_lock(&drv->mutex);
1217ec681f3Smrg   buf = handle_table_get(drv->htab, buf_id);
1227ec681f3Smrg   if (!buf || buf->export_refcount > 0) {
1237ec681f3Smrg      mtx_unlock(&drv->mutex);
1247ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
1257ec681f3Smrg   }
1267ec681f3Smrg
1277ec681f3Smrg   if (buf->derived_surface.resource) {
1287ec681f3Smrg      struct pipe_resource *resource;
1297ec681f3Smrg      struct pipe_box box = {};
1307ec681f3Smrg
1317ec681f3Smrg      resource = buf->derived_surface.resource;
1327ec681f3Smrg      box.width = resource->width0;
1337ec681f3Smrg      box.height = resource->height0;
1347ec681f3Smrg      box.depth = resource->depth0;
1357ec681f3Smrg      *pbuff = drv->pipe->buffer_map(drv->pipe, resource, 0, PIPE_MAP_WRITE,
1367ec681f3Smrg                                       &box, &buf->derived_surface.transfer);
1377ec681f3Smrg      mtx_unlock(&drv->mutex);
1387ec681f3Smrg
1397ec681f3Smrg      if (!buf->derived_surface.transfer || !*pbuff)
1407ec681f3Smrg         return VA_STATUS_ERROR_INVALID_BUFFER;
1417ec681f3Smrg
1427ec681f3Smrg      if (buf->type == VAEncCodedBufferType) {
1437ec681f3Smrg         ((VACodedBufferSegment*)buf->data)->buf = *pbuff;
1447ec681f3Smrg         ((VACodedBufferSegment*)buf->data)->size = buf->coded_size;
1457ec681f3Smrg         ((VACodedBufferSegment*)buf->data)->next = NULL;
1467ec681f3Smrg         *pbuff = buf->data;
1477ec681f3Smrg      }
1487ec681f3Smrg   } else {
1497ec681f3Smrg      mtx_unlock(&drv->mutex);
1507ec681f3Smrg      *pbuff = buf->data;
1517ec681f3Smrg   }
1527ec681f3Smrg
1537ec681f3Smrg   return VA_STATUS_SUCCESS;
1547ec681f3Smrg}
1557ec681f3Smrg
1567ec681f3SmrgVAStatus
1577ec681f3SmrgvlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
1587ec681f3Smrg{
1597ec681f3Smrg   vlVaDriver *drv;
1607ec681f3Smrg   vlVaBuffer *buf;
1617ec681f3Smrg
1627ec681f3Smrg   if (!ctx)
1637ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
1647ec681f3Smrg
1657ec681f3Smrg   drv = VL_VA_DRIVER(ctx);
1667ec681f3Smrg   if (!drv)
1677ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
1687ec681f3Smrg
1697ec681f3Smrg   mtx_lock(&drv->mutex);
1707ec681f3Smrg   buf = handle_table_get(drv->htab, buf_id);
1717ec681f3Smrg   if (!buf || buf->export_refcount > 0) {
1727ec681f3Smrg      mtx_unlock(&drv->mutex);
1737ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
1747ec681f3Smrg   }
1757ec681f3Smrg
1767ec681f3Smrg   if (buf->derived_surface.resource) {
1777ec681f3Smrg      if (!buf->derived_surface.transfer) {
1787ec681f3Smrg         mtx_unlock(&drv->mutex);
1797ec681f3Smrg         return VA_STATUS_ERROR_INVALID_BUFFER;
1807ec681f3Smrg      }
1817ec681f3Smrg
1827ec681f3Smrg      pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer);
1837ec681f3Smrg      buf->derived_surface.transfer = NULL;
1847ec681f3Smrg   }
1857ec681f3Smrg   mtx_unlock(&drv->mutex);
1867ec681f3Smrg
1877ec681f3Smrg   return VA_STATUS_SUCCESS;
1887ec681f3Smrg}
1897ec681f3Smrg
1907ec681f3SmrgVAStatus
1917ec681f3SmrgvlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
1927ec681f3Smrg{
1937ec681f3Smrg   vlVaDriver *drv;
1947ec681f3Smrg   vlVaBuffer *buf;
1957ec681f3Smrg
1967ec681f3Smrg   if (!ctx)
1977ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
1987ec681f3Smrg
1997ec681f3Smrg   drv = VL_VA_DRIVER(ctx);
2007ec681f3Smrg   mtx_lock(&drv->mutex);
2017ec681f3Smrg   buf = handle_table_get(drv->htab, buf_id);
2027ec681f3Smrg   if (!buf) {
2037ec681f3Smrg      mtx_unlock(&drv->mutex);
2047ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
2057ec681f3Smrg   }
2067ec681f3Smrg
2077ec681f3Smrg   if (buf->derived_surface.resource) {
2087ec681f3Smrg      pipe_resource_reference(&buf->derived_surface.resource, NULL);
2097ec681f3Smrg
2107ec681f3Smrg      if (buf->derived_image_buffer)
2117ec681f3Smrg         buf->derived_image_buffer->destroy(buf->derived_image_buffer);
2127ec681f3Smrg   }
2137ec681f3Smrg
2147ec681f3Smrg   FREE(buf->data);
2157ec681f3Smrg   FREE(buf);
2167ec681f3Smrg   handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);
2177ec681f3Smrg   mtx_unlock(&drv->mutex);
2187ec681f3Smrg
2197ec681f3Smrg   return VA_STATUS_SUCCESS;
2207ec681f3Smrg}
2217ec681f3Smrg
2227ec681f3SmrgVAStatus
2237ec681f3SmrgvlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type,
2247ec681f3Smrg               unsigned int *size, unsigned int *num_elements)
2257ec681f3Smrg{
2267ec681f3Smrg   vlVaDriver *drv;
2277ec681f3Smrg   vlVaBuffer *buf;
2287ec681f3Smrg
2297ec681f3Smrg   if (!ctx)
2307ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
2317ec681f3Smrg
2327ec681f3Smrg   drv = VL_VA_DRIVER(ctx);
2337ec681f3Smrg   mtx_lock(&drv->mutex);
2347ec681f3Smrg   buf = handle_table_get(drv->htab, buf_id);
2357ec681f3Smrg   mtx_unlock(&drv->mutex);
2367ec681f3Smrg   if (!buf)
2377ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
2387ec681f3Smrg
2397ec681f3Smrg   *type = buf->type;
2407ec681f3Smrg   *size = buf->size;
2417ec681f3Smrg   *num_elements = buf->num_elements;
2427ec681f3Smrg
2437ec681f3Smrg   return VA_STATUS_SUCCESS;
2447ec681f3Smrg}
2457ec681f3Smrg
2467ec681f3SmrgVAStatus
2477ec681f3SmrgvlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
2487ec681f3Smrg                        VABufferInfo *out_buf_info)
2497ec681f3Smrg{
2507ec681f3Smrg   vlVaDriver *drv;
2517ec681f3Smrg   uint32_t i;
2527ec681f3Smrg   uint32_t mem_type;
2537ec681f3Smrg   vlVaBuffer *buf ;
2547ec681f3Smrg   struct pipe_screen *screen;
2557ec681f3Smrg
2567ec681f3Smrg   /* List of supported memory types, in preferred order. */
2577ec681f3Smrg   static const uint32_t mem_types[] = {
2587ec681f3Smrg      VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
2597ec681f3Smrg      0
2607ec681f3Smrg   };
2617ec681f3Smrg
2627ec681f3Smrg   if (!ctx)
2637ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
2647ec681f3Smrg
2657ec681f3Smrg   drv = VL_VA_DRIVER(ctx);
2667ec681f3Smrg   screen = VL_VA_PSCREEN(ctx);
2677ec681f3Smrg   mtx_lock(&drv->mutex);
2687ec681f3Smrg   buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
2697ec681f3Smrg   mtx_unlock(&drv->mutex);
2707ec681f3Smrg
2717ec681f3Smrg   if (!buf)
2727ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
2737ec681f3Smrg
2747ec681f3Smrg   /* Only VA surface|image like buffers are supported for now .*/
2757ec681f3Smrg   if (buf->type != VAImageBufferType)
2767ec681f3Smrg      return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
2777ec681f3Smrg
2787ec681f3Smrg   if (!out_buf_info)
2797ec681f3Smrg      return VA_STATUS_ERROR_INVALID_PARAMETER;
2807ec681f3Smrg
2817ec681f3Smrg   if (!out_buf_info->mem_type)
2827ec681f3Smrg      mem_type = mem_types[0];
2837ec681f3Smrg   else {
2847ec681f3Smrg      mem_type = 0;
2857ec681f3Smrg      for (i = 0; mem_types[i] != 0; i++) {
2867ec681f3Smrg         if (out_buf_info->mem_type & mem_types[i]) {
2877ec681f3Smrg            mem_type = out_buf_info->mem_type;
2887ec681f3Smrg            break;
2897ec681f3Smrg         }
2907ec681f3Smrg      }
2917ec681f3Smrg      if (!mem_type)
2927ec681f3Smrg         return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
2937ec681f3Smrg   }
2947ec681f3Smrg
2957ec681f3Smrg   if (!buf->derived_surface.resource)
2967ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
2977ec681f3Smrg
2987ec681f3Smrg   if (buf->export_refcount > 0) {
2997ec681f3Smrg      if (buf->export_state.mem_type != mem_type)
3007ec681f3Smrg         return VA_STATUS_ERROR_INVALID_PARAMETER;
3017ec681f3Smrg   } else {
3027ec681f3Smrg      VABufferInfo * const buf_info = &buf->export_state;
3037ec681f3Smrg
3047ec681f3Smrg      switch (mem_type) {
3057ec681f3Smrg      case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
3067ec681f3Smrg         struct winsys_handle whandle;
3077ec681f3Smrg
3087ec681f3Smrg         mtx_lock(&drv->mutex);
3097ec681f3Smrg         drv->pipe->flush(drv->pipe, NULL, 0);
3107ec681f3Smrg
3117ec681f3Smrg         memset(&whandle, 0, sizeof(whandle));
3127ec681f3Smrg         whandle.type = WINSYS_HANDLE_TYPE_FD;
3137ec681f3Smrg
3147ec681f3Smrg         if (!screen->resource_get_handle(screen, drv->pipe,
3157ec681f3Smrg                                          buf->derived_surface.resource,
3167ec681f3Smrg                                          &whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) {
3177ec681f3Smrg            mtx_unlock(&drv->mutex);
3187ec681f3Smrg            return VA_STATUS_ERROR_INVALID_BUFFER;
3197ec681f3Smrg         }
3207ec681f3Smrg
3217ec681f3Smrg         mtx_unlock(&drv->mutex);
3227ec681f3Smrg
3237ec681f3Smrg         buf_info->handle = (intptr_t)whandle.handle;
3247ec681f3Smrg         break;
3257ec681f3Smrg      }
3267ec681f3Smrg      default:
3277ec681f3Smrg         return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
3287ec681f3Smrg      }
3297ec681f3Smrg
3307ec681f3Smrg      buf_info->type = buf->type;
3317ec681f3Smrg      buf_info->mem_type = mem_type;
3327ec681f3Smrg      buf_info->mem_size = buf->num_elements * buf->size;
3337ec681f3Smrg   }
3347ec681f3Smrg
3357ec681f3Smrg   buf->export_refcount++;
3367ec681f3Smrg
3377ec681f3Smrg   *out_buf_info = buf->export_state;
3387ec681f3Smrg
3397ec681f3Smrg   return VA_STATUS_SUCCESS;
3407ec681f3Smrg}
3417ec681f3Smrg
3427ec681f3SmrgVAStatus
3437ec681f3SmrgvlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
3447ec681f3Smrg{
3457ec681f3Smrg   vlVaDriver *drv;
3467ec681f3Smrg   vlVaBuffer *buf;
3477ec681f3Smrg
3487ec681f3Smrg   if (!ctx)
3497ec681f3Smrg      return VA_STATUS_ERROR_INVALID_CONTEXT;
3507ec681f3Smrg
3517ec681f3Smrg   drv = VL_VA_DRIVER(ctx);
3527ec681f3Smrg   mtx_lock(&drv->mutex);
3537ec681f3Smrg   buf = handle_table_get(drv->htab, buf_id);
3547ec681f3Smrg   mtx_unlock(&drv->mutex);
3557ec681f3Smrg
3567ec681f3Smrg   if (!buf)
3577ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
3587ec681f3Smrg
3597ec681f3Smrg   if (buf->export_refcount == 0)
3607ec681f3Smrg      return VA_STATUS_ERROR_INVALID_BUFFER;
3617ec681f3Smrg
3627ec681f3Smrg   if (--buf->export_refcount == 0) {
3637ec681f3Smrg      VABufferInfo * const buf_info = &buf->export_state;
3647ec681f3Smrg
3657ec681f3Smrg      switch (buf_info->mem_type) {
3667ec681f3Smrg      case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
3677ec681f3Smrg         close((intptr_t)buf_info->handle);
3687ec681f3Smrg         break;
3697ec681f3Smrg      default:
3707ec681f3Smrg         return VA_STATUS_ERROR_INVALID_BUFFER;
3717ec681f3Smrg      }
3727ec681f3Smrg
3737ec681f3Smrg      buf_info->mem_type = 0;
3747ec681f3Smrg   }
3757ec681f3Smrg
3767ec681f3Smrg   return VA_STATUS_SUCCESS;
3777ec681f3Smrg}
378