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
278 // Input surface color range
279 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_NONE;
280 if (param->input_color_properties.color_range == VA_SOURCE_RANGE_REDUCED)
281 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED;
282 else if (param->input_color_properties.color_range == VA_SOURCE_RANGE_FULL)
283 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL;
284
285 // Input surface chroma sample location
286 context->desc.vidproc.in_chroma_siting = PIPE_VIDEO_VPP_CHROMA_SITING_NONE;
287 if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_TOP)
288 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_TOP;
289 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_CENTER)
290 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_CENTER;
291 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_BOTTOM)
292 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_BOTTOM;
293 if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_LEFT)
294 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT;
295 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_CENTER)
296 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER;
297
298 // Output surface color standard
299 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_NONE;
300 if (param->output_color_standard == VAProcColorStandardBT601)
301 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT601;
302 else if (param->output_color_standard == VAProcColorStandardBT709)
303 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709;
304 else if (param->output_color_standard == VAProcColorStandardBT2020)
305 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT2020;
306
307 // Output surface color range
308 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_NONE;
309 if (param->output_color_properties.color_range == VA_SOURCE_RANGE_REDUCED)
310 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED;
311 else if (param->output_color_properties.color_range == VA_SOURCE_RANGE_FULL)
312 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL;
313
314 // Output surface chroma sample location
315 context->desc.vidproc.out_chroma_siting = PIPE_VIDEO_VPP_CHROMA_SITING_NONE;
316 if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_TOP)
317 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_TOP;
318 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_CENTER)
319 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_CENTER;
320 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_BOTTOM)
321 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_BOTTOM;
322 if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_LEFT)
323 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT;
324 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_CENTER)
325 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER;
326
327 if (context->needs_begin_frame) {
328 context->decoder->begin_frame(context->decoder, dst,
329 &context->desc.base);
330 context->needs_begin_frame = false;
331 }
332 context->decoder->process_frame(context->decoder, src, &context->desc.vidproc);
333
334 return VA_STATUS_SUCCESS;
335 }
336
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)337 static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
338 const VARectangle *src_region,
339 const VARectangle *dst_region,
340 struct pipe_video_buffer *src,
341 struct pipe_video_buffer *dst,
342 enum vl_compositor_deinterlace deinterlace)
343 {
344 struct pipe_surface **src_surfaces;
345 struct pipe_surface **dst_surfaces;
346 struct u_rect src_rect;
347 struct u_rect dst_rect;
348 bool scale = false;
349 bool grab = false;
350 unsigned i;
351
352 if ((src->buffer_format == PIPE_FORMAT_B8G8R8X8_UNORM ||
353 src->buffer_format == PIPE_FORMAT_B8G8R8A8_UNORM ||
354 src->buffer_format == PIPE_FORMAT_R8G8B8X8_UNORM ||
355 src->buffer_format == PIPE_FORMAT_R8G8B8A8_UNORM ||
356 src->buffer_format == PIPE_FORMAT_B10G10R10X2_UNORM ||
357 src->buffer_format == PIPE_FORMAT_B10G10R10A2_UNORM ||
358 src->buffer_format == PIPE_FORMAT_R10G10B10X2_UNORM ||
359 src->buffer_format == PIPE_FORMAT_R10G10B10A2_UNORM) &&
360 !src->interlaced)
361 grab = true;
362
363 if ((src->width != dst->width || src->height != dst->height) &&
364 (src->interlaced && dst->interlaced))
365 scale = true;
366
367 src_surfaces = src->get_surfaces(src);
368 if (!src_surfaces || !src_surfaces[0])
369 return VA_STATUS_ERROR_INVALID_SURFACE;
370
371 if (scale || (src->interlaced != dst->interlaced && dst->interlaced)) {
372 vlVaSurface *surf;
373
374 surf = handle_table_get(drv->htab, context->target_id);
375 if (!surf)
376 return VA_STATUS_ERROR_INVALID_SURFACE;
377 surf->templat.interlaced = false;
378 dst->destroy(dst);
379
380 if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
381 return VA_STATUS_ERROR_ALLOCATION_FAILED;
382
383 dst = context->target = surf->buffer;
384 }
385
386 dst_surfaces = dst->get_surfaces(dst);
387 if (!dst_surfaces || !dst_surfaces[0])
388 return VA_STATUS_ERROR_INVALID_SURFACE;
389
390 src_rect.x0 = src_region->x;
391 src_rect.y0 = src_region->y;
392 src_rect.x1 = src_region->x + src_region->width;
393 src_rect.y1 = src_region->y + src_region->height;
394
395 dst_rect.x0 = dst_region->x;
396 dst_rect.y0 = dst_region->y;
397 dst_rect.x1 = dst_region->x + dst_region->width;
398 dst_rect.y1 = dst_region->y + dst_region->height;
399
400 if (grab) {
401 vl_compositor_convert_rgb_to_yuv(&drv->cstate, &drv->compositor, 0,
402 ((struct vl_video_buffer *)src)->resources[0],
403 dst, &src_rect, &dst_rect);
404
405 return VA_STATUS_SUCCESS;
406 }
407
408 if (src->buffer_format == PIPE_FORMAT_YUYV ||
409 src->buffer_format == PIPE_FORMAT_UYVY ||
410 src->buffer_format == PIPE_FORMAT_YV12 ||
411 src->buffer_format == PIPE_FORMAT_IYUV) {
412 vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
413 src, dst, &src_rect, &dst_rect,
414 VL_COMPOSITOR_NONE);
415
416 return VA_STATUS_SUCCESS;
417 }
418
419 if (src->interlaced != dst->interlaced) {
420 deinterlace = deinterlace ? deinterlace : VL_COMPOSITOR_WEAVE;
421 vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
422 src, dst, &src_rect, &dst_rect,
423 deinterlace);
424
425 return VA_STATUS_SUCCESS;
426 }
427
428 for (i = 0; i < VL_MAX_SURFACES; ++i) {
429 struct pipe_surface *from = src_surfaces[i];
430 struct pipe_blit_info blit;
431
432 if (src->interlaced) {
433 /* Not 100% accurate, but close enough */
434 switch (deinterlace) {
435 case VL_COMPOSITOR_BOB_TOP:
436 from = src_surfaces[i & ~1];
437 break;
438 case VL_COMPOSITOR_BOB_BOTTOM:
439 from = src_surfaces[(i & ~1) + 1];
440 break;
441 default:
442 break;
443 }
444 }
445
446 if (!from || !dst_surfaces[i])
447 continue;
448
449 memset(&blit, 0, sizeof(blit));
450 blit.src.resource = from->texture;
451 blit.src.format = from->format;
452 blit.src.level = 0;
453 blit.src.box.z = from->u.tex.first_layer;
454 blit.src.box.depth = 1;
455 vlVaGetBox(src, i, &blit.src.box, src_region);
456
457 blit.dst.resource = dst_surfaces[i]->texture;
458 blit.dst.format = dst_surfaces[i]->format;
459 blit.dst.level = 0;
460 blit.dst.box.z = dst_surfaces[i]->u.tex.first_layer;
461 blit.dst.box.depth = 1;
462 vlVaGetBox(dst, i, &blit.dst.box, dst_region);
463
464 blit.mask = PIPE_MASK_RGBA;
465 blit.filter = PIPE_TEX_MIPFILTER_LINEAR;
466
467 if (drv->pipe->screen->get_param(drv->pipe->screen,
468 PIPE_CAP_PREFER_COMPUTE_FOR_MULTIMEDIA))
469 util_compute_blit(drv->pipe, &blit, &context->blit_cs);
470 else
471 drv->pipe->blit(drv->pipe, &blit);
472 }
473
474 // TODO: figure out why this is necessary for DMA-buf sharing
475 drv->pipe->flush(drv->pipe, NULL, 0);
476
477 return VA_STATUS_SUCCESS;
478 }
479
480 static struct pipe_video_buffer *
vlVaApplyDeint(vlVaDriver * drv,vlVaContext * context,VAProcPipelineParameterBuffer * param,struct pipe_video_buffer * current,unsigned field)481 vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
482 VAProcPipelineParameterBuffer *param,
483 struct pipe_video_buffer *current,
484 unsigned field)
485 {
486 vlVaSurface *prevprev, *prev, *next;
487
488 if (param->num_forward_references < 2 ||
489 param->num_backward_references < 1)
490 return current;
491
492 prevprev = handle_table_get(drv->htab, param->forward_references[1]);
493 prev = handle_table_get(drv->htab, param->forward_references[0]);
494 next = handle_table_get(drv->htab, param->backward_references[0]);
495
496 if (!prevprev || !prev || !next)
497 return current;
498
499 if (context->deint && (context->deint->video_width != current->width ||
500 context->deint->video_height != current->height ||
501 context->deint->interleaved != !current->interlaced)) {
502 vl_deint_filter_cleanup(context->deint);
503 FREE(context->deint);
504 context->deint = NULL;
505 }
506
507 if (!context->deint) {
508 context->deint = MALLOC(sizeof(struct vl_deint_filter));
509 if (!vl_deint_filter_init(context->deint, drv->pipe, current->width,
510 current->height, false, false, !current->interlaced)) {
511 FREE(context->deint);
512 context->deint = NULL;
513 return current;
514 }
515 }
516
517 if (!vl_deint_filter_check_buffers(context->deint, prevprev->buffer,
518 prev->buffer, current, next->buffer))
519 return current;
520
521 vl_deint_filter_render(context->deint, prevprev->buffer, prev->buffer,
522 current, next->buffer, field);
523 return context->deint->video_buffer;
524 }
525
526 VAStatus
vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver * drv,vlVaContext * context,vlVaBuffer * buf)527 vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
528 {
529 enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_NONE;
530 VARectangle def_src_region, def_dst_region;
531 const VARectangle *src_region, *dst_region;
532 VAProcPipelineParameterBuffer *param;
533 struct pipe_video_buffer *src, *dst;
534 vlVaSurface *src_surface, *dst_surface;
535 unsigned i;
536 struct pipe_screen *pscreen;
537 VAStatus ret;
538
539 if (!drv || !context)
540 return VA_STATUS_ERROR_INVALID_CONTEXT;
541
542 if (!buf || !buf->data)
543 return VA_STATUS_ERROR_INVALID_BUFFER;
544
545 if (!context->target)
546 return VA_STATUS_ERROR_INVALID_SURFACE;
547
548 param = buf->data;
549
550 src_surface = handle_table_get(drv->htab, param->surface);
551 dst_surface = handle_table_get(drv->htab, context->target_id);
552 if (!src_surface || !dst_surface)
553 return VA_STATUS_ERROR_INVALID_SURFACE;
554 vlVaGetSurfaceBuffer(drv, src_surface);
555 vlVaGetSurfaceBuffer(drv, dst_surface);
556 if (!src_surface->buffer || !dst_surface->buffer)
557 return VA_STATUS_ERROR_INVALID_SURFACE;
558
559 src_surface->full_range = vlVaGetFullRange(src_surface,
560 param->input_color_properties.color_range);
561 dst_surface->full_range = vlVaGetFullRange(dst_surface,
562 param->output_color_properties.color_range);
563
564 pscreen = drv->vscreen->pscreen;
565
566 src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region);
567 dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region);
568
569 /* EFC can only do one conversion, and it must be the last postproc
570 * operation immediately before encoding.
571 * Disable EFC completely if this is not the case. */
572 if (drv->last_efc_surface) {
573 vlVaSurface *surf = drv->last_efc_surface;
574 surf->efc_surface = NULL;
575 drv->last_efc_surface = NULL;
576 drv->efc_count = -1;
577 }
578
579 if (drv->efc_count >= 0 && !param->num_filters &&
580 src_region->width == dst_region->width &&
581 src_region->height == dst_region->height &&
582 src_region->x == dst_region->x &&
583 src_region->y == dst_region->y &&
584 pscreen->is_video_target_buffer_supported &&
585 pscreen->is_video_target_buffer_supported(pscreen,
586 dst_surface->buffer->buffer_format,
587 src_surface->buffer,
588 PIPE_VIDEO_PROFILE_UNKNOWN,
589 PIPE_VIDEO_ENTRYPOINT_ENCODE)) {
590
591 dst_surface->efc_surface = src_surface;
592 drv->last_efc_surface = dst_surface;
593
594 /* Do the blit for first few conversions as a fallback in case EFC
595 * could not be used (see above), after that assume EFC can always
596 * be used and skip the blit. */
597 if (drv->efc_count < 16)
598 drv->efc_count++;
599 else
600 return VA_STATUS_SUCCESS;
601 }
602
603 src = src_surface->buffer;
604 dst = dst_surface->buffer;
605
606 /* convert the destination buffer to progressive if we're deinterlacing
607 otherwise we might end up deinterlacing twice */
608 if (param->num_filters && dst->interlaced) {
609 vlVaSurface *surf;
610 surf = dst_surface;
611 surf->templat.interlaced = false;
612 dst->destroy(dst);
613
614 if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
615 return VA_STATUS_ERROR_ALLOCATION_FAILED;
616
617 dst = context->target = surf->buffer;
618 }
619
620 for (i = 0; i < param->num_filters; i++) {
621 vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]);
622 VAProcFilterParameterBufferBase *filter;
623
624 if (!buf || buf->type != VAProcFilterParameterBufferType)
625 return VA_STATUS_ERROR_INVALID_BUFFER;
626
627 filter = buf->data;
628 switch (filter->type) {
629 case VAProcFilterDeinterlacing: {
630 VAProcFilterParameterBufferDeinterlacing *deint = buf->data;
631 switch (deint->algorithm) {
632 case VAProcDeinterlacingBob:
633 if (deint->flags & VA_DEINTERLACING_BOTTOM_FIELD)
634 deinterlace = VL_COMPOSITOR_BOB_BOTTOM;
635 else
636 deinterlace = VL_COMPOSITOR_BOB_TOP;
637 break;
638
639 case VAProcDeinterlacingWeave:
640 deinterlace = VL_COMPOSITOR_WEAVE;
641 break;
642
643 case VAProcDeinterlacingMotionAdaptive:
644 src = vlVaApplyDeint(drv, context, param, src,
645 !!(deint->flags & VA_DEINTERLACING_BOTTOM_FIELD));
646 deinterlace = VL_COMPOSITOR_MOTION_ADAPTIVE;
647 break;
648
649 default:
650 return VA_STATUS_ERROR_UNIMPLEMENTED;
651 }
652 drv->compositor.deinterlace = deinterlace;
653 break;
654 }
655
656 default:
657 return VA_STATUS_ERROR_UNIMPLEMENTED;
658 }
659 }
660
661 /* If the driver supports video engine post proc, attempt to do that
662 * if it fails, fallback to the other existing implementations below
663 */
664 if (pscreen->get_video_param(pscreen,
665 PIPE_VIDEO_PROFILE_UNKNOWN,
666 PIPE_VIDEO_ENTRYPOINT_PROCESSING,
667 PIPE_VIDEO_CAP_SUPPORTED)) {
668 if (!context->decoder) {
669 context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat);
670 if (!context->decoder)
671 return VA_STATUS_ERROR_ALLOCATION_FAILED;
672 }
673
674 context->desc.vidproc.src_surface_fence = src_surface->fence;
675 /* Perform VPBlit, if fail, fallback to other implementations below */
676 if (VA_STATUS_SUCCESS == vlVaVidEngineBlit(drv, context, src_region, dst_region,
677 src, context->target, deinterlace, param))
678 return VA_STATUS_SUCCESS;
679 }
680
681 /* Some devices may be media only (PIPE_VIDEO_ENTRYPOINT_PROCESSING with video engine)
682 * and won't have shader support
683 */
684 if (!drv->vscreen->pscreen->get_param(drv->vscreen->pscreen, PIPE_CAP_GRAPHICS) &&
685 !drv->vscreen->pscreen->get_param(drv->vscreen->pscreen, PIPE_CAP_COMPUTE))
686 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
687
688 vlVaSetProcParameters(drv, src_surface, dst_surface, param);
689
690 /* Try other post proc implementations */
691 if (context->target->buffer_format != PIPE_FORMAT_NV12 &&
692 context->target->buffer_format != PIPE_FORMAT_P010 &&
693 context->target->buffer_format != PIPE_FORMAT_P016)
694 ret = vlVaPostProcCompositor(drv, context, src_region, dst_region,
695 src, context->target, deinterlace);
696 else
697 ret = vlVaPostProcBlit(drv, context, src_region, dst_region,
698 src, context->target, deinterlace);
699
700 /* Reset chroma location */
701 drv->cstate.chroma_location = VL_COMPOSITOR_LOCATION_NONE;
702
703 return ret;
704 }
705