[PATCH 0/2] Support for high DPI outputs via scaling

2013-05-08 Thread alexl
From: Alexander Larsson 

I'm working on trying to make high DPI (i.e. retina-class) outputs
work well on Linux. I've written a proposal here:

https://docs.google.com/document/d/1rvtiZb_Sm9C9718IoYQgnpzkirdl-wJZBBu_qLgaYyY/edit?usp=sharing

This adds the initial protocol support needed for this. I will then
then start adding support for this to weston.

Alexander Larsson (2):
  protocol: Allow versioned message arguments
  protocol: Add buffer_scale to wl_surface and wl_output

 protocol/wayland.xml  | 35 --
 src/connection.c  | 81 +++
 src/scanner.c | 38 
 src/wayland-private.h |  2 ++
 4 files changed, 141 insertions(+), 15 deletions(-)

-- 
1.8.1.4

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


[PATCH 1/2] protocol: Allow versioned message arguments

2013-05-08 Thread alexl
From: Alexander Larsson 

This allows an event to be extended in a backwards compatible way (on
the client side) by marking an argument with a since attribute.
Any arguments with a since value later than then value of the message
itself will be marked optional and the demarshaller will supply
default values for these arguments.

Versioned arguments must be added at the end of the message in strictly
increasing version order. We don't allow optional arguments of fd type
as we can't make useful "default" fds.

Optional arguments have a default value of 0 or 0 length, but messages
of int/unsigned/fixed can have a different default specified.

The changes in the generated client code are ABI compatible, in two senses:
 * For old servers not passing the optional arguments a new client
   will get the default value for the argument
 * A client compiled against the old client headers will not see the
   new arguments, but c calling conventions makes the call work as
   before.

However, this is not strictly API compatible. Building a client that uses
the old version of the interface against a new client header will get a
warning about the callback types mismatching (due to the new arguments).
We could possibly solve this by adding some #ifdefs that you then need
to define to get the new arguments.
---
 src/connection.c  | 81 +++
 src/scanner.c | 38 
 src/wayland-private.h |  2 ++
 3 files changed, 109 insertions(+), 12 deletions(-)

diff --git a/src/connection.c b/src/connection.c
index dca134b..f74f261 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -399,9 +399,33 @@ wl_connection_put_fd(struct wl_connection *connection, 
int32_t fd)
return 0;
 }
 
