Re: Best practices for client side buffer management

2020-07-02 Thread Guillermo Rodriguez Garcia
Hi Brad,

El vie., 19 jun. 2020 a las 5:24, Brad Robinson
() escribió:
[...]
>
> Finally, the toolkit already maintains an off-screen buffer with the window's 
> current contents rendered into it.  I'll probably replace that with a Wayland 
> buffer, but wondering about partial updates.  eg: if the client only needs to 
> redraw a part of the window what's the correct process to update just that 
> part with Wayland.  Can I just update the existing buffer and prompt Wayland 
> to just redraw that part?

I am facing a similar situation with a toolkit that maintains an
off-screen buffer with the current window contents, and will update
that buffer at arbitrary times, when the application needs to update
the UI.

You must consider the following:

Once you submit a buffer to Wayland you cannot touch it anymore until
the compositor releases it back (wl_buffer.release callback). From
Pekka's email:

> When you submit a buffer to a Wayland compositor, it gives the
> compositor permission to read the buffer at any time, as many times as
> it wants to, until it tells you with wl_buffer.release that it will not
> be looking at that buffer again. You must not write to a buffer that
> might be read by the compositor, as that can cause misrendering on
> screen (e.g. your repaint is shown unfinished).

This means you cannot simply use the same off-screen buffer that the
toolkit maintains, since the toolkit should not update the buffer once
it submits it to Wayland.

At some point I thought that I could have separate Wayland buffers and
copy damaged regions from the toolkit buffer to one of these Wayland
buffers before submitting it to the compositor.
The idea would be to copy the set of regions that were damaged since
the last update.

But just copying damaged regions is not enough either. From Pekka's email:

> Also, every buffer you submit must be fully drawn, also outside of the
> areas you mark as damage. The compositor may be reading more than just
> the damage you submit.

So this means that everytime the toolkit updates the off-screen
buffer, I may need to copy _the entire thing_ to a Wayland buffer and
submit it to the compositor... not very efficient I guess.

I have the feeling that Wayland is designed for a model where the
client renders the entire frame on demand (most of the examples I've
found so far work like this) and not for a model where the client is
updating a buffer asynchronously and you just want to tell the
compositor to update parts of the frame.

I would be very interested to learn about your solution to this problem.

Best,

Guillermo Rodriguez Garcia
guille.rodrig...@gmail.com
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: Best practices for client side buffer management

2020-06-24 Thread Pekka Paalanen
On Wed, 24 Jun 2020 23:45:56 +1000
Brad Robinson  wrote:

> Hi Pekka,
> 
> > The problem is, the compositor might not release the buffer until
> > you have already submitted a new one.
> >  
> 
> OK... good to know that approach won't work.
> 
> I guess what I'm trying to figure out (and probably won't solve completely
> till I actually sit down and code it) is how to avoid the software
> rendering part of it as much as possible.  My app can have a complex and
> deep tree of UI elements so I think it's worth trying to avoid additional
> render calls into that tree as much as possible - or at least clip it down
> to just the dirty rectangles.  But this requires the rest of the current
> buffer be kept up to date.  Presumably if there's a cycle of buffers being
> used this would mean either re-rendering certain UI  elements multiple
> times, or copying dirty rectangles from previously rendered frame buffers
> to the one about to be updated.

Hi Brad,

if you limit your render call rate to wl_surface.frame callbacks, then
that should be quite optimal. IOW, don't render when your scene state
changes. Render when you want to submit an update to display.

Your damage regions can be arbitrary, right? Not just one or few
rectangles? Arbitrary regions can be unioned before doing the one
render call for the whole frame. E.g. Weston uses Pixman library for
region computations, the same library that Xorg uses.

Since the Wayland client is in full control of buffer management (while
it should also honour the compositor's reading), you can guarantee that
the buffers keep their old contents the way you want it. In
steady-state, a client will usually be flipping between two buffers, or
re-using a single buffer if the compositor allows. You should be able
to reach a very good content re-use percentage even by rendering the UI
tree straight into Wayland buffers.

You can choose whether you copy the "historical" damage from the latest
buffer or just render it from the UI tree. You would have to go way out
of your way to manage creating buffers where the copying would hurt
performance.

> I'm not sure if this is a valid or even useful question but: once I've
> submitted a buffer to the compositor can I assume the previously submitted
> buffer will be returned imminently?

You can't assume that in the way that your program would freeze or
malfunction if the assumption is violated. There are various reasons
why a compositor might keep more than one buffer busy. Transiently it
can happen for reasons you should not care about, indefinitely it can
happen by client request (e.g. sub-surfaces in sync mode, no commit on
parent surface).

However, there are also reasonable expectations, like the maximum of 4
buffers you might need to allocate for one surface and allocating more
than that should not be necessary in practise. It's hard to imagine a
compositor scenario where it would keep all 4 buffers busy indefinitely.

> The rest of this discussion got a bit beyond me (although I will need to
> support OpenGL eventually).

Ok. When you do go with OpenGL, you will be using EGL. Make note of the
EGL extensions I linked to previously, they should help get the
equivalent buffer re-use going as talked about here. The thing about
EGL is that you will never see the wl_buffer objects, all buffer
management is hidden inside the Wayland-client-side EGL implementation.
That's why you need e.g. EXT_buffer_age extension if you mean to
efficiently re-use buffers.

Luckily, continuously allocating and destroying buffers is expensive,
so you can expect a reasonable EGL implementation to re-use existing
buffers on the EGLSurface allowing EXT_buffer_age to be useful.

There is a way to get a buffer out of EGL and then manually shovel it
through Wayland, but for a normal application I wouldn't recommend it.
It's a bunch of special code to write for no benefit.

> 
> Thanks everyone for insights... much appreciated.

You're welcome. All this should really have been written in the Wayland
documentation, but there's always something else to do...


Thanks,
pq


pgpinJ31Tuz49.pgp
Description: OpenPGP digital signature
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: Best practices for client side buffer management

2020-06-24 Thread Brad Robinson
Hi Pekka,

The problem is, the compositor might not release the buffer until
> you have already submitted a new one.
>

OK... good to know that approach won't work.

I guess what I'm trying to figure out (and probably won't solve completely
till I actually sit down and code it) is how to avoid the software
rendering part of it as much as possible.  My app can have a complex and
deep tree of UI elements so I think it's worth trying to avoid additional
render calls into that tree as much as possible - or at least clip it down
to just the dirty rectangles.  But this requires the rest of the current
buffer be kept up to date.  Presumably if there's a cycle of buffers being
used this would mean either re-rendering certain UI  elements multiple
times, or copying dirty rectangles from previously rendered frame buffers
to the one about to be updated.

I'm not sure if this is a valid or even useful question but: once I've
submitted a buffer to the compositor can I assume the previously submitted
buffer will be returned imminently?

The rest of this discussion got a bit beyond me (although I will need to
support OpenGL eventually).

Thanks everyone for insights... much appreciated.

