OSDN Git Service

Don't show an error on hybrid driver failure
[android-x86/hardware-intel-common-vaapi.git] / src / i965_drv_video.c
index ed18eeb..911c34d 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"
@@ -538,7 +539,8 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
     if (HAS_H264_DECODING(i965) ||
         HAS_H264_ENCODING(i965) ||
         HAS_LP_H264_ENCODING(i965) ||
-        HAS_FEI_H264_ENCODING(i965)) {
+        HAS_FEI_H264_ENCODING(i965) ||
+        HAS_H264_PREENC(i965)) {
         profile_list[i++] = VAProfileH264ConstrainedBaseline;
         profile_list[i++] = VAProfileH264Main;
         profile_list[i++] = VAProfileH264High;
@@ -581,7 +583,8 @@ i965_QueryConfigProfiles(VADriverContextP ctx,
     }
 
     if (HAS_VP9_DECODING_PROFILE(i965, VAProfileVP9Profile0) ||
-        HAS_VP9_ENCODING(i965)) {
+        HAS_VP9_ENCODING(i965) ||
+        HAS_LP_VP9_ENCODING(i965)) {
         profile_list[i++] = VAProfileVP9Profile0;
     }
 
@@ -650,7 +653,10 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
         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))
@@ -715,6 +721,9 @@ i965_QueryConfigEntrypoints(VADriverContextP ctx,
         if (HAS_VP9_ENCODING(i965) && (profile == VAProfileVP9Profile0))
             entrypoint_list[n++] = VAEntrypointEncSlice;
 
+        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;
@@ -767,10 +776,12 @@ i965_validate_config(VADriverContextP ctx, VAProfile profile,
         if ((HAS_H264_DECODING(i965) && entrypoint == VAEntrypointVLD) ||
             (HAS_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSlice) ||
             (HAS_LP_H264_ENCODING(i965) && entrypoint == VAEntrypointEncSliceLP) ||
-            (HAS_FEI_H264_ENCODING(i965) && entrypoint == VAEntrypointFEI)) {
+            (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_FEI_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;
@@ -870,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) {
+                   !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;
@@ -945,6 +962,105 @@ i965_get_default_chroma_formats(VADriverContextP ctx, VAProfile profile,
     return chroma_formats;
 }
 
+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,
@@ -971,68 +1087,13 @@ i965_GetConfigAttributes(VADriverContextP ctx,
             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;
-
-                if (profile == VAProfileVP8Version0_3 ||
-                    profile == VAProfileVP9Profile0 ||
-                    profile == VAProfileHEVCMain)
-                    attrib_list[i].value |= VA_RC_VBR;
-
-                if (profile == VAProfileH264ConstrainedBaseline ||
-                    profile == VAProfileH264Main ||
-                    profile == VAProfileH264High)
-                    attrib_list[i].value = i965->codec_info->h264_brc_mode;
-
-                break;
-            } else if (entrypoint == VAEntrypointEncSliceLP) {
-                struct i965_driver_data * const i965 = i965_driver_data(ctx);
-
-                /* Support low power encoding for H.264 only by now */
-                if (profile == VAProfileH264ConstrainedBaseline ||
-                    profile == VAProfileH264Main ||
-                    profile == VAProfileH264High)
-                    attrib_list[i].value = i965->codec_info->lp_h264_brc_mode;
-                else
-                    attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
-            } else if (entrypoint == VAEntrypointFEI) {
-                /* Only CQP is supported in FEI Entrypoint */
-                if (profile == VAProfileH264ConstrainedBaseline ||
-                    profile == VAProfileH264Main ||
-                    profile == VAProfileH264High)
-                    attrib_list[i].value = VA_RC_CQP;
-                else
-                    attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
-            } else
-                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+            attrib_list[i].value = i965_get_rc_attributes(ctx, profile, entrypoint);
 
             break;
 
         case VAConfigAttribEncPackedHeaders:
-            if (entrypoint == VAEntrypointEncSlice ||
-                entrypoint == VAEntrypointEncSliceLP ||
-                entrypoint == VAEntrypointFEI) {
-                attrib_list[i].value = VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE | VA_ENC_PACKED_HEADER_MISC;
-                if (profile == VAProfileH264ConstrainedBaseline ||
-                    profile == VAProfileH264Main ||
-                    profile == VAProfileH264High ||
-                    profile == VAProfileH264StereoHigh ||
-                    profile == VAProfileH264MultiviewHigh ||
-                    profile == VAProfileHEVCMain ||
-                    profile == VAProfileHEVCMain10) {
-                    attrib_list[i].value |= (VA_ENC_PACKED_HEADER_RAW_DATA |
-                                             VA_ENC_PACKED_HEADER_SLICE);
-                } else if (profile == VAProfileVP9Profile0)
-                    attrib_list[i].value = VA_ENC_PACKED_HEADER_RAW_DATA;
-                break;
-            } else if (entrypoint == VAEntrypointEncPicture) {
-                if (profile == VAProfileJPEGBaseline)
-                    attrib_list[i].value = VA_ENC_PACKED_HEADER_RAW_DATA;
-            }
+            attrib_list[i].value = i965_get_enc_packed_attributes(ctx, profile, entrypoint);
+
             break;
 
         case VAConfigAttribEncMaxRefFrames:
@@ -1043,12 +1104,15 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                     profile == VAProfileH264High ||
                     profile == VAProfileH264StereoHigh ||
                     profile == VAProfileH264MultiviewHigh) {
-                    if (IS_GEN9(i965->intel.device_info))
-                        attrib_list[i].value = (2 << 16) | (8 << 0);
+                    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 (entrypoint == VAEntrypointEncSliceLP) {
                 /* Don't support B frame for low power mode */
@@ -1058,7 +1122,8 @@ 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;
 
@@ -1072,14 +1137,21 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                     profile == VAProfileH264High) {
                     attrib_list[i].value = ENCODER_QUALITY_RANGE;
                     if (entrypoint == VAEntrypointEncSlice) {
-                        if (IS_GEN9(i965->intel.device_info))
+                        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:
@@ -1097,7 +1169,8 @@ 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:
@@ -1112,7 +1185,12 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                     profile == VAProfileH264High) {
 
                     if (IS_GEN9(i965->intel.device_info) &&
-                        (entrypoint == VAEntrypointEncSlice || entrypoint == VAEntrypointFEI))
+                        (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) {
@@ -1146,6 +1224,8 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                 entrypoint == VAEntrypointEncSlice) {
                 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);
 
@@ -1199,13 +1279,27 @@ i965_GetConfigAttributes(VADriverContextP ctx,
             break;
 
         case VAConfigAttribFEIFunctionType:
-            /* Supporing all possible modes of FEI */
-            attrib_list[i].value = VA_FEI_FUNCTION_ENC |
-                                   VA_FEI_FUNCTION_PAK | VA_FEI_FUNCTION_ENC_PAK;
+            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:
-            attrib_list[i].value = 4;
+            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:
@@ -1325,25 +1419,37 @@ i965_CreateConfig(VADriverContextP ctx,
 
 
     if (vaStatus == VA_STATUS_SUCCESS) {
-        VAConfigAttrib attrib, *attrib_found;
-        attrib.type = VAConfigAttribRateControl;
-        attrib_found = i965_lookup_config_attribute(obj_config, attrib.type);
-        switch (profile) {
-        case VAProfileH264ConstrainedBaseline:
-        case VAProfileH264Main:
-        case VAProfileH264High:
-            if ((entrypoint == VAEntrypointEncSlice) && attrib_found &&
-                !(attrib_found->value & i965->codec_info->h264_brc_mode))
-                vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
-            else if ((entrypoint == VAEntrypointEncSliceLP) && attrib_found &&
-                     !(attrib_found->value & i965->codec_info->lp_h264_brc_mode))
-                vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
-            else if ((entrypoint == VAEntrypointFEI) && attrib_found &&
-                     !(attrib_found->value == VA_RC_CQP))
-                vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
-            break;
-        default:
-            break;
+        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;
+                }
+            }
         }
     }
 
@@ -1392,6 +1498,17 @@ i965_CreateConfig(VADriverContextP ctx,
             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) &&
@@ -1573,7 +1690,6 @@ i965_suface_external_memory(VADriverContextP ctx,
         obj_surface->height = memory_attibute->offsets[1] / obj_surface->width;
 
     if (memory_attibute->num_planes > 1) {
-        ASSERT_RET(IS_ALIGNED(obj_surface->height, 16), VA_STATUS_ERROR_INVALID_PARAMETER);
         ASSERT_RET(obj_surface->height >= obj_surface->orig_height, VA_STATUS_ERROR_INVALID_PARAMETER);
     }
 
@@ -2056,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;
@@ -2383,6 +2500,10 @@ 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);
@@ -2439,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 ||
@@ -2453,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();
@@ -2545,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));
@@ -2590,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);
@@ -2685,6 +2829,12 @@ i965_create_buffer_internal(VADriverContextP ctx,
     case VAEncFEIDistortionBufferType:
     case VAEncFEIMBControlBufferType:
     case VAEncFEIMVPredictorBufferType:
+    case VAStatsStatisticsParameterBufferType:
+    case VAStatsStatisticsBufferType:
+    case VAStatsStatisticsBottomFieldBufferType:
+    case VAStatsMVBufferType:
+    case VAStatsMVPredictorBufferType:
+
         /* Ok */
         break;
 
@@ -2752,7 +2902,12 @@ i965_create_buffer_internal(VADriverContextP ctx,
                type == VAEncFEIMBCodeBufferType ||
                type == VAEncFEIDistortionBufferType ||
                type == VAEncFEIMBControlBufferType ||
-               type == VAEncFEIMVPredictorBufferType) {
+               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
@@ -2857,8 +3012,7 @@ i965_BufferSetNumElements(VADriverContextP ctx,
         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;
@@ -3132,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);
@@ -3398,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)
@@ -3756,6 +3915,42 @@ i965_proc_render_picture(VADriverContextP ctx,
     return 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,
@@ -3783,6 +3978,8 @@ i965_RenderPicture(VADriverContextP ctx,
                (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);
     }
@@ -3837,6 +4034,13 @@ 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;
@@ -5685,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
@@ -5763,7 +5968,8 @@ 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 ||
@@ -5778,6 +5984,11 @@ i965_GetSurfaceAttributes(
                             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 */
@@ -5880,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;
@@ -6073,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;
@@ -6256,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++;
         }
     }
 
@@ -6287,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);
@@ -6437,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)
@@ -6684,6 +7156,53 @@ VAStatus i965_QueryVideoProcPipelineCaps(
     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
@@ -6845,13 +7364,13 @@ ensure_vendor_string(struct i965_driver_data *i965, const char *chipset)
     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))
+        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))
+        if (ret < 0 || ret >= (sizeof(i965->va_vendor) - len))
             goto error;
         len += ret;
     }
@@ -6976,7 +7495,7 @@ i965_initialize_wrapper(VADriverContextP ctx, const char *driver_name)
         i965->wrapper_pdrvctx = wrapper_pdrvctx;
         return VA_STATUS_SUCCESS;
     } else {
-        fprintf(stderr, "Failed to wrapper %s%s\n", driver_name, DRIVER_EXTENSION);
+        fprintf(stdout, "Not using %s%s\n", driver_name, DRIVER_EXTENSION);
         free(vtable);
         free(wrapper_pdrvctx);
         return VA_STATUS_ERROR_OPERATION_FAILED;
@@ -7142,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;