[vlc-devel] [PATCH 14/42] vdpau: RGBA subpicture blending for video output display

Rémi Denis-Courmont remi at remlab.net
Fri Jun 28 20:30:02 CEST 2013


---
 modules/hw/vdpau/display.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 99 insertions(+), 2 deletions(-)

diff --git a/modules/hw/vdpau/display.c b/modules/hw/vdpau/display.c
index 2d3ac97..e1e99b6 100644
--- a/modules/hw/vdpau/display.c
+++ b/modules/hw/vdpau/display.c
@@ -144,13 +144,90 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned requested_count)
     return sys->pool;
 }
 
-static void Queue(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
+static void RenderRegion(vout_display_t *vd, VdpOutputSurface target,
+                         const subpicture_region_t *reg, int alpha)
+{
+    vout_display_sys_t *sys = vd->sys;
+    VdpBitmapSurface surface;
+    VdpRGBAFormat fmt = VDP_RGBA_FORMAT_R8G8B8A8; /* TODO? YUVA */
+    /* FIXME: capability checks */
+    VdpStatus err;
+
+    /* Create GPU surface for sub-picture */
+    err = vdp_bitmap_surface_create(sys->vdp, sys->device, fmt,
+        reg->fmt.i_visible_width, reg->fmt.i_visible_height, VDP_FALSE,
+                                    &surface);
+    if (err != VDP_STATUS_OK)
+    {
+        msg_Err(vd, "%s creation failure: %s", "bitmap surface",
+                vdp_get_error_string(sys->vdp, err));
+        return;
+    }
+
+    /* Upload sub-picture to GPU surface */
+    picture_t *subpic = reg->p_picture;
+    const void *data = subpic->p[0].p_pixels;
+    uint32_t pitch = subpic->p[0].i_pitch;
+
+    err = vdp_bitmap_surface_put_bits_native(sys->vdp, surface, &data, &pitch,
+                                             NULL);
+    if (err != VDP_STATUS_OK)
+    {
+        msg_Err(vd, "subpicture upload failure: %s",
+                vdp_get_error_string(sys->vdp, err));
+        goto out;
+    }
+
+    /* Render onto main surface */
+    VdpRect area = {
+        reg->i_x,
+        reg->i_y,
+        reg->i_x + reg->fmt.i_visible_width,
+        reg->i_y + reg->fmt.i_visible_height,
+    };
+    VdpColor color = { 1.f, 1.f, 1.f, reg->i_alpha * alpha / 65535.f };
+    VdpOutputSurfaceRenderBlendState state = {
+        .struct_version = VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION,
+        .blend_factor_source_color =
+            VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA,
+        .blend_factor_destination_color =
+            VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+        .blend_factor_source_alpha =
+            VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO,
+        .blend_factor_destination_alpha =
+            VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
+        .blend_equation_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
+        .blend_equation_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
+        .blend_constant = { 0.f, 0.f, 0.f, 0.f },
+    };
+
+    err = vdp_output_surface_render_bitmap_surface(sys->vdp, target, &area,
+                                             surface, NULL, &color, &state, 0);
+    if (err != VDP_STATUS_OK)
+        msg_Err(vd, "blending failure: %s",
+                vdp_get_error_string(sys->vdp, err));
+
+out:/* Destroy GPU surface */
+    vdp_bitmap_surface_destroy(sys->vdp, surface);
+}
+
+static void Queue(vout_display_t *vd, picture_t *pic, subpicture_t *subpic)
 {
     vout_display_sys_t *sys = vd->sys;
     VdpOutputSurface surface = pic->p_sys->surface;
     VdpStatus err;
 
-    (void) subpicture;
+    VdpPresentationQueueStatus status;
+    VdpTime ts;
+    err = vdp_presentation_queue_query_surface_status(sys->vdp, sys->queue,
+                                                      surface, &status, &ts);
+    if (err == VDP_STATUS_OK && status != VDP_PRESENTATION_QUEUE_STATUS_IDLE)
+        msg_Dbg(vd, "surface status: %u", status);
+
+    if (subpic != NULL)
+        for (subpicture_region_t *r = subpic->p_region; r != NULL;
+             r = r->p_next)
+            RenderRegion(vd, surface, r, subpic->i_alpha);
 
     /* Compute picture presentation time */
     mtime_t now = mdate();
@@ -469,6 +546,25 @@ static int Open(vlc_object_t *obj)
         xcb_map_window(sys->conn, sys->window);
     }
 
+    /* Check bitmap capabilities (for SPU) */
+    const vlc_fourcc_t *spu_chromas = NULL;
+    {
+        static const vlc_fourcc_t subpicture_chromas[] = { VLC_CODEC_RGBA, 0 };
+        uint32_t w, h;
+        VdpBool ok;
+
+        err = vdp_bitmap_surface_query_capabilities(sys->vdp, sys->device,
+                                        VDP_RGBA_FORMAT_R8G8B8A8, &ok, &w, &h);
+        if (err != VDP_STATUS_OK)
+        {
+            msg_Err(vd, "%s capabilities query failure: %s", "output surface",
+                    vdp_get_error_string(sys->vdp, err));
+            ok = VDP_FALSE;
+        }
+        if (ok)
+            spu_chromas = subpicture_chromas;
+    }
+
     /* Initialize VDPAU queue */
     err = vdp_presentation_queue_target_create_x11(sys->vdp, sys->device,
                                                    sys->window, &sys->target);
@@ -500,6 +596,7 @@ static int Open(vlc_object_t *obj)
     vd->sys = sys;
     vd->info.has_pictures_invalid = true;
     vd->info.has_event_thread = true;
+    vd->info.subpicture_chromas = spu_chromas;
     vd->fmt.i_chroma = VLC_CODEC_VDPAU_OUTPUT;
 
     vd->pool = Pool;
-- 
1.8.3.1




More information about the vlc-devel mailing list