From 61fbb1bba1ad8a41ffae4fd1ba90391adf819b6e Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Wed, 23 Apr 2014 17:23:21 +0200 Subject: vp8: fix support for segmentation-enabled streams. If segmentation is enabled, then the segmentation map shall be live across frames until the current frame updates the segment ids. This means that the driver needs to maintain the segmentation map buffer allocation and enable writes (resp. reads) whenever necessary. This fixes decoding of 00-comprehensive-010. Signed-off-by: Gwenole Beauchesne --- src/gen7_mfd.h | 1 + src/gen8_mfd.c | 35 ++++++++++++++++++++++++++++++----- src/i965_decoder_utils.c | 24 ++++++++++++++++++++++++ src/i965_decoder_utils.h | 4 ++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/gen7_mfd.h b/src/gen7_mfd.h index e3111ab..0200216 100644 --- a/src/gen7_mfd.h +++ b/src/gen7_mfd.h @@ -85,6 +85,7 @@ struct gen7_mfd_context GenBuffer bsd_mpc_row_store_scratch_buffer; GenBuffer mpr_row_store_scratch_buffer; GenBuffer bitplane_read_buffer; + GenBuffer segmentation_buffer; VASurfaceID jpeg_wa_surface_id; struct object_surface *jpeg_wa_surface_object; diff --git a/src/gen8_mfd.c b/src/gen8_mfd.c index 72b2640..1742bea 100644 --- a/src/gen8_mfd.c +++ b/src/gen8_mfd.c @@ -2785,6 +2785,9 @@ gen8_mfd_vp8_decode_init(VADriverContextP ctx, dri_bo_reference(gen7_mfd_context->pre_deblocking_output.bo); gen7_mfd_context->pre_deblocking_output.valid = pic_param->pic_fields.bits.loop_filter_disable; + intel_ensure_vp8_segmentation_buffer(ctx, + &gen7_mfd_context->segmentation_buffer, width_in_mbs, height_in_mbs); + /* The same as AVC */ dri_bo_unreference(gen7_mfd_context->intra_row_store_scratch_buffer.bo); bo = dri_bo_alloc(i965->intel.bufmgr, @@ -2838,6 +2841,13 @@ gen8_mfd_vp8_pic_state(VADriverContextP ctx, int i, j,log2num; unsigned int quantization_value[4][6]; + /* There is no safe way to error out if the segmentation buffer + could not be allocated. So, instead of aborting, simply decode + something even if the result may look totally inacurate */ + const unsigned int enable_segmentation = + pic_param->pic_fields.bits.segmentation_enabled && + gen7_mfd_context->segmentation_buffer.valid; + log2num = (int)log2(slice_param->num_of_partitions - 1); BEGIN_BCS_BATCH(batch, 38); @@ -2854,8 +2864,10 @@ gen8_mfd_vp8_pic_state(VADriverContextP ctx, pic_param->pic_fields.bits.mb_no_coeff_skip << 10 | pic_param->pic_fields.bits.update_mb_segmentation_map << 9 | pic_param->pic_fields.bits.segmentation_enabled << 8 | - 0 << 7 | /* segmentation id streamin disabled */ - 0 << 6 | /* segmentation id streamout disabled */ + (enable_segmentation && + !pic_param->pic_fields.bits.update_mb_segmentation_map) << 7 | + (enable_segmentation && + pic_param->pic_fields.bits.update_mb_segmentation_map) << 6 | (pic_param->pic_fields.bits.key_frame == 0 ? 1 : 0) << 5 | /* 0 indicate an intra frame in VP8 stream/spec($9.1)*/ pic_param->pic_fields.bits.filter_type << 4 | (pic_param->pic_fields.bits.version == 3) << 1 | /* full pixel mode for version 3 */ @@ -2950,9 +2962,18 @@ gen8_mfd_vp8_pic_state(VADriverContextP ctx, (pic_param->loop_filter_deltas_mode[0] & 0x7f) << 0); /* segmentation id stream base address, DW35-DW37 */ - OUT_BCS_BATCH(batch, 0); - OUT_BCS_BATCH(batch, 0); - OUT_BCS_BATCH(batch, 0); + if (enable_segmentation) { + OUT_BCS_RELOC(batch, gen7_mfd_context->segmentation_buffer.bo, + 0, I915_GEM_DOMAIN_INSTRUCTION, + 0); + OUT_BCS_BATCH(batch, 0); + OUT_BCS_BATCH(batch, 0); + } + else { + OUT_BCS_BATCH(batch, 0); + OUT_BCS_BATCH(batch, 0); + OUT_BCS_BATCH(batch, 0); + } ADVANCE_BCS_BATCH(batch); } @@ -3142,6 +3163,9 @@ gen8_mfd_context_destroy(void *hw_context) dri_bo_unreference(gen7_mfd_context->bitplane_read_buffer.bo); gen7_mfd_context->bitplane_read_buffer.bo = NULL; + dri_bo_unreference(gen7_mfd_context->segmentation_buffer.bo); + gen7_mfd_context->segmentation_buffer.bo = NULL; + dri_bo_unreference(gen7_mfd_context->jpeg_wa_slice_data_bo); intel_batchbuffer_free(gen7_mfd_context->base.batch); @@ -3174,6 +3198,7 @@ gen8_dec_hw_context_init(VADriverContextP ctx, struct object_config *obj_config) } gen7_mfd_context->jpeg_wa_surface_id = VA_INVALID_SURFACE; + gen7_mfd_context->segmentation_buffer.valid = 0; switch (obj_config->profile) { case VAProfileMPEG2Simple: diff --git a/src/i965_decoder_utils.c b/src/i965_decoder_utils.c index e80749c..2533381 100644 --- a/src/i965_decoder_utils.c +++ b/src/i965_decoder_utils.c @@ -827,3 +827,27 @@ intel_mpeg2_find_next_slice(struct decode_state *decode_state, return NULL; } + +/* Ensure the segmentation buffer is large enough for the supplied + number of MBs, or re-allocate it */ +bool +intel_ensure_vp8_segmentation_buffer(VADriverContextP ctx, GenBuffer *buf, + unsigned int mb_width, unsigned int mb_height) +{ + struct i965_driver_data * const i965 = i965_driver_data(ctx); + /* The segmentation map is a 64-byte aligned linear buffer, with + each cache line holding only 8 bits for 4 continuous MBs */ + const unsigned int buf_size = ((mb_width + 3) / 4) * 64 * mb_height; + + if (buf->valid) { + if (buf->bo && buf->bo->size >= buf_size) + return true; + drm_intel_bo_unreference(buf->bo); + buf->valid = false; + } + + buf->bo = drm_intel_bo_alloc(i965->intel.bufmgr, "segmentation map", + buf_size, 0x1000); + buf->valid = buf->bo != NULL; + return buf->valid; +} diff --git a/src/i965_decoder_utils.h b/src/i965_decoder_utils.h index 8f64dfb..b7b72b3 100644 --- a/src/i965_decoder_utils.h +++ b/src/i965_decoder_utils.h @@ -106,4 +106,8 @@ intel_update_vp8_frame_store_index(VADriverContextP ctx, VAPictureParameterBufferVP8 *pic_param, GenFrameStore frame_store[MAX_GEN_REFERENCE_FRAMES]); +bool +intel_ensure_vp8_segmentation_buffer(VADriverContextP ctx, GenBuffer *buf, + unsigned int mb_width, unsigned int mb_height); + #endif /* I965_DECODER_UTILS_H */ -- cgit v1.2.3