OSDN Git Service

Do not return FEI caps for non-FEI entrypoints
[android-x86/hardware-intel-common-vaapi.git] / src / i965_drv_video.c
index ff309ee..e206a2f 100644 (file)
@@ -30,6 +30,7 @@
 #include "sysdeps.h"
 #include <unistd.h>
 #include <dlfcn.h>
+#include <drm_fourcc.h>
 
 #ifdef HAVE_VA_X11
 # include "i965_output_dri.h"
@@ -238,7 +239,7 @@ static const VADisplayAttribute i965_display_attributes[] = {
     {
         VADisplayAttribRotation,
         0, 3, VA_ROTATION_NONE,
-        VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE
+        VA_DISPLAY_ATTRIB_GETTABLE | VA_DISPLAY_ATTRIB_SETTABLE
     },
 };
 
@@ -250,24 +251,42 @@ typedef struct {
 
 static const i965_image_format_map_t
 i965_image_formats_map[I965_MAX_IMAGE_FORMATS + 1] = {
-    { I965_SURFACETYPE_YUV,
-      { VA_FOURCC_YV12, VA_LSB_FIRST, 12, } },
-    { I965_SURFACETYPE_YUV,
-      { VA_FOURCC_I420, VA_LSB_FIRST, 12, } },
-    { I965_SURFACETYPE_YUV,
-      { VA_FOURCC_NV12, VA_LSB_FIRST, 12, } },
-    { I965_SURFACETYPE_YUV,
-      { VA_FOURCC_YUY2, VA_LSB_FIRST, 16, } },
-    { I965_SURFACETYPE_YUV,
-      { VA_FOURCC_UYVY, VA_LSB_FIRST, 16, } },
-    { I965_SURFACETYPE_YUV,
-      { VA_FOURCC_422H, VA_LSB_FIRST, 16, } },
-    { I965_SURFACETYPE_RGBA,
-      { 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, } },
+    {
+        I965_SURFACETYPE_YUV,
+        { VA_FOURCC_YV12, VA_LSB_FIRST, 12, }
+    },
+    {
+        I965_SURFACETYPE_YUV,
+        { VA_FOURCC_I420, VA_LSB_FIRST, 12, }
+    },
+    {
+        I965_SURFACETYPE_YUV,
+        { VA_FOURCC_NV12, VA_LSB_FIRST, 12, }
+    },
+    {
+        I965_SURFACETYPE_YUV,
+        { VA_FOURCC_YUY2, VA_LSB_FIRST, 16, }
+    },
+    {
+        I965_SURFACETYPE_YUV,
+        { VA_FOURCC_UYVY, VA_LSB_FIRST, 16, }
+    },
+    {
+        I965_SURFACETYPE_YUV,
+        { VA_FOURCC_422H, VA_LSB_FIRST, 16, }
+    },
+    {
+        I965_SURFACETYPE_RGBA,
+        { 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 */
@@ -284,26 +303,42 @@ typedef struct {
 
 static const i965_subpic_format_map_t
 i965_subpic_formats_map[I965_MAX_SUBPIC_FORMATS + 1] = {
-    { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_P4A4_UNORM,
-      { VA_FOURCC_IA44, VA_MSB_FIRST, 8, },
-      COMMON_SUBPICTURE_FLAGS },
-    { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A4P4_UNORM,
-      { VA_FOURCC_AI44, VA_MSB_FIRST, 8, },
-      COMMON_SUBPICTURE_FLAGS },
-    { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_P8A8_UNORM,
-      { VA_FOURCC_IA88, VA_MSB_FIRST, 16, },
-      COMMON_SUBPICTURE_FLAGS },
-    { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A8P8_UNORM,
-      { VA_FOURCC_AI88, VA_MSB_FIRST, 16, },
-      COMMON_SUBPICTURE_FLAGS },
-     { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_B8G8R8A8_UNORM,
-      { VA_FOURCC_BGRA, VA_LSB_FIRST, 32,
-        32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 },
-      COMMON_SUBPICTURE_FLAGS },
-    { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_R8G8B8A8_UNORM,
-      { VA_FOURCC_RGBA, VA_LSB_FIRST, 32,
-        32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 },
-      COMMON_SUBPICTURE_FLAGS },
+    {
+        I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_P4A4_UNORM,
+        { VA_FOURCC_IA44, VA_MSB_FIRST, 8, },
+        COMMON_SUBPICTURE_FLAGS
+    },
+    {
+        I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A4P4_UNORM,
+        { VA_FOURCC_AI44, VA_MSB_FIRST, 8, },
+        COMMON_SUBPICTURE_FLAGS
+    },
+    {
+        I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_P8A8_UNORM,
+        { VA_FOURCC_IA88, VA_MSB_FIRST, 16, },
+        COMMON_SUBPICTURE_FLAGS
+    },
+    {
+        I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A8P8_UNORM,
+        { VA_FOURCC_AI88, VA_MSB_FIRST, 16, },
+        COMMON_SUBPICTURE_FLAGS
+    },
+    {
+        I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_B8G8R8A8_UNORM,
+        {
+            VA_FOURCC_BGRA, VA_LSB_FIRST, 32,
+            32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
+        },
+        COMMON_SUBPICTURE_FLAGS
+    },
+    {
+        I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_R8G8B8A8_UNORM,
+        {
+            VA_FOURCC_RGBA, VA_LSB_FIRST, 32,
+            32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
+        },
+        COMMON_SUBPICTURE_FLAGS
+    },
 };
 
 static const i965_subpic_format_map_t *
@@ -327,7 +362,7 @@ get_subpic_format(const VAImageFormat *va_format)
 /* Checks whether the surface is in busy state */
 static bool
 is_surface_busy(struct i965_driver_data *i965,
-    struct object_surface *obj_surface)
+                struct object_surface *obj_surface)
 {
     assert(obj_surface != NULL);
 
@@ -414,7 +449,7 @@ i965_surface_wrapper(VADriverContextP ctx, VASurfaceID surface)
 
     if (obj_surface->wrapper_surface != VA_INVALID_ID) {
         /* the wrapped surface already exists. just return it */
-       return va_status;
+        return va_status;
     }
 
     if (obj_surface->fourcc == 0)
@@ -425,7 +460,7 @@ i965_surface_wrapper(VADriverContextP ctx, VASurfaceID surface)
      * TBD: Support more surface formats.
      * Currently only NV12 is support as NV12 is used by decoding.
      */
-    if (obj_surface->fourcc != VA_FOURCC_NV12 )
+    if (obj_surface->fourcc != VA_FOURCC_NV12)
         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
     if ((i965->wrapper_pdrvctx == NULL) ||
@@ -487,7 +522,7 @@ i965_surface_wrapper(VADriverContextP ctx, VASurfaceID surface)
 
 }
 
-VAStatus 
+VAStatus
 i965_QueryConfigProfiles(VADriverContextP ctx,
                          VAProfile *profile_list,       /* out */
                          int *num_profiles)             /* out */
@@ -503,7 +538,9 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
 
     if (HAS_H264_DECODING(i965) ||
         HAS_H264_ENCODING(i965) ||
-        HAS_LP_H264_ENCODING(i965)) {
+        HAS_LP_H264_ENCODING(i965) ||
+        HAS_FEI_H264_ENCODING(i965) ||
+        HAS_H264_PREENC(i965)) {
         profile_list[i++] = VAProfileH264ConstrainedBaseline;
         profile_list[i++] = VAProfileH264Main;
         profile_list[i++] = VAProfileH264High;
@@ -535,22 +572,23 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
         profile_list[i++] = VAProfileVP8Version0_3;
     }
 
-    if (HAS_HEVC_DECODING(i965)||
+    if (HAS_HEVC_DECODING(i965) ||
         HAS_HEVC_ENCODING(i965)) {
         profile_list[i++] = VAProfileHEVCMain;
     }
 
-    if (HAS_HEVC10_DECODING(i965)||
+    if (HAS_HEVC10_DECODING(i965) ||
         HAS_HEVC10_ENCODING(i965)) {
         profile_list[i++] = VAProfileHEVCMain10;
     }
 
-    if(HAS_VP9_DECODING_PROFILE(i965, VAProfileVP9Profile0) ||
-        HAS_VP9_ENCODING(i965)) {
+    if (HAS_VP9_DECODING_PROFILE(i965, VAProfileVP9Profile0) ||
+        HAS_VP9_ENCODING(i965) ||
+        HAS_LP_VP9_ENCODING(i965)) {
         profile_list[i++] = VAProfileVP9Profile0;
     }
 
-    if(HAS_VP9_DECODING_PROFILE(i965, VAProfileVP9Profile2)) {
+    if (HAS_VP9_DECODING_PROFILE(i965, VAProfileVP9Profile2)) {
         profile_list[i++] = VAProfileVP9Profile2;
     }
 
@@ -580,7 +618,7 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-VAStatus 
+VAStatus
 i965_QueryConfigEntrypoints(VADriverContextP ctx,
                             VAProfile profile,
                             VAEntrypoint *entrypoint_list,      /* out */
@@ -612,13 +650,19 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
         if (HAS_LP_H264_ENCODING(i965))
             entrypoint_list[n++] = VAEntrypointEncSliceLP;
 
+        if (HAS_FEI_H264_ENCODING(i965))
+            entrypoint_list[n++] = VAEntrypointFEI;
+
+        if (HAS_H264_PREENC(i965))
+            entrypoint_list[n++] = VAEntrypointStats;
         break;
-   case VAProfileH264MultiviewHigh:
-   case VAProfileH264StereoHigh:
-       if (HAS_H264_MVC_DECODING_PROFILE(i965, profile))
+
+    case VAProfileH264MultiviewHigh:
+    case VAProfileH264StereoHigh:
+        if (HAS_H264_MVC_DECODING_PROFILE(i965, profile))
             entrypoint_list[n++] = VAEntrypointVLD;
 
-       if (HAS_H264_MVC_ENCODING(i965))
+        if (HAS_H264_MVC_ENCODING(i965))
             entrypoint_list[n++] = VAEntrypointEncSlice;
         break;
 
@@ -637,7 +681,7 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
     case VAProfileJPEGBaseline:
         if (HAS_JPEG_DECODING(i965))
             entrypoint_list[n++] = VAEntrypointVLD;
-        
+
         if (HAS_JPEG_ENCODING(i965))
             entrypoint_list[n++] = VAEntrypointEncPicture;
         break;
@@ -645,7 +689,7 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
     case VAProfileVP8Version0_3:
         if (HAS_VP8_DECODING(i965))
             entrypoint_list[n++] = VAEntrypointVLD;
-        
+
         if (HAS_VP8_ENCODING(i965))
             entrypoint_list[n++] = VAEntrypointEncSlice;
 
@@ -671,23 +715,26 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
 
     case VAProfileVP9Profile0:
     case VAProfileVP9Profile2:
-        if(HAS_VP9_DECODING_PROFILE(i965, profile))
+        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;
-          }
+        if (HAS_LP_VP9_ENCODING(i965) && (profile == VAProfileVP9Profile0))
+            entrypoint_list[n++] = VAEntrypointEncSliceLP;
+
+        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;
@@ -704,7 +751,7 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
 
 static VAStatus
 i965_validate_config(VADriverContextP ctx, VAProfile profile,
-    VAEntrypoint entrypoint)
+                     VAEntrypoint entrypoint)
 {
     struct i965_driver_data * const i965 = i965_driver_data(ctx);
     VAStatus va_status;
@@ -716,7 +763,7 @@ 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)){
+        } 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;
@@ -728,10 +775,13 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
     case VAProfileH264High:
         if ((HAS_H264_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
             (HAS_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSlice) ||
-            (HAS_LP_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSliceLP)) {
+            (HAS_LP_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSliceLP) ||
+            (HAS_FEI_H264_ENCODING(i965) && entrypoint == VAEntrypointFEI) ||
+            (HAS_H264_PREENC(i965) && entrypoint == VAEntrypointStats)) {
             va_status = VA_STATUS_SUCCESS;
         } else if (!HAS_H264_DECODING(i965) && !HAS_H264_ENCODING(i965) &&
-                   !HAS_LP_H264_ENCODING(i965)){
+                   !HAS_LP_H264_ENCODING(i965) && !HAS_FEI_H264_ENCODING(i965) &&
+                   !HAS_H264_PREENC(i965)) {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -753,7 +803,7 @@ 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)){
+        } else if (!HAS_VPP(i965)) {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -764,7 +814,7 @@ 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)){
+        } 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;
@@ -775,7 +825,7 @@ 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)){
+        } 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;
@@ -789,8 +839,8 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
             (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)) {
+        } 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;
@@ -799,7 +849,7 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
         break;
 
     case VAProfileHEVCMain:
-        if ((HAS_HEVC_DECODING(i965) && (entrypoint == VAEntrypointVLD))||
+        if ((HAS_HEVC_DECODING(i965) && (entrypoint == VAEntrypointVLD)) ||
             (HAS_HEVC_ENCODING(i965) && (entrypoint == VAEntrypointEncSlice))) {
             va_status = VA_STATUS_SUCCESS;
         } else if (!HAS_HEVC_DECODING(i965) && !HAS_HEVC_ENCODING(i965)) {
@@ -811,7 +861,7 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
         break;
 
     case VAProfileHEVCMain10:
-        if ((HAS_HEVC10_DECODING(i965) && (entrypoint == VAEntrypointVLD))||
+        if ((HAS_HEVC10_DECODING(i965) && (entrypoint == VAEntrypointVLD)) ||
             (HAS_HEVC10_ENCODING(i965) &&
              (entrypoint == VAEntrypointEncSlice))) {
             va_status = VA_STATUS_SUCCESS;
@@ -831,12 +881,18 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
         } else if ((HAS_VP9_ENCODING_PROFILE(i965, profile)) &&
                    (entrypoint == VAEntrypointEncSlice)) {
             va_status = VA_STATUS_SUCCESS;
+        } else if ((HAS_LP_VP9_ENCODING(i965) &&
+                    profile == VAProfileVP9Profile0 &&
+                    entrypoint == VAEntrypointEncSliceLP)) {
+            va_status = VA_STATUS_SUCCESS;
         } else if (profile == VAProfileVP9Profile0 &&
                    entrypoint == VAEntrypointVLD &&
                    i965->wrapper_pdrvctx) {
             va_status = VA_STATUS_SUCCESS;
-        } else if(!HAS_VP9_DECODING_PROFILE(i965, profile) &&
-                  !HAS_VP9_ENCODING(i965) && !i965->wrapper_pdrvctx) {
+        } else if (!HAS_VP9_DECODING_PROFILE(i965, profile) &&
+                   !HAS_VP9_ENCODING(i965) &&
+                   !HAS_LP_VP9_ENCODING(i965) &&
+                   !i965->wrapper_pdrvctx) {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
         } else {
             va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
@@ -853,7 +909,7 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
 
 static uint32_t
 i965_get_default_chroma_formats(VADriverContextP ctx, VAProfile profile,
-    VAEntrypoint entrypoint)
+                                VAEntrypoint entrypoint)
 {
     struct i965_driver_data * const i965 = i965_driver_data(ctx);
     uint32_t chroma_formats = VA_RT_FORMAT_YUV420;
@@ -906,7 +962,106 @@ i965_get_default_chroma_formats(VADriverContextP ctx, VAProfile profile,
     return chroma_formats;
 }
 
-VAStatus 
+static uint32_t
+i965_get_rc_attributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+
+    uint32_t rc_attribs = VA_ATTRIB_NOT_SUPPORTED;
+
+    if (entrypoint == VAEntrypointEncSlice) {
+
+        rc_attribs = VA_RC_CQP;
+
+        if (profile != VAProfileMPEG2Main &&
+            profile != VAProfileMPEG2Simple)
+            rc_attribs |= VA_RC_CBR;
+
+        if (profile == VAProfileVP8Version0_3 ||
+            profile == VAProfileHEVCMain ||
+            profile == VAProfileHEVCMain10)
+            rc_attribs |= VA_RC_VBR;
+
+        if (profile == VAProfileVP9Profile0)
+            rc_attribs = i965->codec_info->vp9_brc_mode;
+
+        if (profile == VAProfileH264ConstrainedBaseline ||
+            profile == VAProfileH264Main ||
+            profile == VAProfileH264High ||
+            profile == VAProfileH264MultiviewHigh ||
+            profile == VAProfileH264StereoHigh)
+            rc_attribs = i965->codec_info->h264_brc_mode;
+
+    } else if (entrypoint == VAEntrypointEncSliceLP) {
+
+        if (profile == VAProfileH264ConstrainedBaseline ||
+            profile == VAProfileH264Main ||
+            profile == VAProfileH264High ||
+            profile == VAProfileH264MultiviewHigh ||
+            profile == VAProfileH264StereoHigh)
+            rc_attribs = i965->codec_info->lp_h264_brc_mode;
+
+        else if (profile == VAProfileVP9Profile0)
+            rc_attribs = i965->codec_info->lp_vp9_brc_mode;
+
+    } else if (entrypoint == VAEntrypointFEI) {
+
+        if (profile == VAProfileH264ConstrainedBaseline ||
+            profile == VAProfileH264Main ||
+            profile == VAProfileH264High)
+            rc_attribs = VA_RC_CQP;
+
+    } else if (entrypoint == VAEntrypointEncPicture) {
+        if (profile == VAProfileJPEGBaseline)
+            rc_attribs = VA_RC_CQP;
+    }
+
+    return rc_attribs;
+}
+
+static uint32_t
+i965_get_enc_packed_attributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint)
+{
+    uint32_t enc_packed_attribs = VA_ATTRIB_NOT_SUPPORTED;
+
+    if (entrypoint == VAEntrypointEncSlice ||
+        entrypoint == VAEntrypointEncSliceLP ||
+        entrypoint == VAEntrypointFEI) {
+
+        switch (profile) {
+        case VAProfileMPEG2Simple:
+        case VAProfileMPEG2Main:
+            enc_packed_attribs = VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE | VA_ENC_PACKED_HEADER_MISC;
+            break;
+
+        case VAProfileH264ConstrainedBaseline:
+        case VAProfileH264Main:
+        case VAProfileH264High:
+        case VAProfileH264StereoHigh:
+        case VAProfileH264MultiviewHigh:
+        case VAProfileHEVCMain:
+        case VAProfileHEVCMain10:
+            enc_packed_attribs = VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE | VA_ENC_PACKED_HEADER_MISC;
+            enc_packed_attribs |= (VA_ENC_PACKED_HEADER_RAW_DATA | VA_ENC_PACKED_HEADER_SLICE);
+            break;
+
+        case VAProfileVP9Profile0:
+            enc_packed_attribs = VA_ENC_PACKED_HEADER_RAW_DATA;
+            break;
+
+        default:
+            break;
+        }
+
+    } else if (entrypoint == VAEntrypointEncPicture) {
+        if (profile == VAProfileJPEGBaseline)
+            enc_packed_attribs = VA_ENC_PACKED_HEADER_RAW_DATA;
+    }
+
+    return enc_packed_attribs;
+}
+
+VAStatus
 i965_GetConfigAttributes(VADriverContextP ctx,
                          VAProfile profile,
                          VAEntrypoint entrypoint,
@@ -928,67 +1083,38 @@ i965_GetConfigAttributes(VADriverContextP ctx,
         switch (attrib_list[i].type) {
         case VAConfigAttribRTFormat:
             attrib_list[i].value = i965_get_default_chroma_formats(ctx,
-                profile, entrypoint);
+                                                                   profile, entrypoint);
             break;
 
         case VAConfigAttribRateControl:
-            if (entrypoint == VAEntrypointEncSlice) {
-                attrib_list[i].value = VA_RC_CQP;
-
-                if (profile != VAProfileMPEG2Main &&
-                    profile != VAProfileMPEG2Simple)
-                    attrib_list[i].value |= VA_RC_CBR;
+            attrib_list[i].value = i965_get_rc_attributes(ctx, profile, entrypoint);
 
-                if (profile == VAProfileVP9Profile0 ||
-                    profile == VAProfileH264ConstrainedBaseline ||
-                    profile == VAProfileH264Main ||
-                    profile == VAProfileH264High)
-                    attrib_list[i].value |= VA_RC_VBR;
-
-                break;
-            } else if (entrypoint == VAEntrypointEncSliceLP) {
-                struct i965_driver_data * const i965 = i965_driver_data(ctx);
+            break;
 
-                /* 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;
+        case VAConfigAttribEncPackedHeaders:
+            attrib_list[i].value = i965_get_enc_packed_attributes(ctx, profile, entrypoint);
 
             break;
 
-        case VAConfigAttribEncPackedHeaders:
-            if (entrypoint == VAEntrypointEncSlice ||
-                entrypoint == VAEntrypointEncSliceLP) {
-                attrib_list[i].value = VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE | VA_ENC_PACKED_HEADER_MISC;
+        case VAConfigAttribEncMaxRefFrames:
+            if (entrypoint == VAEntrypointEncSlice || entrypoint == VAEntrypointFEI) {
+                attrib_list[i].value = (1 << 16) | (1 << 0);
                 if (profile == VAProfileH264ConstrainedBaseline ||
                     profile == VAProfileH264Main ||
                     profile == VAProfileH264High ||
                     profile == VAProfileH264StereoHigh ||
-                    profile == VAProfileH264MultiviewHigh ||
-                    profile == VAProfileHEVCMain ||
-                    profile == VAProfileHEVCMain10) {
-                    attrib_list[i].value |= (VA_ENC_PACKED_HEADER_RAW_DATA |
-                                             VA_ENC_PACKED_HEADER_SLICE);
+                    profile == VAProfileH264MultiviewHigh) {
+                    if (IS_GEN8(i965->intel.device_info) ||
+                        IS_GEN9(i965->intel.device_info))
+                        attrib_list[i].value = (1 << 16) | (4 << 0);
+                } else if (profile == VAProfileHEVCMain ||
+                           profile == VAProfileHEVCMain10) {
+                    if (IS_GEN9(i965->intel.device_info))
+                        attrib_list[i].value = (1 << 16) | (3 << 0);
+                    else if (IS_GEN10(i965->intel.device_info))
+                        attrib_list[i].value = (1 << 16) | (3 << 0);
                 }
-                else if (profile == VAProfileVP9Profile0)
-                    attrib_list[i].value = VA_ENC_PACKED_HEADER_RAW_DATA;
-                break;
-            }
-            else if (entrypoint == VAEntrypointEncPicture) {
-                if (profile == VAProfileJPEGBaseline)
-                    attrib_list[i].value = VA_ENC_PACKED_HEADER_RAW_DATA;
-            }
-            break;
-
-        case VAConfigAttribEncMaxRefFrames:
-            if (entrypoint == VAEntrypointEncSlice)
-                attrib_list[i].value = (1 << 16) | (1 << 0);
-            else if (entrypoint == VAEntrypointEncSliceLP) {
+            } else if (entrypoint == VAEntrypointEncSliceLP) {
                 /* Don't support B frame for low power mode */
                 if (profile == VAProfileH264ConstrainedBaseline ||
                     profile == VAProfileH264Main ||
@@ -996,34 +1122,45 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                     attrib_list[i].value = (1 << 0);
                 else
                     attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
-            }
+            } else if (entrypoint == VAEntrypointStats)
+                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
 
             break;
 
         case VAConfigAttribEncQualityRange:
             if (entrypoint == VAEntrypointEncSlice ||
-                entrypoint == VAEntrypointEncSliceLP) {
+                entrypoint == VAEntrypointEncSliceLP ||
+                entrypoint == VAEntrypointFEI) {
                 attrib_list[i].value = 1;
                 if (profile == VAProfileH264ConstrainedBaseline ||
                     profile == VAProfileH264Main ||
-                    profile == VAProfileH264High ){
-                        attrib_list[i].value = ENCODER_QUALITY_RANGE;
-                        if(entrypoint == VAEntrypointEncSlice){
-                            if (IS_GEN9(i965->intel.device_info))
-                                attrib_list[i].value = ENCODER_QUALITY_RANGE_AVC;
-                        }
+                    profile == VAProfileH264High) {
+                    attrib_list[i].value = ENCODER_QUALITY_RANGE;
+                    if (entrypoint == VAEntrypointEncSlice) {
+                        if (IS_GEN9(i965->intel.device_info) ||
+                            IS_GEN10(i965->intel.device_info))
+                            attrib_list[i].value = ENCODER_QUALITY_RANGE_AVC;
+                    }
+                } else if (profile == VAProfileHEVCMain ||
+                           profile == VAProfileHEVCMain10)
+                    attrib_list[i].value = ENCODER_QUALITY_RANGE_HEVC;
+                else if (profile == VAProfileVP9Profile0 &&
+                         entrypoint == VAEntrypointEncSliceLP) {
+                    attrib_list[i].value = ENCODER_QUALITY_RANGE_VP9;
                 }
+
                 break;
-            }
+            } else if (entrypoint == VAEntrypointStats)
+                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
             break;
-    
+
         case VAConfigAttribEncJPEG:
-            ifentrypoint == VAEntrypointEncPicture) {
-                VAConfigAttribValEncJPEG *configVal = (VAConfigAttribValEncJPEG*)&(attrib_list[i].value);
+            if (entrypoint == VAEntrypointEncPicture) {
+                VAConfigAttribValEncJPEG *configVal = (VAConfigAttribValEncJPEG*) & (attrib_list[i].value);
                 (configVal->bits).arithmatic_coding_mode = 0; // Huffman coding is used
                 (configVal->bits).progressive_dct_mode = 0;   // Only Sequential DCT is supported
                 (configVal->bits).non_interleaved_mode = 1;   // Support both interleaved and non-interleaved
-                (configVal->bits).differential_mode = 0;      // Baseline DCT is non-differential 
+                (configVal->bits).differential_mode = 0;      // Baseline DCT is non-differential
                 (configVal->bits).max_num_components = 3;     // Only 3 components supported
                 (configVal->bits).max_num_scans = 1;          // Only 1 scan per frame
                 (configVal->bits).max_num_huffman_tables = 3; // Max 3 huffman tables
@@ -1032,31 +1169,48 @@ i965_GetConfigAttributes(VADriverContextP ctx,
             break;
 
         case VAConfigAttribDecSliceMode:
-            attrib_list[i].value = VA_DEC_SLICE_MODE_NORMAL;
+            if (entrypoint == VAEntrypointVLD)
+                attrib_list[i].value = VA_DEC_SLICE_MODE_NORMAL;
             break;
 
         case VAConfigAttribEncROI:
             if (entrypoint == VAEntrypointEncSlice ||
-                entrypoint == VAEntrypointEncSliceLP) {
+                entrypoint == VAEntrypointEncSliceLP ||
+                entrypoint == VAEntrypointFEI) {
+                VAConfigAttribValEncROI *roi_config =
+                    (VAConfigAttribValEncROI *) & (attrib_list[i].value);
 
                 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;
+                    if (IS_GEN9(i965->intel.device_info) &&
+                        (entrypoint == VAEntrypointEncSlice ||
+                         entrypoint == VAEntrypointFEI ||
+                         entrypoint == VAEntrypointStats))
+                        attrib_list[i].value = 0;
+                    else if (IS_GEN10(i965->intel.device_info) &&
+                             (entrypoint == VAEntrypointEncSlice || entrypoint == VAEntrypointFEI))
+                        attrib_list[i].value = 0;
+                    else {
+                        if (entrypoint == VAEntrypointEncSliceLP) {
+                            roi_config->bits.num_roi_regions = 3;
+                            roi_config->bits.roi_rc_priority_support = 0;
+                            roi_config->bits.roi_rc_qp_delta_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_delta_support = 1;
+                        }
                     }
-                }else {
+                } else if (profile == VAProfileHEVCMain ||
+                           profile == VAProfileHEVCMain10) {
+                    roi_config->bits.num_roi_regions =
+                        I965_MAX_NUM_ROI_REGIONS;
+                    roi_config->bits.roi_rc_priority_support = 1;
+                    roi_config->bits.roi_rc_qp_delta_support = 1;
+                } else {
                     attrib_list[i].value = 0;
                 }
             }
@@ -1068,10 +1222,16 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                  profile == VAProfileH264Main ||
                  profile == VAProfileH264High) &&
                 entrypoint == VAEntrypointEncSlice) {
-                VAConfigAttribValEncRateControlExt *val_config = (VAConfigAttribValEncRateControlExt *)&(attrib_list[i].value);
+                if (IS_GEN9(i965->intel.device_info))
+                    attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+                else if (IS_GEN10(i965->intel.device_info))
+                    attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+                else {
+                    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;
+                    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;
             }
@@ -1079,30 +1239,67 @@ i965_GetConfigAttributes(VADriverContextP ctx,
             break;
 
         case VAConfigAttribEncMaxSlices:
+            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
             if (entrypoint == VAEntrypointEncSlice) {
                 if ((profile == VAProfileH264ConstrainedBaseline ||
-                    profile == VAProfileH264Main ||
-                    profile == VAProfileH264High) ||
+                     profile == VAProfileH264Main ||
+                     profile == VAProfileH264High) ||
                     profile == VAProfileH264StereoHigh ||
                     profile == VAProfileH264MultiviewHigh) {
-                        if (IS_GEN9(i965->intel.device_info))
-                            attrib_list[i].value = 1;
-                        else
-                            attrib_list[i].value = I965_MAX_NUM_SLICE;
-                }else if (profile == VAProfileHEVCMain ||
-                    profile == VAProfileHEVCMain10) {
-                        attrib_list[i].value = I965_MAX_NUM_SLICE;
+                    attrib_list[i].value = I965_MAX_NUM_SLICE;
+                } else if (profile == VAProfileHEVCMain ||
+                           profile == VAProfileHEVCMain10) {
+                    attrib_list[i].value = I965_MAX_NUM_SLICE;
                 }
-            } else if (entrypoint == VAEntrypointEncSliceLP) {
+            } else if (entrypoint == VAEntrypointEncSliceLP || entrypoint == VAEntrypointFEI) {
                 if ((profile == VAProfileH264ConstrainedBaseline ||
-                    profile == VAProfileH264Main ||
-                    profile == VAProfileH264High) ||
+                     profile == VAProfileH264Main ||
+                     profile == VAProfileH264High) ||
                     profile == VAProfileH264StereoHigh ||
                     profile == VAProfileH264MultiviewHigh)
                     attrib_list[i].value = I965_MAX_NUM_SLICE;
-            } else
-                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+            }
+
+            break;
+
+        case VAConfigAttribEncSliceStructure:
+            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+            if (entrypoint == VAEntrypointEncSlice) {
+                if ((profile == VAProfileH264ConstrainedBaseline ||
+                     profile == VAProfileH264Main ||
+                     profile == VAProfileH264High) ||
+                    profile == VAProfileH264StereoHigh ||
+                    profile == VAProfileH264MultiviewHigh ||
+                    profile == VAProfileHEVCMain ||
+                    profile == VAProfileHEVCMain10) {
+                    attrib_list[i].value = VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS;
+                }
+            }
+
+            break;
 
+        case VAConfigAttribFEIFunctionType:
+            if (entrypoint == VAEntrypointFEI) {
+                /* Supporting all possible modes of FEI */
+                attrib_list[i].value = VA_FEI_FUNCTION_ENC |
+                                       VA_FEI_FUNCTION_PAK | VA_FEI_FUNCTION_ENC_PAK;
+            }
+            break;
+
+        case VAConfigAttribFEIMVPredictors:
+            if (entrypoint == VAEntrypointFEI)
+                attrib_list[i].value = 4;
+            break;
+
+        case VAConfigAttribStats:
+            if (entrypoint == VAEntrypointStats) {
+                VAConfigAttribValStats *configVal =
+                    (VAConfigAttribValStats*) & (attrib_list[i].value);
+                (configVal->bits).max_num_past_references = STATS_MAX_NUM_PAST_REFS;
+                (configVal->bits).max_num_future_references = STATS_MAX_NUM_FUTURE_REFS;
+                (configVal->bits).num_outputs = STATS_MAX_NUM_OUTPUTS;
+                (configVal->bits).interlaced = STATS_INTERLACED_SUPPORT;
+            }
             break;
 
         default:
@@ -1115,7 +1312,7 @@ i965_GetConfigAttributes(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-static void 
+static void
 i965_destroy_config(struct object_heap *heap, struct object_base *obj)
 {
     object_heap_free(heap, obj);
@@ -1123,7 +1320,7 @@ i965_destroy_config(struct object_heap *heap, struct object_base *obj)
 
 static VAConfigAttrib *
 i965_lookup_config_attribute(struct object_config *obj_config,
-    VAConfigAttribType type)
+                             VAConfigAttribType type)
 {
     int i;
 
@@ -1137,7 +1334,7 @@ i965_lookup_config_attribute(struct object_config *obj_config,
 
 static VAStatus
 i965_append_config_attribute(struct object_config *obj_config,
-    const VAConfigAttrib *new_attrib)
+                             const VAConfigAttrib *new_attrib)
 {
     VAConfigAttrib *attrib;
 
@@ -1152,7 +1349,7 @@ i965_append_config_attribute(struct object_config *obj_config,
 
 static VAStatus
 i965_ensure_config_attribute(struct object_config *obj_config,
-    const VAConfigAttrib *new_attrib)
+                             const VAConfigAttrib *new_attrib)
 {
     VAConfigAttrib *attrib;
 
@@ -1166,7 +1363,7 @@ i965_ensure_config_attribute(struct object_config *obj_config,
     return i965_append_config_attribute(obj_config, new_attrib);
 }
 
-VAStatus 
+VAStatus
 i965_CreateConfig(VADriverContextP ctx,
                   VAProfile profile,
                   VAEntrypoint entrypoint,
@@ -1201,7 +1398,8 @@ i965_CreateConfig(VADriverContextP ctx,
 
     for (i = 0; i < num_attribs; i++) {
         // add it later and ignore the user input for VAConfigAttribEncMaxSlices
-        if(attrib_list[i].type == VAConfigAttribEncMaxSlices)
+        if (attrib_list[i].type == VAConfigAttribEncMaxSlices ||
+            attrib_list[i].type == VAConfigAttribEncSliceStructure)
             continue;
         vaStatus = i965_ensure_config_attribute(obj_config, &attrib_list[i]);
         if (vaStatus != VA_STATUS_SUCCESS)
@@ -1219,38 +1417,98 @@ i965_CreateConfig(VADriverContextP ctx,
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
     }
 
+
+    if (vaStatus == VA_STATUS_SUCCESS) {
+        VAConfigAttrib *attrib_found = i965_lookup_config_attribute(obj_config, VAConfigAttribRateControl);
+
+        if (attrib_found) {
+            uint32_t rc_attribs = i965_get_rc_attributes(ctx, profile, entrypoint);
+
+            if (!(attrib_found->value & rc_attribs))
+                vaStatus = VA_STATUS_ERROR_INVALID_VALUE;
+        }
+    }
+
+    if (vaStatus == VA_STATUS_SUCCESS) {
+        VAConfigAttrib *attrib_found = i965_lookup_config_attribute(obj_config, VAConfigAttribEncPackedHeaders);
+
+        if (attrib_found) {
+            uint32_t enc_packed_attribs = i965_get_enc_packed_attributes(ctx, profile, entrypoint);
+
+            if (enc_packed_attribs == VA_ATTRIB_NOT_SUPPORTED) {
+                i965_log_info(ctx, "vaCreateConfig: invalid EncPackedHeaders attribute %#x: "
+                              "packed headers are not supported.\n", attrib_found->value);
+                vaStatus = VA_STATUS_ERROR_INVALID_VALUE;
+            } else if (attrib_found->value == 0) {
+                i965_log_info(ctx, "vaCreateConfig: setting the EncPackedHeaders attribute to zero to "
+                              "indicate that no packed headers will be used is deprecated.\n");
+            } else {
+                if (attrib_found->value & ~enc_packed_attribs) {
+                    i965_log_info(ctx, "vaCreateConfig: invalid EncPackedHeaders attribute %#x: "
+                                  "some packed headers are not supported (supported set %#x).\n",
+                                  attrib_found->value, enc_packed_attribs);
+                    vaStatus = VA_STATUS_ERROR_INVALID_VALUE;
+                }
+            }
+        }
+    }
+
     if (vaStatus == VA_STATUS_SUCCESS) {
         VAConfigAttrib attrib;
         attrib.type = VAConfigAttribEncMaxSlices;
         attrib.value = VA_ATTRIB_NOT_SUPPORTED;
         if (entrypoint == VAEntrypointEncSlice) {
             if ((profile == VAProfileH264ConstrainedBaseline ||
-                profile == VAProfileH264Main ||
-                profile == VAProfileH264High) ||
+                 profile == VAProfileH264Main ||
+                 profile == VAProfileH264High) ||
                 profile == VAProfileH264StereoHigh ||
                 profile == VAProfileH264MultiviewHigh) {
-                    if (IS_GEN9(i965->intel.device_info))
-                        attrib.value = 1;
-                    else
-                        attrib.value = I965_MAX_NUM_SLICE;
-            }else if (profile == VAProfileHEVCMain ||
-                profile == VAProfileHEVCMain10) {
                 attrib.value = I965_MAX_NUM_SLICE;
-            }
-        } else if (entrypoint == VAEntrypointEncSliceLP) {
+            } else if (profile == VAProfileHEVCMain ||
+                       profile == VAProfileHEVCMain10)
+                attrib.value = I965_MAX_NUM_SLICE;
+        } else if (entrypoint == VAEntrypointEncSliceLP || entrypoint == VAEntrypointFEI) {
             if ((profile == VAProfileH264ConstrainedBaseline ||
-                profile == VAProfileH264Main ||
-                profile == VAProfileH264High) ||
+                 profile == VAProfileH264Main ||
+                 profile == VAProfileH264High) ||
                 profile == VAProfileH264StereoHigh ||
                 profile == VAProfileH264MultiviewHigh)
                 attrib.value = I965_MAX_NUM_SLICE;
-        } else
-            attrib.value = VA_ATTRIB_NOT_SUPPORTED;
+        }
 
-        if(attrib.value != VA_ATTRIB_NOT_SUPPORTED)
+        if (attrib.value != VA_ATTRIB_NOT_SUPPORTED)
             vaStatus = i965_append_config_attribute(obj_config, &attrib);
     }
 
+    if (vaStatus == VA_STATUS_SUCCESS) {
+        VAConfigAttrib attrib;
+        attrib.type = VAConfigAttribEncSliceStructure;
+        attrib.value = VA_ATTRIB_NOT_SUPPORTED;
+        if (entrypoint == VAEntrypointEncSlice) {
+            if ((profile == VAProfileH264ConstrainedBaseline ||
+                 profile == VAProfileH264Main ||
+                 profile == VAProfileH264High) ||
+                profile == VAProfileH264StereoHigh ||
+                profile == VAProfileH264MultiviewHigh) {
+                attrib.value = VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS;
+            }
+        }
+
+        if (attrib.value != VA_ATTRIB_NOT_SUPPORTED)
+            vaStatus = i965_append_config_attribute(obj_config, &attrib);
+    }
+
+    if (vaStatus == VA_STATUS_SUCCESS) {
+        VAConfigAttrib *attrib_found;
+
+        attrib_found = i965_lookup_config_attribute(obj_config, VAConfigAttribDecSliceMode);
+
+        if (attrib_found &&
+            (entrypoint != VAEntrypointVLD ||
+             attrib_found->value != VA_DEC_SLICE_MODE_NORMAL))
+            vaStatus = VA_STATUS_ERROR_INVALID_VALUE;
+    }
+
     if ((vaStatus == VA_STATUS_SUCCESS) &&
         (profile == VAProfileVP9Profile0) &&
         (entrypoint == VAEntrypointVLD) &&
@@ -1279,7 +1537,7 @@ i965_CreateConfig(VADriverContextP ctx,
     return vaStatus;
 }
 
-VAStatus 
+VAStatus
 i965_DestroyConfig(VADriverContextP ctx, VAConfigID config_id)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
@@ -1320,7 +1578,7 @@ VAStatus i965_QueryConfigAttributes(VADriverContextP ctx,
     *entrypoint = obj_config->entrypoint;
     *num_attribs = obj_config->num_attribs;
 
-    for(i = 0; i < obj_config->num_attribs; i++) {
+    for (i = 0; i < obj_config->num_attribs; i++) {
         attrib_list[i] = obj_config->attrib_list[i];
     }
 
@@ -1342,7 +1600,7 @@ i965_destroy_surface_storage(struct object_surface *obj_surface)
     }
 }
 
-static void 
+static void
 i965_destroy_surface(struct object_heap *heap, struct object_base *obj)
 {
     struct object_surface *obj_surface = (struct object_surface *)obj;
@@ -1351,6 +1609,18 @@ i965_destroy_surface(struct object_heap *heap, struct object_base *obj)
     object_heap_free(heap, obj);
 }
 
+/* byte-per-pixel of the first plane */
+static int
+bpp_1stplane_by_fourcc(unsigned int fourcc)
+{
+    const i965_fourcc_info *info = get_fourcc_info(fourcc);
+
+    if (info && (info->flag & I_S))
+        return info->bpp[0] / 8;
+    else
+        return 0;
+}
+
 static VAStatus
 i965_surface_native_memory(VADriverContextP ctx,
                            struct object_surface *obj_surface,
@@ -1373,7 +1643,7 @@ i965_surface_native_memory(VADriverContextP ctx,
 
     return i965_check_alloc_surface_bo(ctx, obj_surface, tiling, expected_fourcc, get_sampling_from_fourcc(expected_fourcc));
 }
-    
+
 static VAStatus
 i965_suface_external_memory(VADriverContextP ctx,
                             struct object_surface *obj_surface,
@@ -1382,27 +1652,67 @@ i965_suface_external_memory(VADriverContextP ctx,
                             int index)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
+    unsigned int tiling, swizzle;
 
     if (!memory_attibute ||
         !memory_attibute->buffers ||
-        index > memory_attibute->num_buffers)
+        index >= memory_attibute->num_buffers)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    obj_surface->size = memory_attibute->data_size;
+    if (external_memory_type == I965_SURFACE_MEM_GEM_FLINK)
+        obj_surface->bo = drm_intel_bo_gem_create_from_name(i965->intel.bufmgr,
+                                                            "gem flinked vaapi surface",
+                                                            memory_attibute->buffers[index]);
+    else if (external_memory_type == I965_SURFACE_MEM_DRM_PRIME)
+        obj_surface->bo = drm_intel_bo_gem_create_from_prime(i965->intel.bufmgr,
+                                                             memory_attibute->buffers[index],
+                                                             obj_surface->size);
+
+    if (!obj_surface->bo)
         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
+    dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
+
     ASSERT_RET(obj_surface->orig_width == memory_attibute->width, VA_STATUS_ERROR_INVALID_PARAMETER);
     ASSERT_RET(obj_surface->orig_height == memory_attibute->height, VA_STATUS_ERROR_INVALID_PARAMETER);
     ASSERT_RET(memory_attibute->num_planes >= 1, VA_STATUS_ERROR_INVALID_PARAMETER);
 
     obj_surface->fourcc = memory_attibute->pixel_format;
     obj_surface->width = memory_attibute->pitches[0];
-    obj_surface->size = memory_attibute->data_size;
+    int bpp_1stplane = bpp_1stplane_by_fourcc(obj_surface->fourcc);
+    ASSERT_RET(IS_ALIGNED(obj_surface->width, 16), VA_STATUS_ERROR_INVALID_PARAMETER);
+    ASSERT_RET(obj_surface->width >= obj_surface->orig_width * bpp_1stplane, VA_STATUS_ERROR_INVALID_PARAMETER);
 
     if (memory_attibute->num_planes == 1)
         obj_surface->height = memory_attibute->data_size / obj_surface->width;
-    else 
+    else
         obj_surface->height = memory_attibute->offsets[1] / obj_surface->width;
 
+    if (memory_attibute->num_planes > 1) {
+        ASSERT_RET(obj_surface->height >= obj_surface->orig_height, VA_STATUS_ERROR_INVALID_PARAMETER);
+    }
+
+    if (tiling) {
+        ASSERT_RET(IS_ALIGNED(obj_surface->width, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+
+        if (memory_attibute->num_planes > 1)
+            ASSERT_RET(IS_ALIGNED(obj_surface->height, 32), VA_STATUS_ERROR_INVALID_PARAMETER);
+    } else {
+        ASSERT_RET(IS_ALIGNED(obj_surface->width, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
+
+        if (memory_attibute->num_planes > 1)
+            ASSERT_RET(IS_ALIGNED(obj_surface->height, i965->codec_info->min_linear_hpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
+    }
+
     obj_surface->x_cb_offset = 0; /* X offset is always 0 */
     obj_surface->x_cr_offset = 0;
+    if ((obj_surface->fourcc == VA_FOURCC_I420 ||
+         obj_surface->fourcc == VA_FOURCC_IYUV ||
+         obj_surface->fourcc == VA_FOURCC_I010 ||
+         obj_surface->fourcc == VA_FOURCC_YV12 ||
+         obj_surface->fourcc == VA_FOURCC_YV16) && tiling)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
 
     switch (obj_surface->fourcc) {
     case VA_FOURCC_NV12:
@@ -1416,6 +1726,10 @@ i965_suface_external_memory(VADriverContextP ctx,
         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
         obj_surface->cb_cr_height = obj_surface->orig_height / 2;
         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
+        if (tiling)
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+        else
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
 
         break;
 
@@ -1430,7 +1744,12 @@ i965_suface_external_memory(VADriverContextP ctx,
         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
         obj_surface->cb_cr_height = obj_surface->orig_height / 2;
         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
-        
+
+        if (tiling)
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+        else
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
+
         break;
 
     case VA_FOURCC_I420:
@@ -1446,6 +1765,10 @@ i965_suface_external_memory(VADriverContextP ctx,
         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
         obj_surface->cb_cr_height = obj_surface->orig_height / 2;
         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
+        if (tiling)
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+        else
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
 
         break;
 
@@ -1479,7 +1802,7 @@ i965_suface_external_memory(VADriverContextP ctx,
 
     case VA_FOURCC_Y800: /* monochrome surface */
         ASSERT_RET(memory_attibute->num_planes == 1, VA_STATUS_ERROR_INVALID_PARAMETER);
-        
+
         obj_surface->subsampling = SUBSAMPLE_YUV400;
         obj_surface->y_cb_offset = 0;
         obj_surface->y_cr_offset = 0;
@@ -1494,12 +1817,15 @@ i965_suface_external_memory(VADriverContextP ctx,
         ASSERT_RET(memory_attibute->pitches[1] == memory_attibute->pitches[2], VA_STATUS_ERROR_INVALID_PARAMETER);
 
         obj_surface->subsampling = SUBSAMPLE_YUV411;
-        obj_surface->y_cb_offset = 0;
-        obj_surface->y_cr_offset = 0;
+        obj_surface->y_cb_offset = obj_surface->height;
+        obj_surface->y_cr_offset = memory_attibute->offsets[2] / obj_surface->width;
         obj_surface->cb_cr_width = obj_surface->orig_width / 4;
         obj_surface->cb_cr_height = obj_surface->orig_height;
         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
-
+        if (tiling)
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+        else
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
         break;
 
     case VA_FOURCC_422H:
@@ -1512,12 +1838,16 @@ i965_suface_external_memory(VADriverContextP ctx,
         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
         obj_surface->cb_cr_height = obj_surface->orig_height;
         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
+        if (tiling)
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+        else
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
 
         break;
 
     case VA_FOURCC_YV16:
-        assert(memory_attibute->num_planes == 3);
-        assert(memory_attibute->pitches[1] == memory_attibute->pitches[2]);
+        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);
 
         obj_surface->subsampling = SUBSAMPLE_YUV422H;
         obj_surface->y_cr_offset = memory_attibute->offsets[1] / obj_surface->width;
@@ -1525,6 +1855,7 @@ i965_suface_external_memory(VADriverContextP ctx,
         obj_surface->cb_cr_width = obj_surface->orig_width / 2;
         obj_surface->cb_cr_height = obj_surface->orig_height;
         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
+        ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
 
         break;
 
@@ -1538,6 +1869,10 @@ i965_suface_external_memory(VADriverContextP ctx,
         obj_surface->cb_cr_width = obj_surface->orig_width;
         obj_surface->cb_cr_height = obj_surface->orig_height / 2;
         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
+        if (tiling)
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+        else
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
 
         break;
 
@@ -1551,41 +1886,20 @@ i965_suface_external_memory(VADriverContextP ctx,
         obj_surface->cb_cr_width = obj_surface->orig_width;
         obj_surface->cb_cr_height = obj_surface->orig_height;
         obj_surface->cb_cr_pitch = memory_attibute->pitches[1];
+        if (tiling)
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
+        else
+            ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
 
         break;
 
     default:
-
         return VA_STATUS_ERROR_INVALID_PARAMETER;
     }
 
-    if (external_memory_type == I965_SURFACE_MEM_GEM_FLINK)
-        obj_surface->bo = drm_intel_bo_gem_create_from_name(i965->intel.bufmgr,
-                                                            "gem flinked vaapi surface",
-                                                            memory_attibute->buffers[index]);
-    else if (external_memory_type == I965_SURFACE_MEM_DRM_PRIME)
-        obj_surface->bo = drm_intel_bo_gem_create_from_prime(i965->intel.bufmgr,
-                                                             memory_attibute->buffers[index],
-                                                             obj_surface->size);
-
-    if (!obj_surface->bo)
-        return VA_STATUS_ERROR_INVALID_PARAMETER;
-
     return VA_STATUS_SUCCESS;
 }
 
-/* byte-per-pixel of the first plane */
-static int
-bpp_1stplane_by_fourcc(unsigned int fourcc)
-{
-    const i965_fourcc_info *info = get_fourcc_info(fourcc);
-
-    if (info && (info->flag & I_S))
-        return info->bpp[0] / 8;
-    else
-        return 0;
-}
-
 static VAStatus
 i965_CreateSurfaces2(
     VADriverContextP    ctx,
@@ -1596,10 +1910,10 @@ i965_CreateSurfaces2(
     unsigned int        num_surfaces,
     VASurfaceAttrib    *attrib_list,
     unsigned int        num_attribs
-    )
+)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
-    int i,j;
+    int i, j;
     VAStatus vaStatus = VA_STATUS_SUCCESS;
     int expected_fourcc = 0;
     int memory_type = I965_SURFACE_MEM_NATIVE; /* native */
@@ -1614,7 +1928,7 @@ i965_CreateSurfaces2(
 
         if ((attrib_list[i].type == VASurfaceAttribMemoryType) &&
             (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) {
-            
+
             ASSERT_RET(attrib_list[i].value.type == VAGenericValueTypeInteger, VA_STATUS_ERROR_INVALID_PARAMETER);
 
             if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM)
@@ -1663,9 +1977,9 @@ i965_CreateSurfaces2(
         obj_surface->border_cleared = false;
 
         obj_surface->subpic_render_idx = 0;
-        for(j = 0; j < I965_MAX_SUBPIC_SUM; j++){
-           obj_surface->subpic[j] = VA_INVALID_ID;
-           obj_surface->obj_subpic[j] = NULL;
+        for (j = 0; j < I965_MAX_SUBPIC_SUM; j++) {
+            obj_surface->subpic[j] = VA_INVALID_ID;
+            obj_surface->obj_subpic[j] = NULL;
         }
 
         assert(i965->codec_info->min_linear_wpitch);
@@ -1708,7 +2022,7 @@ i965_CreateSurfaces2(
 
                     if (memory_attibute->offsets[1]) {
                         ASSERT_RET(!memory_attibute->offsets[0], VA_STATUS_ERROR_INVALID_PARAMETER);
-                        obj_surface->height = memory_attibute->offsets[1]/memory_attibute->pitches[0];
+                        obj_surface->height = memory_attibute->offsets[1] / memory_attibute->pitches[0];
                         obj_surface->user_v_stride_set = true;
                         ASSERT_RET(IS_ALIGNED(obj_surface->height, 16), VA_STATUS_ERROR_INVALID_PARAMETER);
                         ASSERT_RET(obj_surface->height >= height, VA_STATUS_ERROR_INVALID_PARAMETER);
@@ -1739,7 +2053,7 @@ i965_CreateSurfaces2(
     /* Error recovery */
     if (VA_STATUS_SUCCESS != vaStatus) {
         /* surfaces[i-1] was the last successful allocation */
-        for (; i--; ) {
+        for (; i--;) {
             struct object_surface *obj_surface = SURFACE(surfaces[i]);
 
             surfaces[i] = VA_INVALID_SURFACE;
@@ -1751,7 +2065,7 @@ i965_CreateSurfaces2(
     return vaStatus;
 }
 
-VAStatus 
+VAStatus
 i965_CreateSurfaces(VADriverContextP ctx,
                     int width,
                     int height,
@@ -1769,7 +2083,7 @@ i965_CreateSurfaces(VADriverContextP ctx,
                                 0);
 }
 
-VAStatus 
+VAStatus
 i965_DestroySurfaces(VADriverContextP ctx,
                      VASurfaceID *surface_list,
                      int num_surfaces)
@@ -1778,7 +2092,7 @@ i965_DestroySurfaces(VADriverContextP ctx,
     int i;
     VAStatus va_status = VA_STATUS_SUCCESS;
 
-    for (i = num_surfaces; i--; ) {
+    for (i = num_surfaces; i--;) {
         struct object_surface *obj_surface = SURFACE(surface_list[i]);
 
         ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
@@ -1792,8 +2106,8 @@ i965_DestroySurfaces(VADriverContextP ctx,
             obj_surface->wrapper_surface = VA_INVALID_ID;
         }
         if (obj_surface->exported_primefd >= 0) {
-           close(obj_surface->exported_primefd);
-           obj_surface->exported_primefd = -1;
+            close(obj_surface->exported_primefd);
+            obj_surface->exported_primefd = -1;
         }
 
         i965_destroy_surface(&i965->surface_heap, (struct object_base *)obj_surface);
@@ -1802,7 +2116,7 @@ i965_DestroySurfaces(VADriverContextP ctx,
     return va_status;
 }
 
-VAStatus 
+VAStatus
 i965_QueryImageFormats(VADriverContextP ctx,
                        VAImageFormat *format_list,      /* out */
                        int *num_formats)                /* out */
@@ -1858,6 +2172,7 @@ i965_guess_surface_format(VADriverContextP ctx,
     if (IS_GEN6(i965->intel.device_info) ||
         IS_GEN7(i965->intel.device_info) ||
         IS_GEN8(i965->intel.device_info) ||
+        IS_GEN10(i965->intel.device_info) ||
         IS_GEN9(i965->intel.device_info)) {
         *fourcc = VA_FOURCC_NV12;
         *is_tiled = 1;
@@ -1878,7 +2193,7 @@ i965_guess_surface_format(VADriverContextP ctx,
     }
 }
 
-VAStatus 
+VAStatus
 i965_QuerySubpictureFormats(VADriverContextP ctx,
                             VAImageFormat *format_list,         /* out */
                             unsigned int *flags,                /* out */
@@ -1900,7 +2215,7 @@ i965_QuerySubpictureFormats(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-static void 
+static void
 i965_destroy_subpic(struct object_heap *heap, struct object_base *obj)
 {
     //    struct object_subpic *obj_subpic = (struct object_subpic *)obj;
@@ -1908,14 +2223,14 @@ i965_destroy_subpic(struct object_heap *heap, struct object_base *obj)
     object_heap_free(heap, obj);
 }
 
-VAStatus 
+VAStatus
 i965_CreateSubpicture(VADriverContextP ctx,
                       VAImageID image,
                       VASubpictureID *subpicture)         /* out */
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     VASubpictureID subpicID = NEW_SUBPIC_ID()
-    struct object_subpic *obj_subpic = SUBPIC(subpicID);
+                              struct object_subpic * obj_subpic = SUBPIC(subpicID);
 
     if (!obj_subpic)
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
@@ -1937,11 +2252,11 @@ i965_CreateSubpicture(VADriverContextP ctx,
     obj_subpic->pitch  = obj_image->image.pitches[0];
     obj_subpic->bo     = obj_image->bo;
     obj_subpic->global_alpha = 1.0;
+
     return VA_STATUS_SUCCESS;
 }
 
-VAStatus 
+VAStatus
 i965_DestroySubpicture(VADriverContextP ctx,
                        VASubpictureID subpicture)
 {
@@ -1956,7 +2271,7 @@ i965_DestroySubpicture(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-VAStatus 
+VAStatus
 i965_SetSubpictureImage(VADriverContextP ctx,
                         VASubpictureID subpicture,
                         VAImageID image)
@@ -1965,7 +2280,7 @@ i965_SetSubpictureImage(VADriverContextP ctx,
     return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
-VAStatus 
+VAStatus
 i965_SetSubpictureChromakey(VADriverContextP ctx,
                             VASubpictureID subpicture,
                             unsigned int chromakey_min,
@@ -1976,7 +2291,7 @@ i965_SetSubpictureChromakey(VADriverContextP ctx,
     return VA_STATUS_ERROR_UNIMPLEMENTED;
 }
 
-VAStatus 
+VAStatus
 i965_SetSubpictureGlobalAlpha(VADriverContextP ctx,
                               VASubpictureID subpicture,
                               float global_alpha)
@@ -1984,8 +2299,8 @@ i965_SetSubpictureGlobalAlpha(VADriverContextP ctx,
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_subpic *obj_subpic = SUBPIC(subpicture);
 
-    if(global_alpha > 1.0 || global_alpha < 0.0){
-       return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (global_alpha > 1.0 || global_alpha < 0.0) {
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
     }
 
     if (!obj_subpic)
@@ -1996,7 +2311,7 @@ i965_SetSubpictureGlobalAlpha(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-VAStatus 
+VAStatus
 i965_AssociateSubpicture(VADriverContextP ctx,
                          VASubpictureID subpicture,
                          VASurfaceID *target_surfaces,
@@ -2021,7 +2336,7 @@ i965_AssociateSubpicture(VADriverContextP ctx,
 
     if (!obj_subpic)
         return VA_STATUS_ERROR_INVALID_SUBPICTURE;
-    
+
     ASSERT_RET(obj_subpic->obj_image, VA_STATUS_ERROR_INVALID_SUBPICTURE);
 
     obj_subpic->src_rect.x      = src_x;
@@ -2039,16 +2354,16 @@ i965_AssociateSubpicture(VADriverContextP ctx,
         if (!obj_surface)
             return VA_STATUS_ERROR_INVALID_SURFACE;
 
-        for(j = 0; j < I965_MAX_SUBPIC_SUM; j ++){
-            if(obj_surface->subpic[j] == VA_INVALID_ID){
+        for (j = 0; j < I965_MAX_SUBPIC_SUM; j ++) {
+            if (obj_surface->subpic[j] == VA_INVALID_ID) {
                 assert(obj_surface->obj_subpic[j] == NULL);
                 obj_surface->subpic[j] = subpicture;
                 obj_surface->obj_subpic[j] = obj_subpic;
                 break;
             }
         }
-        
-        if(j == I965_MAX_SUBPIC_SUM){
+
+        if (j == I965_MAX_SUBPIC_SUM) {
             return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
         }
 
@@ -2057,7 +2372,7 @@ i965_AssociateSubpicture(VADriverContextP ctx,
 }
 
 
-VAStatus 
+VAStatus
 i965_DeassociateSubpicture(VADriverContextP ctx,
                            VASubpictureID subpicture,
                            VASurfaceID *target_surfaces,
@@ -2075,7 +2390,7 @@ i965_DeassociateSubpicture(VADriverContextP ctx,
         if (!obj_surface)
             return VA_STATUS_ERROR_INVALID_SURFACE;
 
-        for(j = 0; j < I965_MAX_SUBPIC_SUM; j ++){
+        for (j = 0; j < I965_MAX_SUBPIC_SUM; j ++) {
             if (obj_surface->subpic[j] == subpicture) {
                 assert(obj_surface->obj_subpic[j] == obj_subpic);
                 obj_surface->subpic[j] = VA_INVALID_ID;
@@ -2083,8 +2398,8 @@ i965_DeassociateSubpicture(VADriverContextP ctx,
                 break;
             }
         }
-        
-        if(j == I965_MAX_SUBPIC_SUM){
+
+        if (j == I965_MAX_SUBPIC_SUM) {
             return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
         }
     }
@@ -2092,7 +2407,7 @@ i965_DeassociateSubpicture(VADriverContextP ctx,
 }
 
 void
-i965_reference_buffer_store(struct buffer_store **ptr, 
+i965_reference_buffer_store(struct buffer_store **ptr,
                             struct buffer_store *buffer_store)
 {
     assert(*ptr == NULL);
@@ -2103,7 +2418,7 @@ i965_reference_buffer_store(struct buffer_store **ptr,
     }
 }
 
-void 
+void
 i965_release_buffer_store(struct buffer_store **ptr)
 {
     struct buffer_store *buffer_store = *ptr;
@@ -2114,7 +2429,7 @@ i965_release_buffer_store(struct buffer_store **ptr)
     assert(buffer_store->bo || buffer_store->buffer);
     assert(!(buffer_store->bo && buffer_store->buffer));
     buffer_store->ref_count--;
-    
+
     if (buffer_store->ref_count == 0) {
         dri_bo_unreference(buffer_store->bo);
         free(buffer_store->buffer);
@@ -2126,7 +2441,7 @@ i965_release_buffer_store(struct buffer_store **ptr)
     *ptr = NULL;
 }
 
-static void 
+static void
 i965_destroy_context(struct object_heap *heap, struct object_base *obj)
 {
     struct object_context *obj_context = (struct object_context *)obj;
@@ -2185,12 +2500,17 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
         free(obj_context->codec_state.encode.packed_header_data_ext);
 
         i965_release_buffer_store(&obj_context->codec_state.encode.encmb_map);
+    } else if (obj_context->codec_type == CODEC_PREENC) {
+        /* using the same encode codec_state for preenc too,
+         * since both sharig all most same code except in few places */
+        i965_release_buffer_store(&obj_context->codec_state.encode.stat_param_ext);
     } else {
         assert(obj_context->codec_state.decode.num_slice_params <= obj_context->codec_state.decode.max_slice_params);
         assert(obj_context->codec_state.decode.num_slice_datas <= obj_context->codec_state.decode.max_slice_datas);
 
         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
         i965_release_buffer_store(&obj_context->codec_state.decode.iq_matrix);
+        i965_release_buffer_store(&obj_context->codec_state.decode.huffman_table);
         i965_release_buffer_store(&obj_context->codec_state.decode.bit_plane);
 
         for (i = 0; i < obj_context->codec_state.decode.num_slice_params; i++)
@@ -2240,12 +2560,16 @@ i965_CreateContext(VADriverContextP ctx,
     int i;
     int max_width;
     int max_height;
+    int min_width_height = I965_MIN_CODEC_ENC_RESOLUTION_WIDTH_HEIGHT;
 
     if (NULL == obj_config) {
         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
         return vaStatus;
     }
 
+    if (obj_config->profile == VAProfileJPEGBaseline)
+        min_width_height = 1;
+
     max_resolution(i965, obj_config, &max_width, &max_height);
 
     if (picture_width > max_width ||
@@ -2254,6 +2578,17 @@ i965_CreateContext(VADriverContextP ctx,
         return vaStatus;
     }
 
+    if ((VAEntrypointEncSlice == obj_config->entrypoint) ||
+        (VAEntrypointEncPicture == obj_config->entrypoint) ||
+        (VAEntrypointEncSliceLP == obj_config->entrypoint) ||
+        (VAEntrypointFEI == obj_config->entrypoint)) {
+        if (picture_width < min_width_height ||
+            picture_height < min_width_height) {
+            vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
+            return vaStatus;
+        }
+    }
+
     /* Validate flag */
     /* Validate picture dimensions */
     contextID = NEW_CONTEXT_ID();
@@ -2271,7 +2606,7 @@ i965_CreateContext(VADriverContextP ctx,
     obj_context->picture_width = picture_width;
     obj_context->picture_height = picture_height;
     obj_context->num_render_targets = num_render_targets;
-    obj_context->render_targets = 
+    obj_context->render_targets =
         (VASurfaceID *)calloc(num_render_targets, sizeof(VASurfaceID));
     obj_context->hw_context = NULL;
     obj_context->wrapper_context = VA_INVALID_ID;
@@ -2279,7 +2614,7 @@ i965_CreateContext(VADriverContextP ctx,
     if (!obj_context->render_targets)
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
-    for(i = 0; i < num_render_targets; i++) {
+    for (i = 0; i < num_render_targets; i++) {
         if (NULL == SURFACE(render_targets[i])) {
             vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
             break;
@@ -2295,9 +2630,10 @@ i965_CreateContext(VADriverContextP ctx,
             obj_context->codec_state.proc.current_render_target = VA_INVALID_ID;
             assert(i965->codec_info->proc_hw_context_init);
             obj_context->hw_context = i965->codec_info->proc_hw_context_init(ctx, obj_config);
-         } else if ((VAEntrypointEncSlice == obj_config->entrypoint) || 
-                    (VAEntrypointEncPicture == obj_config->entrypoint) ||
-                    (VAEntrypointEncSliceLP == obj_config->entrypoint)) {
+        } else if ((VAEntrypointEncSlice == obj_config->entrypoint) ||
+                   (VAEntrypointEncPicture == obj_config->entrypoint) ||
+                   (VAEntrypointEncSliceLP == obj_config->entrypoint) ||
+                   (VAEntrypointFEI == 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));
@@ -2329,15 +2665,15 @@ i965_CreateContext(VADriverContextP ctx,
                 obj_context->codec_state.encode.packed_header_flag = packed_attrib->value;
                 if (obj_config->profile == VAProfileVP9Profile0)
                     obj_context->codec_state.encode.packed_header_flag =
-                            packed_attrib->value & VA_ENC_PACKED_HEADER_RAW_DATA;
+                        packed_attrib->value & VA_ENC_PACKED_HEADER_RAW_DATA;
             } else {
                 /* use the default value. SPS/PPS/RAWDATA is passed from user
                  * while Slice_header data is generated by driver.
                  */
                 obj_context->codec_state.encode.packed_header_flag =
-                               VA_ENC_PACKED_HEADER_SEQUENCE |
-                               VA_ENC_PACKED_HEADER_PICTURE |
-                               VA_ENC_PACKED_HEADER_RAW_DATA;
+                    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)
@@ -2345,6 +2681,13 @@ i965_CreateContext(VADriverContextP ctx,
             }
             assert(i965->codec_info->enc_hw_context_init);
             obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config);
+        } else if (VAEntrypointStats == obj_config->entrypoint) {
+            /* PreEnc sharing the ENC structures */
+            obj_context->codec_type = CODEC_PREENC;
+            memset(&obj_context->codec_state.encode, 0, sizeof(obj_context->codec_state.encode));
+            obj_context->codec_state.encode.current_render_target = VA_INVALID_ID;
+            assert(i965->codec_info->enc_hw_context_init);
+            obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config);
         } else {
             obj_context->codec_type = CODEC_DEC;
             memset(&obj_context->codec_state.decode, 0, sizeof(obj_context->codec_state.decode));
@@ -2352,9 +2695,9 @@ i965_CreateContext(VADriverContextP ctx,
             obj_context->codec_state.decode.max_slice_params = NUM_SLICES;
             obj_context->codec_state.decode.max_slice_datas = NUM_SLICES;
             obj_context->codec_state.decode.slice_params = calloc(obj_context->codec_state.decode.max_slice_params,
-                                                               sizeof(*obj_context->codec_state.decode.slice_params));
+                                                                  sizeof(*obj_context->codec_state.decode.slice_params));
             obj_context->codec_state.decode.slice_datas = calloc(obj_context->codec_state.decode.max_slice_datas,
-                                                              sizeof(*obj_context->codec_state.decode.slice_datas));
+                                                                 sizeof(*obj_context->codec_state.decode.slice_datas));
 
             assert(i965->codec_info->dec_hw_context_init);
             obj_context->hw_context = i965->codec_info->dec_hw_context_init(ctx, obj_config);
@@ -2390,6 +2733,7 @@ i965_CreateContext(VADriverContextP ctx,
         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);
@@ -2400,7 +2744,7 @@ i965_CreateContext(VADriverContextP ctx,
     return vaStatus;
 }
 
-VAStatus 
+VAStatus
 i965_DestroyContext(VADriverContextP ctx, VAContextID context)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
@@ -2426,7 +2770,7 @@ i965_DestroyContext(VADriverContextP ctx, VAContextID context)
     return va_status;
 }
 
-static void 
+static void
 i965_destroy_buffer(struct object_heap *heap, struct object_base *obj)
 {
     struct object_buffer *obj_buffer = (struct object_buffer *)obj;
@@ -2479,6 +2823,18 @@ i965_create_buffer_internal(VADriverContextP ctx,
     case VAHuffmanTableBufferType:
     case VAProbabilityBufferType:
     case VAEncMacroblockMapBufferType:
+    case VAEncQPBufferType:
+    case VAEncFEIMVBufferType:
+    case VAEncFEIMBCodeBufferType:
+    case VAEncFEIDistortionBufferType:
+    case VAEncFEIMBControlBufferType:
+    case VAEncFEIMVPredictorBufferType:
+    case VAStatsStatisticsParameterBufferType:
+    case VAStatsStatisticsBufferType:
+    case VAStatsStatisticsBottomFieldBufferType:
+    case VAStatsMVBufferType:
+    case VAStatsMVPredictorBufferType:
+
         /* Ok */
         break;
 
@@ -2536,11 +2892,22 @@ i965_create_buffer_internal(VADriverContextP ctx,
         /* 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 || 
+    } else if (type == VASliceDataBufferType ||
+               type == VAImageBufferType ||
                type == VAEncCodedBufferType ||
                type == VAEncMacroblockMapBufferType ||
-               type == VAProbabilityBufferType) {
+               type == VAProbabilityBufferType ||
+               type == VAEncQPBufferType ||
+               type == VAEncFEIMVBufferType ||
+               type == VAEncFEIMBCodeBufferType ||
+               type == VAEncFEIDistortionBufferType ||
+               type == VAEncFEIMBControlBufferType ||
+               type == VAEncFEIMVPredictorBufferType ||
+               type == VAEncFEIMVPredictorBufferType ||
+               type == VAStatsStatisticsBufferType ||
+               type == VAStatsStatisticsBottomFieldBufferType ||
+               type == VAStatsMVBufferType ||
+               type == VAStatsMVPredictorBufferType) {
 
         /* If the buffer is wrapped, the bo/buffer of buffer_store is bogus.
          * So it is enough to allocate one 64 byte bo
@@ -2559,28 +2926,28 @@ i965_create_buffer_internal(VADriverContextP ctx,
          * 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);
-            coded_buffer_segment = (struct i965_coded_buffer_segment *)buffer_store->bo->virtual;
-            coded_buffer_segment->base.size = size - I965_CODEDBUFFER_HEADER_SIZE;
-            coded_buffer_segment->base.bit_offset = 0;
-            coded_buffer_segment->base.status = 0;
-            coded_buffer_segment->base.buf = NULL;
-            coded_buffer_segment->base.next = NULL;
-            coded_buffer_segment->mapped = 0;
-            coded_buffer_segment->codec = 0;
-            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);
-          }
-       }
+            if (type == VAEncCodedBufferType) {
+                struct i965_coded_buffer_segment *coded_buffer_segment;
+
+                dri_bo_map(buffer_store->bo, 1);
+                coded_buffer_segment = (struct i965_coded_buffer_segment *)buffer_store->bo->virtual;
+                coded_buffer_segment->base.size = size - I965_CODEDBUFFER_HEADER_SIZE;
+                coded_buffer_segment->base.bit_offset = 0;
+                coded_buffer_segment->base.status = 0;
+                coded_buffer_segment->base.buf = NULL;
+                coded_buffer_segment->base.next = NULL;
+                coded_buffer_segment->mapped = 0;
+                coded_buffer_segment->codec = 0;
+                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 {
         int msize = size;
-        
+
         if (type == VAEncPackedHeaderDataBufferType) {
             msize = ALIGN(size, 4);
         }
@@ -2608,7 +2975,7 @@ i965_create_buffer_internal(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-VAStatus 
+VAStatus
 i965_CreateBuffer(VADriverContextP ctx,
                   VAContextID context,          /* in */
                   VABufferType type,            /* in */
@@ -2621,7 +2988,7 @@ i965_CreateBuffer(VADriverContextP ctx,
 }
 
 
-VAStatus 
+VAStatus
 i965_BufferSetNumElements(VADriverContextP ctx,
                           VABufferID buf_id,           /* in */
                           unsigned int num_elements)   /* in */
@@ -2641,12 +3008,11 @@ i965_BufferSetNumElements(VADriverContextP ctx,
 
         CALL_VTABLE(pdrvctx, vaStatus,
                     vaBufferSetNumElements(pdrvctx, obj_buffer->wrapper_buffer,
-                                         num_elements));
+                                           num_elements));
         return vaStatus;
     }
 
-    if ((num_elements < 0) || 
-        (num_elements > obj_buffer->max_num_elements)) {
+    if (num_elements > obj_buffer->max_num_elements) {
         vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
     } else {
         obj_buffer->num_elements = num_elements;
@@ -2658,7 +3024,7 @@ i965_BufferSetNumElements(VADriverContextP ctx,
     return vaStatus;
 }
 
-VAStatus 
+VAStatus
 i965_MapBuffer(VADriverContextP ctx,
                VABufferID buf_id,       /* in */
                void **pbuf)             /* out */
@@ -2734,7 +3100,7 @@ i965_MapBuffer(VADriverContextP ctx,
                         delimiter2 = MPEG2_DELIMITER2;
                         delimiter3 = MPEG2_DELIMITER3;
                         delimiter4 = MPEG2_DELIMITER4;
-                    } else if(coded_buffer_segment->codec == CODEC_JPEG) {
+                    } 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;
@@ -2748,9 +3114,9 @@ i965_MapBuffer(VADriverContextP ctx,
                         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)) {
+                    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;
                             }
                         }
@@ -2794,7 +3160,7 @@ i965_MapBuffer(VADriverContextP ctx,
     return vaStatus;
 }
 
-VAStatus 
+VAStatus
 i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
@@ -2836,10 +3202,10 @@ i965_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
         vaStatus = VA_STATUS_SUCCESS;
     }
 
-    return vaStatus;    
+    return vaStatus;
 }
 
-VAStatus 
+VAStatus
 i965_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
@@ -2861,12 +3227,12 @@ i965_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id)
     return va_status;
 }
 
-VAStatus 
+VAStatus
 i965_BeginPicture(VADriverContextP ctx,
                   VAContextID context,
                   VASurfaceID render_target)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    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;
@@ -2920,6 +3286,10 @@ i965_BeginPicture(VADriverContextP ctx,
                 i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i][j]);
 
         i965_release_buffer_store(&obj_context->codec_state.encode.encmb_map);
+    } else if (obj_context->codec_type == CODEC_PREENC) {
+        /* PreEnc sharing the ENC structures */
+        i965_release_buffer_store(&obj_context->codec_state.encode.stat_param_ext);
+        obj_context->codec_state.encode.current_render_target = render_target;
     } else {
         obj_context->codec_state.decode.current_render_target = render_target;
         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
@@ -3001,8 +3371,8 @@ DEF_RENDER_DECODE_MULTI_BUFFER_FUNC(slice_data, slice_datas)
 
 static VAStatus
 i965_decoder_vp9_wrapper_picture(VADriverContextP ctx,
-                             VABufferID *buffers,
-                             int num_buffers)
+                                 VABufferID *buffers,
+                                 int num_buffers)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     VAStatus vaStatus = VA_STATUS_SUCCESS;
@@ -3047,7 +3417,7 @@ i965_decoder_vp9_wrapper_picture(VADriverContextP ctx,
                     vaStatus = i965_surface_wrapper(ctx, surface_id);
                     if (vaStatus != VA_STATUS_SUCCESS) {
                         pdrvctx->vtable->vaUnmapBuffer(pdrvctx,
-                                    obj_buffer->wrapper_buffer);
+                                                       obj_buffer->wrapper_buffer);
                         goto fail_out;
                     }
                 }
@@ -3112,17 +3482,17 @@ i965_decoder_wrapper_picture(VADriverContextP ctx,
     return vaStatus;
 }
 
-static VAStatus 
+static VAStatus
 i965_decoder_render_picture(VADriverContextP ctx,
                             VAContextID context,
                             VABufferID *buffers,
                             int num_buffers)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_context *obj_context = CONTEXT(context);
     VAStatus vaStatus = VA_STATUS_SUCCESS;
     int i;
-    
+
     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
 
     for (i = 0; i < num_buffers && vaStatus == VA_STATUS_SUCCESS; i++) {
@@ -3135,7 +3505,7 @@ i965_decoder_render_picture(VADriverContextP ctx,
         case VAPictureParameterBufferType:
             vaStatus = I965_RENDER_DECODE_BUFFER(picture_parameter);
             break;
-            
+
         case VAIQMatrixBufferType:
             vaStatus = I965_RENDER_DECODE_BUFFER(iq_matrix);
             break;
@@ -3176,7 +3546,7 @@ i965_decoder_render_picture(VADriverContextP ctx,
 #define I965_RENDER_ENCODE_BUFFER(name) I965_RENDER_BUFFER(encode, name)
 
 #define DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(encode, name, member)
-// DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(sequence_parameter, seq_param)    
+// DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(sequence_parameter, seq_param)
 // DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_parameter, pic_param)
 // DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(picture_control, pic_control)
 DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(qmatrix, q_matrix)
@@ -3186,6 +3556,7 @@ DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(huffman_table, huffman_table)
 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)
+DEF_RENDER_ENCODE_SINGLE_BUFFER_FUNC(statistics_parameter_ext, stat_param_ext)
 
 #define DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(name, member) DEF_RENDER_MULTI_BUFFER_FUNC(encode, name, member)
 // DEF_RENDER_ENCODE_MULTI_BUFFER_FUNC(slice_parameter, slice_params)
@@ -3280,13 +3651,13 @@ i965_encoder_render_misc_parameter_buffer(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-static VAStatus 
+static VAStatus
 i965_encoder_render_picture(VADriverContextP ctx,
                             VAContextID context,
                             VABufferID *buffers,
                             int num_buffers)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_context *obj_context = CONTEXT(context);
     struct object_config *obj_config;
     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
@@ -3298,7 +3669,7 @@ i965_encoder_render_picture(VADriverContextP ctx,
     ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
 
     encode = &obj_context->codec_state.encode;
-    for (i = 0; i < num_buffers; i++) {  
+    for (i = 0; i < num_buffers; i++) {
         struct object_buffer *obj_buffer = BUFFER(buffers[i]);
 
         if (!obj_buffer)
@@ -3333,7 +3704,7 @@ i965_encoder_render_picture(VADriverContextP ctx,
                  * the packed data index/count for the slice
                  */
                 if (!(encode->packed_header_flag & VA_ENC_PACKED_HEADER_SLICE)) {
-                   encode->slice_index++;
+                    encode->slice_index++;
                 }
                 if (encode->slice_index == encode->max_slice_num) {
                     int slice_num = encode->max_slice_num;
@@ -3342,13 +3713,13 @@ i965_encoder_render_picture(VADriverContextP ctx,
                     encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
                                                           (slice_num + NUM_SLICES) * sizeof(int));
                     encode->slice_header_index = realloc(encode->slice_header_index,
-                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                                                         (slice_num + NUM_SLICES) * sizeof(int));
                     memset(encode->slice_rawdata_index + slice_num, 0,
-                        sizeof(int) * NUM_SLICES);
+                           sizeof(int) * NUM_SLICES);
                     memset(encode->slice_rawdata_count + slice_num, 0,
-                        sizeof(int) * NUM_SLICES);
+                           sizeof(int) * NUM_SLICES);
                     memset(encode->slice_header_index + slice_num, 0,
-                        sizeof(int) * NUM_SLICES);
+                           sizeof(int) * NUM_SLICES);
 
                     encode->max_slice_num += NUM_SLICES;
                     if ((encode->slice_rawdata_index == NULL) ||
@@ -3361,32 +3732,30 @@ i965_encoder_render_picture(VADriverContextP ctx,
             }
             break;
 
-        case VAEncPackedHeaderParameterBufferType:
-        {
+        case VAEncPackedHeaderParameterBufferType: {
             VAEncPackedHeaderParameterBuffer *param = (VAEncPackedHeaderParameterBuffer *)obj_buffer->buffer_store->buffer;
             encode->last_packed_header_type = param->type;
 
             if ((param->type == VAEncPackedHeaderRawData) ||
                 (param->type == VAEncPackedHeaderSlice)) {
                 vaStatus = I965_RENDER_ENCODE_BUFFER(packed_header_params_ext);
-            } else if((obj_config->profile == VAProfileHEVCMain ||
-                obj_config->profile == VAProfileHEVCMain10) &&
-                (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
+            } 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,
-                                                                          obj_buffer,
-                                                                          va_enc_packed_type_to_idx(encode->last_packed_header_type) + encode->vps_sps_seq_index);
+                                                                              obj_context,
+                                                                              obj_buffer,
+                                                                              va_enc_packed_type_to_idx(encode->last_packed_header_type) + encode->vps_sps_seq_index);
             } else {
                 vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
-                                                                          obj_context,
-                                                                          obj_buffer,
-                                                                          va_enc_packed_type_to_idx(encode->last_packed_header_type));
+                                                                              obj_context,
+                                                                              obj_buffer,
+                                                                              va_enc_packed_type_to_idx(encode->last_packed_header_type));
             }
             break;
         }
 
-        case VAEncPackedHeaderDataBufferType:
-        {
+        case VAEncPackedHeaderDataBufferType: {
             if (encode->last_packed_header_type == 0) {
                 WARN_ONCE("the packed header data is passed without type!\n");
                 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
@@ -3427,11 +3796,11 @@ i965_encoder_render_picture(VADriverContextP ctx,
                             int slice_num = encode->max_slice_num;
 
                             encode->slice_rawdata_index = realloc(encode->slice_rawdata_index,
-                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                                                                  (slice_num + NUM_SLICES) * sizeof(int));
                             encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
-                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                                                                  (slice_num + NUM_SLICES) * sizeof(int));
                             encode->slice_header_index = realloc(encode->slice_header_index,
-                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                                                                 (slice_num + NUM_SLICES) * sizeof(int));
                             memset(encode->slice_rawdata_index + slice_num, 0,
                                    sizeof(int) * NUM_SLICES);
                             memset(encode->slice_rawdata_count + slice_num, 0,
@@ -3455,38 +3824,38 @@ i965_encoder_render_picture(VADriverContextP ctx,
                                     SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
                             } else {
                                 WARN_ONCE("Multi slice header data is passed for"
-                                      " slice %d!\n", encode->slice_index);
+                                          " slice %d!\n", encode->slice_index);
                             }
                         }
                     }
                 }
             } else {
                 ASSERT_RET(encode->last_packed_header_type == VAEncPackedHeaderSequence ||
-                    encode->last_packed_header_type == VAEncPackedHeaderPicture ||
-                    encode->last_packed_header_type == VAEncPackedHeaderSlice ||
-                   (((encode->last_packed_header_type & VAEncPackedHeaderMiscMask) == VAEncPackedHeaderMiscMask) &&
-                    ((encode->last_packed_header_type & (~VAEncPackedHeaderMiscMask)) != 0)),
-                    VA_STATUS_ERROR_ENCODING_ERROR);
-
-                if((obj_config->profile == VAProfileHEVCMain ||
-                    obj_config->profile == VAProfileHEVCMain10) &&
+                           encode->last_packed_header_type == VAEncPackedHeaderPicture ||
+                           encode->last_packed_header_type == VAEncPackedHeaderSlice ||
+                           (((encode->last_packed_header_type & VAEncPackedHeaderMiscMask) == VAEncPackedHeaderMiscMask) &&
+                            ((encode->last_packed_header_type & (~VAEncPackedHeaderMiscMask)) != 0)),
+                           VA_STATUS_ERROR_ENCODING_ERROR);
+
+                if ((obj_config->profile == VAProfileHEVCMain ||
+                     obj_config->profile == VAProfileHEVCMain10) &&
                     (encode->last_packed_header_type == VAEncPackedHeaderSequence)) {
 
-                        vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
-                            obj_context,
-                            obj_buffer,
-                            va_enc_packed_type_to_idx(encode->last_packed_header_type) + encode->vps_sps_seq_index);
-                        encode->vps_sps_seq_index = (encode->vps_sps_seq_index + 1) % I965_SEQ_PACKED_HEADER_END;
-                }else{
                     vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
-                        obj_context,
-                        obj_buffer,
-                        va_enc_packed_type_to_idx(encode->last_packed_header_type));
+                                                                             obj_context,
+                                                                             obj_buffer,
+                                                                             va_enc_packed_type_to_idx(encode->last_packed_header_type) + encode->vps_sps_seq_index);
+                    encode->vps_sps_seq_index = (encode->vps_sps_seq_index + 1) % I965_SEQ_PACKED_HEADER_END;
+                } else {
+                    vaStatus = i965_encoder_render_packed_header_data_buffer(ctx,
+                                                                             obj_context,
+                                                                             obj_buffer,
+                                                                             va_enc_packed_type_to_idx(encode->last_packed_header_type));
 
                 }
             }
             encode->last_packed_header_type = 0;
-            break;       
+            break;
         }
 
         case VAEncMiscParameterBufferType:
@@ -3494,7 +3863,7 @@ i965_encoder_render_picture(VADriverContextP ctx,
                                                                  obj_context,
                                                                  obj_buffer);
             break;
-            
+
         case VAEncMacroblockMapBufferType:
             vaStatus = I965_RENDER_ENCODE_BUFFER(encmb_map);
             break;
@@ -3503,7 +3872,7 @@ i965_encoder_render_picture(VADriverContextP ctx,
             vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
             break;
         }
-    }  
+    }
 
     return vaStatus;
 }
@@ -3511,15 +3880,15 @@ i965_encoder_render_picture(VADriverContextP ctx,
 #define I965_RENDER_PROC_BUFFER(name) I965_RENDER_BUFFER(proc, name)
 
 #define DEF_RENDER_PROC_SINGLE_BUFFER_FUNC(name, member) DEF_RENDER_SINGLE_BUFFER_FUNC(proc, name, member)
-DEF_RENDER_PROC_SINGLE_BUFFER_FUNC(pipeline_parameter, pipeline_param)    
+DEF_RENDER_PROC_SINGLE_BUFFER_FUNC(pipeline_parameter, pipeline_param)
 
-static VAStatus 
+static VAStatus
 i965_proc_render_picture(VADriverContextP ctx,
                          VAContextID context,
                          VABufferID *buffers,
                          int num_buffers)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_context *obj_context = CONTEXT(context);
     VAStatus vaStatus = VA_STATUS_SUCCESS;
     int i;
@@ -3546,7 +3915,43 @@ i965_proc_render_picture(VADriverContextP ctx,
     return vaStatus;
 }
 
-VAStatus 
+static VAStatus
+i965_pre_encoder_render_picture(VADriverContextP ctx,
+                                VAContextID context,
+                                VABufferID *buffers,
+                                int num_buffers)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct object_context *obj_context = CONTEXT(context);
+    struct object_config *obj_config;
+    VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
+    int i;
+
+    ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
+    obj_config = obj_context->obj_config;
+    ASSERT_RET(obj_config, VA_STATUS_ERROR_INVALID_CONFIG);
+
+    for (i = 0; i < num_buffers; i++) {
+        struct object_buffer *obj_buffer = BUFFER(buffers[i]);
+
+        if (!obj_buffer)
+            return VA_STATUS_ERROR_INVALID_BUFFER;
+
+        switch (obj_buffer->type) {
+        case VAStatsStatisticsParameterBufferType:
+            vaStatus = I965_RENDER_ENCODE_BUFFER(statistics_parameter_ext);
+            break;
+
+        default:
+            vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
+            break;
+        }
+    }
+
+    return vaStatus;
+}
+
+VAStatus
 i965_RenderPicture(VADriverContextP ctx,
                    VAContextID context,
                    VABufferID *buffers,
@@ -3568,10 +3973,13 @@ i965_RenderPicture(VADriverContextP ctx,
 
     if (VAEntrypointVideoProc == obj_config->entrypoint) {
         vaStatus = i965_proc_render_picture(ctx, context, buffers, num_buffers);
-    } else if ((VAEntrypointEncSlice == obj_config->entrypoint ) || 
+    } else if ((VAEntrypointEncSlice == obj_config->entrypoint) ||
                (VAEntrypointEncPicture == obj_config->entrypoint) ||
-               (VAEntrypointEncSliceLP == obj_config->entrypoint)) {
+               (VAEntrypointEncSliceLP == obj_config->entrypoint) ||
+               (VAEntrypointFEI == obj_config->entrypoint)) {
         vaStatus = i965_encoder_render_picture(ctx, context, buffers, num_buffers);
+    } else if (VAEntrypointStats == obj_config->entrypoint) {
+        vaStatus = i965_pre_encoder_render_picture(ctx, context, buffers, num_buffers);
     } else {
         vaStatus = i965_decoder_render_picture(ctx, context, buffers, num_buffers);
     }
@@ -3579,10 +3987,10 @@ i965_RenderPicture(VADriverContextP ctx,
     return vaStatus;
 }
 
-VAStatus 
+VAStatus
 i965_EndPicture(VADriverContextP ctx, VAContextID context)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_context *obj_context = CONTEXT(context);
     struct object_config *obj_config;
 
@@ -3595,11 +4003,12 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
     } else if (obj_context->codec_type == CODEC_ENC) {
         ASSERT_RET(((VAEntrypointEncSlice == obj_config->entrypoint) ||
                     (VAEntrypointEncPicture == obj_config->entrypoint) ||
-                    (VAEntrypointEncSliceLP == obj_config->entrypoint)),
+                    (VAEntrypointEncSliceLP == obj_config->entrypoint) ||
+                    (VAEntrypointFEI == 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) {
+            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;
         }
@@ -3607,14 +4016,14 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
         if (!obj_context->codec_state.encode.seq_param_ext &&
-                (VAEntrypointEncPicture != obj_config->entrypoint)) {
+            (VAEntrypointEncPicture != obj_config->entrypoint)) {
             /* The seq_param is not mandatory for VP9 encoding */
             if (obj_config->profile != VAProfileVP9Profile0)
                 return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
-        if ((obj_context->codec_state.encode.num_slice_params_ext <=0) &&
-                ((obj_config->profile != VAProfileVP8Version0_3) &&
-                 (obj_config->profile != VAProfileVP9Profile0))) {
+        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;
         }
 
@@ -3625,19 +4034,26 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
                       " under packed SLICE_HEADER mode\n");
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
+    } else if (obj_context->codec_type == CODEC_PREENC) {
+        ASSERT_RET((VAEntrypointStats == obj_config->entrypoint),
+                   VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT);
+
+        if (!obj_context->codec_state.encode.stat_param_ext) {
+            return VA_STATUS_ERROR_INVALID_PARAMETER;
+        }
     } else {
         if (obj_context->codec_state.decode.pic_param == NULL) {
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
-        if (obj_context->codec_state.decode.num_slice_params <=0) {
+        if (obj_context->codec_state.decode.num_slice_params <= 0) {
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
-        if (obj_context->codec_state.decode.num_slice_datas <=0) {
+        if (obj_context->codec_state.decode.num_slice_datas <= 0) {
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
 
         if (obj_context->codec_state.decode.num_slice_params !=
-                obj_context->codec_state.decode.num_slice_datas) {
+            obj_context->codec_state.decode.num_slice_datas) {
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
 
@@ -3658,36 +4074,35 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
     return obj_context->hw_context->run(ctx, obj_config->profile, &obj_context->codec_state, obj_context->hw_context);
 }
 
-VAStatus 
+VAStatus
 i965_SyncSurface(VADriverContextP ctx,
                  VASurfaceID render_target)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_surface *obj_surface = SURFACE(render_target);
 
     ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
 
-    if(obj_surface->bo)
+    if (obj_surface->bo)
         drm_intel_bo_wait_rendering(obj_surface->bo);
 
     return VA_STATUS_SUCCESS;
 }
 
-VAStatus 
+VAStatus
 i965_QuerySurfaceStatus(VADriverContextP ctx,
                         VASurfaceID render_target,
                         VASurfaceStatus *status)        /* out */
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_surface *obj_surface = SURFACE(render_target);
 
     ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
 
     if (obj_surface->bo) {
-        if (drm_intel_bo_busy(obj_surface->bo)){
+        if (drm_intel_bo_busy(obj_surface->bo)) {
             *status = VASurfaceRendering;
-        }
-        else {
+        } else {
             *status = VASurfaceReady;
         }
     } else {
@@ -3732,7 +4147,7 @@ i965_display_attributes_init(VADriverContextP ctx)
 
     i965->num_display_attributes = ARRAY_ELEMS(i965_display_attributes);
     i965->display_attributes = malloc(
-        i965->num_display_attributes * sizeof(i965->display_attributes[0]));
+                                   i965->num_display_attributes * sizeof(i965->display_attributes[0]));
     if (!i965->display_attributes)
         goto error;
 
@@ -3762,13 +4177,13 @@ error:
     return false;
 }
 
-/* 
- * Query display attributes 
+/*
+ * Query display attributes
  * The caller must provide a "attr_list" array that can hold at
  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
  * returned in "attr_list" is returned in "num_attributes".
  */
-VAStatus 
+VAStatus
 i965_QueryDisplayAttributes(
     VADriverContextP    ctx,
     VADisplayAttribute *attribs,        /* out */
@@ -3786,13 +4201,13 @@ i965_QueryDisplayAttributes(
     return VA_STATUS_SUCCESS;
 }
 
-/* 
- * Get display attributes 
+/*
+ * Get display attributes
  * This function returns the current attribute values in "attr_list".
  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
- * from vaQueryDisplayAttributes() can have their values retrieved.  
+ * from vaQueryDisplayAttributes() can have their values retrieved.
  */
-VAStatus 
+VAStatus
 i965_GetDisplayAttributes(
     VADriverContextP    ctx,
     VADisplayAttribute *attribs,        /* inout */
@@ -3812,22 +4227,21 @@ i965_GetDisplayAttributes(
             dst_attrib->value     = src_attrib->value;
             dst_attrib->flags     = src_attrib->flags;
         } else if (src_attrib &&
-                (src_attrib->flags & VA_DISPLAY_ATTRIB_SETTABLE)) {
+                   (src_attrib->flags & VA_DISPLAY_ATTRIB_SETTABLE)) {
             dst_attrib->flags     = src_attrib->flags;
-        }
-        else
+        } else
             dst_attrib->flags = VA_DISPLAY_ATTRIB_NOT_SUPPORTED;
     }
     return VA_STATUS_SUCCESS;
 }
 
-/* 
- * Set display attributes 
+/*
+ * Set display attributes
  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
- * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or 
+ * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or
  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
  */
-VAStatus 
+VAStatus
 i965_SetDisplayAttributes(
     VADriverContextP    ctx,
     VADisplayAttribute *attribs,        /* in */
@@ -3856,7 +4270,7 @@ i965_SetDisplayAttributes(
     return VA_STATUS_SUCCESS;
 }
 
-VAStatus 
+VAStatus
 i965_DbgCopySurfaceToBuffer(VADriverContextP ctx,
                             VASurfaceID surface,
                             void **buffer,              /* out */
@@ -3867,11 +4281,11 @@ i965_DbgCopySurfaceToBuffer(VADriverContextP ctx,
 }
 
 static void
-i965_destroy_heap(struct object_heap *heap, 
+i965_destroy_heap(struct object_heap *heap,
                   void (*func)(struct object_heap *heap, struct object_base *object))
 {
     struct object_base *object;
-    object_heap_iterator iter;    
+    object_heap_iterator iter;
 
     object = object_heap_first(heap, &iter);
 
@@ -3886,10 +4300,10 @@ i965_destroy_heap(struct object_heap *heap,
 }
 
 
-VAStatus 
+VAStatus
 i965_DestroyImage(VADriverContextP ctx, VAImageID image);
 
-VAStatus 
+VAStatus
 i965_CreateImage(VADriverContextP ctx,
                  VAImageFormat *format,
                  int width,
@@ -3924,9 +4338,9 @@ i965_CreateImage(VADriverContextP ctx,
 
     if ((format->fourcc == VA_FOURCC_YV12) ||
         (format->fourcc == VA_FOURCC_I420)) {
-            if (awidth % 128 != 0) {
-                awidth = ALIGN(width, 128);    
-            }
+        if (awidth % 128 != 0) {
+            awidth = ALIGN(width, 128);
+        }
     }
 
     aheight = ALIGN(height, i965->codec_info->min_linear_hpitch);
@@ -4059,7 +4473,7 @@ i965_CreateImage(VADriverContextP ctx,
     *out_image                  = *image;
     return VA_STATUS_SUCCESS;
 
- error:
+error:
     i965_DestroyImage(ctx, image_id);
     return va_status;
 }
@@ -4088,19 +4502,19 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
 
     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);
+                   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 * bpp_1stplane, 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;
 
@@ -4115,7 +4529,7 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             obj_surface->y_cr_offset = obj_surface->height;
             region_width = obj_surface->width;
             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32);
-            
+
             break;
 
         case VA_FOURCC_IMC1:
@@ -4139,7 +4553,7 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
             region_width = obj_surface->width;
             region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
-            
+
             break;
 
         case VA_FOURCC_422H:
@@ -4207,13 +4621,13 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             assert(subsampling == SUBSAMPLE_YUV422H);
             obj_surface->width = ALIGN(obj_surface->orig_width * 2, 128);
             obj_surface->cb_cr_pitch = obj_surface->width;
-            obj_surface->y_cb_offset = 0; 
-            obj_surface->y_cr_offset = 0; 
+            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;
             region_width = obj_surface->width;
             region_height = obj_surface->height;
-            
+
             break;
 
         case VA_FOURCC_RGBA:
@@ -4233,8 +4647,8 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
             break;
         }
     } else {
-        assert(subsampling == SUBSAMPLE_YUV420 || 
-               subsampling == SUBSAMPLE_YUV422H || 
+        assert(subsampling == SUBSAMPLE_YUV420 ||
+               subsampling == SUBSAMPLE_YUV422H ||
                subsampling == SUBSAMPLE_YUV422V ||
                subsampling == SUBSAMPLE_RGBX);
 
@@ -4329,7 +4743,7 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
         uint32_t tiling_mode = I915_TILING_Y; /* always uses Y-tiled format */
         unsigned long pitch;
 
-        obj_surface->bo = drm_intel_bo_alloc_tiled(i965->intel.bufmgr, 
+        obj_surface->bo = drm_intel_bo_alloc_tiled(i965->intel.bufmgr,
                                                    "vaapi surface",
                                                    region_width,
                                                    region_height,
@@ -4358,7 +4772,7 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_image *obj_image;
-    struct object_surface *obj_surface; 
+    struct object_surface *obj_surface;
     VAImageID image_id;
     unsigned int w_pitch;
     VAStatus va_status = VA_STATUS_ERROR_OPERATION_FAILED;
@@ -4389,7 +4803,7 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
     obj_image = IMAGE(image_id);
-    
+
     if (!obj_image)
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
@@ -4398,7 +4812,7 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
     obj_image->derived_surface = VA_INVALID_ID;
 
     VAImage * const image = &obj_image->image;
-    
+
     memset(image, 0, sizeof(*image));
     image->image_id = image_id;
     image->buf = VA_INVALID_ID;
@@ -4542,24 +4956,24 @@ VAStatus i965_DeriveImage(VADriverContextP ctx,
 
     return VA_STATUS_SUCCESS;
 
- error:
+error:
     i965_DestroyImage(ctx, image_id);
     return va_status;
 }
 
-static void 
+static void
 i965_destroy_image(struct object_heap *heap, struct object_base *obj)
 {
     object_heap_free(heap, obj);
 }
 
 
-VAStatus 
+VAStatus
 i965_DestroyImage(VADriverContextP ctx, VAImageID image)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
-    struct object_image *obj_image = IMAGE(image); 
-    struct object_surface *obj_surface; 
+    struct object_image *obj_image = IMAGE(image);
+    struct object_surface *obj_surface;
 
     if (!obj_image)
         return VA_STATUS_SUCCESS;
@@ -4594,7 +5008,7 @@ i965_DestroyImage(VADriverContextP ctx, VAImageID image)
  * num_palette_entries * entry_bytes in size.  The order of the components
  * in the palette is described by the component_order in VASubpicture struct
  */
-VAStatus 
+VAStatus
 i965_SetImagePalette(VADriverContextP ctx,
                      VAImageID image,
                      unsigned char *palette)
@@ -4610,13 +5024,13 @@ i965_SetImagePalette(VADriverContextP ctx,
         return VA_STATUS_ERROR_ALLOCATION_FAILED; /* XXX: unpaletted/error */
 
     for (i = 0; i < obj_image->image.num_palette_entries; i++)
-        obj_image->palette[i] = (((unsigned int)palette[3*i + 0] << 16) |
-                                 ((unsigned int)palette[3*i + 1] <<  8) |
-                                 (unsigned int)palette[3*i + 2]);
+        obj_image->palette[i] = (((unsigned int)palette[3 * i + 0] << 16) |
+                                 ((unsigned int)palette[3 * i + 1] <<  8) |
+                                 (unsigned int)palette[3 * i + 2]);
     return VA_STATUS_SUCCESS;
 }
 
-static int 
+static int
 get_sampling_from_fourcc(unsigned int fourcc)
 {
     const i965_fourcc_info *info = get_fourcc_info(fourcc);
@@ -4784,11 +5198,11 @@ get_image_yuy2(struct object_image *obj_image, uint8_t *image_data,
     src = (uint8_t *)obj_surface->bo->virtual;
 
     /* Y plane */
-    dst += rect->y * obj_image->image.pitches[0] + rect->x*2;
-    src += rect->y * obj_surface->width + rect->x*2;
+    dst += rect->y * obj_image->image.pitches[0] + rect->x * 2;
+    src += rect->y * obj_surface->width + rect->x * 2;
     memcpy_pic(dst, obj_image->image.pitches[0],
-               src, obj_surface->width*2,
-               rect->width*2, rect->height);
+               src, obj_surface->width * 2,
+               rect->width * 2, rect->height);
 
     if (tiling != I915_TILING_NONE)
         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
@@ -4798,10 +5212,10 @@ get_image_yuy2(struct object_image *obj_image, uint8_t *image_data,
     return va_status;
 }
 
-static VAStatus 
+static VAStatus
 i965_sw_getimage(VADriverContextP ctx,
-    struct object_surface *obj_surface, struct object_image *obj_image,
-    const VARectangle *rect)
+                 struct object_surface *obj_surface, struct object_image *obj_image,
+                 const VARectangle *rect)
 {
     void *image_data = NULL;
     VAStatus va_status;
@@ -4836,10 +5250,10 @@ i965_sw_getimage(VADriverContextP ctx,
     return va_status;
 }
 
-static VAStatus 
+static VAStatus
 i965_hw_getimage(VADriverContextP ctx,
-    struct object_surface *obj_surface, struct object_image *obj_image,
-    const VARectangle *rect)
+                 struct object_surface *obj_surface, struct object_image *obj_image,
+                 const VARectangle *rect)
 {
     struct i965_surface src_surface;
     struct i965_surface dst_surface;
@@ -4855,7 +5269,7 @@ i965_hw_getimage(VADriverContextP ctx,
     return i965_image_processing(ctx, &src_surface, rect, &dst_surface, rect);
 }
 
-VAStatus 
+VAStatus
 i965_GetImage(VADriverContextP ctx,
               VASurfaceID surface,
               int x,   /* coordinates of the upper left source pixel */
@@ -5053,11 +5467,11 @@ put_image_yuy2(struct object_surface *obj_surface,
     src = image_data + obj_image->image.offsets[0];
 
     /* YUYV packed plane */
-    dst += dst_rect->y * obj_surface->width + dst_rect->x*2;
-    src += src_rect->y * obj_image->image.pitches[0] + src_rect->x*2;
-    memcpy_pic(dst, obj_surface->width*2,
+    dst += dst_rect->y * obj_surface->width + dst_rect->x * 2;
+    src += src_rect->y * obj_image->image.pitches[0] + src_rect->x * 2;
+    memcpy_pic(dst, obj_surface->width * 2,
                src, obj_image->image.pitches[0],
-               src_rect->width*2, src_rect->height);
+               src_rect->width * 2, src_rect->height);
 
     if (tiling != I915_TILING_NONE)
         drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
@@ -5069,8 +5483,8 @@ put_image_yuy2(struct object_surface *obj_surface,
 
 static VAStatus
 i965_sw_putimage(VADriverContextP ctx,
-    struct object_surface *obj_surface, struct object_image *obj_image,
-    const VARectangle *src_rect, const VARectangle *dst_rect)
+                 struct object_surface *obj_surface, struct object_image *obj_image,
+                 const VARectangle *src_rect, const VARectangle *dst_rect)
 {
     VAStatus va_status = VA_STATUS_SUCCESS;
     void *image_data = NULL;
@@ -5089,11 +5503,11 @@ i965_sw_putimage(VADriverContextP ctx,
     else {
         /* VA is surface not used for decoding, use same VA image format */
         va_status = i965_check_alloc_surface_bo(
-            ctx,
-            obj_surface,
-            0, /* XXX: don't use tiled surface */
-            obj_image->image.format.fourcc,
-            get_sampling_from_fourcc (obj_image->image.format.fourcc));
+                        ctx,
+                        obj_surface,
+                        0, /* XXX: don't use tiled surface */
+                        obj_image->image.format.fourcc,
+                        get_sampling_from_fourcc(obj_image->image.format.fourcc));
     }
 
     if (va_status != VA_STATUS_SUCCESS)
@@ -5102,7 +5516,7 @@ i965_sw_putimage(VADriverContextP ctx,
     va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
     if (va_status != VA_STATUS_SUCCESS)
         return va_status;
-     
+
     switch (obj_image->image.format.fourcc) {
     case VA_FOURCC_YV12:
     case VA_FOURCC_I420:
@@ -5125,17 +5539,17 @@ i965_sw_putimage(VADriverContextP ctx,
     return va_status;
 }
 
-static VAStatus 
+static VAStatus
 i965_hw_putimage(VADriverContextP ctx,
-    struct object_surface *obj_surface, struct object_image *obj_image,
-    const VARectangle *src_rect, const VARectangle *dst_rect)
+                 struct object_surface *obj_surface, struct object_image *obj_image,
+                 const VARectangle *src_rect, const VARectangle *dst_rect)
 {
     struct i965_surface src_surface, dst_surface;
     VAStatus va_status = VA_STATUS_SUCCESS;
 
     if (!obj_surface->bo) {
         unsigned int tiling, swizzle;
-        int surface_sampling = get_sampling_from_fourcc (obj_image->image.format.fourcc);;
+        int surface_sampling = get_sampling_from_fourcc(obj_image->image.format.fourcc);;
         dri_bo_get_tiling(obj_image->bo, &tiling, &swizzle);
 
         i965_check_alloc_surface_bo(ctx,
@@ -5164,7 +5578,7 @@ i965_hw_putimage(VADriverContextP ctx,
     return  va_status;
 }
 
-static VAStatus 
+static VAStatus
 i965_PutImage(VADriverContextP ctx,
               VASurfaceID surface,
               VAImageID image,
@@ -5217,15 +5631,15 @@ i965_PutImage(VADriverContextP ctx,
 
     if (HAS_ACCELERATED_PUTIMAGE(i965))
         va_status = i965_hw_putimage(ctx, obj_surface, obj_image,
-            &src_rect, &dst_rect);
-    else 
+                                     &src_rect, &dst_rect);
+    else
         va_status = i965_sw_putimage(ctx, obj_surface, obj_image,
-            &src_rect, &dst_rect);
+                                     &src_rect, &dst_rect);
 
     return va_status;
 }
 
-VAStatus 
+VAStatus
 i965_PutSurface(VADriverContextP ctx,
                 VASurfaceID surface,
                 void *draw, /* X Drawable */
@@ -5333,9 +5747,9 @@ i965_LockSurface(
     }
 
     vaStatus = i965_DeriveImage(
-        ctx,
-        surface,
-        &tmpImage);
+                   ctx,
+                   surface,
+                   &tmpImage);
     if (vaStatus != VA_STATUS_SUCCESS) {
         goto error;
     }
@@ -5343,9 +5757,9 @@ i965_LockSurface(
     obj_surface->locked_image_id = tmpImage.image_id;
 
     vaStatus = i965_MapBuffer(
-        ctx,
-        tmpImage.buf,
-        buffer);
+                   ctx,
+                   tmpImage.buf,
+                   buffer);
     if (vaStatus != VA_STATUS_SUCCESS) {
         goto error;
     }
@@ -5397,22 +5811,22 @@ i965_UnlockSurface(
     }
 
     vaStatus = i965_UnmapBuffer(
-        ctx,
-        locked_img->image.buf);
+                   ctx,
+                   locked_img->image.buf);
     if (vaStatus != VA_STATUS_SUCCESS) {
         goto error;
     }
 
     vaStatus = i965_DestroyImage(
-        ctx,
-        locked_img->image.image_id);
+                   ctx,
+                   locked_img->image.image_id);
     if (vaStatus != VA_STATUS_SUCCESS) {
         goto error;
     }
 
     locked_img->image.image_id = VA_INVALID_ID;
 
- error:
+error:
     obj_surface->locked_image_id = VA_INVALID_ID;
 
     return vaStatus;
@@ -5424,7 +5838,7 @@ i965_GetSurfaceAttributes(
     VAConfigID config,
     VASurfaceAttrib *attrib_list,
     unsigned int num_attribs
-    )
+)
 {
     VAStatus vaStatus = VA_STATUS_SUCCESS;
     struct i965_driver_data *i965 = i965_driver_data(ctx);
@@ -5438,7 +5852,7 @@ i965_GetSurfaceAttributes(
 
     if (obj_config == NULL)
         return VA_STATUS_ERROR_INVALID_CONFIG;
-    
+
     if (attrib_list == NULL || num_attribs == 0)
         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
@@ -5475,7 +5889,8 @@ i965_GetSurfaceAttributes(
                     attrib_list[i].value.value.i = VA_FOURCC_NV12;
                 } else if (IS_GEN7(i965->intel.device_info) ||
                            IS_GEN8(i965->intel.device_info) ||
-                           IS_GEN9(i965->intel.device_info)) {
+                           IS_GEN9(i965->intel.device_info) ||
+                           IS_GEN10(i965->intel.device_info)) {
                     if (obj_config->profile == VAProfileJPEGBaseline)
                         attrib_list[i].value.value.i = 0; /* internal format */
                     else
@@ -5497,7 +5912,7 @@ i965_GetSurfaceAttributes(
                     if (obj_config->profile == VAProfileMPEG2Simple ||
                         obj_config->profile == VAProfileMPEG2Main) {
                         if (attrib_list[i].value.value.i != VA_FOURCC_I420) {
-                            attrib_list[i].value.value.i = 0;                            
+                            attrib_list[i].value.value.i = 0;
                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
                         }
                     } else if (obj_config->profile == VAProfileH264ConstrainedBaseline ||
@@ -5519,7 +5934,7 @@ i965_GetSurfaceAttributes(
                         case VA_FOURCC_RGBA:
                             break;
                         default:
-                            attrib_list[i].value.value.i = 0;                            
+                            attrib_list[i].value.value.i = 0;
                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
                             break;
                         }
@@ -5541,7 +5956,7 @@ i965_GetSurfaceAttributes(
                         case VA_FOURCC_RGBA:
                             break;
                         default:
-                            attrib_list[i].value.value.i = 0;                            
+                            attrib_list[i].value.value.i = 0;
                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
                             break;
                         }
@@ -5553,20 +5968,27 @@ i965_GetSurfaceAttributes(
                     }
                 } else if (IS_GEN7(i965->intel.device_info) ||
                            IS_GEN8(i965->intel.device_info) ||
-                           IS_GEN9(i965->intel.device_info)) {
+                           IS_GEN9(i965->intel.device_info) ||
+                           IS_GEN10(i965->intel.device_info)) {
                     if (obj_config->entrypoint == VAEntrypointEncSlice ||
                         obj_config->entrypoint == VAEntrypointVideoProc ||
-                        obj_config->entrypoint == VAEntrypointEncSliceLP) {
+                        obj_config->entrypoint == VAEntrypointEncSliceLP ||
+                        obj_config->entrypoint == VAEntrypointFEI) {
                         switch (attrib_list[i].value.value.i) {
                         case VA_FOURCC_NV12:
                         case VA_FOURCC_I420:
                         case VA_FOURCC_YV12:
                             break;
                         default:
-                            attrib_list[i].value.value.i = 0;                            
+                            attrib_list[i].value.value.i = 0;
                             attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
                             break;
                         }
+                    } else if (obj_config->entrypoint == VAEntrypointStats) {
+                        if (attrib_list[i].value.value.i != VA_FOURCC_NV12) {
+                            attrib_list[i].value.value.i = 0;
+                            attrib_list[i].flags &= ~VA_SURFACE_ATTRIB_SETTABLE;
+                        }
                     } else {
                         if (obj_config->profile == VAProfileJPEGBaseline) {
                             attrib_list[i].value.value.i = 0;   /* JPEG decoding always uses an internal format */
@@ -5625,7 +6047,7 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
 
     if (obj_config == NULL)
         return VA_STATUS_ERROR_INVALID_CONFIG;
-    
+
     if (!attrib_list && !num_attribs)
         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
@@ -5634,8 +6056,8 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
         return VA_STATUS_SUCCESS;
     }
 
-    attribs = malloc(I965_MAX_SURFACE_ATTRIBUTES *sizeof(*attribs));
-    
+    attribs = malloc(I965_MAX_SURFACE_ATTRIBUTES * sizeof(*attribs));
+
     if (attribs == NULL)
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
@@ -5657,7 +6079,7 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
             attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
             attribs[i].value.value.i = VA_FOURCC_I420;
             i++;
-            
+
             break;
 
         case VAProfileH264ConstrainedBaseline:
@@ -5669,6 +6091,8 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
             attribs[i].value.value.i = VA_FOURCC_NV12;
             i++;
 
+            break;
+
         case VAProfileNone:
             attribs[i].type = VASurfaceAttribPixelFormat;
             attribs[i].value.type = VAGenericValueTypeInteger;
@@ -5683,7 +6107,7 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
             i++;
 
             break;
-            
+
         default:
             break;
         }
@@ -5695,7 +6119,7 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
             attribs[i].value.value.i = VA_FOURCC_NV12;
             i++;
         } else if (obj_config->entrypoint == VAEntrypointEncSlice ||  /* encode */
-                   obj_config->entrypoint == VAEntrypointVideoProc) { /* vpp */ 
+                   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;
@@ -5784,7 +6208,7 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
                 attribs[i].value.value.i = VA_FOURCC_P010;
                 i++;
-             } else {
+            } else {
                 attribs[i].type = VASurfaceAttribPixelFormat;
                 attribs[i].value.type = VAGenericValueTypeInteger;
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
@@ -5792,7 +6216,7 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 i++;
             }
         } else if (obj_config->entrypoint == VAEntrypointEncSlice ||  /* encode */
-                   obj_config->entrypoint == VAEntrypointVideoProc) { /* vpp */ 
+                   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;
@@ -5827,6 +6251,12 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 attribs[i].type = VASurfaceAttribPixelFormat;
                 attribs[i].value.type = VAGenericValueTypeInteger;
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+                attribs[i].value.value.i = VA_FOURCC_UYVY;
+                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_RGBA;
                 i++;
 
@@ -5856,7 +6286,8 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
             }
         }
     } else if (IS_GEN8(i965->intel.device_info) ||
-               IS_GEN9(i965->intel.device_info)) {
+               IS_GEN9(i965->intel.device_info) ||
+               IS_GEN10(i965->intel.device_info)) {
         if (obj_config->entrypoint == VAEntrypointVLD) { /* decode */
             if (obj_config->profile == VAProfileJPEGBaseline) {
                 attribs[i].type = VASurfaceAttribPixelFormat;
@@ -5919,7 +6350,8 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
         } else if (obj_config->entrypoint == VAEntrypointEncSlice ||  /* encode */
                    obj_config->entrypoint == VAEntrypointVideoProc ||
                    obj_config->entrypoint == VAEntrypointEncSliceLP ||
-                   obj_config->entrypoint == VAEntrypointEncPicture) {
+                   obj_config->entrypoint == VAEntrypointEncPicture ||
+                   obj_config->entrypoint == VAEntrypointFEI) {
 
             if (obj_config->profile == VAProfileHEVCMain10) {
                 attribs[i].type = VASurfaceAttribPixelFormat;
@@ -5928,29 +6360,29 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 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++;
+                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) {
@@ -5963,6 +6395,12 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 attribs[i].type = VASurfaceAttribPixelFormat;
                 attribs[i].value.type = VAGenericValueTypeInteger;
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
+                attribs[i].value.value.i = VA_FOURCC_UYVY;
+                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_RGBA;
                 i++;
 
@@ -5990,24 +6428,24 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 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++;
+                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++;
                 }
             }
 
             /* Additional support for jpeg encoder */
             if (obj_config->profile == VAProfileJPEGBaseline
-                    && obj_config->entrypoint == VAEntrypointEncPicture) {
+                && obj_config->entrypoint == VAEntrypointEncPicture) {
                 attribs[i].type = VASurfaceAttribPixelFormat;
                 attribs[i].value.type = VAGenericValueTypeInteger;
                 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
@@ -6032,6 +6470,12 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
                 attribs[i].value.value.i = VA_FOURCC_Y800;
                 i++;
             }
+        } else if (obj_config->entrypoint == VAEntrypointStats) {
+            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++;
         }
     }
 
@@ -6039,8 +6483,8 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
     attribs[i].value.type = VAGenericValueTypeInteger;
     attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
     attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA |
-        VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM |
-        VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
+                               VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM |
+                               VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
     i++;
 
     attribs[i].type = VASurfaceAttribExternalBufferDescriptor;
@@ -6063,6 +6507,27 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
     attribs[i].value.value.i = max_height;
     i++;
 
+    if (obj_config->entrypoint == VAEntrypointEncSlice ||
+        obj_config->entrypoint == VAEntrypointEncSliceLP ||
+        obj_config->entrypoint == VAEntrypointEncPicture ||
+        obj_config->entrypoint == VAEntrypointFEI) {
+        attribs[i].type = VASurfaceAttribMinWidth;
+        attribs[i].value.type = VAGenericValueTypeInteger;
+        attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
+        attribs[i].value.value.i = I965_MIN_CODEC_ENC_RESOLUTION_WIDTH_HEIGHT;
+        if (obj_config->profile == VAProfileJPEGBaseline)
+            attribs[i].value.value.i = 1;
+        i++;
+
+        attribs[i].type = VASurfaceAttribMinHeight;
+        attribs[i].value.type = VAGenericValueTypeInteger;
+        attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE;
+        attribs[i].value.value.i = I965_MIN_CODEC_ENC_RESOLUTION_WIDTH_HEIGHT;
+        if (obj_config->profile == VAProfileJPEGBaseline)
+            attribs[i].value.value.i = 1;
+        i++;
+    }
+
     if (i > *num_attribs) {
         *num_attribs = i;
         free(attribs);
@@ -6079,7 +6544,7 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
 /* Acquires buffer handle for external API usage (internal implementation) */
 static VAStatus
 i965_acquire_buffer_handle(struct object_buffer *obj_buffer,
-    uint32_t mem_type, VABufferInfo *out_buf_info)
+                           uint32_t mem_type, VABufferInfo *out_buf_info)
 {
     struct buffer_store *buffer_store;
 
@@ -6093,8 +6558,7 @@ i965_acquire_buffer_handle(struct object_buffer *obj_buffer,
     if (obj_buffer->export_refcount > 0) {
         if (obj_buffer->export_state.mem_type != mem_type)
             return VA_STATUS_ERROR_INVALID_PARAMETER;
-    }
-    else {
+    } else {
         VABufferInfo * const buf_info = &obj_buffer->export_state;
 
         switch (mem_type) {
@@ -6149,7 +6613,7 @@ i965_release_buffer_handle(struct object_buffer *obj_buffer)
 /** Acquires buffer handle for external API usage */
 static VAStatus
 i965_AcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
-    VABufferInfo *buf_info)
+                         VABufferInfo *buf_info)
 {
     struct i965_driver_data * const i965 = i965_driver_data(ctx);
     struct object_buffer * const obj_buffer = BUFFER(buf_id);
@@ -6214,6 +6678,237 @@ i965_ReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
     return i965_release_buffer_handle(obj_buffer);
 }
 
+// Locally define DRM_FORMAT values not available in older but still
+// supported versions of libdrm.
+#ifndef DRM_FORMAT_R8
+#define DRM_FORMAT_R8        fourcc_code('R', '8', ' ', ' ')
+#endif
+#ifndef DRM_FORMAT_R16
+#define DRM_FORMAT_R16       fourcc_code('R', '1', '6', ' ')
+#endif
+#ifndef DRM_FORMAT_GR88
+#define DRM_FORMAT_GR88      fourcc_code('G', 'R', '8', '8')
+#endif
+#ifndef DRM_FORMAT_GR1616
+#define DRM_FORMAT_GR1616    fourcc_code('G', 'R', '3', '2')
+#endif
+
+static uint32_t drm_format_of_separate_plane(uint32_t fourcc, int plane)
+{
+    if (plane == 0) {
+        switch (fourcc) {
+        case VA_FOURCC_NV12:
+        case VA_FOURCC_I420:
+        case VA_FOURCC_YV12:
+        case VA_FOURCC_YV16:
+        case VA_FOURCC_Y800:
+            return DRM_FORMAT_R8;
+        case VA_FOURCC_P010:
+        case VA_FOURCC_I010:
+            return DRM_FORMAT_R16;
+
+        case VA_FOURCC_YUY2:
+        case VA_FOURCC_UYVY:
+            // These are not representable as separate planes.
+            return 0;
+
+        case VA_FOURCC_RGBA:
+            return DRM_FORMAT_ABGR8888;
+        case VA_FOURCC_RGBX:
+            return DRM_FORMAT_XBGR8888;
+        case VA_FOURCC_BGRA:
+            return DRM_FORMAT_ARGB8888;
+        case VA_FOURCC_BGRX:
+            return DRM_FORMAT_XRGB8888;
+        case VA_FOURCC_ARGB:
+            return DRM_FORMAT_BGRA8888;
+        case VA_FOURCC_ABGR:
+            return DRM_FORMAT_RGBA8888;
+        }
+    } else {
+        switch (fourcc) {
+        case VA_FOURCC_NV12:
+            return DRM_FORMAT_GR88;
+        case VA_FOURCC_I420:
+        case VA_FOURCC_YV12:
+        case VA_FOURCC_YV16:
+            return DRM_FORMAT_R8;
+        case VA_FOURCC_P010:
+            return DRM_FORMAT_GR1616;
+        case VA_FOURCC_I010:
+            return DRM_FORMAT_R16;
+        }
+    }
+    return 0;
+}
+
+static uint32_t drm_format_of_composite_object(uint32_t fourcc)
+{
+    switch (fourcc) {
+    case VA_FOURCC_NV12:
+        return DRM_FORMAT_NV12;
+    case VA_FOURCC_I420:
+        return DRM_FORMAT_YUV420;
+    case VA_FOURCC_YV12:
+        return DRM_FORMAT_YVU420;
+    case VA_FOURCC_YV16:
+        return DRM_FORMAT_YVU422;
+    case VA_FOURCC_YUY2:
+        return DRM_FORMAT_YUYV;
+    case VA_FOURCC_UYVY:
+        return DRM_FORMAT_UYVY;
+    case VA_FOURCC_Y800:
+        return DRM_FORMAT_R8;
+
+    case VA_FOURCC_P010:
+    case VA_FOURCC_I010:
+        // These currently have no composite DRM format - they are usable
+        // only as separate planes.
+        return 0;
+
+    case VA_FOURCC_RGBA:
+        return DRM_FORMAT_ABGR8888;
+    case VA_FOURCC_RGBX:
+        return DRM_FORMAT_XBGR8888;
+    case VA_FOURCC_BGRA:
+        return DRM_FORMAT_ARGB8888;
+    case VA_FOURCC_BGRX:
+        return DRM_FORMAT_XRGB8888;
+    case VA_FOURCC_ARGB:
+        return DRM_FORMAT_BGRA8888;
+    case VA_FOURCC_ABGR:
+        return DRM_FORMAT_RGBA8888;
+    }
+    return 0;
+}
+
+static VAStatus
+i965_ExportSurfaceHandle(VADriverContextP ctx, VASurfaceID surface_id,
+                         uint32_t mem_type, uint32_t flags,
+                         void *descriptor)
+{
+    struct i965_driver_data *const i965 = i965_driver_data(ctx);
+    struct object_surface *obj_surface = SURFACE(surface_id);
+    const i965_fourcc_info *info;
+    VADRMPRIMESurfaceDescriptor *desc;
+    unsigned int tiling, swizzle;
+    uint32_t formats[4], pitch, height, offset;
+    int fd, p;
+    int composite_object =
+        flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS;
+
+    if (!obj_surface || !obj_surface->bo)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) {
+        i965_log_info(ctx, "vaExportSurfaceHandle: memory type %08x "
+                      "is not supported.\n", mem_type);
+        return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
+    }
+
+    info = get_fourcc_info(obj_surface->fourcc);
+    if (!info)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+    if (composite_object) {
+        formats[0] =
+            drm_format_of_composite_object(obj_surface->fourcc);
+        if (!formats[0]) {
+            i965_log_info(ctx, "vaExportSurfaceHandle: fourcc %08x "
+                          "is not supported for export as a composite "
+                          "object.\n", obj_surface->fourcc);
+            return VA_STATUS_ERROR_INVALID_SURFACE;
+        }
+    } else {
+        for (p = 0; p < info->num_planes; p++) {
+            formats[p] =
+                drm_format_of_separate_plane(obj_surface->fourcc, p);
+            if (!formats[p]) {
+                i965_log_info(ctx, "vaExportSurfaceHandle: fourcc %08x "
+                              "is not supported for export as separate "
+                              "planes.\n", obj_surface->fourcc);
+                return VA_STATUS_ERROR_INVALID_SURFACE;
+            }
+        }
+    }
+
+    if (drm_intel_bo_gem_export_to_prime(obj_surface->bo, &fd))
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    if (drm_intel_bo_get_tiling(obj_surface->bo, &tiling, &swizzle))
+        tiling = I915_TILING_NONE;
+
+    desc = descriptor;
+
+    desc->fourcc = obj_surface->fourcc;
+    desc->width  = obj_surface->orig_width;
+    desc->height = obj_surface->orig_height;
+
+    desc->num_objects     = 1;
+    desc->objects[0].fd   = fd;
+    desc->objects[0].size = obj_surface->size;
+    switch (tiling) {
+    case I915_TILING_X:
+        desc->objects[0].drm_format_modifier = I915_FORMAT_MOD_X_TILED;
+        break;
+    case I915_TILING_Y:
+        desc->objects[0].drm_format_modifier = I915_FORMAT_MOD_Y_TILED;
+        break;
+    case I915_TILING_NONE:
+    default:
+        desc->objects[0].drm_format_modifier = DRM_FORMAT_MOD_NONE;
+    }
+
+    if (composite_object) {
+        desc->num_layers = 1;
+
+        desc->layers[0].drm_format = formats[0];
+        desc->layers[0].num_planes = info->num_planes;
+
+        offset = 0;
+        for (p = 0; p < info->num_planes; p++) {
+            desc->layers[0].object_index[p] = 0;
+
+            if (p == 0) {
+                pitch  = obj_surface->width;
+                height = obj_surface->height;
+            } else {
+                pitch  = obj_surface->cb_cr_pitch;
+                height = obj_surface->cb_cr_height;
+            }
+
+            desc->layers[0].offset[p] = offset;
+            desc->layers[0].pitch[p]  = pitch;
+
+            offset += pitch * height;
+        }
+    } else {
+        desc->num_layers = info->num_planes;
+
+        offset = 0;
+        for (p = 0; p < info->num_planes; p++) {
+            desc->layers[p].drm_format = formats[p];
+            desc->layers[p].num_planes = 1;
+
+            desc->layers[p].object_index[0] = 0;
+
+            if (p == 0) {
+                pitch  = obj_surface->width;
+                height = obj_surface->height;
+            } else {
+                pitch  = obj_surface->cb_cr_pitch;
+                height = obj_surface->cb_cr_height;
+            }
+
+            desc->layers[p].offset[0] = offset;
+            desc->layers[p].pitch[0]  = pitch;
+
+            offset += pitch * height;
+        }
+    }
+
+    return VA_STATUS_SUCCESS;
+}
+
 static int
 i965_os_has_ring_support(VADriverContextP ctx,
                          int ring)
@@ -6223,10 +6918,10 @@ i965_os_has_ring_support(VADriverContextP ctx,
     switch (ring) {
     case I965_RING_BSD:
         return i965->intel.has_bsd;
-        
+
     case I965_RING_BLT:
         return i965->intel.has_blt;
-        
+
     case I965_RING_VEBOX:
         return i965->intel.has_vebox;
 
@@ -6241,16 +6936,16 @@ i965_os_has_ring_support(VADriverContextP ctx,
 
     return 0;
 }
-                                
-/* 
- * Query video processing pipeline 
+
+/*
+ * Query video processing pipeline
  */
 VAStatus i965_QueryVideoProcFilters(
     VADriverContextP    ctx,
     VAContextID         context,
     VAProcFilterType   *filters,
     unsigned int       *num_filters
-    )
+)
 {
     struct i965_driver_data *const i965 = i965_driver_data(ctx);
     unsigned int i = 0, num = 0;
@@ -6265,7 +6960,7 @@ VAStatus i965_QueryVideoProcFilters(
 
                 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
             }
-         
+
             filters[num++] = i965->codec_info->filters[i].type;
         }
     }
@@ -6281,7 +6976,7 @@ VAStatus i965_QueryVideoProcFilterCaps(
     VAProcFilterType    type,
     void               *filter_caps,
     unsigned int       *num_filter_caps
-    )
+)
 {
     unsigned int i = 0;
     struct i965_driver_data *const i965 = i965_driver_data(ctx);
@@ -6302,99 +6997,96 @@ VAStatus i965_QueryVideoProcFilterCaps(
 
     switch (type) {
     case VAProcFilterNoiseReduction:
-    case VAProcFilterSharpening:
-        {
-            VAProcFilterCap *cap = filter_caps;
+    case VAProcFilterSharpening: {
+        VAProcFilterCap *cap = filter_caps;
 
-            if (*num_filter_caps < 1) {
-                *num_filter_caps = 1;
-                return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
-            }
-            
-            cap->range.min_value = 0.0;
-            cap->range.max_value = 1.0;
-            cap->range.default_value = 0.5;
-            cap->range.step = 0.03125; /* 1.0 / 32 */
-            i++;
+        if (*num_filter_caps < 1) {
+            *num_filter_caps = 1;
+            return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
         }
 
-        break;
+        cap->range.min_value = 0.0;
+        cap->range.max_value = 1.0;
+        cap->range.default_value = 0.5;
+        cap->range.step = 0.03125; /* 1.0 / 32 */
+        i++;
+    }
 
-    case VAProcFilterDeinterlacing:
-        {
-            VAProcFilterCapDeinterlacing *cap = filter_caps;
+    break;
 
-            if (*num_filter_caps < VAProcDeinterlacingCount) {
-                *num_filter_caps = VAProcDeinterlacingCount;
-                return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
-            }
-        
-            cap->type = VAProcDeinterlacingBob;
-            i++;
-            cap++;
+    case VAProcFilterDeinterlacing: {
+        VAProcFilterCapDeinterlacing *cap = filter_caps;
 
+        if (*num_filter_caps < VAProcDeinterlacingCount) {
+            *num_filter_caps = VAProcDeinterlacingCount;
+            return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
+        }
 
-            if (i965->codec_info->has_di_motion_adptive) {
-                cap->type = VAProcDeinterlacingMotionAdaptive;
-                i++;
-                cap++;
-            }
+        cap->type = VAProcDeinterlacingBob;
+        i++;
+        cap++;
 
-            if (i965->codec_info->has_di_motion_compensated) {
-                cap->type = VAProcDeinterlacingMotionCompensated;
-                i++;
-                cap++;
-            }
-       }
 
-        break;
+        if (i965->codec_info->has_di_motion_adptive) {
+            cap->type = VAProcDeinterlacingMotionAdaptive;
+            i++;
+            cap++;
+        }
 
-    case VAProcFilterColorBalance:
-        {
-            VAProcFilterCapColorBalance *cap = filter_caps;
+        if (i965->codec_info->has_di_motion_compensated) {
+            cap->type = VAProcDeinterlacingMotionCompensated;
+            i++;
+            cap++;
+        }
+    }
 
-            if (*num_filter_caps < VAProcColorBalanceCount) {
-                *num_filter_caps = VAProcColorBalanceCount;
-                return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
-            }
+    break;
 
-            cap->type = VAProcColorBalanceHue;
-            cap->range.min_value = -180.0;
-            cap->range.max_value = 180.0;
-            cap->range.default_value = 0.0;
-            cap->range.step = 1.0; 
-            i++;
-            cap++; 
-            cap->type = VAProcColorBalanceSaturation;
-            cap->range.min_value = 0.0;
-            cap->range.max_value = 10.0;
-            cap->range.default_value = 1.0;
-            cap->range.step = 0.1; 
-            i++;
-            cap++; 
-            cap->type = VAProcColorBalanceBrightness;
-            cap->range.min_value = -100.0;
-            cap->range.max_value = 100.0;
-            cap->range.default_value = 0.0;
-            cap->range.step = 1.0; 
-            i++;
-            cap++; 
-            cap->type = VAProcColorBalanceContrast;
-            cap->range.min_value = 0.0;
-            cap->range.max_value = 10.0;
-            cap->range.default_value = 1.0;
-            cap->range.step = 0.1; 
-            i++;
-            cap++; 
+    case VAProcFilterColorBalance: {
+        VAProcFilterCapColorBalance *cap = filter_caps;
+
+        if (*num_filter_caps < VAProcColorBalanceCount) {
+            *num_filter_caps = VAProcColorBalanceCount;
+            return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
         }
 
-        break;
+        cap->type = VAProcColorBalanceHue;
+        cap->range.min_value = -180.0;
+        cap->range.max_value = 180.0;
+        cap->range.default_value = 0.0;
+        cap->range.step = 1.0;
+        i++;
+        cap++;
+
+        cap->type = VAProcColorBalanceSaturation;
+        cap->range.min_value = 0.0;
+        cap->range.max_value = 10.0;
+        cap->range.default_value = 1.0;
+        cap->range.step = 0.1;
+        i++;
+        cap++;
+
+        cap->type = VAProcColorBalanceBrightness;
+        cap->range.min_value = -100.0;
+        cap->range.max_value = 100.0;
+        cap->range.default_value = 0.0;
+        cap->range.step = 1.0;
+        i++;
+        cap++;
+
+        cap->type = VAProcColorBalanceContrast;
+        cap->range.min_value = 0.0;
+        cap->range.max_value = 10.0;
+        cap->range.default_value = 1.0;
+        cap->range.step = 0.1;
+        i++;
+        cap++;
+    }
+
+    break;
 
     default:
-        
+
         break;
     }
 
@@ -6417,7 +7109,7 @@ VAStatus i965_QueryVideoProcPipelineCaps(
     VABufferID *filters,
     unsigned int num_filters,
     VAProcPipelineCaps *pipeline_cap     /* out */
-    )
+)
 {
     struct i965_driver_data * const i965 = i965_driver_data(ctx);
     unsigned int i = 0;
@@ -6448,28 +7140,75 @@ VAStatus i965_QueryVideoProcPipelineCaps(
             VAProcFilterParameterBufferDeinterlacing *deint = (VAProcFilterParameterBufferDeinterlacing *)base;
 
             ASSERT_RET(deint->algorithm == VAProcDeinterlacingBob ||
-                   deint->algorithm == VAProcDeinterlacingMotionAdaptive ||
-                   deint->algorithm == VAProcDeinterlacingMotionCompensated,
-                   VA_STATUS_ERROR_INVALID_PARAMETER);
-            
+                       deint->algorithm == VAProcDeinterlacingMotionAdaptive ||
+                       deint->algorithm == VAProcDeinterlacingMotionCompensated,
+                       VA_STATUS_ERROR_INVALID_PARAMETER);
+
             if (deint->algorithm == VAProcDeinterlacingMotionAdaptive ||
                 deint->algorithm == VAProcDeinterlacingMotionCompensated)
                 pipeline_cap->num_forward_references++;
         } else if (base->type == VAProcFilterSkinToneEnhancement) {
-                VAProcFilterParameterBuffer *stde = (VAProcFilterParameterBuffer *)base;
-                (void)stde;
+            VAProcFilterParameterBuffer *stde = (VAProcFilterParameterBuffer *)base;
+            (void)stde;
         }
     }
 
     return VA_STATUS_SUCCESS;
 }
 
+void i965_log_error(VADriverContextP ctx, const char *format, ...)
+{
+    va_list vl;
+
+    va_start(vl, format);
+
+    if (!ctx->error_callback) {
+        // No error callback: this is a error message which should be
+        // user-visible, so print it to stderr instead.
+        vfprintf(stderr, format, vl);
+    } else {
+        // Put the message on the stack.  If it overruns the size of the
+        // then it will just be truncated - callers shouldn't be sending
+        // messages which are too long.
+        char tmp[1024];
+        int ret;
+        ret = vsnprintf(tmp, sizeof(tmp), format, vl);
+        if (ret > 0)
+            ctx->error_callback(ctx, tmp);
+    }
+
+    va_end(vl);
+}
+
+void i965_log_info(VADriverContextP ctx, const char *format, ...)
+{
+    va_list vl;
+
+    va_start(vl, format);
+
+    if (!ctx->info_callback) {
+        // No info callback: this message is only useful for developers,
+        // so just discard it.
+    } else {
+        // Put the message on the stack.  If it overruns the size of the
+        // then it will just be truncated - callers shouldn't be sending
+        // messages which are too long.
+        char tmp[1024];
+        int ret;
+        ret = vsnprintf(tmp, sizeof(tmp), format, vl);
+        if (ret > 0)
+            ctx->info_callback(ctx, tmp);
+    }
+
+    va_end(vl);
+}
+
 extern struct hw_codec_info *i965_get_codec_info(int devid);
 
 static bool
 i965_driver_data_init(VADriverContextP ctx)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
 
     i965->codec_info = i965_get_codec_info(i965->intel.device_id);
 
@@ -6484,7 +7223,7 @@ i965_driver_data_init(VADriverContextP ctx)
                          sizeof(struct object_context),
                          CONTEXT_ID_OFFSET))
         goto err_context_heap;
-    
+
     if (object_heap_init(&i965->surface_heap,
                          sizeof(struct object_surface),
                          SURFACE_ID_OFFSET))
@@ -6509,7 +7248,7 @@ i965_driver_data_init(VADriverContextP ctx)
 
     return true;
 
-err_subpic_heap:    
+err_subpic_heap:
     object_heap_destroy(&i965->image_heap);
 err_image_heap:
     object_heap_destroy(&i965->buffer_heap);
@@ -6527,7 +7266,7 @@ err_config_heap:
 static void
 i965_driver_data_terminate(VADriverContextP ctx)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
 
     _i965DestroyMutex(&i965->pp_mutex);
     _i965DestroyMutex(&i965->render_mutex);
@@ -6551,7 +7290,7 @@ struct {
     void (*terminate)(VADriverContextP ctx);
     int display_type;
 } i965_sub_ops[] =  {
-    {   
+    {
         intel_driver_init,
         intel_driver_terminate,
         0,
@@ -6614,24 +7353,24 @@ ensure_vendor_string(struct i965_driver_data *i965, const char *chipset)
 
     len = 0;
     ret = snprintf(i965->va_vendor, sizeof(i965->va_vendor),
-        "%s %s driver for %s - %d.%d.%d",
-        INTEL_STR_DRIVER_VENDOR, INTEL_STR_DRIVER_NAME, chipset,
-        INTEL_DRIVER_MAJOR_VERSION, INTEL_DRIVER_MINOR_VERSION,
-        INTEL_DRIVER_MICRO_VERSION);
+                   "%s %s driver for %s - %d.%d.%d",
+                   INTEL_STR_DRIVER_VENDOR, INTEL_STR_DRIVER_NAME, chipset,
+                   INTEL_DRIVER_MAJOR_VERSION, INTEL_DRIVER_MINOR_VERSION,
+                   INTEL_DRIVER_MICRO_VERSION);
     if (ret < 0 || ret >= sizeof(i965->va_vendor))
         goto error;
     len = ret;
 
     if (INTEL_DRIVER_PRE_VERSION > 0) {
         ret = snprintf(&i965->va_vendor[len], sizeof(i965->va_vendor) - len,
-            ".pre%d", INTEL_DRIVER_PRE_VERSION);
-        if (ret < 0 || ret >= sizeof(i965->va_vendor))
+                       ".pre%d", INTEL_DRIVER_PRE_VERSION);
+        if (ret < 0 || ret >= (sizeof(i965->va_vendor) - len))
             goto error;
         len += ret;
 
         ret = snprintf(&i965->va_vendor[len], sizeof(i965->va_vendor) - len,
-            " (%s)", INTEL_DRIVER_GIT_VERSION);
-        if (ret < 0 || ret >= sizeof(i965->va_vendor))
+                       " (%s)", INTEL_DRIVER_GIT_VERSION);
+        if (ret < 0 || ret >= (sizeof(i965->va_vendor) - len))
             goto error;
         len += ret;
     }
@@ -6652,7 +7391,7 @@ error:
 static VAStatus
 i965_initialize_wrapper(VADriverContextP ctx, const char *driver_name)
 {
-#define DRIVER_EXTENSION       "_drv_video.so"
+#define DRIVER_EXTENSION    "_drv_video.so"
 
     struct i965_driver_data *i965 = i965_driver_data(ctx);
 
@@ -6719,9 +7458,9 @@ i965_initialize_wrapper(VADriverContextP ctx, const char *driver_name)
             };
             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);
+                         "__vaDriverInit_%d_%d",
+                         compatible_versions[i].major,
+                         compatible_versions[i].minor);
                 init_func = (VADriverInit)dlsym(handle, init_func_s);
                 if (init_func) {
                     break;
@@ -6730,7 +7469,7 @@ i965_initialize_wrapper(VADriverContextP ctx, const char *driver_name)
             if (compatible_versions[i].major < 0) {
                 dlclose(handle);
                 fprintf(stderr, "%s has no function %s\n",
-                            driver_path, init_func_s);
+                        driver_path, init_func_s);
                 driver_dir = strtok_r(NULL, ":", &saveptr);
                 continue;
             }
@@ -6764,10 +7503,10 @@ i965_initialize_wrapper(VADriverContextP ctx, const char *driver_name)
 }
 #endif
 
-static VAStatus 
+static VAStatus
 i965_Init(VADriverContextP ctx)
 {
-    struct i965_driver_data *i965 = i965_driver_data(ctx); 
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
     int i;
     const char *chipset;
 
@@ -6815,7 +7554,7 @@ i965_Init(VADriverContextP ctx)
     }
 }
 
-VAStatus 
+VAStatus
 i965_Terminate(VADriverContextP ctx)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
@@ -6844,7 +7583,7 @@ i965_Terminate(VADriverContextP ctx)
             }
 
         free(i965);
-        ctx->pDriverData = NULL;        
+        ctx->pDriverData = NULL;
     }
 
     return VA_STATUS_SUCCESS;
@@ -6853,8 +7592,8 @@ i965_Terminate(VADriverContextP ctx)
 VAStatus DLL_EXPORT
 VA_DRIVER_INIT_FUNC(VADriverContextP ctx);
 
-VAStatus 
-VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
+VAStatus
+VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
 {
     struct VADriverVTable * const vtable = ctx->vtable;
     struct VADriverVTableVPP * const vtable_vpp = ctx->vtable_vpp;
@@ -6922,6 +7661,9 @@ VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
     vtable->vaAcquireBufferHandle = i965_AcquireBufferHandle;
     vtable->vaReleaseBufferHandle = i965_ReleaseBufferHandle;
 
+    /* 1.0.0 */
+    vtable->vaExportSurfaceHandle = i965_ExportSurfaceHandle;
+
     vtable_vpp->vaQueryVideoProcFilters = i965_QueryVideoProcFilters;
     vtable_vpp->vaQueryVideoProcFilterCaps = i965_QueryVideoProcFilterCaps;
     vtable_vpp->vaQueryVideoProcPipelineCaps = i965_QueryVideoProcPipelineCaps;