From e0114be3a2e030fc83cecc894c2a430f8d2eb287 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Mon, 2 Sep 2024 19:11:34 -0400 Subject: [PATCH 01/18] steamcompmgr: remove dead code --- src/steamcompmgr.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index a8d959f78..db2d82b86 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -7967,33 +7967,7 @@ steamcompmgr_main(int argc, char **argv) steamcompmgr_exit(); } -void steamcompmgr_send_frame_done_to_focus_window() -{ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - if ( global_focus.focusWindow && global_focus.focusWindow->xwayland().surface.main_surface ) - { - wlserver_lock(); - wlserver_send_frame_done( global_focus.focusWindow->xwayland().surface.main_surface , &now ); - wlserver_unlock(); - } -} -gamescope_xwayland_server_t *steamcompmgr_get_focused_server() -{ - if (global_focus.inputFocusWindow != nullptr) - { - gamescope_xwayland_server_t *server = NULL; - for (size_t i = 0; (server = wlserver_get_xwayland_server(i)); i++) - { - if (server->ctx->focus.inputFocusWindow == global_focus.inputFocusWindow) - return server; - } - } - - return wlserver_get_xwayland_server(0); -} struct wlr_surface *steamcompmgr_get_server_input_surface( size_t idx ) { From efbd2aeea9f400b6b4e7025b53630cfbe88cdeb6 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Mon, 2 Sep 2024 20:25:44 -0400 Subject: [PATCH 02/18] steamcompmgr, commit.cpp: cleanup some stuff --- src/commit.cpp | 10 ++-- src/steamcompmgr.cpp | 110 ++++++++++++++++++------------------------- 2 files changed, 48 insertions(+), 72 deletions(-) diff --git a/src/commit.cpp b/src/commit.cpp index a16df1f77..fc1767ea7 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -126,7 +126,7 @@ void commit_t::SetFence( int nFence, bool bMangoNudge, CommitDoneList_t *pDoneCo m_pDoneCommits = pDoneCommits; } -void calc_scale_factor(float &out_scale_x, float &out_scale_y, float sourceWidth, float sourceHeight); +glm::vec2 calc_scale_factor(float sourceWidth, float sourceHeight); bool commit_t::ShouldPreemptivelyUpscale() { @@ -143,11 +143,7 @@ bool commit_t::ShouldPreemptivelyUpscale() if ( !vulkanTex ) return false; - float flScaleX = 1.0f; - float flScaleY = 1.0f; - // I wish this function was more programatic with its inputs, but it does do exactly what we want right now... - // It should also return a std::pair or a glm uvec - calc_scale_factor( flScaleX, flScaleY, vulkanTex->width(), vulkanTex->height() ); + glm::vec2 flScale = calc_scale_factor( vulkanTex->width(), vulkanTex->height() ); - return !close_enough( flScaleX, 1.0f ) || !close_enough( flScaleY, 1.0f ); + return !close_enough( flScale.x, 1.0f ) || !close_enough( flScale.y, 1.0f ); } diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index db2d82b86..dcdbc8ac6 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -770,8 +770,6 @@ unsigned long damageSequence = 0; uint64_t cursorHideTime = 10'000ul * 1'000'000ul; -bool gotXError = false; - unsigned int fadeOutStartTime = 0; unsigned int g_FadeOutDuration = 0; @@ -1340,58 +1338,46 @@ window_is_fullscreen( steamcompmgr_win_t *w ) return w && ( window_is_steam( w ) || w->isFullscreen ); } -void calc_scale_factor_scaler(float &out_scale_x, float &out_scale_y, float sourceWidth, float sourceHeight) +glm::vec2 calc_scale_factor_scaler(float sourceWidth, float sourceHeight) { - float XOutputRatio = currentOutputWidth / (float)g_nNestedWidth; - float YOutputRatio = currentOutputHeight / (float)g_nNestedHeight; - float outputScaleRatio = std::min(XOutputRatio, YOutputRatio); + glm::vec2 source = glm::vec2 {sourceWidth, sourceHeight}; + auto outputRatio = glm::vec2 { + currentOutputWidth / (float)g_nNestedWidth, + currentOutputHeight / (float)g_nNestedHeight + }; + float outputScaleRatio = std::min(outputRatio.x, outputRatio.y); - float XRatio = (float)g_nNestedWidth / sourceWidth; - float YRatio = (float)g_nNestedHeight / sourceHeight; + glm::vec2 ratios = glm::vec2 {g_nNestedWidth, g_nNestedHeight} / source; if (g_upscaleScaler == GamescopeUpscaleScaler::STRETCH) { - out_scale_x = XRatio * XOutputRatio; - out_scale_y = YRatio * YOutputRatio; - return; + return ratios * outputRatio; } - if (g_upscaleScaler != GamescopeUpscaleScaler::FILL) - { - out_scale_x = std::min(XRatio, YRatio); - out_scale_y = std::min(XRatio, YRatio); - } - else - { - out_scale_x = std::max(XRatio, YRatio); - out_scale_y = std::max(XRatio, YRatio); - } + auto out_scale = glm::vec2{g_upscaleScaler != GamescopeUpscaleScaler::FILL ? glm::min(ratios.x, ratios.y) : glm::max(ratios.x, ratios.y)}; if (g_upscaleScaler == GamescopeUpscaleScaler::AUTO) { - out_scale_x = std::min(g_flMaxWindowScale, out_scale_x); - out_scale_y = std::min(g_flMaxWindowScale, out_scale_y); + out_scale = glm::min(out_scale, g_flMaxWindowScale); } - out_scale_x *= outputScaleRatio; - out_scale_y *= outputScaleRatio; + out_scale *= outputScaleRatio; if (g_upscaleScaler == GamescopeUpscaleScaler::INTEGER) { - if (out_scale_x > 1.0f) + if (out_scale.x > 1.0f) { // x == y here always. - out_scale_x = out_scale_y = floor(out_scale_x); + out_scale.x = out_scale.y = floor(out_scale.x); } } + + return out_scale; } -void calc_scale_factor(float &out_scale_x, float &out_scale_y, float sourceWidth, float sourceHeight) +glm::vec2 calc_scale_factor(float sourceWidth, float sourceHeight) { - calc_scale_factor_scaler(out_scale_x, out_scale_y, sourceWidth, sourceHeight); - - out_scale_x *= globalScaleRatio; - out_scale_y *= globalScaleRatio; + return calc_scale_factor_scaler(sourceWidth, sourceHeight) * globalScaleRatio; } /** @@ -1757,23 +1743,21 @@ void MouseCursor::paint(steamcompmgr_win_t *window, steamcompmgr_win_t *fit, str cursor_scale = std::max(cursor_scale, 1.0f); float scaledX, scaledY; - float currentScaleRatio_x = 1.0; - float currentScaleRatio_y = 1.0; int cursorOffsetX, cursorOffsetY; - calc_scale_factor(currentScaleRatio_x, currentScaleRatio_y, sourceWidth, sourceHeight); + glm::vec2 currentScaleRatio = calc_scale_factor(sourceWidth, sourceHeight); - cursorOffsetX = (currentOutputWidth - sourceWidth * currentScaleRatio_x) / 2.0f; - cursorOffsetY = (currentOutputHeight - sourceHeight * currentScaleRatio_y) / 2.0f; + cursorOffsetX = (currentOutputWidth - sourceWidth * currentScaleRatio.x) / 2.0f; + cursorOffsetY = (currentOutputHeight - sourceHeight * currentScaleRatio.y) / 2.0f; // Actual point on scaled screen where the cursor hotspot should be - scaledX = (winX - window->GetGeometry().nX) * currentScaleRatio_x + cursorOffsetX; - scaledY = (winY - window->GetGeometry().nY) * currentScaleRatio_y + cursorOffsetY; + scaledX = (winX - window->GetGeometry().nX) * currentScaleRatio.x + cursorOffsetX; + scaledY = (winY - window->GetGeometry().nY) * currentScaleRatio.y + cursorOffsetY; if ( zoomScaleRatio != 1.0 ) { - scaledX += ((sourceWidth / 2) - winX) * currentScaleRatio_x; - scaledY += ((sourceHeight / 2) - winY) * currentScaleRatio_y; + scaledX += ((sourceWidth / 2) - winX) * currentScaleRatio.x; + scaledY += ((sourceHeight / 2) - winY) * currentScaleRatio.y; } // Apply the cursor offset inside the texture using the display scale @@ -1887,8 +1871,6 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win { uint32_t sourceWidth, sourceHeight; int drawXOffset = 0, drawYOffset = 0; - float currentScaleRatio_x = 1.0; - float currentScaleRatio_y = 1.0; // Exit out if we have no window or // no commit. @@ -1958,30 +1940,31 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win bool offset = ( ( w->GetGeometry().nX || w->GetGeometry().nY ) && w != scaleW ); + glm::vec2 currentScaleRatio{}; if (sourceWidth != currentOutputWidth || sourceHeight != currentOutputHeight || offset || globalScaleRatio != 1.0f) { - calc_scale_factor(currentScaleRatio_x, currentScaleRatio_y, sourceWidth, sourceHeight); + currentScaleRatio = calc_scale_factor(sourceWidth, sourceHeight); - drawXOffset = ((int)currentOutputWidth - (int)sourceWidth * currentScaleRatio_x) / 2.0f; - drawYOffset = ((int)currentOutputHeight - (int)sourceHeight * currentScaleRatio_y) / 2.0f; + drawXOffset = ((int)currentOutputWidth - (int)sourceWidth * currentScaleRatio.x) / 2.0f; + drawYOffset = ((int)currentOutputHeight - (int)sourceHeight * currentScaleRatio.y) / 2.0f; if ( w != scaleW ) { - drawXOffset += w->GetGeometry().nX * currentScaleRatio_x; - drawYOffset += w->GetGeometry().nY * currentScaleRatio_y; + drawXOffset += w->GetGeometry().nX * currentScaleRatio.x; + drawYOffset += w->GetGeometry().nY * currentScaleRatio.y; } if ( zoomScaleRatio != 1.0 ) { - drawXOffset += (((int)sourceWidth / 2) - cursor->x()) * currentScaleRatio_x; - drawYOffset += (((int)sourceHeight / 2) - cursor->y()) * currentScaleRatio_y; + drawXOffset += (((int)sourceWidth / 2) - cursor->x()) * currentScaleRatio.x; + drawYOffset += (((int)sourceHeight / 2) - cursor->y()) * currentScaleRatio.y; } } layer->opacity = ( (w->isOverlay || w->isExternalOverlay) ? w->opacity / (float)OPAQUE : 1.0f ) * flOpacityScale; - layer->scale.x = 1.0 / currentScaleRatio_x; - layer->scale.y = 1.0 / currentScaleRatio_y; + layer->scale.x = 1.0 / currentScaleRatio.x; + layer->scale.y = 1.0 / currentScaleRatio.y; if ( w != scaleW ) { @@ -1992,8 +1975,8 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win { int xOffset = 0, yOffset = 0; - int width = w->GetGeometry().nWidth * currentScaleRatio_x; - int height = w->GetGeometry().nHeight * currentScaleRatio_y; + int width = w->GetGeometry().nWidth * currentScaleRatio.x; + int height = w->GetGeometry().nHeight * currentScaleRatio.y; if (globalScaleRatio != 1.0f) { @@ -2037,7 +2020,7 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win if (layer->filter == GamescopeUpscaleFilter::PIXEL) { // Don't bother doing more expensive filtering if we are sharp + integer. - if (float_is_integer(currentScaleRatio_x) && float_is_integer(currentScaleRatio_y)) + if (float_is_integer(currentScaleRatio.x) && float_is_integer(currentScaleRatio.y)) layer->filter = GamescopeUpscaleFilter::NEAREST; } @@ -5899,24 +5882,17 @@ steamcompmgr_exit(void) pthread_exit(NULL); } -static int -handle_io_error(Display *dpy) -{ - xwm_log.errorf("X11 I/O error"); - steamcompmgr_exit(); -} + static bool register_cm(xwayland_ctx_t *ctx) { - Window w; - Atom a; static char net_wm_cm[] = "_NET_WM_CM_Sxx"; snprintf(net_wm_cm, sizeof(net_wm_cm), "_NET_WM_CM_S%d", ctx->scr); - a = XInternAtom(ctx->dpy, net_wm_cm, false); + Atom a = XInternAtom(ctx->dpy, net_wm_cm, false); - w = XGetSelectionOwner(ctx->dpy, a); + Window w = XGetSelectionOwner(ctx->dpy, a); if (w != None) { XTextProperty tp; @@ -6750,6 +6726,10 @@ void init_xwayland_ctx(uint32_t serverId, gamescope_xwayland_server_t *xwayland_ if (!setup_error_handlers) { XSetErrorHandler(error); + static auto handle_io_error = [](Display *dpy) -> int { + xwm_log.errorf("X11 I/O error"); + steamcompmgr_exit(); + }; XSetIOErrorHandler(handle_io_error); setup_error_handlers = true; } From a8b9435bfab2d5df3d4572ce769a2c5c63308a29 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Mon, 2 Sep 2024 21:16:20 -0400 Subject: [PATCH 03/18] make currentOutputWidth/Height a glm::uvec2 --- src/rendervulkan.cpp | 14 ++++----- src/steamcompmgr.cpp | 70 +++++++++++++++++++++----------------------- src/steamcompmgr.hpp | 5 ++-- 3 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/rendervulkan.cpp b/src/rendervulkan.cpp index 63d34b3ca..4466a5eb4 100644 --- a/src/rendervulkan.cpp +++ b/src/rendervulkan.cpp @@ -3824,7 +3824,7 @@ std::optional vulkan_screenshot( const struct FrameInfo_t *frameInfo, const int pixelsPerGroup = 8; - cmdBuffer->dispatch(div_roundup(currentOutputWidth, pixelsPerGroup), div_roundup(currentOutputHeight, pixelsPerGroup)); + cmdBuffer->dispatch(div_roundup(currentOutputResolution.x, pixelsPerGroup), div_roundup(currentOutputResolution.y, pixelsPerGroup)); if ( pYUVOutTexture != nullptr ) { @@ -3939,7 +3939,7 @@ std::optional vulkan_composite( struct FrameInfo_t *frameInfo, gamesco cmdBuffer->bindTarget(compositeImage); cmdBuffer->uploadConstants(frameInfo, g_upscaleFilterSharpness / 10.0f); - cmdBuffer->dispatch(div_roundup(currentOutputWidth, pixelsPerGroup), div_roundup(currentOutputHeight, pixelsPerGroup)); + cmdBuffer->dispatch(div_roundup(currentOutputResolution.x, pixelsPerGroup), div_roundup(currentOutputResolution.y, pixelsPerGroup)); } else if ( frameInfo->useNISLayer0 ) { @@ -3984,11 +3984,11 @@ std::optional vulkan_composite( struct FrameInfo_t *frameInfo, gamesco int pixelsPerGroup = 8; - cmdBuffer->dispatch(div_roundup(currentOutputWidth, pixelsPerGroup), div_roundup(currentOutputHeight, pixelsPerGroup)); + cmdBuffer->dispatch(div_roundup(currentOutputResolution.x, pixelsPerGroup), div_roundup(currentOutputResolution.y, pixelsPerGroup)); } else if ( frameInfo->blurLayer0 ) { - update_tmp_images(currentOutputWidth, currentOutputHeight); + update_tmp_images(currentOutputResolution.x, currentOutputResolution.y); ShaderType type = SHADER_TYPE_BLUR_FIRST_PASS; @@ -4010,7 +4010,7 @@ std::optional vulkan_composite( struct FrameInfo_t *frameInfo, gamesco int pixelsPerGroup = 8; - cmdBuffer->dispatch(div_roundup(currentOutputWidth, pixelsPerGroup), div_roundup(currentOutputHeight, pixelsPerGroup)); + cmdBuffer->dispatch(div_roundup(currentOutputResolution.x, pixelsPerGroup), div_roundup(currentOutputResolution.y, pixelsPerGroup)); bool useSrgbView = frameInfo->layers[0].colorspace == GAMESCOPE_APP_TEXTURE_COLORSPACE_LINEAR; @@ -4023,7 +4023,7 @@ std::optional vulkan_composite( struct FrameInfo_t *frameInfo, gamesco cmdBuffer->setSamplerUnnormalized(VKR_BLUR_EXTRA_SLOT, true); cmdBuffer->setSamplerNearest(VKR_BLUR_EXTRA_SLOT, false); - cmdBuffer->dispatch(div_roundup(currentOutputWidth, pixelsPerGroup), div_roundup(currentOutputHeight, pixelsPerGroup)); + cmdBuffer->dispatch(div_roundup(currentOutputResolution.x, pixelsPerGroup), div_roundup(currentOutputResolution.y, pixelsPerGroup)); } else { @@ -4034,7 +4034,7 @@ std::optional vulkan_composite( struct FrameInfo_t *frameInfo, gamesco const int pixelsPerGroup = 8; - cmdBuffer->dispatch(div_roundup(currentOutputWidth, pixelsPerGroup), div_roundup(currentOutputHeight, pixelsPerGroup)); + cmdBuffer->dispatch(div_roundup(currentOutputResolution.x, pixelsPerGroup), div_roundup(currentOutputResolution.y, pixelsPerGroup)); } if ( pPipewireTexture != nullptr ) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index dcdbc8ac6..de464b48d 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -735,7 +735,7 @@ struct global_focus_t : public focus_t } global_focus; -uint32_t currentOutputWidth, currentOutputHeight; +glm::uvec2 currentOutputResolution; bool currentHDROutput = false; bool currentHDRForce = false; @@ -1340,14 +1340,11 @@ window_is_fullscreen( steamcompmgr_win_t *w ) glm::vec2 calc_scale_factor_scaler(float sourceWidth, float sourceHeight) { - glm::vec2 source = glm::vec2 {sourceWidth, sourceHeight}; - auto outputRatio = glm::vec2 { - currentOutputWidth / (float)g_nNestedWidth, - currentOutputHeight / (float)g_nNestedHeight - }; - float outputScaleRatio = std::min(outputRatio.x, outputRatio.y); + auto sourceDimensions = glm::vec2 {sourceWidth, sourceHeight}; + auto nestedResolution = glm::vec2 { (float) g_nNestedWidth, (float) g_nNestedHeight }; + auto outputRatio = (glm::vec2)currentOutputResolution / nestedResolution; - glm::vec2 ratios = glm::vec2 {g_nNestedWidth, g_nNestedHeight} / source; + glm::vec2 ratios = nestedResolution / sourceDimensions; if (g_upscaleScaler == GamescopeUpscaleScaler::STRETCH) { @@ -1361,7 +1358,8 @@ glm::vec2 calc_scale_factor_scaler(float sourceWidth, float sourceHeight) out_scale = glm::min(out_scale, g_flMaxWindowScale); } - out_scale *= outputScaleRatio; + float flOutputScaleRatio = std::min(outputRatio.x, outputRatio.y); + out_scale *= flOutputScaleRatio; if (g_upscaleScaler == GamescopeUpscaleScaler::INTEGER) { @@ -1729,8 +1727,8 @@ void MouseCursor::paint(steamcompmgr_win_t *window, steamcompmgr_win_t *fit, str if ( fit ) { // If we have an override window, try to fit it in as long as it won't make our scale go below 1.0. - sourceWidth = std::max( sourceWidth, clamp( fit->GetGeometry().nX + fit->GetGeometry().nWidth, 0, currentOutputWidth ) ); - sourceHeight = std::max( sourceHeight, clamp( fit->GetGeometry().nY + fit->GetGeometry().nHeight, 0, currentOutputHeight ) ); + sourceWidth = std::max( sourceWidth, clamp( fit->GetGeometry().nX + fit->GetGeometry().nWidth, 0, currentOutputResolution.x ) ); + sourceHeight = std::max( sourceHeight, clamp( fit->GetGeometry().nY + fit->GetGeometry().nHeight, 0, currentOutputResolution.y ) ); } float cursor_scale = 1.0f; @@ -1747,8 +1745,8 @@ void MouseCursor::paint(steamcompmgr_win_t *window, steamcompmgr_win_t *fit, str glm::vec2 currentScaleRatio = calc_scale_factor(sourceWidth, sourceHeight); - cursorOffsetX = (currentOutputWidth - sourceWidth * currentScaleRatio.x) / 2.0f; - cursorOffsetY = (currentOutputHeight - sourceHeight * currentScaleRatio.y) / 2.0f; + cursorOffsetX = (currentOutputResolution.x - sourceWidth * currentScaleRatio.x) / 2.0f; + cursorOffsetY = (currentOutputResolution.y - sourceHeight * currentScaleRatio.y) / 2.0f; // Actual point on scaled screen where the cursor hotspot should be scaledX = (winX - window->GetGeometry().nX) * currentScaleRatio.x + cursorOffsetX; @@ -1908,8 +1906,8 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win } else if ( flags & PaintWindowFlag::NoScale ) { - sourceWidth = currentOutputWidth; - sourceHeight = currentOutputHeight; + sourceWidth = currentOutputResolution.x; + sourceHeight = currentOutputResolution.y; } else { @@ -1933,20 +1931,20 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win if ( fit ) { // If we have an override window, try to fit it in as long as it won't make our scale go below 1.0. - sourceWidth = std::max( sourceWidth, clamp( fit->GetGeometry().nX + fit->GetGeometry().nWidth, 0, currentOutputWidth ) ); - sourceHeight = std::max( sourceHeight, clamp( fit->GetGeometry().nY + fit->GetGeometry().nHeight, 0, currentOutputHeight ) ); + sourceWidth = std::max( sourceWidth, clamp( fit->GetGeometry().nX + fit->GetGeometry().nWidth, 0, currentOutputResolution.x ) ); + sourceHeight = std::max( sourceHeight, clamp( fit->GetGeometry().nY + fit->GetGeometry().nHeight, 0, currentOutputResolution.y ) ); } } bool offset = ( ( w->GetGeometry().nX || w->GetGeometry().nY ) && w != scaleW ); glm::vec2 currentScaleRatio{}; - if (sourceWidth != currentOutputWidth || sourceHeight != currentOutputHeight || offset || globalScaleRatio != 1.0f) + if (sourceWidth != currentOutputResolution.x || sourceHeight != currentOutputResolution.y || offset || globalScaleRatio != 1.0f) { currentScaleRatio = calc_scale_factor(sourceWidth, sourceHeight); - drawXOffset = ((int)currentOutputWidth - (int)sourceWidth * currentScaleRatio.x) / 2.0f; - drawYOffset = ((int)currentOutputHeight - (int)sourceHeight * currentScaleRatio.y) / 2.0f; + drawXOffset = ((int)currentOutputResolution.x - (int)sourceWidth * currentScaleRatio.x) / 2.0f; + drawYOffset = ((int)currentOutputResolution.y - (int)sourceHeight * currentScaleRatio.y) / 2.0f; if ( w != scaleW ) { @@ -1980,12 +1978,12 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win if (globalScaleRatio != 1.0f) { - xOffset = (currentOutputWidth - currentOutputWidth * globalScaleRatio) / 2.0; - yOffset = (currentOutputHeight - currentOutputHeight * globalScaleRatio) / 2.0; + xOffset = (currentOutputResolution.x - currentOutputResolution.x * globalScaleRatio) / 2.0; + yOffset = (currentOutputResolution.y - currentOutputResolution.y * globalScaleRatio) / 2.0; } - layer->offset.x = (currentOutputWidth - xOffset - width) * -1.0f; - layer->offset.y = (currentOutputHeight - yOffset - height) * -1.0f; + layer->offset.x = (currentOutputResolution.x - xOffset - width) * -1.0f; + layer->offset.y = (currentOutputResolution.y - yOffset - height) * -1.0f; } else { @@ -2772,12 +2770,12 @@ paint_all(bool async) else if (pScreenshotTexture->format() == VK_FORMAT_B8G8R8A8_UNORM) { // Make our own copy of the image to remove the alpha channel. - auto imageData = std::vector(currentOutputWidth * currentOutputHeight * 4); + auto imageData = std::vector(currentOutputResolution.x * currentOutputResolution.y * 4); const uint32_t comp = 4; - const uint32_t pitch = currentOutputWidth * comp; - for (uint32_t y = 0; y < currentOutputHeight; y++) + const uint32_t pitch = currentOutputResolution.x * comp; + for (uint32_t y = 0; y < currentOutputResolution.y; y++) { - for (uint32_t x = 0; x < currentOutputWidth; x++) + for (uint32_t x = 0; x < currentOutputResolution.x; x++) { // BGR... imageData[y * pitch + x * comp + 0] = mappedData[y * pScreenshotTexture->rowPitch() + x * comp + 2]; @@ -2786,7 +2784,7 @@ paint_all(bool async) imageData[y * pitch + x * comp + 3] = 255; } } - if ( stbi_write_png( oScreenshotInfo->szScreenshotPath.c_str(), currentOutputWidth, currentOutputHeight, 4, imageData.data(), pitch ) ) + if ( stbi_write_png( oScreenshotInfo->szScreenshotPath.c_str(), currentOutputResolution.x, currentOutputResolution.y, 4, imageData.data(), pitch ) ) { xwm_log.infof( "Screenshot saved to %s", oScreenshotInfo->szScreenshotPath.c_str() ); bScreenshotSuccess = true; @@ -5376,8 +5374,8 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) if ( !allowSuperRes ) { - width = std::min(width, currentOutputWidth); - height = std::min(height, currentOutputHeight); + width = std::min(width, currentOutputResolution.x); + height = std::min(height, currentOutputResolution.y); } gamescope_xwayland_server_t *server = wlserver_get_xwayland_server( server_idx ); @@ -7396,8 +7394,7 @@ steamcompmgr_main(int argc, char **argv) // Enable color mgmt by default. g_ColorMgmt.pending.enabled = true; - currentOutputWidth = g_nPreferredOutputWidth; - currentOutputHeight = g_nPreferredOutputHeight; + currentOutputResolution = glm::uvec2 { g_nPreferredOutputWidth, g_nPreferredOutputHeight }; init_runtime_info(); @@ -7536,8 +7533,8 @@ steamcompmgr_main(int argc, char **argv) // Pick our width/height for this potential frame, regardless of how it might change later // At some point we might even add proper locking so we get real updates atomically instead // of whatever jumble of races the below might cause over a couple of frames - if ( currentOutputWidth != g_nOutputWidth || - currentOutputHeight != g_nOutputHeight || + if ( currentOutputResolution.x != g_nOutputWidth || + currentOutputResolution.y != g_nOutputHeight || currentHDROutput != g_bOutputHDREnabled || currentHDRForce != g_bForceHDRSupportDebug ) { @@ -7585,8 +7582,7 @@ steamcompmgr_main(int argc, char **argv) } } - currentOutputWidth = g_nOutputWidth; - currentOutputHeight = g_nOutputHeight; + currentOutputResolution = glm::uvec2 { g_nOutputWidth, g_nOutputHeight }; currentHDROutput = g_bOutputHDREnabled; currentHDRForce = g_bForceHDRSupportDebug; diff --git a/src/steamcompmgr.hpp b/src/steamcompmgr.hpp index 91b911b63..6d375009d 100644 --- a/src/steamcompmgr.hpp +++ b/src/steamcompmgr.hpp @@ -6,8 +6,9 @@ #include #include "wlr_end.hpp" -extern uint32_t currentOutputWidth; -extern uint32_t currentOutputHeight; +#include + +extern glm::uvec2 currentOutputResolution; unsigned int get_time_in_milliseconds(void); uint64_t get_time_in_nanos(); From 871acb15ecbf84842cb05fa94443ab1525ce4296 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Mon, 2 Sep 2024 21:26:45 -0400 Subject: [PATCH 04/18] calc_scale_factor_scaler: ternary back to if else --- src/steamcompmgr.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index de464b48d..6cfe27e93 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1351,7 +1351,12 @@ glm::vec2 calc_scale_factor_scaler(float sourceWidth, float sourceHeight) return ratios * outputRatio; } - auto out_scale = glm::vec2{g_upscaleScaler != GamescopeUpscaleScaler::FILL ? glm::min(ratios.x, ratios.y) : glm::max(ratios.x, ratios.y)}; + glm::vec2 out_scale; + if (g_upscaleScaler != GamescopeUpscaleScaler::FILL) { + out_scale = glm::vec2{ glm::min(ratios.x, ratios.y) }; + } else { + out_scale = glm::vec2{ glm::max(ratios.x, ratios.y) }; + } if (g_upscaleScaler == GamescopeUpscaleScaler::AUTO) { From f2a87fd73ef92df0b6f8a0c5ea7534f6262acc6f Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Mon, 2 Sep 2024 21:57:32 -0400 Subject: [PATCH 05/18] steamcompmgr: change a pair of offset vars to glm::ivec2 --- src/steamcompmgr.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 6cfe27e93..ab5acfb87 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1976,19 +1976,18 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win } else if (notificationMode) { - int xOffset = 0, yOffset = 0; + glm::ivec2 offset {0, 0}; int width = w->GetGeometry().nWidth * currentScaleRatio.x; int height = w->GetGeometry().nHeight * currentScaleRatio.y; if (globalScaleRatio != 1.0f) { - xOffset = (currentOutputResolution.x - currentOutputResolution.x * globalScaleRatio) / 2.0; - yOffset = (currentOutputResolution.y - currentOutputResolution.y * globalScaleRatio) / 2.0; + offset = (glm::ivec2) (((glm::vec2)currentOutputResolution - (glm::vec2)currentOutputResolution * globalScaleRatio) / 2.0f); } - layer->offset.x = (currentOutputResolution.x - xOffset - width) * -1.0f; - layer->offset.y = (currentOutputResolution.y - yOffset - height) * -1.0f; + layer->offset.x = (currentOutputResolution.x - offset.x - width) * -1.0f; + layer->offset.y = (currentOutputResolution.y - offset.y - height) * -1.0f; } else { From df805ad376cda5f2e5ac329d6eb5494edeef8c8d Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Tue, 3 Sep 2024 10:59:35 -0400 Subject: [PATCH 06/18] steamcompmgr: misc cleanups --- src/steamcompmgr.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index ab5acfb87..77600ec4d 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -5832,13 +5832,6 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) } } -static int -error(Display *dpy, XErrorEvent *ev) -{ - // Do nothing. XErrors are usually benign. - return 0; -} - [[noreturn]] static void steamcompmgr_exit(void) { @@ -6704,10 +6697,6 @@ const char* g_customCursorPath = nullptr; int g_customCursorHotspotX = 0; int g_customCursorHotspotY = 0; -xwayland_ctx_t g_ctx; - -static bool setup_error_handlers = false; - void init_xwayland_ctx(uint32_t serverId, gamescope_xwayland_server_t *xwayland_server) { assert(!xwayland_server->ctx); @@ -6725,8 +6714,13 @@ void init_xwayland_ctx(uint32_t serverId, gamescope_xwayland_server_t *xwayland_ exit(1); } + static bool setup_error_handlers = false; if (!setup_error_handlers) { + auto error = [](Display *dpy, XErrorEvent *ev) -> int { + // Do nothing. XErrors are usually benign. + return 0; + }; XSetErrorHandler(error); static auto handle_io_error = [](Display *dpy) -> int { xwm_log.errorf("X11 I/O error"); From f951f0f390f409a85fc3454a3709a4cc8f0fc432 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:07:23 -0400 Subject: [PATCH 07/18] steamcompmgr: remove some unused includes + some other cleanups --- src/steamcompmgr.cpp | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 77600ec4d..93bf05d25 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -47,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -57,23 +55,16 @@ #include #include #include -#include -#include -#include #include #if defined(__linux__) #include #elif defined(__DragonFly__) || defined(__FreeBSD__) #include #endif -#include -#include #include #include #include -#include #include -#include #include #include "waitable.h" @@ -94,9 +85,7 @@ #include "Utils/Process.h" #include "Utils/Algorithm.h" -#include "wlr_begin.hpp" #include "wlr/types/wlr_pointer_constraints_v1.h" -#include "wlr_end.hpp" #if HAVE_AVIF #include "avif/avif.h" @@ -2227,22 +2216,16 @@ paint_all(bool async) paintID++; gpuvis_trace_begin_ctx_printf( paintID, "paint_all" ); - steamcompmgr_win_t *w; - steamcompmgr_win_t *overlay; - steamcompmgr_win_t *externalOverlay; - steamcompmgr_win_t *notification; - steamcompmgr_win_t *override; - steamcompmgr_win_t *input; unsigned int currentTime = get_time_in_milliseconds(); bool fadingOut = ( currentTime - fadeOutStartTime < g_FadeOutDuration || g_bPendingFade ) && g_HeldCommits[HELD_COMMIT_FADE] != nullptr; - w = global_focus.focusWindow; - overlay = global_focus.overlayWindow; - externalOverlay = global_focus.externalOverlayWindow; - notification = global_focus.notificationWindow; - override = global_focus.overrideWindow; - input = global_focus.inputFocusWindow; + auto* w = global_focus.focusWindow; + auto* overlay = global_focus.overlayWindow; + auto* externalOverlay = global_focus.externalOverlayWindow; + auto* notification = global_focus.notificationWindow; + auto* override = global_focus.overrideWindow; + auto* input = global_focus.inputFocusWindow; if (++frameCounter == 300) { From 580b3adcbbbea2d78ee92cdf155f40bb9223ef97 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Tue, 3 Sep 2024 13:02:37 -0400 Subject: [PATCH 08/18] steamcompmgr: replace pre-c++20 "poor man's semaphore" w/ c++20 std::counting_semaphore also ensure statsThreadRun is accessed safely on archs w/ weak memory-ordering --- src/steamcompmgr.cpp | 40 ++++++---------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 93bf05d25..e269bca93 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -49,6 +48,7 @@ #include #include #include +#include #include #include @@ -1000,46 +1000,18 @@ namespace gamescope }); } - static std::atomic g_bForceRepaint{false}; extern int g_nCursorScaleHeight; -// poor man's semaphore -class sem -{ -public: - void wait( void ) - { - std::unique_lock lock(mtx); - - while(count == 0){ - cv.wait(lock); - } - count--; - } - - void signal( void ) - { - std::unique_lock lock(mtx); - count++; - cv.notify_one(); - } - -private: - std::mutex mtx; - std::condition_variable cv; - int count = 0; -}; - -sem statsThreadSem; +std::counting_semaphore statsThreadSem {0}; std::mutex statsEventQueueLock; std::vector< std::string > statsEventQueue; std::string statsThreadPath; int statsPipeFD = -1; -bool statsThreadRun; +std::atomic statsThreadRun{false}; //semi-protected by statsThreadSem (on x86[_64]), but should use acquire-release or seq_cst ordering to ensure safety (opting for seq_cst default, since we're only doing loads at runtime, & for x86_64 & aarch64, seq_cst loads have the same overhead as acquire loads) void statsThreadMain( void ) { @@ -1057,7 +1029,7 @@ void statsThreadMain( void ) } wait: - statsThreadSem.wait(); + statsThreadSem.acquire(); if ( statsThreadRun == false ) { @@ -1108,7 +1080,7 @@ static inline void stats_printf( const char* format, ...) statsEventQueue.push_back( eventstr ); - statsThreadSem.signal(); + statsThreadSem.release(); } } } @@ -5836,7 +5808,7 @@ steamcompmgr_exit(void) if ( statsThreadRun == true ) { statsThreadRun = false; - statsThreadSem.signal(); + statsThreadSem.release(); } { From 2d687e82b7df43580694c60c29515de4b6a58d25 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:59:31 -0400 Subject: [PATCH 09/18] steamcompmgr: Even moar tidying --- src/steamcompmgr.cpp | 295 ++++++++++++++++++------------------------- 1 file changed, 126 insertions(+), 169 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index e269bca93..01650c1b9 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -179,8 +179,7 @@ timespec nanos_to_timespec( uint64_t ulNanos ) return ts; } -static void -update_runtime_info(); +static void update_runtime_info(); gamescope::ConVar cv_adaptive_sync( "adaptive_sync", false, "Whether or not adaptive sync is enabled if available." ); gamescope::ConVar cv_adaptive_sync_ignore_overlay( "adaptive_sync_ignore_overlay", false, "Whether or not to ignore overlay planes for pushing commits with adaptive sync." ); @@ -683,11 +682,6 @@ extern bool g_bForceRelativeMouse; CommitDoneList_t g_steamcompmgr_xdg_done_commits; -struct ignore { - struct ignore *next; - unsigned long sequence; -}; - gamescope::CAsyncWaiter> g_ImageWaiter{ "gamescope_img" }; gamescope::CWaiter g_SteamCompMgrWaiter; @@ -732,7 +726,7 @@ std::vector< uint32_t > vecFocuscontrolAppIDs; bool gameFocused; -unsigned int gamesRunningCount; +unsigned int gamesRunningCount; //this is associated w/ gamesRunningAtom, but isn't used for anything float overscanScaleRatio = 1.0; float zoomScaleRatio = 1.0; @@ -957,7 +951,6 @@ bool g_bPendingFade = false; unsigned int frameCounter; unsigned int lastSampledFrameTime; -float currentFrameRate; static bool debugFocus = false; static bool drawDebugInfo = false; @@ -2201,6 +2194,7 @@ paint_all(bool async) if (++frameCounter == 300) { + static float currentFrameRate; currentFrameRate = 300 * 1000.0f / (currentTime - lastSampledFrameTime); lastSampledFrameTime = currentTime; frameCounter = 0; @@ -3071,12 +3065,12 @@ static bool is_good_override_candidate( steamcompmgr_win_t *override, steamcompm static bool pick_primary_focus_and_override(focus_t *out, Window focusControlWindow, const std::vector& vecPossibleFocusWindows, bool globalFocus, const std::vector& ctxFocusControlAppIDs) { - bool localGameFocused = false; - steamcompmgr_win_t *focus = NULL, *override_focus = NULL; bool controlledFocus = focusControlWindow != None || !ctxFocusControlAppIDs.empty(); - if ( controlledFocus ) - { + auto selectFocusableWindow = [=]() -> std::optional { + if ( !controlledFocus ) + return std::nullopt; + if ( focusControlWindow != None ) { for ( steamcompmgr_win_t *focusable_window : vecPossibleFocusWindows ) @@ -3086,9 +3080,7 @@ pick_primary_focus_and_override(focus_t *out, Window focusControlWindow, const s if ( focusable_window->xwayland().id == focusControlWindow ) { - focus = focusable_window; - localGameFocused = true; - goto found; + return focusable_window; } } } @@ -3099,16 +3091,18 @@ pick_primary_focus_and_override(focus_t *out, Window focusControlWindow, const s { if ( focusable_window->appID == focusable_appid ) { - focus = focusable_window; - localGameFocused = true; - goto found; + return focusable_window; } } } + + return std::nullopt; + }; + + auto oFocusWin = selectFocusableWindow(); + bool localGameFocused = !!oFocusWin; -found:; - } - + steamcompmgr_win_t* focus = localGameFocused ? *oFocusWin : nullptr; if ( !focus && ( !globalFocus || !controlledFocus ) ) { if ( !vecPossibleFocusWindows.empty() ) @@ -3118,6 +3112,7 @@ found:; } } + steamcompmgr_win_t* override_focus; auto resolveTransientOverrides = [&](bool maybe) { if ( !focus || focus->type != steamcompmgr_win_type_t::XWAYLAND ) @@ -3222,8 +3217,7 @@ found:; out->focusWindow = focus; } - if ( !override_focus && focus ) - { + auto getOtherOverrideWindow = [=]() -> steamcompmgr_win_t* { if ( controlledFocus ) { for ( auto focusable_appid : ctxFocusControlAppIDs ) @@ -3234,26 +3228,26 @@ found:; { if ( win_maybe_a_dropdown( fake_override ) && is_good_override_candidate( fake_override, focus ) && fake_override->appID == focus->appID ) { - override_focus = fake_override; - goto found2; + return fake_override; } } } } - } - else - { + } else { for ( steamcompmgr_win_t *fake_override : vecPossibleFocusWindows ) { if ( win_maybe_a_dropdown( fake_override ) && is_good_override_candidate( fake_override, focus ) ) { - override_focus = fake_override; - goto found2; + return fake_override; } } } - - found2:; + return nullptr; + }; + + if ( !override_focus && focus ) + { + override_focus = getOtherOverrideWindow(); resolveTransientOverrides( true ); } @@ -3291,7 +3285,7 @@ void xwayland_ctx_t::DetermineAndApplyFocus( const std::vector< steamcompmgr_win { xwayland_ctx_t *ctx = this; - steamcompmgr_win_t *inputFocus = NULL; + steamcompmgr_win_t *inputFocus = nullptr; steamcompmgr_win_t *prevFocusWindow = ctx->focus.focusWindow; ctx->focus.overlayWindow = nullptr; @@ -3333,7 +3327,7 @@ void xwayland_ctx_t::DetermineAndApplyFocus( const std::vector< steamcompmgr_win pick_primary_focus_and_override( &ctx->focus, ctx->focusControlWindow, vecPossibleFocusWindows, false, vecFocuscontrolAppIDs ); - if ( inputFocus == NULL ) + if ( inputFocus == nullptr ) { inputFocus = ctx->focus.focusWindow; } @@ -4504,8 +4498,7 @@ static void circulate_request( xwayland_ctx_t *ctx, XCirculateRequestEvent *circ XCirculateSubwindows( ctx->dpy, circulateRequest->window, circulateRequest->place ); } -static void -finish_destroy_win(xwayland_ctx_t *ctx, Window id, bool gone) +static void finish_destroy_win(xwayland_ctx_t *ctx, Window id, bool gone) { steamcompmgr_win_t **prev, *w; @@ -4539,39 +4532,31 @@ finish_destroy_win(xwayland_ctx_t *ctx, Window id, bool gone) } } -static void -destroy_win(xwayland_ctx_t *ctx, Window id, bool gone, bool fade) +static void destroy_win(xwayland_ctx_t *ctx, Window id, bool gone) { + auto destroyBaseFocusWindows = [id, gone](auto& focus) { + for (std::reference_wrapper focusWin + : (std::reference_wrapper[]) + { + focus.focusWindow, focus.inputFocusWindow, focus.overlayWindow, + focus.externalOverlayWindow, focus.notificationWindow, focus.overrideWindow + }) + { + if (x11_win(focusWin) == id && gone) + focusWin.get() = nullptr; + } + }; + // Context - if (x11_win(ctx->focus.focusWindow) == id && gone) - ctx->focus.focusWindow = nullptr; - if (x11_win(ctx->focus.inputFocusWindow) == id && gone) - ctx->focus.inputFocusWindow = nullptr; - if (x11_win(ctx->focus.overlayWindow) == id && gone) - ctx->focus.overlayWindow = nullptr; - if (x11_win(ctx->focus.externalOverlayWindow) == id && gone) - ctx->focus.externalOverlayWindow = nullptr; - if (x11_win(ctx->focus.notificationWindow) == id && gone) - ctx->focus.notificationWindow = nullptr; - if (x11_win(ctx->focus.overrideWindow) == id && gone) - ctx->focus.overrideWindow = nullptr; + destroyBaseFocusWindows(ctx->focus); if (ctx->currentKeyboardFocusWindow == id && gone) ctx->currentKeyboardFocusWindow = None; // Global Focus - if (x11_win(global_focus.focusWindow) == id && gone) - global_focus.focusWindow = nullptr; - if (x11_win(global_focus.inputFocusWindow) == id && gone) - global_focus.inputFocusWindow = nullptr; - if (x11_win(global_focus.overlayWindow) == id && gone) - global_focus.overlayWindow = nullptr; - if (x11_win(global_focus.notificationWindow) == id && gone) - global_focus.notificationWindow = nullptr; - if (x11_win(global_focus.overrideWindow) == id && gone) - global_focus.overrideWindow = nullptr; + destroyBaseFocusWindows(global_focus); if (x11_win(global_focus.fadeWindow) == id && gone) global_focus.fadeWindow = nullptr; - + MakeFocusDirty(); finish_destroy_win(ctx, id, gone); @@ -4615,8 +4600,8 @@ damage_win(xwayland_ctx_t *ctx, XDamageNotifyEvent *de) static void handle_wl_surface_id(xwayland_ctx_t *ctx, steamcompmgr_win_t *w, uint32_t surfaceID) { - struct wlr_surface *current_surface = NULL; - struct wlr_surface *main_surface = NULL; + struct wlr_surface *current_surface = nullptr; + struct wlr_surface *main_surface = nullptr; wlserver_lock(); @@ -4695,8 +4680,7 @@ handle_system_tray_opcode(xwayland_ctx_t *ctx, XClientMessageEvent *ev) { long opcode = ev->data.l[1]; - switch (opcode) { - case SYSTEM_TRAY_REQUEST_DOCK: { + if (opcode == SYSTEM_TRAY_REQUEST_DOCK) { Window embed_id = ev->data.l[2]; /* At this point we're supposed to initiate the XEmbed lifecycle by @@ -4708,9 +4692,7 @@ handle_system_tray_opcode(xwayland_ctx_t *ctx, XClientMessageEvent *ev) if (w) { w->isSysTrayIcon = true; } - break; - } - default: + } else { xwm_log.debugf("Unhandled _NET_SYSTEM_TRAY_OPCODE %ld", opcode); } } @@ -4865,9 +4847,8 @@ handle_selection_notify(xwayland_ctx_t *ctx, XSelectionEvent *ev) { Atom actual_type; int actual_format; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *data = NULL; + unsigned long nitems, bytes_after; + unsigned char *data = nullptr; XGetWindowProperty(ctx->dpy, ev->requestor, ev->property, 0, 0, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &data); @@ -4878,37 +4859,37 @@ handle_selection_notify(xwayland_ctx_t *ctx, XSelectionEvent *ev) if (actual_type == ctx->atoms.utf8StringAtom && actual_format == 8) { XGetWindowProperty(ctx->dpy, ev->requestor, ev->property, 0, bytes_after, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &data); - if (data) { - const char *contents = (const char *) data; - defer( XFree( data ); ); + if (!data) + return; + const char *contents = (const char *) data; + defer( XFree( data ); ); - if (ev->selection == ctx->atoms.clipboard) + if (ev->selection == ctx->atoms.clipboard) + { + if ( GetBackend()->GetNestedHints() ) { - if ( GetBackend()->GetNestedHints() ) - { - //GetBackend()->GetNestedHints()->SetSelection() - } - else - { - gamescope_set_selection( contents, GAMESCOPE_SELECTION_CLIPBOARD ); - } + //GetBackend()->GetNestedHints()->SetSelection() } - else if (ev->selection == ctx->atoms.primarySelection) + else { - if ( GetBackend()->GetNestedHints() ) - { - //GetBackend()->GetNestedHints()->SetSelection() - } - else - { - gamescope_set_selection( contents, GAMESCOPE_SELECTION_PRIMARY ); - } + gamescope_set_selection( contents, GAMESCOPE_SELECTION_CLIPBOARD ); + } + } + else if (ev->selection == ctx->atoms.primarySelection) + { + if ( GetBackend()->GetNestedHints() ) + { + //GetBackend()->GetNestedHints()->SetSelection() } else { - xwm_log.errorf( "Selection '%s' not supported. Ignoring", XGetAtomName(ctx->dpy, ev->selection) ); + gamescope_set_selection( contents, GAMESCOPE_SELECTION_PRIMARY ); } } + else + { + xwm_log.errorf( "Selection '%s' not supported. Ignoring", XGetAtomName(ctx->dpy, ev->selection) ); + } } } @@ -5699,45 +5680,22 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) gamescope_xwayland_server_t *server = wlserver_get_xwayland_server(server_id); if (server) { - if (global_focus.focusWindow && - global_focus.focusWindow->type == steamcompmgr_win_type_t::XWAYLAND && - global_focus.focusWindow->xwayland().ctx == server->ctx.get()) - global_focus.focusWindow = nullptr; - - if (global_focus.inputFocusWindow && - global_focus.inputFocusWindow->type == steamcompmgr_win_type_t::XWAYLAND && - global_focus.inputFocusWindow->xwayland().ctx == server->ctx.get()) - global_focus.inputFocusWindow = nullptr; - - if (global_focus.overlayWindow && - global_focus.overlayWindow->type == steamcompmgr_win_type_t::XWAYLAND && - global_focus.overlayWindow->xwayland().ctx == server->ctx.get()) - global_focus.overlayWindow = nullptr; - - if (global_focus.externalOverlayWindow && - global_focus.externalOverlayWindow->type == steamcompmgr_win_type_t::XWAYLAND && - global_focus.externalOverlayWindow->xwayland().ctx == server->ctx.get()) - global_focus.externalOverlayWindow = nullptr; - - if (global_focus.notificationWindow && - global_focus.notificationWindow->type == steamcompmgr_win_type_t::XWAYLAND && - global_focus.notificationWindow->xwayland().ctx == server->ctx.get()) - global_focus.notificationWindow = nullptr; - - if (global_focus.overrideWindow && - global_focus.overrideWindow->type == steamcompmgr_win_type_t::XWAYLAND && - global_focus.overrideWindow->xwayland().ctx == server->ctx.get()) - global_focus.overrideWindow = nullptr; - - if (global_focus.keyboardFocusWindow && - global_focus.keyboardFocusWindow->type == steamcompmgr_win_type_t::XWAYLAND && - global_focus.keyboardFocusWindow->xwayland().ctx == server->ctx.get()) - global_focus.keyboardFocusWindow = nullptr; - - if (global_focus.fadeWindow && - global_focus.fadeWindow->type == steamcompmgr_win_type_t::XWAYLAND && - global_focus.fadeWindow->xwayland().ctx == server->ctx.get()) - global_focus.fadeWindow = nullptr; + auto clearXwlWin = [](steamcompmgr_win_t*& win, xwayland_ctx_t* ctx) { + if (win && win->type == steamcompmgr_win_type_t::XWAYLAND + && win->xwayland().ctx == ctx) + win = nullptr; + }; + + for (std::reference_wrapper win + : (std::reference_wrapper[]) + { + global_focus.focusWindow, global_focus.inputFocusWindow, global_focus.overlayWindow, + global_focus.externalOverlayWindow, global_focus.notificationWindow, global_focus.overrideWindow, + global_focus.keyboardFocusWindow, global_focus.fadeWindow + }) + { + clearXwlWin(win, server->ctx.get()); + } if (global_focus.cursor && global_focus.cursor->getCtx() == server->ctx.get()) @@ -6491,7 +6449,7 @@ void xwayland_ctx_t::Dispatch() steamcompmgr_win_t * w = find_win(ctx, ev.xdestroywindow.window); if (w && w->xwayland().id == ev.xdestroywindow.window) - destroy_win(ctx, ev.xdestroywindow.window, true, true); + destroy_win(ctx, ev.xdestroywindow.window, true); break; } case MapNotify: @@ -6550,7 +6508,7 @@ void xwayland_ctx_t::Dispatch() if (w && w->xwayland().id == ev.xreparent.window) { - destroy_win(ctx, ev.xreparent.window, false, true); + destroy_win(ctx, ev.xreparent.window, false); } else { @@ -6672,7 +6630,7 @@ void init_xwayland_ctx(uint32_t serverId, gamescope_xwayland_server_t *xwayland_ static bool setup_error_handlers = false; if (!setup_error_handlers) { - auto error = [](Display *dpy, XErrorEvent *ev) -> int { + static auto error = [](Display *dpy, XErrorEvent *ev) -> int { // Do nothing. XErrors are usually benign. return 0; }; @@ -7024,7 +6982,7 @@ void update_vrr_atoms(xwayland_ctx_t *root_ctx, bool force, bool* needs_flush = // Keep this as a preference, starting with off. if ( force ) { - bool wants_vrr = cv_adaptive_sync; + bool wants_vrr = cv_adaptive_sync; uint32_t enabled_value = wants_vrr ? 1 : 0; XChangeProperty(root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeVRREnabled, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&enabled_value, 1 ); @@ -7084,18 +7042,22 @@ void steamcompmgr_check_xdg(bool vblank, uint64_t vblank_idx) { if (wlserver_xdg_dirty()) { - if (global_focus.focusWindow && global_focus.focusWindow->type == steamcompmgr_win_type_t::XDG) - global_focus.focusWindow = nullptr; - if (global_focus.inputFocusWindow && global_focus.inputFocusWindow->type == steamcompmgr_win_type_t::XDG) - global_focus.inputFocusWindow = nullptr; - if (global_focus.overlayWindow && global_focus.overlayWindow->type == steamcompmgr_win_type_t::XDG) - global_focus.overlayWindow = nullptr; - if (global_focus.notificationWindow && global_focus.notificationWindow->type == steamcompmgr_win_type_t::XDG) - global_focus.notificationWindow = nullptr; - if (global_focus.overrideWindow && global_focus.overrideWindow->type == steamcompmgr_win_type_t::XDG) - global_focus.overrideWindow = nullptr; - if (global_focus.fadeWindow && global_focus.fadeWindow->type == steamcompmgr_win_type_t::XDG) - global_focus.fadeWindow = nullptr; + auto clearXdgWin = [](steamcompmgr_win_t*& w) { + if (w && w->type == steamcompmgr_win_type_t::XDG) + w = nullptr; + }; + + for (std::reference_wrapper focusWin + : (std::reference_wrapper[]) + { + global_focus.focusWindow, global_focus.inputFocusWindow, global_focus.overlayWindow, + global_focus.notificationWindow, global_focus.overrideWindow, + global_focus.fadeWindow + }) + { + clearXdgWin(focusWin); + } + g_steamcompmgr_xdg_wins = wlserver_get_xdg_shell_windows(); MakeFocusDirty(); } @@ -7122,7 +7084,7 @@ void update_edid_prop() if (!filename) return; - gamescope_xwayland_server_t *server = NULL; + gamescope_xwayland_server_t *server = nullptr; for (size_t i = 0; (server = wlserver_get_xwayland_server(i)); i++) { XTextProperty text_property = @@ -7812,24 +7774,21 @@ steamcompmgr_main(int argc, char **argv) { bShouldPaint = hasRepaint; - if ( bIsVBlankFromTimer ) + if ( bIsVBlankFromTimer && hasRepaintNonBasePlane) { - if ( hasRepaintNonBasePlane ) + if ( nIgnoredOverlayRepaints >= cv_adaptive_sync_overlay_cycles ) { - if ( nIgnoredOverlayRepaints >= cv_adaptive_sync_overlay_cycles ) - { - // If we hit vblank and we previously punted on drawing an overlay - // we should go ahead and draw now. - bShouldPaint = true; - } - else if ( !bShouldPaint ) - { - // If we hit vblank (ie. fastest refresh cycle since last commit), - // and we aren't painting and we have a pending overlay, then: - // defer it until the next game update or next true vblank. - if ( !cv_adaptive_sync_ignore_overlay ) - nIgnoredOverlayRepaints++; - } + // If we hit vblank and we previously punted on drawing an overlay + // we should go ahead and draw now. + bShouldPaint = true; + } + else if ( !bShouldPaint ) + { + // If we hit vblank (ie. fastest refresh cycle since last commit), + // and we aren't painting and we have a pending overlay, then: + // defer it until the next game update or next true vblank. + if ( !cv_adaptive_sync_ignore_overlay ) + nIgnoredOverlayRepaints++; } } @@ -7896,8 +7855,6 @@ steamcompmgr_main(int argc, char **argv) steamcompmgr_exit(); } - - struct wlr_surface *steamcompmgr_get_server_input_surface( size_t idx ) { gamescope_xwayland_server_t *server = wlserver_get_xwayland_server( idx ); @@ -7915,7 +7872,7 @@ struct wlserver_x11_surface_info *lookup_x11_surface_info_from_xid( gamescope_xw return nullptr; // Lookup children too so we can get the window - // and go back to it's top-level parent. + // and go back to its top-level parent. // The xwayland bypass layer does this as we can have child windows // that cover the whole parent. std::unique_lock lock( xwayland_server->ctx->list_mutex ); From d59c2d69d22a7846de96ee1a4116b2cacf4dc2d9 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Wed, 4 Sep 2024 18:38:50 -0400 Subject: [PATCH 10/18] steamcompmgr, rc, commit: introduce make_rc() function + use it to cleanup import_commit() --- src/commit.cpp | 28 ++++++++++++++++++++++++++-- src/commit.h | 8 +++++++- src/rc.h | 29 ++++++++++++++++++++++++++++- src/steamcompmgr.cpp | 43 +++++++------------------------------------ 4 files changed, 68 insertions(+), 40 deletions(-) diff --git a/src/commit.cpp b/src/commit.cpp index fc1767ea7..f7920c6b2 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -7,11 +7,35 @@ extern gamescope::CAsyncWaiter> g_ImageWaiter; +uint64_t commit_t::getCommitID() +{ + static uint64_t maxCommmitID = 1; + return maxCommmitID++; +} + commit_t::commit_t() { - static uint64_t maxCommmitID = 0; - commitID = ++maxCommmitID; + commitID = getCommitID();; } + +commit_t::commit_t(std::in_place_t tag, ResListEntry_t& reslistentry, bool is_steam, uint64_t seq) + : RcObject(tag), + buf{reslistentry.buf}, + async{reslistentry.async}, + fifo{reslistentry.fifo}, + is_steam{is_steam}, + feedback( reslistentry.feedback + ? std::optional(std::in_place_t{}, *reslistentry.feedback) + : std::nullopt ), + win_seq{seq}, + surf{reslistentry.surf}, + presentation_feedbacks{std::move(reslistentry.presentation_feedbacks)}, + present_id{reslistentry.present_id}, + desired_present_time{reslistentry.desired_present_time} +{ + commitID = getCommitID(); +} + commit_t::~commit_t() { { diff --git a/src/commit.h b/src/commit.h index 1e45ce3ce..7aa740052 100644 --- a/src/commit.h +++ b/src/commit.h @@ -17,8 +17,14 @@ struct UpscaledTexture_t struct commit_t final : public gamescope::RcObject, public gamescope::IWaitable, public gamescope::NonCopyable { + protected: + ENABLE_IN_PLACE_RC + commit_t(std::in_place_t tag, ResListEntry_t& reslistentry, bool is_steam, uint64_t seq); + + uint64_t getCommitID(); + public: commit_t(); - ~commit_t(); + ~commit_t(); GamescopeAppTextureColorspace colorspace() const; diff --git a/src/rc.h b/src/rc.h index 980dd5c4a..6417c0e95 100644 --- a/src/rc.h +++ b/src/rc.h @@ -2,12 +2,23 @@ #include #include +#include namespace gamescope { + template + class Rc; + #define ENABLE_IN_PLACE_RC using gamescope::RcObject::RcObject; \ + template \ + friend gamescope::Rc gamescope::make_rc(Args&&... args); class RcObject { + template + friend gamescope::Rc make_rc(Args&&... args); + protected: + constexpr RcObject(std::in_place_t) : m_uRefCount{1}, m_uRefPrivate{1} {} public: + RcObject() = default; virtual ~RcObject() { } @@ -67,6 +78,7 @@ namespace gamescope class IRcObject : public RcObject { + using RcObject::RcObject; public: virtual uint32_t IncRef() { @@ -93,15 +105,30 @@ namespace gamescope static void DecRef( T* pObject ) { pObject->DecRefPrivate(); } }; + template + Rc make_rc(Args&&... args) { + T* pObj = new T(std::in_place_t{}, std::forward(args)...); + return Rc{std::in_place_t{}, pObj}; + } + template class Rc { template friend class Rc; + template + friend Rc gamescope::make_rc(Args&&... args); + using RcRef = RcRef_; + + protected: + constexpr Rc( std::in_place_t tag, T* pObject ) + : m_pObject{ pObject } {} //no IncRef here, because this constructor is used w/ in-place RcObject construction via friend function make_rc() + //this is locked behind protected access, to avoid any unintended use + public: - Rc() { } + constexpr Rc() { } Rc( std::nullptr_t ) { } Rc( T* pObject ) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 01650c1b9..5c878187a 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1169,33 +1169,11 @@ static steamcompmgr_win_t * find_win( xwayland_ctx_t *ctx, struct wlr_surface *s static gamescope::CBufferMemoizer s_BufferMemos; -// This really needs cleanup, this function is so silly... -static gamescope::Rc -import_commit ( - steamcompmgr_win_t *w, - struct wlr_surface *surf, - struct wlr_buffer *buf, - bool async, - std::shared_ptr swapchain_feedback, - std::vector presentation_feedbacks, - std::optional present_id, - uint64_t desired_present_time, - bool fifo ) -{ - gamescope::Rc commit = new commit_t; - - commit->win_seq = w->seq; - commit->surf = surf; - commit->buf = buf; - commit->async = async; - commit->fifo = fifo; - commit->is_steam = window_is_steam( w ); - commit->presentation_feedbacks = std::move(presentation_feedbacks); - if (swapchain_feedback) - commit->feedback = *swapchain_feedback; - commit->present_id = present_id; - commit->desired_present_time = desired_present_time; +static gamescope::Rc import_commit(steamcompmgr_win_t *w, ResListEntry_t& reslistentry) +{ + gamescope::Rc commit = gamescope::make_rc(reslistentry, window_is_steam( w ), w->seq); + auto*& buf = reslistentry.buf; if ( gamescope::OwningRc pTexture = s_BufferMemos.LookupVulkanTexture( buf ) ) { // Going from OwningRc -> Rc now. @@ -5686,6 +5664,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) win = nullptr; }; + #pragma GCC unroll 8 for (std::reference_wrapper win : (std::reference_wrapper[]) { @@ -6245,16 +6224,7 @@ void update_wayland_res(CommitDoneList_t *doneCommits, steamcompmgr_win_t *w, Re return; } - gamescope::Rc newCommit = import_commit( - w, - reslistentry.surf, - buf, - reslistentry.async, - std::move(reslistentry.feedback), - std::move(reslistentry.presentation_feedbacks), - reslistentry.present_id, - reslistentry.desired_present_time, - reslistentry.fifo ); + gamescope::Rc newCommit = import_commit(w, reslistentry); int fence = -1; if ( newCommit != nullptr ) @@ -7047,6 +7017,7 @@ void steamcompmgr_check_xdg(bool vblank, uint64_t vblank_idx) w = nullptr; }; + #pragma GCC unroll 6 for (std::reference_wrapper focusWin : (std::reference_wrapper[]) { From 3f9d985933b30b634b9562cdf9db7c924472f6be Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Wed, 4 Sep 2024 20:22:15 -0400 Subject: [PATCH 11/18] fix uninitialized pointer --- src/steamcompmgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 5c878187a..8dcb26c22 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -3090,7 +3090,7 @@ pick_primary_focus_and_override(focus_t *out, Window focusControlWindow, const s } } - steamcompmgr_win_t* override_focus; + steamcompmgr_win_t* override_focus = nullptr; auto resolveTransientOverrides = [&](bool maybe) { if ( !focus || focus->type != steamcompmgr_win_type_t::XWAYLAND ) From 6edf7f1706c2f83eebe462ca18702c99ae233c7b Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Wed, 4 Sep 2024 21:12:07 -0400 Subject: [PATCH 12/18] steamcompmgr: reduce the number of lines taken up by the range based for loop over std::reference_wrapper[] --- src/steamcompmgr.cpp | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 8dcb26c22..1605d7729 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -4514,15 +4514,11 @@ static void destroy_win(xwayland_ctx_t *ctx, Window id, bool gone) { auto destroyBaseFocusWindows = [id, gone](auto& focus) { for (std::reference_wrapper focusWin - : (std::reference_wrapper[]) - { - focus.focusWindow, focus.inputFocusWindow, focus.overlayWindow, - focus.externalOverlayWindow, focus.notificationWindow, focus.overrideWindow - }) - { + : (std::reference_wrapper[]) + { focus.focusWindow, focus.inputFocusWindow, focus.overlayWindow, + focus.externalOverlayWindow, focus.notificationWindow, focus.overrideWindow }) if (x11_win(focusWin) == id && gone) focusWin.get() = nullptr; - } }; // Context @@ -5666,12 +5662,10 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) #pragma GCC unroll 8 for (std::reference_wrapper win - : (std::reference_wrapper[]) - { - global_focus.focusWindow, global_focus.inputFocusWindow, global_focus.overlayWindow, - global_focus.externalOverlayWindow, global_focus.notificationWindow, global_focus.overrideWindow, - global_focus.keyboardFocusWindow, global_focus.fadeWindow - }) + : (std::reference_wrapper[]) + { global_focus.focusWindow, global_focus.inputFocusWindow, global_focus.overlayWindow, + global_focus.externalOverlayWindow, global_focus.notificationWindow, global_focus.overrideWindow, + global_focus.keyboardFocusWindow, global_focus.fadeWindow }) { clearXwlWin(win, server->ctx.get()); } @@ -7012,22 +7006,14 @@ void steamcompmgr_check_xdg(bool vblank, uint64_t vblank_idx) { if (wlserver_xdg_dirty()) { - auto clearXdgWin = [](steamcompmgr_win_t*& w) { - if (w && w->type == steamcompmgr_win_type_t::XDG) - w = nullptr; - }; - #pragma GCC unroll 6 for (std::reference_wrapper focusWin - : (std::reference_wrapper[]) - { - global_focus.focusWindow, global_focus.inputFocusWindow, global_focus.overlayWindow, - global_focus.notificationWindow, global_focus.overrideWindow, - global_focus.fadeWindow - }) - { - clearXdgWin(focusWin); - } + : (std::reference_wrapper[]) + { global_focus.focusWindow, global_focus.inputFocusWindow, global_focus.overlayWindow, + global_focus.notificationWindow, global_focus.overrideWindow, + global_focus.fadeWindow }) + if (auto*& w = focusWin.get(); w && w->type == steamcompmgr_win_type_t::XDG) + w = nullptr; g_steamcompmgr_xdg_wins = wlserver_get_xdg_shell_windows(); MakeFocusDirty(); From 3346c405c9cd47a2a996625c5049604bcd6982f1 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:36:29 -0400 Subject: [PATCH 13/18] steamcompmgr, wayland, etc: attempt to fix regressions --- src/commit.cpp | 4 ++-- src/commit.h | 2 +- src/rc.h | 7 +++---- src/steamcompmgr.cpp | 7 +++---- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/commit.cpp b/src/commit.cpp index f7920c6b2..d72ba0c04 100644 --- a/src/commit.cpp +++ b/src/commit.cpp @@ -18,9 +18,9 @@ commit_t::commit_t() commitID = getCommitID();; } -commit_t::commit_t(std::in_place_t tag, ResListEntry_t& reslistentry, bool is_steam, uint64_t seq) +commit_t::commit_t(std::in_place_t tag, ResListEntry_t& reslistentry, struct wlr_buffer* buf, bool is_steam, uint64_t seq) : RcObject(tag), - buf{reslistentry.buf}, + buf{buf}, async{reslistentry.async}, fifo{reslistentry.fifo}, is_steam{is_steam}, diff --git a/src/commit.h b/src/commit.h index 7aa740052..d7d6e31af 100644 --- a/src/commit.h +++ b/src/commit.h @@ -19,7 +19,7 @@ struct commit_t final : public gamescope::RcObject, public gamescope::IWaitable, { protected: ENABLE_IN_PLACE_RC - commit_t(std::in_place_t tag, ResListEntry_t& reslistentry, bool is_steam, uint64_t seq); + commit_t(std::in_place_t tag, ResListEntry_t& reslistentry, struct wlr_buffer* buf, bool is_steam, uint64_t seq); uint64_t getCommitID(); public: diff --git a/src/rc.h b/src/rc.h index 6417c0e95..ecd6a5f20 100644 --- a/src/rc.h +++ b/src/rc.h @@ -16,7 +16,7 @@ namespace gamescope template friend gamescope::Rc make_rc(Args&&... args); protected: - constexpr RcObject(std::in_place_t) : m_uRefCount{1}, m_uRefPrivate{1} {} + explicit constexpr RcObject(std::in_place_t) : m_uRefCount{1}, m_uRefPrivate{1} {} public: RcObject() = default; virtual ~RcObject() @@ -78,7 +78,6 @@ namespace gamescope class IRcObject : public RcObject { - using RcObject::RcObject; public: virtual uint32_t IncRef() { @@ -123,12 +122,12 @@ namespace gamescope using RcRef = RcRef_; protected: - constexpr Rc( std::in_place_t tag, T* pObject ) + explicit constexpr Rc( std::in_place_t tag, T* pObject ) : m_pObject{ pObject } {} //no IncRef here, because this constructor is used w/ in-place RcObject construction via friend function make_rc() //this is locked behind protected access, to avoid any unintended use public: - constexpr Rc() { } + Rc() { } Rc( std::nullptr_t ) { } Rc( T* pObject ) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 1605d7729..ce922d824 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1169,11 +1169,10 @@ static steamcompmgr_win_t * find_win( xwayland_ctx_t *ctx, struct wlr_surface *s static gamescope::CBufferMemoizer s_BufferMemos; -static gamescope::Rc import_commit(steamcompmgr_win_t *w, ResListEntry_t& reslistentry) +static gamescope::Rc import_commit(steamcompmgr_win_t *w, struct wlr_buffer* buf, ResListEntry_t& reslistentry) { - gamescope::Rc commit = gamescope::make_rc(reslistentry, window_is_steam( w ), w->seq); + gamescope::Rc commit = gamescope::make_rc(reslistentry, buf, window_is_steam( w ), w->seq); - auto*& buf = reslistentry.buf; if ( gamescope::OwningRc pTexture = s_BufferMemos.LookupVulkanTexture( buf ) ) { // Going from OwningRc -> Rc now. @@ -6218,7 +6217,7 @@ void update_wayland_res(CommitDoneList_t *doneCommits, steamcompmgr_win_t *w, Re return; } - gamescope::Rc newCommit = import_commit(w, reslistentry); + gamescope::Rc newCommit = import_commit(w, buf, reslistentry); int fence = -1; if ( newCommit != nullptr ) From bc0e27651b2614efdca7c9c3fcc6c50dd6827d52 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:42:43 -0400 Subject: [PATCH 14/18] commit: mark in-place constructor as explicit --- src/commit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commit.h b/src/commit.h index d7d6e31af..de9bc1379 100644 --- a/src/commit.h +++ b/src/commit.h @@ -19,7 +19,7 @@ struct commit_t final : public gamescope::RcObject, public gamescope::IWaitable, { protected: ENABLE_IN_PLACE_RC - commit_t(std::in_place_t tag, ResListEntry_t& reslistentry, struct wlr_buffer* buf, bool is_steam, uint64_t seq); + explicit commit_t(std::in_place_t tag, ResListEntry_t& reslistentry, struct wlr_buffer* buf, bool is_steam, uint64_t seq); uint64_t getCommitID(); public: From 81f43036ddb259f93366a1aeae10df52f4e35c4d Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:12:17 -0400 Subject: [PATCH 15/18] fix weird wlserver_is_lock_held() assert --- src/wlserver.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wlserver.cpp b/src/wlserver.cpp index ccbd51248..e82262742 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -1699,6 +1699,7 @@ static std::unique_ptr g_InputServer; bool wlserver_init( void ) { assert( wlserver.display != nullptr ); + wlserver_lock(); wl_list_init(&pending_surfaces); wlserver.wlr.multi_backend = wlr_multi_backend_create( wlserver.event_loop ); @@ -1861,11 +1862,13 @@ bool wlserver_init( void ) { wl_display_flush_clients(wlserver.display); if (wl_event_loop_dispatch(wlserver.event_loop, -1) < 0) { wl_log.errorf("wl_event_loop_dispatch failed\n"); + wlserver_unlock(); return false; } } } - + + wlserver_unlock(); return true; } From 2e799b2e6e197d0648a481742877906dd0213ae5 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Fri, 6 Sep 2024 12:36:34 -0400 Subject: [PATCH 16/18] steamcompmgr: initialize glm::vec2 currentScaleRatio to [1.0f 1.0f]. fixes float divide by zero bug I accidentily introduced --- src/steamcompmgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index ce922d824..ef9a73fc5 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1874,7 +1874,7 @@ paint_window_commit( const gamescope::Rc &lastCommit, steamcompmgr_win bool offset = ( ( w->GetGeometry().nX || w->GetGeometry().nY ) && w != scaleW ); - glm::vec2 currentScaleRatio{}; + glm::vec2 currentScaleRatio{1.0f, 1.0f}; if (sourceWidth != currentOutputResolution.x || sourceHeight != currentOutputResolution.y || offset || globalScaleRatio != 1.0f) { currentScaleRatio = calc_scale_factor(sourceWidth, sourceHeight); From 761b73fa95b82d19e5a2e4384b4f3424db4efa93 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Fri, 6 Sep 2024 13:23:03 -0400 Subject: [PATCH 17/18] rc: make_rc(): ensure function can only be used for in-place construction, and not for making copies --- src/rc.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/rc.h b/src/rc.h index ecd6a5f20..af7a9b385 100644 --- a/src/rc.h +++ b/src/rc.h @@ -8,12 +8,16 @@ namespace gamescope { template class Rc; + + template + concept NotTheSameAs = !std::is_same>, std::remove_cvref_t>>::value; + #define ENABLE_IN_PLACE_RC using gamescope::RcObject::RcObject; \ - template \ + template ... Args> \ friend gamescope::Rc gamescope::make_rc(Args&&... args); class RcObject { - template + template ... Args> friend gamescope::Rc make_rc(Args&&... args); protected: explicit constexpr RcObject(std::in_place_t) : m_uRefCount{1}, m_uRefPrivate{1} {} @@ -104,7 +108,7 @@ namespace gamescope static void DecRef( T* pObject ) { pObject->DecRefPrivate(); } }; - template + template ... Args> Rc make_rc(Args&&... args) { T* pObj = new T(std::in_place_t{}, std::forward(args)...); return Rc{std::in_place_t{}, pObj}; @@ -116,7 +120,7 @@ namespace gamescope template friend class Rc; - template + template ... Args> friend Rc gamescope::make_rc(Args&&... args); using RcRef = RcRef_; From 60b39a354a8c32584a12710945651a4d725f97e1 Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:19:06 -0400 Subject: [PATCH 18/18] steamcompmgr, etc: {g_nNestedWidth, g_nNestedHeight} -> g_ivNestedResolution color_helpers: enable using structured bindings w/ glm::vec --- src/Backends/OpenVRBackend.cpp | 2 +- src/Backends/WaylandBackend.cpp | 2 +- src/color_helpers.h | 50 +++++++++++++++++++++++++++++++++ src/main.cpp | 18 ++++++------ src/main.hpp | 4 +-- src/steamcompmgr.cpp | 4 +-- src/wlserver.cpp | 10 +++---- 7 files changed, 69 insertions(+), 21 deletions(-) diff --git a/src/Backends/OpenVRBackend.cpp b/src/Backends/OpenVRBackend.cpp index c4de4aca8..54722778c 100644 --- a/src/Backends/OpenVRBackend.cpp +++ b/src/Backends/OpenVRBackend.cpp @@ -250,7 +250,7 @@ namespace gamescope bool UpdateEdid() { - m_FakeEdid = GenerateSimpleEdid( g_nNestedWidth, g_nNestedHeight ); + m_FakeEdid = GenerateSimpleEdid( g_ivNestedResolution.x, g_ivNestedResolution.y ); return true; } diff --git a/src/Backends/WaylandBackend.cpp b/src/Backends/WaylandBackend.cpp index 6498f3b49..49535e16e 100644 --- a/src/Backends/WaylandBackend.cpp +++ b/src/Backends/WaylandBackend.cpp @@ -811,7 +811,7 @@ namespace gamescope bool CWaylandConnector::UpdateEdid() { - m_FakeEdid = GenerateSimpleEdid( g_nNestedWidth, g_nNestedHeight ); + m_FakeEdid = GenerateSimpleEdid( g_ivNestedResolution.x, g_ivNestedResolution.y ); return true; } diff --git a/src/color_helpers.h b/src/color_helpers.h index 66213e159..40cf202ad 100644 --- a/src/color_helpers.h +++ b/src/color_helpers.h @@ -11,6 +11,56 @@ #include // glm::vec3 #include // glm::mat3 #include +///////////////////////////////////////////////////////// +// Stuff for using structured bindings with glm::vec: // +///////////////////////////////////////////////////////// +namespace std +{ +#define MK_TUPLE_SIZE(size, type) \ + template<> \ + struct tuple_size< ::glm::vec > : \ + std::integral_constant { } + +# define MK_TUPLE_ELEMENT(size) \ + template \ + struct tuple_element> : std::type_identity {} + + MK_TUPLE_SIZE(2, int); + MK_TUPLE_SIZE(2, float); + MK_TUPLE_SIZE(2, unsigned); + + MK_TUPLE_SIZE(3, int); + MK_TUPLE_SIZE(3, float); + MK_TUPLE_SIZE(3, unsigned); + + MK_TUPLE_SIZE(4, int); + MK_TUPLE_SIZE(4, float); + MK_TUPLE_SIZE(4, unsigned); + + MK_TUPLE_ELEMENT(2); + MK_TUPLE_ELEMENT(3); + MK_TUPLE_ELEMENT(4); +} + +namespace glm { +# define INSTANTIATE(qualifier) \ + template< std::size_t I > \ + auto qualifier \ + get( auto qualifier v ) noexcept { \ + if constexpr (I == 0) return v.x; \ + if constexpr (I == 1) return v.y; \ + if constexpr (I == 2) return v.z; \ + if constexpr (I == 3) return v.w; \ + } + + INSTANTIATE(&) + INSTANTIATE(const&) + INSTANTIATE(&&) + INSTANTIATE(const&&) +} +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// + // Color utils inline int quantize( float fVal, float fMaxVal ) diff --git a/src/main.cpp b/src/main.cpp index ca4001249..05d8db9e8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -269,8 +269,7 @@ const char usage[] = std::atomic< bool > g_bRun{true}; -int g_nNestedWidth = 0; -int g_nNestedHeight = 0; +glm::ivec2 g_ivNestedResolution {}; int g_nNestedRefresh = 0; int g_nNestedUnfocusedRefresh = 0; int g_nNestedDisplayIndex = 0; @@ -678,10 +677,10 @@ int main(int argc, char **argv) const char *opt_name; switch (o) { case 'w': - g_nNestedWidth = atoi( optarg ); + g_ivNestedResolution.x = atoi( optarg ); break; case 'h': - g_nNestedHeight = atoi( optarg ); + g_ivNestedResolution.y = atoi( optarg ); break; case 'r': g_nNestedRefresh = gamescope::ConvertHztomHz( atoi( optarg ) ); @@ -918,18 +917,17 @@ int main(int argc, char **argv) } } - if ( g_nNestedHeight == 0 ) + if ( g_ivNestedResolution.y == 0 ) { - if ( g_nNestedWidth != 0 ) + if ( g_ivNestedResolution.x != 0 ) { fprintf( stderr, "Cannot specify -w without -h\n" ); return 1; } - g_nNestedWidth = g_nOutputWidth; - g_nNestedHeight = g_nOutputHeight; + g_ivNestedResolution = glm::ivec2 { g_nOutputWidth, g_nOutputHeight }; } - if ( g_nNestedWidth == 0 ) - g_nNestedWidth = g_nNestedHeight * 16 / 9; + if ( g_ivNestedResolution.x == 0 ) + g_ivNestedResolution.x = g_ivNestedResolution.y * 16 / 9; if ( !wlserver_init() ) { diff --git a/src/main.hpp b/src/main.hpp index 2e6fb833a..e2d62baad 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -8,9 +8,9 @@ extern const char *gamescope_optstring; extern const struct option *gamescope_options; extern std::atomic< bool > g_bRun; +#include -extern int g_nNestedWidth; -extern int g_nNestedHeight; +extern glm::ivec2 g_ivNestedResolution; extern int g_nNestedRefresh; // mHz extern int g_nNestedUnfocusedRefresh; // mHz extern int g_nNestedDisplayIndex; diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index ef9a73fc5..9984ba25d 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1272,7 +1272,7 @@ window_is_fullscreen( steamcompmgr_win_t *w ) glm::vec2 calc_scale_factor_scaler(float sourceWidth, float sourceHeight) { auto sourceDimensions = glm::vec2 {sourceWidth, sourceHeight}; - auto nestedResolution = glm::vec2 { (float) g_nNestedWidth, (float) g_nNestedHeight }; + auto nestedResolution = glm::vec2 { g_ivNestedResolution }; auto outputRatio = (glm::vec2)currentOutputResolution / nestedResolution; glm::vec2 ratios = nestedResolution / sourceDimensions; @@ -7411,7 +7411,7 @@ steamcompmgr_main(int argc, char **argv) { if ( steamMode && g_nXWaylandCount > 1 ) { - g_nNestedHeight = ( g_nNestedWidth * g_nOutputHeight ) / g_nOutputWidth; + g_ivNestedResolution.y = ( g_ivNestedResolution.x * g_nOutputHeight ) / g_nOutputWidth; wlserver_lock(); // Update only Steam, the root ctx, with the new output size for now wlserver_set_xwayland_server_mode( 0, g_nOutputWidth, g_nOutputHeight, g_nOutputRefresh ); diff --git a/src/wlserver.cpp b/src/wlserver.cpp index e82262742..dfb7d9ab7 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -222,7 +222,7 @@ void xwayland_surface_commit(struct wlr_surface *wlr_surface) { wlr_xdg_surface_schedule_configure( wlserver_xdg_surface_info->xdg_surface ); if ( wlserver_xdg_surface_info->layer_surface ) - wlr_layer_surface_v1_configure( wlserver_xdg_surface_info->layer_surface, g_nNestedWidth, g_nNestedHeight ); + wlr_layer_surface_v1_configure( wlserver_xdg_surface_info->layer_surface, g_ivNestedResolution.x, g_ivNestedResolution.y ); wlserver_xdg_surface_info->bDoneConfigure = true; } @@ -1511,7 +1511,7 @@ gamescope_xwayland_server_t::gamescope_xwayland_server_t(wl_display *display) } wlr_output_state_set_enabled(output_state, true); - wlr_output_state_set_custom_mode(output_state, g_nNestedWidth, g_nNestedHeight, refresh); + wlr_output_state_set_custom_mode(output_state, g_ivNestedResolution.x, g_ivNestedResolution.y, refresh); if (!wlr_output_commit_state(output, output_state)) { wl_log.errorf("Failed to commit headless output"); @@ -2080,16 +2080,16 @@ struct wlr_surface *wlserver_surface_to_override_surface( struct wlr_surface *pS return pSurface; } -std::pair wlserver_get_surface_extent( struct wlr_surface *pSurface ) +glm::ivec2 wlserver_get_surface_extent( struct wlr_surface *pSurface ) { assert( wlserver_is_lock_held() ); pSurface = wlserver_surface_to_override_surface( pSurface ); if ( !pSurface ) - return std::make_pair( g_nNestedWidth, g_nNestedHeight ); + return g_ivNestedResolution; - return std::make_pair( pSurface->current.width, pSurface->current.height ); + return glm::ivec2( pSurface->current.width, pSurface->current.height ); } bool ShouldDrawCursor();