Re: input handlig in separate thread
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
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
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.
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
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
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
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
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
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);