Discussion:
[PATCH] protocol: Add buffer_scale to wl_surface and wl_output
alexl
2013-05-14 10:26:48 UTC
Permalink
From: Alexander Larsson <alexl at redhat.com>

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 @@
</event>
</interface>

- <interface name="wl_surface" version="2">
+ <interface name="wl_surface" version="3">
<description summary="an onscreen surface">
A surface is a rectangular area that is displayed on the screen.
It has a location, size and pixel contents.
@@ -1110,6 +1110,30 @@
</description>
<arg name="transform" type="int"/>
</request>
+
+ <!-- Version 3 additions -->
+
+ <request name="set_buffer_scale" since="3">
+ <description summary="sets the buffer scale">
+ 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.
+ </description>
+ <arg name="scale" type="fixed"/>
+ </request>
</interface>

<interface name="wl_seat" version="1">
@@ -1467,7 +1491,7 @@
</event>
</interface>

- <interface name="wl_output" version="1">
+ <interface name="wl_output" version="2">
<description summary="compositor output region">
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.
</description>
<arg name="x" type="int"
summary="x position within the global compositor space"/>
@@ -1565,6 +1591,17 @@
<arg name="height" type="int" summary="height of the mode in pixels"/>
<arg name="refresh" type="int" summary="vertical refresh rate in mHz"/>
</event>
+
+ <event name="geometry2" since="2">
+ <description summary="additional properties of the output">
+ 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.
+ </description>
+ <arg name="scale" type="fixed" summary="scaling factor of output"/>
+ </event>
</interface>

<interface name="wl_region" version="1">
--
1.8.1.4
John Kåre Alsaker
2013-05-14 11:44:27 UTC
Permalink
I'd only accept a proposal which makes the clients tell the compositor how
much they increased the size of their window. If the compositor wants to
resize anything it should resize the entire window and not individual
surfaces/buffers. This also avoids having to position subsurfaces and have
configure requests at fractional surface pixels.

