OSDN Git Service

Add the 10bit-scaling conversion for I010 format
[android-x86/hardware-intel-common-vaapi.git] / src / i965_drv_video.c
index 4ba87f8..fbb6407 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "sysdeps.h"
 #include <unistd.h>
+#include <dlfcn.h>
 
 #ifdef HAVE_VA_X11
 # include "i965_output_dri.h"
 #include "i965_decoder.h"
 #include "i965_encoder.h"
 
+#include "i965_post_processing.h"
+
+#include "gen9_vp9_encapi.h"
+
 #define CONFIG_ID_OFFSET                0x01000000
 #define CONTEXT_ID_OFFSET               0x02000000
 #define SURFACE_ID_OFFSET               0x04000000
 #define IMAGE_ID_OFFSET                 0x0a000000
 #define SUBPIC_ID_OFFSET                0x10000000
 
-#define HAS_MPEG2_DECODING(ctx)  ((ctx)->codec_info->has_mpeg2_decoding && \
-                                  (ctx)->intel.has_bsd)
-
-#define HAS_MPEG2_ENCODING(ctx)  ((ctx)->codec_info->has_mpeg2_encoding && \
-                                  (ctx)->intel.has_bsd)
-
-#define HAS_H264_DECODING(ctx)  ((ctx)->codec_info->has_h264_decoding && \
-                                 (ctx)->intel.has_bsd)
-
-#define HAS_H264_ENCODING(ctx)  ((ctx)->codec_info->has_h264_encoding && \
-                                 (ctx)->intel.has_bsd)
-
-#define HAS_VC1_DECODING(ctx)   ((ctx)->codec_info->has_vc1_decoding && \
-                                 (ctx)->intel.has_bsd)
-
-#define HAS_JPEG_DECODING(ctx)  ((ctx)->codec_info->has_jpeg_decoding && \
-                                 (ctx)->intel.has_bsd)
-                                                                  
-#define HAS_JPEG_ENCODING(ctx)  ((ctx)->codec_info->has_jpeg_encoding && \
-                                 (ctx)->intel.has_bsd)      
-
-#define HAS_VPP(ctx)    ((ctx)->codec_info->has_vpp)
-
-#define HAS_ACCELERATED_GETIMAGE(ctx)   ((ctx)->codec_info->has_accelerated_getimage)
-
-#define HAS_ACCELERATED_PUTIMAGE(ctx)   ((ctx)->codec_info->has_accelerated_putimage)
-
-#define HAS_TILED_SURFACE(ctx) ((ctx)->codec_info->has_tiled_surface)
-
-#define HAS_VP8_DECODING(ctx)   ((ctx)->codec_info->has_vp8_decoding && \
-                                 (ctx)->intel.has_bsd)
-
-#define HAS_VP8_ENCODING(ctx)   ((ctx)->codec_info->has_vp8_encoding && \
-                                 (ctx)->intel.has_bsd)
-
-#define HAS_H264_MVC_DECODING(ctx) \
-    (HAS_H264_DECODING(ctx) && (ctx)->codec_info->h264_mvc_dec_profiles)
-
-#define HAS_H264_MVC_DECODING_PROFILE(ctx, profile)                     \
-    (HAS_H264_MVC_DECODING(ctx) &&                                      \
-     ((ctx)->codec_info->h264_mvc_dec_profiles & (1U << profile)))
-
-#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)
-
 static int get_sampling_from_fourcc(unsigned int fourcc);
 
 /* Check whether we are rendering to X11 (VA/X11 or VA/GLX API) */
@@ -140,11 +94,15 @@ 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_I010  2, 2, 3, {I965_16BITS, I965_4BITS, I965_4BITS}, 3, { {PLANE_0, OFFSET_0}, {PLANE_1, OFFSET_0}, {PLANE_2, OFFSET_0} }
+
 #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} }
 
