OSDN Git Service

Fix the incorrect ver-coord for VDENC encoding
[android-x86/hardware-intel-common-vaapi.git] / src / gen9_vme.c
index b28470b..e98dc71 100644 (file)
 #include "i965_encoder.h"
 #include "gen6_vme.h"
 #include "gen6_mfc.h"
+#include "gen9_mfc.h"
+#include "intel_media.h"
+#include "gen9_vp9_encapi.h"
+#include "i965_post_processing.h"
 
 #ifdef SURFACE_STATE_PADDED_SIZE
 #undef SURFACE_STATE_PADDED_SIZE
@@ -210,7 +214,8 @@ gen9_vme_media_source_surface_state(VADriverContextP ctx,
                                             &vme_context->gpe_context,
                                             obj_surface,
                                             BINDING_TABLE_OFFSET(index),
-                                            SURFACE_STATE_OFFSET(index));
+                                            SURFACE_STATE_OFFSET(index),
+                                            0);
 }
 
 static void
@@ -225,7 +230,8 @@ gen9_vme_media_chroma_source_surface_state(VADriverContextP ctx,
                                                 &vme_context->gpe_context,
                                                 obj_surface,
                                                 BINDING_TABLE_OFFSET(index),
-                                                SURFACE_STATE_OFFSET(index));
+                                                SURFACE_STATE_OFFSET(index),
+                                                0);
 }
 
 static void
