OSDN Git Service

Merge branch 'master' into staging
[android-x86/hardware-intel-common-vaapi.git] / src / i965_drv_video.c
old mode 100644 (file)
new mode 100755 (executable)
index 297ab7c..deee9c8
 #define IMAGE_ID_OFFSET                 0x0a000000
 #define SUBPIC_ID_OFFSET                0x10000000
 
-#define HAS_MPEG2(ctx)  (IS_G4X((ctx)->intel.device_id) ||      \
-                         IS_IRONLAKE((ctx)->intel.device_id) || \
-                         ((IS_GEN6((ctx)->intel.device_id) ||   \
-                           IS_GEN7((ctx)->intel.device_id)) &&  \
-                          (ctx)->intel.has_bsd))
-
-#define HAS_H264(ctx)   ((IS_GEN7((ctx)->intel.device_id) ||            \
-                          IS_GEN6((ctx)->intel.device_id) ||            \
-                          IS_IRONLAKE((ctx)->intel.device_id)) &&       \
-                         (ctx)->intel.has_bsd)
-
-#define HAS_VC1(ctx)    ((IS_GEN7((ctx)->intel.device_id) ||    \
-                          IS_GEN6((ctx)->intel.device_id)) &&   \
-                         (ctx)->intel.has_bsd)
-
-#define HAS_TILED_SURFACE(ctx) ((IS_GEN7((ctx)->intel.device_id) ||     \
-                                 IS_GEN6((ctx)->intel.device_id)) &&    \
-                                (ctx)->render_state.interleaved_uv)
-
-#define HAS_ENCODER(ctx)        ((IS_GEN7((ctx)->intel.device_id) ||    \
-                                  IS_GEN6((ctx)->intel.device_id)) &&   \
+#define HAS_MPEG2_DECODING(ctx)  ((ctx)->codec_info->has_mpeg2_decoding && \
+                                  (ctx)->intel.has_bsd)
+
+#define HAS_MPEG2_ENCODING(ctx)  ((ctx)->codec_info->has_mpeg2_encoding && \
+                                  (ctx)->intel.has_bsd)
+
+#define HAS_H264_DECODING(ctx)  ((ctx)->codec_info->has_h264_decoding && \
+                                 (ctx)->intel.has_bsd)
+
+#define HAS_H264_ENCODING(ctx)  ((ctx)->codec_info->has_h264_encoding && \
+                                 (ctx)->intel.has_bsd)
+
+#define HAS_VC1_DECODING(ctx)   ((ctx)->codec_info->has_vc1_decoding && \
+                                 (ctx)->intel.has_bsd)
+
+#define HAS_JPEG_DECODING(ctx)  ((ctx)->codec_info->has_jpeg_decoding && \
                                  (ctx)->intel.has_bsd)
 
-#define HAS_JPEG(ctx)   (IS_GEN7((ctx)->intel.device_id) &&     \
-                         (ctx)->intel.has_bsd)
+#define HAS_VPP(ctx)    ((ctx)->codec_info->has_vpp)
 
-#define HAS_ACCELERATED_GETIMAGE(ctx)   (IS_GEN6((ctx)->intel.device_id) ||     \
-                                         IS_GEN7((ctx)->intel.device_id))
+#define HAS_ACCELERATED_GETIMAGE(ctx)   ((ctx)->codec_info->has_accelerated_getimage)
 
-#define HAS_ACCELERATED_PUTIMAGE(ctx)   HAS_VPP(ctx)
+#define HAS_ACCELERATED_PUTIMAGE(ctx)   ((ctx)->codec_info->has_accelerated_putimage)
+
+#define HAS_TILED_SURFACE(ctx) ((ctx)->codec_info->has_tiled_surface)
+
+static int get_sampling_from_fourcc(unsigned int fourcc);
 
-#if VA_CHECK_VERSION(0,33,0)
 /* Check whether we are rendering to X11 (VA/X11 or VA/GLX API) */
 #define IS_VA_X11(ctx) \
     (((ctx)->display_type & VA_DISPLAY_MAJOR_MASK) == VA_DISPLAY_X11)
 /* Check whether we are rendering to Wayland */
 #define IS_VA_WAYLAND(ctx) \
     (((ctx)->display_type & VA_DISPLAY_MAJOR_MASK) == VA_DISPLAY_WAYLAND)
-#else
-/* Previous VA-API versions only supported VA/X11 (and VA/GLX) API */
-#define IS_VA_X11(ctx)          1
-#define IS_VA_WAYLAND(ctx)      0
-#endif
 
 enum {
     I965_SURFACETYPE_RGBA = 1,
@@ -126,6 +117,14 @@ i965_image_formats_map[I965_MAX_IMAGE_FORMATS + 1] = {
       { VA_FOURCC('I','4','2','0'), VA_LSB_FIRST, 12, } },
     { I965_SURFACETYPE_YUV,
       { VA_FOURCC('N','V','1','2'), VA_LSB_FIRST, 12, } },
+    { I965_SURFACETYPE_YUV,
+      { VA_FOURCC('Y','U','Y','2'), VA_LSB_FIRST, 16, } },
+    { I965_SURFACETYPE_YUV,
+      { VA_FOURCC('U','Y','V','Y'), VA_LSB_FIRST, 16, } },
+    { I965_SURFACETYPE_RGBA,
+      { VA_FOURCC('R','G','B','X'), VA_LSB_FIRST, 32, 24, 0x000000ff, 0x0000ff00, 0x00ff0000 } },
+    { I965_SURFACETYPE_RGBA,
+      { VA_FOURCC('B','G','R','X'), VA_LSB_FIRST, 32, 24, 0x00ff0000, 0x0000ff00, 0x000000ff } },
 };
 
 /* List of supported subpicture formats */
@@ -182,46 +181,134 @@ get_subpic_format(const VAImageFormat *va_format)
     return NULL;
 }
 
-extern struct hw_context *g4x_dec_hw_context_init(VADriverContextP, VAProfile);
+extern struct hw_context *i965_proc_context_init(VADriverContextP, struct object_config *);
+extern struct hw_context *g4x_dec_hw_context_init(VADriverContextP, struct object_config *);
 static struct hw_codec_info g4x_hw_codec_info = {
     .dec_hw_context_init = g4x_dec_hw_context_init,
     .enc_hw_context_init = NULL,
+    .proc_hw_context_init = NULL,
     .max_width = 2048,
     .max_height = 2048,
+
+    .has_mpeg2_decoding = 1,
 };
 
-extern struct hw_context *ironlake_dec_hw_context_init(VADriverContextP, VAProfile);
+extern struct hw_context *ironlake_dec_hw_context_init(VADriverContextP, struct object_config *);
 static struct hw_codec_info ironlake_hw_codec_info = {
     .dec_hw_context_init = ironlake_dec_hw_context_init,
     .enc_hw_context_init = NULL,
+    .proc_hw_context_init = i965_proc_context_init,
     .max_width = 2048,
     .max_height = 2048,
+
+    .has_mpeg2_decoding = 1,
+    .has_h264_decoding = 1,
+    .has_vpp = 1,
+    .has_accelerated_putimage = 1,
 };
 
-extern struct hw_context *gen6_dec_hw_context_init(VADriverContextP, VAProfile);
-extern struct hw_context *gen6_enc_hw_context_init(VADriverContextP, VAProfile);
+extern struct hw_context *gen6_dec_hw_context_init(VADriverContextP, struct object_config *);
+extern struct hw_context *gen6_enc_hw_context_init(VADriverContextP, struct object_config *);
 static struct hw_codec_info gen6_hw_codec_info = {
     .dec_hw_context_init = gen6_dec_hw_context_init,
     .enc_hw_context_init = gen6_enc_hw_context_init,
+    .proc_hw_context_init = i965_proc_context_init,
     .max_width = 2048,
     .max_height = 2048,
+
+    .has_mpeg2_decoding = 1,
+    .has_mpeg2_encoding = 1,
+    .has_h264_decoding = 1,
+    .has_h264_encoding = 1,
+    .has_vc1_decoding = 1,
+    .has_vpp = 1,
+    .has_accelerated_getimage = 1,
+    .has_accelerated_putimage = 1,
+    .has_tiled_surface = 1,
 };
 
-extern struct hw_context *gen7_dec_hw_context_init(VADriverContextP, VAProfile);
+extern struct hw_context *gen7_dec_hw_context_init(VADriverContextP, struct object_config *);
+extern struct hw_context *gen7_enc_hw_context_init(VADriverContextP, struct object_config *);
 static struct hw_codec_info gen7_hw_codec_info = {
     .dec_hw_context_init = gen7_dec_hw_context_init,
-    .enc_hw_context_init = gen6_enc_hw_context_init,
+    .enc_hw_context_init = gen7_enc_hw_context_init,
+    .proc_hw_context_init = i965_proc_context_init,
     .max_width = 4096,
     .max_height = 4096,
+
+    .has_mpeg2_decoding = 1,
+    .has_mpeg2_encoding = 1,
+    .has_h264_decoding = 1,
+    .has_h264_encoding = 1,
+    .has_vc1_decoding = 1,
+    .has_jpeg_decoding = 1,
+    .has_vpp = 1,
+    .has_accelerated_getimage = 1,
+    .has_accelerated_putimage = 1,
+    .has_tiled_surface = 1,
 };
 
+extern struct hw_context *gen75_proc_context_init(VADriverContextP, struct object_config *);
 static struct hw_codec_info gen75_hw_codec_info = {
     .dec_hw_context_init = gen75_dec_hw_context_init,
     .enc_hw_context_init = gen75_enc_hw_context_init,
+    .proc_hw_context_init = gen75_proc_context_init,
     .max_width = 4096,
     .max_height = 4096,
+
+    .has_mpeg2_decoding = 1,
+    .has_mpeg2_encoding = 1,
+    .has_h264_decoding = 1,
+    .has_h264_encoding = 1,
+    .has_vc1_decoding = 1,
+    .has_jpeg_decoding = 1,
+    .has_vpp = 1,
+    .has_accelerated_getimage = 1,
+    .has_accelerated_putimage = 1,
+    .has_tiled_surface = 1,
 };
 
