xvmc: force assertion in XvMC tests
[mesa.git] / src / gallium / state_trackers / va / buffer.c
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
39 vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type,
40 unsigned int size, unsigned int num_elements, void *data,
41 VABufferID *buf_id)
42 {
43 vlVaBuffer *buf;
44
45 if (!ctx)
46 return VA_STATUS_ERROR_INVALID_CONTEXT;
47
48 buf = CALLOC(1, sizeof(vlVaBuffer));
49 if (!buf)
50 return VA_STATUS_ERROR_ALLOCATION_FAILED;
51
52 buf->type = type;
53 buf->size = size;
54 buf->num_elements = num_elements;
55 buf->data = MALLOC(size * num_elements);
56
57 if (!buf->data) {
58 FREE(buf);
59 return VA_STATUS_ERROR_ALLOCATION_FAILED;
60 }
61
62 if (data)
63 memcpy(buf->data, data, size * num_elements);
64
65 *buf_id = handle_table_add(VL_VA_DRIVER(ctx)->htab, buf);
66
67 return VA_STATUS_SUCCESS;
68 }
69
70 VAStatus
71 vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id,
72 unsigned int num_elements)
73 {
74 vlVaBuffer *buf;
75
76 if (!ctx)
77 return VA_STATUS_ERROR_INVALID_CONTEXT;
78
79 buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
80 if (!buf)
81 return VA_STATUS_ERROR_INVALID_BUFFER;
82
83 if (buf->derived_surface.resource)
84 return VA_STATUS_ERROR_INVALID_BUFFER;
85
86 buf->data = REALLOC(buf->data, buf->size * buf->num_elements,
87 buf->size * num_elements);
88 buf->num_elements = num_elements;
89
90 if (!buf->data)
91 return VA_STATUS_ERROR_ALLOCATION_FAILED;
92
93 return VA_STATUS_SUCCESS;
94 }
95
96 VAStatus
97 vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)
98 {
99 vlVaDriver *drv;
100 vlVaBuffer *buf;
101
102 if (!ctx)
103 return VA_STATUS_ERROR_INVALID_CONTEXT;
104
105 drv = VL_VA_DRIVER(ctx);
106 if (!drv)
107 return VA_STATUS_ERROR_INVALID_CONTEXT;
108
109 if (!pbuff)
110 return VA_STATUS_ERROR_INVALID_PARAMETER;
111
112 buf = handle_table_get(drv->htab, buf_id);
113 if (!buf)
114 return VA_STATUS_ERROR_INVALID_BUFFER;
115
116 if (buf->export_refcount > 0)
117 return VA_STATUS_ERROR_INVALID_BUFFER;
118
119 if (buf->derived_surface.resource) {
120 *pbuff = pipe_buffer_map(drv->pipe, buf->derived_surface.resource,
121 PIPE_TRANSFER_WRITE,
122 &buf->derived_surface.transfer);
123
124 if (!buf->derived_surface.transfer || !*pbuff)
125 return VA_STATUS_ERROR_INVALID_BUFFER;
126
127 } else {
128 *pbuff = buf->data;
129 }
130
131 return VA_STATUS_SUCCESS;
132 }
133
134 VAStatus
135 vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
136 {
137 vlVaDriver *drv;
138 vlVaBuffer *buf;
139
140 if (!ctx)
141 return VA_STATUS_ERROR_INVALID_CONTEXT;
142
143 drv = VL_VA_DRIVER(ctx);
144 if (!drv)
145 return VA_STATUS_ERROR_INVALID_CONTEXT;
146
147 buf = handle_table_get(drv->htab, buf_id);
148 if (!buf)
149 return VA_STATUS_ERROR_INVALID_BUFFER;
150
151 if (buf->export_refcount > 0)
152 return VA_STATUS_ERROR_INVALID_BUFFER;
153
154 if (buf->derived_surface.resource) {
155 if (!buf->derived_surface.transfer)
156 return VA_STATUS_ERROR_INVALID_BUFFER;
157
158 pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer);
159 buf->derived_surface.transfer = NULL;
160 }
161
162 return VA_STATUS_SUCCESS;
163 }
164
165 VAStatus
166 vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
167 {
168 vlVaBuffer *buf;
169
170 if (!ctx)
171 return VA_STATUS_ERROR_INVALID_CONTEXT;
172
173 buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
174 if (!buf)
175 return VA_STATUS_ERROR_INVALID_BUFFER;
176
177 if (buf->derived_surface.resource) {
178 if (buf->export_refcount > 0)
179 return VA_STATUS_ERROR_INVALID_BUFFER;
180
181 pipe_resource_reference(&buf->derived_surface.resource, NULL);
182 }
183
184 FREE(buf->data);
185 FREE(buf);
186 handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);
187
188 return VA_STATUS_SUCCESS;
189 }
190
191 VAStatus
192 vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type,
193 unsigned int *size, unsigned int *num_elements)
194 {
195 vlVaBuffer *buf;
196
197 if (!ctx)
198 return VA_STATUS_ERROR_INVALID_CONTEXT;
199
200 buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
201 if (!buf)
202 return VA_STATUS_ERROR_INVALID_BUFFER;
203
204 *type = buf->type;
205 *size = buf->size;
206 *num_elements = buf->num_elements;
207
208 return VA_STATUS_SUCCESS;
209 }
210
211 VAStatus
212 vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
213 VABufferInfo *out_buf_info)
214 {
215 uint32_t i;
216 uint32_t mem_type;
217 vlVaBuffer *buf ;
218 struct pipe_screen *screen;
219
220 /* List of supported memory types, in preferred order. */
221 static const uint32_t mem_types[] = {
222 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
223 0
224 };
225
226 if (!ctx)
227 return VA_STATUS_ERROR_INVALID_CONTEXT;
228
229 buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
230
231 if (!buf)
232 return VA_STATUS_ERROR_INVALID_BUFFER;
233
234 /* Only VA surface|image like buffers are supported for now .*/
235 if (buf->type != VAImageBufferType)
236 return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
237
238 if (!out_buf_info)
239 return VA_STATUS_ERROR_INVALID_PARAMETER;
240
241 if (!out_buf_info->mem_type)
242 mem_type = mem_types[0];
243 else {
244 mem_type = 0;
245 for (i = 0; mem_types[i] != 0; i++) {
246 if (out_buf_info->mem_type & mem_types[i]) {
247 mem_type = out_buf_info->mem_type;
248 break;
249 }
250 }
251 if (!mem_type)
252 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
253 }
254
255 if (!buf->derived_surface.resource)
256 return VA_STATUS_ERROR_INVALID_BUFFER;
257
258 screen = VL_VA_PSCREEN(ctx);
259
260 if (buf->derived_surface.fence) {
261 screen->fence_finish(screen, buf->derived_surface.fence, PIPE_TIMEOUT_INFINITE);
262 screen->fence_reference(screen, &buf->derived_surface.fence, NULL);
263 }
264
265 if (buf->export_refcount > 0) {
266 if (buf->export_state.mem_type != mem_type)
267 return VA_STATUS_ERROR_INVALID_PARAMETER;
268 } else {
269 VABufferInfo * const buf_info = &buf->export_state;
270
271 switch (mem_type) {
272 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
273 struct winsys_handle whandle;
274
275 memset(&whandle, 0, sizeof(whandle));
276 whandle.type = DRM_API_HANDLE_TYPE_FD;
277
278 if (!screen->resource_get_handle(screen, buf->derived_surface.resource, &whandle))
279 return VA_STATUS_ERROR_INVALID_BUFFER;
280
281 buf_info->handle = (intptr_t)whandle.handle;
282 break;
283 }
284 default:
285 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
286 }
287
288 buf_info->type = buf->type;
289 buf_info->mem_type = mem_type;
290 buf_info->mem_size = buf->num_elements * buf->size;
291 }
292
293 buf->export_refcount++;
294
295 *out_buf_info = buf->export_state;
296
297 return VA_STATUS_SUCCESS;
298 }
299
300 VAStatus
301 vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
302 {
303 vlVaBuffer *buf;
304
305 if (!ctx)
306 return VA_STATUS_ERROR_INVALID_CONTEXT;
307
308 buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
309
310 if (!buf)
311 return VA_STATUS_ERROR_INVALID_BUFFER;
312
313 if (buf->export_refcount == 0)
314 return VA_STATUS_ERROR_INVALID_BUFFER;
315
316 if (--buf->export_refcount == 0) {
317 VABufferInfo * const buf_info = &buf->export_state;
318
319 switch (buf_info->mem_type) {
320 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
321 close((intptr_t)buf_info->handle);
322 break;
323 default:
324 return VA_STATUS_ERROR_INVALID_BUFFER;
325 }
326
327 buf_info->mem_type = 0;
328 }
329
330 return VA_STATUS_SUCCESS;
331 }