[Libva] [Driver PATCH 4/5] support vaGetSurfaceBufferWl

Zhao Halley halley.zhao at intel.com
Tue Jun 5 02:12:11 PDT 2012


From: Zhao halley <halley.zhao at intel.com>

---
 src/i965_drv_video.c      |    5 +
 src/i965_render_wayland.c |  313 ++++++++++++++++-----------------------------
 src/i965_render_wayland.h |    2 +
 3 files changed, 117 insertions(+), 203 deletions(-)

diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
index 79f96f3..daa972e 100755
--- a/src/i965_drv_video.c
+++ b/src/i965_drv_video.c
@@ -3206,6 +3206,11 @@ i965_Terminate(VADriverContextP ctx)
     if (i965_post_processing_terminate(ctx) == False)
         return VA_STATUS_ERROR_UNKNOWN;
 
+#if USE_WAYLAND
+    if (i965_render_wayland_terminate(ctx) == False)
+        return VA_STATUS_ERROR_UNKNOWN;
+#endif
+
     if (intel_driver_terminate(ctx) == False)
         return VA_STATUS_ERROR_UNKNOWN;
 
diff --git a/src/i965_render_wayland.c b/src/i965_render_wayland.c
index 26d7ba0..7d09a77 100755
--- a/src/i965_render_wayland.c
+++ b/src/i965_render_wayland.c
@@ -35,162 +35,23 @@
 
 #define VA_WL_FORMAT_RGBA (WL_DRM_FORMAT_XRGB8888)
 
