Re: input handlig in separate thread

2013-10-20 Thread Eugen Friedrich
2013/10/20 Bill Spitzak spit...@gmail.com

 On 10/19/2013 10:03 AM, Eugen Friedrich wrote:

  Basically i would like to implement a thread(input thread) that should
   only dispatch incoming input events from wayland compositor when the
 rendering thread is idle and the input thread should sleep in wait for
 events function(i think poll on wl_display fd in the example above)
 without blocking the rendering thread, because the input events are not
 the only one trigger for rendering thread to start rendering again.
 in this case the following code should be sufficient right?

 while(!quit)//main loop
 {
   while (wl_display_prepare_read(__**display) != 0)
   wl_display_dispatch_pending(__**display);

   wl_display_flush(display);
   poll(fds, nfds, -1); //wait until new input event arrives
   wl_display_read_events(__**display);
   wl_display_dispatch_pending(__**display);

 }

 And in this case are there some additional modifications/ wayland calls
 in the egl (rendering thread) needed?


 I'm not sure what you are getting at, but it sounds like in effect
 cooperative multitasking between this rendering thread and this thread. I
 think you are saying that the rendering thread will only operate when
 poll() is being called. I don't see any advantage of this over running a
 single thread that does the rendering just before calling poll(), which is
 what I was doing with the idle dispatch.

 The rendering thread can start rendering every time not only if poll is
called. The job of the input handling thread is to dispatch input events if
there is no rendering occurs. If the rendering thread is running the input
events are dispatched by the wl_display_dispatch call inside of the
eglSwapBuffers, but if the rendering stops (e.g. current animation is done)
we need to dispatch the input events somewhere else - this is the aim of
the input thread.
So i'm trying to find a right way to do this without blocking the wayland
display main queue, because rendering can be started also without any
trigger from the input thread!!!

Also your above example can merge the wl_display_dispatch_pending calls
 like this:

   while(!quit)//main loop
   {
 do wl_display_dispatch_pending(__**display);
 while (wl_display_prepare_read(__**display) != 0);

 wl_display_flush(display);
 poll(fds, nfds, -1); //wait until new input event arrives
 wl_display_read_events(__**display);
   }

 If you move the wl_display_read_events up to the top with an if so it is
 not run the same time, you still have my wl_i_want_a_pony() function.

 What I am trying to find is if there ever is a reason to insert any client
 calls between all the functions I put in wl_i_want_a_pony().


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


[PATCH 0/6] Give the wayland backend an actual frame

2013-10-20 Thread Jason Ekstrand
This series of patches makes a few improvements to the wayland backend.  In
particular, it adds a frame using the new frame code in cairo-util.  It
also contains a performance/responsiveness improvement and adds a
SHM/pixman fallback mode if EGL is not available.

Jason Ekstrand (6):
  compositor-wayland: Rename structure members and make things more
consistant
  gl-renderer: Add support for per-output multi-texture borders.
  compositor-wayland: Add an actual frame around the compositor window
  gl-renderer: Remove the renderer-global border support
  compositor-wayland: Flush the display on commit
  compositor-wayland: Add pixman/SHM fallback mode

 configure.ac |   2 +-
 src/compositor-wayland.c | 854 ++-
 src/compositor.c |   1 +
 src/gl-renderer.c| 241 ++---
 src/gl-renderer.h|  41 ++-
 5 files changed, 834 insertions(+), 305 deletions(-)

-- 
1.8.3.1

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


[PATCH 1/6] compositor-wayland: Rename structure members and make things more consistant

2013-10-20 Thread Jason Ekstrand
Signed-off-by: Jason Ekstrand ja...@jlekstrand.net
---
 src/compositor-wayland.c | 76 ++--
 1 file changed, 41 insertions(+), 35 deletions(-)

diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 7b670d9..df487ad 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -39,7 +39,7 @@
 #include ../shared/os-compatibility.h
 
 struct wayland_compositor {
-   struct weston_compositor base;
+   struct weston_compositor base;
 
struct {
struct wl_display *wl_display;
@@ -61,28 +61,34 @@ struct wayland_compositor {
int32_t top, bottom, left, right;
} border;
 
-   struct wl_list input_list;
+   struct wl_list inputs;
 };
 
 struct wayland_output {
-   struct weston_outputbase;
+   struct weston_output base;
+
struct {
-   int  draw_initial_frame;
-   struct wl_surface   *surface;
-   struct wl_shell_surface *shell_surface;
-   struct wl_egl_window*egl_window;
+   int draw_initial_frame;
+   struct wl_surface *surface;
+   struct wl_shell_surface *shell_surface;
+   struct wl_egl_window *egl_window;
} parent;
-   struct weston_mode  mode;
+
+   struct weston_mode mode;
 };
 
 struct wayland_input {
struct weston_seat base;
struct wayland_compositor *compositor;
-   struct wl_seat *seat;
-   struct wl_pointer *pointer;
-   struct wl_keyboard *keyboard;
-   struct wl_touch *touch;
struct wl_list link;
+
+   struct {
+   struct wl_seat *seat;
+   struct wl_pointer *pointer;
+   struct wl_keyboard *keyboard;
+   struct wl_touch *touch;
+   } parent;
+
uint32_t key_serial;
uint32_t enter_serial;
int focus;
@@ -401,7 +407,7 @@ check_focus(struct wayland_input *input, wl_fixed_t x, 
wl_fixed_t y)
notify_pointer_focus(input-base, input-output-base,
 x - wl_fixed_from_int(c-border.left),
 y = wl_fixed_from_int(c-border.top));
-   wl_pointer_set_cursor(input-pointer,
+   wl_pointer_set_cursor(input-parent.pointer,
  input-enter_serial, NULL, 0, 0);
} else if (input-focus  !inside) {
notify_pointer_focus(input-base, NULL, 0, 0);
@@ -598,25 +604,25 @@ input_handle_capabilities(void *data, struct wl_seat 
*seat,
 {
struct wayland_input *input = data;
 
-   if ((caps  WL_SEAT_CAPABILITY_POINTER)  !input-pointer) {
-   input-pointer = wl_seat_get_pointer(seat);
-   wl_pointer_set_user_data(input-pointer, input);
-   wl_pointer_add_listener(input-pointer, pointer_listener,
-   input);
+   if ((caps  WL_SEAT_CAPABILITY_POINTER)  !input-parent.pointer) {
+   input-parent.pointer = wl_seat_get_pointer(seat);
+   wl_pointer_set_user_data(input-parent.pointer, input);
+   wl_pointer_add_listener(input-parent.pointer,
+   pointer_listener, input);
weston_seat_init_pointer(input-base);
-   } else if (!(caps  WL_SEAT_CAPABILITY_POINTER)  input-pointer) {
-   wl_pointer_destroy(input-pointer);
-   input-pointer = NULL;
+   } else if (!(caps  WL_SEAT_CAPABILITY_POINTER)  
input-parent.pointer) {
+   wl_pointer_destroy(input-parent.pointer);
+   input-parent.pointer = NULL;
}
 
-   if ((caps  WL_SEAT_CAPABILITY_KEYBOARD)  !input-keyboard) {
-   input-keyboard = wl_seat_get_keyboard(seat);
-   wl_keyboard_set_user_data(input-keyboard, input);
-   wl_keyboard_add_listener(input-keyboard, keyboard_listener,
-input);
-   } else if (!(caps  WL_SEAT_CAPABILITY_KEYBOARD)  input-keyboard) {
-   wl_keyboard_destroy(input-keyboard);
-   input-keyboard = NULL;
+   if ((caps  WL_SEAT_CAPABILITY_KEYBOARD)  !input-parent.keyboard) {
+   input-parent.keyboard = wl_seat_get_keyboard(seat);
+   wl_keyboard_set_user_data(input-parent.keyboard, input);
+   wl_keyboard_add_listener(input-parent.keyboard,
+keyboard_listener, input);
+   } else if (!(caps  WL_SEAT_CAPABILITY_KEYBOARD)  
input-parent.keyboard) {
+   wl_keyboard_destroy(input-parent.keyboard);
+   input-parent.keyboard = NULL;
}
 }
 
@@ -635,12 +641,12 @@ display_add_seat(struct wayland_compositor *c, uint32_t 
id)
 
weston_seat_init(input-base, c-base, default);
input-compositor = c;
-   input-seat = 

[PATCH 2/6] gl-renderer: Add support for per-output multi-texture borders.

2013-10-20 Thread Jason Ekstrand
The first advantage of this new API is that it is per-output instead of
global to the gl_renderer instance.  This means that different windows can
have different titles, different button states, etc.  The new api also uses
four textures (one for each side) instead of one.  This allows you to draw
real borders with text and buttons in them instead of a simple image that
gets streached.

Images will be scaled as needed, so the right and left can be one pixel
tall if desired.

Signed-off-by: Jason Ekstrand ja...@jlekstrand.net
---
 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, 

[PATCH 3/6] compositor-wayland: Add an actual frame around the compositor window

2013-10-20 Thread Jason Ekstrand
This adds a window frame with a close button.  Similar to the X11 backend,
The window supports dragging but not resizing.

Signed-off-by: Jason Ekstrand ja...@jlekstrand.net
---
 configure.ac |   2 +-
 src/compositor-wayland.c | 407 ++-
 2 files changed, 336 insertions(+), 73 deletions(-)

diff --git a/configure.ac b/configure.ac
index 950086d..e912b18 100644
--- a/configure.ac
+++ b/configure.ac
@@ -159,7 +159,7 @@ AM_CONDITIONAL(ENABLE_WAYLAND_COMPOSITOR,
 if test x$enable_wayland_compositor = xyes -a x$enable_egl = xyes; then
   AC_DEFINE([BUILD_WAYLAND_COMPOSITOR], [1],
[Build the Wayland (nested) compositor])
-  PKG_CHECK_MODULES(WAYLAND_COMPOSITOR, [wayland-client wayland-egl])
+  PKG_CHECK_MODULES(WAYLAND_COMPOSITOR, [wayland-client wayland-egl 
wayland-cursor])
 fi
 
 
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index df487ad..54c51a4 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -32,11 +32,13 @@
 
 #include wayland-client.h
 #include wayland-egl.h
+#include wayland-cursor.h
 
 #include compositor.h
 #include gl-renderer.h
 #include ../shared/image-loader.h
 #include ../shared/os-compatibility.h
+#include ../shared/cairo-util.h
 
 struct wayland_compositor {
struct weston_compositor base;
@@ -57,9 +59,10 @@ struct wayland_compositor {
uint32_t event_mask;
} parent;
 
-   struct {
-   int32_t top, bottom, left, right;
-   } border;
+   struct theme *theme;
+   cairo_device_t *frame_device;
+   struct wl_cursor_theme *cursor_theme;
+   struct wl_cursor *cursor;
 
struct wl_list inputs;
 };
@@ -74,6 +77,16 @@ struct wayland_output {
struct wl_egl_window *egl_window;
} parent;
 
+   int keyboard_count;
+
+   struct frame *frame;
+   struct {
+   cairo_surface_t *top;
+   cairo_surface_t *left;
+   cairo_surface_t *right;
+   cairo_surface_t *bottom;
+   } border;
+
struct weston_mode mode;
 };
 
@@ -87,41 +100,23 @@ struct wayland_input {
struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
struct wl_touch *touch;
+
+   struct {
+   struct wl_surface *surface;
+   int32_t hx, hy;
+   } cursor;
} parent;
 
uint32_t key_serial;
uint32_t enter_serial;
int focus;
struct wayland_output *output;
+   struct wayland_output *keyboard_focus;
 };
 
 struct gl_renderer_interface *gl_renderer;
 
 static void
-create_border(struct wayland_compositor *c)
-{
-   pixman_image_t *image;
-   int32_t edges[4];
-
-   image = load_image(DATADIR /weston/border.png);
-   if (!image) {
-   weston_log(couldn't load border image\n);
-   return;
-   }
-
-   edges[0] = c-border.left;
-   edges[1] = c-border.right;
-   edges[2] = c-border.top;
-   edges[3] = c-border.bottom;
-
-   gl_renderer-set_border(c-base, pixman_image_get_width(image),
-   pixman_image_get_height(image),
-   pixman_image_get_data(image), edges);
-
-   pixman_image_unref(image);
-}
-
-static void
 frame_done(void *data, struct wl_callback *callback, uint32_t time)
 {
struct weston_output *output = data;
@@ -159,8 +154,14 @@ draw_initial_frame(struct wayland_output *output)
int fd;
void *data;
 
-   width = output-mode.width + c-border.left + c-border.right;
-   height = output-mode.height + c-border.top + c-border.bottom;
+   if (output-frame) {
+   width = frame_width(output-frame);
+   height = frame_height(output-frame);
+   } else {
+   width = output-mode.width;
+   height = output-mode.height;
+   }
+
stride = width * 4;
size = height * stride;
 
@@ -197,6 +198,76 @@ draw_initial_frame(struct wayland_output *output)
 }
 
 static void
+wayland_output_update_gl_border(struct wayland_output *output)
+{
+   int32_t ix, iy, iwidth, iheight, fwidth, fheight;
+   cairo_t *cr;
+   
+   if (!output-frame)
+   return;
+   if (!(frame_status(output-frame)  FRAME_STATUS_REPAINT))
+   return;
+   
+   fwidth = frame_width(output-frame);
+   fheight = frame_height(output-frame);
+   frame_interior(output-frame, ix, iy, iwidth, iheight);
+
+   if (!output-border.top)
+   output-border.top =
+   cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+  fwidth, iy);
+   cr = cairo_create(output-border.top);
+   frame_repaint(output-frame, cr);
+   cairo_destroy(cr);
+   gl_renderer-output_set_border(output-base, GL_RENDERER_BORDER_TOP,
+  fwidth, 

[PATCH 4/6] gl-renderer: Remove the renderer-global border support

2013-10-20 Thread Jason Ekstrand
This was only ever used by the wayland backend and is no longer used there.

Signed-off-by: Jason Ekstrand ja...@jlekstrand.net
---
 src/gl-renderer.c | 173 +-
 src/gl-renderer.h |   4 --
 2 files changed, 1 insertion(+), 176 deletions(-)

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 7ca5c22..a2c6ec3 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -99,14 +99,7 @@ struct gl_renderer {
EGLContext egl_context;
EGLConfig egl_config;
 
-   struct {
-   int32_t top, bottom, left, right;
-   GLuint texture;
-   int32_t width, height;
-   } border;
-
struct wl_array vertices;
-   struct wl_array indices; /* only used in compositor-wayland */
struct wl_array vtxcnt;
 
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
@@ -678,121 +671,6 @@ draw_output_border(struct weston_output *output)
   full_width, output-border.bottom);
 }
 
-static int
-texture_border(struct weston_output *output)
-{
-   struct weston_compositor *ec = output-compositor;
-   struct gl_renderer *gr = get_renderer(ec);
-   GLfloat *d;
-   unsigned short *p;
-   int i, j, k, n;
-   GLfloat x[4], y[4], u[4], v[4];
-
-   x[0] = -gr-border.left;
-   x[1] = 0;
-   x[2] = output-current_mode-width;
-   x[3] = output-current_mode-width + gr-border.right;
-
-   y[0] = -gr-border.top;
-   y[1] = 0;
-   y[2] = output-current_mode-height;
-   y[3] = output-current_mode-height + gr-border.bottom;
-
-   u[0] = 0.0;
-   u[1] = (GLfloat) gr-border.left / gr-border.width;
-   u[2] = (GLfloat) (gr-border.width - gr-border.right) / 
gr-border.width;
-   u[3] = 1.0;
-
-   v[0] = 0.0;
-   v[1] = (GLfloat) gr-border.top / gr-border.height;
-   v[2] = (GLfloat) (gr-border.height - gr-border.bottom) / 
gr-border.height;
-   v[3] = 1.0;
-
-   n = 8;
-   d = wl_array_add(gr-vertices, n * 16 * sizeof *d);
-   p = wl_array_add(gr-indices, n * 6 * sizeof *p);
-
-   k = 0;
-   for (i = 0; i  3; i++)
-   for (j = 0; j  3; j++) {
-
-   if (i == 1  j == 1)
-   continue;
-
-   d[ 0] = x[i];
-   d[ 1] = y[j];
-   d[ 2] = u[i];
-   d[ 3] = v[j];
-
-   d[ 4] = x[i];
-   d[ 5] = y[j + 1];
-   d[ 6] = u[i];
-   d[ 7] = v[j + 1];
-
-   d[ 8] = x[i + 1];
-   d[ 9] = y[j];
-   d[10] = u[i + 1];
-   d[11] = v[j];
-
-   d[12] = x[i + 1];
-   d[13] = y[j + 1];
-   d[14] = u[i + 1];
-   d[15] = v[j + 1];
-
-   p[0] = k + 0;
-   p[1] = k + 1;
-   p[2] = k + 2;
-   p[3] = k + 2;
-   p[4] = k + 1;
-   p[5] = k + 3;
-
-   d += 16;
-   p += 6;
-   k += 4;
-   }
-
-   return k / 4;
-}
-
-static void
-draw_global_border(struct weston_output *output)
-{
-   struct weston_compositor *ec = output-compositor;
-   struct gl_renderer *gr = get_renderer(ec);
-   struct gl_shader *shader = gr-texture_shader_rgba;
-   GLfloat *v;
-   int n;
-
-   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);
-
-   n = texture_border(output);
-
-   glActiveTexture(GL_TEXTURE0);
-   glBindTexture(GL_TEXTURE_2D, gr-border.texture);
-
-   v = gr-vertices.data;
-   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, v[0]);
-   glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, v[2]);
-   glEnableVertexAttribArray(0);
-   glEnableVertexAttribArray(1);
-
-   glDrawElements(GL_TRIANGLES, n * 6,
-  GL_UNSIGNED_SHORT, gr-indices.data);
-
-   glDisableVertexAttribArray(1);
-   glDisableVertexAttribArray(0);
-
-   gr-vertices.size = 0;
-   gr-indices.size = 0;
-}
-
 static void
 output_get_buffer_damage(struct weston_output *output,
 pixman_region32_t *buffer_damage)
@@ -887,11 +765,7 @@ gl_renderer_repaint_output(struct weston_output *output,
pixman_region32_fini(total_damage);
pixman_region32_fini(buffer_damage);
 
-   if (gr-border.texture) {
-   draw_global_border(output);
-   } else {
-   draw_output_border(output);
-   }
+   draw_output_border(output);
 

[PATCH 5/6] compositor-wayland: Flush the display on commit

2013-10-20 Thread Jason Ekstrand
This fixes the problem where animations will wait to play until input is
recieved.  In general, it also makes the backend far more responsive.

Signed-off-by: Jason Ekstrand ja...@jlekstrand.net
---
 src/compositor-wayland.c | 43 +++
 1 file changed, 23 insertions(+), 20 deletions(-)

diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 54c51a4..5c01a35 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -212,65 +212,67 @@ wayland_output_update_gl_border(struct wayland_output 
*output)
fheight = frame_height(output-frame);
frame_interior(output-frame, ix, iy, iwidth, iheight);
 
-   if (!output-border.top)
-   output-border.top =
+   if (!output-gl.border.top)
+   output-gl.border.top =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
   fwidth, iy);
-   cr = cairo_create(output-border.top);
+   cr = cairo_create(output-gl.border.top);
frame_repaint(output-frame, cr);
cairo_destroy(cr);
gl_renderer-output_set_border(output-base, GL_RENDERER_BORDER_TOP,
   fwidth, iy,
-  
cairo_image_surface_get_stride(output-border.top) / 4,
-  
cairo_image_surface_get_data(output-border.top));
+  
cairo_image_surface_get_stride(output-gl.border.top) / 4,
+  
cairo_image_surface_get_data(output-gl.border.top));
 
 
-   if (!output-border.left)
-   output-border.left =
+   if (!output-gl.border.left)
+   output-gl.border.left =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
   ix, 1);
-   cr = cairo_create(output-border.left);
+   cr = cairo_create(output-gl.border.left);
cairo_translate(cr, 0, -iy);
frame_repaint(output-frame, cr);
cairo_destroy(cr);
gl_renderer-output_set_border(output-base, GL_RENDERER_BORDER_LEFT,
   ix, 1,
-  
cairo_image_surface_get_stride(output-border.left) / 4,
-  
cairo_image_surface_get_data(output-border.left));
+  
cairo_image_surface_get_stride(output-gl.border.left) / 4,
+  
cairo_image_surface_get_data(output-gl.border.left));
 
 
-   if (!output-border.right)
-   output-border.right =
+   if (!output-gl.border.right)
+   output-gl.border.right =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
   fwidth - (ix + iwidth), 1);