+#define I965_PACKED_HEADER_BASE         0
+#define I965_PACKED_MISC_HEADER_BASE    3
+
+int
+va_enc_packed_type_to_idx(int packed_type)
+{
+    int idx = 0;
+
+    if (packed_type & VAEncPackedHeaderMiscMask) {
+        idx = I965_PACKED_MISC_HEADER_BASE;
+        packed_type = (~VAEncPackedHeaderMiscMask & packed_type);
+        assert(packed_type > 0);
+        idx += (packed_type - 1);
+    } else {
+        idx = I965_PACKED_HEADER_BASE;
+
+        switch (packed_type) {
+        case VAEncPackedHeaderSequence:
+            idx = I965_PACKED_HEADER_BASE + 0;
+            break;
+
+        case VAEncPackedHeaderPicture:
+            idx = I965_PACKED_HEADER_BASE + 1;
+            break;
+
+        case VAEncPackedHeaderSlice:
+            idx = I965_PACKED_HEADER_BASE + 2;
+            break;
+
+        default:
+            /* Should not get here */
+            assert(0);
+            break;
+        }
+    }
+
+    assert(idx < 4);
+    return idx;
+}
+
+
 VAStatus 
 i965_QueryConfigProfiles(VADriverContextP ctx,
                          VAProfile *profile_list,       /* out */
@@ -230,28 +317,32 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
     struct i965_driver_data * const i965 = i965_driver_data(ctx);
     int i = 0;
 
-    if (HAS_MPEG2(i965)) {
+    if (HAS_MPEG2_DECODING(i965) ||
+        HAS_MPEG2_ENCODING(i965)) {
         profile_list[i++] = VAProfileMPEG2Simple;
         profile_list[i++] = VAProfileMPEG2Main;
     }
 
-    if (HAS_H264(i965)) {
+    if (HAS_H264_DECODING(i965) ||
+        HAS_H264_ENCODING(i965)) {
         profile_list[i++] = VAProfileH264Baseline;
         profile_list[i++] = VAProfileH264Main;
         profile_list[i++] = VAProfileH264High;
     }
 
-    if (HAS_VC1(i965)) {
+    if (HAS_VC1_DECODING(i965)) {
         profile_list[i++] = VAProfileVC1Simple;
         profile_list[i++] = VAProfileVC1Main;
         profile_list[i++] = VAProfileVC1Advanced;
     }
 
-#ifdef HAVE_VA_JPEG_DECODE
-    if (HAS_JPEG(i965)) {
+    if (HAS_VPP(i965)) {
+        profile_list[i++] = VAProfileNone;
+    }
+
+    if (HAS_JPEG_DECODING(i965)) {
         profile_list[i++] = VAProfileJPEGBaseline;
     }
-#endif
 
     /* If the assert fails then I965_MAX_PROFILES needs to be bigger */
     assert(i <= I965_MAX_PROFILES);
@@ -272,17 +363,21 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
     switch (profile) {
     case VAProfileMPEG2Simple:
     case VAProfileMPEG2Main:
-        if (HAS_MPEG2(i965))
+        if (HAS_MPEG2_DECODING(i965))
             entrypoint_list[n++] = VAEntrypointVLD;
+
+        if (HAS_MPEG2_ENCODING(i965))
+            entrypoint_list[n++] = VAEntrypointEncSlice;
+
         break;
 
     case VAProfileH264Baseline:
     case VAProfileH264Main:
     case VAProfileH264High:
-        if (HAS_H264(i965))
+        if (HAS_H264_DECODING(i965))
             entrypoint_list[n++] = VAEntrypointVLD;
         
-        if (HAS_ENCODER(i965))
+        if (HAS_H264_ENCODING(i965))
             entrypoint_list[n++] = VAEntrypointEncSlice;
 
         break;
@@ -290,12 +385,17 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
     case VAProfileVC1Simple:
     case VAProfileVC1Main:
     case VAProfileVC1Advanced:
-        if (HAS_VC1(i965))
+        if (HAS_VC1_DECODING(i965))
             entrypoint_list[n++] = VAEntrypointVLD;
         break;
 
+    case VAProfileNone:
+        if (HAS_VPP(i965))
+            entrypoint_list[n++] = VAEntrypointVideoProc;
+        break;
+
     case VAProfileJPEGBaseline:
-        if (HAS_JPEG(i965))
+        if (HAS_JPEG_DECODING(i965))
             entrypoint_list[n++] = VAEntrypointVLD;
         break;
 
@@ -327,8 +427,16 @@ i965_GetConfigAttributes(VADriverContextP ctx,
             break;
 
         case VAConfigAttribRateControl:
-            attrib_list[i].value = VA_RC_VBR;
-            break;
+            if (entrypoint == VAEntrypointEncSlice) {
+                attrib_list[i].value = VA_RC_CBR | VA_RC_CQP;
+                break;
+            }
+
+        case VAConfigAttribEncPackedHeaders:
+            if (entrypoint == VAEntrypointEncSlice) {
+                attrib_list[i].value = VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE | VA_ENC_PACKED_HEADER_MISC;
+                break;
+            }
 
         default:
             /* Do nothing */
@@ -352,7 +460,7 @@ i965_update_attribute(struct object_config *obj_config, VAConfigAttrib *attrib)
     int i;
 
     /* Check existing attrbiutes */
-    for (i = 0; obj_config->num_attribs < i; i++) {
+    for (i = 0; i < obj_config->num_attribs; i++) {
         if (obj_config->attrib_list[i].type == attrib->type) {
             /* Update existing attribute */
             obj_config->attrib_list[i].value = attrib->value;
@@ -389,7 +497,8 @@ i965_CreateConfig(VADriverContextP ctx,
     switch (profile) {
     case VAProfileMPEG2Simple:
     case VAProfileMPEG2Main:
-        if (HAS_MPEG2(i965) && VAEntrypointVLD == entrypoint) {
+        if ((HAS_MPEG2_DECODING(i965) && VAEntrypointVLD == entrypoint) ||
+            (HAS_MPEG2_ENCODING(i965) && VAEntrypointEncSlice == entrypoint)) {
             vaStatus = VA_STATUS_SUCCESS;
         } else {
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -399,8 +508,8 @@ i965_CreateConfig(VADriverContextP ctx,
     case VAProfileH264Baseline:
     case VAProfileH264Main:
     case VAProfileH264High:
-        if ((HAS_H264(i965) && VAEntrypointVLD == entrypoint) ||
-            (HAS_ENCODER(i965) && VAEntrypointEncSlice == entrypoint)) {
+        if ((HAS_H264_DECODING(i965) && VAEntrypointVLD == entrypoint) ||
+            (HAS_H264_ENCODING(i965) && VAEntrypointEncSlice == entrypoint)) {
             vaStatus = VA_STATUS_SUCCESS;
         } else {
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -411,7 +520,16 @@ i965_CreateConfig(VADriverContextP ctx,
     case VAProfileVC1Simple:
     case VAProfileVC1Main:
     case VAProfileVC1Advanced:
-        if (HAS_VC1(i965) && VAEntrypointVLD == entrypoint) {
+        if (HAS_VC1_DECODING(i965) && VAEntrypointVLD == entrypoint) {
+            vaStatus = VA_STATUS_SUCCESS;
+        } else {
+            vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
+        }
+
+        break;
+
+    case VAProfileNone:
+        if (HAS_VPP(i965) && VAEntrypointVideoProc == entrypoint) {
             vaStatus = VA_STATUS_SUCCESS;
         } else {
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -420,7 +538,7 @@ i965_CreateConfig(VADriverContextP ctx,
         break;
 
     case VAProfileJPEGBaseline:
-        if (HAS_JPEG(i965) && VAEntrypointVLD == entrypoint) {
+        if (HAS_JPEG_DECODING(i965) && VAEntrypointVLD == entrypoint) {
             vaStatus = VA_STATUS_SUCCESS;
         } else {
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -525,20 +643,37 @@ i965_destroy_surface(struct object_heap *heap, struct object_base *obj)
     object_heap_free(heap, obj);
 }
 
-VAStatus 
-i965_CreateSurfaces(VADriverContextP ctx,
-                    int width,
-                    int height,
-                    int format,
-                    int num_surfaces,
-                    VASurfaceID *surfaces)      /* out */
+static VAStatus
+i965_CreateSurfaces2(
+    VADriverContextP    ctx,
+    unsigned int        format,
+    unsigned int        width,
+    unsigned int        height,
+    VASurfaceID        *surfaces,
+    unsigned int        num_surfaces,
+    VASurfaceAttrib    *attrib_list,
+    unsigned int        num_attribs
+    )
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     int i,j;
     VAStatus vaStatus = VA_STATUS_SUCCESS;
+    int expected_fourcc = 0;
+
+    for (i = 0; i < num_attribs && attrib_list; i++) {
+        if ((attrib_list[i].type == VASurfaceAttribPixelFormat) &&
+            (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
+            assert(attrib_list[i].value.type == VAGenericValueTypeInteger);
+            expected_fourcc = attrib_list[i].value.value.i;
+            break;
+        }
+    }
 
-    /* We only support one format */
-    if (VA_RT_FORMAT_YUV420 != format) {
+    /* support 420 & 422 & RGB32 format, 422 and RGB32 are only used
+     * for post-processing (including color conversion) */
+    if (VA_RT_FORMAT_YUV420 != format &&
+        VA_RT_FORMAT_YUV422 != format &&
+        VA_RT_FORMAT_RGB32  != format) {
         return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
     }
 
@@ -556,19 +691,14 @@ i965_CreateSurfaces(VADriverContextP ctx,
         obj_surface->orig_width = width;
         obj_surface->orig_height = height;
 
-       if (IS_G4X(i965->intel.device_id) || IS_IRONLAKE(i965->intel.device_id)) {
-               obj_surface->width = ALIGN(width, 16);
-               obj_surface->height = ALIGN(height, 16);
-       } else {
-               obj_surface->width = ALIGN(width, 128);
-               obj_surface->height = ALIGN(height, 32);
-       }
-
         obj_surface->subpic_render_idx = 0;
         for(j = 0; j < I965_MAX_SUBPIC_SUM; j++){
            obj_surface->subpic[j] = VA_INVALID_ID;
+           obj_surface->obj_subpic[j] = NULL;
         }
 
+        obj_surface->width = ALIGN(width, 16);
+        obj_surface->height = ALIGN(height, 16);
         obj_surface->flags = SURFACE_REFERENCED;
         obj_surface->fourcc = 0;
         obj_surface->bo = NULL;
@@ -576,6 +706,31 @@ i965_CreateSurfaces(VADriverContextP ctx,
         obj_surface->private_data = NULL;
         obj_surface->free_private_data = NULL;
         obj_surface->subsampling = SUBSAMPLE_YUV420;
+
+        if (expected_fourcc) {
+            int tiling = HAS_TILED_SURFACE(i965);
+
+            if (expected_fourcc != VA_FOURCC('N', 'V', '1', '2') &&
+                expected_fourcc != VA_FOURCC('R', 'G', 'B', 'X') &&
+                expected_fourcc != VA_FOURCC('R', 'G', 'B', 'A') )
+                tiling = 0;
+            // todo, should we disable tiling for 422 format?
+                       
+            if (VA_RT_FORMAT_YUV420 == format) {
+                obj_surface->subsampling = SUBSAMPLE_YUV420;
+            }
+            else if (VA_RT_FORMAT_YUV422 == format) {
+                obj_surface->subsampling = SUBSAMPLE_YUV422H;
+            }
+            else if (VA_RT_FORMAT_RGB32 == format) {
+                obj_surface->subsampling = SUBSAMPLE_RGBX;
+            }
+             else {
+                assert(0);
+            }
+
+            i965_check_alloc_surface_bo(ctx, obj_surface, tiling, expected_fourcc, obj_surface->subsampling);
+        }
     }
 
     /* Error recovery */
@@ -594,6 +749,24 @@ i965_CreateSurfaces(VADriverContextP ctx,
 }
 
 VAStatus 
+i965_CreateSurfaces(VADriverContextP ctx,
+                    int width,
+                    int height,
+                    int format,
+                    int num_surfaces,
+                    VASurfaceID *surfaces)      /* out */
+{
+    return i965_CreateSurfaces2(ctx,
+                                format,
+                                width,
+                                height,
+                                surfaces,
+                                num_surfaces,
+                                NULL,
+                                0);
+}
+
+VAStatus 
 i965_DestroySurfaces(VADriverContextP ctx,
                      VASurfaceID *surface_list,
                      int num_surfaces)
@@ -630,20 +803,58 @@ i965_QueryImageFormats(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-VAStatus 
-i965_PutImage(VADriverContextP ctx,
-              VASurfaceID surface,
-              VAImageID image,
-              int src_x,
-              int src_y,
-              unsigned int src_width,
-              unsigned int src_height,
-              int dest_x,
-              int dest_y,
-              unsigned int dest_width,
-              unsigned int dest_height)
+/*
+ * Guess the format when the usage of a VA surface is unknown
+ * 1. Without a valid context: YV12
+ * 2. The current context is valid:
+ *    a) always NV12 on GEN6 and later
+ *    b) I420 for MPEG-2 and NV12 for other codec on GEN4 & GEN5
+ */
+static void
+i965_guess_surface_format(VADriverContextP ctx,
+                          VASurfaceID surface,
+                          unsigned int *fourcc,
+                          unsigned int *is_tiled)
 {
-    return VA_STATUS_SUCCESS;
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_context *obj_context = NULL;
+    struct object_config *obj_config = NULL;
+
+    *fourcc = VA_FOURCC('Y', 'V', '1', '2');
+    *is_tiled = 0;
+
+    if (i965->current_context_id == VA_INVALID_ID)
+        return;
+
+    obj_context = CONTEXT(i965->current_context_id);
+
+    if (!obj_context)
+        return;
+
+    obj_config = obj_context->obj_config;
+    assert(obj_config);
+
+    if (!obj_config)
+        return;
+
+    if (IS_GEN6(i965->intel.device_id) || IS_GEN7(i965->intel.device_id)) {
+        *fourcc = VA_FOURCC('N', 'V', '1', '2');
+        *is_tiled = 1;
+        return;
+    }
+
+    switch (obj_config->profile) {
+    case VAProfileMPEG2Simple:
+    case VAProfileMPEG2Main:
+        *fourcc = VA_FOURCC('I', '4', '2', '0');
+        *is_tiled = 0;
+        break;
+
+    default:
+        *fourcc = VA_FOURCC('N', 'V', '1', '2');
+        *is_tiled = 0;
+        break;
+    }
 }
 
 VAStatus 
@@ -698,6 +909,7 @@ i965_CreateSubpicture(VADriverContextP ctx,
 
     *subpicture = subpicID;
     obj_subpic->image  = image;
+    obj_subpic->obj_image = obj_image;
     obj_subpic->format = m->format;
     obj_subpic->width  = obj_image->image.width;
     obj_subpic->height = obj_image->image.height;
@@ -714,6 +926,11 @@ i965_DestroySubpicture(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_subpic *obj_subpic = SUBPIC(subpicture);
+
+    if (!obj_subpic)
+        return VA_STATUS_ERROR_INVALID_SUBPICTURE;
+
+    assert(obj_subpic->obj_image);
     i965_destroy_subpic(&i965->subpic_heap, (struct object_base *)obj_subpic);
     return VA_STATUS_SUCCESS;
 }
@@ -749,6 +966,10 @@ i965_SetSubpictureGlobalAlpha(VADriverContextP ctx,
     if(global_alpha > 1.0 || global_alpha < 0.0){
        return VA_STATUS_ERROR_INVALID_PARAMETER;
     }
+
+    if (!obj_subpic)
+        return VA_STATUS_ERROR_INVALID_SUBPICTURE;
+
     obj_subpic->global_alpha  = global_alpha;
 
     return VA_STATUS_SUCCESS;
@@ -777,6 +998,11 @@ i965_AssociateSubpicture(VADriverContextP ctx,
     struct object_subpic *obj_subpic = SUBPIC(subpicture);
     int i, j;
 
+    if (!obj_subpic)
+        return VA_STATUS_ERROR_INVALID_SUBPICTURE;
+    
+    assert(obj_subpic->obj_image);
+
     obj_subpic->src_rect.x      = src_x;
     obj_subpic->src_rect.y      = src_y;
     obj_subpic->src_rect.width  = src_width;
@@ -794,8 +1020,10 @@ i965_AssociateSubpicture(VADriverContextP ctx,
 
         for(j = 0; j < I965_MAX_SUBPIC_SUM; j ++){
             if(obj_surface->subpic[j] == VA_INVALID_ID){
-               obj_surface->subpic[j] = subpicture;
-               break;
+                assert(obj_surface->obj_subpic[j] == NULL);
+                obj_surface->subpic[j] = subpicture;
+                obj_surface->obj_subpic[j] = obj_subpic;
+                break;
             }
         }
         
@@ -815,17 +1043,23 @@ i965_DeassociateSubpicture(VADriverContextP ctx,
                            int num_surfaces)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_subpic *obj_subpic = SUBPIC(subpicture);
     int i, j;
 
+    if (!obj_subpic)
+        return VA_STATUS_ERROR_INVALID_SUBPICTURE;
+
     for (i = 0; i < num_surfaces; i++) {
         struct object_surface *obj_surface = SURFACE(target_surfaces[i]);
         if (!obj_surface)
             return VA_STATUS_ERROR_INVALID_SURFACE;
 
         for(j = 0; j < I965_MAX_SUBPIC_SUM; j ++){
-            if(obj_surface->subpic[j] == subpicture){
-               obj_surface->subpic[j] = VA_INVALID_ID;
-               break;
+            if (obj_surface->subpic[j] == subpicture) {
+                assert(obj_surface->obj_subpic[j] == obj_subpic);
+                obj_surface->subpic[j] = VA_INVALID_ID;
+                obj_surface->obj_subpic[j] = NULL;
+                break;
             }
         }
         
@@ -882,7 +1116,10 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
         obj_context->hw_context = NULL;
     }
 
-    if (obj_context->codec_type == CODEC_ENC) {
+    if (obj_context->codec_type == CODEC_PROC) {
+        i965_release_buffer_store(&obj_context->codec_state.proc.pipeline_param);
+
+    } else if (obj_context->codec_type == CODEC_ENC) {
         assert(obj_context->codec_state.encode.num_slice_params <= obj_context->codec_state.encode.max_slice_params);
         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
         i965_release_buffer_store(&obj_context->codec_state.encode.seq_param);
@@ -891,6 +1128,24 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params[i]);
 
         free(obj_context->codec_state.encode.slice_params);
+
+        assert(obj_context->codec_state.encode.num_slice_params_ext <= obj_context->codec_state.encode.max_slice_params_ext);
+        i965_release_buffer_store(&obj_context->codec_state.encode.pic_param_ext);
+        i965_release_buffer_store(&obj_context->codec_state.encode.seq_param_ext);
+
+        for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.packed_header_param); i++)
+            i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_param[i]);
+
+        for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.packed_header_data); i++)
+            i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data[i]);
+
+        for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param); i++)
+            i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i]);
+
+        for (i = 0; i < obj_context->codec_state.encode.num_slice_params_ext; i++)
+            i965_release_buffer_store(&obj_context->codec_state.encode.slice_params_ext[i]);
+
+        free(obj_context->codec_state.encode.slice_params_ext);
     } else {
         assert(obj_context->codec_state.decode.num_slice_params <= obj_context->codec_state.decode.max_slice_params);
         assert(obj_context->codec_state.decode.num_slice_datas <= obj_context->codec_state.decode.max_slice_datas);
@@ -958,7 +1213,8 @@ i965_CreateContext(VADriverContextP ctx,
     case VAProfileH264Baseline:
     case VAProfileH264Main:
     case VAProfileH264High:
-        if (!HAS_H264(i965))
+        if (!HAS_H264_DECODING(i965) &&
+            !HAS_H264_ENCODING(i965))
             return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         render_state->interleaved_uv = 1;
         break;
@@ -970,7 +1226,7 @@ i965_CreateContext(VADriverContextP ctx,
     *context = contextID;
     obj_context->flags = flag;
     obj_context->context_id = contextID;
-    obj_context->config_id = config_id;
+    obj_context->obj_config = obj_config;
     obj_context->picture_width = picture_width;
     obj_context->picture_height = picture_height;
     obj_context->num_render_targets = num_render_targets;
@@ -988,7 +1244,13 @@ i965_CreateContext(VADriverContextP ctx,
     }
 
     if (VA_STATUS_SUCCESS == vaStatus) {
-        if (VAEntrypointEncSlice == obj_config->entrypoint ) { /*encode routin only*/
+        if (VAEntrypointVideoProc == obj_config->entrypoint) {
+            obj_context->codec_type = CODEC_PROC;
+            memset(&obj_context->codec_state.proc, 0, sizeof(obj_context->codec_state.proc));
+            obj_context->codec_state.proc.current_render_target = VA_INVALID_ID;
+            assert(i965->codec_info->proc_hw_context_init);
+            obj_context->hw_context = i965->codec_info->proc_hw_context_init(ctx, obj_config);
+        } else if (VAEntrypointEncSlice == obj_config->entrypoint) { /*encode routin only*/
             obj_context->codec_type = CODEC_ENC;
             memset(&obj_context->codec_state.encode, 0, sizeof(obj_context->codec_state.encode));
             obj_context->codec_state.encode.current_render_target = VA_INVALID_ID;
@@ -996,7 +1258,7 @@ i965_CreateContext(VADriverContextP ctx,
             obj_context->codec_state.encode.slice_params = calloc(obj_context->codec_state.encode.max_slice_params,
                                                                sizeof(*obj_context->codec_state.encode.slice_params));
             assert(i965->codec_info->enc_hw_context_init);
-            obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config->profile);
+            obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config);
         } else {
             obj_context->codec_type = CODEC_DEC;
             memset(&obj_context->codec_state.decode, 0, sizeof(obj_context->codec_state.decode));
@@ -1009,7 +1271,7 @@ i965_CreateContext(VADriverContextP ctx,
                                                               sizeof(*obj_context->codec_state.decode.slice_datas));
 
             assert(i965->codec_info->dec_hw_context_init);
-            obj_context->hw_context = i965->codec_info->dec_hw_context_init(ctx, obj_config->profile);
+            obj_context->hw_context = i965->codec_info->dec_hw_context_init(ctx, obj_config);
         }
     }
 
@@ -1018,6 +1280,8 @@ i965_CreateContext(VADriverContextP ctx,
         i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
     }
 
+    i965->current_context_id = contextID;
+
     return vaStatus;
 }
 
@@ -1028,6 +1292,10 @@ i965_DestroyContext(VADriverContextP ctx, VAContextID context)
     struct object_context *obj_context = CONTEXT(context);
 
     assert(obj_context);
+
+    if (i965->current_context_id == context)
+        i965->current_context_id = VA_INVALID_ID;
+
     i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
 
     return VA_STATUS_SUCCESS;
@@ -1062,6 +1330,7 @@ i965_create_buffer_internal(VADriverContextP ctx,
     switch (type) {
     case VAPictureParameterBufferType:
     case VAIQMatrixBufferType:
+    case VAQMatrixBufferType:
     case VABitPlaneBufferType:
     case VASliceGroupMapBufferType:
     case VASliceParameterBufferType:
@@ -1074,9 +1343,12 @@ i965_create_buffer_internal(VADriverContextP ctx,
     case VAEncSequenceParameterBufferType:
     case VAEncPictureParameterBufferType:
     case VAEncSliceParameterBufferType:
-#ifdef HAVE_VA_JPEG_DECODE
-     case VAHuffmanTableBufferType:
-#endif
+    case VAEncPackedHeaderParameterBufferType:
+    case VAEncPackedHeaderDataBufferType:
+    case VAEncMiscParameterBufferType:
+    case VAProcPipelineParameterBufferType:
+    case VAProcFilterParameterBufferType:
+    case VAHuffmanTableBufferType:
         /* Ok */
         break;
 
@@ -1092,7 +1364,8 @@ i965_create_buffer_internal(VADriverContextP ctx,
     }
 
     if (type == VAEncCodedBufferType) {
-        size += ALIGN(sizeof(VACodedBufferSegment), 64);
+        size += I965_CODEDBUFFER_HEADER_SIZE;
+        size += 0x1000; /* for upper bound check */
     }
 
     obj_buffer->max_num_elements = num_elements;
@@ -1110,28 +1383,39 @@ i965_create_buffer_internal(VADriverContextP ctx,
         
         if (data)
             dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
-    } else if (type == VASliceDataBufferType || type == VAImageBufferType || type == VAEncCodedBufferType) {
+    } else if (type == VASliceDataBufferType || 
+               type == VAImageBufferType || 
+               type == VAEncCodedBufferType) {
         buffer_store->bo = dri_bo_alloc(i965->intel.bufmgr, 
                                         "Buffer", 
                                         size * num_elements, 64);
         assert(buffer_store->bo);
 
         if (type == VAEncCodedBufferType) {
-            VACodedBufferSegment *coded_buffer_segment;
+            struct i965_coded_buffer_segment *coded_buffer_segment;
+
             dri_bo_map(buffer_store->bo, 1);
-            coded_buffer_segment = (VACodedBufferSegment *)buffer_store->bo->virtual;
-            coded_buffer_segment->size = size - ALIGN(sizeof(VACodedBufferSegment), 64);
-            coded_buffer_segment->bit_offset = 0;
-            coded_buffer_segment->status = 0;
-            coded_buffer_segment->buf = NULL;
-            coded_buffer_segment->next = NULL;
+            coded_buffer_segment = (struct i965_coded_buffer_segment *)buffer_store->bo->virtual;
+            coded_buffer_segment->base.size = size - I965_CODEDBUFFER_HEADER_SIZE;
+            coded_buffer_segment->base.bit_offset = 0;
+            coded_buffer_segment->base.status = 0;
+            coded_buffer_segment->base.buf = NULL;
+            coded_buffer_segment->base.next = NULL;
+            coded_buffer_segment->mapped = 0;
+            coded_buffer_segment->codec = 0;
             dri_bo_unmap(buffer_store->bo);
         } else if (data) {
             dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
         }
 
     } else {
-        buffer_store->buffer = malloc(size * num_elements);
+        int msize = size;
+        
+        if (type == VAEncPackedHeaderDataBufferType) {
+            msize = ALIGN(size, 4);
+        }
+
+        buffer_store->buffer = malloc(msize * num_elements);
         assert(buffer_store->buffer);
 
         if (data)
@@ -1170,9 +1454,12 @@ i965_BufferSetNumElements(VADriverContextP ctx,
 
     assert(obj_buffer);
 
+    if (!obj_buffer)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
     if ((num_elements < 0) || 
         (num_elements > obj_buffer->max_num_elements)) {
-        vaStatus = VA_STATUS_ERROR_UNKNOWN;
+        vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
     } else {
         obj_buffer->num_elements = num_elements;
         if (obj_buffer->buffer_store != NULL) {
@@ -1196,6 +1483,9 @@ i965_MapBuffer(VADriverContextP ctx,
     assert(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer);
     assert(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer));
 
+    if (!obj_buffer || !obj_buffer->buffer_store)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
     if (NULL != obj_buffer->buffer_store->bo) {
         unsigned int tiling, swizzle;
 
@@ -1210,8 +1500,49 @@ i965_MapBuffer(VADriverContextP ctx,
         *pbuf = obj_buffer->buffer_store->bo->virtual;
 
         if (obj_buffer->type == VAEncCodedBufferType) {
-            VACodedBufferSegment *coded_buffer_segment = (VACodedBufferSegment *)(obj_buffer->buffer_store->bo->virtual);
-            coded_buffer_segment->buf = (unsigned char *)(obj_buffer->buffer_store->bo->virtual) + ALIGN(sizeof(VACodedBufferSegment), 64);
+            int i;
+            unsigned char *buffer = NULL;
+            struct i965_coded_buffer_segment *coded_buffer_segment = (struct i965_coded_buffer_segment *)(obj_buffer->buffer_store->bo->virtual);
+
+            if (!coded_buffer_segment->mapped) {
+                unsigned char delimiter0, delimiter1, delimiter2, delimiter3, delimiter4;
+
+                coded_buffer_segment->base.buf = buffer = (unsigned char *)(obj_buffer->buffer_store->bo->virtual) + I965_CODEDBUFFER_HEADER_SIZE;
+
+                if (coded_buffer_segment->codec == CODED_H264) {
+                    delimiter0 = H264_DELIMITER0;
+                    delimiter1 = H264_DELIMITER1;
+                    delimiter2 = H264_DELIMITER2;
+                    delimiter3 = H264_DELIMITER3;
+                    delimiter4 = H264_DELIMITER4;
+                } else if (coded_buffer_segment->codec == CODED_MPEG2) {
+                    delimiter0 = MPEG2_DELIMITER0;
+                    delimiter1 = MPEG2_DELIMITER1;
+                    delimiter2 = MPEG2_DELIMITER2;
+                    delimiter3 = MPEG2_DELIMITER3;
+                    delimiter4 = MPEG2_DELIMITER4;
+                } else {
+                    assert(0);
+                }
+
+                for (i = 0; i < obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 3 - 0x1000; i++) {
+                    if ((buffer[i] == delimiter0) &&
+                        (buffer[i + 1] == delimiter1) &&
+                        (buffer[i + 2] == delimiter2) &&
+                        (buffer[i + 3] == delimiter3) &&
+                        (buffer[i + 4] == delimiter4))
+                        break;
+                }
+
+                if (i == obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 3 - 0x1000) {
+                    coded_buffer_segment->base.status |= VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
+                }
+
+                coded_buffer_segment->base.size = i;
+                coded_buffer_segment->mapped = 1;
+            } else {
+                assert(coded_buffer_segment->base.buf);
+            }
         }
 
         vaStatus = VA_STATUS_SUCCESS;
@@ -1234,6 +1565,9 @@ i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
     assert(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer);
     assert(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer));
 
+    if (!obj_buffer || !obj_buffer->buffer_store)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
     if (NULL != obj_buffer->buffer_store->bo) {
         unsigned int tiling, swizzle;
 
@@ -1260,6 +1594,10 @@ i965_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id)
     struct object_buffer *obj_buffer = BUFFER(buffer_id);
 
     assert(obj_buffer);
+
+    if (!obj_buffer)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
     i965_destroy_buffer(&i965->buffer_heap, (struct object_base *)obj_buffer);
 
     return VA_STATUS_SUCCESS;
@@ -1274,15 +1612,20 @@ i965_BeginPicture(VADriverContextP ctx,
     struct object_context *obj_context = CONTEXT(context);
     struct object_surface *obj_surface = SURFACE(render_target);
     struct object_config *obj_config;
-    VAContextID config;
     VAStatus vaStatus;
     int i;
 
     assert(obj_context);
+
+    if (!obj_context)
+        return VA_STATUS_ERROR_INVALID_CONTEXT;
+
     assert(obj_surface);
 
-    config = obj_context->config_id;
-    obj_config = CONFIG(config);
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    obj_config = obj_context->obj_config;
     assert(obj_config);
 
     switch (obj_config->profile) {
@@ -1307,22 +1650,42 @@ i965_BeginPicture(VADriverContextP ctx,
         vaStatus = VA_STATUS_SUCCESS;
         break;
 
+    case VAProfileNone:
+        vaStatus = VA_STATUS_SUCCESS;
+        break;
+
     default:
         assert(0);
         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         break;
     }
 
-    if (obj_context->codec_type == CODEC_ENC) {
+    if (obj_context->codec_type == CODEC_PROC) {
+        obj_context->codec_state.proc.current_render_target = render_target;
+    } else if (obj_context->codec_type == CODEC_ENC) {
         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
-        i965_release_buffer_store(&obj_context->codec_state.encode.seq_param);
 
         for (i = 0; i < obj_context->codec_state.encode.num_slice_params; i++) {
             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params[i]);
         }
 
         obj_context->codec_state.encode.num_slice_params = 0;
+
+        /* ext */
+        i965_release_buffer_store(&obj_context->codec_state.encode.pic_param_ext);
+
+        for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.packed_header_param); i++)
+            i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_param[i]);
+
+        for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.packed_header_data); i++)
+            i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data[i]);
+
+        for (i = 0; i < obj_context->codec_state.encode.num_slice_params_ext; i++)
+            i965_release_buffer_store(&obj_context->codec_state.encode.slice_params_ext[i]);
+
+        obj_context->codec_state.encode.num_slice_params_ext = 0;
         obj_context->codec_state.encode.current_render_target = render_target;     /*This is input new frame*/
+        obj_context->codec_state.encode.last_packed_header_type = 0;
     } else {
         obj_context->codec_state.decode.current_render_target = render_target;
         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
@@ -1398,11 +1761,19 @@ i965_decoder_render_picture(VADriverContextP ctx,
     struct object_context *obj_context = CONTEXT(context);
     VAStatus vaStatus = VA_STATUS_SUCCESS;
     int i;
+    
+    assert(obj_context);
+
+    if (!obj_context)
+        return VA_STATUS_ERROR_INVALID_CONTEXT;
 
     for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
         assert(obj_buffer);
 
+        if (!obj_buffer)
+            return VA_STATUS_ERROR_INVALID_BUFFER;
+
         switch (obj_buffer->type) {
         case VAPictureParameterBufferType:
             vaStatus = I965_RENDER_DECODE_BUFFER(picture_parameter);
@@ -1424,11 +1795,9 @@ i965_decoder_render_picture(VADriverContextP ctx,
             vaStatus = I965_RENDER_DECODE_BUFFER(slice_data);
             break;
 
-#ifdef HAVE_VA_JPEG_DECODE
         case VAHuffmanTableBufferType:
             vaStatus = I965_RENDER_DECODE_BUFFER(huffman_table);
             break;
-#endif
 
         default:
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
@@ -1442,14 +1811,68 @@ i965_decoder_render_picture(VADriverContextP ctx,
 #define I965_RENDER_ENCODE_BUFFER(name) I965_RENDER_BUFFER(encode, name)
 
 #define DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(encode, name, member)
-DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(sequence_parameter, seq_param)    
-DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_parameter, pic_param)
-DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_control, pic_control)
+// DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(sequence_parameter, seq_param)    
+// DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_parameter, pic_param)
+// DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_control, pic_control)
 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(qmatrix, q_matrix)
 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(iqmatrix, iq_matrix)
+/* extended buffer */
+DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(sequence_parameter_ext, seq_param_ext)
+DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_parameter_ext, pic_param_ext)
 
 #define DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(name, member) DEF_RENDER_MULTI_BUFFER_FUNC(encode, name, member)
-DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(slice_parameter, slice_params)
+// DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(slice_parameter, slice_params)
+DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(slice_parameter_ext, slice_params_ext)
+
+static VAStatus
+i965_encoder_render_packed_header_parameter_buffer(VADriverContextP ctx,
+                                                   struct object_context *obj_context,
+                                                   struct object_buffer *obj_buffer,
+                                                   int type_index)
+{
+    struct encode_state *encode = &obj_context->codec_state.encode;
+
+    assert(obj_buffer->buffer_store->bo == NULL);
+    assert(obj_buffer->buffer_store->buffer);
+    i965_release_buffer_store(&encode->packed_header_param[type_index]);
+    i965_reference_buffer_store(&encode->packed_header_param[type_index], obj_buffer->buffer_store);
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+i965_encoder_render_packed_header_data_buffer(VADriverContextP ctx,
+                                              struct object_context *obj_context,
+                                              struct object_buffer *obj_buffer,
+                                              int type_index)
+{
+    struct encode_state *encode = &obj_context->codec_state.encode;
+
+    assert(obj_buffer->buffer_store->bo == NULL);
+    assert(obj_buffer->buffer_store->buffer);
+    i965_release_buffer_store(&encode->packed_header_data[type_index]);
+    i965_reference_buffer_store(&encode->packed_header_data[type_index], obj_buffer->buffer_store);
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+i965_encoder_render_misc_parameter_buffer(VADriverContextP ctx,
+                                          struct object_context *obj_context,
+                                          struct object_buffer *obj_buffer)
+{
+    struct encode_state *encode = &obj_context->codec_state.encode;
+    VAEncMiscParameterBuffer *param = NULL;
+
+    assert(obj_buffer->buffer_store->bo == NULL);
+    assert(obj_buffer->buffer_store->buffer);
+
+    param = (VAEncMiscParameterBuffer *)obj_buffer->buffer_store->buffer;
+    i965_release_buffer_store(&encode->misc_param[param->type]);
+    i965_reference_buffer_store(&encode->misc_param[param->type], obj_buffer->buffer_store);
+
+    return VA_STATUS_SUCCESS;
+}
 
 static VAStatus 
 i965_encoder_render_picture(VADriverContextP ctx,
@@ -1459,38 +1882,77 @@ i965_encoder_render_picture(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx); 
     struct object_context *obj_context = CONTEXT(context);
-    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
     int i;
 
-    for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
+    assert(obj_context);
+
+    if (!obj_context)
+        return VA_STATUS_ERROR_INVALID_CONTEXT;
+
+    for (i = 0; i < num_buffers; i++) {  
         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
         assert(obj_buffer);
 
+        if (!obj_buffer)
+            return VA_STATUS_ERROR_INVALID_BUFFER;
+
         switch (obj_buffer->type) {
+        case VAQMatrixBufferType:
+            vaStatus = I965_RENDER_ENCODE_BUFFER(qmatrix);
+            break;
+
+        case VAIQMatrixBufferType:
+            vaStatus = I965_RENDER_ENCODE_BUFFER(iqmatrix);
+            break;
+
         case VAEncSequenceParameterBufferType:
-            vaStatus = I965_RENDER_ENCODE_BUFFER(sequence_parameter);
+            vaStatus = I965_RENDER_ENCODE_BUFFER(sequence_parameter_ext);
             break;
 
         case VAEncPictureParameterBufferType:
-            vaStatus = I965_RENDER_ENCODE_BUFFER(picture_parameter);
-            break;             
+            vaStatus = I965_RENDER_ENCODE_BUFFER(picture_parameter_ext);
+            break;
 
         case VAEncSliceParameterBufferType:
-            vaStatus = I965_RENDER_ENCODE_BUFFER(slice_parameter);
+            vaStatus = I965_RENDER_ENCODE_BUFFER(slice_parameter_ext);
             break;
 
-        case VAPictureParameterBufferType:
-            vaStatus = I965_RENDER_ENCODE_BUFFER(picture_control);
-            break;
+        case VAEncPackedHeaderParameterBufferType:
+        {
+            struct encode_state *encode = &obj_context->codec_state.encode;
+            VAEncPackedHeaderParameterBuffer *param = (VAEncPackedHeaderParameterBuffer *)obj_buffer->buffer_store->buffer;
+            encode->last_packed_header_type = param->type;
 
-        case VAQMatrixBufferType:
-            vaStatus = I965_RENDER_ENCODE_BUFFER(qmatrix);
+            vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
+                                                                          obj_context,
+                                                                          obj_buffer,
+                                                                          va_enc_packed_type_to_idx(encode->last_packed_header_type));
             break;
+        }
 
-        case VAIQMatrixBufferType:
-            vaStatus = I965_RENDER_ENCODE_BUFFER(iqmatrix);
-            break;
+        case VAEncPackedHeaderDataBufferType:
+        {
+            struct encode_state *encode = &obj_context->codec_state.encode;
+
+            assert(encode->last_packed_header_type == VAEncPackedHeaderSequence ||
+                   encode->last_packed_header_type == VAEncPackedHeaderPicture ||
+                   encode->last_packed_header_type == VAEncPackedHeaderSlice ||
+                   (((encode->last_packed_header_type & VAEncPackedHeaderMiscMask) == VAEncPackedHeaderMiscMask) &&
+                    ((encode->last_packed_header_type & (~VAEncPackedHeaderMiscMask)) != 0)));
+            vaStatus = i965_encoder_render_packed_header_data_buffer(ctx, 
+                                                                     obj_context,
+                                                                     obj_buffer,
+                                                                     va_enc_packed_type_to_idx(encode->last_packed_header_type));
+            break;       
+        }
 
+        case VAEncMiscParameterBufferType:
+            vaStatus = i965_encoder_render_misc_parameter_buffer(ctx,
+                                                                 obj_context,
+                                                                 obj_buffer);
+            break;
+            
         default:
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
             break;
@@ -1500,26 +1962,71 @@ i965_encoder_render_picture(VADriverContextP ctx,
     return vaStatus;
 }
 
-VAStatus 
-i965_RenderPicture(VADriverContextP ctx,
-                   VAContextID context,
-                   VABufferID *buffers,
-                   int num_buffers)
+#define I965_RENDER_PROC_BUFFER(name) I965_RENDER_BUFFER(proc, name)
+
+#define DEF_RENDER_PROC_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(proc, name, member)
+DEF_RENDER_PROC_SINGLE_BUFFER_FUNC(pipeline_parameter, pipeline_param)    
+
+static VAStatus 
+i965_proc_render_picture(VADriverContextP ctx,
+                         VAContextID context,
+                         VABufferID *buffers,
+                         int num_buffers)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx);
-    struct object_context *obj_context;
-    struct object_config *obj_config;
-    VAContextID config;
-    VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
+    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct object_context *obj_context = CONTEXT(context);
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    int i;
 
-    obj_context = CONTEXT(context);
     assert(obj_context);
 
-    config = obj_context->config_id;
-    obj_config = CONFIG(config);
+    if (!obj_context)
+        return VA_STATUS_ERROR_INVALID_CONTEXT;
+
+    for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
+        struct object_buffer *obj_buffer = BUFFER(buffers[i]);
+        assert(obj_buffer);
+
+        if (!obj_buffer)
+            return VA_STATUS_ERROR_INVALID_BUFFER;
+
+        switch (obj_buffer->type) {
+        case VAProcPipelineParameterBufferType:
+            vaStatus = I965_RENDER_PROC_BUFFER(pipeline_parameter);
+            break;
+
+        default:
+            vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
+            break;
+        }
+    }
+
+    return vaStatus;
+}
+
+VAStatus 
+i965_RenderPicture(VADriverContextP ctx,
+                   VAContextID context,
+                   VABufferID *buffers,
+                   int num_buffers)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_context *obj_context;
+    struct object_config *obj_config;
+    VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
+
+    obj_context = CONTEXT(context);
+    assert(obj_context);
+
+    if (!obj_context)
+        return VA_STATUS_ERROR_INVALID_CONTEXT;
+    
+    obj_config = obj_context->obj_config;
     assert(obj_config);
 
-    if (VAEntrypointEncSlice == obj_config->entrypoint ){
+    if (VAEntrypointVideoProc == obj_config->entrypoint) {
+        vaStatus = i965_proc_render_picture(ctx, context, buffers, num_buffers);
+    } else if (VAEntrypointEncSlice == obj_config->entrypoint ) {
         vaStatus = i965_encoder_render_picture(ctx, context, buffers, num_buffers);
     } else {
         vaStatus = i965_decoder_render_picture(ctx, context, buffers, num_buffers);
@@ -1534,19 +2041,26 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
     struct i965_driver_data *i965 = i965_driver_data(ctx); 
     struct object_context *obj_context = CONTEXT(context);
     struct object_config *obj_config;
-    VAContextID config;
 
     assert(obj_context);
-    config = obj_context->config_id;
-    obj_config = CONFIG(config);
+
+    if (!obj_context)
+        return VA_STATUS_ERROR_INVALID_CONTEXT;
+
+    obj_config = obj_context->obj_config;
     assert(obj_config);
 
-    if (obj_context->codec_type == CODEC_ENC) {
+    if (obj_context->codec_type == CODEC_PROC) {
+        assert(VAEntrypointVideoProc == obj_config->entrypoint);
+    } else if (obj_context->codec_type == CODEC_ENC) {
         assert(VAEntrypointEncSlice == obj_config->entrypoint);
 
-        assert(obj_context->codec_state.encode.pic_param);
-        assert(obj_context->codec_state.encode.seq_param);
-        assert(obj_context->codec_state.encode.num_slice_params >= 1);
+        assert(obj_context->codec_state.encode.pic_param ||
+               obj_context->codec_state.encode.pic_param_ext);
+        assert(obj_context->codec_state.encode.seq_param ||
+               obj_context->codec_state.encode.seq_param_ext);
+        assert(obj_context->codec_state.encode.num_slice_params >= 1 ||
+               obj_context->codec_state.encode.num_slice_params_ext >= 1);
     } else {
         assert(obj_context->codec_state.decode.pic_param);
         assert(obj_context->codec_state.decode.num_slice_params >= 1);
@@ -1555,9 +2069,7 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
     }
 
     assert(obj_context->hw_context->run);
-    obj_context->hw_context->run(ctx, obj_config->profile, &obj_context->codec_state, obj_context->hw_context);
-
-    return VA_STATUS_SUCCESS;
+    return obj_context->hw_context->run(ctx, obj_config->profile, &obj_context->codec_state, obj_context->hw_context);
 }
 
 VAStatus 
@@ -1615,6 +2127,18 @@ get_display_attribute(VADriverContextP ctx, VADisplayAttribType type)
     return NULL;
 }
 
+static void
+i965_display_attributes_terminate(VADriverContextP ctx)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+
+    if (i965->display_attributes) {
+        free(i965->display_attributes);
+        i965->display_attributes = NULL;
+        i965->num_display_attributes = 0;
+    }
+}
+
 static bool
 i965_display_attributes_init(VADriverContextP ctx)
 {
@@ -1624,7 +2148,7 @@ i965_display_attributes_init(VADriverContextP ctx)
     i965->display_attributes = malloc(
         i965->num_display_attributes * sizeof(i965->display_attributes[0]));
     if (!i965->display_attributes)
-        return false;
+        goto error;
 
     memcpy(
         i965->display_attributes,
@@ -1633,21 +2157,14 @@ i965_display_attributes_init(VADriverContextP ctx)
     );
 
     i965->rotation_attrib = get_display_attribute(ctx, VADisplayAttribRotation);
-    if (!i965->rotation_attrib)
-        return false;
+    if (!i965->rotation_attrib) {
+        goto error;
+    }
     return true;
-}
 
-static void
-i965_display_attributes_terminate(VADriverContextP ctx)
-{
-    struct i965_driver_data * const i965 = i965_driver_data(ctx);
-
-    if (i965->display_attributes) {
-        free(i965->display_attributes);
-        i965->display_attributes = NULL;
-        i965->num_display_attributes = 0;
-    }
+error:
+    i965_display_attributes_terminate(ctx);
+    return false;
 }
 
 /* 
@@ -1749,53 +2266,6 @@ i965_DbgCopySurfaceToBuffer(VADriverContextP ctx,
     return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
-static VAStatus 
-i965_Init(VADriverContextP ctx)
-{
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
-
-    if (intel_driver_init(ctx) == False)
-        return VA_STATUS_ERROR_UNKNOWN;
-
-    if (IS_HASWELL(i965->intel.device_id))
-       i965->codec_info = &gen75_hw_codec_info;
-    else if (IS_G4X(i965->intel.device_id))
-        i965->codec_info = &g4x_hw_codec_info;
-    else if (IS_IRONLAKE(i965->intel.device_id))
-        i965->codec_info = &ironlake_hw_codec_info;
-    else if (IS_GEN6(i965->intel.device_id))
-        i965->codec_info = &gen6_hw_codec_info;
-    else if (IS_GEN7(i965->intel.device_id))
-        i965->codec_info = &gen7_hw_codec_info;
-    else
-        return VA_STATUS_ERROR_UNKNOWN;
-
-    i965->batch = intel_batchbuffer_new(&i965->intel, I915_EXEC_RENDER, 0);
-
-    if (!i965_display_attributes_init(ctx))
-        return VA_STATUS_ERROR_UNKNOWN;
-
-    if (i965_post_processing_init(ctx) == False)
-        return VA_STATUS_ERROR_UNKNOWN;
-
-    if (i965_render_init(ctx) == False)
-        return VA_STATUS_ERROR_UNKNOWN;
-
-#ifdef HAVE_VA_WAYLAND
-    if (IS_VA_WAYLAND(ctx) && !i965_output_wayland_init(ctx))
-        return VA_STATUS_ERROR_UNKNOWN;
-#endif
-
-#ifdef HAVE_VA_X11
-    if (IS_VA_X11(ctx) && !i965_output_dri_init(ctx))
-        return VA_STATUS_ERROR_UNKNOWN;
-#endif
-
-    _i965InitMutex(&i965->render_mutex);
-
-    return VA_STATUS_SUCCESS;
-}
-
 static void
 i965_destroy_heap(struct object_heap *heap, 
                   void (*func)(struct object_heap *heap, struct object_base *object))
@@ -1888,6 +2358,8 @@ i965_CreateImage(VADriverContextP ctx,
     case VA_FOURCC('A','B','G','R'):
     case VA_FOURCC('B','G','R','A'):
     case VA_FOURCC('R','G','B','A'):
+    case VA_FOURCC('B','G','R','X'):
+    case VA_FOURCC('R','G','B','X'):
         image->num_planes = 1;
         image->pitches[0] = width * 4;
         image->offsets[0] = 0;
@@ -1921,6 +2393,13 @@ i965_CreateImage(VADriverContextP ctx,
         image->offsets[1] = size;
         image->data_size  = size + 2 * size2;
         break;
+    case VA_FOURCC('Y','U','Y','2'):
+    case VA_FOURCC('U','Y','V','Y'):
+        image->num_planes = 1;
+        image->pitches[0] = width * 2;
+        image->offsets[0] = 0;
+        image->data_size  = size * 2;
+        break;
     default:
         goto error;
     }
@@ -1930,7 +2409,14 @@ i965_CreateImage(VADriverContextP ctx,
     if (va_status != VA_STATUS_SUCCESS)
         goto error;
 
-    obj_image->bo = BUFFER(image->buf)->buffer_store->bo;
+    struct object_buffer *obj_buffer = BUFFER(image->buf);
+
+    if (!obj_buffer ||
+        !obj_buffer->buffer_store ||
+        !obj_buffer->buffer_store->bo)
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
+
+    obj_image->bo = obj_buffer->buffer_store->bo;
     dri_bo_reference(obj_image->bo);
 
     if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
@@ -1975,14 +2461,38 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
     if (tiled) {
         assert(fourcc == VA_FOURCC('N', 'V', '1', '2') ||
                fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
-               fourcc == VA_FOURCC('I', 'M', 'C', '3'));
+               fourcc == VA_FOURCC('I', 'M', 'C', '3') || 
+               fourcc == VA_FOURCC('R', 'G', 'B', 'A') || 
+               fourcc == VA_FOURCC('R', 'G', 'B', 'X') || 
+               fourcc == VA_FOURCC('B', 'G', 'R', 'A') || 
+               fourcc == VA_FOURCC('B', 'G', 'R', 'X') || 
+               fourcc == VA_FOURCC('Y', 'U', 'Y', '2'));
 
         obj_surface->width = ALIGN(obj_surface->orig_width, 128);
         obj_surface->height = ALIGN(obj_surface->orig_height, 32);
-        obj_surface->cb_cr_pitch = obj_surface->width;
-        region_width = obj_surface->width;
         region_height = obj_surface->height;
 
+        if (fourcc == VA_FOURCC('N', 'V', '1', '2') ||
+            fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
+            fourcc == VA_FOURCC('I', 'M', 'C', '3')) {
+            obj_surface->cb_cr_pitch = obj_surface->width;
+            region_width = obj_surface->width;
+        }
+        else if (fourcc == VA_FOURCC('Y','U', 'Y', '2')) {
+            obj_surface->cb_cr_pitch = obj_surface->width * 2;
+            region_width = obj_surface->width * 2;
+        }
+        else if (fourcc == VA_FOURCC('R', 'G', 'B', 'A') || 
+                 fourcc == VA_FOURCC('R', 'G', 'B', 'X') || 
+                 fourcc == VA_FOURCC('B', 'G', 'R', 'A') || 
+                 fourcc == VA_FOURCC('B', 'G', 'R', 'X')) {
+            region_width = obj_surface->width * 4;
+        }
+        else {
+            assert(0);
+        }
+               
+
         if (fourcc == VA_FOURCC('N', 'V', '1', '2')) {
             assert(subsampling == SUBSAMPLE_YUV420);
             obj_surface->y_cb_offset = obj_surface->height;
@@ -1991,7 +2501,12 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32);
         } else if (fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
-                   fourcc == VA_FOURCC('I', 'M', 'C', '3')) {
+                   fourcc == VA_FOURCC('I', 'M', 'C', '3') || 
+                   fourcc == VA_FOURCC('R', 'G', 'B', 'A') || 
+                   fourcc == VA_FOURCC('R', 'G', 'B', 'X') || 
+                   fourcc == VA_FOURCC('B', 'G', 'R', 'A') || 
+                   fourcc == VA_FOURCC('B', 'G', 'R', 'X') || 
+                   fourcc == VA_FOURCC('Y', 'U', 'Y', '2')) {
             switch (subsampling) {
             case SUBSAMPLE_YUV400:
                 obj_surface->cb_cr_width = 0;
@@ -2022,7 +2537,8 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
                 obj_surface->cb_cr_width = obj_surface->orig_width / 4;
                 obj_surface->cb_cr_height = obj_surface->orig_height;
                 break;
-
+            case SUBSAMPLE_RGBX:
+                break;
             default:
                 assert(0);
                 break;
@@ -2033,15 +2549,29 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             if (fourcc == VA_FOURCC('I', 'M', 'C', '1')) {
                 obj_surface->y_cr_offset = obj_surface->height;
                 obj_surface->y_cb_offset = obj_surface->y_cr_offset + ALIGN(obj_surface->cb_cr_height, 32);
-            } else {
+            } else if (fourcc == VA_FOURCC('I', 'M', 'C', '3')){
                 obj_surface->y_cb_offset = obj_surface->height;
                 obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
             }
+            else if (fourcc == VA_FOURCC('Y','U', 'Y', '2')) {
+                obj_surface->y_cb_offset = 0; 
+                obj_surface->y_cr_offset = 0; 
+                region_height = obj_surface->height;
+            }
+            else if (fourcc == VA_FOURCC('R', 'G', 'B', 'A') || 
+                     fourcc == VA_FOURCC('R', 'G', 'B', 'X') || 
+                     fourcc == VA_FOURCC('B', 'G', 'R', 'A') || 
+                     fourcc == VA_FOURCC('B', 'G', 'R', 'X')) {
+                region_height = obj_surface->height;
+            }
         }
     } else {
         assert(fourcc != VA_FOURCC('I', 'M', 'C', '1') &&
                fourcc != VA_FOURCC('I', 'M', 'C', '3'));
-        assert(subsampling == SUBSAMPLE_YUV420);
+        assert(subsampling == SUBSAMPLE_YUV420 || 
+               subsampling == SUBSAMPLE_YUV422H || 
+               subsampling == SUBSAMPLE_YUV422V || 
+               subsampling == SUBSAMPLE_RGBX);
 
         region_width = obj_surface->width;
         region_height = obj_surface->height;
@@ -2072,6 +2602,23 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             region_height = obj_surface->height + obj_surface->height / 2;
             break;
 
+        case VA_FOURCC('Y','U', 'Y', '2'):
+            obj_surface->y_cb_offset = 0;
+            obj_surface->y_cr_offset = 0;
+            obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+            obj_surface->cb_cr_height = obj_surface->orig_height;
+            obj_surface->cb_cr_pitch = obj_surface->width * 2;
+            region_width = obj_surface->width * 2;
+            region_height = obj_surface->height;
+            break;
+        case VA_FOURCC('R', 'G', 'B', 'A'):
+        case VA_FOURCC('R', 'G', 'B', 'X'):
+        case VA_FOURCC('B', 'G', 'R', 'A'):
+        case VA_FOURCC('B', 'G', 'R', 'X'):
+            region_width = obj_surface->width * 4;
+            region_height = obj_surface->height;
+            break;
+
         default:
             assert(0);
             break;
@@ -2093,7 +2640,9 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
                                                    &pitch,
                                                    0);
         assert(tiling_mode == I915_TILING_Y);
-        assert(pitch == obj_surface->width);
+        assert(pitch == obj_surface->width     || 
+               pitch == obj_surface->width * 2 ||
+               pitch == obj_surface->width * 4) ;
     } else {
         obj_surface->bo = dri_bo_alloc(i965->intel.bufmgr,
                                        "vaapi surface",
@@ -2111,12 +2660,11 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
                           VAImage *out_image)        /* out */
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
-    struct i965_render_state *render_state = &i965->render_state;
     struct object_image *obj_image;
     struct object_surface *obj_surface; 
     VAImageID image_id;
-    unsigned int w_pitch, h_pitch;
-    VAStatus va_status;
+    unsigned int w_pitch;
+    VAStatus va_status = VA_STATUS_ERROR_OPERATION_FAILED;
 
     out_image->image_id = VA_INVALID_ID;
     obj_surface = SURFACE(surface);
@@ -2124,8 +2672,17 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
     if (!obj_surface)
         return VA_STATUS_ERROR_INVALID_SURFACE;
 
+    if (!obj_surface->bo) {
+        unsigned int is_tiled = 0;
+        unsigned int fourcc = VA_FOURCC('Y', 'V', '1', '2');
+        i965_guess_surface_format(ctx, surface, &fourcc, &is_tiled);
+        int sampling = get_sampling_from_fourcc(fourcc);
+        i965_check_alloc_surface_bo(ctx, obj_surface, is_tiled, fourcc, sampling);
+    }
+
+    assert(obj_surface->fourcc);
+
     w_pitch = obj_surface->width;
-    h_pitch = obj_surface->height;
 
     image_id = NEW_IMAGE_ID();
 
@@ -2152,52 +2709,75 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
     image->height = obj_surface->orig_height;
     image->data_size = obj_surface->size;
 
-    if (!render_state->inited) {
-            image->format.fourcc = VA_FOURCC('Y','V','1','2');
-            image->format.byte_order = VA_LSB_FIRST;
-            image->format.bits_per_pixel = 12;
-            image->num_planes = 3;
-            image->pitches[0] = w_pitch;
-            image->offsets[0] = 0;
-            image->pitches[1] = w_pitch / 2;
-            image->offsets[1] = w_pitch * h_pitch;
-            image->pitches[2] = w_pitch / 2;
-            image->offsets[2] = w_pitch * h_pitch + (w_pitch / 2) * (h_pitch / 2);
-    } else {
-        if (render_state->interleaved_uv) {
-            image->format.fourcc = VA_FOURCC('N','V','1','2');
-            image->format.byte_order = VA_LSB_FIRST;
-            image->format.bits_per_pixel = 12;
-            image->num_planes = 2;
-            image->pitches[0] = w_pitch;
-            image->offsets[0] = 0;
-            image->pitches[1] = w_pitch;
-            image->offsets[1] = w_pitch * h_pitch;
-        } else {
-            image->format.fourcc = VA_FOURCC('I','4','2','0');
-            image->format.byte_order = VA_LSB_FIRST;
-            image->format.bits_per_pixel = 12;
-            image->num_planes = 3;
-            image->pitches[0] = w_pitch;
-            image->offsets[0] = 0;
-            image->pitches[1] = w_pitch / 2;
-            image->offsets[1] = w_pitch * h_pitch;
-            image->pitches[2] = w_pitch / 2;
-            image->offsets[2] = w_pitch * h_pitch + (w_pitch / 2) * (h_pitch / 2);
-        }
+    image->format.fourcc = obj_surface->fourcc;
+    image->format.byte_order = VA_LSB_FIRST;
+    image->format.bits_per_pixel = 12;
+
+    switch (image->format.fourcc) {
+    case VA_FOURCC('Y', 'V', '1', '2'):
+        image->num_planes = 3;
+        image->pitches[0] = w_pitch; /* Y */
+        image->offsets[0] = 0;
+        image->pitches[1] = obj_surface->cb_cr_pitch; /* V */
+        image->offsets[1] = w_pitch * obj_surface->y_cr_offset;
+        image->pitches[2] = obj_surface->cb_cr_pitch; /* U */
+        image->offsets[2] = w_pitch * obj_surface->y_cb_offset;
+        break;
+
+    case VA_FOURCC('N', 'V', '1', '2'):
+        image->num_planes = 2;
+        image->pitches[0] = w_pitch; /* Y */
+        image->offsets[0] = 0;
+        image->pitches[1] = obj_surface->cb_cr_pitch; /* UV */
+        image->offsets[1] = w_pitch * obj_surface->y_cb_offset;
+        break;
+
+    case VA_FOURCC('I', '4', '2', '0'):
+        image->num_planes = 3;
+        image->pitches[0] = w_pitch; /* Y */
+        image->offsets[0] = 0;
+        image->pitches[1] = obj_surface->cb_cr_pitch; /* U */
+        image->offsets[1] = w_pitch * obj_surface->y_cb_offset;
+        image->pitches[2] = obj_surface->cb_cr_pitch; /* V */
+        image->offsets[2] = w_pitch * obj_surface->y_cr_offset;
+        break;
+    case VA_FOURCC('Y', 'U', 'Y', '2'):
+        image->num_planes = 1;
+        image->pitches[0] = obj_surface->width * 2; /* Y, width is aligned already */
+        image->offsets[0] = 0;
+        image->pitches[1] = obj_surface->width * 2; /* U */
+        image->offsets[1] = 0;
+        image->pitches[2] = obj_surface->width * 2; /* V */
+        image->offsets[2] = 0;
+        break;
+    case VA_FOURCC('R', 'G', 'B', 'A'):
+    case VA_FOURCC('R', 'G', 'B', 'X'):
+    case VA_FOURCC('B', 'G', 'R', 'A'):
+    case VA_FOURCC('B', 'G', 'R', 'X'):
+        image->num_planes = 1;
+        image->pitches[0] = obj_surface->width * 4;
+        break;
+    default:
+        goto error;
     }
 
-    i965_check_alloc_surface_bo(ctx, obj_surface, HAS_TILED_SURFACE(i965), image->format.fourcc, SUBSAMPLE_YUV420);
     va_status = i965_create_buffer_internal(ctx, 0, VAImageBufferType,
                                             obj_surface->size, 1, NULL, obj_surface->bo, &image->buf);
     if (va_status != VA_STATUS_SUCCESS)
         goto error;
 
-    obj_image->bo = BUFFER(image->buf)->buffer_store->bo;
+    struct object_buffer *obj_buffer = BUFFER(image->buf);
+
+    if (!obj_buffer ||
+        !obj_buffer->buffer_store ||
+        !obj_buffer->buffer_store->bo)
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
+
+    obj_image->bo = obj_buffer->buffer_store->bo;
     dri_bo_reference(obj_image->bo);
 
     if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
-        obj_image->palette = malloc(image->num_palette_entries * sizeof(obj_image->palette));
+        obj_image->palette = malloc(image->num_palette_entries * sizeof(*obj_image->palette));
         if (!obj_image->palette) {
             va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
             goto error;
@@ -2283,6 +2863,33 @@ i965_SetImagePalette(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
+static int 
+get_sampling_from_fourcc(unsigned int fourcc)
+{
+    int surface_sampling = -1;
+    switch (fourcc) {
+    case VA_FOURCC('N', 'V', '1', '2'):
+    case VA_FOURCC('Y', 'V', '1', '2'):
+    case VA_FOURCC('I', '4', '2', '0'):
+    case VA_FOURCC('I', 'M', 'C', '1'):
+    case VA_FOURCC('I', 'M', 'C', '3'):
+        surface_sampling = SUBSAMPLE_YUV420;
+        break;
+    case VA_FOURCC('Y', 'U', 'Y', '2'):
+        surface_sampling = SUBSAMPLE_YUV422H;
+        break;
+    case VA_FOURCC('R','G','B','A'):
+    case VA_FOURCC('R','G','B','X'):
+    case VA_FOURCC('B','G','R','A'):
+    case VA_FOURCC('B','G','R','X'):
+    surface_sampling = SUBSAMPLE_RGBX; 
+        break;
+    default:
+        break;
+    }
+    return surface_sampling;
+}
+
 static inline void
 memcpy_pic(uint8_t *dst, unsigned int dst_stride,
            const uint8_t *src, unsigned int src_stride,
@@ -2406,14 +3013,53 @@ get_image_nv12(struct object_image *obj_image, uint8_t *image_data,
         dri_bo_unmap(obj_surface->bo);
 }
 
-VAStatus 
-i965_GetImage(VADriverContextP ctx,
-              VASurfaceID surface,
-              int x,   /* coordinates of the upper left source pixel */
-              int y,
-              unsigned int width,      /* width and height of the region */
-              unsigned int height,
-              VAImageID image)
+static void
+get_image_yuy2(struct object_image *obj_image, uint8_t *image_data,
+               struct object_surface *obj_surface,
+               const VARectangle *rect)
+{
+    uint8_t *dst, *src;
+    unsigned int tiling, swizzle;
+
+    if (!obj_surface->bo)
+        return;
+
+    assert(obj_surface->fourcc);
+    dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_map_gtt(obj_surface->bo);
+    else
+        dri_bo_map(obj_surface->bo, 0);
+
+    if (!obj_surface->bo->virtual)
+        return;
+
+    /* Both dest VA image and source surface have YUYV format */
+    dst = image_data + obj_image->image.offsets[0];
+    src = (uint8_t *)obj_surface->bo->virtual;
+
+    /* Y plane */
+    dst += rect->y * obj_image->image.pitches[0] + rect->x*2;
+    src += rect->y * obj_surface->width + rect->x*2;
+    memcpy_pic(dst, obj_image->image.pitches[0],
+               src, obj_surface->width*2,
+               rect->width*2, rect->height);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
+    else
+        dri_bo_unmap(obj_surface->bo);
+}
+
+static VAStatus 
+i965_sw_getimage(VADriverContextP ctx,
+                 VASurfaceID surface,
+                 int x,   /* coordinates of the upper left source pixel */
+                 int y,
+                 unsigned int width,      /* width and height of the region */
+                 unsigned int height,
+                 VAImageID image)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct i965_render_state *render_state = &i965->render_state;
@@ -2435,6 +3081,9 @@ i965_GetImage(VADriverContextP ctx,
         y + height > obj_image->image.height)
         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
+    if (obj_surface->fourcc != obj_image->image.format.fourcc)
+        return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
+
     VAStatus va_status;
     void *image_data = NULL;
 
@@ -2462,6 +3111,10 @@ i965_GetImage(VADriverContextP ctx,
             goto operation_failed;
         get_image_nv12(obj_image, image_data, obj_surface, &rect);
         break;
+    case VA_FOURCC('Y','U','Y','2'):
+        /* YUY2 is the format supported by overlay plane */
+        get_image_yuy2(obj_image, image_data, obj_surface, &rect);
+        break;
     default:
     operation_failed:
         va_status = VA_STATUS_ERROR_OPERATION_FAILED;
@@ -2472,85 +3125,498 @@ i965_GetImage(VADriverContextP ctx,
     return va_status;
 }
 
-VAStatus 
-i965_PutSurface(VADriverContextP ctx,
-                VASurfaceID surface,
-                void *draw, /* X Drawable */
-                short srcx,
-                short srcy,
-                unsigned short srcw,
-                unsigned short srch,
-                short destx,
-                short desty,
-                unsigned short destw,
-                unsigned short desth,
-                VARectangle *cliprects, /* client supplied clip list */
-                unsigned int number_cliprects, /* number of clip rects in the clip list */
-                unsigned int flags) /* de-interlacing flags */
+static VAStatus 
+i965_hw_getimage(VADriverContextP ctx,
+                 VASurfaceID surface,
+                 int x,   /* coordinates of the upper left source pixel */
+                 int y,
+                 unsigned int width,      /* width and height of the region */
+                 unsigned int height,
+                 VAImageID image)
 {
-#ifdef HAVE_VA_X11
-    if (IS_VA_X11(ctx)) {
-        VARectangle src_rect, dst_rect;
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct i965_surface src_surface;
+    struct i965_surface dst_surface;
+    VAStatus va_status;
+    VARectangle rect;
+    struct object_surface *obj_surface = SURFACE(surface);
+    struct object_image *obj_image = IMAGE(image);
 
-        src_rect.x      = srcx;
-        src_rect.y      = srcy;
-        src_rect.width  = srcw;
-        src_rect.height = srch;
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
 
-        dst_rect.x      = destx;
-        dst_rect.y      = desty;
-        dst_rect.width  = destw;
-        dst_rect.height = desth;
+    if (!obj_image)
+        return VA_STATUS_ERROR_INVALID_IMAGE;
 
-        return i965_put_surface_dri(ctx, surface, draw, &src_rect, &dst_rect,
-                                    cliprects, number_cliprects, flags);
-    }
-#endif
-    return VA_STATUS_ERROR_UNIMPLEMENTED;
+    if (x < 0 || y < 0)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (x + width > obj_surface->orig_width ||
+        y + height > obj_surface->orig_height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (x + width > obj_image->image.width ||
+        y + height > obj_image->image.height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if (!obj_surface->bo)
+        return VA_STATUS_SUCCESS;
+    assert(obj_image->bo); // image bo is always created, see i965_CreateImage()
+
+    rect.x = x;
+    rect.y = y;
+    rect.width = width;
+    rect.height = height;
+
+    src_surface.base = (struct object_base *)obj_surface;
+    src_surface.type = I965_SURFACE_TYPE_SURFACE;
+    src_surface.flags = I965_SURFACE_FLAG_FRAME;
+
+    dst_surface.base = (struct object_base *)obj_image;
+    dst_surface.type = I965_SURFACE_TYPE_IMAGE;
+    dst_surface.flags = I965_SURFACE_FLAG_FRAME;
+
+    va_status = i965_image_processing(ctx,
+                                      &src_surface,
+                                      &rect,
+                                      &dst_surface,
+                                      &rect);
+
+
+    return va_status;
 }
 
 VAStatus 
-i965_Terminate(VADriverContextP ctx)
+i965_GetImage(VADriverContextP ctx,
+              VASurfaceID surface,
+              int x,   /* coordinates of the upper left source pixel */
+              int y,
+              unsigned int width,      /* width and height of the region */
+              unsigned int height,
+              VAImageID image)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    VAStatus va_status;
+
+    if (HAS_ACCELERATED_GETIMAGE(i965))
+        va_status = i965_hw_getimage(ctx,
+                                     surface,
+                                     x, y,
+                                     width, height,
+                                     image);
+    else
+        va_status = i965_sw_getimage(ctx,
+                                     surface,
+                                     x, y,
+                                     width, height,
+                                     image);
+
+    return va_status;
+}
+
+static void
+put_image_i420(struct object_surface *obj_surface,
+               const VARectangle *dst_rect,
+               struct object_image *obj_image, uint8_t *image_data,
+               const VARectangle *src_rect)
+{
+    uint8_t *dst[3], *src[3];
+    const int Y = 0;
+    const int U = obj_image->image.format.fourcc == obj_surface->fourcc ? 1 : 2;
+    const int V = obj_image->image.format.fourcc == obj_surface->fourcc ? 2 : 1;
+    unsigned int tiling, swizzle;
+
+    if (!obj_surface->bo)
+        return;
+
+    assert(obj_surface->fourcc);
+    assert(dst_rect->width == src_rect->width);
+    assert(dst_rect->height == src_rect->height);
+    dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_map_gtt(obj_surface->bo);
+    else
+        dri_bo_map(obj_surface->bo, 0);
+
+    if (!obj_surface->bo->virtual)
+        return;
+
+    /* Dest VA image has either I420 or YV12 format.
+       Source VA surface alway has I420 format */
+    dst[0] = (uint8_t *)obj_surface->bo->virtual;
+    src[Y] = image_data + obj_image->image.offsets[Y];
+    dst[1] = dst[0] + obj_surface->width * obj_surface->height;
+    src[U] = image_data + obj_image->image.offsets[U];
+    dst[2] = dst[1] + (obj_surface->width / 2) * (obj_surface->height / 2);
+    src[V] = image_data + obj_image->image.offsets[V];
+
+    /* Y plane */
+    dst[0] += dst_rect->y * obj_surface->width + dst_rect->x;
+    src[Y] += src_rect->y * obj_image->image.pitches[Y] + src_rect->x;
+    memcpy_pic(dst[0], obj_surface->width,
+               src[Y], obj_image->image.pitches[Y],
+               src_rect->width, src_rect->height);
+
+    /* U plane */
+    dst[1] += (dst_rect->y / 2) * obj_surface->width / 2 + dst_rect->x / 2;
+    src[U] += (src_rect->y / 2) * obj_image->image.pitches[U] + src_rect->x / 2;
+    memcpy_pic(dst[1], obj_surface->width / 2,
+               src[U], obj_image->image.pitches[U],
+               src_rect->width / 2, src_rect->height / 2);
+
+    /* V plane */
+    dst[2] += (dst_rect->y / 2) * obj_surface->width / 2 + dst_rect->x / 2;
+    src[V] += (src_rect->y / 2) * obj_image->image.pitches[V] + src_rect->x / 2;
+    memcpy_pic(dst[2], obj_surface->width / 2,
+               src[V], obj_image->image.pitches[V],
+               src_rect->width / 2, src_rect->height / 2);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
+    else
+        dri_bo_unmap(obj_surface->bo);
+}
+
+static void
+put_image_nv12(struct object_surface *obj_surface,
+               const VARectangle *dst_rect,
+               struct object_image *obj_image, uint8_t *image_data,
+               const VARectangle *src_rect)
+{
+    uint8_t *dst[2], *src[2];
+    unsigned int tiling, swizzle;
+
+    if (!obj_surface->bo)
+        return;
+
+    assert(obj_surface->fourcc);
+    assert(dst_rect->width == src_rect->width);
+    assert(dst_rect->height == src_rect->height);
+    dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_map_gtt(obj_surface->bo);
+    else
+        dri_bo_map(obj_surface->bo, 0);
+
+    if (!obj_surface->bo->virtual)
+        return;
+
+    /* Both dest VA image and source surface have NV12 format */
+    dst[0] = (uint8_t *)obj_surface->bo->virtual;
+    src[0] = image_data + obj_image->image.offsets[0];
+    dst[1] = dst[0] + obj_surface->width * obj_surface->height;
+    src[1] = image_data + obj_image->image.offsets[1];
+
+    /* Y plane */
+    dst[0] += dst_rect->y * obj_surface->width + dst_rect->x;
+    src[0] += src_rect->y * obj_image->image.pitches[0] + src_rect->x;
+    memcpy_pic(dst[0], obj_surface->width,
+               src[0], obj_image->image.pitches[0],
+               src_rect->width, src_rect->height);
+
+    /* UV plane */
+    dst[1] += (dst_rect->y / 2) * obj_surface->width + (dst_rect->x & -2);
+    src[1] += (src_rect->y / 2) * obj_image->image.pitches[1] + (src_rect->x & -2);
+    memcpy_pic(dst[1], obj_surface->width,
+               src[1], obj_image->image.pitches[1],
+               src_rect->width, src_rect->height / 2);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
+    else
+        dri_bo_unmap(obj_surface->bo);
+}
+
+static void
+put_image_yuy2(struct object_surface *obj_surface,
+               const VARectangle *dst_rect,
+               struct object_image *obj_image, uint8_t *image_data,
+               const VARectangle *src_rect)
+{
+    uint8_t *dst, *src;
+    unsigned int tiling, swizzle;
+
+    if (!obj_surface->bo)
+        return;
+
+    assert(obj_surface->fourcc);
+    assert(dst_rect->width == src_rect->width);
+    assert(dst_rect->height == src_rect->height);
+    dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_map_gtt(obj_surface->bo);
+    else
+        dri_bo_map(obj_surface->bo, 0);
+
+    if (!obj_surface->bo->virtual)
+        return;
+
+    /* Both dest VA image and source surface have YUY2 format */
+    dst = (uint8_t *)obj_surface->bo->virtual;
+    src = image_data + obj_image->image.offsets[0];
+
+    /* YUYV packed plane */
+    dst += dst_rect->y * obj_surface->width + dst_rect->x*2;
+    src += src_rect->y * obj_image->image.pitches[0] + src_rect->x*2;
+    memcpy_pic(dst, obj_surface->width*2,
+               src, obj_image->image.pitches[0],
+               src_rect->width*2, src_rect->height);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
+    else
+        dri_bo_unmap(obj_surface->bo);
+}
+
+
+static VAStatus
+i965_sw_putimage(VADriverContextP ctx,
+                 VASurfaceID surface,
+                 VAImageID image,
+                 int src_x,
+                 int src_y,
+                 unsigned int src_width,
+                 unsigned int src_height,
+                 int dest_x,
+                 int dest_y,
+                 unsigned int dest_width,
+                 unsigned int dest_height)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_surface *obj_surface = SURFACE(surface);
 
-    if (i965->batch)
-        intel_batchbuffer_free(i965->batch);
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
 
-    _i965DestroyMutex(&i965->render_mutex);
+    struct object_image *obj_image = IMAGE(image);
+    if (!obj_image)
+        return VA_STATUS_ERROR_INVALID_IMAGE;
 
-#ifdef HAVE_VA_X11
-    if (IS_VA_X11(ctx))
-        i965_output_dri_terminate(ctx);
-#endif
+    if (src_x < 0 || src_y < 0)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (src_x + src_width > obj_image->image.width ||
+        src_y + src_height > obj_image->image.height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (dest_x < 0 || dest_y < 0)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (dest_x + dest_width > obj_surface->orig_width ||
+        dest_y + dest_height > obj_surface->orig_height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
 
-#ifdef HAVE_VA_WAYLAND
-    if (IS_VA_WAYLAND(ctx))
-        i965_output_wayland_terminate(ctx);
-#endif
+    /* XXX: don't allow scaling */
+    if (src_width != dest_width || src_height != dest_height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
 
-    if (i965_render_terminate(ctx) == False)
-        return VA_STATUS_ERROR_UNKNOWN;
+    if (obj_surface->fourcc) {
+        /* Don't allow format mismatch */
+        if (obj_surface->fourcc != obj_image->image.format.fourcc)
+            return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
+    }
 
-    if (i965_post_processing_terminate(ctx) == False)
-        return VA_STATUS_ERROR_UNKNOWN;
+    else {
+        /* VA is surface not used for decoding, use same VA image format */
+        i965_check_alloc_surface_bo(
+            ctx,
+            obj_surface,
+            0, /* XXX: don't use tiled surface */
+            obj_image->image.format.fourcc,
+            get_sampling_from_fourcc (obj_image->image.format.fourcc));
+    }
 
-    i965_display_attributes_terminate(ctx);
+    VAStatus va_status;
+    void *image_data = NULL;
 
-    i965_destroy_heap(&i965->buffer_heap, i965_destroy_buffer);
-    i965_destroy_heap(&i965->image_heap, i965_destroy_image);
-    i965_destroy_heap(&i965->subpic_heap, i965_destroy_subpic);
-    i965_destroy_heap(&i965->surface_heap, i965_destroy_surface);
-    i965_destroy_heap(&i965->context_heap, i965_destroy_context);
-    i965_destroy_heap(&i965->config_heap, i965_destroy_config);
+    va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
 
-    if (intel_driver_terminate(ctx) == False)
-        return VA_STATUS_ERROR_UNKNOWN;
+    VARectangle src_rect, dest_rect;
+    src_rect.x       = src_x;
+    src_rect.y       = src_y;
+    src_rect.width   = src_width;
+    src_rect.height  = src_height;
+    dest_rect.x      = dest_x;
+    dest_rect.y      = dest_y;
+    dest_rect.width  = dest_width;
+    dest_rect.height = dest_height;
+     
+    switch (obj_image->image.format.fourcc) {
+    case VA_FOURCC('Y','V','1','2'):
+    case VA_FOURCC('I','4','2','0'):
+        put_image_i420(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
+        break;
+    case VA_FOURCC('N','V','1','2'):
+        put_image_nv12(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
+        break;
+    case VA_FOURCC('Y','U','Y','2'):
+        put_image_yuy2(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
+        break;
+    default:
+        va_status = VA_STATUS_ERROR_OPERATION_FAILED;
+        break;
+    }
 
-    free(ctx->pDriverData);
-    ctx->pDriverData = NULL;
+    i965_UnmapBuffer(ctx, obj_image->image.buf);
+    return va_status;
+}
 
-    return VA_STATUS_SUCCESS;
+static VAStatus 
+i965_hw_putimage(VADriverContextP ctx,
+                 VASurfaceID surface,
+                 VAImageID image,
+                 int src_x,
+                 int src_y,
+                 unsigned int src_width,
+                 unsigned int src_height,
+                 int dest_x,
+                 int dest_y,
+                 unsigned int dest_width,
+                 unsigned int dest_height)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_surface *obj_surface = SURFACE(surface);
+    struct object_image *obj_image = IMAGE(image);
+    struct i965_surface src_surface, dst_surface;
+    VAStatus va_status = VA_STATUS_SUCCESS;
+    VARectangle src_rect, dst_rect;
+
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    if (!obj_image || !obj_image->bo)
+        return VA_STATUS_ERROR_INVALID_IMAGE;
+
+    if (src_x < 0 ||
+        src_y < 0 ||
+        src_x + src_width > obj_image->image.width ||
+        src_y + src_height > obj_image->image.height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if (dest_x < 0 ||
+        dest_y < 0 ||
+        dest_x + dest_width > obj_surface->orig_width ||
+        dest_y + dest_height > obj_surface->orig_height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if (!obj_surface->bo) {
+        unsigned int tiling, swizzle;
+        int surface_sampling = get_sampling_from_fourcc (obj_image->image.format.fourcc);;
+        dri_bo_get_tiling(obj_image->bo, &tiling, &swizzle);
+
+        i965_check_alloc_surface_bo(ctx,
+                                    obj_surface,
+                                    !!tiling,
+                                    obj_image->image.format.fourcc,
+                                    surface_sampling);
+    }
+
+    assert(obj_surface->fourcc);
+
+    src_surface.base = (struct object_base *)obj_image;
+    src_surface.type = I965_SURFACE_TYPE_IMAGE;
+    src_surface.flags = I965_SURFACE_FLAG_FRAME;
+    src_rect.x = src_x;
+    src_rect.y = src_y;
+    src_rect.width = src_width;
+    src_rect.height = src_height;
+
+    dst_surface.base = (struct object_base *)obj_surface;
+    dst_surface.type = I965_SURFACE_TYPE_SURFACE;
+    dst_surface.flags = I965_SURFACE_FLAG_FRAME;
+    dst_rect.x = dest_x;
+    dst_rect.y = dest_y;
+    dst_rect.width = dest_width;
+    dst_rect.height = dest_height;
+
+    va_status = i965_image_processing(ctx,
+                                      &src_surface,
+                                      &src_rect,
+                                      &dst_surface,
+                                      &dst_rect);
+
+    return  va_status;
+}
+
+static VAStatus 
+i965_PutImage(VADriverContextP ctx,
+              VASurfaceID surface,
+              VAImageID image,
+              int src_x,
+              int src_y,
+              unsigned int src_width,
+              unsigned int src_height,
+              int dest_x,
+              int dest_y,
+              unsigned int dest_width,
+              unsigned int dest_height)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    VAStatus va_status = VA_STATUS_SUCCESS;
+
+    if (HAS_ACCELERATED_PUTIMAGE(i965))
+        va_status = i965_hw_putimage(ctx,
+                                     surface,
+                                     image,
+                                     src_x,
+                                     src_y,
+                                     src_width,
+                                     src_height,
+                                     dest_x,
+                                     dest_y,
+                                     dest_width,
+                                     dest_height);
+    else 
+        va_status = i965_sw_putimage(ctx,
+                                     surface,
+                                     image,
+                                     src_x,
+                                     src_y,
+                                     src_width,
+                                     src_height,
+                                     dest_x,
+                                     dest_y,
+                                     dest_width,
+                                     dest_height);
+
+    return va_status;
+}
+
+VAStatus 
+i965_PutSurface(VADriverContextP ctx,
+                VASurfaceID surface,
+                void *draw, /* X Drawable */
+                short srcx,
+                short srcy,
+                unsigned short srcw,
+                unsigned short srch,
+                short destx,
+                short desty,
+                unsigned short destw,
+                unsigned short desth,
+                VARectangle *cliprects, /* client supplied clip list */
+                unsigned int number_cliprects, /* number of clip rects in the clip list */
+                unsigned int flags) /* de-interlacing flags */
+{
+#ifdef HAVE_VA_X11
+    if (IS_VA_X11(ctx)) {
+        VARectangle src_rect, dst_rect;
+
+        src_rect.x      = srcx;
+        src_rect.y      = srcy;
+        src_rect.width  = srcw;
+        src_rect.height = srch;
+
+        dst_rect.x      = destx;
+        dst_rect.y      = desty;
+        dst_rect.width  = destw;
+        dst_rect.height = desth;
+
+        return i965_put_surface_dri(ctx, surface, draw, &src_rect, &dst_rect,
+                                    cliprects, number_cliprects, flags);
+    }
+#endif
+    return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
 static VAStatus
@@ -2568,6 +3634,11 @@ i965_BufferInfo(
     i965 = i965_driver_data(ctx);
     obj_buffer = BUFFER(buf_id);
 
+    assert(obj_buffer);
+
+    if (!obj_buffer)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
     *type = obj_buffer->type;
     *size = obj_buffer->size_element;
     *num_elements = obj_buffer->num_elements;
@@ -2707,6 +3778,535 @@ i965_UnlockSurface(
     return vaStatus;
 }
 
+static VAStatus
+i965_GetSurfaceAttributes(
+    VADriverContextP ctx,
+    VAConfigID config,
+    VASurfaceAttrib *attrib_list,
+    unsigned int num_attribs
+    )
+{
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_config *obj_config;
+    int i;
+
+    if (config == VA_INVALID_ID)
+        return VA_STATUS_ERROR_INVALID_CONFIG;
+
+    obj_config = CONFIG(config);
+
+    if (obj_config == NULL)
+        return VA_STATUS_ERROR_INVALID_CONFIG;
+    
+    if (attrib_list == NULL || num_attribs == 0)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    for (i = 0; i < num_attribs; i++) {
+        switch (attrib_list[i].type) {
+        case VASurfaceAttribPixelFormat:
+            attrib_list[i].value.type = VAGenericValueTypeInteger;
+            attrib_list[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+
+            if (attrib_list[i].value.value.i == 0) {
+                if (IS_G4X(i965->intel.device_id)) {
+                    if (obj_config->profile == VAProfileMPEG2Simple ||
+                        obj_config->profile == VAProfileMPEG2Main) {
+                        attrib_list[i].value.value.i = VA_FOURCC('I', '4', '2', '0');
+                    } else {
+                        assert(0);
+                        attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+                    }
+                } else if (IS_IRONLAKE(i965->intel.device_id)) {
+                    if (obj_config->profile == VAProfileMPEG2Simple ||
+                        obj_config->profile == VAProfileMPEG2Main) {
+                        attrib_list[i].value.value.i = VA_FOURCC('I', '4', '2', '0');
+                    } else if (obj_config->profile == VAProfileH264Baseline ||
+                               obj_config->profile == VAProfileH264Main ||
+                               obj_config->profile == VAProfileH264High) {
+                        attrib_list[i].value.value.i = VA_FOURCC('N', 'V', '1', '2');
+                    } else if (obj_config->profile == VAProfileNone) {
+                        attrib_list[i].value.value.i = VA_FOURCC('N', 'V', '1', '2');
+                    } else {
+                        assert(0);
+                        attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+                    }
+                } else if (IS_GEN6(i965->intel.device_id)) {
+                    attrib_list[i].value.value.i = VA_FOURCC('N', 'V', '1', '2');                    
+                } else if (IS_GEN7(i965->intel.device_id)) {
+                    if (obj_config->profile == VAProfileJPEGBaseline)
+                        attrib_list[i].value.value.i = 0; /* internal format */
+                    else
+                        attrib_list[i].value.value.i = VA_FOURCC('N', 'V', '1', '2');
+                }
+            } else {
+                if (IS_G4X(i965->intel.device_id)) {
+                    if (obj_config->profile == VAProfileMPEG2Simple ||
+                        obj_config->profile == VAProfileMPEG2Main) {
+                        if (attrib_list[i].value.value.i != VA_FOURCC('I', '4', '2', '0')) {
+                            attrib_list[i].value.value.i = 0;
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                        }
+                    } else {
+                        assert(0);
+                        attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+                    }
+                } else if (IS_IRONLAKE(i965->intel.device_id)) {
+                    if (obj_config->profile == VAProfileMPEG2Simple ||
+                        obj_config->profile == VAProfileMPEG2Main) {
+                        if (attrib_list[i].value.value.i != VA_FOURCC('I', '4', '2', '0')) {
+                            attrib_list[i].value.value.i = 0;                            
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                        }
+                    } else if (obj_config->profile == VAProfileH264Baseline ||
+                               obj_config->profile == VAProfileH264Main ||
+                               obj_config->profile == VAProfileH264High) {
+                        if (attrib_list[i].value.value.i != VA_FOURCC('N', 'V', '1', '2')) {
+                            attrib_list[i].value.value.i = 0;
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                        }
+                    } else if (obj_config->profile == VAProfileNone) {
+                        switch (attrib_list[i].value.value.i) {
+                        case VA_FOURCC('N', 'V', '1', '2'):
+                        case VA_FOURCC('I', '4', '2', '0'):
+                        case VA_FOURCC('Y', 'V', '1', '2'):
+                        case VA_FOURCC('Y', 'U', 'Y', '2'):
+                        case VA_FOURCC('B', 'G', 'R', 'A'):
+                        case VA_FOURCC('B', 'G', 'R', 'X'):
+                        case VA_FOURCC('R', 'G', 'B', 'X'):
+                        case VA_FOURCC('R', 'G', 'B', 'A'):
+                            break;
+                        default:
+                            attrib_list[i].value.value.i = 0;                            
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                            break;
+                        }
+                    } else {
+                        assert(0);
+                        attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+                    }
+                } else if (IS_GEN6(i965->intel.device_id)) {
+                    if (obj_config->entrypoint == VAEntrypointEncSlice ||
+                        obj_config->entrypoint == VAEntrypointVideoProc) {
+                        switch (attrib_list[i].value.value.i) {
+                        case VA_FOURCC('N', 'V', '1', '2'):
+                        case VA_FOURCC('I', '4', '2', '0'):
+                        case VA_FOURCC('Y', 'V', '1', '2'):
+                        case VA_FOURCC('Y', 'U', 'Y', '2'):
+                        case VA_FOURCC('B', 'G', 'R', 'A'):
+                        case VA_FOURCC('B', 'G', 'R', 'X'):
+                        case VA_FOURCC('R', 'G', 'B', 'X'):
+                        case VA_FOURCC('R', 'G', 'B', 'A'):
+                            break;
+                        default:
+                            attrib_list[i].value.value.i = 0;                            
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                            break;
+                        }
+                    } else {
+                        if (attrib_list[i].value.value.i != VA_FOURCC('N', 'V', '1', '2')) {
+                            attrib_list[i].value.value.i = 0;
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                        }
+                    }
+                } else if (IS_GEN7(i965->intel.device_id)) {
+                    if (obj_config->entrypoint == VAEntrypointEncSlice ||
+                        obj_config->entrypoint == VAEntrypointVideoProc) {
+                        switch (attrib_list[i].value.value.i) {
+                        case VA_FOURCC('N', 'V', '1', '2'):
+                        case VA_FOURCC('I', '4', '2', '0'):
+                        case VA_FOURCC('Y', 'V', '1', '2'):
+                            break;
+                        default:
+                            attrib_list[i].value.value.i = 0;                            
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                            break;
+                        }
+                    } else {
+                        if (obj_config->profile == VAProfileJPEGBaseline) {
+                            attrib_list[i].value.value.i = 0;   /* JPEG decoding always uses an internal format */
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                        } else {
+                            if (attrib_list[i].value.value.i != VA_FOURCC('N', 'V', '1', '2')) {
+                                attrib_list[i].value.value.i = 0;
+                                attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                            }
+                        }
+                    }
+                }
+            }
+
+            break;
+        case VASurfaceAttribMinWidth:
+            /* FIXME: add support for it later */
+            attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+            break;
+        case VASurfaceAttribMaxWidth:
+            attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+            break;
+        case VASurfaceAttribMinHeight:
+            attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+            break;
+        case VASurfaceAttribMaxHeight:
+            attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+            break;
+        default:
+            attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+            break;
+        }
+    }
+
+    return vaStatus;
+}
+
+/* 
+ * Query video processing pipeline 
+ */
+VAStatus i965_QueryVideoProcFilters(
+    VADriverContextP    ctx,
+    VAContextID         context,
+    VAProcFilterType   *filters,
+    unsigned int       *num_filters
+    )
+{
+    struct i965_driver_data *const i965 = i965_driver_data(ctx);
+    unsigned int i = 0;
+    
+    if (HAS_VPP(i965)) {
+        filters[i++] = VAProcFilterNoiseReduction;
+        filters[i++] = VAProcFilterDeinterlacing;
+    }
+
+    if(IS_HASWELL(i965->intel.device_id)){
+        filters[i++] = VAProcFilterNone;
+        filters[i++] = VAProcFilterSharpening;
+        filters[i++] = VAProcFilterColorBalance;
+        filters[i++] = VAProcFilterColorStandard;
+    }
+
+    *num_filters = i;
+
+    return VA_STATUS_SUCCESS;
+}
+
+VAStatus i965_QueryVideoProcFilterCaps(
+    VADriverContextP    ctx,
+    VAContextID         context,
+    VAProcFilterType    type,
+    void               *filter_caps,
+    unsigned int       *num_filter_caps
+    )
+{
+    struct i965_driver_data *const i965 = i965_driver_data(ctx);
+    unsigned int i = 0;
+
+    if (type == VAProcFilterNoiseReduction) {
+        VAProcFilterCap *cap = filter_caps;
+
+        cap->range.min_value = 0.0;
+        cap->range.max_value = 1.0;
+        cap->range.default_value = 0.5;
+        cap->range.step = 0.03125; /* 1.0 / 32 */
+        i++;
+    } else if (type == VAProcFilterDeinterlacing) {
+        VAProcFilterCapDeinterlacing *cap = filter_caps;
+        
+        cap->type = VAProcDeinterlacingBob;
+        i++;
+        cap++;
+    }
+
+    if(IS_HASWELL(i965->intel.device_id)){
+       if(type == VAProcFilterColorBalance){
+         VAProcFilterCapColorBalance *cap = filter_caps;
+         cap->type = VAProcColorBalanceHue;
+         cap->range.min_value = -180.0;
+         cap->range.max_value = 180.0;
+         cap->range.default_value = 0.0;
+         cap->range.step = 1.0; 
+         i++;
+         cap ++; 
+         cap->type = VAProcColorBalanceSaturation;
+         cap->range.min_value = 0.0;
+         cap->range.max_value = 10.0;
+         cap->range.default_value = 0.0;
+         cap->range.step = 0.1; 
+         i++;
+         cap ++; 
+         cap->type = VAProcColorBalanceBrightness;
+         cap->range.min_value = -100.0;
+         cap->range.max_value = 100.0;
+         cap->range.default_value = 0.0;
+         cap->range.step = 1.0; 
+         i++;
+         cap ++; 
+         cap->type = VAProcColorBalanceContrast;
+         cap->range.min_value = 0.0;
+         cap->range.max_value = 10.0;
+         cap->range.default_value = 0.0;
+         cap->range.step = 0.1; 
+         i++;
+         cap ++; 
+      }
+    }
+
+
+    *num_filter_caps = i;
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAProcColorStandardType vpp_input_color_standards[VAProcColorStandardCount] = {
+    VAProcColorStandardBT601,
+};
+
+static VAProcColorStandardType vpp_output_color_standards[VAProcColorStandardCount] = {
+    VAProcColorStandardBT601,
+};
+
+VAStatus i965_QueryVideoProcPipelineCaps(
+    VADriverContextP ctx,
+    VAContextID context,
+    VABufferID *filters,
+    unsigned int num_filters,
+    VAProcPipelineCaps *pipeline_cap     /* out */
+    )
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    unsigned int i = 0;
+
+    pipeline_cap->pipeline_flags = 0;
+    pipeline_cap->filter_flags = 0;
+    pipeline_cap->num_forward_references = 0;
+    pipeline_cap->num_backward_references = 0;
+    pipeline_cap->num_input_color_standards = 1;
+    pipeline_cap->input_color_standards = vpp_input_color_standards;
+    pipeline_cap->num_output_color_standards = 1;
+    pipeline_cap->output_color_standards = vpp_output_color_standards;
+
+    for (i = 0; i < num_filters; i++) {
+        struct object_buffer *obj_buffer = BUFFER(filters[i]);
+
+        if (!obj_buffer ||
+            !obj_buffer->buffer_store ||
+            !obj_buffer->buffer_store->bo)
+            return VA_STATUS_ERROR_INVALID_BUFFER;
+
+        VAProcFilterParameterBufferBase *base = (VAProcFilterParameterBufferBase *)obj_buffer->buffer_store->buffer;
+
+        if (base->type == VAProcFilterNoiseReduction) {
+            VAProcFilterParameterBuffer *denoise = (VAProcFilterParameterBuffer *)base;
+            (void)denoise;
+        } else if (base->type == VAProcFilterDeinterlacing) {
+            VAProcFilterParameterBufferDeinterlacing *deint = (VAProcFilterParameterBufferDeinterlacing *)base;
+
+            assert(deint->algorithm == VAProcDeinterlacingWeave ||
+                   deint->algorithm == VAProcDeinterlacingBob);
+        }
+    }
+
+    return VA_STATUS_SUCCESS;
+}
+
+static bool
+i965_driver_data_init(VADriverContextP ctx)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+
+    if (IS_HASWELL(i965->intel.device_id))
+       i965->codec_info = &gen75_hw_codec_info;
+    else if (IS_G4X(i965->intel.device_id))
+        i965->codec_info = &g4x_hw_codec_info;
+    else if (IS_IRONLAKE(i965->intel.device_id))
+        i965->codec_info = &ironlake_hw_codec_info;
+    else if (IS_GEN6(i965->intel.device_id))
+        i965->codec_info = &gen6_hw_codec_info;
+    else if (IS_GEN7(i965->intel.device_id))
+        i965->codec_info = &gen7_hw_codec_info;
+    else
+        return false;
+
+    if (object_heap_init(&i965->config_heap,
+                         sizeof(struct object_config),
+                         CONFIG_ID_OFFSET))
+        goto err_config_heap;
+    if (object_heap_init(&i965->context_heap,
+                         sizeof(struct object_context),
+                         CONTEXT_ID_OFFSET))
+        goto err_context_heap;
+    
+    if (object_heap_init(&i965->surface_heap,
+                         sizeof(struct object_surface),
+                         SURFACE_ID_OFFSET))
+        goto err_surface_heap;
+    if (object_heap_init(&i965->buffer_heap,
+                         sizeof(struct object_buffer),
+                         BUFFER_ID_OFFSET))
+        goto err_buffer_heap;
+    if (object_heap_init(&i965->image_heap,
+                         sizeof(struct object_image),
+                         IMAGE_ID_OFFSET))
+        goto err_image_heap;
+    if (object_heap_init(&i965->subpic_heap,
+                         sizeof(struct object_subpic),
+                         SUBPIC_ID_OFFSET))
+        goto err_subpic_heap;
+
+    i965->batch = intel_batchbuffer_new(&i965->intel, I915_EXEC_RENDER, 0);
+    _i965InitMutex(&i965->render_mutex);
+    _i965InitMutex(&i965->pp_mutex);
+
+    return true;
+
+err_subpic_heap:    
+    object_heap_destroy(&i965->image_heap);
+err_image_heap:
+    object_heap_destroy(&i965->buffer_heap);
+err_buffer_heap:
+    object_heap_destroy(&i965->surface_heap);
+err_surface_heap:
+    object_heap_destroy(&i965->context_heap);
+err_context_heap:
+    object_heap_destroy(&i965->config_heap);
+err_config_heap:
+
+    return false;
+}
+
+static void
+i965_driver_data_terminate(VADriverContextP ctx)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+
+    _i965DestroyMutex(&i965->pp_mutex);
+    _i965DestroyMutex(&i965->render_mutex);
+
+    if (i965->batch)
+        intel_batchbuffer_free(i965->batch);
+
+    i965_destroy_heap(&i965->subpic_heap, i965_destroy_subpic);
+    i965_destroy_heap(&i965->image_heap, i965_destroy_image);
+    i965_destroy_heap(&i965->buffer_heap, i965_destroy_buffer);
+    i965_destroy_heap(&i965->surface_heap, i965_destroy_surface);
+    i965_destroy_heap(&i965->context_heap, i965_destroy_context);
+    i965_destroy_heap(&i965->config_heap, i965_destroy_config);
+}
+
+struct {
+    bool (*init)(VADriverContextP ctx);
+    void (*terminate)(VADriverContextP ctx);
+    int display_type;
+} i965_sub_ops[] =  {
+    {   
+        intel_driver_init,
+        intel_driver_terminate,
+        0,
+    },
+
+    {
+        i965_driver_data_init,
+        i965_driver_data_terminate,
+        0,
+    },
+
+    {
+        i965_display_attributes_init,
+        i965_display_attributes_terminate,
+        0,
+    },
+
+    {
+        i965_post_processing_init,
+        i965_post_processing_terminate,
+        0,
+    },
+
+    {
+        i965_render_init,
+        i965_render_terminate,
+        0,
+    },
+
+#ifdef HAVE_VA_WAYLAND
+    {
+        i965_output_wayland_init,
+        i965_output_wayland_terminate,
+        VA_DISPLAY_WAYLAND,
+    },
+#endif
+
+#ifdef HAVE_VA_X11
+    {
+        i965_output_dri_init,
+        i965_output_dri_terminate,
+        VA_DISPLAY_X11,
+    },
+#endif
+};
+
+static VAStatus 
+i965_Init(VADriverContextP ctx)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    int i;
+
+    for (i = 0; i < ARRAY_ELEMS(i965_sub_ops); i++) {
+        if ((i965_sub_ops[i].display_type == 0 ||
+             i965_sub_ops[i].display_type == (ctx->display_type & VA_DISPLAY_MAJOR_MASK)) &&
+            !i965_sub_ops[i].init(ctx))
+            break;
+    }
+
+    if (i == ARRAY_ELEMS(i965_sub_ops)) {
+        sprintf(i965->va_vendor, "%s %s driver - %d.%d.%d",
+                INTEL_STR_DRIVER_VENDOR,
+                INTEL_STR_DRIVER_NAME,
+                INTEL_DRIVER_MAJOR_VERSION,
+                INTEL_DRIVER_MINOR_VERSION,
+                INTEL_DRIVER_MICRO_VERSION);
+
+        if (INTEL_DRIVER_PRE_VERSION > 0) {
+            const int len = strlen(i965->va_vendor);
+            sprintf(&i965->va_vendor[len], ".pre%d", INTEL_DRIVER_PRE_VERSION);
+        }
+
+        i965->current_context_id = VA_INVALID_ID;
+
+        return VA_STATUS_SUCCESS;
+    } else {
+        i--;
+
+        for (; i >= 0; i--) {
+            if (i965_sub_ops[i].display_type == 0 ||
+                i965_sub_ops[i].display_type == (ctx->display_type & VA_DISPLAY_MAJOR_MASK)) {
+                i965_sub_ops[i].terminate(ctx);
+            }
+        }
+
+        return VA_STATUS_ERROR_UNKNOWN;
+    }
+}
+
+VAStatus 
+i965_Terminate(VADriverContextP ctx)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    int i;
+
+    if (i965) {
+        for (i = ARRAY_ELEMS(i965_sub_ops); i > 0; i--)
+            if (i965_sub_ops[i - 1].display_type == 0 ||
+                i965_sub_ops[i - 1].display_type == (ctx->display_type & VA_DISPLAY_MAJOR_MASK)) {
+                i965_sub_ops[i - 1].terminate(ctx);
+            }
+    }
+
+    return VA_STATUS_SUCCESS;
+}
+
 VAStatus DLL_EXPORT
 VA_DRIVER_INIT_FUNC(VADriverContextP ctx);
 
@@ -2714,8 +4314,10 @@ VAStatus
 VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
 {
     struct VADriverVTable * const vtable = ctx->vtable;
+    struct VADriverVTableVPP * const vtable_vpp = ctx->vtable_vpp;
+
     struct i965_driver_data *i965;
-    int result;
+    VAStatus ret = VA_STATUS_ERROR_UNKNOWN;
 
     ctx->version_major = VA_MAJOR_VERSION;
     ctx->version_minor = VA_MINOR_VERSION;
@@ -2770,54 +4372,30 @@ VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
     vtable->vaBufferInfo = i965_BufferInfo;
     vtable->vaLockSurface = i965_LockSurface;
     vtable->vaUnlockSurface = i965_UnlockSurface;
-    //    vtable->vaDbgCopySurfaceToBuffer = i965_DbgCopySurfaceToBuffer;
+    vtable->vaGetSurfaceAttributes = i965_GetSurfaceAttributes;
+    vtable->vaCreateSurfaces2 = i965_CreateSurfaces2;
+
+    vtable_vpp->vaQueryVideoProcFilters = i965_QueryVideoProcFilters;
+    vtable_vpp->vaQueryVideoProcFilterCaps = i965_QueryVideoProcFilterCaps;
+    vtable_vpp->vaQueryVideoProcPipelineCaps = i965_QueryVideoProcPipelineCaps;
 
     i965 = (struct i965_driver_data *)calloc(1, sizeof(*i965));
-    assert(i965);
+
+    if (i965 == NULL) {
+        ctx->pDriverData = NULL;
+
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+
     ctx->pDriverData = (void *)i965;
+    ret = i965_Init(ctx);
+
+    if (ret == VA_STATUS_SUCCESS) {
+        ctx->str_vendor = i965->va_vendor;
+    } else {
+        free(i965);
+        ctx->pDriverData = NULL;
+    }
 
-    result = object_heap_init(&i965->config_heap, 
-                              sizeof(struct object_config), 
-                              CONFIG_ID_OFFSET);
-    assert(result == 0);
-
-    result = object_heap_init(&i965->context_heap, 
-                              sizeof(struct object_context), 
-                              CONTEXT_ID_OFFSET);
-    assert(result == 0);
-
-    result = object_heap_init(&i965->surface_heap, 
-                              sizeof(struct object_surface), 
-                              SURFACE_ID_OFFSET);
-    assert(result == 0);
-
-    result = object_heap_init(&i965->buffer_heap, 
-                              sizeof(struct object_buffer), 
-                              BUFFER_ID_OFFSET);
-    assert(result == 0);
-
-    result = object_heap_init(&i965->image_heap, 
-                              sizeof(struct object_image), 
-                              IMAGE_ID_OFFSET);
-    assert(result == 0);
-
-    result = object_heap_init(&i965->subpic_heap, 
-                              sizeof(struct object_subpic), 
-                              SUBPIC_ID_OFFSET);
-    assert(result == 0);
-
-    sprintf(i965->va_vendor, "%s %s driver - %d.%d.%d",
-            INTEL_STR_DRIVER_VENDOR,
-            INTEL_STR_DRIVER_NAME,
-            INTEL_DRIVER_MAJOR_VERSION,
-            INTEL_DRIVER_MINOR_VERSION,
-            INTEL_DRIVER_MICRO_VERSION);
-
-    if (INTEL_DRIVER_PRE_VERSION > 0) {
-        const int len = strlen(i965->va_vendor);
-        sprintf(&i965->va_vendor[len], ".pre%d", INTEL_DRIVER_PRE_VERSION);
-    }
-    ctx->str_vendor = i965->va_vendor;
-
-    return i965_Init(ctx);
+    return ret;
 }