• 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    pipe_mutex_lock(drv->mutex);
68    *buf_id = handle_table_add(drv->htab, buf);
69    pipe_mutex_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    pipe_mutex_lock(drv->mutex);
86    buf = handle_table_get(drv->htab, buf_id);
87    pipe_mutex_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    pipe_mutex_lock(drv->mutex);
121    buf = handle_table_get(drv->htab, buf_id);
122    if (!buf || buf->export_refcount > 0) {
123       pipe_mutex_unlock(drv->mutex);
124       return VA_STATUS_ERROR_INVALID_BUFFER;
125    }
126 
127    if (buf->derived_surface.resource) {
128       *pbuff = pipe_buffer_map(drv->pipe, buf->derived_surface.resource,
129                                PIPE_TRANSFER_WRITE,
130                                &buf->derived_surface.transfer);
131       pipe_mutex_unlock(drv->mutex);
132 
133       if (!buf->derived_surface.transfer || !*pbuff)
134          return VA_STATUS_ERROR_INVALID_BUFFER;
135 
136       if (buf->type == VAEncCodedBufferType) {
137          ((VACodedBufferSegment*)buf->data)->buf = *pbuff;
138          ((VACodedBufferSegment*)buf->data)->size = buf->coded_size;
139          ((VACodedBufferSegment*)buf->data)->next = NULL;
140          *pbuff = buf->data;
141       }
142    } else {
143       pipe_mutex_unlock(drv->mutex);
144       *pbuff = buf->data;
145    }
146 
147    return VA_STATUS_SUCCESS;
148 }
149 
150 VAStatus
vlVaUnmapBuffer(VADriverContextP ctx,VABufferID buf_id)151 vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
152 {
153    vlVaDriver *drv;
154    vlVaBuffer *buf;
155 
156    if (!ctx)
157       return VA_STATUS_ERROR_INVALID_CONTEXT;
158 
159    drv = VL_VA_DRIVER(ctx);
160    if (!drv)
161       return VA_STATUS_ERROR_INVALID_CONTEXT;
162 
163    pipe_mutex_lock(drv->mutex);
164    buf = handle_table_get(drv->htab, buf_id);
165    if (!buf || buf->export_refcount > 0) {
166       pipe_mutex_unlock(drv->mutex);
167       return VA_STATUS_ERROR_INVALID_BUFFER;
168    }
169 
170    if (buf->derived_surface.resource) {
171       if (!buf->derived_surface.transfer) {
172          pipe_mutex_unlock(drv->mutex);
173          return VA_STATUS_ERROR_INVALID_BUFFER;
174       }
175 
176       pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer);
177       buf->derived_surface.transfer = NULL;
178    }
179    pipe_mutex_unlock(drv->mutex);
180 
181    return VA_STATUS_SUCCESS;
182 }
183 
184 VAStatus
vlVaDestroyBuffer(VADriverContextP ctx,VABufferID buf_id)185 vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
186 {
187    vlVaDriver *drv;
188    vlVaBuffer *buf;
189 
190    if (!ctx)
191       return VA_STATUS_ERROR_INVALID_CONTEXT;
192 
193    drv = VL_VA_DRIVER(ctx);
194    pipe_mutex_lock(drv->mutex);
195    buf = handle_table_get(drv->htab, buf_id);
196    if (!buf) {
197       pipe_mutex_unlock(drv->mutex);
198       return VA_STATUS_ERROR_INVALID_BUFFER;
199    }
200 
201    if (buf->derived_surface.resource)
202       pipe_resource_reference(&buf->derived_surface.resource, NULL);
203 
204    FREE(buf->data);
205    FREE(buf);
206    handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);
207    pipe_mutex_unlock(drv->mutex);
208 
209    return VA_STATUS_SUCCESS;
210 }
211 
212 VAStatus
vlVaBufferInfo(VADriverContextP ctx,VABufferID buf_id,VABufferType * type,unsigned int * size,unsigned int * num_elements)213 vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type,
214                unsigned int *size, unsigned int *num_elements)
215 {
216    vlVaDriver *drv;
217    vlVaBuffer *buf;
218 
219    if (!ctx)
220       return VA_STATUS_ERROR_INVALID_CONTEXT;
221 
222    drv = VL_VA_DRIVER(ctx);
223    pipe_mutex_lock(drv->mutex);
224    buf = handle_table_get(drv->htab, buf_id);
225    pipe_mutex_unlock(drv->mutex);
226    if (!buf)
227       return VA_STATUS_ERROR_INVALID_BUFFER;
228 
229    *type = buf->type;
230    *size = buf->size;
231    *num_elements = buf->num_elements;
232 
233    return VA_STATUS_SUCCESS;
234 }
235 
236 VAStatus
vlVaAcquireBufferHandle(VADriverContextP ctx,VABufferID buf_id,VABufferInfo * out_buf_info)237 vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
238                         VABufferInfo *out_buf_info)
239 {
240    vlVaDriver *drv;
241    uint32_t i;
242    uint32_t mem_type;
243    vlVaBuffer *buf ;
244    struct pipe_screen *screen;
245 
246    /* List of supported memory types, in preferred order. */
247    static const uint32_t mem_types[] = {
248       VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
249       0
250    };
251 
252    if (!ctx)
253       return VA_STATUS_ERROR_INVALID_CONTEXT;
254 
255    drv = VL_VA_DRIVER(ctx);
256    screen = VL_VA_PSCREEN(ctx);
257    pipe_mutex_lock(drv->mutex);
258    buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
259    pipe_mutex_unlock(drv->mutex);
260 
261    if (!buf)
262       return VA_STATUS_ERROR_INVALID_BUFFER;
263 
264    /* Only VA surface|image like buffers are supported for now .*/
265    if (buf->type != VAImageBufferType)
266       return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
267 
268    if (!out_buf_info)
269       return VA_STATUS_ERROR_INVALID_PARAMETER;
270 
271    if (!out_buf_info->mem_type)
272       mem_type = mem_types[0];
273    else {
274       mem_type = 0;
275       for (i = 0; mem_types[i] != 0; i++) {
276          if (out_buf_info->mem_type & mem_types[i]) {
277             mem_type = out_buf_info->mem_type;
278             break;
279          }
280       }
281       if (!mem_type)
282          return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
283    }
284 
285    if (!buf->derived_surface.resource)
286       return VA_STATUS_ERROR_INVALID_BUFFER;
287 
288    if (buf->export_refcount > 0) {
289       if (buf->export_state.mem_type != mem_type)
290          return VA_STATUS_ERROR_INVALID_PARAMETER;
291    } else {
292       VABufferInfo * const buf_info = &buf->export_state;
293 
294       switch (mem_type) {
295       case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
296          struct winsys_handle whandle;
297 
298          pipe_mutex_lock(drv->mutex);
299          drv->pipe->flush(drv->pipe, NULL, 0);
300 
301          memset(&whandle, 0, sizeof(whandle));
302          whandle.type = DRM_API_HANDLE_TYPE_FD;
303 
304          if (!screen->resource_get_handle(screen, drv->pipe,
305                                           buf->derived_surface.resource,
306                                           &whandle, PIPE_HANDLE_USAGE_READ_WRITE)) {
307             pipe_mutex_unlock(drv->mutex);
308             return VA_STATUS_ERROR_INVALID_BUFFER;
309          }
310 
311          pipe_mutex_unlock(drv->mutex);
312 
313          buf_info->handle = (intptr_t)whandle.handle;
314          break;
315       }
316       default:
317          return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
318       }
319 
320       buf_info->type = buf->type;
321       buf_info->mem_type = mem_type;
322       buf_info->mem_size = buf->num_elements * buf->size;
323    }
324 
325    buf->export_refcount++;
326 
327    *out_buf_info = buf->export_state;
328 
329    return VA_STATUS_SUCCESS;
330 }
331 
332 VAStatus
vlVaReleaseBufferHandle(VADriverContextP ctx,VABufferID buf_id)333 vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
334 {
335    vlVaDriver *drv;
336    vlVaBuffer *buf;
337 
338    if (!ctx)
339       return VA_STATUS_ERROR_INVALID_CONTEXT;
340 
341    drv = VL_VA_DRIVER(ctx);
342    pipe_mutex_lock(drv->mutex);
343    buf = handle_table_get(drv->htab, buf_id);
344    pipe_mutex_unlock(drv->mutex);
345 
346    if (!buf)
347       return VA_STATUS_ERROR_INVALID_BUFFER;
348 
349    if (buf->export_refcount == 0)
350       return VA_STATUS_ERROR_INVALID_BUFFER;
351 
352    if (--buf->export_refcount == 0) {
353       VABufferInfo * const buf_info = &buf->export_state;
354 
355       switch (buf_info->mem_type) {
356       case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
357          close((intptr_t)buf_info->handle);
358          break;
359       default:
360          return VA_STATUS_ERROR_INVALID_BUFFER;
361       }
362 
363       buf_info->mem_type = 0;
364    }
365 
366    return VA_STATUS_SUCCESS;
367 }
368