set_buffer_scale should be renamed to set_scaling_factor. Otherwise it
could be easily confused with the scaling extension which just scales up
buffers. My suggestion also renders it unrelated to buffers. The geometry2
event should be named scaling_factor. A done event should also be added.
I'd also like a lower and upper bound for the scaling factor as argument to
that.
Post by alexl
From: Alexander Larsson <alexl at redhat.com>
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 @@
</event>
</interface>
- <interface name="wl_surface" version="2">
+ <interface name="wl_surface" version="3">
<description summary="an onscreen surface">
A surface is a rectangular area that is displayed on the screen.
It has a location, size and pixel contents.
@@ -1110,6 +1110,30 @@
</description>
<arg name="transform" type="int"/>
</request>
+
+ <!-- Version 3 additions -->
+
+ <request name="set_buffer_scale" since="3">
+ <description summary="sets the buffer scale">
+ 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.
+ </description>
+ <arg name="scale" type="fixed"/>
+ </request>
</interface>
<interface name="wl_seat" version="1">
@@ -1467,7 +1491,7 @@
</event>
</interface>
- <interface name="wl_output" version="1">
+ <interface name="wl_output" version="2">
<description summary="compositor output region">
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.
</description>
<arg name="x" type="int"
summary="x position within the global compositor space"/>
@@ -1565,6 +1591,17 @@
<arg name="height" type="int" summary="height of the mode in pixels"/>
<arg name="refresh" type="int" summary="vertical refresh rate in mHz"/>
</event>
+
+ <event name="geometry2" since="2">
+ <description summary="additional properties of the output">
+ 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.
+ </description>
+ <arg name="scale" type="fixed" summary="scaling factor of output"/>
+ </event>
</interface>
<interface name="wl_region" version="1">
--
1.8.1.4
_______________________________________________
wayland-devel mailing list
wayland-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20130514/e31f6343/attachment.html>
Alexander Larsson
2013-05-14 12:51:59 UTC
Permalink
Post by John KÃ¥re Alsaker
I'd only accept a proposal which makes the clients tell the compositor
how much they increased the size of their window. If the compositor
wants to resize anything it should resize the entire window and not
individual surfaces/buffers. This also avoids having to position
subsurfaces and have configure requests at fractional surface pixels.
I don't quite understand what you mean by this (like, how is "window"
different from "surface"). Can you give an example of how the API would
look for what you mean.
Post by John KÃ¥re Alsaker
set_buffer_scale should be renamed to set_scaling_factor. Otherwise it
could be easily confused with the scaling extension which just scales
up buffers. My suggestion also renders it unrelated to buffers. The
geometry2 event should be named scaling_factor. A done event should
also be added. I'd also like a lower and upper bound for the scaling
factor as argument to that.
I think a done event is silly, as it is not needed and complicates
clients (since the done event is not always sent for older servers), but
sure I can add one.
Post by John KÃ¥re Alsaker
From: Alexander Larsson <alexl at redhat.com>
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 @@
</event>
</interface>
- <interface name="wl_surface" version="2">
+ <interface name="wl_surface" version="3">
<description summary="an onscreen surface">
A surface is a rectangular area that is displayed on the screen.
It has a location, size and pixel contents.
@@ -1110,6 +1110,30 @@
</description>
<arg name="transform" type="int"/>
</request>
+
+ <!-- Version 3 additions -->
+
+ <request name="set_buffer_scale" since="3">
+ <description summary="sets the buffer scale">
+ 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.
+ </description>
+ <arg name="scale" type="fixed"/>
+ </request>
</interface>
<interface name="wl_seat" version="1">
@@ -1467,7 +1491,7 @@
</event>
</interface>
- <interface name="wl_output" version="1">
+ <interface name="wl_output" version="2">
<description summary="compositor output region">
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.
</description>
<arg name="x" type="int"
summary="x position within the global compositor space"/>
@@ -1565,6 +1591,17 @@
<arg name="height" type="int" summary="height of the
mode in pixels"/>
<arg name="refresh" type="int" summary="vertical
refresh rate in mHz"/>
</event>
+
+ <event name="geometry2" since="2">
+ <description summary="additional properties of the output">
+ 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.
+ </description>
+ <arg name="scale" type="fixed" summary="scaling factor of output"/>
+ </event>
</interface>
<interface name="wl_region" version="1">
--
1.8.1.4
_______________________________________________
wayland-devel mailing list
wayland-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel
John Kåre Alsaker
2013-05-14 13:04:04 UTC
Permalink
Post by Alexander Larsson
Post by John KÃ¥re Alsaker
I'd only accept a proposal which makes the clients tell the compositor
how much they increased the size of their window. If the compositor
wants to resize anything it should resize the entire window and not
individual surfaces/buffers. This also avoids having to position
subsurfaces and have configure requests at fractional surface pixels.
I don't quite understand what you mean by this (like, how is "window"
different from "surface"). Can you give an example of how the API would
look for what you mean.
A window can have multiple surfaces (see the subsurface extension).

The API would be the same, the documentation different.
Post by Alexander Larsson
Post by John KÃ¥re Alsaker
set_buffer_scale should be renamed to set_scaling_factor. Otherwise it
could be easily confused with the scaling extension which just scales
up buffers. My suggestion also renders it unrelated to buffers. The
geometry2 event should be named scaling_factor. A done event should
also be added. I'd also like a lower and upper bound for the scaling
factor as argument to that.
I think a done event is silly, as it is not needed and complicates
clients (since the done event is not always sent for older servers), but
sure I can add one.
Clients can easily require a compositor which implements the done event,
although they may also support older versions. It's just the compositor
that has to take care not sending done (and geometry2) to the old clients.

