st/va: add colospace conversion through Video Post Processing
[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 /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN
352 only for VAEntrypointVideoProc. */
353 attribs[i].type = VASurfaceAttribPixelFormat;
354 attribs[i].value.type = VAGenericValueTypeInteger;
355 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
356 attribs[i].value.value.i = VA_FOURCC_BGRA;
357 i++;
358
359 attribs[i].type = VASurfaceAttribPixelFormat;
360 attribs[i].value.type = VAGenericValueTypeInteger;
361 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
362 attribs[i].value.value.i = VA_FOURCC_RGBA;
363 i++;
364 } else {
365 /* Assume VAEntrypointVLD for now. */
366 attribs[i].type = VASurfaceAttribPixelFormat;
367 attribs[i].value.type = VAGenericValueTypeInteger;
368 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
369 attribs[i].value.value.i = VA_FOURCC_NV12;
370 i++;
371 }
372
373 attribs[i].type = VASurfaceAttribMemoryType;
374 attribs[i].value.type = VAGenericValueTypeInteger;
375 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
376 attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA |
377 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
378 i++;
379
380 attribs[i].type = VASurfaceAttribExternalBufferDescriptor;
381 attribs[i].value.type = VAGenericValueTypePointer;
382 attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE;
383 attribs[i].value.value.p = NULL; /* ignore */
384 i++;
385
386 attribs[i].type = VASurfaceAttribMaxWidth;
387 attribs[i].value.type = VAGenericValueTypeInteger;
388 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
389 attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);
390 i++;
391
392 attribs[i].type = VASurfaceAttribMaxHeight;
393 attribs[i].value.type = VAGenericValueTypeInteger;
394 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
395 attribs[i].value.value.i = vl_video_buffer_max_size(pscreen);
396 i++;
397
398 if (i > *num_attribs) {
399 *num_attribs = i;
400 FREE(attribs);
401 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
402 }
403
404 *num_attribs = i;
405 memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib));
406 FREE(attribs);
407
408 return VA_STATUS_SUCCESS;
409 }
410
411 static VAStatus
412 suface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface,
413 VASurfaceAttribExternalBuffers *memory_attibute,
414 int index, VASurfaceID *surfaces,
415 struct pipe_video_buffer *templat)
416 {
417 vlVaDriver *drv;
418 struct pipe_screen *pscreen;
419 struct pipe_resource *resource;
420 struct pipe_resource res_templ;
421 struct winsys_handle whandle;
422 struct pipe_resource *resources[VL_NUM_COMPONENTS];
423
424 if (!ctx)
425 return VA_STATUS_ERROR_INVALID_PARAMETER;
426
427 pscreen = VL_VA_PSCREEN(ctx);
428 drv = VL_VA_DRIVER(ctx);
429
430 if (!memory_attibute || !memory_attibute->buffers ||
431 index > memory_attibute->num_buffers)
432 return VA_STATUS_ERROR_INVALID_PARAMETER;
433
434 if (surface->templat.width != memory_attibute->width ||
435 surface->templat.height != memory_attibute->height ||
436 memory_attibute->num_planes < 1)
437 return VA_STATUS_ERROR_INVALID_PARAMETER;
438
439 switch (memory_attibute->pixel_format) {
440 case VA_FOURCC_RGBA:
441 case VA_FOURCC_RGBX:
442 case VA_FOURCC_BGRA:
443 case VA_FOURCC_BGRX:
444 if (memory_attibute->num_planes != 1)
445 return VA_STATUS_ERROR_INVALID_PARAMETER;
446 break;
447 default:
448 return VA_STATUS_ERROR_INVALID_PARAMETER;
449 }
450
451 memset(&res_templ, 0, sizeof(res_templ));
452 res_templ.target = PIPE_TEXTURE_2D;
453 res_templ.last_level = 0;
454 res_templ.depth0 = 1;
455 res_templ.array_size = 1;
456 res_templ.width0 = memory_attibute->width;
457 res_templ.height0 = memory_attibute->height;
458 res_templ.format = surface->templat.buffer_format;
459 res_templ.bind = PIPE_BIND_SAMPLER_VIEW;
460 res_templ.usage = PIPE_USAGE_DEFAULT;
461
462 memset(&whandle, 0, sizeof(struct winsys_handle));
463 whandle.type = DRM_API_HANDLE_TYPE_FD;
464 whandle.handle = memory_attibute->buffers[index];
465 whandle.stride = memory_attibute->pitches[index];
466
467 resource = pscreen->resource_from_handle(pscreen, &res_templ, &whandle);
468
469 if (!resource)
470 return VA_STATUS_ERROR_ALLOCATION_FAILED;
471
472 memset(resources, 0, sizeof resources);
473 resources[0] = resource;
474
475 surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources);
476 if (!surface->buffer)
477 return VA_STATUS_ERROR_ALLOCATION_FAILED;
478
479 util_dynarray_init(&surface->subpics);
480 surfaces[index] = handle_table_add(drv->htab, surface);
481
482 if (!surfaces[index])
483 return VA_STATUS_ERROR_ALLOCATION_FAILED;
484
485 return VA_STATUS_SUCCESS;
486 }
487
488 VAStatus
489 vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
490 unsigned int width, unsigned int height,
491 VASurfaceID *surfaces, unsigned int num_surfaces,
492 VASurfaceAttrib *attrib_list, unsigned int num_attribs)
493 {
494 vlVaDriver *drv;
495 VASurfaceAttribExternalBuffers *memory_attibute;
496 struct pipe_video_buffer templat;
497 struct pipe_screen *pscreen;
498 int i;
499 int memory_type;
500 int expected_fourcc;
501 VAStatus vaStatus;
502
503 if (!ctx)
504 return VA_STATUS_ERROR_INVALID_CONTEXT;
505
506 if (!(width && height))
507 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
508
509 drv = VL_VA_DRIVER(ctx);
510
511 if (!drv)
512 return VA_STATUS_ERROR_INVALID_CONTEXT;
513
514 pscreen = VL_VA_PSCREEN(ctx);
515
516 if (!pscreen)
517 return VA_STATUS_ERROR_INVALID_CONTEXT;
518
519 /* Default. */
520 memory_attibute = NULL;
521 memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
522 expected_fourcc = 0;
523
524 for (i = 0; i < num_attribs && attrib_list; i++) {
525 if ((attrib_list[i].type == VASurfaceAttribPixelFormat) &&
526 (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
527 if (attrib_list[i].value.type != VAGenericValueTypeInteger)
528 return VA_STATUS_ERROR_INVALID_PARAMETER;
529 expected_fourcc = attrib_list[i].value.value.i;
530 }
531
532 if ((attrib_list[i].type == VASurfaceAttribMemoryType) &&
533 (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
534
535 if (attrib_list[i].value.type != VAGenericValueTypeInteger)
536 return VA_STATUS_ERROR_INVALID_PARAMETER;
537
538 switch (attrib_list[i].value.value.i) {
539 case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
540 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
541 memory_type = attrib_list[i].value.value.i;
542 break;
543 default:
544 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
545 }
546 }
547
548 if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) &&
549 (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) {
550 if (attrib_list[i].value.type != VAGenericValueTypePointer)
551 return VA_STATUS_ERROR_INVALID_PARAMETER;
552 memory_attibute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
553 }
554 }
555
556 if (VA_RT_FORMAT_YUV420 != format &&
557 VA_RT_FORMAT_YUV422 != format &&
558 VA_RT_FORMAT_YUV444 != format &&
559 VA_RT_FORMAT_RGB32 != format) {
560 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
561 }
562
563 switch (memory_type) {
564 case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
565 break;
566 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
567 if (!memory_attibute)
568 return VA_STATUS_ERROR_INVALID_PARAMETER;
569
570 expected_fourcc = memory_attibute->pixel_format;
571 break;
572 default:
573 assert(0);
574 }
575
576 memset(&templat, 0, sizeof(templat));
577
578 if (expected_fourcc) {
579 templat.buffer_format = VaFourccToPipeFormat(expected_fourcc);
580 templat.interlaced = 0;
581 } else {
582 templat.buffer_format = pscreen->get_video_param
583 (
584 pscreen,
585 PIPE_VIDEO_PROFILE_UNKNOWN,
586 PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
587 PIPE_VIDEO_CAP_PREFERED_FORMAT
588 );
589 templat.interlaced = pscreen->get_video_param
590 (
591 pscreen,
592 PIPE_VIDEO_PROFILE_UNKNOWN,
593 PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
594 PIPE_VIDEO_CAP_PREFERS_INTERLACED
595 );
596 }
597
598 templat.chroma_format = ChromaToPipe(format);
599
600 templat.width = width;
601 templat.height = height;
602
603 memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID));
604
605 for (i = 0; i < num_surfaces; i++) {
606 vlVaSurface *surf = CALLOC(1, sizeof(vlVaSurface));
607 if (!surf)
608 goto no_res;
609
610 surf->templat = templat;
611
612 switch (memory_type) {
613 case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
614 surf->buffer = drv->pipe->create_video_buffer(drv->pipe, &templat);
615 if (!surf->buffer)
616 goto no_res;
617 util_dynarray_init(&surf->subpics);
618 surfaces[i] = handle_table_add(drv->htab, surf);
619 break;
620 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
621 vaStatus = suface_from_external_memory(ctx, surf, memory_attibute, i, surfaces, &templat);
622 if (vaStatus != VA_STATUS_SUCCESS)
623 goto no_res;
624 break;
625 default:
626 assert(0);
627 }
628 }
629
630 return VA_STATUS_SUCCESS;
631
632 no_res:
633 if (i)
634 vlVaDestroySurfaces(ctx, surfaces, i);
635
636 return VA_STATUS_ERROR_ALLOCATION_FAILED;
637 }
638
639 VAStatus
640 vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context,
641 VAProcFilterType *filters, unsigned int *num_filters)
642 {
643 unsigned int num = 0;
644
645 if (!ctx)
646 return VA_STATUS_ERROR_INVALID_CONTEXT;
647
648 if (!num_filters || !filters)
649 return VA_STATUS_ERROR_INVALID_PARAMETER;
650
651 filters[num++] = VAProcFilterNone;
652
653 *num_filters = num;
654
655 return VA_STATUS_SUCCESS;
656 }
657
658 VAStatus
659 vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context,
660 VAProcFilterType type, void *filter_caps,
661 unsigned int *num_filter_caps)
662 {
663 unsigned int i;
664
665 if (!ctx)
666 return VA_STATUS_ERROR_INVALID_CONTEXT;
667
668 if (!filter_caps || !num_filter_caps)
669 return VA_STATUS_ERROR_INVALID_PARAMETER;
670
671 i = 0;
672
673 switch (type) {
674 case VAProcFilterNone:
675 break;
676 case VAProcFilterNoiseReduction:
677 case VAProcFilterDeinterlacing:
678 case VAProcFilterSharpening:
679 case VAProcFilterColorBalance:
680 case VAProcFilterSkinToneEnhancement:
681 return VA_STATUS_ERROR_UNIMPLEMENTED;
682 default:
683 assert(0);
684 }
685
686 *num_filter_caps = i;
687
688 return VA_STATUS_SUCCESS;
689 }
690
691 static VAProcColorStandardType vpp_input_color_standards[VAProcColorStandardCount] = {
692 VAProcColorStandardBT601
693 };
694
695 static VAProcColorStandardType vpp_output_color_standards[VAProcColorStandardCount] = {
696 VAProcColorStandardBT601
697 };
698
699 VAStatus
700 vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context,
701 VABufferID *filters, unsigned int num_filters,
702 VAProcPipelineCaps *pipeline_cap)
703 {
704 unsigned int i = 0;
705
706 if (!ctx)
707 return VA_STATUS_ERROR_INVALID_CONTEXT;
708
709 if (!pipeline_cap)
710 return VA_STATUS_ERROR_INVALID_PARAMETER;
711
712 if (num_filters && !filters)
713 return VA_STATUS_ERROR_INVALID_PARAMETER;
714
715 pipeline_cap->pipeline_flags = 0;
716 pipeline_cap->filter_flags = 0;
717 pipeline_cap->num_forward_references = 0;
718 pipeline_cap->num_backward_references = 0;
719 pipeline_cap->num_input_color_standards = 1;
720 pipeline_cap->input_color_standards = vpp_input_color_standards;
721 pipeline_cap->num_output_color_standards = 1;
722 pipeline_cap->output_color_standards = vpp_output_color_standards;
723
724 for (i = 0; i < num_filters; i++) {
725 vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]);
726
727 if (!buf || buf->type >= VABufferTypeMax)
728 return VA_STATUS_ERROR_INVALID_BUFFER;
729 }
730
731 return VA_STATUS_SUCCESS;
732 }