-struct va_wl_surface {
-    struct wl_drm      *wl_drm;
-    struct wl_surface  *wl_surface;
-    struct wl_buffer   *wl_buffer;
-    struct intel_region region;
-    unsigned int        name;
-    unsigned int        format;
-    unsigned int        width;
-    unsigned int        height;
-};
-
-static void
-va_surface_reset_buffer(
+static bool
+i965_draw_region_reset(
     VADriverContextP      ctx,
-    struct va_wl_surface *va_wl_surface
+    struct object_surface *obj_surface
 )
 {
-    struct intel_region * const region = &va_wl_surface->region;
-
-    if (va_wl_surface->wl_buffer) {
-#if 0
-        /* XXX: automatically destroyed on next wl_surface_attach()? */
-        wl_buffer_destroy(va_wl_surface->wl_buffer);
-#endif
-        va_wl_surface->wl_buffer = NULL;
-    }
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct i965_render_state * const render_state = &i965->render_state;
+    struct intel_region *region = render_state->draw_region;
+    struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
 
     if (region->bo) {
         dri_bo_unreference(region->bo);
         region->bo = NULL;
     }
 
-    va_wl_surface->name   = 0;
-    va_wl_surface->format = 0;
-    va_wl_surface->width  = 0;
-    va_wl_surface->height = 0;
     memset(region, 0, sizeof(*region));
-}
-
-static VAStatus
-va_wayland_create_surface(
-    VADriverContextP       ctx,
-    struct wl_surface     *wl_surface,
-    struct va_wl_surface **out_va_wl_surface
-)
-{
-    struct va_wl_surface *va_wl_surface;
-    uint32_t id;
-
-    if (ctx->display_type != VA_DISPLAY_WAYLAND)
-        return VA_STATUS_ERROR_INVALID_DISPLAY;
-    if (!wl_surface)
-        return VA_STATUS_ERROR_INVALID_SURFACE;
-    if (!out_va_wl_surface)
-        return VA_STATUS_ERROR_INVALID_PARAMETER;
-
-    va_wl_surface = calloc(1, sizeof(*va_wl_surface));
-    if (!va_wl_surface)
-        return VA_STATUS_ERROR_ALLOCATION_FAILED;
-
-    id = wl_display_get_global(ctx->native_dpy, "wl_drm", 1);
-    if (!id) {
-        wl_display_roundtrip(ctx->native_dpy);
-        id = wl_display_get_global(ctx->native_dpy, "wl_drm", 1);
-        if (!id)
-            return VA_STATUS_ERROR_INVALID_DISPLAY;
-    }
-
-    va_wl_surface->wl_drm =
-        wl_display_bind(ctx->native_dpy, id, &wl_drm_interface);
-    if (!va_wl_surface->wl_drm)
-        return VA_STATUS_ERROR_INVALID_DISPLAY;
-
-    va_wl_surface->wl_surface   = wl_surface;
-    va_wl_surface->wl_buffer    = NULL;
-    va_wl_surface->format       = 0;
-    va_wl_surface->width        = 0;
-    va_wl_surface->height       = 0;
-
-    *out_va_wl_surface = va_wl_surface;
-    return VA_STATUS_SUCCESS;
-}
-
-static VAStatus
-va_wayland_destroy_surface(
-    VADriverContextP       ctx,
-    struct va_wl_surface  *va_wl_surface
-)
-{
-    if (ctx->display_type != VA_DISPLAY_WAYLAND)
-        return VA_STATUS_ERROR_INVALID_DISPLAY;
-    if (!va_wl_surface)
-        return VA_STATUS_ERROR_INVALID_SURFACE;
-
-    va_surface_reset_buffer(ctx, va_wl_surface);
-
-    if (va_wl_surface->wl_drm) {
-        wl_drm_destroy(va_wl_surface->wl_drm);
-        va_wl_surface->wl_drm = NULL;
-    }
-
-    free(va_wl_surface);
-    return VA_STATUS_SUCCESS;
-}
-
-static VAStatus
-va_surface_relink_buffer(
-    VADriverContextP      ctx,
-    struct va_wl_surface *va_wl_surface
-)
-{
-    struct i965_driver_data * const i965 = i965_driver_data(ctx);
-    struct i965_render_state * const render_state = &i965->render_state;
-    struct intel_region *region = render_state->draw_region;
-    uint32_t name;
-
-    if (region) {
-        if (!region->bo || dri_bo_flink(region->bo, &name) != 0)
-            return VA_STATUS_ERROR_INVALID_BUFFER;
-
-        if (name != va_wl_surface->name) {
-            dri_bo_unreference(region->bo);
-            region->bo = NULL;
-        }
-    }
-    else {
-        region = calloc(1, sizeof(*region));
-        if (!region)
-            return VA_STATUS_ERROR_ALLOCATION_FAILED;
-        render_state->draw_region = region;
-    }
-
-    if (!region->bo) {
-        *region = va_wl_surface->region;
-
-        region->bo = intel_bo_gem_create_from_name(
-            i965->intel.bufmgr,
-            "render buffer",
-            va_wl_surface->name
-        );
-        assert(region->bo);
-        if (!region->bo)
-            return VA_STATUS_ERROR_ALLOCATION_FAILED;
-    }
-    return VA_STATUS_SUCCESS;
-}
-
-static bool
-va_surface_create_buffer_rgb(
-    VADriverContextP       ctx,
-    struct va_wl_surface  *va_wl_surface,
-    struct object_surface *obj_surface
-)
-{
-    struct i965_driver_data * const i965 = i965_driver_data(ctx);
-    struct intel_region * const region = &va_wl_surface->region;
 
     region->x           = 0;
     region->y           = 0;
@@ -209,45 +70,46 @@ va_surface_create_buffer_rgb(
         return false;
 
     dri_bo_get_tiling(region->bo, &region->tiling, &region->swizzle);
-    if (dri_bo_flink(region->bo, &va_wl_surface->name) != 0) {
+
+    if (dri_bo_flink(region->bo, &vtable->name) != 0) {
         fprintf(stderr, "libva: error: flink failed for bo %p\n", region->bo);
         return false;
     }
-
-    va_wl_surface->format = VA_WL_FORMAT_RGBA;
-    va_wl_surface->width  = obj_surface->orig_width;
-    va_wl_surface->height = obj_surface->orig_height;
+    
     return true;
 }
 
 static VAStatus
-va_attach_rgb_surface(
+i965_render_surface_rgb(
     VADriverContextP       ctx,
-    struct va_wl_surface  *va_wl_surface,
     struct object_surface *obj_surface,
     unsigned int           flags
 )
 {
-    struct intel_region * const region = &va_wl_surface->region;
     VAStatus va_status;
     VASurfaceID va_surface;
     VARectangle src_rect, dst_rect;
     unsigned int pp_flags;
+    
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct i965_render_state * const render_state = &i965->render_state;
+    struct intel_region *region = render_state->draw_region;
+
+    if (!region) {    
+        region = calloc(1, sizeof(*region));
+        if (!region)
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
+        render_state->draw_region = region;
+    }
 
     /* Check local buffer */
-    if (va_wl_surface->format != VA_WL_FORMAT_RGBA        ||
-        va_wl_surface->width  != obj_surface->orig_width  ||
-        va_wl_surface->height != obj_surface->orig_height) {
-        va_surface_reset_buffer(ctx, va_wl_surface);
-        if (!va_surface_create_buffer_rgb(ctx, va_wl_surface, obj_surface))
+    if (region->width  != obj_surface->orig_width  ||
+        region->height != obj_surface->orig_height) {
+        if (!i965_draw_region_reset(ctx, obj_surface))
             return VA_STATUS_ERROR_ALLOCATION_FAILED;
     }
     assert(region->bo);
 
-    /* Check buffer link */
-    va_status = va_surface_relink_buffer(ctx, va_wl_surface);
-    if (va_status != VA_STATUS_SUCCESS)
-        return va_status;
 
     /* Render to RGBA surface */
     va_surface      = obj_surface->base.id;
@@ -272,45 +134,55 @@ va_attach_rgb_surface(
 }
 
 static VAStatus
-va_wayland_attach_surface_unlocked(
+i965_wayland_get_buffer_unlocked(
     VADriverContextP       ctx,
-    struct va_wl_surface  *va_wl_surface,
     struct object_surface *obj_surface,
-    unsigned int           flags
-)
+    struct wl_buffer **out_buffer
+    )
 {
     VAStatus va_status;
-
-    va_status = va_attach_rgb_surface(ctx, va_wl_surface, obj_surface, flags);
+    struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
+    int format = 0;
+
+    // XXXX todo
+    switch (obj_surface->fourcc) {
+    case VA_FOURCC_NV12:
+        
+        break;
+    default:
+        break;
+    }
+        
+#if 1
+    // todo, when YUV buffer is supported in weston/mesa, we can skip color conversion here
+    format = VA_WL_FORMAT_RGBA;
+    va_status = i965_render_surface_rgb(ctx, obj_surface, 0); // set flags to 0
     if (va_status != VA_STATUS_SUCCESS)
         return va_status;
-
-    if (!va_wl_surface->wl_buffer) {
-        va_wl_surface->wl_buffer = wl_drm_create_buffer(
-            va_wl_surface->wl_drm,
-            va_wl_surface->name,
-            va_wl_surface->width,
-            va_wl_surface->height,
-            va_wl_surface->region.pitch,
-            va_wl_surface->format
-        );
-        if (!va_wl_surface->wl_buffer)
-            return VA_STATUS_ERROR_ALLOCATION_FAILED;
-
-        wl_surface_attach(
-            va_wl_surface->wl_surface,
-            va_wl_surface->wl_buffer,
-            0, 0
+#endif    
+
+    // always create a new wl_buffer, right?
+    // todo, consider YUV format here
+    struct wl_buffer   *buffer;
+    buffer = wl_drm_create_buffer(
+        vtable->wl_drm, 
+        vtable->name, 
+        obj_surface->orig_width, 
+        obj_surface->orig_height,
+        obj_surface->width*4,
+        format
         );
+    if (!buffer) {
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
     }
+    *out_buffer = buffer;
 
-    wl_surface_damage(
-        va_wl_surface->wl_surface,
-        0, 0, va_wl_surface->width, va_wl_surface->height
-    );
-
-    obj_surface->flags |= SURFACE_DISPLAYED;
+    // todo, should we add new API to let app set this flag up?
+    // obj_surface->flags |= SURFACE_DISPLAYED;
 
+    // who is responsible for releasing this bo?
+    // for YUV buffer, we'd comment it out
+    #if 1
     if ((obj_surface->flags & SURFACE_ALL_MASK) == SURFACE_DISPLAYED) {
         dri_bo_unreference(obj_surface->bo);
         obj_surface->bo = NULL;
@@ -319,15 +191,16 @@ va_wayland_attach_surface_unlocked(
         if (obj_surface->free_private_data)
             obj_surface->free_private_data(&obj_surface->private_data);
     }
+    #endif
+    
     return VA_STATUS_SUCCESS;
 }
 
 static VAStatus
-va_wayland_attach_surface(
+i965_wayland_get_buffer(
     VADriverContextP       ctx,
-    struct va_wl_surface  *va_wl_surface,
     VASurfaceID            va_surface,
-    unsigned int           flags
+    struct wl_buffer       **out_buffer
 )
 {
     struct i965_driver_data * const i965 = i965_driver_data(ctx);
@@ -336,28 +209,59 @@ va_wayland_attach_surface(
 
     if (ctx->display_type != VA_DISPLAY_WAYLAND)
         return VA_STATUS_ERROR_INVALID_DISPLAY;
-    if (!va_wl_surface)
-        return VA_STATUS_ERROR_INVALID_SURFACE;
 
     obj_surface = SURFACE(va_surface);
     if (!obj_surface || !obj_surface->bo)
         return VA_STATUS_ERROR_INVALID_SURFACE;
 
     _i965LockMutex(&i965->render_mutex);
-    va_status = va_wayland_attach_surface_unlocked(
+    va_status = i965_wayland_get_buffer_unlocked(
         ctx,
-        va_wl_surface,
         obj_surface,
-        flags
+        out_buffer
     );
+
     _i965UnlockMutex(&i965->render_mutex);
     return va_status;
 }
 
+
 bool
 i965_render_wayland_init(VADriverContextP ctx)
 {
     struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
+    uint32_t id;
+
+    if (ctx->display_type != VA_DISPLAY_WAYLAND)
+        return true;
+
+    if (!vtable)
+        return false;
+
+    vtable->wl_drm              = NULL;
+    vtable->name                = 0;
+    vtable->vaGetSurfaceBufferWl   = i965_wayland_get_buffer;
+
+    id = wl_display_get_global(ctx->native_dpy, "wl_drm", 1);
+    if (!id) {
+        wl_display_roundtrip(ctx->native_dpy);
+        id = wl_display_get_global(ctx->native_dpy, "wl_drm", 1);
+        if (!id)
+            return VA_STATUS_ERROR_INVALID_DISPLAY;
+    }
+
+    vtable->wl_drm =
+        wl_display_bind(ctx->native_dpy, id, &wl_drm_interface);
+    if (!vtable->wl_drm)
+        return VA_STATUS_ERROR_INVALID_DISPLAY;
+    return true;
+}
+
+// todo, I can't find a deinit func in i965_drv_video.c to call it. 
+bool
+i965_render_wayland_terminate(VADriverContextP ctx)
+{
+    struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
 
     if (ctx->display_type != VA_DISPLAY_WAYLAND)
         return true;
@@ -365,8 +269,11 @@ i965_render_wayland_init(VADriverContextP ctx)
     if (!vtable)
         return false;
 
-    vtable->vaCreateSurfaceWL   = va_wayland_create_surface;
-    vtable->vaDestroySurfaceWL  = va_wayland_destroy_surface;
-    vtable->vaAttachSurfaceWL   = va_wayland_attach_surface;
+    if (vtable->wl_drm) {
+        wl_drm_destroy(vtable->wl_drm);
+        vtable->wl_drm = NULL;
+    }
+
     return true;
 }
+
diff --git a/src/i965_render_wayland.h b/src/i965_render_wayland.h
index 1418c71..b65e954 100755
--- a/src/i965_render_wayland.h
+++ b/src/i965_render_wayland.h
@@ -29,5 +29,7 @@
 
 bool
 i965_render_wayland_init(VADriverContextP ctx);
+bool
+i965_render_wayland_terminate(VADriverContextP ctx);
 
 #endif /* I965_RENDER_WAYLAND_H */
-- 
1.7.5.4



More information about the Libva mailing list