-   cr = cairo_create(output-border.right);
+   cr = cairo_create(output-gl.border.right);
cairo_translate(cr, -(iwidth + ix), -iy);
frame_repaint(output-frame, cr);
cairo_destroy(cr);
gl_renderer-output_set_border(output-base, GL_RENDERER_BORDER_RIGHT,
   fwidth - (ix + iwidth), 1,
-  
cairo_image_surface_get_stride(output-border.right) / 4,
-  
cairo_image_surface_get_data(output-border.right));
+  
cairo_image_surface_get_stride(output-gl.border.right) / 4,
+  
cairo_image_surface_get_data(output-gl.border.right));
 
 
-   if (!output-border.bottom)
-   output-border.bottom =
+   if (!output-gl.border.bottom)
+   output-gl.border.bottom =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
   fwidth, fheight - (iy + 
iheight));
-   cr = cairo_create(output-border.bottom);
+   cr = cairo_create(output-gl.border.bottom);
cairo_translate(cr, 0, -(iy + iheight));
frame_repaint(output-frame, cr);
cairo_destroy(cr);
gl_renderer-output_set_border(output-base, GL_RENDERER_BORDER_BOTTOM,
   fwidth, fheight - (iy + iheight),
-  
cairo_image_surface_get_stride(output-border.bottom) / 4,
-  
cairo_image_surface_get_data(output-border.bottom));
+  
cairo_image_surface_get_stride(output-gl.border.bottom) / 4,
+  
cairo_image_surface_get_data(output-gl.border.bottom));
 }
 
 static void
 wayland_output_start_repaint_loop(struct weston_output *output_base)
 {
struct wayland_output *output = (struct wayland_output *) output_base;
+   struct wayland_compositor *wc =
+   (struct wayland_compositor 

[PATCH 6/6] compositor-wayland: Add pixman/SHM fallback mode

2013-10-20 Thread Jason Ekstrand
This also adds a --use-pixman command-line option to enable the pixman
renderer explicitly.

Signed-off-by: Jason Ekstrand ja...@jlekstrand.net
---
 src/compositor-wayland.c | 416 ++-
 src/compositor.c |   1 +
 2 files changed, 342 insertions(+), 75 deletions(-)

diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 5c01a35..3e8e41d 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -36,6 +36,7 @@
 
 #include compositor.h
 #include gl-renderer.h
+#include pixman-renderer.h
 #include ../shared/image-loader.h
 #include ../shared/os-compatibility.h
 #include ../shared/cairo-util.h
@@ -59,6 +60,8 @@ struct wayland_compositor {
uint32_t event_mask;
} parent;
 
+   int use_pixman;
+
struct theme *theme;
cairo_device_t *frame_device;
struct wl_cursor_theme *cursor_theme;
@@ -74,22 +77,45 @@ struct wayland_output {
int draw_initial_frame;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
-   struct wl_egl_window *egl_window;
} parent;
 
int keyboard_count;
 
struct frame *frame;
+
struct {
-   cairo_surface_t *top;
-   cairo_surface_t *left;
-   cairo_surface_t *right;
-   cairo_surface_t *bottom;
-   } border;
+   struct wl_egl_window *egl_window;
+   struct {
+   cairo_surface_t *top;
+   cairo_surface_t *left;
+   cairo_surface_t *right;
+   cairo_surface_t *bottom;
+   } border;
+   } gl;
+
+   struct {
+   struct wl_list buffers;
+   struct wl_list free_buffers;
+   } shm;
 
struct weston_mode mode;
 };
 