If you add one, it should be in a separate commit as it's unrelated to this
work.
Post by Alexander Larsson
Post by John KÃ¥re Alsaker
From: Alexander Larsson <alexl at redhat.com>
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 @@
</event>
</interface>
- <interface name="wl_surface" version="2">
+ <interface name="wl_surface" version="3">
<description summary="an onscreen surface">
A surface is a rectangular area that is displayed on the screen.
It has a location, size and pixel contents.
@@ -1110,6 +1110,30 @@
</description>
<arg name="transform" type="int"/>
</request>
+
+ <!-- Version 3 additions -->
+
+ <request name="set_buffer_scale" since="3">
+ <description summary="sets the buffer scale">
+ 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.
+ </description>
+ <arg name="scale" type="fixed"/>
+ </request>
</interface>
<interface name="wl_seat" version="1">
@@ -1467,7 +1491,7 @@
</event>
</interface>
- <interface name="wl_output" version="1">
+ <interface name="wl_output" version="2">
<description summary="compositor output region">
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.
</description>
<arg name="x" type="int"
summary="x position within the global compositor space"/>
@@ -1565,6 +1591,17 @@
<arg name="height" type="int" summary="height of the
mode in pixels"/>
<arg name="refresh" type="int" summary="vertical
refresh rate in mHz"/>
</event>
+
+ <event name="geometry2" since="2">
+ <description summary="additional properties of the output">
+ 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.
+ </description>
+ <arg name="scale" type="fixed" summary="scaling factor
of output"/>
+ </event>
</interface>
<interface name="wl_region" version="1">
--
1.8.1.4
_______________________________________________
wayland-devel mailing list
wayland-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20130514/c4d75985/attachment.html>
Bill Spitzak
2013-05-14 20:16:29 UTC
Permalink
On Tue, May 14, 2013 at 2:51 PM, Alexander Larsson <alexl at redhat.com
Post by John KÃ¥re Alsaker
I'd only accept a proposal which makes the clients tell the
compositor
Post by John KÃ¥re Alsaker
how much they increased the size of their window. If the compositor
wants to resize anything it should resize the entire window and not
individual surfaces/buffers. This also avoids having to position
subsurfaces and have configure requests at fractional surface pixels.
I don't quite understand what you mean by this (like, how is "window"
different from "surface"). Can you give an example of how the API would
look for what you mean.
A window can have multiple surfaces (see the subsurface extension).
I don't see any problem at all. Any scale being applied to a surface to
be applied to it's subsurfaces as well. And subsurface position is in
pre-scaled coordinates so if you want a subsurface to align with some
pixels in the main surface's buffer, the position is still in integers.

Yes the subsurface's destination rectangle is going to be scaled to
non-integers. I think you have to realize you are not going to avoid
this problem by your attempt to link the clipping rectangle to the
scaling factor. Clients should deal with it by rendering images such
that the result is not objectionable, mostly by forcing the edges to be
replicated on buffers, and filling the invisible areas with non-clashing
pixel values.

I now do very much believe that the scaler extension should be altered
so that surface size and events are reported in pre-scaled (ie in buffer
pixels) coordinates. This makes the transformation be done at the same
step as this scaler, reducing the number of different coordinate spaces.
You cannot do it the other way because that *does* require surface sizes
to be non-integers.
Bill Spitzak
2013-05-14 20:43:12 UTC
Permalink
Post by alexl
+ </description>
+ <arg name="scale" type="fixed"/>
+ </request>
</interface>
Fixed is not a good idea for scaling factors. You cannot accurately
represent values like 2/3 or 1/fixed. For an actual problem with
scaling, if the accurate scaling is an odd fixed number, the client
cannot specify that their scale is exactly 1/2 that, thus losing the
ability to get a 2x scale done by the compositor.

I would specify the scale as two integers defining a rational fraction.

This would also allow completely lossless multiplication with the
rational numbers used by the scaler proposal.

