• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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