summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiang, Haihao <haihao.xiang@intel.com>2011-01-27 00:44:43 +0800
committerXiang, Haihao <haihao.xiang@intel.com>2011-01-26 16:55:43 +0800
commitb9c7e24fd79979d7226b0c864c189658dc5c8b8f (patch)
tree7c2c9b2a5835bdd059cdbabd855df689a86b5679
parentae6adeb0c7f4931d6a09c75a2b2a9fe739d74eed (diff)
downloadlibva-b9c7e24fd79979d7226b0c864c189658dc5c8b8f.tar.gz
i965_drv_video: VC-1 on Sandybridge
Currently support progressive picture. Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
-rw-r--r--i965_drv_video/gen6_mfd.c686
-rw-r--r--i965_drv_video/gen6_mfd.h19
-rw-r--r--i965_drv_video/i965_defines.h6
3 files changed, 679 insertions, 32 deletions
diff --git a/i965_drv_video/gen6_mfd.c b/i965_drv_video/gen6_mfd.c
index 0fe7860..cb2162f 100644
--- a/i965_drv_video/gen6_mfd.c
+++ b/i965_drv_video/gen6_mfd.c
@@ -187,17 +187,17 @@ gen6_mfd_avc_frame_store_index(VADriverContextP ctx, VAPictureParameterBufferH26
static void
gen6_mfd_free_avc_surface(void **data)
{
- struct gen6_mfd_surface *gen6_mfd_surface = *data;
+ struct gen6_avc_surface *gen6_avc_surface = *data;
- if (!gen6_mfd_surface)
+ if (!gen6_avc_surface)
return;
- dri_bo_unreference(gen6_mfd_surface->dmv_top);
- gen6_mfd_surface->dmv_top = NULL;
- dri_bo_unreference(gen6_mfd_surface->dmv_bottom);
- gen6_mfd_surface->dmv_bottom = NULL;
+ dri_bo_unreference(gen6_avc_surface->dmv_top);
+ gen6_avc_surface->dmv_top = NULL;
+ dri_bo_unreference(gen6_avc_surface->dmv_bottom);
+ gen6_avc_surface->dmv_bottom = NULL;
- free(gen6_mfd_surface);
+ free(gen6_avc_surface);
*data = NULL;
}
@@ -207,29 +207,29 @@ gen6_mfd_init_avc_surface(VADriverContextP ctx,
struct object_surface *obj_surface)
{
struct i965_driver_data *i965 = i965_driver_data(ctx);
- struct gen6_mfd_surface *gen6_mfd_surface = obj_surface->private_data;
+ struct gen6_avc_surface *gen6_avc_surface = obj_surface->private_data;
obj_surface->free_private_data = gen6_mfd_free_avc_surface;
- if (!gen6_mfd_surface) {
- gen6_mfd_surface = calloc(sizeof(struct gen6_mfd_surface), 1);
+ if (!gen6_avc_surface) {
+ gen6_avc_surface = calloc(sizeof(struct gen6_avc_surface), 1);
assert((obj_surface->size & 0x3f) == 0);
- obj_surface->private_data = gen6_mfd_surface;
+ obj_surface->private_data = gen6_avc_surface;
}
- gen6_mfd_surface->dmv_bottom_flag = (pic_param->pic_fields.bits.field_pic_flag &&
+ gen6_avc_surface->dmv_bottom_flag = (pic_param->pic_fields.bits.field_pic_flag &&
!pic_param->seq_fields.bits.direct_8x8_inference_flag);
- if (gen6_mfd_surface->dmv_top == NULL) {
- gen6_mfd_surface->dmv_top = dri_bo_alloc(i965->intel.bufmgr,
+ if (gen6_avc_surface->dmv_top == NULL) {
+ gen6_avc_surface->dmv_top = dri_bo_alloc(i965->intel.bufmgr,
"direct mv w/r buffer",
DMV_SIZE,
0x1000);
}
- if (gen6_mfd_surface->dmv_bottom_flag &&
- gen6_mfd_surface->dmv_bottom == NULL) {
- gen6_mfd_surface->dmv_bottom = dri_bo_alloc(i965->intel.bufmgr,
+ if (gen6_avc_surface->dmv_bottom_flag &&
+ gen6_avc_surface->dmv_bottom == NULL) {
+ gen6_avc_surface->dmv_bottom = dri_bo_alloc(i965->intel.bufmgr,
"direct mv w/r buffer",
DMV_SIZE,
0x1000);
@@ -288,8 +288,8 @@ gen6_mfd_surface_state(VADriverContextP ctx,
OUT_BCS_BATCH(ctx, MFX_SURFACE_STATE | (6 - 2));
OUT_BCS_BATCH(ctx, 0);
OUT_BCS_BATCH(ctx,
- ((obj_surface->height - 1) << 19) |
- ((obj_surface->width - 1) << 6));
+ ((obj_surface->orig_height - 1) << 19) |
+ ((obj_surface->orig_width - 1) << 6));
OUT_BCS_BATCH(ctx,
(MFX_SURFACE_PLANAR_420_8 << 28) | /* 420 planar YUV surface */
(1 << 27) | /* must be 1 for interleave U/V, hardware requirement */
@@ -578,7 +578,7 @@ gen6_mfd_avc_directmode_state(VADriverContextP ctx,
struct i965_media_state *media_state = &i965->media_state;
struct gen6_mfd_context *gen6_mfd_context = media_state->private_context;
struct object_surface *obj_surface;
- struct gen6_mfd_surface *gen6_mfd_surface;
+ struct gen6_avc_surface *gen6_avc_surface;
VAPictureH264 *va_pic;
int i, j;
@@ -590,22 +590,22 @@ gen6_mfd_avc_directmode_state(VADriverContextP ctx,
if (gen6_mfd_context->reference_surface[i].surface_id != VA_INVALID_ID) {
obj_surface = SURFACE(gen6_mfd_context->reference_surface[i].surface_id);
assert(obj_surface);
- gen6_mfd_surface = obj_surface->private_data;
+ gen6_avc_surface = obj_surface->private_data;
- if (gen6_mfd_surface == NULL) {
+ if (gen6_avc_surface == NULL) {
OUT_BCS_BATCH(ctx, 0);
OUT_BCS_BATCH(ctx, 0);
} else {
- OUT_BCS_RELOC(ctx, gen6_mfd_surface->dmv_top,
+ OUT_BCS_RELOC(ctx, gen6_avc_surface->dmv_top,
I915_GEM_DOMAIN_INSTRUCTION, 0,
0);
- if (gen6_mfd_surface->dmv_bottom_flag == 1)
- OUT_BCS_RELOC(ctx, gen6_mfd_surface->dmv_bottom,
+ if (gen6_avc_surface->dmv_bottom_flag == 1)
+ OUT_BCS_RELOC(ctx, gen6_avc_surface->dmv_bottom,
I915_GEM_DOMAIN_INSTRUCTION, 0,
0);
else
- OUT_BCS_RELOC(ctx, gen6_mfd_surface->dmv_top,
+ OUT_BCS_RELOC(ctx, gen6_avc_surface->dmv_top,
I915_GEM_DOMAIN_INSTRUCTION, 0,
0);
}
@@ -620,18 +620,18 @@ gen6_mfd_avc_directmode_state(VADriverContextP ctx,
assert(!(va_pic->flags & VA_PICTURE_H264_INVALID));
obj_surface = SURFACE(va_pic->picture_id);
assert(obj_surface && obj_surface->bo && obj_surface->private_data);
- gen6_mfd_surface = obj_surface->private_data;
+ gen6_avc_surface = obj_surface->private_data;
- OUT_BCS_RELOC(ctx, gen6_mfd_surface->dmv_top,
+ OUT_BCS_RELOC(ctx, gen6_avc_surface->dmv_top,
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
0);
- if (gen6_mfd_surface->dmv_bottom_flag == 1)
- OUT_BCS_RELOC(ctx, gen6_mfd_surface->dmv_bottom,
+ if (gen6_avc_surface->dmv_bottom_flag == 1)
+ OUT_BCS_RELOC(ctx, gen6_avc_surface->dmv_bottom,
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
0);
else
- OUT_BCS_RELOC(ctx, gen6_mfd_surface->dmv_top,
+ OUT_BCS_RELOC(ctx, gen6_avc_surface->dmv_top,
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
0);
@@ -1405,10 +1405,634 @@ gen6_mfd_mpeg2_decode_picture(VADriverContextP ctx, struct decode_state *decode_
intel_batchbuffer_flush_bcs(ctx);
}
+static const int va_to_gen6_vc1_pic_type[5] = {
+ GEN6_VC1_BI_PICTURE, /* FIXME */
+ GEN6_VC1_P_PICTURE,
+ GEN6_VC1_B_PICTURE,
+ GEN6_VC1_BI_PICTURE,
+ GEN6_VC1_P_PICTURE,
+};
+
+static const int va_to_gen6_vc1_mv[4] = {
+ 1, /* 1-MV */
+ 2, /* 1-MV half-pel */
+ 3, /* 1-MV half-pef bilinear */
+ 0, /* Mixed MV */
+};
+
+static const int b_picture_scale_factor[21] = {
+ 128, 85, 170, 64, 192,
+ 51, 102, 153, 204, 43,
+ 215, 37, 74, 111, 148,
+ 185, 222, 32, 96, 160,
+ 224,
+};
+
+static const int va_to_gen6_vc1_condover[3] = {
+ 0,
+ 2,
+ 3
+};
+
+static const int va_to_gen6_vc1_profile[4] = {
+ GEN6_VC1_SIMPLE_PROFILE,
+ GEN6_VC1_MAIN_PROFILE,
+ GEN6_VC1_RESERVED_PROFILE,
+ GEN6_VC1_ADVANCED_PROFILE
+};
+
+static const int va_to_gen6_vc1_ttfrm[8] = {
+ 0, /* 8x8 */
+ 1, /* 8x4 bottom */
+ 1, /* 8x4 top */
+ 1, /* 8x4 */
+ 2, /* 4x8 bottom */
+ 2, /* 4x8 top */
+ 2, /* 4x8 */
+ 3, /* 4x4 */
+};
+
+static void
+gen6_mfd_free_vc1_surface(void **data)
+{
+ struct gen6_vc1_surface *gen6_vc1_surface = *data;
+
+ if (!gen6_vc1_surface)
+ return;
+
+ dri_bo_unreference(gen6_vc1_surface->dmv);
+ free(gen6_vc1_surface);
+ *data = NULL;
+}
+
+static void
+gen6_mfd_init_vc1_surface(VADriverContextP ctx,
+ VAPictureParameterBufferVC1 *pic_param,
+ struct object_surface *obj_surface)
+{
+ struct i965_driver_data *i965 = i965_driver_data(ctx);
+ struct gen6_vc1_surface *gen6_vc1_surface = obj_surface->private_data;
+
+ obj_surface->free_private_data = gen6_mfd_free_vc1_surface;
+
+ if (!gen6_vc1_surface) {
+ gen6_vc1_surface = calloc(sizeof(struct gen6_vc1_surface), 1);
+ assert((obj_surface->size & 0x3f) == 0);
+ obj_surface->private_data = gen6_vc1_surface;
+ }
+
+ gen6_vc1_surface->picture_type = pic_param->picture_fields.bits.picture_type;
+
+ if (gen6_vc1_surface->dmv == NULL) {
+ gen6_vc1_surface->dmv = dri_bo_alloc(i965->intel.bufmgr,
+ "direct mv w/r buffer",
+ 557056, /* 64 * 128 * 64 */
+ 0x1000);
+ }
+}
+
+static void
+gen6_mfd_vc1_decode_init(VADriverContextP ctx, struct decode_state *decode_state)
+{
+ VAPictureParameterBufferVC1 *pic_param;
+ struct i965_driver_data *i965 = i965_driver_data(ctx);
+ struct i965_media_state *media_state = &i965->media_state;
+ struct gen6_mfd_context *gen6_mfd_context;
+ struct object_surface *obj_surface;
+ int i;
+ dri_bo *bo;
+
+ assert(decode_state->pic_param && decode_state->pic_param->buffer);
+ pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer;
+ gen6_mfd_context = media_state->private_context;
+
+ if (gen6_mfd_context == NULL) {
+ gen6_mfd_context = calloc(1, sizeof(struct gen6_mfd_context));
+ media_state->private_context = gen6_mfd_context;
+
+ for (i = 0; i < ARRAY_ELEMS(gen6_mfd_context->reference_surface); i++) {
+ gen6_mfd_context->reference_surface[i].surface_id = VA_INVALID_ID;
+ gen6_mfd_context->reference_surface[i].frame_store_id = -1;
+ }
+ }
+
+ /* reference picture */
+ obj_surface = SURFACE(pic_param->forward_reference_picture);
+
+ if (obj_surface && obj_surface->bo)
+ gen6_mfd_context->reference_surface[0].surface_id = pic_param->forward_reference_picture;
+ else
+ gen6_mfd_context->reference_surface[0].surface_id = VA_INVALID_ID;
+
+ obj_surface = SURFACE(pic_param->backward_reference_picture);
+
+ if (obj_surface && obj_surface->bo)
+ gen6_mfd_context->reference_surface[1].surface_id = pic_param->backward_reference_picture;
+ else
+ gen6_mfd_context->reference_surface[1].surface_id = pic_param->forward_reference_picture;
+
+ /* must do so !!! */
+ for (i = 2; i < ARRAY_ELEMS(gen6_mfd_context->reference_surface); i++)
+ gen6_mfd_context->reference_surface[i].surface_id = gen6_mfd_context->reference_surface[i % 2].surface_id;
+
+ /* Current decoded picture */
+ obj_surface = SURFACE(decode_state->current_render_target);
+ assert(obj_surface);
+ gen6_mfd_init_vc1_surface(ctx, pic_param, obj_surface);
+
+ if (obj_surface->bo == NULL) {
+ uint32_t tiling_mode = I915_TILING_Y;
+ unsigned long pitch;
+
+ obj_surface->bo = drm_intel_bo_alloc_tiled(i965->intel.bufmgr,
+ "vaapi surface",
+ obj_surface->width,
+ obj_surface->height + obj_surface->height / 2,
+ 1,
+ &tiling_mode,
+ &pitch,
+ 0);
+ assert(obj_surface->bo);
+ assert(tiling_mode == I915_TILING_Y);
+ assert(pitch == obj_surface->width);
+ }
+
+ dri_bo_unreference(gen6_mfd_context->post_deblocking_output.bo);
+ gen6_mfd_context->post_deblocking_output.bo = obj_surface->bo;
+ dri_bo_reference(gen6_mfd_context->post_deblocking_output.bo);
+ gen6_mfd_context->post_deblocking_output.valid = pic_param->entrypoint_fields.bits.loopfilter;
+
+ dri_bo_unreference(gen6_mfd_context->pre_deblocking_output.bo);
+ gen6_mfd_context->pre_deblocking_output.bo = obj_surface->bo;
+ dri_bo_reference(gen6_mfd_context->pre_deblocking_output.bo);
+ gen6_mfd_context->pre_deblocking_output.valid = !pic_param->entrypoint_fields.bits.loopfilter;
+
+ dri_bo_unreference(gen6_mfd_context->intra_row_store_scratch_buffer.bo);
+ bo = dri_bo_alloc(i965->intel.bufmgr,
+ "intra row store",
+ 128 * 64,
+ 0x1000);
+ assert(bo);
+ gen6_mfd_context->intra_row_store_scratch_buffer.bo = bo;
+ gen6_mfd_context->intra_row_store_scratch_buffer.valid = 1;
+
+ dri_bo_unreference(gen6_mfd_context->deblocking_filter_row_store_scratch_buffer.bo);
+ bo = dri_bo_alloc(i965->intel.bufmgr,
+ "deblocking filter row store",
+ 46080, /* 6 * 120 * 64 */
+ 0x1000);
+ assert(bo);
+ gen6_mfd_context->deblocking_filter_row_store_scratch_buffer.bo = bo;
+ gen6_mfd_context->deblocking_filter_row_store_scratch_buffer.valid = 1;
+
+ dri_bo_unreference(gen6_mfd_context->bsd_mpc_row_store_scratch_buffer.bo);
+ bo = dri_bo_alloc(i965->intel.bufmgr,
+ "bsd mpc row store",
+ 11520, /* 1.5 * 120 * 64 */
+ 0x1000);
+ assert(bo);
+ gen6_mfd_context->bsd_mpc_row_store_scratch_buffer.bo = bo;
+ gen6_mfd_context->bsd_mpc_row_store_scratch_buffer.valid = 1;
+
+ gen6_mfd_context->mpr_row_store_scratch_buffer.valid = 0;
+
+ gen6_mfd_context->bitplane_read_buffer.valid = !!pic_param->bitplane_present.value;
+ dri_bo_unreference(gen6_mfd_context->bitplane_read_buffer.bo);
+
+ if (gen6_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 bitplane_width = ALIGN(width_in_mbs, 2) / 2;
+ int bitplane_height = height_in_mbs;
+ int src_w, src_h, dst_w, dst_h;
+ uint8_t *src = NULL, *dst = NULL;
+
+ assert(decode_state->bit_plane->buffer);
+ src = decode_state->bit_plane->buffer;
+
+ bo = dri_bo_alloc(i965->intel.bufmgr,
+ "VC-1 Bitplane",
+ bitplane_width * bitplane_width,
+ 0x1000);
+ assert(bo);
+ gen6_mfd_context->bitplane_read_buffer.bo = bo;
+
+ dri_bo_map(bo, True);
+ assert(bo->virtual);
+ dst = bo->virtual;
+
+ for (src_h = 0; src_h < height_in_mbs; src_h++) {
+ for(src_w = 0; src_w < width_in_mbs; src_w++) {
+ int src_index, dst_index;
+ int src_shift;
+ uint8_t src_value;
+
+ src_index = (src_h * width_in_mbs + src_w) / 2;
+ src_shift = !((src_h * width_in_mbs + src_w) & 1) * 4;
+ src_value = ((src[src_index] >> src_shift) & 0xf);
+
+ dst_index = src_w / 2;
+ dst[dst_index] = ((dst[dst_index] >> 4) | (src_value << 4));
+ }
+
+ if (src_w & 1)
+ dst[src_w / 2] >>= 4;
+
+ dst += bitplane_width;
+ }
+
+ dri_bo_unmap(bo);
+ } else
+ gen6_mfd_context->bitplane_read_buffer.bo = NULL;
+}
+
+static void
+gen6_mfd_vc1_pic_state(VADriverContextP ctx, struct decode_state *decode_state)
+{
+ VAPictureParameterBufferVC1 *pic_param;
+ struct i965_driver_data *i965 = i965_driver_data(ctx);
+ struct object_surface *obj_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 ref_field_pic_polarity = 0;
+ int scale_factor = 0;
+ int trans_ac_y = 0;
+ int dmv_surface_valid = 0;
+ int brfd = 0;
+ int fcm = 0;
+ int picture_type;
+
+ assert(decode_state->pic_param && decode_state->pic_param->buffer);
+ pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer;
+
+ 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;
+ dqdbedge = pic_param->pic_quantizer_fields.bits.dq_db_edge;
+ dqsbedge = pic_param->pic_quantizer_fields.bits.dq_sb_edge;
+ dqbilevel = pic_param->pic_quantizer_fields.bits.dq_binary_level;
+ alt_pq = pic_param->pic_quantizer_fields.bits.alt_pic_quantizer;
+
+ if (dquant == 0) {
+ alt_pquant_config = 0;
+ alt_pquant_edge_mask = 0;
+ } else if (dquant == 2) {
+ alt_pquant_config = 1;
+ alt_pquant_edge_mask = 0xf;
+ } else {
+ assert(dquant == 1);
+ if (dquantfrm == 0) {
+ alt_pquant_config = 0;
+ alt_pquant_edge_mask = 0;
+ alt_pq = 0;
+ } else {
+ assert(dquantfrm == 1);
+ alt_pquant_config = 1;
+
+ switch (dqprofile) {
+ case 3:
+ if (dqbilevel == 0) {
+ alt_pquant_config = 2;
+ alt_pquant_edge_mask = 0;
+ } else {
+ assert(dqbilevel == 1);
+ alt_pquant_config = 3;
+ alt_pquant_edge_mask = 0;
+ }
+ break;
+
+ case 0:
+ alt_pquant_edge_mask = 0xf;
+ break;
+
+ case 1:
+ if (dqdbedge == 3)
+ alt_pquant_edge_mask = 0x9;
+ else
+ alt_pquant_edge_mask = (0x3 << dqdbedge);
+
+ break;
+
+ case 2:
+ alt_pquant_edge_mask = (0x1 << dqsbedge);
+ break;
+
+ default:
+ assert(0);
+ }
+ }
+ }
+
+ if (pic_param->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation) {
+ assert(pic_param->mv_fields.bits.mv_mode2 < 4);
+ unified_mv_mode = va_to_gen6_vc1_mv[pic_param->mv_fields.bits.mv_mode2];
+ } else {
+ assert(pic_param->mv_fields.bits.mv_mode < 4);
+ unified_mv_mode = va_to_gen6_vc1_mv[pic_param->mv_fields.bits.mv_mode];
+ }
+
+ 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->b_picture_fraction < 21)
+ scale_factor = b_picture_scale_factor[pic_param->b_picture_fraction];
+
+ picture_type = va_to_gen6_vc1_pic_type[pic_param->picture_fields.bits.picture_type];
+
+ if (picture_type == GEN6_VC1_I_PICTURE || picture_type == GEN6_VC1_BI_PICTURE) /* I picture */
+ trans_ac_y = pic_param->transform_fields.bits.transform_ac_codingset_idx2;
+ else
+ trans_ac_y = pic_param->transform_fields.bits.transform_ac_codingset_idx1;
+
+
+ if (picture_type == GEN6_VC1_B_PICTURE) {
+ struct gen6_vc1_surface *gen6_vc1_surface = NULL;
+
+ obj_surface = SURFACE(pic_param->backward_reference_picture);
+ assert(obj_surface);
+ gen6_vc1_surface = obj_surface->private_data;
+
+ if (!gen6_vc1_surface ||
+ (va_to_gen6_vc1_pic_type[gen6_vc1_surface->picture_type] == GEN6_VC1_I_PICTURE ||
+ va_to_gen6_vc1_pic_type[gen6_vc1_surface->picture_type] == GEN6_VC1_BI_PICTURE))
+ dmv_surface_valid = 0;
+ else
+ 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;
+ else
+ fcm = 3;
+ }
+
+ if (pic_param->picture_fields.bits.picture_type == GEN6_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 (brfd < 0)
+ brfd = 0;
+ }
+
+ assert(pic_param->conditional_overlap_flag < 3);
+ assert(pic_param->mv_fields.bits.mv_table < 4); /* FIXME: interlace mode */
+
+ BEGIN_BCS_BATCH(ctx, 6);
+ OUT_BCS_BATCH(ctx, MFX_VC1_PIC_STATE | (6 - 2));
+ OUT_BCS_BATCH(ctx,
+ (ALIGN(pic_param->coded_height, 16) / 16) << 16 |
+ (ALIGN(pic_param->coded_width, 16) / 16));
+ OUT_BCS_BATCH(ctx,
+ pic_param->sequence_fields.bits.syncmarker << 31 |
+ 1 << 29 | /* concealment */
+ alt_pq << 24 |
+ pic_param->entrypoint_fields.bits.loopfilter << 23 |
+ pic_param->sequence_fields.bits.overlap << 22 |
+ (pic_param->pic_quantizer_fields.bits.quantizer == 0) << 21 | /* implicit quantizer */
+ pic_param->pic_quantizer_fields.bits.pic_quantizer_scale << 16 |
+ alt_pquant_edge_mask << 12 |
+ alt_pquant_config << 10 |
+ pic_param->pic_quantizer_fields.bits.half_qp << 9 |
+ pic_param->pic_quantizer_fields.bits.pic_quantizer_type << 8 |
+ va_to_gen6_vc1_condover[pic_param->conditional_overlap_flag] << 6 |
+ !pic_param->picture_fields.bits.is_first_field << 5 |
+ picture_type << 2 |
+ fcm << 0);
+ OUT_BCS_BATCH(ctx,
+ !!pic_param->bitplane_present.value << 23 |
+ !pic_param->bitplane_present.flags.bp_forward_mb << 22 |
+ !pic_param->bitplane_present.flags.bp_mv_type_mb << 21 |
+ !pic_param->bitplane_present.flags.bp_skip_mb << 20 |
+ !pic_param->bitplane_present.flags.bp_direct_mb << 19 |
+ !pic_param->bitplane_present.flags.bp_overflags << 18 |
+ !pic_param->bitplane_present.flags.bp_ac_pred << 17 |
+ !pic_param->bitplane_present.flags.bp_field_tx << 16 |
+ pic_param->mv_fields.bits.extended_dmv_range << 14 |
+ pic_param->mv_fields.bits.extended_mv_range << 12 |
+ pic_param->mv_fields.bits.four_mv_switch << 11 |
+ pic_param->fast_uvmc_flag << 10 |
+ unified_mv_mode << 8 |
+ ref_field_pic_polarity << 6 |
+ pic_param->reference_fields.bits.num_reference_pictures << 5 |
+ pic_param->reference_fields.bits.reference_distance << 0);
+ OUT_BCS_BATCH(ctx,
+ scale_factor << 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 |
+ va_to_gen6_vc1_ttfrm[pic_param->transform_fields.bits.frame_level_transform_type] << 12 |
+ pic_param->transform_fields.bits.mb_level_transform_type_flag << 11 |
+ pic_param->mb_mode_table << 8 |
+ trans_ac_y << 6 |
+ pic_param->transform_fields.bits.transform_ac_codingset_idx1 << 4 |
+ pic_param->transform_fields.bits.intra_transform_dc_table << 3 |
+ pic_param->cbp_table << 0);
+ OUT_BCS_BATCH(ctx,
+ dmv_surface_valid << 13 |
+ brfd << 8 |
+ ((ALIGN(pic_param->coded_width, 16) / 16 + 1) / 2 - 1));
+ ADVANCE_BCS_BATCH(ctx);
+}
+
+static void
+gen6_mfd_vc1_pred_pipe_state(VADriverContextP ctx, struct decode_state *decode_state)
+{
+ VAPictureParameterBufferVC1 *pic_param;
+ int interpolation_mode = 0;
+
+ assert(decode_state->pic_param && decode_state->pic_param->buffer);
+ pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer;
+
+ 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 = 2; /* 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 = 0; /* Half-pel bicubic */
+ else
+ interpolation_mode = 1; /* Quarter-pel bicubic */
+
+ assert(decode_state->pic_param && decode_state->pic_param->buffer);
+ pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer;
+
+ BEGIN_BCS_BATCH(ctx, 7);
+ OUT_BCS_BATCH(ctx, MFX_VC1_PRED_PIPE_STATE | (7 - 2));
+ OUT_BCS_BATCH(ctx,
+ 0 << 8 | /* FIXME: interlace mode */
+ pic_param->rounding_control << 4 |
+ va_to_gen6_vc1_profile[pic_param->sequence_fields.bits.profile] << 2);
+ OUT_BCS_BATCH(ctx,
+ pic_param->luma_shift << 16 |
+ pic_param->luma_scale << 0); /* FIXME: Luma Scaling */
+ OUT_BCS_BATCH(ctx, 0);
+ OUT_BCS_BATCH(ctx, 0);
+ OUT_BCS_BATCH(ctx, 0);
+ OUT_BCS_BATCH(ctx,
+ interpolation_mode << 19 |
+ pic_param->fast_uvmc_flag << 18 |
+ 0 << 17 | /* FIXME: scale up or down ??? */
+ pic_param->range_reduction_frame << 16 |
+ 0 << 6 |
+ 0 << 4 |
+ 0 << 2 | /* FIXME: Intensity Compensation */
+ 0 << 0);
+ ADVANCE_BCS_BATCH(ctx);
+}
+
+
+static void
+gen6_mfd_vc1_directmode_state(VADriverContextP ctx, struct decode_state *decode_state)
+{
+ VAPictureParameterBufferVC1 *pic_param;
+ struct i965_driver_data *i965 = i965_driver_data(ctx);
+ struct object_surface *obj_surface;
+ dri_bo *dmv_read_buffer = NULL, *dmv_write_buffer = NULL;
+
+ assert(decode_state->pic_param && decode_state->pic_param->buffer);
+ pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer;
+
+ obj_surface = SURFACE(decode_state->current_render_target);
+
+ if (obj_surface && obj_surface->private_data) {
+ dmv_write_buffer = ((struct gen6_vc1_surface *)(obj_surface->private_data))->dmv;
+ }
+
+ obj_surface = SURFACE(pic_param->backward_reference_picture);
+
+ if (obj_surface && obj_surface->private_data) {
+ dmv_read_buffer = ((struct gen6_vc1_surface *)(obj_surface->private_data))->dmv;
+ }
+
+ BEGIN_BCS_BATCH(ctx, 3);
+ OUT_BCS_BATCH(ctx, MFX_VC1_DIRECTMODE_STATE | (3 - 2));
+
+ if (dmv_write_buffer)
+ OUT_BCS_RELOC(ctx, dmv_write_buffer,
+ I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
+ 0);
+ else
+ OUT_BCS_BATCH(ctx, 0);
+
+ if (dmv_read_buffer)
+ OUT_BCS_RELOC(ctx, dmv_read_buffer,
+ I915_GEM_DOMAIN_INSTRUCTION, 0,
+ 0);
+ else
+ OUT_BCS_BATCH(ctx, 0);
+
+ ADVANCE_BCS_BATCH(ctx);
+}
+
+static int
+gen6_mfd_vc1_get_macroblock_bit_offset(uint8_t *buf, int in_slice_data_bit_offset)
+{
+ int out_slice_data_bit_offset;
+ int slice_header_size = in_slice_data_bit_offset / 8;
+ int i, j;
+
+ 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) {
+ i++, j += 2;
+ }
+ }
+
+ out_slice_data_bit_offset = 8 * j + in_slice_data_bit_offset % 8;
+
+ return out_slice_data_bit_offset;
+}
+
+static void
+gen6_mfd_vc1_bsd_object(VADriverContextP ctx,
+ VAPictureParameterBufferVC1 *pic_param,
+ VASliceParameterBufferVC1 *slice_param,
+ VASliceParameterBufferVC1 *next_slice_param,
+ dri_bo *slice_data_bo)
+{
+ int next_slice_start_vert_pos;
+ int macroblock_offset;
+ uint8_t *slice_data = NULL;
+
+ dri_bo_map(slice_data_bo, 0);
+ slice_data = (uint8_t *)(slice_data_bo->virtual + slice_param->slice_data_offset);
+ macroblock_offset = gen6_mfd_vc1_get_macroblock_bit_offset(slice_data, slice_param->macroblock_offset);
+ dri_bo_unmap(slice_data_bo);
+
+ if (next_slice_param)
+ next_slice_start_vert_pos = next_slice_param->slice_vertical_position;
+ else
+ next_slice_start_vert_pos = ALIGN(pic_param->coded_height, 16) / 16;
+
+ BEGIN_BCS_BATCH(ctx, 4);
+ OUT_BCS_BATCH(ctx, MFD_VC1_BSD_OBJECT | (4 - 2));
+ OUT_BCS_BATCH(ctx,
+ slice_param->slice_data_size - (macroblock_offset >> 3));
+ OUT_BCS_BATCH(ctx,
+ slice_param->slice_data_offset + (macroblock_offset >> 3));
+ OUT_BCS_BATCH(ctx,
+ slice_param->slice_vertical_position << 24 |
+ next_slice_start_vert_pos << 16 |
+ (macroblock_offset & 0x7));
+ ADVANCE_BCS_BATCH(ctx);
+}
+
static void
gen6_mfd_vc1_decode_picture(VADriverContextP ctx, struct decode_state *decode_state)
{
+ VAPictureParameterBufferVC1 *pic_param;
+ VASliceParameterBufferVC1 *slice_param, *next_slice_param;
+ dri_bo *slice_data_bo;
+ int i, j;
+
+ assert(decode_state->pic_param && decode_state->pic_param->buffer);
+ pic_param = (VAPictureParameterBufferVC1 *)decode_state->pic_param->buffer;
+ gen6_mfd_vc1_decode_init(ctx, decode_state);
+ intel_batchbuffer_start_atomic_bcs(ctx, 0x1000);
+ intel_batchbuffer_emit_mi_flush_bcs(ctx);
+ gen6_mfd_pipe_mode_select(ctx, decode_state, MFX_FORMAT_VC1);
+ gen6_mfd_surface_state(ctx, decode_state, MFX_FORMAT_VC1);
+ gen6_mfd_pipe_buf_addr_state(ctx, decode_state, MFX_FORMAT_VC1);
+ gen6_mfd_bsp_buf_base_addr_state(ctx, decode_state, MFX_FORMAT_VC1);
+ gen6_mfd_vc1_pic_state(ctx, decode_state);
+ gen6_mfd_vc1_pred_pipe_state(ctx, decode_state);
+ gen6_mfd_vc1_directmode_state(ctx, decode_state);
+
+ assert(decode_state->num_slice_params == 1);
+ for (j = 0; j < decode_state->num_slice_params; j++) {
+ assert(decode_state->slice_params && decode_state->slice_params[j]->buffer);
+ slice_param = (VASliceParameterBufferVC1 *)decode_state->slice_params[j]->buffer;
+ slice_data_bo = decode_state->slice_datas[j]->bo;
+ gen6_mfd_ind_obj_base_addr_state(ctx, slice_data_bo, MFX_FORMAT_VC1);
+
+ for (i = 0; i < decode_state->slice_params[j]->num_elements; i++) {
+ assert(slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL);
+
+ if (i < decode_state->slice_params[j]->num_elements - 1)
+ next_slice_param = slice_param + 1;
+ else
+ next_slice_param = NULL;
+
+ gen6_mfd_vc1_bsd_object(ctx, pic_param, slice_param, next_slice_param, slice_data_bo);
+ slice_param++;
+ }
+ }
+
+ intel_batchbuffer_end_atomic_bcs(ctx);
+ intel_batchbuffer_flush_bcs(ctx);
}
void
diff --git a/i965_drv_video/gen6_mfd.h b/i965_drv_video/gen6_mfd.h
index dba1d07..a39137e 100644
--- a/i965_drv_video/gen6_mfd.h
+++ b/i965_drv_video/gen6_mfd.h
@@ -34,13 +34,30 @@
#include <i915_drm.h>
#include <intel_bufmgr.h>
-struct gen6_mfd_surface
+struct gen6_avc_surface
{
dri_bo *dmv_top;
dri_bo *dmv_bottom;
int dmv_bottom_flag;
};
+#define GEN6_VC1_I_PICTURE 0
+#define GEN6_VC1_P_PICTURE 1
+#define GEN6_VC1_B_PICTURE 2
+#define GEN6_VC1_BI_PICTURE 3
+#define GEN6_VC1_SKIPPED_PICTURE 4
+
+#define GEN6_VC1_SIMPLE_PROFILE 0
+#define GEN6_VC1_MAIN_PROFILE 1
+#define GEN6_VC1_ADVANCED_PROFILE 2
+#define GEN6_VC1_RESERVED_PROFILE 3
+
+struct gen6_vc1_surface
+{
+ dri_bo *dmv;
+ int picture_type;
+};
+
#define MAX_MFX_REFERENCE_SURFACES 16
struct gen6_mfd_context
{
diff --git a/i965_drv_video/i965_defines.h b/i965_drv_video/i965_defines.h
index 6c202c7..b03dc00 100644
--- a/i965_drv_video/i965_defines.h
+++ b/i965_drv_video/i965_defines.h
@@ -159,6 +159,12 @@
#define MFD_MPEG2_BSD_OBJECT MFX(2, 3, 1, 8)
+#define MFX_VC1_PIC_STATE MFX(2, 2, 0, 0)
+#define MFX_VC1_PRED_PIPE_STATE MFX(2, 2, 0, 1)
+#define MFX_VC1_DIRECTMODE_STATE MFX(2, 2, 0, 2)
+
+#define MFD_VC1_BSD_OBJECT MFX(2, 2, 1, 8)
+
#define I965_DEPTHFORMAT_D32_FLOAT 1
#define BASE_ADDRESS_MODIFY (1 << 0)