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

Rendering goes bonkers with headless and wdisplays #2164

Closed
any1 opened this issue May 6, 2020 · 11 comments · Fixed by #2292
Closed

Rendering goes bonkers with headless and wdisplays #2164

any1 opened this issue May 6, 2020 · 11 comments · Fixed by #2292

Comments

@any1
Copy link
Contributor

any1 commented May 6, 2020

Steps to reproduce:

  • swaymsg create_output
  • Run wdisplays
  • Move the headless display and "Apply"
@Hummer12007
Copy link

Another issue with headless outputs: image capture is messed up (images contain two copies of the headless output): https://l.sr.ht/04m1.jpg

@any1
Copy link
Contributor Author

any1 commented May 10, 2020

The following patch fixes the flickering on the main output when wdisplays is run:

diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c
index 82077617..3e8079ca 100644
--- a/backend/drm/renderer.c
+++ b/backend/drm/renderer.c
@@ -127,7 +127,13 @@ static void finish_drm_surface(struct wlr_drm_surface *surf) {

 bool drm_surface_make_current(struct wlr_drm_surface *surf,
                int *buffer_damage) {
-       return wlr_egl_make_current(&surf->renderer->egl, surf->egl, buffer_damage);
+       if(!wlr_egl_make_current(&surf->renderer->egl, surf->egl, buffer_damage)) {
+               return false;
+       }
+
+       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+       return true;
 }

 bool export_drm_bo(struct gbm_bo *bo, struct wlr_dmabuf_attributes *attribs) {

There still remains an issue that wdisplays doesn't exit when its window is closed, leaving the display name overlay on all outputs. It needs to be killed to go away. Running wdisplays again after killing it works but it doesn't show the display contents like before.

@emersion
Copy link
Member

Hmm, weird, we're supposed to already reset the FB here: https://github.com/swaywm/wlroots/blob/master/backend/headless/output.c#L133

@emersion
Copy link
Member

Ah, maybe swap the wlr_egl_make_current and the glBindFramebuffer calls?

@any1
Copy link
Contributor Author

any1 commented May 10, 2020

Ah, maybe swap the wlr_egl_make_current and the glBindFramebuffer calls?

Doesn't do anything. :)

@any1
Copy link
Contributor Author

any1 commented May 10, 2020

Maybe the problem is that rendering to different outputs can happen concurrently? If I do this:

diff --git a/types/wlr_output.c b/types/wlr_output.c
index 3316653a..24e779a6 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -436,6 +436,8 @@ static void output_state_clear_buffer(struct wlr_output_state *state) {
 }

 bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) {
+       printf("Attach render %p\n", output);
+
        if (!output->impl->attach_render(output, buffer_age)) {
                return false;
        }
@@ -555,6 +557,8 @@ bool wlr_output_test(struct wlr_output *output) {
 }

 bool wlr_output_commit(struct wlr_output *output) {
+       printf("Commit %p\n", output);
+
        if (!output_basic_test(output)) {
                wlr_log(WLR_ERROR, "Basic output test failed");
                return false;

and then run sway, I get some instances of attach_render being called twice in a row, like this:

Attach render 0x556c13a1abb0
Attach render 0x556c13848280
Commit 0x556c13848280
Attach render 0x556c13848280
Commit 0x556c13848280
Attach render 0x556c13a1abb0
Commit 0x556c13a1abb0

@emersion
Copy link
Member

Can you add a log in wlr_output_rollback too?

Rendering can't happen concurrently, that would be a Sway bug.

@any1
Copy link
Contributor Author

any1 commented May 10, 2020

Yes, indeed rollback is called before attach.

@any1
Copy link
Contributor Author

any1 commented May 25, 2020

Running wf-recorder or wayvnc on the headless display also causes flickering on the display connected to HDMI, so that's most likely triggered by wlr-screencopy

@any1
Copy link
Contributor Author

any1 commented Jun 16, 2020

Running with apitrace, I can see that the glFramebufferBind and the context is sometimes left hanging. Example:

133653 eglMakeCurrent(dpy = 0x55563f0135b0, draw = NULL, read = NULL, ctx = 0x55563f01c4b0) = EGL_TRUE
133654 glBindFramebuffer(target = GL_FRAMEBUFFER, framebuffer = 301)
133655 eglGetCurrentContext() = 0x55563f01c4b0
133656 glGetIntegerv(pname = GL_IMPLEMENTATION_COLOR_READ_FORMAT, params = &6408)
133657 glGetIntegerv(pname = GL_IMPLEMENTATION_COLOR_READ_TYPE, params = &5121)
133659 eglMakeCurrent(dpy = 0x55563f0135b0, draw = 0x55563fa80be0, read = 0x55563fa80be0, ctx = 0x55563f01c4b0) = EGL_TRUE
133660 eglQuerySurface(dpy = 0x55563f0135b0, surface = 0x55563fa80be0, attribute = EGL_BUFFER_AGE_KHR, value = &3) = EGL_TRUE
133661 eglGetCurrentContext() = 0x55563f01c4b0
133662 glViewport(x = 0, y = 0, width = 2560, height = 1440)
133663 glEnable(cap = GL_BLEND)
133664 glBlendFunc(sfactor = GL_ONE, dfactor = GL_ONE_MINUS_SRC_ALPHA)

The virtual output is 1080p, so that second eglMakeCurrent followed by glViewport with different dimensions means that a different output is suddenly being targeted.

It is perhaps a point of interest that glGetIntegerv is a result of wlr_output_preferred_read_format which is called from screencopy when a client requests a new frame.

@any1
Copy link
Contributor Author

any1 commented Jun 16, 2020

Ahh, I figured it out: https://github.com/swaywm/wlroots/blob/master/types/wlr_output.c#L451

emersion added a commit to emersion/wlroots that referenced this issue Jun 19, 2020
…_format

attach_render was called without un-setting the current rendering
context afterwards.

Closes: swaywm#2164
ddevault pushed a commit that referenced this issue Jun 19, 2020
…_format

attach_render was called without un-setting the current rendering
context afterwards.

Closes: #2164
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
3 participants