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
)
150 return VA_STATUS_ERROR_INVALID_CONTEXT
;
152 return VA_STATUS_SUCCESS
;
156 vlVaQuerySurfaceError(VADriverContextP ctx
, VASurfaceID render_target
, VAStatus error_status
, void **error_info
)
159 return VA_STATUS_ERROR_INVALID_CONTEXT
;
161 return VA_STATUS_ERROR_UNIMPLEMENTED
;
165 upload_sampler(struct pipe_context
*pipe
, struct pipe_sampler_view
*dst
,
166 const struct pipe_box
*dst_box
, const void *src
, unsigned src_stride
,
167 unsigned src_x
, unsigned src_y
)
169 struct pipe_transfer
*transfer
;
172 map
= pipe
->transfer_map(pipe
, dst
->texture
, 0, PIPE_TRANSFER_WRITE
,
177 util_copy_rect(map
, dst
->texture
->format
, transfer
->stride
, 0, 0,
178 dst_box
->width
, dst_box
->height
,
179 src
, src_stride
, src_x
, src_y
);
181 pipe
->transfer_unmap(pipe
, transfer
);
185 vlVaPutSubpictures(vlVaSurface
*surf
, vlVaDriver
*drv
,
186 struct pipe_surface
*surf_draw
, struct u_rect
*dirty_area
,
187 struct u_rect
*src_rect
, struct u_rect
*dst_rect
)
192 if (!(surf
->subpics
.data
|| surf
->subpics
.size
))
193 return VA_STATUS_SUCCESS
;
195 for (i
= 0; i
< surf
->subpics
.size
/sizeof(vlVaSubpicture
*); i
++) {
196 struct pipe_blend_state blend
;
200 struct u_rect
*s
, *d
, sr
, dr
, c
;
203 sub
= ((vlVaSubpicture
**)surf
->subpics
.data
)[i
];
207 buf
= handle_table_get(drv
->htab
, sub
->image
->buf
);
209 return VA_STATUS_ERROR_INVALID_IMAGE
;
214 box
.width
= sub
->dst_rect
.x1
- sub
->dst_rect
.x0
;
215 box
.height
= sub
->dst_rect
.y1
- sub
->dst_rect
.y0
;
224 c
.x0
= MAX2(d
->x0
, s
->x0
);
225 c
.y0
= MAX2(d
->y0
, s
->y0
);
226 c
.x1
= MIN2(d
->x0
+ dw
, src_rect
->x1
);
227 c
.y1
= MIN2(d
->y0
+ dh
, src_rect
->y1
);
228 sr
.x0
= s
->x0
+ (c
.x0
- d
->x0
)*(sw
/(float)dw
);
229 sr
.y0
= s
->y0
+ (c
.y0
- d
->y0
)*(sh
/(float)dh
);
230 sr
.x1
= s
->x0
+ (c
.x1
- d
->x0
)*(sw
/(float)dw
);
231 sr
.y1
= s
->y0
+ (c
.y1
- d
->y0
)*(sh
/(float)dh
);
239 dr
.x0
= d
->x0
+ c
.x0
*(dw
/(float)sw
);
240 dr
.y0
= d
->y0
+ c
.y0
*(dh
/(float)sh
);
241 dr
.x1
= d
->x0
+ c
.x1
*(dw
/(float)sw
);
242 dr
.y1
= d
->y0
+ c
.y1
*(dh
/(float)sh
);
244 memset(&blend
, 0, sizeof(blend
));
245 blend
.independent_blend_enable
= 0;
246 blend
.rt
[0].blend_enable
= 1;
247 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_SRC_ALPHA
;
248 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
249 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ZERO
;
250 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
251 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
252 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
253 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
254 blend
.logicop_enable
= 0;
255 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
257 blend_state
= drv
->pipe
->create_blend_state(drv
->pipe
, &blend
);
259 vl_compositor_clear_layers(&drv
->cstate
);
260 vl_compositor_set_layer_blend(&drv
->cstate
, 0, blend_state
, false);
261 upload_sampler(drv
->pipe
, sub
->sampler
, &box
, buf
->data
,
262 sub
->image
->pitches
[0], 0, 0);
263 vl_compositor_set_rgba_layer(&drv
->cstate
, &drv
->compositor
, 0, sub
->sampler
,
265 vl_compositor_set_layer_dst_area(&drv
->cstate
, 0, &dr
);
266 vl_compositor_render(&drv
->cstate
, &drv
->compositor
, surf_draw
, dirty_area
, false);
267 drv
->pipe
->delete_blend_state(drv
->pipe
, blend_state
);
270 return VA_STATUS_SUCCESS
;
274 vlVaPutSurface(VADriverContextP ctx
, VASurfaceID surface_id
, void* draw
, short srcx
, short srcy
,
275 unsigned short srcw
, unsigned short srch
, short destx
, short desty
,
276 unsigned short destw
, unsigned short desth
, VARectangle
*cliprects
,
277 unsigned int number_cliprects
, unsigned int flags
)
281 struct pipe_screen
*screen
;
282 struct pipe_resource
*tex
;
283 struct pipe_surface surf_templ
, *surf_draw
;
284 struct vl_screen
*vscreen
;
285 struct u_rect src_rect
, *dirty_area
;
286 struct u_rect dst_rect
= {destx
, destx
+ destw
, desty
, desty
+ desth
};
287 enum pipe_format format
;
291 return VA_STATUS_ERROR_INVALID_CONTEXT
;
293 drv
= VL_VA_DRIVER(ctx
);
294 mtx_lock(&drv
->mutex
);
295 surf
= handle_table_get(drv
->htab
, surface_id
);
297 mtx_unlock(&drv
->mutex
);
298 return VA_STATUS_ERROR_INVALID_SURFACE
;
301 screen
= drv
->pipe
->screen
;
302 vscreen
= drv
->vscreen
;
304 tex
= vscreen
->texture_from_drawable(vscreen
, draw
);
306 mtx_unlock(&drv
->mutex
);
307 return VA_STATUS_ERROR_INVALID_DISPLAY
;
310 dirty_area
= vscreen
->get_dirty_area(vscreen
);
312 memset(&surf_templ
, 0, sizeof(surf_templ
));
313 surf_templ
.format
= tex
->format
;
314 surf_draw
= drv
->pipe
->create_surface(drv
->pipe
, tex
, &surf_templ
);
316 pipe_resource_reference(&tex
, NULL
);
317 mtx_unlock(&drv
->mutex
);
318 return VA_STATUS_ERROR_INVALID_DISPLAY
;
323 src_rect
.x1
= srcw
+ srcx
;
324 src_rect
.y1
= srch
+ srcy
;
326 format
= surf
->buffer
->buffer_format
;
328 vl_compositor_clear_layers(&drv
->cstate
);
330 if (format
== PIPE_FORMAT_B8G8R8A8_UNORM
|| format
== PIPE_FORMAT_B8G8R8X8_UNORM
||
331 format
== PIPE_FORMAT_R8G8B8A8_UNORM
|| format
== PIPE_FORMAT_R8G8B8X8_UNORM
) {
332 struct pipe_sampler_view
**views
;
334 views
= surf
->buffer
->get_sampler_view_planes(surf
->buffer
);
335 vl_compositor_set_rgba_layer(&drv
->cstate
, &drv
->compositor
, 0, views
[0], &src_rect
, NULL
, NULL
);
337 vl_compositor_set_buffer_layer(&drv
->cstate
, &drv
->compositor
, 0, surf
->buffer
, &src_rect
, NULL
, VL_COMPOSITOR_WEAVE
);
339 vl_compositor_set_layer_dst_area(&drv
->cstate
, 0, &dst_rect
);
340 vl_compositor_render(&drv
->cstate
, &drv
->compositor
, surf_draw
, dirty_area
, true);
342 status
= vlVaPutSubpictures(surf
, drv
, surf_draw
, dirty_area
, &src_rect
, &dst_rect
);
344 mtx_unlock(&drv
->mutex
);
348 /* flush before calling flush_frontbuffer so that rendering is flushed
349 * to back buffer so the texture can be copied in flush_frontbuffer
351 drv
->pipe
->flush(drv
->pipe
, NULL
, 0);
353 screen
->flush_frontbuffer(screen
, tex
, 0, 0,
354 vscreen
->get_private(vscreen
), NULL
);
357 pipe_resource_reference(&tex
, NULL
);
358 pipe_surface_reference(&surf_draw
, NULL
);
359 mtx_unlock(&drv
->mutex
);
361 return VA_STATUS_SUCCESS
;
365 vlVaLockSurface(VADriverContextP ctx
, VASurfaceID surface
, unsigned int *fourcc
,
366 unsigned int *luma_stride
, unsigned int *chroma_u_stride
, unsigned int *chroma_v_stride
,
367 unsigned int *luma_offset
, unsigned int *chroma_u_offset
, unsigned int *chroma_v_offset
,
368 unsigned int *buffer_name
, void **buffer
)
371 return VA_STATUS_ERROR_INVALID_CONTEXT
;
373 return VA_STATUS_ERROR_UNIMPLEMENTED
;
377 vlVaUnlockSurface(VADriverContextP ctx
, VASurfaceID surface
)
380 return VA_STATUS_ERROR_INVALID_CONTEXT
;
382 return VA_STATUS_ERROR_UNIMPLEMENTED
;
386 vlVaQuerySurfaceAttributes(VADriverContextP ctx
, VAConfigID config_id
,
387 VASurfaceAttrib
*attrib_list
, unsigned int *num_attribs
)
391 VASurfaceAttrib
*attribs
;
392 struct pipe_screen
*pscreen
;
395 STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats
) <= VL_VA_MAX_IMAGE_FORMATS
);
397 if (config_id
== VA_INVALID_ID
)
398 return VA_STATUS_ERROR_INVALID_CONFIG
;
400 if (!attrib_list
&& !num_attribs
)
401 return VA_STATUS_ERROR_INVALID_PARAMETER
;
404 *num_attribs
= VL_VA_MAX_IMAGE_FORMATS
+ VASurfaceAttribCount
;
405 return VA_STATUS_SUCCESS
;
409 return VA_STATUS_ERROR_INVALID_CONTEXT
;
411 drv
= VL_VA_DRIVER(ctx
);
414 return VA_STATUS_ERROR_INVALID_CONTEXT
;
416 mtx_lock(&drv
->mutex
);
417 config
= handle_table_get(drv
->htab
, config_id
);
418 mtx_unlock(&drv
->mutex
);
421 return VA_STATUS_ERROR_INVALID_CONFIG
;
423 pscreen
= VL_VA_PSCREEN(ctx
);
426 return VA_STATUS_ERROR_INVALID_CONTEXT
;
428 attribs
= CALLOC(VL_VA_MAX_IMAGE_FORMATS
+ VASurfaceAttribCount
,
429 sizeof(VASurfaceAttrib
));
432 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
436 /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN
437 * only for VAEntrypointVideoProc. */
438 if (config
->profile
== PIPE_VIDEO_PROFILE_UNKNOWN
) {
439 if (config
->rt_format
& VA_RT_FORMAT_RGB32
) {
440 for (j
= 0; j
< ARRAY_SIZE(vpp_surface_formats
); ++j
) {
441 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
442 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
443 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
444 attribs
[i
].value
.value
.i
= PipeFormatToVaFourcc(vpp_surface_formats
[j
]);
449 if (config
->rt_format
& VA_RT_FORMAT_YUV420
) {
450 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
451 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
452 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
453 attribs
[i
].value
.value
.i
= VA_FOURCC_NV12
;
456 if (config
->rt_format
& VA_RT_FORMAT_YUV420_10BPP
) {
457 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
458 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
459 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
460 attribs
[i
].value
.value
.i
= VA_FOURCC_P010
;
462 attribs
[i
].type
= VASurfaceAttribPixelFormat
;
463 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
464 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
465 attribs
[i
].value
.value
.i
= VA_FOURCC_P016
;
469 attribs
[i
].type
= VASurfaceAttribMemoryType
;
470 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
471 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
| VA_SURFACE_ATTRIB_SETTABLE
;
472 attribs
[i
].value
.value
.i
= VA_SURFACE_ATTRIB_MEM_TYPE_VA
|
473 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
;
476 attribs
[i
].type
= VASurfaceAttribExternalBufferDescriptor
;
477 attribs
[i
].value
.type
= VAGenericValueTypePointer
;
478 attribs
[i
].flags
= VA_SURFACE_ATTRIB_SETTABLE
;
479 attribs
[i
].value
.value
.p
= NULL
; /* ignore */
482 if (config
->entrypoint
!= PIPE_VIDEO_ENTRYPOINT_UNKNOWN
) {
483 attribs
[i
].type
= VASurfaceAttribMaxWidth
;
484 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
485 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
486 attribs
[i
].value
.value
.i
=
487 pscreen
->get_video_param(pscreen
,
488 config
->profile
, config
->entrypoint
,
489 PIPE_VIDEO_CAP_MAX_WIDTH
);
492 attribs
[i
].type
= VASurfaceAttribMaxHeight
;
493 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
494 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
495 attribs
[i
].value
.value
.i
=
496 pscreen
->get_video_param(pscreen
,
497 config
->profile
, config
->entrypoint
,
498 PIPE_VIDEO_CAP_MAX_HEIGHT
);
501 attribs
[i
].type
= VASurfaceAttribMaxWidth
;
502 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
503 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
504 attribs
[i
].value
.value
.i
= vl_video_buffer_max_size(pscreen
);
507 attribs
[i
].type
= VASurfaceAttribMaxHeight
;
508 attribs
[i
].value
.type
= VAGenericValueTypeInteger
;
509 attribs
[i
].flags
= VA_SURFACE_ATTRIB_GETTABLE
;
510 attribs
[i
].value
.value
.i
= vl_video_buffer_max_size(pscreen
);
514 if (i
> *num_attribs
) {
517 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED
;
521 memcpy(attrib_list
, attribs
, i
* sizeof(VASurfaceAttrib
));
524 return VA_STATUS_SUCCESS
;
528 surface_from_external_memory(VADriverContextP ctx
, vlVaSurface
*surface
,
529 VASurfaceAttribExternalBuffers
*memory_attribute
,
530 unsigned index
, struct pipe_video_buffer
*templat
)
533 struct pipe_screen
*pscreen
;
534 struct pipe_resource
*resource
;
535 struct pipe_resource res_templ
;
536 struct winsys_handle whandle
;
537 struct pipe_resource
*resources
[VL_NUM_COMPONENTS
];
539 pscreen
= VL_VA_PSCREEN(ctx
);
540 drv
= VL_VA_DRIVER(ctx
);
542 if (!memory_attribute
|| !memory_attribute
->buffers
||
543 index
> memory_attribute
->num_buffers
)
544 return VA_STATUS_ERROR_INVALID_PARAMETER
;
546 if (surface
->templat
.width
!= memory_attribute
->width
||
547 surface
->templat
.height
!= memory_attribute
->height
||
548 memory_attribute
->num_planes
< 1)
549 return VA_STATUS_ERROR_INVALID_PARAMETER
;
551 switch (memory_attribute
->pixel_format
) {
556 if (memory_attribute
->num_planes
!= 1)
557 return VA_STATUS_ERROR_INVALID_PARAMETER
;
560 return VA_STATUS_ERROR_INVALID_PARAMETER
;
563 memset(&res_templ
, 0, sizeof(res_templ
));
564 res_templ
.target
= PIPE_TEXTURE_2D
;
565 res_templ
.last_level
= 0;
566 res_templ
.depth0
= 1;
567 res_templ
.array_size
= 1;
568 res_templ
.width0
= memory_attribute
->width
;
569 res_templ
.height0
= memory_attribute
->height
;
570 res_templ
.format
= surface
->templat
.buffer_format
;
571 res_templ
.bind
= PIPE_BIND_SAMPLER_VIEW
;
572 res_templ
.usage
= PIPE_USAGE_DEFAULT
;
574 memset(&whandle
, 0, sizeof(struct winsys_handle
));
575 whandle
.type
= DRM_API_HANDLE_TYPE_FD
;
576 whandle
.handle
= memory_attribute
->buffers
[index
];
577 whandle
.stride
= memory_attribute
->pitches
[0];
579 resource
= pscreen
->resource_from_handle(pscreen
, &res_templ
, &whandle
,
580 PIPE_HANDLE_USAGE_READ_WRITE
);
583 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
585 memset(resources
, 0, sizeof resources
);
586 resources
[0] = resource
;
588 surface
->buffer
= vl_video_buffer_create_ex2(drv
->pipe
, templat
, resources
);
589 if (!surface
->buffer
)
590 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
592 return VA_STATUS_SUCCESS
;
596 vlVaHandleSurfaceAllocate(vlVaDriver
*drv
, vlVaSurface
*surface
,
597 struct pipe_video_buffer
*templat
)
599 struct pipe_surface
**surfaces
;
602 surface
->buffer
= drv
->pipe
->create_video_buffer(drv
->pipe
, templat
);
603 if (!surface
->buffer
)
604 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
606 surfaces
= surface
->buffer
->get_surfaces(surface
->buffer
);
607 for (i
= 0; i
< VL_MAX_SURFACES
; ++i
) {
608 union pipe_color_union c
= {};
613 if (i
> !!surface
->buffer
->interlaced
)
614 c
.f
[0] = c
.f
[1] = c
.f
[2] = c
.f
[3] = 0.5f
;
616 drv
->pipe
->clear_render_target(drv
->pipe
, surfaces
[i
], &c
, 0, 0,
617 surfaces
[i
]->width
, surfaces
[i
]->height
,
620 drv
->pipe
->flush(drv
->pipe
, NULL
, 0);
622 return VA_STATUS_SUCCESS
;
626 vlVaCreateSurfaces2(VADriverContextP ctx
, unsigned int format
,
627 unsigned int width
, unsigned int height
,
628 VASurfaceID
*surfaces
, unsigned int num_surfaces
,
629 VASurfaceAttrib
*attrib_list
, unsigned int num_attribs
)
632 VASurfaceAttribExternalBuffers
*memory_attribute
;
633 struct pipe_video_buffer templat
;
634 struct pipe_screen
*pscreen
;
642 return VA_STATUS_ERROR_INVALID_CONTEXT
;
644 if (!(width
&& height
))
645 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT
;
647 drv
= VL_VA_DRIVER(ctx
);
650 return VA_STATUS_ERROR_INVALID_CONTEXT
;
652 pscreen
= VL_VA_PSCREEN(ctx
);
655 return VA_STATUS_ERROR_INVALID_CONTEXT
;
658 memory_attribute
= NULL
;
659 memory_type
= VA_SURFACE_ATTRIB_MEM_TYPE_VA
;
662 for (i
= 0; i
< num_attribs
&& attrib_list
; i
++) {
663 if ((attrib_list
[i
].type
== VASurfaceAttribPixelFormat
) &&
664 (attrib_list
[i
].flags
& VA_SURFACE_ATTRIB_SETTABLE
)) {
665 if (attrib_list
[i
].value
.type
!= VAGenericValueTypeInteger
)
666 return VA_STATUS_ERROR_INVALID_PARAMETER
;
667 expected_fourcc
= attrib_list
[i
].value
.value
.i
;
670 if ((attrib_list
[i
].type
== VASurfaceAttribMemoryType
) &&
671 (attrib_list
[i
].flags
& VA_SURFACE_ATTRIB_SETTABLE
)) {
673 if (attrib_list
[i
].value
.type
!= VAGenericValueTypeInteger
)
674 return VA_STATUS_ERROR_INVALID_PARAMETER
;
676 switch (attrib_list
[i
].value
.value
.i
) {
677 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
678 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
679 memory_type
= attrib_list
[i
].value
.value
.i
;
682 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
686 if ((attrib_list
[i
].type
== VASurfaceAttribExternalBufferDescriptor
) &&
687 (attrib_list
[i
].flags
== VA_SURFACE_ATTRIB_SETTABLE
)) {
688 if (attrib_list
[i
].value
.type
!= VAGenericValueTypePointer
)
689 return VA_STATUS_ERROR_INVALID_PARAMETER
;
690 memory_attribute
= (VASurfaceAttribExternalBuffers
*)attrib_list
[i
].value
.value
.p
;
694 if (VA_RT_FORMAT_YUV420
!= format
&&
695 VA_RT_FORMAT_YUV422
!= format
&&
696 VA_RT_FORMAT_YUV444
!= format
&&
697 VA_RT_FORMAT_YUV420_10BPP
!= format
&&
698 VA_RT_FORMAT_RGB32
!= format
) {
699 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT
;
702 switch (memory_type
) {
703 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
705 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
706 if (!memory_attribute
)
707 return VA_STATUS_ERROR_INVALID_PARAMETER
;
709 expected_fourcc
= memory_attribute
->pixel_format
;
715 memset(&templat
, 0, sizeof(templat
));
717 templat
.buffer_format
= pscreen
->get_video_param(
719 PIPE_VIDEO_PROFILE_UNKNOWN
,
720 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
721 PIPE_VIDEO_CAP_PREFERED_FORMAT
723 templat
.interlaced
= pscreen
->get_video_param(
725 PIPE_VIDEO_PROFILE_UNKNOWN
,
726 PIPE_VIDEO_ENTRYPOINT_BITSTREAM
,
727 PIPE_VIDEO_CAP_PREFERS_INTERLACED
730 if (expected_fourcc
) {
731 enum pipe_format expected_format
= VaFourccToPipeFormat(expected_fourcc
);
733 if (expected_format
!= templat
.buffer_format
|| memory_attribute
)
734 templat
.interlaced
= 0;
736 templat
.buffer_format
= expected_format
;
739 templat
.chroma_format
= ChromaToPipe(format
);
741 templat
.width
= width
;
742 templat
.height
= height
;
744 memset(surfaces
, VA_INVALID_ID
, num_surfaces
* sizeof(VASurfaceID
));
746 mtx_lock(&drv
->mutex
);
747 for (i
= 0; i
< num_surfaces
; i
++) {
748 surf
= CALLOC(1, sizeof(vlVaSurface
));
750 vaStatus
= VA_STATUS_ERROR_ALLOCATION_FAILED
;
754 surf
->templat
= templat
;
756 switch (memory_type
) {
757 case VA_SURFACE_ATTRIB_MEM_TYPE_VA
:
758 /* The application will clear the TILING flag when the surface is
759 * intended to be exported as dmabuf. Adding shared flag because not
760 * null memory_attribute means VASurfaceAttribExternalBuffers is used.
762 if (memory_attribute
&&
763 !(memory_attribute
->flags
& VA_SURFACE_EXTBUF_DESC_ENABLE_TILING
))
764 templat
.bind
= PIPE_BIND_LINEAR
| PIPE_BIND_SHARED
;
766 vaStatus
= vlVaHandleSurfaceAllocate(drv
, surf
, &templat
);
767 if (vaStatus
!= VA_STATUS_SUCCESS
)
771 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
:
772 vaStatus
= surface_from_external_memory(ctx
, surf
, memory_attribute
, i
, &templat
);
773 if (vaStatus
!= VA_STATUS_SUCCESS
)
781 util_dynarray_init(&surf
->subpics
, NULL
);
782 surfaces
[i
] = handle_table_add(drv
->htab
, surf
);
784 vaStatus
= VA_STATUS_ERROR_ALLOCATION_FAILED
;
788 mtx_unlock(&drv
->mutex
);
790 return VA_STATUS_SUCCESS
;
793 surf
->buffer
->destroy(surf
->buffer
);
799 mtx_unlock(&drv
->mutex
);
801 vlVaDestroySurfaces(ctx
, surfaces
, i
);
807 vlVaQueryVideoProcFilters(VADriverContextP ctx
, VAContextID context
,
808 VAProcFilterType
*filters
, unsigned int *num_filters
)
810 unsigned int num
= 0;
813 return VA_STATUS_ERROR_INVALID_CONTEXT
;
815 if (!num_filters
|| !filters
)
816 return VA_STATUS_ERROR_INVALID_PARAMETER
;
818 filters
[num
++] = VAProcFilterDeinterlacing
;
822 return VA_STATUS_SUCCESS
;
826 vlVaQueryVideoProcFilterCaps(VADriverContextP ctx
, VAContextID context
,
827 VAProcFilterType type
, void *filter_caps
,
828 unsigned int *num_filter_caps
)
833 return VA_STATUS_ERROR_INVALID_CONTEXT
;
835 if (!filter_caps
|| !num_filter_caps
)
836 return VA_STATUS_ERROR_INVALID_PARAMETER
;
841 case VAProcFilterNone
:
843 case VAProcFilterDeinterlacing
: {
844 VAProcFilterCapDeinterlacing
*deint
= filter_caps
;
846 if (*num_filter_caps
< 3) {
847 *num_filter_caps
= 3;
848 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED
;
851 deint
[i
++].type
= VAProcDeinterlacingBob
;
852 deint
[i
++].type
= VAProcDeinterlacingWeave
;
853 deint
[i
++].type
= VAProcDeinterlacingMotionAdaptive
;
857 case VAProcFilterNoiseReduction
:
858 case VAProcFilterSharpening
:
859 case VAProcFilterColorBalance
:
860 case VAProcFilterSkinToneEnhancement
:
861 return VA_STATUS_ERROR_UNIMPLEMENTED
;
866 *num_filter_caps
= i
;
868 return VA_STATUS_SUCCESS
;
871 static VAProcColorStandardType vpp_input_color_standards
[] = {
872 VAProcColorStandardBT601
875 static VAProcColorStandardType vpp_output_color_standards
[] = {
876 VAProcColorStandardBT601
880 vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx
, VAContextID context
,
881 VABufferID
*filters
, unsigned int num_filters
,
882 VAProcPipelineCaps
*pipeline_cap
)
887 return VA_STATUS_ERROR_INVALID_CONTEXT
;
890 return VA_STATUS_ERROR_INVALID_PARAMETER
;
892 if (num_filters
&& !filters
)
893 return VA_STATUS_ERROR_INVALID_PARAMETER
;
895 pipeline_cap
->pipeline_flags
= 0;
896 pipeline_cap
->filter_flags
= 0;
897 pipeline_cap
->num_forward_references
= 0;
898 pipeline_cap
->num_backward_references
= 0;
899 pipeline_cap
->num_input_color_standards
= ARRAY_SIZE(vpp_input_color_standards
);
900 pipeline_cap
->input_color_standards
= vpp_input_color_standards
;
901 pipeline_cap
->num_output_color_standards
= ARRAY_SIZE(vpp_output_color_standards
);
902 pipeline_cap
->output_color_standards
= vpp_output_color_standards
;
904 for (i
= 0; i
< num_filters
; i
++) {
905 vlVaBuffer
*buf
= handle_table_get(VL_VA_DRIVER(ctx
)->htab
, filters
[i
]);
906 VAProcFilterParameterBufferBase
*filter
;
908 if (!buf
|| buf
->type
!= VAProcFilterParameterBufferType
)
909 return VA_STATUS_ERROR_INVALID_BUFFER
;
912 switch (filter
->type
) {
913 case VAProcFilterDeinterlacing
: {
914 VAProcFilterParameterBufferDeinterlacing
*deint
= buf
->data
;
915 if (deint
->algorithm
== VAProcDeinterlacingMotionAdaptive
) {
916 pipeline_cap
->num_forward_references
= 2;
917 pipeline_cap
->num_backward_references
= 1;
922 return VA_STATUS_ERROR_UNIMPLEMENTED
;
926 return VA_STATUS_SUCCESS
;
929 #if VA_CHECK_VERSION(1, 1, 0)
931 vlVaExportSurfaceHandle(VADriverContextP ctx
,
932 VASurfaceID surface_id
,
939 struct pipe_surface
**surfaces
;
940 struct pipe_screen
*screen
;
945 VADRMPRIMESurfaceDescriptor
*desc
= descriptor
;
947 if (mem_type
!= VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2
)
948 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
949 if (flags
& VA_EXPORT_SURFACE_COMPOSED_LAYERS
)
950 return VA_STATUS_ERROR_INVALID_SURFACE
;
952 drv
= VL_VA_DRIVER(ctx
);
953 screen
= VL_VA_PSCREEN(ctx
);
954 mtx_lock(&drv
->mutex
);
956 surf
= handle_table_get(drv
->htab
, surface_id
);
957 if (!surf
|| !surf
->buffer
) {
958 mtx_unlock(&drv
->mutex
);
959 return VA_STATUS_ERROR_INVALID_SURFACE
;
962 if (surf
->buffer
->interlaced
) {
963 struct pipe_video_buffer
*interlaced
= surf
->buffer
;
964 struct u_rect src_rect
, dst_rect
;
966 surf
->templat
.interlaced
= false;
968 ret
= vlVaHandleSurfaceAllocate(drv
, surf
, &surf
->templat
);
969 if (ret
!= VA_STATUS_SUCCESS
) {
970 mtx_unlock(&drv
->mutex
);
971 return VA_STATUS_ERROR_ALLOCATION_FAILED
;
974 src_rect
.x0
= dst_rect
.x0
= 0;
975 src_rect
.y0
= dst_rect
.y0
= 0;
976 src_rect
.x1
= dst_rect
.x1
= surf
->templat
.width
;
977 src_rect
.y1
= dst_rect
.y1
= surf
->templat
.height
;
979 vl_compositor_yuv_deint_full(&drv
->cstate
, &drv
->compositor
,
980 interlaced
, surf
->buffer
,
981 &src_rect
, &dst_rect
,
982 VL_COMPOSITOR_WEAVE
);
984 interlaced
->destroy(interlaced
);
987 surfaces
= surf
->buffer
->get_surfaces(surf
->buffer
);
990 if (flags
& VA_EXPORT_SURFACE_READ_ONLY
)
991 usage
|= PIPE_HANDLE_USAGE_READ
;
992 if (flags
& VA_EXPORT_SURFACE_WRITE_ONLY
)
993 usage
|= PIPE_HANDLE_USAGE_WRITE
;
995 desc
->fourcc
= PipeFormatToVaFourcc(surf
->buffer
->buffer_format
);
996 desc
->width
= surf
->buffer
->width
;
997 desc
->height
= surf
->buffer
->height
;
999 for (p
= 0; p
< VL_MAX_SURFACES
; p
++) {
1000 struct winsys_handle whandle
;
1001 struct pipe_resource
*resource
;
1002 uint32_t drm_format
;
1007 resource
= surfaces
[p
]->texture
;
1009 switch (resource
->format
) {
1010 case PIPE_FORMAT_R8_UNORM
:
1011 drm_format
= DRM_FORMAT_R8
;
1013 case PIPE_FORMAT_R8G8_UNORM
:
1014 drm_format
= DRM_FORMAT_GR88
;
1016 case PIPE_FORMAT_R16_UNORM
:
1017 drm_format
= DRM_FORMAT_R16
;
1019 case PIPE_FORMAT_R16G16_UNORM
:
1020 drm_format
= DRM_FORMAT_GR1616
;
1022 case PIPE_FORMAT_B8G8R8A8_UNORM
:
1023 drm_format
= DRM_FORMAT_ARGB8888
;
1025 case PIPE_FORMAT_R8G8B8A8_UNORM
:
1026 drm_format
= DRM_FORMAT_ABGR8888
;
1028 case PIPE_FORMAT_B8G8R8X8_UNORM
:
1029 drm_format
= DRM_FORMAT_XRGB8888
;
1031 case PIPE_FORMAT_R8G8B8X8_UNORM
:
1032 drm_format
= DRM_FORMAT_XBGR8888
;
1035 ret
= VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE
;
1039 memset(&whandle
, 0, sizeof(whandle
));
1040 whandle
.type
= DRM_API_HANDLE_TYPE_FD
;
1042 if (!screen
->resource_get_handle(screen
, drv
->pipe
, resource
,
1044 ret
= VA_STATUS_ERROR_INVALID_SURFACE
;
1048 desc
->objects
[p
].fd
= (int)whandle
.handle
;
1049 desc
->objects
[p
].size
= 0;
1050 desc
->objects
[p
].drm_format_modifier
= whandle
.modifier
;
1052 desc
->layers
[p
].drm_format
= drm_format
;
1053 desc
->layers
[p
].num_planes
= 1;
1054 desc
->layers
[p
].object_index
[0] = p
;
1055 desc
->layers
[p
].offset
[0] = whandle
.offset
;
1056 desc
->layers
[p
].pitch
[0] = whandle
.stride
;
1059 desc
->num_objects
= p
;
1060 desc
->num_layers
= p
;
1062 mtx_unlock(&drv
->mutex
);
1064 return VA_STATUS_SUCCESS
;
1067 for (i
= 0; i
< p
; i
++)
1068 close(desc
->objects
[i
].fd
);
1070 mtx_unlock(&drv
->mutex
);