+struct wayland_shm_buffer {
+   struct wayland_output *output;
+   struct wl_list link;
+   struct wl_list free_link;
+
+   struct wl_buffer *buffer;
+   void *data;
+   size_t size;
+   pixman_region32_t damage;
+   int frame_damaged;
+
+   pixman_image_t *pm_image;
+   cairo_surface_t *c_surface;
+};
+
 struct wayland_input {
struct weston_seat base;
struct wayland_compositor *compositor;
@@ -117,42 +143,59 @@ struct wayland_input {
 struct gl_renderer_interface *gl_renderer;
 
 static void
-frame_done(void *data, struct wl_callback *callback, uint32_t time)
+wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
 {
-   struct weston_output *output = data;
+   cairo_surface_destroy(buffer-c_surface);
+   pixman_image_unref(buffer-pm_image);
 
-   wl_callback_destroy(callback);
-   weston_output_finish_frame(output, time);
-}
+   wl_buffer_destroy(buffer-buffer);
+   munmap(buffer-data, buffer-size);
 
-static const struct wl_callback_listener frame_listener = {
-   frame_done
-};
+   pixman_region32_fini(buffer-damage);
+   
+   wl_list_remove(buffer-link);
+   wl_list_remove(buffer-free_link);
+   free(buffer);
+}
 
 static void
 buffer_release(void *data, struct wl_buffer *buffer)
 {
-   wl_buffer_destroy(buffer);
+   struct wayland_shm_buffer *sb = data;
+
+   if (sb-output) {
+   wl_list_insert(sb-output-shm.free_buffers, sb-free_link);
+   } else {
+   wayland_shm_buffer_destroy(sb);
+   }
 }
 
 static const struct wl_buffer_listener buffer_listener = {
buffer_release
 };
 
-static void
-draw_initial_frame(struct wayland_output *output)
+static struct wayland_shm_buffer *
+wayland_output_get_shm_buffer(struct wayland_output *output)
 {
struct wayland_compositor *c =
(struct wayland_compositor *) output-base.compositor;
struct wl_shm *shm = c-parent.shm;
-   struct wl_surface *surface = output-parent.surface;
-   struct wl_shm_pool *pool;
-   struct wl_buffer *buffer;
+   struct wayland_shm_buffer *sb;
 
+   struct wl_shm_pool *pool;
int width, height, stride;
-   int size;
+   int32_t fx, fy;
int fd;
-   void *data;
+   unsigned char *data;
+
+   if (!wl_list_empty(output-shm.free_buffers)) {
+   sb = container_of(output-shm.free_buffers.next,
+ struct wayland_shm_buffer, free_link);
+   wl_list_remove(sb-free_link);
+   wl_list_init(sb-free_link);
+
+   return sb;
+   }
 
if (output-frame) {
width = frame_width(output-frame);
@@ -162,39 +205,90 @@ draw_initial_frame(struct wayland_output *output)
height = output-mode.height;
}
 
-   stride = width * 4;
-   size = height * stride;
+   stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
 
-   fd = os_create_anonymous_file(size);
+   fd = os_create_anonymous_file(height * stride);
 

[PATCH 6/6 v2] compositor-wayland: Add pixman/SHM fallback mode

2013-10-20 Thread Jason Ekstrand
This also adds a --use-pixman command-line option to enable the pixman
renderer explicitly.

Signed-off-by: Jason Ekstrand ja...@jlekstrand.net
---

The new version fixes a couple of damage-related bugs.

 src/compositor-wayland.c | 419 ++-
 src/compositor.c |   1 +
 2 files changed, 345 insertions(+), 75 deletions(-)

diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 5c01a35..595e0d4 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -36,6 +36,7 @@
 
 #include compositor.h
 #include gl-renderer.h
+#include pixman-renderer.h
 #include ../shared/image-loader.h
 #include ../shared/os-compatibility.h
 #include ../shared/cairo-util.h
@@ -59,6 +60,8 @@ struct wayland_compositor {
uint32_t event_mask;
} parent;
 
+   int use_pixman;
+
struct theme *theme;
cairo_device_t *frame_device;
struct wl_cursor_theme *cursor_theme;
@@ -74,22 +77,45 @@ struct wayland_output {
int draw_initial_frame;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
-   struct wl_egl_window *egl_window;
} parent;
 
int keyboard_count;
 
struct frame *frame;
+
struct {
-   cairo_surface_t *top;
-   cairo_surface_t *left;
-   cairo_surface_t *right;
-   cairo_surface_t *bottom;
-   } border;
+   struct wl_egl_window *egl_window;
+   struct {
+   cairo_surface_t *top;
+   cairo_surface_t *left;
+   cairo_surface_t *right;
+   cairo_surface_t *bottom;
+   } border;
+   } gl;
+
+   struct {
+   struct wl_list buffers;
+   struct wl_list free_buffers;
+   } shm;
 
struct weston_mode mode;
 };
 
