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
->transfer_map(drv
->pipe
, resource
, 0, PIPE_TRANSFER_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
);
212 handle_table_remove(VL_VA_DRIVER(ctx
)->htab
, buf_id
);
213 mtx_unlock(&drv
->mutex
);
215 return VA_STATUS_SUCCESS
;
219 vlVaBufferInfo(VADriverContextP ctx
, VABufferID buf_id
, VABufferType
*type
,
220 unsigned int *size
, unsigned int *num_elements
)
226 return VA_STATUS_ERROR_INVALID_CONTEXT
;
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
);
233 return VA_STATUS_ERROR_INVALID_BUFFER
;
237 *num_elements
= buf
->num_elements
;
239 return VA_STATUS_SUCCESS
;
243 vlVaAcquireBufferHandle(VADriverContextP ctx
, VABufferID buf_id
,
244 VABufferInfo
*out_buf_info
)
250 struct pipe_screen
*screen
;
252 /* List of supported memory types, in preferred order. */
253 static const uint32_t mem_types
[] = {
254 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
,
259 return VA_STATUS_ERROR_INVALID_CONTEXT
;
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
);
268 return VA_STATUS_ERROR_INVALID_BUFFER
;
270 /* Only VA surface|image like buffers are supported for now .*/
271 if (buf
->type
!= VAImageBufferType
)
272 return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE
;
275 return VA_STATUS_ERROR_INVALID_PARAMETER
;
277 if (!out_buf_info
->mem_type
)
278 mem_type
= mem_types
[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
;
288 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
291 if (!buf
->derived_surface
.resource
)
292 return VA_STATUS_ERROR_INVALID_BUFFER
;
294 if (buf
->export_refcount
> 0) {
295 if (buf
->export_state
.mem_type
!= mem_type
)
296 return VA_STATUS_ERROR_INVALID_PARAMETER
;
298 VABufferInfo
* const buf_info
= &buf
->export_state
;
301 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
: {
302 struct winsys_handle whandle
;
304 mtx_lock(&drv
->mutex
);
305 drv
->pipe
->flush(drv
->pipe
, NULL
, 0);
307 memset(&whandle
, 0, sizeof(whandle
));
308 whandle
.type
= WINSYS_HANDLE_TYPE_FD
;
310 if (!screen
->resource_get_handle(screen
, drv
->pipe
,
311 buf
->derived_surface
.resource
,
312 &whandle
, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE
)) {
313 mtx_unlock(&drv
->mutex
);
314 return VA_STATUS_ERROR_INVALID_BUFFER
;
317 mtx_unlock(&drv
->mutex
);
319 buf_info
->handle
= (intptr_t)whandle
.handle
;
323 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
326 buf_info
->type
= buf
->type
;
327 buf_info
->mem_type
= mem_type
;
328 buf_info
->mem_size
= buf
->num_elements
* buf
->size
;
331 buf
->export_refcount
++;
333 *out_buf_info
= buf
->export_state
;
335 return VA_STATUS_SUCCESS
;
339 vlVaReleaseBufferHandle(VADriverContextP ctx
, VABufferID buf_id
)
345 return VA_STATUS_ERROR_INVALID_CONTEXT
;
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
);
353 return VA_STATUS_ERROR_INVALID_BUFFER
;
355 if (buf
->export_refcount
== 0)
356 return VA_STATUS_ERROR_INVALID_BUFFER
;
358 if (--buf
->export_refcount
== 0) {
359 VABufferInfo
* const buf_info
= &buf
->export_state
;
361 switch (buf_info
->mem_type
) {
362 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
363 close((intptr_t)buf_info
->handle
);
366 return VA_STATUS_ERROR_INVALID_BUFFER
;
369 buf_info
->mem_type
= 0;
372 return VA_STATUS_SUCCESS
;