You may also want to allow different horizontal and vertical scales,
mostly because all plausable implementations can do this with no loss of
speed, and the scaler api allows this. You will need to define if this
is before or after the buffer transform...
Pekka Paalanen
2013-05-15 05:54:05 UTC
Permalink
On Tue, 14 May 2013 13:43:12 -0700
Post by Bill Spitzak
You may also want to allow different horizontal and vertical scales,
mostly because all plausable implementations can do this with no loss of
speed, and the scaler api allows this. You will need to define if this
is before or after the buffer transform...
Only if there are monitors with non-square pixels that we care about.
Otherwise no.
- pq
Alexander Larsson
2013-05-15 06:44:15 UTC
Permalink
Post by Bill Spitzak
Post by alexl
+ </description>
+ <arg name="scale" type="fixed"/>
+ </request>
</interface>
Fixed is not a good idea for scaling factors. You cannot accurately
represent values like 2/3 or 1/fixed. For an actual problem with
scaling, if the accurate scaling is an odd fixed number, the client
cannot specify that their scale is exactly 1/2 that, thus losing the
ability to get a 2x scale done by the compositor.
I would specify the scale as two integers defining a rational fraction.
This would also allow completely lossless multiplication with the
rational numbers used by the scaler proposal.
You may also want to allow different horizontal and vertical scales,
mostly because all plausable implementations can do this with no loss of
speed, and the scaler api allows this. You will need to define if this
is before or after the buffer transform...
In fact, working on this in weston a bit it seems that in general, scale
is seldom used by itself but rather its used to calculate the buffer and
screen size which are then used, and we want both of these to be
integers. So, it seems to me that we should specify scaling by giving
the width/heigh of the surface, which in combination with the buffer
size gives the exact scaling ratios, plus it guarantees that the scaling
maps integers to integers.
Bill Spitzak
2013-05-15 18:51:02 UTC
Permalink
Post by Alexander Larsson
In fact, working on this in weston a bit it seems that in general, scale
is seldom used by itself but rather its used to calculate the buffer and
screen size which are then used, and we want both of these to be
integers. So, it seems to me that we should specify scaling by giving
the width/heigh of the surface, which in combination with the buffer
size gives the exact scaling ratios, plus it guarantees that the scaling
maps integers to integers.
This now sounds exactly like the "scaler" api.

What is really happening is that the hi-dpi scheme proposed is providing
a "denominator" to the x,y, and size of the output rectangle provided to
the scaler api, so that it can now be fractions. It would work perfectly
well to move that denominator into the scaler api.

Except that events are reported as though the positions are multiplied
by the denominator. I think this is a mistake and events should be
reported in the input space, but this strangeness can be worked around
pretty easily.

Pekka Paalanen
2013-05-15 08:13:11 UTC
Permalink
On Tue, 14 May 2013 12:26:48 +0200
Post by alexl
From: Alexander Larsson <alexl at redhat.com>
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.
I think I can understand this paragraph, but could we express it more
clearly?

"Output with sub-pixel precision" could probably use some explanation
about what it is here, like is it about sub-pixels in the RGB pixel
parts sense. Can this be used for RGB-sub-pixel things somehow?

"Compositor space" and "scaled space" need to be clearly defined, I am
not sure what they refer to here. The well-known coordinate spaces we
already have are surface (local) coordinates, and global coordinates.
Output coordinates likely too, and buffer coordinates will be
introduced with the surface crop & scale extension[1] to further
differentiate from surface coordinates.
Post by alexl
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 @@
</event>
</interface>
- <interface name="wl_surface" version="2">
+ <interface name="wl_surface" version="3">
You have to bump also the wl_compositor version. wl_surface is not a
global, and only globals can have their interface version negotiated.
The global that can create wl_surface objects is wl_compositor, and
wl_compositor only.

The version of wl_surface in use will be implied by the negotiated
version of wl_compositor.

(Yes, it is a bit strange perhaps, but that is how it is.)
Post by alexl
<description summary="an onscreen surface">
A surface is a rectangular area that is displayed on the screen.
It has a location, size and pixel contents.
@@ -1110,6 +1110,30 @@
</description>
<arg name="transform" type="int"/>
</request>
+
+ <!-- Version 3 additions -->
+
+ <request name="set_buffer_scale" since="3">
+ <description summary="sets the buffer scale">
+ 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.
..in each dimension. Ok.
Post by alexl
+
+ 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.
You could also mention, that it is expected that clients will use
an output's scale property value as the set_buffer_scale argument. Or
at least that is the intended use here.
Post by alexl
+ </description>
+ <arg name="scale" type="fixed"/>
Are you sure you really want fixed as the type?
Integer scaling factors sounded a lot more straightforward. When we are
dealing with pixel buffers, integers make sense.