Brad

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


Re: Best practices for client side buffer management

2020-06-24 Thread Pekka Paalanen
On Wed, 24 Jun 2020 13:35:12 +0200
Sebastian Wick  wrote:

> On 2020-06-24 13:14, Pekka Paalanen wrote:
> > On Wed, 24 Jun 2020 19:17:57 +1000
> > Brad Robinson  wrote:
> >   

> >> 1. the compositor doesn't change the contents of the buffer and that 
> >> when
> >> it's returned it's still got the old content.  
> > 
> > With Wayland, wl_surface.attach does not allow the compositor to write
> > into the buffer, it only allows reading. So that is safe, also because
> > the client manages its own buffers (allocate, re-use, destroy).  
> 
> Isn't this a little bit more subtle? In particular if you use OpenGL in
> the compositor to access the image there might be layout transitions
> which change the image in place.
> 
> So while the buffer is owned by the compositor the client must not read
> or write to it and when the ownership is transferred back to the client
> the image might be in another layout.
> 
> Or am I missing something here?

Well, graphics is all about lying after all. If no-one can observe it,
it's cool.

Hardware buffers will be read through the appropriate rendering APIs
anyway, so if there is any tricks going on, the driver will make sure
to maintain the illusion.

It's nothing a toolkit developer needs to be concerned with, and it
definitely does not apply to software rendering.

Besides, if the client re-uses the buffer, there is no public protocol
that would demand updating the metadata about it, so the next time the
compositor imports it, it will use the original DRM modifier etc.


Thanks,
pq


pgpQRhEMNoNwN.pgp
Description: OpenPGP digital signature
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: Best practices for client side buffer management

2020-06-24 Thread Sebastian Wick

On 2020-06-24 13:14, Pekka Paalanen wrote:

On Wed, 24 Jun 2020 19:17:57 +1000
Brad Robinson  wrote:


Hi All,

@Guillermo: yep, that's exactly the same problem I'm thinking about.


Hi,

I answered to Guillermo as well further down.


I had an idea that I'm wondering about  the rendering model in my
toolkit is essentially the same as Windows/OSX - where the application
invalidates part of the window, and then at some later point the OS 
calls
back with a message prompting the app to paint that part of the 
screen.
ie: multiple invalidate calls are coalesced into a single paint call 
at a
later time - typically just before entering the message loop's idle 
state.


Could a Wayland app mimic this behaviour by having a single background
buffer that contains the current window content?  When the application
invalidates the window it does one of two things depending on whether 
the

buffer has been returned from the compositor yet.

* If the buffer has been returned and no longer in use by the 
compositor,

it queues a paint message to itself.

* If the buffer hasn't been returned and is still in use by the 
compositor,
set a flag on the window.  When the buffer is returned from the 
compositor,
it checks that flag and if set then it clears the flag and queues the 
paint

message.


The problem is, the compositor might not release the buffer until
you have already submitted a new one.

A compositor, that textures directly from the buffer you submitted as a
client, cannot release the buffer until it gets a new buffer to replace
it. A compositor may repaint at any time for any reason, so it must
always have window content (some buffer) available. Compare this to X11
expose events: expose events require the client to draw the damaged
area and until it does, the display will have garbage there. A Wayland
compositor handles expose events completely internally, which means
that no such garbage is ever shown on display.

You can of course keep a shadow buffer as the main buffer, and copy
appropriately to Wayland buffers when you update, but it consumes an
extra buffer obviously.

It would be preferable if your widget tree / scenegraph was able to
draw arbitrary regions from scratch to arbitrary buffers on-demand, and 
not

autonomously at "random" times, so you can draw directly into Wayland
buffers exactly the parts that need drawing. Then you would also never
throw any drawing away without showing it, so it's also an energy usage
optimization.

It's not actually that different from the window invalidation you
describe, except it will be all completely internal to your toolkit and
"the window" is actually "a buffer", and you need to keep track of
damage history as well. More on that below.


The paint message redraws all the invalidated (damaged) rectangles and
re-submits it to the compositor and the whole cycle starts again.

Obviously there's more logic around maintaining the dirty region,
coalescing multiple invalidate/damage calls, an assumption that 
there's a
mechanism to post a message via the message loop etc... but I hope 
this

explains the idea.

Would this work?  I think the main requirement would be that:

1. the compositor doesn't change the contents of the buffer and that 
when

it's returned it's still got the old content.


With Wayland, wl_surface.attach does not allow the compositor to write
into the buffer, it only allows reading. So that is safe, also because
the client manages its own buffers (allocate, re-use, destroy).


Isn't this a little bit more subtle? In particular if you use OpenGL in
the compositor to access the image there might be layout transitions
which change the image in place.

So while the buffer is owned by the compositor the client must not read
or write to it and when the ownership is transferred back to the client
the image might be in another layout.

Or am I missing something here?

2. that the compositor returns buffers it's finished with in a timely 
manner


This is false as described above.

It's not clear to me from what I've read that either of these points 
are

true or safe assumptions.

This would eliminate the need to manage multiple buffers, multiple 
dirty
regions, the need to copy previously rendered content between buffers 
and

fits nicely with the rendering model of Windows/OSX giving similar
semantics on all platforms.


Unfortunately you cannot avoid multi-buffering in a client that aims to
be correct.

If Wayland dictated that clients must be able to run fine with just one
buffer per window, then quite likely the compositor would be forced to
maintain a full copy of the window contents, or it would not be able to
refresh the screen at all times, or it might end up showing
transitional garbage (glitch).

The Wayland design principle is "every frame is perfect", which more or
less leads to "never show garbage", and "never stall waiting for
clients to respond".



On Wed, Jun 24, 2020 at 6:11 PM Guillermo Rodriguez Garcia <

Re: Best practices for client side buffer management

2020-06-24 Thread Carsten Haitzler
On Wed, 24 Jun 2020 14:28:18 +0300 Pekka Paalanen  said:

> On Wed, 24 Jun 2020 10:58:41 +0100
> Carsten Haitzler (The Rasterman)  wrote:
> 
> > you keep a sliding window of the last 2 frames with of rect regions you
> > union (merge with) the current frame's update rects... then render that.
> > you can play tricks like copy back some regions from a previous frame
> > instead of re-rendering them (as it's a read from, not a write to that
> > buffer it's safe..
> 
> Yes, copying from a busy buffer is safe.
> 
> > but beware that readbacks may have issues especially if regions are not
> > mapped as non-cachable because they are being scanned out/displayed for
> > example. it depends on hardware entirely so the safe thing is to their
> > shadow them and make a copy before you display or just re-render them. it
> > turns out the just re-render is simpler to do and generally performant).
> 
> You said you were going to cover only software-rendering, but here you
> go. ;-)

you can software render to hardware mappable buffers... quite common if you
have a system with no GPU - just a simple display processor with a single
fraembuffer output or maybe a few layers/sprites or perhaps just a 2d
accel unit (blitter funtimes)... :) my point was more that you have explicit
control over the ABC buffer ordering as opposed to going via gl (egl) where you
don't have control and have to query and hope for sanity... :)

