Maniphest T98462

Save Screenshot (glReadPixels) fails under Wayland
Closed, Resolved

Assigned To
Campbell Barton (campbellbarton)
Authored By
Campbell Barton (campbellbarton)
May 28 2022, 7:18 AM
Tags
  • Platform: Linux
  • BF Blender
Subscribers
Campbell Barton (campbellbarton)
Christian Rauch (christian.rauch)
Hans Goudey (HooglyBoogly)

Description

When running Blender under Wayland, taking a screenshot doesn't work,
it just produces a black image.


Steps to reproduce:

  • Open blender with factory settings.
  • Window -> Save Screenshot
  • Save the screenshot.
  • View the image, it's entirely black.
NOTE: Calling bpy.ops.screen.screenshot(filepath="/tmp/screen.png") is also a quick way to test this.


I looked into a fix but couldn't find a solution, opening this report.

Findings so far:

  • Tested with da9e14b0b91c81d29c4e44f40ac299ae847367de.
  • Tested with D12034 applied (no difference).
  • glReadPixels works as expected for off-screen buffers, it only fails when reading from the front-buffer.

Screenshot fails under the following configurations:

  • Gnome-Shell's Wayland Compositor.
  • Sway Window Manger.
  • River Window Manager (which I used for all other tests).

These Configurations Fail

  • Default factory startup with WITH_GHOST_WAYLAND enabled and WITH_GHOST_X11 disabled.
  • Default factory startup with WITH_GHOST_WAYLAND enabled and WITH_GHOST_X11 enabled.
  • Software GL LIBGL_ALWAYS_SOFTWARE=1 GALLIUM_DRIVER=llvmpipe, when launching Blender with this environment as well as both gnome-shell & Blender.
  • Using WITH_GHOST_SDL in Wayland.

These Configurations Work

  • Default factory startup in Wayland, inside Xwayland with WITH_GHOST_X11 enabled.
  • Default factory startup in Wayland, inside Xwayland with WITH_GHOST_SDL enabled.

Other details

  • There are no errors reported by OpenGL after glReadPixels.
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);

Return GL_UNSIGNED_BYTE & GL_RGBA, which is whats being used.


Since screenshot works in SDL+X11 but fails in SDL+Wayland,
it seems there may be some limitation in the Wayland OpenGL implementation.

... from looking further online there seems to be issues with Wayland & glReadPixels but most of the information I found related to embedded devices.

Revisions and Commits

rB Blender

Event Timeline

Campbell Barton (campbellbarton) created this task.May 28 2022, 7:18 AM
Campbell Barton (campbellbarton) mentioned this in T76428: GHOST/Wayland Support.May 28 2022, 7:59 AM
Hans Goudey (HooglyBoogly) changed the task status from Needs Triage to Confirmed.May 30 2022, 3:03 PM
Hans Goudey (HooglyBoogly) added a subscriber: Hans Goudey (HooglyBoogly).

I have no idea about this area, but this also crashes Blender with a use-after-free ASAN report for me, so I can "confirm" this.

Christian Rauch (christian.rauch) added a subscriber: Christian Rauch (christian.rauch).Jun 7 2022, 1:27 AM

Does this also appear with EGL on X11 (WITH_GL_EGL=ON but WITH_GHOST_WAYLAND=OFF)?

Which driver are you using? Your log says "AMD Radeon RX 5700 XT (navi10, LLVM 13.0.1, DRM 3.44, 5.17.9-arch1-1)" which sounds like software rendering through LLVMpipe.

Campbell Barton (campbellbarton) added a comment.EditedJun 7 2022, 2:28 AM

@Christian Rauch (christian.rauch) yes, WITH_GL_EGL in X11 works.
The driver being used is AMDgpu: https://en.wikipedia.org/wiki/AMDgpu_(Linux_kernel_module) I don't think I can use alternative drivers, besides software rendering (the closed source AMD drivers only seem to work for Xorg).


