VIGS: Support underlays and alpha blending 01/27401/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Tue, 1 Apr 2014 15:44:36 +0000 (19:44 +0400)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Fri, 12 Sep 2014 08:46:24 +0000 (17:46 +0900)
z-pos of planes has new meaning, if
it's >= 0 - plane is an overlay, i.e. it's layered
above root surface. if z-pos is < 0 - plane is underlay,
i.e. it's layered beneath the root surface. This new
logic has no meaning without alpha blending, so it's
supported as well (for all types of planes)

Change-Id: I61a80b48a1ef6c486fc83d0190d0bd5c1b7d4472
Signed-off-by: Stanislav Vorobiov <s.vorobiov@samsung.com>
hw/vigs/vigs_gl_backend.c
hw/vigs/vigs_gl_backend.h
hw/vigs/vigs_gl_backend_cgl.c
hw/vigs/vigs_gl_backend_glx.c
hw/vigs/vigs_gl_backend_wgl.c

index 720e618..438de8d 100644 (file)
@@ -1230,6 +1230,74 @@ static void vigs_gl_backend_read_pixels_work(struct work_queue_item *wq_item)
     g_free(item);
 }
 
+/*
+ * 'above_root' means we want to render only planes that are above root surface.
+ * 'bottom' means that if at least one plane is going to be rendered it'll be
+ *  bottom plane, i.e. the first one in surface stack.
+ */
+static bool vigs_gl_backend_composite_planes(struct vigs_gl_backend *gl_backend,
+                                             const struct vigs_plane **planes,
+                                             bool above_root,
+                                             bool bottom)
+{
+    uint32_t i;
+    GLfloat *vert_coords = vigs_vector_data(&gl_backend->v1);
+    GLfloat *tex_coords = vigs_vector_data(&gl_backend->v2);
+
+    for (i = 0; i < VIGS_MAX_PLANES; ++i) {
+        const struct vigs_plane *plane = planes[i];
+        struct vigs_gl_surface *gl_sfc;
+        struct vigs_winsys_gl_surface *ws_sfc;
+        GLfloat src_w, src_h;
+
+        if (!plane->sfc || ((plane->z_pos >= 0) ^ above_root)) {
+            continue;
+        }
+
+        gl_sfc = (struct vigs_gl_surface*)plane->sfc;
+        ws_sfc = get_ws_sfc(gl_sfc);
+
+        src_w = ws_sfc->base.base.width;
+        src_h = ws_sfc->base.base.height;
+
+        vert_coords[6] = vert_coords[0] = plane->dst_x;
+        vert_coords[7] = vert_coords[1] = plane->dst_y;
+        vert_coords[2] = plane->dst_x + (int)plane->dst_size.w;
+        vert_coords[3] = plane->dst_y;
+        vert_coords[8] = vert_coords[4] = plane->dst_x + (int)plane->dst_size.w;
+        vert_coords[9] = vert_coords[5] = plane->dst_y + (int)plane->dst_size.h;
+        vert_coords[10] = plane->dst_x;
+        vert_coords[11] = plane->dst_y + (int)plane->dst_size.h;
+
+        tex_coords[6] = tex_coords[0] = (GLfloat)plane->src_rect.pos.x / src_w;
+        tex_coords[7] = tex_coords[1] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
+        tex_coords[2] = (GLfloat)(plane->src_rect.pos.x + plane->src_rect.size.w) / src_w;
+        tex_coords[3] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
+        tex_coords[8] = tex_coords[4] = (GLfloat)(plane->src_rect.pos.x + plane->src_rect.size.w) / src_w;
+        tex_coords[9] = tex_coords[5] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
+        tex_coords[10] = (GLfloat)plane->src_rect.pos.x / src_w;
+        tex_coords[11] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
+
+        if (!bottom && (plane->sfc->format == vigsp_surface_bgra8888)) {
+            /*
+             * This is not bottom plane and it has alpha, turn on blending.
+             */
+            gl_backend->Enable(GL_BLEND);
+            gl_backend->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        } else {
+            gl_backend->Disable(GL_BLEND);
+        }
+
+        gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
+
+        vigs_gl_draw_tex_prog(gl_backend, 6);
+
+        bottom = false;
+    }
+
+    return bottom;
+}
+
 static void vigs_gl_backend_composite(struct vigs_surface *surface,
                                       const struct vigs_plane *planes,
                                       vigs_composite_start_cb start_cb,
@@ -1245,17 +1313,16 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
     const struct vigs_plane *sorted_planes[VIGS_MAX_PLANES];
     uint32_t size = surface->stride * surface->ws_sfc->height;
     struct vigs_gl_backend_read_pixels_work_item *item;
+    bool bottom = true;
 
     VIGS_LOG_TRACE("enter");
 
-    if (!surface->ptr) {
-        if (!ws_root_sfc->tex) {
-            VIGS_LOG_WARN("compositing garbage (root surface) ???");
-        }
+    if (!surface->ptr && !ws_root_sfc->tex) {
+        VIGS_LOG_WARN("compositing garbage (root surface) ???");
+    }
 
-        if (!vigs_winsys_gl_surface_create_texture(ws_root_sfc)) {
-            goto out;
-        }
+    if (!vigs_winsys_gl_surface_create_texture(ws_root_sfc)) {
+        goto out;
     }
 
     if (!vigs_gl_surface_create_tmp_texture(gl_root_sfc)) {
@@ -1288,6 +1355,20 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
         goto out;
     }
 
+    /*
+     * Sort planes, only 2 of them now, don't bother...
+     */
+
+    assert(VIGS_MAX_PLANES == 2);
+
+    if (planes[0].z_pos <= planes[1].z_pos) {
+        sorted_planes[0] = &planes[0];
+        sorted_planes[1] = &planes[1];
+    } else {
+        sorted_planes[0] = &planes[1];
+        sorted_planes[1] = &planes[0];
+    }
+
     vigs_vector_resize(&gl_backend->v1, 0);
     vigs_vector_resize(&gl_backend->v2, 0);
 
@@ -1307,7 +1388,7 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
         gl_backend->PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
         gl_backend->PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
 
-        gl_backend->BindTexture(GL_TEXTURE_2D, gl_root_sfc->tmp_tex);
+        gl_backend->BindTexture(GL_TEXTURE_2D, ws_root_sfc->tex);
 
         gl_backend->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
                                   ws_root_sfc->base.base.width,
@@ -1320,91 +1401,64 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface,
     gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                      GL_TEXTURE_2D, gl_root_sfc->tmp_tex, 0);
 
-    if (!surface->ptr) {
-        /*
-         * If root surface is not scanout then we must render
-         * it.
-         */
-
-        vert_coords[6] = vert_coords[0] = 0;
-        vert_coords[7] = vert_coords[1] = ws_root_sfc->base.base.height;
-        vert_coords[2] = ws_root_sfc->base.base.width;
-        vert_coords[3] = ws_root_sfc->base.base.height;
-        vert_coords[8] = vert_coords[4] = ws_root_sfc->base.base.width;
-        vert_coords[9] = vert_coords[5] = 0;
-        vert_coords[10] = 0;
-        vert_coords[11] = 0;
-
-        tex_coords[6] = tex_coords[0] = 0;
-        tex_coords[7] =tex_coords[1] = 0;
-        tex_coords[2] = 1;
-        tex_coords[3] = 0;
-        tex_coords[8] = tex_coords[4] = 1;
-        tex_coords[9] = tex_coords[5] = 1;
-        tex_coords[10] = 0;
-        tex_coords[11] = 1;
-
-        gl_backend->BindTexture(GL_TEXTURE_2D, ws_root_sfc->tex);
-
-        vigs_gl_draw_tex_prog(gl_backend, 6);
-    }
+    bottom = vigs_gl_backend_composite_planes(gl_backend,
+                                              sorted_planes,
+                                              false,
+                                              bottom);
 
     /*
-     * Sort planes, only 2 of them now, don't bother...
+     * Render root surface.
      */
 
-    assert(VIGS_MAX_PLANES == 2);
+    vert_coords[6] = vert_coords[0] = 0;
+    vert_coords[7] = vert_coords[1] = ws_root_sfc->base.base.height;
+    vert_coords[2] = ws_root_sfc->base.base.width;
+    vert_coords[3] = ws_root_sfc->base.base.height;
+    vert_coords[8] = vert_coords[4] = ws_root_sfc->base.base.width;
+    vert_coords[9] = vert_coords[5] = 0;
+    vert_coords[10] = 0;
+    vert_coords[11] = 0;
 
-    if (planes[0].z_pos <= planes[1].z_pos) {
-        sorted_planes[0] = &planes[0];
-        sorted_planes[1] = &planes[1];
+    tex_coords[6] = tex_coords[0] = 0;
+    tex_coords[7] =tex_coords[1] = 0;
+    tex_coords[2] = 1;
+    tex_coords[3] = 0;
+    tex_coords[8] = tex_coords[4] = 1;
+    tex_coords[9] = tex_coords[5] = 1;
+    tex_coords[10] = 0;
+    tex_coords[11] = 1;
+
+    if (!bottom) {
+        /*
+         * Root surface has planes beneath it, turn on blending.
+         *
+         * Note that we DON'T check for alpha on root surface, i.e.:
+         * (surface->format == vigsp_surface_bgra8888)
+         * The reasons are:
+         * + X.Org doesn't allow having 32 depths, i.e. only bpp can
+         *   be 32, depth must be <= 24, i.e. X.Org is not underlay-aware,
+         *   but that doesn't mean we can't have them with X.Org
+         * + Since we DO have something beneath the root surface that means
+         *   root surface just got to have alpha, otherwise user won't be
+         *   able to see that "something", i.e. specifying alpha in root
+         *   surface format is not that necessary in this case
+         */
+        gl_backend->Enable(GL_BLEND);
+        gl_backend->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     } else {
-        sorted_planes[0] = &planes[1];
-        sorted_planes[1] = &planes[0];
+        gl_backend->Disable(GL_BLEND);
     }
 
-    /*
-     * Now render planes, respect z-order.
-     */
+    gl_backend->BindTexture(GL_TEXTURE_2D, ws_root_sfc->tex);
 
-    for (i = 0; i < VIGS_MAX_PLANES; ++i) {
-        const struct vigs_plane *plane = sorted_planes[i];
-        struct vigs_gl_surface *gl_sfc;
-        struct vigs_winsys_gl_surface *ws_sfc;
-        GLfloat src_w, src_h;
-
-        if (!plane->sfc) {
-            continue;
-        }
-
-        gl_sfc = (struct vigs_gl_surface*)plane->sfc;
-        ws_sfc = get_ws_sfc(gl_sfc);
-
-        src_w = ws_sfc->base.base.width;
-        src_h = ws_sfc->base.base.height;
-
-        vert_coords[6] = vert_coords[0] = plane->dst_x;
-        vert_coords[7] = vert_coords[1] = plane->dst_y;
-        vert_coords[2] = plane->dst_x + (int)plane->dst_size.w;
-        vert_coords[3] = plane->dst_y;
-        vert_coords[8] = vert_coords[4] = plane->dst_x + (int)plane->dst_size.w;
-        vert_coords[9] = vert_coords[5] = plane->dst_y + (int)plane->dst_size.h;
-        vert_coords[10] = plane->dst_x;
-        vert_coords[11] = plane->dst_y + (int)plane->dst_size.h;
-
-        tex_coords[6] = tex_coords[0] = (GLfloat)plane->src_rect.pos.x / src_w;
-        tex_coords[7] = tex_coords[1] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
-        tex_coords[2] = (GLfloat)(plane->src_rect.pos.x + plane->src_rect.size.w) / src_w;
-        tex_coords[3] = (GLfloat)(src_h - plane->src_rect.pos.y) / src_h;
-        tex_coords[8] = tex_coords[4] = (GLfloat)(plane->src_rect.pos.x + plane->src_rect.size.w) / src_w;
-        tex_coords[9] = tex_coords[5] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
-        tex_coords[10] = (GLfloat)plane->src_rect.pos.x / src_w;
-        tex_coords[11] = (GLfloat)(src_h - (plane->src_rect.pos.y + plane->src_rect.size.h)) / src_h;
+    vigs_gl_draw_tex_prog(gl_backend, 6);
 
-        gl_backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex);
+    bottom = false;
 
-        vigs_gl_draw_tex_prog(gl_backend, 6);
-    }
+    vigs_gl_backend_composite_planes(gl_backend,
+                                     sorted_planes,
+                                     true,
+                                     bottom);
 
     /*
      * Now schedule asynchronous glReadPixels.
index e761ed1..5d3b019 100644 (file)
@@ -92,6 +92,7 @@ struct vigs_gl_backend
     void (GLAPIENTRY *GetIntegerv)(GLenum pname, GLint *params);
     const GLubyte *(GLAPIENTRY *GetString)(GLenum name);
     void (GLAPIENTRY *DrawArrays)(GLenum mode, GLint first, GLsizei count);
+    void (GLAPIENTRY *BlendFunc)(GLenum sfactor, GLenum dfactor);
     void (GLAPIENTRY *GenBuffers)(GLsizei n, GLuint *buffers);
     void (GLAPIENTRY *DeleteBuffers)(GLsizei n, const GLuint *buffers);
     void (GLAPIENTRY *BindBuffer)(GLenum target, GLuint buffer);
index 0819409..996618a 100644 (file)
@@ -292,6 +292,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
     VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv);
     VIGS_GL_GET_PROC(GetString, glGetString);
     VIGS_GL_GET_PROC(DrawArrays, glDrawArrays);
+    VIGS_GL_GET_PROC(BlendFunc, glBlendFunc);
     VIGS_GL_GET_PROC(GenBuffers, glGenBuffers);
     VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers);
     VIGS_GL_GET_PROC(BindBuffer, glBindBuffer);
index 5394b19..caf5096 100644 (file)
@@ -441,6 +441,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
     VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv);
     VIGS_GL_GET_PROC(GetString, glGetString);
     VIGS_GL_GET_PROC(DrawArrays, glDrawArrays);
+    VIGS_GL_GET_PROC(BlendFunc, glBlendFunc);
     VIGS_GL_GET_PROC(GenBuffers, glGenBuffers);
     VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers);
     VIGS_GL_GET_PROC(BindBuffer, glBindBuffer);
index 7cb650e..b9b689e 100644 (file)
@@ -582,6 +582,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display)
     VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv);
     VIGS_GL_GET_PROC(GetString, glGetString);
     VIGS_GL_GET_PROC(DrawArrays, glDrawArrays);
+    VIGS_GL_GET_PROC(BlendFunc, glBlendFunc);
     VIGS_GL_GET_PROC(GenBuffers, glGenBuffers);
     VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers);
     VIGS_GL_GET_PROC(BindBuffer, glBindBuffer);