Re: Texture object locking

2014-06-10 Thread Neil Roberts
Jason wrote:

 Kristian and I were looking at this today, and there seems to be a
 substantial race in the way that we are doing texture locking.

Yes, it does look like this is a problem. I also noticed another
dodgy-looking pattern when implementing the GL_ARB_clear_texture
extension. Whenever it enters a meta function that operates on a
texture image it unlocks the texture object and then does stuff
directly using the texture image pointer. Presumably that pointer
could also be freed at any point. Take a look at
copytexsubimage_using_blit_framebuffer in meta.c for an example.

I suppose in practice though it's probably not all that likely that an
application will go and delete textures in another thread without the
other threads expecting it so I don't know whether it's a major
concern.

I knocked up the following patch to Weston's simple-egl example to try
and get it to crash when deleting textures from multiple threads and
sure enough it does segfault.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)
Subject: Hack to test multi-threaded deleting textures

---
 clients/simple-egl.c | 125 +--
 1 file changed, 112 insertions(+), 13 deletions(-)

diff --git a/clients/simple-egl.c b/clients/simple-egl.c
index 2097b4c..6e592b4 100644
--- a/clients/simple-egl.c
+++ b/clients/simple-egl.c
@@ -39,6 +39,7 @@
 #include GLES2/gl2.h
 #include EGL/egl.h
 #include EGL/eglext.h
+#include pthread.h
 
 #include xdg-shell-client-protocol.h
 
@@ -100,6 +101,13 @@ struct window {
int fullscreen, opaque, buffer_size, frame_sync;
 };
 
+struct thread_data {
+   EGLDisplay dpy;
+   EGLSurface surface;
+   EGLContext ctx;
+   int thread_num;
+};
+
 static const char *vert_shader_text =
uniform mat4 rotation;\n
attribute vec4 pos;\n
@@ -117,15 +125,25 @@ static const char *frag_shader_text =
  gl_FragColor = v_color;\n
}\n;
 
+static const EGLint context_attribs[] = {
+   EGL_CONTEXT_CLIENT_VERSION, 2,
+   EGL_NONE
+};
+
 static int running = 1;
 