@@ -332,6 +338,7 @@ gen9_vme_surface_setup(VADriverContextP ctx,
     /*Setup surfaces state*/
     /* current picture for encoding */
     obj_surface = encode_state->input_yuv_object;
+    assert(obj_surface);
     gen9_vme_source_surface_state(ctx, 0, obj_surface, encoder_context);
     gen9_vme_media_source_surface_state(ctx, 4, obj_surface, encoder_context);
     gen9_vme_media_chroma_source_surface_state(ctx, 6, obj_surface, encoder_context);
@@ -352,6 +359,9 @@ gen9_vme_surface_setup(VADriverContextP ctx,
     /* VME output */
     gen9_vme_avc_output_buffer_setup(ctx, encode_state, 3, encoder_context);
     gen9_vme_avc_output_vme_batchbuffer_setup(ctx, encode_state, 5, encoder_context);
+    intel_h264_setup_cost_surface(ctx, encode_state, encoder_context,
+                                  BINDING_TABLE_OFFSET(INTEL_COST_TABLE_OFFSET),
+                                  SURFACE_STATE_OFFSET(INTEL_COST_TABLE_OFFSET));
 
     return VA_STATUS_SUCCESS;
 }
@@ -366,10 +376,10 @@ static VAStatus gen9_vme_interface_setup(VADriverContextP ctx,
     dri_bo *bo;
     unsigned char *desc_ptr;
 
-    bo = vme_context->gpe_context.dynamic_state.bo;
+    bo = vme_context->gpe_context.idrt.bo;
     dri_bo_map(bo, 1);
     assert(bo->virtual);
-    desc_ptr = (unsigned char *)bo->virtual + vme_context->gpe_context.idrt_offset;
+    desc_ptr = (unsigned char *)bo->virtual + vme_context->gpe_context.idrt.offset;
 
     desc = (struct gen8_interface_descriptor_data *)desc_ptr;
 
@@ -397,7 +407,8 @@ static VAStatus gen9_vme_interface_setup(VADriverContextP ctx,
 
 static VAStatus gen9_vme_constant_setup(VADriverContextP ctx,
                                         struct encode_state *encode_state,
-                                        struct intel_encoder_context *encoder_context)
+                                        struct intel_encoder_context *encoder_context,
+                                        int denom)
 {
     struct gen6_vme_context *vme_context = encoder_context->vme_context;
     unsigned char *constant_buffer;
@@ -409,13 +420,13 @@ static VAStatus gen9_vme_constant_setup(VADriverContextP ctx,
     if (encoder_context->codec == CODEC_H264 ||
         encoder_context->codec == CODEC_H264_MVC) {
         if (vme_context->h264_level >= 30) {
-            mv_num = 16;
+            mv_num = 16 / denom;
 
             if (vme_context->h264_level >= 31)
-                mv_num = 8;
+                mv_num = 8 / denom;
         }
     } else if (encoder_context->codec == CODEC_MPEG2) {
-        mv_num = 2;
+        mv_num = 2 / denom;
     }else if (encoder_context->codec == CODEC_HEVC) {
         if (vme_context->hevc_level >= 30*3) {
             mv_num = 16;
@@ -427,10 +438,10 @@ static VAStatus gen9_vme_constant_setup(VADriverContextP ctx,
 
     vme_state_message[31] = mv_num;
 
-    dri_bo_map(vme_context->gpe_context.dynamic_state.bo, 1);
-    assert(vme_context->gpe_context.dynamic_state.bo->virtual);
-    constant_buffer = (unsigned char *)vme_context->gpe_context.dynamic_state.bo->virtual +
-                                         vme_context->gpe_context.curbe_offset;
+    dri_bo_map(vme_context->gpe_context.curbe.bo, 1);
+    assert(vme_context->gpe_context.curbe.bo->virtual);
+    constant_buffer = (unsigned char *)vme_context->gpe_context.curbe.bo->virtual +
+                                         vme_context->gpe_context.curbe.offset;
 
     /* VME MV/Mb cost table is passed by using const buffer */
     /* Now it uses the fixed search path. So it is constructed directly
@@ -438,7 +449,7 @@ static VAStatus gen9_vme_constant_setup(VADriverContextP ctx,
      */
     memcpy(constant_buffer, (char *)vme_context->vme_state_message, 128);
 
-    dri_bo_unmap(vme_context->gpe_context.dynamic_state.bo);
+    dri_bo_unmap(vme_context->gpe_context.curbe.bo);
 
     return VA_STATUS_SUCCESS;
 }
@@ -603,6 +614,17 @@ gen9_vme_fill_vme_batchbuffer(VADriverContextP ctx,
     int mb_x = 0, mb_y = 0;
     int i, s;
     unsigned int *command_ptr;
+    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+    VAEncPictureParameterBufferH264 *pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
+    VAEncSliceParameterBufferH264 *slice_param = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[0]->buffer;
+    int qp;
+    int slice_type = intel_avc_enc_slice_type_fixup(slice_param->slice_type);
+    int qp_mb, qp_index;
+
+    if (encoder_context->rate_control_mode == VA_RC_CQP)
+        qp = pic_param->pic_init_qp + slice_param->slice_qp_delta;
+    else
+        qp = mfc_context->brc.qp_prime_y[encoder_context->layer.curr_frame_layer_id][slice_type];
 
     dri_bo_map(vme_context->vme_batchbuffer.bo, 1);
     command_ptr = vme_context->vme_batchbuffer.bo->virtual;
@@ -640,7 +662,7 @@ gen9_vme_fill_vme_batchbuffer(VADriverContextP ctx,
             if ((i == mb_width) && slice_mb_x) {
                 mb_intra_ub &= ~(INTRA_PRED_AVAIL_FLAG_D);
             }
-            *command_ptr++ = (CMD_MEDIA_OBJECT | (8 - 2));
+            *command_ptr++ = (CMD_MEDIA_OBJECT | (9 - 2));
             *command_ptr++ = kernel;
             *command_ptr++ = 0;
             *command_ptr++ = 0;
@@ -650,6 +672,13 @@ gen9_vme_fill_vme_batchbuffer(VADriverContextP ctx,
             /*inline data */
             *command_ptr++ = (mb_width << 16 | mb_y << 8 | mb_x);
             *command_ptr++ = ((encoder_context->quality_level << 24) | (1 << 16) | transform_8x8_mode_flag | (mb_intra_ub << 8));
+            /* qp occupies one byte */
+            if (vme_context->roi_enabled) {
+                qp_index = mb_y * mb_width + mb_x;
+                qp_mb = *(vme_context->qp_per_mb + qp_index);
+            } else
+                qp_mb = qp;
+            *command_ptr++ = qp_mb;
 
             *command_ptr++ = CMD_MEDIA_STATE_FLUSH;
             *command_ptr++ = 0;
@@ -710,7 +739,7 @@ static void gen9_vme_pipeline_programing(VADriverContextP ctx,
     }
 
     if ((pSliceParameter->slice_type == SLICE_TYPE_I) ||
-        (pSliceParameter->slice_type == SLICE_TYPE_I)) {
+        (pSliceParameter->slice_type == SLICE_TYPE_SI)) {
         kernel_shader = VME_INTRA_SHADER;
     } else if ((pSliceParameter->slice_type == SLICE_TYPE_P) ||
                (pSliceParameter->slice_type == SLICE_TYPE_SP)) {
@@ -739,11 +768,10 @@ static void gen9_vme_pipeline_programing(VADriverContextP ctx,
     gen9_gpe_pipeline_setup(ctx, &vme_context->gpe_context, batch);
     BEGIN_BATCH(batch, 3);
     OUT_BATCH(batch, MI_BATCH_BUFFER_START | (1 << 8) | (1 << 0));
-    OUT_RELOC(batch,
+    OUT_RELOC64(batch,
               vme_context->vme_batchbuffer.bo,
               I915_GEM_DOMAIN_COMMAND, 0,
               0);
-    OUT_BATCH(batch, 0);
     ADVANCE_BATCH(batch);
 
     gen9_gpe_pipeline_end(ctx, &vme_context->gpe_context, batch);
@@ -767,12 +795,14 @@ static VAStatus gen9_vme_prepare(VADriverContextP ctx,
     }
 
     intel_vme_update_mbmv_cost(ctx, encode_state, encoder_context);
+    intel_h264_initialize_mbmv_cost(ctx, encode_state, encoder_context);
+    intel_h264_enc_roi_config(ctx, encode_state, encoder_context);
 
     /*Setup all the memory object*/
     gen9_vme_surface_setup(ctx, encode_state, is_intra, encoder_context);
     gen9_vme_interface_setup(ctx, encode_state, encoder_context);
     //gen9_vme_vme_state_setup(ctx, encode_state, is_intra, encoder_context);
-    gen9_vme_constant_setup(ctx, encode_state, encoder_context);
+    gen9_vme_constant_setup(ctx, encode_state, encoder_context, (pSliceParameter->slice_type == SLICE_TYPE_B) ? 2 : 1);
 
     /*Programing media pipeline*/
     gen9_vme_pipeline_programing(ctx, encode_state, encoder_context);
@@ -1131,12 +1161,11 @@ gen9_vme_mpeg2_pipeline_programing(VADriverContextP ctx,
     gen9_gpe_pipeline_setup(ctx, &vme_context->gpe_context, batch);
     BEGIN_BATCH(batch, 4);
     OUT_BATCH(batch, MI_BATCH_BUFFER_START | (1 << 8) | (1 << 0));
-    OUT_RELOC(batch,
+    OUT_RELOC64(batch,
               vme_context->vme_batchbuffer.bo,
               I915_GEM_DOMAIN_COMMAND, 0,
               0);
     OUT_BATCH(batch, 0);
-    OUT_BATCH(batch, 0);
     ADVANCE_BATCH(batch);
 
     gen9_gpe_pipeline_end(ctx, &vme_context->gpe_context, batch);
@@ -1164,7 +1193,7 @@ gen9_vme_mpeg2_prepare(VADriverContextP ctx,
     gen9_vme_interface_setup(ctx, encode_state, encoder_context);
     //gen9_vme_vme_state_setup(ctx, encode_state, slice_param->is_intra_slice, encoder_context);
     intel_vme_mpeg2_state_setup(ctx, encode_state, encoder_context);
-    gen9_vme_constant_setup(ctx, encode_state, encoder_context);
+    gen9_vme_constant_setup(ctx, encode_state, encoder_context, 1);
 
     /*Programing media pipeline*/
     gen9_vme_mpeg2_pipeline_programing(ctx, encode_state, slice_param->is_intra_slice, encoder_context);
@@ -1272,12 +1301,11 @@ gen9_vme_vp8_pipeline_programing(VADriverContextP ctx,
     gen9_gpe_pipeline_setup(ctx, &vme_context->gpe_context, batch);
     BEGIN_BATCH(batch, 4);
     OUT_BATCH(batch, MI_BATCH_BUFFER_START | (1 << 8) | (1 << 0));
-    OUT_RELOC(batch,
+    OUT_RELOC64(batch,
               vme_context->vme_batchbuffer.bo,
               I915_GEM_DOMAIN_COMMAND, 0,
               0);
     OUT_BATCH(batch, 0);
-    OUT_BATCH(batch, 0);
     ADVANCE_BATCH(batch);
 
     gen9_gpe_pipeline_end(ctx, &vme_context->gpe_context, batch);
@@ -1299,7 +1327,7 @@ static VAStatus gen9_vme_vp8_prepare(VADriverContextP ctx,
     /*Setup all the memory object*/
     gen9_vme_vp8_surface_setup(ctx, encode_state, is_intra, encoder_context);
     gen9_vme_interface_setup(ctx, encode_state, encoder_context);
-    gen9_vme_constant_setup(ctx, encode_state, encoder_context);
+    gen9_vme_constant_setup(ctx, encode_state, encoder_context, 1);
 
     /*Programing media pipeline*/
     gen9_vme_vp8_pipeline_programing(ctx, encode_state, is_intra, encoder_context);
@@ -1392,10 +1420,19 @@ gen9_vme_hevc_surface_setup(VADriverContextP ctx,
                        struct intel_encoder_context *encoder_context)
 {
     struct object_surface *obj_surface;
+    VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
+    GenHevcSurface *hevc_encoder_surface = NULL;
 
     /*Setup surfaces state*/
     /* current picture for encoding */
     obj_surface = encode_state->input_yuv_object;
+
+    if((pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8 > 0)
+        || (pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8 > 0)) {
+        hevc_encoder_surface = (GenHevcSurface *) obj_surface->private_data;
+        assert(hevc_encoder_surface);
+        obj_surface = hevc_encoder_surface->nv12_surface_obj;
+    }
     gen9_vme_source_surface_state(ctx, 0, obj_surface, encoder_context);
     gen9_vme_media_source_surface_state(ctx, 4, obj_surface, encoder_context);
     gen9_vme_media_chroma_source_surface_state(ctx, 6, obj_surface, encoder_context);
@@ -1697,11 +1734,10 @@ static void gen9_vme_hevc_pipeline_programing(VADriverContextP ctx,
     gen9_gpe_pipeline_setup(ctx, &vme_context->gpe_context, batch);
     BEGIN_BATCH(batch, 3);
     OUT_BATCH(batch, MI_BATCH_BUFFER_START | (1 << 8) | (1 << 0));
-    OUT_RELOC(batch,
+    OUT_RELOC64(batch,
               vme_context->vme_batchbuffer.bo,
               I915_GEM_DOMAIN_COMMAND, 0,
               0);
-    OUT_BATCH(batch, 0);
     ADVANCE_BATCH(batch);
 
     gen9_gpe_pipeline_end(ctx, &vme_context->gpe_context, batch);
@@ -1709,6 +1745,150 @@ static void gen9_vme_hevc_pipeline_programing(VADriverContextP ctx,
     intel_batchbuffer_end_atomic(batch);
 }
 
+static VAStatus gen9_intel_init_hevc_surface(VADriverContextP ctx,
+                            struct intel_encoder_context *encoder_context,
+                            struct encode_state *encode_state,
+                            struct object_surface *input_obj_surface)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
+    VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
+    GenHevcSurface *hevc_encoder_surface;
+    struct i965_surface src_surface, dst_surface;
+    struct object_surface *obj_surface;
+    VARectangle rect;
+    VAStatus status;
+
+    uint32_t size;
+
+    obj_surface = input_obj_surface;
+    assert(obj_surface && obj_surface->bo);
+
+    if (obj_surface->private_data == NULL) {
+
+        if (mfc_context->pic_size.ctb_size == 16)
+            size = ((pSequenceParameter->pic_width_in_luma_samples + 63) >> 6) *
+            ((pSequenceParameter->pic_height_in_luma_samples + 15) >> 4);
+        else
+            size = ((pSequenceParameter->pic_width_in_luma_samples + 31) >> 5) *
+            ((pSequenceParameter->pic_height_in_luma_samples + 31) >> 5);
+        size <<= 6; /* in unit of 64bytes */
+
+        hevc_encoder_surface = calloc(sizeof(GenHevcSurface), 1);
+
+        assert(hevc_encoder_surface);
+        hevc_encoder_surface->motion_vector_temporal_bo =
+            dri_bo_alloc(i965->intel.bufmgr,
+            "motion vector temporal buffer",
+            size,
+            0x1000);
+        assert(hevc_encoder_surface->motion_vector_temporal_bo);
+
+        hevc_encoder_surface->ctx = ctx;
+        hevc_encoder_surface->nv12_surface_obj = NULL;
+        hevc_encoder_surface->nv12_surface_id = VA_INVALID_SURFACE;
+        hevc_encoder_surface->has_p010_to_nv12_done = 0;
+
+        obj_surface->private_data = (void *)hevc_encoder_surface;
+        obj_surface->free_private_data = (void *)gen_free_hevc_surface;
+    }
+
+    hevc_encoder_surface = (GenHevcSurface *) obj_surface->private_data;
+
+    if(!hevc_encoder_surface->has_p010_to_nv12_done && obj_surface->fourcc == VA_FOURCC_P010)
+    {
+        // convert input
+        rect.x = 0;
+        rect.y = 0;
+        rect.width = obj_surface->orig_width;
+        rect.height = obj_surface->orig_height;
+
+        src_surface.base = (struct object_base *)obj_surface;
+        src_surface.type = I965_SURFACE_TYPE_SURFACE;
+        src_surface.flags = I965_SURFACE_FLAG_FRAME;
+
+        if(SURFACE(hevc_encoder_surface->nv12_surface_id) == NULL)
+        {
+            status = i965_CreateSurfaces(ctx,
+                obj_surface->orig_width,
+                obj_surface->orig_height,
+                VA_RT_FORMAT_YUV420,
+                1,
+                &hevc_encoder_surface->nv12_surface_id);
+            assert(status == VA_STATUS_SUCCESS);
+
+            if (status != VA_STATUS_SUCCESS)
+                return status;
+        }
+
+        obj_surface = SURFACE(hevc_encoder_surface->nv12_surface_id);
+        hevc_encoder_surface->nv12_surface_obj = obj_surface;
+        assert(obj_surface);
+        i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
+
+        dst_surface.base = (struct object_base *)obj_surface;
+        dst_surface.type = I965_SURFACE_TYPE_SURFACE;
+        dst_surface.flags = I965_SURFACE_FLAG_FRAME;
+
+        status = i965_image_processing(ctx,
+            &src_surface,
+            &rect,
+            &dst_surface,
+            &rect);
+        assert(status == VA_STATUS_SUCCESS);
+        hevc_encoder_surface->has_p010_to_nv12_done = 1;
+    }
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus gen9_intel_hevc_input_check(VADriverContextP ctx,
+                            struct encode_state *encode_state,
+                            struct intel_encoder_context *encoder_context)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
+    struct object_surface *obj_surface;
+    GenHevcSurface *hevc_encoder_surface = NULL;
+    int i;
+    int fourcc;
+
+    obj_surface = SURFACE(encode_state->current_render_target);
+    assert(obj_surface && obj_surface->bo);
+    hevc_encoder_surface = (GenHevcSurface *) obj_surface->private_data;
+    if(hevc_encoder_surface)
+        hevc_encoder_surface->has_p010_to_nv12_done = 0;
+    gen9_intel_init_hevc_surface(ctx,encoder_context,encode_state,obj_surface);
+
+    fourcc = obj_surface->fourcc;
+    /* Setup current frame and current direct mv buffer*/
+    obj_surface = encode_state->reconstructed_object;
+    if(fourcc == VA_FOURCC_P010)
+        i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_P010, SUBSAMPLE_YUV420);
+    else
+        i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
+    hevc_encoder_surface = NULL;
+    hevc_encoder_surface = (GenHevcSurface *) obj_surface->private_data;
+    if(hevc_encoder_surface)
+        hevc_encoder_surface->has_p010_to_nv12_done = 1;
+    gen9_intel_init_hevc_surface(ctx,encoder_context,encode_state,obj_surface);
+
+    /* Setup reference frames and direct mv buffers*/
+    for (i = 0; i < MAX_HCP_REFERENCE_SURFACES; i++) {
+        obj_surface = encode_state->reference_objects[i];
+
+        if (obj_surface && obj_surface->bo) {
+            mfc_context->reference_surfaces[i].bo = obj_surface->bo;
+            dri_bo_reference(obj_surface->bo);
+
+            gen9_intel_init_hevc_surface(ctx,encoder_context,encode_state,obj_surface);
+        } else {
+            break;
+        }
+    }
+
+    return VA_STATUS_SUCCESS;
+}
+
 static VAStatus gen9_vme_hevc_prepare(VADriverContextP ctx,
                                  struct encode_state *encode_state,
                                  struct intel_encoder_context *encoder_context)
@@ -1725,13 +1905,16 @@ static VAStatus gen9_vme_hevc_prepare(VADriverContextP ctx,
         vme_context->hevc_level = pSequenceParameter->general_level_idc;
     }
 
+    //internal input check for main10
+    gen9_intel_hevc_input_check(ctx,encode_state,encoder_context);
+
     intel_vme_hevc_update_mbmv_cost(ctx, encode_state, encoder_context);
 
     /*Setup all the memory object*/
     gen9_vme_hevc_surface_setup(ctx, encode_state, is_intra, encoder_context);
     gen9_vme_interface_setup(ctx, encode_state, encoder_context);
     //gen9_vme_vme_state_setup(ctx, encode_state, is_intra, encoder_context);
-    gen9_vme_constant_setup(ctx, encode_state, encoder_context);
+    gen9_vme_constant_setup(ctx, encode_state, encoder_context, 1);
 
     /*Programing media pipeline*/
     gen9_vme_hevc_pipeline_programing(ctx, encode_state, encoder_context);
@@ -1771,20 +1954,43 @@ gen9_vme_context_destroy(void *context)
     dri_bo_unreference(vme_context->vme_batchbuffer.bo);
     vme_context->vme_batchbuffer.bo = NULL;
 
-    if (vme_context->vme_state_message) {
-        free(vme_context->vme_state_message);
-        vme_context->vme_state_message = NULL;
-    }
+    free(vme_context->vme_state_message);
+    vme_context->vme_state_message = NULL;
+
+    dri_bo_unreference(vme_context->i_qp_cost_table);
+    vme_context->i_qp_cost_table = NULL;
+
+    dri_bo_unreference(vme_context->p_qp_cost_table);
+    vme_context->p_qp_cost_table = NULL;
+
+    dri_bo_unreference(vme_context->b_qp_cost_table);
+    vme_context->b_qp_cost_table = NULL;
+
+    free(vme_context->qp_per_mb);
+    vme_context->qp_per_mb = NULL;
 
     free(vme_context);
 }
 
 Bool gen9_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context)
 {
-    struct gen6_vme_context *vme_context = calloc(1, sizeof(struct gen6_vme_context));
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct gen6_vme_context *vme_context;
     struct i965_kernel *vme_kernel_list = NULL;
     int i965_kernel_num;
 
+    if (encoder_context->low_power_mode || encoder_context->codec == CODEC_JPEG) {
+        encoder_context->vme_context = NULL;
+        encoder_context->vme_pipeline = NULL;
+        encoder_context->vme_context_destroy = NULL;
+
+        return True;
+    } else if (encoder_context->codec == CODEC_VP9) {
+        return gen9_vp9_vme_context_init(ctx, encoder_context);
+    }
+
+    vme_context = calloc(1, sizeof(struct gen6_vme_context));
+
     switch (encoder_context->codec) {
     case CODEC_H264:
     case CODEC_H264_MVC:
@@ -1817,15 +2023,23 @@ Bool gen9_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *e
 
         break;
     }
+
+    assert(vme_context);
     vme_context->vme_kernel_sum = i965_kernel_num;
     vme_context->gpe_context.surface_state_binding_table.length = (SURFACE_STATE_PADDED_SIZE + sizeof(unsigned int)) * MAX_MEDIA_SURFACES_GEN6;
 
-    vme_context->gpe_context.idrt_size = sizeof(struct gen8_interface_descriptor_data) * MAX_INTERFACE_DESC_GEN6;
-    vme_context->gpe_context.curbe_size = CURBE_TOTAL_DATA_LENGTH;
-    vme_context->gpe_context.sampler_size = 0;
+    vme_context->gpe_context.idrt.entry_size = ALIGN(sizeof(struct gen8_interface_descriptor_data), 64);
+    vme_context->gpe_context.idrt.max_entries = MAX_INTERFACE_DESC_GEN6;
+    vme_context->gpe_context.curbe.length = CURBE_TOTAL_DATA_LENGTH;
+    vme_context->gpe_context.sampler.entry_size = 0;
+    vme_context->gpe_context.sampler.max_entries = 0;
 
+    if (i965->intel.eu_total > 0) {
+        vme_context->gpe_context.vfe_state.max_num_threads = 6 *
+                              i965->intel.eu_total;
+    } else
+        vme_context->gpe_context.vfe_state.max_num_threads = 60 - 1;
 
-    vme_context->gpe_context.vfe_state.max_num_threads = 60 - 1;
     vme_context->gpe_context.vfe_state.num_urb_entries = 64;
     vme_context->gpe_context.vfe_state.gpgpu_mode = 0;
     vme_context->gpe_context.vfe_state.urb_entry_size = 16;