1 /**************************************************************************
2 *
3 * Copyright 2015 Advanced Micro Devices, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "util/u_handle_table.h"
29 #include "util/u_memory.h"
30 #include "util/u_compute.h"
31
32 #include "vl/vl_defines.h"
33 #include "vl/vl_video_buffer.h"
34 #include "vl/vl_deint_filter.h"
35 #include "vl/vl_winsys.h"
36
37 #include "va_private.h"
38
39 static const VARectangle *
vlVaRegionDefault(const VARectangle * region,vlVaSurface * surf,VARectangle * def)40 vlVaRegionDefault(const VARectangle *region, vlVaSurface *surf,
41 VARectangle *def)
42 {
43 if (region)
44 return region;
45
46 def->x = 0;
47 def->y = 0;
48 def->width = surf->templat.width;
49 def->height = surf->templat.height;
50
51 return def;
52 }
53
54 static VAStatus
vlVaPostProcCompositor(vlVaDriver * drv,vlVaContext * context,const VARectangle * src_region,const VARectangle * dst_region,struct pipe_video_buffer * src,struct pipe_video_buffer * dst,enum vl_compositor_deinterlace deinterlace)55 vlVaPostProcCompositor(vlVaDriver *drv, vlVaContext *context,
56 const VARectangle *src_region,
57 const VARectangle *dst_region,
58 struct pipe_video_buffer *src,
59 struct pipe_video_buffer *dst,
60 enum vl_compositor_deinterlace deinterlace)
61 {
62 struct pipe_surface **surfaces;
63 struct u_rect src_rect;
64 struct u_rect dst_rect;
65
66 surfaces = dst->get_surfaces(dst);
67 if (!surfaces || !surfaces[0])
68 return VA_STATUS_ERROR_INVALID_SURFACE;
69
70 src_rect.x0 = src_region->x;
71 src_rect.y0 = src_region->y;
72 src_rect.x1 = src_region->x + src_region->width;
73 src_rect.y1 = src_region->y + src_region->height;
74
75 dst_rect.x0 = dst_region->x;
76 dst_rect.y0 = dst_region->y;
77 dst_rect.x1 = dst_region->x + dst_region->width;
78 dst_rect.y1 = dst_region->y + dst_region->height;
79
80 vl_compositor_clear_layers(&drv->cstate);
81 vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src,
82 &src_rect, NULL, deinterlace);
83 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
84 vl_compositor_render(&drv->cstate, &drv->compositor, surfaces[0], NULL, false);
85
86 drv->pipe->flush(drv->pipe, NULL, 0);
87 return VA_STATUS_SUCCESS;
88 }
89
vlVaGetBox(struct pipe_video_buffer * buf,unsigned idx,struct pipe_box * box,const VARectangle * region)90 static void vlVaGetBox(struct pipe_video_buffer *buf, unsigned idx,
91 struct pipe_box *box, const VARectangle *region)
92 {
93 unsigned plane = buf->interlaced ? idx / 2: idx;
94 unsigned x, y, width, height;
95
96 x = abs(region->x);
97 y = abs(region->y);
98 width = region->width;
99 height = region->height;
100
101 vl_video_buffer_adjust_size(&x, &y, plane,
102 pipe_format_to_chroma_format(buf->buffer_format),
103 buf->interlaced);
104 vl_video_buffer_adjust_size(&width, &height, plane,
105 pipe_format_to_chroma_format(buf->buffer_format),
106 buf->interlaced);
107
108 box->x = region->x < 0 ? -x : x;
109 box->y = region->y < 0 ? -y : y;
110 box->width = width;
111 box->height = height;
112 }
113
vlVaGetFullRange(vlVaSurface * surface,uint8_t va_range)114 static bool vlVaGetFullRange(vlVaSurface *surface, uint8_t va_range)
115 {
116 if (va_range != VA_SOURCE_RANGE_UNKNOWN)
117 return va_range == VA_SOURCE_RANGE_FULL;
118
119 /* Assume limited for YUV, full for RGB */
120 return !util_format_is_yuv(surface->buffer->buffer_format);
121 }
122
vlVaGetChromaLocation(unsigned va_chroma_location,enum pipe_format format)123 static unsigned vlVaGetChromaLocation(unsigned va_chroma_location,
124 enum pipe_format format)
125 {
126 unsigned ret = VL_COMPOSITOR_LOCATION_NONE;
127
128 if (util_format_get_plane_height(format, 1, 4) != 4) {
129 /* Bits 0-1 */
130 switch (va_chroma_location & 3) {
131 case VA_CHROMA_SITING_VERTICAL_TOP:
132 ret |= VL_COMPOSITOR_LOCATION_VERTICAL_TOP;
133 break;
134 case VA_CHROMA_SITING_VERTICAL_BOTTOM:
135 ret |= VL_COMPOSITOR_LOCATION_VERTICAL_BOTTOM;
136 break;
137 case VA_CHROMA_SITING_VERTICAL_CENTER:
138 default:
139 ret |= VL_COMPOSITOR_LOCATION_VERTICAL_CENTER;
140 break;
141 }
142 }
143
144 if (util_format_is_subsampled_422(format) ||
145 util_format_get_plane_width(format, 1, 4) != 4) {
146 /* Bits 2-3 */
147 switch (va_chroma_location & 12) {
148 case VA_CHROMA_SITING_HORIZONTAL_CENTER:
149 ret |= VL_COMPOSITOR_LOCATION_HORIZONTAL_CENTER;
150 break;
151 case VA_CHROMA_SITING_HORIZONTAL_LEFT:
152 default:
153 ret |= VL_COMPOSITOR_LOCATION_HORIZONTAL_LEFT;
154 break;
155 }
156 }
157
158 return ret;
159 }
160
vlVaSetProcParameters(vlVaDriver * drv,vlVaSurface * src,vlVaSurface * dst,VAProcPipelineParameterBuffer * param)161 static void vlVaSetProcParameters(vlVaDriver *drv,
162 vlVaSurface *src,
163 vlVaSurface *dst,
164 VAProcPipelineParameterBuffer *param)
165 {
166 enum VL_CSC_COLOR_STANDARD color_standard;
167 bool src_yuv = util_format_is_yuv(src->buffer->buffer_format);
168 bool dst_yuv = util_format_is_yuv(dst->buffer->buffer_format);
169
170 if (src_yuv == dst_yuv) {
171 color_standard = VL_CSC_COLOR_STANDARD_IDENTITY;
172 } else if (src_yuv) {
173 switch (param->surface_color_standard) {
174 case VAProcColorStandardBT601:
175 color_standard = VL_CSC_COLOR_STANDARD_BT_601;
176 break;
177 case VAProcColorStandardBT709:
178 default:
179 color_standard = src->full_range ?
180 VL_CSC_COLOR_STANDARD_BT_709_FULL :
181 VL_CSC_COLOR_STANDARD_BT_709;
182 break;
183 }
184 } else {
185 color_standard = VL_CSC_COLOR_STANDARD_BT_709_REV;
186 }
187
188 vl_csc_get_matrix(color_standard, NULL, dst->full_range, &drv->csc);
189 vl_compositor_set_csc_matrix(&drv->cstate, &drv->csc, 1.0f, 0.0f);
190
191 if (src_yuv)
192 drv->cstate.chroma_location =
193 vlVaGetChromaLocation(param->input_color_properties.chroma_sample_location,
194 src->buffer->buffer_format);
195 else if (dst_yuv)
196 drv->cstate.chroma_location =
197 vlVaGetChromaLocation(param->output_color_properties.chroma_sample_location,
198 dst->buffer->buffer_format);
199 }
200
vlVaVidEngineBlit(vlVaDriver * drv,vlVaContext * context,const VARectangle * src_region,const VARectangle * dst_region,struct pipe_video_buffer * src,struct pipe_video_buffer * dst,enum vl_compositor_deinterlace deinterlace,VAProcPipelineParameterBuffer * param)201 static VAStatus vlVaVidEngineBlit(vlVaDriver *drv, vlVaContext *context,
202 const VARectangle *src_region,
203 const VARectangle *dst_region,
204 struct pipe_video_buffer *src,
205 struct pipe_video_buffer *dst,
206 enum vl_compositor_deinterlace deinterlace,
207 VAProcPipelineParameterBuffer* param)
208 {
209 if (deinterlace != VL_COMPOSITOR_NONE)
210 return VA_STATUS_ERROR_UNIMPLEMENTED;
211
212 if (!drv->pipe->screen->is_video_format_supported(drv->pipe->screen,
213 src->buffer_format,
214 PIPE_VIDEO_PROFILE_UNKNOWN,
215 PIPE_VIDEO_ENTRYPOINT_PROCESSING))
216 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
217
218 if (!drv->pipe->screen->is_video_format_supported(drv->pipe->screen,
219 dst->buffer_format,
220 PIPE_VIDEO_PROFILE_UNKNOWN,
221 PIPE_VIDEO_ENTRYPOINT_PROCESSING))
222 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
223
224 struct u_rect src_rect;
225 struct u_rect dst_rect;
226
227 src_rect.x0 = src_region->x;
228 src_rect.y0 = src_region->y;
229 src_rect.x1 = src_region->x + src_region->width;
230 src_rect.y1 = src_region->y + src_region->height;
231
232 dst_rect.x0 = dst_region->x;
233 dst_rect.y0 = dst_region->y;
234 dst_rect.x1 = dst_region->x + dst_region->width;
235 dst_rect.y1 = dst_region->y + dst_region->height;
236
237 context->desc.vidproc.base.input_format = src->buffer_format;
238 context->desc.vidproc.base.output_format = dst->buffer_format;
239
240 context->desc.vidproc.src_region = src_rect;
241 context->desc.vidproc.dst_region = dst_rect;
242
243 if (param->rotation_state == VA_ROTATION_NONE)
244 context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ORIENTATION_DEFAULT;
245 else if (param->rotation_state == VA_ROTATION_90)
246 context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_90;
247 else if (param->rotation_state == VA_ROTATION_180)
248 context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_180;
249 else if (param->rotation_state == VA_ROTATION_270)
250 context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_270;
251
252 if (param->mirror_state == VA_MIRROR_HORIZONTAL)
253 context->desc.vidproc.orientation |= PIPE_VIDEO_VPP_FLIP_HORIZONTAL;
254 if (param->mirror_state == VA_MIRROR_VERTICAL)
255 context->desc.vidproc.orientation |= PIPE_VIDEO_VPP_FLIP_VERTICAL;
256
257 memset(&context->desc.vidproc.blend, 0, sizeof(context->desc.vidproc.blend));
258 context->desc.vidproc.blend.mode = PIPE_VIDEO_VPP_BLEND_MODE_NONE;
259 if (param->blend_state != NULL) {
260 if (param->blend_state->flags & VA_BLEND_GLOBAL_ALPHA) {
261 context->desc.vidproc.blend.mode = PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA;
262 context->desc.vidproc.blend.global_alpha = param->blend_state->global_alpha;
263 }
264 }
265
266 // Output background color
267 context->desc.vidproc.background_color = param->output_background_color;
268
269 // Input surface color standard
270 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_NONE;
271 if (param->surface_color_standard == VAProcColorStandardBT601)
272 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT601;
273 else if (param->surface_color_standard == VAProcColorStandardBT709)
274 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709;
275 else if (param->surface_color_standard == VAProcColorStandardBT2020)
276 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT2020;
277 else if (param->surface_color_standard == VAProcColorStandardExplicit) {
278 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_EXPLICIT;
279 context->desc.vidproc.in_color_primaries = param->input_color_properties.colour_primaries;
280 context->desc.vidproc.in_transfer_characteristics = param->input_color_properties.transfer_characteristics;
281 context->desc.vidproc.in_matrix_coefficients = param->input_color_properties.matrix_coefficients;
282 }
283
284 // Input surface color range
285 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_NONE;
286 if (param->input_color_properties.color_range == VA_SOURCE_RANGE_REDUCED)
287 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED;
288 else if (param->input_color_properties.color_range == VA_SOURCE_RANGE_FULL)
289 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL;
290
291 // Input surface chroma sample location
292 context->desc.vidproc.in_chroma_siting = PIPE_VIDEO_VPP_CHROMA_SITING_NONE;
293 if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_TOP)
294 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_TOP;
295 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_CENTER)
296 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_CENTER;
297 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_BOTTOM)
298 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_BOTTOM;
299 if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_LEFT)
300 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT;
301 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_CENTER)
302 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER;
303
304 // Output surface color standard
305 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_NONE;
306 if (param->output_color_standard == VAProcColorStandardBT601)
307 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT601;
308 else if (param->output_color_standard == VAProcColorStandardBT709)
309 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709;
310 else if (param->output_color_standard == VAProcColorStandardBT2020)
311 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT2020;
312 else if (param->output_color_standard == VAProcColorStandardExplicit) {
313 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_EXPLICIT;
314 context->desc.vidproc.out_color_primaries = param->output_color_properties.colour_primaries;
315 context->desc.vidproc.out_transfer_characteristics = param->output_color_properties.transfer_characteristics;
316 context->desc.vidproc.out_matrix_coefficients = param->output_color_properties.matrix_coefficients;
317 }
318
319 // Output surface color range
320 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_NONE;
321 if (param->output_color_properties.color_range == VA_SOURCE_RANGE_REDUCED)
322 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED;
323 else if (param->output_color_properties.color_range == VA_SOURCE_RANGE_FULL)
324 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL;
325
326 // Output surface chroma sample location
327 context->desc.vidproc.out_chroma_siting = PIPE_VIDEO_VPP_CHROMA_SITING_NONE;
328 if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_TOP)
329 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_TOP;
330 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_CENTER)
331 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_CENTER;
332 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_BOTTOM)
333 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_BOTTOM;
334 if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_LEFT)
335 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT;
336 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_CENTER)
337 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER;
338
339 if (context->needs_begin_frame) {
340 context->decoder->begin_frame(context->decoder, dst,
341 &context->desc.base);
342 context->needs_begin_frame = false;
343 }
344
345 if (context->decoder->process_frame(context->decoder, src, &context->desc.vidproc))
346 return VA_STATUS_ERROR_OPERATION_FAILED;
347
348 return VA_STATUS_SUCCESS;
349 }
350
vlVaPostProcBlit(vlVaDriver * drv,vlVaContext * context,const VARectangle * src_region,const VARectangle * dst_region,struct pipe_video_buffer * src,struct pipe_video_buffer * dst,enum vl_compositor_deinterlace deinterlace)351 static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
352 const VARectangle *src_region,
353 const VARectangle *dst_region,
354 struct pipe_video_buffer *src,
355 struct pipe_video_buffer *dst,
356 enum vl_compositor_deinterlace deinterlace)
357 {
358 struct pipe_surface **src_surfaces;
359 struct pipe_surface **dst_surfaces;
360 struct u_rect src_rect;
361 struct u_rect dst_rect;
362 bool grab = false;
363 unsigned i, src_num_planes, dst_num_planes;
364
365 src_num_planes = util_format_get_num_planes(src->buffer_format);
366 dst_num_planes = util_format_get_num_planes(dst->buffer_format);
367
368 if ((src->buffer_format == PIPE_FORMAT_B8G8R8X8_UNORM ||
369 src->buffer_format == PIPE_FORMAT_B8G8R8A8_UNORM ||
370 src->buffer_format == PIPE_FORMAT_R8G8B8X8_UNORM ||
371 src->buffer_format == PIPE_FORMAT_R8G8B8A8_UNORM ||
372 src->buffer_format == PIPE_FORMAT_B10G10R10X2_UNORM ||
373 src->buffer_format == PIPE_FORMAT_B10G10R10A2_UNORM ||
374 src->buffer_format == PIPE_FORMAT_R10G10B10X2_UNORM ||
375 src->buffer_format == PIPE_FORMAT_R10G10B10A2_UNORM) &&
376 !src->interlaced)
377 grab = true;
378
379 src_surfaces = src->get_surfaces(src);
380 if (!src_surfaces || !src_surfaces[0])
381 return VA_STATUS_ERROR_INVALID_SURFACE;
382
383 dst_surfaces = dst->get_surfaces(dst);
384 if (!dst_surfaces || !dst_surfaces[0])
385 return VA_STATUS_ERROR_INVALID_SURFACE;
386
387 src_rect.x0 = src_region->x;
388 src_rect.y0 = src_region->y;
389 src_rect.x1 = src_region->x + src_region->width;
390 src_rect.y1 = src_region->y + src_region->height;
391
392 dst_rect.x0 = dst_region->x;
393 dst_rect.y0 = dst_region->y;
394 dst_rect.x1 = dst_region->x + dst_region->width;
395 dst_rect.y1 = dst_region->y + dst_region->height;
396
397 if (grab) {
398 vl_compositor_convert_rgb_to_yuv(&drv->cstate, &drv->compositor, 0,
399 ((struct vl_video_buffer *)src)->resources[0],
400 dst, &src_rect, &dst_rect);
401
402 return VA_STATUS_SUCCESS;
403 }
404
405 if (src->buffer_format == PIPE_FORMAT_YUYV ||
406 src->buffer_format == PIPE_FORMAT_UYVY ||
407 src->buffer_format == PIPE_FORMAT_YV12 ||
408 src->buffer_format == PIPE_FORMAT_IYUV ||
409 (src->interlaced == dst->interlaced &&
410 src_num_planes != dst_num_planes)) {
411 vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
412 src, dst, &src_rect, &dst_rect,
413 VL_COMPOSITOR_NONE);
414
415 return VA_STATUS_SUCCESS;
416 }
417
418 if (src->interlaced != dst->interlaced) {
419 deinterlace = deinterlace ? deinterlace : VL_COMPOSITOR_WEAVE;
420 vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
421 src, dst, &src_rect, &dst_rect,
422 deinterlace);
423
424 return VA_STATUS_SUCCESS;
425 }
426
427 for (i = 0; i < VL_MAX_SURFACES; ++i) {
428 struct pipe_surface *from = src_surfaces[i];
429 struct pipe_blit_info blit;
430
431 if (src->interlaced) {
432 /* Not 100% accurate, but close enough */
433 switch (deinterlace) {
434 case VL_COMPOSITOR_BOB_TOP:
435 from = src_surfaces[i & ~1];
436 break;
437 case VL_COMPOSITOR_BOB_BOTTOM:
438 from = src_surfaces[(i & ~1) + 1];
439 break;
440 default:
441 break;
442 }
443 }
444
445 if (!from || !dst_surfaces[i])
446 continue;
447
448 memset(&blit, 0, sizeof(blit));
449 blit.src.resource = from->texture;
450 blit.src.format = from->format;
451 blit.src.level = 0;
452 blit.src.box.z = from->u.tex.first_layer;
453 blit.src.box.depth = 1;
454 vlVaGetBox(src, i, &blit.src.box, src_region);
455
456 blit.dst.resource = dst_surfaces[i]->texture;
457 blit.dst.format = dst_surfaces[i]->format;
458 blit.dst.level = 0;
459 blit.dst.box.z = dst_surfaces[i]->u.tex.first_layer;
460 blit.dst.box.depth = 1;
461 vlVaGetBox(dst, i, &blit.dst.box, dst_region);
462
463 blit.mask = PIPE_MASK_RGBA;
464 blit.filter = PIPE_TEX_MIPFILTER_LINEAR;
465
466 if (drv->pipe->screen->caps.prefer_compute_for_multimedia)
467 util_compute_blit(drv->pipe, &blit, &context->blit_cs);
468 else
469 drv->pipe->blit(drv->pipe, &blit);
470 }
471
472 // TODO: figure out why this is necessary for DMA-buf sharing
473 drv->pipe->flush(drv->pipe, NULL, 0);
474
475 return VA_STATUS_SUCCESS;
476 }
477
478 static struct pipe_video_buffer *
vlVaApplyDeint(vlVaDriver * drv,vlVaContext * context,VAProcPipelineParameterBuffer * param,struct pipe_video_buffer * current,unsigned field)479 vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
480 VAProcPipelineParameterBuffer *param,
481 struct pipe_video_buffer *current,
482 unsigned field)
483 {
484 vlVaSurface *prevprev, *prev, *next;
485
486 if (param->num_forward_references < 2 ||
487 param->num_backward_references < 1)
488 return current;
489
490 prevprev = handle_table_get(drv->htab, param->forward_references[1]);
491 prev = handle_table_get(drv->htab, param->forward_references[0]);
492 next = handle_table_get(drv->htab, param->backward_references[0]);
493
494 if (!prevprev || !prev || !next)
495 return current;
496
497 if (context->deint && (context->deint->video_width != current->width ||
498 context->deint->video_height != current->height ||
499 context->deint->interleaved != !current->interlaced)) {
500 vl_deint_filter_cleanup(context->deint);
501 FREE(context->deint);
502 context->deint = NULL;
503 }
504
505 if (!drv->pipe_gfx) {
506 drv->pipe_gfx = pipe_create_multimedia_context(drv->pipe->screen, false);
507 if (!drv->pipe_gfx)
508 return current;
509 }
510
511 if (!context->deint) {
512 context->deint = MALLOC(sizeof(struct vl_deint_filter));
513 if (!vl_deint_filter_init(context->deint, drv->pipe_gfx, current->width,
514 current->height, false, false, !current->interlaced)) {
515 FREE(context->deint);
516 context->deint = NULL;
517 return current;
518 }
519 }
520
521 if (!vl_deint_filter_check_buffers(context->deint, prevprev->buffer,
522 prev->buffer, current, next->buffer))
523 return current;
524
525 vl_deint_filter_render(context->deint, prevprev->buffer, prev->buffer,
526 current, next->buffer, field);
527
528 drv->pipe_gfx->flush(drv->pipe_gfx, NULL, 0);
529
530 return context->deint->video_buffer;
531 }
532
533 VAStatus
vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver * drv,vlVaContext * context,vlVaBuffer * buf)534 vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
535 {
536 enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_NONE;
537 VARectangle def_src_region, def_dst_region;
538 const VARectangle *src_region, *dst_region;
539 VAProcPipelineParameterBuffer *param;
540 struct pipe_video_buffer *src;
541 vlVaSurface *src_surface, *dst_surface;
542 unsigned i;
543 struct pipe_screen *pscreen;
544 VAStatus ret;
545
546 if (!drv || !context)
547 return VA_STATUS_ERROR_INVALID_CONTEXT;
548
549 if (!buf || !buf->data)
550 return VA_STATUS_ERROR_INVALID_BUFFER;
551
552 if (!context->target)
553 return VA_STATUS_ERROR_INVALID_SURFACE;
554
555 param = buf->data;
556
557 src_surface = handle_table_get(drv->htab, param->surface);
558 dst_surface = handle_table_get(drv->htab, context->target_id);
559 if (!src_surface || !dst_surface)
560 return VA_STATUS_ERROR_INVALID_SURFACE;
561 vlVaGetSurfaceBuffer(drv, src_surface);
562 vlVaGetSurfaceBuffer(drv, dst_surface);
563 if (!src_surface->buffer || !dst_surface->buffer)
564 return VA_STATUS_ERROR_INVALID_SURFACE;
565
566 src_surface->full_range = vlVaGetFullRange(src_surface,
567 param->input_color_properties.color_range);
568 dst_surface->full_range = vlVaGetFullRange(dst_surface,
569 param->output_color_properties.color_range);
570
571 pscreen = drv->vscreen->pscreen;
572
573 src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region);
574 dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region);
575
576 /* EFC can only do one conversion, and it must be the last postproc
577 * operation immediately before encoding.
578 * Disable EFC completely if this is not the case. */
579 if (drv->last_efc_surface) {
580 vlVaSurface *surf = drv->last_efc_surface;
581 surf->efc_surface = NULL;
582 drv->last_efc_surface = NULL;
583 drv->efc_count = -1;
584 }
585
586 if (drv->efc_count >= 0 && !param->num_filters &&
587 src_region->width == dst_region->width &&
588 src_region->height == dst_region->height &&
589 src_region->x == dst_region->x &&
590 src_region->y == dst_region->y &&
591 pscreen->is_video_target_buffer_supported &&
592 pscreen->is_video_target_buffer_supported(pscreen,
593 dst_surface->buffer->buffer_format,
594 src_surface->buffer,
595 PIPE_VIDEO_PROFILE_UNKNOWN,
596 PIPE_VIDEO_ENTRYPOINT_ENCODE)) {
597
598 dst_surface->efc_surface = src_surface;
599 drv->last_efc_surface = dst_surface;
600
601 /* Do the blit for first few conversions as a fallback in case EFC
602 * could not be used (see above), after that assume EFC can always
603 * be used and skip the blit. */
604 if (drv->efc_count < 16)
605 drv->efc_count++;
606 else
607 return VA_STATUS_SUCCESS;
608 }
609
610 src = src_surface->buffer;
611
612 for (i = 0; i < param->num_filters; i++) {
613 vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]);
614 VAProcFilterParameterBufferBase *filter;
615
616 if (!buf || buf->type != VAProcFilterParameterBufferType)
617 return VA_STATUS_ERROR_INVALID_BUFFER;
618
619 filter = buf->data;
620 switch (filter->type) {
621 case VAProcFilterDeinterlacing: {
622 VAProcFilterParameterBufferDeinterlacing *deint = buf->data;
623 switch (deint->algorithm) {
624 case VAProcDeinterlacingBob:
625 if (deint->flags & VA_DEINTERLACING_BOTTOM_FIELD)
626 deinterlace = VL_COMPOSITOR_BOB_BOTTOM;
627 else
628 deinterlace = VL_COMPOSITOR_BOB_TOP;
629 break;
630
631 case VAProcDeinterlacingWeave:
632 deinterlace = VL_COMPOSITOR_WEAVE;
633 break;
634
635 case VAProcDeinterlacingMotionAdaptive:
636 src = vlVaApplyDeint(drv, context, param, src,
637 !!(deint->flags & VA_DEINTERLACING_BOTTOM_FIELD));
638 deinterlace = VL_COMPOSITOR_MOTION_ADAPTIVE;
639 break;
640
641 default:
642 return VA_STATUS_ERROR_UNIMPLEMENTED;
643 }
644 drv->compositor.deinterlace = deinterlace;
645 break;
646 }
647
648 default:
649 return VA_STATUS_ERROR_UNIMPLEMENTED;
650 }
651 }
652
653 /* If the driver supports video engine post proc, attempt to do that
654 * if it fails, fallback to the other existing implementations below
655 */
656 if (pscreen->get_video_param(pscreen,
657 PIPE_VIDEO_PROFILE_UNKNOWN,
658 PIPE_VIDEO_ENTRYPOINT_PROCESSING,
659 PIPE_VIDEO_CAP_SUPPORTED)) {
660 if (!context->decoder) {
661 context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat);
662 if (!context->decoder)
663 return VA_STATUS_ERROR_ALLOCATION_FAILED;
664 }
665
666 context->desc.vidproc.src_surface_fence = src_surface->fence;
667 /* Perform VPBlit, if fail, fallback to other implementations below */
668 if (VA_STATUS_SUCCESS == vlVaVidEngineBlit(drv, context, src_region, dst_region,
669 src, context->target, deinterlace, param))
670 return VA_STATUS_SUCCESS;
671 }
672
673 /* Some devices may be media only (PIPE_VIDEO_ENTRYPOINT_PROCESSING with video engine)
674 * and won't have shader support
675 */
676 if (!drv->vscreen->pscreen->caps.graphics && !drv->vscreen->pscreen->caps.compute)
677 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
678
679 /* Subsampled formats not supported */
680 if (util_format_is_subsampled_422(context->target->buffer_format))
681 return VA_STATUS_ERROR_UNIMPLEMENTED;
682
683 vlVaSetProcParameters(drv, src_surface, dst_surface, param);
684
685 /* Try other post proc implementations */
686 if (!util_format_is_yuv(context->target->buffer_format))
687 ret = vlVaPostProcCompositor(drv, context, src_region, dst_region,
688 src, context->target, deinterlace);
689 else
690 ret = vlVaPostProcBlit(drv, context, src_region, dst_region,
691 src, context->target, deinterlace);
692
693 /* Reset chroma location */
694 drv->cstate.chroma_location = VL_COMPOSITOR_LOCATION_NONE;
695
696 return ret;
697 }
698