Smithay / smithay

A smithy for rusty wayland compositors
MIT License
1.9k stars 168 forks source link

Not screenshot #1595

Open rediskap opened 4 days ago

rediskap commented 4 days ago

In niri wm, where the smithay library is used, screenshots do not work! In the detailed thread https://github.com/YaLTeR/niri/issues/807, they refer to smithay

YaLTeR commented 3 days ago

It seems that downloading the screenshot texture from GPU to CPU fails in a way unexpected in Smithay code:

2024-11-15T19:37:13.717921Z ERROR smithay::backend::renderer::gles: [GL] GL_INVALID_ENUM in glBufferData(invalid usage: GL_STREAM_READ)
2024-11-15T19:37:13.718971Z ERROR smithay::backend::renderer::gles: [GL] GL_INVALID_OPERATION in glReadPixels(out of bounds PBO access)
2024-11-15T19:37:13.719081Z  WARN niri::input: error capturing screenshot: error copying texture
Caused by:
    Unsupported pixel format: DrmFourcc(AB24)
2024-11-15T19:37:17.534903Z ERROR smithay::backend::renderer::gles: [GL] GL_INVALID_ENUM in glBufferData(invalid usage: GL_STREAM_READ)
2024-11-15T19:37:17.534963Z ERROR smithay::backend::renderer::gles: [GL] GL_INVALID_OPERATION in glReadPixels(out of bounds PBO access)
2024-11-15T19:37:17.534982Z  WARN niri::input: error taking screenshot: error rendering
Caused by:
    0: error copying framebuffer
    1: Unsupported pixel format: DrmFourcc(AB24)
2024-11-15T19:37:20.300862Z ERROR smithay::backend::renderer::gles: [GL] GL_INVALID_ENUM in glBufferData(invalid usage: GL_STREAM_READ)
2024-11-15T19:37:20.300922Z ERROR smithay::backend::renderer::gles: [GL] GL_INVALID_OPERATION in glReadPixels(out of bounds PBO access)
2024-11-15T19:37:20.300949Z  WARN niri::input: error taking screenshot: error rendering
Caused by:
    0: error copying framebuffer
    1: Unsupported pixel format: DrmFourcc(AB24)

There's eglinfo output: https://github.com/user-attachments/files/17801961/egl.txt

System:

Drakulix commented 3 days ago

What format is the framebuffer in this case? (The full compositor log should show this.)

If the framebuffer uses ARGB, but niri is trying to read ABGR the driver might not be happy about this and doesn't do the swizzle for us.

Note that unsupported-pixel-format is a matchable GlesError by design, because OpenGL ES 2.0 doesn't guarantee that reading back a buffer with glReadPixels will work with anything but the framebuffers format. while also not guaranteeing, that reading BGRA_EXT will work at all.

Which leads to fun combinations of e.g. Mesa allowing to read BGRA on BGRA framebuffers, but nvidia doesn't, but is happy to do the swizzle for us. As a result this API is designed to be failable, so compositors could try both.

YaLTeR commented 3 days ago

According to drm_info from https://github.com/user-attachments/files/17797382/drm_info.txt, the primary plane is XRGB8888. (Which may be notable considering niri only passes Argb/Abgr as supported color formats.)

During a screenshot, niri always creates a new Abgr8888 texture and renders to it from scratch, then downloads the result to CPU.

Drakulix commented 3 days ago

(Which may be notable considering niri only passes Argb/Abgr as supported color formats.)

No it's not. Internally smithay maps these to their X-variants for buffer allocation, if the A-variants aren't available, as the primary plane can obviously be opaque (if no underlays are present). (The GL Buffers are still alpha-variants to allow for blending.)

During a screenshot, niri always creates a new Abgr8888 texture and renders to it from scratch, then downloads the result to CPU.

Ah, so you are controlling the framebuffer- (the texture in this case) and read-format by not reading back directly from the plane buffer.

In that case the gl-format and type should be GL_RGBA and GL_UNSIGNED_BYTE (as seen here), which really should be supported reading the docs (see also usage here and error codes mapped to UnsupportedPixelFormat here). OpenGl ES 3.0 (which we may also bind) does add a few more error cases, but again nothing that should apply imo.

So the only reason I could think of is PBO's being unsupported, which we use for asynchronous read-back (which is also very heavily used in the multi-renderer). Reading about them, they are technically a GL ES 3.0 feature, if neither GL_ARB_pixel_buffer_object or GL_EXT_pixel_buffer_object are available, which according to the eglinfo-output is indeed not the case for this very barebones GL ES implementation from crocus.

So we probably need a new capability and a synchronous pixel download to fix this...