Bug 7825

Summary: Vivante: Spurious frame sent to compositor after hiding Wayland window
Product: [Build System, Metadata & Runtime] BSPs Reporter: Thomas McGuire <thomas.mcguire>
Component: bsps-meta-fsl-armAssignee: Otavio Salvador <otavio>
Status: RESOLVED OBSOLETE QA Contact:
Severity: normal    
Priority: Medium CC: richard.purdie
Version: 1.8   
Target Milestone: Future   
Hardware: Other   
OS: arm   
Whiteboard:
OS type for building Yocto: --- Type of Regression: ---
Verified: Documentation change: No (bug/feature does not impact docs)
Attachments:
Description Flags
Testcase of the problem (source and binary) none

Description Thomas McGuire 2015-05-29 13:13:25 UTC
Created attachment 2529 [details]
Testcase of the problem (source and binary)

When a Wayland client hides a window by attaching a nil buffer to the window's surface, the Wayland compositor will not hide the window, but display the last frame that was rendered.

Attaching a nil buffer is how Wayland clients written in Qt hide their window, which means every Qt application that hides a window and uses Wayland is affected.

This can be reproduced with the attached testcase. The testcase contains the source and a binary build on fido/imx6qsabresd. In the testcase, the window is hidden after 4 seconds, yet Weston still displays the window.

I reproduced this on Yocto dizzy and on Yocto fido, using core-image-weston on an imx6qsabresd.

This happens with Weston and with Qt-based compositors, the bug is in the eglSwapBuffers() implementation of the Vivante driver: The Vivante driver sends wl_surface::commit() messages to the compositor *after* the last eglSwapBuffers() call, as seen in the following log (WAYLAND_DEBUG=client):

Hiding window...
    Attaching nil buffer to window.
[2081588.396]  -> wl_surface@3.attach(nil, 0, 0)
[2081588.798]  -> wl_surface@3.commit()
Done hiding window...
[2081590.690] wl_callback@12.done(2506047518)
[2081590.946]  -> wl_surface@3.frame(new id wl_callback@12)
[2081591.200]  -> wl_surface@3.attach(wl_buffer@8, 0, 0)
[2081591.568]  -> wl_surface@3.damage(0, 0, 640, 480)
[2081592.106]  -> wl_surface@3.commit()

eglSwapBuffers() should not return before having sent the wl_surface::commit() message to the compositor. While I can't find any official documentation for that behavior, it is mentioned in multiple places:

http://www.jlekstrand.net/jason/projects/wayland/wayland-android/ - "eglSwapBuffers [..] must call wl_display.attach, wl_display.damage, and wl_display.commit before it returns."

https://www.mail-archive.com/wayland-devel@lists.freedesktop.org/msg12706.html: "eglSwapBuffers should be calling wl_surface.commit before it returns."

The QtWayland developers also said that this would be the expected behavior from eglSwapBuffers().
Comment 1 Thomas McGuire 2015-05-29 13:16:49 UTC
FYI, this works fine on a desktop machine with Mesa drivers (Intel in this case).
Comment 2 Thomas McGuire 2015-05-29 13:19:43 UTC
A QtWayland developer mentioned on IRC that this is not the only problem caused by the incorrect eglSwapBuffers() behaviour, here is what he said:

"note that that is only one of the problems that can be caused by that bug
 say you call wl_surface_set_buffer_transform and then eglSwapBuffers
 by the time that returns you expect the new transform to have taken affect
 but with Vivante that won't be true
 and same problem with all double buffered properties"
Comment 3 Richard Purdie 2018-01-18 16:16:32 UTC
This has now become an obsolete/wontfix issue. If anyone is going to actively
work on this on maintained releases please reopen and change the targets but
I'll close it given the current inactivity.