On Wed, 26 Oct 2022 20:56:14 -0700 Joel Winarske <joel.winar...@gmail.com> wrote:
> When using sub_surfaces what is the expected behavior for frame callbacks > on a given surface? Hi, frame callbacks will trigger at the compositor's discretion after the wl_surface update with that frame callback request is applied, and if the wl_surface is mapped. A wl_surface update is applied on wl_surface.commit, unless that is postponed by some other extension, e.g. the wl_surface is a sub-surface in synchronized mode, in which case the update gets applied when the next parent wl_surface update committed after the sub-surface update gets applied. > Say I have the following: > > 1. base surface > 2. xdg surface referencing base surface > 3. wl surface A > 4. subsurface from a and base surface (default settings - none applied) > 5. wl surface B (set for sync) > 6. subsurface from wl surface B and wl surface A (above/sync setting) In other words, you have: - wl_surface "base", e.g. a top-level - wl_surface "A" is a sub-surface of "base", synchronized (default by the spec) - wl_surface "B" is a sub-surface of "A", synchronized Above/below makes no difference for this, unless it causes one of the wl_surfaces to be fully occluded. Fully occluded wl_surfaces might not trigger frame callbacks, because the content would not be seen anyway. > I find if I use wl_callback_add_listener using "surface A" when working > with "surface B" I get frame event callbacks of "surface A". If I use > wl_callback_add_listener with "surface B" I never see a frame callback. Do > I need to explicitly set the state of each subsurface in the stack to > match, and not rely on "default settings"? > > I tried setting "subsurface from B and surface B" as de-sync and I > experienced no change in behavior. > > I am at the point of mocking up a minimum repro case to exercise this > further. I'm hoping someone can enlighten me. I did not fully understand what your program is doing, so it's hard to say. The exact sequence of requests is crucial. Mind, that for frame callbacks to trigger, the wl_surface must be mapped first. If you ask for a frame callback, that frame callback will trigger when the compositor thinks it's a good time to draw again. Setting a frame callback is "double-buffered state", which means that for non-sub-surfaces you must send wl_surface.commit before the wl_surface.frame request will be acted on. On synchronized sub-surfaces, you will need a wl_surface.commit on the sub-surface first, *and* a wl_surface.commit on the parent surface next. It's actually recursive, so if the parent surface is a synchronized sub-surface for another wl_surface, then that other wl_surface needs a commit after the earlier ones as well. So in your case with the surfaces base -> A -> B You need this sequence to be able to get a frame callback triggered on wl_surface B: B.frame(cb) B.commit() A.commit() base.commit() And also all three surfaces must be already mapped or become mapped in that sequence. set_desync() is specified to apply immediately, so this should work too: B.set_desync() B.frame(cb) B.commit() But it is still conditional on all three surfaces getting mapped. A sub-surface cannot be visible unless all its ancestors are visible too. A surface that is not visible (not mapped, or is fully occluded) likely does not trigger frame callbacks. Thanks, pq
pgpNI_Vmd0BgO.pgp
Description: OpenPGP digital signature