OSDN Git Service

i965_drv: add support for per-codec max resolution
[android-x86/hardware-intel-common-vaapi.git] / src / i965_drv_video.c
old mode 100755 (executable)
new mode 100644 (file)
index 8da5a94..66cdb9e
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2009 Intel Corporation
+ * Copyright ?2009 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
@@ -28,6 +28,8 @@
  */
 
 #include "sysdeps.h"
+#include <unistd.h>
+#include <dlfcn.h>
 
 #ifdef HAVE_VA_X11
 # include "i965_output_dri.h"
@@ -37,6 +39,7 @@
 # include "i965_output_wayland.h"
 #endif
 
+#include "intel_version.h"
 #include "intel_driver.h"
 #include "intel_memman.h"
 #include "intel_batchbuffer.h"
@@ -45,6 +48,8 @@
 #include "i965_decoder.h"
 #include "i965_encoder.h"
 
+#include "gen9_vp9_encapi.h"
+
 #define CONFIG_ID_OFFSET                0x01000000
 #define CONTEXT_ID_OFFSET               0x02000000
 #define SURFACE_ID_OFFSET               0x04000000
 #define HAS_H264_ENCODING(ctx)  ((ctx)->codec_info->has_h264_encoding && \
                                  (ctx)->intel.has_bsd)
 
+#define HAS_LP_H264_ENCODING(ctx)  ((ctx)->codec_info->has_lp_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_ENCODING(ctx)  ((ctx)->codec_info->has_jpeg_encoding && \
+                                 (ctx)->intel.has_bsd)      
 
 #define HAS_VPP(ctx)    ((ctx)->codec_info->has_vpp)
 
 #define HAS_H264_MVC_ENCODING(ctx)  ((ctx)->codec_info->has_h264_mvc_encoding && \
                                      (ctx)->intel.has_bsd)
 
+#define HAS_HEVC_DECODING(ctx)          ((ctx)->codec_info->has_hevc_decoding && \
+                                         (ctx)->intel.has_bsd)
+
+#define HAS_HEVC_ENCODING(ctx)          ((ctx)->codec_info->has_hevc_encoding && \
+                                         (ctx)->intel.has_bsd)
+
+#define HAS_VP9_DECODING(ctx)          ((ctx)->codec_info->has_vp9_decoding && \
+                                         (ctx)->intel.has_bsd)
+
+#define HAS_VP9_DECODING_PROFILE(ctx, profile)                     \
+    (HAS_VP9_DECODING(ctx) &&                                      \
+     ((ctx)->codec_info->vp9_dec_profiles & (1U << (profile - VAProfileVP9Profile0))))
+
+#define HAS_HEVC10_DECODING(ctx)        ((ctx)->codec_info->has_hevc10_decoding && \
+                                         (ctx)->intel.has_bsd)
+
+#define HAS_VPP_P010(ctx)        ((ctx)->codec_info->has_vpp_p010 && \
+                                         (ctx)->intel.has_bsd)
+
+#define HAS_VP9_ENCODING(ctx)          ((ctx)->codec_info->has_vp9_encoding && \
+                                         (ctx)->intel.has_bsd)
+
 static int get_sampling_from_fourcc(unsigned int fourcc);
 
 /* Check whether we are rendering to X11 (VA/X11 or VA/GLX API) */
@@ -129,11 +162,13 @@ static int get_sampling_from_fourcc(unsigned int fourcc);
 #define I_YV12  2, 2, 3, {I965_8BITS, I965_2BITS, I965_2BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_2, OFFSET_0}, {PLANE_1, OFFSET_0} }
 #define I_IMC1  I_YV12
 
+#define I_P010  2, 2, 2, {I965_16BITS, I965_8BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_1, OFFSET_16} }
+
 #define I_422H  2, 1, 3, {I965_8BITS, I965_4BITS, I965_4BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
 #define I_422V  1, 2, 3, {I965_8BITS, I965_4BITS, I965_4BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
 #define I_YV16  2, 1, 3, {I965_8BITS, I965_4BITS, I965_4BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_2, OFFSET_0}, {PLANE_1, OFFSET_0} }
-#define I_YUY2  2, 1, 1, {I965_32BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_24} }
-#define I_UYVY  2, 1, 1, {I965_32BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_16} }
+#define I_YUY2  2, 1, 1, {I965_16BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_24} }
+#define I_UYVY  2, 1, 1, {I965_16BITS}, 3, { {PLANE_0, OFFSET_8}, {PLANE_0, OFFSET_0}, {PLANE_0, OFFSET_16} }
 
 #define I_444P  1, 1, 3, {I965_8BITS, I965_8BITS, I965_8BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
 
@@ -173,6 +208,8 @@ static const i965_fourcc_info i965_fourcc_infos[] = {
     DEF_YUV(YV12, YUV420, I_SI),
     DEF_YUV(IMC1, YUV420, I_S),
 
+    DEF_YUV(P010, YUV420, I_SI),
+
     DEF_YUV(422H, YUV422H, I_SI),
     DEF_YUV(422V, YUV422V, I_S),
     DEF_YUV(YV16, YUV422H, I_S),
@@ -205,7 +242,7 @@ get_fourcc_info(unsigned int fourcc)
 {
     unsigned int i;
 
-    for (i = 0; ARRAY_ELEMS(i965_fourcc_infos); i++) {
+    for (i = 0; i < ARRAY_ELEMS(i965_fourcc_infos); i++) {
         const i965_fourcc_info * const info = &i965_fourcc_infos[i];
 
         if (info->fourcc == fourcc)
@@ -215,6 +252,22 @@ get_fourcc_info(unsigned int fourcc)
     return NULL;
 }
 
+static int
+get_bpp_from_fourcc(unsigned int fourcc)
+{
+    const i965_fourcc_info *info = get_fourcc_info(fourcc);
+    unsigned int i = 0;
+    unsigned int bpp = 0;
+
+    if (!info)
+        return 0;
+
+    for (i = 0; i < info->num_planes; i++)
+        bpp += info->bpp[i];
+
+    return bpp;
+}
+
 enum {
     I965_SURFACETYPE_RGBA = 1,
     I965_SURFACETYPE_YUV,
@@ -278,6 +331,8 @@ i965_image_formats_map[I965_MAX_IMAGE_FORMATS + 1] = {
       { VA_FOURCC_RGBX, VA_LSB_FIRST, 32, 24, 0x000000ff, 0x0000ff00, 0x00ff0000 } },
     { I965_SURFACETYPE_RGBA,
       { VA_FOURCC_BGRX, VA_LSB_FIRST, 32, 24, 0x00ff0000, 0x0000ff00, 0x000000ff } },
+    { I965_SURFACETYPE_YUV,
+      { VA_FOURCC_P010, VA_LSB_FIRST, 24, } },
 };
 
 /* List of supported subpicture formats */
@@ -334,8 +389,43 @@ get_subpic_format(const VAImageFormat *va_format)
     return NULL;
 }
 
+/* Checks whether the surface is in busy state */
+static bool
+is_surface_busy(struct i965_driver_data *i965,
+    struct object_surface *obj_surface)
+{
+    assert(obj_surface != NULL);
+
+    if (obj_surface->locked_image_id != VA_INVALID_ID)
+        return true;
+    if (obj_surface->derived_image_id != VA_INVALID_ID)
+        return true;
+    return false;
+}
+
+/* Checks whether the image is in busy state */
+static bool
+is_image_busy(struct i965_driver_data *i965, struct object_image *obj_image, VASurfaceID surface)
+{
+    struct object_buffer *obj_buffer;
+
+    assert(obj_image != NULL);
+
+    if (obj_image->derived_surface != VA_INVALID_ID &&
+        obj_image->derived_surface == surface)
+        return true;
+
+    obj_buffer = BUFFER(obj_image->image.buf);
+    if (obj_buffer && obj_buffer->export_refcount > 0)
+        return true;
+    return false;
+}
+
 #define I965_PACKED_HEADER_BASE         0
-#define I965_PACKED_MISC_HEADER_BASE    3
+#define I965_SEQ_PACKED_HEADER_BASE     0
+#define I965_SEQ_PACKED_HEADER_END      2
+#define I965_PIC_PACKED_HEADER_BASE     2
+#define I965_PACKED_MISC_HEADER_BASE    4
 
 int
 va_enc_packed_type_to_idx(int packed_type)
@@ -352,15 +442,15 @@ va_enc_packed_type_to_idx(int packed_type)
 
         switch (packed_type) {
         case VAEncPackedHeaderSequence:
-            idx = I965_PACKED_HEADER_BASE + 0;
+            idx = I965_SEQ_PACKED_HEADER_BASE + 0;
             break;
 
         case VAEncPackedHeaderPicture:
-            idx = I965_PACKED_HEADER_BASE + 1;
+            idx = I965_PIC_PACKED_HEADER_BASE + 0;
             break;
 
         case VAEncPackedHeaderSlice:
-            idx = I965_PACKED_HEADER_BASE + 2;
+            idx = I965_PIC_PACKED_HEADER_BASE + 1;
             break;
 
         default:
@@ -370,10 +460,98 @@ va_enc_packed_type_to_idx(int packed_type)
         }
     }
 
-    ASSERT_RET(idx < 4, 0);
+    ASSERT_RET(idx < 5, 0);
     return idx;
 }
 
