buffer.c revision 7ec681f3
1/************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Sørensen & 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 "frontend/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 38VAStatus 39vlVaCreateBuffer(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 74VAStatus 75vlVaBufferSetNumElements(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 104VAStatus 105vlVaMapBuffer(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->buffer_map(drv->pipe, resource, 0, PIPE_MAP_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 156VAStatus 157vlVaUnmapBuffer(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 190VAStatus 191vlVaDestroyBuffer(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 if (buf->derived_image_buffer) 211 buf->derived_image_buffer->destroy(buf->derived_image_buffer); 212 } 213 214 FREE(buf->data); 215 FREE(buf); 216 handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id); 217 mtx_unlock(&drv->mutex); 218 219 return VA_STATUS_SUCCESS; 220} 221 222VAStatus 223vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type, 224 unsigned int *size, unsigned int *num_elements) 225{ 226 vlVaDriver *drv; 227 vlVaBuffer *buf; 228 229 if (!ctx) 230 return VA_STATUS_ERROR_INVALID_CONTEXT; 231 232 drv = VL_VA_DRIVER(ctx); 233 mtx_lock(&drv->mutex); 234 buf = handle_table_get(drv->htab, buf_id); 235 mtx_unlock(&drv->mutex); 236 if (!buf) 237 return VA_STATUS_ERROR_INVALID_BUFFER; 238 239 *type = buf->type; 240 *size = buf->size; 241 *num_elements = buf->num_elements; 242 243 return VA_STATUS_SUCCESS; 244} 245 246VAStatus 247vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id, 248 VABufferInfo *out_buf_info) 249{ 250 vlVaDriver *drv; 251 uint32_t i; 252 uint32_t mem_type; 253 vlVaBuffer *buf ; 254 struct pipe_screen *screen; 255 256 /* List of supported memory types, in preferred order. */ 257 static const uint32_t mem_types[] = { 258 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, 259 0 260 }; 261 262 if (!ctx) 263 return VA_STATUS_ERROR_INVALID_CONTEXT; 264 265 drv = VL_VA_DRIVER(ctx); 266 screen = VL_VA_PSCREEN(ctx); 267 mtx_lock(&drv->mutex); 268 buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id); 269 mtx_unlock(&drv->mutex); 270 271 if (!buf) 272 return VA_STATUS_ERROR_INVALID_BUFFER; 273 274 /* Only VA surface|image like buffers are supported for now .*/ 275 if (buf->type != VAImageBufferType) 276 return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; 277 278 if (!out_buf_info) 279 return VA_STATUS_ERROR_INVALID_PARAMETER; 280 281 if (!out_buf_info->mem_type) 282 mem_type = mem_types[0]; 283 else { 284 mem_type = 0; 285 for (i = 0; mem_types[i] != 0; i++) { 286 if (out_buf_info->mem_type & mem_types[i]) { 287 mem_type = out_buf_info->mem_type; 288 break; 289 } 290 } 291 if (!mem_type) 292 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 293 } 294 295 if (!buf->derived_surface.resource) 296 return VA_STATUS_ERROR_INVALID_BUFFER; 297 298 if (buf->export_refcount > 0) { 299 if (buf->export_state.mem_type != mem_type) 300 return VA_STATUS_ERROR_INVALID_PARAMETER; 301 } else { 302 VABufferInfo * const buf_info = &buf->export_state; 303 304 switch (mem_type) { 305 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: { 306 struct winsys_handle whandle; 307 308 mtx_lock(&drv->mutex); 309 drv->pipe->flush(drv->pipe, NULL, 0); 310 311 memset(&whandle, 0, sizeof(whandle)); 312 whandle.type = WINSYS_HANDLE_TYPE_FD; 313 314 if (!screen->resource_get_handle(screen, drv->pipe, 315 buf->derived_surface.resource, 316 &whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { 317 mtx_unlock(&drv->mutex); 318 return VA_STATUS_ERROR_INVALID_BUFFER; 319 } 320 321 mtx_unlock(&drv->mutex); 322 323 buf_info->handle = (intptr_t)whandle.handle; 324 break; 325 } 326 default: 327 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 328 } 329 330 buf_info->type = buf->type; 331 buf_info->mem_type = mem_type; 332 buf_info->mem_size = buf->num_elements * buf->size; 333 } 334 335 buf->export_refcount++; 336 337 *out_buf_info = buf->export_state; 338 339 return VA_STATUS_SUCCESS; 340} 341 342VAStatus 343vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id) 344{ 345 vlVaDriver *drv; 346 vlVaBuffer *buf; 347 348 if (!ctx) 349 return VA_STATUS_ERROR_INVALID_CONTEXT; 350 351 drv = VL_VA_DRIVER(ctx); 352 mtx_lock(&drv->mutex); 353 buf = handle_table_get(drv->htab, buf_id); 354 mtx_unlock(&drv->mutex); 355 356 if (!buf) 357 return VA_STATUS_ERROR_INVALID_BUFFER; 358 359 if (buf->export_refcount == 0) 360 return VA_STATUS_ERROR_INVALID_BUFFER; 361 362 if (--buf->export_refcount == 0) { 363 VABufferInfo * const buf_info = &buf->export_state; 364 365 switch (buf_info->mem_type) { 366 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 367 close((intptr_t)buf_info->handle); 368 break; 369 default: 370 return VA_STATUS_ERROR_INVALID_BUFFER; 371 } 372 373 buf_info->mem_type = 0; 374 } 375 376 return VA_STATUS_SUCCESS; 377} 378