From aa52f89b6ae838677b32dd90a2aa8b17d44706da Mon Sep 17 00:00:00 2001 From: fritsch Date: Thu, 19 Mar 2015 16:53:39 +0100 Subject: [PATCH] libva-intel-driver: Fix Advanced deinterlacing on IVB SNB BYT --- ...el-driver-01-fix-mcdi-on-ivb-byt-snb.patch | 1168 +++++++++++++++++ 1 file changed, 1168 insertions(+) create mode 100644 packages/multimedia/libva-intel-driver/patches/libva-intel-driver-01-fix-mcdi-on-ivb-byt-snb.patch diff --git a/packages/multimedia/libva-intel-driver/patches/libva-intel-driver-01-fix-mcdi-on-ivb-byt-snb.patch b/packages/multimedia/libva-intel-driver/patches/libva-intel-driver-01-fix-mcdi-on-ivb-byt-snb.patch new file mode 100644 index 0000000000..d24fb25402 --- /dev/null +++ b/packages/multimedia/libva-intel-driver/patches/libva-intel-driver-01-fix-mcdi-on-ivb-byt-snb.patch @@ -0,0 +1,1168 @@ +From 80dc29f005cd04de5e0f75701f86ef17f515ae48 Mon Sep 17 00:00:00 2001 +From: Gwenole Beauchesne +Date: Tue, 28 Oct 2014 13:21:43 +0100 +Subject: [PATCH 1/4] vpp: fix memory leak in DNDI code path. + +The original current_out_surface was never released on exit. Main +reason for that is the legacy VPP framework that did not allow the +VADriverContextP handle to be passed down to the desired .finalize() +hook. Improved that to bring it on par with the VEBOX code path. + +Signed-off-by: Gwenole Beauchesne +--- + src/gen8_post_processing.c | 3 ++- + src/i965_post_processing.c | 18 ++++++++++++++---- + src/i965_post_processing.h | 4 +++- + 3 files changed, 19 insertions(+), 6 deletions(-) + +diff --git a/src/gen8_post_processing.c b/src/gen8_post_processing.c +index 320a1bf..de56b39 100644 +--- a/src/gen8_post_processing.c ++++ b/src/gen8_post_processing.c +@@ -1386,7 +1386,8 @@ gen8_post_processing( + } + + static void +-gen8_post_processing_context_finalize(struct i965_post_processing_context *pp_context) ++gen8_post_processing_context_finalize(VADriverContextP ctx, ++ struct i965_post_processing_context *pp_context) + { + dri_bo_unreference(pp_context->surface_state_binding_table.bo); + pp_context->surface_state_binding_table.bo = NULL; +diff --git a/src/i965_post_processing.c b/src/i965_post_processing.c +index 0481408..fddba54 100755 +--- a/src/i965_post_processing.c ++++ b/src/i965_post_processing.c +@@ -5272,7 +5272,8 @@ i965_image_processing(VADriverContextP ctx, + } + + static void +-i965_post_processing_context_finalize(struct i965_post_processing_context *pp_context) ++i965_post_processing_context_finalize(VADriverContextP ctx, ++ struct i965_post_processing_context *pp_context) + { + int i; + +@@ -5301,6 +5302,13 @@ i965_post_processing_context_finalize(struct i965_post_processing_context *pp_co + dri_bo_unreference(pp_context->pp_dndi_context.stmm_bo); + pp_context->pp_dndi_context.stmm_bo = NULL; + ++ if (pp_context->pp_dndi_context.current_out_surface != VA_INVALID_ID) { ++ i965_DestroySurfaces(ctx, ++ &pp_context->pp_dndi_context.current_out_surface, 1); ++ pp_context->pp_dndi_context.current_out_surface = VA_INVALID_ID; ++ pp_context->pp_dndi_context.current_out_obj_surface = NULL; ++ } ++ + dri_bo_unreference(pp_context->pp_dn_context.stmm_bo); + pp_context->pp_dn_context.stmm_bo = NULL; + +@@ -5324,7 +5332,7 @@ i965_post_processing_terminate(VADriverContextP ctx) + struct i965_post_processing_context *pp_context = i965->pp_context; + + if (pp_context) { +- pp_context->finalize(pp_context); ++ pp_context->finalize(ctx, pp_context); + free(pp_context); + } + +@@ -5699,9 +5707,10 @@ error: + static void + i965_proc_context_destroy(void *hw_context) + { +- struct i965_proc_context *proc_context = (struct i965_proc_context *)hw_context; ++ struct i965_proc_context * const proc_context = hw_context; ++ VADriverContextP const ctx = proc_context->driver_context; + +- i965_post_processing_context_finalize(&proc_context->pp_context); ++ i965_post_processing_context_finalize(ctx, &proc_context->pp_context); + intel_batchbuffer_free(proc_context->base.batch); + free(proc_context); + } +@@ -5716,6 +5725,7 @@ i965_proc_context_init(VADriverContextP ctx, struct object_config *obj_config) + proc_context->base.destroy = i965_proc_context_destroy; + proc_context->base.run = i965_proc_picture; + proc_context->base.batch = intel_batchbuffer_new(intel, I915_EXEC_RENDER, 0); ++ proc_context->driver_context = ctx; + i965->codec_info->post_processing_context_init(ctx, &proc_context->pp_context, proc_context->base.batch); + + return (struct hw_context *)proc_context; +diff --git a/src/i965_post_processing.h b/src/i965_post_processing.h +index d434527..e6940c0 100755 +--- a/src/i965_post_processing.h ++++ b/src/i965_post_processing.h +@@ -542,12 +542,14 @@ struct i965_post_processing_context + const VARectangle *dst_rect, + int pp_index, + void * filter_param); +- void (*finalize)(struct i965_post_processing_context *pp_context); ++ void (*finalize)(VADriverContextP ctx, ++ struct i965_post_processing_context *pp_context); + }; + + struct i965_proc_context + { + struct hw_context base; ++ void *driver_context; + struct i965_post_processing_context pp_context; + }; + +-- +1.9.1 + + +From db34504cdfe705c4b26e417e35a72c8bbaf4ce52 Mon Sep 17 00:00:00 2001 +From: Gwenole Beauchesne +Date: Tue, 21 Oct 2014 17:13:07 +0200 +Subject: [PATCH 2/4] vpp: fix advanced deinterlacing on Sandybridge and + Ivybridge. + +This fixes support for Motion Adaptive deinterlacing mode on both +Sandybridge and Ivybridge platforms. In particular, correct field +ordering is now supported, and STMM ping-pong buffering is added. + +v2: changed STMM surface format to Y800 for a single plane. + +Signed-off-by: Gwenole Beauchesne +--- + src/gen8_post_processing.c | 6 - + src/i965_post_processing.c | 779 +++++++++++++++++++++++++-------------------- + src/i965_post_processing.h | 27 +- + 3 files changed, 452 insertions(+), 360 deletions(-) + +diff --git a/src/gen8_post_processing.c b/src/gen8_post_processing.c +index de56b39..8e57af2 100644 +--- a/src/gen8_post_processing.c ++++ b/src/gen8_post_processing.c +@@ -1392,9 +1392,6 @@ gen8_post_processing_context_finalize(VADriverContextP ctx, + dri_bo_unreference(pp_context->surface_state_binding_table.bo); + pp_context->surface_state_binding_table.bo = NULL; + +- dri_bo_unreference(pp_context->pp_dndi_context.stmm_bo); +- pp_context->pp_dndi_context.stmm_bo = NULL; +- + dri_bo_unreference(pp_context->pp_dn_context.stmm_bo); + pp_context->pp_dn_context.stmm_bo = NULL; + +@@ -1498,9 +1495,6 @@ gen8_post_processing_context_common_init(VADriverContextP ctx, + pp_context->pp_static_parameter = calloc(sizeof(struct gen7_pp_static_parameter), 1); + pp_context->pp_inline_parameter = calloc(sizeof(struct gen7_pp_inline_parameter), 1); + +- pp_context->pp_dndi_context.current_out_surface = VA_INVALID_SURFACE; +- pp_context->pp_dndi_context.current_out_obj_surface = NULL; +- pp_context->pp_dndi_context.frame_order = -1; + pp_context->batch = batch; + + pp_context->idrt_size = 5 * sizeof(struct gen8_interface_descriptor_data); +diff --git a/src/i965_post_processing.c b/src/i965_post_processing.c +index fddba54..588b065 100755 +--- a/src/i965_post_processing.c ++++ b/src/i965_post_processing.c +@@ -1137,6 +1137,271 @@ static struct pp_module pp_modules_gen75[] = { + + }; + ++static void ++pp_dndi_frame_store_reset(DNDIFrameStore *fs) ++{ ++ fs->obj_surface = NULL; ++ fs->surface_id = VA_INVALID_ID; ++ fs->is_scratch_surface = 0; ++} ++ ++static inline void ++pp_dndi_frame_store_swap(DNDIFrameStore *fs1, DNDIFrameStore *fs2) ++{ ++ const DNDIFrameStore tmpfs = *fs1; ++ *fs1 = *fs2; ++ *fs2 = tmpfs; ++} ++ ++static inline void ++pp_dndi_frame_store_clear(DNDIFrameStore *fs, VADriverContextP ctx) ++{ ++ if (fs->obj_surface && fs->is_scratch_surface) { ++ VASurfaceID va_surface = fs->obj_surface->base.id; ++ i965_DestroySurfaces(ctx, &va_surface, 1); ++ } ++ pp_dndi_frame_store_reset(fs); ++} ++ ++static void ++pp_dndi_context_init(struct pp_dndi_context *dndi_ctx) ++{ ++ int i; ++ ++ memset(dndi_ctx, 0, sizeof(*dndi_ctx)); ++ for (i = 0; i < ARRAY_ELEMS(dndi_ctx->frame_store); i++) ++ pp_dndi_frame_store_reset(&dndi_ctx->frame_store[i]); ++} ++ ++static VAStatus ++pp_dndi_context_init_surface_params(struct pp_dndi_context *dndi_ctx, ++ struct object_surface *obj_surface, ++ const VAProcPipelineParameterBuffer *pipe_params, ++ const VAProcFilterParameterBufferDeinterlacing *deint_params) ++{ ++ DNDIFrameStore *fs; ++ ++ dndi_ctx->is_di_enabled = 1; ++ dndi_ctx->is_di_adv_enabled = 0; ++ dndi_ctx->is_first_frame = 0; ++ dndi_ctx->is_second_field = 0; ++ ++ /* Check whether we are deinterlacing the second field */ ++ if (dndi_ctx->is_di_enabled) { ++ const unsigned int tff = ++ !(deint_params->flags & VA_DEINTERLACING_BOTTOM_FIELD_FIRST); ++ const unsigned int is_top_field = ++ !(deint_params->flags & VA_DEINTERLACING_BOTTOM_FIELD); ++ ++ if ((tff ^ is_top_field) != 0) { ++ fs = &dndi_ctx->frame_store[DNDI_FRAME_IN_CURRENT]; ++ if (fs->surface_id != obj_surface->base.id) { ++ WARN_ONCE("invalid surface provided for second field\n"); ++ return VA_STATUS_ERROR_INVALID_PARAMETER; ++ } ++ dndi_ctx->is_second_field = 1; ++ } ++ } ++ ++ /* Check whether we are deinterlacing the first frame */ ++ if (dndi_ctx->is_di_enabled) { ++ switch (deint_params->algorithm) { ++ case VAProcDeinterlacingBob: ++ dndi_ctx->is_first_frame = 1; ++ break; ++ case VAProcDeinterlacingMotionAdaptive: ++ fs = &dndi_ctx->frame_store[DNDI_FRAME_IN_CURRENT]; ++ if (fs->surface_id == VA_INVALID_ID) ++ dndi_ctx->is_first_frame = 1; ++ else if (dndi_ctx->is_second_field) { ++ /* At this stage, we have already deinterlaced the ++ first field successfully. So, the first frame flag ++ is trigerred if the previous field was deinterlaced ++ without reference frame */ ++ fs = &dndi_ctx->frame_store[DNDI_FRAME_IN_PREVIOUS]; ++ if (fs->surface_id == VA_INVALID_ID) ++ dndi_ctx->is_first_frame = 1; ++ } ++ else { ++ if (pipe_params->num_forward_references < 1 || ++ pipe_params->forward_references[0] == VA_INVALID_ID) { ++ WARN_ONCE("A forward temporal reference is needed for Motion adaptive/compensated deinterlacing !!!\n"); ++ return VA_STATUS_ERROR_INVALID_PARAMETER; ++ } ++ } ++ dndi_ctx->is_di_adv_enabled = 1; ++ break; ++ default: ++ WARN_ONCE("unsupported deinterlacing algorithm (%d)\n", ++ deint_params->algorithm); ++ return VA_STATUS_ERROR_UNSUPPORTED_FILTER; ++ } ++ } ++ return VA_STATUS_SUCCESS; ++} ++ ++static VAStatus ++pp_dndi_context_ensure_surfaces_storage(VADriverContextP ctx, ++ struct i965_post_processing_context *pp_context, ++ struct object_surface *src_surface, struct object_surface *dst_surface) ++{ ++ struct i965_driver_data * const i965 = i965_driver_data(ctx); ++ struct pp_dndi_context * const dndi_ctx = &pp_context->pp_dndi_context; ++ unsigned int src_fourcc, dst_fourcc; ++ unsigned int src_sampling, dst_sampling; ++ unsigned int src_tiling, dst_tiling; ++ unsigned int i, swizzle; ++ VAStatus status; ++ ++ /* Determine input surface info. Always use NV12 Y-tiled */ ++ if (src_surface->bo) { ++ src_fourcc = src_surface->fourcc; ++ src_sampling = src_surface->subsampling; ++ dri_bo_get_tiling(src_surface->bo, &src_tiling, &swizzle); ++ src_tiling = !!src_tiling; ++ } ++ else { ++ src_fourcc = VA_FOURCC_NV12; ++ src_sampling = SUBSAMPLE_YUV420; ++ src_tiling = 1; ++ status = i965_check_alloc_surface_bo(ctx, src_surface, ++ src_tiling, src_fourcc, src_sampling); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ } ++ ++ /* Determine output surface info. Always use NV12 Y-tiled */ ++ if (dst_surface->bo) { ++ dst_fourcc = dst_surface->fourcc; ++ dst_sampling = dst_surface->subsampling; ++ dri_bo_get_tiling(dst_surface->bo, &dst_tiling, &swizzle); ++ dst_tiling = !!dst_tiling; ++ } ++ else { ++ dst_fourcc = VA_FOURCC_NV12; ++ dst_sampling = SUBSAMPLE_YUV420; ++ dst_tiling = 1; ++ status = i965_check_alloc_surface_bo(ctx, dst_surface, ++ dst_tiling, dst_fourcc, dst_sampling); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ } ++ ++ /* Create pipeline surfaces */ ++ for (i = 0; i < ARRAY_ELEMS(dndi_ctx->frame_store); i ++) { ++ struct object_surface *obj_surface; ++ VASurfaceID new_surface; ++ unsigned int width, height; ++ ++ if (dndi_ctx->frame_store[i].obj_surface) ++ continue; // user allocated surface, not VPP internal ++ ++ if (i <= DNDI_FRAME_IN_STMM) { ++ width = src_surface->orig_width; ++ height = src_surface->orig_height; ++ } ++ else { ++ width = dst_surface->orig_width; ++ height = dst_surface->orig_height; ++ } ++ ++ status = i965_CreateSurfaces(ctx, width, height, VA_RT_FORMAT_YUV420, ++ 1, &new_surface); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ ++ obj_surface = SURFACE(new_surface); ++ assert(obj_surface != NULL); ++ ++ if (i <= DNDI_FRAME_IN_PREVIOUS) { ++ status = i965_check_alloc_surface_bo(ctx, obj_surface, ++ src_tiling, src_fourcc, src_sampling); ++ } ++ else if (i == DNDI_FRAME_IN_STMM || i == DNDI_FRAME_OUT_STMM) { ++ status = i965_check_alloc_surface_bo(ctx, obj_surface, ++ 1, VA_FOURCC_Y800, SUBSAMPLE_YUV400); ++ } ++ else if (i >= DNDI_FRAME_OUT_CURRENT) { ++ status = i965_check_alloc_surface_bo(ctx, obj_surface, ++ dst_tiling, dst_fourcc, dst_sampling); ++ } ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ ++ dndi_ctx->frame_store[i].obj_surface = obj_surface; ++ dndi_ctx->frame_store[i].is_scratch_surface = 1; ++ } ++ return VA_STATUS_SUCCESS; ++} ++ ++static VAStatus ++pp_dndi_context_ensure_surfaces(VADriverContextP ctx, ++ struct i965_post_processing_context *pp_context, ++ struct object_surface *src_surface, struct object_surface *dst_surface) ++{ ++ struct i965_driver_data * const i965 = i965_driver_data(ctx); ++ struct pp_dndi_context * const dndi_ctx = &pp_context->pp_dndi_context; ++ DNDIFrameStore *ifs, *ofs; ++ bool is_new_frame = false; ++ ++ /* Update the previous input surface */ ++ is_new_frame = dndi_ctx->frame_store[DNDI_FRAME_IN_CURRENT].surface_id != ++ src_surface->base.id; ++ if (is_new_frame) { ++ ifs = &dndi_ctx->frame_store[DNDI_FRAME_IN_PREVIOUS]; ++ ofs = &dndi_ctx->frame_store[DNDI_FRAME_IN_CURRENT]; ++ do { ++ const VAProcPipelineParameterBuffer * const pipe_params = ++ pp_context->pipeline_param; ++ struct object_surface *obj_surface; ++ ++ if (pipe_params->num_forward_references < 1) ++ break; ++ if (pipe_params->forward_references[0] == VA_INVALID_ID) ++ break; ++ ++ obj_surface = SURFACE(pipe_params->forward_references[0]); ++ if (!obj_surface || obj_surface->base.id == ifs->surface_id) ++ break; ++ ++ pp_dndi_frame_store_clear(ifs, ctx); ++ if (obj_surface->base.id == ofs->surface_id) { ++ *ifs = *ofs; ++ pp_dndi_frame_store_reset(ofs); ++ } ++ else { ++ ifs->obj_surface = obj_surface; ++ ifs->surface_id = obj_surface->base.id; ++ } ++ } while (0); ++ } ++ ++ /* Update the input surface */ ++ ifs = &dndi_ctx->frame_store[DNDI_FRAME_IN_CURRENT]; ++ pp_dndi_frame_store_clear(ifs, ctx); ++ ifs->obj_surface = src_surface; ++ ifs->surface_id = src_surface->base.id; ++ ++ /* Update the Spatial Temporal Motion Measure (STMM) surfaces */ ++ if (is_new_frame) ++ pp_dndi_frame_store_swap(&dndi_ctx->frame_store[DNDI_FRAME_IN_STMM], ++ &dndi_ctx->frame_store[DNDI_FRAME_OUT_STMM]); ++ ++ /* Update the output surfaces */ ++ ofs = &dndi_ctx->frame_store[DNDI_FRAME_OUT_CURRENT]; ++ if (dndi_ctx->is_di_adv_enabled && !dndi_ctx->is_first_frame) { ++ pp_dndi_frame_store_swap(ofs, ++ &dndi_ctx->frame_store[DNDI_FRAME_OUT_PREVIOUS]); ++ if (!dndi_ctx->is_second_field) ++ ofs = &dndi_ctx->frame_store[DNDI_FRAME_OUT_PREVIOUS]; ++ } ++ pp_dndi_frame_store_clear(ofs, ctx); ++ ofs->obj_surface = dst_surface; ++ ofs->surface_id = dst_surface->base.id; ++ ++ return VA_STATUS_SUCCESS; ++} ++ + static int + pp_get_surface_fourcc(VADriverContextP ctx, const struct i965_surface *surface) + { +@@ -3071,177 +3336,91 @@ pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_contex + const VARectangle *dst_rect, + void *filter_param) + { +- struct i965_driver_data *i965 = i965_driver_data(ctx); +- struct pp_dndi_context *pp_dndi_context = (struct pp_dndi_context *)&pp_context->pp_dndi_context; ++ struct pp_dndi_context * const dndi_ctx = &pp_context->pp_dndi_context; + struct pp_inline_parameter *pp_inline_parameter = pp_context->pp_inline_parameter; + struct pp_static_parameter *pp_static_parameter = pp_context->pp_static_parameter; +- struct object_surface *previous_in_obj_surface, *current_in_obj_surface, *previous_out_obj_surface, *current_out_obj_surface; ++ const VAProcPipelineParameterBuffer * const pipe_params = ++ pp_context->pipeline_param; ++ const VAProcFilterParameterBufferDeinterlacing * const deint_params = ++ filter_param; ++ struct object_surface * const src_obj_surface = (struct object_surface *) ++ src_surface->base; ++ struct object_surface * const dst_obj_surface = (struct object_surface *) ++ dst_surface->base; ++ struct object_surface *obj_surface; + struct i965_sampler_dndi *sampler_dndi; +- int index; +- int w, h; +- int orig_w, orig_h; +- int dndi_top_first = 1; +- VAProcFilterParameterBufferDeinterlacing *di_filter_param = (VAProcFilterParameterBufferDeinterlacing *)filter_param; +- int is_first_frame = (pp_dndi_context->frame_order == -1); +- +- if (di_filter_param->flags & VA_DEINTERLACING_BOTTOM_FIELD) +- dndi_top_first = 0; +- else +- dndi_top_first = 1; +- +- /* surface */ +- current_in_obj_surface = (struct object_surface *)src_surface->base; +- +- if (di_filter_param->algorithm == VAProcDeinterlacingBob) { +- previous_in_obj_surface = current_in_obj_surface; +- is_first_frame = 1; +- } else if (di_filter_param->algorithm == VAProcDeinterlacingMotionAdaptive) { +- if (pp_dndi_context->frame_order == 0) { +- VAProcPipelineParameterBuffer *pipeline_param = pp_context->pipeline_param; +- if (!pipeline_param || +- !pipeline_param->num_forward_references || +- pipeline_param->forward_references[0] == VA_INVALID_ID) { +- WARN_ONCE("A forward temporal reference is needed for Motion adaptive deinterlacing !!!\n"); +- +- return VA_STATUS_ERROR_INVALID_PARAMETER; +- } else { +- previous_in_obj_surface = SURFACE(pipeline_param->forward_references[0]); +- assert(previous_in_obj_surface && previous_in_obj_surface->bo); +- +- is_first_frame = 0; +- } +- } else if (pp_dndi_context->frame_order == 1) { +- vpp_surface_convert(ctx, +- pp_dndi_context->current_out_obj_surface, +- (struct object_surface *)dst_surface->base); +- pp_dndi_context->frame_order = (pp_dndi_context->frame_order + 1) % 2; +- is_first_frame = 0; +- +- return VA_STATUS_SUCCESS_1; +- } else { +- previous_in_obj_surface = current_in_obj_surface; +- is_first_frame = 1; +- } +- } else { +- return VA_STATUS_ERROR_UNIMPLEMENTED; +- } +- +- /* source (temporal reference) YUV surface index 5 */ +- orig_w = previous_in_obj_surface->orig_width; +- orig_h = previous_in_obj_surface->orig_height; +- w = previous_in_obj_surface->width; +- h = previous_in_obj_surface->height; +- i965_pp_set_surface2_state(ctx, pp_context, +- previous_in_obj_surface->bo, 0, +- orig_w, orig_h, w, +- 0, h, +- SURFACE_FORMAT_PLANAR_420_8, 1, +- 5); +- +- /* source surface */ +- orig_w = current_in_obj_surface->orig_width; +- orig_h = current_in_obj_surface->orig_height; +- w = current_in_obj_surface->width; +- h = current_in_obj_surface->height; +- +- /* source UV surface index 2 */ +- i965_pp_set_surface_state(ctx, pp_context, +- current_in_obj_surface->bo, w * h, +- orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, +- 2, 0); +- +- /* source YUV surface index 4 */ +- i965_pp_set_surface2_state(ctx, pp_context, +- current_in_obj_surface->bo, 0, +- orig_w, orig_h, w, +- 0, h, +- SURFACE_FORMAT_PLANAR_420_8, 1, +- 4); +- +- /* source STMM surface index 6 */ +- if (pp_dndi_context->stmm_bo == NULL) { +- pp_dndi_context->stmm_bo = dri_bo_alloc(i965->intel.bufmgr, +- "STMM surface", +- w * h, +- 4096); +- assert(pp_dndi_context->stmm_bo); +- } +- +- i965_pp_set_surface_state(ctx, pp_context, +- pp_dndi_context->stmm_bo, 0, +- orig_w, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, +- 6, 0); +- +- /* destination (Previous frame) */ +- previous_out_obj_surface = (struct object_surface *)dst_surface->base; +- orig_w = previous_out_obj_surface->orig_width; +- orig_h = previous_out_obj_surface->orig_height; +- w = previous_out_obj_surface->width; +- h = previous_out_obj_surface->height; +- +- if (is_first_frame) { +- current_out_obj_surface = previous_out_obj_surface; +- } else { +- VAStatus va_status; +- +- if (pp_dndi_context->current_out_surface == VA_INVALID_SURFACE) { +- unsigned int tiling = 0, swizzle = 0; +- dri_bo_get_tiling(previous_out_obj_surface->bo, &tiling, &swizzle); +- +- va_status = i965_CreateSurfaces(ctx, +- orig_w, +- orig_h, +- VA_RT_FORMAT_YUV420, +- 1, +- &pp_dndi_context->current_out_surface); +- assert(va_status == VA_STATUS_SUCCESS); +- pp_dndi_context->current_out_obj_surface = SURFACE(pp_dndi_context->current_out_surface); +- assert(pp_dndi_context->current_out_obj_surface); +- i965_check_alloc_surface_bo(ctx, +- pp_dndi_context->current_out_obj_surface, +- tiling != I915_TILING_NONE, +- VA_FOURCC_NV12, +- SUBSAMPLE_YUV420); +- } ++ int index, dndi_top_first; ++ int w, h, orig_w, orig_h; ++ VAStatus status; + +- current_out_obj_surface = pp_dndi_context->current_out_obj_surface; +- } ++ status = pp_dndi_context_init_surface_params(dndi_ctx, src_obj_surface, ++ pipe_params, deint_params); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ ++ status = pp_dndi_context_ensure_surfaces(ctx, pp_context, ++ src_obj_surface, dst_obj_surface); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ ++ status = pp_dndi_context_ensure_surfaces_storage(ctx, pp_context, ++ src_obj_surface, dst_obj_surface); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ ++ /* Current input surface (index = 4) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_IN_CURRENT].obj_surface; ++ i965_pp_set_surface2_state(ctx, pp_context, obj_surface->bo, 0, ++ obj_surface->orig_width, obj_surface->orig_height, obj_surface->width, ++ 0, obj_surface->y_cb_offset, SURFACE_FORMAT_PLANAR_420_8, 1, 4); ++ ++ /* Previous input surface (index = 5) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_IN_PREVIOUS].obj_surface; ++ i965_pp_set_surface2_state(ctx, pp_context, obj_surface->bo, 0, ++ obj_surface->orig_width, obj_surface->orig_height, obj_surface->width, ++ 0, obj_surface->y_cb_offset, SURFACE_FORMAT_PLANAR_420_8, 1, 5); ++ ++ /* STMM input surface (index = 6) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_IN_STMM].obj_surface; ++ i965_pp_set_surface_state(ctx, pp_context, obj_surface->bo, 0, ++ obj_surface->orig_width, obj_surface->orig_height, obj_surface->width, ++ I965_SURFACEFORMAT_R8_UNORM, 6, 1); ++ ++ /* Previous output surfaces (index = { 7, 8 }) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_OUT_PREVIOUS].obj_surface; ++ w = obj_surface->width; ++ h = obj_surface->height; ++ orig_w = obj_surface->orig_width; ++ orig_h = obj_surface->orig_height; + +- /* destination (Previous frame) Y surface index 7 */ +- i965_pp_set_surface_state(ctx, pp_context, +- previous_out_obj_surface->bo, 0, +- orig_w / 4, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, +- 7, 1); ++ i965_pp_set_surface_state(ctx, pp_context, obj_surface->bo, 0, ++ orig_w / 4, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, 7, 1); ++ i965_pp_set_surface_state(ctx, pp_context, obj_surface->bo, w * h, ++ orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, 8, 1); + +- /* destination (Previous frame) UV surface index 8 */ +- i965_pp_set_surface_state(ctx, pp_context, +- previous_out_obj_surface->bo, w * h, +- orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, +- 8, 1); ++ /* Current output surfaces (index = { 10, 11 }) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_OUT_CURRENT].obj_surface; ++ w = obj_surface->width; ++ h = obj_surface->height; ++ orig_w = obj_surface->orig_width; ++ orig_h = obj_surface->orig_height; + +- /* destination(Current frame) */ +- orig_w = current_out_obj_surface->orig_width; +- orig_h = current_out_obj_surface->orig_height; +- w = current_out_obj_surface->width; +- h = current_out_obj_surface->height; ++ i965_pp_set_surface_state(ctx, pp_context, obj_surface->bo, 0, ++ orig_w / 4, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, 10, 1); ++ i965_pp_set_surface_state(ctx, pp_context, obj_surface->bo, w * h, ++ orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, 11, 1); + +- /* destination (Current frame) Y surface index xxx */ +- i965_pp_set_surface_state(ctx, pp_context, +- current_out_obj_surface->bo, 0, +- orig_w / 4, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, +- 10, 1); ++ /* STMM output surface (index = 20) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_OUT_STMM].obj_surface; ++ i965_pp_set_surface_state(ctx, pp_context, obj_surface->bo, 0, ++ obj_surface->orig_width, obj_surface->orig_height, obj_surface->width, ++ I965_SURFACEFORMAT_R8_UNORM, 20, 1); + +- /* destination (Current frame) UV surface index xxx */ +- i965_pp_set_surface_state(ctx, pp_context, +- current_out_obj_surface->bo, w * h, +- orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, +- 11, 1); +- +- /* STMM output surface, index 20 */ +- i965_pp_set_surface_state(ctx, pp_context, +- pp_dndi_context->stmm_bo, 0, +- orig_w, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, +- 20, 1); ++ /* If we are in "First Frame" mode, i.e. past frames are not ++ available for motion measure, then don't use the TFF flag */ ++ dndi_top_first = !(deint_params->flags & (dndi_ctx->is_first_frame ? ++ VA_DEINTERLACING_BOTTOM_FIELD : ++ VA_DEINTERLACING_BOTTOM_FIELD_FIRST)); + + /* sampler dndi */ + dri_bo_map(pp_context->sampler_state_table.bo, True); +@@ -3290,7 +3469,7 @@ pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_contex + sampler_dndi[index].dw6.di_partial = 0; + sampler_dndi[index].dw6.dndi_top_first = dndi_top_first; + sampler_dndi[index].dw6.dndi_stream_id = 0; +- sampler_dndi[index].dw6.dndi_first_frame = is_first_frame; ++ sampler_dndi[index].dw6.dndi_first_frame = dndi_ctx->is_first_frame; + sampler_dndi[index].dw6.progressive_dn = 0; + sampler_dndi[index].dw6.fmd_tear_threshold = 2; + sampler_dndi[index].dw6.fmd2_vertical_difference_threshold = 100; +@@ -3306,7 +3485,7 @@ pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_contex + /* private function & data */ + pp_context->pp_x_steps = pp_dndi_x_steps; + pp_context->pp_y_steps = pp_dndi_y_steps; +- pp_context->private_context = &pp_context->pp_dndi_context; ++ pp_context->private_context = dndi_ctx; + pp_context->pp_set_block_parameter = pp_dndi_set_block_parameter; + + pp_static_parameter->grf1.statistics_surface_picth = w / 2; +@@ -3319,13 +3498,10 @@ pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_contex + pp_inline_parameter->grf5.block_vertical_mask = 0xff; + pp_inline_parameter->grf5.block_horizontal_mask = 0xffff; + +- pp_dndi_context->dest_w = w; +- pp_dndi_context->dest_h = h; ++ dndi_ctx->dest_w = w; ++ dndi_ctx->dest_h = h; + + dst_surface->flags = I965_SURFACE_FLAG_FRAME; +- +- pp_dndi_context->frame_order = (pp_dndi_context->frame_order + 1) % 2; +- + return VA_STATUS_SUCCESS; + } + +@@ -3571,176 +3747,90 @@ gen7_pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_c + const VARectangle *dst_rect, + void *filter_param) + { +- struct i965_driver_data *i965 = i965_driver_data(ctx); +- struct pp_dndi_context *pp_dndi_context = (struct pp_dndi_context *)&pp_context->pp_dndi_context; ++ struct pp_dndi_context * const dndi_ctx = &pp_context->pp_dndi_context; + struct gen7_pp_static_parameter *pp_static_parameter = pp_context->pp_static_parameter; +- struct object_surface *previous_in_obj_surface, *current_in_obj_surface, *previous_out_obj_surface, *current_out_obj_surface; ++ const VAProcPipelineParameterBuffer * const pipe_params = ++ pp_context->pipeline_param; ++ const VAProcFilterParameterBufferDeinterlacing * const deint_params = ++ filter_param; ++ struct object_surface * const src_obj_surface = (struct object_surface *) ++ src_surface->base; ++ struct object_surface * const dst_obj_surface = (struct object_surface *) ++ dst_surface->base; ++ struct object_surface *obj_surface; + struct gen7_sampler_dndi *sampler_dndi; +- int index; +- int w, h; +- int orig_w, orig_h; +- int dndi_top_first = 1; +- VAProcFilterParameterBufferDeinterlacing *di_filter_param = (VAProcFilterParameterBufferDeinterlacing *)filter_param; +- int is_first_frame = (pp_dndi_context->frame_order == -1); +- +- if (di_filter_param->flags & VA_DEINTERLACING_BOTTOM_FIELD) +- dndi_top_first = 0; +- else +- dndi_top_first = 1; +- +- /* surface */ +- current_in_obj_surface = (struct object_surface *)src_surface->base; +- +- if (di_filter_param->algorithm == VAProcDeinterlacingBob) { +- previous_in_obj_surface = current_in_obj_surface; +- is_first_frame = 1; +- } else if (di_filter_param->algorithm == VAProcDeinterlacingMotionAdaptive) { +- if (pp_dndi_context->frame_order == 0) { +- VAProcPipelineParameterBuffer *pipeline_param = pp_context->pipeline_param; +- if (!pipeline_param || +- !pipeline_param->num_forward_references || +- pipeline_param->forward_references[0] == VA_INVALID_ID) { +- WARN_ONCE("A forward temporal reference is needed for Motion adaptive deinterlacing !!!\n"); +- +- return VA_STATUS_ERROR_INVALID_PARAMETER; +- } else { +- previous_in_obj_surface = SURFACE(pipeline_param->forward_references[0]); +- assert(previous_in_obj_surface && previous_in_obj_surface->bo); +- +- is_first_frame = 0; +- } +- } else if (pp_dndi_context->frame_order == 1) { +- vpp_surface_convert(ctx, +- pp_dndi_context->current_out_obj_surface, +- (struct object_surface *)dst_surface->base); +- pp_dndi_context->frame_order = (pp_dndi_context->frame_order + 1) % 2; +- is_first_frame = 0; +- +- return VA_STATUS_SUCCESS_1; +- } else { +- previous_in_obj_surface = current_in_obj_surface; +- is_first_frame = 1; +- } +- } else { +- return VA_STATUS_ERROR_UNIMPLEMENTED; +- } +- +- /* source (temporal reference) YUV surface index 4 */ +- orig_w = previous_in_obj_surface->orig_width; +- orig_h = previous_in_obj_surface->orig_height; +- w = previous_in_obj_surface->width; +- h = previous_in_obj_surface->height; +- gen7_pp_set_surface2_state(ctx, pp_context, +- previous_in_obj_surface->bo, 0, +- orig_w, orig_h, w, +- 0, h, +- SURFACE_FORMAT_PLANAR_420_8, 1, +- 4); +- +- /* source surface */ +- orig_w = current_in_obj_surface->orig_width; +- orig_h = current_in_obj_surface->orig_height; +- w = current_in_obj_surface->width; +- h = current_in_obj_surface->height; +- +- /* source UV surface index 1 */ +- gen7_pp_set_surface_state(ctx, pp_context, +- current_in_obj_surface->bo, w * h, +- orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, +- 1, 0); +- +- /* source YUV surface index 3 */ +- gen7_pp_set_surface2_state(ctx, pp_context, +- current_in_obj_surface->bo, 0, +- orig_w, orig_h, w, +- 0, h, +- SURFACE_FORMAT_PLANAR_420_8, 1, +- 3); +- +- /* STMM / History Statistics input surface, index 5 */ +- if (pp_dndi_context->stmm_bo == NULL) { +- pp_dndi_context->stmm_bo = dri_bo_alloc(i965->intel.bufmgr, +- "STMM surface", +- w * h, +- 4096); +- assert(pp_dndi_context->stmm_bo); +- } +- +- gen7_pp_set_surface_state(ctx, pp_context, +- pp_dndi_context->stmm_bo, 0, +- orig_w, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, +- 5, 1); +- +- /* destination surface */ +- previous_out_obj_surface = (struct object_surface *)dst_surface->base; +- orig_w = previous_out_obj_surface->orig_width; +- orig_h = previous_out_obj_surface->orig_height; +- w = previous_out_obj_surface->width; +- h = previous_out_obj_surface->height; +- +- if (is_first_frame) { +- current_out_obj_surface = previous_out_obj_surface; +- } else { +- VAStatus va_status; +- +- if (pp_dndi_context->current_out_surface == VA_INVALID_SURFACE) { +- unsigned int tiling = 0, swizzle = 0; +- dri_bo_get_tiling(previous_out_obj_surface->bo, &tiling, &swizzle); +- +- va_status = i965_CreateSurfaces(ctx, +- orig_w, +- orig_h, +- VA_RT_FORMAT_YUV420, +- 1, +- &pp_dndi_context->current_out_surface); +- assert(va_status == VA_STATUS_SUCCESS); +- pp_dndi_context->current_out_obj_surface = SURFACE(pp_dndi_context->current_out_surface); +- assert(pp_dndi_context->current_out_obj_surface); +- i965_check_alloc_surface_bo(ctx, +- pp_dndi_context->current_out_obj_surface, +- tiling != I915_TILING_NONE, +- VA_FOURCC_NV12, +- SUBSAMPLE_YUV420); +- } +- +- current_out_obj_surface = pp_dndi_context->current_out_obj_surface; +- } +- +- /* destination(Previous frame) Y surface index 27 */ +- gen7_pp_set_surface_state(ctx, pp_context, +- previous_out_obj_surface->bo, 0, +- orig_w / 4, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, +- 27, 1); ++ int index, dndi_top_first; ++ int w, h, orig_w, orig_h; ++ VAStatus status; + +- /* destination(Previous frame) UV surface index 28 */ +- gen7_pp_set_surface_state(ctx, pp_context, +- previous_out_obj_surface->bo, w * h, +- orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, +- 28, 1); ++ status = pp_dndi_context_init_surface_params(dndi_ctx, src_obj_surface, ++ pipe_params, deint_params); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ ++ status = pp_dndi_context_ensure_surfaces(ctx, pp_context, ++ src_obj_surface, dst_obj_surface); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ ++ status = pp_dndi_context_ensure_surfaces_storage(ctx, pp_context, ++ src_obj_surface, dst_obj_surface); ++ if (status != VA_STATUS_SUCCESS) ++ return status; ++ ++ /* Current input surface (index = 3) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_IN_CURRENT].obj_surface; ++ gen7_pp_set_surface2_state(ctx, pp_context, obj_surface->bo, 0, ++ obj_surface->orig_width, obj_surface->orig_height, obj_surface->width, ++ 0, obj_surface->y_cb_offset, SURFACE_FORMAT_PLANAR_420_8, 1, 3); ++ ++ /* Previous input surface (index = 4) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_IN_PREVIOUS].obj_surface; ++ gen7_pp_set_surface2_state(ctx, pp_context, obj_surface->bo, 0, ++ obj_surface->orig_width, obj_surface->orig_height, obj_surface->width, ++ 0, obj_surface->y_cb_offset, SURFACE_FORMAT_PLANAR_420_8, 1, 4); ++ ++ /* STMM input surface (index = 5) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_IN_STMM].obj_surface; ++ gen7_pp_set_surface_state(ctx, pp_context, obj_surface->bo, 0, ++ obj_surface->orig_width, obj_surface->orig_height, obj_surface->width, ++ I965_SURFACEFORMAT_R8_UNORM, 5, 1); ++ ++ /* Previous output surfaces (index = { 27, 28 }) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_OUT_PREVIOUS].obj_surface; ++ w = obj_surface->width; ++ h = obj_surface->height; ++ orig_w = obj_surface->orig_width; ++ orig_h = obj_surface->orig_height; + +- /* destination(Current frame) Y surface index 30 */ +- gen7_pp_set_surface_state(ctx, pp_context, +- current_out_obj_surface->bo, 0, +- orig_w / 4, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, +- 30, 1); ++ gen7_pp_set_surface_state(ctx, pp_context, obj_surface->bo, 0, ++ orig_w / 4, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, 27, 1); ++ gen7_pp_set_surface_state(ctx, pp_context, obj_surface->bo, w * h, ++ orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, 28, 1); + +- /* destination(Current frame) UV surface index 31 */ +- orig_w = current_out_obj_surface->orig_width; +- orig_h = current_out_obj_surface->orig_height; +- w = current_out_obj_surface->width; +- h = current_out_obj_surface->height; ++ /* Current output surfaces (index = { 30, 31 }) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_OUT_CURRENT].obj_surface; ++ w = obj_surface->width; ++ h = obj_surface->height; ++ orig_w = obj_surface->orig_width; ++ orig_h = obj_surface->orig_height; + +- gen7_pp_set_surface_state(ctx, pp_context, +- current_out_obj_surface->bo, w * h, +- orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, +- 31, 1); ++ gen7_pp_set_surface_state(ctx, pp_context, obj_surface->bo, 0, ++ orig_w / 4, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, 30, 1); ++ gen7_pp_set_surface_state(ctx, pp_context, obj_surface->bo, w * h, ++ orig_w / 4, orig_h / 2, w, I965_SURFACEFORMAT_R8G8_UNORM, 31, 1); + +- /* STMM output surface, index 33 */ +- gen7_pp_set_surface_state(ctx, pp_context, +- pp_dndi_context->stmm_bo, 0, +- orig_w, orig_h, w, I965_SURFACEFORMAT_R8_UNORM, +- 33, 1); ++ /* STMM output surface (index = 33) */ ++ obj_surface = dndi_ctx->frame_store[DNDI_FRAME_OUT_STMM].obj_surface; ++ gen7_pp_set_surface_state(ctx, pp_context, obj_surface->bo, 0, ++ obj_surface->orig_width, obj_surface->orig_height, obj_surface->width, ++ I965_SURFACEFORMAT_R8_UNORM, 33, 1); + ++ /* If we are in "First Frame" mode, i.e. past frames are not ++ available for motion measure, then don't use the TFF flag */ ++ dndi_top_first = !(deint_params->flags & (dndi_ctx->is_first_frame ? ++ VA_DEINTERLACING_BOTTOM_FIELD : ++ VA_DEINTERLACING_BOTTOM_FIELD_FIRST)); + + /* sampler dndi */ + dri_bo_map(pp_context->sampler_state_table.bo, True); +@@ -3792,7 +3882,7 @@ gen7_pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_c + sampler_dndi[index].dw6.di_partial = 0; + sampler_dndi[index].dw6.dndi_top_first = dndi_top_first; + sampler_dndi[index].dw6.dndi_stream_id = 1; +- sampler_dndi[index].dw6.dndi_first_frame = is_first_frame; ++ sampler_dndi[index].dw6.dndi_first_frame = dndi_ctx->is_first_frame; + sampler_dndi[index].dw6.progressive_dn = 0; + sampler_dndi[index].dw6.mcdi_enable = 0; + sampler_dndi[index].dw6.fmd_tear_threshold = 2; +@@ -3814,7 +3904,7 @@ gen7_pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_c + /* private function & data */ + pp_context->pp_x_steps = gen7_pp_dndi_x_steps; + pp_context->pp_y_steps = gen7_pp_dndi_y_steps; +- pp_context->private_context = &pp_context->pp_dndi_context; ++ pp_context->private_context = dndi_ctx; + pp_context->pp_set_block_parameter = gen7_pp_dndi_set_block_parameter; + + pp_static_parameter->grf1.di_statistics_surface_pitch_div2 = w / 2; +@@ -3829,13 +3919,10 @@ gen7_pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_c + pp_static_parameter->grf4.di_hoffset_svf_from_dvf = 0; + pp_static_parameter->grf4.di_voffset_svf_from_dvf = 0; + +- pp_dndi_context->dest_w = w; +- pp_dndi_context->dest_h = h; ++ dndi_ctx->dest_w = w; ++ dndi_ctx->dest_h = h; + + dst_surface->flags = I965_SURFACE_FLAG_FRAME; +- +- pp_dndi_context->frame_order = (pp_dndi_context->frame_order + 1) % 2; +- + return VA_STATUS_SUCCESS; + } + +@@ -5299,15 +5386,9 @@ i965_post_processing_context_finalize(VADriverContextP ctx, + dri_bo_unreference(pp_context->vfe_state.bo); + pp_context->vfe_state.bo = NULL; + +- dri_bo_unreference(pp_context->pp_dndi_context.stmm_bo); +- pp_context->pp_dndi_context.stmm_bo = NULL; +- +- if (pp_context->pp_dndi_context.current_out_surface != VA_INVALID_ID) { +- i965_DestroySurfaces(ctx, +- &pp_context->pp_dndi_context.current_out_surface, 1); +- pp_context->pp_dndi_context.current_out_surface = VA_INVALID_ID; +- pp_context->pp_dndi_context.current_out_obj_surface = NULL; +- } ++ for (i = 0; i < ARRAY_ELEMS(pp_context->pp_dndi_context.frame_store); i++) ++ pp_dndi_frame_store_clear(&pp_context->pp_dndi_context.frame_store[i], ++ ctx); + + dri_bo_unreference(pp_context->pp_dn_context.stmm_bo); + pp_context->pp_dn_context.stmm_bo = NULL; +@@ -5412,10 +5493,8 @@ i965_post_processing_context_init(VADriverContextP ctx, + pp_context->pp_inline_parameter = calloc(sizeof(struct pp_inline_parameter), 1); + } + +- pp_context->pp_dndi_context.current_out_surface = VA_INVALID_SURFACE; +- pp_context->pp_dndi_context.current_out_obj_surface = NULL; +- pp_context->pp_dndi_context.frame_order = -1; + pp_context->batch = batch; ++ pp_dndi_context_init(&pp_context->pp_dndi_context); + + avs_config = IS_IRONLAKE(i965->intel.device_info) ? &gen5_avs_config : + &gen6_avs_config; +diff --git a/src/i965_post_processing.h b/src/i965_post_processing.h +index e6940c0..477f0ca 100755 +--- a/src/i965_post_processing.h ++++ b/src/i965_post_processing.h +@@ -88,14 +88,33 @@ struct pp_avs_context + float horiz_range; + }; + ++enum { ++ DNDI_FRAME_IN_CURRENT = 0, ++ DNDI_FRAME_IN_PREVIOUS, ++ DNDI_FRAME_IN_STMM, ++ DNDI_FRAME_OUT_STMM, ++ DNDI_FRAME_OUT_CURRENT, ++ DNDI_FRAME_OUT_PREVIOUS, ++ DNDI_FRAME_STORE_COUNT ++}; ++ ++typedef struct dndi_frame_store { ++ struct object_surface *obj_surface; ++ VASurfaceID surface_id; /* always relative to the input surface */ ++ unsigned int is_scratch_surface : 1; ++} DNDIFrameStore; ++ + struct pp_dndi_context + { + int dest_w; + int dest_h; +- dri_bo *stmm_bo; +- int frame_order; /* -1 for the first frame */ +- VASurfaceID current_out_surface; +- struct object_surface *current_out_obj_surface; ++ DNDIFrameStore frame_store[DNDI_FRAME_STORE_COUNT]; ++ ++ /* Temporary flags live until the current picture is processed */ ++ unsigned int is_di_enabled : 1; ++ unsigned int is_di_adv_enabled : 1; ++ unsigned int is_first_frame : 1; ++ unsigned int is_second_field : 1; + }; + + struct pp_dn_context +-- +1.9.1 + + +From e1b05745e622baf67f688bcd560dc7ad63264a3f Mon Sep 17 00:00:00 2001 +From: Gwenole Beauchesne +Date: Tue, 21 Oct 2014 17:13:07 +0200 +Subject: [PATCH 3/4] vpp: add support for Motion-Compensated deinterlacing on + Ivybridge. + +Signed-off-by: Gwenole Beauchesne +--- + src/i965_device_info.c | 1 + + src/i965_post_processing.c | 4 +++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/i965_device_info.c b/src/i965_device_info.c +index 50bb78d..1f4025d 100644 +--- a/src/i965_device_info.c ++++ b/src/i965_device_info.c +@@ -162,6 +162,7 @@ static struct hw_codec_info ivb_hw_codec_info = { + .has_accelerated_putimage = 1, + .has_tiled_surface = 1, + .has_di_motion_adptive = 1, ++ .has_di_motion_compensated = 1, + + .num_filters = 2, + .filters = { +diff --git a/src/i965_post_processing.c b/src/i965_post_processing.c +index 588b065..2c01e43 100755 +--- a/src/i965_post_processing.c ++++ b/src/i965_post_processing.c +@@ -1210,6 +1210,7 @@ pp_dndi_context_init_surface_params(struct pp_dndi_context *dndi_ctx, + dndi_ctx->is_first_frame = 1; + break; + case VAProcDeinterlacingMotionAdaptive: ++ case VAProcDeinterlacingMotionCompensated: + fs = &dndi_ctx->frame_store[DNDI_FRAME_IN_CURRENT]; + if (fs->surface_id == VA_INVALID_ID) + dndi_ctx->is_first_frame = 1; +@@ -3884,7 +3885,8 @@ gen7_pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_c + sampler_dndi[index].dw6.dndi_stream_id = 1; + sampler_dndi[index].dw6.dndi_first_frame = dndi_ctx->is_first_frame; + sampler_dndi[index].dw6.progressive_dn = 0; +- sampler_dndi[index].dw6.mcdi_enable = 0; ++ sampler_dndi[index].dw6.mcdi_enable = ++ (deint_params->algorithm == VAProcDeinterlacingMotionCompensated); + sampler_dndi[index].dw6.fmd_tear_threshold = 2; + sampler_dndi[index].dw6.cat_th1 = 0; + sampler_dndi[index].dw6.fmd2_vertical_difference_threshold = 100; +-- +1.9.1 + + +From 18e0a507fb9ba89f277c0032cebdd97fdd4b4a75 Mon Sep 17 00:00:00 2001 +From: "Xiang, Haihao" +Date: Thu, 19 Mar 2015 18:54:16 +0100 +Subject: [PATCH 4/4] Signed-off-by: Xiang, Haihao + +--- + src/i965_post_processing.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/i965_post_processing.c b/src/i965_post_processing.c +index 2c01e43..72f298f 100755 +--- a/src/i965_post_processing.c ++++ b/src/i965_post_processing.c +@@ -3457,7 +3457,7 @@ pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_contex + sampler_dndi[index].dw4.sdi_threshold = 100; + sampler_dndi[index].dw4.stmm_output_shift = 5; // stmm_max - stmm_min = 2 ^ stmm_output_shift + sampler_dndi[index].dw4.stmm_shift_up = 1; +- sampler_dndi[index].dw4.stmm_shift_down = 0; ++ sampler_dndi[index].dw4.stmm_shift_down = 3; + sampler_dndi[index].dw4.minimum_stmm = 118; + + sampler_dndi[index].dw5.fmd_temporal_difference_threshold = 175; +@@ -3871,7 +3871,7 @@ gen7_pp_nv12_dndi_initialize(VADriverContextP ctx, struct i965_post_processing_c + sampler_dndi[index].dw4.sdi_threshold = 100; + sampler_dndi[index].dw4.stmm_output_shift = 5; // stmm_max - stmm_min = 2 ^ stmm_output_shift + sampler_dndi[index].dw4.stmm_shift_up = 1; +- sampler_dndi[index].dw4.stmm_shift_down = 0; ++ sampler_dndi[index].dw4.stmm_shift_down = 3; + sampler_dndi[index].dw4.minimum_stmm = 118; + + sampler_dndi[index].dw5.fmd_temporal_difference_threshold = 175; +-- +1.9.1 +