• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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
vlVaCreateBuffer(VADriverContextP ctx,VAContextID context,VABufferType type,unsigned int size,unsigned int num_elements,void * data,VABufferID * buf_id)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
vlVaBufferSetNumElements(VADriverContextP ctx,VABufferID buf_id,unsigned int num_elements)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
vlVaMapBuffer(VADriverContextP ctx,VABufferID buf_id,void ** pbuff)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
vlVaUnmapBuffer(VADriverContextP ctx,VABufferID buf_id)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
vlVaDestroyBuffer(VADriverContextP ctx,VABufferID buf_id)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
vlVaBufferInfo(VADriverContextP ctx,VABufferID buf_id,VABufferType * type,unsigned int * size,unsigned int * num_elements)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
vlVaAcquireBufferHandle(VADriverContextP ctx,VABufferID buf_id,VABufferInfo * out_buf_info)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
vlVaReleaseBufferHandle(VADriverContextP ctx,VABufferID buf_id)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