[Libva] [PATCH 1/2] Add vaPutImage() implementation.

Gwenole Beauchesne gb.devel at gmail.com
Mon Sep 5 06:22:13 PDT 2011


---
 src/i965_drv_video.c |  218 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 202 insertions(+), 16 deletions(-)

diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
index 906dfed..2052ecc 100644
--- a/src/i965_drv_video.c
+++ b/src/i965_drv_video.c
@@ -548,22 +548,6 @@ i965_QueryImageFormats(VADriverContextP ctx,
 }
 
 VAStatus 
-i965_PutImage(VADriverContextP ctx,
-              VASurfaceID surface,
-              VAImageID image,
-              int src_x,
-              int src_y,
-              unsigned int src_width,
-              unsigned int src_height,
-              int dest_x,
-              int dest_y,
-              unsigned int dest_width,
-              unsigned int dest_height)
-{
-    return VA_STATUS_SUCCESS;
-}
-
-VAStatus 
 i965_QuerySubpictureFormats(VADriverContextP ctx,
                             VAImageFormat *format_list,         /* out */
                             unsigned int *flags,                /* out */
@@ -2220,6 +2204,208 @@ i965_GetImage(VADriverContextP ctx,
     return va_status;
 }
 
+static void
+put_image_i420(struct object_surface *obj_surface,
+               const VARectangle *dst_rect,
+               struct object_image *obj_image, uint8_t *image_data,
+               const VARectangle *src_rect)
+{
+    uint8_t *dst[3], *src[3];
+    const int Y = 0;
+    const int U = obj_image->image.format.fourcc == obj_surface->fourcc ? 1 : 2;
+    const int V = obj_image->image.format.fourcc == obj_surface->fourcc ? 2 : 1;
+    unsigned int tiling, swizzle;
+
+    if (!obj_surface->bo)
+        return;
+
+    assert(obj_surface->fourcc);
+    assert(dst_rect->width == src_rect->width);
+    assert(dst_rect->height == src_rect->height);
+    dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_map_gtt(obj_surface->bo);
+    else
+        dri_bo_map(obj_surface->bo, 0);
+
+    if (!obj_surface->bo->virtual)
+        return;
+
+    /* Dest VA image has either I420 or YV12 format.
+       Source VA surface alway has I420 format */
+    dst[0] = (uint8_t *)obj_surface->bo->virtual;
+    src[Y] = image_data + obj_image->image.offsets[Y];
+    dst[1] = dst[0] + obj_surface->width * obj_surface->height;
+    src[U] = image_data + obj_image->image.offsets[U];
+    dst[2] = dst[1] + (obj_surface->width / 2) * (obj_surface->height / 2);
+    src[V] = image_data + obj_image->image.offsets[V];
+
+    /* Y plane */
+    dst[0] += dst_rect->y * obj_surface->width + dst_rect->x;
+    src[Y] += src_rect->y * obj_image->image.pitches[Y] + src_rect->x;
+    memcpy_pic(dst[0], obj_surface->width,
+               src[Y], obj_image->image.pitches[Y],
+               src_rect->width, src_rect->height);
+
+    /* U plane */
+    dst[1] += (dst_rect->y / 2) * obj_surface->width / 2 + dst_rect->x / 2;
+    src[U] += (src_rect->y / 2) * obj_image->image.pitches[U] + src_rect->x / 2;
+    memcpy_pic(dst[1], obj_surface->width / 2,
+               src[U], obj_image->image.pitches[U],
+               src_rect->width / 2, src_rect->height / 2);
+
+    /* V plane */
+    dst[2] += (dst_rect->y / 2) * obj_surface->width / 2 + dst_rect->x / 2;
+    src[V] += (src_rect->y / 2) * obj_image->image.pitches[V] + src_rect->x / 2;
+    memcpy_pic(dst[2], obj_surface->width / 2,
+               src[V], obj_image->image.pitches[V],
+               src_rect->width / 2, src_rect->height / 2);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
+    else
+        dri_bo_unmap(obj_surface->bo);
+}
+
+static void
+put_image_nv12(struct object_surface *obj_surface,
+               const VARectangle *dst_rect,
+               struct object_image *obj_image, uint8_t *image_data,
+               const VARectangle *src_rect)
+{
+    uint8_t *dst[2], *src[2];
+    unsigned int tiling, swizzle;
+
+    if (!obj_surface->bo)
+        return;
+
+    assert(obj_surface->fourcc);
+    assert(dst_rect->width == src_rect->width);
+    assert(dst_rect->height == src_rect->height);
+    dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_map_gtt(obj_surface->bo);
+    else
+        dri_bo_map(obj_surface->bo, 0);
+
+    if (!obj_surface->bo->virtual)
+        return;
+
+    /* Both dest VA image and source surface have NV12 format */
+    dst[0] = (uint8_t *)obj_surface->bo->virtual;
+    src[0] = image_data + obj_image->image.offsets[0];
+    dst[1] = dst[0] + obj_surface->width * obj_surface->height;
+    src[1] = image_data + obj_image->image.offsets[1];
+
+    /* Y plane */
+    dst[0] += dst_rect->y * obj_surface->width + dst_rect->x;
+    src[0] += src_rect->y * obj_image->image.pitches[0] + src_rect->x;
+    memcpy_pic(dst[0], obj_surface->width,
+               src[0], obj_image->image.pitches[0],
+               src_rect->width, src_rect->height);
+
+    /* UV plane */
+    dst[1] += (dst_rect->y / 2) * obj_surface->width + (dst_rect->x & -2);
+    src[1] += (src_rect->y / 2) * obj_image->image.pitches[1] + (src_rect->x & -2);
+    memcpy_pic(dst[1], obj_surface->width,
+               src[1], obj_image->image.pitches[1],
+               src_rect->width, src_rect->height / 2);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_unmap_gtt(obj_surface->bo);
+    else
+        dri_bo_unmap(obj_surface->bo);
+}
+
+VAStatus 
+i965_PutImage(VADriverContextP ctx,
+               VASurfaceID surface,
+               VAImageID image,
+               int src_x,
+               int src_y,
+               unsigned int src_width,
+               unsigned int src_height,
+               int dest_x,
+               int dest_y,
+               unsigned int dest_width,
+               unsigned int dest_height)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+
+    struct object_surface *obj_surface = SURFACE(surface);
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    struct object_image *obj_image = IMAGE(image);
+    if (!obj_image)
+        return VA_STATUS_ERROR_INVALID_IMAGE;
+
+    if (src_x < 0 || src_y < 0)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (src_x + src_width > obj_image->image.width ||
+        src_y + src_height > obj_image->image.height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (dest_x < 0 || dest_y < 0)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (dest_x + dest_width > obj_surface->orig_width ||
+        dest_y + dest_height > obj_surface->orig_height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    /* XXX: don't allow scaling */
+    if (src_width != dest_width || src_height != dest_height)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if (obj_surface->fourcc) {
+        /* Don't allow format mismatch */
+        if (obj_surface->fourcc != obj_image->image.format.fourcc)
+            return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
+    }
+    else {
+        /* VA is surface not used for decoding, use same VA image format */
+        i965_check_alloc_surface_bo(
+            ctx,
+            obj_surface,
+            0, /* XXX: don't use tiled surface */
+            obj_image->image.format.fourcc
+        );
+    }
+
+    VAStatus va_status;
+    void *image_data = NULL;
+
+    va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    VARectangle src_rect, dest_rect;
+    src_rect.x       = src_x;
+    src_rect.y       = src_y;
+    src_rect.width   = src_width;
+    src_rect.height  = src_height;
+    dest_rect.x      = dest_x;
+    dest_rect.y      = dest_y;
+    dest_rect.width  = dest_width;
+    dest_rect.height = dest_height;
+     
+    switch (obj_image->image.format.fourcc) {
+    case VA_FOURCC('Y','V','1','2'):
+    case VA_FOURCC('I','4','2','0'):
+        put_image_i420(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
+        break;
+    case VA_FOURCC('N','V','1','2'):
+        put_image_nv12(obj_surface, &dest_rect, obj_image, image_data, &src_rect);
+        break;
+    default:
+        va_status = VA_STATUS_ERROR_OPERATION_FAILED;
+        break;
+    }
+
+    i965_UnmapBuffer(ctx, obj_image->image.buf);
+    return va_status;
+}
+
 VAStatus 
 i965_PutSurface(VADriverContextP ctx,
                 VASurfaceID surface,
-- 
1.7.4.1



More information about the Libva mailing list