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