Fix graphics memory allocation for VA surface
authorXiang, Haihao <haihao.xiang@intel.com>
Wed, 18 Jan 2012 03:27:10 +0000 (11:27 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Wed, 18 Jan 2012 03:27:10 +0000 (11:27 +0800)
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
src/gen6_mfc.c
src/gen6_mfd.c
src/gen7_mfc.c
src/gen7_mfd.c
src/i965_avc_bsd.c
src/i965_defines.h
src/i965_drv_video.c
src/i965_drv_video.h
src/i965_media_mpeg2.c
src/i965_post_processing.c
src/i965_render.c

index 19857cf..b90596b 100644 (file)
@@ -873,7 +873,7 @@ static VAStatus gen6_mfc_avc_prepare(VADriverContextP ctx,
     /* Setup current frame and current direct mv buffer*/
     obj_surface = SURFACE(pPicParameter->CurrPic.picture_id);
     assert(obj_surface);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
     if ( obj_surface->private_data == NULL) {
         gen6_avc_surface = calloc(sizeof(struct gen6_mfc_avc_surface_aux), 1);
         gen6_avc_surface->dmv_top = 
index 407b2ce..b5d8f62 100644 (file)
@@ -119,7 +119,7 @@ gen6_mfd_avc_frame_store_index(VADriverContextP ctx,
             struct object_surface *obj_surface = SURFACE(ref_pic->picture_id);
             
             assert(obj_surface);
-            i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N', 'V', '1', '2'));
+            i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N', 'V', '1', '2'), SUBSAMPLE_YUV420);
 
             for (frame_idx = 0; frame_idx < ARRAY_ELEMS(gen6_mfd_context->reference_surface); frame_idx++) {
                 for (j = 0; j < ARRAY_ELEMS(gen6_mfd_context->reference_surface); j++) {
@@ -1040,7 +1040,7 @@ gen6_mfd_avc_decode_init(VADriverContextP ctx,
     assert(obj_surface);
     obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
     obj_surface->flags |= (pic_param->pic_fields.bits.reference_pic_flag ? SURFACE_REFERENCED : 0);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
     gen6_mfd_init_avc_surface(ctx, pic_param, obj_surface);
 
     dri_bo_unreference(gen6_mfd_context->post_deblocking_output.bo);
@@ -1190,7 +1190,7 @@ gen6_mfd_mpeg2_decode_init(VADriverContextP ctx,
     /* Current decoded picture */
     obj_surface = SURFACE(decode_state->current_render_target);
     assert(obj_surface);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
 
     dri_bo_unreference(gen6_mfd_context->pre_deblocking_output.bo);
     gen6_mfd_context->pre_deblocking_output.bo = obj_surface->bo;
@@ -1510,7 +1510,7 @@ gen6_mfd_vc1_decode_init(VADriverContextP ctx,
     /* Current decoded picture */
     obj_surface = SURFACE(decode_state->current_render_target);
     assert(obj_surface);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
     gen6_mfd_init_vc1_surface(ctx, pic_param, obj_surface);
 
     dri_bo_unreference(gen6_mfd_context->post_deblocking_output.bo);
index a454b8e..ecfe27f 100644 (file)
@@ -928,7 +928,7 @@ gen7_mfc_avc_prepare(VADriverContextP ctx,
     /* Setup current frame and current direct mv buffer*/
     obj_surface = SURFACE(pPicParameter->CurrPic.picture_id);
     assert(obj_surface);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
 
     if ( obj_surface->private_data == NULL) {
         gen7_avc_surface = calloc(sizeof(struct gen7_mfc_avc_surface_aux), 1);
index 45e229e..09c327f 100644 (file)
@@ -119,7 +119,7 @@ gen7_mfd_avc_frame_store_index(VADriverContextP ctx,
             struct object_surface *obj_surface = SURFACE(ref_pic->picture_id);
             
             assert(obj_surface);
-            i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+            i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
 
             for (frame_idx = 0; frame_idx < ARRAY_ELEMS(gen7_mfd_context->reference_surface); frame_idx++) {
                 for (j = 0; j < ARRAY_ELEMS(gen7_mfd_context->reference_surface); j++) {
@@ -269,17 +269,9 @@ gen7_mfd_surface_state(VADriverContextP ctx,
 
     assert(obj_surface);
 
-    if (obj_surface->fourcc == VA_FOURCC('I', 'M', 'C', '1')) {
-        y_cb_offset = ALIGN(obj_surface->height, 32) + ALIGN(obj_surface->height / 2, 32);
-        y_cr_offset = ALIGN(obj_surface->height, 32);
-    } else if (obj_surface->fourcc == VA_FOURCC('I', 'M', 'C', '3')) {
-        y_cb_offset = ALIGN(obj_surface->height, 32);
-        y_cr_offset = ALIGN(obj_surface->height, 32) + ALIGN(obj_surface->height / 2, 32);
-    } else {
-        y_cb_offset = ALIGN(obj_surface->height, 32);
-        y_cr_offset = 0;
-    }
-    
+    y_cb_offset = obj_surface->y_cb_offset;
+    y_cr_offset = obj_surface->y_cr_offset;
+
     BEGIN_BCS_BATCH(batch, 6);
     OUT_BCS_BATCH(batch, MFX_SURFACE_STATE | (6 - 2));
     OUT_BCS_BATCH(batch, 0);
@@ -1000,7 +992,7 @@ gen7_mfd_avc_decode_init(VADriverContextP ctx,
     assert(obj_surface);
     obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
     obj_surface->flags |= (pic_param->pic_fields.bits.reference_pic_flag ? SURFACE_REFERENCED : 0);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
     gen7_mfd_init_avc_surface(ctx, pic_param, obj_surface);
 
     dri_bo_unreference(gen7_mfd_context->post_deblocking_output.bo);
@@ -1149,7 +1141,7 @@ gen7_mfd_mpeg2_decode_init(VADriverContextP ctx,
     /* Current decoded picture */
     obj_surface = SURFACE(decode_state->current_render_target);
     assert(obj_surface);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
 
     dri_bo_unreference(gen7_mfd_context->pre_deblocking_output.bo);
     gen7_mfd_context->pre_deblocking_output.bo = obj_surface->bo;
@@ -1478,7 +1470,7 @@ gen7_mfd_vc1_decode_init(VADriverContextP ctx,
     /* Current decoded picture */
     obj_surface = SURFACE(decode_state->current_render_target);
     assert(obj_surface);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
     gen7_mfd_init_vc1_surface(ctx, pic_param, obj_surface);
 
     dri_bo_unreference(gen7_mfd_context->post_deblocking_output.bo);
@@ -2000,11 +1992,52 @@ gen7_mfd_jpeg_decode_init(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_surface *obj_surface;
+    VAPictureParameterBufferJPEG *pic_param;
+    int subsampling = SUBSAMPLE_YUV420;
+
+    pic_param = (VAPictureParameterBufferJPEG *)decode_state->pic_param->buffer;
+
+    if (pic_param->num_components == 1)
+        subsampling = SUBSAMPLE_YUV400;
+    else if (pic_param->num_components == 3) {
+        int h1 = pic_param->components[0].h_sampling_factor;
+        int h2 = pic_param->components[1].h_sampling_factor;
+        int h3 = pic_param->components[2].h_sampling_factor;
+        int v1 = pic_param->components[0].v_sampling_factor;
+        int v2 = pic_param->components[1].v_sampling_factor;
+        int v3 = pic_param->components[2].v_sampling_factor;
+
+        if (h1 == 2 && h2 == 1 && h3 == 1 &&
+            v1 == 2 && v2 == 1 && v3 == 1)
+            subsampling = SUBSAMPLE_YUV420;
+        else if (h1 == 2 && h2 == 1 && h3 == 1 &&
+                 v1 == 1 && v2 == 1 && v3 == 1)
+            subsampling = SUBSAMPLE_YUV422H;
+        else if (h1 == 1 && h2 == 1 && h3 == 1 &&
+                 v1 == 1 && v2 == 1 && v3 == 1)
+            subsampling = SUBSAMPLE_YUV444;
+        else if (h1 == 4 && h2 == 1 && h3 == 1 &&
+                 v1 == 1 && v2 == 1 && v3 == 1)
+            subsampling = SUBSAMPLE_YUV411;
+        else if (h1 == 1 && h2 == 1 && h3 == 1 &&
+                 v1 == 2 && v2 == 1 && v3 == 1)
+            subsampling = SUBSAMPLE_YUV422V;
+        else if (h1 == 2 && h2 == 1 && h3 == 1 &&
+                 v1 == 2 && v2 == 2 && v3 == 2)
+            subsampling = SUBSAMPLE_YUV422H;
+        else if (h2 == 2 && h2 == 2 && h3 == 2 &&
+                 v1 == 2 && v2 == 1 && v3 == 1)
+            subsampling = SUBSAMPLE_YUV422V;
+        else
+            assert(0);
+    } else {
+        assert(0);
+    }
 
     /* Current decoded picture */
     obj_surface = SURFACE(decode_state->current_render_target);
     assert(obj_surface);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('I','M','C','1'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC('I','M','C','1'), subsampling);
 
     dri_bo_unreference(gen7_mfd_context->pre_deblocking_output.bo);
     gen7_mfd_context->pre_deblocking_output.bo = obj_surface->bo;
@@ -2044,7 +2077,7 @@ gen7_mfd_jpeg_pic_state(VADriverContextP ctx,
 {
     struct intel_batchbuffer *batch = gen7_mfd_context->base.batch;
     VAPictureParameterBufferJPEG *pic_param;
-    int chroma_type = GEN7_YUV400;
+    int chroma_type = GEN7_YUV420;
     int frame_width_in_blks;
     int frame_height_in_blks;
 
index 67d2bac..f04c5a0 100644 (file)
@@ -512,7 +512,7 @@ i965_avc_bsd_buf_base_state(VADriverContextP ctx,
     assert(obj_surface);
     obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
     obj_surface->flags |= (pic_param->pic_fields.bits.reference_pic_flag ? SURFACE_REFERENCED : 0);
-    i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
     i965_avc_bsd_init_avc_bsd_surface(ctx, obj_surface, pic_param, i965_h264_context);
     avc_bsd_surface = obj_surface->private_data;
 
@@ -957,7 +957,7 @@ i965_avc_bsd_frame_store_index(VADriverContextP ctx,
             int frame_idx;
             struct object_surface *obj_surface = SURFACE(ref_pic->picture_id);
             assert(obj_surface);
-            i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('N','V','1','2'));
+            i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
             
             for (frame_idx = 0; frame_idx < ARRAY_ELEMS(i965_h264_context->fsid_list); frame_idx++) {
                 for (j = 0; j < ARRAY_ELEMS(i965_h264_context->fsid_list); j++) {
index 8d23bec..0988a15 100644 (file)
 #define MFD_MODE_IT             1
 
 #define MFX_SURFACE_PLANAR_420_8        4
+#define MFX_SURFACE_PLANAR_411_8        5
+#define MFX_SURFACE_PLANAR_422_8        6
 #define MFX_SURFACE_MONOCHROME          12
 
 #define MPEG_TOP_FIELD         1
 #define MPEG_BOTTOM_FIELD      2
 #define MPEG_FRAME             3
 
+#define SUBSAMPLE_YUV400        0
+#define SUBSAMPLE_YUV420        1
+#define SUBSAMPLE_YUV422H       2
+#define SUBSAMPLE_YUV422V       3
+#define SUBSAMPLE_YUV444        4
+#define SUBSAMPLE_YUV411        5
+
 #define URB_SIZE(intel)         (IS_GEN7(intel->device_id) ? 4096 :     \
                                  IS_GEN6(intel->device_id) ? 1024 :     \
                                  IS_IRONLAKE(intel->device_id) ? 1024 : \
index a0a0e02..de52bda 100644 (file)
@@ -532,21 +532,15 @@ i965_CreateSurfaces(VADriverContextP ctx,
         obj_surface->orig_width = width;
         obj_surface->orig_height = height;
 
-        if (IS_GEN6(i965->intel.device_id) ||
-            IS_GEN7(i965->intel.device_id)) {
-            obj_surface->width = ALIGN(obj_surface->orig_width, 128);
-            obj_surface->height = ALIGN(obj_surface->orig_height, 32);
-        } else {
-            obj_surface->width = ALIGN(obj_surface->orig_width, 16);
-            obj_surface->height = ALIGN(obj_surface->orig_height, 16);
-        }
-
+        obj_surface->width = ALIGN(width, 16);
+        obj_surface->height = ALIGN(height, 16);
         obj_surface->flags = SURFACE_REFERENCED;
         obj_surface->fourcc = 0;
         obj_surface->bo = NULL;
         obj_surface->locked_image_id = VA_INVALID_ID;
         obj_surface->private_data = NULL;
         obj_surface->free_private_data = NULL;
+        obj_surface->subsampling = SUBSAMPLE_YUV420;
     }
 
     /* Error recovery */
@@ -639,7 +633,7 @@ i965_PutImage(VADriverContextP ctx,
         dest_y + dest_height > obj_surface->orig_height)
         return VA_STATUS_ERROR_INVALID_PARAMETER;
 
-    i965_check_alloc_surface_bo(ctx, obj_surface, HAS_TILED_SURFACE(i965), VA_FOURCC('N', 'V', '1', '2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, HAS_TILED_SURFACE(i965), VA_FOURCC('N', 'V', '1', '2'), SUBSAMPLE_YUV420);
 
     src_surface.id = image;
     src_surface.type = I965_SURFACE_TYPE_IMAGE;
@@ -2067,37 +2061,138 @@ void
 i965_check_alloc_surface_bo(VADriverContextP ctx,
                             struct object_surface *obj_surface,
                             int tiled,
-                            unsigned int fourcc)
+                            unsigned int fourcc,
+                            unsigned int subsampling)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
+    int region_width, region_height;
 
     if (obj_surface->bo) {
         assert(obj_surface->fourcc);
         assert(obj_surface->fourcc == fourcc);
+        assert(obj_surface->subsampling == subsampling);
         return;
     }
 
-    if (fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
-        fourcc == VA_FOURCC('I', 'M', 'C', '3'))
-        obj_surface->size = ALIGN(obj_surface->width * obj_surface->height * 2, 0x1000);
-    else 
-        obj_surface->size = ALIGN(obj_surface->width * obj_surface->height * 3 / 2, 0x1000);
+    obj_surface->x_cb_offset = 0; /* X offset is always 0 */
+    obj_surface->x_cr_offset = 0;
+
+    if (tiled) {
+        assert(fourcc == VA_FOURCC('N', 'V', '1', '2') ||
+               fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
+               fourcc == VA_FOURCC('I', 'M', 'C', '3'));
+
+        obj_surface->width = ALIGN(obj_surface->orig_width, 128);
+        obj_surface->height = ALIGN(obj_surface->orig_height, 32);
+        obj_surface->cb_cr_pitch = obj_surface->width;
+        region_width = obj_surface->width;
+        region_height = obj_surface->height;
+
+        if (fourcc == VA_FOURCC('N', 'V', '1', '2')) {
+            assert(subsampling == SUBSAMPLE_YUV420);
+            obj_surface->y_cb_offset = obj_surface->height;
+            obj_surface->y_cr_offset = obj_surface->height;
+            obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+            obj_surface->cb_cr_height = obj_surface->orig_height / 2;
+            region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32);
+        } else if (fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
+                   fourcc == VA_FOURCC('I', 'M', 'C', '3')) {
+            switch (subsampling) {
+            case SUBSAMPLE_YUV400:
+                obj_surface->cb_cr_width = 0;
+                obj_surface->cb_cr_height = 0;
+                break;
+
+            case SUBSAMPLE_YUV420:
+                obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+                obj_surface->cb_cr_height = obj_surface->orig_height / 2;
+                break;
+
+            case SUBSAMPLE_YUV422H:
+                obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+                obj_surface->cb_cr_height = obj_surface->orig_height;
+                break;
+
+            case SUBSAMPLE_YUV422V:
+                obj_surface->cb_cr_width = obj_surface->orig_width;
+                obj_surface->cb_cr_height = obj_surface->orig_height / 2;
+                break;
+
+            case SUBSAMPLE_YUV444:
+                obj_surface->cb_cr_width = obj_surface->orig_width;
+                obj_surface->cb_cr_height = obj_surface->orig_height;
+                break;
+
+            case SUBSAMPLE_YUV411:
+                obj_surface->cb_cr_width = obj_surface->orig_width / 4;
+                obj_surface->cb_cr_height = obj_surface->orig_height;
+                break;
+
+            default:
+                assert(0);
+                break;
+            }
+
+            region_height = obj_surface->height + ALIGN(obj_surface->cb_cr_height, 32) * 2;
+
+            if (fourcc == VA_FOURCC('I', 'M', 'C', '1')) {
+                obj_surface->y_cb_offset = obj_surface->height;
+                obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
+            } else {
+                obj_surface->y_cb_offset = obj_surface->height;
+                obj_surface->y_cr_offset = obj_surface->y_cb_offset + ALIGN(obj_surface->cb_cr_height, 32);
+            }
+        }
+    } else {
+        assert(fourcc != VA_FOURCC('I', 'M', 'C', '1') &&
+               fourcc != VA_FOURCC('I', 'M', 'C', '3'));
+        assert(subsampling == SUBSAMPLE_YUV420);
+
+        region_width = obj_surface->width;
+        region_height = obj_surface->height;
+
+        switch (fourcc) {
+        case VA_FOURCC('N', 'V', '1', '2'):
+            obj_surface->y_cb_offset = obj_surface->height;
+            obj_surface->y_cr_offset = obj_surface->height;
+            obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+            obj_surface->cb_cr_height = obj_surface->orig_height / 2;
+            obj_surface->cb_cr_pitch = obj_surface->width;
+            region_height = obj_surface->height + obj_surface->height / 2;
+            break;
+
+        case VA_FOURCC('Y', 'V', '1', '2'):
+        case VA_FOURCC('I', '4', '2', '0'):
+            if (fourcc == VA_FOURCC('Y', 'V', '1', '2')) {
+                obj_surface->y_cr_offset = obj_surface->height;
+                obj_surface->y_cb_offset = obj_surface->height + obj_surface->height / 4;
+            } else {
+                obj_surface->y_cb_offset = obj_surface->height;
+                obj_surface->y_cr_offset = obj_surface->height + obj_surface->height / 4;
+            }
+
+            obj_surface->cb_cr_width = obj_surface->orig_width / 2;
+            obj_surface->cb_cr_height = obj_surface->orig_height / 2;
+            obj_surface->cb_cr_pitch = obj_surface->width / 2;
+            region_height = obj_surface->height + obj_surface->height / 2;
+            break;
+
+        default:
+            assert(0);
+            break;
+        }
+    }
+
+    obj_surface->size = ALIGN(region_width * region_height, 0x1000);
 
     if (tiled) {
         uint32_t tiling_mode = I915_TILING_Y; /* always uses Y-tiled format */
         unsigned long pitch;
-        unsigned long height;
-
-        if (fourcc == VA_FOURCC('I', 'M', 'C', '1') ||
-            fourcc == VA_FOURCC('I', 'M', 'C', '3'))
-            height = ALIGN(obj_surface->height, 32) + ALIGN(obj_surface->height / 2, 32) * 2;
-        else
-            height = ALIGN(obj_surface->height, 32) + ALIGN(obj_surface->height / 2, 32);
 
         obj_surface->bo = drm_intel_bo_alloc_tiled(i965->intel.bufmgr, 
                                                    "vaapi surface",
-                                                   obj_surface->width,
-                                                   height,
+                                                   region_width,
+                                                   region_height,
                                                    1,
                                                    &tiling_mode,
                                                    &pitch,
@@ -2112,6 +2207,7 @@ i965_check_alloc_surface_bo(VADriverContextP ctx,
     }
 
     obj_surface->fourcc = fourcc;
+    obj_surface->subsampling = subsampling;
     assert(obj_surface->bo);
 }
 
@@ -2132,7 +2228,7 @@ 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'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, HAS_TILED_SURFACE(i965), VA_FOURCC('N', 'V', '1', '2'), SUBSAMPLE_YUV420);
 
     w_pitch = obj_surface->width;
     h_pitch = obj_surface->height;
index 0410c34..4f2873c 100644 (file)
@@ -199,6 +199,14 @@ struct object_surface
     VAImageID locked_image_id;
     void (*free_private_data)(void **data);
     void *private_data;
+    unsigned int subsampling;
+    int x_cb_offset;
+    int y_cb_offset;
+    int x_cr_offset;
+    int y_cr_offset;
+    int cb_cr_width;
+    int cb_cr_height;
+    int cb_cr_pitch;
 };
 
 struct object_buffer 
@@ -292,6 +300,7 @@ void
 i965_check_alloc_surface_bo(VADriverContextP ctx,
                             struct object_surface *obj_surface,
                             int tiled,
-                            unsigned int fourcc);
+                            unsigned int fourcc,
+                            unsigned int subsampling);
 
 #endif /* _I965_DRV_VIDEO_H_ */
index 1d87d9b..9278ab7 100644 (file)
@@ -514,7 +514,7 @@ i965_media_mpeg2_surface_setup(VADriverContextP ctx,
     int w = obj_surface->width;
     int h = obj_surface->height;
 
-    i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('I','4','2','0'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('I','4','2','0'), SUBSAMPLE_YUV420);
 
     if (picture_structure == MPEG_FRAME) {
        i965_media_mpeg2_surface_state(ctx, base_index + 0, obj_surface,
index a7a6409..63db076 100644 (file)
@@ -3377,7 +3377,7 @@ i965_post_processing(
                                          &out_surface_id);
             assert(status == VA_STATUS_SUCCESS);
             obj_surface = SURFACE(out_surface_id);
-            i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('N','V','1','2'));
+            i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
 
             src_surface.id = in_surface_id;
             src_surface.type = I965_SURFACE_TYPE_SURFACE;
@@ -3411,7 +3411,7 @@ i965_post_processing(
                                          &out_surface_id);
             assert(status == VA_STATUS_SUCCESS);
             obj_surface = SURFACE(out_surface_id);
-            i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('N','V','1','2'));
+            i965_check_alloc_surface_bo(ctx, obj_surface, 0, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
 
             src_surface.id = in_surface_id;
             src_surface.type = I965_SURFACE_TYPE_SURFACE;
@@ -3757,7 +3757,7 @@ i965_proc_picture(VADriverContextP ctx,
         assert(status == VA_STATUS_SUCCESS);
         tmp_surfaces[num_tmp_surfaces++] = out_surface_id;
         obj_surface = SURFACE(out_surface_id);
-        i965_check_alloc_surface_bo(ctx, obj_surface, !!tiling, VA_FOURCC('N', 'V', '1', '2'));
+        i965_check_alloc_surface_bo(ctx, obj_surface, !!tiling, VA_FOURCC('N', 'V', '1', '2'), SUBSAMPLE_YUV420);
 
         dst_surface.id = out_surface_id;
         dst_surface.type = I965_SURFACE_TYPE_SURFACE;
@@ -3780,7 +3780,7 @@ i965_proc_picture(VADriverContextP ctx,
     }
 
     obj_surface = SURFACE(proc_state->current_render_target);
-    i965_check_alloc_surface_bo(ctx, obj_surface, !!tiling, VA_FOURCC('N','V','1','2'));
+    i965_check_alloc_surface_bo(ctx, obj_surface, !!tiling, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
     
     for (i = 0; i < VA_PROC_PIPELINE_MAX_NUM_FILTERS; i++) {
         VAProcFilterType filter_type = pipeline_param->filter_pipeline[i];
@@ -3800,7 +3800,7 @@ i965_proc_picture(VADriverContextP ctx,
             assert(status == VA_STATUS_SUCCESS);
             tmp_surfaces[num_tmp_surfaces++] = out_surface_id;
             obj_surface = SURFACE(out_surface_id);
-            i965_check_alloc_surface_bo(ctx, obj_surface, !!tiling, VA_FOURCC('N','V','1','2'));
+            i965_check_alloc_surface_bo(ctx, obj_surface, !!tiling, VA_FOURCC('N','V','1','2'), SUBSAMPLE_YUV420);
             dst_surface.id = out_surface_id;
             dst_surface.type = I965_SURFACE_TYPE_SURFACE;
             status = i965_post_processing_internal(ctx, &proc_context->pp_context,
index e01664c..0c2efb8 100644 (file)
@@ -757,53 +757,47 @@ i965_render_src_surfaces_state(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);  
     struct object_surface *obj_surface;
-    int w, h;
+    int region_pitch;
     int rw, rh;
     dri_bo *region;
 
     obj_surface = SURFACE(surface);
     assert(obj_surface);
 
-    w = obj_surface->width;
-    h = obj_surface->height;
+    region_pitch = obj_surface->width;
     rw = obj_surface->orig_width;
     rh = obj_surface->orig_height;
     region = obj_surface->bo;
 
-    i965_render_src_surface_state(ctx, 1, region, 0, rw, rh, w, I965_SURFACEFORMAT_R8_UNORM);     /* Y */
-    i965_render_src_surface_state(ctx, 2, region, 0, rw, rh, w, I965_SURFACEFORMAT_R8_UNORM);
-
-    if (obj_surface->fourcc == VA_FOURCC('Y','V','1','2')) {
-        int u3 = 5, u4 = 6, v5 = 3, v6 = 4;
-
-        i965_render_src_surface_state(ctx, u3, region, w * h, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM); /* U */
-        i965_render_src_surface_state(ctx, u4, region, w * h, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
-        i965_render_src_surface_state(ctx, v5, region, w * h + w * h / 4, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);     /* V */
-        i965_render_src_surface_state(ctx, v6, region, w * h + w * h / 4, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
-    } else if (obj_surface->fourcc == VA_FOURCC('I', 'M', 'C', '1')) {
-        int u3 = 5, u4 = 6, v5 = 3, v6 = 4;
-
-        i965_render_src_surface_state(ctx, u3, region, w * h, rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8_UNORM); /* U */
-        i965_render_src_surface_state(ctx, u4, region, w * h, rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8_UNORM);
-        i965_render_src_surface_state(ctx, v5, region, w * h + w * ALIGN(h / 2, 32), rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8_UNORM);     /* V */
-        i965_render_src_surface_state(ctx, v6, region, w * h + w * ALIGN(h / 2, 32), rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8_UNORM);
-    } else if (obj_surface->fourcc == VA_FOURCC('I', 'M', 'C', '3')) {
-        int u3 = 3, u4 = 4, v5 = 5, v6 = 6;
-
-        i965_render_src_surface_state(ctx, u3, region, w * h, rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8_UNORM); /* U */
-        i965_render_src_surface_state(ctx, u4, region, w * h, rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8_UNORM);
-        i965_render_src_surface_state(ctx, v5, region, w * h + w * ALIGN(h / 2, 32), rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8_UNORM);     /* V */
-        i965_render_src_surface_state(ctx, v6, region, w * h + w * ALIGN(h / 2, 32), rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8_UNORM);
-    } else if (obj_surface->fourcc == VA_FOURCC('N','V','1','2')) {
-        i965_render_src_surface_state(ctx, 3, region, w * h, rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8G8_UNORM); /* UV */
-        i965_render_src_surface_state(ctx, 4, region, w * h, rw / 2, rh / 2, w, I965_SURFACEFORMAT_R8G8_UNORM);
+    i965_render_src_surface_state(ctx, 1, region, 0, rw, rh, region_pitch, I965_SURFACEFORMAT_R8_UNORM);     /* Y */
+    i965_render_src_surface_state(ctx, 2, region, 0, rw, rh, region_pitch, I965_SURFACEFORMAT_R8_UNORM);
+
+    if (obj_surface->fourcc == VA_FOURCC('N', 'V', '1', '2')) {
+        i965_render_src_surface_state(ctx, 3, region,
+                                      region_pitch * obj_surface->y_cb_offset,
+                                      obj_surface->cb_cr_width, obj_surface->cb_cr_height, obj_surface->cb_cr_pitch,
+                                      I965_SURFACEFORMAT_R8G8_UNORM); /* UV */
+        i965_render_src_surface_state(ctx, 4, region,
+                                      region_pitch * obj_surface->y_cb_offset,
+                                      obj_surface->cb_cr_width, obj_surface->cb_cr_height, obj_surface->cb_cr_pitch,
+                                      I965_SURFACEFORMAT_R8G8_UNORM);
     } else {
-        int u3 = 3, u4 = 4, v5 = 5, v6 = 6;
-        
-        i965_render_src_surface_state(ctx, u3, region, w * h, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM); /* U */
-        i965_render_src_surface_state(ctx, u4, region, w * h, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
-        i965_render_src_surface_state(ctx, v5, region, w * h + w * h / 4, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);     /* V */
-        i965_render_src_surface_state(ctx, v6, region, w * h + w * h / 4, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
+        i965_render_src_surface_state(ctx, 3, region,
+                                      region_pitch * obj_surface->y_cb_offset,
+                                      obj_surface->cb_cr_width, obj_surface->cb_cr_height, obj_surface->cb_cr_pitch,
+                                      I965_SURFACEFORMAT_R8_UNORM); /* U */
+        i965_render_src_surface_state(ctx, 4, region,
+                                      region_pitch * obj_surface->y_cb_offset,
+                                      obj_surface->cb_cr_width, obj_surface->cb_cr_height, obj_surface->cb_cr_pitch,
+                                      I965_SURFACEFORMAT_R8_UNORM);
+        i965_render_src_surface_state(ctx, 5, region,
+                                      region_pitch * obj_surface->y_cr_offset,
+                                      obj_surface->cb_cr_width, obj_surface->cb_cr_height, obj_surface->cb_cr_pitch,
+                                      I965_SURFACEFORMAT_R8_UNORM); /* V */
+        i965_render_src_surface_state(ctx, 6, region,
+                                      region_pitch * obj_surface->y_cr_offset,
+                                      obj_surface->cb_cr_width, obj_surface->cb_cr_height, obj_surface->cb_cr_pitch,
+                                      I965_SURFACEFORMAT_R8_UNORM);
     }
 }