+struct wayland_shm_buffer {
+   struct wayland_output *output;
+   struct wl_list link;
+   struct wl_list free_link;
+
+   struct wl_buffer *buffer;
+   void *data;
+   size_t size;
+   pixman_region32_t damage;
+   int frame_damaged;
+
+   pixman_image_t *pm_image;
+   cairo_surface_t *c_surface;
+};
+
 struct wayland_input {
struct weston_seat base;
struct wayland_compositor *compositor;
@@ -117,42 +143,59 @@ struct wayland_input {
 struct gl_renderer_interface *gl_renderer;
 
 static void
-frame_done(void *data, struct wl_callback *callback, uint32_t time)
+wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
 {
-   struct weston_output *output = data;
+   cairo_surface_destroy(buffer-c_surface);
+   pixman_image_unref(buffer-pm_image);
 
-   wl_callback_destroy(callback);
-   weston_output_finish_frame(output, time);
-}
+   wl_buffer_destroy(buffer-buffer);
+   munmap(buffer-data, buffer-size);
 
-static const struct wl_callback_listener frame_listener = {
-   frame_done
-};
+   pixman_region32_fini(buffer-damage);
+   
+   wl_list_remove(buffer-link);
+   wl_list_remove(buffer-free_link);
+   free(buffer);
+}
 
 static void
 buffer_release(void *data, struct wl_buffer *buffer)
 {
-   wl_buffer_destroy(buffer);
+   struct wayland_shm_buffer *sb = data;
+
+   if (sb-output) {
+   wl_list_insert(sb-output-shm.free_buffers, sb-free_link);
+   } else {
+   wayland_shm_buffer_destroy(sb);
+   }
 }
 
 static const struct wl_buffer_listener buffer_listener = {
buffer_release
 };
 
-static void
-draw_initial_frame(struct wayland_output *output)
+static struct wayland_shm_buffer *
+wayland_output_get_shm_buffer(struct wayland_output *output)
 {
struct wayland_compositor *c =
(struct wayland_compositor *) output-base.compositor;
struct wl_shm *shm = c-parent.shm;
-   struct wl_surface *surface = output-parent.surface;
-   struct wl_shm_pool *pool;
-   struct wl_buffer *buffer;
+   struct wayland_shm_buffer *sb;
 
+   struct wl_shm_pool *pool;
int width, height, stride;
-   int size;
+   int32_t fx, fy;
int fd;
-   void *data;
+   unsigned char *data;
+
+   if (!wl_list_empty(output-shm.free_buffers)) {
+   sb = container_of(output-shm.free_buffers.next,
+ struct wayland_shm_buffer, free_link);
+   wl_list_remove(sb-free_link);
+   wl_list_init(sb-free_link);
+
+   return sb;
+   }
 
if (output-frame) {
width = frame_width(output-frame);
@@ -162,39 +205,90 @@ draw_initial_frame(struct wayland_output *output)
height = output-mode.height;
}
 
-   stride = width * 4;
-   size = height * stride;
+   stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
 
-   fd = os_create_anonymous_file(size);