> IOW, the caching thing applies to hardware buffers (some of which can
> be written to by CPU). But a usual desktop application or a toolkit
> should not use hardware buffers for software rendering. The performance
> hit you refer to can also happen in the compositor!

correct. so it depends on the situation, but also how to map the buffer at the
time and other hardware constraints. i've had to beat some interesting hardware
into shape before. if 99% of the time the compositor just displays a frame
(assigns the buffer to a hw scanout) then the readback problem is not bad and
only hits you sometimes. it's a whole ymmv and just something to know about if
you are poking around in this world. :)


-- 
- Codito, ergo sum - "I code, therefore I am" --
Carsten Haitzler - ras...@rasterman.com

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


Re: Best practices for client side buffer management

2020-06-24 Thread Pekka Paalanen
On Wed, 24 Jun 2020 10:58:41 +0100
Carsten Haitzler (The Rasterman)  wrote:

> you keep a sliding window of the last 2 frames with of rect regions you union
> (merge with) the current frame's update rects... then render that. you can 
> play
> tricks like copy back some regions from a previous frame instead of
> re-rendering them (as it's a read from, not a write to that buffer it's safe..

Yes, copying from a busy buffer is safe.

> but beware that readbacks may have issues especially if regions are not mapped
> as non-cachable because they are being scanned out/displayed for example. it
> depends on hardware entirely so the safe thing is to their shadow them and 
> make
> a copy before you display or just re-render them. it turns out the just
> re-render is simpler to do and generally performant).

You said you were going to cover only software-rendering, but here you
go. ;-)

IOW, the caching thing applies to hardware buffers (some of which can
be written to by CPU). But a usual desktop application or a toolkit
should not use hardware buffers for software rendering. The performance
hit you refer to can also happen in the compositor!


Thanks,
pq


pgpzSj0C97GmX.pgp
Description: OpenPGP digital signature
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: Best practices for client side buffer management

2020-06-24 Thread Pekka Paalanen
On Wed, 24 Jun 2020 19:17:57 +1000
Brad Robinson  wrote:

> Hi All,
> 
> @Guillermo: yep, that's exactly the same problem I'm thinking about.

Hi,

I answered to Guillermo as well further down.

> I had an idea that I'm wondering about  the rendering model in my
> toolkit is essentially the same as Windows/OSX - where the application
> invalidates part of the window, and then at some later point the OS calls
> back with a message prompting the app to paint that part of the screen.
> ie: multiple invalidate calls are coalesced into a single paint call at a
> later time - typically just before entering the message loop's idle state.
> 
> Could a Wayland app mimic this behaviour by having a single background
> buffer that contains the current window content?  When the application
> invalidates the window it does one of two things depending on whether the
> buffer has been returned from the compositor yet.
> 
> * If the buffer has been returned and no longer in use by the compositor,
> it queues a paint message to itself.
> 
> * If the buffer hasn't been returned and is still in use by the compositor,
> set a flag on the window.  When the buffer is returned from the compositor,
> it checks that flag and if set then it clears the flag and queues the paint
> message.

The problem is, the compositor might not release the buffer until
you have already submitted a new one.

A compositor, that textures directly from the buffer you submitted as a
client, cannot release the buffer until it gets a new buffer to replace
it. A compositor may repaint at any time for any reason, so it must
always have window content (some buffer) available. Compare this to X11
expose events: expose events require the client to draw the damaged
area and until it does, the display will have garbage there. A Wayland
compositor handles expose events completely internally, which means
that no such garbage is ever shown on display.

You can of course keep a shadow buffer as the main buffer, and copy
appropriately to Wayland buffers when you update, but it consumes an
extra buffer obviously.

It would be preferable if your widget tree / scenegraph was able to
draw arbitrary regions from scratch to arbitrary buffers on-demand, and not
autonomously at "random" times, so you can draw directly into Wayland
buffers exactly the parts that need drawing. Then you would also never
throw any drawing away without showing it, so it's also an energy usage
optimization.

It's not actually that different from the window invalidation you
describe, except it will be all completely internal to your toolkit and
"the window" is actually "a buffer", and you need to keep track of
damage history as well. More on that below.

> The paint message redraws all the invalidated (damaged) rectangles and
> re-submits it to the compositor and the whole cycle starts again.
> 
> Obviously there's more logic around maintaining the dirty region,
> coalescing multiple invalidate/damage calls, an assumption that there's a
> mechanism to post a message via the message loop etc... but I hope this
> explains the idea.
> 
> Would this work?  I think the main requirement would be that:
> 
> 1. the compositor doesn't change the contents of the buffer and that when
> it's returned it's still got the old content.

With Wayland, wl_surface.attach does not allow the compositor to write
into the buffer, it only allows reading. So that is safe, also because
the client manages its own buffers (allocate, re-use, destroy).

> 2. that the compositor returns buffers it's finished with in a timely manner

This is false as described above.

> It's not clear to me from what I've read that either of these points are
> true or safe assumptions.
> 
> This would eliminate the need to manage multiple buffers, multiple dirty
> regions, the need to copy previously rendered content between buffers and
> fits nicely with the rendering model of Windows/OSX giving similar
> semantics on all platforms.

Unfortunately you cannot avoid multi-buffering in a client that aims to
be correct.

If Wayland dictated that clients must be able to run fine with just one
buffer per window, then quite likely the compositor would be forced to
maintain a full copy of the window contents, or it would not be able to
refresh the screen at all times, or it might end up showing
transitional garbage (glitch).

The Wayland design principle is "every frame is perfect", which more or
less leads to "never show garbage", and "never stall waiting for
clients to respond".


> On Wed, Jun 24, 2020 at 6:11 PM Guillermo Rodriguez Garcia <
> guille.rodrig...@gmail.com> wrote:  
> 
> > Hi Brad,
> >
> > El vie., 19 jun. 2020 a las 5:24, Brad Robinson
> > () escribió:
> > [...]  
> > >
> > > Finally, the toolkit already maintains an off-screen buffer with the  
> > window's current contents rendered into it.  I'll probably replace that
> > with a Wayland buffer, but wondering about partial updates.  eg: if the
> > client only needs to redraw a 

Re: Best practices for client side buffer management

2020-06-24 Thread The Rasterman
On Wed, 24 Jun 2020 19:17:57 +1000 Brad Robinson 
said:

EFL has the same model - it tracks damage rects (either sent by expose/damage
events from windowing system combined with a set of rect regions it calculates
itself based on previous frame state vs current frame state and which
exposed/visible regions needed updating and it can do "just re-render a
blinking cursor" region without a full buffer render. you just needs to handle
a set of buffers and partial updates properly. it can also be done with opengl
(using the  buffer age extension and also hinting to the compositor/display
system which regions changed with swap with damage regions too, but it's the
same idea as with software rendering so i'll just cover software).

so you keep a set of buffers. A, B, C. at a minimum A and B, but ABC is the
best.

you fully render A, then display it. you then render all of B and display, then
all of C and display. you now have 3 fully rendered buffers. you will be in a
steady state like this through 99.999% of the life of a window (unless it
resizes where we begin with a new set of buffers, or we do fun things like
drop all buffers but the visible one to compact memory usage).

from now on, let us call the set of rectangles that define the regions rendered
as Ar, Br and Cr per buffer. every time we need to render a frame we are doing
frames in order ABCABCABCABCA... etc.

that means we have the calculated "these areas need updating" ArBrCrArBrCr...
etc. ..

so those are the regions you actually calculate to ne re-rendered. it's the
minimum update area to cover changes. to do this right though you have to
actually over-render. so let us call the set of rects that you REALLY render
and tell the compositor you updated as u. so we have AuBuCuAuBuCu... let us say
+ is the UNION of 2 rect regions.

current u == current r + previous r + previous - 1 r.

so: Cu = Cr + Br + Ar
then next frame is A again: Au = Ar + Cr + Br
then: Br = Br + Ar + Cr

etc

you keep a sliding window of the last 2 frames with of rect regions you union
(merge with) the current frame's update rects... then render that. you can play
tricks like copy back some regions from a previous frame instead of
re-rendering them (as it's a read from, not a write to that buffer it's safe..
but beware that readbacks may have issues especially if regions are not mapped
as non-cachable because they are being scanned out/displayed for example. it
depends on hardware entirely so the safe thing is to their shadow them and make
a copy before you display or just re-render them. it turns out the just
re-render is simpler to do and generally performant).

so basically you need to start thinking of a ring of buffers and managing
those and tracking updates over multiple frames... then you can happily do
fairly minimal "only update this region" drawing. i've been doing this for
many years .. even in X11. it's not a wayland specific thing. you will HAVE
to do this if you want to do partial updates with acceleration like with
opengl :) it works...

this all removes the need for copies and allows zero-copy minimum region
partial updates. :)

p.s.  reason for 3 buffers is to allow for the compositor having not released
the current front buffer yet. compositor can hold onto its buffer. you can have
already sent/submitted a new buffer that's waiting on the compositor to notice
and pick up, and in the meantime you still have a 3rd buffer you can prepare
another frame on while the one in flight arrives and the compositor releases
what it has.

you will need to come up with solutions for if you render this, submit it then
the compositor is still hanging onto its buffer now with 2 in flight. at this
point you can block or "defer" the frame until the 3rd buffer is released, or
perhaps just don't submit a new buffer until the first buffer was released.
then you can just render AGAIN to the 3rd buffer that you have not sent yet,
updating it and now you only render the partial update regions on this one
since the last frame... keep going until compositor releases the first buffer.

i prefer the first method of "defer the rendering and don't render anything
until we get the in-flight buffer to the compositor AND it releases the current
one as this avoids getting too far ahead of the compositor and avoids rendering
possibly useless frames that will never be displayed because the compositor is
having a hiccup and blocking for a few hundred ms - on a heavily loaded system
either cpu or gpu wise its better to back off and not just render more frames
and give things space to get past the spike of work. using the frame requests
from the compositor is a way of this all working out well as compositor calls
you saying "i need a new frame now" and this serves as a kind of throttling in
these cases anyway.

> Hi All,
> 
> @Guillermo: yep, that's exactly the same problem I'm thinking about.
> 
> I had an idea that I'm wondering about  the rendering model in my
> toolkit is essentially the 

Re: Best practices for client side buffer management

2020-06-24 Thread Brad Robinson
Hi All,

@Guillermo: yep, that's exactly the same problem I'm thinking about.

I had an idea that I'm wondering about  the rendering model in my
toolkit is essentially the same as Windows/OSX - where the application
invalidates part of the window, and then at some later point the OS calls
back with a message prompting the app to paint that part of the screen.
ie: multiple invalidate calls are coalesced into a single paint call at a
later time - typically just before entering the message loop's idle state.

Could a Wayland app mimic this behaviour by having a single background
buffer that contains the current window content?  When the application
invalidates the window it does one of two things depending on whether the
buffer has been returned from the compositor yet.

* If the buffer has been returned and no longer in use by the compositor,
it queues a paint message to itself.

* If the buffer hasn't been returned and is still in use by the compositor,
set a flag on the window.  When the buffer is returned from the compositor,
it checks that flag and if set then it clears the flag and queues the paint
message.

The paint message redraws all the invalidated (damaged) rectangles and
re-submits it to the compositor and the whole cycle starts again.

Obviously there's more logic around maintaining the dirty region,
coalescing multiple invalidate/damage calls, an assumption that there's a
mechanism to post a message via the message loop etc... but I hope this
explains the idea.

Would this work?  I think the main requirement would be that:

1. the compositor doesn't change the contents of the buffer and that when
it's returned it's still got the old content.
2. that the compositor returns buffers it's finished with in a timely manner

It's not clear to me from what I've read that either of these points are
true or safe assumptions.

This would eliminate the need to manage multiple buffers, multiple dirty
regions, the need to copy previously rendered content between buffers and
fits nicely with the rendering model of Windows/OSX giving similar
semantics on all platforms.

Brad

On Wed, Jun 24, 2020 at 6:11 PM Guillermo Rodriguez Garcia <
guille.rodrig...@gmail.com> wrote:

> Hi Brad,
>
> El vie., 19 jun. 2020 a las 5:24, Brad Robinson
> () escribió:
> [...]
> >
> > Finally, the toolkit already maintains an off-screen buffer with the
> window's current contents rendered into it.  I'll probably replace that
> with a Wayland buffer, but wondering about partial updates.  eg: if the
> client only needs to redraw a part of the window what's the correct process
> to update just that part with Wayland.  Can I just update the existing
> buffer and prompt Wayland to just redraw that part?
>
> I am facing a similar situation with a toolkit that maintains an
> off-screen buffer with the current window contents, and will update
> that buffer at arbitrary times, when the application needs to update
> the UI.
>
> You must consider the following:
>
> Once you submit a buffer to Wayland you cannot touch it anymore until
> the compositor releases it back (wl_buffer.release callback). From
> Pekka's email:
>
> > When you submit a buffer to a Wayland compositor, it gives the
> > compositor permission to read the buffer at any time, as many times as
> > it wants to, until it tells you with wl_buffer.release that it will not
> > be looking at that buffer again. You must not write to a buffer that
> > might be read by the compositor, as that can cause misrendering on
> > screen (e.g. your repaint is shown unfinished).
>
> This means you cannot simply use the same off-screen buffer that the
> toolkit maintains, since the toolkit should not update the buffer once
> it submits it to Wayland.
>
> At some point I thought that I could have separate Wayland buffers and
> copy damaged regions from the toolkit buffer to one of these Wayland
> buffers before submitting it to the compositor.
> The idea would be to copy the set of regions that were damaged since
> the last update.
>
> But just copying damaged regions is not enough either. From Pekka's email:
>
> > Also, every buffer you submit must be fully drawn, also outside of the
> > areas you mark as damage. The compositor may be reading more than just
> > the damage you submit.
>
> So this means that everytime the toolkit updates the off-screen
> buffer, I may need to copy _the entire thing_ to a Wayland buffer and
> submit it to the compositor... not very efficient I guess.
>
> I have the feeling that Wayland is designed for a model where the
> client renders the entire frame on demand (most of the examples I've
> found so far work like this) and not for a model where the client is
> updating a buffer asynchronously and you just want to tell the
> compositor to update parts of the frame.
>
> I would be very interested to learn about your solution to this problem.
>
> Best,
>
> Guillermo Rodriguez Garcia
> guille.rodrig...@gmail.com
>
___