Also, I do not buy the argument, that integer scaling factors are not
finely grained enough. If an output device (monitor) has such a hidpi,
and a user wants the default scaling, then we will simply have an
integer scaling factor >1, for example 2. Clients will correspondingly
somehow see, that the output resolution is "small", so they will adapt,
and the final window size will not be doubled all the way unless it
actually fits the output. This happens by the client choosing to draw a
smaller window to begin with, not by scaling, when compared to what it
would do if the default scaling factor was 1. Fractional scaling factors
are simply not needed here, in my opinion.

Can we have any use for scales less than one?

In other words, can you even imagine a case, where the compositor would
by default down-scale all surfaces? I cannot, since I think that default
behaviour could only make the image worse, even if it could fit more on
screen. Rather than that, clients know the current output resolution,
and need to adapt to it directly by initially not making a window too
large.

Also, one issue raised was that if an output has a scaling factor A,
and a buffer has a scaling factor B, then final scaling factor is
rational. To me that is a non-issue. It can only occur for a
misbehaving client, in which case it gets what it deserves, or in a
multi-output case of one surface spanning several non-identical
monitors. I think the latter case it not worth caring about.
Non-identical monitors are not identical, and you get what you happen
to get when you use a single buffer to composite to both.
Post by alexl
+ </request>
</interface>
<interface name="wl_seat" version="1">
@@ -1467,7 +1491,7 @@
</event>
</interface>
- <interface name="wl_output" version="1">
+ <interface name="wl_output" version="2">
<description summary="compositor output region">
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.
</description>
<arg name="x" type="int"
summary="x position within the global compositor space"/>
@@ -1565,6 +1591,17 @@
<arg name="height" type="int" summary="height of the mode in pixels"/>
<arg name="refresh" type="int" summary="vertical refresh rate in mHz"/>
</event>
+
+ <event name="geometry2" since="2">
The event needs a better name. "scale"? "default_scale"?
Post by alexl
+ <description summary="additional properties of the output">
The summary should refer to the scale specifically.
Post by alexl
+ 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.
The "geometry event always follows a geometry2 event" could also be
documented generally in the geometry event: all (any?) supported
additional output properties are sent before the geometry event, and
then the geometry event indicates the end of events for this batch.

Here you should document, what this scaling factor actually means, and
then refer to wl_surface.set_buffer_scale.
Post by alexl
+ </description>
+ <arg name="scale" type="fixed" summary="scaling factor of output"/>
+ </event>
</interface>
<interface name="wl_region" version="1">
We still need to define precisely how this interacts with the various
coordinate systems. Let's look at it first without the crop & scale
extension in between. If I understood right, it would go like this:

Coordinate systems the client is aware of:

A. Buffer pixel coordinates, which are essentially equivalent to byte
addresses of pixels in the buffer.

- Apply (inverse?) buffer_transform and inverse buffer_scale to get:

B. Surface coordinates, i.e. the local coordinates where all window
management and input happens.

Coordinate systems internal to a compositor:

- Apply surface transform (usually only translation, but visual effects
may do other stuff, too) to get:

C. Global coordinates, where all surfaces and outputs are laid out.

- Apply output transform and output scale, to get:

D. Output framebuffer pixel coordinates, which correspond to the byte
addresses of pixels in the scanout buffer.


The important thing is to make all client-visible coordinate systems
consistent and logical.

Buffer size in coordinate system A is always integers, naturally. We
also want to keep the surface size in coordinate system B integers,
because the protocol already assumes that (wl_surface.attach, shell
protocol, maybe others). Therefore, buffer_scale should be an integer
to guarantee that.

When a surface comes to coordinate systems C and D, there is no
requirement to have its size or position as integers. The surface
transform, that is private to the compositor, could warp the surface
along a curve for all we care, but usually it doesn't. Usually it only
does a translation to position the surface, and does not change the
scale. Then the renderer in a compositor just does its best to realize
the total transformation from buffer pixels to framebuffer pixels.

In the best case, when buffer_scale equals output_scale and surface
transform is only a translation, the pixels from a surface's buffer are
mapped 1:1 to the framebuffer pixels.

If buffer_scale is 1, set explicitly by a client or just by default,
the buffer pixels will be scaled by the integer factor output_scale.

