---
 src/compositor.h     |   5 ++
 src/gles2-renderer.c | 164 +++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 152 insertions(+), 17 deletions(-)

diff --git a/src/compositor.h b/src/compositor.h
index 733f423..c24545d 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -169,6 +169,11 @@ struct weston_output {
        uint32_t frame_time;
        int disable_planes;
 
+       int indirect_disable;
+       int indirect_drawing;
+       GLuint indirect_texture;
+       GLuint indirect_fbo;
+
        char *make, *model;
        uint32_t subpixel;
        uint32_t transform;
diff --git a/src/gles2-renderer.c b/src/gles2-renderer.c
index 54d380a..1136cba 100644
--- a/src/gles2-renderer.c
+++ b/src/gles2-renderer.c
@@ -533,23 +533,12 @@ triangle_fan_debug(struct weston_surface *surface, int 
first, int count)
 }
 
 static void
-repaint_region(struct weston_surface *es, pixman_region32_t *region,
-               pixman_region32_t *surf_region)
+repaint_region(struct weston_compositor *ec, struct weston_surface *es,
+               int nfans)
 {
-       struct weston_compositor *ec = es->compositor;
        GLfloat *v;
        unsigned int *vtxcnt;
-       int i, first, nfans;
-
-       /* The final region to be painted is the intersection of
-        * 'region' and 'surf_region'. However, 'region' is in the global
-        * coordinates, and 'surf_region' is in the surface-local
-        * coordinates. texture_region() will iterate over all pairs of
-        * rectangles from both regions, compute the intersection
-        * polygon for each pair, and store it as a triangle fan if
-        * it has a non-zero area (at least 3 vertices, actually).
-        */
-       nfans = texture_region(es, region, surf_region);
+       int i, first;
 
        v = ec->vertices.data;
        vtxcnt = ec->vtxcnt.data;
@@ -564,7 +553,7 @@ repaint_region(struct weston_surface *es, pixman_region32_t 
*region,
 
        for (i = 0, first = 0; i < nfans; i++) {
                glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
-               if (ec->fan_debug)
+               if (es && ec->fan_debug)
                        triangle_fan_debug(es, first, vtxcnt[i]);
                first += vtxcnt[i];
        }
@@ -577,6 +566,73 @@ repaint_region(struct weston_surface *es, 
pixman_region32_t *region,
 }
 
 static void
+repaint_surface(struct weston_surface *es, pixman_region32_t *region,
+               pixman_region32_t *surf_region)
+{
+       /* The final region to be painted is the intersection of
+        * 'region' and 'surf_region'. However, 'region' is in the global
+        * coordinates, and 'surf_region' is in the surface-local
+        * coordinates. texture_region() will iterate over all pairs of
+        * rectangles from both regions, compute the intersection
+        * polygon for each pair, and store it as a triangle fan if
+        * it has a non-zero area (at least 3 vertices, actually).
+        */
+       int nfans = texture_region(es, region, surf_region);
+
+       repaint_region(es->compositor, es, nfans);
+}
+
+static void
+output_emit_vertex(struct weston_output *output, GLfloat **v, int32_t x, 
int32_t y)
+{
+       struct weston_vector vector;
+
+       /* position: */
+       *((*v)++) = x;
+       *((*v)++) = y;
+
+       /* texcoord: */
+
+       vector.f[0] = x;
+       vector.f[1] = y;
+       vector.f[2] = 0.0f;
+       vector.f[3] = 1.0f;
+
+       weston_matrix_transform(&output->matrix, &vector);
+
+       *((*v)++) = (vector.f[0] + 1.0f) * 0.5f;
+       *((*v)++) = (vector.f[1] + 1.0f) * 0.5f;
+}
+
+static void
+repaint_output(struct weston_output *output, pixman_region32_t *region)
+{
+       struct weston_compositor *ec = output->compositor;
+       GLfloat *v;
+       unsigned int *vtxcnt, nvtx = 0;
+       pixman_box32_t *rects;
+       int i, nrects;
+
+       rects = pixman_region32_rectangles(region, &nrects);
+
+       v = wl_array_add(&ec->vertices, nrects * 4 * 4 * sizeof *v);
+       vtxcnt = wl_array_add(&ec->vtxcnt, nrects * sizeof *vtxcnt);
+
+       for (i = 0; i < nrects; i++) {
+               pixman_box32_t *rect = &rects[i];
+
+               output_emit_vertex(output, &v, rect->x1, rect->y1);
+               output_emit_vertex(output, &v, rect->x2, rect->y1);
+               output_emit_vertex(output, &v, rect->x2, rect->y2);
+               output_emit_vertex(output, &v, rect->x1, rect->y2);
+
+               vtxcnt[nvtx++] = 4;
+       }
+
+       repaint_region(ec, NULL, nvtx);
+}
+
+static void
 weston_compositor_use_shader(struct weston_compositor *compositor,
                             struct weston_shader *shader)
 {
@@ -588,6 +644,69 @@ weston_compositor_use_shader(struct weston_compositor 
*compositor,
 }
 
 static void
+repaint_surfaces_start(struct weston_output *output, pixman_region32_t *damage)
+{
+       output->indirect_drawing = 0 && !output->indirect_disable;
+
+       if(output->indirect_drawing) {
+               if(!output->indirect_fbo)
+                       glGenFramebuffers(1, &output->indirect_fbo);
+
+               glBindFramebuffer(GL_FRAMEBUFFER, output->indirect_fbo);
+
+               if(!output->indirect_texture) {
+                       glGenTextures(1, &output->indirect_texture);
+
+                       glBindTexture(GL_TEXTURE_2D, output->indirect_texture);
+
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
GL_CLAMP_TO_EDGE);
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
GL_CLAMP_TO_EDGE);
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
GL_NEAREST);
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
GL_NEAREST);
+
+                       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 
output->current->width, output->current->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 
0);
+                       glFramebufferTexture2D(GL_FRAMEBUFFER, 
GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, output->indirect_texture, 0);
+               }
+
+               GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+               if(status != GL_FRAMEBUFFER_COMPLETE) {
+                       weston_log("unable to create framebuffer for indirect 
rendering %d\n", (int)status);
+                       output->indirect_drawing = 0;
+                       output->indirect_disable = 1;
+
+                       return;
+               }
+       }
+}
+
+static void
+repaint_surfaces_finish(struct weston_output *output, pixman_region32_t 
*damage)
+{
+       struct weston_compositor *ec = output->compositor;
+
+       if(output->indirect_drawing) {
+               glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+               struct weston_shader *shader = &ec->texture_shader_rgba;
+
+               weston_compositor_use_shader(ec, shader);
+
+               glUniformMatrix4fv(shader->proj_uniform,
+                                  1, GL_FALSE, output->matrix.d);
+               glUniform1f(shader->alpha_uniform, 1.0);
+               glUniform1i(shader->tex_uniforms[0], 0);
+
+               glDisable(GL_BLEND);
+
+               glActiveTexture(GL_TEXTURE0);
+               glBindTexture(GL_TEXTURE_2D, output->indirect_texture);
+
+               repaint_output(output, damage);
+       }
+}
+
+static void
 weston_shader_uniforms(struct weston_shader *shader,
                       struct weston_surface *surface,
                       struct weston_output *output)
