st/va: implement dmabuf import for VaCreateSurfaces2
[mesa.git] / src / gallium / state_trackers / va / surface.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 "pipe/p_video_codec.h"
31
32 #include "state_tracker/drm_driver.h"
33
34 #include "util/u_memory.h"
35 #include "util/u_handle_table.h"
36 #include "util/u_rect.h"
37 #include "util/u_sampler.h"
38 #include "util/u_surface.h"
39
40 #include "vl/vl_compositor.h"
41 #include "vl/vl_video_buffer.h"
42 #include "vl/vl_winsys.h"
43
44 #include "va_private.h"
45
46 #include <va/va_drmcommon.h>
47
48 VAStatus
49 vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format,
50 int num_surfaces, VASurfaceID *surfaces)
51 {
52 return vlVaCreateSurfaces2(ctx, format, width, height, surfaces, num_surfaces,
53 NULL, 0);
54 }
55
56 VAStatus
57 vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces)
58 {
59 vlVaDriver *drv;
60 int i;
61
62 if (!ctx)
63 return VA_STATUS_ERROR_INVALID_CONTEXT;
64
65 drv = VL_VA_DRIVER(ctx);
66 for (i = 0; i < num_surfaces; ++i) {
67 vlVaSurface *surf = handle_table_get(drv->htab, surface_list[i]);
68 if (surf->buffer)
69 surf->buffer->destroy(surf->buffer);
70 if(surf->fence)
71 drv->pipe->screen->fence_reference(drv->pipe->screen, &surf->fence, NULL);
72 util_dynarray_fini(&surf->subpics);
73 FREE(surf);
74 handle_table_remove(drv->htab, surface_list[i]);
75 }
76
77 return VA_STATUS_SUCCESS;
78 }
79
80 VAStatus
81 vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)
82 {
83 if (!ctx)
84 return VA_STATUS_ERROR_INVALID_CONTEXT;
85
86 return VA_STATUS_SUCCESS;
87 }
88
89 VAStatus
90 vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status)
91 {
92 if (!ctx)
93 return VA_STATUS_ERROR_INVALID_CONTEXT;
94
95 return VA_STATUS_SUCCESS;
96 }
97
98 VAStatus
99 vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info)
100 {
101 if (!ctx)
102 return VA_STATUS_ERROR_INVALID_CONTEXT;
103
104 return VA_STATUS_ERROR_UNIMPLEMENTED;
105 }
106
107 static void
108 upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst,
109 const struct pipe_box *dst_box, const void *src, unsigned src_stride,
110 unsigned src_x, unsigned src_y)
111 {
112 struct pipe_transfer *transfer;
113 void *map;
114
115 map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE,
116 dst_box, &transfer);
117 if (!map)
118 return;
119
120 util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0,
121 dst_box->width, dst_box->height,
122 src, src_stride, src_x, src_y);
123
124 pipe->transfer_unmap(pipe, transfer);
125 }
126
127 static VAStatus
128 vlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv,
129 struct pipe_surface *surf_draw, struct u_rect *dirty_area,
130 struct u_rect *src_rect, struct u_rect *dst_rect)
131 {
132 vlVaSubpicture *sub;
133 int i;
134
135 if (!(surf->subpics.data || surf->subpics.size))
136 return VA_STATUS_SUCCESS;
137
138 for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) {
139 struct pipe_blend_state blend;
140 void *blend_state;
141 vlVaBuffer *buf;
142 struct pipe_box box;
143 struct u_rect *s, *d, sr, dr, c;
144 int sw, sh, dw, dh;
145
146 sub = ((vlVaSubpicture **)surf->subpics.data)[i];
147 if (!sub)
148 continue;
149
150 buf = handle_table_get(drv->htab, sub->image->buf);
151 if (!buf)
152 return VA_STATUS_ERROR_INVALID_IMAGE;
153
154 box.x = 0;
155 box.y = 0;
156 box.z = 0;
157 box.width = sub->dst_rect.x1 - sub->dst_rect.x0;
158 box.height = sub->dst_rect.y1 - sub->dst_rect.y0;
159 box.depth = 1;
160
161 s = &sub->src_rect;
162 d = &sub->dst_rect;
163 sw = s->x1 - s->x0;
164 sh = s->y1 - s->y0;
165 dw = d->x1 - d->x0;
166 dh = d->y1 - d->y0;
167 c.x0 = MAX2(d->x0, s->x0);
168 c.y0 = MAX2(d->y0, s->y0);
169 c.x1 = MIN2(d->x0 + dw, src_rect->x1);
170 c.y1 = MIN2(d->y0 + dh, src_rect->y1);
171 sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw);
172 sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh);
173 sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw);
174 sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh);
175
176 s = src_rect;
177 d = dst_rect;
178 sw = s->x1 - s->x0;
179 sh = s->y1 - s->y0;
180 dw = d->x1 - d->x0;
181 dh = d->y1 - d->y0;
182 dr.x0 = d->x0 + c.x0*(dw/(float)sw);
183 dr.y0 = d->y0 + c.y0*(dh/(float)sh);
184 dr.x1 = d->x0 + c.x1*(dw/(float)sw);
185 dr.y1 = d->y0 + c.y1*(dh/(float)sh);
186
187 memset(&blend, 0, sizeof(blend));
188 blend.independent_blend_enable = 0;
189 blend.rt[0].blend_enable = 1;
190 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
191 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
192 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
193 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
194 blend.rt[0].rgb_func = PIPE_BLEND_ADD;
195 blend.rt[0].alpha_func = PIPE_BLEND_ADD;
196 blend.rt[0].colormask = PIPE_MASK_RGBA;
197 blend.logicop_enable = 0;
198 blend.logicop_func = PIPE_LOGICOP_CLEAR;
199 blend.dither = 0;
200 blend_state = drv->pipe->create_blend_state(drv->pipe, &blend);
201
202 vl_compositor_clear_layers(&drv->cstate);
203 vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false);
204 upload_sampler(drv->pipe, sub->sampler, &box, buf->data,
205 sub->image->pitches[0], 0, 0);
206 vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler,
207 &sr, NULL, NULL);
208 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr);
209 vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false);
210 drv->pipe->delete_blend_state(drv->pipe, blend_state);
211 }
212
213 return VA_STATUS_SUCCESS;
214 }
215
216 VAStatus
217 vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy,
218 unsigned short srcw, unsigned short srch, short destx, short desty,
219 unsigned short destw, unsigned short desth, VARectangle *cliprects,
220 unsigned int number_cliprects, unsigned int flags)
221 {
222 vlVaDriver *drv;
223 vlVaSurface *surf;
224 struct pipe_screen *screen;
225 struct pipe_resource *tex;
226 struct pipe_surface surf_templ, *surf_draw;
227 struct u_rect src_rect, *dirty_area;
228 struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth};
229 VAStatus status;
230
231 if (!ctx)
232 return VA_STATUS_ERROR_INVALID_CONTEXT;
233
234 drv = VL_VA_DRIVER(ctx);
235 surf = handle_table_get(drv->htab, surface_id);
236 if (!surf)
237 return VA_STATUS_ERROR_INVALID_SURFACE;
238
239 screen = drv->pipe->screen;
240
241 if(surf->fence) {
242 screen->fence_finish(screen, surf->fence, PIPE_TIMEOUT_INFINITE);
243 screen->fence_reference(screen, &surf->fence, NULL);
244 }
245
246 tex = vl_screen_texture_from_drawable(drv->vscreen, (Drawable)draw);
247 if (!tex)
248 return VA_STATUS_ERROR_INVALID_DISPLAY;
249
250 dirty_area = vl_screen_get_dirty_area(drv->vscreen);
251
252 memset(&surf_templ, 0, sizeof(surf_templ));
253 surf_templ.format = tex->format;
254 surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ);
255 if (!surf_draw) {
256 pipe_resource_reference(&tex, NULL);
257 return VA_STATUS_ERROR_INVALID_DISPLAY;
258 }
259
260 src_rect.x0 = srcx;
261 src_rect.y0 = srcy;
262 src_rect.x1 = srcw + srcx;
263 src_rect.y1 = srch + srcy;
264
265 vl_compositor_clear_layers(&drv->cstate);
266 vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE);
267 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
268 vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true);
269
270 status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect);
271 if (status)
272 return status;
273
274 screen->flush_frontbuffer
275 (
276 screen, tex, 0, 0,
277 vl_screen_get_private(drv->vscreen), NULL
278 );
279
280 screen->fence_reference(screen, &surf->fence, NULL);
281 drv->pipe->flush(drv->pipe, &surf->fence, 0);
282
283 pipe_resource_reference(&tex, NULL);
284 pipe_surface_reference(&surf_draw, NULL);
285
286 return VA_STATUS_SUCCESS;
287 }
288
289 VAStatus
290 vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc,
291 unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride,
292 unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset,
293 unsigned int *buffer_name, void **buffer)
294 {
295 if (!ctx)
296 return VA_STATUS_ERROR_INVALID_CONTEXT;
297
298 return VA_STATUS_ERROR_UNIMPLEMENTED;
299 }
300
301 VAStatus
302 vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface)
303 {
304 if (!ctx)
305 return VA_STATUS_ERROR_INVALID_CONTEXT;
306
307 return VA_STATUS_ERROR_UNIMPLEMENTED;
308 }
309
310 VAStatus
311 vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config,
312 VASurfaceAttrib *attrib_list, unsigned int *num_attribs)
313 {
314 vlVaDriver *drv;
315 VASurfaceAttrib *attribs;
316 struct pipe_screen *pscreen;
317 int i;
318
319 if (config == VA_INVALID_ID)
320 return VA_STATUS_ERROR_INVALID_CONFIG;
321
322 if (!attrib_list && !num_attribs)
323 return VA_STATUS_ERROR_INVALID_PARAMETER;
324
325 if (!attrib_list) {
326 *num_attribs = VASurfaceAttribCount;
327 return VA_STATUS_SUCCESS;
328 }
329
330 if (!ctx)
331 return VA_STATUS_ERROR_INVALID_CONTEXT;
332
333 drv = VL_VA_DRIVER(ctx);
334
335 if (!drv)
336 return VA_STATUS_ERROR_INVALID_CONTEXT;
337
338 pscreen = VL_VA_PSCREEN(ctx);
339
340 if (!pscreen)
341 return VA_STATUS_ERROR_INVALID_CONTEXT;
342
343 attribs = CALLOC(VASurfaceAttribCount, sizeof(VASurfaceAttrib));
344
345 if (!attribs)
346 return VA_STATUS_ERROR_ALLOCATION_FAILED;
347
348 i = 0;
349
350 if (config == PIPE_VIDEO_PROFILE_UNKNOWN) {
351 /* Assume VAEntrypointVideoProc for now. */
352 attribs[i].type = VASurfaceAttribPixelFormat;
353 attribs[i].value.type = VAGenericValueTypeInteger;
354 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
355 attribs[i].value.value.i = VA_FOURCC_BGRA;
356 i++;
357
358 attribs[i].type = VASurfaceAttribPixelFormat;
359 attribs[i].value.type = VAGenericValueTypeInteger;
360 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
361 attribs[i].value.value.i = VA_FOURCC_RGBA;
362 i++;
363 } else {
364 /* Assume VAEntrypointVLD for now. */
365 attribs[i].type = VASurfaceAttribPixelFormat;
366 attribs[i].value.type = VAGenericValueTypeInteger;
367 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
368 attribs[i].value.value.i = VA_FOURCC_NV12;
369 i++;
370 }
371
372 attribs[i].type = VASurfaceAttribMemoryType;
373 attribs[i].value.type = VAGenericValueTypeInteger;
374 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
375 attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA |
376 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
377 i++;
378
379 attribs[i].type = VASurfaceAttribExternalBufferDescriptor;
380 attribs[i].value.type = VAGenericValueTypePointer;
381 attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;
382 attribs[i].value.value.p = NULL; /* ignore */
383 i++;
384
385 attribs[i].type = VASurfaceAttribMaxWidth;
386 attribs[i].value.type = VAGenericValueTypeInteger;
387 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
388 attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);
389 i++;
390
391 attribs[i].type = VASurfaceAttribMaxHeight;
392 attribs[i].value.type = VAGenericValueTypeInteger;
393 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
394 attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);
395 i++;
396
397 if (i > *num_attribs) {
398 *num_attribs = i;
399 FREE(attribs);
400 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
401 }
402
403 *num_attribs = i;
404 memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib));
405 FREE(attribs);
406
407 return VA_STATUS_SUCCESS;
408 }
409
410 static VAStatus
411 suface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface,
412 VASurfaceAttribExternalBuffers *memory_attibute,
413 int index, VASurfaceID *surfaces,
414 struct pipe_video_buffer *templat)
415 {
416 vlVaDriver *drv;
417 struct pipe_screen *pscreen;
418 struct pipe_resource *resource;
419 struct pipe_resource res_templ;
420 struct winsys_handle whandle;
421 struct pipe_resource *resources[VL_NUM_COMPONENTS];
422
423 if (!ctx)
424 return VA_STATUS_ERROR_INVALID_PARAMETER;
425
426 pscreen = VL_VA_PSCREEN(ctx);
427 drv = VL_VA_DRIVER(ctx);
428
429 if (!memory_attibute || !memory_attibute->buffers ||
430 index > memory_attibute->num_buffers)
431 return VA_STATUS_ERROR_INVALID_PARAMETER;
432
433 if (surface->templat.width != memory_attibute->width ||
434 surface->templat.height != memory_attibute->height ||
435 memory_attibute->num_planes < 1)
436 return VA_STATUS_ERROR_INVALID_PARAMETER;
437
438 switch (memory_attibute->pixel_format) {
439 case VA_FOURCC_RGBA:
440 case VA_FOURCC_RGBX:
441 case VA_FOURCC_BGRA:
442 case VA_FOURCC_BGRX:
443 if (memory_attibute->num_planes != 1)
444 return VA_STATUS_ERROR_INVALID_PARAMETER;
445 break;
446 default:
447 return VA_STATUS_ERROR_INVALID_PARAMETER;
448 }
449
450 memset(&res_templ, 0, sizeof(res_templ));
451 res_templ.target = PIPE_TEXTURE_2D;
452 res_templ.last_level = 0;
453 res_templ.depth0 = 1;
454 res_templ.array_size = 1;
455 res_templ.width0 = memory_attibute->width;
456 res_templ.height0 = memory_attibute->height;
457 res_templ.format = surface->templat.buffer_format;
458 res_templ.bind = PIPE_BIND_SAMPLER_VIEW;
459 res_templ.usage = PIPE_USAGE_DEFAULT;
460
461 memset(&whandle, 0, sizeof(struct winsys_handle));
462 whandle.type = DRM_API_HANDLE_TYPE_FD;
463 whandle.handle = memory_attibute->buffers[index];
464 whandle.stride = memory_attibute->pitches[index];
465
466 resource = pscreen->resource_from_handle(pscreen, &res_templ, &whandle);
467
468 if (!resource)
469 return VA_STATUS_ERROR_ALLOCATION_FAILED;
470
471 memset(resources, 0, sizeof resources);
472 resources[0] = resource;
473
474 surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources);
475 if (!surface->buffer)
476 return VA_STATUS_ERROR_ALLOCATION_FAILED;
477
478 util_dynarray_init(&surface->subpics);
479 surfaces[index] = handle_table_add(drv->htab, surface);
480
481 if (!surfaces[index])
482 return VA_STATUS_ERROR_ALLOCATION_FAILED;
483
484 return VA_STATUS_SUCCESS;
485 }
486
487 VAStatus
488 vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
489 unsigned int width, unsigned int height,
490 VASurfaceID *surfaces, unsigned int num_surfaces,
491 VASurfaceAttrib *attrib_list, unsigned int num_attribs)
492 {
493 vlVaDriver *drv;
494 VASurfaceAttribExternalBuffers *memory_attibute;
495 struct pipe_video_buffer templat;
496 struct pipe_screen *pscreen;
497 int i;
498 int memory_type;
499 int expected_fourcc;
500 VAStatus vaStatus;
501
502 if (!ctx)
503 return VA_STATUS_ERROR_INVALID_CONTEXT;
504
505 if (!(width && height))
506 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
507
508 drv = VL_VA_DRIVER(ctx);
509
510 if (!drv)
511 return VA_STATUS_ERROR_INVALID_CONTEXT;
512
513 pscreen = VL_VA_PSCREEN(ctx);
514
515 if (!pscreen)
516 return VA_STATUS_ERROR_INVALID_CONTEXT;
517
518 /* Default. */
519 memory_attibute = NULL;
520 memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
521 expected_fourcc = 0;
522
523 for (i = 0; i < num_attribs && attrib_list; i++) {
524 if ((attrib_list[i].type == VASurfaceAttribPixelFormat) &&
525 (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
526 if (attrib_list[i].value.type != VAGenericValueTypeInteger)
527 return VA_STATUS_ERROR_INVALID_PARAMETER;
528 expected_fourcc = attrib_list[i].value.value.i;
529 }
530
531 if ((attrib_list[i].type == VASurfaceAttribMemoryType) &&
532 (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
533
534 if (attrib_list[i].value.type != VAGenericValueTypeInteger)
535 return VA_STATUS_ERROR_INVALID_PARAMETER;
536
537 switch (attrib_list[i].value.value.i) {
538 case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
539 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
540 memory_type = attrib_list[i].value.value.i;
541 break;
542 default:
543 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
544 }
545 }
546
547 if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) &&
548 (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) {
549 if (attrib_list[i].value.type != VAGenericValueTypePointer)
550 return VA_STATUS_ERROR_INVALID_PARAMETER;
551 memory_attibute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
552 }
553 }
554
555 if (VA_RT_FORMAT_YUV420 != format &&
556 VA_RT_FORMAT_YUV422 != format &&
557 VA_RT_FORMAT_YUV444 != format &&
558 VA_RT_FORMAT_RGB32 != format) {
559 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
560 }
561
562 switch (memory_type) {
563 case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
564 break;
565 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
566 if (!memory_attibute)
567 return VA_STATUS_ERROR_INVALID_PARAMETER;
568
569 expected_fourcc = memory_attibute->pixel_format;
570 break;
571 default:
572 assert(0);
573 }
574
575 memset(&templat, 0, sizeof(templat));
576
577 if (expected_fourcc) {
578 templat.buffer_format = VaFourccToPipeFormat(expected_fourcc);
579 templat.interlaced = 0;
580 } else {
581 templat.buffer_format = pscreen->get_video_param
582 (
583 pscreen,
584 PIPE_VIDEO_PROFILE_UNKNOWN,
585 PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
586 PIPE_VIDEO_CAP_PREFERED_FORMAT
587 );
588 templat.interlaced = pscreen->get_video_param
589 (
590 pscreen,
591 PIPE_VIDEO_PROFILE_UNKNOWN,
592 PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
593 PIPE_VIDEO_CAP_PREFERS_INTERLACED
594 );
595 }
596
597 templat.chroma_format = ChromaToPipe(format);
598
599 templat.width = width;
600 templat.height = height;
601
602 memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID));
603
604 for (i = 0; i < num_surfaces; i++) {
605 vlVaSurface *surf = CALLOC(1, sizeof(vlVaSurface));
606 if (!surf)
607 goto no_res;
608
609 surf->templat = templat;
610
611 switch (memory_type) {
612 case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
613 surf->buffer = drv->pipe->create_video_buffer(drv->pipe, &templat);
614 if (!surf->buffer)
615 goto no_res;
616 util_dynarray_init(&surf->subpics);
617 surfaces[i] = handle_table_add(drv->htab, surf);
618 break;
619 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
620 vaStatus = suface_from_external_memory(ctx, surf, memory_attibute, i, surfaces, &templat);
621 if (vaStatus != VA_STATUS_SUCCESS)
622 goto no_res;
623 break;
624 default:
625 assert(0);
626 }
627 }
628
629 return VA_STATUS_SUCCESS;
630
631 no_res:
632 if (i)
633 vlVaDestroySurfaces(ctx, surfaces, i);
634
635 return VA_STATUS_ERROR_ALLOCATION_FAILED;
636 }