Some things worth checking:

  • Is this intentional? From what I can tell reading screen data is viewed by wayland as a security hole (see https://bugs.freedesktop.org/show_bug.cgi?id=98672 ), making actions such as simulating events, warping the cursor and screen shot utilities impossible or difficult to implement.

    Investigating this most likely involves using a debug OpenGL library to check what glReadPixels is doing internally.
  • Is this spesific to AMD GPU's? (do Intel drivers work for e.g.).

If this is intentional & can't be worked around on our side. we could avoid using glReadPixels which is only used screen-shot and as a fallback for UI_OT_eyedropper_color (when accessing image pixels directly isn't possible).

Possible ways to avoid could be to access the textures used to draw the area/region (in the case of sampling).

In the case of screen-shot it may also be possible to access the textures used for drawing the window. Or, use the wayland API to access this info (check on how wayland screen-shot tools such as grim work https://git.sr.ht/~emersion/grim ), then access screenshot as part of ghost.

As I don't think this is all that high priority, we could even disable screenshot for wayland until a solution is found. (or disable for AMD if this only impacts AMD).

Campbell Barton (campbellbarton) added a comment.Jun 7 2022, 5:19 AM

@Hans Goudey (HooglyBoogly) what hardware are you using and what was the ASAN crash?

Hans Goudey (HooglyBoogly) added a comment.Jun 7 2022, 11:15 AM

Hmm, I actually can't reproduce this anymore. I think I was using the built-in gnome screenshot tool, but that does sound a bit weird.
Now Blender's screenshot operator seems to work fine too.

Just in case:

Operating system: Linux-5.17.7-300.fc36.x86_64-x86_64-with-glibc2.35 64 Bits
Graphics card: AMD Radeon RX 590 Series (polaris10, LLVM 14.0.0, DRM 3.44, 5.17.7-300.fc36.x86_64) AMD 4.6 (Core Profile) Mesa 22.0.3
Campbell Barton (campbellbarton) added a comment.Jun 7 2022, 1:53 PM

@Hans Goudey (HooglyBoogly) does it work with WITH_GHOST_X11=OFF and WITH_GHOST_WAYLAND=ON ? (As X11 under Xwayland works for me too).

Hans Goudey (HooglyBoogly) added a comment.Jun 7 2022, 2:21 PM

Yeah, everything seems to work fine for me with those build options. I'm using Fedora 36 with Wayland. I wish I took more detailed notes of the problem before. Just in case, I checked WITH_GL_EGL and it also worked.

Pratik Borhade (PratikPB2123) added a project: BF Blender.Jun 7 2022, 2:32 PM
Campbell Barton (campbellbarton) updated the task description.Aug 16 2022, 6:37 AM
Campbell Barton (campbellbarton) closed this task as Resolved by committing rB48da8c40405c: Fix T98462: Save Screenshot (glReadPixels) fails under Wayland.Aug 17 2022, 4:58 AM
Campbell Barton (campbellbarton) claimed this task.
Campbell Barton (campbellbarton) added a commit: rB48da8c40405c: Fix T98462: Save Screenshot (glReadPixels) fails under Wayland.
Campbell Barton (campbellbarton) added a comment.EditedAug 17 2022, 5:05 AM

This bug was caused by the behavior of eglSwapBuffer, On my system EGL_BUFFER_PRESERVED is not supported, so accessing the front-buffer isn't a reliable way of reading the image. Although it does work under some conditions, for example - removing the redraw before reading the front-buffer works as expected. There is an issue with drawing into the back-buffer, calling eglSwapBuffer then immediately accessing the front-buffer. Given some time for wayland to draw the window this should work, but when these commands run without time for the egl-surface to draw it fails.
It's possible to redraw then read from the back-buffer, or tweak buffer swapping to make it work but this seems too fragile and likely to break (since drawing doesn't always call buffer-swap).

So I've committed off-screen buffer drawing instead, while this is a workaround I don't see any down-sides as this is more likely to give correct output in some corner cases (minimized window, partially off-screen windows ... etc).