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
31 #include "vl/vl_defines.h"
32 #include "vl/vl_video_buffer.h"
33 #include "vl/vl_deint_filter.h"
34 #include "vl/vl_winsys.h"
35
36 #include "va_private.h"
37
38 static const VARectangle *
vlVaRegionDefault(const VARectangle * region,vlVaSurface * surf,VARectangle * def)39 vlVaRegionDefault(const VARectangle *region, vlVaSurface *surf,
40 VARectangle *def)
41 {
42 if (region)
43 return region;
44
45 def->x = 0;
46 def->y = 0;
47 def->width = surf->templat.width;
48 def->height = surf->templat.height;
49
50 return def;
51 }
52
53 static bool
vlVaGetFullRange(enum pipe_format format,uint8_t va_range)54 vlVaGetFullRange(enum pipe_format format, uint8_t va_range)
55 {
56 if (va_range != VA_SOURCE_RANGE_UNKNOWN)
57 return va_range == VA_SOURCE_RANGE_FULL;
58
59 /* Assume limited for YUV, full for RGB */
60 return !util_format_is_yuv(format);
61 }
62
63 static unsigned
vlVaGetChromaLocation(unsigned va_chroma_location,enum pipe_format format)64 vlVaGetChromaLocation(unsigned va_chroma_location, enum pipe_format format)
65 {
66 unsigned ret = VL_COMPOSITOR_LOCATION_NONE;
67
68 if (util_format_get_plane_height(format, 1, 4) != 4) {
69 /* Bits 0-1 */
70 switch (va_chroma_location & 3) {
71 case VA_CHROMA_SITING_VERTICAL_TOP:
72 ret |= VL_COMPOSITOR_LOCATION_VERTICAL_TOP;
73 break;
74 case VA_CHROMA_SITING_VERTICAL_BOTTOM:
75 ret |= VL_COMPOSITOR_LOCATION_VERTICAL_BOTTOM;
76 break;
77 case VA_CHROMA_SITING_VERTICAL_CENTER:
78 default:
79 ret |= VL_COMPOSITOR_LOCATION_VERTICAL_CENTER;
80 break;
81 }
82 }
83
84 if (util_format_is_subsampled_422(format) ||
85 util_format_get_plane_width(format, 1, 4) != 4) {
86 /* Bits 2-3 */
87 switch (va_chroma_location & 12) {
88 case VA_CHROMA_SITING_HORIZONTAL_CENTER:
89 ret |= VL_COMPOSITOR_LOCATION_HORIZONTAL_CENTER;
90 break;
91 case VA_CHROMA_SITING_HORIZONTAL_LEFT:
92 default:
93 ret |= VL_COMPOSITOR_LOCATION_HORIZONTAL_LEFT;
94 break;
95 }
96 }
97
98 return ret;
99 }
100
101 VAStatus
vlVaPostProcCompositor(vlVaDriver * drv,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)102 vlVaPostProcCompositor(vlVaDriver *drv,
103 const VARectangle *src_region,
104 const VARectangle *dst_region,
105 struct pipe_video_buffer *src,
106 struct pipe_video_buffer *dst,
107 enum vl_compositor_deinterlace deinterlace,
108 VAProcPipelineParameterBuffer *param)
109 {
110 struct pipe_surface **surfaces;
111 struct u_rect src_rect;
112 struct u_rect dst_rect;
113 enum VL_CSC_COLOR_STANDARD color_standard;
114 enum vl_compositor_rotation rotation;
115 enum vl_compositor_mirror mirror;
116 bool src_yuv = util_format_is_yuv(src->buffer_format);
117 bool dst_yuv = util_format_is_yuv(dst->buffer_format);
118 bool src_full_range = vlVaGetFullRange(src->buffer_format,
119 param->input_color_properties.color_range);
120 bool dst_full_range = vlVaGetFullRange(dst->buffer_format,
121 param->output_color_properties.color_range);
122
123 if (!drv->cstate.pipe)
124 return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
125
126 /* Subsampled formats not supported */
127 if (util_format_is_subsampled_422(dst->buffer_format))
128 return VA_STATUS_ERROR_UNIMPLEMENTED;
129
130 surfaces = dst->get_surfaces(dst);
131 if (!surfaces || !surfaces[0])
132 return VA_STATUS_ERROR_INVALID_SURFACE;
133
134 src_rect.x0 = src_region->x;
135 src_rect.y0 = src_region->y;
136 src_rect.x1 = src_region->x + src_region->width;
137 src_rect.y1 = src_region->y + src_region->height;
138
139 dst_rect.x0 = dst_region->x;
140 dst_rect.y0 = dst_region->y;
141 dst_rect.x1 = dst_region->x + dst_region->width;
142 dst_rect.y1 = dst_region->y + dst_region->height;
143
144 if (src_yuv == dst_yuv) {
145 color_standard = VL_CSC_COLOR_STANDARD_IDENTITY;
146 } else if (src_yuv) {
147 switch (param->surface_color_standard) {
148 case VAProcColorStandardBT601:
149 color_standard = VL_CSC_COLOR_STANDARD_BT_601;
150 break;
151 case VAProcColorStandardBT709:
152 default:
153 color_standard = src_full_range ?
154 VL_CSC_COLOR_STANDARD_BT_709_FULL :
155 VL_CSC_COLOR_STANDARD_BT_709;
156 break;
157 }
158 } else {
159 color_standard = VL_CSC_COLOR_STANDARD_BT_709_REV;
160 }
161
162 if (util_format_get_nr_components(src->buffer_format) == 1)
163 color_standard = VL_CSC_COLOR_STANDARD_IDENTITY;
164
165 vl_csc_get_matrix(color_standard, NULL, dst_full_range, &drv->csc);
166 vl_compositor_set_csc_matrix(&drv->cstate, &drv->csc, 1.0f, 0.0f);
167
168 if (src_yuv)
169 drv->cstate.chroma_location =
170 vlVaGetChromaLocation(param->input_color_properties.chroma_sample_location,
171 src->buffer_format);
172 else if (dst_yuv)
173 drv->cstate.chroma_location =
174 vlVaGetChromaLocation(param->output_color_properties.chroma_sample_location,
175 dst->buffer_format);
176
177 switch (param->rotation_state) {
178 default:
179 case VA_ROTATION_NONE:
180 rotation = VL_COMPOSITOR_ROTATE_0;
181 break;
182 case VA_ROTATION_90:
183 rotation = VL_COMPOSITOR_ROTATE_90;
184 break;
185 case VA_ROTATION_180:
186 rotation = VL_COMPOSITOR_ROTATE_180;
187 break;
188 case VA_ROTATION_270:
189 rotation = VL_COMPOSITOR_ROTATE_270;
190 break;
191 }
192
193 switch (param->mirror_state) {
194 default:
195 case VA_MIRROR_NONE:
196 mirror = VL_COMPOSITOR_MIRROR_NONE;
197 break;
198 case VA_MIRROR_HORIZONTAL:
199 mirror = VL_COMPOSITOR_MIRROR_HORIZONTAL;
200 break;
201 case VA_MIRROR_VERTICAL:
202 mirror = VL_COMPOSITOR_MIRROR_VERTICAL;
203 break;
204 }
205
206 vl_compositor_clear_layers(&drv->cstate);
207 vl_compositor_set_layer_rotation(&drv->cstate, 0, rotation);
208 vl_compositor_set_layer_mirror(&drv->cstate, 0, mirror);
209
210 if (dst_yuv) {
211 if (src_yuv) {
212 /* YUV -> YUV */
213 if (src->interlaced == dst->interlaced)
214 deinterlace = VL_COMPOSITOR_NONE;
215 vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
216 src, dst, &src_rect, &dst_rect,
217 deinterlace);
218 } else {
219 /* RGB -> YUV */
220 vl_compositor_convert_rgb_to_yuv(&drv->cstate, &drv->compositor, 0,
221 ((struct vl_video_buffer *)src)->resources[0],
222 dst, &src_rect, &dst_rect);
223 }
224 } else {
225 /* YUV/RGB -> RGB */
226 vl_compositor_clear_layers(&drv->cstate);
227 vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src,
228 &src_rect, NULL, deinterlace);
229 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect);
230 vl_compositor_render(&drv->cstate, &drv->compositor, surfaces[0], NULL, false);
231 }
232
233 drv->cstate.chroma_location = VL_COMPOSITOR_LOCATION_NONE;
234
235 return VA_STATUS_SUCCESS;
236 }
237
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)238 static VAStatus vlVaVidEngineBlit(vlVaDriver *drv, vlVaContext *context,
239 const VARectangle *src_region,
240 const VARectangle *dst_region,
241 struct pipe_video_buffer *src,
242 struct pipe_video_buffer *dst,
243 enum vl_compositor_deinterlace deinterlace,
244 VAProcPipelineParameterBuffer* param)
245 {
246 if (deinterlace != VL_COMPOSITOR_NONE)
247 return VA_STATUS_ERROR_UNIMPLEMENTED;
248
249 if (!drv->pipe->screen->is_video_format_supported(drv->pipe->screen,
250 src->buffer_format,
251 PIPE_VIDEO_PROFILE_UNKNOWN,
252 PIPE_VIDEO_ENTRYPOINT_PROCESSING))
253 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
254
255 if (!drv->pipe->screen->is_video_format_supported(drv->pipe->screen,
256 dst->buffer_format,
257 PIPE_VIDEO_PROFILE_UNKNOWN,
258 PIPE_VIDEO_ENTRYPOINT_PROCESSING))
259 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
260
261 struct u_rect src_rect;
262 struct u_rect dst_rect;
263
264 src_rect.x0 = src_region->x;
265 src_rect.y0 = src_region->y;
266 src_rect.x1 = src_region->x + src_region->width;
267 src_rect.y1 = src_region->y + src_region->height;
268
269 dst_rect.x0 = dst_region->x;
270 dst_rect.y0 = dst_region->y;
271 dst_rect.x1 = dst_region->x + dst_region->width;
272 dst_rect.y1 = dst_region->y + dst_region->height;
273
274 context->desc.vidproc.base.input_format = src->buffer_format;
275 context->desc.vidproc.base.output_format = dst->buffer_format;
276
277 context->desc.vidproc.src_region = src_rect;
278 context->desc.vidproc.dst_region = dst_rect;
279
280 if (param->rotation_state == VA_ROTATION_NONE)
281 context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ORIENTATION_DEFAULT;
282 else if (param->rotation_state == VA_ROTATION_90)
283 context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_90;
284 else if (param->rotation_state == VA_ROTATION_180)
285 context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_180;
286 else if (param->rotation_state == VA_ROTATION_270)
287 context->desc.vidproc.orientation = PIPE_VIDEO_VPP_ROTATION_270;
288
289 if (param->mirror_state == VA_MIRROR_HORIZONTAL)
290 context->desc.vidproc.orientation |= PIPE_VIDEO_VPP_FLIP_HORIZONTAL;
291 if (param->mirror_state == VA_MIRROR_VERTICAL)
292 context->desc.vidproc.orientation |= PIPE_VIDEO_VPP_FLIP_VERTICAL;
293
294 memset(&context->desc.vidproc.blend, 0, sizeof(context->desc.vidproc.blend));
295 context->desc.vidproc.blend.mode = PIPE_VIDEO_VPP_BLEND_MODE_NONE;
296 if (param->blend_state != NULL) {
297 if (param->blend_state->flags & VA_BLEND_GLOBAL_ALPHA) {
298 context->desc.vidproc.blend.mode = PIPE_VIDEO_VPP_BLEND_MODE_GLOBAL_ALPHA;
299 context->desc.vidproc.blend.global_alpha = param->blend_state->global_alpha;
300 }
301 }
302
303 // Output background color
304 context->desc.vidproc.background_color = param->output_background_color;
305
306 // Input surface color standard
307 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_NONE;
308 if (param->surface_color_standard == VAProcColorStandardBT601)
309 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT601;
310 else if (param->surface_color_standard == VAProcColorStandardBT709)
311 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709;
312 else if (param->surface_color_standard == VAProcColorStandardBT2020)
313 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT2020;
314 else if (param->surface_color_standard == VAProcColorStandardExplicit) {
315 context->desc.vidproc.in_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_EXPLICIT;
316 context->desc.vidproc.in_color_primaries = param->input_color_properties.colour_primaries;
317 context->desc.vidproc.in_transfer_characteristics = param->input_color_properties.transfer_characteristics;
318 context->desc.vidproc.in_matrix_coefficients = param->input_color_properties.matrix_coefficients;
319 }
320
321 // Input surface color range
322 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_NONE;
323 if (param->input_color_properties.color_range == VA_SOURCE_RANGE_REDUCED)
324 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED;
325 else if (param->input_color_properties.color_range == VA_SOURCE_RANGE_FULL)
326 context->desc.vidproc.in_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL;
327
328 // Input surface chroma sample location
329 context->desc.vidproc.in_chroma_siting = PIPE_VIDEO_VPP_CHROMA_SITING_NONE;
330 if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_TOP)
331 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_TOP;
332 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_CENTER)
333 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_CENTER;
334 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_BOTTOM)
335 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_BOTTOM;
336 if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_LEFT)
337 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT;
338 else if (param->input_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_CENTER)
339 context->desc.vidproc.in_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER;
340
341 // Output surface color standard
342 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_NONE;
343 if (param->output_color_standard == VAProcColorStandardBT601)
344 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT601;
345 else if (param->output_color_standard == VAProcColorStandardBT709)
346 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709;
347 else if (param->output_color_standard == VAProcColorStandardBT2020)
348 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT2020;
349 else if (param->output_color_standard == VAProcColorStandardExplicit) {
350 context->desc.vidproc.out_colors_standard = PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_EXPLICIT;
351 context->desc.vidproc.out_color_primaries = param->output_color_properties.colour_primaries;
352 context->desc.vidproc.out_transfer_characteristics = param->output_color_properties.transfer_characteristics;
353 context->desc.vidproc.out_matrix_coefficients = param->output_color_properties.matrix_coefficients;
354 }
355
356 // Output surface color range
357 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_NONE;
358 if (param->output_color_properties.color_range == VA_SOURCE_RANGE_REDUCED)
359 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED;
360 else if (param->output_color_properties.color_range == VA_SOURCE_RANGE_FULL)
361 context->desc.vidproc.out_color_range = PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL;
362
363 // Output surface chroma sample location
364 context->desc.vidproc.out_chroma_siting = PIPE_VIDEO_VPP_CHROMA_SITING_NONE;
365 if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_TOP)
366 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_TOP;
367 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_CENTER)
368 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_CENTER;
369 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_VERTICAL_BOTTOM)
370 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_VERTICAL_BOTTOM;
371 if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_LEFT)
372 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_LEFT;
373 else if (param->output_color_properties.chroma_sample_location & VA_CHROMA_SITING_HORIZONTAL_CENTER)
374 context->desc.vidproc.out_chroma_siting |= PIPE_VIDEO_VPP_CHROMA_SITING_HORIZONTAL_CENTER;
375
376 if (context->needs_begin_frame) {
377 context->decoder->begin_frame(context->decoder, dst,
378 &context->desc.base);
379 context->needs_begin_frame = false;
380 }
381
382 if (context->decoder->process_frame(context->decoder, src, &context->desc.vidproc))
383 return VA_STATUS_ERROR_OPERATION_FAILED;
384
385 return VA_STATUS_SUCCESS;
386 }
387
388 static struct pipe_video_buffer *
vlVaApplyDeint(vlVaDriver * drv,vlVaContext * context,VAProcPipelineParameterBuffer * param,struct pipe_video_buffer * current,unsigned field)389 vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
390 VAProcPipelineParameterBuffer *param,
391 struct pipe_video_buffer *current,
392 unsigned field)
393 {
394 vlVaSurface *prevprev, *prev, *next;
395
396 if (param->num_forward_references < 2 ||
397 param->num_backward_references < 1)
398 return current;
399
400 prevprev = handle_table_get(drv->htab, param->forward_references[1]);
401 prev = handle_table_get(drv->htab, param->forward_references[0]);
402 next = handle_table_get(drv->htab, param->backward_references[0]);
403
404 if (!prevprev || !prev || !next)
405 return current;
406
407 if (context->deint && (context->deint->video_width != current->width ||
408 context->deint->video_height != current->height ||
409 context->deint->interleaved != !current->interlaced)) {
410 vl_deint_filter_cleanup(context->deint);
411 FREE(context->deint);
412 context->deint = NULL;
413 }
414
415 if (!context->deint) {
416 context->deint = MALLOC(sizeof(struct vl_deint_filter));
417 if (!vl_deint_filter_init(context->deint, drv->pipe, current->width,
418 current->height, false, false, !current->interlaced)) {
419 FREE(context->deint);
420 context->deint = NULL;
421 return current;
422 }
423 }
424
425 if (!vl_deint_filter_check_buffers(context->deint, prevprev->buffer,
426 prev->buffer, current, next->buffer))
427 return current;
428
429 vl_deint_filter_render(context->deint, prevprev->buffer, prev->buffer,
430 current, next->buffer, field);
431
432 return context->deint->video_buffer;
433 }
434
435 VAStatus
vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver * drv,vlVaContext * context,vlVaBuffer * buf)436 vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
437 {
438 enum vl_compositor_deinterlace deinterlace = VL_COMPOSITOR_NONE;
439 VARectangle def_src_region, def_dst_region;
440 const VARectangle *src_region, *dst_region;
441 VAProcPipelineParameterBuffer *param;
442 struct pipe_video_buffer *src;
443 vlVaSurface *src_surface, *dst_surface;
444 unsigned i;
445 struct pipe_screen *pscreen;
446
447 if (!drv || !context)
448 return VA_STATUS_ERROR_INVALID_CONTEXT;
449
450 if (!buf || !buf->data)
451 return VA_STATUS_ERROR_INVALID_BUFFER;
452
453 if (!context->target)
454 return VA_STATUS_ERROR_INVALID_SURFACE;
455
456 param = buf->data;
457
458 src_surface = handle_table_get(drv->htab, param->surface);
459 dst_surface = handle_table_get(drv->htab, context->target_id);
460 if (!src_surface || !dst_surface)
461 return VA_STATUS_ERROR_INVALID_SURFACE;
462 vlVaGetSurfaceBuffer(drv, src_surface);
463 vlVaGetSurfaceBuffer(drv, dst_surface);
464 if (!src_surface->buffer || !dst_surface->buffer)
465 return VA_STATUS_ERROR_INVALID_SURFACE;
466
467 src_surface->full_range = vlVaGetFullRange(src_surface->buffer->buffer_format,
468 param->input_color_properties.color_range);
469 dst_surface->full_range = vlVaGetFullRange(dst_surface->buffer->buffer_format,
470 param->output_color_properties.color_range);
471
472 pscreen = drv->vscreen->pscreen;
473
474 src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region);
475 dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region);
476
477 /* EFC can only do one conversion, and it must be the last postproc
478 * operation immediately before encoding.
479 * Disable EFC completely if this is not the case. */
480 if (drv->last_efc_surface) {
481 vlVaSurface *surf = drv->last_efc_surface;
482 surf->efc_surface = NULL;
483 drv->last_efc_surface = NULL;
484 drv->efc_count = -1;
485 }
486
487 if (drv->efc_count >= 0 && !param->num_filters &&
488 src_region->width == dst_region->width &&
489 src_region->height == dst_region->height &&
490 src_region->x == dst_region->x &&
491 src_region->y == dst_region->y &&
492 pscreen->is_video_target_buffer_supported &&
493 pscreen->is_video_target_buffer_supported(pscreen,
494 dst_surface->buffer->buffer_format,
495 src_surface->buffer,
496 PIPE_VIDEO_PROFILE_UNKNOWN,
497 PIPE_VIDEO_ENTRYPOINT_ENCODE)) {
498
499 dst_surface->efc_surface = src_surface;
500 drv->last_efc_surface = dst_surface;
501
502 /* Do the blit for first few conversions as a fallback in case EFC
503 * could not be used (see above), after that assume EFC can always
504 * be used and skip the blit. */
505 if (drv->efc_count < 16)
506 drv->efc_count++;
507 else
508 return VA_STATUS_SUCCESS;
509 }
510
511 src = src_surface->buffer;
512
513 for (i = 0; i < param->num_filters; i++) {
514 vlVaBuffer *buf = handle_table_get(drv->htab, param->filters[i]);
515 VAProcFilterParameterBufferBase *filter;
516
517 if (!buf || buf->type != VAProcFilterParameterBufferType)
518 return VA_STATUS_ERROR_INVALID_BUFFER;
519
520 filter = buf->data;
521 switch (filter->type) {
522 case VAProcFilterDeinterlacing: {
523 VAProcFilterParameterBufferDeinterlacing *deint = buf->data;
524 switch (deint->algorithm) {
525 case VAProcDeinterlacingBob:
526 if (deint->flags & VA_DEINTERLACING_BOTTOM_FIELD)
527 deinterlace = VL_COMPOSITOR_BOB_BOTTOM;
528 else
529 deinterlace = VL_COMPOSITOR_BOB_TOP;
530 break;
531
532 case VAProcDeinterlacingWeave:
533 deinterlace = VL_COMPOSITOR_WEAVE;
534 break;
535
536 case VAProcDeinterlacingMotionAdaptive:
537 src = vlVaApplyDeint(drv, context, param, src,
538 !!(deint->flags & VA_DEINTERLACING_BOTTOM_FIELD));
539 deinterlace = VL_COMPOSITOR_MOTION_ADAPTIVE;
540 break;
541
542 default:
543 return VA_STATUS_ERROR_UNIMPLEMENTED;
544 }
545 drv->compositor.deinterlace = deinterlace;
546 break;
547 }
548
549 default:
550 return VA_STATUS_ERROR_UNIMPLEMENTED;
551 }
552 }
553
554 /* If the driver supports video engine post proc, attempt to do that
555 * if it fails, fallback to the other existing implementations below
556 */
557 if (pscreen->get_video_param(pscreen,
558 PIPE_VIDEO_PROFILE_UNKNOWN,
559 PIPE_VIDEO_ENTRYPOINT_PROCESSING,
560 PIPE_VIDEO_CAP_SUPPORTED)) {
561 if (!context->decoder) {
562 mtx_lock(&context->mutex);
563 context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat);
564 mtx_unlock(&context->mutex);
565 if (!context->decoder)
566 return VA_STATUS_ERROR_ALLOCATION_FAILED;
567 }
568
569 context->desc.vidproc.src_surface_fence = src_surface->fence;
570 /* Perform VPBlit, if fail, fallback to other implementations below */
571 if (VA_STATUS_SUCCESS == vlVaVidEngineBlit(drv, context, src_region, dst_region,
572 src, context->target, deinterlace, param))
573 return VA_STATUS_SUCCESS;
574 }
575
576 VAStatus ret = vlVaPostProcCompositor(drv, src_region, dst_region,
577 src, context->target, deinterlace, param);
578 vlVaSurfaceFlush(drv, dst_surface);
579 return ret;
580 }
581