Re: Best practices for client side buffer management

2020-06-23 Thread Brad Robinson
Hi Pekka,

Thanks for the detailed insight.  That's exactly the kind of info I was
after about how to manage some of this stuff.  I still haven't had a chance
to dig into this in any detail but hope to in the next day or so...

Brad


On Mon, Jun 22, 2020 at 6:46 PM Pekka Paalanen  wrote:

> On Fri, 19 Jun 2020 11:21:34 +0100
> Carsten Haitzler (The Rasterman)  wrote:
>
> > On Fri, 19 Jun 2020 13:24:12 +1000 Brad Robinson <
> brobin...@toptensoftware.com>
> > said:
> >
> > > Hi All,
> > >
> > > I'm fairly new to Wayland and Linux GUI programming in general, but
> doing
> > > some experiments to figure out how to integrate it into my custom UI
> > > toolkit library and have a couple of questions about client side buffer
> > > management.
> > >
> > > Firstly, this is how I'm allocating the backing memory for client side
> > > buffer pools.  This is C# p-invoking to libc, and basically it's using
> > > mkstemp() to get a temp file, ftruncate() to set its length, mmap() to
> map
> > > it and then unlink() once mapped so temp files aren't left behind.  Any
> > > issues with this approach?
> > >
> > > // Get temp file
> > > var sb = new
> > > StringBuilder(System.IO.Path.Join(System.IO.Path.GetTempPath(),
> > > "mmXX"));
> > > int fd = mkstemp(sb);
> > > ftruncate(fd, (ulong)capacity);
> >
> > i assume GetTempPath() will be looking at /tmp ... and /tmp may not be a
> > ramdisk. it may be a real disk... in which case your buffers may be
> getting
> > written to an actual disk. don't use /tmp.
>
> Hi,
>
> that's true. The trick we have been using is create the file in
> $XDG_RUNTIME_DIR which is practically always a tmpfs, but OTOH it might
> not be the best place to store large pixel buffers.
>
> > you might wan to to loop at shm_open or memfd
>
> Right.
>
> > or libdrm for specific drivr
> > allocation calls like drm_intel_bo_alloc_tiled, drm_intel_bo_map/unmap
> etc. the
>
> No, please do not do that!
>
> That will make your program specific to a certain hardware driver,
> which makes it specific to that hardware. Plus, you will have to learn how
> to program specifically for that driver. It's not worth it.
>
> The wl_shm Wayland interface is for software rendering anyway. No-one
> expects a wl_shm-based buffer to be directly usable by a display or a
> GPU driver, it will always be copied by a compositor. So trying to
> shove "hardware buffers" through wl_shm is only picking the worst of
> all options, as direct CPU access to them is often sub-optimal, perhaps
> even prohibitively slow.
>
> > latter libdrm ones wo9uld allow your buffers to possibly be scanned out
> > directly to the screen or used as textures directly without copies, but
> will
> > need careful handling, so do this only as an advanced step.
>
> If you want to use hardware acceleration or allow direct scanout, use
> the proper APIs intended for them: GBM, EGL, Vulkan; if you need to
> pass hardware buffers manually through Wayland, use zwp_linux_dmabuf_v1
> extension instead of wl_shm.
>
> >
> > > // Map it
> > > var addr = mmap(IntPtr.Zero, (ulong)capacity, Prot.Read |
> > > Prot.Write, Map.Shared, fd, 0);
> > >
> > > // Unlink it (so temp files not left behind)
> > > unlink(sb.ToString());
> > >
> > > Secondly I'm wondering about practical strategies for managing client
> side
> > > buffers.  The toolkit in question basically needs arbitrarily sized
> buffers
> > > to render whatever size the window happens to be.  Seems like to use a
> > > buffer pool for this would require some sort of heap manager to manage
> > > what's in each pool.  I'm wondering if there's any recommendations or
> best
> > > practices for how to deal with this.  eg: create one big pool and
> > > explicitly manage what's in there as a heap, use lots of little pools
> with
> > > one buffer in each, a combination of both, something else?
> >
> > resizes of windows are less common (in general) than rendering to them.
> here
> > i'd go for a scheme of N buffers in a ring per window. so you have
> buffers A,
> > B, C and you first render to A then display it, then next frame B, then
> C, then
> > A, then B, then C. You could get away without C. as the buffers retain
> their
> > state you can take advantage of this and only partially render part of a
> > buffer for updates "since 1 or 2 frames ago" (depending if you do double
> or
> > triple buffering). as its predictable ABCABCABC you can just keep a
> "Sliding
> > window of the update regions of the past N frames" and merge those into
> the
> > "current amount to update" but always store per-frame update rectangle
> regions
> > before this merge-at-render-time. 3 buffers allows you to be rendering a
> 3rd
> > buffer while 1 buffer is queued to be displayed and one is still being
> > displayed. if you find you need a 4th buffer, perhaps just overdraw the
> 3rd on
> > you just did and "update it" ... or just block or don't 

Re: Best practices for client side buffer management

2020-06-22 Thread Carsten Haitzler
On Mon, 22 Jun 2020 11:46:41 +0300 Pekka Paalanen  said:

> On Fri, 19 Jun 2020 11:21:34 +0100
> Carsten Haitzler (The Rasterman)  wrote:
> 
> > On Fri, 19 Jun 2020 13:24:12 +1000 Brad Robinson
> >  said:
> > 
> > > Hi All,
> > > 
> > > I'm fairly new to Wayland and Linux GUI programming in general, but doing
> > > some experiments to figure out how to integrate it into my custom UI
> > > toolkit library and have a couple of questions about client side buffer
> > > management.
> > > 
> > > Firstly, this is how I'm allocating the backing memory for client side
> > > buffer pools.  This is C# p-invoking to libc, and basically it's using
> > > mkstemp() to get a temp file, ftruncate() to set its length, mmap() to map
> > > it and then unlink() once mapped so temp files aren't left behind.  Any
> > > issues with this approach?
> > > 
> > > // Get temp file
> > > var sb = new
> > > StringBuilder(System.IO.Path.Join(System.IO.Path.GetTempPath(),
> > > "mmXX"));
> > > int fd = mkstemp(sb);
> > > ftruncate(fd, (ulong)capacity);  
> > 
> > i assume GetTempPath() will be looking at /tmp ... and /tmp may not be a
> > ramdisk. it may be a real disk... in which case your buffers may be getting
> > written to an actual disk. don't use /tmp.
> 
> Hi,
> 
> that's true. The trick we have been using is create the file in
> $XDG_RUNTIME_DIR which is practically always a tmpfs, but OTOH it might
> not be the best place to store large pixel buffers.