@@ -184,6 +142,9 @@ 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(I010, YUV420, I_S),
+
     DEF_YUV(422H, YUV422H, I_SI),
     DEF_YUV(422V, YUV422V, I_S),
     DEF_YUV(YV16, YUV422H, I_S),
@@ -216,7 +177,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)
@@ -226,6 +187,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,
@@ -289,6 +266,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 */
@@ -420,6 +399,94 @@ va_enc_packed_type_to_idx(int packed_type)
     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 */
@@ -435,14 +502,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)) {
@@ -465,16 +535,44 @@ 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)||
+        HAS_HEVC10_ENCODING(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 */
     ASSERT_RET(i <= I965_MAX_PROFILES, VA_STATUS_ERROR_OPERATION_FAILED);
     *num_profiles = i;
@@ -511,6 +609,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:
@@ -559,6 +660,38 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
 
         break;
 
+    case VAProfileHEVCMain10:
+        if (HAS_HEVC10_DECODING(i965))
+            entrypoint_list[n++] = VAEntrypointVLD;
+
+        if (HAS_HEVC10_ENCODING(i965))
+            entrypoint_list[n++] = VAEntrypointEncSlice;
+
+        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;
     }
@@ -583,6 +716,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
         if ((HAS_MPEG2_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
             (HAS_MPEG2_ENCODING(i965) && entrypoint == VAEntrypointEncSlice)) {
             va_status = VA_STATUS_SUCCESS;
+        } else if (!HAS_MPEG2_DECODING(i965) && !HAS_MPEG2_ENCODING(i965)){
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
         }
@@ -592,8 +727,12 @@ 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 if (!HAS_H264_DECODING(i965) && !HAS_H264_ENCODING(i965) &&
+                   !HAS_LP_H264_ENCODING(i965)){
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
         }
@@ -604,6 +743,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
     case VAProfileVC1Advanced:
         if (HAS_VC1_DECODING(i965) && entrypoint == VAEntrypointVLD) {
             va_status = VA_STATUS_SUCCESS;
+        } else if (!HAS_VC1_DECODING(i965)) {
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
         }
@@ -612,6 +753,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
     case VAProfileNone:
         if (HAS_VPP(i965) && VAEntrypointVideoProc == entrypoint) {
             va_status = VA_STATUS_SUCCESS;
+        } else if (!HAS_VPP(i965)){
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
         }
@@ -621,6 +764,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
         if ((HAS_JPEG_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
             (HAS_JPEG_ENCODING(i965) && entrypoint == VAEntrypointEncPicture)) {
             va_status = VA_STATUS_SUCCESS;
+        } else if (!HAS_JPEG_DECODING(i965) && !HAS_JPEG_ENCODING(i965)){
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
         }
@@ -630,6 +775,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
         if ((HAS_VP8_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
             (HAS_VP8_ENCODING(i965) && entrypoint == VAEntrypointEncSlice)) {
             va_status = VA_STATUS_SUCCESS;
+        } else if (!HAS_VP8_DECODING(i965) && !HAS_VP8_ENCODING(i965)){
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
         }
@@ -639,8 +786,12 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
     case VAProfileH264StereoHigh:
         if ((HAS_H264_MVC_DECODING_PROFILE(i965, profile) &&
              entrypoint == VAEntrypointVLD) ||
-            (HAS_H264_MVC_ENCODING(i965) && entrypoint == VAEntrypointEncSlice)) {
+            (HAS_H264_MVC_ENCODING(i965) &&
+             entrypoint == VAEntrypointEncSlice)) {
             va_status = VA_STATUS_SUCCESS;
+        } else if(!HAS_H264_MVC_DECODING_PROFILE(i965, profile) &&
+                  !HAS_H264_MVC_ENCODING(i965)) {
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
         }
@@ -649,10 +800,45 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
 
     case VAProfileHEVCMain:
         if ((HAS_HEVC_DECODING(i965) && (entrypoint == VAEntrypointVLD))||
-            (HAS_HEVC_ENCODING(i965) && (entrypoint == VAEntrypointEncSlice)))
+            (HAS_HEVC_ENCODING(i965) && (entrypoint == VAEntrypointEncSlice))) {
             va_status = VA_STATUS_SUCCESS;
-        else
+        } else if (!HAS_HEVC_DECODING(i965) && !HAS_HEVC_ENCODING(i965)) {
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
+        } else {
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
+        }
+
+        break;
+
+    case VAProfileHEVCMain10:
+        if ((HAS_HEVC10_DECODING(i965) && (entrypoint == VAEntrypointVLD))||
+            (HAS_HEVC10_ENCODING(i965) &&
+             (entrypoint == VAEntrypointEncSlice))) {
+            va_status = VA_STATUS_SUCCESS;
+        } else if (!HAS_HEVC10_DECODING(i965) && !HAS_HEVC10_ENCODING(i965)) {
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
+        } 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_PROFILE(i965, profile)) &&
+                   (entrypoint == VAEntrypointEncSlice)) {
+            va_status = VA_STATUS_SUCCESS;
+        } else if (profile == VAProfileVP9Profile0 && i965->wrapper_pdrvctx) {
+            va_status = VA_STATUS_SUCCESS;
+        } else if(!HAS_VP9_DECODING_PROFILE(i965, profile) &&
+                  !HAS_VP9_ENCODING(i965) && !i965->wrapper_pdrvctx) {
+            va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
+        } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
+        }
 
         break;
 
