i965_drv_video: Implement vaDeriveImage()
authorXiang, Haihao <haihao.xiang@intel.com>
Thu, 10 Mar 2011 02:26:23 +0000 (10:26 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Thu, 10 Mar 2011 05:10:36 +0000 (13:10 +0800)
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
i965_drv_video/gen6_mfd.c
i965_drv_video/i965_avc_bsd.c
i965_drv_video/i965_drv_video.c
i965_drv_video/i965_drv_video.h
i965_drv_video/i965_render.c

index 0265687..3b178c2 100644 (file)
@@ -85,10 +85,10 @@ gen6_mfd_avc_frame_store_index(VADriverContextP ctx, VAPictureParameterBufferH26
             struct object_surface *obj_surface = SURFACE(gen6_mfd_context->reference_surface[i].surface_id);
             obj_surface->flags &= ~SURFACE_REFERENCED;
 
-            if (obj_surface->flags & SURFACE_DISPLAYED) {
+            if ((obj_surface->flags & SURFACE_ALL_MASK) == SURFACE_DISPLAYED) {
                 dri_bo_unreference(obj_surface->bo);
                 obj_surface->bo = NULL;
-                obj_surface->flags = 0;
+                obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
             }
 
             if (obj_surface->free_private_data)
@@ -1039,7 +1039,8 @@ gen6_mfd_avc_decode_init(VADriverContextP ctx, struct decode_state *decode_state
     assert(!(va_pic->flags & VA_PICTURE_H264_INVALID));
     obj_surface = SURFACE(va_pic->picture_id);
     assert(obj_surface);
-    obj_surface->flags = (pic_param->pic_fields.bits.reference_pic_flag ? SURFACE_REFERENCED : 0);
+    obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
+    obj_surface->flags |= (pic_param->pic_fields.bits.reference_pic_flag ? SURFACE_REFERENCED : 0);
     gen6_mfd_init_avc_surface(ctx, pic_param, obj_surface);
 
     if (obj_surface->bo == NULL) {
index 0976439..89bd169 100644 (file)
@@ -507,7 +507,8 @@ i965_avc_bsd_buf_base_state(VADriverContextP ctx,
     assert(!(va_pic->flags & VA_PICTURE_H264_INVALID));
     obj_surface = SURFACE(va_pic->picture_id);
     assert(obj_surface);
-    obj_surface->flags = (pic_param->pic_fields.bits.reference_pic_flag ? SURFACE_REFERENCED : 0);
+    obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
+    obj_surface->flags |= (pic_param->pic_fields.bits.reference_pic_flag ? SURFACE_REFERENCED : 0);
     i965_avc_bsd_init_avc_bsd_surface(ctx, obj_surface, pic_param);
     avc_bsd_surface = obj_surface->private_data;
 
@@ -922,10 +923,10 @@ i965_avc_bsd_frame_store_index(VADriverContextP ctx,
             struct object_surface *obj_surface = SURFACE(i965_h264_context->fsid_list[i].surface_id);
             obj_surface->flags &= ~SURFACE_REFERENCED;
 
-            if (obj_surface->flags & SURFACE_DISPLAYED) {
+            if ((obj_surface->flags & SURFACE_ALL_MASK) == SURFACE_DISPLAYED) {
                 dri_bo_unreference(obj_surface->bo);
                 obj_surface->bo = NULL;
-                obj_surface->flags = 0;
+                obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
             }
 
             if (obj_surface->free_private_data)
index 68cfbf1..0c8c1be 100644 (file)
@@ -57,6 +57,8 @@
                          (IS_IRONLAKE((ctx)->intel.device_id) && \
                           (ctx)->intel.has_bsd))
 
+#define HAS_TILED_SURFACE(ctx) (IS_GEN6((ctx)->intel.device_id))
+
 enum {
     I965_SURFACETYPE_RGBA = 1,
     I965_SURFACETYPE_YUV,
@@ -838,14 +840,15 @@ i965_destroy_buffer(struct object_heap *heap, struct object_base *obj)
     object_heap_free(heap, obj);
 }
 
-VAStatus 
-i965_CreateBuffer(VADriverContextP ctx,
-                  VAContextID context,          /* in */
-                  VABufferType type,            /* in */
-                  unsigned int size,            /* in */
-                  unsigned int num_elements,    /* in */
-                  void *data,                   /* in */
-                  VABufferID *buf_id)           /* out */
+static VAStatus
+i965_create_buffer_internal(VADriverContextP ctx,
+                            VAContextID context,
+                            VABufferType type,
+                            unsigned int size,
+                            unsigned int num_elements,
+                            void *data,
+                            dri_bo *store_bo,
+                            VABufferID *buf_id)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_buffer *obj_buffer = NULL;
@@ -887,7 +890,13 @@ i965_CreateBuffer(VADriverContextP ctx,
     assert(buffer_store);
     buffer_store->ref_count = 1;
 
-    if (type == VASliceDataBufferType || type == VAImageBufferType) {
+    if (store_bo != NULL) {
+        buffer_store->bo = store_bo;
+        dri_bo_reference(buffer_store->bo);
+        
+        if (data)
+            dri_bo_subdata(buffer_store->bo, 0, size * num_elements, data);
+    } else if (type == VASliceDataBufferType || type == VAImageBufferType) {
         buffer_store->bo = dri_bo_alloc(i965->intel.bufmgr, 
                                         "Buffer", 
                                         size * num_elements, 64);
@@ -911,6 +920,18 @@ i965_CreateBuffer(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
+VAStatus 
+i965_CreateBuffer(VADriverContextP ctx,
+                  VAContextID context,          /* in */
+                  VABufferType type,            /* in */
+                  unsigned int size,            /* in */
+                  unsigned int num_elements,    /* in */
+                  void *data,                   /* in */
+                  VABufferID *buf_id)           /* out */
+{
+    return i965_create_buffer_internal(ctx, context, type, size, num_elements, data, NULL, buf_id);
+}
+
 
 VAStatus 
 i965_BufferSetNumElements(VADriverContextP ctx,
@@ -1252,6 +1273,18 @@ i965_QuerySurfaceStatus(VADriverContextP ctx,
     struct object_surface *obj_surface = SURFACE(render_target);
 
     assert(obj_surface);
+
+    /* Commit pending operations to the HW */
+    intel_batchbuffer_flush(ctx);
+
+    /* Usually GEM will handle synchronization with the graphics hardware */
+#if 0
+    if (obj_surface->bo) {
+        dri_bo_map(obj_surface->bo, 0);
+        dri_bo_unmap(obj_surface->bo);
+    }
+#endif
+    
     *status = obj_surface->status;
 
     return VA_STATUS_SUCCESS;
@@ -1385,6 +1418,7 @@ i965_CreateImage(VADriverContextP ctx,
         return VA_STATUS_ERROR_ALLOCATION_FAILED;
     obj_image->bo         = NULL;
     obj_image->palette    = NULL;
+    obj_image->derived_surface = VA_INVALID_ID;
 
     VAImage * const image = &obj_image->image;
     image->image_id       = image_id;
@@ -1459,6 +1493,7 @@ i965_CreateImage(VADriverContextP ctx,
         goto error;
 
     obj_image->bo = BUFFER(image->buf)->buffer_store->bo;
+    dri_bo_reference(obj_image->bo);
 
     if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
         obj_image->palette = malloc(image->num_palette_entries * sizeof(obj_image->palette));
@@ -1481,10 +1516,125 @@ error:
 
 VAStatus i965_DeriveImage(VADriverContextP ctx,
                           VASurfaceID surface,
-                          VAImage *image)        /* out */
+                          VAImage *out_image)        /* out */
 {
-    /* TODO */
-    return VA_STATUS_ERROR_OPERATION_FAILED;
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct i965_render_state *render_state = &i965->render_state;
+    struct object_image *obj_image;
+    struct object_surface *obj_surface; 
+    VAImageID image_id;
+    unsigned int w_pitch, h_pitch;
+    unsigned int data_size;
+    VAStatus va_status;
+
+    out_image->image_id = VA_INVALID_ID;
+    obj_surface = SURFACE(surface);
+
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    w_pitch = obj_surface->width;
+    h_pitch = obj_surface->height;
+    data_size = obj_surface->orig_width * obj_surface->orig_height +
+        2 * (((obj_surface->orig_width + 1) / 2) * ((obj_surface->orig_height + 1) / 2));
+
+    image_id = NEW_IMAGE_ID();
+
+    if (image_id == VA_INVALID_ID)
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
+
+    obj_image = IMAGE(image_id);
+    
+    if (!obj_image)
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
+
+    obj_image->bo = NULL;
+    obj_image->palette = NULL;
+    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;
+    image->num_palette_entries = 0;
+    image->entry_bytes = 0;
+    image->width = obj_surface->orig_width;
+    image->height = obj_surface->orig_height;
+    image->data_size = data_size;
+
+    if (render_state->interleaved_uv) {
+        image->format.fourcc = VA_FOURCC('N','V','1','2');
+        image->format.byte_order = VA_LSB_FIRST;
+        image->format.bits_per_pixel = 12;
+        image->num_planes = 2;
+        image->pitches[0] = w_pitch;
+        image->offsets[0] = 0;
+        image->pitches[1] = w_pitch;
+        image->offsets[1] = w_pitch * h_pitch;
+    } else {
+        image->format.fourcc = VA_FOURCC('Y','V','1','2');
+        image->format.byte_order = VA_LSB_FIRST;
+        image->format.bits_per_pixel = 12;
+        image->num_planes = 3;
+        image->pitches[0] = w_pitch;
+        image->offsets[0] = 0;
+        image->pitches[1] = w_pitch / 2;
+        image->offsets[1] = w_pitch * h_pitch;
+        image->pitches[2] = w_pitch / 2;
+        image->offsets[2] = w_pitch * h_pitch + (w_pitch / 2) * (h_pitch / 2);
+    }
+
+    if (obj_surface->bo == NULL) {
+        if (HAS_TILED_SURFACE(i965)) {
+        
+            uint32_t tiling_mode = I915_TILING_Y;
+            unsigned long pitch;
+
+            obj_surface->bo = drm_intel_bo_alloc_tiled(i965->intel.bufmgr, 
+                                                       "vaapi surface",
+                                                       obj_surface->width, 
+                                                       obj_surface->height + obj_surface->height / 2,
+                                                       1,
+                                                       &tiling_mode,
+                                                       &pitch,
+                                                       0);
+            assert(obj_surface->bo);
+            assert(tiling_mode == I915_TILING_Y);
+            assert(pitch == obj_surface->width);
+        } else {
+            obj_surface->bo = dri_bo_alloc(i965->intel.bufmgr,
+                                           "vaapi surface",
+                                           obj_surface->size,
+                                           0x1000);
+        }
+    }
+
+    assert(obj_surface->bo);
+    va_status = i965_create_buffer_internal(ctx, 0, VAImageBufferType,
+                                            obj_surface->size, 1, NULL, obj_surface->bo, &image->buf);
+    if (va_status != VA_STATUS_SUCCESS)
+        goto error;
+
+    obj_image->bo = BUFFER(image->buf)->buffer_store->bo;
+    dri_bo_reference(obj_image->bo);
+
+    if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
+        obj_image->palette = malloc(image->num_palette_entries * sizeof(obj_image->palette));
+        if (!obj_image->palette) {
+            va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
+            goto error;
+        }
+    }
+
+    *out_image = *image;
+    obj_surface->flags |= SURFACE_DERIVED;
+
+    return VA_STATUS_SUCCESS;
+
+error:
+    i965_DestroyImage(ctx, image_id);
+    return va_status;
 }
 
 static void 
@@ -1499,10 +1649,14 @@ 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; 
 
     if (!obj_image)
         return VA_STATUS_SUCCESS;
 
+    dri_bo_unreference(obj_image->bo);
+    obj_image->bo = NULL;
+
     if (obj_image->image.buf != VA_INVALID_ID) {
         i965_DestroyBuffer(ctx, obj_image->image.buf);
         obj_image->image.buf = VA_INVALID_ID;
@@ -1513,6 +1667,12 @@ i965_DestroyImage(VADriverContextP ctx, VAImageID image)
         obj_image->palette = NULL;
     }
 
+    obj_surface = SURFACE(obj_image->derived_surface);
+
+    if (obj_surface) {
+        obj_surface->flags &= ~SURFACE_DERIVED;
+    }
+
     i965_destroy_image(&i965->image_heap, (struct object_base *)obj_image);
        
     return VA_STATUS_SUCCESS;
@@ -1831,10 +1991,10 @@ i965_PutSurface(VADriverContextP ctx,
     dri_swap_buffer(ctx, dri_drawable);
     obj_surface->flags |= SURFACE_DISPLAYED;
 
-    if (!(obj_surface->flags & SURFACE_REFERENCED)) {
+    if ((obj_surface->flags & SURFACE_ALL_MASK) == SURFACE_DISPLAYED) {
         dri_bo_unreference(obj_surface->bo);
         obj_surface->bo = NULL;
-        obj_surface->flags = 0;
+        obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
 
         if (obj_surface->free_private_data)
             obj_surface->free_private_data(&obj_surface->private_data);
index 7fc9cdb..a62e472 100644 (file)
@@ -96,6 +96,12 @@ struct object_context
 
 #define SURFACE_REFERENCED      (1 << 0)
 #define SURFACE_DISPLAYED       (1 << 1)
+#define SURFACE_DERIVED         (1 << 2)
+#define SURFACE_REF_DIS_MASK    ((SURFACE_REFERENCED) | \
+                                 (SURFACE_DISPLAYED))
+#define SURFACE_ALL_MASK        ((SURFACE_REFERENCED) | \
+                                 (SURFACE_DISPLAYED) |  \
+                                 (SURFACE_DERIVED))
 
 struct object_surface 
 {
@@ -134,6 +140,7 @@ struct object_image
     VAImage image;
     dri_bo *bo;
     unsigned int *palette;
+    VASurfaceID derived_surface;
 };
 
 struct object_subpic 
index 91d183a..9a713f6 100644 (file)
@@ -685,10 +685,16 @@ i965_render_src_surfaces_state(VADriverContextP ctx,
         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);
     } else {
-        i965_render_src_surface_state(ctx, 3, region, w * h, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM); /* U */
-        i965_render_src_surface_state(ctx, 4, region, w * h, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
-        i965_render_src_surface_state(ctx, 5, region, w * h + w * h / 4, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);     /* V */
-        i965_render_src_surface_state(ctx, 6, region, w * h + w * h / 4, rw / 2, rh / 2, w / 2, I965_SURFACEFORMAT_R8_UNORM);
+        int u3 = 3, u4 = 4, v5 = 5, v6 = 6;
+
+        if (obj_surface->flags & SURFACE_DERIVED) {
+            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);
     }
 }