<div dir="ltr"><div><div>You are correct that it is equally valid to convert buffer_damage coordinates to surface coordinates and store the union of those.<br><br></div><div>More importantly, I think you are correct that the "new" transform should be used. Ideally the last transform the client sent (even though it is not committed yet). I made a mistake of thinking you had to use the old transform to go from surface to buffer coordinates, that was wrong. This also means that the compositor only has to track the current transformation and only has to keep one copy of it that is replaced when it gets the request, so it is probably the simplest.<br><br></div><div>I figure clients will send damage rectangles produced by their drawing toolkit as damage requests, which are necessarily in buffer coordinates. If the client is correctly implemented and using wl_surface.damage, it will transform this from buffer coordinates to surface coordinates.<br><br>My belief is that most clients are written on the assumption that the compositor immediately transforms these back, and therefore have to use any transform they already have and cannot use a transform that was not sent yet. So it probably uses whatever transform it just sent. Although allowing the final composite to be performed on only a region is really nice, I suspect the main advantage of buffer damage is to reduce the size of the rectangle copied from the buffer to gpu texture memory, which is why I always figured buffer coordinates are more useful for compositors and why clients would assume compositors would immediately translate back.<br><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 20, 2015 at 6:37 PM, Derek Foreman <span dir="ltr"><<a href="mailto:derekf@osg.samsung.com" target="_blank">derekf@osg.samsung.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 20/11/15 07:39 PM, Bill Spitzak wrote:<br>
> I am pretty certain you can just convert wl_surface.damage coordinates<br>
> *to* buffer coordinates, using the transform the old buffer was attached<br>
> with, and thus merge all the wl_surface.damage and<br>
> wl_surface.damage_buffer into a single region in buffer space.<br>
<br>
</span>Yep, that should be fine.  We have all the code to do that already since<br>
we previously stored damage in surface co-ords exclusively and gl<br>
texture uploads needed buffer co-ordinates.<br>
<br>
We need the co-ordinates in both spaces regardless - surface as a step<br>
to screen space co-ordinates for that damage, and buffer for texture damage.<br>
<br>
I chose to convert buffer space co-ordinates to screen space since all<br>
the existing code used screen space.  I just dumped it all into the<br>
accumulated surface space region after the buffer to surface matrix was<br>
set up.<br>
<span class=""><br>
> If the transformation does not change, you can back-transform this<br>
> region into the changed region in screen space.<br>
><br>
> You seem to be worried about what happens if the transformation is<br>
> different between the old and new buffers. But in that case the<br>
> on-screen changed area is the union of the entire old buffer with it's<br>
> old transform and the new buffer with it's new transform. The damage<br>
> region is ignored when figuring out the screen-space damage so it does<br>
> not matter what it was set to.<br>
<br>
</span>Well, I'm somewhat concerned about loss of precision due to the double<br>
transform - but I think the matrices we're working with should be ok for<br>
that.<br>
<br>
I'm also annoyed that wasted math gets done (buffer to surface and back<br>
again), but I think avoiding that wasted transform is probably far more<br>
code complexity than is worthwhile to eliminate what's not very much math.<br>
<br>
I'm actually not bothered by the transform being changed - I think we<br>
just have to specify that all damage is posted in the "new co-ordinates"<br>
that the rest of the commit sets up, then we don't have to worry.<br>
<br>
We do have an existing bug - either in simple-damage or weston - where<br>
changing transformations results in bad damage.  weston-simple-damage<br>
--rotating-transform shows this. This has been around before<br>
damage_buffer existed, so I haven't bothered to dig into it yet.<br>
<br>
Now that I think of it, I think the client's posting bad damage - it's<br>
posting the remove for the old bouncing-green-ball and the arrival of<br>
the new frame of bouncing-green-ball as if they were in the same<br>
co-ordinate space.<br>
<span class=""><br>
> If a client actually sends the "correct" wl_surface.damage for a<br>
> transform change, it will be a region that translates to cover the<br>
> entire old buffer. This may be excessive but is harmless.<br>
<br>
</span>Nod.  I guess some of our trivial test apps (simple-damage has a fixed<br>
white border) could preserve some buffer content over certain transform<br>
changes, but in the real world I can't imagine anyone trying to do this.<br>
<span class=""><br>
> I suppose rotating a perfectly square buffer which is filled with a<br>
> solid color could, under the old system, turn into no damage, while the<br>
> new one will not know (unless it compares the buffers) and damage an<br>
> unchanged area. However this seems really trivial. Any client that<br>
> actually tries to do this correctly with wl_surface.damage will send a<br>
> region that necessarily translates to something that includes all the<br>
> damage to the buffer.<br>
<br>
</span>You just broke my head. :)<br>
<br>
I think we agree that on a transform change any app (that isn't<br>
impossibly clever) doing the right thing will damage its entire buffer<br>
or its entire surface, depending on which request it chooses.  And that<br>
the end result should be the same regardless which they chose.<br>
<br>
I may be missing some trick in that last paragraph, but I don't think<br>
it's one that could be usefully leveraged by a real world client?<br>
<br>
Maybe this takes us back to the simple-damage bug.  Even if it<br>
translated the damage from the previous frame to the new frame space and<br>
posted damage "properly", it would still be broken with the GL renderer<br>
because the buffer damage wouldn't be properly accounted for.<br>
<br>
The pixman renderer doesn't need the buffer damage (no texture upload),<br>
so it might actually draw the right thing if the surface damage were<br>
correct.<br>
<br>
It's far too late on a Friday to verify any of this.  I'll report back<br>
sometime next week. ;)<br>
<br>
Thanks,<br>
Derek<br>
<span class=""><br>
> On Fri, Nov 20, 2015 at 1:49 PM, Derek Foreman <<a href="mailto:derekf@osg.samsung.com">derekf@osg.samsung.com</a><br>
</span><div><div class="h5">> <mailto:<a href="mailto:derekf@osg.samsung.com">derekf@osg.samsung.com</a>>> wrote:<br>
><br>
>     wl_surface.damage uses surface local co-ordinates.<br>
><br>
>     Buffer scale and buffer transforms came along, and EGL surfaces<br>
>     have no understanding of them.<br>
><br>
>     Theoretically, clients pass damage rectangles - in Y-inverted surface<br>
>     co-ordinates) to EGLSwapBuffersWithDamage, and the EGL implementation<br>
>     passed them on to wayland.  However, for this to work the EGL<br>
>     implementation must be able to flip those rectangles into the space<br>
>     the compositor is expecting, but it's unable to do so because it<br>
>     doesn't know the height of the transformed buffer.<br>
><br>
>     So, currently, EGLSwapBuffersWithDamage is unusable and EGLSwapBuffers<br>
>     has to pass (0,0) - (INT32_MAX, INT32_MAX) damage to function.<br>
><br>
>     wl_surface.damage_buffer allows damage to be registered on a surface<br>
>     in buffer co-ordinates, avoiding this problem.<br>
><br>
>     Credit where it's due, these ideas are not entirely my own:<br>
>     Over a year ago the idea of changing damage co-ordinates to buffer<br>
>     co-ordinates was suggested (by Jason Ekstrand), and it was at least<br>
>     partially rejected and abandoned.  At the time it was also suggested<br>
>     (by Pekka Paalanen) that adding a new wl_surface.damage_buffer request<br>
>     was another option.<br>
><br>
>     This will eventually resolve:<br>
>     <a href="https://bugs.freedesktop.org/show_bug.cgi?id=78190" rel="noreferrer" target="_blank">https://bugs.freedesktop.org/show_bug.cgi?id=78190</a><br>
>     by making the problem irrelevant.<br>
><br>
>     Signed-off-by: Derek Foreman <<a href="mailto:derekf@osg.samsung.com">derekf@osg.samsung.com</a><br>
</div></div>>     <mailto:<a href="mailto:derekf@osg.samsung.com">derekf@osg.samsung.com</a>>><br>
<div><div class="h5">>     ---<br>
><br>
>     New change: Explain that damages can't be combined until commit<br>
><br>
>     Also, copy the new wl_surface.damage text that doesn't require attach<br>
>     to be before damage<br>
><br>
>     (enough text is new that I haven't carried over any RBs)<br>
><br>
>      protocol/wayland.xml | 48<br>
>     ++++++++++++++++++++++++++++++++++++++++++++++--<br>
>      1 file changed, 46 insertions(+), 2 deletions(-)<br>
><br>
>     diff --git a/protocol/wayland.xml b/protocol/wayland.xml<br>
>     index 525e092..4d75f39 100644<br>
>     --- a/protocol/wayland.xml<br>
>     +++ b/protocol/wayland.xml<br>
>     @@ -176,7 +176,7 @@<br>
>          </event><br>
>        </interface><br>
><br>
>     -  <interface name="wl_compositor" version="3"><br>
>     +  <interface name="wl_compositor" version="4"><br>
>          <description summary="the compositor singleton"><br>
>            A compositor.  This object is a singleton global.  The<br>
>            compositor is in charge of combining the contents of multiple<br>
>     @@ -986,7 +986,7 @@<br>
>          </event><br>
>        </interface><br>
><br>
>     -  <interface name="wl_surface" version="3"><br>
>     +  <interface name="wl_surface" version="4"><br>
>          <description summary="an onscreen surface"><br>
>            A surface is a rectangular area that is displayed on the screen.<br>
>            It has a location, size and pixel contents.<br>
>     @@ -1109,6 +1109,10 @@<br>
>             wl_surface.commit assigns pending damage as the current damage,<br>
>             and clears pending damage. The server will clear the current<br>
>             damage as it repaints the surface.<br>
>     +<br>
>     +       Alternatively, damage can be posted with<br>
>     wl_surface.damage_buffer<br>
>     +       which uses buffer co-ordinates instead of surface co-ordinates,<br>
>     +       and is probably the preferred and intuitive way of doing this.<br>
>            </description><br>
><br>
>            <arg name="x" type="int"/><br>
>     @@ -1325,6 +1329,46 @@<br>
>            </description><br>
>            <arg name="scale" type="int"/><br>
>          </request><br>
>     +<br>
>     +    <!-- Version 4 additions --><br>
>     +    <request name="damage_buffer" since="4"><br>
>     +      <description summary="mark part of the surface damaged using<br>
>     buffer co-ordinates"><br>
>     +       This request is used to describe the regions where the pending<br>
>     +       buffer is different from the current surface contents, and where<br>
>     +       the surface therefore needs to be repainted. The compositor<br>
>     +       ignores the parts of the damage that fall outside of the<br>
>     surface.<br>
>     +<br>
>     +       Damage is double-buffered state, see wl_surface.commit.<br>
>     +<br>
>     +       The damage rectangle is specified in buffer coordinates.<br>
>     +<br>
>     +       The initial value for pending damage is empty: no damage.<br>
>     +       wl_surface.damage_buffer adds pending damage: the new pending<br>
>     +       damage is the union of old pending damage and the given<br>
>     rectangle.<br>
>     +<br>
>     +       wl_surface.commit assigns pending damage as the current damage,<br>
>     +       and clears pending damage. The server will clear the current<br>
>     +       damage as it repaints the surface.<br>
>     +<br>
>     +       This request differs from wl_surface.damage in only one way - it<br>
>     +       takes damage in buffer co-ordinates instead of surface local<br>
>     +       co-ordinates.  While this generally is more intuitive than<br>
>     surface<br>
>     +       co-ordinates, it is especially desirable when using wp_viewport<br>
>     +       or when a drawing library (like EGL) is unaware of buffer scale<br>
>     +       and buffer transform.<br>
>     +<br>
>     +       Since it is impossible to convert between buffer and surface<br>
>     +       co-ordinates until the late stages of wl_surface.commit,<br>
>     +       damage from wl_surface.damage and wl_surace.damage_buffer must<br>
>     +       be accumulated separately and only combined during<br>
>     +       wl_surface.commit.<br>
>     +      </description><br>
>     +<br>
>     +      <arg name="x" type="int"/><br>
>     +      <arg name="y" type="int"/><br>
>     +      <arg name="width" type="int"/><br>
>     +      <arg name="height" type="int"/><br>
>     +    </request><br>
>         </interface><br>
><br>
>        <interface name="wl_seat" version="5"><br>
>     --<br>
>     2.6.2<br>
><br>
>     _______________________________________________<br>
>     wayland-devel mailing list<br>
>     <a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a><br>
</div></div>>     <mailto:<a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.freedesktop.org</a>><br>
>     <a href="http://lists.freedesktop.org/mailman/listinfo/wayland-devel" rel="noreferrer" target="_blank">http://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
><br>
><br>
<br>
</blockquote></div><br></div>