These two are the most important cases to my understanding.

If additionally to the best case, the translation in the surface
transform is zero, buffer transform matches the output transform, and
the buffer is the size of the output resolution, the buffer could be
scanned out directly, bypassing the compositing. Overlay hardware can
allow scanout even with some scaling.

Thinking about input events, there are no problems. Input always comes
in coordinate system B, the surface coordinates. As position/motion in
input events is always of type wl_fixed, you can address individual
pixels in a buffer up to scaling factor 256.

The usual shell operations should work as is, too.
wl_shell_surface.configure tells you the desired surface size in
surface coordinates, and then you realize that any way you want in a
client. Transient and pop-up surfaces that are relative to a parent
surface work, too, since the child surface's position and size is
negotiated and given in parent surface's coordinates. The same works
with sub-surfaces.

And now the questions.

If an output has a scaling factor f, what does the wl_output
report as the output's current and supported video modes?

What about x,y in the wl_output.geometry event (which I think are just a
global coordinate space leak that should not be there)?

The video modes are important because of the
wl_shell_surface.set_fullscreen with method DRIVER. A fullscreen
surface with method DRIVER implies, that the client wants the
compositor to change the video mode to match this surface. Of course
this usually only happens when the fullscreen surface is topmost and
active.

A client can use the list of supported video modes from the wl_output
to choose the size of its fullscreen surface. E.g. if video mode
800x600 is supported, the client may choose to make the fullscreened
surface of size 800x600, and assume that the server ideally switches
the video mode 800x600 to present the surface.

How do buffer_scale and output scale interact with this mechanism?

I'll leave the interactions with the crop & scale extension for later,
I have a feeling there is a relatively clean and logical solution.


Thanks,
pq

[1] http://lists.freedesktop.org/archives/wayland-devel/2013-April/008927.html
Alexander Larsson
2013-05-15 13:11:33 UTC
Permalink
Post by Pekka Paalanen
On Tue, 14 May 2013 12:26:48 +0200
Lots of good stuff snipped. I'll try to fix things up based on that.
Some responses below.
Post by Pekka Paalanen
Post by alexl
+ </description>
+ <arg name="scale" type="fixed"/>
Are you sure you really want fixed as the type?
Integer scaling factors sounded a lot more straightforward. When we are
dealing with pixel buffers, integers make sense.
Also, I do not buy the argument, that integer scaling factors are not
finely grained enough. If an output device (monitor) has such a hidpi,
and a user wants the default scaling, then we will simply have an
integer scaling factor >1, for example 2. Clients will correspondingly
somehow see, that the output resolution is "small", so they will adapt,
and the final window size will not be doubled all the way unless it
actually fits the output. This happens by the client choosing to draw a
smaller window to begin with, not by scaling, when compared to what it
would do if the default scaling factor was 1. Fractional scaling factors
are simply not needed here, in my opinion.
I agree that fixed is a poor choice here. The alternative is to always
use an int scaling factor, or allow the client to separately specify the
surface size and the buffer size. Both of these guarantee that both
buffer and surface are integers, which I agree with you that they have
to be. Of course, the later means that the actual scaling factor differs
slightly from window to window for fractional scaling due to rounding.

Having started a bit on the implementation in gtk+ and weston it seems
that allowing fractional scales increases the implementation complexity
quite a bit. For instance, having widgets end on non-whole-integer
positions makes clipping and dirty region tracking harder. Another
example is that damage regions on a buffer need not correspond to a
integer region in global coordinates (or vice versa if we define damage
to be in surface coordinates).

On the other hand, It seems that a few OSX users seem to want to use
fractional scaling (in particular the 1.5 scaling from 2880x1800 to
1920x1200 seems very popular even if its not as nice looking as the 2x
one), so there seems to be a demand for it.