+#define CALL_VTABLE(vawr, status, param) status = (vawr->vtable->param)
+
+static VAStatus
+i965_surface_wrapper(VADriverContextP ctx, VASurfaceID surface)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_surface *obj_surface = SURFACE(surface);
+    VAStatus va_status = VA_STATUS_SUCCESS;
+
+    if (!obj_surface) {
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+    }
+
+    if (obj_surface->wrapper_surface != VA_INVALID_ID) {
+        /* the wrapped surface already exists. just return it */
+       return va_status;
+    }
+
+    if (obj_surface->fourcc == 0)
+        i965_check_alloc_surface_bo(ctx, obj_surface,
+                                    1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
+
+    /*
+     * TBD: Support more surface formats.
+     * Currently only NV12 is support as NV12 is used by decoding.
+     */
+    if (obj_surface->fourcc != VA_FOURCC_NV12 )
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if ((i965->wrapper_pdrvctx == NULL) ||
+        (obj_surface->bo == NULL))
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    {
+        int fd_handle;
+        VASurfaceAttrib attrib_list[2];
+        VASurfaceAttribExternalBuffers buffer_descriptor;
+        VAGenericID wrapper_surface;
+
+        if (drm_intel_bo_gem_export_to_prime(obj_surface->bo, &fd_handle) != 0)
+            return VA_STATUS_ERROR_OPERATION_FAILED;
+
+        obj_surface->exported_primefd = fd_handle;
+
+        memset(&attrib_list, 0, sizeof(attrib_list));
+        memset(&buffer_descriptor, 0, sizeof(buffer_descriptor));
+
+        attrib_list[0].type = VASurfaceAttribExternalBufferDescriptor;
+        attrib_list[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
+        attrib_list[0].value.value.p = &buffer_descriptor;
+        attrib_list[0].value.type = VAGenericValueTypePointer;
+
+        attrib_list[1].type = VASurfaceAttribMemoryType;
+        attrib_list[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
+        attrib_list[1].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
+        attrib_list[1].value.type = VAGenericValueTypeInteger;
+
+        buffer_descriptor.num_buffers = 1;
+        buffer_descriptor.num_planes = 2;
+        buffer_descriptor.width = obj_surface->orig_width;
+        buffer_descriptor.height = obj_surface->orig_height;
+        buffer_descriptor.pixel_format = obj_surface->fourcc;
+        buffer_descriptor.data_size = obj_surface->size;
+        buffer_descriptor.pitches[0] = obj_surface->width;
+        buffer_descriptor.pitches[1] = obj_surface->cb_cr_pitch;
+        buffer_descriptor.offsets[0] = 0;
+        buffer_descriptor.offsets[1] = obj_surface->width * obj_surface->height;
+        buffer_descriptor.buffers = (void *)&fd_handle;
+
+        CALL_VTABLE(i965->wrapper_pdrvctx, va_status,
+                    vaCreateSurfaces2(i965->wrapper_pdrvctx,
+                                      VA_RT_FORMAT_YUV420,
+                                      obj_surface->orig_width,
+                                      obj_surface->orig_height,
+                                      &wrapper_surface, 1,
+                                      attrib_list, 2));
+
+        if (va_status == VA_STATUS_SUCCESS) {
+            obj_surface->wrapper_surface = wrapper_surface;
+        } else {
+            /* This needs to be checked */
+            va_status = VA_STATUS_ERROR_OPERATION_FAILED;
+        }
+        return va_status;
+    }
+
+}
+
 VAStatus 
 i965_QueryConfigProfiles(VADriverContextP ctx,
                          VAProfile *profile_list,       /* out */
@@ -389,14 +567,17 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
     }
 
     if (HAS_H264_DECODING(i965) ||
-        HAS_H264_ENCODING(i965)) {
+        HAS_H264_ENCODING(i965) ||
+        HAS_LP_H264_ENCODING(i965)) {
         profile_list[i++] = VAProfileH264ConstrainedBaseline;
         profile_list[i++] = VAProfileH264Main;
         profile_list[i++] = VAProfileH264High;
     }
-    if (HAS_H264_MVC_DECODING_PROFILE(i965, VAProfileH264MultiviewHigh))
+    if (HAS_H264_MVC_DECODING_PROFILE(i965, VAProfileH264MultiviewHigh) ||
+        HAS_H264_MVC_ENCODING(i965))
         profile_list[i++] = VAProfileH264MultiviewHigh;
-    if (HAS_H264_MVC_DECODING_PROFILE(i965, VAProfileH264StereoHigh))
+    if (HAS_H264_MVC_DECODING_PROFILE(i965, VAProfileH264StereoHigh) ||
+        HAS_H264_MVC_ENCODING(i965))
         profile_list[i++] = VAProfileH264StereoHigh;
 
     if (HAS_VC1_DECODING(i965)) {
@@ -409,7 +590,8 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
         profile_list[i++] = VAProfileNone;
     }
 
-    if (HAS_JPEG_DECODING(i965)) {
+    if (HAS_JPEG_DECODING(i965) ||
+        HAS_JPEG_ENCODING(i965)) {
         profile_list[i++] = VAProfileJPEGBaseline;
     }
 
@@ -418,9 +600,41 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
         profile_list[i++] = VAProfileVP8Version0_3;
     }
 
-    if (HAS_H264_MVC_ENCODING(i965)) {
-        profile_list[i++] = VAProfileH264MultiviewHigh;
-        profile_list[i++] = VAProfileH264StereoHigh;
+    if (HAS_HEVC_DECODING(i965)||
+        HAS_HEVC_ENCODING(i965)) {
+        profile_list[i++] = VAProfileHEVCMain;
+    }
+
+    if (HAS_HEVC10_DECODING(i965)) {
+        profile_list[i++] = VAProfileHEVCMain10;
+    }
+
+    if(HAS_VP9_DECODING_PROFILE(i965, VAProfileVP9Profile0) ||
+        HAS_VP9_ENCODING(i965)) {
+        profile_list[i++] = VAProfileVP9Profile0;
+    }
+
+    if(HAS_VP9_DECODING_PROFILE(i965, VAProfileVP9Profile2)) {
+        profile_list[i++] = VAProfileVP9Profile2;
+    }
+
+    if (i965->wrapper_pdrvctx) {
+        VAProfile wrapper_list[4];
+        int wrapper_num;
+        VADriverContextP pdrvctx;
+        VAStatus va_status;
+
+        pdrvctx = i965->wrapper_pdrvctx;
+        CALL_VTABLE(pdrvctx, va_status,
+                    vaQueryConfigProfiles(pdrvctx,
+                                          wrapper_list, &wrapper_num));
+
+        if (va_status == VA_STATUS_SUCCESS) {
+            int j;
+            for (j = 0; j < wrapper_num; j++)
+                if (wrapper_list[j] != VAProfileNone)
+                    profile_list[i++] = wrapper_list[j];
+        }
     }
 
     /* If the assert fails then I965_MAX_PROFILES needs to be bigger */
@@ -459,6 +673,9 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
         if (HAS_H264_ENCODING(i965))
             entrypoint_list[n++] = VAEntrypointEncSlice;
 
+        if (HAS_LP_H264_ENCODING(i965))
+            entrypoint_list[n++] = VAEntrypointEncSliceLP;
+
         break;
    case VAProfileH264MultiviewHigh:
    case VAProfileH264StereoHigh:
@@ -484,6 +701,9 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
     case VAProfileJPEGBaseline:
         if (HAS_JPEG_DECODING(i965))
             entrypoint_list[n++] = VAEntrypointVLD;
+        
+        if (HAS_JPEG_ENCODING(i965))
+            entrypoint_list[n++] = VAEntrypointEncPicture;
         break;
 
     case VAProfileVP8Version0_3:
@@ -493,6 +713,46 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
         if (HAS_VP8_ENCODING(i965))
             entrypoint_list[n++] = VAEntrypointEncSlice;
 
+        break;
+
+    case VAProfileHEVCMain:
+        if (HAS_HEVC_DECODING(i965))
+            entrypoint_list[n++] = VAEntrypointVLD;
+
+        if (HAS_HEVC_ENCODING(i965))
+            entrypoint_list[n++] = VAEntrypointEncSlice;
+
+        break;
+
+    case VAProfileHEVCMain10:
+        if (HAS_HEVC10_DECODING(i965))
+            entrypoint_list[n++] = VAEntrypointVLD;
+
+        break;
+
+    case VAProfileVP9Profile0:
+    case VAProfileVP9Profile2:
+        if(HAS_VP9_DECODING_PROFILE(i965, profile))
+            entrypoint_list[n++] = VAEntrypointVLD;
+
+        if (HAS_VP9_ENCODING(i965) && (profile == VAProfileVP9Profile0))
+            entrypoint_list[n++] = VAEntrypointEncSlice;
+
+        if(profile == VAProfileVP9Profile0) {
+          if (i965->wrapper_pdrvctx) {
+              VAStatus va_status = VA_STATUS_SUCCESS;
+              VADriverContextP pdrvctx = i965->wrapper_pdrvctx;
+
+              CALL_VTABLE(pdrvctx, va_status,
+                          vaQueryConfigEntrypoints(pdrvctx, profile,
+                                                   entrypoint_list,
+                                                   num_entrypoints));
+              return va_status;
+          }
+        }
+
+        break;
+
     default:
         break;
     }
@@ -526,7 +786,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
     case VAProfileH264Main:
     case VAProfileH264High:
         if ((HAS_H264_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
-            (HAS_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSlice)) {
+            (HAS_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSlice) ||
+            (HAS_LP_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSliceLP)) {
             va_status = VA_STATUS_SUCCESS;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -552,7 +813,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
         break;
 
     case VAProfileJPEGBaseline:
-        if (HAS_JPEG_DECODING(i965) && entrypoint == VAEntrypointVLD) {
+        if ((HAS_JPEG_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
+            (HAS_JPEG_ENCODING(i965) && entrypoint == VAEntrypointEncPicture)) {
             va_status = VA_STATUS_SUCCESS;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -580,6 +842,35 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
 
         break;
 
+    case VAProfileHEVCMain:
+        if ((HAS_HEVC_DECODING(i965) && (entrypoint == VAEntrypointVLD))||
+            (HAS_HEVC_ENCODING(i965) && (entrypoint == VAEntrypointEncSlice)))
+            va_status = VA_STATUS_SUCCESS;
+        else
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
+
+        break;
+
+    case VAProfileHEVCMain10:
+        if (HAS_HEVC10_DECODING(i965) && (entrypoint == VAEntrypointVLD))
+            va_status = VA_STATUS_SUCCESS;
+        else
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
+
+        break;
+
+    case VAProfileVP9Profile0:
+    case VAProfileVP9Profile2:
+        if ((HAS_VP9_DECODING_PROFILE(i965, profile)) && (entrypoint == VAEntrypointVLD))
+            va_status = VA_STATUS_SUCCESS;
+       else if ((HAS_VP9_ENCODING(i965)) && (entrypoint == VAEntrypointEncSlice))
+            va_status = VA_STATUS_SUCCESS;
+        else if ((profile == VAProfileVP9Profile0) && i965->wrapper_pdrvctx)
+            va_status = VA_STATUS_SUCCESS;
+        else
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
+        break;
+
     default:
         va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         break;
@@ -611,6 +902,24 @@ i965_get_default_chroma_formats(VADriverContextP ctx, VAProfile profile,
     case VAProfileJPEGBaseline:
         if (HAS_JPEG_DECODING(i965) && entrypoint == VAEntrypointVLD)
             chroma_formats |= i965->codec_info->jpeg_dec_chroma_formats;
+        if (HAS_JPEG_ENCODING(i965) && entrypoint == VAEntrypointEncPicture)
+            chroma_formats |= i965->codec_info->jpeg_enc_chroma_formats;
+        break;
+
+    case VAProfileHEVCMain10:
+        if (HAS_HEVC10_DECODING(i965) && entrypoint == VAEntrypointVLD)
+            chroma_formats |= i965->codec_info->hevc_dec_chroma_formats;
+        break;
+
+    case VAProfileNone:
+       if(HAS_VPP_P010(i965))
+            chroma_formats |= VA_RT_FORMAT_YUV420_10BPP;
+        break;
+
+    case VAProfileVP9Profile0:
+    case VAProfileVP9Profile2:
+        if (HAS_VP9_DECODING_PROFILE(i965, profile) && entrypoint == VAEntrypointVLD)
+            chroma_formats |= i965->codec_info->vp9_dec_chroma_formats;
         break;
 
     default:
@@ -636,6 +945,7 @@ i965_GetConfigAttributes(VADriverContextP ctx,
     /* Other attributes don't seem to be defined */
     /* What to do if we don't know the attribute? */
     for (i = 0; i < num_attribs; i++) {
+        attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
         switch (attrib_list[i].type) {
         case VAConfigAttribRTFormat:
             attrib_list[i].value = i965_get_default_chroma_formats(ctx,
@@ -649,27 +959,104 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                 if (profile != VAProfileMPEG2Main &&
                     profile != VAProfileMPEG2Simple)
                     attrib_list[i].value |= VA_RC_CBR;
+
+                if (profile == VAProfileVP9Profile0)
+                    attrib_list[i].value |= VA_RC_VBR;
+
                 break;
-            }
+            } else if (entrypoint == VAEntrypointEncSliceLP) {
+                struct i965_driver_data * const i965 = i965_driver_data(ctx);
+
+                /* Support low power encoding for H.264 only by now */
+                if (profile == VAProfileH264ConstrainedBaseline ||
+                    profile == VAProfileH264Main ||
+                    profile == VAProfileH264High)
+                    attrib_list[i].value = i965->codec_info->lp_h264_brc_mode;
+                else
+                    attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+            } else
+                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+
+            break;
 
         case VAConfigAttribEncPackedHeaders:
-            if (entrypoint == VAEntrypointEncSlice) {
+            if (entrypoint == VAEntrypointEncSlice ||
+                entrypoint == VAEntrypointEncSliceLP) {
                 attrib_list[i].value = VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE | VA_ENC_PACKED_HEADER_MISC;
                 if (profile == VAProfileH264ConstrainedBaseline ||
                     profile == VAProfileH264Main ||
                     profile == VAProfileH264High ||
-                    profile == VAProfileH264MultiviewHigh) {
+                    profile == VAProfileH264StereoHigh ||
+                    profile == VAProfileH264MultiviewHigh ||
+                    profile == VAProfileHEVCMain) {
                     attrib_list[i].value |= (VA_ENC_PACKED_HEADER_RAW_DATA |
                                              VA_ENC_PACKED_HEADER_SLICE);
                 }
+                else if (profile == VAProfileVP9Profile0)
+                    attrib_list[i].value = VA_ENC_PACKED_HEADER_RAW_DATA;
+                break;
+            }
+            else if (entrypoint == VAEntrypointEncPicture) {
+                if (profile == VAProfileJPEGBaseline)
+                    attrib_list[i].value = VA_ENC_PACKED_HEADER_RAW_DATA;
+            }
+            break;
+
+        case VAConfigAttribEncMaxRefFrames:
+            if (entrypoint == VAEntrypointEncSlice)
+                attrib_list[i].value = (1 << 16) | (1 << 0);
+            else if (entrypoint == VAEntrypointEncSliceLP) {
+                /* Don't support B frame for low power mode */
+                if (profile == VAProfileH264ConstrainedBaseline ||
+                    profile == VAProfileH264Main ||
+                    profile == VAProfileH264High)
+                    attrib_list[i].value = (1 << 0);
+                else
+                    attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+            }
+
+            break;
+
+        case VAConfigAttribEncQualityRange:
+            if (entrypoint == VAEntrypointEncSlice ||
+                entrypoint == VAEntrypointEncSliceLP) {
+                attrib_list[i].value = 1;
+                if (profile == VAProfileH264ConstrainedBaseline ||
+                    profile == VAProfileH264Main ||
+                    profile == VAProfileH264High )
+                    attrib_list[i].value = ENCODER_QUALITY_RANGE;
                 break;
             }
+            break;
+    
+        case VAConfigAttribEncJPEG:
+            if( entrypoint == VAEntrypointEncPicture) {
+                VAConfigAttribValEncJPEG *configVal = (VAConfigAttribValEncJPEG*)&(attrib_list[i].value);
+                (configVal->bits).arithmatic_coding_mode = 0; // Huffman coding is used
+                (configVal->bits).progressive_dct_mode = 0;   // Only Sequential DCT is supported
+                (configVal->bits).non_interleaved_mode = 1;   // Support both interleaved and non-interleaved
+                (configVal->bits).differential_mode = 0;      // Baseline DCT is non-differential 
+                (configVal->bits).max_num_components = 3;     // Only 3 components supported
+                (configVal->bits).max_num_scans = 1;          // Only 1 scan per frame
+                (configVal->bits).max_num_huffman_tables = 3; // Max 3 huffman tables
+                (configVal->bits).max_num_quantization_tables = 3; // Max 3 quantization tables
+            }
+            break;
+
+        case VAConfigAttribDecSliceMode:
+            attrib_list[i].value = VA_DEC_SLICE_MODE_NORMAL;
+            break;
 
-       case VAConfigAttribEncMaxRefFrames:
-           if (entrypoint == VAEntrypointEncSlice) {
-               attrib_list[i].value = (1 << 16) | (1 << 0);
-               break;
-           }
+        case VAConfigAttribEncROI:
+            if ((entrypoint == VAEntrypointEncSliceLP) &&
+                (profile == VAProfileH264ConstrainedBaseline ||
+                 profile == VAProfileH264Main ||
+                 profile == VAProfileH264High))
+                attrib_list[i].value = 3;
+            else
+                attrib_list[i].value = 0;
+
+            break;
 
         default:
             /* Do nothing */
@@ -763,6 +1150,7 @@ i965_CreateConfig(VADriverContextP ctx,
     obj_config->profile = profile;
     obj_config->entrypoint = entrypoint;
     obj_config->num_attribs = 0;
+    obj_config->wrapper_config = VA_INVALID_ID;
 
     for (i = 0; i < num_attribs; i++) {
         vaStatus = i965_ensure_config_attribute(obj_config, &attrib_list[i]);
@@ -781,6 +1169,24 @@ i965_CreateConfig(VADriverContextP ctx,
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
     }
 
+    if ((vaStatus == VA_STATUS_SUCCESS) &&
+        (profile == VAProfileVP9Profile0) &&
+        (entrypoint == VAEntrypointVLD) &&
+        !HAS_VP9_DECODING(i965)) {
+
+        if (i965->wrapper_pdrvctx) {
+            VAGenericID wrapper_config;
+
+            CALL_VTABLE(i965->wrapper_pdrvctx, vaStatus,
+                        vaCreateConfig(i965->wrapper_pdrvctx, profile,
+                                       entrypoint, attrib_list,
+                                       num_attribs, &wrapper_config));
+
+            if (vaStatus == VA_STATUS_SUCCESS)
+                obj_config->wrapper_config = wrapper_config;
+        }
+    }
+
     /* Error recovery */
     if (VA_STATUS_SUCCESS != vaStatus) {
         i965_destroy_config(&i965->config_heap, (struct object_base *)obj_config);
@@ -803,6 +1209,14 @@ i965_DestroyConfig(VADriverContextP ctx, VAConfigID config_id)
         return vaStatus;
     }
 
+    if ((obj_config->wrapper_config != VA_INVALID_ID) &&
+        i965->wrapper_pdrvctx) {
+        CALL_VTABLE(i965->wrapper_pdrvctx, vaStatus,
+                    vaDestroyConfig(i965->wrapper_pdrvctx,
+                                    obj_config->wrapper_config));
+        obj_config->wrapper_config = VA_INVALID_ID;
+    }
+
     i965_destroy_config(&i965->config_heap, (struct object_base *)obj_config);
     return VA_STATUS_SUCCESS;
 }
@@ -873,10 +1287,8 @@ i965_surface_native_memory(VADriverContextP ctx,
         expected_fourcc == VA_FOURCC_YV12 ||
         expected_fourcc == VA_FOURCC_YV16)
         tiling = 0;
-               
-    i965_check_alloc_surface_bo(ctx, obj_surface, tiling, expected_fourcc, get_sampling_from_fourcc(expected_fourcc));
 
-    return VA_STATUS_SUCCESS;
+    return i965_check_alloc_surface_bo(ctx, obj_surface, tiling, expected_fourcc, get_sampling_from_fourcc(expected_fourcc));
 }
     
 static VAStatus
@@ -911,6 +1323,7 @@ i965_suface_external_memory(VADriverContextP ctx,
 
     switch (obj_surface->fourcc) {
     case VA_FOURCC_NV12:
+    case VA_FOURCC_P010:
         ASSERT_RET(memory_attibute->num_planes == 2, VA_STATUS_ERROR_INVALID_PARAMETER);
         ASSERT_RET(memory_attibute->pitches[0] == memory_attibute->pitches[1], VA_STATUS_ERROR_INVALID_PARAMETER);
 
@@ -1138,6 +1551,7 @@ i965_CreateSurfaces2(
     /* 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_YUV420_10BPP != format &&
         VA_RT_FORMAT_YUV422 != format &&
         VA_RT_FORMAT_YUV444 != format &&
         VA_RT_FORMAT_YUV411 != format &&
@@ -1175,12 +1589,17 @@ i965_CreateSurfaces2(
         obj_surface->height = ALIGN(height, i965->codec_info->min_linear_hpitch);
         obj_surface->flags = SURFACE_REFERENCED;
         obj_surface->fourcc = 0;
+        obj_surface->expected_format = format;
         obj_surface->bo = NULL;
         obj_surface->locked_image_id = VA_INVALID_ID;
+        obj_surface->derived_image_id = VA_INVALID_ID;
         obj_surface->private_data = NULL;
         obj_surface->free_private_data = NULL;
         obj_surface->subsampling = SUBSAMPLE_YUV420;
 
+        obj_surface->wrapper_surface = VA_INVALID_ID;
+        obj_surface->exported_primefd = -1;
+
         switch (memory_type) {
         case I965_SURFACE_MEM_NATIVE:
             if (memory_attibute) {
@@ -1197,10 +1616,10 @@ i965_CreateSurfaces2(
                 if (memory_attibute->pitches[0]) {
                     int bpp_1stplane = bpp_1stplane_by_fourcc(expected_fourcc);
                     ASSERT_RET(bpp_1stplane, VA_STATUS_ERROR_INVALID_PARAMETER);
-                    obj_surface->width = memory_attibute->pitches[0]/bpp_1stplane;
+                    obj_surface->width = memory_attibute->pitches[0];
                     obj_surface->user_h_stride_set = true;
                     ASSERT_RET(IS_ALIGNED(obj_surface->width, 16), VA_STATUS_ERROR_INVALID_PARAMETER);
-                    ASSERT_RET(obj_surface->width >= width, VA_STATUS_ERROR_INVALID_PARAMETER);
+                    ASSERT_RET(obj_surface->width >= width * bpp_1stplane, VA_STATUS_ERROR_INVALID_PARAMETER);
 
                     if (memory_attibute->offsets[1]) {
                         ASSERT_RET(!memory_attibute->offsets[0], VA_STATUS_ERROR_INVALID_PARAMETER);
@@ -1211,19 +1630,23 @@ i965_CreateSurfaces2(
                     }
                 }
             }
-            i965_surface_native_memory(ctx,
-                                       obj_surface,
-                                       format,
-                                       expected_fourcc);
+            vaStatus = i965_surface_native_memory(ctx,
+                                                  obj_surface,
+                                                  format,
+                                                  expected_fourcc);
             break;
 
         case I965_SURFACE_MEM_GEM_FLINK:
         case I965_SURFACE_MEM_DRM_PRIME:
-            i965_suface_external_memory(ctx,
-                                        obj_surface,
-                                        memory_type,
-                                        memory_attibute,
-                                        i);
+            vaStatus = i965_suface_external_memory(ctx,
+                                                   obj_surface,
+                                                   memory_type,
+                                                   memory_attibute,
+                                                   i);
+            break;
+        }
+        if (VA_STATUS_SUCCESS != vaStatus) {
+            i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
             break;
         }
     }
@@ -1268,15 +1691,30 @@ i965_DestroySurfaces(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     int i;
+    VAStatus va_status = VA_STATUS_SUCCESS;
 
     for (i = num_surfaces; i--; ) {
         struct object_surface *obj_surface = SURFACE(surface_list[i]);
 
         ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
+
+        if ((obj_surface->wrapper_surface != VA_INVALID_ID) &&
+            i965->wrapper_pdrvctx) {
+            CALL_VTABLE(i965->wrapper_pdrvctx, va_status,
+                        vaDestroySurfaces(i965->wrapper_pdrvctx,
+                                          &(obj_surface->wrapper_surface),
+                                          1));
+            obj_surface->wrapper_surface = VA_INVALID_ID;
+        }
+        if (obj_surface->exported_primefd >= 0) {
+           close(obj_surface->exported_primefd);
+           obj_surface->exported_primefd = -1;
+        }
+
         i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
     }
 
-    return VA_STATUS_SUCCESS;
+    return va_status;
 }
 
 VAStatus 
@@ -1334,7 +1772,8 @@ i965_guess_surface_format(VADriverContextP ctx,
 
     if (IS_GEN6(i965->intel.device_info) ||
         IS_GEN7(i965->intel.device_info) ||
-        IS_GEN8(i965->intel.device_info)) {
+        IS_GEN8(i965->intel.device_info) ||
+        IS_GEN9(i965->intel.device_info)) {
         *fourcc = VA_FOURCC_NV12;
         *is_tiled = 1;
         return;
@@ -1621,6 +2060,9 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
         i965_release_buffer_store(&obj_context->codec_state.encode.seq_param);
 
+        i965_release_buffer_store(&obj_context->codec_state.encode.q_matrix);
+        i965_release_buffer_store(&obj_context->codec_state.encode.huffman_table);
+
         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]);
 
@@ -1665,6 +2107,7 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data_ext[i]);
         free(obj_context->codec_state.encode.packed_header_data_ext);
 
+        i965_release_buffer_store(&obj_context->codec_state.encode.encmb_map);
     } 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);
@@ -1687,6 +2130,20 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
     object_heap_free(heap, obj);
 }
 
+static inline void
+max_resolution(struct i965_driver_data *i965,
+               struct object_config *obj_config,
+               int *w,                                  /* out */
+               int *h)                                  /* out */
+{
+    if (i965->codec_info->max_resolution) {
+        i965->codec_info->max_resolution(i965, obj_config, w, h);
+    } else {
+        *w = i965->codec_info->max_width;
+        *h = i965->codec_info->max_height;
+    }
+}
+
 VAStatus
 i965_CreateContext(VADriverContextP ctx,
                    VAConfigID config_id,
@@ -1698,21 +2155,24 @@ i965_CreateContext(VADriverContextP ctx,
                    VAContextID *context)                /* out */
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
-    struct i965_render_state *render_state = &i965->render_state;
     struct object_config *obj_config = CONFIG(config_id);
     struct object_context *obj_context = NULL;
     VAConfigAttrib *attrib;
     VAStatus vaStatus = VA_STATUS_SUCCESS;
     int contextID;
     int i;
+    int max_width;
+    int max_height;
 
     if (NULL == obj_config) {
         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
         return vaStatus;
     }
 
-    if (picture_width > i965->codec_info->max_width ||
-        picture_height > i965->codec_info->max_height) {
+    max_resolution(i965, obj_config, &max_width, &max_height);
+
+    if (picture_width > max_width ||
+        picture_height > max_height) {
         vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
         return vaStatus;
     }
@@ -1727,28 +2187,6 @@ i965_CreateContext(VADriverContextP ctx,
         return vaStatus;
     }
 
-    render_state->inited = 1;
-
-    switch (obj_config->profile) {
-    case VAProfileH264ConstrainedBaseline:
-    case VAProfileH264Main:
-    case VAProfileH264High:
-        if (!HAS_H264_DECODING(i965) &&
-            !HAS_H264_ENCODING(i965))
-            return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
-        render_state->interleaved_uv = 1;
-        break;
-    case VAProfileH264MultiviewHigh:
-    case VAProfileH264StereoHigh:
-        if (!HAS_H264_MVC_DECODING(i965))
-            return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
-        render_state->interleaved_uv = 1;
-        break;
-    default:
-        render_state->interleaved_uv = !!(IS_GEN6(i965->intel.device_info) || IS_GEN7(i965->intel.device_info) || IS_GEN8(i965->intel.device_info));
-        break;
-    }
-
     *context = contextID;
     obj_context->flags = flag;
     obj_context->context_id = contextID;
@@ -1759,6 +2197,10 @@ i965_CreateContext(VADriverContextP ctx,
     obj_context->render_targets = 
         (VASurfaceID *)calloc(num_render_targets, sizeof(VASurfaceID));
     obj_context->hw_context = NULL;
+    obj_context->wrapper_context = VA_INVALID_ID;
+
+    if (!obj_context->render_targets)
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
     for(i = 0; i < num_render_targets; i++) {
         if (NULL == SURFACE(render_targets[i])) {
@@ -1776,7 +2218,10 @@ i965_CreateContext(VADriverContextP ctx,
             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*/
+         } else if ((VAEntrypointEncSlice == obj_config->entrypoint) || 
+                    (VAEntrypointEncPicture == obj_config->entrypoint) ||
+                    (VAEntrypointEncSliceLP == obj_config->entrypoint)) {
+            VAConfigAttrib *packed_attrib;
             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;
@@ -1793,15 +2238,37 @@ i965_CreateContext(VADriverContextP ctx,
                 calloc(obj_context->codec_state.encode.max_packed_header_data_ext,
                        sizeof(struct buffer_store *));
 
-            obj_context->codec_state.encode.slice_num = NUM_SLICES;
+            obj_context->codec_state.encode.max_slice_num = NUM_SLICES;
             obj_context->codec_state.encode.slice_rawdata_index =
-                calloc(obj_context->codec_state.encode.slice_num, sizeof(int));
+                calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
             obj_context->codec_state.encode.slice_rawdata_count =
-                calloc(obj_context->codec_state.encode.slice_num, sizeof(int));
+                calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
 
             obj_context->codec_state.encode.slice_header_index =
-                calloc(obj_context->codec_state.encode.slice_num, sizeof(int));
+                calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
+
+            obj_context->codec_state.encode.vps_sps_seq_index = 0;
 
+            obj_context->codec_state.encode.slice_index = 0;
+            packed_attrib = i965_lookup_config_attribute(obj_config, VAConfigAttribEncPackedHeaders);
+            if (packed_attrib) {
+                obj_context->codec_state.encode.packed_header_flag = packed_attrib->value;
+                if (obj_config->profile == VAProfileVP9Profile0)
+                    obj_context->codec_state.encode.packed_header_flag =
+                            packed_attrib->value & VA_ENC_PACKED_HEADER_RAW_DATA;
+            } else {
+                /* use the default value. SPS/PPS/RAWDATA is passed from user
+                 * while Slice_header data is generated by driver.
+                 */
+                obj_context->codec_state.encode.packed_header_flag =
+                               VA_ENC_PACKED_HEADER_SEQUENCE |
+                               VA_ENC_PACKED_HEADER_PICTURE |
+                               VA_ENC_PACKED_HEADER_RAW_DATA;
+
+                /* it is not used for VP9 */
+                if (obj_config->profile == VAProfileVP9Profile0)
+                    obj_context->codec_state.encode.packed_header_flag = 0;
+            }
             assert(i965->codec_info->enc_hw_context_init);
             obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config);
         } else {
@@ -1825,6 +2292,30 @@ i965_CreateContext(VADriverContextP ctx,
         return VA_STATUS_ERROR_INVALID_CONFIG;
     obj_context->codec_state.base.chroma_formats = attrib->value;
 
+    if (obj_config->wrapper_config != VA_INVALID_ID) {
+        /* The wrapper_pdrvctx should exist when wrapper_config is valid.
+         * So it won't check i965->wrapper_pdrvctx again.
+         * Fixme if it is incorrect.
+         */
+        VAGenericID wrapper_context;
+
+        /*
+         * The render_surface is not passed when calling
+         * vaCreateContext.
+         * If it is needed, we must get the wrapped surface
+         * for the corresponding Surface_list.
+         * So the wrapped surface conversion is deferred.
+         */
+        CALL_VTABLE(i965->wrapper_pdrvctx, vaStatus,
+                    vaCreateContext(i965->wrapper_pdrvctx,
+                                    obj_config->wrapper_config,
+                                    picture_width, picture_height,
+                                    flag, NULL, 0,
+                                    &wrapper_context));
+
+        if (vaStatus == VA_STATUS_SUCCESS)
+            obj_context->wrapper_context = wrapper_context;
+    }
     /* Error recovery */
     if (VA_STATUS_SUCCESS != vaStatus) {
         i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
@@ -1840,15 +2331,25 @@ i965_DestroyContext(VADriverContextP ctx, VAContextID context)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_context *obj_context = CONTEXT(context);
+    VAStatus va_status = VA_STATUS_SUCCESS;
 
     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
 
     if (i965->current_context_id == context)
         i965->current_context_id = VA_INVALID_ID;
 
+    if ((obj_context->wrapper_context != VA_INVALID_ID) &&
+        i965->wrapper_pdrvctx) {
+        CALL_VTABLE(i965->wrapper_pdrvctx, va_status,
+                    vaDestroyContext(i965->wrapper_pdrvctx,
+                                     obj_context->wrapper_context));
+
+        obj_context->wrapper_context = VA_INVALID_ID;
+    }
+
     i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context);
 
-    return VA_STATUS_SUCCESS;
+    return va_status;
 }
 
 static void 
@@ -1875,6 +2376,9 @@ i965_create_buffer_internal(VADriverContextP ctx,
     struct object_buffer *obj_buffer = NULL;
     struct buffer_store *buffer_store = NULL;
     int bufferID;
+    VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
+    struct object_context *obj_context = CONTEXT(context);
+    int wrapper_flag = 0;
 
     /* Validate type */
     switch (type) {
@@ -1900,6 +2404,7 @@ i965_create_buffer_internal(VADriverContextP ctx,
     case VAProcFilterParameterBufferType:
     case VAHuffmanTableBufferType:
     case VAProbabilityBufferType:
+    case VAEncMacroblockMapBufferType:
         /* Ok */
         break;
 
@@ -1923,27 +2428,64 @@ i965_create_buffer_internal(VADriverContextP ctx,
     obj_buffer->num_elements = num_elements;
     obj_buffer->size_element = size;
     obj_buffer->type = type;
+    obj_buffer->export_refcount = 0;
     obj_buffer->buffer_store = NULL;
+    obj_buffer->wrapper_buffer = VA_INVALID_ID;
+    obj_buffer->context_id = context;
+
     buffer_store = calloc(1, sizeof(struct buffer_store));
     assert(buffer_store);
     buffer_store->ref_count = 1;
 
+    if (obj_context &&
+        (obj_context->wrapper_context != VA_INVALID_ID) &&
+        i965->wrapper_pdrvctx) {
+        VAGenericID wrapper_buffer;
+        VADriverContextP pdrvctx = i965->wrapper_pdrvctx;
+
+        CALL_VTABLE(pdrvctx, vaStatus,
+                    vaCreateBuffer(pdrvctx, obj_context->wrapper_context, type, size, num_elements,
+                                   data, &wrapper_buffer));
+        if (vaStatus == VA_STATUS_SUCCESS) {
+            obj_buffer->wrapper_buffer = wrapper_buffer;
+        } else {
+            free(buffer_store);
+            return vaStatus;
+        }
+        wrapper_flag = 1;
+    }
+
     if (store_bo != NULL) {
         buffer_store->bo = store_bo;
         dri_bo_reference(buffer_store->bo);
-        
-        if (data)
+
+        /* If the buffer is wrapped, the buffer_store is bogus. Unnecessary to copy it */
+        if (data && !wrapper_flag)
             dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
     } else if (type == VASliceDataBufferType || 
                type == VAImageBufferType || 
                type == VAEncCodedBufferType ||
+               type == VAEncMacroblockMapBufferType ||
                type == VAProbabilityBufferType) {
-        buffer_store->bo = dri_bo_alloc(i965->intel.bufmgr, 
-                                        "Buffer", 
-                                        size * num_elements, 64);
+
+        /* If the buffer is wrapped, the bo/buffer of buffer_store is bogus.
+         * So it is enough to allocate one 64 byte bo
+         */
+        if (wrapper_flag)
+            buffer_store->bo = dri_bo_alloc(i965->intel.bufmgr, "Bogus buffer",
+                                            64, 64);
+        else
+            buffer_store->bo = dri_bo_alloc(i965->intel.bufmgr,
+                                            "Buffer",
+                                            size * num_elements, 64);
         assert(buffer_store->bo);
 
-        if (type == VAEncCodedBufferType) {
+        /* If the buffer is wrapped, the bo/buffer of buffer_store is bogus.
+         * In fact it can be skipped. But it is still allocated and it is
+         * only to follow the normal flowchart of buffer_allocation/release.
+         */
+        if (!wrapper_flag) {
+          if (type == VAEncCodedBufferType) {
             struct i965_coded_buffer_segment *coded_buffer_segment;
 
             dri_bo_map(buffer_store->bo, 1);
@@ -1955,10 +2497,12 @@ i965_create_buffer_internal(VADriverContextP ctx,
             coded_buffer_segment->base.next = NULL;
             coded_buffer_segment->mapped = 0;
             coded_buffer_segment->codec = 0;
+            coded_buffer_segment->status_support = 0;
             dri_bo_unmap(buffer_store->bo);
-        } else if (data) {
-            dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
-        }
+          } else if (data) {
+              dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
+          }
+       }
 
     } else {
         int msize = size;
@@ -1967,10 +2511,14 @@ i965_create_buffer_internal(VADriverContextP ctx,
             msize = ALIGN(size, 4);
         }
 
-        buffer_store->buffer = malloc(msize * num_elements);
+        /* If the buffer is wrapped, it is enough to allocate 4 bytes */
+        if (wrapper_flag)
+            buffer_store->buffer = malloc(4);
+        else
+            buffer_store->buffer = malloc(msize * num_elements);
         assert(buffer_store->buffer);
 
-        if (data)
+        if (data && (!wrapper_flag))
             memcpy(buffer_store->buffer, data, size * num_elements);
     }
 
@@ -2006,6 +2554,19 @@ i965_BufferSetNumElements(VADriverContextP ctx,
 
     ASSERT_RET(obj_buffer, VA_STATUS_ERROR_INVALID_BUFFER);
 
+    /* When the wrapper_buffer exists, it will wrapper to the
+     * buffer allocated from backend driver.
+     */
+    if ((obj_buffer->wrapper_buffer != VA_INVALID_ID) &&
+        i965->wrapper_pdrvctx) {
+        VADriverContextP pdrvctx = i965->wrapper_pdrvctx;
+
+        CALL_VTABLE(pdrvctx, vaStatus,
+                    vaBufferSetNumElements(pdrvctx, obj_buffer->wrapper_buffer,
+                                         num_elements));
+        return vaStatus;
+    }
+
     if ((num_elements < 0) || 
         (num_elements > obj_buffer->max_num_elements)) {
         vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
@@ -2027,11 +2588,30 @@ i965_MapBuffer(VADriverContextP ctx,
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_buffer *obj_buffer = BUFFER(buf_id);
     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
+    struct object_context *obj_context;
 
     ASSERT_RET(obj_buffer && obj_buffer->buffer_store, VA_STATUS_ERROR_INVALID_BUFFER);
+
+    obj_context = CONTEXT(obj_buffer->context_id);
+
+    /* When the wrapper_buffer exists, it will wrapper to the
+     * buffer allocated from backend driver.
+     */
+    if ((obj_buffer->wrapper_buffer != VA_INVALID_ID) &&
+        i965->wrapper_pdrvctx) {
+        VADriverContextP pdrvctx = i965->wrapper_pdrvctx;
+
+        CALL_VTABLE(pdrvctx, vaStatus,
+                    vaMapBuffer(pdrvctx, obj_buffer->wrapper_buffer, pbuf));
+        return vaStatus;
+    }
+
     ASSERT_RET(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_INVALID_BUFFER);
     ASSERT_RET(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer), VA_STATUS_ERROR_INVALID_BUFFER);
 
+    if (obj_buffer->export_refcount > 0)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
     if (NULL != obj_buffer->buffer_store->bo) {
         unsigned int tiling, swizzle;
 
@@ -2044,10 +2624,12 @@ i965_MapBuffer(VADriverContextP ctx,
 
         ASSERT_RET(obj_buffer->buffer_store->bo->virtual, VA_STATUS_ERROR_OPERATION_FAILED);
         *pbuf = obj_buffer->buffer_store->bo->virtual;
+        vaStatus = VA_STATUS_SUCCESS;
 
         if (obj_buffer->type == VAEncCodedBufferType) {
             int i;
             unsigned char *buffer = NULL;
+            unsigned int  header_offset = I965_CODEDBUFFER_HEADER_SIZE;
             struct i965_coded_buffer_segment *coded_buffer_segment = (struct i965_coded_buffer_segment *)(obj_buffer->buffer_store->bo->virtual);
 
             if (!coded_buffer_segment->mapped) {
@@ -2055,44 +2637,89 @@ i965_MapBuffer(VADriverContextP ctx,
 
                 coded_buffer_segment->base.buf = buffer = (unsigned char *)(obj_buffer->buffer_store->bo->virtual) + I965_CODEDBUFFER_HEADER_SIZE;
 
-                if (coded_buffer_segment->codec == CODEC_H264 ||
-                    coded_buffer_segment->codec == CODEC_H264_MVC) {
-                    delimiter0 = H264_DELIMITER0;
-                    delimiter1 = H264_DELIMITER1;
-                    delimiter2 = H264_DELIMITER2;
-                    delimiter3 = H264_DELIMITER3;
-                    delimiter4 = H264_DELIMITER4;
-                } else if (coded_buffer_segment->codec == CODEC_MPEG2) {
-                    delimiter0 = MPEG2_DELIMITER0;
-                    delimiter1 = MPEG2_DELIMITER1;
-                    delimiter2 = MPEG2_DELIMITER2;
-                    delimiter3 = MPEG2_DELIMITER3;
-                    delimiter4 = MPEG2_DELIMITER4;
+                if (obj_context &&
+                    obj_context->hw_context &&
+                    obj_context->hw_context->get_status &&
+                    coded_buffer_segment->status_support) {
+                    vaStatus = obj_context->hw_context->get_status(ctx, obj_context->hw_context, coded_buffer_segment);
                 } else {
-                    ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_PROFILE);
-                }
 
-                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 (coded_buffer_segment->codec == CODEC_VP9) {
+
+                        if (obj_context == NULL)
+                            return VA_STATUS_ERROR_ENCODING_ERROR;
+
+                        gen9_vp9_get_coded_status(ctx, (char *)coded_buffer_segment,
+                                                  obj_context->hw_context);
+                    }
+                    else if (coded_buffer_segment->codec == CODEC_H264 ||
+                        coded_buffer_segment->codec == CODEC_H264_MVC) {
+                        delimiter0 = H264_DELIMITER0;
+                        delimiter1 = H264_DELIMITER1;
+                        delimiter2 = H264_DELIMITER2;
+                        delimiter3 = H264_DELIMITER3;
+                        delimiter4 = H264_DELIMITER4;
+                    } else if (coded_buffer_segment->codec == CODEC_MPEG2) {
+                        delimiter0 = MPEG2_DELIMITER0;
+                        delimiter1 = MPEG2_DELIMITER1;
+                        delimiter2 = MPEG2_DELIMITER2;
+                        delimiter3 = MPEG2_DELIMITER3;
+                        delimiter4 = MPEG2_DELIMITER4;
+                    } else if(coded_buffer_segment->codec == CODEC_JPEG) {
+                        //In JPEG End of Image (EOI = 0xDDF9) marker can be used for delimiter.
+                        delimiter0 = 0xFF;
+                        delimiter1 = 0xD9;
+                    } else if (coded_buffer_segment->codec == CODEC_HEVC) {
+                        delimiter0 = HEVC_DELIMITER0;
+                        delimiter1 = HEVC_DELIMITER1;
+                        delimiter2 = HEVC_DELIMITER2;
+                        delimiter3 = HEVC_DELIMITER3;
+                        delimiter4 = HEVC_DELIMITER4;
+                    } else if (coded_buffer_segment->codec != CODEC_VP8) {
+                        ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_PROFILE);
+                    }
+
+                    if(coded_buffer_segment->codec == CODEC_VP9) {
+                        /* it is already handled */
+                    } else
+                    if(coded_buffer_segment->codec == CODEC_JPEG) {
+                        for(i = 0; i <  obj_buffer->size_element - header_offset - 1 - 0x1000; i++) {
+                            if( (buffer[i] == 0xFF) && (buffer[i + 1] == 0xD9)) {
+                                break;
+                            }
+                        }
+                        coded_buffer_segment->base.size = i + 2;
+                    } else if (coded_buffer_segment->codec != CODEC_VP8) {
+                        /* vp8 coded buffer size can be told by vp8 internal statistics buffer,
+                           so it don't need to traversal the coded buffer */
+                        for (i = 0; i < obj_buffer->size_element - header_offset - 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 - header_offset - 3 - 0x1000) {
+                            coded_buffer_segment->base.status |= VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
+                        }
+                        coded_buffer_segment->base.size = i;
+                    }
+
+                    if (coded_buffer_segment->base.size >= obj_buffer->size_element - header_offset - 0x1000) {
+                        coded_buffer_segment->base.status |= VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
+                    }
 
-                if (i == obj_buffer->size_element - I965_CODEDBUFFER_HEADER_SIZE - 3 - 0x1000) {
-                    coded_buffer_segment->base.status |= VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
+                    vaStatus = VA_STATUS_SUCCESS;
                 }
 
-                coded_buffer_segment->base.size = i;
                 coded_buffer_segment->mapped = 1;
             } else {
                 assert(coded_buffer_segment->base.buf);
+                vaStatus = VA_STATUS_SUCCESS;
             }
         }
-
-        vaStatus = VA_STATUS_SUCCESS;
     } else if (NULL != obj_buffer->buffer_store->buffer) {
         *pbuf = obj_buffer->buffer_store->buffer;
         vaStatus = VA_STATUS_SUCCESS;
@@ -2112,6 +2739,18 @@ i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
         return VA_STATUS_ERROR_INVALID_BUFFER;
 
     ASSERT_RET(obj_buffer && obj_buffer->buffer_store, VA_STATUS_ERROR_INVALID_BUFFER);
+    /* When the wrapper_buffer exists, it will wrapper to the
+     * buffer allocated from backend driver.
+     */
+    if ((obj_buffer->wrapper_buffer != VA_INVALID_ID) &&
+        i965->wrapper_pdrvctx) {
+        VADriverContextP pdrvctx = i965->wrapper_pdrvctx;
+
+        CALL_VTABLE(pdrvctx, vaStatus,
+                    vaUnmapBuffer(pdrvctx, obj_buffer->wrapper_buffer));
+        return vaStatus;
+    }
+
     ASSERT_RET(obj_buffer->buffer_store->bo || obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_OPERATION_FAILED);
     ASSERT_RET(!(obj_buffer->buffer_store->bo && obj_buffer->buffer_store->buffer), VA_STATUS_ERROR_OPERATION_FAILED);
 
@@ -2139,12 +2778,21 @@ i965_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_buffer *obj_buffer = BUFFER(buffer_id);
+    VAStatus va_status = VA_STATUS_SUCCESS;
 
     ASSERT_RET(obj_buffer, VA_STATUS_ERROR_INVALID_BUFFER);
 
+    if ((obj_buffer->wrapper_buffer != VA_INVALID_ID) &&
+        i965->wrapper_pdrvctx) {
+        CALL_VTABLE(i965->wrapper_pdrvctx, va_status,
+                    vaDestroyBuffer(i965->wrapper_pdrvctx,
+                                    obj_buffer->wrapper_buffer));
+        obj_buffer->wrapper_buffer = VA_INVALID_ID;
+    }
+
     i965_destroy_buffer(&i965->buffer_heap, (struct object_base *)obj_buffer);
 
-    return VA_STATUS_SUCCESS;
+    return va_status;
 }
 
 VAStatus 
@@ -2156,7 +2804,7 @@ i965_BeginPicture(VADriverContextP ctx,
     struct object_context *obj_context = CONTEXT(context);
     struct object_surface *obj_surface = SURFACE(render_target);
     struct object_config *obj_config;
-    VAStatus vaStatus;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
     int i;
 
     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
@@ -2164,50 +2812,8 @@ i965_BeginPicture(VADriverContextP ctx,
     obj_config = obj_context->obj_config;
     ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
 
-    switch (obj_config->profile) {
-    case VAProfileMPEG2Simple:
-    case VAProfileMPEG2Main:
-        vaStatus = VA_STATUS_SUCCESS;
-        break;
-
-    case VAProfileH264ConstrainedBaseline:
-    case VAProfileH264Main:
-    case VAProfileH264High:
-        vaStatus = VA_STATUS_SUCCESS;
-        break;
-
-    case VAProfileH264MultiviewHigh:
-    case VAProfileH264StereoHigh:
-        if (HAS_H264_MVC_DECODING_PROFILE(i965, obj_config->profile) ||
-            HAS_H264_MVC_ENCODING(i965)) {
-            vaStatus = VA_STATUS_SUCCESS;
-        } else {
-            ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_PROFILE);
-        }
-        break;
-
-    case VAProfileVC1Simple:
-    case VAProfileVC1Main:
-    case VAProfileVC1Advanced:
-        vaStatus = VA_STATUS_SUCCESS;
-        break;
-
-    case VAProfileJPEGBaseline:
-        vaStatus = VA_STATUS_SUCCESS;
-        break;
-
-    case VAProfileNone:
-        vaStatus = VA_STATUS_SUCCESS;
-        break;
-
-    case VAProfileVP8Version0_3:
-        vaStatus = VA_STATUS_SUCCESS;
-        break;
-
-    default:
-        ASSERT_RET(0, VA_STATUS_ERROR_UNSUPPORTED_PROFILE);
-        break;
-    }
+    if (is_surface_busy(i965, obj_surface))
+        return VA_STATUS_ERROR_SURFACE_BUSY;
 
     if (obj_context->codec_type == CODEC_PROC) {
         obj_context->codec_state.proc.current_render_target = render_target;
@@ -2236,11 +2842,11 @@ i965_BeginPicture(VADriverContextP ctx,
         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;
         memset(obj_context->codec_state.encode.slice_rawdata_index, 0,
-               sizeof(int) * obj_context->codec_state.encode.slice_num);
+               sizeof(int) * obj_context->codec_state.encode.max_slice_num);
         memset(obj_context->codec_state.encode.slice_rawdata_count, 0,
-               sizeof(int) * obj_context->codec_state.encode.slice_num);
+               sizeof(int) * obj_context->codec_state.encode.max_slice_num);
         memset(obj_context->codec_state.encode.slice_header_index, 0,
-               sizeof(int) * obj_context->codec_state.encode.slice_num);
+               sizeof(int) * obj_context->codec_state.encode.max_slice_num);
 
         for (i = 0; i < obj_context->codec_state.encode.num_packed_header_params_ext; i++)
             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_params_ext[i]);
@@ -2248,6 +2854,16 @@ i965_BeginPicture(VADriverContextP ctx,
             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data_ext[i]);
         obj_context->codec_state.encode.num_packed_header_params_ext = 0;
         obj_context->codec_state.encode.num_packed_header_data_ext = 0;
+        obj_context->codec_state.encode.slice_index = 0;
+        obj_context->codec_state.encode.vps_sps_seq_index = 0;
+        i965_release_buffer_store(&obj_context->codec_state.encode.encmb_map);
+
+        if (obj_config->profile == VAProfileVP9Profile0) {
+            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]);
+
+            i965_release_buffer_store(&obj_context->codec_state.encode.seq_param_ext);
+        }
     } else {
         obj_context->codec_state.decode.current_render_target = render_target;
         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
@@ -2262,6 +2878,20 @@ i965_BeginPicture(VADriverContextP ctx,
 
         obj_context->codec_state.decode.num_slice_params = 0;
         obj_context->codec_state.decode.num_slice_datas = 0;
+
+        if ((obj_context->wrapper_context != VA_INVALID_ID) &&
+            i965->wrapper_pdrvctx) {
+            if (obj_surface->wrapper_surface == VA_INVALID_ID)
+                vaStatus = i965_surface_wrapper(ctx, render_target);
+
+            if (vaStatus != VA_STATUS_SUCCESS)
+                return vaStatus;
+
+            CALL_VTABLE(i965->wrapper_pdrvctx, vaStatus,
+                        vaBeginPicture(i965->wrapper_pdrvctx,
+                                       obj_context->wrapper_context,
+                                       obj_surface->wrapper_surface));
+        }
     }
 
     return vaStatus;
@@ -2312,6 +2942,120 @@ DEF_RENDER_DECODE_SINGLE_BUFFER_FUNC(probability_data, probability_data)
 DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(slice_parameter, slice_params)
 DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(slice_data, slice_datas)
 
+
+static VAStatus
+i965_decoder_vp9_wrapper_picture(VADriverContextP ctx,
+                             VABufferID *buffers,
+                             int num_buffers)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    int i;
+    VADecPictureParameterBufferVP9 *pVp9PicParams;
+    VADriverContextP pdrvctx;
+    struct object_buffer *obj_buffer;
+
+    pdrvctx = i965->wrapper_pdrvctx;
+    /* do the conversion of VADecPictureParameterBufferVP9 */
+    for (i = 0; i < num_buffers; i++) {
+        obj_buffer = BUFFER(buffers[i]);
+
+        if (!obj_buffer)
+            continue;
+
+        if (obj_buffer->wrapper_buffer == VA_INVALID_ID)
+            continue;
+
+        if (obj_buffer->type == VAPictureParameterBufferType) {
+            int j;
+            VASurfaceID surface_id;
+            struct object_surface *obj_surface;
+
+            pdrvctx = i965->wrapper_pdrvctx;
+
+            CALL_VTABLE(pdrvctx, vaStatus,
+                        vaMapBuffer(pdrvctx, obj_buffer->wrapper_buffer,
+                                    (void **)(&pVp9PicParams)));
+
+            if (vaStatus != VA_STATUS_SUCCESS)
+                return vaStatus;
+
+            for (j = 0; j < 8; j++) {
+                surface_id = pVp9PicParams->reference_frames[j];
+                obj_surface = SURFACE(surface_id);
+
+                if (!obj_surface)
+                    continue;
+
+                if (obj_surface->wrapper_surface == VA_INVALID_ID) {
+                    vaStatus = i965_surface_wrapper(ctx, surface_id);
+                    if (vaStatus != VA_STATUS_SUCCESS) {
+                        pdrvctx->vtable->vaUnmapBuffer(pdrvctx,
+                                    obj_buffer->wrapper_buffer);
+                        goto fail_out;
+                    }
+                }
+
+                pVp9PicParams->reference_frames[j] = obj_surface->wrapper_surface;
+            }
+            CALL_VTABLE(pdrvctx, vaStatus,
+                        vaUnmapBuffer(pdrvctx, obj_buffer->wrapper_buffer));
+            break;
+        }
+    }
+
+    return VA_STATUS_SUCCESS;
+
+fail_out:
+    return vaStatus;
+}
+
+static VAStatus
+i965_decoder_wrapper_picture(VADriverContextP ctx,
+                             VAContextID context,
+                             VABufferID *buffers,
+                             int num_buffers)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_context *obj_context = CONTEXT(context);
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    int i;
+    VADriverContextP pdrvctx;
+    struct object_buffer *obj_buffer;
+
+    if (obj_context == NULL)
+        return VA_STATUS_ERROR_INVALID_CONTEXT;
+
+    /* When it is not wrapped context, continue the normal flowchart */
+    if (obj_context->wrapper_context == VA_INVALID_ID)
+        return vaStatus;
+
+    if (obj_context->obj_config &&
+        (obj_context->obj_config->profile == VAProfileVP9Profile0)) {
+        vaStatus = i965_decoder_vp9_wrapper_picture(ctx, buffers, num_buffers);
+    } else
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    pdrvctx = i965->wrapper_pdrvctx;
+
+    for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
+        obj_buffer = BUFFER(buffers[i]);
+
+        if (!obj_buffer)
+            continue;
+
+        if (obj_buffer->wrapper_buffer == VA_INVALID_ID) {
+            vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
+            break;
+        }
+
+        CALL_VTABLE(pdrvctx, vaStatus,
+                    vaRenderPicture(pdrvctx, obj_context->wrapper_context,
+                                    &(obj_buffer->wrapper_buffer), 1));
+    }
+    return vaStatus;
+}
+
 static VAStatus 
 i965_decoder_render_picture(VADriverContextP ctx,
                             VAContextID context,
@@ -2366,6 +3110,10 @@ i965_decoder_render_picture(VADriverContextP ctx,
         }
     }
 
+    if ((vaStatus == VA_STATUS_SUCCESS) &&
+        (obj_context->wrapper_context != VA_INVALID_ID))
+        vaStatus = i965_decoder_wrapper_picture(ctx, context, buffers, num_buffers);
+
     return vaStatus;
 }
 
@@ -2377,9 +3125,11 @@ i965_decoder_render_picture(VADriverContextP ctx,
 // 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)
+DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(huffman_table, huffman_table)
 /* 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)
+DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(encmb_map, encmb_map)
 
 #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)
@@ -2450,11 +3200,14 @@ i965_encoder_render_picture(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx); 
     struct object_context *obj_context = CONTEXT(context);
+    struct object_config *obj_config;
     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
     struct encode_state *encode;
     int i;
 
     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
+    obj_config = obj_context->obj_config;
+    ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
 
     encode = &obj_context->codec_state.encode;
     for (i = 0; i < num_buffers; i++) {  
@@ -2480,6 +3233,10 @@ i965_encoder_render_picture(VADriverContextP ctx,
             vaStatus = I965_RENDER_ENCODE_BUFFER(picture_parameter_ext);
             break;
 
+        case VAHuffmanTableBufferType:
+            vaStatus = I965_RENDER_ENCODE_BUFFER(huffman_table);
+            break;
+
         case VAEncSliceParameterBufferType:
             vaStatus = I965_RENDER_ENCODE_BUFFER(slice_parameter_ext);
             if (vaStatus == VA_STATUS_SUCCESS) {
@@ -2487,14 +3244,25 @@ i965_encoder_render_picture(VADriverContextP ctx,
                  * to reallocate the arrays that is used to store
                  * the packed data index/count for the slice
                  */
-                if (encode->max_slice_params_ext > encode->slice_num) {
-                    encode->slice_num = encode->max_slice_params_ext;
+                if (!(encode->packed_header_flag & VA_ENC_PACKED_HEADER_SLICE)) {
+                   encode->slice_index++;
+                }
+                if (encode->slice_index == encode->max_slice_num) {
+                    int slice_num = encode->max_slice_num;
                     encode->slice_rawdata_index = realloc(encode->slice_rawdata_index,
-                                                          encode->slice_num * sizeof(int));
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
                     encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
-                                                          encode->slice_num * sizeof(int));
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
                     encode->slice_header_index = realloc(encode->slice_header_index,
-                                                          encode->slice_num * sizeof(int));
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                    memset(encode->slice_rawdata_index + slice_num, 0,
+                        sizeof(int) * NUM_SLICES);
+                    memset(encode->slice_rawdata_count + slice_num, 0,
+                        sizeof(int) * NUM_SLICES);
+                    memset(encode->slice_header_index + slice_num, 0,
+                        sizeof(int) * NUM_SLICES);
+
+                    encode->max_slice_num += NUM_SLICES;
                     if ((encode->slice_rawdata_index == NULL) ||
                         (encode->slice_header_index == NULL)  ||
                         (encode->slice_rawdata_count == NULL)) {
@@ -2513,6 +3281,12 @@ i965_encoder_render_picture(VADriverContextP ctx,
             if ((param->type == VAEncPackedHeaderRawData) ||
                 (param->type == VAEncPackedHeaderSlice)) {
                 vaStatus = I965_RENDER_ENCODE_BUFFER(packed_header_params_ext);
+            } else if((obj_config->profile == VAProfileHEVCMain) &&
+                (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
+                vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
+                                                                          obj_context,
+                                                                          obj_buffer,
+                                                                          va_enc_packed_type_to_idx(encode->last_packed_header_type) + encode->vps_sps_seq_index);
             } else {
                 vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
                                                                           obj_context,
@@ -2529,23 +3303,71 @@ i965_encoder_render_picture(VADriverContextP ctx,
                 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
                 return vaStatus;
             }
+
             if (encode->last_packed_header_type == VAEncPackedHeaderRawData ||
                 encode->last_packed_header_type == VAEncPackedHeaderSlice) {
                 vaStatus = I965_RENDER_ENCODE_BUFFER(packed_header_data_ext);
-                if (vaStatus == VA_STATUS_SUCCESS) {
+
+                if (obj_config->profile == VAProfileVP9Profile0)
+                    break;
+
+                /* When the PACKED_SLICE_HEADER flag is passed, it will use
+                 * the packed_slice_header as the delimeter to decide how
+                 * the packed rawdata is inserted for the given slice.
+                 * Otherwise it will use the VAEncSequenceParameterBuffer
+                 * as the delimeter
+                 */
+                if (encode->packed_header_flag & VA_ENC_PACKED_HEADER_SLICE) {
                     /* store the first index of the packed header data for current slice */
-                    if (encode->slice_rawdata_index[encode->num_slice_params_ext] == 0) {
-                        encode->slice_rawdata_index[encode->num_slice_params_ext] =
-                             SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
+                    if (encode->slice_rawdata_index[encode->slice_index] == 0) {
+                        encode->slice_rawdata_index[encode->slice_index] =
+                            SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
                     }
-                    encode->slice_rawdata_count[encode->num_slice_params_ext]++;
+                    encode->slice_rawdata_count[encode->slice_index]++;
                     if (encode->last_packed_header_type == VAEncPackedHeaderSlice) {
-                        if (encode->slice_header_index[encode->num_slice_params_ext] == 0) {
-                            encode->slice_header_index[encode->num_slice_params_ext] =
+                        /* find one packed slice_header delimeter. And the following
+                         * packed data is for the next slice
+                         */
+                        encode->slice_header_index[encode->slice_index] =
+                            SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
+                        encode->slice_index++;
+                        /* Reallocate the buffer to record the index/count of
+                         * packed_data for one slice.
+                         */
+                        if (encode->slice_index == encode->max_slice_num) {
+                            int slice_num = encode->max_slice_num;
+
+                            encode->slice_rawdata_index = realloc(encode->slice_rawdata_index,
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                            encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                            encode->slice_header_index = realloc(encode->slice_header_index,
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                            memset(encode->slice_rawdata_index + slice_num, 0,
+                                   sizeof(int) * NUM_SLICES);
+                            memset(encode->slice_rawdata_count + slice_num, 0,
+                                   sizeof(int) * NUM_SLICES);
+                            memset(encode->slice_header_index + slice_num, 0,
+                                   sizeof(int) * NUM_SLICES);
+                            encode->max_slice_num += NUM_SLICES;
+                        }
+                    }
+                } else {
+                    if (vaStatus == VA_STATUS_SUCCESS) {
+                        /* store the first index of the packed header data for current slice */
+                        if (encode->slice_rawdata_index[encode->slice_index] == 0) {
+                            encode->slice_rawdata_index[encode->slice_index] =
                                 SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
-                        } else {
-                            WARN_ONCE("Multi slice header data is passed for"
-                                      " slice %d!\n", encode->num_slice_params_ext);
+                        }
+                        encode->slice_rawdata_count[encode->slice_index]++;
+                        if (encode->last_packed_header_type == VAEncPackedHeaderSlice) {
+                            if (encode->slice_header_index[encode->slice_index] == 0) {
+                                encode->slice_header_index[encode->slice_index] =
+                                    SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
+                            } else {
+                                WARN_ONCE("Multi slice header data is passed for"
+                                      " slice %d!\n", encode->slice_index);
+                            }
                         }
                     }
                 }
@@ -2556,10 +3378,22 @@ i965_encoder_render_picture(VADriverContextP ctx,
                    (((encode->last_packed_header_type & VAEncPackedHeaderMiscMask) == VAEncPackedHeaderMiscMask) &&
                     ((encode->last_packed_header_type & (~VAEncPackedHeaderMiscMask)) != 0)),
                     VA_STATUS_ERROR_ENCODING_ERROR);
-                vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
-                                                                     obj_context,
-                                                                     obj_buffer,
-                                                                     va_enc_packed_type_to_idx(encode->last_packed_header_type));
+
+                if((obj_config->profile == VAProfileHEVCMain) &&
+                    (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
+
+                        vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
+                            obj_context,
+                            obj_buffer,
+                            va_enc_packed_type_to_idx(encode->last_packed_header_type) + encode->vps_sps_seq_index);
+                        encode->vps_sps_seq_index = (encode->vps_sps_seq_index + 1) % I965_SEQ_PACKED_HEADER_END;
+                }else{
+                    vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
+                        obj_context,
+                        obj_buffer,
+                        va_enc_packed_type_to_idx(encode->last_packed_header_type));
+
+                }
             }
             encode->last_packed_header_type = 0;
             break;       
@@ -2571,6 +3405,10 @@ i965_encoder_render_picture(VADriverContextP ctx,
                                                                  obj_buffer);
             break;
             
+        case VAEncMacroblockMapBufferType:
+            vaStatus = I965_RENDER_ENCODE_BUFFER(encmb_map);
+            break;
+
         default:
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
             break;
@@ -2640,7 +3478,9 @@ i965_RenderPicture(VADriverContextP ctx,
 
     if (VAEntrypointVideoProc == obj_config->entrypoint) {
         vaStatus = i965_proc_render_picture(ctx, context, buffers, num_buffers);
-    } else if (VAEntrypointEncSlice == obj_config->entrypoint ) {
+    } else if ((VAEntrypointEncSlice == obj_config->entrypoint ) || 
+               (VAEntrypointEncPicture == obj_config->entrypoint) ||
+               (VAEntrypointEncSliceLP == obj_config->entrypoint)) {
         vaStatus = i965_encoder_render_picture(ctx, context, buffers, num_buffers);
     } else {
         vaStatus = i965_decoder_render_picture(ctx, context, buffers, num_buffers);
@@ -2663,7 +3503,10 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
     if (obj_context->codec_type == CODEC_PROC) {
         ASSERT_RET(VAEntrypointVideoProc == obj_config->entrypoint, VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT);
     } else if (obj_context->codec_type == CODEC_ENC) {
-        ASSERT_RET(VAEntrypointEncSlice == obj_config->entrypoint, VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT);
+        ASSERT_RET(((VAEntrypointEncSlice == obj_config->entrypoint) ||
+                    (VAEntrypointEncPicture == obj_config->entrypoint) ||
+                    (VAEntrypointEncSliceLP == obj_config->entrypoint)),
+                   VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT);
 
         if (obj_context->codec_state.encode.num_packed_header_params_ext !=
                obj_context->codec_state.encode.num_packed_header_data_ext) {
@@ -2675,11 +3518,24 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
         if (!(obj_context->codec_state.encode.seq_param ||
-                obj_context->codec_state.encode.seq_param_ext)) {
-            return VA_STATUS_ERROR_INVALID_PARAMETER;
+                obj_context->codec_state.encode.seq_param_ext) &&
+                (VAEntrypointEncPicture != obj_config->entrypoint)) {
+            /* The seq_param is not mandatory for VP9 encoding */
+            if (obj_config->profile != VAProfileVP9Profile0)
+                return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
         if ((obj_context->codec_state.encode.num_slice_params <=0) &&
-                (obj_context->codec_state.encode.num_slice_params_ext <=0)) {
+                (obj_context->codec_state.encode.num_slice_params_ext <=0) &&
+                ((obj_config->profile != VAProfileVP8Version0_3) &&
+                 (obj_config->profile != VAProfileVP9Profile0))) {
+            return VA_STATUS_ERROR_INVALID_PARAMETER;
+        }
+
+        if ((obj_context->codec_state.encode.packed_header_flag & VA_ENC_PACKED_HEADER_SLICE) &&
+            (obj_context->codec_state.encode.num_slice_params_ext !=
+             obj_context->codec_state.encode.slice_index)) {
+            WARN_ONCE("packed slice_header data is missing for some slice"
+                      " under packed SLICE_HEADER mode\n");
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
     } else {
@@ -2697,6 +3553,18 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
                 obj_context->codec_state.decode.num_slice_datas) {
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
+
+        if (obj_context->wrapper_context != VA_INVALID_ID) {
+            /* call the vaEndPicture of wrapped driver */
+            VADriverContextP pdrvctx;
+            VAStatus va_status;
+
+            pdrvctx = i965->wrapper_pdrvctx;
+            CALL_VTABLE(pdrvctx, va_status,
+                        vaEndPicture(pdrvctx, obj_context->wrapper_context));
+
+            return va_status;
+        }
     }
 
     ASSERT_RET(obj_context->hw_context->run, VA_STATUS_ERROR_OPERATION_FAILED);
@@ -2963,10 +3831,10 @@ i965_CreateImage(VADriverContextP ctx,
     awidth = ALIGN(width, i965->codec_info->min_linear_wpitch);
 
     if ((format->fourcc == VA_FOURCC_YV12) ||
-               (format->fourcc == VA_FOURCC_I420)) {
-       if (awidth % 128 != 0) {
-               awidth = ALIGN(width, 128);     
-       }
+        (format->fourcc == VA_FOURCC_I420)) {
+            if (awidth % 128 != 0) {
+                awidth = ALIGN(width, 128);    
+            }
     }
 
     aheight = ALIGN(height, i965->codec_info->min_linear_hpitch);
@@ -3058,6 +3926,14 @@ i965_CreateImage(VADriverContextP ctx,
         image->offsets[0] = 0;
         image->data_size  = size * 2;
         break;
+    case VA_FOURCC_P010:
+        image->num_planes = 2;
+        image->pitches[0] = awidth * 2;
+        image->offsets[0] = 0;
+        image->pitches[1] = awidth * 2;
+        image->offsets[1] = size * 2;
+        image->data_size  = size * 2 + 2 * size2 * 2;
+        break;
     default:
         goto error;
     }
@@ -3116,25 +3992,29 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
     obj_surface->x_cb_offset = 0; /* X offset is always 0 */
     obj_surface->x_cr_offset = 0;
 
+    int bpp_1stplane = bpp_1stplane_by_fourcc(fourcc);
+
     if ((tiled && !obj_surface->user_disable_tiling)) {
         ASSERT_RET(fourcc != VA_FOURCC_I420 &&
                fourcc != VA_FOURCC_IYUV &&
                fourcc != VA_FOURCC_YV12,
                VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT);
+
         if (obj_surface->user_h_stride_set) {
-            ASSERT_RET(IS_ALIGNED(obj_surface->width, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+           ASSERT_RET(IS_ALIGNED(obj_surface->width, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
         } else
-            obj_surface->width = ALIGN(obj_surface->orig_width, 128);
+          obj_surface->width = ALIGN(obj_surface->orig_width * bpp_1stplane, 128);
 
         if (obj_surface->user_v_stride_set) {
-            ASSERT_RET(IS_ALIGNED(obj_surface->height, 32), VA_STATUS_ERROR_INVALID_PARAMETER);
-        } else
-            obj_surface->height = ALIGN(obj_surface->orig_height, 32);
+          ASSERT_RET(IS_ALIGNED(obj_surface->height, 32), VA_STATUS_ERROR_INVALID_PARAMETER);
+        }else
+          obj_surface->height = ALIGN(obj_surface->orig_height, 32);
 
         region_height = obj_surface->height;
 
         switch (fourcc) {
         case VA_FOURCC_NV12:
+        case VA_FOURCC_P010:
             assert(subsampling == SUBSAMPLE_YUV420);
             obj_surface->cb_cr_pitch = obj_surface->width;
             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
@@ -3271,6 +4151,7 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
 
         switch (fourcc) {
         case VA_FOURCC_NV12:
+        case VA_FOURCC_P010:
             obj_surface->y_cb_offset = obj_surface->height;
             obj_surface->y_cr_offset = obj_surface->height;
             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
@@ -3418,7 +4299,10 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
 
     image->format.fourcc = obj_surface->fourcc;
     image->format.byte_order = VA_LSB_FIRST;
-    image->format.bits_per_pixel = 12;
+    image->format.bits_per_pixel = get_bpp_from_fourcc(obj_surface->fourcc);
+
+    if (!image->format.bits_per_pixel)
+        goto error;
 
     switch (image->format.fourcc) {
     case VA_FOURCC_YV12:
@@ -3442,6 +4326,7 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
         break;
 
     case VA_FOURCC_NV12:
+    case VA_FOURCC_P010:
         image->num_planes = 2;
         image->pitches[0] = w_pitch; /* Y */
         image->offsets[0] = 0;
@@ -3477,6 +4362,39 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
     case VA_FOURCC_BGRX:
         image->num_planes = 1;
         image->pitches[0] = obj_surface->width;
+
+        switch (image->format.fourcc) {
+        case VA_FOURCC_RGBA:
+        case VA_FOURCC_RGBX:
+            image->format.red_mask = 0x000000ff;
+            image->format.green_mask = 0x0000ff00;
+            image->format.blue_mask = 0x00ff0000;
+            break;
+        case VA_FOURCC_BGRA:
+        case VA_FOURCC_BGRX:
+            image->format.red_mask = 0x00ff0000;
+            image->format.green_mask = 0x0000ff00;
+            image->format.blue_mask = 0x000000ff;
+            break;
+        default:
+            goto error;
+        }
+
+        switch (image->format.fourcc) {
+        case VA_FOURCC_RGBA:
+        case VA_FOURCC_BGRA:
+            image->format.alpha_mask = 0xff000000;
+            image->format.depth = 32;
+            break;
+        case VA_FOURCC_RGBX:
+        case VA_FOURCC_BGRX:
+            image->format.alpha_mask = 0x00000000;
+            image->format.depth = 24;
+            break;
+        default:
+            goto error;
+        }
+
         break;
     default:
         goto error;
@@ -3507,6 +4425,7 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
 
     *out_image = *image;
     obj_surface->flags |= SURFACE_DERIVED;
+    obj_surface->derived_image_id = image_id;
     obj_image->derived_surface = surface;
 
     return VA_STATUS_SUCCESS;
@@ -3550,6 +4469,7 @@ i965_DestroyImage(VADriverContextP ctx, VAImageID image)
 
     if (obj_surface) {
         obj_surface->flags &= ~SURFACE_DERIVED;
+        obj_surface->derived_image_id = VA_INVALID_ID;
     }
 
     i965_destroy_image(&i965->image_heap, (struct object_base *)obj_image);
@@ -3768,73 +4688,35 @@ get_image_yuy2(struct object_image *obj_image, uint8_t *image_data,
 
 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 object_surface *obj_surface, struct object_image *obj_image,
+    const VARectangle *rect)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx);
-    struct i965_render_state *render_state = &i965->render_state;
-    VAStatus va_status = VA_STATUS_SUCCESS;
-
-    struct object_surface *obj_surface = SURFACE(surface);
-    if (!obj_surface)
-        return VA_STATUS_ERROR_INVALID_SURFACE;
-
-    struct object_image *obj_image = IMAGE(image);
-    if (!obj_image)
-        return VA_STATUS_ERROR_INVALID_IMAGE;
-
-    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;
+    void *image_data = NULL;
+    VAStatus va_status;
 
     if (obj_surface->fourcc != obj_image->image.format.fourcc)
         return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
 
-    void *image_data = NULL;
-
     va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
     if (va_status != VA_STATUS_SUCCESS)
         return va_status;
 
-    VARectangle rect;
-    rect.x = x;
-    rect.y = y;
-    rect.width = width;
-    rect.height = height;
-
     switch (obj_image->image.format.fourcc) {
     case VA_FOURCC_YV12:
     case VA_FOURCC_I420:
-        /* I420 is native format for MPEG-2 decoded surfaces */
-        if (render_state->interleaved_uv)
-            goto operation_failed;
-        get_image_i420(obj_image, image_data, obj_surface, &rect);
+        get_image_i420(obj_image, image_data, obj_surface, rect);
         break;
     case VA_FOURCC_NV12:
-        /* NV12 is native format for H.264 decoded surfaces */
-        if (!render_state->interleaved_uv)
-            goto operation_failed;
-        get_image_nv12(obj_image, image_data, obj_surface, &rect);
+        get_image_nv12(obj_image, image_data, obj_surface, rect);
         break;
     case VA_FOURCC_YUY2:
         /* YUY2 is the format supported by overlay plane */
-        get_image_yuy2(obj_image, image_data, obj_surface, &rect);
+        get_image_yuy2(obj_image, image_data, obj_surface, rect);
         break;
     default:
-    operation_failed:
         va_status = VA_STATUS_ERROR_OPERATION_FAILED;
         break;
     }
-
     if (va_status != VA_STATUS_SUCCESS)
         return va_status;
 
@@ -3844,44 +4726,11 @@ i965_sw_getimage(VADriverContextP ctx,
 
 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)
+    struct object_surface *obj_surface, struct object_image *obj_image,
+    const VARectangle *rect)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct i965_surface src_surface;
     struct i965_surface dst_surface;
-    VAStatus va_status = VA_STATUS_SUCCESS;
-    VARectangle rect;
-    struct object_surface *obj_surface = SURFACE(surface);
-    struct object_image *obj_image = IMAGE(image);
-
-    if (!obj_surface)
-        return VA_STATUS_ERROR_INVALID_SURFACE;
-
-    if (!obj_image)
-        return VA_STATUS_ERROR_INVALID_IMAGE;
-
-    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;
@@ -3891,14 +4740,7 @@ i965_hw_getimage(VADriverContextP ctx,
     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;
+    return i965_image_processing(ctx, &src_surface, rect, &dst_surface, rect);
 }
 
 VAStatus 
@@ -3911,20 +4753,41 @@ i965_GetImage(VADriverContextP ctx,
               VAImageID image)
 {
     struct i965_driver_data * const i965 = i965_driver_data(ctx);
-    VAStatus va_status = VA_STATUS_SUCCESS;
+    struct object_surface * const obj_surface = SURFACE(surface);
+    struct object_image * const obj_image = IMAGE(image);
+    VARectangle rect;
+    VAStatus va_status;
+
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+    if (!obj_surface->bo) /* don't get anything, keep previous data */
+        return VA_STATUS_SUCCESS;
+    if (is_surface_busy(i965, obj_surface))
+        return VA_STATUS_ERROR_SURFACE_BUSY;
+
+    if (!obj_image || !obj_image->bo)
+        return VA_STATUS_ERROR_INVALID_IMAGE;
+    if (is_image_busy(i965, obj_image, surface))
+        return VA_STATUS_ERROR_SURFACE_BUSY;
+
+    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;
+
+    rect.x = x;
+    rect.y = y;
+    rect.width = width;
+    rect.height = height;
 
     if (HAS_ACCELERATED_GETIMAGE(i965))
-        va_status = i965_hw_getimage(ctx,
-                                     surface,
-                                     x, y,
-                                     width, height,
-                                     image);
+        va_status = i965_hw_getimage(ctx, obj_surface, obj_image, &rect);
     else
-        va_status = i965_sw_getimage(ctx,
-                                     surface,
-                                     x, y,
-                                     width, height,
-                                     image);
+        va_status = i965_sw_getimage(ctx, obj_surface, obj_image, &rect);
 
     return va_status;
 }
@@ -4092,42 +4955,17 @@ put_image_yuy2(struct object_surface *obj_surface,
     return va_status;
 }
 
-
 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 object_surface *obj_surface, struct object_image *obj_image,
+    const VARectangle *src_rect, const VARectangle *dst_rect)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx);
-    struct object_surface *obj_surface = SURFACE(surface);
-    struct object_image *obj_image = IMAGE(image);
     VAStatus va_status = VA_STATUS_SUCCESS;
     void *image_data = NULL;
 
-    ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
-    ASSERT_RET(obj_image, VA_STATUS_ERROR_INVALID_IMAGE);
-
-    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;
-
     /* XXX: don't allow scaling */
-    if (src_width != dest_width || src_height != dest_height)
+    if (src_rect->width != dst_rect->width ||
+        src_rect->height != dst_rect->height)
         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
     if (obj_surface->fourcc) {
@@ -4152,27 +4990,17 @@ i965_sw_putimage(VADriverContextP ctx,
     va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
     if (va_status != VA_STATUS_SUCCESS)
         return va_status;
-
-    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_YV12:
     case VA_FOURCC_I420:
-        va_status = put_image_i420(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
+        va_status = put_image_i420(obj_surface, dst_rect, obj_image, image_data, src_rect);
         break;
     case VA_FOURCC_NV12:
-        va_status = put_image_nv12(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
+        va_status = put_image_nv12(obj_surface, dst_rect, obj_image, image_data, src_rect);
         break;
     case VA_FOURCC_YUY2:
-        va_status = put_image_yuy2(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
+        va_status = put_image_yuy2(obj_surface, dst_rect, obj_image, image_data, src_rect);
         break;
     default:
         va_status = VA_STATUS_ERROR_OPERATION_FAILED;
@@ -4187,38 +5015,11 @@ i965_sw_putimage(VADriverContextP ctx,
 
 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 object_surface *obj_surface, struct object_image *obj_image,
+    const VARectangle *src_rect, const VARectangle *dst_rect)
 {
-    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;
-
-    ASSERT_RET(obj_surface,VA_STATUS_ERROR_INVALID_SURFACE);
-    ASSERT_RET(obj_image && obj_image->bo, 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;
@@ -4237,24 +5038,16 @@ i965_hw_putimage(VADriverContextP ctx,
     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,
+                                      src_rect,
                                       &dst_surface,
-                                      &dst_rect);
+                                      dst_rect);
 
     return  va_status;
 }
@@ -4272,33 +5065,50 @@ i965_PutImage(VADriverContextP ctx,
               unsigned int dest_width,
               unsigned int dest_height)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx);
-    VAStatus va_status = VA_STATUS_SUCCESS;
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct object_surface * const obj_surface = SURFACE(surface);
+    struct object_image * const obj_image = IMAGE(image);
+    VARectangle src_rect, dst_rect;
+    VAStatus va_status;
+
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+    if (is_surface_busy(i965, obj_surface))
+        return VA_STATUS_ERROR_SURFACE_BUSY;
+
+    if (!obj_image || !obj_image->bo)
+        return VA_STATUS_ERROR_INVALID_IMAGE;
+    if (is_image_busy(i965, obj_image, surface))
+        return VA_STATUS_ERROR_SURFACE_BUSY;
+
+    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;
+
+    src_rect.x       = src_x;
+    src_rect.y       = src_y;
+    src_rect.width   = src_width;
+    src_rect.height  = src_height;
+
+    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;
+
+    dst_rect.x      = dest_x;
+    dst_rect.y      = dest_y;
+    dst_rect.width  = dest_width;
+    dst_rect.height = dest_height;
 
     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);
+        va_status = i965_hw_putimage(ctx, obj_surface, obj_image,
+            &src_rect, &dst_rect);
     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);
+        va_status = i965_sw_putimage(ctx, obj_surface, obj_image,
+            &src_rect, &dst_rect);
 
     return va_status;
 }
@@ -4552,7 +5362,8 @@ i965_GetSurfaceAttributes(
                 } else if (IS_GEN6(i965->intel.device_info)) {
                     attrib_list[i].value.value.i = VA_FOURCC_NV12;
                 } else if (IS_GEN7(i965->intel.device_info) ||
-                           IS_GEN8(i965->intel.device_info)) {
+                           IS_GEN8(i965->intel.device_info) ||
+                           IS_GEN9(i965->intel.device_info)) {
                     if (obj_config->profile == VAProfileJPEGBaseline)
                         attrib_list[i].value.value.i = 0; /* internal format */
                     else
@@ -4629,9 +5440,11 @@ i965_GetSurfaceAttributes(
                         }
                     }
                 } else if (IS_GEN7(i965->intel.device_info) ||
-                           IS_GEN8(i965->intel.device_info)) {
+                           IS_GEN8(i965->intel.device_info) ||
+                           IS_GEN9(i965->intel.device_info)) {
                     if (obj_config->entrypoint == VAEntrypointEncSlice ||
-                        obj_config->entrypoint == VAEntrypointVideoProc) {
+                        obj_config->entrypoint == VAEntrypointVideoProc ||
+                        obj_config->entrypoint == VAEntrypointEncSliceLP) {
                         switch (attrib_list[i].value.value.i) {
                         case VA_FOURCC_NV12:
                         case VA_FOURCC_I420:
@@ -4690,7 +5503,9 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
     struct object_config *obj_config;
     int i = 0;
     VASurfaceAttrib *attribs = NULL;
-    
+    int max_width;
+    int max_height;
+
     if (config == VA_INVALID_ID)
         return VA_STATUS_ERROR_INVALID_CONFIG;
 
@@ -4851,7 +5666,13 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
                 attribs[i].value.value.i = VA_FOURCC_444P;
                 i++;
-            } else {
+            } else if (obj_config->profile == VAProfileHEVCMain10) {
+                attribs[i].type = VASurfaceAttribPixelFormat;
+                attribs[i].value.type = VAGenericValueTypeInteger;
+                attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+                attribs[i].value.value.i = VA_FOURCC_P010;
+                i++;
+             } else {
                 attribs[i].type = VASurfaceAttribPixelFormat;
                 attribs[i].value.type = VAGenericValueTypeInteger;
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
@@ -4906,11 +5727,24 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 attribs[i].type = VASurfaceAttribPixelFormat;
                 attribs[i].value.type = VAGenericValueTypeInteger;
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+                attribs[i].value.value.i = VA_FOURCC_BGRA;
+                i++;
+
+                attribs[i].type = VASurfaceAttribPixelFormat;
+                attribs[i].value.type = VAGenericValueTypeInteger;
+                attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+                attribs[i].value.value.i = VA_FOURCC_BGRX;
+                i++;
+
+                attribs[i].type = VASurfaceAttribPixelFormat;
+                attribs[i].value.type = VAGenericValueTypeInteger;
+                attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
                 attribs[i].value.value.i = VA_FOURCC_YV16;
                 i++;
             }
         }
-    } else if (IS_GEN8(i965->intel.device_info)) {
+    } else if (IS_GEN8(i965->intel.device_info) ||
+               IS_GEN9(i965->intel.device_info)) {
         if (obj_config->entrypoint == VAEntrypointVLD) { /* decode */
             if (obj_config->profile == VAProfileJPEGBaseline) {
                 attribs[i].type = VASurfaceAttribPixelFormat;
@@ -4962,31 +5796,40 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 i++;
             }
         } else if (obj_config->entrypoint == VAEntrypointEncSlice ||  /* encode */
-                   obj_config->entrypoint == VAEntrypointVideoProc) { /* vpp */
-
-            attribs[i].type = VASurfaceAttribPixelFormat;
-            attribs[i].value.type = VAGenericValueTypeInteger;
-            attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
-            attribs[i].value.value.i = VA_FOURCC_NV12;
-            i++;
-
-            attribs[i].type = VASurfaceAttribPixelFormat;
-            attribs[i].value.type = VAGenericValueTypeInteger;
-            attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
-            attribs[i].value.value.i = VA_FOURCC_I420;
-            i++;
+                   obj_config->entrypoint == VAEntrypointVideoProc ||
+                   obj_config->entrypoint == VAEntrypointEncSliceLP) {
 
-            attribs[i].type = VASurfaceAttribPixelFormat;
-            attribs[i].value.type = VAGenericValueTypeInteger;
-            attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
-            attribs[i].value.value.i = VA_FOURCC_YV12;
-            i++;
-
-            attribs[i].type = VASurfaceAttribPixelFormat;
-            attribs[i].value.type = VAGenericValueTypeInteger;
-            attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
-            attribs[i].value.value.i = VA_FOURCC_IMC3;
-            i++;
+            if (obj_config->profile == VAProfileHEVCMain10) {
+                attribs[i].type = VASurfaceAttribPixelFormat;
+                attribs[i].value.type = VAGenericValueTypeInteger;
+                attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+                attribs[i].value.value.i = VA_FOURCC_P010;
+                i++;
+            } else {
+              attribs[i].type = VASurfaceAttribPixelFormat;
+              attribs[i].value.type = VAGenericValueTypeInteger;
+              attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+              attribs[i].value.value.i = VA_FOURCC_NV12;
+              i++;
+
+              attribs[i].type = VASurfaceAttribPixelFormat;
+              attribs[i].value.type = VAGenericValueTypeInteger;
+              attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+              attribs[i].value.value.i = VA_FOURCC_I420;
+              i++;
+
+              attribs[i].type = VASurfaceAttribPixelFormat;
+              attribs[i].value.type = VAGenericValueTypeInteger;
+              attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+              attribs[i].value.value.i = VA_FOURCC_YV12;
+              i++;
+
+              attribs[i].type = VASurfaceAttribPixelFormat;
+              attribs[i].value.type = VAGenericValueTypeInteger;
+              attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+              attribs[i].value.value.i = VA_FOURCC_IMC3;
+              i++;
+            }
 
             if (obj_config->entrypoint == VAEntrypointVideoProc) {
                 attribs[i].type = VASurfaceAttribPixelFormat;
@@ -5024,6 +5867,14 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
                 attribs[i].value.value.i = VA_FOURCC_YV16;
                 i++;
+
+                if(HAS_VPP_P010(i965)) {
+                  attribs[i].type = VASurfaceAttribPixelFormat;
+                  attribs[i].value.type = VAGenericValueTypeInteger;
+                  attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+                  attribs[i].value.value.i = VA_FOURCC_P010;
+                  i++;
+                }
             }
         }
     }
@@ -5042,6 +5893,20 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
     attribs[i].value.value.p = NULL; /* ignore */
     i++;
 
+    max_resolution(i965, obj_config, &max_width, &max_height);
+
+    attribs[i].type = VASurfaceAttribMaxWidth;
+    attribs[i].value.type = VAGenericValueTypeInteger;
+    attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
+    attribs[i].value.value.i = max_width;
+    i++;
+
+    attribs[i].type = VASurfaceAttribMaxHeight;
+    attribs[i].value.type = VAGenericValueTypeInteger;
+    attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
+    attribs[i].value.value.i = max_height;
+    i++;
+
     if (i > *num_attribs) {
         *num_attribs = i;
         free(attribs);
@@ -5055,6 +5920,144 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
     return vaStatus;
 }
 
+/* Acquires buffer handle for external API usage (internal implementation) */
+static VAStatus
+i965_acquire_buffer_handle(struct object_buffer *obj_buffer,
+    uint32_t mem_type, VABufferInfo *out_buf_info)
+{
+    struct buffer_store *buffer_store;
+
+    buffer_store = obj_buffer->buffer_store;
+    if (!buffer_store || !buffer_store->bo)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
+    /* Synchronization point */
+    drm_intel_bo_wait_rendering(buffer_store->bo);
+
+    if (obj_buffer->export_refcount > 0) {
+        if (obj_buffer->export_state.mem_type != mem_type)
+            return VA_STATUS_ERROR_INVALID_PARAMETER;
+    }
+    else {
+        VABufferInfo * const buf_info = &obj_buffer->export_state;
+
+        switch (mem_type) {
+        case VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM: {
+            uint32_t name;
+            if (drm_intel_bo_flink(buffer_store->bo, &name) != 0)
+                return VA_STATUS_ERROR_INVALID_BUFFER;
+            buf_info->handle = name;
+            break;
+        }
+        case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
+            int fd;
+            if (drm_intel_bo_gem_export_to_prime(buffer_store->bo, &fd) != 0)
+                return VA_STATUS_ERROR_INVALID_BUFFER;
+            buf_info->handle = (intptr_t)fd;
+            break;
+        }
+        }
+
+        buf_info->type = obj_buffer->type;
+        buf_info->mem_type = mem_type;
+        buf_info->mem_size =
+            obj_buffer->num_elements * obj_buffer->size_element;
+    }
+
+    obj_buffer->export_refcount++;
+    *out_buf_info = obj_buffer->export_state;
+    return VA_STATUS_SUCCESS;
+}
+
+/* Releases buffer handle after usage (internal implementation) */
+static VAStatus
+i965_release_buffer_handle(struct object_buffer *obj_buffer)
+{
+    if (obj_buffer->export_refcount == 0)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
+    if (--obj_buffer->export_refcount == 0) {
+        VABufferInfo * const buf_info = &obj_buffer->export_state;
+
+        switch (buf_info->mem_type) {
+        case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
+            close((intptr_t)buf_info->handle);
+            break;
+        }
+        }
+        buf_info->mem_type = 0;
+    }
+    return VA_STATUS_SUCCESS;
+}
+
+/** Acquires buffer handle for external API usage */
+static VAStatus
+i965_AcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
+    VABufferInfo *buf_info)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct object_buffer * const obj_buffer = BUFFER(buf_id);
+    uint32_t i, mem_type;
+
+    /* List of supported memory types, in preferred order */
+    static const uint32_t mem_types[] = {
+        VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
+        VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM,
+        0
+    };
+
+    if (!obj_buffer)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+    /* XXX: only VA surface|image like buffers are supported for now */
+    if (obj_buffer->type != VAImageBufferType)
+        return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
+
+    /*
+     * As the allocated buffer by calling vaCreateBuffer is related with
+     * the specific context, it is unnecessary to export it.
+     * So it is not supported when the buffer is allocated from wrapped
+     * backend dirver.
+     */
+    if (obj_buffer->wrapper_buffer != VA_INVALID_ID) {
+        return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
+    }
+
+    if (!buf_info)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if (!buf_info->mem_type)
+        mem_type = mem_types[0];
+    else {
+        mem_type = 0;
+        for (i = 0; mem_types[i] != 0; i++) {
+            if (buf_info->mem_type & mem_types[i]) {
+                mem_type = buf_info->mem_type;
+                break;
+            }
+        }
+        if (!mem_type)
+            return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
+    }
+    return i965_acquire_buffer_handle(obj_buffer, mem_type, buf_info);
+}
+
+/** Releases buffer handle after usage from external API */
+static VAStatus
+i965_ReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct object_buffer * const obj_buffer = BUFFER(buf_id);
+
+    if (!obj_buffer)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
+    if (obj_buffer->wrapper_buffer != VA_INVALID_ID) {
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+    }
+
+    return i965_release_buffer_handle(obj_buffer);
+}
+
 static int
 i965_os_has_ring_support(VADriverContextP ctx,
                          int ring)
@@ -5294,7 +6297,7 @@ VAStatus i965_QueryVideoProcPipelineCaps(
                    VA_STATUS_ERROR_INVALID_PARAMETER);
             
             if (deint->algorithm == VAProcDeinterlacingMotionAdaptive ||
-                deint->algorithm == VAProcDeinterlacingMotionCompensated);
+                deint->algorithm == VAProcDeinterlacingMotionCompensated)
                 pipeline_cap->num_forward_references++;
         } else if (base->type == VAProcFilterSkinToneEnhancement) {
                 VAProcFilterParameterBuffer *stde = (VAProcFilterParameterBuffer *)base;
@@ -5305,7 +6308,7 @@ VAStatus i965_QueryVideoProcPipelineCaps(
     return VA_STATUS_SUCCESS;
 }
 
-extern const struct hw_codec_info *i965_get_codec_info(int devid);
+extern struct hw_codec_info *i965_get_codec_info(int devid);
 
 static bool
 i965_driver_data_init(VADriverContextP ctx)
@@ -5439,6 +6442,166 @@ struct {
 #endif
 };
 
+static bool
+ensure_vendor_string(struct i965_driver_data *i965, const char *chipset)
+{
+    int ret, len;
+
+    if (i965->va_vendor[0] != '\0')
+        return true;
+
+    len = 0;
+    ret = snprintf(i965->va_vendor, sizeof(i965->va_vendor),
+        "%s %s driver for %s - %d.%d.%d",
+        INTEL_STR_DRIVER_VENDOR, INTEL_STR_DRIVER_NAME, chipset,
+        INTEL_DRIVER_MAJOR_VERSION, INTEL_DRIVER_MINOR_VERSION,
+        INTEL_DRIVER_MICRO_VERSION);
+    if (ret < 0 || ret >= sizeof(i965->va_vendor))
+        goto error;
+    len = ret;
+
+    if (INTEL_DRIVER_PRE_VERSION > 0) {
+        ret = snprintf(&i965->va_vendor[len], sizeof(i965->va_vendor) - len,
+            ".pre%d", INTEL_DRIVER_PRE_VERSION);
+        if (ret < 0 || ret >= sizeof(i965->va_vendor))
+            goto error;
+        len += ret;
+
+        ret = snprintf(&i965->va_vendor[len], sizeof(i965->va_vendor) - len,
+            " (%s)", INTEL_DRIVER_GIT_VERSION);
+        if (ret < 0 || ret >= sizeof(i965->va_vendor))
+            goto error;
+        len += ret;
+    }
+    return true;
+
+error:
+    i965->va_vendor[0] = '\0';
+    ASSERT_RET(ret > 0 && len < sizeof(i965->va_vendor), false);
+    return false;
+}
+
+/* Only when the option of "enable-wrapper" is passed, it is possible
+ * to initialize/load the wrapper context of backend driver.
+ * Otherwise it is not loaded.
+ */
+#if HAVE_HYBRID_CODEC
+
+static VAStatus
+i965_initialize_wrapper(VADriverContextP ctx, const char *driver_name)
+{
+#define DRIVER_EXTENSION       "_drv_video.so"
+
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+
+    VADriverContextP wrapper_pdrvctx;
+    struct VADriverVTable *vtable;
+    char *search_path, *driver_dir;
+    char *saveptr;
+    char driver_path[256];
+    void *handle = NULL;
+    VAStatus va_status = VA_STATUS_SUCCESS;
+    bool driver_loaded = false;
+
+    if (HAS_VP9_DECODING(i965)) {
+        i965->wrapper_pdrvctx = NULL;
+        return va_status;
+    }
+
+    wrapper_pdrvctx = calloc(1, sizeof(*wrapper_pdrvctx));
+    vtable = calloc(1, sizeof(*vtable));
+
+    if (!wrapper_pdrvctx || !vtable) {
+        fprintf(stderr, "Failed to allocate memory for wrapper \n");
+        free(wrapper_pdrvctx);
+        free(vtable);
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+
+    /* use the same drm_state with CTX */
+    wrapper_pdrvctx->drm_state = ctx->drm_state;
+    wrapper_pdrvctx->display_type = ctx->display_type;
+    wrapper_pdrvctx->vtable = vtable;
+
+    search_path = VA_DRIVERS_PATH;
+    search_path = strdup((const char *)search_path);
+
+    driver_dir = strtok_r(search_path, ":", &saveptr);
+    while (driver_dir && !driver_loaded) {
+        memset(driver_path, 0, sizeof(driver_path));
+        sprintf(driver_path, "%s/%s%s", driver_dir, driver_name, DRIVER_EXTENSION);
+
+        handle = dlopen(driver_path, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
+        if (!handle) {
+            fprintf(stderr, "failed to open %s\n", driver_path);
+            driver_dir = strtok_r(NULL, ":", &saveptr);
+            continue;
+        }
+        {
+            VADriverInit init_func = NULL;
+            char init_func_s[256];
+            int i;
+
+            static const struct {
+                int major;
+                int minor;
+            } compatible_versions[] = {
+                { VA_MAJOR_VERSION, VA_MINOR_VERSION },
+                { 0, 37 },
+                { 0, 36 },
+                { 0, 35 },
+                { 0, 34 },
+                { 0, 33 },
+                { 0, 32 },
+                { -1, }
+            };
+            for (i = 0; compatible_versions[i].major >= 0; i++) {
+                snprintf(init_func_s, sizeof(init_func_s),
+                     "__vaDriverInit_%d_%d",
+                     compatible_versions[i].major,
+                     compatible_versions[i].minor);
+                init_func = (VADriverInit)dlsym(handle, init_func_s);
+                if (init_func) {
+                    break;
+                }
+            }
+            if (compatible_versions[i].major < 0) {
+                dlclose(handle);
+                fprintf(stderr, "%s has no function %s\n",
+                            driver_path, init_func_s);
+                driver_dir = strtok_r(NULL, ":", &saveptr);
+                continue;
+            }
+
+            if (init_func)
+                va_status = (*init_func)(wrapper_pdrvctx);
+
+            if (va_status != VA_STATUS_SUCCESS) {
+                dlclose(handle);
+                fprintf(stderr, "%s init failed\n", driver_path);
+                driver_dir = strtok_r(NULL, ":", &saveptr);
+                continue;
+            }
+
+            wrapper_pdrvctx->handle = handle;
+            driver_loaded = true;
+        }
+    }
+
+    free(search_path);
+
+    if (driver_loaded) {
+        i965->wrapper_pdrvctx = wrapper_pdrvctx;
+        return VA_STATUS_SUCCESS;
+    } else {
+        fprintf(stderr, "Failed to wrapper %s%s\n", driver_name, DRIVER_EXTENSION);
+        free(vtable);
+        free(wrapper_pdrvctx);
+        return VA_STATUS_ERROR_OPERATION_FAILED;
+    }
+}
+#endif
+
 static VAStatus 
 i965_Init(VADriverContextP ctx)
 {
@@ -5463,21 +6626,18 @@ i965_Init(VADriverContextP ctx)
             break;
         }
 
-        sprintf(i965->va_vendor, "%s %s driver for %s - %d.%d.%d",
-                INTEL_STR_DRIVER_VENDOR,
-                INTEL_STR_DRIVER_NAME,
-                chipset,
-                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);
-        }
+        if (!ensure_vendor_string(i965, chipset))
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
         i965->current_context_id = VA_INVALID_ID;
 
+        if (i965->codec_info && i965->codec_info->preinit_hw_codec)
+            i965->codec_info->preinit_hw_codec(ctx, i965->codec_info);
+
+#if HAVE_HYBRID_CODEC
+        i965_initialize_wrapper(ctx, "hybrid");
+#endif
+
         return VA_STATUS_SUCCESS;
     } else {
         i--;
@@ -5500,6 +6660,19 @@ i965_Terminate(VADriverContextP ctx)
     int i;
 
     if (i965) {
+        if (i965->wrapper_pdrvctx) {
+            VADriverContextP pdrvctx;
+            pdrvctx = i965->wrapper_pdrvctx;
+            if (pdrvctx->handle) {
+                pdrvctx->vtable->vaTerminate(pdrvctx);
+                dlclose(pdrvctx->handle);
+                pdrvctx->handle = NULL;
+            }
+            free(pdrvctx->vtable);
+            free(pdrvctx);
+            i965->wrapper_pdrvctx = NULL;
+        }
+
         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)) {
@@ -5581,6 +6754,10 @@ VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
     vtable->vaQuerySurfaceAttributes = i965_QuerySurfaceAttributes;
     vtable->vaCreateSurfaces2 = i965_CreateSurfaces2;
 
+    /* 0.36.0 */
+    vtable->vaAcquireBufferHandle = i965_AcquireBufferHandle;
+    vtable->vaReleaseBufferHandle = i965_ReleaseBufferHandle;
+
     vtable_vpp->vaQueryVideoProcFilters = i965_QueryVideoProcFilters;
     vtable_vpp->vaQueryVideoProcFilterCaps = i965_QueryVideoProcFilterCaps;
     vtable_vpp->vaQueryVideoProcPipelineCaps = i965_QueryVideoProcPipelineCaps;
@@ -5593,6 +6770,7 @@ VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
     }
 
+    i965->wrapper_pdrvctx = NULL;
     ctx->pDriverData = (void *)i965;
     ret = i965_Init(ctx);