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"
39 #include "util/u_video.h"
41 #include "vl/vl_compositor.h"
42 #include "vl/vl_video_buffer.h"
43 #include "vl/vl_winsys.h"
45 #include "va_private.h"
47 #include <va/va_drmcommon.h>
48 #include <drm-uapi/drm_fourcc.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 mtx_lock(&drv
->mutex
);
74 for (i
= 0; i
< num_surfaces
; ++i
) {
75 vlVaSurface
*surf
= handle_table_get(drv
->htab
, surface_list
[i
]);
77 mtx_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 mtx_unlock(&drv
->mutex
);
88 return VA_STATUS_SUCCESS
;
92 vlVaSyncSurface(VADriverContextP ctx
, VASurfaceID render_target
)
99 return VA_STATUS_ERROR_INVALID_CONTEXT
;
101 drv
= VL_VA_DRIVER(ctx
);
103 return VA_STATUS_ERROR_INVALID_CONTEXT
;
105 mtx_lock(&drv
->mutex
);
106 surf
= handle_table_get(drv
->htab
, render_target
);
108 if (!surf
|| !surf
->buffer
) {
109 mtx_unlock(&drv
->mutex
);
110 return VA_STATUS_ERROR_INVALID_SURFACE
;
113 if (!surf
->feedback
) {
114 // No outstanding operation: nothing to do.
115 mtx_unlock(&drv
->mutex
);
116 return VA_STATUS_SUCCESS
;
119 context
= handle_table_get(drv
->htab
, surf
->ctx
);
121 mtx_unlock(&drv
->mutex
);
122 return VA_STATUS_ERROR_INVALID_CONTEXT
;
125 if (context
->decoder
->entrypoint
== PIPE_VIDEO_ENTRYPOINT_ENCODE
) {
126 if (u_reduce_video_profile(context
->templat
.profile
) == PIPE_VIDEO_FORMAT_MPEG4_AVC
) {
128 if (context
->desc
.h264enc
.frame_num_cnt
>= surf
->frame_num_cnt
)
129 frame_diff
= context
->desc
.h264enc
.frame_num_cnt
- surf
->frame_num_cnt
;
131 frame_diff
= 0xFFFFFFFF - surf
->frame_num_cnt
+ 1 + context
->desc
.h264enc
.frame_num_cnt
;
132 if ((frame_diff
== 0) &&
133 (surf
->force_flushed
== false) &&
134 (context
->desc
.h264enc
.frame_num_cnt
% 2 != 0)) {
135 context
->decoder
->flush(context
->decoder
);
136 context
->first_single_submitted
= true;
139 context
->decoder
->get_feedback(context
->decoder
, surf
->feedback
, &(surf
->coded_buf
->coded_size
));
140 surf
->feedback
= NULL
;
142 mtx_unlock(&drv
->mutex
);
143 return VA_STATUS_SUCCESS
;
147 vlVaQuerySurfaceStatus(VADriverContextP ctx
, VASurfaceID render_target
, VASurfaceStatus
*status
)
151 vlVaContext
*context
;
154 return VA_STATUS_ERROR_INVALID_CONTEXT
;
156 drv
= VL_VA_DRIVER(ctx
);
158 return VA_STATUS_ERROR_INVALID_CONTEXT
;
160 mtx_lock(&drv
->mutex
);
162 surf
= handle_table_get(drv
->htab
, render_target
);
163 if (!surf
|| !surf
->buffer
) {
164 mtx_unlock(&drv
->mutex
);
165 return VA_STATUS_ERROR_INVALID_SURFACE
;
168 context
= handle_table_get(drv
->htab
, surf
->ctx
);
170 mtx_unlock(&drv
->mutex
);
171 return VA_STATUS_ERROR_INVALID_CONTEXT
;
174 if (context
->decoder
->entrypoint
== PIPE_VIDEO_ENTRYPOINT_ENCODE
) {
175 if(surf
->feedback
== NULL
)
176 *status
=VASurfaceReady
;
178 *status
=VASurfaceRendering
;
181 mtx_unlock(&drv
->mutex
);
183 return VA_STATUS_SUCCESS
;
187 vlVaQuerySurfaceError(VADriverContextP ctx
, VASurfaceID render_target
, VAStatus error_status
, void **error_info
)
190 return VA_STATUS_ERROR_INVALID_CONTEXT
;
192 return VA_STATUS_ERROR_UNIMPLEMENTED
;
196 upload_sampler(struct pipe_context
*pipe
, struct pipe_sampler_view
*dst
,
197 const struct pipe_box
*dst_box
, const void *src
, unsigned src_stride
,
198 unsigned src_x
, unsigned src_y
)
200 struct pipe_transfer
*transfer
;
203 map
= pipe
->transfer_map(pipe
, dst
->texture
, 0, PIPE_TRANSFER_WRITE
,
208 util_copy_rect(map
, dst
->texture
->format
, transfer
->stride
, 0, 0,
209 dst_box
->width
, dst_box
->height
,
210 src
, src_stride
, src_x
, src_y
);
212 pipe
->transfer_unmap(pipe
, transfer
);
216 vlVaPutSubpictures(vlVaSurface
*surf
, vlVaDriver
*drv
,
217 struct pipe_surface
*surf_draw
, struct u_rect
*dirty_area
,
218 struct u_rect
*src_rect
, struct u_rect
*dst_rect
)
223 if (!(surf
->subpics
.data
|| surf
->subpics
.size
))
224 return VA_STATUS_SUCCESS
;
226 for (i
= 0; i
< surf
->subpics
.size
/sizeof(vlVaSubpicture
*); i
++) {
227 struct pipe_blend_state blend
;
231 struct u_rect
*s
, *d
, sr
, dr
, c
;
234 sub
= ((vlVaSubpicture
**)surf
->subpics
.data
)[i
];
238 buf
= handle_table_get(drv
->htab
, sub
->image
->buf
);
240 return VA_STATUS_ERROR_INVALID_IMAGE
;
245 box
.width
= sub
->dst_rect
.x1
- sub
->dst_rect
.x0
;
246 box
.height
= sub
->dst_rect
.y1
- sub
->dst_rect
.y0
;
255 c
.x0
= MAX2(d
->x0
, s
->x0
);
256 c
.y0
= MAX2(d
->y0
, s
->y0
);
257 c
.x1
= MIN2(d
->x0
+ dw
, src_rect
->x1
);
258 c
.y1
= MIN2(d
->y0
+ dh
, src_rect
->y1
);
259 sr
.x0
= s
->x0
+ (c
.x0
- d
->x0
)*(sw
/(float)dw
);
260 sr
.y0
= s
->y0
+ (c
.y0
- d
->y0
)*(sh
/(float)dh
);
261 sr
.x1
= s
->x0
+ (c
.x1
- d
->x0
)*(sw
/(float)dw
);
262 sr
.y1
= s
->y0
+ (c
.y1
- d
->y0
)*(sh
/(float)dh
);
270 dr
.x0
= d
->x0
+ c
.x0
*(dw
/(float)sw
);
271 dr
.y0
= d
->y0
+ c
.y0
*(dh
/(float)sh
);
272 dr
.x1
= d
->x0
+ c
.x1
*(dw
/(float)sw
);
273 dr
.y1
= d
->y0
+ c
.y1
*(dh
/(float)sh
);
275 memset(&blend
, 0, sizeof(blend
));
276 blend
.independent_blend_enable
= 0;
277 blend
.rt
[0].blend_enable
= 1;
278 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
279 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
280 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ZERO
;
281 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
282 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
283 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
284 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
285 blend
.logicop_enable
= 0;
286 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
288 blend_state
= drv
->pipe
->create_blend_state(drv
->pipe
, &blend
);
290 vl_compositor_clear_layers(&drv
->cstate
);
291 vl_compositor_set_layer_blend(&drv
->cstate
, 0, blend_state
, false);
292 upload_sampler(drv
->pipe
, sub
->sampler
, &box
, buf
->data
,
293 sub
->image
->pitches
[0], 0, 0);
294 vl_compositor_set_rgba_layer(&drv
->cstate
, &drv
->compositor
, 0, sub
->sampler
,
296 vl_compositor_set_layer_dst_area(&drv
->cstate
, 0, &dr
);
297 vl_compositor_render(&drv
->cstate
, &drv
->compositor
, surf_draw
, dirty_area
, false);
298 drv
->pipe
->delete_blend_state(drv
->pipe
, blend_state
);
301 return VA_STATUS_SUCCESS
;
305 vlVaPutSurface(VADriverContextP ctx
, VASurfaceID surface_id
, void* draw
, short srcx
, short srcy
,
306 unsigned short srcw
, unsigned short srch
, short destx
, short desty
,
307 unsigned short destw
, unsigned short desth
, VARectangle
*cliprects
,
308 unsigned int number_cliprects
, unsigned int flags
)
312 struct pipe_screen
*screen
;
313 struct pipe_resource
*tex
;
314 struct pipe_surface surf_templ
, *surf_draw
;
315 struct vl_screen
*vscreen
;
316 struct u_rect src_rect
, *dirty_area
;
317 struct u_rect dst_rect
= {destx
, destx
+ destw
, desty
, desty
+ desth
};
318 enum pipe_format format
;
322 return VA_STATUS_ERROR_INVALID_CONTEXT
;
324 drv
= VL_VA_DRIVER(ctx
);
325 mtx_lock(&drv
->mutex
);
326 surf
= handle_table_get(drv
->htab
, surface_id
);
328 mtx_unlock(&drv
->mutex
);
329 return VA_STATUS_ERROR_INVALID_SURFACE
;
332 screen
= drv
->pipe
->screen
;
333 vscreen
= drv
->vscreen
;
335 tex
= vscreen
->texture_from_drawable(vscreen
, draw
);
337 mtx_unlock(&drv
->mutex
);
338 return VA_STATUS_ERROR_INVALID_DISPLAY
;
341 dirty_area
= vscreen
->get_dirty_area(vscreen
);
343 memset(&surf_templ
, 0, sizeof(surf_templ
));
344 surf_templ
.format
= tex
->format
;
345 surf_draw
= drv
->pipe
->create_surface(drv
->pipe
, tex
, &surf_templ
);
347 pipe_resource_reference(&tex
, NULL
);
348 mtx_unlock(&drv
->mutex
);
349 return VA_STATUS_ERROR_INVALID_DISPLAY
;
354 src_rect
.x1
= srcw
+ srcx
;
355 src_rect
.y1
= srch
+ srcy
;
357 format
= surf
->buffer
->buffer_format
;
359 vl_compositor_clear_layers(&drv
->cstate
);
361 if (format
== PIPE_FORMAT_B8G8R8A8_UNORM
|| format
== PIPE_FORMAT_B8G8R8X8_UNORM
||
362 format
== PIPE_FORMAT_R8G8B8A8_UNORM
|| format
== PIPE_FORMAT_R8G8B8X8_UNORM
) {
363 struct pipe_sampler_view
**views
;
365 views
= surf
->buffer
->get_sampler_view_planes(surf
->buffer
);
366 vl_compositor_set_rgba_layer(&drv
->cstate
, &drv
->compositor
, 0, views
[0], &src_rect
, NULL
, NULL
);
368 vl_compositor_set_buffer_layer(&drv
->cstate
, &drv
->compositor
, 0, surf
->buffer
, &src_rect
, NULL
, VL_COMPOSITOR_WEAVE
);
370 vl_compositor_set_layer_dst_area(&drv
->cstate
, 0, &dst_rect
);
371 vl_compositor_render(&drv
->cstate
, &drv
->compositor
, surf_draw
, dirty_area
, true);
373 status
= vlVaPutSubpictures(surf
, drv
, surf_draw
, dirty_area
, &src_rect
, &dst_rect
);
375 mtx_unlock(&drv
->mutex
);
379 /* flush before calling flush_frontbuffer so that rendering is flushed
380 * to back buffer so the texture can be copied in flush_frontbuffer
382 drv
->pipe
->flush(drv
->pipe
, NULL
, 0);
384 screen
->flush_frontbuffer(screen
, tex
, 0, 0,
385 vscreen
->get_private(vscreen
), NULL
);
388 pipe_resource_reference(&tex
, NULL
);
389 pipe_surface_reference(&surf_draw
, NULL
);
390 mtx_unlock(&drv
->mutex
);
392 return VA_STATUS_SUCCESS
;
396 vlVaLockSurface(VADriverContextP ctx
, VASurfaceID surface
, unsigned int *fourcc
,
397 unsigned int *luma_stride
, unsigned int *chroma_u_stride
, unsigned int *chroma_v_stride
,
398 unsigned int *luma_offset
, unsigned int *chroma_u_offset
, unsigned int *chroma_v_offset
,
399 unsigned int *buffer_name
, void **buffer
)
402 return VA_STATUS_ERROR_INVALID_CONTEXT
;
404 return VA_STATUS_ERROR_UNIMPLEMENTED
;
408 vlVaUnlockSurface(VADriverContextP ctx
, VASurfaceID surface
)
411 return VA_STATUS_ERROR_INVALID_CONTEXT
;
413 return VA_STATUS_ERROR_UNIMPLEMENTED
;
417 vlVaQuerySurfaceAttributes(VADriverContextP ctx
, VAConfigID config_id
,
418 VASurfaceAttrib
*attrib_list
, unsigned int *num_attribs
)
422 VASurfaceAttrib
*attribs
;
423 struct pipe_screen
*pscreen
;
426 STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats
) <= VL_VA_MAX_IMAGE_FORMATS
);
428 if (config_id
== VA_INVALID_ID
)
429 return VA_STATUS_ERROR_INVALID_CONFIG
;
431 if (!attrib_list
&& !num_attribs
)
432 return VA_STATUS_ERROR_INVALID_PARAMETER
;
435 *num_attribs
= VL_VA_MAX_IMAGE_FORMATS
+ VASurfaceAttribCount
;
436 return VA_STATUS_SUCCESS
;
440 return VA_STATUS_ERROR_INVALID_CONTEXT
;
442 drv
= VL_VA_DRIVER(ctx
);
445 return VA_STATUS_ERROR_INVALID_CONTEXT
;
447 mtx_lock(&drv
->mutex
);
448 config
= handle_table_get(drv
->htab
, config_id
);
449 mtx_unlock(&drv
->mutex
);
452 return VA_STATUS_ERROR_INVALID_CONFIG
;
454 pscreen
= VL_VA_PSCREEN(ctx
);
457 return VA_STATUS_ERROR_INVALID_CONTEXT
;
459 attribs
= CALLOC(VL_VA_MAX_IMAGE_FORMATS
+ VASurfaceAttribCount
,
460 sizeof(VASurfaceAttrib
));
463 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
467 /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN
468 * only for VAEntrypointVideoProc. */
469 if (config
->profile
== PIPE_VIDEO_PROFILE_UNKNOWN
) {
470 if (config
->rt_format
& VA_RT_FORMAT_RGB32
) {
471 for (j
= 0; j
< ARRAY_SIZE(vpp_surface_formats
); ++j
) {
472 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
473 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
474 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
475 attribs
[i
].value
.value
.i
= PipeFormatToVaFourcc(vpp_surface_formats
[j
]);
480 if (config
->rt_format
& VA_RT_FORMAT_YUV420
) {
481 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
482 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
483 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
484 attribs
[i
].value
.value
.i
= VA_FOURCC_NV12
;
487 if (config
->rt_format
& VA_RT_FORMAT_YUV420_10BPP
) {
488 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
489 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
490 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
491 attribs
[i
].value
.value
.i
= VA_FOURCC_P010
;
493 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
494 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
495 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
496 attribs
[i
].value
.value
.i
= VA_FOURCC_P016
;
500 attribs
[i
].type
= VASurfaceAttribMemoryType
;
501 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
502 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
503 attribs
[i
].value
.value
.i
= VA_SURFACE_ATTRIB_MEM_TYPE_VA
|
504 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
;
507 attribs
[i
].type
= VASurfaceAttribExternalBufferDescriptor
;
508 attribs
[i
].value
.type
= VAGenericValueTypePointer
;
509 attribs
[i
].flags
= VA_SURFACE_ATTRIB_SETTABLE
;
510 attribs
[i
].value
.value
.p
= NULL
; /* ignore */
513 if (config
->entrypoint
!= PIPE_VIDEO_ENTRYPOINT_UNKNOWN
) {
514 attribs
[i
].type
= VASurfaceAttribMaxWidth
;
515 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
516 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
517 attribs
[i
].value
.value
.i
=
518 pscreen
->get_video_param(pscreen
,
519 config
->profile
, config
->entrypoint
,
520 PIPE_VIDEO_CAP_MAX_WIDTH
);
523 attribs
[i
].type
= VASurfaceAttribMaxHeight
;
524 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
525 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
526 attribs
[i
].value
.value
.i
=
527 pscreen
->get_video_param(pscreen
,
528 config
->profile
, config
->entrypoint
,
529 PIPE_VIDEO_CAP_MAX_HEIGHT
);
532 attribs
[i
].type
= VASurfaceAttribMaxWidth
;
533 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
534 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
535 attribs
[i
].value
.value
.i
= vl_video_buffer_max_size(pscreen
);
538 attribs
[i
].type
= VASurfaceAttribMaxHeight
;
539 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
540 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
541 attribs
[i
].value
.value
.i
= vl_video_buffer_max_size(pscreen
);
545 if (i
> *num_attribs
) {
548 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED
;
552 memcpy(attrib_list
, attribs
, i
* sizeof(VASurfaceAttrib
));
555 return VA_STATUS_SUCCESS
;
559 surface_from_external_memory(VADriverContextP ctx
, vlVaSurface
*surface
,
560 VASurfaceAttribExternalBuffers
*memory_attribute
,
561 unsigned index
, struct pipe_video_buffer
*templat
)
564 struct pipe_screen
*pscreen
;
565 struct pipe_resource res_templ
;
566 struct winsys_handle whandle
;
567 struct pipe_resource
*resources
[VL_NUM_COMPONENTS
];
568 const enum pipe_format
*resource_formats
= NULL
;
572 pscreen
= VL_VA_PSCREEN(ctx
);
573 drv
= VL_VA_DRIVER(ctx
);
575 if (!memory_attribute
|| !memory_attribute
->buffers
||
576 index
> memory_attribute
->num_buffers
)
577 return VA_STATUS_ERROR_INVALID_PARAMETER
;
579 if (surface
->templat
.width
!= memory_attribute
->width
||
580 surface
->templat
.height
!= memory_attribute
->height
||
581 memory_attribute
->num_planes
< 1)
582 return VA_STATUS_ERROR_INVALID_PARAMETER
;
584 if (memory_attribute
->num_planes
> VL_NUM_COMPONENTS
)
585 return VA_STATUS_ERROR_INVALID_PARAMETER
;
587 resource_formats
= vl_video_buffer_formats(pscreen
, templat
->buffer_format
);
588 if (!resource_formats
)
589 return VA_STATUS_ERROR_INVALID_PARAMETER
;
591 memset(&res_templ
, 0, sizeof(res_templ
));
592 res_templ
.target
= PIPE_TEXTURE_2D
;
593 res_templ
.last_level
= 0;
594 res_templ
.depth0
= 1;
595 res_templ
.array_size
= 1;
596 res_templ
.width0
= memory_attribute
->width
;
597 res_templ
.height0
= memory_attribute
->height
;
598 res_templ
.bind
= PIPE_BIND_SAMPLER_VIEW
;
599 res_templ
.usage
= PIPE_USAGE_DEFAULT
;
601 memset(&whandle
, 0, sizeof(struct winsys_handle
));
602 whandle
.type
= WINSYS_HANDLE_TYPE_FD
;
603 whandle
.handle
= memory_attribute
->buffers
[index
];
605 // Create a resource for each plane.
606 memset(resources
, 0, sizeof resources
);
607 for (i
= 0; i
< memory_attribute
->num_planes
; i
++) {
608 res_templ
.format
= resource_formats
[i
];
609 if (res_templ
.format
== PIPE_FORMAT_NONE
) {
610 result
= VA_STATUS_ERROR_INVALID_PARAMETER
;
614 whandle
.stride
= memory_attribute
->pitches
[i
];
615 whandle
.offset
= memory_attribute
->offsets
[i
];
616 resources
[i
] = pscreen
->resource_from_handle(pscreen
, &res_templ
, &whandle
,
617 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE
);
619 result
= VA_STATUS_ERROR_ALLOCATION_FAILED
;
624 surface
->buffer
= vl_video_buffer_create_ex2(drv
->pipe
, templat
, resources
);
625 if (!surface
->buffer
) {
626 result
= VA_STATUS_ERROR_ALLOCATION_FAILED
;
629 return VA_STATUS_SUCCESS
;
632 for (i
= 0; i
< VL_NUM_COMPONENTS
; i
++)
633 pipe_resource_reference(&resources
[i
], NULL
);
638 vlVaHandleSurfaceAllocate(vlVaDriver
*drv
, vlVaSurface
*surface
,
639 struct pipe_video_buffer
*templat
)
641 struct pipe_surface
**surfaces
;
644 surface
->buffer
= drv
->pipe
->create_video_buffer(drv
->pipe
, templat
);
645 if (!surface
->buffer
)
646 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
648 surfaces
= surface
->buffer
->get_surfaces(surface
->buffer
);
649 for (i
= 0; i
< VL_MAX_SURFACES
; ++i
) {
650 union pipe_color_union c
= {};
655 if (i
> !!surface
->buffer
->interlaced
)
656 c
.f
[0] = c
.f
[1] = c
.f
[2] = c
.f
[3] = 0.5f
;
658 drv
->pipe
->clear_render_target(drv
->pipe
, surfaces
[i
], &c
, 0, 0,
659 surfaces
[i
]->width
, surfaces
[i
]->height
,
662 drv
->pipe
->flush(drv
->pipe
, NULL
, 0);
664 return VA_STATUS_SUCCESS
;
668 vlVaCreateSurfaces2(VADriverContextP ctx
, unsigned int format
,
669 unsigned int width
, unsigned int height
,
670 VASurfaceID
*surfaces
, unsigned int num_surfaces
,
671 VASurfaceAttrib
*attrib_list
, unsigned int num_attribs
)
674 VASurfaceAttribExternalBuffers
*memory_attribute
;
675 struct pipe_video_buffer templat
;
676 struct pipe_screen
*pscreen
;
684 return VA_STATUS_ERROR_INVALID_CONTEXT
;
686 if (!(width
&& height
))
687 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT
;
689 drv
= VL_VA_DRIVER(ctx
);
692 return VA_STATUS_ERROR_INVALID_CONTEXT
;
694 pscreen
= VL_VA_PSCREEN(ctx
);
697 return VA_STATUS_ERROR_INVALID_CONTEXT
;
700 memory_attribute
= NULL
;
701 memory_type
= VA_SURFACE_ATTRIB_MEM_TYPE_VA
;
704 for (i
= 0; i
< num_attribs
&& attrib_list
; i
++) {
705 if ((attrib_list
[i
].type
== VASurfaceAttribPixelFormat
) &&
706 (attrib_list
[i
].flags
& VA_SURFACE_ATTRIB_SETTABLE
)) {
707 if (attrib_list
[i
].value
.type
!= VAGenericValueTypeInteger
)
708 return VA_STATUS_ERROR_INVALID_PARAMETER
;
709 expected_fourcc
= attrib_list
[i
].value
.value
.i
;
712 if ((attrib_list
[i
].type
== VASurfaceAttribMemoryType
) &&
713 (attrib_list
[i
].flags
& VA_SURFACE_ATTRIB_SETTABLE
)) {
715 if (attrib_list
[i
].value
.type
!= VAGenericValueTypeInteger
)
716 return VA_STATUS_ERROR_INVALID_PARAMETER
;
718 switch (attrib_list
[i
].value
.value
.i
) {
719 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
720 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
721 memory_type
= attrib_list
[i
].value
.value
.i
;
724 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
728 if ((attrib_list
[i
].type
== VASurfaceAttribExternalBufferDescriptor
) &&
729 (attrib_list
[i
].flags
== VA_SURFACE_ATTRIB_SETTABLE
)) {
730 if (attrib_list
[i
].value
.type
!= VAGenericValueTypePointer
)
731 return VA_STATUS_ERROR_INVALID_PARAMETER
;
732 memory_attribute
= (VASurfaceAttribExternalBuffers
*)attrib_list
[i
].value
.value
.p
;
736 if (VA_RT_FORMAT_YUV420
!= format
&&
737 VA_RT_FORMAT_YUV422
!= format
&&
738 VA_RT_FORMAT_YUV444
!= format
&&
739 VA_RT_FORMAT_YUV420_10BPP
!= format
&&
740 VA_RT_FORMAT_RGB32
!= format
) {
741 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT
;
744 switch (memory_type
) {
745 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
747 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
748 if (!memory_attribute
)
749 return VA_STATUS_ERROR_INVALID_PARAMETER
;
751 expected_fourcc
= memory_attribute
->pixel_format
;
757 memset(&templat
, 0, sizeof(templat
));
759 templat
.buffer_format
= pscreen
->get_video_param(
761 PIPE_VIDEO_PROFILE_UNKNOWN
,
762 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
763 PIPE_VIDEO_CAP_PREFERED_FORMAT
765 templat
.interlaced
= pscreen
->get_video_param(
767 PIPE_VIDEO_PROFILE_UNKNOWN
,
768 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
769 PIPE_VIDEO_CAP_PREFERS_INTERLACED
772 if (expected_fourcc
) {
773 enum pipe_format expected_format
= VaFourccToPipeFormat(expected_fourcc
);
775 if (expected_format
!= templat
.buffer_format
|| memory_attribute
)
776 templat
.interlaced
= 0;
778 templat
.buffer_format
= expected_format
;
781 templat
.chroma_format
= ChromaToPipe(format
);
783 templat
.width
= width
;
784 templat
.height
= height
;
786 memset(surfaces
, VA_INVALID_ID
, num_surfaces
* sizeof(VASurfaceID
));
788 mtx_lock(&drv
->mutex
);
789 for (i
= 0; i
< num_surfaces
; i
++) {
790 surf
= CALLOC(1, sizeof(vlVaSurface
));
792 vaStatus
= VA_STATUS_ERROR_ALLOCATION_FAILED
;
796 surf
->templat
= templat
;
798 switch (memory_type
) {
799 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
800 /* The application will clear the TILING flag when the surface is
801 * intended to be exported as dmabuf. Adding shared flag because not
802 * null memory_attribute means VASurfaceAttribExternalBuffers is used.
804 if (memory_attribute
&&
805 !(memory_attribute
->flags
& VA_SURFACE_EXTBUF_DESC_ENABLE_TILING
))
806 templat
.bind
= PIPE_BIND_LINEAR
| PIPE_BIND_SHARED
;
808 vaStatus
= vlVaHandleSurfaceAllocate(drv
, surf
, &templat
);
809 if (vaStatus
!= VA_STATUS_SUCCESS
)
813 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
814 vaStatus
= surface_from_external_memory(ctx
, surf
, memory_attribute
, i
, &templat
);
815 if (vaStatus
!= VA_STATUS_SUCCESS
)
823 util_dynarray_init(&surf
->subpics
, NULL
);
824 surfaces
[i
] = handle_table_add(drv
->htab
, surf
);
826 vaStatus
= VA_STATUS_ERROR_ALLOCATION_FAILED
;
830 mtx_unlock(&drv
->mutex
);
832 return VA_STATUS_SUCCESS
;
835 surf
->buffer
->destroy(surf
->buffer
);
841 mtx_unlock(&drv
->mutex
);
843 vlVaDestroySurfaces(ctx
, surfaces
, i
);
849 vlVaQueryVideoProcFilters(VADriverContextP ctx
, VAContextID context
,
850 VAProcFilterType
*filters
, unsigned int *num_filters
)
852 unsigned int num
= 0;
855 return VA_STATUS_ERROR_INVALID_CONTEXT
;
857 if (!num_filters
|| !filters
)
858 return VA_STATUS_ERROR_INVALID_PARAMETER
;
860 filters
[num
++] = VAProcFilterDeinterlacing
;
864 return VA_STATUS_SUCCESS
;
868 vlVaQueryVideoProcFilterCaps(VADriverContextP ctx
, VAContextID context
,
869 VAProcFilterType type
, void *filter_caps
,
870 unsigned int *num_filter_caps
)
875 return VA_STATUS_ERROR_INVALID_CONTEXT
;
877 if (!filter_caps
|| !num_filter_caps
)
878 return VA_STATUS_ERROR_INVALID_PARAMETER
;
883 case VAProcFilterNone
:
885 case VAProcFilterDeinterlacing
: {
886 VAProcFilterCapDeinterlacing
*deint
= filter_caps
;
888 if (*num_filter_caps
< 3) {
889 *num_filter_caps
= 3;
890 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED
;
893 deint
[i
++].type
= VAProcDeinterlacingBob
;
894 deint
[i
++].type
= VAProcDeinterlacingWeave
;
895 deint
[i
++].type
= VAProcDeinterlacingMotionAdaptive
;
899 case VAProcFilterNoiseReduction
:
900 case VAProcFilterSharpening
:
901 case VAProcFilterColorBalance
:
902 case VAProcFilterSkinToneEnhancement
:
903 return VA_STATUS_ERROR_UNIMPLEMENTED
;
908 *num_filter_caps
= i
;
910 return VA_STATUS_SUCCESS
;
913 static VAProcColorStandardType vpp_input_color_standards
[] = {
914 VAProcColorStandardBT601
917 static VAProcColorStandardType vpp_output_color_standards
[] = {
918 VAProcColorStandardBT601
922 vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx
, VAContextID context
,
923 VABufferID
*filters
, unsigned int num_filters
,
924 VAProcPipelineCaps
*pipeline_cap
)
929 return VA_STATUS_ERROR_INVALID_CONTEXT
;
932 return VA_STATUS_ERROR_INVALID_PARAMETER
;
934 if (num_filters
&& !filters
)
935 return VA_STATUS_ERROR_INVALID_PARAMETER
;
937 pipeline_cap
->pipeline_flags
= 0;
938 pipeline_cap
->filter_flags
= 0;
939 pipeline_cap
->num_forward_references
= 0;
940 pipeline_cap
->num_backward_references
= 0;
941 pipeline_cap
->num_input_color_standards
= ARRAY_SIZE(vpp_input_color_standards
);
942 pipeline_cap
->input_color_standards
= vpp_input_color_standards
;
943 pipeline_cap
->num_output_color_standards
= ARRAY_SIZE(vpp_output_color_standards
);
944 pipeline_cap
->output_color_standards
= vpp_output_color_standards
;
946 for (i
= 0; i
< num_filters
; i
++) {
947 vlVaBuffer
*buf
= handle_table_get(VL_VA_DRIVER(ctx
)->htab
, filters
[i
]);
948 VAProcFilterParameterBufferBase
*filter
;
950 if (!buf
|| buf
->type
!= VAProcFilterParameterBufferType
)
951 return VA_STATUS_ERROR_INVALID_BUFFER
;
954 switch (filter
->type
) {
955 case VAProcFilterDeinterlacing
: {
956 VAProcFilterParameterBufferDeinterlacing
*deint
= buf
->data
;
957 if (deint
->algorithm
== VAProcDeinterlacingMotionAdaptive
) {
958 pipeline_cap
->num_forward_references
= 2;
959 pipeline_cap
->num_backward_references
= 1;
964 return VA_STATUS_ERROR_UNIMPLEMENTED
;
968 return VA_STATUS_SUCCESS
;
971 #if VA_CHECK_VERSION(1, 1, 0)
973 vlVaExportSurfaceHandle(VADriverContextP ctx
,
974 VASurfaceID surface_id
,
981 struct pipe_surface
**surfaces
;
982 struct pipe_screen
*screen
;
987 VADRMPRIMESurfaceDescriptor
*desc
= descriptor
;
989 if (mem_type
!= VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2
)
990 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
991 if (flags
& VA_EXPORT_SURFACE_COMPOSED_LAYERS
)
992 return VA_STATUS_ERROR_INVALID_SURFACE
;
994 drv
= VL_VA_DRIVER(ctx
);
995 screen
= VL_VA_PSCREEN(ctx
);
996 mtx_lock(&drv
->mutex
);
998 surf
= handle_table_get(drv
->htab
, surface_id
);
999 if (!surf
|| !surf
->buffer
) {
1000 mtx_unlock(&drv
->mutex
);
1001 return VA_STATUS_ERROR_INVALID_SURFACE
;
1004 if (surf
->buffer
->interlaced
) {
1005 struct pipe_video_buffer
*interlaced
= surf
->buffer
;
1006 struct u_rect src_rect
, dst_rect
;
1008 surf
->templat
.interlaced
= false;
1010 ret
= vlVaHandleSurfaceAllocate(drv
, surf
, &surf
->templat
);
1011 if (ret
!= VA_STATUS_SUCCESS
) {
1012 mtx_unlock(&drv
->mutex
);
1013 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
1016 src_rect
.x0
= dst_rect
.x0
= 0;
1017 src_rect
.y0
= dst_rect
.y0
= 0;
1018 src_rect
.x1
= dst_rect
.x1
= surf
->templat
.width
;
1019 src_rect
.y1
= dst_rect
.y1
= surf
->templat
.height
;
1021 vl_compositor_yuv_deint_full(&drv
->cstate
, &drv
->compositor
,
1022 interlaced
, surf
->buffer
,
1023 &src_rect
, &dst_rect
,
1024 VL_COMPOSITOR_WEAVE
);
1026 interlaced
->destroy(interlaced
);
1029 surfaces
= surf
->buffer
->get_surfaces(surf
->buffer
);
1032 if (flags
& VA_EXPORT_SURFACE_WRITE_ONLY
)
1033 usage
|= PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE
;
1035 desc
->fourcc
= PipeFormatToVaFourcc(surf
->buffer
->buffer_format
);
1036 desc
->width
= surf
->buffer
->width
;
1037 desc
->height
= surf
->buffer
->height
;
1039 for (p
= 0; p
< VL_MAX_SURFACES
; p
++) {
1040 struct winsys_handle whandle
;
1041 struct pipe_resource
*resource
;
1042 uint32_t drm_format
;
1047 resource
= surfaces
[p
]->texture
;
1049 switch (resource
->format
) {
1050 case PIPE_FORMAT_R8_UNORM
:
1051 drm_format
= DRM_FORMAT_R8
;
1053 case PIPE_FORMAT_R8G8_UNORM
:
1054 drm_format
= DRM_FORMAT_GR88
;
1056 case PIPE_FORMAT_R16_UNORM
:
1057 drm_format
= DRM_FORMAT_R16
;
1059 case PIPE_FORMAT_R16G16_UNORM
:
1060 drm_format
= DRM_FORMAT_GR1616
;
1062 case PIPE_FORMAT_B8G8R8A8_UNORM
:
1063 drm_format
= DRM_FORMAT_ARGB8888
;
1065 case PIPE_FORMAT_R8G8B8A8_UNORM
:
1066 drm_format
= DRM_FORMAT_ABGR8888
;
1068 case PIPE_FORMAT_B8G8R8X8_UNORM
:
1069 drm_format
= DRM_FORMAT_XRGB8888
;
1071 case PIPE_FORMAT_R8G8B8X8_UNORM
:
1072 drm_format
= DRM_FORMAT_XBGR8888
;
1075 ret
= VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
1079 memset(&whandle
, 0, sizeof(whandle
));
1080 whandle
.type
= WINSYS_HANDLE_TYPE_FD
;
1082 if (!screen
->resource_get_handle(screen
, drv
->pipe
, resource
,
1084 ret
= VA_STATUS_ERROR_INVALID_SURFACE
;
1088 desc
->objects
[p
].fd
= (int)whandle
.handle
;
1089 desc
->objects
[p
].size
= 0;
1090 desc
->objects
[p
].drm_format_modifier
= whandle
.modifier
;
1092 desc
->layers
[p
].drm_format
= drm_format
;
1093 desc
->layers
[p
].num_planes
= 1;
1094 desc
->layers
[p
].object_index
[0] = p
;
1095 desc
->layers
[p
].offset
[0] = whandle
.offset
;
1096 desc
->layers
[p
].pitch
[0] = whandle
.stride
;
1099 desc
->num_objects
= p
;
1100 desc
->num_layers
= p
;
1102 mtx_unlock(&drv
->mutex
);
1104 return VA_STATUS_SUCCESS
;
1107 for (i
= 0; i
< p
; i
++)
1108 close(desc
->objects
[i
].fd
);
1110 mtx_unlock(&drv
->mutex
);