1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4 * Copyright 2014 Advanced Micro Devices, Inc.
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:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
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.
27 **************************************************************************/
29 #include "pipe/p_screen.h"
30 #include "pipe/p_video_codec.h"
32 #include "state_tracker/drm_driver.h"
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"
40 #include "vl/vl_compositor.h"
41 #include "vl/vl_video_buffer.h"
42 #include "vl/vl_winsys.h"
44 #include "va_private.h"
46 DEBUG_GET_ONCE_BOOL_OPTION(nointerlace
, "VAAPI_DISABLE_INTERLACE", FALSE
);
48 #include <va/va_drmcommon.h>
50 static const enum pipe_format vpp_surface_formats
[] = {
51 PIPE_FORMAT_B8G8R8A8_UNORM
, PIPE_FORMAT_R8G8B8A8_UNORM
,
52 PIPE_FORMAT_B8G8R8X8_UNORM
, PIPE_FORMAT_R8G8B8X8_UNORM
56 vlVaCreateSurfaces(VADriverContextP ctx
, int width
, int height
, int format
,
57 int num_surfaces
, VASurfaceID
*surfaces
)
59 return vlVaCreateSurfaces2(ctx
, format
, width
, height
, surfaces
, num_surfaces
,
64 vlVaDestroySurfaces(VADriverContextP ctx
, VASurfaceID
*surface_list
, int num_surfaces
)
70 return VA_STATUS_ERROR_INVALID_CONTEXT
;
72 drv
= VL_VA_DRIVER(ctx
);
73 pipe_mutex_lock(drv
->mutex
);
74 for (i
= 0; i
< num_surfaces
; ++i
) {
75 vlVaSurface
*surf
= handle_table_get(drv
->htab
, surface_list
[i
]);
77 pipe_mutex_unlock(drv
->mutex
);
78 return VA_STATUS_ERROR_INVALID_SURFACE
;
81 surf
->buffer
->destroy(surf
->buffer
);
82 util_dynarray_fini(&surf
->subpics
);
84 handle_table_remove(drv
->htab
, surface_list
[i
]);
86 pipe_mutex_unlock(drv
->mutex
);
88 return VA_STATUS_SUCCESS
;
92 vlVaSyncSurface(VADriverContextP ctx
, VASurfaceID render_target
)
100 return VA_STATUS_ERROR_INVALID_CONTEXT
;
102 drv
= VL_VA_DRIVER(ctx
);
104 return VA_STATUS_ERROR_INVALID_CONTEXT
;
106 pipe_mutex_lock(drv
->mutex
);
107 surf
= handle_table_get(drv
->htab
, render_target
);
109 if (!surf
|| !surf
->buffer
)
110 return VA_STATUS_ERROR_INVALID_SURFACE
;
112 context
= handle_table_get(drv
->htab
, surf
->ctx
);
114 pipe_mutex_unlock(drv
->mutex
);
115 return VA_STATUS_ERROR_INVALID_CONTEXT
;
118 if (context
->decoder
->entrypoint
== PIPE_VIDEO_ENTRYPOINT_ENCODE
) {
120 if (context
->desc
.h264enc
.frame_num_cnt
> surf
->frame_num_cnt
)
121 frame_diff
= context
->desc
.h264enc
.frame_num_cnt
- surf
->frame_num_cnt
;
123 frame_diff
= 0xFFFFFFFF - surf
->frame_num_cnt
+ 1 + context
->desc
.h264enc
.frame_num_cnt
;
125 context
->decoder
->flush(context
->decoder
);
126 context
->decoder
->get_feedback(context
->decoder
, surf
->feedback
, &(surf
->coded_buf
->coded_size
));
128 pipe_mutex_unlock(drv
->mutex
);
129 return VA_STATUS_SUCCESS
;
133 vlVaQuerySurfaceStatus(VADriverContextP ctx
, VASurfaceID render_target
, VASurfaceStatus
*status
)
136 return VA_STATUS_ERROR_INVALID_CONTEXT
;
138 return VA_STATUS_SUCCESS
;
142 vlVaQuerySurfaceError(VADriverContextP ctx
, VASurfaceID render_target
, VAStatus error_status
, void **error_info
)
145 return VA_STATUS_ERROR_INVALID_CONTEXT
;
147 return VA_STATUS_ERROR_UNIMPLEMENTED
;
151 upload_sampler(struct pipe_context
*pipe
, struct pipe_sampler_view
*dst
,
152 const struct pipe_box
*dst_box
, const void *src
, unsigned src_stride
,
153 unsigned src_x
, unsigned src_y
)
155 struct pipe_transfer
*transfer
;
158 map
= pipe
->transfer_map(pipe
, dst
->texture
, 0, PIPE_TRANSFER_WRITE
,
163 util_copy_rect(map
, dst
->texture
->format
, transfer
->stride
, 0, 0,
164 dst_box
->width
, dst_box
->height
,
165 src
, src_stride
, src_x
, src_y
);
167 pipe
->transfer_unmap(pipe
, transfer
);
171 vlVaPutSubpictures(vlVaSurface
*surf
, vlVaDriver
*drv
,
172 struct pipe_surface
*surf_draw
, struct u_rect
*dirty_area
,
173 struct u_rect
*src_rect
, struct u_rect
*dst_rect
)
178 if (!(surf
->subpics
.data
|| surf
->subpics
.size
))
179 return VA_STATUS_SUCCESS
;
181 for (i
= 0; i
< surf
->subpics
.size
/sizeof(vlVaSubpicture
*); i
++) {
182 struct pipe_blend_state blend
;
186 struct u_rect
*s
, *d
, sr
, dr
, c
;
189 sub
= ((vlVaSubpicture
**)surf
->subpics
.data
)[i
];
193 buf
= handle_table_get(drv
->htab
, sub
->image
->buf
);
195 return VA_STATUS_ERROR_INVALID_IMAGE
;
200 box
.width
= sub
->dst_rect
.x1
- sub
->dst_rect
.x0
;
201 box
.height
= sub
->dst_rect
.y1
- sub
->dst_rect
.y0
;
210 c
.x0
= MAX2(d
->x0
, s
->x0
);
211 c
.y0
= MAX2(d
->y0
, s
->y0
);
212 c
.x1
= MIN2(d
->x0
+ dw
, src_rect
->x1
);
213 c
.y1
= MIN2(d
->y0
+ dh
, src_rect
->y1
);
214 sr
.x0
= s
->x0
+ (c
.x0
- d
->x0
)*(sw
/(float)dw
);
215 sr
.y0
= s
->y0
+ (c
.y0
- d
->y0
)*(sh
/(float)dh
);
216 sr
.x1
= s
->x0
+ (c
.x1
- d
->x0
)*(sw
/(float)dw
);
217 sr
.y1
= s
->y0
+ (c
.y1
- d
->y0
)*(sh
/(float)dh
);
225 dr
.x0
= d
->x0
+ c
.x0
*(dw
/(float)sw
);
226 dr
.y0
= d
->y0
+ c
.y0
*(dh
/(float)sh
);
227 dr
.x1
= d
->x0
+ c
.x1
*(dw
/(float)sw
);
228 dr
.y1
= d
->y0
+ c
.y1
*(dh
/(float)sh
);
230 memset(&blend
, 0, sizeof(blend
));
231 blend
.independent_blend_enable
= 0;
232 blend
.rt
[0].blend_enable
= 1;
233 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
234 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
235 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ZERO
;
236 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
237 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
238 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
239 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
240 blend
.logicop_enable
= 0;
241 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
243 blend_state
= drv
->pipe
->create_blend_state(drv
->pipe
, &blend
);
245 vl_compositor_clear_layers(&drv
->cstate
);
246 vl_compositor_set_layer_blend(&drv
->cstate
, 0, blend_state
, false);
247 upload_sampler(drv
->pipe
, sub
->sampler
, &box
, buf
->data
,
248 sub
->image
->pitches
[0], 0, 0);
249 vl_compositor_set_rgba_layer(&drv
->cstate
, &drv
->compositor
, 0, sub
->sampler
,
251 vl_compositor_set_layer_dst_area(&drv
->cstate
, 0, &dr
);
252 vl_compositor_render(&drv
->cstate
, &drv
->compositor
, surf_draw
, dirty_area
, false);
253 drv
->pipe
->delete_blend_state(drv
->pipe
, blend_state
);
256 return VA_STATUS_SUCCESS
;
260 vlVaPutSurface(VADriverContextP ctx
, VASurfaceID surface_id
, void* draw
, short srcx
, short srcy
,
261 unsigned short srcw
, unsigned short srch
, short destx
, short desty
,
262 unsigned short destw
, unsigned short desth
, VARectangle
*cliprects
,
263 unsigned int number_cliprects
, unsigned int flags
)
267 struct pipe_screen
*screen
;
268 struct pipe_resource
*tex
;
269 struct pipe_surface surf_templ
, *surf_draw
;
270 struct vl_screen
*vscreen
;
271 struct u_rect src_rect
, *dirty_area
;
272 struct u_rect dst_rect
= {destx
, destx
+ destw
, desty
, desty
+ desth
};
276 return VA_STATUS_ERROR_INVALID_CONTEXT
;
278 drv
= VL_VA_DRIVER(ctx
);
279 pipe_mutex_lock(drv
->mutex
);
280 surf
= handle_table_get(drv
->htab
, surface_id
);
282 pipe_mutex_unlock(drv
->mutex
);
283 return VA_STATUS_ERROR_INVALID_SURFACE
;
286 screen
= drv
->pipe
->screen
;
287 vscreen
= drv
->vscreen
;
289 tex
= vscreen
->texture_from_drawable(vscreen
, draw
);
291 pipe_mutex_unlock(drv
->mutex
);
292 return VA_STATUS_ERROR_INVALID_DISPLAY
;
295 dirty_area
= vscreen
->get_dirty_area(vscreen
);
297 memset(&surf_templ
, 0, sizeof(surf_templ
));
298 surf_templ
.format
= tex
->format
;
299 surf_draw
= drv
->pipe
->create_surface(drv
->pipe
, tex
, &surf_templ
);
301 pipe_resource_reference(&tex
, NULL
);
302 pipe_mutex_unlock(drv
->mutex
);
303 return VA_STATUS_ERROR_INVALID_DISPLAY
;
308 src_rect
.x1
= srcw
+ srcx
;
309 src_rect
.y1
= srch
+ srcy
;
311 vl_compositor_clear_layers(&drv
->cstate
);
312 vl_compositor_set_buffer_layer(&drv
->cstate
, &drv
->compositor
, 0, surf
->buffer
, &src_rect
, NULL
, VL_COMPOSITOR_WEAVE
);
313 vl_compositor_set_layer_dst_area(&drv
->cstate
, 0, &dst_rect
);
314 vl_compositor_render(&drv
->cstate
, &drv
->compositor
, surf_draw
, dirty_area
, true);
316 status
= vlVaPutSubpictures(surf
, drv
, surf_draw
, dirty_area
, &src_rect
, &dst_rect
);
318 pipe_mutex_unlock(drv
->mutex
);
322 screen
->flush_frontbuffer(screen
, tex
, 0, 0,
323 vscreen
->get_private(vscreen
), NULL
);
325 drv
->pipe
->flush(drv
->pipe
, NULL
, 0);
327 pipe_resource_reference(&tex
, NULL
);
328 pipe_surface_reference(&surf_draw
, NULL
);
329 pipe_mutex_unlock(drv
->mutex
);
331 return VA_STATUS_SUCCESS
;
335 vlVaLockSurface(VADriverContextP ctx
, VASurfaceID surface
, unsigned int *fourcc
,
336 unsigned int *luma_stride
, unsigned int *chroma_u_stride
, unsigned int *chroma_v_stride
,
337 unsigned int *luma_offset
, unsigned int *chroma_u_offset
, unsigned int *chroma_v_offset
,
338 unsigned int *buffer_name
, void **buffer
)
341 return VA_STATUS_ERROR_INVALID_CONTEXT
;
343 return VA_STATUS_ERROR_UNIMPLEMENTED
;
347 vlVaUnlockSurface(VADriverContextP ctx
, VASurfaceID surface
)
350 return VA_STATUS_ERROR_INVALID_CONTEXT
;
352 return VA_STATUS_ERROR_UNIMPLEMENTED
;
356 vlVaQuerySurfaceAttributes(VADriverContextP ctx
, VAConfigID config_id
,
357 VASurfaceAttrib
*attrib_list
, unsigned int *num_attribs
)
361 VASurfaceAttrib
*attribs
;
362 struct pipe_screen
*pscreen
;
365 STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats
) <= VL_VA_MAX_IMAGE_FORMATS
);
367 if (config_id
== VA_INVALID_ID
)
368 return VA_STATUS_ERROR_INVALID_CONFIG
;
370 if (!attrib_list
&& !num_attribs
)
371 return VA_STATUS_ERROR_INVALID_PARAMETER
;
374 *num_attribs
= VL_VA_MAX_IMAGE_FORMATS
+ VASurfaceAttribCount
;
375 return VA_STATUS_SUCCESS
;
379 return VA_STATUS_ERROR_INVALID_CONTEXT
;
381 drv
= VL_VA_DRIVER(ctx
);
384 return VA_STATUS_ERROR_INVALID_CONTEXT
;
386 pipe_mutex_lock(drv
->mutex
);
387 config
= handle_table_get(drv
->htab
, config_id
);
388 pipe_mutex_unlock(drv
->mutex
);
391 return VA_STATUS_ERROR_INVALID_CONFIG
;
393 pscreen
= VL_VA_PSCREEN(ctx
);
396 return VA_STATUS_ERROR_INVALID_CONTEXT
;
398 attribs
= CALLOC(VL_VA_MAX_IMAGE_FORMATS
+ VASurfaceAttribCount
,
399 sizeof(VASurfaceAttrib
));
402 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
406 /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN
407 * only for VAEntrypointVideoProc. */
408 if (config
->profile
== PIPE_VIDEO_PROFILE_UNKNOWN
) {
409 for (j
= 0; j
< ARRAY_SIZE(vpp_surface_formats
); ++j
) {
410 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
411 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
412 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
413 attribs
[i
].value
.value
.i
= PipeFormatToVaFourcc(vpp_surface_formats
[j
]);
417 /* Assume VAEntrypointVLD for now. */
418 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
419 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
420 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
421 attribs
[i
].value
.value
.i
= VA_FOURCC_NV12
;
425 attribs
[i
].type
= VASurfaceAttribMemoryType
;
426 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
427 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
428 attribs
[i
].value
.value
.i
= VA_SURFACE_ATTRIB_MEM_TYPE_VA
|
429 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
;
432 attribs
[i
].type
= VASurfaceAttribExternalBufferDescriptor
;
433 attribs
[i
].value
.type
= VAGenericValueTypePointer
;
434 attribs
[i
].flags
= VA_SURFACE_ATTRIB_SETTABLE
;
435 attribs
[i
].value
.value
.p
= NULL
; /* ignore */
438 attribs
[i
].type
= VASurfaceAttribMaxWidth
;
439 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
440 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
441 attribs
[i
].value
.value
.i
= vl_video_buffer_max_size(pscreen
);
444 attribs
[i
].type
= VASurfaceAttribMaxHeight
;
445 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
446 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
447 attribs
[i
].value
.value
.i
= vl_video_buffer_max_size(pscreen
);
450 if (i
> *num_attribs
) {
453 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED
;
457 memcpy(attrib_list
, attribs
, i
* sizeof(VASurfaceAttrib
));
460 return VA_STATUS_SUCCESS
;
464 suface_from_external_memory(VADriverContextP ctx
, vlVaSurface
*surface
,
465 VASurfaceAttribExternalBuffers
*memory_attibute
,
466 int index
, VASurfaceID
*surfaces
,
467 struct pipe_video_buffer
*templat
)
470 struct pipe_screen
*pscreen
;
471 struct pipe_resource
*resource
;
472 struct pipe_resource res_templ
;
473 struct winsys_handle whandle
;
474 struct pipe_resource
*resources
[VL_NUM_COMPONENTS
];
477 return VA_STATUS_ERROR_INVALID_PARAMETER
;
479 pscreen
= VL_VA_PSCREEN(ctx
);
480 drv
= VL_VA_DRIVER(ctx
);
482 if (!memory_attibute
|| !memory_attibute
->buffers
||
483 index
> memory_attibute
->num_buffers
)
484 return VA_STATUS_ERROR_INVALID_PARAMETER
;
486 if (surface
->templat
.width
!= memory_attibute
->width
||
487 surface
->templat
.height
!= memory_attibute
->height
||
488 memory_attibute
->num_planes
< 1)
489 return VA_STATUS_ERROR_INVALID_PARAMETER
;
491 switch (memory_attibute
->pixel_format
) {
496 if (memory_attibute
->num_planes
!= 1)
497 return VA_STATUS_ERROR_INVALID_PARAMETER
;
500 return VA_STATUS_ERROR_INVALID_PARAMETER
;
503 memset(&res_templ
, 0, sizeof(res_templ
));
504 res_templ
.target
= PIPE_TEXTURE_2D
;
505 res_templ
.last_level
= 0;
506 res_templ
.depth0
= 1;
507 res_templ
.array_size
= 1;
508 res_templ
.width0
= memory_attibute
->width
;
509 res_templ
.height0
= memory_attibute
->height
;
510 res_templ
.format
= surface
->templat
.buffer_format
;
511 res_templ
.bind
= PIPE_BIND_SAMPLER_VIEW
;
512 res_templ
.usage
= PIPE_USAGE_DEFAULT
;
514 memset(&whandle
, 0, sizeof(struct winsys_handle
));
515 whandle
.type
= DRM_API_HANDLE_TYPE_FD
;
516 whandle
.handle
= memory_attibute
->buffers
[index
];
517 whandle
.stride
= memory_attibute
->pitches
[index
];
519 resource
= pscreen
->resource_from_handle(pscreen
, &res_templ
, &whandle
,
520 PIPE_HANDLE_USAGE_READ_WRITE
);
523 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
525 memset(resources
, 0, sizeof resources
);
526 resources
[0] = resource
;
528 surface
->buffer
= vl_video_buffer_create_ex2(drv
->pipe
, templat
, resources
);
529 if (!surface
->buffer
)
530 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
532 util_dynarray_init(&surface
->subpics
);
533 surfaces
[index
] = handle_table_add(drv
->htab
, surface
);
535 if (!surfaces
[index
]) {
536 surface
->buffer
->destroy(surface
->buffer
);
537 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
540 return VA_STATUS_SUCCESS
;
544 vlVaCreateSurfaces2(VADriverContextP ctx
, unsigned int format
,
545 unsigned int width
, unsigned int height
,
546 VASurfaceID
*surfaces
, unsigned int num_surfaces
,
547 VASurfaceAttrib
*attrib_list
, unsigned int num_attribs
)
550 VASurfaceAttribExternalBuffers
*memory_attibute
;
551 struct pipe_video_buffer templat
;
552 struct pipe_screen
*pscreen
;
559 return VA_STATUS_ERROR_INVALID_CONTEXT
;
561 if (!(width
&& height
))
562 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT
;
564 drv
= VL_VA_DRIVER(ctx
);
567 return VA_STATUS_ERROR_INVALID_CONTEXT
;
569 pscreen
= VL_VA_PSCREEN(ctx
);
572 return VA_STATUS_ERROR_INVALID_CONTEXT
;
575 memory_attibute
= NULL
;
576 memory_type
= VA_SURFACE_ATTRIB_MEM_TYPE_VA
;
579 for (i
= 0; i
< num_attribs
&& attrib_list
; i
++) {
580 if ((attrib_list
[i
].type
== VASurfaceAttribPixelFormat
) &&
581 (attrib_list
[i
].flags
& VA_SURFACE_ATTRIB_SETTABLE
)) {
582 if (attrib_list
[i
].value
.type
!= VAGenericValueTypeInteger
)
583 return VA_STATUS_ERROR_INVALID_PARAMETER
;
584 expected_fourcc
= attrib_list
[i
].value
.value
.i
;
587 if ((attrib_list
[i
].type
== VASurfaceAttribMemoryType
) &&
588 (attrib_list
[i
].flags
& VA_SURFACE_ATTRIB_SETTABLE
)) {
590 if (attrib_list
[i
].value
.type
!= VAGenericValueTypeInteger
)
591 return VA_STATUS_ERROR_INVALID_PARAMETER
;
593 switch (attrib_list
[i
].value
.value
.i
) {
594 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
595 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
596 memory_type
= attrib_list
[i
].value
.value
.i
;
599 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
603 if ((attrib_list
[i
].type
== VASurfaceAttribExternalBufferDescriptor
) &&
604 (attrib_list
[i
].flags
== VA_SURFACE_ATTRIB_SETTABLE
)) {
605 if (attrib_list
[i
].value
.type
!= VAGenericValueTypePointer
)
606 return VA_STATUS_ERROR_INVALID_PARAMETER
;
607 memory_attibute
= (VASurfaceAttribExternalBuffers
*)attrib_list
[i
].value
.value
.p
;
611 if (VA_RT_FORMAT_YUV420
!= format
&&
612 VA_RT_FORMAT_YUV422
!= format
&&
613 VA_RT_FORMAT_YUV444
!= format
&&
614 VA_RT_FORMAT_RGB32
!= format
) {
615 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT
;
618 switch (memory_type
) {
619 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
621 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
622 if (!memory_attibute
)
623 return VA_STATUS_ERROR_INVALID_PARAMETER
;
625 expected_fourcc
= memory_attibute
->pixel_format
;
631 memset(&templat
, 0, sizeof(templat
));
633 if (expected_fourcc
) {
634 templat
.buffer_format
= VaFourccToPipeFormat(expected_fourcc
);
635 templat
.interlaced
= 0;
637 templat
.buffer_format
= pscreen
->get_video_param
640 PIPE_VIDEO_PROFILE_UNKNOWN
,
641 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
642 PIPE_VIDEO_CAP_PREFERED_FORMAT
644 templat
.interlaced
= pscreen
->get_video_param
647 PIPE_VIDEO_PROFILE_UNKNOWN
,
648 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
649 PIPE_VIDEO_CAP_PREFERS_INTERLACED
653 templat
.chroma_format
= ChromaToPipe(format
);
655 templat
.width
= width
;
656 templat
.height
= height
;
657 if (debug_get_option_nointerlace())
658 templat
.interlaced
= false;
660 memset(surfaces
, VA_INVALID_ID
, num_surfaces
* sizeof(VASurfaceID
));
662 pipe_mutex_lock(drv
->mutex
);
663 for (i
= 0; i
< num_surfaces
; i
++) {
664 vlVaSurface
*surf
= CALLOC(1, sizeof(vlVaSurface
));
668 surf
->templat
= templat
;
670 switch (memory_type
) {
671 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
672 /* The application will clear the TILING flag when the surface is
673 * intended to be exported as dmabuf. Adding shared flag because not
674 * null memory_attibute means VASurfaceAttribExternalBuffers is used.
676 if (memory_attibute
&&
677 !(memory_attibute
->flags
& VA_SURFACE_EXTBUF_DESC_ENABLE_TILING
))
678 templat
.bind
= PIPE_BIND_LINEAR
| PIPE_BIND_SHARED
;
680 surf
->buffer
= drv
->pipe
->create_video_buffer(drv
->pipe
, &templat
);
685 util_dynarray_init(&surf
->subpics
);
686 surfaces
[i
] = handle_table_add(drv
->htab
, surf
);
688 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
689 vaStatus
= suface_from_external_memory(ctx
, surf
, memory_attibute
, i
, surfaces
, &templat
);
690 if (vaStatus
!= VA_STATUS_SUCCESS
) {
699 pipe_mutex_unlock(drv
->mutex
);
701 return VA_STATUS_SUCCESS
;
704 pipe_mutex_unlock(drv
->mutex
);
706 vlVaDestroySurfaces(ctx
, surfaces
, i
);
708 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
712 vlVaQueryVideoProcFilters(VADriverContextP ctx
, VAContextID context
,
713 VAProcFilterType
*filters
, unsigned int *num_filters
)
715 unsigned int num
= 0;
718 return VA_STATUS_ERROR_INVALID_CONTEXT
;
720 if (!num_filters
|| !filters
)
721 return VA_STATUS_ERROR_INVALID_PARAMETER
;
723 filters
[num
++] = VAProcFilterDeinterlacing
;
727 return VA_STATUS_SUCCESS
;
731 vlVaQueryVideoProcFilterCaps(VADriverContextP ctx
, VAContextID context
,
732 VAProcFilterType type
, void *filter_caps
,
733 unsigned int *num_filter_caps
)
738 return VA_STATUS_ERROR_INVALID_CONTEXT
;
740 if (!filter_caps
|| !num_filter_caps
)
741 return VA_STATUS_ERROR_INVALID_PARAMETER
;
746 case VAProcFilterNone
:
748 case VAProcFilterDeinterlacing
: {
749 VAProcFilterCapDeinterlacing
*deint
= filter_caps
;
751 if (*num_filter_caps
< 3) {
752 *num_filter_caps
= 3;
753 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED
;
756 deint
[i
++].type
= VAProcDeinterlacingBob
;
757 deint
[i
++].type
= VAProcDeinterlacingWeave
;
758 deint
[i
++].type
= VAProcDeinterlacingMotionAdaptive
;
762 case VAProcFilterNoiseReduction
:
763 case VAProcFilterSharpening
:
764 case VAProcFilterColorBalance
:
765 case VAProcFilterSkinToneEnhancement
:
766 return VA_STATUS_ERROR_UNIMPLEMENTED
;
771 *num_filter_caps
= i
;
773 return VA_STATUS_SUCCESS
;
776 static VAProcColorStandardType vpp_input_color_standards
[] = {
777 VAProcColorStandardBT601
780 static VAProcColorStandardType vpp_output_color_standards
[] = {
781 VAProcColorStandardBT601
785 vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx
, VAContextID context
,
786 VABufferID
*filters
, unsigned int num_filters
,
787 VAProcPipelineCaps
*pipeline_cap
)
792 return VA_STATUS_ERROR_INVALID_CONTEXT
;
795 return VA_STATUS_ERROR_INVALID_PARAMETER
;
797 if (num_filters
&& !filters
)
798 return VA_STATUS_ERROR_INVALID_PARAMETER
;
800 pipeline_cap
->pipeline_flags
= 0;
801 pipeline_cap
->filter_flags
= 0;
802 pipeline_cap
->num_forward_references
= 0;
803 pipeline_cap
->num_backward_references
= 0;
804 pipeline_cap
->num_input_color_standards
= ARRAY_SIZE(vpp_input_color_standards
);
805 pipeline_cap
->input_color_standards
= vpp_input_color_standards
;
806 pipeline_cap
->num_output_color_standards
= ARRAY_SIZE(vpp_output_color_standards
);
807 pipeline_cap
->output_color_standards
= vpp_output_color_standards
;
809 for (i
= 0; i
< num_filters
; i
++) {
810 vlVaBuffer
*buf
= handle_table_get(VL_VA_DRIVER(ctx
)->htab
, filters
[i
]);
811 VAProcFilterParameterBufferBase
*filter
;
813 if (!buf
|| buf
->type
!= VAProcFilterParameterBufferType
)
814 return VA_STATUS_ERROR_INVALID_BUFFER
;
817 switch (filter
->type
) {
818 case VAProcFilterDeinterlacing
: {
819 VAProcFilterParameterBufferDeinterlacing
*deint
= buf
->data
;
820 if (deint
->algorithm
== VAProcDeinterlacingMotionAdaptive
) {
821 pipeline_cap
->num_forward_references
= 1;
822 pipeline_cap
->num_backward_references
= 2;
827 return VA_STATUS_ERROR_UNIMPLEMENTED
;
831 return VA_STATUS_SUCCESS
;