This new border API is sufficiently powerful border suffort for doing a
full window frame.

Signed-off-by: Jason Ekstrand <[email protected]>
---
 src/gl-renderer.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/gl-renderer.h |  39 ++++++++++++++++
 2 files changed, 168 insertions(+), 3 deletions(-)

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index f02445b..7ca5c22 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -50,9 +50,18 @@ struct gl_shader {
 
 #define BUFFER_DAMAGE_COUNT 2
 
+struct gl_border_image {
+       GLuint tex;
+       int32_t width, height;
+       int32_t tex_width;
+       int dirty;
+       void *data;
+};
+
 struct gl_output_state {
        EGLSurface egl_surface;
        pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
+       struct gl_border_image borders[4];
 };
 
 enum buffer_type {
@@ -570,6 +579,104 @@ repaint_surfaces(struct weston_output *output, 
pixman_region32_t *damage)
                        draw_surface(surface, output, damage);
 }
 
+static void
+draw_output_border_texture(struct gl_border_image *img, int32_t x, int32_t y,
+                          int32_t width, int32_t height)
+{
+       static GLushort indices [] = { 0, 1, 3, 3, 1, 2 };
+
+       if (!img->data) {
+               if (img->tex) {
+                       glDeleteTextures(1, &img->tex);
+                       img->tex = 0;
+               }
+
+               return;
+       }
+
+       if (!img->tex) {
+               glGenTextures(1, &img->tex);
+               glBindTexture(GL_TEXTURE_2D, img->tex);
+
+               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);
+       } else {
+               glBindTexture(GL_TEXTURE_2D, img->tex);
+       }
+
+       if (img->dirty) {
+               glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
+                            img->tex_width, img->height, 0,
+                            GL_BGRA_EXT, GL_UNSIGNED_BYTE, img->data);
+
+       }
+
+       glBindTexture(GL_TEXTURE_2D, img->tex);
+
+       GLfloat texcoord[] = {
+               0.0f, 0.0f,
+               (GLfloat)img->width / (GLfloat)img->tex_width, 0.0f,
+               (GLfloat)img->width / (GLfloat)img->tex_width, 1.0f,
+               0.0f, 1.0f,
+       };
+
+       GLfloat verts[] = {
+               x, y,
+               x + width, y,
+               x + width, y + height,
+               x, y + height
+       };
+
+       glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
+       glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
+       glEnableVertexAttribArray(0);
+       glEnableVertexAttribArray(1);
+
+       glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+       glDisableVertexAttribArray(1);
+       glDisableVertexAttribArray(0);
+}
+
+static void
+draw_output_border(struct weston_output *output)
+{
+       struct gl_output_state *go = get_output_state(output);
+       struct gl_renderer *gr = get_renderer(output->compositor);
+       struct gl_shader *shader = &gr->texture_shader_rgba;
+       int32_t full_width;
+
+       glDisable(GL_BLEND);
+       use_shader(gr, shader);
+
+       glUniformMatrix4fv(shader->proj_uniform,
+                          1, GL_FALSE, output->matrix.d);
+
+       glUniform1i(shader->tex_uniforms[0], 0);
+       glUniform1f(shader->alpha_uniform, 1);
+       glActiveTexture(GL_TEXTURE0);
+
+       full_width = output->width + output->border.left + output->border.right;
+       draw_output_border_texture(&go->borders[0],
+                                  -output->border.left, -output->border.top,
+                                  full_width, output->border.top);
+       draw_output_border_texture(&go->borders[1],
+                                  -output->border.left, 0,
+                                  output->border.left, output->height);
+       draw_output_border_texture(&go->borders[2],
+                                  output->width, 0,
+                                  output->border.right, output->height);
+       draw_output_border_texture(&go->borders[3],
+                                  -output->border.left, output->height,
+                                  full_width, output->border.bottom);
+}
 
 static int
 texture_border(struct weston_output *output)
@@ -648,7 +755,7 @@ texture_border(struct weston_output *output)
 }
 
 static void