correct. also just opening files in /dev/shm ... but shm_open acts as a
portable front-end to that.

> > you might wan to to loop at shm_open or memfd 
> 
> Right.
> 
> > or libdrm for specific drivr
> > allocation calls like drm_intel_bo_alloc_tiled, drm_intel_bo_map/unmap etc.
> > the
> 
> No, please do not do that!
> 
> That will make your program specific to a certain hardware driver,
> which makes it specific to that hardware. Plus, you will have to learn how
> to program specifically for that driver. It's not worth it.

we do... but we also have other paths to alloc memory so this is a "if on intel
and that works, then use this". also have one for vc4... :) it certainly should
not be the only method :)

> The wl_shm Wayland interface is for software rendering anyway. No-one
> expects a wl_shm-based buffer to be directly usable by a display or a
> GPU driver, it will always be copied by a compositor. So trying to
> shove "hardware buffers" through wl_shm is only picking the worst of
> all options, as direct CPU access to them is often sub-optimal, perhaps
> even prohibitively slow.

oh this wont be for wl-shm ... :) sorry. i didn't mention that.

> > latter libdrm ones wo9uld allow your buffers to possibly be scanned out
> > directly to the screen or used as textures directly without copies, but will
> > need careful handling, so do this only as an advanced step.
> 
> If you want to use hardware acceleration or allow direct scanout, use
> the proper APIs intended for them: GBM, EGL, Vulkan; if you need to
> pass hardware buffers manually through Wayland, use zwp_linux_dmabuf_v1
> extension instead of wl_shm.

yeah. we use linux-dmabuf protocol with these intel and vc4 buffers, not
wl_shm. :)

> > 
> > > // Map it
> > > var addr = mmap(IntPtr.Zero, (ulong)capacity, Prot.Read |
> > > Prot.Write, Map.Shared, fd, 0);
> > > 
> > > // Unlink it (so temp files not left behind)
> > > unlink(sb.ToString());
> > > 
> > > Secondly I'm wondering about practical strategies for managing client side
> > > buffers.  The toolkit in question basically needs arbitrarily sized
> > > buffers to render whatever size the window happens to be.  Seems like to
> > > use a buffer pool for this would require some sort of heap manager to
> > > manage what's in each pool.  I'm wondering if there's any recommendations
> > > or best practices for how to deal with this.  eg: create one big pool and
> > > explicitly manage what's in there as a heap, use lots of little pools with
> > > one buffer in each, a combination of both, something else?  
> > 
> > resizes of windows are less common (in general) than rendering to them. here
> > i'd go for a scheme of N buffers in a ring per window. so you have buffers
> > A, B, C and you first render to A then display it, then next frame B, then
> > C, then A, then B, then C. You could get away without C. as the buffers
> > retain their state you can take advantage of this and only partially render
> > part of a buffer for updates "since 1 or 2 frames ago" (depending if you do
> > double or triple buffering). as its predictable ABCABCABC you can just keep
> > a "Sliding window of the update regions of the past N frames" and merge
> > those into the "current amount to update" but always store per-frame update
> > rectangle regions before this merge-at-render-time. 3 buffers allows you to
> > be rendering a 3rd buffer while 1 buffer is queued to be displayed and one
> > is 

Re: Best practices for client side buffer management

2020-06-22 Thread Pekka Paalanen
On Fri, 19 Jun 2020 11:21:34 +0100
Carsten Haitzler (The Rasterman)  wrote:

> On Fri, 19 Jun 2020 13:24:12 +1000 Brad Robinson 
> 
> said:
> 
> > Hi All,
> > 
> > I'm fairly new to Wayland and Linux GUI programming in general, but doing
> > some experiments to figure out how to integrate it into my custom UI
> > toolkit library and have a couple of questions about client side buffer
> > management.
> > 
> > Firstly, this is how I'm allocating the backing memory for client side
> > buffer pools.  This is C# p-invoking to libc, and basically it's using
> > mkstemp() to get a temp file, ftruncate() to set its length, mmap() to map
> > it and then unlink() once mapped so temp files aren't left behind.  Any
> > issues with this approach?
> > 
> > // Get temp file
> > var sb = new
> > StringBuilder(System.IO.Path.Join(System.IO.Path.GetTempPath(),
> > "mmXX"));
> > int fd = mkstemp(sb);
> > ftruncate(fd, (ulong)capacity);  
> 
> i assume GetTempPath() will be looking at /tmp ... and /tmp may not be a
> ramdisk. it may be a real disk... in which case your buffers may be getting
> written to an actual disk. don't use /tmp.

Hi,

that's true. The trick we have been using is create the file in
$XDG_RUNTIME_DIR which is practically always a tmpfs, but OTOH it might
not be the best place to store large pixel buffers.

> you might wan to to loop at shm_open or memfd 

Right.

> or libdrm for specific drivr
> allocation calls like drm_intel_bo_alloc_tiled, drm_intel_bo_map/unmap etc. 
> the

No, please do not do that!

That will make your program specific to a certain hardware driver,
which makes it specific to that hardware. Plus, you will have to learn how
to program specifically for that driver. It's not worth it.

The wl_shm Wayland interface is for software rendering anyway. No-one
expects a wl_shm-based buffer to be directly usable by a display or a
GPU driver, it will always be copied by a compositor. So trying to
shove "hardware buffers" through wl_shm is only picking the worst of
all options, as direct CPU access to them is often sub-optimal, perhaps
even prohibitively slow.

> latter libdrm ones wo9uld allow your buffers to possibly be scanned out
> directly to the screen or used as textures directly without copies, but will
> need careful handling, so do this only as an advanced step.

If you want to use hardware acceleration or allow direct scanout, use
the proper APIs intended for them: GBM, EGL, Vulkan; if you need to
pass hardware buffers manually through Wayland, use zwp_linux_dmabuf_v1
extension instead of wl_shm.