I'm more and more likeing the way OSX solves this, i.e. only allow and
expose integer scaling factors in the APIs, but then do fractional
downscaling in the compositor (i.e. say the output is 1920x1200 in
global coords with a scaling factor of two, but actually render this by
scaling the user-supplied buffer by 0.75). It keeps the implementation
and APIs very simple, it does the right thing for the "nice" case of 2x
scaling and it allows the fractional scaling.
Post by Pekka Paalanen
Can we have any use for scales less than one?
I don't think so.
Post by Pekka Paalanen
Also, one issue raised was that if an output has a scaling factor A,
and a buffer has a scaling factor B, then final scaling factor is
rational. To me that is a non-issue. It can only occur for a
misbehaving client, in which case it gets what it deserves, or in a
multi-output case of one surface spanning several non-identical
monitors. I think the latter case it not worth caring about.
Non-identical monitors are not identical, and you get what you happen
to get when you use a single buffer to composite to both.
Yeah, i don't think this is really a practical problem. It'll look
somewhat fuzzy in some construed cases.
Post by Pekka Paalanen
The important thing is to make all client-visible coordinate systems
consistent and logical.
Yeah, i'll try to use these names in the docs and be more clear which
coordinate spaces different requests/events work in.
Post by Pekka Paalanen
And now the questions.
If an output has a scaling factor f, what does the wl_output
report as the output's current and supported video modes?
I believe it should report the resolution in global coordinates.
Although we should maybe extend the mode with scale information. This is
the right thing to do in terms of "backwards compatibility", but it is
also useful for e.g. implementing the fractional scaling. So, a
2880x1800 panel would report that there exists a 1920x1200 at 2x mode,
which wouldn't be possible if we had to report the size in output
coordinates.

