1
/**************************************************************************
3
* Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4
* Copyright 2014 Advanced Micro Devices, Inc.
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:
15
* The above copyright notice and this permission notice (including the
16
* next paragraph) shall be included in all copies or substantial portions
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.
27
**************************************************************************/
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"
36
#include "va_private.h"
39
vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type,
40
unsigned int size, unsigned int num_elements, void *data,
47
return VA_STATUS_ERROR_INVALID_CONTEXT;
49
buf = CALLOC(1, sizeof(vlVaBuffer));
51
return VA_STATUS_ERROR_ALLOCATION_FAILED;
55
buf->num_elements = num_elements;
56
buf->data = MALLOC(size * num_elements);
60
return VA_STATUS_ERROR_ALLOCATION_FAILED;
64
memcpy(buf->data, data, size * num_elements);
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);
71
return VA_STATUS_SUCCESS;
75
vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id,
76
unsigned int num_elements)
82
return VA_STATUS_ERROR_INVALID_CONTEXT;
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);
89
return VA_STATUS_ERROR_INVALID_BUFFER;
91
if (buf->derived_surface.resource)
92
return VA_STATUS_ERROR_INVALID_BUFFER;
94
buf->data = REALLOC(buf->data, buf->size * buf->num_elements,
95
buf->size * num_elements);
96
buf->num_elements = num_elements;
99
return VA_STATUS_ERROR_ALLOCATION_FAILED;
101
return VA_STATUS_SUCCESS;
105
vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)
111
return VA_STATUS_ERROR_INVALID_CONTEXT;
113
drv = VL_VA_DRIVER(ctx);
115
return VA_STATUS_ERROR_INVALID_CONTEXT;
118
return VA_STATUS_ERROR_INVALID_PARAMETER;
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;
127
if (buf->derived_surface.resource) {
128
struct pipe_resource *resource;
129
struct pipe_box box = {};
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);
139
if (!buf->derived_surface.transfer || !*pbuff)
140
return VA_STATUS_ERROR_INVALID_BUFFER;
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;
149
mtx_unlock(&drv->mutex);
153
return VA_STATUS_SUCCESS;
157
vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
163
return VA_STATUS_ERROR_INVALID_CONTEXT;
165
drv = VL_VA_DRIVER(ctx);
167
return VA_STATUS_ERROR_INVALID_CONTEXT;
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;
176
if (buf->derived_surface.resource) {
177
if (!buf->derived_surface.transfer) {
178
mtx_unlock(&drv->mutex);
179
return VA_STATUS_ERROR_INVALID_BUFFER;
182
pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer);
183
buf->derived_surface.transfer = NULL;
185
mtx_unlock(&drv->mutex);
187
return VA_STATUS_SUCCESS;
191
vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
197
return VA_STATUS_ERROR_INVALID_CONTEXT;
199
drv = VL_VA_DRIVER(ctx);
200
mtx_lock(&drv->mutex);
201
buf = handle_table_get(drv->htab, buf_id);
203
mtx_unlock(&drv->mutex);
204
return VA_STATUS_ERROR_INVALID_BUFFER;
207
if (buf->derived_surface.resource) {
208
pipe_resource_reference(&buf->derived_surface.resource, NULL);
210
if (buf->derived_image_buffer)
211
buf->derived_image_buffer->destroy(buf->derived_image_buffer);
216
handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);
217
mtx_unlock(&drv->mutex);
219
return VA_STATUS_SUCCESS;
223
vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type,
224
unsigned int *size, unsigned int *num_elements)
230
return VA_STATUS_ERROR_INVALID_CONTEXT;
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);
237
return VA_STATUS_ERROR_INVALID_BUFFER;
241
*num_elements = buf->num_elements;
243
return VA_STATUS_SUCCESS;
247
vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
248
VABufferInfo *out_buf_info)
254
struct pipe_screen *screen;
256
/* List of supported memory types, in preferred order. */
257
static const uint32_t mem_types[] = {
258
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
263
return VA_STATUS_ERROR_INVALID_CONTEXT;
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);
272
return VA_STATUS_ERROR_INVALID_BUFFER;
274
/* Only VA surface|image like buffers are supported for now .*/
275
if (buf->type != VAImageBufferType)
276
return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
279
return VA_STATUS_ERROR_INVALID_PARAMETER;
281
if (!out_buf_info->mem_type)
282
mem_type = mem_types[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;
292
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
295
if (!buf->derived_surface.resource)
296
return VA_STATUS_ERROR_INVALID_BUFFER;
298
if (buf->export_refcount > 0) {
299
if (buf->export_state.mem_type != mem_type)
300
return VA_STATUS_ERROR_INVALID_PARAMETER;
302
VABufferInfo * const buf_info = &buf->export_state;
305
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
306
struct winsys_handle whandle;
308
mtx_lock(&drv->mutex);
309
drv->pipe->flush(drv->pipe, NULL, 0);
311
memset(&whandle, 0, sizeof(whandle));
312
whandle.type = WINSYS_HANDLE_TYPE_FD;
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;
321
mtx_unlock(&drv->mutex);
323
buf_info->handle = (intptr_t)whandle.handle;
327
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
330
buf_info->type = buf->type;
331
buf_info->mem_type = mem_type;
332
buf_info->mem_size = buf->num_elements * buf->size;
335
buf->export_refcount++;
337
*out_buf_info = buf->export_state;
339
return VA_STATUS_SUCCESS;
343
vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
349
return VA_STATUS_ERROR_INVALID_CONTEXT;
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);
357
return VA_STATUS_ERROR_INVALID_BUFFER;
359
if (buf->export_refcount == 0)
360
return VA_STATUS_ERROR_INVALID_BUFFER;
362
if (--buf->export_refcount == 0) {
363
VABufferInfo * const buf_info = &buf->export_state;
365
switch (buf_info->mem_type) {
366
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
367
close((intptr_t)buf_info->handle);
370
return VA_STATUS_ERROR_INVALID_BUFFER;
373
buf_info->mem_type = 0;
376
return VA_STATUS_SUCCESS;