> 
> > // Map it
> > var addr = mmap(IntPtr.Zero, (ulong)capacity, Prot.Read |
> > Prot.Write, Map.Shared, fd, 0);
> > 
> > // Unlink it (so temp files not left behind)
> > unlink(sb.ToString());
> > 
> > Secondly I'm wondering about practical strategies for managing client side
> > buffers.  The toolkit in question basically needs arbitrarily sized buffers
> > to render whatever size the window happens to be.  Seems like to use a
> > buffer pool for this would require some sort of heap manager to manage
> > what's in each pool.  I'm wondering if there's any recommendations or best
> > practices for how to deal with this.  eg: create one big pool and
> > explicitly manage what's in there as a heap, use lots of little pools with
> > one buffer in each, a combination of both, something else?  
> 
> resizes of windows are less common (in general) than rendering to them. here
> i'd go for a scheme of N buffers in a ring per window. so you have buffers A,
> B, C and you first render to A then display it, then next frame B, then C, 
> then
> A, then B, then C. You could get away without C. as the buffers retain their
> state you can take advantage of this and only partially render part of a
> buffer for updates "since 1 or 2 frames ago" (depending if you do double or
> triple buffering). as its predictable ABCABCABC you can just keep a "Sliding
> window of the update regions of the past N frames" and merge those into the
> "current amount to update" but always store per-frame update rectangle regions
> before this merge-at-render-time. 3 buffers allows you to be rendering a 3rd
> buffer while 1 buffer is queued to be displayed and one is still being
> displayed. if you find you need a 4th buffer, perhaps just overdraw the 3rd on
> you just did and "update it" ... or just block or don't update yet as you are
> getting too far ahead of the compositor.

Such a strict sequence of buffers is wasteful and not necessary. You
don't need that to keep track of damage for doing partial updates. The
slight complication in tracking the damage is very much worth it over
the use of more buffers than you really need.

Instead, allocate buffers on-demand, and re-use buffers as soon as the
compositor you are connected to releases them. If you have more than one
buffer idle, you can destroy the extra ones, perhaps 

Re: Best practices for client side buffer management

2020-06-19 Thread Brad Robinson
Hi Carsten,


> i assume GetTempPath() will be looking at /tmp ... and /tmp may not be a
> ramdisk. it may be a real disk... in which case your buffers may be getting
> written to an actual disk. don't use /tmp.
>

That's kind of what was in the back of my head when I decided to post this,
but being new to Linux dev thought it might have been a silly question and
wasn't sure how to express it.  Going to switch to memfd_create for now.


> resizes of windows are less common (in general) than rendering to them.
> here
> i'd go for a scheme of N buffers in a ring per window. so you have buffers
> A,
> B, C and you first render to A then display it, then next frame B, then C,
> then
> A, then B, then C. You could get away without C. as the buffers retain
> their
> state you can take advantage of this and only partially render part of a
> buffer for updates "since 1 or 2 frames ago" (depending if you do double or
> triple buffering). as its predictable ABCABCABC you can just keep a
> "Sliding
> window of the update regions of the past N frames" and merge those into the
> "current amount to update" but always store per-frame update rectangle
> regions
> before this merge-at-render-time. 3 buffers allows you to be rendering a
> 3rd
> buffer while 1 buffer is queued to be displayed and one is still being
> displayed. if you find you need a 4th buffer, perhaps just overdraw the
> 3rd on
> you just did and "update it" ... or just block or don't update yet as you
> are
> getting too far ahead of the compositor.
>
> > Finally, the toolkit already maintains an off-screen buffer with the
> > window's current contents rendered into it.  I'll probably replace that
> > with a Wayland buffer, but wondering about partial updates.  eg: if the
> > client only needs to redraw a part of the window what's the correct
> process
> > to update just that part with Wayland.  Can I just update the existing
> > buffer and prompt Wayland to just redraw that part?
>
> no. never do that. always have more than 1 and update a buffer that is not
> being displayed or queued to be displayed. the above sliding window allows
> your
> partial rendering to work as you can depend on previous content still being
> there where you left it from N frames ago.
>
>
OK thanks - that's pointing me in the right direction.  I have questions
about all this, but I don't want to waste your time until I've had time to
dig into it myself first.

(I'm a bit slow with all this because it's an evening side project and I'm
doing it in C# and trying to get the protocol bindings and libc pinvoke
functions all wired up at the same time as figuring out how it all works).

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


Re: Best practices for client side buffer management

2020-06-19 Thread Brad Robinson
Hi Scott,

Thanks - memfd_create looks like a good option.  I think I'll switch to
that and fall back if it's not available.

Sounds like one pool per window is the way to go...  really didn't feel
like implementing a heap allocator.

Brad


On Fri, Jun 19, 2020 at 1:55 PM Scott Anderson 
wrote:

> On 19/06/20 3:24 pm, Brad Robinson wrote:
> > Hi All,
> >
> > I'm fairly new to Wayland and Linux GUI programming in general, but
> > doing some experiments to figure out how to integrate it into my custom
> > UI toolkit library and have a couple of questions about client side
> > buffer management.
> >
> > Firstly, this is how I'm allocating the backing memory for client side
> > buffer pools.  This is C# p-invoking to libc, and basically it's using
> > mkstemp() to get a temp file, ftruncate() to set its length, mmap() to
> > map it and then unlink() once mapped so temp files aren't left behind.
> > Any issues with this approach?
> >
> >  // Get temp file
> >  var sb = new
> > StringBuilder(System.IO.Path.Join(System.IO.Path.GetTempPath(),
> > "mmXX"));
> >  int fd = mkstemp(sb);
> >  ftruncate(fd, (ulong)capacity);
> >
> >  // Map it
> >  var addr = mmap(IntPtr.Zero, (ulong)capacity, Prot.Read |
> > Prot.Write, Map.Shared, fd, 0);
> >
> >  // Unlink it (so temp files not left behind)
> >  unlink(sb.ToString());
>
> An alternative implementation would be to use memfd_create, but that is
> Linux-specific. Otherwise what you have there looks correct to me.
>
> > Secondly I'm wondering about practical strategies for managing client
> > side buffers.  The toolkit in question basically needs arbitrarily sized
> > buffers to render whatever size the window happens to be.  Seems like to
> > use a buffer pool for this would require some sort of heap manager to
> > manage what's in each pool.  I'm wondering if there's any
> > recommendations or best practices for how to deal with this.  eg: create
> > one big pool and explicitly manage what's in there as a heap, use lots
> > of little pools with one buffer in each, a combination of both,
> > something else?
>
> It would be possible to deal use heaps, but in practice most clients
> will just use a dedicated shared memory object (wl_shm_pool) for each
> buffer, which works perfectly fine. Shared memory clients usually only
> need 2 buffers, but it's a good idea to write your program in a way so
> that it can use up to 4, allocating the extra as needed, and freeing
> them when you're done.
>
> > Finally, the toolkit already maintains an off-screen buffer with the
> > window's current contents rendered into it.  I'll probably replace that
> > with a Wayland buffer, but wondering about partial updates.  eg: if the
> > client only needs to redraw a part of the window what's the correct
> > process to update just that part with Wayland.  Can I just update the
> > existing buffer and prompt Wayland to just redraw that part?
>
> There are requests in the protocol specifically for telling the
> compositor about partial updates, which are wl_surface.damage and
> wl_surface.damage_buffer. Using wl_surface.damage_buffer is generally a
> better idea.
>
> Here is a blog post that goes over some more general details:
> https://emersion.fr/blog/2019/intro-to-damage-tracking/
> It's slightly more slanted to talking about the compositor side of
> things, but I still think could be helpful.
>
> Scott
>
> > Any advice appreciated...
> >
> > Brad
>
>
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: Best practices for client side buffer management