It also seems right from a user perspective. The list of resolutions
would be "2880x1800, 1920x1200, 1400x900", which is to a first degree
what users will experience with these modes. Furthermore, this will
allow us to expose "fake" modes for lower resolutions that maybe some
LCD panels don't support (or do with a bad looking scaling), which some
games may want.
Post by Pekka Paalanen
What about x,y in the wl_output.geometry event (which I think are just a
global coordinate space leak that should not be there)?
Yeah, this is in global coords, and seems like a leak.
Post by Pekka Paalanen
The video modes are important because of the
wl_shell_surface.set_fullscreen with method DRIVER. A fullscreen
surface with method DRIVER implies, that the client wants the
compositor to change the video mode to match this surface. Of course
this usually only happens when the fullscreen surface is topmost and
active.
A client can use the list of supported video modes from the wl_output
to choose the size of its fullscreen surface. E.g. if video mode
800x600 is supported, the client may choose to make the fullscreened
surface of size 800x600, and assume that the server ideally switches
the video mode 800x600 to present the surface.
How do buffer_scale and output scale interact with this mechanism?
I think the modes reported should say whether the mode is native or
scaled, so the app can chose whether to use it or not. However, I think
its nice that we can support 800x600 in a scaled version even if the lcd
panel can't drive this natively (or do so poorly). This means you can
run games designed for 800x600 even on that hardware.
Alex Deucher
2013-05-15 13:22:58 UTC
Permalink
Post by Alexander Larsson
Post by Pekka Paalanen
On Tue, 14 May 2013 12:26:48 +0200
Lots of good stuff snipped. I'll try to fix things up based on that.
Some responses below.
Post by Pekka Paalanen
Post by alexl
+ </description>
+ <arg name="scale" type="fixed"/>
Are you sure you really want fixed as the type?
Integer scaling factors sounded a lot more straightforward. When we are
dealing with pixel buffers, integers make sense.
Also, I do not buy the argument, that integer scaling factors are not
finely grained enough. If an output device (monitor) has such a hidpi,
and a user wants the default scaling, then we will simply have an
integer scaling factor >1, for example 2. Clients will correspondingly
somehow see, that the output resolution is "small", so they will adapt,
and the final window size will not be doubled all the way unless it
actually fits the output. This happens by the client choosing to draw a
smaller window to begin with, not by scaling, when compared to what it
would do if the default scaling factor was 1. Fractional scaling factors
are simply not needed here, in my opinion.
I agree that fixed is a poor choice here. The alternative is to always
use an int scaling factor, or allow the client to separately specify the
surface size and the buffer size. Both of these guarantee that both
buffer and surface are integers, which I agree with you that they have
to be. Of course, the later means that the actual scaling factor differs
slightly from window to window for fractional scaling due to rounding.
Having started a bit on the implementation in gtk+ and weston it seems
that allowing fractional scales increases the implementation complexity
quite a bit. For instance, having widgets end on non-whole-integer
positions makes clipping and dirty region tracking harder. Another
example is that damage regions on a buffer need not correspond to a
integer region in global coordinates (or vice versa if we define damage
to be in surface coordinates).
On the other hand, It seems that a few OSX users seem to want to use
fractional scaling (in particular the 1.5 scaling from 2880x1800 to
1920x1200 seems very popular even if its not as nice looking as the 2x
one), so there seems to be a demand for it.
I'm more and more likeing the way OSX solves this, i.e. only allow and
expose integer scaling factors in the APIs, but then do fractional
downscaling in the compositor (i.e. say the output is 1920x1200 in
global coords with a scaling factor of two, but actually render this by
scaling the user-supplied buffer by 0.75). It keeps the implementation
and APIs very simple, it does the right thing for the "nice" case of 2x
scaling and it allows the fractional scaling.
Post by Pekka Paalanen
Can we have any use for scales less than one?
I don't think so.
Post by Pekka Paalanen
Also, one issue raised was that if an output has a scaling factor A,
and a buffer has a scaling factor B, then final scaling factor is
rational. To me that is a non-issue. It can only occur for a
misbehaving client, in which case it gets what it deserves, or in a
multi-output case of one surface spanning several non-identical
monitors. I think the latter case it not worth caring about.
Non-identical monitors are not identical, and you get what you happen
to get when you use a single buffer to composite to both.
Yeah, i don't think this is really a practical problem. It'll look
somewhat fuzzy in some construed cases.
Post by Pekka Paalanen
The important thing is to make all client-visible coordinate systems
consistent and logical.
Yeah, i'll try to use these names in the docs and be more clear which
coordinate spaces different requests/events work in.
Post by Pekka Paalanen
And now the questions.
If an output has a scaling factor f, what does the wl_output
report as the output's current and supported video modes?
I believe it should report the resolution in global coordinates.
Although we should maybe extend the mode with scale information. This is
the right thing to do in terms of "backwards compatibility", but it is
also useful for e.g. implementing the fractional scaling. So, a
2880x1800 panel would report that there exists a 1920x1200 at 2x mode,
which wouldn't be possible if we had to report the size in output
coordinates.
It also seems right from a user perspective. The list of resolutions
would be "2880x1800, 1920x1200, 1400x900", which is to a first degree
what users will experience with these modes. Furthermore, this will
allow us to expose "fake" modes for lower resolutions that maybe some
LCD panels don't support (or do with a bad looking scaling), which some
games may want.
Just a note that a lot of drivers already expose "fake" scaled modes
using the scalers in the display hardware for fixed mode panels so
you'll have to differentiate whether you want the display hardware or
wayland to do the scaling.

Alex
Post by Alexander Larsson
Post by Pekka Paalanen
What about x,y in the wl_output.geometry event (which I think are just a
global coordinate space leak that should not be there)?
Yeah, this is in global coords, and seems like a leak.
Post by Pekka Paalanen
The video modes are important because of the
wl_shell_surface.set_fullscreen with method DRIVER. A fullscreen
surface with method DRIVER implies, that the client wants the
compositor to change the video mode to match this surface. Of course
this usually only happens when the fullscreen surface is topmost and
active.
A client can use the list of supported video modes from the wl_output
to choose the size of its fullscreen surface. E.g. if video mode
800x600 is supported, the client may choose to make the fullscreened
surface of size 800x600, and assume that the server ideally switches
the video mode 800x600 to present the surface.
How do buffer_scale and output scale interact with this mechanism?
I think the modes reported should say whether the mode is native or
scaled, so the app can chose whether to use it or not. However, I think
its nice that we can support 800x600 in a scaled version even if the lcd
panel can't drive this natively (or do so poorly). This means you can
run games designed for 800x600 even on that hardware.
_______________________________________________
wayland-devel mailing list
wayland-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel
Loading...