+#define N_THREADS 63
+#define N_TEXTURES 512
+#define TEX_SIZE 128
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static uint64_t running_threads;
+static GLuint textures[N_TEXTURES];
+
 static void
 init_egl(struct display *display, struct window *window)
 {
-   static const EGLint context_attribs[] = {
-   EGL_CONTEXT_CLIENT_VERSION, 2,
-   EGL_NONE
-   };
const char *extensions;
 
EGLint config_attribs[] = {
@@ -748,13 +766,101 @@ usage(int error_code)
exit(error_code);
 }
 
+static GLuint
+create_texture(void)
+{
+   GLuint tex;
+   GLubyte data[TEX_SIZE * TEX_SIZE * 4];
+
+   glGenTextures(1, tex);
+   glBindTexture(GL_TEXTURE_2D, tex);
+   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0,
+GL_RGBA, GL_UNSIGNED_BYTE, data);
+   glBindTexture(GL_TEXTURE_2D, 0);
+
+   return tex;
+}
+
+static void *
+thread_func(void *data)
+{
+   struct thread_data *thread_data = data;
+   int i;
+
+   eglMakeCurrent(thread_data-dpy,
+  thread_data-surface,
+  thread_data-surface,
+  thread_data-ctx);
+
+   while (true) {
+   /* Wait until this thread is told to run */
+   pthread_mutex_lock(mutex);
+   while (!(running_threads  (1ULL  thread_data-thread_num)))
+   pthread_cond_wait(cond, mutex);
+   pthread_mutex_unlock(mutex);
+
+   /* Delete all of the textures */
+   for (i = 0; i  N_TEXTURES; i++)
+   glDeleteTextures(1, textures + i);
+
+   /* Report that our thread is no longer running */
+   pthread_mutex_lock(mutex);
+   running_threads = ~(1ULL  thread_data-thread_num);
+   pthread_cond_broadcast(cond);
+   pthread_mutex_unlock(mutex);
+   }
+
+   return data;
+}
+
+static void
+delete_thread_test(struct display *display)
+{
+   pthread_t thread;
+   struct thread_data thread_data[N_THREADS];
+   int i;
+
+   for (i = 0; i  N_THREADS; i++) {
+   thread_data[i].dpy = display-egl.dpy;
+   thread_data[i].surface = display-window-egl_surface;
+   thread_data[i].ctx = eglCreateContext(display-egl.dpy,
+ display-egl.conf,
+ display-egl.ctx,
+ context_attribs);
+   thread_data[i].thread_num = i;
+   pthread_create(thread,
+  NULL, /* attr */
+  thread_func,
+  thread_data + i);
+   }
+
+ 

[PATCH weston] Apply output transform to the cursor while copying into a plane

2014-05-21 Thread Neil Roberts
Previously if the output had a transform then the cursor plane would
be disabled. However as we have to copy the cursor image into a buffer
with the CPU anyway it probably won't cost much extra to also apply
the transform in the process and then we can avoid disabling the
plane.

If the transform is either normal or flipped-180 then a slightly
faster path is used that still copies the lines one at a time with
memcpy. Otherwise there is a slower path which copies one pixel at a
time.

Previously the check for whether to disable the plane was only looking
at whether the output has a transform. However it should probably have
also been disabled if the surface has a transform. This patch changes
it to just look at the surface transform instead. It could be possible
to work out a relative transform and apply that so that any
combinations of transforms will work, but this patch doesn't attempt
that.
---
 src/compositor-drm.c | 120 ---
 1 file changed, 113 insertions(+), 7 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 7d514e4..553454d 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -958,7 +958,7 @@ drm_output_prepare_cursor_view(struct weston_output 
*output_base,
 
if (c-gbm == NULL)
return NULL;
-   if (output-base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
+   if (viewport-buffer.transform != WL_OUTPUT_TRANSFORM_NORMAL)
return NULL;
if (viewport-buffer.scale != output_base-current_scale)
return NULL;
@@ -979,6 +979,102 @@ drm_output_prepare_cursor_view(struct weston_output 
*output_base,
 }
 
 static void
+transform_cursor_buffer_slow(enum wl_output_transform transform,
+uint32_t *buf,
+unsigned char *s,
+int32_t width,
+int32_t height,
+int stride)
+{
+   int angle = transform  3;
+   int swap_xy = transform  1;
+   int flip_x, flip_y;
+   int buf_x_increment, buf_y_increment;
+   int s_y_increment;
+   int sx, sy;
+
+   /* Flip here means we flip the direction of the destination
+* iterators */
+   flip_x = (angle  1) ^ (angle  1);
+   flip_y = (angle  1);
+
+   if (swap_xy) {
+   if (transform  4)
+   flip_y = !flip_y;
+
+   if (flip_y) {
+   buf += (width - 1) * 64;
+   buf_x_increment = -64;
+   } else {
+   buf_x_increment = 64;
+   }
+
+   if (flip_x) {
+   buf += height - 1;
+   buf_y_increment = -1 - buf_x_increment * width;
+   } else {
+   buf_y_increment = 1 - buf_x_increment * width;
+   }
+   } else {
+   if (transform  4)
+   flip_x = !flip_x;
+
+   if (flip_x) {
+   buf += width - 1;
+   buf_x_increment = -1;
+   } else {
+   buf_x_increment = 1;
+   }
+
+   if (flip_y) {
+   buf += (height - 1) * 64;
+   buf_y_increment = -64 - buf_x_increment * width;
+   } else {
+   buf_y_increment = 64 - buf_x_increment * width;
+   }
+   }
+
+   s_y_increment = stride - width * 4;
+
+   for (sy = 0; sy  height; sy++) {
+   for (sx = 0; sx  width; sx++) {
+   memcpy(buf, s, 4);
+   s += 4;
+   buf += buf_x_increment;
+   }
+   s += s_y_increment;
+   buf += buf_y_increment;
+   }
+}
+
+static void
+transform_cursor_buffer(enum wl_output_transform transform,
+   uint32_t *buf,
+   unsigned char *s,
+   int32_t width,
+   int32_t height,
+   int stride)
+{
+   int y;
+
+   switch (transform) {
+   case WL_OUTPUT_TRANSFORM_NORMAL:
+   for (y = 0; y  height; y++)
+   memcpy(buf + y * 64, s + y * stride, width * 4);
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+   for (y = 0; y  height; y++)
+   memcpy(buf + y * 64, s + (height - 1 - y) * stride,
+  width * 4);
+   break;
+   default:
+   transform_cursor_buffer_slow(transform,
+buf, s, width, height, stride);
+   break;
+   }
+}
+
+static void
 drm_output_set_cursor(struct drm_output *output)
 {
struct weston_view *ev = output-cursor_view;
@@ -989,7 +1085,8 @@ drm_output_set_cursor(struct drm_output *output)
struct gbm_bo 

Re: [PATCH 3/4] Add a macro to get the opcode number of a request given the interface

2014-05-20 Thread Neil Roberts
Jason Ekstrand ja...@jlekstrand.net writes:

 Ooh, I like this.  I thought about having wayland-scanner emit more
 #defines, but this works rather nicely.  One question: do we want it in
 wayland-util or wayland-server?  Putting it in wayland-util exposes it
 client-side as well.
 --Jason

Yeah, I agree, perhaps it would make more sense in wayland-server.h.

Thanks for the review.

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


Re: [PATCH weston 1/4] Handle requests using outputs that have been unplugged

2014-05-20 Thread Neil Roberts
Jason Ekstrand ja...@jlekstrand.net writes:

 Yeah, these are the wrong semantics.  If they specify an output and it
 turns out to be a zombie, we should do nothing.  A null output in
 wl_fullscreen_shell.present_surface means put it somewhere.  In the case
 of weston's implementation, it goes on all outputs.  We don't want a
 surface to accidentally end up everywhere when it was intended for a
 particular output.

Ok yes, that makes sense.

 This is a bit ugly. In my original snippit, I pulled a similar stunt
 and stashed the opcode in the implementation implementation pointer.
 Is there some particular reason why you opted for the internal wl_list
 link instead?

Well, the main reason was that I wanted to avoid having to add a
wl_resource_get_implementation function, but I agree it would be cleaner
to just add that as you say.

Thanks for the review.

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


Re: [PATCH weston 1/4] Handle requests using outputs that have been unplugged

2014-05-20 Thread Neil Roberts
Jason Ekstrand ja...@jlekstrand.net writes:

 The destructor passed in here should be 0, why is it ~0? Also, it
 might be a good idea to throw it in a #define or enum for clarity.

The ~0 is meant to signify ‘there is no destructor’, ie, it's a fake
opcode that will never match a request. The reason is that I put this
patch first before the separate patch to handle the wl_output.release
request which changes it to 0. Yes, it would probably be good to have a
define for this but as it was only in one temporary patch I thought it
wasn't worth adding. Maybe just reordering the patches would make it
cleaner.

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


[PATCH] Add wl_resource_get_implementation

2014-05-20 Thread Neil Roberts
This gets the implementation for a resource that was set in the
implementation argument of wl_resource_set_implementation or
wl_resource_set_dispatcher. This is mostly useful in conjuction with a
dispatcher which may want to dispatch via the implementation pointers
or just store some extra information there.
---
 src/wayland-server.c | 6 ++
 src/wayland-server.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index 1c9d4d0..4ce219a 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -1166,6 +1166,12 @@ wl_resource_set_implementation(struct wl_resource 
*resource,
resource-dispatcher = NULL;
 }
 
+WL_EXPORT const void *
+wl_resource_get_implementation(struct wl_resource *resource)
+{
+   return resource-object.implementation;
+}
+
 WL_EXPORT void
 wl_resource_set_dispatcher(struct wl_resource *resource,
   wl_dispatcher_func_t dispatcher,
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 24cd53f..4f56457 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -369,6 +369,8 @@ wl_resource_set_implementation(struct wl_resource *resource,
   const void *implementation,
   void *data,
   wl_resource_destroy_func_t destroy);
+const void *
+wl_resource_get_implementation(struct wl_resource *resource);
 void
 wl_resource_set_dispatcher(struct wl_resource *resource,
   wl_dispatcher_func_t dispatcher,
-- 
1.9.0

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


[PATCH v2] Add a macro to get the opcode number of a request given the interface

2014-05-20 Thread Neil Roberts
Here is a version two of the patch which moves the macro to
wayland-server.h and fixes a typo in the docs.

- Neil

--- 8 --- (use git am --scissors to automatically chop here)

This adds a macro called WL_REQUEST_OPCODE which takes the name of the
struct for the interface and the name of one of its members. It then
calculates the opcode number by dividing the offsetof the member by
the size of a function pointer. This assumes the interface struct only
contains function pointers and that they are in order of the opcodes.
---
 src/wayland-server.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/src/wayland-server.h b/src/wayland-server.h
index 7fc5b47..24cd53f 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -39,6 +39,18 @@ enum {
WL_EVENT_ERROR= 0x08
 };
 
+/**
+ * Gets the opcode of a request from its interface struct
+ *
+ * Given the name of an interface struct and a request within it this
+ * will return the opcode number. For example it can be used like
+ * this:
+ *
+ * int opcode = WL_REQUEST_OPCODE(wl_region_interface, subtract);
+ */
+#define WL_REQUEST_OPCODE(interface, member) \
+   (offsetof(struct interface, member) / sizeof (void (*) (void)))
+
 struct wl_event_loop;
 struct wl_event_source;
 typedef int (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data);
-- 
1.9.0

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


[PATCH weston v2] Handle wl_output.release

2014-05-20 Thread Neil Roberts
Here is a version two of the patch which is just needed so that the
patches can be reordered and this can come before the patch to handle
zombies.

--- 8 --- (use git am --scissors to automatically chop here)

The wl_output.release request is now handled. It just causes the
resource to be destroyed. This is also set as the destructor when
zombifying the resource.
---
 src/compositor.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 574db2d..d3a52bd 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3038,6 +3038,18 @@ weston_compositor_stack_plane(struct weston_compositor 
*ec,
wl_list_insert(ec-plane_list, plane-link);
 }
 
+static void
+output_release(struct wl_client *client,
+  struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static struct wl_output_interface
+output_interface = {
+   output_release
+};
+
 static void unbind_resource(struct wl_resource *resource)
 {
wl_list_remove(wl_resource_get_link(resource));
@@ -3052,14 +3064,15 @@ bind_output(struct wl_client *client,
struct wl_resource *resource;
 
resource = wl_resource_create(client, wl_output_interface,
- MIN(version, 2), id);
+ MIN(version, 3), id);
if (resource == NULL) {
wl_client_post_no_memory(client);
return;
}
 
wl_list_insert(output-resource_list, wl_resource_get_link(resource));
-   wl_resource_set_implementation(resource, NULL, data, unbind_resource);
+   wl_resource_set_implementation(resource, output_interface,
+  data, unbind_resource);
 
wl_output_send_geometry(resource,
output-x,
@@ -3321,7 +3334,7 @@ weston_output_init(struct weston_output *output, struct 
weston_compositor *c,
output-compositor-output_id_pool |= 1  output-id;
 
output-global =
-   wl_global_create(c-wl_display, wl_output_interface, 2,
+   wl_global_create(c-wl_display, wl_output_interface, 3,
 output, bind_output);
wl_signal_emit(c-output_created_signal, output);
 }
-- 
1.9.0

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


[PATCH weston v2] Handle requests using outputs that have been unplugged

2014-05-20 Thread Neil Roberts
Version 2 of the patch makes the following changes:

• The patch is reordered to be on top of the patch to handle
  wl_output.release so that it doesn't need to have a dummy marker for
  zombifying without a destructor.

• The destructor opcode is stored in the implementation pointer rather
  than using the list node. This requires the Wayland patch to add
  wl_resource_get_implementation.

• The wl_fullscreen_shell.present_surface function now bails out if
  the output is a zombie instead of treating it as if it were NULL.

I've pushed the patches to the following two branches to make it a bit
easier to untangle the thread:

https://github.com/bpeel/wayland/commits/wip/output-release
https://github.com/bpeel/weston/commits/wip/output-release

- Neil

--- 8 --- (use git am --scissors to automatically chop here)

Previously when an output was unplugged the clients' resources for it
were left around and if they were used in a request it could cause
Weston to access invalid memory. Now when an output is unplugged the
resources for it are marked as zombies. This is done by setting a
dummy dispatcher and setting the user data to NULL. The dispatcher
ignores all requests except for one which is marked as a destructor.
When the destructor is called the zombie resource will be destroyed.
The opcode for the destructor request is stashed into the
implementation pointer so that it can be compared against all of the
opcodes later.

Any requests that take a wl_output as an argument have also been
patched to take into account that the output can now be a zombie.
These are handled on a case-by-case basis but in general if the
argument is allowed to be NULL then zombie resources will be treated
as such. Otherwise the request is generally completely ignored.

The screenshooter interface is a special case because that has a
callback so we can't really just ignore the request. Instead the
buffer for the screenshot is cleared and the callback is immediately
invoked.

The code for zombifying a resource is based on a snippet by Jason
Esktrand.

https://bugs.freedesktop.org/show_bug.cgi?id=78415
---
 desktop-shell/input-panel.c |  6 +
 desktop-shell/shell.c   | 38 ++---
 fullscreen-shell/fullscreen-shell.c | 13 ++
 src/compositor.c| 33 +
 src/compositor.h|  3 +++
 src/screenshooter.c | 48 +
 6 files changed, 128 insertions(+), 13 deletions(-)

diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c
index 7623f6c..df365fb 100644
--- a/desktop-shell/input-panel.c
+++ b/desktop-shell/input-panel.c
@@ -252,6 +252,12 @@ input_panel_surface_set_toplevel(struct wl_client *client,
struct input_panel_surface *input_panel_surface =
wl_resource_get_user_data(resource);
struct desktop_shell *shell = input_panel_surface-shell;
+   struct weston_output *output;
+
+   output = wl_resource_get_user_data(output_resource);
+   /* Ignore the request if the output has become a zombie */
+   if (output == NULL)
+   return;
 
wl_list_insert(shell-input_panel.surfaces,
   input_panel_surface-link);
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index dd0b2f9..97c5d11 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -2431,10 +2431,12 @@ shell_surface_set_fullscreen(struct wl_client *client,
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
struct weston_output *output;
 
-   if (output_resource)
+   if (output_resource) {
output = wl_resource_get_user_data(output_resource);
-   else
+   /* Output can be NULL here if the resource is a zombie */
+   } else {
output = NULL;
+   }
 
shell_surface_set_parent(shsurf, NULL);
 
@@ -2566,10 +2568,12 @@ shell_surface_set_maximized(struct wl_client *client,
shsurf-type = SHELL_SURFACE_TOPLEVEL;
shell_surface_set_parent(shsurf, NULL);
 
-   if (output_resource)
+   if (output_resource) {
output = wl_resource_get_user_data(output_resource);
-   else
+   /* output can be NULL here if the resource is zombified */
+   } else {
output = NULL;
+   }
 
shell_surface_set_output(shsurf, output);
 
@@ -3487,10 +3491,13 @@ xdg_surface_set_fullscreen(struct wl_client *client,
shsurf-state_requested = true;
shsurf-requested_state.fullscreen = true;
 
-   if (output_resource)
+   if (output_resource) {
output = wl_resource_get_user_data(output_resource);
-   else
+   /* output can still be NULL here if the resource has
+* become a zombie */
+   } else {
output = NULL;
+   }
 
shell_surface_set_output(shsurf, output);

[PATCH weston 1/4] Handle requests using outputs that have been unplugged

2014-05-19 Thread Neil Roberts
Previously when an output was unplugged the clients' resources for it
were left around and if they were used in a request it could cause
Weston to access invalid memory. Now when an output is unplugged the
resources for it are marked as zombies. This is done by setting a
dummy dispatcher and setting the user data to NULL. The dispatcher
ignores all requests except for one which is marked as a destructor.
When the destructor is called the zombie resource will be destroyed.
The opcode for the destructor request is stashed into one of the
pointers in the resource's linked-list node so that it can be compared
against all of the opcodes later. The wl_output interface doesn't
currently have any requests nor a destructor but the intention is that
this mechanism could also be used later for more complicated
interfaces.

Any requests that take a wl_output as an argument have also been
patched to take into account that the output can now be a zombie.
These are handled on a case-by-case basis but in general if the
argument is allowed to be NULL then zombie resources will be treated
as such. Otherwise the request is generally completely ignored.

The screenshooter interface is a special case because that has a
callback so we can't really just ignore the request. Instead the
buffer for the screenshot is cleared and the callback is immediately
invoked.

The code for zombifying a resource is based on a snippet by Jason
Esktrand.

https://bugs.freedesktop.org/show_bug.cgi?id=78415
---
 desktop-shell/input-panel.c |  6 +
 desktop-shell/shell.c   | 38 ++---
 fullscreen-shell/fullscreen-shell.c | 12 ++
 src/compositor.c| 36 
 src/compositor.h|  3 +++
 src/screenshooter.c | 48 +
 6 files changed, 130 insertions(+), 13 deletions(-)

diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c
index 7623f6c..df365fb 100644
--- a/desktop-shell/input-panel.c
+++ b/desktop-shell/input-panel.c
@@ -252,6 +252,12 @@ input_panel_surface_set_toplevel(struct wl_client *client,
struct input_panel_surface *input_panel_surface =
wl_resource_get_user_data(resource);
struct desktop_shell *shell = input_panel_surface-shell;
+   struct weston_output *output;
+
+   output = wl_resource_get_user_data(output_resource);
+   /* Ignore the request if the output has become a zombie */
+   if (output == NULL)
+   return;
 
wl_list_insert(shell-input_panel.surfaces,
   input_panel_surface-link);
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index dd0b2f9..97c5d11 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -2431,10 +2431,12 @@ shell_surface_set_fullscreen(struct wl_client *client,
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
struct weston_output *output;
 
-   if (output_resource)
+   if (output_resource) {
output = wl_resource_get_user_data(output_resource);
-   else
+   /* Output can be NULL here if the resource is a zombie */
+   } else {
output = NULL;
+   }
 
shell_surface_set_parent(shsurf, NULL);
 
@@ -2566,10 +2568,12 @@ shell_surface_set_maximized(struct wl_client *client,
shsurf-type = SHELL_SURFACE_TOPLEVEL;
shell_surface_set_parent(shsurf, NULL);
 
-   if (output_resource)
+   if (output_resource) {
output = wl_resource_get_user_data(output_resource);
-   else
+   /* output can be NULL here if the resource is zombified */
+   } else {
output = NULL;
+   }
 
shell_surface_set_output(shsurf, output);
 
@@ -3487,10 +3491,13 @@ xdg_surface_set_fullscreen(struct wl_client *client,
shsurf-state_requested = true;
shsurf-requested_state.fullscreen = true;
 
-   if (output_resource)
+   if (output_resource) {
output = wl_resource_get_user_data(output_resource);
-   else
+   /* output can still be NULL here if the resource has
+* become a zombie */
+   } else {
output = NULL;
+   }
 
shell_surface_set_output(shsurf, output);
shsurf-fullscreen_output = shsurf-output;
@@ -3919,6 +3926,10 @@ desktop_shell_set_background(struct wl_client *client,
return;
}
 
+   /* Skip the request if the output has become a zombie */
+   if (wl_resource_get_user_data(output_resource) == NULL)
+   return;
+
wl_list_for_each_safe(view, next, surface-views, surface_link)
weston_view_destroy(view);
view = weston_view_create(surface);
@@ -3953,6 +3964,7 @@ desktop_shell_set_panel(struct wl_client *client,
struct desktop_shell *shell = wl_resource_get_user_data(resource);

[PATCH 2/4] Add a release request to wl_output

2014-05-19 Thread Neil Roberts
Outputs can come and go within the compositor. If we don't have a way
for the client to destroy the resource then the resources within the
compositor will effectively leak until the client disconnects. This is
similar to the release event for wl_pointer.
---
 protocol/wayland.xml | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 22eb6e7..d1680f7 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -1652,7 +1652,7 @@
 /request
   /interface
 
-  interface name=wl_output version=2
+  interface name=wl_output version=3
 description summary=compositor output region
   An output describes part of the compositor geometry.  The
   compositor works in the 'compositor coordinate system' and an
@@ -1790,6 +1790,12 @@
   /description
   arg name=factor type=int summary=scaling factor of output/
 /event
+
+!-- Version 3 additions --
+
+request name=release type=destructor since=3
+  description summary=release the output object/
+/request
   /interface
 
   interface name=wl_region version=1
-- 
1.9.0

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


[PATCH weston 4/4] Handle wl_output.release

2014-05-19 Thread Neil Roberts
The wl_output.release request is now handled. It just causes the
resource to be destroyed. This is also set as the destructor when
zombifying the resource.
---
 src/compositor.c | 23 +++
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index ea0c9b4..f9bd25b 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3038,6 +3038,18 @@ weston_compositor_stack_plane(struct weston_compositor 
*ec,
wl_list_insert(ec-plane_list, plane-link);
 }
 
+static void
+output_release(struct wl_client *client,
+  struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static struct wl_output_interface
+output_interface = {
+   output_release
+};
+
 static void unbind_resource(struct wl_resource *resource)
 {
wl_list_remove(wl_resource_get_link(resource));
@@ -3052,14 +3064,15 @@ bind_output(struct wl_client *client,
struct wl_resource *resource;
 
resource = wl_resource_create(client, wl_output_interface,
- MIN(version, 2), id);
+ MIN(version, 3), id);
if (resource == NULL) {
wl_client_post_no_memory(client);
return;
}
 
wl_list_insert(output-resource_list, wl_resource_get_link(resource));
-   wl_resource_set_implementation(resource, NULL, data, unbind_resource);
+   wl_resource_set_implementation(resource, output_interface,
+  data, unbind_resource);
 
wl_output_send_geometry(resource,
output-x,
@@ -3159,7 +3172,9 @@ weston_output_destroy(struct weston_output *output)
wl_global_destroy(output-global);
 
wl_resource_for_each_safe(resource, tmp, output-resource_list)
-   weston_resource_zombify(resource, ~0);
+   weston_resource_zombify(resource,
+   WL_REQUEST_OPCODE(wl_output_interface,
+ release));
 }
 
 static void
@@ -3357,7 +3372,7 @@ weston_output_init(struct weston_output *output, struct 
weston_compositor *c,
output-compositor-output_id_pool |= 1  output-id;
 
output-global =
-   wl_global_create(c-wl_display, wl_output_interface, 2,
+   wl_global_create(c-wl_display, wl_output_interface, 3,
 output, bind_output);
wl_signal_emit(c-output_created_signal, output);
 }
-- 
1.9.0

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


[PATCH 3/4] Add a macro to get the opcode number of a request given the interface

2014-05-19 Thread Neil Roberts
This adds a macro called WL_REQUEST_OPCODE which takes the name of the
struct for the interface and the name of one of its members. It then
calculates the opcode number by dividing the offsetof the member by
the size of a function pointer. This assumes the interface struct only
contains function pointers and that they are in order of the opcodes.
---
 src/wayland-util.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/src/wayland-util.h b/src/wayland-util.h
index fd32826..480a887 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -73,6 +73,18 @@ struct wl_interface {
const struct wl_message *events;
 };
 
+/**
+ * Gets the opcode of a request from its interface struct
+ *
+ * Given the name of an interface struct an a request within it this
+ * will return the opcode number. For example it can be used like
+ * this:
+ *
+ * int opcode = WL_REQUEST_OPCODE(wl_region_interface, subtract);
+ */
+#define WL_REQUEST_OPCODE(interface, member) \
+   (offsetof(struct interface, member) / sizeof (void (*) (void)))
+
 /** \class wl_list
  *
  * \brief doubly-linked list
-- 
1.9.0

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


Re: [PATCH v2] configure.ac: Change in build system to use the path from pkg-config for wayland-scanner.

2014-05-15 Thread Neil Roberts
Hi,

Srivardhan Hebbar sri.heb...@samsung.com writes:

 +AC_PATH_PROG([wayland_scanner], [wayland-scanner],,
 + [${WAYLAND_SCANNER_PATH}])

I don't think it makes much sense to search the path for wayland-scanner
when pkg-config already gives you the complete filename. Instead of
trying to derive a directory to search we could just use the filename
directly and check whether it is executable. Then instead of AC_PATH_PROG it
could do something like this:

AC_MSG_CHECKING([for wayland-scanner])
AS_IF([AS_EXECUTABLE_P([${wayland_scanner}])],
  [AC_MSG_RESULT([${wayland_scanner}])
   AC_SUBST(wayland_scanner)],
  [AC_MSG_RESULT([not found])
   AC_MSG_ERROR([wayland-scanner was not found])])

The --wayland-scanner-path option could also be replaced with something
that would just take the whole filename too.

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


Re: [PATCH] Destroy resources when destroying input and output

2014-05-14 Thread Neil Roberts
After looking at it a bit more I don't think we can really make the
automatic zombie idea work. The trouble is that libwayland-server would
need to know when the client has destroyed the proxy in order to destroy
the zombie resource. However the destroy semantics are
interface-dependent so only an implementation of the interface can know
when the resource is really destroyed.

The wl_output interface doesn't currently have a destructor so in this
particular case it's even worse. I guess if a client binds to an output
then the resource for it has to leak until the client disconnects.

Assuming we later add a release request to wl_output (I think we should)
then I think we would still need to make the zombie handling specific to
the output implementation in Weston. We can't just set the
implementation to NULL because then nothing would destroy the resource
when the release request is called.

Perhaps the best thing to do would be to make Weston swap out the
interface for a simple one that only waits for the release event when an
output is unplugged. We would also have to do this for pointers,
keyboards and touch devices. This could end up with quite a lot of code
because you have to double up all of the implementations. We also have
to be aware of these zombie objects if we ever add any more requests
that can refer to these objects because they would have to check if the
object is a zombie and skip the request.

If there's ever a Wayland 2.0 I think it would be good to make all
interfaces implicitly have a destructor which is handled outside of the
protocol description. I can't think of an interface that shouldn't have
a destructor. Even with wl_callback which is defined to be destroyed
when it is signalled it might make sense to allow the client to destroy
the callback early if it's no longer interested.

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


Re: [PATCH] Destroy resources when destroying input and output

2014-05-09 Thread Neil Roberts
Perhaps we should consider applying the patch anyway even though it's
not ideal. Currently if a client uses a dead output in a request such as
xdg_surface.set_output Weston will end up with a weston_output pointer
that points to freed memory. This could cause the compositor to crash.
That is worse than the alternative provided by this patch which is to
make the client abort. The clients know about the output being destroyed
via the wl_registry.global_remove event so in practice they would only
hit the problem in the unlikely event that they used the output in a
request in the short time between the output being unplugged and
noticing the removal event.

In the longer term I was thinking maybe it would be good to handle the
inert resource idea within libwayland-server. We could add a function
like wl_resource_zombify() which would mark the resource as a zombie and
call the destroy handlers. From the compositor's perspective it can then
act as if the resource has been destroyed. We could detect zombie
resources being used within the request marshalling code and ignore the
request. If the request creates new resource we can internally create
new zombie resources too and Weston would never need to know about it. I
am planning to experiment with this approach now.

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


Re: [PATCH] Destroy resources when destroying input and output

2014-05-09 Thread Neil Roberts
Jason Ekstrand ja...@jlekstrand.net writes:

 Most of the magic there is in allowing resources with no handler in
 libwayland-server. The patch would be about 4 lines. Right now,
 client-side wl_proxy objects are allowed to have a NULL implementation
 and there's no problem; server-side, this is not currently allowed. If
 we allowed this ten Neil's wl_resource_zombify would only have to set
 the destructor, and implementation to NULL. For that matter, we could
 just do that explicitly in weston and not add API for it.

Don't forget that we also want to ignore requests that have zombie
resources as arguments, not just if the resource is directly used as a
target of a request.

It looks like the client-side already has code to handle zombie objects
by putting a marker called WL_ZOMBIE_OBJECT in the ID map. Perhaps we
should use the same mechanism on the server side too.

If a zombie object is received in an event on the client side it looks
like wl_closure_lookup_objects just sets the proxy object to NULL. Is
that safe? Wouldn't the event handlers crash if they get a NULL resource
in an event?

If we can somehow make wl_closure_lookup_objects report when it finds a
zombie object we can make the upper layers just consume the event. We
could do this on both the client and side and the server side.

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


[PATCH weston] Destroy resources when destroying an output

2014-05-08 Thread Neil Roberts
When an output is destroyed it now also destroys any resources that
were pointing to it. Otherwise if the resource is destroyed after the
output then the resource would try to remove itself from the resource
list but the head of the resource list would no longer be valid and it
would write to invalid memory.

This was found using Valgrind. It looks like there is a similar
problem for weston_pointer_destroy and in that case there is even a
comment suggesting we should do something about it.

https://bugs.freedesktop.org/show_bug.cgi?id=78415
---
 src/compositor.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/compositor.c b/src/compositor.c
index cd1ca9a..4162315 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3110,6 +3110,8 @@ weston_compositor_remove_output(struct weston_compositor 
*compositor,
 WL_EXPORT void
 weston_output_destroy(struct weston_output *output)
 {
+   struct wl_resource *resource, *tmp;
+
output-destroying = 1;
 
weston_compositor_remove_output(output-compositor, output);
@@ -3124,6 +3126,9 @@ weston_output_destroy(struct weston_output *output)
output-compositor-output_id_pool = ~(1  output-id);
 
wl_global_destroy(output-global);
+
+   wl_resource_for_each_safe(resource, tmp, output-resource_list)
+   wl_resource_destroy(resource);
 }
 
 static void
-- 
1.9.0

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


[PATCH weston] simple-touch: Handle multiple seats

2014-05-07 Thread Neil Roberts
Previously simple-touch would only handle one seat. If there were
multiple seats it would lose track of whether there is a touch device
available depending on what order the capability events arrive in.
This makes it keep a linked list of seats and to track a separate
touch device for each seat so that it doesn't matter what order they
arrive in.

https://bugs.freedesktop.org/show_bug.cgi?id=78365
---
 clients/simple-touch.c | 77 +++---
 1 file changed, 60 insertions(+), 17 deletions(-)

diff --git a/clients/simple-touch.c b/clients/simple-touch.c
index b5a84d7..a45de46 100644
--- a/clients/simple-touch.c
+++ b/clients/simple-touch.c
@@ -42,18 +42,25 @@ struct touch {
struct wl_compositor *compositor;
struct wl_shell *shell;
struct wl_shm *shm;
-   struct wl_seat *seat;
-   struct wl_touch *wl_touch;
struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
struct wl_buffer *buffer;
+   struct wl_list seats;
int has_argb;
int width, height;
void *data;
 };
 
+struct touch_seat {
+   struct touch *touch;
+   struct wl_touch *wl_touch;
+   struct wl_seat *wl_seat;
+   struct wl_list link;
+   uint32_t name;
+};
+
 static void
 create_shm_buffer(struct touch *touch)
 {
@@ -156,7 +163,8 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
  uint32_t serial, uint32_t time, struct wl_surface *surface,
  int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
 {
-   struct touch *touch = data;
+   struct touch_seat *seat = data;
+   struct touch *touch = seat-touch;
float x = wl_fixed_to_double(x_w);
float y = wl_fixed_to_double(y_w);
 
@@ -173,7 +181,8 @@ static void
 touch_handle_motion(void *data, struct wl_touch *wl_touch,
uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
 {
-   struct touch *touch = data;
+   struct touch_seat *seat = data;
+   struct touch *touch = seat-touch;
float x = wl_fixed_to_double(x_w);
float y = wl_fixed_to_double(y_w);
 
@@ -199,18 +208,18 @@ static const struct wl_touch_listener touch_listener = {
 };
 
 static void
-seat_handle_capabilities(void *data, struct wl_seat *seat,
+seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
 enum wl_seat_capability caps)
 {
-   struct touch *touch = data;
-
-   if ((caps  WL_SEAT_CAPABILITY_TOUCH)  !touch-wl_touch) {
-   touch-wl_touch = wl_seat_get_touch(seat);
-   wl_touch_set_user_data(touch-wl_touch, touch);
-   wl_touch_add_listener(touch-wl_touch, touch_listener, touch);
-   } else if (!(caps  WL_SEAT_CAPABILITY_TOUCH)  touch-wl_touch) {
-   wl_touch_destroy(touch-wl_touch);
-   touch-wl_touch = NULL;
+   struct touch_seat *seat = data;
+
+   if ((caps  WL_SEAT_CAPABILITY_TOUCH)  !seat-wl_touch) {
+   seat-wl_touch = wl_seat_get_touch(wl_seat);
+   wl_touch_set_user_data(seat-wl_touch, seat);
+   wl_touch_add_listener(seat-wl_touch, touch_listener, seat);
+   } else if (!(caps  WL_SEAT_CAPABILITY_TOUCH)  seat-wl_touch) {
+   wl_touch_destroy(seat-wl_touch);
+   seat-wl_touch = NULL;
}
 }
 
@@ -243,6 +252,31 @@ static const struct wl_shell_surface_listener 
shell_surface_listener = {
 };
 
 static void
+add_seat(struct touch *touch, uint32_t name)
+{
+   struct touch_seat *seat;
+
+   seat = malloc(sizeof *seat);
+   seat-touch = touch;
+   seat-wl_seat = wl_registry_bind(touch-registry, name,
+wl_seat_interface, 1);
+   seat-name = name;
+   seat-wl_touch = NULL;
+   wl_seat_add_listener(seat-wl_seat, seat_listener, seat);
+   wl_list_insert(touch-seats, seat-link);
+}
+
+static void
+remove_seat(struct touch_seat *seat)
+{
+   if (seat-wl_touch)
+   wl_touch_destroy(seat-wl_touch);
+   wl_seat_destroy(seat-wl_seat);
+   wl_list_remove(seat-link);
+   free(seat);
+}
+
+static void
 handle_global(void *data, struct wl_registry *registry,
  uint32_t name, const char *interface, uint32_t version)
 {
@@ -261,15 +295,22 @@ handle_global(void *data, struct wl_registry *registry,
  wl_shm_interface, 1);
wl_shm_add_listener(touch-shm, shm_listener, touch);
} else if (strcmp(interface, wl_seat) == 0) {
-   touch-seat = wl_registry_bind(registry, name,
-  wl_seat_interface, 1);
-   wl_seat_add_listener(touch-seat, seat_listener, touch);
+   add_seat(touch, name);
}
 }
 
 static void
 handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
 {

Re: [PATCH weston 2/3] simple-touch: Handle multiple seats properly

2014-05-07 Thread Neil Roberts
Oh no, I didn't notice this patch buried in the patch series and
implemented the same thing:

http://lists.freedesktop.org/archives/wayland-devel/2014-May/014690.html

Ander, it would be really helpful if you could leave a little note on
the bug report if you post a patch to reduce that chance that I'll waste
time looking at the same bug.

Regards,
- Neil

Ander Conselvan de Oliveira conselv...@gmail.com writes:

 From: Ander Conselvan de Oliveira ander.conselvan.de.olive...@intel.com

 If simple-touch ran on a compositor with multiple seats, and the first
 one happened to have the touch capability while the second one didn't,
 the handler for seat capabilities would destroy the wl_touch device it
 created on the first call for the first seat when it was called a again
 for the second seat that has not touch capabilities.

 Fix this problem by creating a separate struct for each seat.

 https://bugs.freedesktop.org/show_bug.cgi?id=78365
 ---
  clients/simple-touch.c | 48 +---
  1 file changed, 33 insertions(+), 15 deletions(-)

 diff --git a/clients/simple-touch.c b/clients/simple-touch.c
 index b5a84d7..d8439ac 100644
 --- a/clients/simple-touch.c
 +++ b/clients/simple-touch.c
 @@ -36,14 +36,18 @@
  
  #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
  
 +struct seat {
 + struct touch *touch;
 + struct wl_seat *seat;
 + struct wl_touch *wl_touch;
 +};
 +
  struct touch {
   struct wl_display *display;
   struct wl_registry *registry;
   struct wl_compositor *compositor;
   struct wl_shell *shell;
   struct wl_shm *shm;
 - struct wl_seat *seat;
 - struct wl_touch *wl_touch;
   struct wl_pointer *pointer;
   struct wl_keyboard *keyboard;
   struct wl_surface *surface;
 @@ -199,18 +203,19 @@ static const struct wl_touch_listener touch_listener = {
  };
  
  static void
 -seat_handle_capabilities(void *data, struct wl_seat *seat,
 +seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
enum wl_seat_capability caps)
  {
 - struct touch *touch = data;
 -
 - if ((caps  WL_SEAT_CAPABILITY_TOUCH)  !touch-wl_touch) {
 - touch-wl_touch = wl_seat_get_touch(seat);
 - wl_touch_set_user_data(touch-wl_touch, touch);
 - wl_touch_add_listener(touch-wl_touch, touch_listener, touch);
 - } else if (!(caps  WL_SEAT_CAPABILITY_TOUCH)  touch-wl_touch) {
 - wl_touch_destroy(touch-wl_touch);
 - touch-wl_touch = NULL;
 + struct seat *seat = data;
 + struct touch *touch = seat-touch;
 +
 + if ((caps  WL_SEAT_CAPABILITY_TOUCH)  !seat-wl_touch) {
 + seat-wl_touch = wl_seat_get_touch(wl_seat);
 + wl_touch_set_user_data(seat-wl_touch, touch);
 + wl_touch_add_listener(seat-wl_touch, touch_listener, touch);
 + } else if (!(caps  WL_SEAT_CAPABILITY_TOUCH)  seat-wl_touch) {
 + wl_touch_destroy(seat-wl_touch);
 + seat-wl_touch = NULL;
   }
  }
  
 @@ -219,6 +224,21 @@ static const struct wl_seat_listener seat_listener = {
  };
  
  static void
 +add_seat(struct touch *touch, uint32_t name, uint32_t version)
 +{
 + struct seat *seat;
 +
 + seat = malloc(sizeof *seat);
 + assert(seat);
 +
 + seat-touch = touch;
 + seat-wl_touch = NULL;
 + seat-seat = wl_registry_bind(touch-registry, name,
 +   wl_seat_interface, 1);
 + wl_seat_add_listener(seat-seat, seat_listener, seat);
 +}
 +
 +static void
  handle_ping(void *data, struct wl_shell_surface *shell_surface,
   uint32_t serial)
  {
 @@ -261,9 +281,7 @@ handle_global(void *data, struct wl_registry *registry,
 wl_shm_interface, 1);
   wl_shm_add_listener(touch-shm, shm_listener, touch);
   } else if (strcmp(interface, wl_seat) == 0) {
 - touch-seat = wl_registry_bind(registry, name,
 -wl_seat_interface, 1);
 - wl_seat_add_listener(touch-seat, seat_listener, touch);
 + add_seat(touch, name, version);
   }
  }
  
 -- 
 1.8.3.2

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


Re: [PATCH 1/3] protocol: Add an event to specify the name of an output

2014-05-06 Thread Neil Roberts
Pekka Paalanen ppaala...@gmail.com writes:

 were you aware of […] perhaps? :-)

Ah, no, I hadn't noticed those patches. Oops!

 Your series is almost identical to Quanxian's, except:
 - wording differences, of course
 - patch 2 checks if output-name is set before sending (can it ever be
   NULL?)
 - patch 2 missed setting the actual protocol object version
 - you add support to weston-info in patch 3
 - Quanxian adds empty handlers to window.c and desktop-shell.c which
   isn't really necessary

Ok, it sounds like it would make the most sense to use Quanxian's
patches without the empty handlers and then land my weston-info patch on
top.

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


[PATCH weston] Apply the zoom transformation before the output transformation

2014-05-06 Thread Neil Roberts
The zoom translation is just a scale and a translate. The translation
is calculated based on the coordinates of the pointer which are in
global space. Previously the calculated translation was transformed by
the output transformation so that when the zoom transform is applied
after the output transform then it will be correct. However if we just
apply the zoom transformation first then we get the same result
without the zoom code having to be aware of the output transformation.

This also fixes weston_output_transform_coordinate which was applying
the output and zoom transforms in the wrong order.

https://bugs.freedesktop.org/show_bug.cgi?id=78211
---
 src/compositor.c |  4 ++--
 src/zoom.c   | 47 ---
 2 files changed, 2 insertions(+), 49 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 3d65e4c..cd1ca9a 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3198,8 +3198,6 @@ weston_output_update_matrix(struct weston_output *output)
2.0 / output-width,
-2.0 / output-height, 1);
 
-   weston_output_compute_transform(output);
-
if (output-zoom.active) {
magnification = 1 / (1 - output-zoom.spring_z.current);
weston_output_update_zoom(output);
@@ -3209,6 +3207,8 @@ weston_output_update_matrix(struct weston_output *output)
magnification, 1.0);
}
 
+   weston_output_compute_transform(output);
+
output-dirty = 0;
 }
 
diff --git a/src/zoom.c b/src/zoom.c
index 622c0d7..7553849 100644
--- a/src/zoom.c
+++ b/src/zoom.c
@@ -111,50 +111,6 @@ zoom_area_center_from_pointer(struct weston_output *output,
 }
 
 static void
-weston_zoom_apply_output_transform(struct weston_output *output,
-   float *x, float *y)
-{
-   float tx, ty;
-
-   switch(output-transform) {
-   case WL_OUTPUT_TRANSFORM_NORMAL:
-   default:
-   return;
-   case WL_OUTPUT_TRANSFORM_90:
-   tx = -*y;
-   ty = *x;
-   break;
-   case WL_OUTPUT_TRANSFORM_180:
-   tx = -*x;
-   ty = -*y;
-   break;
-   case WL_OUTPUT_TRANSFORM_270:
-   tx = *y;
-   ty = -*x;
-   break;
-   case WL_OUTPUT_TRANSFORM_FLIPPED:
-   tx = -*x;
-   ty = *y;
-   break;
-   case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-   tx = -*y;
-   ty = -*x;
-   break;
-   case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-   tx = *x;
-   ty = -*y;
-   break;
-   case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-   tx = *y;
-   ty = *x;
-   break;
-   }
-
-   *x = tx;
-   *y = ty;
-}
-
-static void
 weston_output_update_zoom_transform(struct weston_output *output)
 {
float global_x, global_y;
@@ -183,9 +139,6 @@ weston_output_update_zoom_transform(struct weston_output 
*output)
global_y - output-y) / output-height) *
(level * 2)) - level) * ratio;
 
-   weston_zoom_apply_output_transform(output, output-zoom.trans_x,
-  output-zoom.trans_y);
-
trans_max = level * 2 - level;
trans_min = -trans_max;
 
-- 
1.9.0

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


Thoughts on getting surfaces to appear on the right output

2014-05-02 Thread Neil Roberts
Hi,

Currently Weston has a problem that it always puts new surfaces on the
same output as the one the first pointer is in. I guess the idea is that
most of the time surfaces are created as a result of mouse events and
there is usually only one pointer so it works most of the time. However
of course this doesn't work if a surface is created by a touch event, a
keyboard event or an event from a second pointer. The problem is
mentioned in the following bug report:

https://bugs.freedesktop.org/show_bug.cgi?id=73715

I guess ideally you want the client to explicitly say what output new
surfaces should appear on because only the client knows which input
event caused the new surface to be created. We already have
xdg_shell.set_output which the client could use for this purpose. It
doesn't look like Weston takes that chosen output into account if the
surface is not fullscreen or maximised, but perhaps we could change it
so that it does?

This isn't a complete solution however because when the client first
connects it doesn't know what event caused its process to be executed so
it doesn't know which output to put itself on. This is the case when
panel buttons are used to launch an application from desktop-shell. I
was thinking that maybe we need a request that desktop-shell can make to
specify a default output for new surfaces from the clients that it
launches. To do this I was thinking that maybe desktop-shell could make
a connection to the compositor on behalf of the client, call a request
to set the default output and then pass the socket down to client using
the existing WAYLAND_SOCKET mechanism.

That would be an unusual use of WAYLAND_SOCKET because in the other
cases the socket that is passed down is created with socketpair and is
not first used for any communication. This would have the effect that
wl_display_connect_to_fd is called twice on a connected socket. However,
it doesn't look like any data is sent or any negotiation is done when
that is called so it might not be a problem.

Doing requests on the connection before passing it down might cause the
resource ID numbers to get out of sync. However I was thinking that if
the parent process is careful to destroy any resources that it creates
before forking the child and if the Wayland protocol aggressively reuses
IDs then it might reset back to zero anyway and it would just work.

I was going to experiment with adding this request as a Weston-specific
extension unless someone points out why it won't work. However, I think
this probably shouldn't be Weston-specific because normal clients may
also want to launch child clients in response to an input event and they
too will want to do something similar.

This approach wouldn't help for something like launching clients from a
terminal window because obviously bash isn't going to do this trick
before forking. As a fallback perhaps the positioning mechanism should
be that the surface will appear on the last output that received *any*
input event instead of where one of the pointers is. It's probably
relatively safe to assume that a new surface is related to last input
event.

You could argue that doing that alone would be enough to fix the problem
and we don't need to bother with the new request. However I don't think
it would be very robust in cases where the new application is slow to
start and there are multiple seats. If someone launches LibreOffice on
their seat you don't want the surface to appear on someone else's seat
just because it took a while to start and the other person had clicked a
button in the meantime.

Any thoughts?

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


Re: Thoughts on getting surfaces to appear on the right output

2014-05-02 Thread Neil Roberts
Bill Spitzak spit...@gmail.com writes:

 1. It would seem more useful for the desktop shell to send some info
 about how the client was launched in environment variables.

Yes, maybe it would be cleaner to agree on some protocol for the parent
process to send the information directly to the child. I'm not sure
about using environment variables though because they tend to be
inherited. For example if you used the desktop shell to launch a
terminal then all clients that that terminal launched would end up with
the same environment variables.

 2. If the desktop shell creates the socket, there is no need for it to
 send commands on it. Instead it can directly manipulate the local
 end to have the results of those commands.

The desktop shell is also a client in a separate process so it can't
directly manipulate the compositor's view of the new client without some
sort of protocol.

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


[PATCH weston] Take into account the zoom when applying the output transform

2014-05-01 Thread Neil Roberts
When converting output-relative coordinates (such as from an input
event) to global coordinates it now takes into account the zoom
transform. Previously this would only work for the primary pointer
because the transform doesn't affect the primary pointer position due
to that way zoom follows the mouse. Touch events and multiple pointers
were not working correctly.

https://bugs.freedesktop.org/show_bug.cgi?id=68620
---
 src/compositor.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index ee8dc24..3d65e4c 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -,6 +,7 @@ weston_output_transform_coordinate(struct weston_output 
*output,
 {
wl_fixed_t tx, ty;
wl_fixed_t width, height;
+   float zoom_scale, zx, zy;
 
width = wl_fixed_from_int(output-width * output-current_scale - 1);
height = wl_fixed_from_int(output-height * output-current_scale - 1);
@@ -3373,8 +3374,23 @@ weston_output_transform_coordinate(struct weston_output 
*output,
break;
}
 
-   *x = tx / output-current_scale + wl_fixed_from_int(output-x);
-   *y = ty / output-current_scale + wl_fixed_from_int(output-y);
+   tx /= output-current_scale;
+   ty /= output-current_scale;
+
+   if (output-zoom.active) {
+   zoom_scale = output-zoom.spring_z.current;
+   zx = (wl_fixed_to_double(tx) * (1.0f - zoom_scale) +
+ output-width / 2.0f *
+ (zoom_scale + output-zoom.trans_x));
+   zy = (wl_fixed_to_double(ty) * (1.0f - zoom_scale) +
+ output-height / 2.0f *
+ (zoom_scale + output-zoom.trans_y));
+   tx = wl_fixed_from_double(zx);
+   ty = wl_fixed_from_double(zy);
+   }
+
+   *x = tx + wl_fixed_from_int(output-x);
+   *y = ty + wl_fixed_from_int(output-y);
 }
 
 static void
-- 
1.9.0

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


[PATCH weston] drm: Don't use the cursor overlay if the scale doesn't match

2014-05-01 Thread Neil Roberts
If the scale for the cursor surface doesn't match that of the output
then we shouldn't use the cursor overlay because otherwise it will be
drawn at the wrong size. This problem is particularly noticable with
multiple pointers because it randomly alternates between drawing one
cursor or the other at a larger size depending on which one gets put
in the cursor overlay.
---
 src/compositor-drm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 9d293bc..4441308 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -953,12 +953,15 @@ drm_output_prepare_cursor_view(struct weston_output 
*output_base,
 {
struct drm_compositor *c =
(struct drm_compositor *) output_base-compositor;
+   struct weston_buffer_viewport *viewport = ev-surface-buffer_viewport;
struct drm_output *output = (struct drm_output *) output_base;
 
if (c-gbm == NULL)
return NULL;
if (output-base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
return NULL;
+   if (viewport-buffer.scale != output_base-current_scale)
+   return NULL;
if (output-cursor_view)
return NULL;
if (ev-output_mask != (1u  output_base-id))
-- 
1.9.0

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


[PATCH 1/3] protocol: Add an event to specify the name of an output

2014-04-30 Thread Neil Roberts
This bumps the version of the wl_output interface to 3 and adds a
separate event to report the output's name.
---
 protocol/wayland.xml | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 330f8ab..60fa81e 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -1645,7 +1645,7 @@
 /event
   /interface
 
-  interface name=wl_output version=2
+  interface name=wl_output version=3
 description summary=compositor output region
   An output describes part of the compositor geometry.  The
   compositor works in the 'compositor coordinate system' and an
@@ -1783,6 +1783,17 @@
   /description
   arg name=factor type=int summary=scaling factor of output/
 /event
+
+!-- Version 3 additions --
+
+event name=name since=3
+  description summary=name of the output
+The name event contains a human-readable name for the output.
+If the output has a name then this event is sent after binding
+to the output object.
+  /description
+  arg name=name type=string summary=name of the output/
+/event
   /interface
 
   interface name=wl_region version=1
-- 
1.9.0

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


[PATCH weston 2/3] Send the new wl_output.name event when binding an output

2014-04-30 Thread Neil Roberts
This version for the wl_output interface has been changed to 3 and it
now sends out the name event when a client binds an output.
---
 src/compositor.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/compositor.c b/src/compositor.c
index ee8dc24..6a333df 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3081,6 +3081,9 @@ bind_output(struct wl_client *client,
mode-refresh);
}
 
+   if (version = 3  output-name)
+   wl_output_send_name(resource, output-name);
+
if (version = 2)
wl_output_send_done(resource);
 }
@@ -3321,7 +3324,7 @@ weston_output_init(struct weston_output *output, struct 
weston_compositor *c,
output-compositor-output_id_pool |= 1  output-id;
 
output-global =
-   wl_global_create(c-wl_display, wl_output_interface, 2,
+   wl_global_create(c-wl_display, wl_output_interface, 3,
 output, bind_output);
wl_signal_emit(c-output_created_signal, output);
 }
-- 
1.9.0

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


[PATCH weston 3/3] weston-info: Display the name from the new wl_output.name event

2014-04-30 Thread Neil Roberts
If the compositor supports version 3 of the wl_output interface and
sends a name event then this will now be displayed in the info.
---
 clients/weston-info.c | 39 ++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/clients/weston-info.c b/clients/weston-info.c
index df869e3..05edd21 100644
--- a/clients/weston-info.c
+++ b/clients/weston-info.c
@@ -59,6 +59,8 @@ struct output_info {
 
struct wl_output *output;
 
+   char *name;
+
struct {
int32_t x, y;
int32_t physical_width, physical_height;
@@ -160,6 +162,9 @@ print_output_info(void *data)
 
print_global_info(data);
 
+   if (output-name)
+   printf(\tname: %s\n, output-name);
+
switch (output-geometry.subpixel) {
case WL_OUTPUT_SUBPIXEL_UNKNOWN:
subpixel_orientation = unknown;
@@ -423,9 +428,35 @@ output_handle_mode(void *data, struct wl_output *wl_output,
wl_list_insert(output-modes.prev, mode-link);
 }
 
+static void
+output_handle_name(void *data,
+struct wl_output *wl_output,
+const char *name)
+{
+   struct output_info *output = data;
+
+   output-name = xstrdup(name);
+}
+
+static void
+output_handle_done(void *data,
+  struct wl_output *wl_output)
+{
+}
+
+static void
+output_handle_scale(void *data,
+   struct wl_output *wl_output,
+   int32_t factor)
+{
+}
+
 static const struct wl_output_listener output_listener = {
output_handle_geometry,
output_handle_mode,
+   output_handle_done,
+   output_handle_scale,
+   output_handle_name,
 };
 
 static void
@@ -440,6 +471,8 @@ destroy_output_info(void *data)
free(output-geometry.make);
if (output-geometry.model != NULL)
free(output-geometry.model);
+   if (output-name != NULL)
+   free(output-name);
 
wl_list_for_each_safe(mode, tmp, output-modes, link) {
wl_list_remove(mode-link);
@@ -458,8 +491,12 @@ add_output_info(struct weston_info *info, uint32_t id, 
uint32_t version)
 
wl_list_init(output-modes);
 
+   if (version  3)
+   version = 3;
+
output-output = wl_registry_bind(info-registry, id,
- wl_output_interface, 1);
+ wl_output_interface,
+ version);
wl_output_add_listener(output-output, output_listener,
   output);
 
-- 
1.9.0

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


[PATCH weston] Simply the matrix calculation for zooming

2014-04-25 Thread Neil Roberts
In order to apply the zoom transformation to the output matrix, Weston was
doing the following:

• Create a temporary matrix to hold the translation
• Invert the translation matrix using weston_matrix_invert into
  another temporary matrix
• Scale that matrix by the scale factor
• Multiply the current matrix with the temporary matrix

Using weston_matrix_invert to invert a translation matrix is over the top.
Instead we can just negate the values we pass to weston_matrix_translate.
Matrix multiplication is associative so creating a temporary matrix to hold the
scale and translation transform should be equivalent to just applying them
directly to the output matrix.
---
 src/compositor.c | 13 -
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index fd2decb..f836cf7 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3186,8 +3186,6 @@ WL_EXPORT void
 weston_output_update_matrix(struct weston_output *output)
 {
float magnification;
-   struct weston_matrix camera;
-   struct weston_matrix modelview;
 
weston_matrix_init(output-matrix);
weston_matrix_translate(output-matrix,
@@ -3202,14 +3200,11 @@ weston_output_update_matrix(struct weston_output 
*output)
 
if (output-zoom.active) {
magnification = 1 / (1 - output-zoom.spring_z.current);
-   weston_matrix_init(camera);
-   weston_matrix_init(modelview);
weston_output_update_zoom(output);
-   weston_matrix_translate(camera, output-zoom.trans_x,
-   -output-zoom.trans_y, 0);
-   weston_matrix_invert(modelview, camera);
-   weston_matrix_scale(modelview, magnification, magnification, 
1.0);
-   weston_matrix_multiply(output-matrix, modelview);
+   weston_matrix_translate(output-matrix, -output-zoom.trans_x,
+   output-zoom.trans_y, 0);
+   weston_matrix_scale(output-matrix, magnification,
+   magnification, 1.0);
}
 
output-dirty = 0;
-- 
1.9.0

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


Re: [PATCH weston 3/4] evdev: Fix assertion error for unplugged output with paired touchscreen

2014-04-24 Thread Neil Roberts
I think I wrote the goto handled code. The advantage of that over
putting the assert in the default handler is that if a new event type is
added to the evdev_event_type enum then GCC will give a nice warning for
that switch statement so we'd know we need to add a handler for it.

I think I would personally prefer to change the breaks to be ‘goto
handled’ too but I suppose that is a trade off for readability so I
won't complain either way.

The rest of the patches look good to me. I've tested it briefly and I
don't get the crashes anymore.

Regards,
- Neil

Ander Conselvan de Oliveira conselv...@gmail.com writes:

 From: Ander Conselvan de Oliveira ander.conselvan.de.olive...@intel.com

 If the output a touchscreen is paired to is unplugged, events coming
 from it should be ignored. Commit 17bccaed introduced logic for that
 in evdev_flush_pending_damage(). However, the break statements it
 introduced would cause the assertion after the switch statement to
 fail.

 That function has the odd behavior that goto's are used to skip the
 assertion after the switch statement and jump to the hunk of code that
 marks the event as processed. Only in the case where the event type has
 an invalid value the assertion should trigger. So this patch fixes the
 problem by moving the assertion into the default case of the switch
 and replacing the goto statements with break ones.

 https://bugs.freedesktop.org/show_bug.cgi?id=73950
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH weston] Assign any output to a seat if it doesn't have one

2014-04-23 Thread Neil Roberts
Commit 4ade0e4a29 changed the order of initialising the seats and outputs so
that the seats would be done before the outputs. However the device_added
function in libinput-seat and udev-seat which gets called during initialisation
was trying to use the output list to assign an output to the device. If the
device doesn't have an output name associated with it then it would just use
the first output in the list. At this point during the initialisation the
output list is empty so it would actually end up with a garbage pointer and it
would later crash when a touch event tries to access the details of the output.

This patch changes it to only assign an output to the device if the output list
is not empty. That way the device's output will remain NULL during the
initialisation. It now also assigns the first output that is created to the
device during notify_output_create if it does not already have an output. If a
later output is created which matches the device's output name then that will
replace the selected output as before.
---
 src/libinput-seat.c | 10 ++
 src/udev-seat.c | 10 ++
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/libinput-seat.c b/src/libinput-seat.c
index 8bf538c..bea8f6e 100644
--- a/src/libinput-seat.c
+++ b/src/libinput-seat.c
@@ -86,7 +86,7 @@ device_added(struct udev_input *input, struct libinput_device 
*libinput_device)
evdev_device_set_output(device, output);
}
 
-   if (device-output == NULL) {
+   if (device-output == NULL  !wl_list_empty(c-output_list)) {
output = container_of(c-output_list.next,
  struct weston_output, link);
evdev_device_set_output(device, output);
@@ -316,11 +316,13 @@ notify_output_create(struct wl_listener *listener, void 
*data)
struct evdev_device *device;
struct weston_output *output = data;
 
-   wl_list_for_each(device, seat-devices_list, link)
-   if (device-output_name 
-   strcmp(output-name, device-output_name) == 0) {
+   wl_list_for_each(device, seat-devices_list, link) {
+   if (device-output == NULL ||
+   (device-output_name 
+strcmp(output-name, device-output_name) == 0)) {
evdev_device_set_output(device, output);
}
+   }
 }
 
 static struct udev_seat *
diff --git a/src/udev-seat.c b/src/udev-seat.c
index 5e018de..853a15c 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -127,7 +127,7 @@ device_added(struct udev_device *udev_device, struct 
udev_input *input)
evdev_device_set_output(device, output);
}
 
-   if (device-output == NULL) {
+   if (device-output == NULL  !wl_list_empty(c-output_list)) {
output = container_of(c-output_list.next,
  struct weston_output, link);
evdev_device_set_output(device, output);
@@ -359,11 +359,13 @@ notify_output_create(struct wl_listener *listener, void 
*data)
struct evdev_device *device;
struct weston_output *output = data;
 
-   wl_list_for_each(device, seat-devices_list, link)
-   if (device-output_name 
-   strcmp(output-name, device-output_name) == 0) {
+   wl_list_for_each(device, seat-devices_list, link) {
+   if (device-output == NULL ||
+   (device-output_name 
+strcmp(output-name, device-output_name) == 0)) {
evdev_device_set_output(device, output);
}
+   }
 }
 
 static struct udev_seat *
-- 
1.9.0

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


Re: [PATCH weston 4/4] input: Fix errors due to initializing input before creating outputs

2014-04-23 Thread Neil Roberts
I think we accientally wrote nearly identical patches at the same time:

http://lists.freedesktop.org/archives/wayland-devel/2014-April/014392.html

However, I still get the crash with Ander's patch because it looks like
it is missing the check for wl_list_empty in the libinput-seat.c version
of device_added.

I think it would make sense to fix this patch and use it rather than my
version because my one assumes the old behaviour where if we can't find
an output with the right name for a seat then we default to using any
output. This is changed in patch 1 of Ander's series. I think Ander's
approach is more robust. Ie, if we can't find an output for a seat that
has an explicit output name then we just ignore events for it.

However I notice that patch 1 of the series also doesn't make this
revert for the libinput-seat.c version of device_added so that will
still maintain the behaviour of resorting to a default output from this
commit:

http://cgit.freedesktop.org/wayland/weston/commit/?id=161c6c56944cdfbda

- Neil

Ander Conselvan de Oliveira conselv...@gmail.com writes:

 From: Ander Conselvan de Oliveira ander.conselvan.de.olive...@intel.com

 Make sure that we don't map a device to an invalid output pointer and
 intead remap devices when an output is created.
 ---
  src/evdev.c   | 2 +-
  src/libinput-device.c | 2 +-
  src/libinput-seat.c   | 6 +-
  src/udev-seat.c   | 8 ++--
  4 files changed, 13 insertions(+), 5 deletions(-)

 diff --git a/src/evdev.c b/src/evdev.c
 index ff951d3..888dfbd 100644
 --- a/src/evdev.c
 +++ b/src/evdev.c
 @@ -601,7 +601,7 @@ notify_output_destroy(struct wl_listener *listener, void 
 *data)
   struct weston_compositor *c = device-seat-compositor;
   struct weston_output *output;
  
 - if (!device-output_name) {
 + if (!device-output_name  !wl_list_empty(c-output_list)) {
   output = container_of(c-output_list.next,
 struct weston_output, link);
   evdev_device_set_output(device, output);
 diff --git a/src/libinput-device.c b/src/libinput-device.c
 index 753583a..4605a76 100644
 --- a/src/libinput-device.c
 +++ b/src/libinput-device.c
 @@ -264,7 +264,7 @@ notify_output_destroy(struct wl_listener *listener, void 
 *data)
   struct weston_compositor *c = device-seat-compositor;
   struct weston_output *output;
  
 - if (!device-output_name) {
 + if (!device-output_name  !wl_list_empty(c-output_list)) {
   output = container_of(c-output_list.next,
 struct weston_output, link);
   evdev_device_set_output(device, output);
 diff --git a/src/libinput-seat.c b/src/libinput-seat.c
 index 8bf538c..e900744 100644
 --- a/src/libinput-seat.c
 +++ b/src/libinput-seat.c
 @@ -316,11 +316,15 @@ notify_output_create(struct wl_listener *listener, void 
 *data)
   struct evdev_device *device;
   struct weston_output *output = data;
  
 - wl_list_for_each(device, seat-devices_list, link)
 + wl_list_for_each(device, seat-devices_list, link) {
   if (device-output_name 
   strcmp(output-name, device-output_name) == 0) {
   evdev_device_set_output(device, output);
   }
 +
 + if (device-output_name == NULL  device-output == NULL)
 + evdev_device_set_output(device, output);
 + }
  }
  
  static struct udev_seat *
 diff --git a/src/udev-seat.c b/src/udev-seat.c
 index dfeb17f..93984e1 100644
 --- a/src/udev-seat.c
 +++ b/src/udev-seat.c
 @@ -125,7 +125,7 @@ device_added(struct udev_device *udev_device, struct 
 udev_input *input)
   wl_list_for_each(output, c-output_list, link)
   if (strcmp(output-name, device-output_name) == 0)
   evdev_device_set_output(device, output);
 - } else if (device-output == NULL) {
 + } else if (device-output == NULL  !wl_list_empty(c-output_list)) {
   output = container_of(c-output_list.next,
 struct weston_output, link);
   evdev_device_set_output(device, output);
 @@ -357,11 +357,15 @@ notify_output_create(struct wl_listener *listener, void 
 *data)
   struct evdev_device *device;
   struct weston_output *output = data;
  
 - wl_list_for_each(device, seat-devices_list, link)
 + wl_list_for_each(device, seat-devices_list, link) {
   if (device-output_name 
   strcmp(output-name, device-output_name) == 0) {
   evdev_device_set_output(device, output);
   }
 +
 + if (device-output_name == NULL  device-output == NULL)
 + evdev_device_set_output(device, output);
 + }
  }
  
  static struct udev_seat *
 -- 
 1.8.3.2

 ___
 wayland-devel mailing list
 wayland-devel@lists.freedesktop.org
 

[PATCH weston] clients/window: Don't remove the touch listener on a frame event

2014-04-23 Thread Neil Roberts
It looks like the handler for frame events from the wl_touch interface for
widgets may have been erroneously copied from the cancel handler so that it
removes all handlers as they are processed. I don't think this makes much sense
for the frame event. This was stopping the panel icons from being pushable with
touch events when using libinput since commit 1679f232e541489e. All that commit
does it make it start sending the frame events.
---
 clients/window.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index e770a04..e2f7010 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -3065,9 +3065,6 @@ touch_handle_frame(void *data, struct wl_touch *wl_touch)
if (tp-widget-touch_frame_handler)
(*tp-widget-touch_frame_handler)(tp-widget, input, 
   
tp-widget-user_data);
-
-   wl_list_remove(tp-link);
-   free(tp);
}
 }
 
-- 
1.9.0

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


Re: [PATCH weston] compositor-drm: Fix crash when setting up seat constrained by an output

2014-04-22 Thread Neil Roberts
It looks like this patch makes Weston crash on touch events.

The device_added functions in udev-seat.c and libinput-seat.c try to use
the output list in order to assign the output for the newly created
device. These functions get called via udev_input_init so I guess that
means this function and create_outputs now depend on each other making a
chicken and egg situation. If the device_added function can't find an
output for the new device then it defaults to first output in the list.
However since this patch the output list is now empty at that point so
it ends up with a garbage pointer for the output. When the input code
tries to handle an absolute event (eg, a touch event) then it tries to
get the width and height from the current mode of the output for the
device but this is now garbage. For me with libinput this causes it to
segfault whereas without libinput it gets garbage width and height
values and causes a floating point exception later on.

I haven't looked any further to decide what's the best thing to do.

- Neil

Ander Conselvan de Oliveira conselv...@gmail.com writes:

 From: Ander Conselvan de Oliveira ander.conselvan.de.olive...@intel.com

 Commit 58e15865 changed the parameters for udev_get_seat_by_name() to
 receive a struct udev_input. However, when this gets called from
 create_output_from_connector() during initialization, the input struct
 is not yet initialized, leading to a crash. Previously, that function
 would take only a pointer to the compositor.

 This patch fixes the crash by initializing input before creating any
 outputs.

 https://bugs.freedesktop.org/show_bug.cgi?id=77503
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: An idea for a newbie project: Wayland protocol dumper

2014-04-09 Thread Neil Roberts
I think this could be really useful. I've struggled a few times trying
to filter the output from WAYLAND_DEBUG=server when I only want to know
about a particular client.

Pekka Paalanen ppaala...@gmail.com writes:

 - Some messages carry file descriptors. Is it possible to write a
 proxy without having the protocol definition (XML files) needed to
 decode the messages? If not, the dumper won't work for unknown
 protocol extensions.

The file descriptors come out-of-band as ‘control data’. Presumably we
could make the tracer always read the control data when it reads from
the socket and if it sees a file descriptor it can just pass it on
without having to understand the protocol.

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


[PATCH weston 1/2] Reset focus on unknown seats when restoring focus state

2014-04-09 Thread Neil Roberts
The focus_state list on a workspace only contains entries for seats
which have a keyboard focus on that workspace. For workspaces that
have no surfaces the list will be empty. That means that when a
workspace with no surfaces is switched to it would previously leave
the keyboard focus unaffected and you could still type in the surface
on the old workspace.

This patch makes it instead reset the keyboard focus to NULL for seats
without a focus_state. It does this by temporarily stealing the
compositor's list of seats while it iterates the focus_states. After
all of the focus states have been processed any seats remaining in
this temporary list have their focus reset.

https://bugs.freedesktop.org/show_bug.cgi?id=73905
---
 desktop-shell/shell.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 466ea93..fa081f3 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -694,8 +694,20 @@ restore_focus_state(struct desktop_shell *shell, struct 
workspace *ws)
 {
struct focus_state *state, *next;
struct weston_surface *surface;
+   struct wl_list pending_seat_list;
+   struct weston_seat *seat, *next_seat;
+
+   /* Temporarily steal the list of seats so that we can keep
+* track of the seats we've already processed */
+   wl_list_init(pending_seat_list);
+   wl_list_insert_list(pending_seat_list, shell-compositor-seat_list);
+   wl_list_init(shell-compositor-seat_list);
 
wl_list_for_each_safe(state, next, ws-focus_list, link) {
+   wl_list_remove(state-seat-link);
+   wl_list_insert(shell-compositor-seat_list,
+  state-seat-link);
+
if (state-seat-keyboard == NULL)
continue;
 
@@ -703,6 +715,17 @@ restore_focus_state(struct desktop_shell *shell, struct 
workspace *ws)
 
weston_keyboard_set_focus(state-seat-keyboard, surface);
}
+
+   /* For any remaining seats that we don't have a focus state
+* for we'll reset the keyboard focus to NULL */
+   wl_list_for_each_safe(seat, next_seat, pending_seat_list, link) {
+   wl_list_insert(shell-compositor-seat_list, seat-link);
+
+   if (state-seat-keyboard == NULL)
+   continue;
+
+   weston_keyboard_set_focus(seat-keyboard, NULL);
+   }
 }
 
 static void
-- 
1.8.5.3

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


[PATCH weston 2/2] Reset the keyboard focus on all seats when the compositor is locked

2014-04-09 Thread Neil Roberts
Before commit 2f5faff7f9142 when the compositor is locked it would
reset the keyboard focus on all of the seats as part of pushing the
focus_state. This was removed because it now always keeps track of the
focus_state in the workspace instead of waiting until the state is
pushed. However this had the side effect that the active surface would
retain focus when the compositor is locked. This patch just makes it
explicitly set the keyboard focus to NULL on all of the seats when
locking. This will be restored based on the workspace's state when
unlocking.

https://bugs.freedesktop.org/show_bug.cgi?id=73905
---
 desktop-shell/shell.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index fa081f3..b19965f 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -4498,6 +4498,19 @@ touch_to_activate_binding(struct weston_seat *seat, 
uint32_t time, void *data)
 }
 
 static void
+unfocus_all_seats(struct desktop_shell *shell)
+{
+   struct weston_seat *seat, *next;
+
+   wl_list_for_each_safe(seat, next, shell-compositor-seat_list, link) {
+   if (seat-keyboard == NULL)
+   continue;
+
+   weston_keyboard_set_focus(seat-keyboard, NULL);
+   }
+}
+
+static void
 lock(struct desktop_shell *shell)
 {
struct workspace *ws = get_current_workspace(shell);
@@ -4523,6 +4536,11 @@ lock(struct desktop_shell *shell)
 
launch_screensaver(shell);
 
+   /* Remove the keyboard focus on all seats. This will be
+* restored to the workspace's saved state via
+* restore_focus_state when the compositor is unlocked */
+   unfocus_all_seats(shell);
+
/* TODO: disable bindings that should not work while locked. */
 
/* All this must be undone in resume_desktop(). */
-- 
1.8.5.3

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


Re: [PATCH weston 2/2] Reset the keyboard focus on all seats when the compositor is locked

2014-04-09 Thread Neil Roberts
Jasper St. Pierre jstpie...@mecheye.net writes:

 Why is this necessary? Won't events never be delivered while locked
 anyway?

Events do seem to get delivered, you can try it if you run weston -i5
and then open a terminal and let it lock. You can still type in the
terminal and launch programs.

But yeah, I guess an alternative solution could be to block it at a
lower level in the input handling code. I'm not sure whether that's a
good idea though because eventually we might want a password entry or
something on the lock screen and then we would want the keyboard to
work. It would a shame to have to put too much special magic in there to
get that to work.

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


[PATCH weston] gl-renderer: Keep track of the GL format used for SHM buffers

2014-04-07 Thread Neil Roberts
Jason Ekstrand wrote:

 We may still have a problem if the client changes buffer formats
 mid-stream. Say it starts out with RGB565 to save memory but latter
 decides it wants alpha so it switches to ARGB. We should
 probably detect this and make sure glTexImage2D gets called again to
 reset the internal format.

Yeah, you're right. I think it would be good to fix this especially
now that we support multiple outputs with different formats. It's not
entirely unlikely that a client might try to detect when it is moved
from one output to another with a different bit depth and then try to
switch buffer depths. The original patch has already landed in master
so here is an extra patch.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

If the client attaches a new SHM buffer with a different format from a
previous one then we ought to trigger a full upload so that GL can
allocate a new texture. Otherwise Weston would technically be doing
invalid operations because it would call glTexSubImage2D with a
different format from the one specified in glTexImage2D. Presumably it
would also mean GL would have to convert the buffer as it copies the
sub-region in which isn't ideal.

This patch makes it decide the GL format when the buffer is attached
instead of when processing the damage and it will set
needs_full_upload if it is different from what it used before.
---
 src/gl-renderer.c | 45 ++---
 1 file changed, 22 insertions(+), 23 deletions(-)

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 1cebc79..f534f51 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -90,6 +90,12 @@ struct gl_surface_state {
int needs_full_upload;
pixman_region32_t texture_damage;
 
+   /* These are only used by SHM surfaces to detect when we need
+* to do a full upload to specify a new internal texture
+* format */
+   GLenum gl_format;
+   GLenum gl_pixel_type;
+
EGLImageKHR images[3];
GLenum target;
int num_images;
@@ -998,8 +1004,6 @@ gl_renderer_flush_damage(struct weston_surface *surface)
struct weston_buffer *buffer = gs-buffer_ref.buffer;
struct weston_view *view;
int texture_used;
-   GLenum format;
-   int pixel_type;
 
 #ifdef GL_EXT_unpack_subimage
pixman_box32_t *rectangles;
@@ -1032,29 +1036,13 @@ gl_renderer_flush_damage(struct weston_surface *surface)
!gs-needs_full_upload)
goto done;
 
-   switch (wl_shm_buffer_get_format(buffer-shm_buffer)) {
-   case WL_SHM_FORMAT_XRGB:
-   case WL_SHM_FORMAT_ARGB:
-   format = GL_BGRA_EXT;
-   pixel_type = GL_UNSIGNED_BYTE;
-   break;
-   case WL_SHM_FORMAT_RGB565:
-   format = GL_RGB;
-   pixel_type = GL_UNSIGNED_SHORT_5_6_5;
-   break;
-   default:
-   weston_log(warning: unknown shm buffer format\n);
-   format = GL_BGRA_EXT;
-   pixel_type = GL_UNSIGNED_BYTE;
-   }
-
glBindTexture(GL_TEXTURE_2D, gs-textures[0]);
 
if (!gr-has_unpack_subimage) {
wl_shm_buffer_begin_access(buffer-shm_buffer);
-   glTexImage2D(GL_TEXTURE_2D, 0, format,
+   glTexImage2D(GL_TEXTURE_2D, 0, gs-gl_format,
 gs-pitch, buffer-height, 0,
-format, pixel_type,
+gs-gl_format, gs-gl_pixel_type,
 wl_shm_buffer_get_data(buffer-shm_buffer));
wl_shm_buffer_end_access(buffer-shm_buffer);
 
@@ -1069,9 +1057,9 @@ gl_renderer_flush_damage(struct weston_surface *surface)
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
wl_shm_buffer_begin_access(buffer-shm_buffer);
-   glTexImage2D(GL_TEXTURE_2D, 0, format,
+   glTexImage2D(GL_TEXTURE_2D, 0, gs-gl_format,
 gs-pitch, buffer-height, 0,
-format, pixel_type, data);
+gs-gl_format, gs-gl_pixel_type, data);
wl_shm_buffer_end_access(buffer-shm_buffer);
goto done;
}
@@ -1087,7 +1075,7 @@ gl_renderer_flush_damage(struct weston_surface *surface)
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
r.x2 - r.x1, r.y2 - r.y1,
-   format, pixel_type, data);
+   gs-gl_format, gs-gl_pixel_type, data);
}
wl_shm_buffer_end_access(buffer-shm_buffer);
 #endif
@@ -1127,6 +1115,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct 
weston_buffer *buffer,
struct weston_compositor *ec = es-compositor;
struct gl_renderer 

[PATCH weston] Always use glTexImage2D instead of glTexSubImage2D for first upload

2014-04-04 Thread Neil Roberts
Previously when uploading SHM data we would initialise the texture
with glTexImage2D and NULL data when the buffer is attached. Then if
the GL_EXT_unpack_subimage extension is available we would always use
glTexSubImage2D to upload the data. The problem with that is that the
first glTexImage2D was always setting the internal format to
GL_BGRA_EXT and then if a 16-bit texture is used we would later call
glTexSubImage2D with a data format of GL_RGBA. Under GLES2 the
internal format must always match the data format so this is
technically invalid.

This patch makes it so that it always calls glTexImage2D when flushing
the damage for the first time. That way it will use the right internal
format and we don't need to call glTexImage2D with NULL data.

https://bugs.freedesktop.org/show_bug.cgi?id=75251
---
 src/gl-renderer.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 6ef1240..1cebc79 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -1069,9 +1069,9 @@ gl_renderer_flush_damage(struct weston_surface *surface)
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
wl_shm_buffer_begin_access(buffer-shm_buffer);
-   glTexSubImage2D(GL_TEXTURE_2D, 0,
-   0, 0, gs-pitch, buffer-height,
-   format, pixel_type, data);
+   glTexImage2D(GL_TEXTURE_2D, 0, format,
+gs-pitch, buffer-height, 0,
+format, pixel_type, data);
wl_shm_buffer_end_access(buffer-shm_buffer);
goto done;
}
@@ -1168,10 +1168,6 @@ gl_renderer_attach_shm(struct weston_surface *es, struct 
weston_buffer *buffer,
gs-surface = es;
 
ensure_textures(gs, 1);
-   glBindTexture(GL_TEXTURE_2D, gs-textures[0]);
-   glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
-gs-pitch, buffer-height, 0,
-GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
}
 }
 
-- 
1.8.5.3

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


Re: [Mesa-dev] [PATCH 0/7] EGL_MESA_configless_context

2014-03-13 Thread Neil Roberts
Kristian Høgsberg k...@bitplanet.net writes:

 Thanks Neil, series applied to mesa and weston.

Great, thanks!

I've reposted the piglit patch to the piglit list in case someone wants
to review it there.

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


[PATCH mesa 3/7] eglCreateContext: Remove the check for whether config == 0

2014-03-07 Thread Neil Roberts
In eglCreateContext there is a check for whether the config parameter is zero
and in this case it will avoid reporting an error if the
EGL_KHR_surfacless_context extension is supported. However there is nothing in
that extension which says you can create a context without a config and Mesa
breaks if you try this so it is probably better to leave it reporting an
error.

The original check was added in b90a3e7d8b1bc based on the API-specific
extensions EGL_KHR_surfaceless_opengl/gles1/gles2. This was later changed to
refer to EGL_KHR_surfacless_context in b50703aea5. Perhaps the original
extensions specified a configless context but the new one does not.
---
 src/egl/main/eglapi.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 59e214c..42bcb72 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -431,11 +431,8 @@ eglCreateContext(EGLDisplay dpy, EGLConfig config, 
EGLContext share_list,
 
_EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
 
-   if (!config) {
-  /* config may be NULL if surfaceless */
-  if (!disp-Extensions.KHR_surfaceless_context)
- RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
-   }
+   if (!config)
+  RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
 
if (!share  share_list != EGL_NO_CONTEXT)
   RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
-- 
1.8.5.3

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


[PATCH mesa 4/7] Add the EGL_MESA_configless_context extension

2014-03-07 Thread Neil Roberts
This extension provides a way for an application to render to multiple
surfaces with different buffer formats without having to use multiple
contexts. An EGLContext can be created without an EGLConfig by passing
EGL_NO_CONFIG_MESA. In that case there are no restrictions on the surfaces
that can be used with the context apart from that they must be using the same
EGLDisplay.

_mesa_initialze_context can now take a NULL gl_config which will mark the
context as ‘configless’. It will memset the visual to zero in that case.
Previously the i965 and i915 drivers were explicitly creating a zeroed visual
whenever 0 is passed for the EGLConfig. Mesa needs to be aware that the
context is configless because it affects the initial value to use for
glDrawBuffer. The first time the context is bound it will set the initial
value for configless contexts depending on whether the framebuffer used is
double-buffered.
---
 docs/specs/MESA_configless_context.spec   | 120 ++
 include/EGL/eglext.h  |   5 ++
 src/egl/drivers/dri2/egl_dri2.c   |   1 +
 src/egl/main/eglapi.c |   2 +-
 src/egl/main/eglcontext.c |  20 -
 src/egl/main/egldisplay.h |   1 +
 src/egl/main/eglmisc.c|   1 +
 src/mesa/drivers/dri/i915/intel_context.c |   6 --
 src/mesa/drivers/dri/i965/brw_context.c   |   6 --
 src/mesa/main/context.c   |  82 +++-
 src/mesa/main/mtypes.h|   6 ++
 11 files changed, 213 insertions(+), 37 deletions(-)
 create mode 100644 docs/specs/MESA_configless_context.spec

diff --git a/docs/specs/MESA_configless_context.spec 
b/docs/specs/MESA_configless_context.spec
new file mode 100644
index 000..8bed90d
--- /dev/null
+++ b/docs/specs/MESA_configless_context.spec
@@ -0,0 +1,120 @@
+Name
+
+MESA_configless_context
+
+Name Strings
+
+EGL_MESA_configless_context
+
+Contact
+
+Neil Roberts neil.s.robe...@intel.com
+
+Status
+
+Proposal
+
+Version
+
+Version 1, February 28, 2014
+
+Number
+
+EGL Extension #not assigned
+
+Dependencies
+
+Requires EGL 1.4 or later.  This extension is written against the
+wording of the EGL 1.4 specification.
+
+Overview
+
+This extension provides a means to use a single context to render to
+multiple surfaces which have different EGLConfigs. Without this extension
+the EGLConfig for every surface used by the context must be compatible
+with the one used by the context. The only way to render to surfaces with
+different formats would be to create multiple contexts but this is
+inefficient with modern GPUs where this restriction is unnecessary.
+
+IP Status
+
+Open-source; freely implementable.
+
+New Procedures and Functions
+
+None.
+
+New Tokens
+
+Accepted as config in eglCreateContext
+
+EGL_NO_CONFIG_MESA  ((EGLConfig)0)
+
+Additions to the EGL Specification section 2.2 Rendering Contexts and Drawing
+Surfaces
+
+Add the following to the 3rd paragraph:
+
+   EGLContexts can also optionally be created with respect to an EGLConfig
+depending on the parameters used at creation time. If a config is provided
+then additional restrictions apply on what surfaces can be used with the
+context.
+
+Replace the last sentence of the 6th paragraph with:
+
+   In order for a context to be compatible with a surface they both must have
+been created with respect to the same EGLDisplay. If the context was
+created without respect to an EGLConfig then there are no further
+constraints. Otherwise they are only compatible if:
+
+Remove the last bullet point in the list of constraints.
+
+Additions to the EGL Specification section 3.7.1 Creating Rendering Contexts
+
+Replace the paragraph starting If config is not a valid EGLConfig...
+with
+
+   The config argument can either be a valid EGLConfig or EGL_NO_CONFIG_MESA.
+If it is neither of these then an EGL_BAD_CONFIG error is generated. If a
+valid config is passed then the error will also be generated if the config
+does not support the requested client API (this includes requesting
+creation of an OpenGL ES 1.x context when the EGL_RENDERABLE_TYPE
+attribute of config does not contain EGL_OPENGL_ES_BIT, or creation of an
+OpenGL ES 2.x context when the attribute does not contain
+EGL_OPENGL_ES2_BIT).
+
+Passing EGL_NO_CONFIG_MESA will create a configless context. When a
+configless context is used with the OpenGL API it can be assumed that the
+initial values of the context's state will be decided when the context is
+first made current. In particular this means that the decision of whether
+to use GL_BACK or GL_FRONT for the initial value of the first output in
+glDrawBuffers will be decided based on the config of the draw surface when
+it is first bound. If the context is later bound to another

[PATCH piglit 5/7] Add a test for EGL_MESA_configless_context

2014-03-07 Thread Neil Roberts
This tests creating an EGLContext without an EGLConfig and then
creates three surfaces with different configs and tries rendering to
them. The test is skipped if the extension is not available.
---
 tests/all.py   |   4 +
 tests/egl/CMakeLists.gl.txt|   1 +
 tests/egl/egl-configless-context.c | 380 +
 3 files changed, 385 insertions(+)
 create mode 100644 tests/egl/egl-configless-context.c

diff --git a/tests/all.py b/tests/all.py
index d6daed2..8e6ac8e 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -3765,6 +3765,10 @@ egl_khr_create_context['valid debug flag GL'] = 
plain_test('egl-create-context-v
 for api in ('gles1', 'gles2', 'gles3'):
 egl_khr_create_context['valid debug flag ' + api] = 
plain_test('egl-create-context-valid-flag-debug-gles ' + api)
 
+egl_mesa_configless_context = Group()
+spec['EGL_MESA_configless_context']= egl_mesa_configless_context
+egl_mesa_configless_context['basic'] = plain_test('egl-configless-context')
+
 egl_ext_client_extensions = Group()
 spec['EGL_EXT_client_extensions'] = egl_ext_client_extensions
 for i in [1, 2, 3]:
diff --git a/tests/egl/CMakeLists.gl.txt b/tests/egl/CMakeLists.gl.txt
index d7f17f6..bad6d87 100644
--- a/tests/egl/CMakeLists.gl.txt
+++ b/tests/egl/CMakeLists.gl.txt
@@ -20,6 +20,7 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES Linux)
target_link_libraries(egl-create-surface pthread ${X11_X11_LIB})
piglit_add_executable (egl-query-surface egl-util.c egl-query-surface.c)
target_link_libraries(egl-query-surface pthread ${X11_X11_LIB})
+piglit_add_executable (egl-configless-context egl-configless-context.c)
 ENDIF(${CMAKE_SYSTEM_NAME} MATCHES Linux)
 
 # vim: ft=cmake:
diff --git a/tests/egl/egl-configless-context.c 
b/tests/egl/egl-configless-context.c
new file mode 100644
index 000..f088056
--- /dev/null
+++ b/tests/egl/egl-configless-context.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright © 2010, 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the Software),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors: Neil Roberts neil.s.robe...@intel.com
+ *  Kristian Høgsberg k...@bitplanet.net
+ */
+
+/** @file egl-configless-context.c
+ *
+ * Test the EGL_MESA_configless_context extension
+ */
+
+/* Chunks of code in this file are taken from egl-util.c */
+
+#include X11/Xlib.h
+
+#include piglit-util-gl-common.h
+#include piglit-util-egl.h
+
+#ifndef EGL_MESA_configless_context
+#define EGL_MESA_configless_context 1
+#define EGL_NO_CONFIG_MESA ((EGLConfig)0)
+#endif
+
+struct state {
+   Display *dpy;
+   EGLDisplay egl_dpy;
+   EGLint egl_major, egl_minor;
+   EGLContext ctx;
+};
+
+struct window {
+   EGLConfig config;
+   Window win;
+   EGLSurface surface;
+};
+
+static EGLint
+get_config_attrib(EGLDisplay egl_dpy,
+ EGLConfig config,
+ EGLenum attrib)
+{
+   EGLBoolean status;
+   EGLint value;
+
+   status = eglGetConfigAttrib(egl_dpy,
+   config,
+   attrib,
+   value);
+   if (!status) {
+   fprintf(stderr, eglGetConfigAttrib failed\n);
+   piglit_report_result(PIGLIT_FAIL);
+   }
+
+   return value;
+}
+
+static EGLConfig
+choose_config(EGLDisplay egl_dpy,
+ int depth,
+ EGLBoolean has_depth_buffer)
+{
+   EGLint attribs[32], *a = attribs;
+   EGLConfig configs[128];
+   EGLBoolean status;
+   EGLint config_count, i;
+   EGLint buffer_size;
+   EGLint depth_size;
+   EGLConfig best_config = 0;
+
+   switch (depth) {
+   case 16:
+   *(a++) = EGL_RED_SIZE;
+   *(a++) = 5;
+   *(a++) = EGL_GREEN_SIZE;
+   *(a++) = 6;
+   *(a++) = EGL_BLUE_SIZE;
+   *(a++) = 5

[PATCH 0/7] EGL_MESA_configless_context

2014-03-07 Thread Neil Roberts
Here is a series of patches to add an extension which makes it
possible to create an EGL context without specifying a config. A
context created in this way can be bound with any surface using the
same EGLDisplay rather than being restricted to those using the same
config. The main use case is that it would then be possible for a
Wayland compositor to drive two displays which may have different
bit-depths without having to wastefully create two contexts.

Mesa seems to mostly cope with this already so the patches are mostly
just to add the extension and remove the restriction.

There is also a patch for Piglit to try and test the extension. I
tried running the branch though the 'all tests' test suite and apart
from this new test now passing there was only one difference which is
that the GLX_OML_sync_control/swapbuffersmsc-divisor-zero test failed.
However if I run piglit-run.py again and set a regexp so it only runs
that one test then it passes so I'm wondering if it might just be an
intermittent failure.

The main thorny issue with the extension is how to handle the initial
value of glDrawBuffer when a configless context is used. If a config
is used then we can just say the default is GL_BACK if the config is
double-buffered and GL_FRONT otherwise. I have taken the approach that
this decision is made the first time the context is bound rather than
when it is first created. There should be no way to query the value of
glDrawBuffer until the context is first bound so it shouldn't cause
any harm that Mesa changes the value at that point. I think this is
worth doing for the convenience to the application which would
otherwise have to remember to explicitly set it to GL_BACK in the
common case that double-buffering is used.

I've also included a couple of patches to take advantage of the
extension in Weston.

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


[PATCH weston 7/7] Add support for having different GBM formats for different outputs

2014-03-07 Thread Neil Roberts
The gbm-format configuration option can now be specified per-output as
well as in the core config section. If it is not specified it will
default to the format specified in the core section. The
EGL_MESA_configless_context extension is required for this to work. If
this extension is available it will create a context without an
EGLConfig and then it will potentially use a different EGLConfig for
each output.

The gl-renderer interface has been changed so that it takes the EGL
attributes and visual ID in the create_output function as well as in
the create function.
---
 src/compositor-drm.c |  65 ---
 src/compositor-fbdev.c   |   4 +-
 src/compositor-wayland.c |   4 +-
 src/compositor-x11.c |   4 +-
 src/gl-renderer.c| 134 +--
 src/gl-renderer.h|   4 +-
 6 files changed, 141 insertions(+), 74 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index e45f47d..3f584a6 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -147,6 +147,7 @@ struct drm_output {
drmModeCrtcPtr original_crtc;
struct drm_edid edid;
drmModePropertyPtr dpms_prop;
+   uint32_t format;
 
int vblank_pending;
int page_flip_pending;
@@ -420,8 +421,6 @@ static uint32_t
 drm_output_check_scanout_format(struct drm_output *output,
struct weston_surface *es, struct gbm_bo *bo)
 {
-   struct drm_compositor *c =
-   (struct drm_compositor *) output-base.compositor;
uint32_t format;
pixman_region32_t r;
 
@@ -442,7 +441,7 @@ drm_output_check_scanout_format(struct drm_output *output,
pixman_region32_fini(r);
}
 
-   if (c-format == format)
+   if (output-format == format)
return format;
 
return 0;
@@ -507,7 +506,7 @@ drm_output_render_gl(struct drm_output *output, 
pixman_region32_t *damage)
return;
}
 
-   output-next = drm_fb_get_from_bo(bo, c, c-format);
+   output-next = drm_fb_get_from_bo(bo, c, output-format);
if (!output-next) {
weston_log(failed to get drm_fb for bo\n);
gbm_surface_release_buffer(output-surface, bo);
@@ -1528,12 +1527,13 @@ find_crtc_for_connector(struct drm_compositor *ec,
 static int
 drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
 {
+   EGLint format = output-format;
int i, flags;
 
output-surface = gbm_surface_create(ec-gbm,
 output-base.current_mode-width,
 output-base.current_mode-height,
-ec-format,
+format,
 GBM_BO_USE_SCANOUT |
 GBM_BO_USE_RENDERING);
if (!output-surface) {
@@ -1541,7 +1541,9 @@ drm_output_init_egl(struct drm_output *output, struct 
drm_compositor *ec)
return -1;
}
 
-   if (gl_renderer-output_create(output-base, output-surface)  0) {
+   if (gl_renderer-output_create(output-base, output-surface,
+  gl_renderer-opaque_attribs,
+  format)  0) {
weston_log(failed to create gl renderer output state\n);
gbm_surface_destroy(output-surface);
return -1;
@@ -1853,6 +1855,35 @@ setup_output_seat_constraint(struct drm_compositor *ec,
 }
 
 static int
+get_gbm_format_from_section(struct weston_config_section *section,
+   uint32_t default_value,
+   uint32_t *format)
+{
+   char *s;
+   int ret = 0;
+
+   weston_config_section_get_string(section,
+gbm-format, s, NULL);
+
+   if (s == NULL)
+   *format = default_value;
+   else if (strcmp(s, xrgb) == 0)
+   *format = GBM_FORMAT_XRGB;
+   else if (strcmp(s, rgb565) == 0)
+   *format = GBM_FORMAT_RGB565;
+   else if (strcmp(s, xrgb2101010) == 0)
+   *format = GBM_FORMAT_XRGB2101010;
+   else {
+   weston_log(fatal: unrecognized pixel format: %s\n, s);
+   ret = -1;
+   }
+
+   free(s);
+
+   return ret;
+}
+
+static int
 create_output_for_connector(struct drm_compositor *ec,
drmModeRes *resources,
drmModeConnector *connector,
@@ -1919,6 +1950,11 @@ create_output_for_connector(struct drm_compositor *ec,
transform = parse_transform(s, output-base.name);
free(s);
 
+   if (get_gbm_format_from_section(section,
+   ec-format,
+   output-format) == -1)
+   output-format = ec-format;
+

[PATCH mesa 2/7] Fix the initial value of glDrawBuffers for GLES

2014-03-07 Thread Neil Roberts
Under GLES 3 it is not valid to pass GL_FRONT to glDrawBuffers. Instead,
GL_BACK has a magic interpretation which means it will render to the front
buffer on single-buffered contexts and the back buffer on double-buffered. We
were incorrectly setting the initial value to GL_FRONT for single-buffered
contexts. This probably doesn't really matter at the moment except that
presumably it would be exposed in the API via glGetIntegerv.

When we switch to configless contexts this is more important because in that
case we always want to rely on the magic interpretation of GL_BACK in order to
automatically switch between the front and back buffer when a new surface with
a different number of buffers is bound. We also do this for GLES 1 and 2
because the internal value doesn't matter in that case and it is convenient to
use the same code to have the magic interpretation of GL_BACK.
---
 src/mesa/main/blend.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c
index eb4f1d6..c37c0fe 100644
--- a/src/mesa/main/blend.c
+++ b/src/mesa/main/blend.c
@@ -911,7 +911,9 @@ void _mesa_init_color( struct gl_context * ctx )
ctx-Color.LogicOp = GL_COPY;
ctx-Color.DitherFlag = GL_TRUE;
 
-   if (ctx-Visual.doubleBufferMode) {
+   /* GL_FRONT is not possible on GLES. Instead GL_BACK will render to either
+* the front or the back buffer depending on the config */
+   if (ctx-Visual.doubleBufferMode || _mesa_is_gles(ctx)) {
   ctx-Color.DrawBuffer[0] = GL_BACK;
}
else {
-- 
1.8.5.3

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


[PATCH mesa 1/7] Use the magic behaviour of GL_BACK in GLES 1 and 2 as well as 3

2014-03-07 Thread Neil Roberts
In GLES 3 it is not possible to select rendering to the front buffer and
instead selecting GL_BACK has the magic interpretation that it is either the
front buffer on single-buffered configs or the back buffer on double-buffered.
GLES 1 and 2 have no way of selecting the draw buffer at all. In that case we
were initialising the draw buffer to either GL_FRONT or GL_BACK depending on
the context's config and then leaving it at that. When we switch to having
configless contexts we ideally want Mesa to automatically switch between the
front and back buffer whenever a double- or single-buffered surface is bound.
To make this happen we can just allow the magic behaviour from GLES 3 in GLES
1 and 2 as well. It shouldn't matter what the internal value of the draw
buffer is in GLES 1 and 2 because there is no way to query it from the
external API.
---
 src/mesa/main/buffers.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c
index 6cbce9d..b13a7af 100644
--- a/src/mesa/main/buffers.c
+++ b/src/mesa/main/buffers.c
@@ -101,7 +101,7 @@ draw_buffer_enum_to_bitmask(const struct gl_context *ctx, 
GLenum buffer)
   case GL_FRONT:
  return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT;
   case GL_BACK:
- if (_mesa_is_gles3(ctx)) {
+ if (_mesa_is_gles(ctx)) {
 /* Page 181 (page 192 of the PDF) in section 4.2.1 of the OpenGL
  * ES 3.0.1 specification says:
  *
@@ -111,6 +111,11 @@ draw_buffer_enum_to_bitmask(const struct gl_context *ctx, 
GLenum buffer)
  *
  * Since there is no stereo rendering in ES 3.0, only return the
  * LEFT bits.  This also satisfies the n must be 1 requirement.
+ *
+ * We also do this for GLES 1 and 2 because those APIs have no
+ * concept of selecting the front and back buffer anyway and it's
+ * convenient to be able to maintain the magic behaviour of
+ * GL_BACK in that case.
  */
 if (ctx-DrawBuffer-Visual.doubleBufferMode)
return BUFFER_BIT_BACK_LEFT;
-- 
1.8.5.3

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


[PATCH weston v2] Add a nested YUV client to the weston-nested example

2014-02-25 Thread Neil Roberts
Here is a second version of the patch to match with the changes in v2
of the extension.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

This adds a separate nested client to the weston-nested example which
will create YUV buffers using libva. The code is based on the
putsurface test in libva. The client can be used by passing the -y
option to weston-nested.

In the subcompositor when it detects that the client has passed a
planar buffer it will use eglCreateWaylandBufferFromPlanarImagesWL
instead of the original function. The function pointer prototype in
eglext.h for this is not used so that Weston can still be compiled
with the old version of the extension. In that case weston-nested will
crash if you pass the -y option, but it will otherwise work.
---
 .gitignore  |1 +
 Makefile.am |   11 +
 clients/nested-client-yuv.c | 1035 +++
 clients/nested.c|  125 --
 configure.ac|   21 +-
 5 files changed, 1151 insertions(+), 42 deletions(-)
 create mode 100644 clients/nested-client-yuv.c

diff --git a/.gitignore b/.gitignore
index e0a73c0..3728f36 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ weston-gears
 weston-image
 weston-nested
 weston-nested-client
+weston-nested-client-yuv
 weston-resizor
 weston-scaler
 weston-simple-egl
diff --git a/Makefile.am b/Makefile.am
index 64d0743..788bcdf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -478,6 +478,17 @@ weston_nested_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
 weston_nested_client_SOURCES = clients/nested-client.c
 weston_nested_client_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
 weston_nested_client_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+
+if HAVE_LIBVA_WAYLAND
+demo_clients += weston-nested-client-yuv
+weston_nested_client_yuv_SOURCES = clients/nested-client-yuv.c
+weston_nested_client_yuv_LDADD = $(LIBVA_WAYLAND_LIBS) $(SIMPLE_CLIENT_LIBS)
+weston_nested_client_yuv_CFLAGS = \
+   $(CLIENT_CFLAGS) \
+   $(AM_CFLAGS) \
+   $(LIBVA_WAYLAND_CFLAGS)
+endif
+
 endif
 
 weston_eventdemo_SOURCES = clients/eventdemo.c
diff --git a/clients/nested-client-yuv.c b/clients/nested-client-yuv.c
new file mode 100644
index 000..c37b999
--- /dev/null
+++ b/clients/nested-client-yuv.c
@@ -0,0 +1,1035 @@
+/*
+ * Copyright (c) 2008, 2009, 2014 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * Software), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include stdio.h
+#include string.h
+#include stdlib.h
+#include stdint.h
+
+#include sys/time.h
+
+#include unistd.h
+
+#include sys/types.h
+#include sys/stat.h
+#include fcntl.h
+#include assert.h
+#include pthread.h
+
+#include va/va_wayland.h
+
+#define CHECK_VASTATUS(va_status,func) \
+   if (va_status != VA_STATUS_SUCCESS) {   \
+   fprintf(stderr,%s:%s (%d) failed,exit\n,  \
+   __func__,   \
+   func,   \
+   __LINE__);  \
+   exit(1);\
+   }
+
+static void *open_display(void);
+static void close_display(void *win_display);
+static int create_window(void *win_display,
+int x, int y, int width, int height);
+static int check_window_event(void *win_display, void *drawable,
+ int *width, int *height, int *quit);
+
+struct display;
+struct drawable;
+
+static VAStatus
+va_put_surface(VADisplaydpy,
+  struct drawable  *wl_drawable,
+  VASurfaceID   va_surface,
+  const VARectangle*src_rect,
+  const VARectangle*dst_rect,
+  const VARectangle*cliprects,
+  unsigned 

[PATCH weston] nested: Disable cairo on the subsurfaces

2014-02-24 Thread Neil Roberts
The subsurface widgets on the nested example aren't using Cairo to
render so we should turn it off to prevent the toy toolkit from
creating a redundant extra surface for it. This is particularly
important since Mesa commit 6c9d6898fdfd7e2 because the surface that
the toolkit tries to create is zero-sized and that patch prevents that
from working. This was causing weston-nested to crash.
---
 clients/nested.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clients/nested.c b/clients/nested.c
index d75e953..3bdb961 100644
--- a/clients/nested.c
+++ b/clients/nested.c
@@ -976,6 +976,8 @@ ss_surface_init(struct nested_surface *surface)
  nested,
  SUBSURFACE_SYNCHRONIZED);
 
+   widget_set_use_cairo(ss_surface-widget, 0);
+
ss_surface-surface = widget_get_wl_surface(ss_surface-widget);
ss_surface-subsurface = widget_get_wl_subsurface(ss_surface-widget);
 
-- 
1.8.5.3

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


[PATCH v2] Adapt the EGL_WL_create_wayland_buffer_from_image extension for YUV

2014-02-14 Thread Neil Roberts
 updates to the image will also be updated in the wl_buffer. Typically the
@@ -82,13 +89,50 @@ Additions to the EGL 1.4 Specification:
 format or tiling mode or that the buffer is in memory that is inaccessible
 to the GPU that the given EGLDisplay is using.
 
+Alternatively it is possible to create a buffer from a planar image where
+each plane is contained in a separate EGLImage using the following
+function:
+
+struct wl_buffer *eglCreateWaylandBufferFromPlanarImagesWL(EGLDisplay dpy,
+   EGLenum format,
+   EGLImageKHR 
*ims,
+   EGLint 
n_images);
+
+The number of images passed should match the number of planes required for
+the format given in the format parameter. For non-planar formats this will
+just be 1. Each image represents one plane within the buffer.
+
+The formats accepted in the format parameter are:
+
+   EGL_TEXTURE_RGBA single image is used which contains RGB
+  components.
+   EGL_TEXTURE_RGBA   A single image is used which contains RGBA
+  components.
+   EGL_TEXTURE_Y_U_V_WL   Three images are used; one containing the
+  luminance component, one containing the
+  U component of the chrominance data and another
+  containing the V component.
+   EGL_TEXTURE_Y_UV_WLTwo images are used; one containing a single
+  luminance component and the other containing the
+  two chrominance components.
+   EGL_TEXTURE_Y_XUXV_WL  Two images are used; one containing a single
+  luminance component and the other containing the
+  two chrominance components along with two unused
+  components.
+
+Dependencies on EGL_WL_bind_wayland_display
+
+If EGL_WL_bind_wayland_display is not implemented then references to
+EGL_TEXTURE_Y_U_V_WL, EGL_TEXTURE_Y_UV_WL and EGL_TEXTURE_Y_XUXV_WL are
+void.
+
 Issues
 
 1) Under what circumstances can the EGL_BAD_MATCH error be generated? Does
this include for example unsupported tiling modes?
 
RESOLVED: Yes, the EGL_BAD_MATCH error can be generated for any reason
-   which prevents the implementation from representing the image as a
+   which prevents the implementation from representing the images as a
wl_buffer. For example, these problems can be but are not limited to
unsupported tiling modes, inaccessible memory or an unsupported pixel
format.
@@ -99,3 +143,6 @@ Revision History
 Initial draft (Neil Roberts)
 Version 2, October 25, 2013
 Added a note about more possible reasons for returning EGL_BAD_FORMAT.
+Version 3, February 5, 2014
+Support for passing multiple images in order to create a planar
+buffer.
diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index b3229e3..b78aa8b 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -139,8 +139,10 @@ typedef EGLBoolean (EGLAPIENTRYP 
PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, st
 
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI struct wl_buffer * EGLAPIENTRY 
eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);
+EGLAPI struct wl_buffer * EGLAPIENTRY 
eglCreateWaylandBufferFromPlanarImagesWL(EGLDisplay dpy, EGLenum format, 
EGLImageKHR *images, EGLint n_images);
 #endif
 typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) 
(EGLDisplay dpy, EGLImageKHR image);
+typedef struct wl_buffer * (EGLAPIENTRYP 
PFNEGLCREATEWAYLANDBUFFERFROMPLANARIMAGESWL) (EGLDisplay dpy, EGLenum format, 
EGLImageKHR *images, EGLint n_images);
 
 #endif
 
diff --git a/src/egl/drivers/dri2/platform_wayland.c 
b/src/egl/drivers/dri2/platform_wayland.c
index 089ed62..556a45a 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -698,64 +698,238 @@ dri2_can_handle_format(struct dri2_egl_display *dri2_dpy,
return EGL_FALSE;
 }
 
+struct plane_attribs {
+   struct dri2_egl_image *dri2_img;
+   __DRIimage *image;
+   int offset;
+   int stride;
+   int width;
+   int height;
+   int format;
+};
+
+struct planar_format {
+   enum wl_drm_format wl_format;
+   EGLenum components;
+   int n_planes;
+   struct {
+  int width_shift;
+  int height_shift;
+  uint32_t dri_format;
+   } planes[3];
+};
+
+static const struct planar_format
+planar_formats[] = {
+   { WL_DRM_FORMAT_ARGB, EGL_TEXTURE_RGBA, 1,
+ { { 0, 0, __DRI_IMAGE_FORMAT_ARGB } } },
+
+   { WL_DRM_FORMAT_XRGB, EGL_TEXTURE_RGB, 1,
+ { { 0, 0, __DRI_IMAGE_FORMAT_XRGB }, } },
+
+   { WL_DRM_FORMAT_RGB565, EGL_TEXTURE_RGB

[PATCH mesa 3/3] Adapt the EGL_WL_create_wayland_buffer_from_image extension for YUV

2014-02-06 Thread Neil Roberts
.
+
+The formats accepted in the format parameter are:
+
+   EGL_TEXTURE_RGBA single image is used which contains RGB
+  components.
+   EGL_TEXTURE_RGBA   A single image is used which contains RGBA
+  components.
+   EGL_TEXTURE_Y_U_V_WL   Three images are used; one containing the
+  luminance component, one containing the
+  U component of the chrominance data and another
+  containing the V component.
+   EGL_TEXTURE_Y_UV_WLTwo images are used; one containing a single
+  luminance component and the other containing the
+  two chrominance components.
+   EGL_TEXTURE_Y_XUXV_WL  Two images are used; one containing a single
+  luminance component and the other containing the
+  two chrominance components along with two unused
+  components.
+
 If there was an error then the function will return NULL. In particular it
 will generate EGL_BAD_MATCH if the implementation is not able to represent
-the image as a wl_buffer. The possible reasons for this error are
+the images as a wl_buffer. The possible reasons for this error are
 implementation-dependant but may include problems such as an unsupported
 format or tiling mode or that the buffer is in memory that is inaccessible
 to the GPU that the given EGLDisplay is using.
 
+Dependencies on EGL_WL_bind_wayland_display
+
+If EGL_WL_bind_wayland_display is not implemented then references to
+EGL_TEXTURE_Y_U_V_WL, EGL_TEXTURE_Y_UV_WL and EGL_TEXTURE_Y_XUXV_WL are
+void.
+
 Issues
 
 1) Under what circumstances can the EGL_BAD_MATCH error be generated? Does
this include for example unsupported tiling modes?
 
RESOLVED: Yes, the EGL_BAD_MATCH error can be generated for any reason
-   which prevents the implementation from representing the image as a
+   which prevents the implementation from representing the images as a
wl_buffer. For example, these problems can be but are not limited to
unsupported tiling modes, inaccessible memory or an unsupported pixel
format.
@@ -99,3 +133,6 @@ Revision History
 Initial draft (Neil Roberts)
 Version 2, October 25, 2013
 Added a note about more possible reasons for returning EGL_BAD_FORMAT.
+Version 3, February 5, 2014
+Support for passing multiple images in order to create a planar
+buffer.
diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index b3229e3..de90369 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -138,9 +138,9 @@ typedef EGLBoolean (EGLAPIENTRYP 
PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, st
 #define EGL_WL_create_wayland_buffer_from_image 1
 
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI struct wl_buffer * EGLAPIENTRY 
eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);
+EGLAPI struct wl_buffer * EGLAPIENTRY 
eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLenum format, EGLImageKHR 
*images, EGLint n_images);
 #endif
-typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) 
(EGLDisplay dpy, EGLImageKHR image);
+typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) 
(EGLDisplay dpy, EGLenum format, EGLImageKHR *images, EGLint n_images);
 
 #endif
 
diff --git a/src/egl/drivers/dri2/platform_wayland.c 
b/src/egl/drivers/dri2/platform_wayland.c
index 089ed62..e9262fb 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -698,64 +698,238 @@ dri2_can_handle_format(struct dri2_egl_display *dri2_dpy,
return EGL_FALSE;
 }
 
+struct plane_attribs {
+   struct dri2_egl_image *dri2_img;
+   __DRIimage *image;
+   int offset;
+   int stride;
+   int width;
+   int height;
+   int format;
+};
+
+struct planar_format {
+   enum wl_drm_format wl_format;
+   EGLenum components;
+   int n_planes;
+   struct {
+  int width_shift;
+  int height_shift;
+  uint32_t dri_format;
+   } planes[3];
+};
+
+static const struct planar_format
+planar_formats[] = {
+   { WL_DRM_FORMAT_ARGB, EGL_TEXTURE_RGBA, 1,
+ { { 0, 0, __DRI_IMAGE_FORMAT_ARGB } } },
+
+   { WL_DRM_FORMAT_XRGB, EGL_TEXTURE_RGB, 1,
+ { { 0, 0, __DRI_IMAGE_FORMAT_XRGB }, } },
+
+   { WL_DRM_FORMAT_RGB565, EGL_TEXTURE_RGB, 1,
+ { { 0, 0, __DRI_IMAGE_FORMAT_RGB565 } } },
+
+   { WL_DRM_FORMAT_YUV410, EGL_TEXTURE_Y_U_V_WL, 3,
+ { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+   { 2, 2, __DRI_IMAGE_FORMAT_R8 },
+   { 2, 2, __DRI_IMAGE_FORMAT_R8 } } },
+
+   { WL_DRM_FORMAT_YUV411, EGL_TEXTURE_Y_U_V_WL, 3,
+ { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+   { 2, 0, __DRI_IMAGE_FORMAT_R8 },
+   { 2, 0, __DRI_IMAGE_FORMAT_R8 } } },
+
+   { WL_DRM_FORMAT_YUV420

[PATCH mesa 1/3] wayland: Keep track of the formats in a sorted array instead of flags

2014-02-06 Thread Neil Roberts
In order to support YUV formats in CreateWaylandBufferFromImageWL we need to
be able to check whether the compositor supports a larger number of formats so
storing them in flags is a bit awkard. Instead all of the formats are now
stored in a sorted array using wl_array. A binary search is used to check for
the format.
---
 src/egl/drivers/dri2/egl_dri2.h |  2 +-
 src/egl/drivers/dri2/platform_wayland.c | 85 -
 2 files changed, 64 insertions(+), 23 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index dfc5927..3f90582 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -131,7 +131,7 @@ struct dri2_egl_display
struct wl_drm*wl_drm;
struct wl_event_queue*wl_queue;
int  authenticated;
-   int  formats;
+   struct wl_array   formats;
uint32_t  capabilities;
 #endif
 
diff --git a/src/egl/drivers/dri2/platform_wayland.c 
b/src/egl/drivers/dri2/platform_wayland.c
index 50750a9..089ed62 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -41,12 +41,6 @@
 #include wayland-client.h
 #include wayland-drm-client-protocol.h
 
-enum wl_drm_format_flags {
-   HAS_ARGB = 1,
-   HAS_XRGB = 2,
-   HAS_RGB565 = 4,
-};
-
 static void
 sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
 {
@@ -679,6 +673,31 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, 
_EGLSurface *draw)
return dri2_swap_buffers_with_damage (drv, disp, draw, NULL, 0);
 }
 
+static EGLBoolean
+dri2_can_handle_format(struct dri2_egl_display *dri2_dpy,
+   enum wl_drm_format format)
+{
+   const enum wl_drm_format *formats;
+   int min, mid, max;
+
+   /* Binary search for the format */
+   min = 0;
+   max = dri2_dpy-formats.size / sizeof (enum wl_drm_format);
+   formats = dri2_dpy-formats.data;
+
+   while (max  min) {
+  mid = (max + min) / 2;
+  if (formats[mid]  format)
+ min = mid + 1;
+  else if (formats[mid]  format)
+ max = mid;
+  else
+ return EGL_TRUE;
+   }
+
+   return EGL_FALSE;
+}
+
 static struct wl_buffer *
 dri2_create_wayland_buffer_from_image_wl(_EGLDriver *drv,
  _EGLDisplay *disp,
@@ -695,12 +714,12 @@ dri2_create_wayland_buffer_from_image_wl(_EGLDriver *drv,
 
switch (format) {
case __DRI_IMAGE_FORMAT_ARGB:
-  if (!(dri2_dpy-formats  HAS_ARGB))
+  if (!dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_ARGB))
  goto bad_format;
   wl_format = WL_DRM_FORMAT_ARGB;
   break;
case __DRI_IMAGE_FORMAT_XRGB:
-  if (!(dri2_dpy-formats  HAS_XRGB))
+  if (!dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_XRGB))
  goto bad_format;
   wl_format = WL_DRM_FORMAT_XRGB;
   break;
@@ -794,6 +813,7 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
wl_drm_destroy(dri2_dpy-wl_drm);
if (dri2_dpy-own_device)
   wl_display_disconnect(dri2_dpy-wl_dpy);
+   wl_array_release(dri2_dpy-formats);
free(dri2_dpy);
disp-DriverData = NULL;
 
@@ -834,18 +854,36 @@ static void
 drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
 {
struct dri2_egl_display *dri2_dpy = data;
-
-   switch (format) {
-   case WL_DRM_FORMAT_ARGB:
-  dri2_dpy-formats |= HAS_ARGB;
-  break;
-   case WL_DRM_FORMAT_XRGB:
-  dri2_dpy-formats |= HAS_XRGB;
-  break;
-   case WL_DRM_FORMAT_RGB565:
-  dri2_dpy-formats |= HAS_RGB565;
-  break;
+   enum wl_drm_format *formats = dri2_dpy-formats.data;
+   int n_formats;
+   int min, mid, max;
+
+   n_formats = dri2_dpy-formats.size / sizeof (enum wl_drm_format);
+
+   /* Search for the insert position to keep the format array sorted */
+   min = 0;
+   max = n_formats;
+
+   while (max  min) {
+  mid = (max + min) / 2;
+  if (formats[mid]  format)
+ min = mid + 1;
+  else if (formats[mid]  format)
+ max = mid;
+  else
+ return;
}
+
+   if (wl_array_add(dri2_dpy-formats, sizeof (enum wl_drm_format)) == NULL)
+  return;
+
+   formats = dri2_dpy-formats.data;
+
+   /* Move the subsequent formats out of the way */
+   memmove(formats + min + 1,
+   formats + min,
+   (n_formats - min) * sizeof *formats);
+   formats[min] = format;
 }
 
 static void
@@ -980,6 +1018,8 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
if (!dri2_dpy)
   return _eglError(EGL_BAD_ALLOC, eglInitialize);
 
+   wl_array_init(dri2_dpy-formats);
+
disp-DriverData = (void *) dri2_dpy;
if (disp-PlatformDisplay == NULL) {
   dri2_dpy-wl_dpy = wl_display_connect(NULL);
@@ -1050,11 +1090,11 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay 
*disp)
types = EGL_WINDOW_BIT;
for (i = 0; dri2_dpy-driver_configs[i]; i++) 

[PATCH] Don't deref the sample pointer in the wl_container_of macro

2014-02-04 Thread Neil Roberts
The previous implementation of the wl_container_of macro was
dereferencing the sample pointer in order to get an address of the
member to calculate the offset. Ideally this shouldn't cause any
problems because the dereference doesn't actually cause the address to
be read from so it shouldn't matter if the pointer is uninitialised.
However this is probably technically invalid and could cause undefined
behavior. Clang appears to take advantage of this undefined behavior
and doesn't bother doing the subtraction. It also gives a warning when
it does this.

The documentation for wl_container_of implies that it should only be
given an initialised pointer and if that is done then there is no
problem with clang. However this is quite easy to forget and doesn't
cause any problems or warnings with gcc so it's quite easy to
accidentally break clang.

To fix the problem this changes the macro to use pointer -
offsetof(__typeof__(sample), member) so that it doesn't need to deref
the sample pointer. This does however require that the __typeof__
operator is supported by the compiler. In practice we probably only
care about gcc and clang and both of these happily support the
operator.

The previous implementation was also using __typeof__ but it had a
fallback path avoiding it when the operator isn't available. The
fallback effectively has undefined behaviour and it is targetting
unknown compilers so it is probably not a good idea to leave it in.
Instead, this patch just removes it. If someone finds a compiler that
doesn't have __typeof__ but does work with the old implementation then
maybe they could add it back in as a special case.

This patch removes the initialisation anywhere where the sample
pointer was being unitialised before using wl_container_of. The
documentation for the macro has also been updated to specify that this
is OK.
---
 src/wayland-server.c |  2 +-
 src/wayland-server.h |  2 +-
 src/wayland-util.h   | 30 +-
 3 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index 489b99d..294497d 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -571,7 +571,7 @@ wl_resource_get_link(struct wl_resource *resource)
 WL_EXPORT struct wl_resource *
 wl_resource_from_link(struct wl_list *link)
 {
-   struct wl_resource *resource = NULL;
+   struct wl_resource *resource;
 
return wl_container_of(link, resource, link);
 }
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 3fcaaf6..7fc5b47 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -162,7 +162,7 @@ wl_client_post_no_memory(struct wl_client *client);
  * \code
  * void your_listener(struct wl_listener *listener, void *data)
  * {
- * struct your_data *data = NULL;
+ * struct your_data *data;
  *
  * your_data = wl_container_of(listener, data, your_member_name);
  * }
diff --git a/src/wayland-util.h b/src/wayland-util.h
index 68d91e2..57764d9 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -135,7 +135,7 @@ void wl_list_insert_list(struct wl_list *list, struct 
wl_list *other);
  *
  * void example_container_destroy(struct wl_listener *listener, void *data)
  * {
- * struct example_container *ctr = NULL;
+ * struct example_container *ctr;
  *
  * ctr = wl_container_of(listener, ctr, destroy_listener);
  * \comment{destroy ctr...}
@@ -144,44 +144,40 @@ void wl_list_insert_list(struct wl_list *list, struct 
wl_list *other);
  *
  * \param ptr A valid pointer to the contained item.
  *
- * \param sample A pointer to the type of content that the list item stores.
- * Sample does not need be a valid pointer; a null pointer will suffice.
+ * \param sample A pointer to the type of content that the list item
+ * stores. Sample does not need be a valid pointer; a null or
+ * an uninitialised pointer will suffice.
  *
  * \param member The named location of ptr within the sample type.
  *
  * \return The container for the specified pointer.
  */
-#ifdef __GNUC__
 #define wl_container_of(ptr, sample, member)   \
-   (__typeof__(sample))((char *)(ptr)  -   \
-((char *)(sample)-member - (char *)(sample)))
-#else
-#define wl_container_of(ptr, sample, member)   \
-   (void *)((char *)(ptr)  -   \
-((char *)(sample)-member - (char *)(sample)))
-#endif
+   (__typeof__(sample))((char *)(ptr) -\
+offsetof(__typeof__(*sample), member))
+/* If the above macro causes problems on your compiler you might be
+ * able to find an alternative name for the non-standard __typeof__
+ * operator and add a special case here */
 
 #define wl_list_for_each(pos, head, member)\
-   for (pos = 0, pos = wl_container_of((head)-next, pos, member); \
+   for (pos = 

Re: Make safe double remove?

2014-01-29 Thread Neil Roberts
Jonathan Howard jonat...@unbiased.name writes:

 wl_list_remove changed isn't 100% guaranteed to not break anything, on
 the other hand there is no guarantee the code does not have the fatal
 double remove already.

We definitely do already have a double-remove bug in Weston as described
here:

http://lists.freedesktop.org/archives/wayland-devel/2014-January/012891.html

I think the proposed change to wl_list_remove would fix that too.

Regards,
- Neil


pgpe_dAD0aq9Y.pgp
Description: PGP signature
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: weston crash in destroy_shell_surface

2014-01-21 Thread Neil Roberts
It looks like the rest of the code assumes that shsurf-children_link
is always a consistent list. For example, shell_surface_set_parent
resets children_link to the empty list after it unlinks a child from
its parent. The destroy_shell_surface code just calls wl_list_remove
which leaves the list node with invalid NULL pointers. Maybe the
simplest way to fix it is just to call shell_surface_set_parent in
that code instead of directly manipulating the list. Here is a patch
to do that.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)
Subject: shell: Use shell_surface_set_parent to unlink children on destroy

Previously when a shell surface is destroyed it would walk through the
list of child surfaces and directly remove their children_link from
the list. This would leave children_link as an invalid list with just
NULL pointers for prev and next. Other parts of the code such as
shell_surface_set_parent assume that children_link is always in a
consistent state (ie, it is the list of sibling surfaces).
destroy_shell_surface also assumes that it can unconditionally call
wl_list_remove on the children_link of the surface being destroyed to
unlink it from its parent if there is one. However, this crashes if
the child's parent is destroyed first because it would leave the child
with an invalid children_link.

To fix it this patch makes it call shell_surface_set_parent(..., NULL)
when unlinking the surface's children instead of directly manipulating
the list because that function will reset children_link to an empty
list leaving it in a consistent state.
---
 desktop-shell/shell.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 2f8e610..e3e2c96 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -2914,10 +2914,8 @@ destroy_shell_surface(struct shell_surface *shsurf)
weston_view_destroy(shsurf-view);
 
wl_list_remove(shsurf-children_link);
-   wl_list_for_each_safe(child, next, shsurf-children_list, 
children_link) {
-   wl_list_remove(child-children_link);
-   child-parent = NULL;
-   }
+   wl_list_for_each_safe(child, next, shsurf-children_list, 
children_link)
+   shell_surface_set_parent(child, NULL);
 
wl_list_remove(shsurf-link);
free(shsurf);
-- 
1.8.4.2

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


[PATCH weston] westoy: Add an option to explicitly disable cairo on a widget

2013-12-19 Thread Neil Roberts
This problem was found while looking at the following bug:

https://bugs.freedesktop.org/show_bug.cgi?id=72612

It turns out the patch doesn't help to fix the bug but I think it
would be a good thing to do anyway.

--- 8 --- (use git am --scissors to automatically chop here)

The subsurfaces example creates a subsurface widget and uses EGL to
render to it directly rather than using the cairo context from the
widget. In theory this shouldn't cause any problems because the westoy
window code lazily creates the cairo surface when an application
creates a cairo context. However commit fdca95c7 changed the behaviour
to force the lazy creation at the beginning of each surface redraw.
This ends up making the triangle surface get two attaches – one from
Cairo and one from the direct EGL.

It looks like it would be difficult to reinstate the lazy surface
creation behaviour whilst still maintaining the error handling for
surface creation because none of the redraw handlers in the example
clients are designed to cope with that. Instead, this patch adds an
explicit option on a widget to disable creating the Cairo surface and
the subsurface example now uses that.
---
 clients/subsurfaces.c |  1 +
 clients/window.c  | 18 +-
 clients/window.h  |  2 ++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/clients/subsurfaces.c b/clients/subsurfaces.c
index 0f11009..45cc44b 100644
--- a/clients/subsurfaces.c
+++ b/clients/subsurfaces.c
@@ -498,6 +498,7 @@ triangle_create(struct window *window, struct egl_state 
*egl)
tri-egl = egl;
tri-widget = window_add_subsurface(window, tri,
int_to_mode(option_triangle_mode));
+   widget_set_use_cairo(tri-widget, 0);
widget_set_resize_handler(tri-widget, triangle_resize_handler);
widget_set_redraw_handler(tri-widget, triangle_redraw_handler);
 
diff --git a/clients/window.c b/clients/window.c
index 43761ca..5a8df43 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -285,6 +285,11 @@ struct widget {
int opaque;
int tooltip_count;
int default_cursor;
+   /* If this is set to false then no cairo surface will be
+* created before redrawing the surface. This is useful if the
+* redraw handler is going to do completely custom rendering
+* such as using EGL directly */
+   int use_cairo;
 };
 
 struct touch_point {
@@ -1608,6 +1613,7 @@ widget_create(struct window *window, struct surface 
*surface, void *data)
widget-tooltip = NULL;
widget-tooltip_count = 0;
widget-default_cursor = CURSOR_LEFT_PTR;
+   widget-use_cairo = 1;
 
return widget;
 }
@@ -1706,6 +1712,8 @@ widget_get_cairo_surface(struct widget *widget)
struct surface *surface = widget-surface;
struct window *window = widget-window;
 
+   assert(widget-use_cairo);
+
if (!surface-cairo_surface) {
if (surface == window-main_surface)
window_create_main_surface(window);
@@ -1938,6 +1946,13 @@ widget_schedule_redraw(struct widget *widget)
window_schedule_redraw_task(widget-window);
 }
 
+void
+widget_set_use_cairo(struct widget *widget,
+int use_cairo)
+{
+   widget-use_cairo = use_cairo;
+}
+
 cairo_surface_t *
 window_get_surface(struct window *window)
 {
@@ -3942,7 +3957,8 @@ surface_redraw(struct surface *surface)
wl_callback_destroy(surface-frame_cb);
}
 
-   if (!widget_get_cairo_surface(surface-widget)) {
+   if (surface-widget-use_cairo 
+   !widget_get_cairo_surface(surface-widget)) {
DBG_OBJ(surface-surface, cancelled due buffer failure\n);
return -1;
}
diff --git a/clients/window.h b/clients/window.h
index cf8fc6c..1e12374 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -507,6 +507,8 @@ widget_set_axis_handler(struct widget *widget,
widget_axis_handler_t handler);
 void
 widget_schedule_redraw(struct widget *widget);
+void
+widget_set_use_cairo(struct widget *widget, int use_cairo);
 
 struct widget *
 window_frame_create(struct window *window, void *data);
-- 
1.8.3.1

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


[PATCH weston] tests: Test whether a simple EGL main loop uses too many buffers

2013-12-05 Thread Neil Roberts
Hi,

Here is a rebased version of the patch. The old one didn't apply
cleanly anymore because of some changes in tests/Makefile.am

I think there is some confusion about why it ends up using 3 buffers
and I also keep getting in a muddle about it. I'll try to describe
what I think is happening here.

The client has a loop like this:

while (1) {
draw_something();
eglSwapBuffers();
}

It begins its first frame. In draw_something it will call get_back_bo
which will allocate a buffer because there are currently no buffers.
It will then call eglSwapBuffers which will install a frame callback
and give the buffer to the compositor. As this is the first buffer,
the compositor won't send a release event yet.

The client will now start rendering its second frame. It will call
get_back_bo which will detect that the first buffer is still locked so
it will allocate a second buffer. It will then call eglSwapBuffers
which will cause it to block for the frame callback. There is still no
release event so this won't cause any buffers to be unlocked. Once the
frame callback is received it will commit the second buffer. The
compositor only needs to keep hold of one buffer so it will
immediately queue a release event. (It could alternatively immediately
post the event here but that doesn't actually fix the problem.) After
the commit the client will install a frame callback. This will
guarantee that the release event will be flushed to the client
eventually.

Now the client will start rendering its third frame. The release event
may or may not have been received in the client's socket buffer
depending on the timing. It doesn't actually matter though and the bug
will be triggered either way. The first thing it does while rendering
is call get_back_bo. The first thing get_back_bo does is dispatch any
pending events in its queue. However this doesn't do anything for the
release event because nothing has read from the socket yet so it is
still only sitting the socket's buffer. At this point the client
hasn't seen any release events yet so it will think both buffers are
still locked and it will allocate a third buffer. Eventually the
client will finish rendering to this third buffer and it will call
eglSwapBuffers. At this point the client will block on the frame
callback which will end up reading from the socket and dispatching the
release event, but it is too late.

When the client calls get_back_bo for its fourth frame it will have
seen one release event so it will reuse the first buffer. It will
continue like this cycling between three buffers.

I hope that makes sense!

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

This adds a test that tries to simulate a simple game loop that would
be like this:

while (1) {
draw_something();
eglSwapBuffers();
}

In this case the test is relying on eglSwapBuffers to throttle to a
sensible frame rate.

The test then verifies that only 2 EGL buffers are used. This is done
via a new request and event in the wayland-test protocol.

Currently this causes 3 buffers to be created because the release
event generated by the swap buffers is not processed by Mesa until it
blocks for the frame complete event in the next swap buffers call, but
that is too late.

This can be fixed in Mesa by issuing a sync request after the swap
buffers and blocking on it before deciding whether to allocate a new
buffer.
---
 configure.ac  |   7 +++
 protocol/wayland-test.xml |   7 +++
 tests/Makefile.am |  15 -
 tests/buffer-count-test.c | 128 ++
 tests/weston-test-client-helper.c |  22 ++-
 tests/weston-test-client-helper.h |   4 ++
 tests/weston-test.c   |  51 ++-
 7 files changed, 231 insertions(+), 3 deletions(-)
 create mode 100644 tests/buffer-count-test.c

diff --git a/configure.ac b/configure.ac
index 86940d5..6e57c25 100644
--- a/configure.ac
+++ b/configure.ac
@@ -61,10 +61,17 @@ COMPOSITOR_MODULES=wayland-server = 1.3.90 pixman-1
 
 AC_ARG_ENABLE(egl, [  --disable-egl],,
   enable_egl=yes)
+AC_ARG_ENABLE(egl-tests, [  --enable-egl-tests],,
+  enable_egl_tests=yes)
 AM_CONDITIONAL(ENABLE_EGL, test x$enable_egl = xyes)
+AM_CONDITIONAL(ENABLE_EGL_TESTS, test x$enable_egl = xyes -a 
x$enable_egl_tests = xyes)
 if test x$enable_egl = xyes; then
AC_DEFINE([ENABLE_EGL], [1], [Build Weston with EGL support])
PKG_CHECK_MODULES(EGL, [egl = 7.10 glesv2])
+
+if test x$enable_egl_tests = xyes; then
+  PKG_CHECK_MODULES([EGL_TESTS], [egl = 7.10 glesv2 wayland-client 
wayland-egl])
+fi
 fi
 
 AC_ARG_ENABLE(xkbcommon,
diff --git a/protocol/wayland-test.xml b/protocol/wayland-test.xml
index 2993f08..18b6625 100644
--- a/protocol/wayland-test.xml
+++ b/protocol/wayland-test.xml
@@ -51,5 +51,12 @@
   arg name=x type=fixed/
   arg name=y type=fixed/
 /event

Re: [PATCH] Flush the wl_display at the end of SwapBuffers

2013-12-04 Thread Neil Roberts
I think this is a good idea. Imagine a simple game main loop like this:

while (TRUE) {
do_some_game_logic();
redraw();
eglSwapBuffers();
}

In that case it wouldn't flush the commit until the right at the
beginning of each call to eglSwapBuffers when it waits for the frame
callback. Then it would have to block waiting for the compositor to
finish rendering before it receives the frame callback. If we dispatch
after the swap buffers then in this case the compositor could start
rendering while the game is in do_some_game_logic().

There was a similar patch proposed on the Mesa-dev mailing list here:

http://lists.freedesktop.org/archives/mesa-dev/2013-August/043697.html

That also points out the additional problem case where the rendering is
done in a separate thread. After the rendering is done potentially
nothing would wake up the main loop thread and cause a dispatch.

That patch also moves the call to dri2_dpy-flush-flush further up. I'm
not sure if that is necessary. It also adds a pointer to the wl_display
in struct dri2_egl_surface which definitely looks unnecessary. So I
think Axel's patch makes more sense.

Reviewed-by: Neil Roberts n...@linux.intel.com

Regards,
- Neil

Axel Davy axel.d...@ens.fr writes:

 We would like the compositor to receive the commited buffer
 as soon as possible, so it has the time to treat it, and 
 release old ones. We shouldn't rely on the client
 to flush the queue for us.

 Signed-off-by: Axel Davy axel.d...@ens.fr
 ---
 We flush the wl_display after we flush the drawable.

  src/egl/drivers/dri2/platform_wayland.c | 2 ++
  1 file changed, 2 insertions(+)

 diff --git a/src/egl/drivers/dri2/platform_wayland.c 
 b/src/egl/drivers/dri2/platform_wayland.c
 index 7e3733b..8c3d1f1 100644
 --- a/src/egl/drivers/dri2/platform_wayland.c
 +++ b/src/egl/drivers/dri2/platform_wayland.c
 @@ -627,6 +627,8 @@ dri2_swap_buffers_with_damage(_EGLDriver *drv,
(*dri2_dpy-flush-flush)(dri2_surf-dri_drawable);
 (*dri2_dpy-flush-invalidate)(dri2_surf-dri_drawable);
  
 +   wl_display_flush(dri2_dpy-wl_dpy);
 +
 return EGL_TRUE;
  }
  
 -- 
 1.8.1.2

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


pgpfefzQHS56N.pgp
Description: PGP signature
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH weston] Automatically generate weston.ini with the right paths

2013-11-23 Thread Neil Roberts
Kristian Høgsberg hoegsb...@gmail.com writes:

 That's a nice idea.  Could we just generate it from configure.ac by
 listing it in AC_CONFIG_FILES?

Sadly that doesn't work because the autoconf expansions still include
variables for make. Eg, @bindir@ expands to ${exec_prefix}/bin. I think
that is needed so that you can use DESTDIR to change the prefix without
rerunning configure. This trick of doing it with sed is recommended in
the autoconf manual: http://is.gd/YivZyl (near the bottom).

 Also, I was thinking that we should add a comment to the top of the
 file saying that this is a sample weston.ini, that there's a
 weston.ini man page, and that you can copy the sample weston.ini to
 ~/.config/weston.ini or /etc/xdg/weston/weston.ini.

Yes, that would be nice. I didn't discover that until yesterday! Perhaps
that would make more sense as a separate patch.

Regards,
- Neil


pgpAG_T_F1M6r.pgp
Description: PGP signature
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH 0/10] Add a mechanism for nested compositors to use subsurfaces without blitting

2013-11-22 Thread Neil Roberts
Hi,

I think this thread has gotten a bit tangled so I've done a bit of minor
rebasing for the patches and pushed them all to github:

https://github.com/bpeel/wayland/commits/wip/wayland-subcompositor
https://github.com/bpeel/mesa/commits/wip/wayland-subcompositor
https://github.com/bpeel/weston/commits/wip/wayland-subcompositor

Regards,
- Neil


pgpkWCY7gPFId.pgp
Description: PGP signature
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH weston] Automatically generate weston.ini with the right paths

2013-11-22 Thread Neil Roberts
Previously weston.ini had hardcoded paths for the weston-* clients in
/usr/bin and /usr/libexec. This was a bit annoying when testing Weston
because you wouldn't usually install those in the system prefix. This
patch adds a make rule to automatically generate weston.ini from a
template file with some replacement markers for the paths so that they
can have the right prefix.
---
 .gitignore|  1 +
 Makefile.am   | 11 +-
 weston.ini| 67 ---
 weston.ini.in | 67 +++
 4 files changed, 78 insertions(+), 68 deletions(-)
 delete mode 100644 weston.ini
 create mode 100644 weston.ini.in

diff --git a/.gitignore b/.gitignore
index b3fb2a1..111c56c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,7 @@ cscope.out
 /missing
 /stamp-h1
 /test-driver
+/weston.ini
 Makefile
 Makefile.in
 TAGS
diff --git a/Makefile.am b/Makefile.am
index e9ecc38..3a7d337 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,4 +6,13 @@ SUBDIRS = shared src clients data protocol tests 
$(wcap_subdir) man
 
 DISTCHECK_CONFIGURE_FLAGS = --disable-setuid-install
 
-EXTRA_DIST = weston.ini wayland-scanner.mk
+EXTRA_DIST = weston.ini.in wayland-scanner.mk
+
+weston.ini : $(srcdir)/weston.ini.in
+   $(AM_V_GEN)$(SED) \
+   -e 's|@bindir[@]|$(bindir)|g' \
+   -e 's|@abs_top_builddir[@]|$(abs_top_builddir)|g' \
+   -e 's|@libexecdir[@]|$(libexecdir)|g' \
+   $  $@
+
+all-local : weston.ini
diff --git a/weston.ini b/weston.ini
deleted file mode 100644
index 4761bed..000
--- a/weston.ini
+++ /dev/null
@@ -1,67 +0,0 @@
-[core]
-#modules=xwayland.so,cms-colord.so
-#shell=desktop-shell.so
-#gbm-format=xrgb2101010
-
-[shell]
-background-image=/usr/share/backgrounds/gnome/Aqua.jpg
-background-color=0xff002244
-background-type=tile
-panel-color=0x90ff
-locking=true
-animation=zoom
-startup-animation=fade
-#binding-modifier=ctrl
-#num-workspaces=6
-#cursor-theme=whiteglass
-#cursor-size=24
-
-#lockscreen-icon=/usr/share/icons/gnome/256x256/actions/lock.png
-#lockscreen=/usr/share/backgrounds/gnome/Garden.jpg
-#homescreen=/usr/share/backgrounds/gnome/Blinds.jpg
-#animation=fade
-
-[launcher]
-icon=/usr/share/icons/gnome/24x24/apps/utilities-terminal.png
-path=/usr/bin/gnome-terminal
-
-[launcher]
-icon=/usr/share/icons/gnome/24x24/apps/utilities-terminal.png
-path=/usr/bin/weston-terminal
-
-[launcher]
-icon=/usr/share/icons/hicolor/24x24/apps/google-chrome.png
-path=/usr/bin/google-chrome
-
-[launcher]
-icon=/usr/share/icons/gnome/24x24/apps/arts.png
-path=./clients/weston-flower
-
-[screensaver]
-# Uncomment path to disable screensaver
-path=/usr/libexec/weston-screensaver
-duration=600
-
-[input-method]
-path=/usr/libexec/weston-keyboard
-
-#[output]
-#name=LVDS1
-#mode=1680x1050
-#transform=90
-#icc_profile=/usr/share/color/icc/colord/Bluish.icc
-
-#[output]
-#name=VGA1
-#mode=173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
-#transform=flipped
-
-#[output]
-#name=X1
-#mode=1024x768
-#transform=flipped-270
-
-#[touchpad]
-#constant_accel_factor = 50
-#min_accel_factor = 0.16
-#max_accel_factor = 1.0
diff --git a/weston.ini.in b/weston.ini.in
new file mode 100644
index 000..5181a9e
--- /dev/null
+++ b/weston.ini.in
@@ -0,0 +1,67 @@
+[core]
+#modules=xwayland.so,cms-colord.so
+#shell=desktop-shell.so
+#gbm-format=xrgb2101010
+
+[shell]
+background-image=/usr/share/backgrounds/gnome/Aqua.jpg
+background-color=0xff002244
+background-type=tile
+panel-color=0x90ff
+locking=true
+animation=zoom
+startup-animation=fade
+#binding-modifier=ctrl
+#num-workspaces=6
+#cursor-theme=whiteglass
+#cursor-size=24
+
+#lockscreen-icon=/usr/share/icons/gnome/256x256/actions/lock.png
+#lockscreen=/usr/share/backgrounds/gnome/Garden.jpg
+#homescreen=/usr/share/backgrounds/gnome/Blinds.jpg
+#animation=fade
+
+[launcher]
+icon=/usr/share/icons/gnome/24x24/apps/utilities-terminal.png
+path=/usr/bin/gnome-terminal
+
+[launcher]
+icon=/usr/share/icons/gnome/24x24/apps/utilities-terminal.png
+path=@bindir@/weston-terminal
+
+[launcher]
+icon=/usr/share/icons/hicolor/24x24/apps/google-chrome.png
+path=/usr/bin/google-chrome
+
+[launcher]
+icon=/usr/share/icons/gnome/24x24/apps/arts.png
+path=@abs_top_builddir@/clients/weston-flower
+
+[screensaver]
+# Uncomment path to disable screensaver
+path=@libexecdir@/weston-screensaver
+duration=600
+
+[input-method]
+path=@libexecdir@/weston-keyboard
+
+#[output]
+#name=LVDS1
+#mode=1680x1050
+#transform=90
+#icc_profile=/usr/share/color/icc/colord/Bluish.icc
+
+#[output]
+#name=VGA1
+#mode=173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
+#transform=flipped
+
+#[output]
+#name=X1
+#mode=1024x768
+#transform=flipped-270
+
+#[touchpad]
+#constant_accel_factor = 50
+#min_accel_factor = 0.16
+#max_accel_factor = 1.0
-- 
1.8.3.1

___
wayland-devel mailing list

Re: Thoughts about decoration information in the xdg_shell

2013-11-18 Thread Neil Roberts
Thiago Macieira thiago.macie...@intel.com writes:

 Make it simpler: all clients MUST be able to draw decorations. That's what 
 Wayland up until now requires anyway.

I think it's a shame to throw out the idea of making the policy be that
clients are allowed to expect SSD if they don't want to draw decorations
themselves. Requiring CSD support only makes it simpler for compositor
developers, but it adds a lot of burden on things like SDL, glut and
applications that really just want a space to render GL content into.

I guess you could make a toolkit-agnostic decorations library using
subsurfaces that these types of applications can use. However I don't
think that will solve the consistency issue because most game-type
applications will want to bundle all of their dependencies so they will
end up wanting to bundle this library. The consistency will then break
when the distro updates its version of the library.

I think the most important decision to make for xdg-shell is whether to
require CSD support or SSD support. How it is actually negotatied is not
as important. I think you have to have a policy of requiring support for
one or the other because it'd be a mess to have a situation where some
apps can't work on certain compositors.

If Gnome Shell doesn't add support for SSD then I suppose that
effectively mandates CSD support in clients that want to be portable
regardless of what is specified in xdg-shell.

It looks like the main incentive to not require SSD support is that it
creates work for the Gnome Shell developers. However you have to bear in
mind that requiring CSD also creates work for all other toolkit
developers which may turn out to be more work overall.

Regards,
- Neil


pgpUPMn3FzCC9.pgp
Description: PGP signature
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH mesa 1/2] wayland: Block for the frame callback in get_back_bo not dri2_swap_buffers

2013-11-15 Thread Neil Roberts
As per Kristian's suggestion we can avoid the problem of effectively
disabling the event queuing mechanism by only doing the sync request
when the swap interval is zero. To fix the bug of using three buffers
we can just block for the frame callback in get_back_bo instead of
swap_buffers. I was originally a bit reluctant to do this because it
will end up blocking in an unusual place (ie, usually in glClear) but
I suppose that doesn't really matter.

I've split that change out into a separate patch because it is an
independent problem. The new swap interval patch can now share the
callback variable with the frame callback because they are now blocked
for in the same place.

Just to note, in addition to these two patches I think it would be
good to apply these other two patches which are buried in this thread
(although they are not required):

http://lists.freedesktop.org/archives/wayland-devel/2013-October/011766.html
http://lists.freedesktop.org/archives/wayland-devel/2013-September/010967.html

- Neil

--- 8 --- (use git am --scissors to automatically chop here)

Consider a typical game-style main loop which might be like this:

while (1) {
draw_something();
eglSwapBuffers();
}

In this case the game is relying on eglSwapBuffers to throttle to a sensible
frame rate. Previously this game would end up using three buffers even though
it should only need two. This is because Mesa decides whether to allocate a
new buffer in get_back_bo which would be before it has tried to read any
events from the compositor so it wouldn't have seen any buffer release events
yet.

This patch just moves the block for the frame callback to get_back_bo.
Typically the compositor will send a release event immediately after one of
the attaches so if we block for the frame callback here then we can be sure to
have completed at least one roundtrip and received that release event after
attaching the previous buffer before deciding whether to allocate a new one.

dri2_swap_buffers always calls get_back_bo so even if the client doesn't
render anything we will still be sure to block to the frame callback. The code
to create the new frame callback has been moved to after this call so that we
can be sure to have cleared the previous frame callback before requesting a
new one.
---
 src/egl/drivers/dri2/platform_wayland.c | 34 +++--
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/src/egl/drivers/dri2/platform_wayland.c 
b/src/egl/drivers/dri2/platform_wayland.c
index f9065bb..5ce8981 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -263,8 +263,19 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
   dri2_egl_display(dri2_surf-base.Resource.Display);
int i;
 
-   /* There might be a buffer release already queued that wasn't processed */
-   wl_display_dispatch_queue_pending(dri2_dpy-wl_dpy, dri2_dpy-wl_queue);
+   if (dri2_surf-frame_callback == NULL) {
+  /* There might be a buffer release already queued that wasn't processed 
*/
+  wl_display_dispatch_queue_pending(dri2_dpy-wl_dpy, dri2_dpy-wl_queue);
+   } else {
+  /* We throttle to the frame callback here so that we can be sure to have
+   * received any release events before trying to decide whether to
+   * allocate a new buffer */
+  do {
+ if (wl_display_dispatch_queue(dri2_dpy-wl_dpy,
+   dri2_dpy-wl_queue) == -1)
+return EGL_FALSE;
+  } while (dri2_surf-frame_callback != NULL);
+   }
 
if (dri2_surf-back == NULL) {
   for (i = 0; i  ARRAY_SIZE(dri2_surf-color_buffers); i++) {
@@ -557,18 +568,7 @@ dri2_swap_buffers_with_damage(_EGLDriver *drv,
 {
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
-   int i, ret = 0;
-
-   while (dri2_surf-frame_callback  ret != -1)
-  ret = wl_display_dispatch_queue(dri2_dpy-wl_dpy, dri2_dpy-wl_queue);
-   if (ret  0)
-  return EGL_FALSE;
-
-   dri2_surf-frame_callback = wl_surface_frame(dri2_surf-wl_win-surface);
-   wl_callback_add_listener(dri2_surf-frame_callback,
-frame_listener, dri2_surf);
-   wl_proxy_set_queue((struct wl_proxy *) dri2_surf-frame_callback,
-  dri2_dpy-wl_queue);
+   int i;
 
for (i = 0; i  ARRAY_SIZE(dri2_surf-color_buffers); i++)
   if (dri2_surf-color_buffers[i].age  0)
@@ -581,6 +581,12 @@ dri2_swap_buffers_with_damage(_EGLDriver *drv,
   return EGL_FALSE;
}
 
+   dri2_surf-frame_callback = wl_surface_frame(dri2_surf-wl_win-surface);
+   wl_callback_add_listener(dri2_surf-frame_callback,
+frame_listener, dri2_surf);
+   wl_proxy_set_queue((struct wl_proxy *) dri2_surf-frame_callback,
+  dri2_dpy-wl_queue);
+
dri2_surf-back-age = 1;
dri2_surf-current = dri2_surf-back;
dri2_surf-back = NULL;

[PATCH mesa v5 2/2] wayland: Add support for eglSwapInterval

2013-11-15 Thread Neil Roberts
The Wayland EGL platform now respects the eglSwapInterval value. The value is
clamped to either 0 or 1 because it is difficult (and probably not useful) to
sync to more than 1 redraw.

The main change is that if the swap interval is 0 then Mesa won't install a
frame callback so that eglSwapBuffers can be executed as often as necessary.
Instead it will do a sync request after the swap buffers. It will block for
sync complete event in get_back_bo instead of the frame callback. The
compositor is likely to send a release event while processing the new buffer
attach and this makes sure we will receive that before deciding whether to
allocate a new buffer.

If there are no buffers available then instead of returning with an error,
get_back_bo will now poll the compositor by repeatedly sending sync requests
every 10ms. This is a last resort and in theory this shouldn't happen because
there should be no reason for the compositor to hold on to more than three
buffers. That means whenever we attach the fourth buffer we should always get
an immediate release event which should come in with the notification for the
first sync request that we are throttled to.

When the compositor is directly scanning out from the application's buffer it
may end up holding on to three buffers. These are the one that is is currently
scanning out from, one that has been given to DRM as the next buffer to flip
to, and one that has been attached and will be given to DRM as soon as the
previous flip completes. When we attach a fourth buffer to the compositor it
should replace that third buffer so we should get a release event immediately
after that. This patch therefore also changes the number of buffer slots to 4
so that we can accomodate that situation.

If DRM eventually gets a way to cancel a pending page flip then the compositors
can be changed to only need to hold on to two buffers and this value can be
put back to 3.

This also moves the vblank configuration defines from platform_x11.c to the
common egl_dri2.h header so they can be shared by both platforms.
---
 src/egl/drivers/dri2/egl_dri2.h |  10 +-
 src/egl/drivers/dri2/platform_wayland.c | 199 +++-
 src/egl/drivers/dri2/platform_x11.c |   6 -
 3 files changed, 179 insertions(+), 36 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 8c303d9..d29dd98 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -174,7 +174,7 @@ struct dri2_egl_surface
struct wl_egl_window  *wl_win;
intdx;
intdy;
-   struct wl_callback*frame_callback;
+   struct wl_callback*throttle_callback;
int   format;
 #endif
 
@@ -194,7 +194,7 @@ struct dri2_egl_surface
 #endif
   int locked;
   int age;
-   } color_buffers[3], *back, *current;
+   } color_buffers[4], *back, *current;
 #endif
 
 #ifdef HAVE_ANDROID_PLATFORM
@@ -220,6 +220,12 @@ struct dri2_egl_image
__DRIimage *dri_image;
 };
 
+/* From xmlpool/options.h, user exposed so should be stable */
+#define DRI_CONF_VBLANK_NEVER 0
+#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
+#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
+#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
+
 /* standard typecasts */
 _EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
 _EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
diff --git a/src/egl/drivers/dri2/platform_wayland.c 
b/src/egl/drivers/dri2/platform_wayland.c
index 5ce8981..fca35db 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -34,6 +34,7 @@
 #include unistd.h
 #include fcntl.h
 #include xf86drm.h
+#include poll.h
 
 #include egl_dri2.h
 
@@ -183,8 +184,16 @@ dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay 
*disp,
   _EGLConfig *conf, EGLNativeWindowType window,
   const EGLint *attrib_list)
 {
-   return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   _EGLSurface *surf;
+
+   surf = dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
  window, attrib_list);
+
+   if (surf != NULL)
+  drv-API.SwapInterval(drv, disp, surf, dri2_dpy-default_swap_interval);
+
+   return surf;
 }
 
 /**
@@ -217,8 +226,8 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, 
_EGLSurface *surf)
  dri2_dpy-dri2-releaseBuffer(dri2_dpy-dri_screen,
dri2_surf-dri_buffers[i]);
 
-   if (dri2_surf-frame_callback)
-  wl_callback_destroy(dri2_surf-frame_callback);
+   if (dri2_surf-throttle_callback)
+  wl_callback_destroy(dri2_surf-throttle_callback);
 
if (dri2_surf-base.Type == EGL_WINDOW_BIT) {
   dri2_surf-wl_win-private = NULL;
@@ -257,41 +266,99 @@ dri2_release_buffers(struct dri2_egl_surface *dri2_surf)
 }
 
 static int
+poll_compositor(struct 

[PATCH] Add documentation for wl_shm_buffer_begin/end_access

2013-11-14 Thread Neil Roberts
It's not obvious that these functions are needed so it would be good
to have some documentation for them.
---
 doc/doxygen/Makefile.am |  3 ++-
 src/wayland-shm.c   | 64 +
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/doc/doxygen/Makefile.am b/doc/doxygen/Makefile.am
index 0351c1e..078506d 100644
--- a/doc/doxygen/Makefile.am
+++ b/doc/doxygen/Makefile.am
@@ -14,7 +14,8 @@ scanned_src_files_client =\
 scanned_src_files_server = \
$(scanned_src_files_shared) \
$(top_srcdir)/src/wayland-server.c  \
-   $(top_srcdir)/src/wayland-server.h
+   $(top_srcdir)/src/wayland-server.h  \
+   $(top_srcdir)/src/wayland-shm.c
 
 # find all man/man3/wl_foo.3 pages
 # for this to work, we need to create them before the man target (hence
diff --git a/src/wayland-shm.c b/src/wayland-shm.c
index 28f52f4..814a4cf 100644
--- a/src/wayland-shm.c
+++ b/src/wayland-shm.c
@@ -358,6 +358,23 @@ wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer)
return buffer-stride;
 }
 
+
+/** Get a pointer to the memory for the SHM buffer
+ *
+ * \param buffer The buffer object
+ *
+ * Returns a pointer which can be used to read the data contained in
+ * the given SHM buffer.
+ *
+ * As this buffer is memory-mapped, reading it from may generate
+ * SIGBUS signals. This can happen if the client claims that the
+ * buffer is larger than it is or if something truncates the
+ * underlying file. To prevent this signal from causing the compositor
+ * to crash you should call wl_shm_buffer_begin_access and
+ * wl_shm_buffer_end_access around code that reads from the memory.
+ *
+ * \memberof wl_shm_buffer
+ */
 WL_EXPORT void *
 wl_shm_buffer_get_data(struct wl_shm_buffer *buffer)
 {
@@ -454,6 +471,42 @@ init_sigbus_data_key(void)
pthread_key_create(wl_shm_sigbus_data_key, destroy_sigbus_data);
 }
 
+/** Mark that the given SHM buffer is about to be accessed
+ *
+ * \param buffer The SHM buffer
+ *
+ * An SHM buffer is a memory-mapped file given by the client.
+ * According to POSIX, reading from a memory-mapped region that
+ * extends off the end of the file will cause a SIGBUS signal to be
+ * generated. Normally this would cause the compositor to terminate.
+ * In order to make the compositor robust against clients that change
+ * the size of the underlying file or lie about its size, you should
+ * protect access to the buffer by calling this function before
+ * reading from the memory and call wl_shm_buffer_end_access
+ * afterwards. This will install a signal handler for SIGBUS which
+ * will prevent the compositor from crashing.
+ *
+ * After calling this function the signal handler will remain
+ * installed for the lifetime of the compositor process. Note that
+ * this function will not work properly if the compositor is also
+ * installing its own handler for SIGBUS.
+ *
+ * If a SIGBUS signal is received for an address within the range of
+ * the SHM pool of the given buffer then the client will be sent an
+ * error event when wl_shm_buffer_end_access is called. If the signal
+ * is for an address outside that range then the signal handler will
+ * reraise the signal which would will likely cause the compositor to
+ * terminate.
+ *
+ * It is safe to nest calls to these functions as long as the nested
+ * calls are all accessing the same buffer. The number of calls to
+ * wl_shm_buffer_end_access must match the number of calls to
+ * wl_shm_buffer_begin_access. These functions are thread-safe and it
+ * is allowed to simultaneously access different buffers or the same
+ * buffer from multiple threads.
+ *
+ * \memberof wl_shm_buffer
+ */
 WL_EXPORT void
 wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
 {
@@ -480,6 +533,17 @@ wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
sigbus_data-access_count++;
 }
 
+/** Ends the access to a buffer started by wl_shm_buffer_begin_access
+ *
+ * \param buffer The SHM buffer
+ *
+ * This should be called after wl_shm_buffer_begin_access once the
+ * buffer is no longer being accessed. If a SIGBUS signal was
+ * generated in-between these two calls then the resource for the
+ * given buffer will be sent an error.
+ *
+ * \memberof wl_shm_buffer
+ */
 WL_EXPORT void
 wl_shm_buffer_end_access(struct wl_shm_buffer *buffer)
 {
-- 
1.8.3.1

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


[PATCH v2] server: Add API to protect access to an SHM buffer

2013-11-13 Thread Neil Roberts
Ok, here is a second version of the patch which leaves the signal
handler permanently installed and uses thread-local storage to keep
track of the current pool.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

Linux will let you mmap a region of a file that is larger than the
size of the file. If you then try to read from that region the process
will get a SIGBUS signal. Currently the clients can use this to crash
a compositor because it can create a pool and lie about the size of
the file which will cause the compositor to try and read past the end
of it. The compositor can't simply check the size of the file to
verify that it is big enough because then there is a race condition
where the client may truncate the file after the check is performed.

This patch adds the following two public functions in the server API
which can be used wrap access to an SHM buffer:

void wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer);
void wl_shm_buffer_end_access(struct wl_shm_buffer *buffer);

The first time wl_shm_buffer_begin_access is called a signal handler
for SIGBUS will be installed. If the signal is caught then the buffer
for the current pool is remapped to an anonymous private buffer at the
same address which allows the compositor to continue without crashing.
The end_access function will then post an error to the buffer
resource.

The current pool is stored as part of some thread-local storage so
that multiple threads can safely independently access separate
buffers.

Eventually we may want to add some more API so that compositors can
hook into the signal handler or replace it entirely if they also want
to do some SIGBUS handling.
---
 src/wayland-server.h |   6 +++
 src/wayland-shm.c| 131 +++
 2 files changed, 137 insertions(+)

diff --git a/src/wayland-server.h b/src/wayland-server.h
index 36c9a15..f5427fd 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -412,6 +412,12 @@ wl_resource_get_destroy_listener(struct wl_resource 
*resource,
 
 struct wl_shm_buffer;
 
+void
+wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer);
+
+void
+wl_shm_buffer_end_access(struct wl_shm_buffer *buffer);
+
 struct wl_shm_buffer *
 wl_shm_buffer_get(struct wl_resource *resource);
 
diff --git a/src/wayland-shm.c b/src/wayland-shm.c
index eff29c3..28f52f4 100644
--- a/src/wayland-shm.c
+++ b/src/wayland-shm.c
@@ -32,10 +32,20 @@
 #include string.h
 #include sys/mman.h
 #include unistd.h
+#include assert.h
+#include signal.h
+#include pthread.h
 
 #include wayland-private.h
 #include wayland-server.h
 
+/* This once_t is used to synchronize installing the SIGBUS handler
+ * and creating the TLS key. This will be done in the first call
+ * wl_shm_buffer_begin_access which can happen from any thread */
+static pthread_once_t wl_shm_sigbus_once = PTHREAD_ONCE_INIT;
+static pthread_key_t wl_shm_sigbus_data_key;
+static struct sigaction wl_shm_old_sigbus_action;
+
 struct wl_shm_pool {
struct wl_resource *resource;
int refcount;
@@ -52,6 +62,12 @@ struct wl_shm_buffer {
struct wl_shm_pool *pool;
 };
 
+struct wl_shm_sigbus_data {
+   struct wl_shm_pool *current_pool;
+   int access_count;
+   int fallback_mapping_used;
+};
+
 static void
 shm_pool_unref(struct wl_shm_pool *pool)
 {
@@ -368,3 +384,118 @@ wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
 {
return buffer-height;
 }
+
+static void
+reraise_sigbus(void)
+{
+   /* If SIGBUS is raised for some other reason than accessing
+* the pool then we'll uninstall the signal handler so we can
+* reraise it. This would presumably kill the process */
+   sigaction(SIGBUS, wl_shm_old_sigbus_action, NULL);
+   raise(SIGBUS);
+}
+
+static void
+sigbus_handler(int signum, siginfo_t *info, void *context)
+{
+   struct wl_shm_sigbus_data *sigbus_data =
+   pthread_getspecific(wl_shm_sigbus_data_key);
+   struct wl_shm_pool *pool;
+
+   if (sigbus_data == NULL) {
+   reraise_sigbus();
+   return;
+   }
+
+   pool = sigbus_data-current_pool;
+
+   /* If the offending address is outside the mapped space for
+* the pool then the error is a real problem so we'll reraise
+* the signal */
+   if (pool == NULL ||
+   (char *) info-si_addr  pool-data ||
+   (char *) info-si_addr = pool-data + pool-size) {
+   reraise_sigbus();
+   return;
+   }
+
+   sigbus_data-fallback_mapping_used = 1;
+
+   /* This should replace the previous mapping */
+   if (mmap(pool-data, pool-size,
+PROT_READ | PROT_WRITE,
+MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
+0, 0) == (void *) -1) {
+   reraise_sigbus();
+   return;
+   }
+}
+
+static void
+destroy_sigbus_data(void *data)
+{
+   struct wl_shm_sigbus_data 

[PATCH weston v2] Add calls to wl_shm_buffer_begin/end_access

2013-11-13 Thread Neil Roberts
Thanks for the feedback. Here is a version two of the patch which
fixes some merge conflicts on master and adds support for the pixman
renderer.

Kristian wrote:

 As for the pixman renderer it should be a matter of just wrapping
 the calls to pixman_image_composite32() in
 pixman_renderer_read_pixels() and around the last if/else in
 draw_view() where we end up calling repaint_region() in either
 branch.

I think the pixman_renderer_read_pixels case doesn't need the wrapper
functions because it is reading from the output's buffer into another
malloc'd buffer. Both of those are allocated by the compositor and
shouldn't cause any problems.

I put the wrapper calls inside repaint_region in order to minimise the
length of time that the wrapper is enabled.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

This wraps all accesses to an SHM buffer between wl_shm_buffer_begin
and end so that wayland-shm can install a handler for SIGBUS and catch
attempts to pass the compositor a buffer that is too small.
---
 src/compositor-drm.c  | 11 ---
 src/gl-renderer.c |  6 ++
 src/pixman-renderer.c |  6 ++
 src/rpi-renderer.c|  4 
 src/screenshooter.c   |  4 
 5 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index b929728..d4fc871 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -974,6 +974,7 @@ static void
 drm_output_set_cursor(struct drm_output *output)
 {
struct weston_view *ev = output-cursor_view;
+   struct weston_buffer *buffer;
struct drm_compositor *c =
(struct drm_compositor *) output-base.compositor;
EGLint handle, stride;
@@ -988,18 +989,22 @@ drm_output_set_cursor(struct drm_output *output)
return;
}
 
-   if (ev-surface-buffer_ref.buffer 
+   buffer = ev-surface-buffer_ref.buffer;
+
+   if (buffer 
pixman_region32_not_empty(output-cursor_plane.damage)) {
pixman_region32_fini(output-cursor_plane.damage);
pixman_region32_init(output-cursor_plane.damage);
output-current_cursor ^= 1;
bo = output-cursor_bo[output-current_cursor];
memset(buf, 0, sizeof buf);
-   stride = 
wl_shm_buffer_get_stride(ev-surface-buffer_ref.buffer-shm_buffer);
-   s = 
wl_shm_buffer_get_data(ev-surface-buffer_ref.buffer-shm_buffer);
+   stride = wl_shm_buffer_get_stride(buffer-shm_buffer);
+   s = wl_shm_buffer_get_data(buffer-shm_buffer);
+   wl_shm_buffer_begin_access(buffer-shm_buffer);
for (i = 0; i  ev-geometry.height; i++)
memcpy(buf + i * 64, s + i * stride,
   ev-geometry.width * 4);
+   wl_shm_buffer_end_access(buffer-shm_buffer);
 
if (gbm_bo_write(bo, buf, sizeof buf)  0)
weston_log(failed update cursor: %m\n);
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 68a071f..7a535c7 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -899,10 +899,12 @@ gl_renderer_flush_damage(struct weston_surface *surface)
glBindTexture(GL_TEXTURE_2D, gs-textures[0]);
 
if (!gr-has_unpack_subimage) {
+   wl_shm_buffer_begin_access(buffer-shm_buffer);
glTexImage2D(GL_TEXTURE_2D, 0, format,
 gs-pitch, buffer-height, 0,
 format, pixel_type,
 wl_shm_buffer_get_data(buffer-shm_buffer));
+   wl_shm_buffer_end_access(buffer-shm_buffer);
 
goto done;
}
@@ -914,13 +916,16 @@ gl_renderer_flush_damage(struct weston_surface *surface)
if (gs-needs_full_upload) {
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
+   wl_shm_buffer_begin_access(buffer-shm_buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, gs-pitch, buffer-height,
format, pixel_type, data);
+   wl_shm_buffer_end_access(buffer-shm_buffer);
goto done;
}
 
rectangles = pixman_region32_rectangles(gs-texture_damage, n);
+   wl_shm_buffer_begin_access(buffer-shm_buffer);
for (i = 0; i  n; i++) {
pixman_box32_t r;
 
@@ -932,6 +937,7 @@ gl_renderer_flush_damage(struct weston_surface *surface)
r.x2 - r.x1, r.y2 - r.y1,
format, pixel_type, data);
}
+   wl_shm_buffer_end_access(buffer-shm_buffer);
 #endif
 
 done:
diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index a80be5f..b719829 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -305,6 +305,9 @@ repaint_region(struct weston_view *ev, struct 

Re: [PATCH mesa v4] wayland: Add support for eglSwapInterval

2013-10-30 Thread Neil Roberts
Tomeu Vizoso to...@tomeuvizoso.net writes:

 What I fail to see is why a single sync should be enough, as we don't
 know when the GPU will signal that it's done with the buffer that we
 are waiting to be released.

You are right that we don't know when the GPU will release the buffer.
However we are not waiting for that. We are assuming that the GPU is
only going to hold on to at most 2 buffers. In the DRM / Mesa case it
needs to hold on to these because one will be used for scanout and one
will be queued for the page flip. If we attach a third buffer then it
will be held by the compositor as a queue for the next flip. We are
assuming it won't have given this buffer to the GPU. Therefore if we
attach a fourth buffer it is easy for the compositor to immediately
release its lock on the third buffer and replace it with the fourth. So
we can assume that the fourth attach will always generate an immediate
release event. Sending a sync request will ensure that we always get
this release event. So if we have four buffer slots we can assume that
one of the attaches will always generate an immediate release event.

In the non-fullscreen case where we don't really need to wait for the
GPU, we only need 2 slots because the compositor will only lock one
buffer.

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


Re: [PATCH mesa v4] wayland: Add support for eglSwapInterval

2013-10-29 Thread Neil Roberts
Jason Ekstrand ja...@jlekstrand.net writes:

 You don't have to continuously sync, just sync after every
 attach/commit. While it may be somewhat non-obvious, I don't see how
 calling sync once per frame is any worse than setting some flag
 somewhere.

Hrmm thinking about it, I suppose sending the sync request isn't totally
free because it will end up waking up the client an extra time to get
the sync complete event. In a normal client this information wouldn't be
used until the next time get_back_bo is called and Mesa's event queue is
flushed so the wake up is not necessary. Waking up an extra time
effectively negates the whole point of having the queuing mechanism in
the first place.

In this version 4 of the patch I made it so that it always does a sync
request even if the application is using eglSwapInterval(1). This is
needed because otherwise if the application isn't installing its own
frame callback then it won't try to block for Mesa's frame callback
until the next eglSwapInterval which means it won't have had a chance to
receive any release events when get_back_bo is called. That would cause
it to use an extra unnecessary buffer.

So the patch effectively just turns off the queuing mechanism for all
EGL clients through the backdoor.

You could argue that we shouldn't use the sync request for
eglSwapInterval(0) but I don't think that would be a good idea. The case
where this would cause an extra redundant buffer is not a corner case.
I think most game-style applications (eg, something using SDL) would hit
this case because they would be relying on eglSwapInterval to do the
throttling.

I think making those games use an extra buffer is a worse crime than
waking up the clients an extra time. The problem is not specific to the
my patch and is happening right now with Weston master. I'm starting to
wonder if we should just give up on the event queuing altogether.

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


[PATCH weston] tests: Test whether a simple EGL main loop uses too many buffers

2013-10-29 Thread Neil Roberts
Here is a test case which demonstrates the 3 buffers problem. It is
fixed by the eglSwapInterval patch because that installs a sync event,
but note the problem isn't really related to eglSwapInterval and is
something we should probably fix anyway.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

This adds a test that tries to simulate a simple game loop that would
be like this:

while (1) {
draw_something();
eglSwapBuffers();
}

In this case the test is relying on eglSwapBuffers to throttle to a
sensible frame rate.

The test then verifies that only 2 EGL buffers are used. This is done
via a new request and event in the wayland-test protocol.

Currently this causes 3 buffers to be created because the release
event generated by the swap buffers is not processed by Mesa until it
blocks for the frame complete event in the next swap buffers call, but
that is too late.

This can be fixed in Mesa by issuing a sync request after the swap
buffers and blocking on it before deciding whether to allocate a new
buffer.
---
 configure.ac  |   7 +++
 protocol/wayland-test.xml |   7 +++
 tests/Makefile.am |  12 
 tests/buffer-count-test.c | 128 ++
 tests/weston-test-client-helper.c |  22 ++-
 tests/weston-test-client-helper.h |   4 ++
 tests/weston-test.c   |  51 ++-
 7 files changed, 229 insertions(+), 2 deletions(-)
 create mode 100644 tests/buffer-count-test.c

diff --git a/configure.ac b/configure.ac
index 5d0d060..ce0fdbe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -59,10 +59,17 @@ COMPOSITOR_MODULES=wayland-server = 1.3.90 pixman-1
 
 AC_ARG_ENABLE(egl, [  --disable-egl],,
   enable_egl=yes)
+AC_ARG_ENABLE(egl-tests, [  --enable-egl-tests],,
+  enable_egl_tests=yes)
 AM_CONDITIONAL(ENABLE_EGL, test x$enable_egl = xyes)
+AM_CONDITIONAL(ENABLE_EGL_TESTS, test x$enable_egl = xyes -a 
x$enable_egl_tests = xyes)
 if test x$enable_egl = xyes; then
AC_DEFINE([ENABLE_EGL], [1], [Build Weston with EGL support])
PKG_CHECK_MODULES(EGL, [egl = 7.10 glesv2])
+
+if test x$enable_egl_tests = xyes; then
+  PKG_CHECK_MODULES([EGL_TESTS], [egl = 7.10 glesv2 wayland-client 
wayland-egl])
+fi
 fi
 
 AC_ARG_ENABLE(xkbcommon,
diff --git a/protocol/wayland-test.xml b/protocol/wayland-test.xml
index 2993f08..18b6625 100644
--- a/protocol/wayland-test.xml
+++ b/protocol/wayland-test.xml
@@ -51,5 +51,12 @@
   arg name=x type=fixed/
   arg name=y type=fixed/
 /event
+request name=get_n_egl_buffers
+  !-- causes a n_egl_buffers event to be sent which reports how many
+   buffer objects are live for the client --
+/request
+event name=n_egl_buffers
+  arg name=n type=uint/
+/event
   /interface
 /protocol
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5be52c6..e458eff 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -18,6 +18,11 @@ weston_tests =   \
subsurface.weston   \
$(xwayland_test)
 
+if ENABLE_EGL_TESTS
+weston_tests +=\
+   buffer-count.weston
+endif
+
 AM_TESTS_ENVIRONMENT = \
abs_builddir='$(abs_builddir)'; export abs_builddir;
 
@@ -63,6 +68,10 @@ weston_test_la_SOURCES = \
wayland-test-protocol.c \
wayland-test-server-protocol.h
 
+if ENABLE_EGL_TESTS
+weston_test_la_LDFLAGS += $(EGL_TESTS_LIBS)
+endif
+
 weston_test_runner_src =   \
weston-test-runner.c\
weston-test-runner.h
@@ -117,6 +126,9 @@ text_weston_LDADD = $(weston_test_client_libs)
 subsurface_weston_SOURCES = subsurface-test.c $(weston_test_client_src)
 subsurface_weston_LDADD = $(weston_test_client_libs)
 
+buffer_count_weston_SOURCES = buffer-count-test.c $(weston_test_client_src)
+buffer_count_weston_LDADD = $(weston_test_client_libs) $(EGL_TESTS_LIBS)
+
 xwayland_weston_SOURCES = xwayland-test.c  $(weston_test_client_src)
 
 xwayland_weston_LDADD = $(weston_test_client_libs) $(XWAYLAND_TEST_LIBS)
diff --git a/tests/buffer-count-test.c b/tests/buffer-count-test.c
new file mode 100644
index 000..ad2bcee
--- /dev/null
+++ b/tests/buffer-count-test.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this 

Re: [PATCH mesa v4] wayland: Add support for eglSwapInterval

2013-10-28 Thread Neil Roberts
Just to be clear, I think the discussion about whether to queue release
events is no longer related to implementing eglSwapInterval(0) so it
shouldn't hold up the patch. As far as I understand if you want to
render at the maximum rate you need four buffer slots and being able to
disable the queuing mechanism isn't going to affect that. If the device
can't handle four buffers then applications simply can't use
eglSwapInterval(0) when rendering fullscreen. Increasing the number of
buffer slots doesn't affect the number of buffers that will actually be
used in the normal case of non-fullscreen applications which should
continue to just use two buffers.

I agree that we should probably do something about the event queuing
anyway. Currently if a fullscreen application goes idle after drawing
its last frame it will never get the release event for the buffer
because nothing will flush the queue. This would deny the application a
chance to free the buffer. However I don't know if having a mechanism to
explicitly disable the queuing is the right answer in this case and it
might make more sense for the compositor to ensure that it always
eventually flushes the queue instead of keeping it indefinitely. My
previous patch to disable the queuing when there are no frame callbacks
could still be a good way to achieve that.

Regards,
- Neil

Daniel Stone dan...@fooishbar.org writes:

 Hi,

 On 28 October 2013 11:19, Tomeu Vizoso to...@tomeuvizoso.net wrote:
 I'm still concerned about platforms with high resolution displays but
 relatively little memory.

 I'm thinking of the RPi, but my understanding is that Android goes to
 great lengths to reduce the number of buffers that clients have to
 keep, because of general memory consumption, but also because scanout
 buffers are precious when you try to get the smoothest of the
 experiences that is possible on these phones.

 I think we should still consider adding a flag through which the
 client can tell the compositor to send the release events immediately
 instead of queuing them.

 Otherwise, the compositor is making a very broad assumption on the
 client's inner workings if it assumes that release events can be
 queued without a negative impact on performance.

 Yeah, I agree.  Maybe it could be an eglQueryWaylandBufferWL parameter
 for EGL buffers?

 Ramping up the number of buffers used just isn't an option on
 platforms with not massive amounts of memory, but enormous displays.
 It also kinda cancels out some of the buffer_age benefits too.  I take
 the point that this is solving a different symptom of the same
 problem, but I'm worried that it'll paper over the problem and we'll
 end up just shipping patched versions (or fielding bug reports) on ARM
 indefinitely.

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


[PATCH mesa v3] wayland: Add an extension to create wl_buffers from EGLImages

2013-10-28 Thread Neil Roberts
Here is an updated version of the patch to address Axel Davy's
concerns and change the wording of the extension to make it clear that
the function can return EGL_BAD_MATCH for any reason which prevents
the buffer from being represented as a wl_buffer and not just due to
differences in the format. This should make it clear that it is
acceptable for the function to fail if the compositor is running on a
different graphics card from the compositor and the buffer is using an
unsupported tiling format.

I haven't made any changes to the implementation because as far as I
understand the Wayland backend currently always uses the same device
as the compositor which is the one that is passed down in the device
event in the wl_drm interface so it can't have problems with tiling
layouts yets.

There is still some ongoing discussion about whether to add
wl_display_get_main_queue(). Kristian had two alternative proposals.
The first was to make Mesa internally bind a second wl_drm object
which wouldn't have a queue set on it and use that to create the
wl_buffers. I couldn't get that to work because that would also need a
second wl_registry with the default queue but we wouldn't be able to
read the events from that without messing up the application. The
second proposal was to make wl_proxy_set_queue take a NULL argument
which would reset the queue back to the default. I'm not really a big
fan of that because it's not very obvious and I don't see a good
reason to hide the main queue.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

This adds an extension called EGL_WL_create_wayland_buffer_from_image
which adds the following single function:

struct wl_buffer *
eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);

The function creates a wl_buffer which shares its contents with the given
EGLImage. The expected use case for this is in a nested Wayland compositor
which is using subsurfaces to present buffers from its clients. Using this
extension it can attach the client buffers directly to the subsurface without
having to blit the contents into an intermediate buffer. The compositing can
then be done in the parent compositor.

The extension is only implemented in the Wayland EGL platform because of
course it wouldn't make sense anywhere else.
---
 .../specs/WL_create_wayland_buffer_from_image.spec | 101 +
 include/EGL/eglmesaext.h   |  10 ++
 src/egl/drivers/dri2/platform_wayland.c|  79 
 src/egl/main/eglapi.c  |  25 +
 src/egl/main/eglapi.h  |   8 ++
 src/egl/main/egldisplay.h  |   1 +
 src/egl/main/eglmisc.c |   1 +
 7 files changed, 225 insertions(+)
 create mode 100644 docs/specs/WL_create_wayland_buffer_from_image.spec

diff --git a/docs/specs/WL_create_wayland_buffer_from_image.spec 
b/docs/specs/WL_create_wayland_buffer_from_image.spec
new file mode 100644
index 000..aa5eb4d
--- /dev/null
+++ b/docs/specs/WL_create_wayland_buffer_from_image.spec
@@ -0,0 +1,101 @@
+Name
+
+WL_create_wayland_buffer_from_image
+
+Name Strings
+
+EGL_WL_create_wayland_buffer_from_image
+
+Contributors
+
+Neil Roberts
+Axel Davy
+Daniel Stone
+
+Contact
+
+Neil Roberts neil.s.robe...@intel.com
+
+Status
+
+Proposal
+
+Version
+
+Version 2, October 25, 2013
+
+Number
+
+EGL Extension #not assigned
+
+Dependencies
+
+Requires EGL 1.4 or later.  This extension is written against the
+wording of the EGL 1.4 specification.
+
+EGL_KHR_base_image is required.
+
+Overview
+
+This extension provides an entry point to create a wl_buffer which shares
+its contents with a given EGLImage. The expected use case for this is in a
+nested Wayland compositor which is using subsurfaces to present buffers
+from its clients. Using this extension it can attach the client buffers
+directly to the subsurface without having to blit the contents into an
+intermediate buffer. The compositing can then be done in the parent
+compositor.
+
+The nested compositor can create an EGLImage from a client buffer resource
+using the existing WL_bind_wayland_display extension. It should also be
+possible to create buffers using other types of images although there is
+no expected use case for that.
+
+IP Status
+
+Open-source; freely implementable.
+
+New Procedures and Functions
+
+struct wl_buffer *eglCreateWaylandBufferFromImageWL(EGLDisplay dpy,
+EGLImageKHR image);
+
+New Tokens
+
+None.
+
+Additions to the EGL 1.4 Specification:
+
+To create a client-side wl_buffer from an EGLImage call
+
+  struct wl_buffer *eglCreateWaylandBufferFromImageWL(EGLDisplay dpy,
+  EGLImageKHR image);
+
+The returned

[PATCH mesa v4] wayland: Add support for eglSwapInterval

2013-10-25 Thread Neil Roberts
Ok, here is version 4 of the patch taking into account the discussion
with Jason Ekstrand. The assumption is that if we have enough buffer
slots then we should always get a release event immediately after one
of the attaches. That means we can just rely on sending a sync request
after the commit in order to get a buffer release and we don't need to
bother with the request to disable the queuing mechanism.

The previous version of the patch would block in a loop calling
wl_dispatch_queue if it couldn't find a buffer. This is only a
sensible option if we know that the compositor isn't queueing the
release events. If not this loop would just block indefinitely. If the
theory about getting release events is correct then we should never
actually hit this loop so it probably doesn't really matter what it
does. However, I didn't like the idea of having a loop there that
would just block forever so I changed it to poll the compositor with a
sync request every 10ms in order to force it to flush the queue. It
prints a warning if this case is hit so that we will know there is a
problem.

I made the change to make it use 4 buffer slots in this patch and
tested that it does use exactly all 4 of them when the application is
fullscreen. This does work and it doesn't hit the polling path. I
guess we could change to be five in order to cope with the subsurface
case but I'm a bit reluctant to do that because it seems like quite a
corner case and maybe it's better to just let it hit the warning path
in that case.

In the previous versions of the patch it would only do a sync request
if the swap interval is zero. In this version I've changed it so that
it always installs it. This is necessary because if an application is
doing swap interval 1 but isn't installing a frame callback it would
end up rendering and calling get_back_bo before we've handled any data
from the compositor and it would use a redundant third buffer.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

The Wayland EGL platform now respects the eglSwapInterval value. The value is
clamped to either 0 or 1 because it is difficult (and probably not useful) to
sync to more than 1 redraw.

The main change is that if the swap interval is 0 then Mesa won't install a
frame callback so that eglSwapBuffers can be executed as often as necessary.
However it now always does a sync request after the swap buffers and blocks
until this is complete in get_back_bo. The compositor is likely to send a
release event while processing the new buffer attach and this makes sure we
will receive that before deciding whether to allocate a new buffer. This is
done even if the application is using swap interval 1 because otherwise if the
application is not installing its own frame callback it may end up calling
get_back_bo before we've handled any data from the compositor and it would end
up using a redundant extra buffer.

If there are no buffers available then instead of returning with an error,
get_back_bo will now poll the compositor by repeatedly sending sync requests
every 10ms. This is a last resort and in theory this shouldn't happen because
there should be no reason for the compositor to hold on to more than three
buffers. That means whenever we attach the fourth buffer we should always get
an immediate release event which should come in with the notification for the
first sync request that we are throttled to.

When the compositor is directly scanning out from the application's buffer it
may end up holding on to three buffers. These are the one that is is currently
scanning out from, one that has been given to DRM as the next buffer to flip
to, and one that has been attached and will be given to DRM as soon as the
previous flip completes. When we attach a fourth buffer to the compositor it
should replace that third buffer so we should get a release event immediately
after that. This patch therefore also changes the number of buffer slots to 4
so that we can accomodate that situation.

If DRM eventually gets a way to cancel a pending page flip then the compositors
can be changed to only need to hold on to two buffers and this value can be
put back to 3.

This also moves the vblank configuration defines from platform_x11.c to the
common egl_dri2.h header so they can be shared by both platforms.
---
 src/egl/drivers/dri2/egl_dri2.h |   9 +-
 src/egl/drivers/dri2/platform_wayland.c | 204 +---
 src/egl/drivers/dri2/platform_x11.c |   6 -
 3 files changed, 193 insertions(+), 26 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 7a2e098..7de5916 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -174,6 +174,7 @@ struct dri2_egl_surface
intdx;
intdy;
struct wl_callback*frame_callback;
+   struct wl_callback*sync_callback;
int   format;
 

Re: Buffer release events (was: Add support for eglSwapInterval)

2013-10-24 Thread Neil Roberts
Hi

Thanks for the interesting insights.

 It seems to me as if the default should always be to just send the
 event.

I think I would vote for leaving the default as it is, ie, queuing the
release events. It's really quite a corner case that delaying events has
any effect on an application because most applications don't need to
know about the release events until they are about to draw something.
Usually they would only draw something in response to some event such as
a frame callback or an input event. In that case the event will have
caused the queue to flush so they will certainly be up-to-date about
what buffers are available at the point when they start drawing. If we
default to not queuing the event then I'd imagine most applications
wouldn't realise they should enable it and would miss out on the
optimisation.

 We can identify buffer release events in weston as coming from one of
 three sources:

 1) wl_surface.commit
 2) surface_flush_damage (the gl renderer releases SHM buffers here)
 3) random releases from the backdend/renderer

 Number 2 above happens during the redraw loop so we can just post the
 event and won't get a double-wakeup.

Yes, I guess even if the compositor posts the event it's not going to
actually send it to the client until the compositor goes idle again
anyway and at that point it will probably have posted a frame complete
callback too so the client would wake up anyway.

 Number 3 is something we can't really control; I'd personally lean
 towards posting the event here, but it's probably at most one
 reference per surface so we can probably get away with queueing.
 (Also, if the backend knows when it would release in the render cycle,
 it may be able to optimize this better than some compositor-general
 solution.) For these two, we can add an argument to
 weston_buffer_reference to set the release event type.

I think case number 3 is the main problem. It's useful for most
fullscreen apps to have the event queued because most of them will be
throttled to the frame callback and don't need the release events
immediately. However this is also the use case most likely to want
eglSwapInterval(0) which would want them immediately so really for this
situation it is an application choice whether they should be queued or
not.

 Number 1 above is the source of the vast majority of out release
 events. [...] The good news is that we can, from a client perspective,
 deal with this one easily. The solution is to send a wl_display.sync
 request immediately after the commit.

Yes, I think it makes sense to always sync the rendering to at least a
wl_display.sync call and the Mesa patch I sent does already do this. You
are right that in practice this effectively solves the problem for most
use cases. So really the only case where this matters is when the
compositor is directly scanning out from the client's buffer. But on the
other hand, that is exactly what a fullscreen game is likely to be doing
and that is the most likely candidate for doing eglSwapInterval(0).

 In any case, dummy sync and frame requests (you may need both) will allow
 you to achieve glSwapInterval(0) without server-side support.

I'm not sure I follow you here. The release event may be queued at any
point after the frame complete is sent. In that case sending a sync
event to flush the queue is only going to help if Mesa sends it
repeatedly, but that amounts to busy-waiting which would be terrible.

I still feel like the new request is the right way to go. The difficulty
with interface versioning feels like a separate wider problem that we
should think about. The crux of the problem is that Mesa probably
shouldn't be using proxy objects that are created outside of Mesa
because in that case it doesn't have control over what interface version
or event queue it is using. Working around the need for the new request
would just side-step the issue but it doesn't seem unlikely that Mesa
would want to use further new surface interfaces requests later too and
the same problem would come back.

Maybe we should have a separate object that you can create per surface
in order to do new requests. This could be created by a new global
object much like the wl_shell interface. In order to make it usable to
both Mesa and the application, we would have to allow creating multiple
resources of the new interface for a single surface. I'm not sure what
to call it though because it would just end up being something like
‘wl_surface_extra_stuff’. Considering that other objects may end up also
needing a similar kind of interface, maybe it would make more sense to
rethink it a bit and make the compositor allow multiple resources for an
object in general. Then you could have something like
wl_compositor.rebind_resource(object, version) which would make a new
resource for any object and it could have its own interface version. I
am just thinking aloud here though, I haven't really thought that
through much.

I will take a look at how much hassle 

[PATCH] protocol: Add a request to disable queuing of buffer release events

2013-10-23 Thread Neil Roberts
Adds a request called wl_surface.set_release which provides a way for
a client to explicitly disable the queuing mechanism for buffer
release events so that it can get them as soon as the buffer is no
longer being used. This is useful for example when doing
eglSwapInterval(0) because in that case the client is not likely to be
installing a frame complete callback so nothing will cause the event
queue to be flushed. However the EGL driver is likely to be using a
finite number of buffers and it may be blocking until a release event
is received. Without this request the driver may end up blocking
forever.

There was some discussion for this patch on whether the request should
be on the wl_buffer interface rather than wl_surface. However it would
be difficult for the compositor to use if it was on the wl_buffer
interface because the implementation for that is in Mesa and
wayland-shm. That means that we would have to have some extra EGL API
to query the release mode in order for the compositor to see it.
---
 protocol/wayland.xml | 51 ---
 1 file changed, 48 insertions(+), 3 deletions(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index a1df007..77d098a 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -173,7 +173,7 @@
 /event
   /interface
 
-  interface name=wl_compositor version=3
+  interface name=wl_compositor version=4
 description summary=the compositor singleton
   A compositor.  This object is a singleton global.  The
   compositor is in charge of combining the contents of multiple
@@ -959,7 +959,7 @@
 /event
   /interface
 
-  interface name=wl_surface version=3
+  interface name=wl_surface version=4
 description summary=an onscreen surface
   A surface is a rectangular area that is displayed on the screen.
   It has a location, size and pixel contents.
@@ -1233,7 +1233,52 @@
   /description
   arg name=scale type=int/
 /request
-   /interface
+
+!-- Version 4 additions --
+
+enum name=release since=4
+  description summary=options for when to send a buffer release event
+These values are used for the wl_surface.set_release request to
+specify when to send buffer release events.
+WL_SURFACE_RELEASE_IMMEDIATE means the release event will be
+sent as soon as the buffer is no longer used by the
+compositor. WL_SURFACE_RELEASE_DELAYED means that the
+compositor may choose to put the release event into a queue
+and only flush it once some other events are ready to send as
+well. Typically a client will want the latter because it
+doesn't usually need to know about the release events until it
+is about to render something so it can avoid being woken up
+unnecessarily. The default value is WL_SURFACE_RELEASE_DELAYED.
+  /description
+  entry name=delayed value=0/
+  entry name=immediate value=1/
+/enum
+
+request name=set_release since=4
+  description summary=sets whether the release event for the buffer 
being attached will be delayed
+By default the compositor will typically delay sending release
+events for a buffer until some other event is also being sent
+in order to avoid waking up the clients more often than
+necessary. Usually the buffer release will end up being sent
+along with the frame complete callback. However some clients
+will want to be able to reuse the buffers earlier than that
+for example if they are not using the frame complete callback.
+This can be used to give a hint to the compositor that the
+client wants the release event for the given buffer as soon as
+possible.
+
+The release mode is double-buffered state, see
+wl_surface.commit.
+
+The default value is WL_SURFACE_RELEASE_DELAYED meaning that
+the release events will be delayed. Setting the value to
+WL_SURFACE_RELEASE_IMMEDIATE only effects the buffer currently
+being attached and subsequent attaches will continue to default
+to WL_SURFACE_RELEASE_DELAYED.
+  /description
+  arg name=value type=uint summary=The new value/
+/request
+  /interface
 
   interface name=wl_seat version=3
 description summary=group of input devices
-- 
1.8.3.1

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


[PATCH weston 1/2] Implement wl_surface.set_release

2013-10-23 Thread Neil Roberts
Implements the wl_surface.set_release request which just causes the
buffer release events to be sent with wl_resource_post_event instead
of wl_resource_queue_event. The release mode is part of the
double-buffered surface state and gets reset to the default as soon as
a commit is performed on the surface.
---
 src/compositor.c | 53 +
 src/compositor.h |  4 
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 7e2a394..0a48f39 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -376,6 +376,7 @@ weston_surface_create(struct weston_compositor *compositor)
surface-buffer_scale = 1;
surface-pending.buffer_transform = surface-buffer_transform;
surface-pending.buffer_scale = surface-buffer_scale;
+   surface-pending.release_mode = WL_SURFACE_RELEASE_DELAYED;
surface-output = NULL;
surface-plane = compositor-primary_plane;
surface-pending.newly_attached = 0;
@@ -1167,6 +1168,7 @@ weston_buffer_from_resource(struct wl_resource *resource)
wl_signal_init(buffer-destroy_signal);
buffer-destroy_listener.notify = weston_buffer_destroy_handler;
buffer-y_inverted = 1;
+   buffer-release_mode = WL_SURFACE_RELEASE_DELAYED;
wl_resource_add_destroy_listener(resource, buffer-destroy_listener);

return buffer;
@@ -1184,17 +1186,30 @@ weston_buffer_reference_handle_destroy(struct 
wl_listener *listener,
ref-buffer = NULL;
 }
 
+static void
+weston_buffer_send_release(struct weston_buffer *buffer)
+{
+   assert(wl_resource_get_client(buffer-resource));
+
+   if (buffer-release_mode == WL_SURFACE_RELEASE_DELAYED) {
+   wl_resource_queue_event(buffer-resource, WL_BUFFER_RELEASE);
+   } else {
+   /* The release mode state should only effect a single
+* attach so we'll reset it back to the default after
+* posting the event */
+   buffer-release_mode = WL_SURFACE_RELEASE_DELAYED;
+   wl_resource_post_event(buffer-resource, WL_BUFFER_RELEASE);
+   }
+}
+
 WL_EXPORT void
 weston_buffer_reference(struct weston_buffer_reference *ref,
struct weston_buffer *buffer)
 {
if (ref-buffer  buffer != ref-buffer) {
ref-buffer-busy_count--;
-   if (ref-buffer-busy_count == 0) {
-   assert(wl_resource_get_client(ref-buffer-resource));
-   wl_resource_queue_event(ref-buffer-resource,
-   WL_BUFFER_RELEASE);
-   }
+   if (ref-buffer-busy_count == 0)
+   weston_buffer_send_release(ref-buffer);
wl_list_remove(ref-destroy_listener.link);
}
 
@@ -1655,6 +1670,17 @@ weston_surface_commit(struct weston_surface *surface)
/* wl_surface.set_buffer_scale */
surface-buffer_scale = surface-pending.buffer_scale;
 
+   /* wl_surface.set_release */
+   if (surface-pending.release_mode == WL_SURFACE_RELEASE_IMMEDIATE) {
+   if (surface-pending.buffer)
+   surface-pending.buffer-release_mode =
+   WL_SURFACE_RELEASE_IMMEDIATE;
+   /* The release mode state should only effect a single
+* attach so we'll reset it back to the default after
+* setting it on the buffer */
+   surface-pending.release_mode = WL_SURFACE_RELEASE_DELAYED;
+   }
+
/* wl_surface.attach */
if (surface-pending.buffer || surface-pending.newly_attached)
weston_surface_attach(surface, surface-pending.buffer);
@@ -1762,6 +1788,16 @@ surface_set_buffer_scale(struct wl_client *client,
surface-pending.buffer_scale = scale;
 }
 
+static void
+surface_set_release(struct wl_client *client,
+   struct wl_resource *resource,
+   uint32_t value)
+{
+   struct weston_surface *surface = wl_resource_get_user_data(resource);
+
+   surface-pending.release_mode = value;
+}
+
 static const struct wl_surface_interface surface_interface = {
surface_destroy,
surface_attach,
@@ -1771,7 +1807,8 @@ static const struct wl_surface_interface 
surface_interface = {
surface_set_input_region,
surface_commit,
surface_set_buffer_transform,
-   surface_set_buffer_scale
+   surface_set_buffer_scale,
+   surface_set_release
 };
 
 static void
@@ -2928,7 +2965,7 @@ compositor_bind(struct wl_client *client,
struct wl_resource *resource;
 
resource = wl_resource_create(client, wl_compositor_interface,
- MIN(version, 3), id);
+ MIN(version, 4), id);
if (resource == NULL) {
wl_client_post_no_memory(client);
return;
@@ 

Re: Buffer release events (was: Add support for eglSwapInterval)

2013-10-23 Thread Neil Roberts
Neil Roberts n...@linux.intel.com writes:

 Currently the only proposed complete solution is just to add a request
 to explicitly disable the queuing mechanism.

I started writing this patch but I've hit a stumbling block while trying
to make use of it in Mesa. Adding the new request requires altering the
version of the wl_compositor and wl_surface interfaces. The problem is
that Mesa can't really use the new request unless the wl_surface object
is using the new version. However, the version of the interface that is
actually in use is determined by the application when it binds the
compositor object. As far as I can tell, there is no way for Mesa to
determine what version the surface proxy object is using. Potentially we
could add some API to query this, but I think even that wouldn't be
ideal because really Mesa wants to know the interface version number
right up front when the display is initialised so that it can determine
the value to report for EGL_MIN_SWAP_INTERVAL.

I'm not sure how to proceed with this. It seems like ideally Mesa should
be able to make requests on the surface using its own binding of the
compositor object so that it's not tied to the version of the interface
that the application is using. I guess that would imply that it would
have some way to get its own resource for the surface. That seems like
quite a packed can of worms though.

Anyone have any ideas?

I'll attach the work in progress patches anyway just for good measure.

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


[PATCH weston 2/2] Add a test for wl_surface.set_release

2013-10-23 Thread Neil Roberts
The test attaches a buffer and then verifies that it doesn't get the
release event until a roundtrip is issued causing the event queue to
flush. It then sets the release mode to immediate and then verifies
that it doesn't need to do a roundtrip to get the release event. The
default mode is then used a second time to verify that setting it to
immediate only lasts for a single commit.
---
 tests/Makefile.am |   7 ++
 tests/delayed-release-test.c  | 150 ++
 tests/weston-test-client-helper.c |   2 +-
 3 files changed, 158 insertions(+), 1 deletion(-)
 create mode 100644 tests/delayed-release-test.c

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5be52c6..c1de1cb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -16,6 +16,7 @@ weston_tests =\
button.weston   \
text.weston \
subsurface.weston   \
+   delayed-release.weston  \
$(xwayland_test)
 
 AM_TESTS_ENVIRONMENT = \
@@ -117,6 +118,12 @@ text_weston_LDADD = $(weston_test_client_libs)
 subsurface_weston_SOURCES = subsurface-test.c $(weston_test_client_src)
 subsurface_weston_LDADD = $(weston_test_client_libs)
 
+delayed_release_weston_SOURCES = \
+   delayed-release-test.c \
+   $(weston_test_client_src)
+delayed_release_weston_LDADD = \
+   $(weston_test_client_libs)
+
 xwayland_weston_SOURCES = xwayland-test.c  $(weston_test_client_src)
 
 xwayland_weston_LDADD = $(weston_test_client_libs) $(XWAYLAND_TEST_LIBS)
diff --git a/tests/delayed-release-test.c b/tests/delayed-release-test.c
new file mode 100644
index 000..9d61bbc
--- /dev/null
+++ b/tests/delayed-release-test.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided as is without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include string.h
+
+#include weston-test-client-helper.h
+#include stdio.h
+#include poll.h
+#include time.h
+
+struct test_data {
+   struct client *client;
+   int release_received;
+};
+
+static void
+buffer_release(void *data, struct wl_buffer *buffer)
+{
+   struct test_data *test_data = data;
+
+   test_data-release_received = 1;
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+   buffer_release
+};
+
+static long int
+timespec_diff(const struct timespec *a, const struct timespec *b)
+{
+   return ((a-tv_sec - b-tv_sec) * 1000 +
+   (a-tv_nsec - b-tv_nsec) / 100);
+}
+
+static void wait_release_event(struct test_data *test_data)
+{
+   struct timespec start_time, now;
+   struct pollfd pollfd;
+
+   test_data-release_received = 0;
+
+   clock_gettime(CLOCK_MONOTONIC, start_time);
+
+   /* Wait for up to ¼ seconds for a release event from the
+* compositor. We don't want to call wl_display_roundtrip
+* because the callback that it installs would cause the event
+* queue to be flushed */
+
+   pollfd.fd = wl_display_get_fd(test_data-client-wl_display);
+   pollfd.events = POLLIN;
+
+   while (!test_data-release_received) {
+   long int diff;
+
+   wl_display_dispatch_pending(test_data-client-wl_display);
+   wl_display_flush(test_data-client-wl_display);
+
+   clock_gettime(CLOCK_MONOTONIC, now);
+
+   diff = timespec_diff(now, start_time);
+
+   if (diff = 250)
+   break;
+
+   pollfd.revents = 0;
+
+   poll(pollfd, 1, 250 - diff);
+
+   if (pollfd.revents)
+   wl_display_dispatch(test_data-client-wl_display);
+   }
+}
+
+static void assert_delayed_release(struct test_data *test_data)
+{
+   wait_release_event(test_data);
+   assert(!test_data-release_received);
+
+   /* Do a roundtrip to 

Re: [PATCH v2] Post buffer release events instead of queue when no frame callback

2013-10-04 Thread Neil Roberts
Neil Roberts n...@linux.intel.com writes:

 I think that would mean you could cause tearing if you are using
 eglSwapInterval(0) because you could write into the released buffer
 while the GPU is actually still rendering the previous frame using the
 buffer in a texture.

 I think this doesn't actually happen at the moment because as far as I
 can tell the gl-renderer immediately queues the buffer release when you
 attach a new one rather than waiting for the swap to actually
 complete.

Thanks to some explanation from Kristian and Pekka I now understand that
this is the expected behaviour. The assumption is that it will be up to
the GL driver or hardware to ensure that GL commands submitted by the
client will be executed after those submitted by the compositor so the
compositor is free to release straight after the eglSwapBuffer call. If the
hardware doesn't just do this naturally then it would still be possible
for a driver's buffer sharing implementation to also transfer fence
objects so that it can ensure these semantics in the driver.

Regards,
- Neil
-
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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


Re: Buffer release events (was: Add support for eglSwapInterval)

2013-10-04 Thread Neil Roberts
Here is a quick summary of the discussion about the release event
handling that has partially happened on this list and partially on IRC.

Currently the release events are put into a queue so that they are only
sent alongside another event sent by the compositor in order to avoid
waking up the client more times than necessary. Usually this will end up
being sent alongside the frame complete callback. The assumption is that
most clients don't care about the buffer release events until they are
about to draw something, which usually only happens when they get the
frame callback so they don't need to wake up early.

This assumption doesn't work if the client isn't installing a frame
callback for example when doing eglSwapInterval(0). In that case the
client may be blocked waiting for a buffer release event but the queue
will never get flushed because no other events are being sent from the
compositor. It could also happen if the compositor is not sending the
release events until some time after the frame callback completes, for
example if it waits until a pending swap buffer completes before
releasing the buffer. Currently this doesn't happen for normal clients
because the GL renderer immediately releases the buffer when a new one
is attached but it may happen for fullscreen clients.

One solution is to always post the release event instead of queuing
whenever the client doesn't have a frame callback currently installed.
This fixes the clients doing eglSwapInterval(0) without breaking all the
normal clients. However this still isn't a perfect solution because it's
still possible that a client would want to do eglSwapInterval(0) and
render as fast as possible but still install its own frame callback,
perhaps just to get information about how fast the frames are being
displayed on the screen.

Currently the only proposed complete solution is just to add a request
to explicitly disable the queuing mechanism. This would have to be a
request on the surface rather than being hidden away as part of wl_drm
because the compositor needs to know about it. Mesa could implicitly
send this request whenever eglSwapInterval is called.

As far as I understand the explicit toggle is the current expected plan
although it does feel a bit like a kludge so we may want to sit on it a
bit in case we can think of something better.

Regards,
- Neil
-
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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


[PATCH weston 1/4] Add a touch binding to activate a surface

2013-10-03 Thread Neil Roberts
Adds a new binding type for touch events via the new function
weston_compositor_add_touch_binding. The binding can only be added for
a touch down with the first finger. The shell now uses this to install
a binding to activate the current surface.
---
 src/bindings.c   | 36 
 src/compositor.c |  2 ++
 src/compositor.h | 14 ++
 src/input.c  |  2 ++
 src/shell.c  | 36 
 5 files changed, 82 insertions(+), 8 deletions(-)

diff --git a/src/bindings.c b/src/bindings.c
index f6ec9ea..03c9238 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -94,6 +94,24 @@ weston_compositor_add_button_binding(struct 
weston_compositor *compositor,
 }
 
 WL_EXPORT struct weston_binding *
+weston_compositor_add_touch_binding(struct weston_compositor *compositor,
+   uint32_t modifier,
+   weston_touch_binding_handler_t handler,
+   void *data)
+{
+   struct weston_binding *binding;
+
+   binding = weston_compositor_add_binding(compositor, 0, 0, 0,
+   modifier, handler, data);
+   if (binding == NULL)
+   return NULL;
+
+   wl_list_insert(compositor-touch_binding_list.prev, binding-link);
+
+   return binding;
+}
+
+WL_EXPORT struct weston_binding *
 weston_compositor_add_axis_binding(struct weston_compositor *compositor,
   uint32_t axis, uint32_t modifier,
   weston_axis_binding_handler_t handler,
@@ -253,6 +271,24 @@ weston_compositor_run_button_binding(struct 
weston_compositor *compositor,
}
 }
 
+WL_EXPORT void
+weston_compositor_run_touch_binding(struct weston_compositor *compositor,
+   struct weston_seat *seat, uint32_t time,
+   int touch_type)
+{
+   struct weston_binding *b;
+
+   if (seat-num_tp != 1 || touch_type != WL_TOUCH_DOWN)
+   return;
+
+   wl_list_for_each(b, compositor-touch_binding_list, link) {
+   if (b-modifier == seat-modifier_state) {
+   weston_touch_binding_handler_t handler = b-handler;
+   handler(seat, time, b-data);
+   }
+   }
+}
+
 WL_EXPORT int
 weston_compositor_run_axis_binding(struct weston_compositor *compositor,
   struct weston_seat *seat,
diff --git a/src/compositor.c b/src/compositor.c
index b8e442a..935015a 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3112,6 +3112,7 @@ weston_compositor_init(struct weston_compositor *ec,
wl_list_init(ec-output_list);
wl_list_init(ec-key_binding_list);
wl_list_init(ec-button_binding_list);
+   wl_list_init(ec-touch_binding_list);
wl_list_init(ec-axis_binding_list);
wl_list_init(ec-debug_binding_list);
 
@@ -3172,6 +3173,7 @@ weston_compositor_shutdown(struct weston_compositor *ec)
 
weston_binding_list_destroy_all(ec-key_binding_list);
weston_binding_list_destroy_all(ec-button_binding_list);
+   weston_binding_list_destroy_all(ec-touch_binding_list);
weston_binding_list_destroy_all(ec-axis_binding_list);
weston_binding_list_destroy_all(ec-debug_binding_list);
 
diff --git a/src/compositor.h b/src/compositor.h
index 9b48287..ad5a786 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -575,6 +575,7 @@ struct weston_compositor {
struct wl_list plane_list;
struct wl_list key_binding_list;
struct wl_list button_binding_list;
+   struct wl_list touch_binding_list;
struct wl_list axis_binding_list;
struct wl_list debug_binding_list;
 
@@ -984,6 +985,15 @@ weston_compositor_add_button_binding(struct 
weston_compositor *compositor,
 weston_button_binding_handler_t binding,
 void *data);
 
+typedef void (*weston_touch_binding_handler_t)(struct weston_seat *seat,
+  uint32_t time,
+  void *data);
+struct weston_binding *
+weston_compositor_add_touch_binding(struct weston_compositor *compositor,
+   enum weston_keyboard_modifier modifier,
+   weston_touch_binding_handler_t binding,
+   void *data);
+
 typedef void (*weston_axis_binding_handler_t)(struct weston_seat *seat,
  uint32_t time, uint32_t axis,
  wl_fixed_t value, void *data);
@@ -1014,6 +1024,10 @@ weston_compositor_run_button_binding(struct 
weston_compositor *compositor,
 struct weston_seat *seat, uint32_t time,
 uint32_t button,

[PATCH weston 2/4] Add a touch move binding

2013-10-03 Thread Neil Roberts
When holding the compositor super key the touch events can now be used
to move a window.
---
 src/shell.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/src/shell.c b/src/shell.c
index 4a0c122..2822a2b 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -2774,6 +2774,26 @@ move_binding(struct weston_seat *seat, uint32_t time, 
uint32_t button, void *dat
 }
 
 static void
+touch_move_binding(struct weston_seat *seat, uint32_t time, void *data)
+{
+   struct weston_surface *focus =
+   (struct weston_surface *) seat-touch-focus;
+   struct weston_surface *surface;
+   struct shell_surface *shsurf;
+
+   surface = weston_surface_get_main_surface(focus);
+   if (surface == NULL)
+   return;
+
+   shsurf = get_shell_surface(surface);
+   if (shsurf == NULL || shsurf-type == SHELL_SURFACE_FULLSCREEN ||
+   shsurf-type == SHELL_SURFACE_MAXIMIZED)
+   return;
+
+   surface_touch_move(shsurf, (struct weston_seat *) seat);
+}
+
+static void
 resize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void 
*data)
 {
struct weston_surface *focus =
@@ -4531,6 +4551,7 @@ shell_add_bindings(struct weston_compositor *ec, struct 
desktop_shell *shell)
  zoom_key_binding, NULL);
weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
 shell);
+   weston_compositor_add_touch_binding(ec, mod, touch_move_binding, shell);
weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
 resize_binding, shell);
 
-- 
1.8.3.1

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


[PATCH weston 4/4] Don't remove the touch grab until the last touch point is removed

2013-10-03 Thread Neil Roberts
Previously if you move a window around and temporarily add a second
finger then it will cancel the grab even though the original finger is
still held on the screen. It seems more robust to avoid cancelling the
grab until all fingers have been removed.
---
 src/shell.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/shell.c b/src/shell.c
index 2822a2b..45bbed3 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1085,7 +1085,9 @@ touch_move_grab_up(struct weston_touch_grab *grab, 
uint32_t time, int touch_id)
struct shell_touch_grab *shell_grab = container_of(grab, 
   struct 
shell_touch_grab,
   grab);
-   shell_touch_grab_end(shell_grab);
+
+   if (grab-touch-seat-num_tp == 0)
+   shell_touch_grab_end(shell_grab);
 }
 
 static void
-- 
1.8.3.1

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


[PATCH weston 3/4] Only update the touch grab position for the first finger

2013-10-03 Thread Neil Roberts
Previously if you add a second finger while moving a window with a
touch grab then the position will keep jumping between the position of
each finger as you move them around. This patch changes it so that it
keeps track of the first touch id that starts the grab and only
updates the grab position when that finger moves.
---
 src/compositor.h | 1 +
 src/input.c  | 7 +--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/compositor.h b/src/compositor.h
index ad5a786..ffa5124 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -343,6 +343,7 @@ struct weston_touch {
 
struct weston_touch_grab *grab;
struct weston_touch_grab default_grab;
+   int grab_touch_id;
wl_fixed_t grab_x, grab_y;
uint32_t grab_serial;
uint32_t grab_time;
diff --git a/src/input.c b/src/input.c
index 3e4f4b1..4e6818c 100644
--- a/src/input.c
+++ b/src/input.c
@@ -1093,8 +1093,10 @@ notify_touch(struct weston_seat *seat, uint32_t time, 
int touch_id,
wl_fixed_t sx, sy;
 
/* Update grab's global coordinates. */
-   touch-grab_x = x;
-   touch-grab_y = y;
+   if (touch_id == touch-grab_touch_id  touch_type != WL_TOUCH_UP) {
+   touch-grab_x = x;
+   touch-grab_y = y;
+   }
 
switch (touch_type) {
case WL_TOUCH_DOWN:
@@ -1124,6 +1126,7 @@ notify_touch(struct weston_seat *seat, uint32_t time, int 
touch_id,
if (seat-num_tp == 1) {
touch-grab_serial =
wl_display_get_serial(ec-wl_display);
+   touch-grab_touch_id = touch_id;
touch-grab_time = time;
touch-grab_x = x;
touch-grab_y = y;
-- 
1.8.3.1

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


Re: [PATCH v2] Post buffer release events instead of queue when no frame callback

2013-10-02 Thread Neil Roberts
I don't think this function would help in cases where the buffer is
released after the frame is drawn but the compositor is not drawing
anything else. Ie, if the events were like this:

1 - client attaches a buffer and waits for the next release
2 - compositor redraws a frame
3 - the redraw completes so the compositor flushes all event queues
4 - the swap completes and the compositor queues a release event

If nothing else causes the compositor to queue a redraw the release
event will just sit in the event queue forever and the client will still
be blocked waiting for it.

I think this doesn't actually happen at the moment because as far as I
can tell the gl-renderer immediately queues the buffer release when you
attach a new one rather than waiting for the swap to actually complete.
I think that would mean you could cause tearing if you are using
eglSwapInterval(0) because you could write into the released buffer
while the GPU is actually still rendering the previous frame using the
buffer in a texture.

I will try an experiment to check this. If that's right then we should
probably add an extra buffer reference in the gl-renderer whenever it
uses a texture to draw and then only release it when the frame is
complete.

Regards,
- Neil

Jason Ekstrand ja...@jlekstrand.net writes:

 All,
 Perhaps a simpler approach would be better.  We could add a function to
 wayland-server called wl_client_post_event_queue which would simply set the
 wants_flush flag on the client connection. This function would be fast
 ,require no I/O, and safe to call multiple times so Weston could simply
 call it on all clients with surfaces visible on the output in question at
 the time when it would call frame events.  Then, when the event loop
 flushes the clients, the release events will get sent out.
 --Jason Ekstrand
-
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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


Re: [PATCH] server: Add API to protect access to an SHM buffer

2013-10-01 Thread Neil Roberts
Hi

José Bollo jo...@nonadev.net writes:

 That is a really interesting point.
 I have two questions about it:
  - Is it normal that the client trucates the buffer? Is your patch
designed to allow normal operations? or to allow forbiden uses?
  - If it is not normal, is there good reasons to continue to 
serve a nasty client?

No, it's not normal that the client would truncate the buffer. The patch
is effectively designed to disallow this and recover gracefully instead
of making the compositor crash. It won't continue to serve the client
but instead it will send it an error. The problem with truncating is
probably only an issue if there are malicious clients. However the case
where the client sends the wrong size to wl_shm.create_pool would be
worth guarding against in any case because it would be quite easy for a
buggy client to get that wrong and the compositor should really be
robust against that.

Regards,
- Neil
-
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH] server: Add API to protect access to an SHM buffer

2013-09-30 Thread Neil Roberts
Linux will let you mmap a region of a file that is larger than the
size of the file. If you then try to read from that region the process
will get a SIGBUS signal. Currently the clients can use this to crash
a compositor because it can create a pool and lie about the size of
the file which will cause the compositor to try and read past the end
of it. The compositor can't simply check the size of the file to
verify that it is big enough because then there is a race condition
where the client may truncate the file after the check is performed.

This patch adds the following two public functions in the server API
which can be used wrap access to an SHM buffer:

void wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer);
void wl_shm_buffer_end_access(struct wl_shm_buffer *buffer);

In-between calls to these functions there will be a signal handler for
SIGBUS. If the signal is caught then the buffer is remapped to an
anonymous private buffer at the same address which allows the
compositor to continue without crashing. The end_access function will
then post an error to the buffer resource.
---

This problem was pointed out earlier by wm4 on #wayland and it seems
like quite a thorny issue. Here is a first attempt at a patch which
does seem to work for Weston but I think there are plenty of issues to
think about. It might not be such a good idea to be messing with
signal handlers if the compositor itself also wants to handle SIGBUS.
There are probably some threading concerns here too.

I think you could do the patch without adding any extra API and just
make it automatically work out which region to remap if you had a list
of wl_shm_pools. The signal handler gets passed the address so it
could check which pool contains it and just remap that one. However
the end_access function seems like a nice place to post an event back
to the client when it fails so I'm not sure which way is better. It's
also probably a good idea to keep the signal handler as simple as
possible.

 src/wayland-server.h |  6 
 src/wayland-shm.c| 87 
 2 files changed, 93 insertions(+)

diff --git a/src/wayland-server.h b/src/wayland-server.h
index c93987d..b371c9e 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -412,6 +412,12 @@ wl_resource_get_destroy_listener(struct wl_resource 
*resource,
 
 struct wl_shm_buffer;
 
+void
+wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer);
+
+void
+wl_shm_buffer_end_access(struct wl_shm_buffer *buffer);
+
 struct wl_shm_buffer *
 wl_shm_buffer_get(struct wl_resource *resource);
 
diff --git a/src/wayland-shm.c b/src/wayland-shm.c
index eff29c3..95b1f33 100644
--- a/src/wayland-shm.c
+++ b/src/wayland-shm.c
@@ -32,15 +32,22 @@
 #include string.h
 #include sys/mman.h
 #include unistd.h
+#include assert.h
+#include signal.h
 
 #include wayland-private.h
 #include wayland-server.h
 
+static struct wl_shm_pool *wl_shm_current_pool;
+static struct sigaction wl_shm_old_sigbus_action;
+
 struct wl_shm_pool {
struct wl_resource *resource;
int refcount;
char *data;
int size;
+   int access_count;
+   int fallback_mapping_used;
 };
 
 struct wl_shm_buffer {
@@ -219,6 +226,7 @@ shm_create_pool(struct wl_client *client, struct 
wl_resource *resource,
 
pool-refcount = 1;
pool-size = size;
+   pool-fallback_mapping_used = 0;
pool-data = mmap(NULL, size,
  PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (pool-data == MAP_FAILED) {
@@ -368,3 +376,82 @@ wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
 {
return buffer-height;
 }
+
+static void
+unset_sigbus_handler(void)
+{
+   sigaction(SIGBUS, wl_shm_old_sigbus_action, NULL);
+}
+
+static void
+sigbus_handler(int signum, siginfo_t *info, void *context)
+{
+   struct wl_shm_pool *pool = wl_shm_current_pool;
+
+   unset_sigbus_handler();
+
+   /* If the offending address is outside the mapped space for
+* the pool then the error is a real problem so we'll reraise
+* the signal */
+   if ((char *) info-si_addr  pool-data ||
+   (char *) info-si_addr = pool-data + pool-size)
+   raise(signum);
+
+   pool-fallback_mapping_used = 1;
+
+   /* This should replace the previous mapping */
+   if (mmap(pool-data, pool-size,
+PROT_READ | PROT_WRITE,
+MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
+0, 0) == (void *) -1)
+   raise(signum);
+}
+
+static void
+set_sigbus_handler(void)
+{
+   struct sigaction new_action = {
+   .sa_sigaction = sigbus_handler,
+   .sa_flags = SA_SIGINFO | SA_NODEFER
+   };
+
+   sigemptyset(new_action.sa_mask);
+
+   sigaction(SIGBUS, new_action, wl_shm_old_sigbus_action);
+}
+
+WL_EXPORT void
+wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
+{
+   struct wl_shm_pool *pool = buffer-pool;
+
+  

[PATCH weston] Add calls to wl_shm_buffer_begin/end_access

2013-09-30 Thread Neil Roberts
This wraps all accesses to an SHM buffer between wl_shm_buffer_begin
and end so that wayland-shm can install a handler for SIGBUS and catch
attempts to pass the compositor a buffer that is too small.

Note, this patch doesn't do anything to fix the pixman renderer.
---
 src/compositor-drm.c  | 3 +++
 src/gl-renderer.c | 6 ++
 src/pixman-renderer.c | 2 ++
 src/rpi-renderer.c| 4 
 src/screenshooter.c   | 4 
 5 files changed, 19 insertions(+)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 2770c85..180c3ee 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -964,9 +964,12 @@ drm_output_set_cursor(struct drm_output *output)
memset(buf, 0, sizeof buf);
stride = 
wl_shm_buffer_get_stride(es-buffer_ref.buffer-shm_buffer);
s = wl_shm_buffer_get_data(es-buffer_ref.buffer-shm_buffer);
+
+   wl_shm_buffer_begin_access(es-buffer_ref.buffer-shm_buffer);
for (i = 0; i  es-geometry.height; i++)
memcpy(buf + i * 64, s + i * stride,
   es-geometry.width * 4);
+   wl_shm_buffer_end_access(es-buffer_ref.buffer-shm_buffer);
 
if (gbm_bo_write(bo, buf, sizeof buf)  0)
weston_log(failed update cursor: %m\n);
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index ae69f22..90e8148 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -875,10 +875,12 @@ gl_renderer_flush_damage(struct weston_surface *surface)
glBindTexture(GL_TEXTURE_2D, gs-textures[0]);
 
if (!gr-has_unpack_subimage) {
+   wl_shm_buffer_begin_access(buffer-shm_buffer);
glTexImage2D(GL_TEXTURE_2D, 0, format,
 gs-pitch, buffer-height, 0,
 format, pixel_type,
 wl_shm_buffer_get_data(buffer-shm_buffer));
+   wl_shm_buffer_end_access(buffer-shm_buffer);
 
goto done;
}
@@ -890,13 +892,16 @@ gl_renderer_flush_damage(struct weston_surface *surface)
if (gs-needs_full_upload) {
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
+   wl_shm_buffer_begin_access(buffer-shm_buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, gs-pitch, buffer-height,
format, pixel_type, data);
+   wl_shm_buffer_end_access(buffer-shm_buffer);
goto done;
}
 
rectangles = pixman_region32_rectangles(gs-texture_damage, n);
+   wl_shm_buffer_begin_access(buffer-shm_buffer);
for (i = 0; i  n; i++) {
pixman_box32_t r;
 
@@ -908,6 +913,7 @@ gl_renderer_flush_damage(struct weston_surface *surface)
r.x2 - r.x1, r.y2 - r.y1,
format, pixel_type, data);
}
+   wl_shm_buffer_end_access(buffer-shm_buffer);
 #endif
 
 done:
diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index 987c539..80d41a8 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -574,6 +574,8 @@ pixman_renderer_attach(struct weston_surface *es, struct 
weston_buffer *buffer)
buffer-width = wl_shm_buffer_get_width(shm_buffer);
buffer-height = wl_shm_buffer_get_height(shm_buffer);
 
+   /* XXX what about wl_shm_buffer_begin_access? */
+
ps-image = pixman_image_create_bits(pixman_format,
buffer-width, buffer-height,
wl_shm_buffer_get_data(shm_buffer),
diff --git a/src/rpi-renderer.c b/src/rpi-renderer.c
index 3ba5fc4..a964899 100644
--- a/src/rpi-renderer.c
+++ b/src/rpi-renderer.c
@@ -277,6 +277,8 @@ rpi_resource_update(struct rpi_resource *resource, struct 
weston_buffer *buffer,
pixman_region32_intersect(write_region,
  write_region, region);
 
+   wl_shm_buffer_begin_access(buffer-shm_buffer);
+
 #ifdef HAVE_RESOURCE_WRITE_DATA_RECT
/* XXX: Can this do a format conversion, so that scanout does not have 
to? */
r = pixman_region32_rectangles(write_region, n);
@@ -311,6 +313,8 @@ rpi_resource_update(struct rpi_resource *resource, struct 
weston_buffer *buffer,
width, r-y2 - r-y1, 0, r-y1, ret);
 #endif
 
+   wl_shm_buffer_end_access(buffer-shm_buffer);
+
pixman_region32_fini(write_region);
 
return ret ? -1 : 0;
diff --git a/src/screenshooter.c b/src/screenshooter.c
index 645114d..0c657bc 100644
--- a/src/screenshooter.c
+++ b/src/screenshooter.c
@@ -144,6 +144,8 @@ screenshooter_frame_notify(struct wl_listener *listener, 
void *data)
d = wl_shm_buffer_get_data(l-buffer-shm_buffer);
s = pixels + stride * (l-buffer-height - 1);
 
+   wl_shm_buffer_begin_access(l-buffer-shm_buffer);
+
switch (compositor-read_format) {
case 

Re: idle tasks starving in toytoolkit

2013-09-27 Thread Neil Roberts
Pekka Paalanen ppaala...@gmail.com writes:

 If not, is there not a possibility to break existing applications by
 blocking too early?

Yes, you're right, the patch is nonsense because it won't work when the
application does wl_display_dispatch_pending because it might end up
with some events still in the queue but the poll won't wake up to
process them.

It would be nice if the recommended main loop was more like this:

 while (TRUE) {
   int need_read;
   int timeout;

   if (wl_display_prepare_read(display)) {
 need_read = 1;
 timeout = -1;
   } else {
 need_read = 0;
 timeout = 0;
   }

   wl_display_flush(dpy);

   poll(fds, nfds, timeout);

   if (need_read)
 wl_display_read_events(dpy);

   wl_display_dispatch_pending(dpy);
 }

That way it doesn't matter if wl_display_dispatch_pending doesn't clear
all of the events.

That is effectively what I think we need do in GTK anyway because in
that case you really ought to avoid dispatching events in the prepare
function before the poll and instead should only be dispatching after.

I guess it's too late to change the semantics of
wl_display_dispatch_pending though so this doesn't help much.

Regards,
- Neil
-
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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


RE: idle tasks starving in toytoolkit

2013-09-26 Thread Neil Roberts
One idea to fix this might be to make dispatch_queue only ever
dispatch the events that were current when the loop is started. That
way if any further events are added while processing the current
events it will give control back to the main loop before processing
them.

Here's a not-heavily-tested patch that would do that.

Regards,
- Neil

--- 8 --- (use git am --scissors to automatically chop here)

Subject: [PATCH] client: Don't dispatch events that are added while dispatching

Previously wl_display_dispatch_queue would keep dispatching events
until the event queue becomes empty. If more events are queued while
dispatching those events the loop can run indefinitely. This patch
changes it so that instead of iterating the list of events directly in
the queue it steals the list of events before dispatching and iterates
the local list instead. That way it will only iterate the events that
were current before the loop started and if further events are added
the application will drop back to the main loop before processing
them.
---
 src/wayland-client.c | 31 ++-
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index a20a71e..ae00ef0 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -918,16 +918,12 @@ decrease_closure_args_refcount(struct wl_closure *closure)
 }
 
 static void
-dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
+dispatch_event(struct wl_display *display, struct wl_closure *closure)
 {
-   struct wl_closure *closure;
struct wl_proxy *proxy;
int opcode;
bool proxy_destroyed;
 
-   closure = container_of(queue-event_list.next,
-  struct wl_closure, link);
-   wl_list_remove(closure-link);
opcode = closure-opcode;
 
/* Verify that the receiving object is still valid by checking if has
@@ -1049,19 +1045,36 @@ wl_display_read_events(struct wl_display *display)
 static int
 dispatch_queue(struct wl_display *display, struct wl_event_queue *queue)
 {
-   int count;
+   struct wl_closure *closure, *tmp;
+   struct wl_list event_list;
+   int count = 0;
 
if (display-last_error)
goto err;
 
-   for (count = 0; !wl_list_empty(queue-event_list); count++) {
-   dispatch_event(display, queue);
+   /* Steal the list of events from the queue so that if more
+* events are added while dispatching the current ones we
+* won't get stuck in this loop indefinitely */
+   wl_list_init(event_list);
+   wl_list_insert_list(event_list, queue-event_list);
+   wl_list_init(queue-event_list);
+
+   wl_list_for_each_safe(closure, tmp, event_list, link) {
+   wl_list_remove(closure-link);
+   count++;
+
+   dispatch_event(display, closure);
+
if (display-last_error)
-   goto err;
+   goto err_queue;
}
 
return count;
 
+err_queue:
+   /* Put any remaining events back in the queue */
+   wl_list_insert_list(queue-event_list, event_list);
+
 err:
errno = display-last_error;
 
-- 
1.8.3.1

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


[PATCH v2] client: Fix handling display-reader_count if poll fails

2013-09-25 Thread Neil Roberts
In wl_display_dispatch_queue, if poll fails then it would previously
return immediately and leak a reference in display-reader_count. Then
if the application ignores the error and tries to read again it will
block forever. This can happen for example if the poll fails with
EINTR which the application might consider to be a recoverable error.
This patch makes it cancel the read so the reader_count will be
decremented when poll fails.
---

Ok, here is a second version of the patch which calls
wl_display_cancel_read as you suggested. Thanks for the review.

 src/wayland-client.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index cad587d..a20a71e 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -1224,8 +1224,10 @@ wl_display_dispatch_queue(struct wl_display *display,
 
pfd[0].fd = display-fd;
pfd[0].events = POLLIN;
-   if (poll(pfd, 1, -1) == -1)
+   if (poll(pfd, 1, -1) == -1) {
+   wl_display_cancel_read(display);
return -1;
+   }
 
pthread_mutex_lock(display-mutex);
 
-- 
1.8.3.1

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


[PATCH 1/3 wayland-fits] core/pointer: Keep track of the focus serial

2013-09-25 Thread Neil Roberts
The focus serial is needed to correctly send a cursor so it is useful
to be able to verify that this is working correctly.
---
 src/test/core/pointer.cpp | 2 ++
 src/test/core/pointer.h   | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/src/test/core/pointer.cpp b/src/test/core/pointer.cpp
index be6f9a9..eb94fd3 100644
--- a/src/test/core/pointer.cpp
+++ b/src/test/core/pointer.cpp
@@ -29,6 +29,7 @@ namespace core {
 Pointer::Pointer(const Seat seat)
: seat_(seat)
, focus_(NULL)
+   , focusSerial_(0)
, x_(-1)
, y_(-1)
, button_(0)
@@ -73,6 +74,7 @@ bool Pointer::hasFocus(wl_surface* surface)
 //  wl_fixed_to_int(y)  std::endl;

pointer-focus_ = wl_surface;
+   pointer-focusSerial_ = serial;
pointer-x_ = wl_fixed_to_int(x);
pointer-y_ = wl_fixed_to_int(y);
 }
diff --git a/src/test/core/pointer.h b/src/test/core/pointer.h
index e891142..3607861 100644
--- a/src/test/core/pointer.h
+++ b/src/test/core/pointer.h
@@ -57,6 +57,7 @@ public:
const uint32_t button() const { return button_; }
const uint32_t buttonState() const { return buttonState_; }
wl_surface* focus() const { return focus_; }
+   const uint32_t focusSerial() const { return focusSerial_; }
 
bool hasFocus(wl_surface*);
 
@@ -76,6 +77,7 @@ private:
 
const Seat seat_;
wl_surface* focus_;
+   uint32_tfocusSerial_;
int32_t x_;
int32_t y_;
uint32_tbutton_;
-- 
1.8.3.1

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


[PATCH 2/3 wayland-fits] core: Add a wrapper for the keyboard

2013-09-25 Thread Neil Roberts
This adds a wrapper for a wl_keyboard in a similar way to the pointer
wrapper. It keeps track of the keys that are pressed so that they can
be quickly verified. wayland-fits now depends on libxkbcommon so that
the keyboard wrapper can pass the keymap to it and get the modifier
indices.
---
 configure.ac   |   2 +
 src/test/Makefile.am   |   2 +
 src/test/core/Makefile.am  |   3 +
 src/test/core/display.cpp  |  13 +++
 src/test/core/display.h|   3 +
 src/test/core/keyboard.cpp | 213 +
 src/test/core/keyboard.h   | 107 +++
 src/test/efl/Makefile.am   |   2 +
 src/test/gtk+/Makefile.am  |   2 +
 9 files changed, 347 insertions(+)
 create mode 100644 src/test/core/keyboard.cpp
 create mode 100644 src/test/core/keyboard.h

diff --git a/configure.ac b/configure.ac
index de84adf..5ad59ca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -61,6 +61,8 @@ PKG_CHECK_MODULES([WAYLAND],
 )
 PKG_CHECK_MODULES(WAYLAND_SERVER, [wayland-server = wayland_req_version])
 
+PKG_CHECK_MODULES([XKBCOMMON], xkbcommon)
+
 have_weston=no
 want_weston_extensions=auto
 AC_ARG_ENABLE([weston-extensions],
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index ba5e5ce..e50c0fc 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -14,6 +14,7 @@ wfits_SOURCES =   \
 wfits_LDADD =  \
core/libwfits-core.la   \
$(CHECK_LIBS)   \
+   $(XKBCOMMON_LIBS)   \
$(WAYLAND_LIBS) \
$(BOOST_LIBS)
 
@@ -23,6 +24,7 @@ wfits_LDFLAGS =   \
 wfits_CPPFLAGS =   \
-I$(top_srcdir)/src \
$(CHECK_CFLAGS) \
+   $(XKBCOMMON_CFLAGS) \
$(WAYLAND_CFLAGS)   \
$(BOOST_CPPFLAGS)
 
diff --git a/src/test/core/Makefile.am b/src/test/core/Makefile.am
index bff1c5a..3a93a67 100644
--- a/src/test/core/Makefile.am
+++ b/src/test/core/Makefile.am
@@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libwfits-core.la
 libwfits_core_la_SOURCES = \
display.cpp \
compositor.cpp  \
+   keyboard.cpp\
shell.cpp   \
seat.cpp\
pointer.cpp \
@@ -23,11 +24,13 @@ libwfits_core_la_SOURCES =  \
 
 libwfits_core_la_LIBADD =  \
$(WAYLAND_LIBS) \
+   $(XKBCOMMON_LIBS)   \
$(CHECK_LIBS)
 
 libwfits_core_la_CPPFLAGS =\
-I$(top_srcdir)/src \
$(WAYLAND_CFLAGS)   \
+   $(XKBCOMMON_CFLAGS) \
$(CHECK_CFLAGS)
 
 AM_CXXFLAGS =  \
diff --git a/src/test/core/display.cpp b/src/test/core/display.cpp
index 1c29dbf..5c9a459 100644
--- a/src/test/core/display.cpp
+++ b/src/test/core/display.cpp
@@ -30,6 +30,7 @@ Display::Display()
: wl_display_(wl_display_connect(0))
, wl_registry_(NULL)
, globals_()
+   , xkbContext_(NULL)
 {
ASSERT(wl_display_ != NULL);
 
@@ -49,6 +50,8 @@ Display::Display()
 
 /*virtual*/ Display::~Display()
 {
+   if (xkbContext_)
+   xkb_context_unref(xkbContext_);
wl_registry_destroy(wl_registry_);
wl_display_disconnect(*this);
 }
@@ -69,6 +72,16 @@ void Display::yield(const unsigned time) const
usleep(time);
 }
 
+struct xkb_context *Display::xkbContext() const
+{
+   if (xkbContext_ == NULL) {
+   xkbContext_ = xkb_context_new((enum xkb_context_flags) 0);
+   ASSERT(xkbContext_ != NULL);
+   }
+
+   return xkbContext_;
+}
+
 /*static*/ void Display::global(
void *data, struct wl_registry *wl_registry, uint32_t id,
const char* interface, uint32_t version)
diff --git a/src/test/core/display.h b/src/test/core/display.h
index 0a4c10a..bf09057 100644
--- a/src/test/core/display.h
+++ b/src/test/core/display.h
@@ -25,6 +25,7 @@
 
 #include map
 #include wayland-client.h
+#include xkbcommon/xkbcommon.h
 #include test/tools.h
 
 namespace wfits {
@@ -63,6 +64,7 @@ public:
void roundtrip() const;
void dispatch() const;
void yield(const unsigned = 0.001 * 1e6) const;
+   struct xkb_context *xkbContext() const;
 
operator wl_display*() const { return wl_display_; }
operator wl_registry*() const { return wl_registry_; }
@@ -74,6 +76,7 @@ private:
wl_display  *wl_display_;
wl_registry *wl_registry_;
Globals globals_;
+   mutable struct xkb_context *xkbContext_;
 };
 
 } // namespace core
diff --git a/src/test/core/keyboard.cpp b/src/test/core/keyboard.cpp
new file mode 100644
index 000..aa49413
--- /dev/null
+++ b/src/test/core/keyboard.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright © 2013 Intel 

[PATCH 3/3 wayland-fits] core: Add a test for multiple pointer and keyboard resources

2013-09-25 Thread Neil Roberts
This adds a test which creates multiple pointer and keyboard resources
for the same client and verifies that they all receive events. It also
tests various combiniations of pointer and keyboard focus and ensures
that for example a keyboard created while the surface already has
focus will correctly get updated about the state.
---
 src/test/core/Makefile.am |   1 +
 src/test/core/test_multi_resource.cpp | 259 ++
 2 files changed, 260 insertions(+)
 create mode 100644 src/test/core/test_multi_resource.cpp

diff --git a/src/test/core/Makefile.am b/src/test/core/Makefile.am
index 3a93a67..ec7901b 100644
--- a/src/test/core/Makefile.am
+++ b/src/test/core/Makefile.am
@@ -19,6 +19,7 @@ libwfits_core_la_SOURCES =\
test_bind_interface.cpp \
test_cursor.cpp \
test_data.cpp   \
+   test_multi_resource.cpp \
test_surface.cpp\
test_dnd.cpp
 
diff --git a/src/test/core/test_multi_resource.cpp 
b/src/test/core/test_multi_resource.cpp
new file mode 100644
index 000..d3fb003
--- /dev/null
+++ b/src/test/core/test_multi_resource.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided as is without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include harness.h
+#include compositor.h
+#include pointer.h
+#include keyboard.h
+#include seat.h
+#include surface.h
+#include shell.h
+#include shell_surface.h
+#include shm.h
+
+namespace wfits {
+namespace test {
+namespace core {
+namespace input {
+
+class DummyClient
+{
+public:
+   DummyClient()
+   : display_()
+   , compositor_(display_)
+   , shell_(display_)
+   , seat_(display_)
+   , surface_(compositor_)
+   , shellSurface_(shell_, surface_)
+   , shm_(display_)
+   , buffer_(shm_, 128, 128)
+   {
+   wl_surface_attach(surface_, buffer_, 0, 0);
+   wl_surface_damage(surface_, 0, 0,
+ buffer_.width(), buffer_.height());
+   surface_.commit();
+   }
+
+private:
+   Display display_;
+   Compositor compositor_;
+   Shell shell_;
+   Seat seat_;
+   Surface surface_;
+   ShellSurface shellSurface_;
+   SharedMemory shm_;
+   SharedMemoryBuffer buffer_;
+};
+
+class MultiResourceTest : public Harness
+{
+public:
+   MultiResourceTest()
+   : Harness::Harness()
+   , compositor_(display())
+   , shell_(display())
+   , seat_(display())
+   , surface_(compositor_)
+   , shellSurface_(shell_, surface_)
+   , shm_(display())
+   , buffer_(shm_, 128, 128)
+   {
+   }
+
+   void setup();
+   void testPointer();
+   void testKeyboard();
+
+   void movePointer(const int32_t x, const int32_t y)
+   {
+   Geometry geometry(getSurfaceGeometry(surface_));
+   setGlobalPointerPosition(geometry.x + x, geometry.y + y);
+   }
+
+   void checkPointer(Pointer *pointer, const int32_t x, const int32_t y)
+   {
+   YIELD_UNTIL(pointer-x() == x and pointer-y() == y);
+   }
+
+private:
+   Compositor compositor_;
+   Shell shell_;
+   Seat seat_;
+   Surface surface_;
+   ShellSurface shellSurface_;
+   SharedMemory shm_;
+   SharedMemoryBuffer buffer_;
+};
+
+void MultiResourceTest::setup()
+{
+   wl_surface_attach(surface_, buffer_, 0, 0);
+   wl_surface_damage(surface_, 0, 0, buffer_.width(), buffer_.height());
+   surface_.commit();
+
+   queueStep(boost::bind(MultiResourceTest::testPointer, 
boost::ref(*this)));
+   queueStep(boost::bind(MultiResourceTest::testKeyboard, 
boost::ref(*this)));
+}
+

[PATCH 1/2] Fix a typo in a log message

2013-09-24 Thread Neil Roberts
Without the space it would end up printing ‘downbut’.
---
 src/input.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/input.c b/src/input.c
index 1313b52..0c3e480 100644
--- a/src/input.c
+++ b/src/input.c
@@ -1115,7 +1115,7 @@ notify_touch(struct weston_seat *seat, uint32_t time, int 
touch_id,
/* Unexpected condition: We have non-initial touch but
 * there is no focused surface.
 */
-   weston_log(touch event received with %d points down
+   weston_log(touch event received with %d points down 
   but no surface focused\n, seat-num_tp);
return;
}
-- 
1.8.3.1

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


Re: [PATCH weston 1/2 v2] input: Emit events on all resources for a client

2013-09-23 Thread Neil Roberts
Kristian Høgsberg hoegsb...@gmail.com writes:

 Instead of this manual marker, you can add comments like the above
 below the three dashes that git inserts between the commit message and
 the actual patch. git am will take the text up until the --- marker as
 the commit message and discard everything from there on until the
 actual patch.

This isn't quite a manual marker. If you apply the patch using ‘git am
--scissors’ it will automatically cut out the message at the top. You
can also do ‘git config --global mailinfo.scissors yes’ to set that
automatically. I'm not sure why that's not the default. I think the
scissors are slightly nicer than putting a comment next to the diffstat
because you can put the message at the beginning of the email. However
I'm happy to follow whatever convention the list uses.

It looks like the ‘From’ tag got messed up when the patch was applied so
now it has given me credit for Rob's patch and I have now co-authored it
with myself. Git is hard!

Regards,
- Neil
-
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH weston 1/2 v2] input: Emit events on all resources for a client

2013-09-19 Thread Neil Roberts
Here is a second version of Robert's patch with the following changes:

I think the problem where clients would not immediately become active
when starting was caused by it calling weston_*_set_focus instead of
sending the enter event for the first keyboard or pointer resource.
The set_focus functions don't do anything if the surface already has
focus so the client was never getting the enter event. I've changed it
so that it uses the same code path regardless of whether it is the
first or a subsequent resource and now it just always explicitly sends
the enter event.

I've removed the focus listeners. We don't need them anymore because
the resource will automatically remove itself from the list when it is
destroyed and that will have the same effect as the old destroy
callback which would just unset the focus resource pointer. This
should remove the need for Robert's patch which changes the destroy
listeners to listen to the client resource.

When setting the pointer focus it will now send the keyboard modifiers
regardless of whether the focused client has a pointer resource. This
is not how it works in master and Rob's patch also changed it to do
this but I'm not sure if that was intentional. This is important
because otherwise if you get the pointer later than getting the
keyboard then the modifiers might not be up-to-date.

I've changed the move_resource function to just use wl_list_insert
which should have the same effect but will be faster because it
doesn't need to iterate the list.

In a couple of places the patch made it so that it would increment the
serial even if there are no resources for the pointer or keyboard.
I've changed these so that it checks if the resource list is empty to
make it retain the old behaviour. In particular this was happening in
binding_key and default_grab_key.

When getting the keyboard, it now sends the modifiers to the client
when it either has the pointer focus or the keyboard focus, instead of
only if it has the keyboard focus.

I've split up long lines and moved some bits of code into common
functions, for example to emit the modifiers event.

I've brought back the find_resource_for_surface functions so that the
set focus functions can avoid incrementing the serial if there is no
pointer or keyboard resource for the client of that surface.

I removed the duplicated checks for seat-touch_focus != surface in
wl_touch_set_focus because this is ensured right at the start of the
function so it is redundant to check it again.

I fixed the spelling of ‘focussed‘.

Regards,
- Neil

-- 8 --

From: Rob Bradford r...@linux.intel.com

The Wayland protocol permits a client to request the pointer, keyboard
and touch multiple times from the seat global. This is very useful in a
component like Clutter-GTK where we are combining two libraries that use
Wayland together.

This change migrates the weston input handling code to emit the
events for all the resources for the client by using the newly added
wl_resource_for_each macro to iterate over the resources that are
associated with the focused surface's client.

We maintain a list of focused resources on the pointer and keyboard
which is updated when the focus changes. However since we can have
resources created after the focus has already been set we must add the
resources to the right list and also update any state.

Additionally when setting the pointer focus it will now send the
keyboard modifiers regardless of whether the focused client has a
pointer resource. This is important because otherwise if the client
gets the pointer later than you getting the keyboard then the
modifiers might not be up-to-date.

Co-author: Neil Roberts n...@linux.intel.com
---
 src/bindings.c|  21 +--
 src/compositor.h  |   9 +-
 src/data-device.c |  16 ++-
 src/input.c   | 399 +++---
 src/shell.c   |  34 +++--
 5 files changed, 309 insertions(+), 170 deletions(-)

diff --git a/src/bindings.c b/src/bindings.c
index a871c26..f6ec9ea 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -160,7 +160,6 @@ binding_key(struct weston_keyboard_grab *grab,
struct weston_keyboard *keyboard = grab-keyboard;
struct wl_display *display = keyboard-seat-compositor-wl_display;
 
-   resource = grab-keyboard-focus_resource;
if (key == b-key) {
if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
weston_keyboard_end_grab(grab-keyboard);
@@ -168,9 +167,15 @@ binding_key(struct weston_keyboard_grab *grab,
keyboard-grab = keyboard-input_method_grab;
free(b);
}
-   } else if (resource) {
+   } else if (!wl_list_empty(keyboard-focus_resource_list)) {
serial = wl_display_next_serial(display);
-   wl_keyboard_send_key(resource, serial, time, key, state);
+   wl_resource_for_each(resource, keyboard-focus_resource_list

[PATCH 2/2] Add a hacky client to test multiple pointer/keyboard resources

2013-09-19 Thread Neil Roberts
** I don't expect this patch to be landed but it might be useful if
   anyone wants to test the multi-resource stuff **

This adds a hacked version of simple-shm which can create multiple
pointer and keyboard resources. The resources are created with the
command line options -p and -k. Both take an integer argument which
specifies the time in seconds after the program is started when the
resource should be created. It can also take a second time with a
colon separator to specify when the resource should be released.

For example:

 weston-multi-resource -p5 -p7 -k9 -p12:14

That would create a pointer after 5 seconds, a second pointer 2
seconds later, a keyboard 2 seconds after that, a third pointer after
a further 3 seconds and finally after 2 more seconds it would release
that final pointer resource.

This can be used along with WAYLAND_DEBUG to check that it gets the
right events for example if the pointer is created while the client's
surface already has focus and so on.
---
 clients/Makefile.am  |   9 +-
 clients/multi-resource.c | 596 +++
 2 files changed, 604 insertions(+), 1 deletion(-)
 create mode 100644 clients/multi-resource.c

diff --git a/clients/Makefile.am b/clients/Makefile.am
index 24c6489..d4bee2a 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -32,7 +32,8 @@ AM_CPPFLAGS = \
 if BUILD_SIMPLE_CLIENTS
 simple_clients_programs =  \
weston-simple-shm   \
-   weston-simple-touch
+   weston-simple-touch \
+   weston-multi-resource
 
 weston_simple_shm_SOURCES = simple-shm.c   \
../shared/os-compatibility.c\
@@ -45,6 +46,12 @@ weston_simple_touch_SOURCES = simple-touch.c \
../shared/os-compatibility.h
 weston_simple_touch_CPPFLAGS = $(SIMPLE_CLIENT_CFLAGS)
 weston_simple_touch_LDADD = $(SIMPLE_CLIENT_LIBS)
+
+weston_multi_resource_SOURCES = multi-resource.c   \
+   ../shared/os-compatibility.c\
+   ../shared/os-compatibility.h
+weston_multi_resource_CPPFLAGS = $(SIMPLE_CLIENT_CFLAGS)
+weston_multi_resource_LDADD = $(SIMPLE_CLIENT_LIBS)
 endif
 
 if BUILD_SIMPLE_EGL_CLIENTS
diff --git a/clients/multi-resource.c b/clients/multi-resource.c
new file mode 100644
index 000..1c2e5c9
--- /dev/null
+++ b/clients/multi-resource.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright © 2011 Benjamin Franzke
+ * Copyright © 2010, 2013 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided as
+ * is without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include config.h
+
+#include stdio.h
+#include stdlib.h
+#include errno.h
+#include string.h
+#include stdbool.h
+#include assert.h
+#include unistd.h
+#include sys/mman.h
+#include signal.h
+#include time.h
+#include sys/poll.h
+#include float.h
+
+#include wayland-client.h
+#include ../shared/os-compatibility.h
+
+struct device {
+   enum { KEYBOARD, POINTER } type;
+
+   int start_time;
+   int end_time;
+   struct wl_list link;
+
+   union {
+   struct wl_keyboard *keyboard;
+   struct wl_pointer *pointer;
+   } p;
+};
+
+struct display {
+   struct wl_display *display;
+   struct wl_registry *registry;
+   struct wl_compositor *compositor;
+   struct wl_shell *shell;
+   struct wl_seat *seat;
+   struct wl_shm *shm;
+   uint32_t formats;
+   struct wl_list devices;
+};
+
+struct window {
+   struct display *display;
+   int width, height;
+   struct wl_surface *surface;
+   struct wl_shell_surface *shell_surface;
+};
+
+static void
+buffer_release(void *data, struct wl_buffer *buffer)
+{
+   wl_buffer_destroy(buffer);
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+   buffer_release
+};
+
+static int
+attach_buffer(struct window *window, int width, int height)
+{

  1   2   >