How to release the weston_buffer after weston_view is destroyed.

Pekka Paalanen ppaalanen at gmail.com
Fri Aug 3 11:49:21 UTC 2018


> On Sat, Jul 28, 2018 at 8:15 PM, Sichem Zhou <sichem.zh at gmail.com> wrote:
> 
> > Dear Weston devs:
> >
> > Sorry for the bothering in when weston-5.0 is approaching, but I am stuck
> > in the project for three days I need some one's help very much.
> >
> > I have a widget implementation of shell widgets that destroys the
> > weston_view
> > when pressed Esc. The widget is implemented in wayland EGL. Here is the
> > view_destroy code.
> >
> > void
> > twshell_close_ui_surface(struct weston_surface *wd_surface)
> > {
> >         struct weston_view *view, *next;
> >         wd_surface->committed = NULL;
> >         wd_surface->committed_private = NULL;
> >         wl_list_for_each_safe(view, next, &wd_surface->views,
> > surface_link) {
> >                 weston_view_destroy(view);
> >         }
> > }
> >
> > The weston_view is destroyed but the the buffer in the last commit was not
> > released and the done event was not sent to the widget. When I triggered
> > the event to show widget again, the client was stuck in EGLSwapbuffer. I
> > found out about this by using WAYLAND_DEBUG env variable, I hope to the
> > way to release the buffer after umapping the weston view. Thanks very much.

Hi,

destroying or unmapping a weston_view is not meant to release the
wl_surface's buffer. If the compositor spontaneously chooses to hide a
surface, it may also spontaneously choose to show it again. To show a
surface, it must have content, so if the renderer needs the buffer
around, hiding cannot release the buffer.

Views are Weston internal objects, clients are completely unaware of
them. However, clients are aware of the mappedness of a wl_surface
(weston_surface). Clients issue protocol requests and assume a specific
sequence will map the surface. A compositor must keep up that
appearance, even if it was a lie internally. That is, if a compositor
spontaneously unmaps the view, it will not make the surface unmapped.
This is also why we have 'bool is_mapped' in both weston_surface and
weston_view. The client still thinks the surface is mapped, so it will
not even expect the buffer to be released.

The only client-visible effect of unmapping all views is that the frame
callbacks will pause. This does not mean that the surface is unmapped,
it is just temporarily not visible. Frame callbacks are used to
throttle clients so that they don't draw frames that will not be shown.

If you don't forcefully release the buffer, re-creating the view should
let your app continue as usual while Weston is showing the last frame
it got.

It is also intentional that frame callback 'done' events are only ever
triggered from repaint. Repaint makes the frame visible. As long as the
frame is not processed yet, 'done' should not be sent.

'done' means that it is a good time for a continuously animating client
to start drawing the next frame. It is an advisory throttling
mechanism, and if your client really knows better, it can choose to
draw new frames regardless.

When you use EGL in a client, is it important to never let
eglSwapBuffers() block for you. You need to track frame callbacks
manually or set eglSwapInterval to zero, preferably both, so your
application code does not get blocked by EGL API that was designed for
applications far less smart than yours.


On Sun, 29 Jul 2018 20:49:24 -0400
Sichem Zhou <sichem.zh at gmail.com> wrote:

> I actually found the reason, in the function `weston_output_repaint`, the
> frame_callbacks
> only send the done events for surface which has view on the compositor's
> view_list,
> but this poses a dilemma, since I cannot either destroy or unmap the view
> before the
> output repainted.

I don't see a problem on the compositor side. You can unmap or destroy
the view, and the frame callbacks will stall until you re-map the view
again. The last buffer will not get released while unmapped, because
the compositor needs it on re-map. The pending frame callbacks will
resume once the view is re-mapped.

It sounds like your problem is in the app: do not let eglSwapBuffers()
block on a frame callback. Create a frame callback just before you call
eglSwapBuffers(), and do not call eglSwapBuffers() again until that
frame callback has signalled. That way eglSwapBuffers should never
block indefinitely. Additionally you can set eglSwapInterval to zero in
case there are situations where you really need to eglSwapBuffers()
before the frame callback has signalled.


Thanks,
pq
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20180803/a4337a65/attachment.sig>


More information about the wayland-devel mailing list