-draw_border(struct weston_output *output)
+draw_global_border(struct weston_output *output)
 {
        struct weston_compositor *ec = output->compositor;
        struct gl_renderer *gr = get_renderer(ec);
@@ -780,8 +887,11 @@ gl_renderer_repaint_output(struct weston_output *output,
        pixman_region32_fini(&total_damage);
        pixman_region32_fini(&buffer_damage);
 
-       if (gr->border.texture)
-               draw_border(output);
+       if (gr->border.texture) {
+               draw_global_border(output);
+       } else {
+               draw_output_border(output);
+       }
 
        pixman_region32_copy(&output->previous_damage, output_damage);
        wl_signal_emit(&output->frame_signal, output);
@@ -1432,6 +1542,21 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig 
eglconfig)
 }
 
 static void
+gl_renderer_output_set_border(struct weston_output *output,
+                             enum gl_renderer_border_side side,
+                             int32_t width, int32_t height,
+                             int32_t tex_width, unsigned char *data)
+{
+       struct gl_output_state *go = get_output_state(output);
+
+       go->borders[side].width = width;
+       go->borders[side].height = height;
+       go->borders[side].tex_width = tex_width;
+       go->borders[side].data = data;
+       go->borders[side].dirty = 1;
+}
+
+static void
 output_apply_border(struct weston_output *output, struct gl_renderer *gr)
 {
        output->border.top = gr->border.top;
@@ -1873,6 +1998,7 @@ WL_EXPORT struct gl_renderer_interface 
gl_renderer_interface = {
        .output_create = gl_renderer_output_create,
        .output_destroy = gl_renderer_output_destroy,
        .output_surface = gl_renderer_output_surface,
+       .output_set_border = gl_renderer_output_set_border,
        .set_border = gl_renderer_set_border,
        .print_egl_error_state = gl_renderer_print_egl_error_state
 };
diff --git a/src/gl-renderer.h b/src/gl-renderer.h
index 0342134..8a36c89 100644
--- a/src/gl-renderer.h
+++ b/src/gl-renderer.h
@@ -39,6 +39,13 @@ typedef intptr_t EGLNativeWindowType;
 
 #endif
 
+enum gl_renderer_border_side {
+       GL_RENDERER_BORDER_TOP = 0,
+       GL_RENDERER_BORDER_LEFT = 1,
+       GL_RENDERER_BORDER_RIGHT = 2,
+       GL_RENDERER_BORDER_BOTTOM = 3,
+};
+
 struct gl_renderer_interface {
        const EGLint *opaque_attribs;
        const EGLint *alpha_attribs;
@@ -57,6 +64,38 @@ struct gl_renderer_interface {
 
        EGLSurface (*output_surface)(struct weston_output *output);
 
+       /* Sets the output border.
+        *
+        * The side specifies the side for which we are setting the border.
+        * The width and height are the width and height of the border.
+        * The tex_width patemeter specifies the width of the actual
+        * texture; this may be larger than width if the data is not
+        * tightly packed.
+        *
+        * The top and bottom textures will extend over the sides to the
+        * full width of the bordered window while.  The right and left
+        * edges, however, will extend only to the top and bottom of the
+        * compositor surface.  This is demonstrated by the picture below:
+        *
+        * +-----------------------+
+        * |          TOP          |
+        * +-+-------------------+-+
+        * | |                   | |
+        * |L|                   |R|
+        * |E|                   |I|
+        * |F|                   |G|
+        * |T|                   |H|
+        * | |                   |T|
+        * | |                   | |
+        * +-+-------------------+-+
+        * |        BOTTOM         |
+        * +-----------------------+
+        */
+       void (*output_set_border)(struct weston_output *output,
+                                 enum gl_renderer_border_side side,
+                                 int32_t width, int32_t height,
+                                 int32_t tex_width, unsigned char *data);
+
        void (*set_border)(struct weston_compositor *ec,
                           int32_t width, int32_t height,
                           void *data, int32_t *edges);
-- 
1.8.3.1

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to