@@ -669,13 +788,13 @@ draw_surface(struct weston_surface *es, struct 
weston_output *output,
                else
                        glDisable(GL_BLEND);
 
-               repaint_region(es, &repaint, &es->opaque);
+               repaint_surface(es, &repaint, &es->opaque);
        }
 
        if (pixman_region32_not_empty(&surface_blend)) {
                weston_compositor_use_shader(ec, es->shader);
                glEnable(GL_BLEND);
-               repaint_region(es, &repaint, &surface_blend);
+               repaint_surface(es, &repaint, &surface_blend);
        }
 
        pixman_region32_fini(&surface_blend);
@@ -690,9 +809,13 @@ repaint_surfaces(struct weston_output *output, 
pixman_region32_t *damage)
        struct weston_compositor *compositor = output->compositor;
        struct weston_surface *surface;
 
+       repaint_surfaces_start(output, damage);
+
        wl_list_for_each_reverse(surface, &compositor->surface_list, link)
                if (surface->plane == &compositor->primary_plane)
                        draw_surface(surface, output, damage);
+
+       repaint_surfaces_finish(output, damage);
 }
 
 static void
@@ -1130,11 +1253,18 @@ WL_EXPORT void
 gles2_renderer_surface_create(struct weston_output *output, EGLSurface 
egl_surface)
 {
        output->egl_surface = egl_surface;
+
+       output->indirect_texture = 0;
+       output->indirect_fbo = 0;
+       output->indirect_disable = 0;
 }
 
 WL_EXPORT void
 gles2_renderer_surface_destroy(struct weston_output *output)
 {
+       glDeleteTextures(1, &output->indirect_texture);
+       glDeleteFramebuffers(1, &output->indirect_fbo);
+
        eglDestroySurface(output->compositor->egl_display, output->egl_surface);
 }
 
-- 
1.7.12

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to