Post by Sichem ZhouPost by Sichem ZhouSorry 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
Post by Sichem ZhouI 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