+static int
+char_is_digit (char c)
+{
+  return c >= '0' && c <= '9';
+}
+
+static int
+digit_value (char c)
+{
+  return c - '0';
+}
+
 const char *
 get_next_argument(const char *signature, struct argument_details *details)
 {
+   if (*signature == '#') {
+   details->optional = 1;
+   details->default_value = 0;
+   signature++;
+
+   while (char_is_digit (*signature)) {
+   details->default_value = 10*details->default_value + 
digit_value (*signature);
+   signature++;
+   }
+   } else
+   details->optional = 0;
+
if (*signature == '?') {
details->nullable = 1;
signature++;
@@ -417,8 +441,15 @@ arg_count_for_signature(const char *signature)
 {
int count = 0;
while (*signature) {
-   if (*signature != '?')
-   count++;
+   if (*signature == '#') {
+   signature++;
+   while (char_is_digit (*signature))
+   signature++;
+   }
+   if (*signature == '?') {
+   signature++;
+   }
+   count++;
signature++;
}
return count;
@@ -572,10 +603,10 @@ wl_connection_demarshal(struct wl_connection *connection,
struct wl_map *objects,
const struct wl_message *message)
 {
-   uint32_t *p, *next, *end, length, id;
+   uint32_t *p, *next, *end, length, id, first;
int fd;
char *s;
-   unsigned int i, count, num_arrays;
+   unsigned int i, count, num_arrays, is_optional;;
const char *signature;
struct argument_details arg;
struct wl_closure *closure;
@@ -609,7 +640,7 @@ wl_connection_demarshal(struct wl_connection *connection,
for (i = 0; i < count; i++) {
signature = get_next_argument(signature, &arg);
 
-   if (arg.type != 'h' && p + 1 > end) {
+   if (!arg.optional && arg.type != 'h' && p + 1 > end) {
printf("message too short, "
   "object (%d), message %s(%s)\n",
   *p, message->name, message->signature);
@@ -617,24 +648,41 @@ wl_connection_demarshal(struct wl_connection *connection,
goto err;
}
 
+   is_optional = p + 1 > end && arg.type != 'h';
+   if (is_optional)
+   first = arg.default_value;
+   else if (arg.type != 'h')
+   first = *p++;
+   else
+   first = 0;
+
switch (arg.type) {
case 'u':
-   closure->args[i].u = *p++;
+   closure->args[i].u = first;
break;
case 'i':
-   closure->args[i].i = *p++;
+   closure->args[i].i = first;
break;
case 'f':
-   closure->args[i].f = *p++;
+   closure->a

[PATCH 2/2] protocol: Add buffer_scale to wl_surface and wl_output

2013-05-08 Thread alexl
From: Alexander Larsson 

This adds wl_surface_set_buffer_scale() to set the buffer
scale of a surface.

It is similar to set_buffer_transform in that it says that the buffer
is stored in a way that has been transformed (in this case
scaled). This means that if an output is naturally scaled (i.e. has
sub-pixel precision) we can directly use the pre-scaled buffer with
additional data, rather than having to scale it.

It also adds a scale member to the wl_output geometry event
that specifies the natural scaling of an output.

This is meant to be used for outputs with a very high DPI to tell
the client that this particular output has subpixel precision.
The coordinates for e.g. input and the positioning in the compositor
wrt other outputs (which may be non-subpixel-precision) are in
"logical" pixel coordinates, and need to be multiplied by the
scaling factor to convert to the physical pixels of the output.

This setup means global properties like mouse acceleration/speed, pointer
size, monitor geometry, etc can be specified in a "mostly similar" resolution
even on a multimonitor setup where some monitors are low dpi and some are
e.g. retina-class outputs.

It also adds a scale_priority to the geometry event. This can
be used by clients to know what scale factor to use for buffers
on mirrored displays. If a window surface is equally much on two
outputs, such as the case of a mirrored output, the app doesn't
know what scale factor to pick to match the native output. In
this case it can pick the one with the highest priority, giving
the compositor (and thus the user) the possibility of selecting
which output should look "best".
---
 protocol/wayland.xml | 35 ---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 3bce022..941952a 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -876,7 +876,7 @@
 
   
 
-  
+  
 
   A surface is a rectangular area that is displayed on the screen.
   It has a location, size and pixel contents.
@@ -1110,7 +1110,32 @@
   
   
 
-   
+
+
+
+
+  
+   This request sets an optional scaling factor on how the compositor
+   interprets the contents of the buffer attached to the surface. A
+   value larger than 1, like e.g. 2 means that the buffer is 2 times the
+   size of the surface.
+
+   Buffer scale is double-buffered state, see wl_surface.commit.
+
+   A newly created surface has its buffer scale set to 1.
+
+   The purpose of this request is to allow clients to supply higher 
resolution
+   buffer data for use on high-resolution outputs where the output itself
+   has a scaling factor set. For instance, a laptop with a high DPI
+   internal screen and an low DPI external screen would have two outputs
+   with different scaling, and a wl_surface rendered on the scaled output
+   would normally be scaled up. To avoid this upscaling the app can supply
+   a pre-scaled version with more detail by using set_buffer_scale.
+  
+  
+
+
+  
 
   
 
@@ -1467,7 +1492,7 @@
 
   
 
-  
+  
 
   An output describes part of the compositor geometry.  The
   compositor works in the 'compositor coordinate system' and an
@@ -1537,6 +1562,10 @@
   summary="textual description of the model"/>
   
+  
+  
 
 
 
-- 
1.8.1.4

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


[PATCH] protocol: Add buffer_scale to wl_surface and wl_output

2013-05-14 Thread alexl
From: Alexander Larsson 

This adds wl_surface_set_buffer_scale() to set the buffer scale of a
surface.

It is similar to set_buffer_transform that the buffer is stored in a
way that has been transformed (in this case scaled). This means that
if an output is scaled we can directly use the pre-scaled buffer with
additional data, rather than having to scale it.

It also adds a geometry2 event with a scale member to wl_output that
specifies the scaling of an output.

This is meant to be used for outputs with a very high DPI to tell the
client that this particular output has subpixel precision. Coordinates
in other parts of the protocol, like input events, relative window
positioning and output positioning are still in the compositor space
rather than the scaled space. However, input has subpixel precision
so you can still get input at full resolution.

This setup means global properties like mouse acceleration/speed,
pointer size, monitor geometry, etc can be specified in a "mostly
similar" resolution even on a multimonitor setup where some monitors
are low dpi and some are e.g. retina-class outputs.
---
 protocol/wayland.xml | 41 +++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 3bce022..e5744c7 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -876,7 +876,7 @@
 
   
 
-  
+  
 
   A surface is a rectangular area that is displayed on the screen.
   It has a location, size and pixel contents.
@@ -1110,6 +1110,30 @@
   
   
 
+
+
+
+
+  
+   This request sets an optional scaling factor on how the compositor
+   interprets the contents of the buffer attached to the surface. A
+   value larger than 1, like e.g. 2 means that the buffer is 2 times the
+   size of the surface.
+
+   Buffer scale is double-buffered state, see wl_surface.commit.
+
+   A newly created surface has its buffer scale set to 1.
+
+   The purpose of this request is to allow clients to supply higher 
resolution
+   buffer data for use on high-resolution outputs where the output itself
+   has a scaling factor set. For instance, a laptop with a high DPI
+   internal screen and an low DPI external screen would have two outputs
+   with different scaling, and a wl_surface rendered on the scaled output
+   would normally be scaled up. To avoid this upscaling the app can supply
+   a pre-scaled version with more detail by using set_buffer_scale.
+  
+  
+

 
   
@@ -1467,7 +1491,7 @@
 
   
 
-  
+  
 
   An output describes part of the compositor geometry.  The
   compositor works in the 'compositor coordinate system' and an
@@ -1520,6 +1544,8 @@
The geometry event describes geometric properties of the output.
The event is sent when binding to the output object and whenever
any of the properties change.
+
+Some additional properties were later added, see wl_output.geometry2.
   
   
@@ -1565,6 +1591,17 @@
   
   
 
+
+
+  
+   This event contains additional geometric information
+that are not in the geometry event. Whenever it is sent
+it will be followed by a geometry event. This way you can
+tell by the time the geometry event is recieved whether a
+geometry2 event will be seen or not.
+  
+  
+
   
 
   
-- 
1.8.1.4

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


[PATCH 0/2] Updated scaling patch

2013-05-16 Thread alexl
From: Alexander Larsson 

Here is a new version of the scaling work, based on the feedback
from Pekka. Changes in this version are:

* Better documentation in general, and about coordinate spaces
  in particular.
* Scaling is an integer
* Updated wl_compository version as needed
* Added a flag to wl_output.mode to mark resolutions that
  are scaled
* Support grouping of property changes to wl_output using a
  wl_output.done event

Alexander Larsson (2):
  protocol: Allow output changes to be treated atomically
  protocol: Support scaled outputs and surfaces

 protocol/wayland.xml | 119 ---
 1 file changed, 104 insertions(+), 15 deletions(-)

-- 
1.8.1.4

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


[PATCH 1/2] protocol: Allow output changes to be treated atomically

2013-05-16 Thread alexl
From: Alexander Larsson 

This add a wl_output.done event which is send after every group
of events caused by some property change. This allows clients to treat
changes touching multiple events in an atomic fashion.
---
 protocol/wayland.xml | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 3bce022..d3ae149 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -1467,7 +1467,7 @@
 
   
 
-  
+  
 
   An output describes part of the compositor geometry.  The
   compositor works in the 'compositor coordinate system' and an
@@ -1565,6 +1565,16 @@
   
   
 
+
+
+  
+This event is sent after all other properties has been
+sent after binding to the output object and after any
+other property changes done after that. This allows
+changes to the output properties to be seen as
+atomic, even if they happen via multiple events.
+  
+
   
 
   
-- 
1.8.1.4

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


[PATCH 2/2] protocol: Support scaled outputs and surfaces

2013-05-16 Thread alexl
From: Alexander Larsson 

This adds the wl_surface.set_buffer_scale request, and a wl_output.scale
event. These together lets us support automatic upscaling of "old"
clients on very high resolution monitors, while allowing "new" clients
to take advantage of this to render at the higher resolution when the
surface is displayed on the scaled output.

It is similar to set_buffer_transform in that the buffer is stored in
a transformed pixels (in this case scaled). This means that if an output
is scaled we can directly use the pre-scaled buffer with additional data,
rather than having to scale it.

Additionally this adds a "scaled" flag to the wl_output.mode flags
so that clients know which resolutions are native and which are scaled.

Also, in places where the documentation was previously not clear as to
what coordinate system was used this was fleshed out.

It also adds a scaling_factor event to wl_output that specifies the
scaling of an output.

This is meant to be used for outputs with a very high DPI to tell the
client that this particular output has subpixel precision. Coordinates
in other parts of the protocol, like input events, relative window
positioning and output positioning are still in the compositor space
rather than the scaled space. However, input has subpixel precision
so you can still get input at full resolution.

This setup means global properties like mouse acceleration/speed,
pointer size, monitor geometry, etc can be specified in a "mostly
similar" resolution even on a multimonitor setup where some monitors
are low dpi and some are e.g. retina-class outputs.
---
 protocol/wayland.xml | 107 ---
 1 file changed, 93 insertions(+), 14 deletions(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index d3ae149..acfb140 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -173,7 +173,7 @@
 
   
 
-  
+  
 
   A compositor.  This object is a singleton global.  The
   compositor is in charge of combining the contents of multiple
@@ -709,7 +709,7 @@
 
The x and y arguments specify the locations of the upper left
corner of the surface relative to the upper left corner of the
-   parent surface.
+   parent surface, in surface local coordinates.
 
The flags argument controls details of the transient behaviour.
   
@@ -777,6 +777,10 @@
in any of the clients surfaces is reported as normal, however,
clicks in other clients surfaces will be discarded and trigger
the callback.
+
+   The x and y arguments specify the locations of the upper left
+   corner of the surface relative to the upper left corner of the
+   parent surface, in surface local coordinates.
   
 
   
@@ -860,6 +864,9 @@
 
The client is free to dismiss all but the last configure
event it received.
+
+   The width and height arguments specify the size of the window
+   in surface local coordinates.
   
 
   
@@ -876,11 +883,16 @@
 
   
 
-  
+  
 
   A surface is a rectangular area that is displayed on the screen.
   It has a location, size and pixel contents.
 
+  The size of a surface (and relative positions on it) is described
+  in surface local coordinates, which may differ from the buffer
+  local coordinates of the pixel content, in case a buffer_transform
+  or a buffer_scale is used.
+
   Surfaces are also used for some special purposes, e.g. as
   cursor images for pointers, drag icons, etc.
 
@@ -895,20 +907,25 @@
   
Set a buffer as the content of this surface.
 
+   The new size of the surface is calculated based on the buffer
+   size transformed by the inverse buffer_transform and the
+   inverse buffer_scale. This means that the supplied buffer
+   must be an integer multiple of the buffer_scale.
+
The x and y arguments specify the location of the new pending
-   buffer's upper left corner, relative to the current buffer's
-   upper left corner. In other words, the x and y, and the width
-   and height of the wl_buffer together define in which directions
-   the surface's size changes.
+   buffer's upper left corner, relative to the current buffer's upper
+   left corner, in surface local coordinates. In other words, the
+   x and y, combined with the new surface size define in which
+   directions the surface's size changes.
 
Surface contents are double-buffered state, see wl_surface.commit.
 
The initial surface contents are void; there is no content.
wl_surface.attach assigns the given wl_buffer as the pending
wl_buffer. wl_surface.commit makes the pending wl_buffer the new
-   surface contents, and the size of the surface becomes the size of
-   the wl_buffer, as described above. After commit, there is no
-   pending buffer until the next attach.
+   surface contents, 

[PATCH 00/15] weston scaling support

2013-05-22 Thread alexl
From: Alexander Larsson 

This adds support to weston (X11 and DRM backends) for output
scale and buffer_scale. It also contains some work on the
example clients to make them support buffer scaling.

I think the support is fairly comprehensive, although I'm aware of
a few outstanding issues:

* The drm backend doesn't upscale pointers on the DRM backend
* There is no support in the desktop shell for setting up a higher resolution
  cursor image on scaled outputs
* I did not yet look at the screenshoter/read_pixels APIs

Overall I think the approach is working out well, but an obvious issue is how 
we handle
scaling wrt modes. I'll bring this up in another mail.

The series is also availible in the scale branch here: (eventually)
 http://cgit.freedesktop.org/~alexl/weston/

Alexander Larsson (15):
  window: Support transform in widget_cairo_create()
  transformed: Rely on transformation in widget_cairo_create
  window: Track output scales
  window: allow setting a buffer scale on a window
  window: Apply buffer_scale automatically in widget_cairo_create
  transformed: Use the scale factor from the output
  window: Store server_allocation in surface size
  desktop-shell: Respect output scale and translate
  window: Add window_get_output_scale()
  terminal: Handle output transform
  transformed: Add keyboard shortcuts to change transform
  pixman-renderer: Fix up transform handling
  compositor: Support output/buffer scaling
  compositor-x11: Only repaint the damaged region
  compositor-drm: Support output scaling

 clients/desktop-shell.c   |  75 ++--
 clients/terminal.c|  13 +-
 clients/transformed.c | 124 ++---
 clients/window.c  | 237 ++---
 clients/window.h  |  13 ++
 src/compositor-drm.c  |  88 +++---
 src/compositor-fbdev.c|   3 +-
 src/compositor-headless.c |   2 +-
 src/compositor-rpi.c  |   3 +-
 src/compositor-wayland.c  |   2 +-
 src/compositor-x11.c  | 166 --
 src/compositor.c  | 110 +---
 src/compositor.h  |  18 +-
 src/gl-renderer.c |  21 +--
 src/pixman-renderer.c | 436 ++
 15 files changed, 977 insertions(+), 334 deletions(-)

-- 
1.8.1.4

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


[PATCH 01/15] window: Support transform in widget_cairo_create()

2013-05-22 Thread alexl
From: Alexander Larsson 

If a buffer_transform it specified in the window we automatically
compensate for it in the cairo_t
---
 clients/window.c | 77 
 1 file changed, 77 insertions(+)

diff --git a/clients/window.c b/clients/window.c
index 40c0ef4..48b784d 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -1607,6 +1607,81 @@ widget_get_cairo_surface(struct widget *widget)
return surface->cairo_surface;
 }
 
+static void
+widget_cairo_update_transform(struct widget *widget, cairo_t *cr)
+{
+   struct surface *surface = widget->surface;
+   double angle;
+   cairo_matrix_t m;
+   enum wl_output_transform transform;
+   int surface_width, surface_height;
+   int translate_x, translate_y;
+
+   surface_width = surface->allocation.width;
+   surface_height = surface->allocation.height;
+
+   transform = window_get_buffer_transform(widget->window);
+   switch (transform) {
+   case WL_OUTPUT_TRANSFORM_FLIPPED:
+   case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+   case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+   case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+   cairo_matrix_init(&m, -1, 0, 0, 1, 0, 0);
+   break;
+   default:
+   cairo_matrix_init_identity(&m);
+   break;
+   }
+
+   switch (transform) {
+   case WL_OUTPUT_TRANSFORM_NORMAL:
+   default:
+   angle = 0;
+   translate_x = 0;
+   translate_y = 0;
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED:
+   angle = 0;
+   translate_x = surface_width;
+   translate_y = 0;
+   break;
+   case WL_OUTPUT_TRANSFORM_90:
+   angle = M_PI_2;
+   translate_x = surface_height;
+   translate_y = 0;
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+   angle = M_PI_2;
+   translate_x = surface_height;
+   translate_y = surface_width;
+   break;
+   case WL_OUTPUT_TRANSFORM_180:
+   angle = M_PI;
+   translate_x = surface_width;
+   translate_y = surface_height;
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+   angle = M_PI;
+   translate_x = 0;
+   translate_y = surface_height;
+   break;
+   case WL_OUTPUT_TRANSFORM_270:
+   angle = M_PI + M_PI_2;
+   translate_x = 0;
+   translate_y = surface_width;
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+   angle = M_PI + M_PI_2;
+   translate_x = 0;
+   translate_y = 0;
+   break;
+   }
+
+   cairo_translate(cr, translate_x, translate_y);
+   cairo_rotate(cr, angle);
+   cairo_transform(cr, &m);
+}
+
 cairo_t *
 widget_cairo_create(struct widget *widget)
 {
@@ -1617,6 +1692,8 @@ widget_cairo_create(struct widget *widget)
cairo_surface = widget_get_cairo_surface(widget);
cr = cairo_create(cairo_surface);
 
+   widget_cairo_update_transform(widget, cr);
+
cairo_translate(cr, -surface->allocation.x, -surface->allocation.y);
 
return cr;
-- 
1.8.1.4

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


[PATCH 02/15] transformed: Rely on transformation in widget_cairo_create

2013-05-22 Thread alexl
From: Alexander Larsson 

Rather than doing our own transformation handling when drawing we
just rely on the generic code in widget_cairo_create
---
 clients/transformed.c | 69 ++-
 1 file changed, 8 insertions(+), 61 deletions(-)

diff --git a/clients/transformed.c b/clients/transformed.c
index 8983bb5..560ddf3 100644
--- a/clients/transformed.c
+++ b/clients/transformed.c
@@ -42,67 +42,14 @@ struct transformed {
 };
 
 static void
-update_transform(cairo_t *cr, enum wl_output_transform transform)
+draw_stuff(cairo_t *cr, int width, int height)
 {
-   double angle;
-
cairo_matrix_t m;
+   cairo_get_matrix (cr, &m);
 
-   switch(transform) {
-   case WL_OUTPUT_TRANSFORM_FLIPPED:
-   case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-   case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-   case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-   cairo_matrix_init(&m, -1, 0, 0, 1, 0, 0);
-   break;
-   default:
-   cairo_matrix_init_identity(&m);
-   break;
-   }
-   switch (transform) {
-   case WL_OUTPUT_TRANSFORM_NORMAL:
-   case WL_OUTPUT_TRANSFORM_FLIPPED:
-   default:
-   angle = 0;
-   break;
-   case WL_OUTPUT_TRANSFORM_90:
-   case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-   angle = M_PI_2;
-   break;
-   case WL_OUTPUT_TRANSFORM_180:
-   case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-   angle = M_PI;
-   break;
-   case WL_OUTPUT_TRANSFORM_270:
-   case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-   angle = M_PI + M_PI_2;
-   break;
-   }
-
-   cairo_rotate(cr, angle);
-   cairo_transform(cr, &m);
-}
-
-static void
-draw_stuff(cairo_surface_t *surface, int width, int height, int transform)
-{
-   cairo_t *cr;
-   int tmp;
-
-   if (transform & 1) {
-   tmp = width;
-   width = height;
-   height = tmp;
-   }
-
-   cr = cairo_create(surface);
-
-   cairo_identity_matrix(cr);
cairo_translate(cr, width / 2, height / 2);
cairo_scale(cr, width / 2, height / 2);
 
-   update_transform(cr, transform);
-
cairo_set_source_rgba(cr, 0, 0, 0.3, 1.0);
cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
cairo_rectangle(cr, -1, -1, 2, 2);
@@ -113,7 +60,7 @@ draw_stuff(cairo_surface_t *surface, int width, int height, 
int transform)
cairo_line_to(cr, 0, -1);
 
cairo_save(cr);
-   cairo_identity_matrix(cr);
+   cairo_set_matrix(cr, &m);
cairo_set_line_width(cr, 2.0);
cairo_stroke(cr);
cairo_restore(cr);
@@ -123,7 +70,7 @@ draw_stuff(cairo_surface_t *surface, int width, int height, 
int transform)
cairo_line_to(cr, 1, 0);
 
cairo_save(cr);
-   cairo_identity_matrix(cr);
+   cairo_set_matrix(cr, &m);
cairo_set_line_width(cr, 2.0);
cairo_stroke(cr);
cairo_restore(cr);
@@ -135,7 +82,7 @@ draw_stuff(cairo_surface_t *surface, int width, int height, 
int transform)
cairo_line_to(cr, -1, 0);
 
cairo_save(cr);
-   cairo_identity_matrix(cr);
+   cairo_set_matrix(cr, &m);
cairo_set_line_width(cr, 2.0);
cairo_stroke(cr);
cairo_restore(cr);
@@ -168,7 +115,7 @@ redraw_handler(struct widget *widget, void *data)
struct transformed *transformed = data;
struct rectangle allocation;
cairo_surface_t *surface;
-   int transform;
+   cairo_t *cr;
 
surface = window_get_surface(transformed->window);
if (surface == NULL ||
@@ -178,9 +125,9 @@ redraw_handler(struct widget *widget, void *data)
}
 
widget_get_allocation(transformed->widget, &allocation);
-   transform = window_get_buffer_transform(transformed->window);
 
-   draw_stuff(surface, allocation.width, allocation.height, transform);
+   cr = widget_cairo_create(widget);
+   draw_stuff(cr, allocation.width, allocation.height);
 
cairo_surface_destroy(surface);
 }
-- 
1.8.1.4

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


[PATCH 03/15] window: Track output scales

2013-05-22 Thread alexl
From: Alexander Larsson 

---
 clients/window.c | 30 --
 clients/window.h |  3 +++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 48b784d..36fda25 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -322,6 +322,7 @@ struct output {
struct rectangle allocation;
struct wl_list link;
int transform;
+   int scale;
 
display_output_handler_t destroy_handler;
void *user_data;
@@ -4382,6 +4383,22 @@ display_handle_geometry(void *data,
 }
 
 static void
+display_handle_done(void *data,
+struct wl_output *wl_output)
+{
+}
+
+static void
+display_handle_scale(void *data,
+struct wl_output *wl_output,
+uint32_t scale)
+{
+   struct output *output = data;
+
+   output->scale = scale;
+}
+
+static void
 display_handle_mode(void *data,
struct wl_output *wl_output,
uint32_t flags,
@@ -4403,7 +4420,9 @@ display_handle_mode(void *data,
 
 static const struct wl_output_listener output_listener = {
display_handle_geometry,
-   display_handle_mode
+   display_handle_mode,
+   display_handle_done,
+   display_handle_scale
 };
 
 static void
@@ -4417,8 +4436,9 @@ display_add_output(struct display *d, uint32_t id)
 
memset(output, 0, sizeof *output);
output->display = d;
+   output->scale = 1;
output->output =
-   wl_registry_bind(d->registry, id, &wl_output_interface, 1);
+   wl_registry_bind(d->registry, id, &wl_output_interface, 2);
wl_list_insert(d->output_list.prev, &output->link);
 
wl_output_add_listener(output->output, &output_listener, output);
@@ -4522,6 +4542,12 @@ output_get_transform(struct output *output)
return output->transform;
 }
 
+uint32_t
+output_get_scale(struct output *output)
+{
+   return output->scale;
+}
+
 static void
 fini_xkb(struct input *input)
 {
diff --git a/clients/window.h b/clients/window.h
index 7db9c63..c0a7cb6 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -504,6 +504,9 @@ output_get_wl_output(struct output *output);
 enum wl_output_transform
 output_get_transform(struct output *output);
 
+uint32_t
+output_get_scale(struct output *output);
+
 void
 keysym_modifiers_add(struct wl_array *modifiers_map,
 const char *name);
-- 
1.8.1.4

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


[PATCH 04/15] window: allow setting a buffer scale on a window

2013-05-22 Thread alexl
From: Alexander Larsson 

---
 clients/window.c | 25 +++--
 clients/window.h |  7 +++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 36fda25..378cc75 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -152,7 +152,7 @@ struct toysurface {
 * Prepare the surface for drawing. Makes sure there is a surface
 * of the right size available for rendering, and returns it.
 * dx,dy are the x,y of wl_surface.attach.
-* width,height are the new surface size.
+* width,height are the new buffer size.
 * If flags has SURFACE_HINT_RESIZE set, the user is
 * doing continuous resizing.
 * Returns the Cairo surface to draw to.
@@ -208,6 +208,7 @@ struct surface {
 
enum window_buffer_type buffer_type;
enum wl_output_transform buffer_transform;
+   uint32_t buffer_scale;
 
cairo_surface_t *cairo_surface;
 
@@ -1325,6 +1326,9 @@ surface_create_surface(struct surface *surface, int dx, 
int dy, uint32_t flags)
break;
}
 
+   allocation.width *= surface->buffer_scale;
+   allocation.height *= surface->buffer_scale;
+
if (!surface->toysurface && display->dpy &&
surface->buffer_type == WINDOW_BUFFER_TYPE_EGL_WINDOW) {
surface->toysurface =
@@ -1383,6 +1387,21 @@ window_set_buffer_transform(struct window *window,
transform);
 }
 
+void
+window_set_buffer_scale(struct window *window,
+   uint32_t scale)
+{
+   window->main_surface->buffer_scale = scale;
+   wl_surface_set_buffer_scale(window->main_surface->surface,
+   scale);
+}
+
+uint32_t
+window_get_buffer_scale(struct window *window)
+{
+   return window->main_surface->buffer_scale;
+}
+
 static void frame_destroy(struct frame *frame);
 
 static void
@@ -1621,7 +1640,8 @@ widget_cairo_update_transform(struct widget *widget, 
cairo_t *cr)
surface_width = surface->allocation.width;
surface_height = surface->allocation.height;
 
-   transform = window_get_buffer_transform(widget->window);
+   transform = surface->buffer_transform;
+
switch (transform) {
case WL_OUTPUT_TRANSFORM_FLIPPED:
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
@@ -4057,6 +4077,7 @@ surface_create(struct window *window)
 
surface->window = window;
surface->surface = wl_compositor_create_surface(display->compositor);
+   surface->buffer_scale = 1;
wl_surface_add_listener(surface->surface, &surface_listener, window);
 
wl_list_insert(&window->subsurface_list, &surface->link);
diff --git a/clients/window.h b/clients/window.h
index c0a7cb6..fec601f 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -253,6 +253,13 @@ void
 window_set_buffer_transform(struct window *window,
enum wl_output_transform transform);
 
+uint32_t
+window_get_buffer_scale(struct window *window);
+
+void
+window_set_buffer_scale(struct window *window,
+uint32_t scale);
+
 void
 window_destroy(struct window *window);
 
-- 
1.8.1.4

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


[PATCH 05/15] window: Apply buffer_scale automatically in widget_cairo_create

2013-05-22 Thread alexl
From: Alexander Larsson 

---
 clients/window.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clients/window.c b/clients/window.c
index 378cc75..00ffd27 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -1636,11 +1636,13 @@ widget_cairo_update_transform(struct widget *widget, 
cairo_t *cr)
enum wl_output_transform transform;
int surface_width, surface_height;
int translate_x, translate_y;
+   uint32_t scale;
 
surface_width = surface->allocation.width;
surface_height = surface->allocation.height;
 
transform = surface->buffer_transform;
+   scale = surface->buffer_scale;
 
switch (transform) {
case WL_OUTPUT_TRANSFORM_FLIPPED:
@@ -1698,6 +1700,7 @@ widget_cairo_update_transform(struct widget *widget, 
cairo_t *cr)
break;
}
 
+   cairo_scale(cr, scale, scale);
cairo_translate(cr, translate_x, translate_y);
cairo_rotate(cr, angle);
cairo_transform(cr, &m);
-- 
1.8.1.4

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


[PATCH 06/15] transformed: Use the scale factor from the output

2013-05-22 Thread alexl
From: Alexander Larsson 

---
 clients/transformed.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clients/transformed.c b/clients/transformed.c
index 560ddf3..d685330 100644
--- a/clients/transformed.c
+++ b/clients/transformed.c
@@ -140,6 +140,7 @@ output_handler(struct window *window, struct output 
*output, int enter,
return;
 
window_set_buffer_transform(window, output_get_transform(output));
+   window_set_buffer_scale(window, output_get_scale(output));
window_schedule_redraw(window);
 }
 
-- 
1.8.1.4

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


[PATCH 07/15] window: Store server_allocation in surface size

2013-05-22 Thread alexl
From: Alexander Larsson 

We used to just store the buffer size here which is not right if the
surface has a buffer_transform or a buffer_scale. To fix this we pass
the transform and scale into the toysurface prepare and swap calls and
move both the surface to buffer and the buffer to surface size
conversion there.

Without this interactive resize on the top or left sides of a transformed
or scaled surface will not work correctly.
---
 clients/window.c | 92 
 1 file changed, 72 insertions(+), 20 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 00ffd27..6dd6533 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -158,7 +158,8 @@ struct toysurface {
 * Returns the Cairo surface to draw to.
 */
cairo_surface_t *(*prepare)(struct toysurface *base, int dx, int dy,
-   int width, int height, uint32_t flags);
+   int32_t width, int32_t height, uint32_t 
flags,
+   enum wl_output_transform buffer_transform, 
uint32_t buffer_scale);
 
/*
 * Post the surface to the server, returning the server allocation
@@ -166,6 +167,7 @@ struct toysurface {
 * after calling this.
 */
void (*swap)(struct toysurface *base,
+enum wl_output_transform buffer_transform, uint32_t 
buffer_scale,
 struct rectangle *server_allocation);
 
/*
@@ -463,6 +465,50 @@ debug_print(void *proxy, int line, const char *func, const 
char *fmt, ...)
 
 #endif
 
+static void
+surface_to_buffer_size (enum wl_output_transform buffer_transform, uint32_t 
buffer_scale, int32_t *width, int32_t *height)
+{
+   int32_t tmp;
+
+   switch (buffer_transform) {
+   case WL_OUTPUT_TRANSFORM_90:
+   case WL_OUTPUT_TRANSFORM_270:
+   case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+   case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+   tmp = *width;
+   *width = *height;
+   *height = tmp;
+   break;
+   default:
+   break;
+   }
+
+   *width *= buffer_scale;
+   *height *= buffer_scale;
+}
+
+static void
+buffer_to_surface_size (enum wl_output_transform buffer_transform, uint32_t 
buffer_scale, int32_t *width, int32_t *height)
+{
+   int32_t tmp;
+
+   switch (buffer_transform) {
+   case WL_OUTPUT_TRANSFORM_90:
+   case WL_OUTPUT_TRANSFORM_270:
+   case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+   case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+   tmp = *width;
+   *width = *height;
+   *height = tmp;
+   break;
+   default:
+   break;
+   }
+
+   *width /= buffer_scale;
+   *height /= buffer_scale;
+}
+
 #ifdef HAVE_CAIRO_EGL
 
 struct egl_window_surface {
@@ -482,10 +528,13 @@ to_egl_window_surface(struct toysurface *base)
 
 static cairo_surface_t *
 egl_window_surface_prepare(struct toysurface *base, int dx, int dy,
-  int width, int height, uint32_t flags)
+  int32_t width, int32_t height, uint32_t flags,
+  enum wl_output_transform buffer_transform, uint32_t 
buffer_scale)
 {
struct egl_window_surface *surface = to_egl_window_surface(base);
 
+   surface_to_buffer_size (buffer_transform, buffer_scale, &width, 
&height);
+
wl_egl_window_resize(surface->egl_window, width, height, dx, dy);
cairo_gl_surface_set_size(surface->cairo_surface, width, height);
 
@@ -494,6 +543,7 @@ egl_window_surface_prepare(struct toysurface *base, int dx, 
int dy,
 
 static void
 egl_window_surface_swap(struct toysurface *base,
+   enum wl_output_transform buffer_transform, uint32_t 
buffer_scale,
struct rectangle *server_allocation)
 {
struct egl_window_surface *surface = to_egl_window_surface(base);
@@ -502,6 +552,10 @@ egl_window_surface_swap(struct toysurface *base,
wl_egl_window_get_attached_size(surface->egl_window,
&server_allocation->width,
&server_allocation->height);
+
+   buffer_to_surface_size (buffer_transform, buffer_scale,
+   &server_allocation->width,
+   &server_allocation->height);
 }
 
 static int
@@ -948,11 +1002,12 @@ static const struct wl_buffer_listener 
shm_surface_buffer_listener = {
 
 static cairo_surface_t *
 shm_surface_prepare(struct toysurface *base, int dx, int dy,
-   int width, int height, uint32_t flags)
+   int32_t width, int32_t height, uint32_t flags,
+   enum wl_output_transform buffer_transform, uint32_t 
buffer_scale)
 {
int resize_hint = !!(flags & SURFACE_HINT_RESIZE);
struct shm_surface *surface = to_shm_surface(base);
-   struct rectang

[PATCH 08/15] desktop-shell: Respect output scale and translate

2013-05-22 Thread alexl
From: Alexander Larsson 

We pick the window scale/tranform based on what the output uses, which means
we can avoid rotations in the compositor, and get sharper rendering
in scaled outputs.
---
 clients/desktop-shell.c | 75 -
 1 file changed, 62 insertions(+), 13 deletions(-)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index 3949975..497e4ff 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -201,12 +201,10 @@ static void
 panel_launcher_redraw_handler(struct widget *widget, void *data)
 {
struct panel_launcher *launcher = data;
-   cairo_surface_t *surface;
struct rectangle allocation;
cairo_t *cr;
 
-   surface = window_get_surface(launcher->panel->window);
-   cr = cairo_create(surface);
+   cr = widget_cairo_create(launcher->panel->widget);
 
widget_get_allocation(widget, &allocation);
if (launcher->pressed) {
@@ -255,13 +253,13 @@ panel_redraw_handler(struct widget *widget, void *data)
cairo_t *cr;
struct panel *panel = data;
 
-   surface = window_get_surface(panel->window);
-   cr = cairo_create(surface);
+   cr = widget_cairo_create(panel->widget);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
set_hex_color(cr, key_panel_color);
cairo_paint(cr);
 
cairo_destroy(cr);
+   surface = window_get_surface(panel->window);
cairo_surface_destroy(surface);
 }
 
@@ -317,7 +315,6 @@ clock_func(struct task *task, uint32_t events)
 static void
 panel_clock_redraw_handler(struct widget *widget, void *data)
 {
-   cairo_surface_t *surface;
struct panel_clock *clock = data;
cairo_t *cr;
struct rectangle allocation;
@@ -335,8 +332,7 @@ panel_clock_redraw_handler(struct widget *widget, void 
*data)
if (allocation.width == 0)
return;
 
-   surface = window_get_surface(clock->panel->window);
-   cr = cairo_create(surface);
+   cr = widget_cairo_create(clock->panel->widget);
cairo_select_font_face(cr, "sans",
   CAIRO_FONT_SLANT_NORMAL,
   CAIRO_FONT_WEIGHT_NORMAL);
@@ -644,7 +640,7 @@ background_draw(struct widget *widget, void *data)
 
surface = window_get_surface(background->window);
 
-   cr = cairo_create(surface);
+   cr = widget_cairo_create(background->widget);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
cairo_paint(cr);
@@ -713,13 +709,12 @@ unlock_dialog_redraw_handler(struct widget *widget, void 
*data)
 {
struct unlock_dialog *dialog = data;
struct rectangle allocation;
-   cairo_t *cr;
cairo_surface_t *surface;
+   cairo_t *cr;
cairo_pattern_t *pat;
double cx, cy, r, f;
 
-   surface = window_get_surface(dialog->window);
-   cr = cairo_create(surface);
+   cr = widget_cairo_create(widget);
 
widget_get_allocation(dialog->widget, &allocation);
cairo_rectangle(cr, allocation.x, allocation.y,
@@ -752,6 +747,7 @@ unlock_dialog_redraw_handler(struct widget *widget, void 
*data)
 
cairo_destroy(cr);
 
+   surface = window_get_surface(dialog->window);
cairo_surface_destroy(surface);
 }
 
@@ -1025,6 +1021,57 @@ desktop_destroy_outputs(struct desktop *desktop)
 }
 
 static void
+output_handle_geometry(void *data,
+   struct wl_output *wl_output,
+   int x, int y,
+   int physical_width,
+   int physical_height,
+   int subpixel,
+   const char *make,
+   const char *model,
+   int transform)
+{
+   struct output *output = data;
+
+   window_set_buffer_transform(output->panel->window, transform);
+   window_set_buffer_transform(output->background->window, transform);
+}
+
+static void
+output_handle_mode(void *data,
+  struct wl_output *wl_output,
+  uint32_t flags,
+  int width,
+  int height,
+  int refresh)
+{
+}
+
+static void
+output_handle_done(void *data,
+   struct wl_output *wl_output)
+{
+}
+
+static void
+output_handle_scale(void *data,
+struct wl_output *wl_output,
+uint32_t scale)
+{
+   struct output *output = data;
+
+   window_set_buffer_scale(output->panel->window, scale);
+   window_set_buffer_scale(output->background->window, scale);
+}
+
+static const struct wl_output_listener output_listener = {
+   output_handle_geometry,
+   output_handle_mode,
+   output_handle_done,
+   output_handle_scale
+};
+
+static void
 create_output(struct desktop *desktop, uint32_t id)
 {
struct output *output;
@@ -1034,7 +1081,9 @@ create_output(struct desktop 

[PATCH 09/15] window: Add window_get_output_scale()

2013-05-22 Thread alexl
From: Alexander Larsson 

This lets you find the maximal scale for all the outputs a window
is on, which is useful for picking a buffer_scale.
---
 clients/window.c | 18 ++
 clients/window.h |  3 +++
 2 files changed, 21 insertions(+)

diff --git a/clients/window.c b/clients/window.c
index 6dd6533..09573f6 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -1454,6 +1454,22 @@ window_get_buffer_scale(struct window *window)
return window->main_surface->buffer_scale;
 }
 
+uint32_t
+window_get_output_scale(struct window *window)
+{
+   struct window_output *window_output;
+   struct window_output *window_output_tmp;
+   int scale = 1;
+
+   wl_list_for_each_safe(window_output, window_output_tmp,
+ &window->window_output_list, link) {
+   if (window_output->output->scale > scale)
+   scale = window_output->output->scale;
+   }
+
+   return scale;
+}
+
 static void frame_destroy(struct frame *frame);
 
 static void
@@ -4370,6 +4386,8 @@ window_show_menu(struct display *display,
 
menu->window = window;
menu->widget = window_add_widget(menu->window, menu);
+   window_set_buffer_scale (menu->window, window_get_buffer_scale 
(parent));
+   window_set_buffer_transform (menu->window, window_get_buffer_transform 
(parent));
menu->entries = entries;
menu->count = count;
menu->release_count = 0;
diff --git a/clients/window.h b/clients/window.h
index fec601f..f7b3f28 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -260,6 +260,9 @@ void
 window_set_buffer_scale(struct window *window,
 uint32_t scale);
 
+uint32_t
+window_get_output_scale(struct window *window);
+
 void
 window_destroy(struct window *window);
 
-- 
1.8.1.4

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


[PATCH 10/15] terminal: Handle output transform

2013-05-22 Thread alexl
From: Alexander Larsson 

We pick the highest scale of any output the terminal is on, and the
transform from the last one it entered.
---
 clients/terminal.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/clients/terminal.c b/clients/terminal.c
index f11a6cc..2985726 100644
--- a/clients/terminal.c
+++ b/clients/terminal.c
@@ -933,7 +933,7 @@ redraw_handler(struct widget *widget, void *data)
 
surface = window_get_surface(terminal->window);
widget_get_allocation(terminal->widget, &allocation);
-   cr = cairo_create(surface);
+   cr = widget_cairo_create(terminal->widget);
cairo_rectangle(cr, allocation.x, allocation.y,
allocation.width, allocation.height);
cairo_clip(cr);
@@ -2517,6 +2517,16 @@ motion_handler(struct widget *widget,
return CURSOR_IBEAM;
 }
 
+static void
+output_handler(struct window *window, struct output *output, int enter,
+  void *data)
+{
+   if (enter)
+   window_set_buffer_transform(window, 
output_get_transform(output));
+   window_set_buffer_scale(window, window_get_output_scale(window));
+   window_schedule_redraw(window);
+}
+
 static struct terminal *
 terminal_create(struct display *display)
 {
@@ -2549,6 +2559,7 @@ terminal_create(struct display *display)
window_set_keyboard_focus_handler(terminal->window,
  keyboard_focus_handler);
window_set_fullscreen_handler(terminal->window, fullscreen_handler);
+   window_set_output_handler(terminal->window, output_handler);
window_set_close_handler(terminal->window, close_handler);
 
widget_set_redraw_handler(terminal->widget, redraw_handler);
-- 
1.8.1.4

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


[PATCH 11/15] transformed: Add keyboard shortcuts to change transform

2013-05-22 Thread alexl
From: Alexander Larsson 

This makes it easy to test buffer_transform and buffer_scale handling.
left-right: rotate
space: toggle inverse
z: toggle scale between 1 and 2
---
 clients/transformed.c | 54 +++
 1 file changed, 54 insertions(+)

diff --git a/clients/transformed.c b/clients/transformed.c
index d685330..e8d817d 100644
--- a/clients/transformed.c
+++ b/clients/transformed.c
@@ -145,6 +145,59 @@ output_handler(struct window *window, struct output 
*output, int enter,
 }
 
 static void
+key_handler(struct window *window, struct input *input, uint32_t time,
+   uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
+   void *data)
+{
+   int transform, scale;
+
+   if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
+   return;
+
+   transform = window_get_buffer_transform (window);
+   scale = window_get_buffer_scale (window);
+   switch (sym) {
+   case XKB_KEY_Left:
+   if (transform == 0)
+   transform = 3;
+   else if (transform == 4)
+   transform = 7;
+   else
+   transform--;
+   break;
+
+   case XKB_KEY_Right:
+   if (transform == 3)
+   transform = 0;
+   else if (transform == 7)
+   transform = 4;
+   else
+   transform++;
+   break;
+
+   case XKB_KEY_space:
+   if (transform >= 4)
+   transform -= 4;
+   else
+   transform += 4;
+   break;
+
+   case XKB_KEY_z:
+   if (scale == 1)
+   scale = 2;
+   else
+   scale = 1;
+   break;
+   }
+
+   printf ("setting buffer transform to %d\n", transform);
+   printf ("setting buffer scale to %d\n", scale);
+   window_set_buffer_transform(window, transform);
+   window_set_buffer_scale(window, scale);
+   window_schedule_redraw(window);
+}
+
+static void
 button_handler(struct widget *widget,
   struct input *input, uint32_t time,
   uint32_t button, enum wl_pointer_button_state state, void *data)
@@ -234,6 +287,7 @@ int main(int argc, char *argv[])
widget_set_redraw_handler(transformed.widget, redraw_handler);
widget_set_button_handler(transformed.widget, button_handler);
 
+   window_set_key_handler(transformed.window, key_handler);
window_set_fullscreen_handler(transformed.window, fullscreen_handler);
window_set_output_handler(transformed.window, output_handler);
 
-- 
1.8.1.4

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


[PATCH 12/15] pixman-renderer: Fix up transform handling

2013-05-22 Thread alexl
From: Alexander Larsson 

Rather than storing the shadow_image in the untransformed space
and rotating on copy to hw_buffer we store both on the transformed
space. This means a copy between them is a straight copy, and that
apps supplying correctly transformed surface buffers need not
change them.

We also correctly handle all output transform including the previously
unhandled flipped ones, as well as client supplied buffer_transforms (which
were previously ignored).

We also simplify the actual rendering by just converting any damage
region to output coordinates and set it on a clip and composite
the whole buffer, letting pixman do the rectangle handling. This
means we always do all the transforms, including the surface positioning
as a pixman_image transform. This simplifies the code and sets us up
for handling scaling at a later stage.

The transform looks complicated, but in practice it ends up being
an integer translation almost always, so it will hit the pixman
fastpaths.
---
 src/pixman-renderer.c | 408 ++
 1 file changed, 248 insertions(+), 160 deletions(-)

diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index 60800bc..92c6bb3 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -105,92 +105,98 @@ pixman_renderer_read_pixels(struct weston_output *output,
 }
 
 static void
-box_translate(pixman_box32_t *dst, const pixman_box32_t *src, int x, int y)
+transform_region (pixman_region32_t *region, int width, int height, enum 
wl_output_transform transform)
 {
-   dst->x1 = src->x1 + x;
-   dst->x2 = src->x2 + x;
-   dst->y1 = src->y1 + y;
-   dst->y2 = src->y2 + y;
-}
-
-#define D2F(v) pixman_double_to_fixed((double)v)
-
-static void
-repaint_region_complex(struct weston_surface *es, struct weston_output *output,
-   pixman_region32_t *region)
-{
-   struct pixman_renderer *pr =
-   (struct pixman_renderer *) output->compositor->renderer;
-   struct pixman_surface_state *ps = get_surface_state(es);
-   struct pixman_output_state *po = get_output_state(output);
+   pixman_box32_t *rects, *transformed_rects;
int nrects, i;
-   pixman_box32_t *rects, rect;
 
-   /* Pixman supports only 2D transform matrix, but Weston uses 3D,
-* so we're omitting Z coordinate here
-*/
-   pixman_transform_t transform = {{
-   { D2F(es->transform.matrix.d[0]),
- D2F(es->transform.matrix.d[4]),
- D2F(es->transform.matrix.d[12]),
-   },
-   { D2F(es->transform.matrix.d[1]),
- D2F(es->transform.matrix.d[5]),
- D2F(es->transform.matrix.d[13]),
-   },
-   { D2F(es->transform.matrix.d[3]),
- D2F(es->transform.matrix.d[7]),
- D2F(es->transform.matrix.d[15]),
-   }
-   }};
-
-   pixman_transform_invert(&transform, &transform);
-
-   pixman_image_set_transform(ps->image, &transform);
-   pixman_image_set_filter(ps->image, PIXMAN_FILTER_BILINEAR, NULL, 0);
+   if (transform == WL_OUTPUT_TRANSFORM_NORMAL)
+   return;
 
rects = pixman_region32_rectangles(region, &nrects);
+   transformed_rects = calloc(nrects, sizeof(pixman_box32_t));
+
for (i = 0; i < nrects; i++) {
-   box_translate(&rect, &rects[i], -output->x, -output->y);
-   pixman_image_composite32(PIXMAN_OP_OVER,
-   ps->image, /* src */
-   NULL /* mask */,
-   po->shadow_image, /* dest */
-   rects[i].x1, rects[i].y1, /* src_x, src_y */
-   0, 0, /* mask_x, mask_y */
-   rect.x1, rect.y1, /* dst_x, dst_y */
-   rect.x2 - rect.x1, /* width */
-   rect.y2 - rect.y1 /* height */
-   );
+   switch (transform) {
+   default:
+   case WL_OUTPUT_TRANSFORM_NORMAL:
+   transformed_rects[i].x1 = rects[i].x1;
+   transformed_rects[i].y1 = rects[i].y1;
+   transformed_rects[i].x2 = rects[i].x2;
+   transformed_rects[i].y2 = rects[i].y2;
+   break;
+   case WL_OUTPUT_TRANSFORM_90:
+   transformed_rects[i].x1 = height - rects[i].y2;
+   transformed_rects[i].y1 = rects[i].x1;
+   transformed_rects[i].x2 = height - rects[i].y1;
+   transformed_rects[i].y2 = rects[i].x2;
+   break;
+   case WL_OUTPUT_TRANSFORM_180:
+   transformed_rects[i].x1 = width - rects[i].x2;
+   transformed_rects[i].y1 = height - rects[i].y2;
+   transformed_rects[i].x2 = width - rects[i].x1;
+   transforme

[PATCH 13/15] compositor: Support output/buffer scaling

2013-05-22 Thread alexl
From: Alexander Larsson 

If you specify e.g. scale=2 in weston.ini an output section for the
X11 backend we automatically upscale all normal surfaces by this
amount. Additionally we respect a buffer_scale set on the buffer to
mean that the buffer is already in a scaled form.

This works with both the gl and the pixman renderer. The non-X
backends compile and work, but don't support changing the output
scale (they do downscale as needed due to buffer_scale though).

This also sends the new "scale" and "done" events on wl_output,
making clients aware of the scale.
---
 src/compositor-drm.c  |   7 +--
 src/compositor-fbdev.c|   3 +-
 src/compositor-headless.c |   2 +-
 src/compositor-rpi.c  |   3 +-
 src/compositor-wayland.c  |   2 +-
 src/compositor-x11.c  |  60 ++---
 src/compositor.c  | 110 +-
 src/compositor.h  |  18 +++-
 src/gl-renderer.c |  21 +++--
 src/pixman-renderer.c |  48 +---
 10 files changed, 210 insertions(+), 64 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 35019e0..8b33256 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -858,7 +858,8 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
box = pixman_region32_extents(&dest_rect);
tbox = weston_transformed_rect(output_base->width,
   output_base->height,
-  output_base->transform, *box);
+  output_base->transform,
+  1, *box);
s->dest_x = tbox.x1;
s->dest_y = tbox.y1;
s->dest_w = tbox.x2 - tbox.x1;
@@ -895,7 +896,7 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
 
tbox = weston_transformed_rect(wl_fixed_from_int(es->geometry.width),
   wl_fixed_from_int(es->geometry.height),
-  es->buffer_transform, tbox);
+  es->buffer_transform, 1, tbox);
 
s->src_x = tbox.x1 << 8;
s->src_y = tbox.y1 << 8;
@@ -1813,7 +1814,7 @@ create_output_for_connector(struct drm_compositor *ec,
 
weston_output_init(&output->base, &ec->base, x, y,
   connector->mmWidth, connector->mmHeight,
-  o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
+  o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL, 1);
 
if (ec->use_pixman) {
if (drm_output_init_pixman(output, ec) < 0) {
diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c
index 21028a5..c643c23 100644
--- a/src/compositor-fbdev.c
+++ b/src/compositor-fbdev.c
@@ -537,7 +537,8 @@ fbdev_output_create(struct fbdev_compositor *compositor,
weston_output_init(&output->base, &compositor->base,
   0, 0, output->fb_info.width_mm,
   output->fb_info.height_mm,
-  WL_OUTPUT_TRANSFORM_NORMAL);
+  WL_OUTPUT_TRANSFORM_NORMAL,
+  1);
 
width = output->fb_info.x_resolution;
height = output->fb_info.y_resolution;
diff --git a/src/compositor-headless.c b/src/compositor-headless.c
index 0df0f7d..e4bd1be 100644
--- a/src/compositor-headless.c
+++ b/src/compositor-headless.c
@@ -112,7 +112,7 @@ headless_compositor_create_output(struct 
headless_compositor *c,
 
output->base.current = &output->mode;
weston_output_init(&output->base, &c->base, 0, 0, width, height,
-  WL_OUTPUT_TRANSFORM_NORMAL);
+  WL_OUTPUT_TRANSFORM_NORMAL, 1);
 
output->base.make = "weston";
output->base.model = "headless";
diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c
index 3cb2b56..226c5ce 100644
--- a/src/compositor-rpi.c
+++ b/src/compositor-rpi.c
@@ -1080,7 +1080,8 @@ rpi_output_create(struct rpi_compositor *compositor)
 
weston_output_init(&output->base, &compositor->base,
   0, 0, round(mm_width), round(mm_height),
-  WL_OUTPUT_TRANSFORM_NORMAL);
+  WL_OUTPUT_TRANSFORM_NORMAL,
+  1);
 
if (gl_renderer_output_create(&output->base,
(EGLNativeWindowType)&output->egl_window) < 0)
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 4112401..511a12d 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -267,7 +267,7 @@ wayland_compositor_create_output(struct wayland_compositor 
*c,
 
output->base.current = &output->mode;
weston_output_init(&output->base, &c->base, 0, 0, width, height,
-   WL_OUTPUT_TRANSFORM_NORMAL);
+  WL_OUTPUT_TRANSFORM_NORMAL, 1);
 

[PATCH 14/15] compositor-x11: Only repaint the damaged region

2013-05-22 Thread alexl
From: Alexander Larsson 

Set a clip on the GC when painting the damaged region so that
we don't copy the entire shadow buffer each time.
---
 src/compositor-x11.c | 106 +++
 1 file changed, 106 insertions(+)

diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 58ccc16..9d6b6e7 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -355,6 +355,111 @@ x11_output_repaint_gl(struct weston_output *output_base,
 }
 
 static void
+set_clip_for_output(struct weston_output *output_base, pixman_region32_t 
*region)
+{
+   struct x11_output *output = (struct x11_output *)output_base;
+   struct weston_compositor *ec = output->base.compositor;
+   struct x11_compositor *c = (struct x11_compositor *)ec;
+   pixman_box32_t *rects;
+   xcb_rectangle_t *output_rects;
+   pixman_box32_t rect, transformed_rect;
+   xcb_void_cookie_t cookie;
+   int width, height, nrects, i;
+   xcb_generic_error_t *err;
+
+   rects = pixman_region32_rectangles(region, &nrects);
+   output_rects = calloc(nrects, sizeof(xcb_rectangle_t));
+
+   if (output_rects == NULL)
+   return;
+
+   width = output_base->width;
+   height = output_base->height;
+
+   for (i = 0; i < nrects; i++) {
+   rect = rects[i];
+   rect.x1 -= output_base->x;
+   rect.y1 -= output_base->y;
+   rect.x2 -= output_base->x;
+   rect.y2 -= output_base->y;
+
+   switch (output_base->transform) {
+   default:
+   case WL_OUTPUT_TRANSFORM_NORMAL:
+   transformed_rect.x1 = rect.x1;
+   transformed_rect.y1 = rect.y1;
+   transformed_rect.x2 = rect.x2;
+   transformed_rect.y2 = rect.y2;
+   break;
+   case WL_OUTPUT_TRANSFORM_90:
+   transformed_rect.x1 = height - rect.y2;
+   transformed_rect.y1 = rect.x1;
+   transformed_rect.x2 = height - rect.y1;
+   transformed_rect.y2 = rect.x2;
+   break;
+   case WL_OUTPUT_TRANSFORM_180:
+   transformed_rect.x1 = width - rect.x2;
+   transformed_rect.y1 = height - rect.y2;
+   transformed_rect.x2 = width - rect.x1;
+   transformed_rect.y2 = height - rect.y1;
+   break;
+   case WL_OUTPUT_TRANSFORM_270:
+   transformed_rect.x1 = rect.y1;
+   transformed_rect.y1 = width - rect.x2;
+   transformed_rect.x2 = rect.y2;
+   transformed_rect.y2 = width - rect.x1;
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED:
+   transformed_rect.x1 = width - rect.x2;
+   transformed_rect.y1 = rect.y1;
+   transformed_rect.x2 = width - rect.x1;
+   transformed_rect.y2 = rect.y2;
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+   transformed_rect.x1 = height - rect.y2;
+   transformed_rect.y1 = width - rect.x2;
+   transformed_rect.x2 = height - rect.y1;
+   transformed_rect.y2 = width - rect.x1;
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+   transformed_rect.x1 = rect.x1;
+   transformed_rect.y1 = height - rect.y2;
+   transformed_rect.x2 = rect.x2;
+   transformed_rect.y2 = height - rect.y1;
+   break;
+   case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+   transformed_rect.x1 = rect.y1;
+   transformed_rect.y1 = rect.x1;
+   transformed_rect.x2 = rect.y2;
+   transformed_rect.y2 = rect.x2;
+   break;
+   }
+
+   transformed_rect.x1 *= output_base->scale;
+   transformed_rect.y1 *= output_base->scale;
+   transformed_rect.x2 *= output_base->scale;
+   transformed_rect.y2 *= output_base->scale;
+
+   output_rects[i].x = transformed_rect.x1;
+   output_rects[i].y = transformed_rect.y1;
+   output_rects[i].width = transformed_rect.x2 - 
transformed_rect.x1;
+   output_rects[i].height = transformed_rect.y2 - 
transformed_rect.y1;
+   }
+
+   cookie = xcb_set_clip_rectangles_checked(c->conn, 
XCB_CLIP_ORDERING_UNSORTED,
+   output->gc,
+   0, 0, nrects,
+   output_rects);
+   err = xcb_request_check(c->conn, cookie);
+   if (err !

[PATCH 15/15] compositor-drm: Support output scaling

2013-05-22 Thread alexl
From: Alexander Larsson 

If you specify e.g. scale=2 in an output section in weston.ini
we scale all modes by that factor.

We also correctly scale cursor positioning, but ATM there is no
scaling of the cursor sprite itself.
---
 src/compositor-drm.c | 87 +++-
 1 file changed, 59 insertions(+), 28 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 8b33256..1485c6c 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -61,6 +61,7 @@ static int option_current_mode = 0;
 static char *output_name;
 static char *output_mode;
 static char *output_transform;
+static char *output_scale;
 static struct wl_list configured_output_list;
 
 enum output_config {
@@ -76,6 +77,7 @@ struct drm_configured_output {
char *name;
char *mode;
uint32_t transform;
+   int32_t scale;
int32_t width, height;
drmModeModeInfo crtc_mode;
enum output_config config;
@@ -463,6 +465,7 @@ drm_output_prepare_scanout_surface(struct weston_output 
*_output,
buffer->width != output->base.current->width ||
buffer->height != output->base.current->height ||
output->base.transform != es->buffer_transform ||
+   output->base.scale != es->buffer_scale ||
es->transform.enabled)
return NULL;
 
@@ -791,6 +794,9 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
if (es->buffer_transform != output_base->transform)
return NULL;
 
+   if (es->buffer_scale != output_base->scale)
+   return NULL;
+
if (c->sprites_are_broken)
return NULL;
 
@@ -859,7 +865,8 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
tbox = weston_transformed_rect(output_base->width,
   output_base->height,
   output_base->transform,
-  1, *box);
+  output_base->scale,
+  *box);
s->dest_x = tbox.x1;
s->dest_y = tbox.y1;
s->dest_w = tbox.x2 - tbox.x1;
@@ -896,7 +903,7 @@ drm_output_prepare_overlay_surface(struct weston_output 
*output_base,
 
tbox = weston_transformed_rect(wl_fixed_from_int(es->geometry.width),
   wl_fixed_from_int(es->geometry.height),
-  es->buffer_transform, 1, tbox);
+  es->buffer_transform, es->buffer_scale, 
tbox);
 
s->src_x = tbox.x1 << 8;
s->src_y = tbox.y1 << 8;
@@ -977,8 +984,8 @@ drm_output_set_cursor(struct drm_output *output)
}
}
 
-   x = es->geometry.x - output->base.x;
-   y = es->geometry.y - output->base.y;
+   x = (es->geometry.x - output->base.x) * output->base.scale;
+   y = (es->geometry.y - output->base.y) * output->base.scale;
if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
if (drmModeMoveCursor(c->drm.fd, output->crtc_id, x, y)) {
weston_log("failed to move cursor: %m\n");
@@ -1258,18 +1265,29 @@ init_pixman(struct drm_compositor *ec)
 }
 
 static struct drm_mode *
-drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
+drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info, struct 
drm_configured_output *config)
 {
struct drm_mode *mode;
uint64_t refresh;
+int scale;
 
mode = malloc(sizeof *mode);
if (mode == NULL)
return NULL;
 
+scale = 1;
+if (config)
+  scale = config->scale;
+
+   if (info->hdisplay % scale != 0 ||
+   info->vdisplay % scale) {
+   weston_log("Mode %dx%d not multiple of scale %d\n", 
info->hdisplay, info->vdisplay, scale);
+   return NULL;
+   }
+
mode->base.flags = 0;
-   mode->base.width = info->hdisplay;
-   mode->base.height = info->vdisplay;
+   mode->base.width = info->hdisplay / scale;
+   mode->base.height = info->vdisplay / scale;
 
/* Calculate higher precision (mHz) refresh rate */
refresh = (info->clock * 100LL / info->htotal +
@@ -1285,6 +1303,9 @@ drm_output_add_mode(struct drm_output *output, 
drmModeModeInfo *info)
mode->base.refresh = refresh;
mode->mode_info = *info;
 
+   if (scale != 1)
+   mode->base.flags |= WL_OUTPUT_MODE_SCALED;
+
if (info->type & DRM_MODE_TYPE_PREFERRED)
mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
 
@@ -1446,8 +1467,8 @@ drm_output_init_egl(struct drm_output *output, struct 
drm_compositor *ec)
int i, flags;
 
output->surface = gbm_surface_create(ec->gbm,
-output->base.current->width,
- 

[PATCH 0/4] Add version support to wl_resource

2013-05-23 Thread alexl
From: Alexander Larsson 

Unfortunately there seems to be no easy way to add a version
field to wl_resource in a compatible way, even if we are willing
to break the server library API for compositors, as the wl_resource
struct is embedded in a struct in the EGL code in mesa.

Here is a version that uses one of the two pointers in wl_resource.link
as a privat pointer allowing us to put extra info in the wl_resource.
This is an incompatible ABI/API change in the server libraries, as
anything using the wl_resource.link field need to be updated.

There is also a slight cost to this as removal from a singly linked list
is O(n) whereas it is O(1) on doubly linked list, but I don't expect
the wayland lists to become very long, so this is probably ok.

Alexander Larsson (4):
  Add single linked lists wl_slist similar to wl_list
  Convert wl_resource.link to a wl_slink
  wl_resource: Add a private field to wl_resource
  wl_resource: Add version field and getter/setter

 src/wayland-private.h |  4 
 src/wayland-server.c  | 50 +++---
 src/wayland-server.h  | 11 -
 src/wayland-util.c| 66 +++
 src/wayland-util.h| 24 +++
 5 files changed, 146 insertions(+), 9 deletions(-)

-- 
1.8.1.4

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


[PATCH 1/4] Add single linked lists wl_slist similar to wl_list

2013-05-23 Thread alexl
From: Alexander Larsson 

---
 src/wayland-util.c | 66 ++
 src/wayland-util.h | 24 
 2 files changed, 90 insertions(+)

diff --git a/src/wayland-util.c b/src/wayland-util.c
index 598ab42..c774a7e 100644
--- a/src/wayland-util.c
+++ b/src/wayland-util.c
@@ -89,6 +89,72 @@ wl_list_insert_list(struct wl_list *list, struct wl_list 
*other)
 }
 
 WL_EXPORT void
+wl_slist_init(struct wl_slist *list)
+{
+   list->next = list;
+}
+
+WL_EXPORT void
+wl_slist_insert(struct wl_slist *list, struct wl_slist *elm)
+{
+   elm->next = list->next;
+   list->next = elm;
+}
+
+WL_EXPORT void
+wl_slist_remove(struct wl_slist *list, struct wl_slist *elm)
+{
+   struct wl_slist *prev;
+
+   prev = list;
+   while (prev->next != elm && prev->next != list)
+   prev = prev->next;
+
+   if (prev->next == elm) {
+   prev->next = elm->next;
+   elm->next = NULL;
+   }
+}
+
+WL_EXPORT int
+wl_slist_length(const struct wl_slist *list)
+{
+   struct wl_slist *e;
+   int count;
+
+   count = 0;
+   e = list->next;
+   while (e != list) {
+   e = e->next;
+   count++;
+   }
+
+   return count;
+}
+
+WL_EXPORT int
+wl_slist_empty(const struct wl_slist *list)
+{
+   return list->next == list;
+}
+
+WL_EXPORT void
+wl_slist_insert_list(struct wl_slist *list, struct wl_slist *other)
+{
+   struct wl_slist *end;
+
+   if (wl_slist_empty(other))
+   return;
+
+   end = other;
+   while (end->next != other)
+   end = end->next;
+
+   end->next = list->next;
+   list->next = other->next;
+}
+
+WL_EXPORT void
 wl_array_init(struct wl_array *array)
 {
memset(array, 0, sizeof *array);
diff --git a/src/wayland-util.h b/src/wayland-util.h
index dbe05a5..40f2509 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -145,6 +145,30 @@ void wl_list_insert_list(struct wl_list *list, struct 
wl_list *other);
 pos = tmp, \
 tmp = wl_container_of(pos->member.prev, tmp, member))
 
+struct wl_slist {
+   struct wl_slist *next;
+};
+
+void wl_slist_init(struct wl_slist *list);
+void wl_slist_insert(struct wl_slist *list, struct wl_slist *elm);
+void wl_slist_remove(struct wl_slist *list, struct wl_slist *elm);
+int wl_slist_length(const struct wl_slist *list);
+int wl_slist_empty(const struct wl_slist *list);
+void wl_slist_insert_list(struct wl_slist *list, struct wl_slist *other);
+
+#define wl_slist_for_each(pos, head, member)   \
+   for (pos = 0, pos = wl_container_of((head)->next, pos, member); \
+&pos->member != (head);\
+pos = wl_container_of(pos->member.next, pos, member))
+
+#define wl_slist_for_each_safe(pos, tmp, head, member) \
+   for (pos = 0, tmp = 0,  \
+pos = wl_container_of((head)->next, pos, member),  \
+tmp = wl_container_of((pos)->member.next, tmp, member);\
+&pos->member != (head);\
+pos = tmp, \
+tmp = wl_container_of(pos->member.next, tmp, member))
+
 struct wl_array {
size_t size;
size_t alloc;
-- 
1.8.1.4

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


[PATCH 2/4] Convert wl_resource.link to a wl_slink

2013-05-23 Thread alexl
From: Alexander Larsson 

This lets us free up an extra pointer in wl_resource for other use.
---
 src/wayland-server.c | 17 ++---
 src/wayland-server.h |  3 ++-
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index a3d3887..f1a6aac 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -86,7 +86,7 @@ struct wl_display {
uint32_t id;
uint32_t serial;
 
-   struct wl_list registry_resource_list;
+   struct wl_slist registry_resource_list;
struct wl_list global_list;
struct wl_list socket_list;
struct wl_list client_list;
@@ -513,7 +513,10 @@ display_sync(struct wl_client *client,
 static void
 unbind_resource(struct wl_resource *resource)
 {
-   wl_list_remove(&resource->link);
+   struct wl_display *display = resource->data;
+
+   wl_slist_remove(&display->registry_resource_list,
+   &resource->link);
free(resource);
 }
 
@@ -530,8 +533,8 @@ display_get_registry(struct wl_client *client,
 ®istry_interface, id, display);
registry_resource->destroy = unbind_resource;
 
-   wl_list_insert(&display->registry_resource_list,
-  ®istry_resource->link);
+   wl_slist_insert(&display->registry_resource_list,
+   ®istry_resource->link);
 
wl_list_for_each(global, &display->global_list, link)
wl_resource_post_event(registry_resource,
@@ -590,7 +593,7 @@ wl_display_create(void)
wl_list_init(&display->global_list);
wl_list_init(&display->socket_list);
wl_list_init(&display->client_list);
-   wl_list_init(&display->registry_resource_list);
+   wl_slist_init(&display->registry_resource_list);
 
wl_signal_init(&display->destroy_signal);
 
@@ -649,7 +652,7 @@ wl_display_add_global(struct wl_display *display,
global->bind = bind;
wl_list_insert(display->global_list.prev, &global->link);
 
-   wl_list_for_each(resource, &display->registry_resource_list, link)
+   wl_slist_for_each(resource, &display->registry_resource_list, link)
wl_resource_post_event(resource,
   WL_REGISTRY_GLOBAL,
   global->name,
@@ -664,7 +667,7 @@ wl_display_remove_global(struct wl_display *display, struct 
wl_global *global)
 {
struct wl_resource *resource;
 
-   wl_list_for_each(resource, &display->registry_resource_list, link)
+   wl_slist_for_each(resource, &display->registry_resource_list, link)
wl_resource_post_event(resource, WL_REGISTRY_GLOBAL_REMOVE,
   global->name);
wl_list_remove(&global->link);
diff --git a/src/wayland-server.h b/src/wayland-server.h
index a9cf544..4867652 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -180,7 +180,8 @@ wl_signal_emit(struct wl_signal *signal, void *data)
 struct wl_resource {
struct wl_object object;
void (*destroy)(struct wl_resource *resource);
-   struct wl_list link;
+   struct wl_slist link;
+   void *reserved;
struct wl_signal destroy_signal;
struct wl_client *client;
void *data;
-- 
1.8.1.4

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


[PATCH 3/4] wl_resource: Add a private field to wl_resource

2013-05-23 Thread alexl
From: Alexander Larsson 

This takes the place of the second pointer in the old wl_list and
lets us add more fields to wl_resource in a backwards compat fashion.
---
 src/wayland-private.h |  4 
 src/wayland-server.c  | 17 -
 src/wayland-server.h  |  4 +++-
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/src/wayland-private.h b/src/wayland-private.h
index c4ce6b0..105f9b9 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -47,6 +47,10 @@ struct wl_map {
uint32_t free_list;
 };
 
+struct wl_resource_private {
+   uint32_t dummy;
+};
+
 typedef void (*wl_iterator_func_t)(void *element, void *data);
 
 void wl_map_init(struct wl_map *map);
diff --git a/src/wayland-server.c b/src/wayland-server.c
index f1a6aac..e3a0376 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -377,6 +377,14 @@ WL_EXPORT uint32_t
 wl_client_add_resource(struct wl_client *client,
   struct wl_resource *resource)
 {
+   struct wl_resource_private *priv;
+
+   priv = calloc(1, sizeof(struct wl_resource_private));
+   if (!priv) {
+   wl_resource_post_no_memory(resource);
+   return 0;
+   }
+
if (resource->object.id == 0) {
resource->object.id =
wl_map_insert_new(&client->objects,
@@ -387,9 +395,11 @@ wl_client_add_resource(struct wl_client *client,
   WL_DISPLAY_ERROR_INVALID_OBJECT,
   "invalid new id %d",
   resource->object.id);
+   free(priv);
return 0;
}
 
+   resource->priv = priv;
resource->client = client;
wl_signal_init(&resource->destroy_signal);
 
@@ -413,11 +423,15 @@ static void
 destroy_resource(void *element, void *data)
 {
struct wl_resource *resource = element;
+   struct wl_resource_private *resource_priv = resource->priv;
 
wl_signal_emit(&resource->destroy_signal, resource);
 
if (resource->destroy)
resource->destroy(resource);
+
+   if (resource_priv != (struct wl_resource_private *)(resource + 1))
+   free (resource_priv);
 }
 
 WL_EXPORT void
@@ -906,13 +920,14 @@ wl_client_add_object(struct wl_client *client,
 {
struct wl_resource *resource;
 
-   resource = malloc(sizeof *resource);
+   resource = malloc(sizeof *resource + sizeof (struct 
wl_resource_private));
if (resource == NULL) {
wl_resource_post_no_memory(client->display_resource);
return NULL;
}
 
wl_resource_init(resource, interface, implementation, id, data);
+   resource->priv = (struct wl_resource_private *)(resource + 1);
resource->client = client;
resource->destroy = (void *) free;
 
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 4867652..3ac0351 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -177,11 +177,13 @@ wl_signal_emit(struct wl_signal *signal, void *data)
l->notify(l, data);
 }
 
+struct wl_resource_private;
+
 struct wl_resource {
struct wl_object object;
void (*destroy)(struct wl_resource *resource);
struct wl_slist link;
-   void *reserved;
+   struct wl_resource_private *priv;
struct wl_signal destroy_signal;
struct wl_client *client;
void *data;
-- 
1.8.1.4

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


[PATCH 4/4] wl_resource: Add version field and getter/setter

2013-05-23 Thread alexl
From: Alexander Larsson 

This lets us track the actual version of a resource which
is generally the min of what the client requested and what
the server supports. This will let us avoid sending messages
the client doesn't support and to not handle requests the
server doesn't support.
---
 src/wayland-private.h |  2 +-
 src/wayland-server.c  | 16 
 src/wayland-server.h  |  6 ++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/src/wayland-private.h b/src/wayland-private.h
index 105f9b9..b184309 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -48,7 +48,7 @@ struct wl_map {
 };
 
 struct wl_resource_private {
-   uint32_t dummy;
+   uint32_t version;
 };
 
 typedef void (*wl_iterator_func_t)(void *element, void *data);
diff --git a/src/wayland-server.c b/src/wayland-server.c
index e3a0376..c7a5e1d 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -401,6 +401,7 @@ wl_client_add_resource(struct wl_client *client,
 
resource->priv = priv;
resource->client = client;
+   resource->priv->version = 1;
wl_signal_init(&resource->destroy_signal);
 
return resource->object.id;
@@ -912,6 +913,20 @@ wl_display_get_destroy_listener(struct wl_display *display,
return wl_signal_get(&display->destroy_signal, notify);
 }
 
+WL_EXPORT void
+wl_resource_set_version(struct wl_resource *resource,
+   uint32_t version)
+{
+   resource->priv->version = version;
+}
+
+WL_EXPORT uint32_t
+wl_resource_get_version(struct wl_resource *resource)
+{
+   return resource->priv->version;
+}
+
+
 WL_EXPORT struct wl_resource *
 wl_client_add_object(struct wl_client *client,
 const struct wl_interface *interface,
@@ -930,6 +945,7 @@ wl_client_add_object(struct wl_client *client,
resource->priv = (struct wl_resource_private *)(resource + 1);
resource->client = client;
resource->destroy = (void *) free;
+   resource->priv->version = 1;
 
if (wl_map_insert_at(&client->objects, resource->object.id, resource) < 
0) {
wl_resource_post_error(client->display_resource,
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 3ac0351..22b845c 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -135,6 +135,12 @@ wl_client_new_object(struct wl_client *client,
 struct wl_resource *
 wl_client_get_object(struct wl_client *client, uint32_t id);
 
+void
+wl_resource_set_version(struct wl_resource *resource,
+   uint32_t version);
+uint32_t
+wl_resource_get_version(struct wl_resource *resource);
+
 struct wl_listener {
struct wl_list link;
wl_notify_func_t notify;
-- 
1.8.1.4

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


[PATCH 0/3] Do proper version negotiation

2013-05-23 Thread alexl
From: Alexander Larsson 

This initializes the new version field of wl_resource to the
negotiated value (i.e. the min of the requested version and the
version supported by weston).

Alexander Larsson (3):
  Update wl_resource.link to wl_slist due to wayland change
  Add MIN() macro
  compositor/shell: Set version on all wl_resources

 src/compositor.c  | 34 +++---
 src/compositor.h  | 16 --
 src/data-device.c | 10 +
 src/input.c   | 62 +++
 src/shell.c   | 11 ++
 5 files changed, 94 insertions(+), 39 deletions(-)

-- 
1.8.1.4

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


[PATCH 1/3] Update wl_resource.link to wl_slist due to wayland change

2013-05-23 Thread alexl
From: Alexander Larsson 

---
 src/compositor.c  | 12 ++-
 src/compositor.h  | 12 +--
 src/data-device.c | 10 +
 src/input.c   | 62 +++
 src/shell.c   | 10 +
 5 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 02e79e6..13a6f47 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -505,11 +505,11 @@ weston_surface_damage_below(struct weston_surface 
*surface)
 }
 
 static struct wl_resource *
-find_resource_for_client(struct wl_list *list, struct wl_client *client)
+find_resource_for_client(struct wl_slist *list, struct wl_client *client)
 {
 struct wl_resource *r;
 
-wl_list_for_each(r, list, link) {
+wl_slist_for_each(r, list, link) {
 if (r->client == client)
 return r;
 }
@@ -2494,7 +2494,9 @@ weston_compositor_stack_plane(struct weston_compositor 
*ec,
 
 static void unbind_resource(struct wl_resource *resource)
 {
-   wl_list_remove(&resource->link);
+   struct weston_output *output = resource->data;
+
+   wl_slist_remove(&output->resource_list, &resource->link);
free(resource);
 }
 
@@ -2509,7 +2511,7 @@ bind_output(struct wl_client *client,
resource = wl_client_add_object(client,
&wl_output_interface, NULL, id, data);
 
-   wl_list_insert(&output->resource_list, &resource->link);
+   wl_slist_insert(&output->resource_list, &resource->link);
resource->destroy = unbind_resource;
 
wl_output_send_geometry(resource,
@@ -2712,7 +2714,7 @@ weston_output_init(struct weston_output *output, struct 
weston_compositor *c,
wl_signal_init(&output->frame_signal);
wl_signal_init(&output->destroy_signal);
wl_list_init(&output->animation_list);
-   wl_list_init(&output->resource_list);
+   wl_slist_init(&output->resource_list);
 
output->id = ffs(~output->compositor->output_id_pool) - 1;
output->compositor->output_id_pool |= 1 << output->id;
diff --git a/src/compositor.h b/src/compositor.h
index 06476cc..176b501 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -161,7 +161,7 @@ struct weston_output {
void *renderer_state;
 
struct wl_list link;
-   struct wl_list resource_list;
+   struct wl_slist resource_list;
struct wl_global *global;
struct weston_compositor *compositor;
struct weston_matrix matrix;
@@ -279,7 +279,7 @@ struct wl_data_source {
 struct weston_pointer {
struct weston_seat *seat;
 
-   struct wl_list resource_list;
+   struct wl_slist resource_list;
struct weston_surface *focus;
struct wl_resource *focus_resource;
struct wl_listener focus_listener;
@@ -305,7 +305,7 @@ struct weston_pointer {
 struct weston_touch {
struct weston_seat *seat;
 
-   struct wl_list resource_list;
+   struct wl_slist resource_list;
struct weston_surface *focus;
struct wl_resource *focus_resource;
struct wl_listener focus_listener;
@@ -388,7 +388,7 @@ struct weston_xkb_info {
 struct weston_keyboard {
struct weston_seat *seat;
 
-   struct wl_list resource_list;
+   struct wl_slist resource_list;
struct weston_surface *focus;
struct wl_resource *focus_resource;
struct wl_listener focus_listener;
@@ -415,7 +415,7 @@ struct weston_keyboard {
 };
 
 struct weston_seat {
-   struct wl_list base_resource_list;
+   struct wl_slist base_resource_list;
 
struct weston_pointer *pointer;
struct weston_keyboard *keyboard;
@@ -428,7 +428,7 @@ struct weston_seat {
enum weston_keyboard_modifier modifier_state;
struct weston_surface *saved_kbd_focus;
struct wl_listener saved_kbd_focus_listener;
-   struct wl_list drag_resource_list;
+   struct wl_slist drag_resource_list;
 
uint32_t selection_serial;
struct wl_data_source *selection_data_source;
diff --git a/src/data-device.c b/src/data-device.c
index 0decbb9..9dc988f 100644
--- a/src/data-device.c
+++ b/src/data-device.c
@@ -163,11 +163,11 @@ static struct wl_data_source_interface 
data_source_interface = {
 };
 
 static struct wl_resource *
-find_resource(struct wl_list *list, struct wl_client *client)
+find_resource(struct wl_slist *list, struct wl_client *client)
 {
struct wl_resource *r;
 
-   wl_list_for_each(r, list, link) {
+   wl_slist_for_each(r, list, link) {
if (r->client == client)
return r;
}
@@ -563,7 +563,9 @@ create_data_source(struct wl_client *client,
 
 static void unbind_data_device(struct wl_resource *resource)
 {
-   wl_list_remove(&resource->link);
+   struct weston_seat *seat = resource->data;
+
+   wl_slist_remove(&seat->drag_resource_list, &resource->link);
free(resource);
 }
 
@@ -

[PATCH 2/3] Add MIN() macro

2013-05-23 Thread alexl
From: Alexander Larsson 

This will be needed for the version negotiation
---
 src/compositor.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/src/compositor.h b/src/compositor.h
index 176b501..5ddbc95 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -36,6 +36,10 @@ extern "C" {
 #include "matrix.h"
 #include "config-parser.h"
 
+#ifndef MIN
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+#endif
+
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 
 #define container_of(ptr, type, member) ({ \
-- 
1.8.1.4

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


[PATCH 3/3] compositor/shell: Set version on all wl_resources

2013-05-23 Thread alexl
From: Alexander Larsson 

A few wl_resources have version != 1, we need to set this based
on the supported version and the client requested version.
---
 src/compositor.c | 22 --
 src/shell.c  |  1 +
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 13a6f47..1e27d51 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1671,6 +1671,21 @@ compositor_create_surface(struct wl_client *client,
surface->resource.data = surface;
 
wl_client_add_resource(client, &surface->resource);
+
+   /* The surface version depends on the requested compositor version, as
+  that is the only way to negotiate surface versions */
+   switch (wl_resource_get_version (resource)) {
+   case 1:
+ wl_resource_set_version (&surface->resource, 1);
+ break;
+   case 2:
+ wl_resource_set_version (&surface->resource, 2);
+ break;
+   case 3:
+   default:
+ wl_resource_set_version (&surface->resource, 3);
+ break;
+   }
 }
 
 static void
@@ -2510,6 +2525,7 @@ bind_output(struct wl_client *client,
 
resource = wl_client_add_object(client,
&wl_output_interface, NULL, id, data);
+   wl_resource_set_version (resource, MIN(version, 2));
 
wl_slist_insert(&output->resource_list, &resource->link);
resource->destroy = unbind_resource;
@@ -2730,9 +2746,11 @@ compositor_bind(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
 {
struct weston_compositor *compositor = data;
+   struct wl_resource *resource;
 
-   wl_client_add_object(client, &wl_compositor_interface,
-&compositor_interface, id, compositor);
+   resource = wl_client_add_object(client, &wl_compositor_interface,
+   &compositor_interface, id, compositor);
+   wl_resource_set_version (resource, MIN(version, 3));
 }
 
 static void
diff --git a/src/shell.c b/src/shell.c
index dc7cd05..1e42d6b 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -3582,6 +3582,7 @@ bind_desktop_shell(struct wl_client *client,
resource = wl_client_add_object(client, &desktop_shell_interface,
&desktop_shell_implementation,
id, shell);
+   wl_resouce_set_version (resource, MIN(version, 2));
 
if (client == shell->child.client) {
resource->destroy = unbind_desktop_shell;
-- 
1.8.1.4

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


[PATCH] Add version support to wl_resource

2013-05-23 Thread alexl
From: Alexander Larsson 

New simpler version that uses a destroy notify to stash away
the private pointer.

Alexander Larsson (1):
  wl_resource: Add version field and getter/setter

 src/wayland-server.c | 58 +++-
 src/wayland-server.h |  6 ++
 2 files changed, 63 insertions(+), 1 deletion(-)

-- 
1.8.1.4

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


[PATCH] wl_resource: Add version field and getter/setter

2013-05-23 Thread alexl
From: Alexander Larsson 

We create a private structure for extra data and store it in
a destroy notifier. In this way we can store the version
in a backwards compatible way.

This lets us track the actual version of a resource which
is generally the min of what the client requested and what
the server supports. This will let us avoid sending messages
the client doesn't support and to not handle requests the
server doesn't support.
---
 src/wayland-server.c | 58 +++-
 src/wayland-server.h |  6 ++
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index a3d3887..c808f6a 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -102,6 +102,11 @@ struct wl_global {
struct wl_list link;
 };
 
+struct wl_resource_private {
+   struct wl_listener listener;
+   uint32_t version;
+};
+
 static int wl_debug = 0;
 
 static void
@@ -377,6 +382,14 @@ WL_EXPORT uint32_t
 wl_client_add_resource(struct wl_client *client,
   struct wl_resource *resource)
 {
+   struct wl_resource_private *priv;
+
+   priv = calloc(1, sizeof(struct wl_resource_private));
+   if (!priv) {
+   wl_resource_post_no_memory(resource);
+   return 0;
+   }
+
if (resource->object.id == 0) {
resource->object.id =
wl_map_insert_new(&client->objects,
@@ -387,12 +400,18 @@ wl_client_add_resource(struct wl_client *client,
   WL_DISPLAY_ERROR_INVALID_OBJECT,
   "invalid new id %d",
   resource->object.id);
+   free(priv);
return 0;
}
 
resource->client = client;
wl_signal_init(&resource->destroy_signal);
 
+   priv->listener.notify = (wl_notify_func_t)free;
+   wl_signal_add(&resource->destroy_signal, &priv->listener);
+
+   priv->version = 1;
+
return resource->object.id;
 }
 
@@ -895,6 +914,35 @@ wl_display_get_destroy_listener(struct wl_display *display,
return wl_signal_get(&display->destroy_signal, notify);
 }
 
+static struct wl_resource_private *
+wl_resource_get_priv (struct wl_resource *resource)
+{
+   /* The priv pointer is always the notify handler */
+   return (struct wl_resource_private 
*)resource->destroy_signal.listener_list.next;
+}
+
+WL_EXPORT void
+wl_resource_set_version(struct wl_resource *resource,
+   uint32_t version)
+{
+   struct wl_resource_private *priv = wl_resource_get_priv (resource);
+
+   priv->version = version;
+}
+
+WL_EXPORT uint32_t
+wl_resource_get_version(struct wl_resource *resource)
+{
+   struct wl_resource_private *priv = wl_resource_get_priv (resource);
+
+   return priv->version;
+}
+
+static void
+dummy_notify(struct wl_listener *listener, void *data)
+{
+}
+
 WL_EXPORT struct wl_resource *
 wl_client_add_object(struct wl_client *client,
 const struct wl_interface *interface,
@@ -902,8 +950,9 @@ wl_client_add_object(struct wl_client *client,
 uint32_t id, void *data)
 {
struct wl_resource *resource;
+   struct wl_resource_private *priv;
 
-   resource = malloc(sizeof *resource);
+   resource = malloc(sizeof *resource + sizeof (struct 
wl_resource_private));
if (resource == NULL) {
wl_resource_post_no_memory(client->display_resource);
return NULL;
@@ -913,6 +962,13 @@ wl_client_add_object(struct wl_client *client,
resource->client = client;
resource->destroy = (void *) free;
 
+   priv = (struct wl_resource_private *)(resource + 1);
+
+   priv->listener.notify = dummy_notify;
+   wl_signal_add(&resource->destroy_signal, &priv->listener);
+
+   priv->version = 1;
+
if (wl_map_insert_at(&client->objects, resource->object.id, resource) < 
0) {
wl_resource_post_error(client->display_resource,
   WL_DISPLAY_ERROR_INVALID_OBJECT,
diff --git a/src/wayland-server.h b/src/wayland-server.h
index a9cf544..6beb0dd 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -135,6 +135,12 @@ wl_client_new_object(struct wl_client *client,
 struct wl_resource *
 wl_client_get_object(struct wl_client *client, uint32_t id);
 
+void
+wl_resource_set_version(struct wl_resource *resource,
+   uint32_t version);
+uint32_t
+wl_resource_get_version(struct wl_resource *resource);
+
 struct wl_listener {
struct wl_list link;
wl_notify_func_t notify;
-- 
1.8.1.4

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


[PATCH 0/2] Do proper version negotiation V2

2013-05-23 Thread alexl
From: Alexander Larsson 

This initializes the new version field of wl_resource to the
negotiated value (i.e. the min of the requested version and the
version supported by weston).

Alexander Larsson (2):
  Add MIN() macro
  compositor/shell: Set version on all wl_resources

 src/compositor.c | 22 --
 src/compositor.h |  4 
 src/shell.c  |  1 +
 3 files changed, 25 insertions(+), 2 deletions(-)

-- 
1.8.1.4

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


[PATCH 1/2] Add MIN() macro

2013-05-23 Thread alexl
From: Alexander Larsson 

This will be needed for the version negotiation
---
 src/compositor.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/src/compositor.h b/src/compositor.h
index 06476cc..8f96016 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -36,6 +36,10 @@ extern "C" {
 #include "matrix.h"
 #include "config-parser.h"
 
+#ifndef MIN
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+#endif
+
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 
 #define container_of(ptr, type, member) ({ \
-- 
1.8.1.4

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


[PATCH 2/2] compositor/shell: Set version on all wl_resources

2013-05-23 Thread alexl
From: Alexander Larsson 

A few wl_resources have version != 1, we need to set this based
on the supported version and the client requested version.
---
 src/compositor.c | 22 --
 src/shell.c  |  1 +
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 02e79e6..9df4014 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1671,6 +1671,21 @@ compositor_create_surface(struct wl_client *client,
surface->resource.data = surface;
 
wl_client_add_resource(client, &surface->resource);
+
+   /* The surface version depends on the requested compositor version, as
+  that is the only way to negotiate surface versions */
+   switch (wl_resource_get_version (resource)) {
+   case 1:
+ wl_resource_set_version (&surface->resource, 1);
+ break;
+   case 2:
+ wl_resource_set_version (&surface->resource, 2);
+ break;
+   case 3:
+   default:
+ wl_resource_set_version (&surface->resource, 3);
+ break;
+   }
 }
 
 static void
@@ -2508,6 +2523,7 @@ bind_output(struct wl_client *client,
 
resource = wl_client_add_object(client,
&wl_output_interface, NULL, id, data);
+   wl_resource_set_version (resource, MIN(version, 2));
 
wl_list_insert(&output->resource_list, &resource->link);
resource->destroy = unbind_resource;
@@ -2728,9 +2744,11 @@ compositor_bind(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
 {
struct weston_compositor *compositor = data;
+   struct wl_resource *resource;
 
-   wl_client_add_object(client, &wl_compositor_interface,
-&compositor_interface, id, compositor);
+   resource = wl_client_add_object(client, &wl_compositor_interface,
+   &compositor_interface, id, compositor);
+   wl_resource_set_version (resource, MIN(version, 3));
 }
 
 static void
diff --git a/src/shell.c b/src/shell.c
index eb8d802..12f6b5e 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -3580,6 +3580,7 @@ bind_desktop_shell(struct wl_client *client,
resource = wl_client_add_object(client, &desktop_shell_interface,
&desktop_shell_implementation,
id, shell);
+   wl_resource_set_version (resource, MIN(version, 2));
 
if (client == shell->child.client) {
resource->destroy = unbind_desktop_shell;
-- 
1.8.1.4

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


[PATCH] wayland-server: Version check requests

2013-05-23 Thread alexl
From: Alexander Larsson 

If an interface has any messages and its version is larger than 1
then we emit a method counts array which lists the number of methods
for each version of the interface. This can be used in addition
to the normal method_count to reject requests that the
server doesn't support. This allows the wayland server library
to be upgraded and still safely run oler compositors that don't
implement the new requests.

Since there is no other space in the wm_interface we add the
method count array at the end of the events array. We then
add some warnings to the event sending code so that we never
accidentally trigger these events.

Then we add code in the server to reject messages that are not
supported by the server version of the object they are sent to.
---
 src/scanner.c| 54 ++--
 src/wayland-server.c | 34 +++--
 2 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/src/scanner.c b/src/scanner.c
index 9c14ad3..38e7909 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -1019,12 +1019,13 @@ emit_types(struct protocol *protocol, struct wl_list 
*message_list)
 
 static void
 emit_messages(struct wl_list *message_list,
- struct interface *interface, const char *suffix)
+ struct interface *interface, const char *suffix,
+ int emit_method_counts)
 {
struct message *m;
struct arg *a;
 
-   if (wl_list_empty(message_list))
+   if (wl_list_empty(message_list) && !emit_method_counts)
return;
 
printf("static const struct wl_message "
@@ -1070,13 +1071,52 @@ emit_messages(struct wl_list *message_list,
printf("\", types + %d },\n", m->type_index);
}
 
+   if (emit_method_counts) {
+   printf("\t{ NULL, \"\", (void *)%s_method_counts },\n", 
interface->name);
+   }
+
+   printf("};\n\n");
+}
+
+static int
+emit_method_counts(struct wl_list *message_list,
+  struct interface *interface)
+{
+   struct message *m;
+   int version = 1;
+   int count;
+
+   if (wl_list_empty(message_list) || interface->version == 1)
+   return 0;
+
+   printf("static const uint32_t "
+  "%s_method_counts[] = { ",
+  interface->name);
+
+   count = 0;
+   wl_list_for_each(m, message_list, link) {
+   while (m->since != version) {
+   printf("%d,", count);
+   version++;
+   }
+   count++;
+   }
+
+   while (version <= interface->version) {
+   printf("%d, ", count);
+   version++;
+   }
+
printf("};\n\n");
+
+   return 1;
 }
 
 static void
 emit_code(struct protocol *protocol)
 {
struct interface *i;
+   int has_method_counts;
 
if (protocol->copyright)
format_copyright(protocol->copyright);
@@ -1101,8 +1141,10 @@ emit_code(struct protocol *protocol)
 
wl_list_for_each(i, &protocol->interface_list, link) {
 
-   emit_messages(&i->request_list, i, "requests");
-   emit_messages(&i->event_list, i, "events");
+
+   emit_messages(&i->request_list, i, "requests", 0);
+   has_method_counts = emit_method_counts(&i->request_list, i);
+   emit_messages(&i->event_list, i, "events", has_method_counts);
 
printf("WL_EXPORT const struct wl_interface "
   "%s_interface = {\n"
@@ -1115,9 +1157,9 @@ emit_code(struct protocol *protocol)
else
printf("\t0, NULL,\n");
 
-   if (!wl_list_empty(&i->event_list))
+   if (!wl_list_empty(&i->event_list) || has_method_counts)
printf("\t%d, %s_events,\n",
-  wl_list_length(&i->event_list), i->name);
+  wl_list_length(&i->event_list) + 
has_method_counts, i->name);
else
printf("\t0, NULL,\n");
 
diff --git a/src/wayland-server.c b/src/wayland-server.c
index c808f6a..e94366b 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -124,6 +124,12 @@ wl_resource_post_event(struct wl_resource *resource, 
uint32_t opcode, ...)
struct wl_object *object = &resource->object;
va_list ap;
 
+   if (opcode >= (uint32_t)object->interface->event_count ||
+   object->interface->events[opcode].name == NULL) {
+   wl_log ("Trying to post unsupported event\n");
+   return;
+   }
+
va_start(ap, opcode);
closure = wl_closure_vmarshal(object, opcode, ap,
  &object->interface->events[opcode]);
@@ -150,6 +156,12 @@ wl_resource_queue_event(struct wl_resource *resource, 
uint32_t opcode, ...)
struct wl_object *object = &resource->object;
va_list ap;
 
+   

[PATCH 0/2] resource versioning V3

2013-05-24 Thread alexl
From: Alexander Larsson 

New in this version:
* We look up the private with wl_signal_get
* Fixed off-by-one error in method_counts array lookup
  (version 1 is at offset 0)

Alexander Larsson (2):
  wl_resource: Add version field and getter/setter
  wayland-server: Version check requests

 src/scanner.c|  54 
 src/wayland-server.c | 100 +--
 src/wayland-server.h |   6 
 3 files changed, 151 insertions(+), 9 deletions(-)

-- 
1.8.1.4

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


[PATCH 1/2] wl_resource: Add version field and getter/setter

2013-05-24 Thread alexl
From: Alexander Larsson 

We create a private structure for extra data and store it in
a destroy notifier. In this way we can store the version
in a backwards compatible way.

This lets us track the actual version of a resource which
is generally the min of what the client requested and what
the server supports. This will let us avoid sending messages
the client doesn't support and to not handle requests the
server doesn't support.
---
 src/wayland-server.c | 66 +++-
 src/wayland-server.h |  6 +
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index a3d3887..4604008 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -102,6 +102,11 @@ struct wl_global {
struct wl_list link;
 };
 
+struct wl_resource_private {
+   struct wl_listener listener;
+   uint32_t version;
+};
+
 static int wl_debug = 0;
 
 static void
@@ -373,10 +378,28 @@ wl_client_get_credentials(struct wl_client *client,
*gid = client->ucred.gid;
 }
 
+static void
+resource_private_notify(struct wl_listener *listener, void *data)
+{
+   struct wl_resource *resource = data;
+   struct wl_resource_private *priv = (struct wl_resource_private 
*)listener;
+
+   if (priv != (struct wl_resource_private *)(resource + 1))
+   free (priv);
+}
+
 WL_EXPORT uint32_t
 wl_client_add_resource(struct wl_client *client,
   struct wl_resource *resource)
 {
+   struct wl_resource_private *priv;
+
+   priv = calloc(1, sizeof(struct wl_resource_private));
+   if (!priv) {
+   wl_resource_post_no_memory(resource);
+   return 0;
+   }
+
if (resource->object.id == 0) {
resource->object.id =
wl_map_insert_new(&client->objects,
@@ -387,12 +410,18 @@ wl_client_add_resource(struct wl_client *client,
   WL_DISPLAY_ERROR_INVALID_OBJECT,
   "invalid new id %d",
   resource->object.id);
+   free(priv);
return 0;
}
 
resource->client = client;
wl_signal_init(&resource->destroy_signal);
 
+   priv->listener.notify = resource_private_notify;
+   wl_signal_add(&resource->destroy_signal, &priv->listener);
+
+   priv->version = 1;
+
return resource->object.id;
 }
 
@@ -895,6 +924,33 @@ wl_display_get_destroy_listener(struct wl_display *display,
return wl_signal_get(&display->destroy_signal, notify);
 }
 
+static struct wl_resource_private *
+wl_resource_get_priv (struct wl_resource *resource)
+{
+   return (struct wl_resource_private *)
+   wl_signal_get(&resource->destroy_signal, 
resource_private_notify);
+}
+
+WL_EXPORT void
+wl_resource_set_version(struct wl_resource *resource,
+   uint32_t version)
+{
+   struct wl_resource_private *priv = wl_resource_get_priv (resource);
+
+   /* We don't want anything to set this to 0, as that will cause us
+  to look before the start of the method_counts array */
+   if (version >= 1)
+   priv->version = version;
+}
+
+WL_EXPORT uint32_t
+wl_resource_get_version(struct wl_resource *resource)
+{
+   struct wl_resource_private *priv = wl_resource_get_priv (resource);
+
+   return priv->version;
+}
+
 WL_EXPORT struct wl_resource *
 wl_client_add_object(struct wl_client *client,
 const struct wl_interface *interface,
@@ -902,8 +958,9 @@ wl_client_add_object(struct wl_client *client,
 uint32_t id, void *data)
 {
struct wl_resource *resource;
+   struct wl_resource_private *priv;
 
-   resource = malloc(sizeof *resource);
+   resource = malloc(sizeof *resource + sizeof (struct 
wl_resource_private));
if (resource == NULL) {
wl_resource_post_no_memory(client->display_resource);
return NULL;
@@ -913,6 +970,13 @@ wl_client_add_object(struct wl_client *client,
resource->client = client;
resource->destroy = (void *) free;
 
+   priv = (struct wl_resource_private *)(resource + 1);
+
+   priv->listener.notify = resource_private_notify;
+   wl_signal_add(&resource->destroy_signal, &priv->listener);
+
+   priv->version = 1;
+
if (wl_map_insert_at(&client->objects, resource->object.id, resource) < 
0) {
wl_resource_post_error(client->display_resource,
   WL_DISPLAY_ERROR_INVALID_OBJECT,
diff --git a/src/wayland-server.h b/src/wayland-server.h
index a9cf544..6beb0dd 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -135,6 +135,12 @@ wl_client_new_object(struct wl_client *client,
 struct wl_resource *
 wl_client_get_object(struct wl_client *client, uint32_t id);
 
+void
+wl_resource_set_version(struct wl_resource *

[PATCH 2/2] wayland-server: Version check requests

2013-05-24 Thread alexl
From: Alexander Larsson 

If an interface has any messages and its version is larger than 1
then we emit a method counts array which lists the number of methods
for each version of the interface. This can be used in addition
to the normal method_count to reject requests that the
server doesn't support. This allows the wayland server library
to be upgraded and still safely run oler compositors that don't
implement the new requests.

Since there is no other space in the wm_interface we add the
method count array at the end of the events array. We then
add some warnings to the event sending code so that we never
accidentally trigger these events.

Then we add code in the server to reject messages that are not
supported by the server version of the object they are sent to.
---
 src/scanner.c| 54 ++--
 src/wayland-server.c | 34 +++--
 2 files changed, 80 insertions(+), 8 deletions(-)

diff --git a/src/scanner.c b/src/scanner.c
index 9c14ad3..38e7909 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -1019,12 +1019,13 @@ emit_types(struct protocol *protocol, struct wl_list 
*message_list)
 
 static void
 emit_messages(struct wl_list *message_list,
- struct interface *interface, const char *suffix)
+ struct interface *interface, const char *suffix,
+ int emit_method_counts)
 {
struct message *m;
struct arg *a;
 
-   if (wl_list_empty(message_list))
+   if (wl_list_empty(message_list) && !emit_method_counts)
return;
 
printf("static const struct wl_message "
@@ -1070,13 +1071,52 @@ emit_messages(struct wl_list *message_list,
printf("\", types + %d },\n", m->type_index);
}
 
+   if (emit_method_counts) {
+   printf("\t{ NULL, \"\", (void *)%s_method_counts },\n", 
interface->name);
+   }
+
+   printf("};\n\n");
+}
+
+static int
+emit_method_counts(struct wl_list *message_list,
+  struct interface *interface)
+{
+   struct message *m;
+   int version = 1;
+   int count;
+
+   if (wl_list_empty(message_list) || interface->version == 1)
+   return 0;
+
+   printf("static const uint32_t "
+  "%s_method_counts[] = { ",
+  interface->name);
+
+   count = 0;
+   wl_list_for_each(m, message_list, link) {
+   while (m->since != version) {
+   printf("%d,", count);
+   version++;
+   }
+   count++;
+   }
+
+   while (version <= interface->version) {
+   printf("%d, ", count);
+   version++;
+   }
+
printf("};\n\n");
+
+   return 1;
 }
 
 static void
 emit_code(struct protocol *protocol)
 {
struct interface *i;
+   int has_method_counts;
 
if (protocol->copyright)
format_copyright(protocol->copyright);
@@ -1101,8 +1141,10 @@ emit_code(struct protocol *protocol)
 
wl_list_for_each(i, &protocol->interface_list, link) {
 
-   emit_messages(&i->request_list, i, "requests");
-   emit_messages(&i->event_list, i, "events");
+
+   emit_messages(&i->request_list, i, "requests", 0);
+   has_method_counts = emit_method_counts(&i->request_list, i);
+   emit_messages(&i->event_list, i, "events", has_method_counts);
 
printf("WL_EXPORT const struct wl_interface "
   "%s_interface = {\n"
@@ -1115,9 +1157,9 @@ emit_code(struct protocol *protocol)
else
printf("\t0, NULL,\n");
 
-   if (!wl_list_empty(&i->event_list))
+   if (!wl_list_empty(&i->event_list) || has_method_counts)
printf("\t%d, %s_events,\n",
-  wl_list_length(&i->event_list), i->name);
+  wl_list_length(&i->event_list) + 
has_method_counts, i->name);
else
printf("\t0, NULL,\n");
 
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 4604008..a82707a 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -124,6 +124,12 @@ wl_resource_post_event(struct wl_resource *resource, 
uint32_t opcode, ...)
struct wl_object *object = &resource->object;
va_list ap;
 
+   if (opcode >= (uint32_t)object->interface->event_count ||
+   object->interface->events[opcode].name == NULL) {
+   wl_log ("Trying to post unsupported event\n");
+   return;
+   }
+
va_start(ap, opcode);
closure = wl_closure_vmarshal(object, opcode, ap,
  &object->interface->events[opcode]);
@@ -150,6 +156,12 @@ wl_resource_queue_event(struct wl_resource *resource, 
uint32_t opcode, ...)
struct wl_object *object = &resource->object;
va_list ap;
 
+   

[PATCH] window: Bind to version 3 of compositor

2013-05-24 Thread alexl
From: Alexander Larsson 

We need version 3 of the compositor to get version 3 of wl_surface
which has set_buffer_transform and set_buffer_scale.
---
 clients/window.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clients/window.c b/clients/window.c
index b2e1af7..8e49f22 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -4749,7 +4749,7 @@ registry_handle_global(void *data, struct wl_registry 
*registry, uint32_t id,
 
if (strcmp(interface, "wl_compositor") == 0) {
d->compositor = wl_registry_bind(registry, id,
-&wl_compositor_interface, 1);
+&wl_compositor_interface, 3);
} else if (strcmp(interface, "wl_output") == 0) {
display_add_output(d, id);
} else if (strcmp(interface, "wl_seat") == 0) {
-- 
1.8.1.4

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


[PATCH] protocol: Use signed int for scale values

2013-05-24 Thread alexl
From: Alexander Larsson 

We usually use signed ints for things like this, to avoid
issues C sign coersion.
---
 protocol/wayland.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index acfb140..0c7c053 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -1155,7 +1155,7 @@
a buffer that is larger (by a factor of scale in each dimension)
than the desired surface size.
   
-  
+  
 

 
@@ -1652,7 +1652,7 @@
avoid scaling the surface, and the client can supply
a higher detail image.
   
-  
+  
 
   
 
-- 
1.8.1.4

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


[PATCH] Convert all scales to int32_t

2013-05-24 Thread alexl
From: Alexander Larsson 

The type changed in the protocol, so update weston for this.
---
 clients/desktop-shell.c |  2 +-
 clients/window.c| 24 
 clients/window.h|  2 +-
 src/compositor-x11.c|  4 ++--
 src/compositor.c| 12 ++--
 src/compositor.h| 14 +++---
 6 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index 40dd1dd..51ce3ec 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -1115,7 +1115,7 @@ output_handle_done(void *data,
 static void
 output_handle_scale(void *data,
 struct wl_output *wl_output,
-uint32_t scale)
+int32_t scale)
 {
struct output *output = data;
 
diff --git a/clients/window.c b/clients/window.c
index b2e1af7..3870898 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -159,7 +159,7 @@ struct toysurface {
 */
cairo_surface_t *(*prepare)(struct toysurface *base, int dx, int dy,
int32_t width, int32_t height, uint32_t 
flags,
-   enum wl_output_transform buffer_transform, 
uint32_t buffer_scale);
+   enum wl_output_transform buffer_transform, 
int32_t buffer_scale);
 
/*
 * Post the surface to the server, returning the server allocation
@@ -167,7 +167,7 @@ struct toysurface {
 * after calling this.
 */
void (*swap)(struct toysurface *base,
-enum wl_output_transform buffer_transform, uint32_t 
buffer_scale,
+enum wl_output_transform buffer_transform, int32_t 
buffer_scale,
 struct rectangle *server_allocation);
 
/*
@@ -210,7 +210,7 @@ struct surface {
 
enum window_buffer_type buffer_type;
enum wl_output_transform buffer_transform;
-   uint32_t buffer_scale;
+   int32_t buffer_scale;
 
cairo_surface_t *cairo_surface;
 
@@ -468,7 +468,7 @@ debug_print(void *proxy, int line, const char *func, const 
char *fmt, ...)
 #endif
 
 static void
-surface_to_buffer_size (enum wl_output_transform buffer_transform, uint32_t 
buffer_scale, int32_t *width, int32_t *height)
+surface_to_buffer_size (enum wl_output_transform buffer_transform, int32_t 
buffer_scale, int32_t *width, int32_t *height)
 {
int32_t tmp;
 
@@ -490,7 +490,7 @@ surface_to_buffer_size (enum wl_output_transform 
buffer_transform, uint32_t buff
 }
 
 static void
-buffer_to_surface_size (enum wl_output_transform buffer_transform, uint32_t 
buffer_scale, int32_t *width, int32_t *height)
+buffer_to_surface_size (enum wl_output_transform buffer_transform, int32_t 
buffer_scale, int32_t *width, int32_t *height)
 {
int32_t tmp;
 
@@ -531,7 +531,7 @@ to_egl_window_surface(struct toysurface *base)
 static cairo_surface_t *
 egl_window_surface_prepare(struct toysurface *base, int dx, int dy,
   int32_t width, int32_t height, uint32_t flags,
-  enum wl_output_transform buffer_transform, uint32_t 
buffer_scale)
+  enum wl_output_transform buffer_transform, int32_t 
buffer_scale)
 {
struct egl_window_surface *surface = to_egl_window_surface(base);
 
@@ -545,7 +545,7 @@ egl_window_surface_prepare(struct toysurface *base, int dx, 
int dy,
 
 static void
 egl_window_surface_swap(struct toysurface *base,
-   enum wl_output_transform buffer_transform, uint32_t 
buffer_scale,
+   enum wl_output_transform buffer_transform, int32_t 
buffer_scale,
struct rectangle *server_allocation)
 {
struct egl_window_surface *surface = to_egl_window_surface(base);
@@ -1017,7 +1017,7 @@ static const struct wl_buffer_listener 
shm_surface_buffer_listener = {
 static cairo_surface_t *
 shm_surface_prepare(struct toysurface *base, int dx, int dy,
int32_t width, int32_t height, uint32_t flags,
-   enum wl_output_transform buffer_transform, uint32_t 
buffer_scale)
+   enum wl_output_transform buffer_transform, int32_t 
buffer_scale)
 {
int resize_hint = !!(flags & SURFACE_HINT_RESIZE);
struct shm_surface *surface = to_shm_surface(base);
@@ -1095,7 +1095,7 @@ out:
 
 static void
 shm_surface_swap(struct toysurface *base,
-enum wl_output_transform buffer_transform, uint32_t 
buffer_scale,
+enum wl_output_transform buffer_transform, int32_t 
buffer_scale,
 struct rectangle *server_allocation)
 {
struct shm_surface *surface = to_shm_surface(base);
@@ -1457,7 +1457,7 @@ window_set_buffer_transform(struct window *window,
 
 void
 window_set_buffer_scale(struct window *window,
-   uint32_t scale)
+   int32_t scale)
 {
window->main_surface->buffer_scale = scale;

[PATCH] protocol: Modes are specified in HW pixels

2013-05-28 Thread alexl
From: Alexander Larsson 

Modes are mainly meant to be used in coordination with fullscreen in
DRIVER mode, by e.g. games. For such games what they generally want
is to match some hardware mode and resize their window for that. We
don't really need to complicate this with the scaling. So, we
keep the resolutions in HW pixels, and drop the SCALED flag (as it
is now useless).

This lets you just create e.g an 800x600 buffer of scale 1 and
fullscreen that, ignoring the output scaling factor (although you can
of course also respect it and create a 400x300 surface at scale 2).
Conceptually the mode change is treated like a scaling which overrides
the normal output scale.

The only complexity is the FILL mode where it can happen that the user
specifies a buffer of the same size as the screen, but the output has scale
2 and the buffer scale 1. Just scanning out this buffer will work, but
effectively this is a downscaling operation, as the "real" size of the surface
in pels is twice the size of the output. We solve this by allowing FILL to
downscale (but still not upscale).
---
 protocol/wayland.xml | 30 +-
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index acfb140..1ec704b 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -729,7 +729,7 @@
   
   
   
-  
+  
 
 
 
@@ -751,6 +751,19 @@
indicates that the app does not care about framerate.  The
framerate is specified in mHz, that is framerate of 6 is 60Hz.
 
+   A method of "scale" or "driver" implies a scaling operation of
+   the surface, either via a direct scaling operation or a change of
+   the output mode. This will override any kind of output scaling, so
+   that mapping a surface with a buffer size equal to the mode can
+   fill the screen independent of buffer_scale.
+
+   A method of "fill" means we don't scale up the buffer, however
+   any output scale is applied. This means that you may run into
+   an edge case where the application maps a buffer with the same
+   size of the output mode but buffer_scale 1 (thus making a
+   surface larger than the output). In this case it is allowed to
+   downscale the results to fit the screen.
+
The compositor must reply to this request with a configure event
with the dimensions for the output on which the surface will
be made fullscreen.
@@ -1596,8 +1609,6 @@
 summary="indicates this is the current mode"/>
   
-  
 
 
 
@@ -1610,14 +1621,15 @@
current.  In other words, the current mode is always the last
mode that was received with the current flag set.
 
-   The size of a mode is given relative to the global compositor
-   space. This is not necessarily the native size of the display,
-   as the output might be scaled, as described in wl_output.scale.
-   In this case the scaled flag will be set.
+   The size of a mode is given in physical hardware units of
+the output device. This is not necessarily the same as
+the output size in the global compositor space. For instance,
+the output may be scaled, as described in wl_output.scale,
+or transformed , as described in wl_output.transform.
   
   
-  
-  
+  
+  
   
 
 
-- 
1.8.1.4

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


[PATCH 0/9] Update weston to the change in how modes work

2013-05-28 Thread alexl
From: Alexander Larsson 

This series updates weston wrt the protocol changes in:
http://lists.freedesktop.org/archives/wayland-devel/2013-May/009498.html

It also has a test client and some general fullscreen bugfixes.

Alexander Larsson (9):
  shell: Position DRIVER fullscreen surfaces at origin
  input: Fix possible crash in clip_pointer_motion
  fullscreen: Add fullscreen testing client
  compositor-x11: Set original mode after current
  compositor: Store modes in physical units
  compositor: Store original output scale
  shell: Use buffer_scale as output scale on fullscreen DRIVER
  shell: Always go to original mode when focused window not fullscreen
  shell: Center window in fullscreen if needed

 clients/Makefile.am   |   4 +
 clients/fullscreen.c  | 356 ++
 src/compositor-drm.c  |  37 ++
 src/compositor-x11.c  |   8 +-
 src/compositor.c  |  32 +++--
 src/compositor.h  |   5 +-
 src/gl-renderer.c |   4 +-
 src/input.c   |   2 +-
 src/pixman-renderer.c |   4 +-
 src/shell.c   |  46 +--
 10 files changed, 436 insertions(+), 62 deletions(-)
 create mode 100644 clients/fullscreen.c

-- 
1.8.1.4

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


[PATCH 1/9] shell: Position DRIVER fullscreen surfaces at origin

2013-05-28 Thread alexl
From: Alexander Larsson 

When a window is fullscreened with DRIVER method and we succeeded
in changing mode we need to actually move the surface to the
origin of the output, or it won't be used for scanout.
---
 src/shell.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/shell.c b/src/shell.c
index 1443328..07be564 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1802,6 +1802,9 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
shsurf->fullscreen.framerate};
 
if (weston_output_switch_mode(output, &mode) == 0) {
+   weston_surface_set_position(surface,
+   output->x - surf_x,
+   output->y - surf_y);

weston_surface_configure(shsurf->fullscreen.black_surface,
 output->x - surf_x,
 output->y - surf_y,
-- 
1.8.1.4

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


[PATCH 2/9] input: Fix possible crash in clip_pointer_motion

2013-05-28 Thread alexl
From: Alexander Larsson 

It was erronously using output->current->height in one
place where it should use output->height. This may cause
it to create an invalid clipped coordinate in case of output
scaling or transform, because the next round "prev" would
end up NULL.
---
 src/input.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/input.c b/src/input.c
index 129593f..89f74f4 100644
--- a/src/input.c
+++ b/src/input.c
@@ -593,7 +593,7 @@ clip_pointer_motion(struct weston_seat *seat, wl_fixed_t 
*fx, wl_fixed_t *fy)
prev->width - 1);
if (y < prev->y)
*fy = wl_fixed_from_int(prev->y);
-   else if (y >= prev->y + prev->current->height)
+   else if (y >= prev->y + prev->height)
*fy = wl_fixed_from_int(prev->y +
prev->height - 1);
}
-- 
1.8.1.4

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


[PATCH 3/9] fullscreen: Add fullscreen testing client

2013-05-28 Thread alexl
From: Alexander Larsson 

This lets you try fullscreen in different methods, sizes, scales,
translations, etc. You can verify both output and input (via mouse over
of the rectangles).
---
 clients/Makefile.am  |   4 +
 clients/fullscreen.c | 356 +++
 2 files changed, 360 insertions(+)
 create mode 100644 clients/fullscreen.c

diff --git a/clients/Makefile.am b/clients/Makefile.am
index d360174..12a9938 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -63,6 +63,7 @@ clients_programs =\
eventdemo   \
clickdot\
transformed \
+   fullscreen  \
calibrator  \
$(subsurfaces)  \
$(full_gl_client_programs)
@@ -129,6 +130,9 @@ clickdot_LDADD = libtoytoolkit.la
 transformed_SOURCES = transformed.c
 transformed_LDADD = libtoytoolkit.la
 
+fullscreen_SOURCES = fullscreen.c
+fullscreen_LDADD = libtoytoolkit.la
+
 calibrator_SOURCES = calibrator.c ../shared/matrix.c ../shared/matrix.h
 calibrator_LDADD = libtoytoolkit.la
 
diff --git a/clients/fullscreen.c b/clients/fullscreen.c
new file mode 100644
index 000..bea1a15
--- /dev/null
+++ b/clients/fullscreen.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ * Copyright © 2012 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include "window.h"
+
+struct fullscreen {
+   struct display *display;
+   struct window *window;
+   struct widget *widget;
+   int width, height;
+   int fullscreen;
+   float pointer_x, pointer_y;
+   enum wl_shell_surface_fullscreen_method fullscreen_method;
+};
+
+static void
+fullscreen_handler(struct window *window, void *data)
+{
+   struct fullscreen *fullscreen = data;
+
+   fullscreen->fullscreen ^= 1;
+   window_set_fullscreen(window, fullscreen->fullscreen);
+}
+
+static void
+resize_handler(struct widget *widget, int width, int height, void *data)
+{
+   struct fullscreen *fullscreen = data;
+
+   widget_set_size(widget, fullscreen->width, fullscreen->height);
+}
+
+static void
+draw_string(cairo_t *cr,
+   const char *fmt, ...)
+{
+   char buffer[4096];
+   char *p, *end;
+   va_list argp;
+   cairo_text_extents_t text_extents;
+   cairo_font_extents_t font_extents;
+
+   cairo_save(cr);
+
+   cairo_select_font_face(cr, "sans",
+  CAIRO_FONT_SLANT_NORMAL,
+  CAIRO_FONT_WEIGHT_NORMAL);
+   cairo_set_font_size(cr, 14);
+
+   cairo_font_extents (cr, &font_extents);
+
+   va_start(argp, fmt);
+
+   vsnprintf(buffer, sizeof(buffer), fmt, argp);
+
+   p = buffer;
+   while (*p) {
+   end = strchr(p, '\n');
+   if (end)
+   *end = 0;
+
+   cairo_show_text(cr, p);
+   cairo_text_extents (cr, p, &text_extents);
+   cairo_rel_move_to (cr, -text_extents.x_advance, 
font_extents.height);
+
+   if (end)
+   p = end + 1;
+   else
+   break;
+   }
+
+   va_end(argp);
+
+   cairo_restore(cr);
+
+}
+
+static void
+redraw_handler(struct widget *widget, void *data)
+{
+   struct fullscreen *fullscreen = data;
+   struct rectangle allocation;
+   cairo_surface_t *surface;
+   cairo_t *cr;
+   int i;
+   double x, y, border;
+   const char *method_name[] = { "default", "scale", "driver", "fill" };
+
+   surface = window_get_surface(fullscreen->window);
+   if (surface

[PATCH 4/9] compositor-x11: Set original mode after current

2013-05-28 Thread alexl
From: Alexander Larsson 

Otherwise we're pointing the original mode on some uninitialized
value.
---
 src/compositor-x11.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 279f1b3..ba6d053 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -887,7 +887,6 @@ x11_compositor_create_output(struct x11_compositor *c, int 
x, int y,
if (fullscreen)
x11_output_wait_for_map(c, output);
 
-   output->base.origin = output->base.current;
output->base.start_repaint_loop = x11_output_start_repaint_loop;
if (c->use_pixman)
output->base.repaint = x11_output_repaint_shm;
@@ -899,6 +898,7 @@ x11_compositor_create_output(struct x11_compositor *c, int 
x, int y,
output->base.set_dpms = NULL;
output->base.switch_mode = NULL;
output->base.current = &output->mode;
+   output->base.origin = output->base.current;
output->base.make = "xwayland";
output->base.model = "none";
weston_output_init(&output->base, &c->base,
-- 
1.8.1.4

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


[PATCH 6/9] compositor: Store original output scale

2013-05-28 Thread alexl
From: Alexander Larsson 

We want this so we can restore the original mode
with the original size (after having been fullscreen).
---
 src/compositor.c | 1 +
 src/compositor.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/compositor.c b/src/compositor.c
index 79acc76..8f82ba6 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -2697,6 +2697,7 @@ weston_output_init(struct weston_output *output, struct 
weston_compositor *c,
output->mm_width = mm_width;
output->mm_height = mm_height;
output->dirty = 1;
+   output->origin_scale = scale;
 
weston_output_transform_scale_init(output, transform, scale);
weston_output_init_zoom(output);
diff --git a/src/compositor.h b/src/compositor.h
index 3b428c5..b17d832 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -187,6 +187,7 @@ struct weston_output {
 
struct weston_mode *current;
struct weston_mode *origin;
+   int32_t origin_scale;
struct wl_list mode_list;
 
void (*start_repaint_loop)(struct weston_output *output);
-- 
1.8.1.4

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


[PATCH 5/9] compositor: Store modes in physical units

2013-05-28 Thread alexl
From: Alexander Larsson 

We changed the protocol to always list modes in physical pixel
units (not scaled). And we removed the scaled mode flag. This
just updates the DRM and X11 compositors and the gl and pixman renderers
to handle this.
---
 src/compositor-drm.c  | 37 +
 src/compositor-x11.c  |  6 ++
 src/compositor.c  | 27 +++
 src/compositor.h  |  2 +-
 src/gl-renderer.c |  4 ++--
 src/pixman-renderer.c |  4 ++--
 6 files changed, 31 insertions(+), 49 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 4435162..4222e57 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -449,7 +449,6 @@ drm_output_prepare_scanout_surface(struct weston_output 
*_output,
buffer->width != output->base.current->width ||
buffer->height != output->base.current->height ||
output->base.transform != es->buffer_transform ||
-   output->base.scale != es->buffer_scale ||
es->transform.enabled)
return NULL;
 
@@ -1249,7 +1248,7 @@ init_pixman(struct drm_compositor *ec)
 }
 
 static struct drm_mode *
-drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info, int 
scale)
+drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
 {
struct drm_mode *mode;
uint64_t refresh;
@@ -1258,15 +1257,9 @@ drm_output_add_mode(struct drm_output *output, 
drmModeModeInfo *info, int scale)
if (mode == NULL)
return NULL;
 
-   if (info->hdisplay % scale != 0 ||
-   info->vdisplay % scale) {
-   weston_log("Mode %dx%d not multiple of scale %d\n", 
info->hdisplay, info->vdisplay, scale);
-   return NULL;
-   }
-
mode->base.flags = 0;
-   mode->base.width = info->hdisplay / scale;
-   mode->base.height = info->vdisplay / scale;
+   mode->base.width = info->hdisplay;
+   mode->base.height = info->vdisplay;
 
/* Calculate higher precision (mHz) refresh rate */
refresh = (info->clock * 100LL / info->htotal +
@@ -1282,9 +1275,6 @@ drm_output_add_mode(struct drm_output *output, 
drmModeModeInfo *info, int scale)
mode->base.refresh = refresh;
mode->mode_info = *info;
 
-   if (scale != 1)
-   mode->base.flags |= WL_OUTPUT_MODE_SCALED;
-
if (info->type & DRM_MODE_TYPE_PREFERRED)
mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
 
@@ -1446,8 +1436,8 @@ drm_output_init_egl(struct drm_output *output, struct 
drm_compositor *ec)
int i, flags;
 
output->surface = gbm_surface_create(ec->gbm,
-output->base.current->width * 
output->base.scale,
-output->base.current->height * 
output->base.scale,
+output->base.current->width,
+output->base.current->height,
 GBM_FORMAT_XRGB,
 GBM_BO_USE_SCANOUT |
 GBM_BO_USE_RENDERING);
@@ -1491,12 +1481,12 @@ drm_output_init_pixman(struct drm_output *output, 
struct drm_compositor *c)
/* FIXME error checking */
 
for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
-   output->dumb[i] = drm_fb_create_dumb(c, w * output->base.scale, 
h * output->base.scale);
+   output->dumb[i] = drm_fb_create_dumb(c, w, h);
if (!output->dumb[i])
goto err;
 
output->image[i] =
-   pixman_image_create_bits(PIXMAN_x8r8g8b8, w * 
output->base.scale, h * output->base.scale,
+   pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
 output->dumb[i]->map,
 output->dumb[i]->stride);
if (!output->image[i])
@@ -1507,7 +1497,7 @@ drm_output_init_pixman(struct drm_output *output, struct 
drm_compositor *c)
goto err;
 
pixman_region32_init_rect(&output->previous_damage,
- output->base.x, output->base.y, w, h);
+ output->base.x, output->base.y, 
output->base.width, output->base.height);
 
return 0;
 
@@ -1839,8 +1829,7 @@ create_output_for_connector(struct drm_compositor *ec,
}
 
for (i = 0; i < connector->count_modes; i++) {
-   drm_mode = drm_output_add_mode(output, 
-  &connector->modes[i], scale);
+   drm_mode = drm_output_add_mode(output, &connector->modes[i]);
if (!drm_mode)
goto err_free;
}
@@ -1858,8 +1847,8 @@ create_output_for_connector(struct drm_compositor *ec,
 
wl_list_for_each(drm_m

[PATCH 8/9] shell: Always go to original mode when focused window not fullscreen

2013-05-28 Thread alexl
From: Alexander Larsson 

Right now we only switch mode on activating a fullscreened window.
This has several problems:

* Once you're in fullscreen its hard to switch to a non-fullscreened
  window with alt-tab as you stay in the small resolution.
* If you switch from a fullscreened window to a non-fullscreened
  window and the fullscreened window is destroyed we will not
  restore the original mode (since the window is not
  shell_surface_is_top_fullscreen()
* Its hard to reach a different output on the right with the mouse
  when the mode is smaller that the original, as there is a "gap"
  between the two outputs. So, if you alt-tab to another window
  you can not always reach it.

This is somewhat of a sledge hammer, as it means you can't e.g.
focus a non-fullscreen on one output and have a window fullscreened
on another output. However, trying to restore only the outputs
the new window is on is problematic:

* It may later change output
* We want to see all windows anyway during alt-tab
* Can't reach the other windows with the mouse anyway

So, this seems like an ok solution.
---
 src/shell.c | 38 +-
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/src/shell.c b/src/shell.c
index 1f2ad60..eac8471 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1496,15 +1496,32 @@ get_default_output(struct weston_compositor *compositor)
 }
 
 static void
+restore_output_mode(struct weston_output *output)
+{
+   if (output->current != output->origin ||
+   (int32_t)output->scale != output->origin_scale)
+   weston_output_switch_mode(output,
+ output->origin,
+ output->origin_scale);
+}
+
+static void
+restore_all_output_modes(struct weston_compositor *compositor)
+{
+   struct weston_output *output;
+
+   wl_list_for_each(output, &compositor->output_list, link)
+   restore_output_mode(output);
+}
+
+static void
 shell_unset_fullscreen(struct shell_surface *shsurf)
 {
struct workspace *ws;
/* undo all fullscreen things here */
if (shsurf->fullscreen.type == 
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
shell_surface_is_top_fullscreen(shsurf)) {
-   weston_output_switch_mode(shsurf->fullscreen_output,
- shsurf->fullscreen_output->origin,
- 
shsurf->fullscreen_output->origin_scale);
+   restore_output_mode(shsurf->fullscreen_output);
}
shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
shsurf->fullscreen.framerate = 0;
@@ -1742,6 +1759,9 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
float scale, output_aspect, surface_aspect, x, y;
int32_t surf_x, surf_y, surf_width, surf_height;
 
+   if (shsurf->fullscreen.type != 
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER)
+   restore_output_mode(output);
+
if (!shsurf->fullscreen.black_surface)
shsurf->fullscreen.black_surface =
create_black_surface(surface->compositor,
@@ -1812,7 +1832,8 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
 output->width,
 output->height);
break;
-   }
+   } else
+   restore_output_mode(output);
}
break;
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
@@ -2150,11 +2171,8 @@ destroy_shell_surface(struct shell_surface *shsurf)
}
 
if (shsurf->fullscreen.type == 
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
-   shell_surface_is_top_fullscreen(shsurf)) {
-   weston_output_switch_mode(shsurf->fullscreen_output,
- shsurf->fullscreen_output->origin,
- 
shsurf->fullscreen_output->origin_scale);
-   }
+   shell_surface_is_top_fullscreen(shsurf))
+   restore_output_mode (shsurf->fullscreen_output);
 
if (shsurf->fullscreen.black_surface)
weston_surface_destroy(shsurf->fullscreen.black_surface);
@@ -2924,6 +2942,7 @@ activate(struct desktop_shell *shell, struct 
weston_surface *es,
shell_configure_fullscreen(get_shell_surface(main_surface));
break;
default:
+   restore_all_output_modes(shell->compositor);
ws = get_current_workspace(shell);
weston_surface_restack(main_surface, &ws->layer.surface_list);
break;
@@ -4014,6 +4033,7 @@ switcher_binding(struct weston_seat *seat, uint32_t time, 
uint32_t key,
switcher->listener.notify = switcher_handle_surface_destroy;
wl_list_init(&switcher->listener

[PATCH 7/9] shell: Use buffer_scale as output scale on fullscreen DRIVER

2013-05-28 Thread alexl
From: Alexander Larsson 

It may happen that you e.g. fullscreen a 800x600 surface with
buffer_scale 1 (e.g. a 800x600 buffer) on an output that is
otherwise scale 2. In this case we want to temporarily set
the output scale to 1, as we're really scanning out of a
scale 1 buffer. This causes us to e.g. report the input
positions in the right place, etc.

When we restore the original mode we also restore the original
scale.

Note that the scale change is a purely compositor internal change,
to clients it still looks like the output is scale 2.
---
 src/compositor.c |  4 +++-
 src/compositor.h |  2 +-
 src/shell.c  | 12 +++-
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 8f82ba6..b5b5ab8 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -95,7 +95,7 @@ static void
 weston_output_transform_scale_init(struct weston_output *output, uint32_t 
transform, uint32_t scale);
 
 WL_EXPORT int
-weston_output_switch_mode(struct weston_output *output, struct weston_mode 
*mode)
+weston_output_switch_mode(struct weston_output *output, struct weston_mode 
*mode, int32_t scale)
 {
struct weston_seat *seat;
pixman_region32_t old_output_region;
@@ -108,6 +108,8 @@ weston_output_switch_mode(struct weston_output *output, 
struct weston_mode *mode
if (ret < 0)
return ret;
 
+output->scale = scale;
+
pixman_region32_init(&old_output_region);
pixman_region32_copy(&old_output_region, &output->region);
 
diff --git a/src/compositor.h b/src/compositor.h
index b17d832..86793f5 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -1141,7 +1141,7 @@ void
 weston_surface_destroy(struct weston_surface *surface);
 
 int
-weston_output_switch_mode(struct weston_output *output, struct weston_mode 
*mode);
+weston_output_switch_mode(struct weston_output *output, struct weston_mode 
*mode, int32_t scale);
 
 int
 noop_renderer_init(struct weston_compositor *ec);
diff --git a/src/shell.c b/src/shell.c
index 07be564..1f2ad60 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1503,7 +1503,8 @@ shell_unset_fullscreen(struct shell_surface *shsurf)
if (shsurf->fullscreen.type == 
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
shell_surface_is_top_fullscreen(shsurf)) {
weston_output_switch_mode(shsurf->fullscreen_output,
- shsurf->fullscreen_output->origin);
+ shsurf->fullscreen_output->origin,
+ 
shsurf->fullscreen_output->origin_scale);
}
shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
shsurf->fullscreen.framerate = 0;
@@ -1797,11 +1798,11 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
if (shell_surface_is_top_fullscreen(shsurf)) {
struct weston_mode mode = {0,
-   surf_width,
-   surf_height,
+   surf_width * surface->buffer_scale,
+   surf_height * surface->buffer_scale,
shsurf->fullscreen.framerate};
 
-   if (weston_output_switch_mode(output, &mode) == 0) {
+   if (weston_output_switch_mode(output, &mode, 
surface->buffer_scale) == 0) {
weston_surface_set_position(surface,
output->x - surf_x,
output->y - surf_y);
@@ -2151,7 +2152,8 @@ destroy_shell_surface(struct shell_surface *shsurf)
if (shsurf->fullscreen.type == 
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
shell_surface_is_top_fullscreen(shsurf)) {
weston_output_switch_mode(shsurf->fullscreen_output,
- shsurf->fullscreen_output->origin);
+ shsurf->fullscreen_output->origin,
+ 
shsurf->fullscreen_output->origin_scale);
}
 
if (shsurf->fullscreen.black_surface)
-- 
1.8.1.4

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


[PATCH 9/9] shell: Center window in fullscreen if needed

2013-05-28 Thread alexl
From: Alexander Larsson 

If modeset fails With DRIVER method, and always with FILL method
we want to center the window.
---
 src/shell.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/shell.c b/src/shell.c
index eac8471..ebeef55 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1832,11 +1832,14 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
 output->width,
 output->height);
break;
-   } else
+   } else {
restore_output_mode(output);
+   center_on_output(surface, output);
+   }
}
break;
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
+   center_on_output(surface, output);
break;
default:
break;
-- 
1.8.1.4

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


[PATCH] compositor-drm: Handle cursors on scaled screens

2013-05-28 Thread alexl
From: Alexander Larsson 

We fall back to not using the drm cursor any time
the scale differs, or the scaled size is to large.
---
 src/compositor-drm.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 4222e57..a87cbc3 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -909,6 +909,8 @@ drm_output_prepare_cursor_surface(struct weston_output 
*output_base,
return NULL;
if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
return NULL;
+   if (output->base.scale != es->buffer_scale)
+   return NULL;
if (output->cursor_surface)
return NULL;
if (es->output_mask != (1u << output_base->id))
@@ -917,7 +919,7 @@ drm_output_prepare_cursor_surface(struct weston_output 
*output_base,
return NULL;
if (es->buffer_ref.buffer == NULL ||
!wl_buffer_is_shm(es->buffer_ref.buffer) ||
-   es->geometry.width > 64 || es->geometry.height > 64)
+   es->geometry.width * es->buffer_scale > 64 || es->geometry.height * 
es->buffer_scale > 64)
return NULL;
 
output->cursor_surface = es;
@@ -952,9 +954,9 @@ drm_output_set_cursor(struct drm_output *output)
memset(buf, 0, sizeof buf);
stride = wl_shm_buffer_get_stride(es->buffer_ref.buffer);
s = wl_shm_buffer_get_data(es->buffer_ref.buffer);
-   for (i = 0; i < es->geometry.height; i++)
+   for (i = 0; i < es->geometry.height * es->buffer_scale; i++)
memcpy(buf + i * 64, s + i * stride,
-  es->geometry.width * 4);
+  es->geometry.width * es->buffer_scale * 4);
 
if (gbm_bo_write(bo, buf, sizeof buf) < 0)
weston_log("failed update cursor: %m\n");
-- 
1.8.1.4

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


[PATCH 0/3] Fix screenshooter/recorder for scale

2013-05-29 Thread alexl
From: Alexander Larsson 

The actual fix for output scale is trivial, but I needed
two fixes to get screenshooting to work with the pixman
renderer.

Alexander Larsson (3):
  screenshoter: Make recorder handle PIXMAN_x8r8g8b8
  pixman-renderer: Fix read_pixels for screen recorder
  screenshooter: Scale damage by output scale in screen recorder

 src/pixman-renderer.c | 33 -
 src/screenshooter.c   |  6 ++
 2 files changed, 26 insertions(+), 13 deletions(-)

-- 
1.8.1.4

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


[PATCH 1/3] screenshoter: Make recorder handle PIXMAN_x8r8g8b8

2013-05-29 Thread alexl
From: Alexander Larsson 

This is what the pixman renderer reports for the read format.
---
 src/screenshooter.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/screenshooter.c b/src/screenshooter.c
index dde052f..d088cf7 100644
--- a/src/screenshooter.c
+++ b/src/screenshooter.c
@@ -465,6 +465,7 @@ weston_recorder_create(struct weston_output *output, const 
char *filename)
header.magic = WCAP_HEADER_MAGIC;
 
switch (compositor->read_format) {
+   case PIXMAN_x8r8g8b8:
case PIXMAN_a8r8g8b8:
header.format = WCAP_FORMAT_XRGB;
break;
-- 
1.8.1.4

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


[PATCH 2/3] pixman-renderer: Fix read_pixels for screen recorder

2013-05-29 Thread alexl
From: Alexander Larsson 

The old code had an off-by-one error on the y coordinate
where it says height - (cur_y - y). And it does the vflipping of
the *destination* buffer, whereas what is really needed is to
vflip the whole source buffer. This only affects when you read
out part of the image, such as when using the screen recoder.

Also, instead of doing the flipping manually we just let pixman
handle it.
---
 src/pixman-renderer.c | 33 -
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index ba7cb43..2c42390 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -72,8 +72,8 @@ pixman_renderer_read_pixels(struct weston_output *output,
   uint32_t width, uint32_t height)
 {
struct pixman_output_state *po = get_output_state(output);
+   pixman_transform_t transform;
pixman_image_t *out_buf;
-   uint32_t cur_y;
 
if (!po->hw_buffer) {
errno = ENODEV;
@@ -86,18 +86,25 @@ pixman_renderer_read_pixels(struct weston_output *output,
pixels,
(PIXMAN_FORMAT_BPP(format) / 8) * width);
 
-   /* Caller expects vflipped image */
-   for (cur_y = y; cur_y < y + height; cur_y++) {
-   pixman_image_composite32(PIXMAN_OP_SRC,
-   po->hw_buffer, /* src */
-   NULL /* mask */,
-   out_buf, /* dest */
-   x, cur_y, /* src_x, src_y */
-   0, 0, /* mask_x, mask_y */
-   0, height - (cur_y - y), /* dest_x, dest_y */
-   width, /* width */
-   1 /* height */);
-   }
+   /* Caller expects vflipped source image */
+   pixman_transform_init_translate(&transform,
+   pixman_int_to_fixed (x),
+   pixman_int_to_fixed (y - 
pixman_image_get_height (po->hw_buffer)));
+   pixman_transform_scale(&transform, NULL,
+  pixman_fixed_1,
+  pixman_fixed_minus_1);
+   pixman_image_set_transform(po->hw_buffer, &transform);
+
+   pixman_image_composite32(PIXMAN_OP_SRC,
+po->hw_buffer, /* src */
+NULL /* mask */,
+out_buf, /* dest */
+0, 0, /* src_x, src_y */
+0, 0, /* mask_x, mask_y */
+0, 0, /* dest_x, dest_y */
+pixman_image_get_width (po->hw_buffer), /* 
width */
+pixman_image_get_height (po->hw_buffer) /* 
height */);
+   pixman_image_set_transform(po->hw_buffer, NULL);
 
pixman_image_unref(out_buf);
 
-- 
1.8.1.4

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


[PATCH 3/3] screenshooter: Scale damage by output scale in screen recorder

2013-05-29 Thread alexl
From: Alexander Larsson 

The damage region is in compositor coords, we need to scale it by
the output scale when using the damage to read output buffer data.
---
 src/screenshooter.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/screenshooter.c b/src/screenshooter.c
index d088cf7..83ad192 100644
--- a/src/screenshooter.c
+++ b/src/screenshooter.c
@@ -330,6 +330,11 @@ transform_rect(struct weston_output *output, 
pixman_box32_t *r)
 default:
 break;
 }
+
+   r->x1 *= output->scale;
+   r->y1 *= output->scale;
+   r->x2 *= output->scale;
+   r->y2 *= output->scale;
 }
 
 static void
-- 
1.8.1.4

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