From f8687ab1ed294adf9175b2f64f5ea60748f66759 Mon Sep 17 00:00:00 2001 From: "Xiang, Haihao" Date: Thu, 2 Feb 2012 10:37:38 +0800 Subject: [PATCH] Guess the format of a VA surface in vaDeriveImage() Sometimes we don't know the usage of a VA surface, so we have to guess the format according to the current valid context (a hint). Note it is not always right, pixel format conversion is needed internally for mismatched pixel format. Signed-off-by: Xiang, Haihao --- src/i965_drv_video.c | 93 +++++++++++++++++++++++++++++++++++++++++++++------- src/i965_drv_video.h | 2 ++ 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c index 5aa04eb..5bfcaee 100644 --- a/src/i965_drv_video.c +++ b/src/i965_drv_video.c @@ -598,6 +598,59 @@ i965_QueryImageFormats(VADriverContextP ctx, return VA_STATUS_SUCCESS; } +/* + * Guess the format when the usage of a VA surface is unknown + * 1. Without a valid context: YV12 + * 2. The current context is valid: + * a) always NV12 on GEN6 and later + * b) I420 for MPEG-2 and NV12 for other codec on GEN4 & GEN5 + */ +static void +i965_guess_surface_format(VADriverContextP ctx, + VASurfaceID surface, + unsigned int *fourcc, + unsigned int *is_tiled) +{ + struct i965_driver_data *i965 = i965_driver_data(ctx); + struct object_context *obj_context = NULL; + struct object_config *obj_config = NULL; + + *fourcc = VA_FOURCC('Y', 'V', '1', '2'); + *is_tiled = 0; + + if (i965->current_context_id == VA_INVALID_ID) + return; + + obj_context = CONTEXT(i965->current_context_id); + + if (!obj_context || obj_context->config_id == VA_INVALID_ID) + return; + + obj_config = CONFIG(obj_context->config_id); + + if (!obj_config) + return; + + if (IS_GEN6(i965->intel.device_id) || IS_GEN7(i965->intel.device_id)) { + *fourcc = VA_FOURCC('N', 'V', '1', '2'); + *is_tiled = 1; + return; + } + + switch (obj_config->profile) { + case VAProfileMPEG2Simple: + case VAProfileMPEG2Main: + *fourcc = VA_FOURCC('I', '4', '2', '0'); + *is_tiled = 0; + break; + + default: + *fourcc = VA_FOURCC('N', 'V', '1', '2'); + *is_tiled = 0; + break; + } +} + VAStatus i965_PutImage(VADriverContextP ctx, VASurfaceID surface, @@ -1028,6 +1081,8 @@ i965_CreateContext(VADriverContextP ctx, i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context); } + i965->current_context_id = contextID; + return vaStatus; } @@ -1038,6 +1093,10 @@ i965_DestroyContext(VADriverContextP ctx, VAContextID context) struct object_context *obj_context = CONTEXT(context); assert(obj_context); + + if (i965->current_context_id == context) + i965->current_context_id = VA_INVALID_ID; + i965_destroy_context(&i965->context_heap, (struct object_base *)obj_context); return VA_STATUS_SUCCESS; @@ -2231,7 +2290,14 @@ VAStatus i965_DeriveImage(VADriverContextP ctx, if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; - i965_check_alloc_surface_bo(ctx, obj_surface, HAS_TILED_SURFACE(i965), VA_FOURCC('N', 'V', '1', '2'), SUBSAMPLE_YUV420); + if (!obj_surface->bo) { + unsigned int is_tiled = 0; + unsigned int fourcc = VA_FOURCC('Y', 'V', '1', '2'); + i965_guess_surface_format(ctx, surface, &fourcc, &is_tiled); + i965_check_alloc_surface_bo(ctx, obj_surface, is_tiled, fourcc, SUBSAMPLE_YUV420); + } + + assert(obj_surface->fourcc); w_pitch = obj_surface->width; h_pitch = obj_surface->height; @@ -2270,28 +2336,28 @@ VAStatus i965_DeriveImage(VADriverContextP ctx, image->num_planes = 3; image->pitches[0] = w_pitch; /* Y */ image->offsets[0] = 0; - image->pitches[1] = w_pitch / 2; /* V */ - image->offsets[1] = w_pitch * h_pitch; - image->pitches[2] = w_pitch / 2; /* U */ - image->offsets[2] = w_pitch * h_pitch + (w_pitch / 2) * (h_pitch / 2); + image->pitches[1] = obj_surface->cb_cr_pitch; /* V */ + image->offsets[1] = w_pitch * obj_surface->y_cr_offset; + image->pitches[2] = obj_surface->cb_cr_pitch; /* U */ + image->offsets[2] = w_pitch * obj_surface->y_cb_offset; break; case VA_FOURCC('N', 'V', '1', '2'): image->num_planes = 2; image->pitches[0] = w_pitch; /* Y */ image->offsets[0] = 0; - image->pitches[1] = w_pitch; /* UV */ - image->offsets[1] = w_pitch * h_pitch; + image->pitches[1] = obj_surface->cb_cr_pitch; /* UV */ + image->offsets[1] = w_pitch * obj_surface->y_cb_offset; break; case VA_FOURCC('I', '4', '2', '0'): image->num_planes = 3; image->pitches[0] = w_pitch; /* Y */ image->offsets[0] = 0; - image->pitches[1] = w_pitch / 2; /* U */ - image->offsets[1] = w_pitch * h_pitch; - image->pitches[2] = w_pitch / 2; /* V */ - image->offsets[2] = w_pitch * h_pitch + (w_pitch / 2) * (h_pitch / 2); + image->pitches[1] = obj_surface->cb_cr_pitch; /* U */ + image->offsets[1] = w_pitch * obj_surface->y_cb_offset; + image->pitches[2] = obj_surface->cb_cr_pitch; /* V */ + image->offsets[2] = w_pitch * obj_surface->y_cr_offset; break; default: @@ -3148,7 +3214,10 @@ VA_DRIVER_INIT_FUNC( VADriverContextP ctx ) const int len = strlen(i965->va_vendor); sprintf(&i965->va_vendor[len], ".pre%d", INTEL_DRIVER_PRE_VERSION); } - ctx->str_vendor = i965->va_vendor; + i965->current_context_id = VA_INVALID_ID; + + ctx->str_vendor = i965->va_vendor; + return i965_Init(ctx); } diff --git a/src/i965_drv_video.h b/src/i965_drv_video.h index 4f2873c..a6ec3ed 100644 --- a/src/i965_drv_video.h +++ b/src/i965_drv_video.h @@ -268,6 +268,8 @@ struct i965_driver_data struct i965_render_state render_state; void *pp_context; char va_vendor[256]; + + VAContextID current_context_id; }; #define NEW_CONFIG_ID() object_heap_allocate(&i965->config_heap); -- 2.7.4