@@ -689,7 +875,25 @@ i965_get_default_chroma_formats(VADriverContextP ctx, VAProfile profile,
             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;
+
+        if (HAS_VPP(i965))
+            chroma_formats |= VA_RT_FORMAT_YUV422 | VA_RT_FORMAT_RGB32;
+        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:
@@ -706,7 +910,6 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                          int num_attribs)
 {
     VAStatus va_status;
-    struct i965_driver_data *i965 = i965_driver_data(ctx);
     int i;
 
     va_status = i965_validate_config(ctx, profile, entrypoint);
@@ -730,22 +933,42 @@ 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 == VAProfileH264StereoHigh ||
                     profile == VAProfileH264MultiviewHigh ||
-                    profile == VAProfileHEVCMain) {
+                    profile == VAProfileHEVCMain ||
+                    profile == VAProfileHEVCMain10) {
                     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) {
@@ -755,14 +978,23 @@ i965_GetConfigAttributes(VADriverContextP ctx,
             break;
 
         case VAConfigAttribEncMaxRefFrames:
-            if (entrypoint == VAEntrypointEncSlice) {
+            if (entrypoint == VAEntrypointEncSlice)
                 attrib_list[i].value = (1 << 16) | (1 << 0);
-                break;
+            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) {
+            if (entrypoint == VAEntrypointEncSlice ||
+                entrypoint == VAEntrypointEncSliceLP) {
                 attrib_list[i].value = 1;
                 if (profile == VAProfileH264ConstrainedBaseline ||
                     profile == VAProfileH264Main ||
@@ -786,6 +1018,53 @@ i965_GetConfigAttributes(VADriverContextP ctx,
             }
             break;
 
+        case VAConfigAttribDecSliceMode:
+            attrib_list[i].value = VA_DEC_SLICE_MODE_NORMAL;
+            break;
+
+        case VAConfigAttribEncROI:
+            if (entrypoint == VAEntrypointEncSlice ||
+                entrypoint == VAEntrypointEncSliceLP) {
+
+                if (profile == VAProfileH264ConstrainedBaseline ||
+                    profile == VAProfileH264Main ||
+                    profile == VAProfileH264High) {
+
+                    VAConfigAttribValEncROI *roi_config =
+                        (VAConfigAttribValEncROI *)&(attrib_list[i].value);
+
+                    if(entrypoint == VAEntrypointEncSliceLP) {
+                        roi_config->bits.num_roi_regions = 3;
+                        roi_config->bits.roi_rc_priority_support = 0;
+                        roi_config->bits.roi_rc_qp_delat_support = 0;
+                    } else {
+                        roi_config->bits.num_roi_regions =
+                            I965_MAX_NUM_ROI_REGIONS;
+                        roi_config->bits.roi_rc_priority_support = 0;
+                        roi_config->bits.roi_rc_qp_delat_support = 1;
+                    }
+                }else {
+                    attrib_list[i].value = 0;
+                }
+            }
+
+            break;
+
+        case VAConfigAttribEncRateControlExt:
+            if ((profile == VAProfileH264ConstrainedBaseline ||
+                 profile == VAProfileH264Main ||
+                 profile == VAProfileH264High) &&
+                entrypoint == VAEntrypointEncSlice) {
+                VAConfigAttribValEncRateControlExt *val_config = (VAConfigAttribValEncRateControlExt *)&(attrib_list[i].value);
+
+                val_config->bits.max_num_temporal_layers_minus1 = MAX_TEMPORAL_LAYERS - 1;
+                val_config->bits.temporal_layer_bitrate_control_flag = 1;
+            } else {
+                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+            }
+
+            break;
+
         default:
             /* Do nothing */
             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
@@ -878,6 +1157,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]);
@@ -896,6 +1176,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);
@@ -918,6 +1216,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;
 }
@@ -985,6 +1291,7 @@ i965_surface_native_memory(VADriverContextP ctx,
     // todo, should we disable tiling for 422 format?
     if (expected_fourcc == VA_FOURCC_I420 ||
         expected_fourcc == VA_FOURCC_IYUV ||
+        expected_fourcc == VA_FOURCC_I010 ||
         expected_fourcc == VA_FOURCC_YV12 ||
         expected_fourcc == VA_FOURCC_YV16)
         tiling = 0;
@@ -1024,6 +1331,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);
 
@@ -1053,6 +1361,7 @@ i965_suface_external_memory(VADriverContextP ctx,
     case VA_FOURCC_I420:
     case VA_FOURCC_IYUV:
     case VA_FOURCC_IMC3:
+    case VA_FOURCC_I010:
         ASSERT_RET(memory_attibute->num_planes == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
         ASSERT_RET(memory_attibute->pitches[1] == memory_attibute->pitches[2], VA_STATUS_ERROR_INVALID_PARAMETER);
 
@@ -1251,6 +1560,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 &&
@@ -1275,6 +1585,7 @@ i965_CreateSurfaces2(
         obj_surface->user_disable_tiling = false;
         obj_surface->user_h_stride_set = false;
         obj_surface->user_v_stride_set = false;
+        obj_surface->border_cleared = false;
 
         obj_surface->subpic_render_idx = 0;
         for(j = 0; j < I965_MAX_SUBPIC_SUM; j++){
@@ -1288,6 +1599,7 @@ 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;
@@ -1295,6 +1607,9 @@ i965_CreateSurfaces2(
         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) {
@@ -1311,10 +1626,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);
@@ -1386,15 +1701,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 
@@ -1725,7 +2055,7 @@ static void
 i965_destroy_context(struct object_heap *heap, struct object_base *obj)
 {
     struct object_context *obj_context = (struct object_context *)obj;
-    int i;
+    int i, j;
 
     if (obj_context->hw_context) {
         obj_context->hw_context->destroy(obj_context->hw_context);
@@ -1736,14 +2066,8 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
         i965_release_buffer_store(&obj_context->codec_state.proc.pipeline_param);
 
     } else if (obj_context->codec_type == CODEC_ENC) {
-        assert(obj_context->codec_state.encode.num_slice_params <= obj_context->codec_state.encode.max_slice_params);
-        i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
-        i965_release_buffer_store(&obj_context->codec_state.encode.seq_param);
-
-        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]);
-
-        free(obj_context->codec_state.encode.slice_params);
+        i965_release_buffer_store(&obj_context->codec_state.encode.q_matrix);
+        i965_release_buffer_store(&obj_context->codec_state.encode.huffman_table);
 
         assert(obj_context->codec_state.encode.num_slice_params_ext <= obj_context->codec_state.encode.max_slice_params_ext);
         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param_ext);
@@ -1756,7 +2080,8 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data[i]);
 
         for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param); i++)
-            i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i]);
+            for (j = 0; j < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param[0]); j++)
+                i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i][j]);
 
         for (i = 0; i < obj_context->codec_state.encode.num_slice_params_ext; i++)
             i965_release_buffer_store(&obj_context->codec_state.encode.slice_params_ext[i]);
