X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fgen7_mfd.c;h=6805bd876fab48d37389a67df01abc84f510865e;hb=368a87fc3ca77ead34919ab35b7b57ffa8787d70;hp=80be4f615c12bd381248654ab88a4137ac02eff9;hpb=b708e8f58583fc1aa04694bcd7b61e7969107720;p=android-x86%2Fhardware-intel-common-vaapi.git diff --git a/src/gen7_mfd.c b/src/gen7_mfd.c index 80be4f6..6805bd8 100644 --- a/src/gen7_mfd.c +++ b/src/gen7_mfd.c @@ -1205,11 +1205,15 @@ static const int va_to_gen7_vc1_condover[3] = { 3 }; -static const int va_to_gen7_vc1_profile[4] = { - GEN7_VC1_SIMPLE_PROFILE, - GEN7_VC1_MAIN_PROFILE, - GEN7_VC1_RESERVED_PROFILE, - GEN7_VC1_ADVANCED_PROFILE +static const int fptype_to_picture_type[8][2] = { + {GEN7_VC1_I_PICTURE, GEN7_VC1_I_PICTURE}, + {GEN7_VC1_I_PICTURE, GEN7_VC1_P_PICTURE}, + {GEN7_VC1_P_PICTURE, GEN7_VC1_I_PICTURE}, + {GEN7_VC1_P_PICTURE, GEN7_VC1_P_PICTURE}, + {GEN7_VC1_B_PICTURE, GEN7_VC1_B_PICTURE}, + {GEN7_VC1_B_PICTURE, GEN7_VC1_BI_PICTURE}, + {GEN7_VC1_BI_PICTURE, GEN7_VC1_B_PICTURE}, + {GEN7_VC1_BI_PICTURE, GEN7_VC1_BI_PICTURE} }; static void @@ -1220,7 +1224,8 @@ gen7_mfd_free_vc1_surface(void **data) if (!gen7_vc1_surface) return; - dri_bo_unreference(gen7_vc1_surface->dmv); + dri_bo_unreference(gen7_vc1_surface->dmv_top); + dri_bo_unreference(gen7_vc1_surface->dmv_bottom); free(gen7_vc1_surface); *data = NULL; } @@ -1232,7 +1237,17 @@ gen7_mfd_init_vc1_surface(VADriverContextP ctx, { struct i965_driver_data *i965 = i965_driver_data(ctx); struct gen7_vc1_surface *gen7_vc1_surface = obj_surface->private_data; - int height_in_mbs = ALIGN(pic_param->coded_height, 16) / 16; + int height_in_mbs; + int picture_type; + int is_first_field = 1; + + if (!pic_param->sequence_fields.bits.interlace || + (pic_param->picture_fields.bits.frame_coding_mode < 2)) { /* Progressive or Frame-Interlace */ + picture_type = pic_param->picture_fields.bits.picture_type; + } else {/* Field-Interlace */ + is_first_field = pic_param->picture_fields.bits.is_first_field; + picture_type = fptype_to_picture_type[pic_param->picture_fields.bits.picture_type][!is_first_field]; + } obj_surface->free_private_data = gen7_mfd_free_vc1_surface; @@ -1243,13 +1258,50 @@ gen7_mfd_init_vc1_surface(VADriverContextP ctx, obj_surface->private_data = gen7_vc1_surface; } - gen7_vc1_surface->picture_type = pic_param->picture_fields.bits.picture_type; - gen7_vc1_surface->intensity_compensation = 0; - gen7_vc1_surface->luma_scale = 0; - gen7_vc1_surface->luma_shift = 0; + if (!pic_param->sequence_fields.bits.interlace || + pic_param->picture_fields.bits.frame_coding_mode < 2 || /* Progressive or Frame-Interlace */ + is_first_field) { + gen7_vc1_surface->picture_type_top = 0; + gen7_vc1_surface->picture_type_bottom = 0; + gen7_vc1_surface->intensity_compensation_top = 0; + gen7_vc1_surface->intensity_compensation_bottom = 0; + gen7_vc1_surface->luma_scale_top[0] = 0; + gen7_vc1_surface->luma_scale_top[1] = 0; + gen7_vc1_surface->luma_scale_bottom[0] = 0; + gen7_vc1_surface->luma_scale_bottom[1] = 0; + gen7_vc1_surface->luma_shift_top[0] = 0; + gen7_vc1_surface->luma_shift_top[1] = 0; + gen7_vc1_surface->luma_shift_bottom[0] = 0; + gen7_vc1_surface->luma_shift_bottom[1] = 0; + } + + if (!pic_param->sequence_fields.bits.interlace || + pic_param->picture_fields.bits.frame_coding_mode < 2) { /* Progressive or Frame-Interlace */ + gen7_vc1_surface->picture_type_top = picture_type; + gen7_vc1_surface->picture_type_bottom = picture_type; + } else if (pic_param->picture_fields.bits.top_field_first ^ is_first_field) + gen7_vc1_surface->picture_type_bottom = picture_type; + else + gen7_vc1_surface->picture_type_top = picture_type; + + /* + * The Direct MV buffer is scalable with frame height, but + * does not scale with frame width as the hardware assumes + * that frame width is fixed at 128 MBs. + */ + + if (gen7_vc1_surface->dmv_top == NULL) { + height_in_mbs = ALIGN(obj_surface->orig_height, 16) / 16; + gen7_vc1_surface->dmv_top = dri_bo_alloc(i965->intel.bufmgr, + "direct mv w/r buffer", + 128 * height_in_mbs * 64, + 0x1000); + } - if (gen7_vc1_surface->dmv == NULL) { - gen7_vc1_surface->dmv = dri_bo_alloc(i965->intel.bufmgr, + if (pic_param->sequence_fields.bits.interlace && + gen7_vc1_surface->dmv_bottom == NULL) { + height_in_mbs = ALIGN(obj_surface->orig_height, 32) / 32; + gen7_vc1_surface->dmv_bottom = dri_bo_alloc(i965->intel.bufmgr, "direct mv w/r buffer", 128 * height_in_mbs * 64, 0x1000); @@ -1264,34 +1316,24 @@ gen7_mfd_vc1_decode_init(VADriverContextP ctx, VAPictureParameterBufferVC1 *pic_param; struct i965_driver_data *i965 = i965_driver_data(ctx); struct object_surface *obj_surface; + struct gen7_vc1_surface *gen7_vc1_current_surface; + struct gen7_vc1_surface *gen7_vc1_forward_surface; dri_bo *bo; int width_in_mbs; int picture_type; - int intensity_compensation; + int is_first_field = 1; + int i; assert(decode_state->pic_param && decode_state->pic_param->buffer); pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer; width_in_mbs = ALIGN(pic_param->coded_width, 16) / 16; - picture_type = pic_param->picture_fields.bits.picture_type; - intensity_compensation = (pic_param->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation); - - intel_update_vc1_frame_store_index(ctx, - decode_state, - pic_param, - gen7_mfd_context->reference_surface); - /* Forward reference picture */ - obj_surface = decode_state->reference_objects[0]; - if (pic_param->forward_reference_picture != VA_INVALID_ID && - obj_surface && - obj_surface->private_data) { - if (picture_type == 1 && intensity_compensation) { /* P picture */ - struct gen7_vc1_surface *gen7_vc1_surface = obj_surface->private_data; - - gen7_vc1_surface->intensity_compensation = intensity_compensation; - gen7_vc1_surface->luma_scale = pic_param->luma_scale; - gen7_vc1_surface->luma_shift = pic_param->luma_shift; - } + if (!pic_param->sequence_fields.bits.interlace || + (pic_param->picture_fields.bits.frame_coding_mode < 2)) { /* Progressive or Frame-Interlace */ + picture_type = pic_param->picture_fields.bits.picture_type; + } else {/* Field-Interlace */ + is_first_field = pic_param->picture_fields.bits.is_first_field; + picture_type = fptype_to_picture_type[pic_param->picture_fields.bits.picture_type][!is_first_field]; } /* Current decoded picture */ @@ -1302,12 +1344,148 @@ gen7_mfd_vc1_decode_init(VADriverContextP ctx, dri_bo_unreference(gen7_mfd_context->post_deblocking_output.bo); gen7_mfd_context->post_deblocking_output.bo = obj_surface->bo; dri_bo_reference(gen7_mfd_context->post_deblocking_output.bo); - gen7_mfd_context->post_deblocking_output.valid = pic_param->entrypoint_fields.bits.loopfilter; dri_bo_unreference(gen7_mfd_context->pre_deblocking_output.bo); gen7_mfd_context->pre_deblocking_output.bo = obj_surface->bo; dri_bo_reference(gen7_mfd_context->pre_deblocking_output.bo); - gen7_mfd_context->pre_deblocking_output.valid = !pic_param->entrypoint_fields.bits.loopfilter; + + if (picture_type == GEN7_VC1_SKIPPED_PICTURE) { + gen7_mfd_context->post_deblocking_output.valid = 0; + gen7_mfd_context->pre_deblocking_output.valid = 1; + } else { + gen7_mfd_context->post_deblocking_output.valid = pic_param->entrypoint_fields.bits.loopfilter; + gen7_mfd_context->pre_deblocking_output.valid = !pic_param->entrypoint_fields.bits.loopfilter; + } + + intel_update_vc1_frame_store_index(ctx, + decode_state, + pic_param, + gen7_mfd_context->reference_surface); + + if (picture_type == GEN7_VC1_P_PICTURE) { + obj_surface = decode_state->reference_objects[0]; + gen7_vc1_current_surface = (struct gen7_vc1_surface *)(decode_state->render_object->private_data); + if (pic_param->forward_reference_picture != VA_INVALID_ID && + obj_surface) + gen7_vc1_forward_surface = (struct gen7_vc1_surface *)(obj_surface->private_data); + else + gen7_vc1_forward_surface = NULL; + + if (!pic_param->sequence_fields.bits.interlace || + pic_param->picture_fields.bits.frame_coding_mode == 0) { /* Progressive */ + if (pic_param->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation) { + if (gen7_vc1_forward_surface) { + gen7_vc1_forward_surface->intensity_compensation_top = 1; + gen7_vc1_forward_surface->intensity_compensation_bottom = 1; + gen7_vc1_forward_surface->luma_scale_top[0] = pic_param->luma_scale; + gen7_vc1_forward_surface->luma_scale_bottom[0] = pic_param->luma_scale; + gen7_vc1_forward_surface->luma_shift_top[0] = pic_param->luma_shift; + gen7_vc1_forward_surface->luma_shift_bottom[0] = pic_param->luma_shift; + } + } + } else if (pic_param->sequence_fields.bits.interlace && + pic_param->picture_fields.bits.frame_coding_mode == 1) { /* Frame-Interlace */ + if (pic_param->picture_fields.bits.intensity_compensation) { + if (gen7_vc1_forward_surface) { + gen7_vc1_forward_surface->intensity_compensation_top = 1; + gen7_vc1_forward_surface->intensity_compensation_bottom = 1; + gen7_vc1_forward_surface->luma_scale_top[0] = pic_param->luma_scale; + gen7_vc1_forward_surface->luma_scale_bottom[0] = pic_param->luma_scale; + gen7_vc1_forward_surface->luma_shift_top[0] = pic_param->luma_shift; + gen7_vc1_forward_surface->luma_shift_bottom[0] = pic_param->luma_shift; + } + } + } else if (pic_param->sequence_fields.bits.interlace && + pic_param->picture_fields.bits.frame_coding_mode == 2) { /* Field-Interlace */ + if (pic_param->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation) { + if (pic_param->intensity_compensation_field == 1 || /* Top field */ + pic_param->intensity_compensation_field == 0) { /* Both fields */ + if (is_first_field) { + if ((!pic_param->reference_fields.bits.num_reference_pictures && + (pic_param->reference_fields.bits.reference_field_pic_indicator == + pic_param->picture_fields.bits.top_field_first)) || + pic_param->reference_fields.bits.num_reference_pictures) { + if (gen7_vc1_forward_surface) { + i = gen7_vc1_forward_surface->intensity_compensation_top++; + gen7_vc1_forward_surface->luma_scale_top[i] = pic_param->luma_scale; + gen7_vc1_forward_surface->luma_shift_top[i] = pic_param->luma_shift; + } + } + } else { /* Second field */ + if (pic_param->picture_fields.bits.top_field_first) { + if ((!pic_param->reference_fields.bits.num_reference_pictures && + !pic_param->reference_fields.bits.reference_field_pic_indicator) || + pic_param->reference_fields.bits.num_reference_pictures) { + i = gen7_vc1_current_surface->intensity_compensation_top++; + gen7_vc1_current_surface->luma_scale_top[i] = pic_param->luma_scale; + gen7_vc1_current_surface->luma_shift_top[i] = pic_param->luma_shift; + } + } else { + if ((!pic_param->reference_fields.bits.num_reference_pictures && + pic_param->reference_fields.bits.reference_field_pic_indicator) || + pic_param->reference_fields.bits.num_reference_pictures) { + if (gen7_vc1_forward_surface) { + i = gen7_vc1_forward_surface->intensity_compensation_top++; + gen7_vc1_forward_surface->luma_scale_top[i] = pic_param->luma_scale; + gen7_vc1_forward_surface->luma_shift_top[i] = pic_param->luma_shift; + } + } + } + } + } + if (pic_param->intensity_compensation_field == 2 || /* Bottom field */ + pic_param->intensity_compensation_field == 0) { /* Both fields */ + if (is_first_field) { + if ((!pic_param->reference_fields.bits.num_reference_pictures && + (pic_param->reference_fields.bits.reference_field_pic_indicator ^ + pic_param->picture_fields.bits.top_field_first)) || + pic_param->reference_fields.bits.num_reference_pictures) { + if (gen7_vc1_forward_surface) { + i = gen7_vc1_forward_surface->intensity_compensation_bottom++; + if (pic_param->intensity_compensation_field == 2) { /* Bottom field */ + gen7_vc1_forward_surface->luma_scale_bottom[i] = pic_param->luma_scale; + gen7_vc1_forward_surface->luma_shift_bottom[i] = pic_param->luma_shift; + } else { /* Both fields */ + gen7_vc1_forward_surface->luma_scale_bottom[i] = pic_param->luma_scale2; + gen7_vc1_forward_surface->luma_shift_bottom[i] = pic_param->luma_shift2; + } + } + } + } else { /* Second field */ + if (pic_param->picture_fields.bits.top_field_first) { + if ((!pic_param->reference_fields.bits.num_reference_pictures && + pic_param->reference_fields.bits.reference_field_pic_indicator) || + pic_param->reference_fields.bits.num_reference_pictures) { + if (gen7_vc1_forward_surface) { + i = gen7_vc1_forward_surface->intensity_compensation_bottom++; + if (pic_param->intensity_compensation_field == 2) { /* Bottom field */ + gen7_vc1_forward_surface->luma_scale_bottom[i] = pic_param->luma_scale; + gen7_vc1_forward_surface->luma_shift_bottom[i] = pic_param->luma_shift; + } else { /* Both fields */ + gen7_vc1_forward_surface->luma_scale_bottom[i] = pic_param->luma_scale2; + gen7_vc1_forward_surface->luma_shift_bottom[i] = pic_param->luma_shift2; + } + } + } + } else { + if ((!pic_param->reference_fields.bits.num_reference_pictures && + !pic_param->reference_fields.bits.reference_field_pic_indicator) || + pic_param->reference_fields.bits.num_reference_pictures) { + i = gen7_vc1_current_surface->intensity_compensation_bottom++; + if (pic_param->intensity_compensation_field == 2) { /* Bottom field */ + gen7_vc1_current_surface->luma_scale_bottom[i] = pic_param->luma_scale; + gen7_vc1_current_surface->luma_shift_bottom[i] = pic_param->luma_shift; + } else { /* Both fields */ + gen7_vc1_current_surface->luma_scale_bottom[i] = pic_param->luma_scale2; + gen7_vc1_current_surface->luma_shift_bottom[i] = pic_param->luma_shift2; + } + } + } + } + } + } + } + } dri_bo_unreference(gen7_mfd_context->intra_row_store_scratch_buffer.bo); bo = dri_bo_alloc(i965->intel.bufmgr, @@ -1346,11 +1524,17 @@ gen7_mfd_vc1_decode_init(VADriverContextP ctx, if (gen7_mfd_context->bitplane_read_buffer.valid) { int width_in_mbs = ALIGN(pic_param->coded_width, 16) / 16; - int height_in_mbs = ALIGN(pic_param->coded_height, 16) / 16; + int height_in_mbs; int bitplane_width = ALIGN(width_in_mbs, 2) / 2; int src_w, src_h; uint8_t *src = NULL, *dst = NULL; + if (!pic_param->sequence_fields.bits.interlace || + (pic_param->picture_fields.bits.frame_coding_mode < 2)) /* Progressive or Frame-Interlace */ + height_in_mbs = ALIGN(pic_param->coded_height, 16) / 16; + else /* Field-Interlace */ + height_in_mbs = ALIGN(pic_param->coded_height, 32) / 32; + bo = dri_bo_alloc(i965->intel.bufmgr, "VC-1 Bitplane", bitplane_width * height_in_mbs, @@ -1415,27 +1599,44 @@ gen7_mfd_vc1_pic_state(VADriverContextP ctx, struct intel_batchbuffer *batch = gen7_mfd_context->base.batch; VAPictureParameterBufferVC1 *pic_param; struct object_surface *obj_surface; + struct gen7_vc1_surface *gen7_vc1_current_surface; + struct gen7_vc1_surface *gen7_vc1_reference_surface; int alt_pquant_config = 0, alt_pquant_edge_mask = 0, alt_pq; int dquant, dquantfrm, dqprofile, dqdbedge, dqsbedge, dqbilevel; - int unified_mv_mode; + int unified_mv_mode = 0; int ref_field_pic_polarity = 0; int scale_factor = 0; int trans_ac_y = 0; int dmv_surface_valid = 0; + int frfd = 0; int brfd = 0; int fcm = 0; int picture_type; int ptype; - int profile; int overlap = 0; int interpolation_mode = 0; + int height_in_mbs; + int is_first_field = 1; + int loopfilter = 0; + int bitplane_present; + int range_reduction = 0; + int range_reduction_scale = 0; + int forward_mb = 0, mv_type_mb = 0, skip_mb = 0, direct_mb = 0; + int overflags = 0, ac_pred = 0, field_tx = 0; assert(decode_state->pic_param && decode_state->pic_param->buffer); pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer; - picture_type = pic_param->picture_fields.bits.picture_type; + if (!pic_param->sequence_fields.bits.interlace || + (pic_param->picture_fields.bits.frame_coding_mode < 2)) { /* Progressive or Frame-Interlace */ + picture_type = pic_param->picture_fields.bits.picture_type; + height_in_mbs = ALIGN(pic_param->coded_height, 16) / 16; + } else {/* Field-Interlace */ + is_first_field = pic_param->picture_fields.bits.is_first_field; + picture_type = fptype_to_picture_type[pic_param->picture_fields.bits.picture_type][!is_first_field]; + height_in_mbs = ALIGN(pic_param->coded_height, 32) / 32; + } - profile = va_to_gen7_vc1_profile[pic_param->sequence_fields.bits.profile]; dquant = pic_param->pic_quantizer_fields.bits.dquant; dquantfrm = pic_param->pic_quantizer_fields.bits.dq_frame; dqprofile = pic_param->pic_quantizer_fields.bits.dq_profile; @@ -1494,32 +1695,85 @@ gen7_mfd_vc1_pic_state(VADriverContextP ctx, } } - if (pic_param->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation) { - assert(pic_param->mv_fields.bits.mv_mode2 < 4); - unified_mv_mode = va_to_gen7_vc1_mv[pic_param->mv_fields.bits.mv_mode2]; - } else { - assert(pic_param->mv_fields.bits.mv_mode < 4); - unified_mv_mode = va_to_gen7_vc1_mv[pic_param->mv_fields.bits.mv_mode]; + if (pic_param->sequence_fields.bits.profile == 1 && /* Main Profile */ + pic_param->sequence_fields.bits.rangered) { + obj_surface = decode_state->reference_objects[0]; + + gen7_vc1_current_surface = (struct gen7_vc1_surface *)(decode_state->render_object->private_data); + + if (pic_param->forward_reference_picture != VA_INVALID_ID && + obj_surface) + gen7_vc1_reference_surface = (struct gen7_vc1_surface *)(obj_surface->private_data); + else + gen7_vc1_reference_surface = NULL; + + if (picture_type == GEN7_VC1_SKIPPED_PICTURE) + if (gen7_vc1_reference_surface) + gen7_vc1_current_surface->range_reduction_frame = gen7_vc1_reference_surface->range_reduction_frame; + else + gen7_vc1_current_surface->range_reduction_frame = 0; + else + gen7_vc1_current_surface->range_reduction_frame = pic_param->range_reduction_frame; + + if (gen7_vc1_reference_surface) { + if (gen7_vc1_current_surface->range_reduction_frame && + !gen7_vc1_reference_surface->range_reduction_frame) { + range_reduction = 1; + range_reduction_scale = 0; + } else if (!gen7_vc1_current_surface->range_reduction_frame && + gen7_vc1_reference_surface->range_reduction_frame) { + range_reduction = 1; + range_reduction_scale = 1; + } + } } - if (pic_param->sequence_fields.bits.interlace == 1 && - pic_param->picture_fields.bits.frame_coding_mode != 0) { /* frame-interlace or field-interlace */ - /* FIXME: calculate reference field picture polarity */ - assert(0); - ref_field_pic_polarity = 0; + if ((!pic_param->sequence_fields.bits.interlace || + pic_param->picture_fields.bits.frame_coding_mode != 1) && /* Progressive or Field-Interlace */ + (picture_type == GEN7_VC1_P_PICTURE || + picture_type == GEN7_VC1_B_PICTURE)) { + if (pic_param->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation) { + assert(pic_param->mv_fields.bits.mv_mode2 < 4); + unified_mv_mode = va_to_gen7_vc1_mv[pic_param->mv_fields.bits.mv_mode2]; + } else { + assert(pic_param->mv_fields.bits.mv_mode < 4); + unified_mv_mode = va_to_gen7_vc1_mv[pic_param->mv_fields.bits.mv_mode]; + } + } + + if (pic_param->sequence_fields.bits.interlace && + pic_param->picture_fields.bits.frame_coding_mode == 2 && /* Field-Interlace */ + picture_type == GEN7_VC1_P_PICTURE && + !pic_param->reference_fields.bits.num_reference_pictures) { + if (pic_param->reference_fields.bits.reference_field_pic_indicator == 0) { + ref_field_pic_polarity = is_first_field ? + pic_param->picture_fields.bits.top_field_first : + !pic_param->picture_fields.bits.top_field_first; + } else { + ref_field_pic_polarity = is_first_field ? + !pic_param->picture_fields.bits.top_field_first : + pic_param->picture_fields.bits.top_field_first; + } } if (pic_param->b_picture_fraction < 21) scale_factor = b_picture_scale_factor[pic_param->b_picture_fraction]; - if (picture_type == GEN7_VC1_SKIPPED_PICTURE) + if (picture_type == GEN7_VC1_SKIPPED_PICTURE) { ptype = GEN7_VC1_P_PICTURE; - else + bitplane_present = 1; + } else { ptype = pic_param->picture_fields.bits.picture_type; - - if (profile == GEN7_VC1_ADVANCED_PROFILE && - picture_type == GEN7_VC1_I_PICTURE) - picture_type = GEN7_VC1_BI_PICTURE; + bitplane_present = !!(pic_param->bitplane_present.value & 0x7f); + forward_mb = pic_param->raw_coding.flags.forward_mb; + mv_type_mb = pic_param->raw_coding.flags.mv_type_mb; + skip_mb = pic_param->raw_coding.flags.skip_mb; + direct_mb = pic_param->raw_coding.flags.direct_mb; + overflags = pic_param->raw_coding.flags.overflags; + ac_pred = pic_param->raw_coding.flags.ac_pred; + field_tx = pic_param->raw_coding.flags.field_tx; + loopfilter = pic_param->entrypoint_fields.bits.loopfilter; + } if (picture_type == GEN7_VC1_I_PICTURE || picture_type == GEN7_VC1_BI_PICTURE) /* I picture */ trans_ac_y = pic_param->transform_fields.bits.transform_ac_codingset_idx2; @@ -1537,45 +1791,68 @@ gen7_mfd_vc1_pic_state(VADriverContextP ctx, } } - if (picture_type == GEN7_VC1_B_PICTURE) { - struct gen7_vc1_surface *gen7_vc1_surface = NULL; - obj_surface = decode_state->reference_objects[1]; - if (obj_surface) - gen7_vc1_surface = obj_surface->private_data; - - if (!gen7_vc1_surface || - (gen7_vc1_surface->picture_type == GEN7_VC1_I_PICTURE || - gen7_vc1_surface->picture_type == GEN7_VC1_BI_PICTURE)) - dmv_surface_valid = 0; + if (pic_param->backward_reference_picture != VA_INVALID_ID && + obj_surface) + gen7_vc1_reference_surface = (struct gen7_vc1_surface *)(obj_surface->private_data); else - dmv_surface_valid = 1; + gen7_vc1_reference_surface = NULL; + + if (gen7_vc1_reference_surface) { + if (pic_param->sequence_fields.bits.interlace && + pic_param->picture_fields.bits.frame_coding_mode == 2 && /* Field-Interlace */ + pic_param->picture_fields.bits.top_field_first ^ is_first_field) { + if (gen7_vc1_reference_surface->picture_type_bottom == GEN7_VC1_P_PICTURE) + dmv_surface_valid = 1; + } else if (gen7_vc1_reference_surface->picture_type_top == GEN7_VC1_P_PICTURE) + dmv_surface_valid = 1; + } } assert(pic_param->picture_fields.bits.frame_coding_mode < 3); - if (pic_param->picture_fields.bits.frame_coding_mode < 2) - fcm = pic_param->picture_fields.bits.frame_coding_mode; - else { - if (pic_param->picture_fields.bits.top_field_first) - fcm = 2; + if (pic_param->sequence_fields.bits.interlace) { + if (pic_param->picture_fields.bits.frame_coding_mode < 2) + fcm = pic_param->picture_fields.bits.frame_coding_mode; + else if (!pic_param->picture_fields.bits.top_field_first) + fcm = 3; /* Field with bottom field first */ else - fcm = 3; + fcm = 2; /* Field with top field first */ } - if (picture_type == GEN7_VC1_B_PICTURE) { /* B picture */ - brfd = pic_param->reference_fields.bits.reference_distance; - brfd = (scale_factor * brfd) >> 8; - brfd = pic_param->reference_fields.bits.reference_distance - brfd - 1; + if (pic_param->sequence_fields.bits.interlace && + pic_param->picture_fields.bits.frame_coding_mode == 2) { /* Field-Interlace */ + if (picture_type == GEN7_VC1_I_PICTURE || + picture_type == GEN7_VC1_P_PICTURE) { + gen7_vc1_current_surface = (struct gen7_vc1_surface *)(decode_state->render_object->private_data); + + if (is_first_field) + gen7_vc1_current_surface->reference_distance = pic_param->reference_fields.bits.reference_distance; + + frfd = gen7_vc1_current_surface->reference_distance; + } else if (picture_type == GEN7_VC1_B_PICTURE) { + obj_surface = decode_state->reference_objects[1]; - if (brfd < 0) - brfd = 0; + if (pic_param->backward_reference_picture != VA_INVALID_ID && + obj_surface) + gen7_vc1_reference_surface = (struct gen7_vc1_surface *)(obj_surface->private_data); + else + gen7_vc1_reference_surface = NULL; + + if (gen7_vc1_reference_surface) { + frfd = (scale_factor * gen7_vc1_reference_surface->reference_distance) >> 8; + + brfd = gen7_vc1_reference_surface->reference_distance - frfd - 1; + if (brfd < 0) + brfd = 0; + } + } } if (pic_param->sequence_fields.bits.overlap) { - if (profile == GEN7_VC1_ADVANCED_PROFILE) { + if (pic_param->sequence_fields.bits.profile == 3) { /* Advanced Profile */ if (picture_type == GEN7_VC1_P_PICTURE && pic_param->pic_quantizer_fields.bits.pic_quantizer_scale >= 9) { overlap = 1; @@ -1597,24 +1874,17 @@ gen7_mfd_vc1_pic_state(VADriverContextP ctx, } } - assert(pic_param->conditional_overlap_flag < 3); - assert(pic_param->mv_fields.bits.mv_table < 4); /* FIXME: interlace mode */ - if (pic_param->mv_fields.bits.mv_mode == VAMvMode1MvHalfPelBilinear || (pic_param->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation && pic_param->mv_fields.bits.mv_mode2 == VAMvMode1MvHalfPelBilinear)) - interpolation_mode = 9; /* Half-pel bilinear */ - else if (pic_param->mv_fields.bits.mv_mode == VAMvMode1MvHalfPel || - (pic_param->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation && - pic_param->mv_fields.bits.mv_mode2 == VAMvMode1MvHalfPel)) - interpolation_mode = 1; /* Half-pel bicubic */ + interpolation_mode = 8 | pic_param->fast_uvmc_flag; else - interpolation_mode = 0; /* Quarter-pel bicubic */ + interpolation_mode = 0 | pic_param->fast_uvmc_flag; BEGIN_BCS_BATCH(batch, 6); OUT_BCS_BATCH(batch, MFD_VC1_LONG_PIC_STATE | (6 - 2)); OUT_BCS_BATCH(batch, - (((ALIGN(pic_param->coded_height, 16) / 16) - 1) << 16) | + ((height_in_mbs - 1) << 16) | ((ALIGN(pic_param->coded_width, 16) / 16) - 1)); OUT_BCS_BATCH(batch, ((ALIGN(pic_param->coded_width, 16) / 16 + 1) / 2 - 1) << 24 | @@ -1623,12 +1893,12 @@ gen7_mfd_vc1_pic_state(VADriverContextP ctx, pic_param->rounding_control << 13 | pic_param->sequence_fields.bits.syncmarker << 12 | interpolation_mode << 8 | - 0 << 7 | /* FIXME: scale up or down ??? */ - pic_param->range_reduction_frame << 6 | - pic_param->entrypoint_fields.bits.loopfilter << 5 | + range_reduction_scale << 7 | + range_reduction << 6 | + loopfilter << 5 | overlap << 4 | - !pic_param->picture_fields.bits.is_first_field << 3 | - (pic_param->sequence_fields.bits.profile == 3) << 0); + !is_first_field << 3 | + (pic_param->sequence_fields.bits.profile == 3) << 0); /* Advanced Profile */ OUT_BCS_BATCH(batch, va_to_gen7_vc1_condover[pic_param->conditional_overlap_flag] << 29 | ptype << 26 | @@ -1642,8 +1912,8 @@ gen7_mfd_vc1_pic_state(VADriverContextP ctx, pic_param->fast_uvmc_flag << 26 | ref_field_pic_polarity << 25 | pic_param->reference_fields.bits.num_reference_pictures << 24 | - pic_param->reference_fields.bits.reference_distance << 20 | - pic_param->reference_fields.bits.reference_distance << 16 | /* FIXME: ??? */ + brfd << 20 | + frfd << 16 | pic_param->mv_fields.bits.extended_dmv_range << 10 | pic_param->mv_fields.bits.extended_mv_range << 8 | alt_pquant_edge_mask << 4 | @@ -1651,14 +1921,14 @@ gen7_mfd_vc1_pic_state(VADriverContextP ctx, pic_param->pic_quantizer_fields.bits.half_qp << 1 | pic_param->pic_quantizer_fields.bits.pic_quantizer_type << 0); OUT_BCS_BATCH(batch, - !!(pic_param->bitplane_present.value & 0x7f) << 31 | - pic_param->raw_coding.flags.forward_mb << 30 | - pic_param->raw_coding.flags.mv_type_mb << 29 | - pic_param->raw_coding.flags.skip_mb << 28 | - pic_param->raw_coding.flags.direct_mb << 27 | - pic_param->raw_coding.flags.overflags << 26 | - pic_param->raw_coding.flags.ac_pred << 25 | - pic_param->raw_coding.flags.field_tx << 24 | + bitplane_present << 31 | + forward_mb << 30 | + mv_type_mb << 29 | + skip_mb << 28 | + direct_mb << 27 | + overflags << 26 | + ac_pred << 25 | + field_tx << 24 | pic_param->mv_fields.bits.mv_table << 20 | pic_param->mv_fields.bits.four_mv_block_pattern_table << 18 | pic_param->mv_fields.bits.two_mv_block_pattern_table << 16 | @@ -1679,41 +1949,140 @@ gen7_mfd_vc1_pred_pipe_state(VADriverContextP ctx, { struct intel_batchbuffer *batch = gen7_mfd_context->base.batch; VAPictureParameterBufferVC1 *pic_param; + struct gen7_vc1_surface *gen7_vc1_top_surface; + struct gen7_vc1_surface *gen7_vc1_bottom_surface; int picture_type; + int is_first_field = 1; int intensitycomp_single_fwd = 0; - int luma_scale1 = 0; - int luma_shift1 = 0; + int intensitycomp_single_bwd = 0; + int intensitycomp_double_fwd = 0; + int lumscale1_single_fwd = 0; + int lumscale2_single_fwd = 0; + int lumshift1_single_fwd = 0; + int lumshift2_single_fwd = 0; + int lumscale1_single_bwd = 0; + int lumscale2_single_bwd = 0; + int lumshift1_single_bwd = 0; + int lumshift2_single_bwd = 0; + int lumscale1_double_fwd = 0; + int lumscale2_double_fwd = 0; + int lumshift1_double_fwd = 0; + int lumshift2_double_fwd = 0; + int replication_mode = 0; assert(decode_state->pic_param && decode_state->pic_param->buffer); pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer; - picture_type = pic_param->picture_fields.bits.picture_type; - - if (gen7_mfd_context->reference_surface[0].surface_id != VA_INVALID_ID) { - if (picture_type == 1 || picture_type == 2) { /* P/B picture */ - struct gen7_vc1_surface *gen7_vc1_surface = gen7_mfd_context->reference_surface[0].obj_surface->private_data; - if (gen7_vc1_surface) { - intensitycomp_single_fwd = gen7_vc1_surface->intensity_compensation; - luma_scale1 = gen7_vc1_surface->luma_scale; - luma_shift1 = gen7_vc1_surface->luma_shift; + + if (!pic_param->sequence_fields.bits.interlace || + (pic_param->picture_fields.bits.frame_coding_mode < 2)) { /* Progressive or Frame-Interlace */ + picture_type = pic_param->picture_fields.bits.picture_type; + } else {/* Field-Interlace */ + is_first_field = pic_param->picture_fields.bits.is_first_field; + picture_type = fptype_to_picture_type[pic_param->picture_fields.bits.picture_type][!is_first_field]; + } + + if (picture_type == GEN7_VC1_P_PICTURE || + picture_type == GEN7_VC1_B_PICTURE) { + if (gen7_mfd_context->reference_surface[0].surface_id != VA_INVALID_ID) + gen7_vc1_top_surface = (struct gen7_vc1_surface *)(gen7_mfd_context->reference_surface[0].obj_surface->private_data); + else + gen7_vc1_top_surface = NULL; + + if (gen7_vc1_top_surface) { + intensitycomp_single_fwd = !!gen7_vc1_top_surface->intensity_compensation_top; + lumscale1_single_fwd = gen7_vc1_top_surface->luma_scale_top[0]; + lumshift1_single_fwd = gen7_vc1_top_surface->luma_shift_top[0]; + if (gen7_vc1_top_surface->intensity_compensation_top == 2) { + intensitycomp_double_fwd = 1; + lumscale1_double_fwd = gen7_vc1_top_surface->luma_scale_top[1]; + lumshift1_double_fwd = gen7_vc1_top_surface->luma_shift_top[1]; + } + } + + if (pic_param->sequence_fields.bits.interlace && + pic_param->picture_fields.bits.frame_coding_mode > 0) { /* Frame-Interlace or Field-Interlace */ + if (gen7_mfd_context->reference_surface[2].surface_id != VA_INVALID_ID) + gen7_vc1_bottom_surface = (struct gen7_vc1_surface *)(gen7_mfd_context->reference_surface[2].obj_surface->private_data); + else + gen7_vc1_bottom_surface = NULL; + + if (gen7_vc1_bottom_surface) { + intensitycomp_single_fwd |= !!gen7_vc1_bottom_surface->intensity_compensation_bottom << 1; + lumscale2_single_fwd = gen7_vc1_bottom_surface->luma_scale_bottom[0]; + lumshift2_single_fwd = gen7_vc1_bottom_surface->luma_shift_bottom[0]; + if (gen7_vc1_bottom_surface->intensity_compensation_bottom == 2) { + intensitycomp_double_fwd |= 2; + lumscale2_double_fwd = gen7_vc1_bottom_surface->luma_scale_bottom[1]; + lumshift2_double_fwd = gen7_vc1_bottom_surface->luma_shift_bottom[1]; + } + } + } + } + + if (picture_type == GEN7_VC1_B_PICTURE) { + if (gen7_mfd_context->reference_surface[1].surface_id != VA_INVALID_ID) + gen7_vc1_top_surface = (struct gen7_vc1_surface *)(gen7_mfd_context->reference_surface[1].obj_surface->private_data); + else + gen7_vc1_top_surface = NULL; + + if (gen7_vc1_top_surface) { + intensitycomp_single_bwd = !!gen7_vc1_top_surface->intensity_compensation_top; + lumscale1_single_bwd = gen7_vc1_top_surface->luma_scale_top[0]; + lumshift1_single_bwd = gen7_vc1_top_surface->luma_shift_top[0]; + } + + if (pic_param->sequence_fields.bits.interlace && + pic_param->picture_fields.bits.frame_coding_mode > 0) { /* Frame-Interlace or Field-Interlace */ + if (gen7_mfd_context->reference_surface[3].surface_id != VA_INVALID_ID) + gen7_vc1_bottom_surface = (struct gen7_vc1_surface *)(gen7_mfd_context->reference_surface[3].obj_surface->private_data); + else + gen7_vc1_bottom_surface = NULL; + + if (gen7_vc1_bottom_surface) { + intensitycomp_single_bwd |= !!gen7_vc1_bottom_surface->intensity_compensation_bottom << 1; + lumscale2_single_bwd = gen7_vc1_bottom_surface->luma_scale_bottom[0]; + lumshift2_single_bwd = gen7_vc1_bottom_surface->luma_shift_bottom[0]; } } } + if (pic_param->sequence_fields.bits.interlace && + pic_param->picture_fields.bits.frame_coding_mode > 0) { /* Frame-Interlace or Field-Interlace */ + if (picture_type == GEN7_VC1_P_PICTURE) + replication_mode = 0x5; + else if (picture_type == GEN7_VC1_B_PICTURE) + replication_mode = 0xf; + } + BEGIN_BCS_BATCH(batch, 6); OUT_BCS_BATCH(batch, MFX_VC1_PRED_PIPE_STATE | (6 - 2)); OUT_BCS_BATCH(batch, - 0 << 14 | /* FIXME: double ??? */ + intensitycomp_double_fwd << 14 | 0 << 12 | intensitycomp_single_fwd << 10 | - 0 << 8 | - 0 << 4 | /* FIXME: interlace mode */ + intensitycomp_single_bwd << 8 | + replication_mode << 4 | 0); OUT_BCS_BATCH(batch, - luma_shift1 << 16 | - luma_scale1 << 0); - OUT_BCS_BATCH(batch, 0); - OUT_BCS_BATCH(batch, 0); - OUT_BCS_BATCH(batch, 0); + lumshift2_single_fwd << 24 | + lumshift1_single_fwd << 16 | + lumscale2_single_fwd << 8 | + lumscale1_single_fwd << 0); + OUT_BCS_BATCH(batch, + lumshift2_double_fwd << 24 | + lumshift1_double_fwd << 16 | + lumscale2_double_fwd << 8 | + lumscale1_double_fwd << 0); + OUT_BCS_BATCH(batch, + lumshift2_single_bwd << 24 | + lumshift1_single_bwd << 16 | + lumscale2_single_bwd << 8 | + lumscale1_single_bwd << 0); + OUT_BCS_BATCH(batch, + 0 << 24 | + 0 << 16 | + 0 << 8 | + 0 << 0); ADVANCE_BCS_BATCH(batch); } @@ -1724,19 +2093,47 @@ gen7_mfd_vc1_directmode_state(VADriverContextP ctx, struct gen7_mfd_context *gen7_mfd_context) { struct intel_batchbuffer *batch = gen7_mfd_context->base.batch; + VAPictureParameterBufferVC1 *pic_param; struct object_surface *obj_surface; dri_bo *dmv_read_buffer = NULL, *dmv_write_buffer = NULL; + int picture_type; + int is_first_field = 1; - obj_surface = decode_state->render_object; + pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer; - if (obj_surface && obj_surface->private_data) { - dmv_write_buffer = ((struct gen7_vc1_surface *)(obj_surface->private_data))->dmv; + if (!pic_param->sequence_fields.bits.interlace || + (pic_param->picture_fields.bits.frame_coding_mode < 2)) { /* Progressive or Frame-Interlace */ + picture_type = pic_param->picture_fields.bits.picture_type; + } else {/* Field-Interlace */ + is_first_field = pic_param->picture_fields.bits.is_first_field; + picture_type = fptype_to_picture_type[pic_param->picture_fields.bits.picture_type][!is_first_field]; } - obj_surface = decode_state->reference_objects[1]; + if (picture_type == GEN7_VC1_P_PICTURE || + picture_type == GEN7_VC1_SKIPPED_PICTURE) { + obj_surface = decode_state->render_object; - if (obj_surface && obj_surface->private_data) { - dmv_read_buffer = ((struct gen7_vc1_surface *)(obj_surface->private_data))->dmv; + if (pic_param->sequence_fields.bits.interlace && + (pic_param->picture_fields.bits.frame_coding_mode == 2) && /* Field-Interlace */ + (pic_param->picture_fields.bits.top_field_first ^ is_first_field)) + dmv_write_buffer = ((struct gen7_vc1_surface *)(obj_surface->private_data))->dmv_bottom; + else + dmv_write_buffer = ((struct gen7_vc1_surface *)(obj_surface->private_data))->dmv_top; + } + + if (picture_type == GEN7_VC1_B_PICTURE) { + obj_surface = decode_state->reference_objects[1]; + if (pic_param->backward_reference_picture != VA_INVALID_ID && + obj_surface && + obj_surface->private_data) { + + if (pic_param->sequence_fields.bits.interlace && + (pic_param->picture_fields.bits.frame_coding_mode == 2) && /* Field-Interlace */ + (pic_param->picture_fields.bits.top_field_first ^ is_first_field)) + dmv_read_buffer = ((struct gen7_vc1_surface *)(obj_surface->private_data))->dmv_bottom; + else + dmv_read_buffer = ((struct gen7_vc1_surface *)(obj_surface->private_data))->dmv_top; + } } BEGIN_BCS_BATCH(batch, 3); @@ -1766,22 +2163,23 @@ gen7_mfd_vc1_get_macroblock_bit_offset(uint8_t *buf, int in_slice_data_bit_offse int slice_header_size = in_slice_data_bit_offset / 8; int i, j; - if (profile != 3) - out_slice_data_bit_offset = in_slice_data_bit_offset; - else { - for (i = 0, j = 0; i < slice_header_size; i++, j++) { - if (!buf[j] && !buf[j + 1] && buf[j + 2] == 3 && buf[j + 3] < 4) { - if (i < slice_header_size - 1) + if (profile == 3 && slice_header_size) { /* Advanced Profile */ + for (i = 0, j = 0; i < slice_header_size - 1; i++, j++) + if (!buf[j] && !buf[j + 1] && buf[j + 2] == 3 && buf[j + 3] < 4) i++, j += 2; - else { - buf[j + 2] = buf[j + 1]; - j++; - } + + if (i == slice_header_size - 1) { + if (!buf[j] && !buf[j + 1] && buf[j + 2] == 3 && buf[j + 3] < 4) { + buf[j + 2] = 0; + j++; } + + j++; } out_slice_data_bit_offset = 8 * j + in_slice_data_bit_offset % 8; - } + } else /* Simple or Main Profile */ + out_slice_data_bit_offset = in_slice_data_bit_offset; return out_slice_data_bit_offset; } @@ -1808,8 +2206,11 @@ gen7_mfd_vc1_bsd_object(VADriverContextP ctx, if (next_slice_param) next_slice_start_vert_pos = next_slice_param->slice_vertical_position; - else + else if (!pic_param->sequence_fields.bits.interlace || + pic_param->picture_fields.bits.frame_coding_mode < 2) /* Progressive or Frame-Interlace */ next_slice_start_vert_pos = ALIGN(pic_param->coded_height, 16) / 16; + else /* Field-Interlace */ + next_slice_start_vert_pos = ALIGN(pic_param->coded_height, 32) / 32; BEGIN_BCS_BATCH(batch, 5); OUT_BCS_BATCH(batch, MFD_VC1_BSD_OBJECT | (5 - 2));