2020-06-19 Thread The Rasterman
On Fri, 19 Jun 2020 13:24:12 +1000 Brad Robinson 
said:

> Hi All,
> 
> I'm fairly new to Wayland and Linux GUI programming in general, but doing
> some experiments to figure out how to integrate it into my custom UI
> toolkit library and have a couple of questions about client side buffer
> management.
> 
> Firstly, this is how I'm allocating the backing memory for client side
> buffer pools.  This is C# p-invoking to libc, and basically it's using
> mkstemp() to get a temp file, ftruncate() to set its length, mmap() to map
> it and then unlink() once mapped so temp files aren't left behind.  Any
> issues with this approach?
> 
> // Get temp file
> var sb = new
> StringBuilder(System.IO.Path.Join(System.IO.Path.GetTempPath(),
> "mmXX"));
> int fd = mkstemp(sb);
> ftruncate(fd, (ulong)capacity);

i assume GetTempPath() will be looking at /tmp ... and /tmp may not be a
ramdisk. it may be a real disk... in which case your buffers may be getting
written to an actual disk. don't use /tmp.

you might wan to to loop at shm_open or memfd or libdrm for specific drivr
allocation calls like drm_intel_bo_alloc_tiled, drm_intel_bo_map/unmap etc. the
latter libdrm ones wo9uld allow your buffers to possibly be scanned out
directly to the screen or used as textures directly without copies, but will
need careful handling, so do this only as an advanced step.

> // Map it
> var addr = mmap(IntPtr.Zero, (ulong)capacity, Prot.Read |
> Prot.Write, Map.Shared, fd, 0);
> 
> // Unlink it (so temp files not left behind)
> unlink(sb.ToString());
> 
> Secondly I'm wondering about practical strategies for managing client side
> buffers.  The toolkit in question basically needs arbitrarily sized buffers
> to render whatever size the window happens to be.  Seems like to use a
> buffer pool for this would require some sort of heap manager to manage
> what's in each pool.  I'm wondering if there's any recommendations or best
> practices for how to deal with this.  eg: create one big pool and
> explicitly manage what's in there as a heap, use lots of little pools with
> one buffer in each, a combination of both, something else?

resizes of windows are less common (in general) than rendering to them. here
i'd go for a scheme of N buffers in a ring per window. so you have buffers A,
B, C and you first render to A then display it, then next frame B, then C, then
A, then B, then C. You could get away without C. as the buffers retain their
state you can take advantage of this and only partially render part of a
buffer for updates "since 1 or 2 frames ago" (depending if you do double or
triple buffering). as its predictable ABCABCABC you can just keep a "Sliding
window of the update regions of the past N frames" and merge those into the
"current amount to update" but always store per-frame update rectangle regions
before this merge-at-render-time. 3 buffers allows you to be rendering a 3rd
buffer while 1 buffer is queued to be displayed and one is still being
displayed. if you find you need a 4th buffer, perhaps just overdraw the 3rd on
you just did and "update it" ... or just block or don't update yet as you are
getting too far ahead of the compositor.

> Finally, the toolkit already maintains an off-screen buffer with the
> window's current contents rendered into it.  I'll probably replace that
> with a Wayland buffer, but wondering about partial updates.  eg: if the
> client only needs to redraw a part of the window what's the correct process
> to update just that part with Wayland.  Can I just update the existing
> buffer and prompt Wayland to just redraw that part?

no. never do that. always have more than 1 and update a buffer that is not
being displayed or queued to be displayed. the above sliding window allows your
partial rendering to work as you can depend on previous content still being
there where you left it from N frames ago.

> Any advice appreciated...
> 
> Brad


-- 
- Codito, ergo sum - "I code, therefore I am" --
Carsten Haitzler - ras...@rasterman.com

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


Re: Best practices for client side buffer management

2020-06-18 Thread Scott Anderson

On 19/06/20 3:24 pm, Brad Robinson wrote:

Hi All,

I'm fairly new to Wayland and Linux GUI programming in general, but 
doing some experiments to figure out how to integrate it into my custom 
UI toolkit library and have a couple of questions about client side 
buffer management.


Firstly, this is how I'm allocating the backing memory for client side 
buffer pools.  This is C# p-invoking to libc, and basically it's using 
mkstemp() to get a temp file, ftruncate() to set its length, mmap() to 
map it and then unlink() once mapped so temp files aren't left behind.  
Any issues with this approach?


             // Get temp file
             var sb = new 
StringBuilder(System.IO.Path.Join(System.IO.Path.GetTempPath(), 
"mmXX"));

             int fd = mkstemp(sb);
             ftruncate(fd, (ulong)capacity);

             // Map it
             var addr = mmap(IntPtr.Zero, (ulong)capacity, Prot.Read | 
Prot.Write, Map.Shared, fd, 0);


             // Unlink it (so temp files not left behind)
             unlink(sb.ToString());


An alternative implementation would be to use memfd_create, but that is 
Linux-specific. Otherwise what you have there looks correct to me.


Secondly I'm wondering about practical strategies for managing client 
side buffers.  The toolkit in question basically needs arbitrarily sized 
buffers to render whatever size the window happens to be.  Seems like to 
use a buffer pool for this would require some sort of heap manager to 
manage what's in each pool.  I'm wondering if there's any 
recommendations or best practices for how to deal with this.  eg: create 
one big pool and explicitly manage what's in there as a heap, use lots 
of little pools with one buffer in each, a combination of both, 
something else?


It would be possible to deal use heaps, but in practice most clients 
will just use a dedicated shared memory object (wl_shm_pool) for each 
buffer, which works perfectly fine. Shared memory clients usually only 
need 2 buffers, but it's a good idea to write your program in a way so 
that it can use up to 4, allocating the extra as needed, and freeing 
them when you're done.


Finally, the toolkit already maintains an off-screen buffer with the 
window's current contents rendered into it.  I'll probably replace that 
with a Wayland buffer, but wondering about partial updates.  eg: if the 
client only needs to redraw a part of the window what's the correct 
process to update just that part with Wayland.  Can I just update the 
existing buffer and prompt Wayland to just redraw that part?


There are requests in the protocol specifically for telling the 
compositor about partial updates, which are wl_surface.damage and 
wl_surface.damage_buffer. Using wl_surface.damage_buffer is generally a 
better idea.


Here is a blog post that goes over some more general details: 
https://emersion.fr/blog/2019/intro-to-damage-tracking/
It's slightly more slanted to talking about the compositor side of 
things, but I still think could be helpful.


Scott


Any advice appreciated...

Brad


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