Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Augment wlr_buffer to support swapchains #2044

Merged
merged 3 commits into from
Apr 2, 2020

Conversation

emersion
Copy link
Member

@emersion emersion commented Feb 28, 2020

Depends on #2043

This PR adds the required infrastructure to wlr_buffer to support swapchains. glider has been updated to use it: emersion/glider#7.

Once this PR is merged, it will be possible to add DRM support to #1985 via libliftoff.


wlr_buffer now has a concept of "released", "producer" and "consumer". A buffer is created by a producer (the allocator or the client). It's then referenced by consumers (e.g. the backend or the compositor). Once all consumers are done with the buffer (ie. once they have un-referenced the buffer), the buffer is released and can be re-used (by the swapchain or the client).

This is inspired from glider's buffer: https://github.com/emersion/glider/blob/c66847dd1cf8ae5e68666ce7cb3be41427b38dc7/include/allocator.h#L17. One difference is that this PR is less explicit: both consumers and producers call wlr_buffer_unref. On glider, there's one API for producers (glider_buffer_init, glider_buffer_unref) and a separate API for consumers (glider_buffer_lock, glider_buffer_unlock). This makes it more obvious when the buffer is released. Is it worth it to make this breaking change? Renamed.

glider's buffer is itself inspired from the renderer v6's wlr_image type: https://github.com/swaywm/wlroots/pull/1355/files#diff-6105fb2a3a3620a8a1aabaa7b11beb84R16


Breaking changes:

  • Compositors that want to keep a reference to a wlr_buffer to read it later should call wlr_buffer_lock and wlr_buffer_unlock instead of wlr_buffer_ref and wlr_buffer_unref. Same applies to backends.
  • wlr_client_buffer_create has been renamed to wlr_client_buffer_import. Callers need to wlr_buffer_unlock the resulting buffer once they're done with it.
  • Users who create buffers need to call wlr_buffer_drop instead of wlr_buffer_unref.

Sway PR: swaywm/sway#5088

emersion added a commit to emersion/glider that referenced this pull request Feb 28, 2020
With [1], wlr_buffer has the required infrastructure to handle
swapchains.

[1]: swaywm/wlroots#2044
@emersion emersion changed the title [WIP] Augment wlr_buffer to support swapchains Augment wlr_buffer to support swapchains Mar 7, 2020
@emersion
Copy link
Member Author

emersion commented Mar 7, 2020

This is now ready for review.

types/wlr_surface.c Outdated Show resolved Hide resolved
emersion added a commit to emersion/glider that referenced this pull request Mar 8, 2020
With [1], wlr_buffer has the required infrastructure to handle
swapchains.

[1]: swaywm/wlroots#2044
emersion added a commit to emersion/glider that referenced this pull request Mar 9, 2020
With [1], wlr_buffer has the required infrastructure to handle
swapchains.

[1]: swaywm/wlroots#2044
emersion added a commit to emersion/sway that referenced this pull request Mar 9, 2020
*/
struct wlr_buffer *wlr_buffer_ref(struct wlr_buffer *buffer);
void wlr_buffer_drop(struct wlr_buffer *buffer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Release?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conflicts with the concept of "releasing" a buffer when all consumers are done with it (wording used in the Wayland protocol: wl_buffer.release).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh. Don't have any better ideas.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But maybe we should s/lock/acquire/ and s/unlock/release/?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, chose to use "drop" instead of keeping "unref" so that old wlr_buffer_unref users don't forget to update their code to use wlr_buffer_unlock.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, okay.

@emersion emersion added the breaking Breaking change in public API label Mar 9, 2020
Consumers call wlr_buffer_lock. Once all consumers are done with the
buffer, only the producer should have a reference to the buffer. In this
case, we can release the buffer (and let the producer re-use it).
@ascent12
Copy link
Member

I don't really want to turn this into bikeshedding the function names, but would something a bit more explicit about "reading" be clearer?

  • wlr_buffer_lock => wlr_buffer_read_lock
  • wlr_buffer_unlock => wlr_buffer_read_unlock
    or something vaguely similar.

drop and unlock don't really have enough context on their own to say who is supposed to use what.

@emersion
Copy link
Member Author

Actually, locking is necessary for write access too. In the case of a swapchain:

  • The swapchain holds the buffers, and needs to know when the buffers can be re-used
  • The renderer writes to the buffers
  • The buffers should be locked while being rendered to, so that they don't get re-used

@ascent12
Copy link
Member

Yeah, that makes sense.

*/
struct wlr_buffer *wlr_buffer_ref(struct wlr_buffer *buffer);
void wlr_buffer_drop(struct wlr_buffer *buffer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function really necessary? There are only 2 potential users of this function, which is wlr_client_buffer, and a swapchain.
wlr_client_buffer doesn't need it, because it can just destroy the buffer on the release signal.
The swapchain can just implement this itself, taking the release event into account.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that we can replace wlr_buffer_drop with wlr_buffer_destroy?

This is necessary when e.g. resizing a swapchain: the old buffers (with the old size) can be dropped by the swapchain while still being used by e.g. DRM for scanout.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And in wlr_surface, we'd need to have a list of buffers the compositor is still using and a bunch of release listeners to only destroy buffers when we can.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary when e.g. resizing a swapchain: the old buffers (with the old size) can be dropped by the swapchain while still being used by e.g. DRM for scanout.

My point is that you'd still keep roughly the same logic, but it would be implement in the swapchain rather than in wlr_buffer.

And in wlr_surface, we'd need to have a list of buffers the compositor is still using and a bunch of release listeners to only destroy buffers when we can.

Isn't that just done by the reference counting?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is that you'd still keep roughly the same logic, but it would be implement in the swapchain rather than in wlr_buffer.

If the swapchain has 3 slots and is resized, there are 3 "dangling buffers" still used by DRM that will need to be destroyed when released.

Isn't that just done by the reference counting?

What do you suggest actually? I realize I may have misunderstood.

Do you want to remove wlr_buffer_drop and replace it with a wlr_buffer_destroy function which just immediately destroys the buffer? If that's the case, someone needs to keep track of the release event and destroy the buffer when it happens. I don't want to duplicate this logic in wlr_surface and in the swapchain.

@emersion
Copy link
Member Author

@ascent12 Ping? Any better naming ideas? (e.g. lock → acquire / unlock → release?)

@emersion
Copy link
Member Author

Bump

@emersion
Copy link
Member Author

emersion commented Apr 2, 2020

So… What do we want to do with this pull request? Are there any actionable tasks to unblock it?

@emersion emersion merged commit 1fa9e02 into swaywm:master Apr 2, 2020
@emersion emersion deleted the buffer-next branch April 2, 2020 13:03
emersion added a commit to emersion/glider that referenced this pull request Apr 2, 2020
With [1], wlr_buffer has the required infrastructure to handle
swapchains.

[1]: swaywm/wlroots#2044
emersion added a commit to emersion/glider that referenced this pull request Apr 2, 2020
With [1], wlr_buffer has the required infrastructure to handle
swapchains.

[1]: swaywm/wlroots#2044
emersion added a commit to swaywm/sway that referenced this pull request Apr 2, 2020
@emersion emersion added this to the 0.11.0 milestone Jul 15, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
breaking Breaking change in public API
Development

Successfully merging this pull request may close these issues.

None yet

3 participants