From b2ba15425ce41e134d7e1187e366374d9cb41a06 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Wed, 3 Jul 2024 20:06:20 +0200 Subject: [PATCH] Hopefully fix screenshots on Wayland - screenshots on native wayland (SDL_VIDEODRIVER=wayland) were black, at least on Gnome => fixed(?) by reading from the default (back) buffer instead of the front buffer - after taking a screenshot, resizing the window (or switching to fullscreen) was broken (window remained black or became invisible or partly contained garbage), both with native wayland and xwayland => fixed by restoring the glReadBuffer state after reading the pixels --- neo/renderer/RenderSystem.h | 1 + neo/renderer/RenderSystem_init.cpp | 18 ++++++++++++++++-- neo/sys/glimp.cpp | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/neo/renderer/RenderSystem.h b/neo/renderer/RenderSystem.h index 2972ba26..15a98645 100644 --- a/neo/renderer/RenderSystem.h +++ b/neo/renderer/RenderSystem.h @@ -93,6 +93,7 @@ typedef struct glconfig_s { // DG: current video backend is known to need opaque default framebuffer // used if r_fillWindowAlphaChan == -1 bool shouldFillWindowAlpha; + bool isWayland; // DG: for other wayland-specific hacks.. (does *not* detect XWayland!) // For some reason people decided that we need displays with ultra small pixels, // so everything rendered on them must be scaled up to be legible. diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index d9a4a1cb..3a5fd169 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -1251,8 +1251,22 @@ void R_ReadTiledPixels( int width, int height, byte *buffer, renderView_t *ref = h = height - yo; } - qglReadBuffer( GL_FRONT ); - qglReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, temp ); + if ( glConfig.isWayland ) { + // DG: Native Wayland (=> not XWayland) doesn't seem to support reading + // from the front buffer - screenshot is black then.. + // So just read from the default (probably back-) buffer + qglReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, temp ); + } else { + // DG: It's probably better to restore the glReadBuffer mode after reading the pixels.. + // (at least with XWayland on GNOME changing resolutions is wonky when not doing this) + GLint oldReadBuf = GL_BACK; + qglGetIntegerv( GL_READ_BUFFER, &oldReadBuf ); + qglReadBuffer( GL_FRONT ); + + qglReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, temp ); + + qglReadBuffer( oldReadBuf ); + } int row = ( w * 3 + 3 ) & ~3; // OpenGL pads to dword boundaries diff --git a/neo/sys/glimp.cpp b/neo/sys/glimp.cpp index dc4ca35b..afee28dc 100644 --- a/neo/sys/glimp.cpp +++ b/neo/sys/glimp.cpp @@ -579,10 +579,12 @@ try_again: // for r_fillWindowAlphaChan -1, see also the big comment above glConfig.shouldFillWindowAlpha = false; + glConfig.isWayland = false; #if SDL_VERSION_ATLEAST(2, 0, 0) const char* videoDriver = SDL_GetCurrentVideoDriver(); if (idStr::Icmp(videoDriver, "wayland") == 0) { glConfig.shouldFillWindowAlpha = true; + glConfig.isWayland = true; } #endif