@@ -1784,6 +2109,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);
@@ -1806,6 +2132,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,
@@ -1817,21 +2157,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;
     }
@@ -1856,6 +2199,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])) {
@@ -1874,14 +2221,12 @@ i965_CreateContext(VADriverContextP ctx,
             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) || 
-                   (VAEntrypointEncPicture == obj_config->entrypoint)) { /*encode routine only*/
+                    (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;
-            obj_context->codec_state.encode.max_slice_params = NUM_SLICES;
-            obj_context->codec_state.encode.slice_params = calloc(obj_context->codec_state.encode.max_slice_params,
-                                                               sizeof(*obj_context->codec_state.encode.slice_params));
             obj_context->codec_state.encode.max_packed_header_params_ext = NUM_SLICES;
             obj_context->codec_state.encode.packed_header_params_ext =
                 calloc(obj_context->codec_state.encode.max_packed_header_params_ext,
@@ -1905,9 +2250,12 @@ i965_CreateContext(VADriverContextP ctx,
 
             obj_context->codec_state.encode.slice_index = 0;
             packed_attrib = i965_lookup_config_attribute(obj_config, VAConfigAttribEncPackedHeaders);
-            if (packed_attrib)
+            if (packed_attrib) {
                 obj_context->codec_state.encode.packed_header_flag = packed_attrib->value;
-            else {
+                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.
                  */
@@ -1915,6 +2263,10 @@ i965_CreateContext(VADriverContextP ctx,
                                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);
@@ -1939,6 +2291,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);
@@ -1954,15 +2330,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 
@@ -1990,6 +2376,8 @@ i965_create_buffer_internal(VADriverContextP ctx,
     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) {
@@ -2015,6 +2403,7 @@ i965_create_buffer_internal(VADriverContextP ctx,
     case VAProcFilterParameterBufferType:
     case VAHuffmanTableBufferType:
     case VAProbabilityBufferType:
+    case VAEncMacroblockMapBufferType:
         /* Ok */
         break;
 
@@ -2040,26 +2429,62 @@ i965_create_buffer_internal(VADriverContextP ctx,
     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);
@@ -2071,10 +2496,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;
@@ -2083,10 +2510,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);
     }
 
@@ -2122,6 +2553,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;
@@ -2143,8 +2587,24 @@ 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);
 
@@ -2163,6 +2623,7 @@ 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;
@@ -2175,69 +2636,77 @@ 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;
-                } 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 (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 {
+                    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_JPEG) {
-                    for(i = 0; i <  obj_buffer->size_element - header_offset - 1 - 0x1000; i++) {
-                        if( (buffer[i] == 0xFF) && (buffer[i + 1] == 0xD9)) {
-                            break;
+                    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;
+                        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 (i == obj_buffer->size_element - header_offset - 3 - 0x1000) {
+                    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;
                     }
-                    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;
+                    vaStatus = VA_STATUS_SUCCESS;
                 }
 
                 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;
@@ -2257,6 +2726,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);
 
@@ -2284,94 +2765,46 @@ 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 
-i965_BeginPicture(VADriverContextP ctx,
-                  VAContextID context,
-                  VASurfaceID render_target)
-{
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
-    struct object_context *obj_context = CONTEXT(context);
-    struct object_surface *obj_surface = SURFACE(render_target);
-    struct object_config *obj_config;
-    VAStatus vaStatus;
-    int i;
-
-    ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
-    ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
-    obj_config = obj_context->obj_config;
-    ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
-
-    if (is_surface_busy(i965, obj_surface))
-        return VA_STATUS_ERROR_SURFACE_BUSY;
-
-    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;
+VAStatus 
+i965_BeginPicture(VADriverContextP ctx,
+                  VAContextID context,
+                  VASurfaceID render_target)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct object_context *obj_context = CONTEXT(context);
+    struct object_surface *obj_surface = SURFACE(render_target);
+    struct object_config *obj_config;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    int i, j;
 
-    case VAProfileHEVCMain:
-        vaStatus = VA_STATUS_SUCCESS;
-        break;
+    ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
+    ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
+    obj_config = obj_context->obj_config;
+    ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
 
-    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;
     } else if (obj_context->codec_type == CODEC_ENC) {
-        i965_release_buffer_store(&obj_context->codec_state.encode.pic_param);
-
-        for (i = 0; i < obj_context->codec_state.encode.num_slice_params; i++) {
-            i965_release_buffer_store(&obj_context->codec_state.encode.slice_params[i]);
-        }
-
-        obj_context->codec_state.encode.num_slice_params = 0;
-
         /* ext */
         i965_release_buffer_store(&obj_context->codec_state.encode.pic_param_ext);
 
@@ -2402,6 +2835,25 @@ i965_BeginPicture(VADriverContextP ctx,
         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;
+        /*
+        * Based on ROI definition in va/va.h, the ROI set through this
+        * structure is applicable only to the current frame or field.
+        * That is to say: it is on-the-fly setting. If it is not set,
+        * the current frame doesn't use ROI.
+        * It is uncertain whether the other misc buffer should be released.
+        * So only release the previous ROI buffer.
+        */
+        i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[VAEncMiscParameterTypeROI][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++)
+                for (j = 0; j < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param[0]); j++)
+                    i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i][j]);
+
+            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);
@@ -2416,6 +2868,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;
@@ -2466,6 +2932,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,
@@ -2520,6 +3100,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;
 }
 
@@ -2535,6 +3119,7 @@ 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)
@@ -2575,6 +3160,29 @@ i965_encoder_render_packed_header_data_buffer(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
+static int
+i965_encoder_get_misc_paramerter_buffer_index(VADriverContextP ctx,
+                                              struct encode_state *encode,
+                                              VAEncMiscParameterBuffer *misc_param)
+{
+    int index = 0;
+
+    if (!encode->has_layers)
+        return 0;
+
+    if (misc_param->type == VAEncMiscParameterTypeRateControl) {
+        VAEncMiscParameterRateControl *misc_rate_control = (VAEncMiscParameterRateControl *)misc_param->data;
+
+        index = misc_rate_control->rc_flags.bits.temporal_id;
+    } else if (misc_param->type == VAEncMiscParameterTypeFrameRate) {
+        VAEncMiscParameterFrameRate *misc_frame_rate = (VAEncMiscParameterFrameRate *)misc_param->data;
+
+        index = misc_frame_rate->framerate_flags.bits.temporal_id;
+    }
+
+    return index;
+}
+
 static VAStatus
 i965_encoder_render_misc_parameter_buffer(VADriverContextP ctx,
                                           struct object_context *obj_context,
@@ -2582,6 +3190,7 @@ i965_encoder_render_misc_parameter_buffer(VADriverContextP ctx,
 {
     struct encode_state *encode = &obj_context->codec_state.encode;
     VAEncMiscParameterBuffer *param = NULL;
+    int index;
 
     ASSERT_RET(obj_buffer->buffer_store->bo == NULL, VA_STATUS_ERROR_INVALID_BUFFER);
     ASSERT_RET(obj_buffer->buffer_store->buffer, VA_STATUS_ERROR_INVALID_BUFFER);
@@ -2591,8 +3200,16 @@ i965_encoder_render_misc_parameter_buffer(VADriverContextP ctx,
     if (param->type >= ARRAY_ELEMS(encode->misc_param))
         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
-    i965_release_buffer_store(&encode->misc_param[param->type]);
-    i965_reference_buffer_store(&encode->misc_param[param->type], obj_buffer->buffer_store);
+    if (param->type == VAEncMiscParameterTypeTemporalLayerStructure)
+        encode->has_layers = 1;
+
+    index = i965_encoder_get_misc_paramerter_buffer_index(ctx, encode, param);
+
+    if (index >= ARRAY_ELEMS(encode->misc_param[0]))
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    i965_release_buffer_store(&encode->misc_param[param->type][index]);
+    i965_reference_buffer_store(&encode->misc_param[param->type][index], obj_buffer->buffer_store);
 
     return VA_STATUS_SUCCESS;
 }
@@ -2686,7 +3303,8 @@ 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)&&
+            } else if((obj_config->profile == VAProfileHEVCMain ||
+                obj_config->profile == VAProfileHEVCMain10) &&
                 (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
                 vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
                                                                           obj_context,
@@ -2708,10 +3326,14 @@ 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 (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.
@@ -2780,7 +3402,8 @@ i965_encoder_render_picture(VADriverContextP ctx,
                     ((encode->last_packed_header_type & (~VAEncPackedHeaderMiscMask)) != 0)),
                     VA_STATUS_ERROR_ENCODING_ERROR);
 
-                if((obj_config->profile == VAProfileHEVCMain)&&
+                if((obj_config->profile == VAProfileHEVCMain ||
+                    obj_config->profile == VAProfileHEVCMain10) &&
                     (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
 
                         vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
@@ -2806,6 +3429,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;
@@ -2876,7 +3503,8 @@ 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 ) || 
-               (VAEntrypointEncPicture == 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);
@@ -2899,25 +3527,28 @@ 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) || (VAEntrypointEncPicture == 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) {
             WARN_ONCE("the packed header/data is not paired for encoding!\n");
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
-        if (!(obj_context->codec_state.encode.pic_param ||
-                obj_context->codec_state.encode.pic_param_ext)) {
+        if (!obj_context->codec_state.encode.pic_param_ext) {
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
-        if (!(obj_context->codec_state.encode.seq_param ||
-                obj_context->codec_state.encode.seq_param_ext) &&
+        if (!obj_context->codec_state.encode.seq_param_ext &&
                 (VAEntrypointEncPicture != obj_config->entrypoint)) {
-            return VA_STATUS_ERROR_INVALID_PARAMETER;
+            /* 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_config->profile != VAProfileVP8Version0_3)) {
+        if ((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;
         }
 
@@ -2943,6 +3574,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);
@@ -3304,6 +3947,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;
     }
@@ -3362,25 +4013,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;
@@ -3484,7 +4139,7 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             obj_surface->y_cb_offset = 0; 
             obj_surface->y_cr_offset = 0; 
             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
-            obj_surface->cb_cr_height = obj_surface->orig_height / 2;
+            obj_surface->cb_cr_height = obj_surface->orig_height;
             region_width = obj_surface->width;
             region_height = obj_surface->height;
             
@@ -3517,6 +4172,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;
@@ -3527,15 +4183,18 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
 
         case VA_FOURCC_YV16:
             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+            obj_surface->width = ALIGN(obj_surface->cb_cr_width, i965->codec_info->min_linear_wpitch) * 2;
             obj_surface->cb_cr_height = obj_surface->orig_height;
             obj_surface->y_cr_offset = obj_surface->height;
             obj_surface->y_cb_offset = obj_surface->y_cr_offset + ALIGN(obj_surface->cb_cr_height, 32) / 2;
             obj_surface->cb_cr_pitch = obj_surface->width / 2;
+            region_width = obj_surface->width;
             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32);
             break;
 
         case VA_FOURCC_YV12:
         case VA_FOURCC_I420:
+        case VA_FOURCC_IYUV:
             if (fourcc == VA_FOURCC_YV12) {
                 obj_surface->y_cr_offset = obj_surface->height;
                 obj_surface->y_cb_offset = obj_surface->height + obj_surface->height / 4;
@@ -3545,11 +4204,24 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             }
 
             obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+            obj_surface->width = ALIGN(obj_surface->cb_cr_width, i965->codec_info->min_linear_wpitch) * 2;
             obj_surface->cb_cr_height = obj_surface->orig_height / 2;
             obj_surface->cb_cr_pitch = obj_surface->width / 2;
+            region_width = obj_surface->width;
             region_height = obj_surface->height + obj_surface->height / 2;
             break;
 
+        case VA_FOURCC_I010:
+            obj_surface->y_cb_offset = obj_surface->height;
+            obj_surface->y_cr_offset = obj_surface->height + obj_surface->height / 4;
+            obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+            obj_surface->width = ALIGN(obj_surface->cb_cr_width * 2, i965->codec_info->min_linear_wpitch) * 2;
+            obj_surface->cb_cr_height = obj_surface->orig_height / 2;
+            obj_surface->cb_cr_pitch = obj_surface->width / 2;
+            region_width = obj_surface->width;
+            region_height = obj_surface->height + obj_surface->height / 2;
+
+            break;
         case VA_FOURCC_YUY2:
         case VA_FOURCC_UYVY:
             obj_surface->width = ALIGN(obj_surface->orig_width * 2, i965->codec_info->min_linear_wpitch);
@@ -3664,7 +4336,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:
@@ -3688,6 +4363,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;
@@ -3696,6 +4372,7 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
         break;
 
     case VA_FOURCC_I420:
+    case VA_FOURCC_I010:
     case VA_FOURCC_422H:
     case VA_FOURCC_IMC3:
     case VA_FOURCC_444P:
@@ -3723,6 +4400,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;
@@ -4019,8 +4729,6 @@ i965_sw_getimage(VADriverContextP ctx,
     struct object_surface *obj_surface, struct object_image *obj_image,
     const VARectangle *rect)
 {
-    struct i965_driver_data * const i965 = i965_driver_data(ctx);
-    struct i965_render_state *render_state = &i965->render_state;
     void *image_data = NULL;
     VAStatus va_status;
 
@@ -4044,7 +4752,6 @@ i965_sw_getimage(VADriverContextP ctx,
         get_image_yuy2(obj_image, image_data, obj_surface, rect);
         break;
     default:
-    operation_failed:
         va_status = VA_STATUS_ERROR_OPERATION_FAILED;
         break;
     }
@@ -4774,7 +5481,8 @@ i965_GetSurfaceAttributes(
                            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:
@@ -4833,7 +5541,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;
 
@@ -4994,7 +5704,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;
@@ -5116,33 +5832,51 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
                 attribs[i].value.value.i = VA_FOURCC_NV12;
                 i++;
+
+                if ((obj_config->profile == VAProfileHEVCMain10) ||
+                    (obj_config->profile == VAProfileVP9Profile2)) {
+                    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 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;
@@ -5180,6 +5914,20 @@ 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++;
+
+                  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_I010;
+                  i++;
+                }
             }
         }
     }
@@ -5198,16 +5946,18 @@ 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 = i965->codec_info->max_width;
+    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 = i965->codec_info->max_height;
+    attribs[i].value.value.i = max_height;
     i++;
 
     if (i > *num_attribs) {
@@ -5315,6 +6065,16 @@ i965_AcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
     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;
 
@@ -5344,6 +6104,10 @@ i965_ReleaseBufferHandle(VADriverContextP ctx, VABufferID 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);
 }
 
@@ -5770,6 +6534,127 @@ error:
     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)
 {
@@ -5802,6 +6687,10 @@ i965_Init(VADriverContextP ctx)
         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--;
@@ -5824,6 +6713,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)) {
@@ -5921,6 +6823,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);