From 646446c157d55d8508c734cddfc3025834f7cf50 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Fri, 17 May 2024 19:43:49 -0500 Subject: [PATCH 01/21] Add touch-gestures to open up Steam menus --- src/main.cpp | 5 +++++ src/wlserver.cpp | 28 ++++++++++++++++++++++++++++ src/wlserver.hpp | 1 + 3 files changed, 34 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index ca40012..3a1b1ae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -108,6 +108,8 @@ const struct option *gamescope_options = (struct option[]){ // wlserver options { "xwayland-count", required_argument, nullptr, 0 }, + { "touch-gestures", no_argument, nullptr, 0 }, + // steamcompmgr options { "cursor", required_argument, nullptr, 0 }, @@ -185,6 +187,7 @@ const char usage[] = " -T, --stats-path write statistics to path\n" " -C, --hide-cursor-delay hide cursor image after delay\n" " -e, --steam enable Steam integration\n" + " --touch-gestures enable touch gestures for Steam menus\n" " --xwayland-count create N xwayland servers\n" " --prefer-vk-device prefer Vulkan device for compositing (ex: 1002:7300)\n" " --force-orientation rotate the internal display (left, right, normal, upsidedown)\n" @@ -734,6 +737,8 @@ int main(int argc, char **argv) g_bDebugLayers = true; } else if (strcmp(opt_name, "disable-color-management") == 0) { g_bForceDisableColorMgmt = true; + } else if (strcmp(opt_name, "touch-gestures") == 0) { + cv_touch_gestures = true; } else if (strcmp(opt_name, "xwayland-count") == 0) { g_nXWaylandCount = atoi( optarg ); } else if (strcmp(opt_name, "composite-debug") == 0) { diff --git a/src/wlserver.cpp b/src/wlserver.cpp index ccbd512..26b953a 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -81,6 +81,7 @@ using namespace std::literals; extern gamescope::ConVar<bool> cv_drm_debug_disable_explicit_sync; //#define GAMESCOPE_SWAPCHAIN_DEBUG +gamescope::ConVar<bool> cv_touch_gestures( "enable_touch_gestures", false, "Enable/Disable the usage of touch gestures" ); struct wlserver_t wlserver = { .touch_down_ids = {} @@ -2526,6 +2527,33 @@ void wlserver_touchmotion( double x, double y, int touch_id, uint32_t time, bool if ( bAlwaysWarpCursor ) wlserver_mousewarp( tx, ty, time, false ); + + if (cv_touch_gestures) { + bool start_gesture = false; + + // Round the x-coordinate to the nearest whole number + uint32_t roundedCursorX = static_cast<int>(std::round(tx)); + // Grab 2% of the display to be used for the edge range + uint32_t edge_range = static_cast<uint32_t>(g_nOutputWidth * 0.02); + + // Determine if the gesture should start + if (roundedCursorX <= edge_range || roundedCursorX >= g_nOutputWidth - edge_range) { + start_gesture = true; + } + + // Handle Home gesture + if (start_gesture && roundedCursorX >= edge_range) { + wlserver_open_steam_menu(0); + start_gesture = false; + } + + // Handle QAM gesture + if (start_gesture && roundedCursorX >= g_nOutputWidth - edge_range && roundedCursorX <= g_nOutputWidth) { + wlserver_open_steam_menu(1); + start_gesture = false; + } + } + } else if ( eMode == gamescope::TouchClickModes::Disabled ) { diff --git a/src/wlserver.hpp b/src/wlserver.hpp index 0569472..3304c18 100644 --- a/src/wlserver.hpp +++ b/src/wlserver.hpp @@ -272,6 +272,7 @@ void wlserver_x11_surface_info_finish( struct wlserver_x11_surface_info *surf ); void wlserver_set_xwayland_server_mode( size_t idx, int w, int h, int refresh ); extern std::atomic<bool> g_bPendingTouchMovement; +extern gamescope::ConVar<bool> cv_touch_gestures; void wlserver_open_steam_menu( bool qam ); -- 2.46.0 From 97c2ed0ea6a5cd43b450e0952db20c08d82bbe60 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Fri, 17 May 2024 20:16:20 -0500 Subject: [PATCH 02/21] Add bypass_steam_resolution to workaround the 720p/800p restrictions Steam has for games --- src/main.cpp | 3 +++ src/steamcompmgr.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 3a1b1ae..534779d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,6 +129,8 @@ const struct option *gamescope_options = (struct option[]){ { "fade-out-duration", required_argument, nullptr, 0 }, { "force-orientation", required_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, + { "bypass-steam-resolution", no_argument, nullptr, 0 }, + { "disable-color-management", no_argument, nullptr, 0 }, { "sdr-gamut-wideness", required_argument, nullptr, 0 }, @@ -187,6 +189,7 @@ const char usage[] = " -T, --stats-path write statistics to path\n" " -C, --hide-cursor-delay hide cursor image after delay\n" " -e, --steam enable Steam integration\n" + " --bypass-steam-resolution bypass Steam's default 720p/800p default resolution\n" " --touch-gestures enable touch gestures for Steam menus\n" " --xwayland-count create N xwayland servers\n" " --prefer-vk-device prefer Vulkan device for compositing (ex: 1002:7300)\n" diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index e997c85..952a5f8 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -356,6 +356,8 @@ bool g_bForceHDR10OutputDebug = false; gamescope::ConVar<bool> cv_hdr_enabled{ "hdr_enabled", false, "Whether or not HDR is enabled if it is available." }; bool g_bHDRItmEnable = false; int g_nCurrentRefreshRate_CachedValue = 0; +gamescope::ConVar<bool> cv_bypass_steam_resolution{ "bypass_steam_resolution", false, "Workaround the 720p/800p limits Steam uses for games" }; + static void update_color_mgmt() @@ -5387,6 +5389,13 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) size_t server_idx = size_t{ xwayland_mode_ctl[ 0 ] }; int width = xwayland_mode_ctl[ 1 ]; int height = xwayland_mode_ctl[ 2 ]; + + if ( g_nOutputWidth != 1280 && width == 1280 && cv_bypass_steam_resolution ) + { + width = g_nOutputWidth; + height = g_nOutputHeight; + } + bool allowSuperRes = !!xwayland_mode_ctl[ 3 ]; if ( !allowSuperRes ) @@ -7370,6 +7379,8 @@ steamcompmgr_main(int argc, char **argv) bForceWindowsFullscreen = true; } else if (strcmp(opt_name, "hdr-enabled") == 0) { cv_hdr_enabled = true; + } else if (strcmp(opt_name, "bypass_steam_resolution") == 0) { + cv_bypass_steam_resolution = true; } else if (strcmp(opt_name, "hdr-debug-force-support") == 0) { g_bForceHDRSupportDebug = true; } else if (strcmp(opt_name, "hdr-debug-force-output") == 0) { -- 2.46.0 From 234e3bb0369b7ed45a8e2f3c41f3c1e900be9d34 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Wed, 26 Jul 2023 20:46:29 -0500 Subject: [PATCH 03/21] Add force external orientation. Co-authored-by: Bouke Sybren Haarsma <boukehaarsma23@gmail.com> --- src/Backends/DRMBackend.cpp | 5 +++++ src/main.cpp | 25 ++++++++++++++++++++++++- src/main.hpp | 1 + src/wlserver.cpp | 23 +++++++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 799fd39..3815b98 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -537,6 +537,7 @@ bool g_bSupportsSyncObjs = false; extern gamescope::GamescopeModeGeneration g_eGamescopeModeGeneration; extern GamescopePanelOrientation g_DesiredInternalOrientation; +extern GamescopePanelOrientation g_DesiredExternalOrientation; extern bool g_bForceDisableColorMgmt; @@ -2031,6 +2032,10 @@ namespace gamescope { m_ChosenOrientation = g_DesiredInternalOrientation; } + else if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO ) + { + m_ChosenOrientation = g_DesiredExternalOrientation; + } else { if ( this->GetProperties().panel_orientation ) diff --git a/src/main.cpp b/src/main.cpp index 534779d..f9be05e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,6 +128,7 @@ const struct option *gamescope_options = (struct option[]){ { "disable-xres", no_argument, nullptr, 'x' }, { "fade-out-duration", required_argument, nullptr, 0 }, { "force-orientation", required_argument, nullptr, 0 }, + { "force-external-orientation", required_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, { "bypass-steam-resolution", no_argument, nullptr, 0 }, @@ -194,6 +195,7 @@ const char usage[] = " --xwayland-count create N xwayland servers\n" " --prefer-vk-device prefer Vulkan device for compositing (ex: 1002:7300)\n" " --force-orientation rotate the internal display (left, right, normal, upsidedown)\n" + " --force-external-orientation rotate the external display (left, right, normal, upsidedown)\n" " --force-windows-fullscreen force windows inside of gamescope to be the size of the nested display (fullscreen)\n" " --cursor-scale-height if specified, sets a base output height to linearly scale the cursor against.\n" " --hdr-enabled enable HDR output (needs Gamescope WSI layer enabled for support from clients)\n" @@ -289,6 +291,8 @@ bool g_bOutputHDREnabled = false; bool g_bFullscreen = false; bool g_bForceRelativeMouse = false; +bool g_bExternalForced = false; + bool g_bGrabbed = false; float g_mouseSensitivity = 1.0; @@ -362,7 +366,24 @@ static GamescopePanelOrientation force_orientation(const char *str) } else if (strcmp(str, "upsidedown") == 0) { return GAMESCOPE_PANEL_ORIENTATION_180; } else { - fprintf( stderr, "gamescope: invalid value for --force-orientation\n" ); + fprintf( stderr, "gamescope: invalid value for given for --force-orientation\n" ); + exit(1); + } +} + +GamescopePanelOrientation g_DesiredExternalOrientation = GAMESCOPE_PANEL_ORIENTATION_AUTO; +static GamescopePanelOrientation force_external_orientation(const char *str) +{ + if (strcmp(str, "normal") == 0) { + return GAMESCOPE_PANEL_ORIENTATION_0; + } else if (strcmp(str, "right") == 0) { + return GAMESCOPE_PANEL_ORIENTATION_270; + } else if (strcmp(str, "left") == 0) { + return GAMESCOPE_PANEL_ORIENTATION_90; + } else if (strcmp(str, "upsidedown") == 0) { + return GAMESCOPE_PANEL_ORIENTATION_180; + } else { + fprintf( stderr, "gamescope: invalid value for --force-external-orientation\n" ); exit(1); } } @@ -755,6 +776,8 @@ int main(int argc, char **argv) g_eGamescopeModeGeneration = parse_gamescope_mode_generation( optarg ); } else if (strcmp(opt_name, "force-orientation") == 0) { g_DesiredInternalOrientation = force_orientation( optarg ); + } else if (strcmp(opt_name, "force-external-orientation") == 0) { + g_DesiredExternalOrientation = force_external_orientation( optarg ); } else if (strcmp(opt_name, "sharpness") == 0 || strcmp(opt_name, "fsr-sharpness") == 0) { g_upscaleFilterSharpness = atoi( optarg ); diff --git a/src/main.hpp b/src/main.hpp index 2e6fb83..ebd018a 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -28,6 +28,7 @@ extern bool g_bGrabbed; extern float g_mouseSensitivity; extern const char *g_sOutputName; +extern bool g_bExternalForced; enum class GamescopeUpscaleFilter : uint32_t { diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 26b953a..837079a 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -2488,6 +2488,29 @@ static void apply_touchscreen_orientation(double *x, double *y ) break; } + // Rotate screen if it's forced with --force-external-orientation + switch ( GetBackend()->GetConnector( gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL )->GetCurrentOrientation() ) + { + default: + case GAMESCOPE_PANEL_ORIENTATION_AUTO: + case GAMESCOPE_PANEL_ORIENTATION_0: + tx = *x; + ty = *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_90: + tx = 1.0 - *y; + ty = *x; + break; + case GAMESCOPE_PANEL_ORIENTATION_180: + tx = 1.0 - *x; + ty = 1.0 - *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_270: + tx = *y; + ty = 1.0 - *x; + break; + } + *x = tx; *y = ty; } -- 2.46.0 From bc0ddd46fd9db62fbc3fe14e0b1493e35ceb2be8 Mon Sep 17 00:00:00 2001 From: Bouke Sybren Haarsma <boukehaarsma23@gmail.com> Date: Tue, 12 Mar 2024 00:07:57 +0100 Subject: [PATCH 04/21] implement force-panel-type --- src/backend.h | 3 +++ src/gamescope_shared.h | 1 + src/main.cpp | 16 ++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/backend.h b/src/backend.h index 7d9fb46..08e8268 100644 --- a/src/backend.h +++ b/src/backend.h @@ -18,6 +18,7 @@ struct wlr_buffer; struct wlr_dmabuf_attributes; struct FrameInfo_t; +extern gamescope::GamescopeScreenType g_ForcedScreenType; namespace gamescope { @@ -221,6 +222,8 @@ namespace gamescope // Dumb helper we should remove to support multi display someday. gamescope::GamescopeScreenType GetScreenType() { + if (g_ForcedScreenType != GAMESCOPE_SCREEN_TYPE_AUTO) + return g_ForcedScreenType; if ( GetCurrentConnector() ) return GetCurrentConnector()->GetScreenType(); diff --git a/src/gamescope_shared.h b/src/gamescope_shared.h index 5ce8591..d1b7a6e 100644 --- a/src/gamescope_shared.h +++ b/src/gamescope_shared.h @@ -25,6 +25,7 @@ namespace gamescope { GAMESCOPE_SCREEN_TYPE_INTERNAL, GAMESCOPE_SCREEN_TYPE_EXTERNAL, + GAMESCOPE_SCREEN_TYPE_AUTO, GAMESCOPE_SCREEN_TYPE_COUNT }; diff --git a/src/main.cpp b/src/main.cpp index f9be05e..dc3e9c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,6 +129,7 @@ const struct option *gamescope_options = (struct option[]){ { "fade-out-duration", required_argument, nullptr, 0 }, { "force-orientation", required_argument, nullptr, 0 }, { "force-external-orientation", required_argument, nullptr, 0 }, + { "force-panel-type", required_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, { "bypass-steam-resolution", no_argument, nullptr, 0 }, @@ -196,6 +197,7 @@ const char usage[] = " --prefer-vk-device prefer Vulkan device for compositing (ex: 1002:7300)\n" " --force-orientation rotate the internal display (left, right, normal, upsidedown)\n" " --force-external-orientation rotate the external display (left, right, normal, upsidedown)\n" + " --force-panel-type force gamescope to treat the display as either internal or external\n" " --force-windows-fullscreen force windows inside of gamescope to be the size of the nested display (fullscreen)\n" " --cursor-scale-height if specified, sets a base output height to linearly scale the cursor against.\n" " --hdr-enabled enable HDR output (needs Gamescope WSI layer enabled for support from clients)\n" @@ -387,6 +389,18 @@ static GamescopePanelOrientation force_external_orientation(const char *str) exit(1); } } +gamescope::GamescopeScreenType g_ForcedScreenType = gamescope::GAMESCOPE_SCREEN_TYPE_AUTO; +static gamescope::GamescopeScreenType force_panel_type(const char *str) +{ + if (strcmp(str, "internal") == 0) { + return gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL; + } else if (strcmp(str, "external") == 0) { + return gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL; + } else { + fprintf( stderr, "gamescope: invalid value for --force-panel-type\n" ); + exit(1); + } +} static enum GamescopeUpscaleScaler parse_upscaler_scaler(const char *str) { @@ -778,6 +792,8 @@ int main(int argc, char **argv) g_DesiredInternalOrientation = force_orientation( optarg ); } else if (strcmp(opt_name, "force-external-orientation") == 0) { g_DesiredExternalOrientation = force_external_orientation( optarg ); + } else if (strcmp(opt_name, "force-panel-type") == 0) { + g_ForcedScreenType = force_panel_type( optarg ); } else if (strcmp(opt_name, "sharpness") == 0 || strcmp(opt_name, "fsr-sharpness") == 0) { g_upscaleFilterSharpness = atoi( optarg ); -- 2.46.0 From 2a0c92febded984bc0d610eaedc9e8cc4d4ce51a Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Fri, 17 May 2024 21:11:34 -0500 Subject: [PATCH 05/21] wlserver: Fix an issue that would cause gamescope to crash when the touchscreen was used --- src/wlserver.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 837079a..26b953a 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -2488,29 +2488,6 @@ static void apply_touchscreen_orientation(double *x, double *y ) break; } - // Rotate screen if it's forced with --force-external-orientation - switch ( GetBackend()->GetConnector( gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL )->GetCurrentOrientation() ) - { - default: - case GAMESCOPE_PANEL_ORIENTATION_AUTO: - case GAMESCOPE_PANEL_ORIENTATION_0: - tx = *x; - ty = *y; - break; - case GAMESCOPE_PANEL_ORIENTATION_90: - tx = 1.0 - *y; - ty = *x; - break; - case GAMESCOPE_PANEL_ORIENTATION_180: - tx = 1.0 - *x; - ty = 1.0 - *y; - break; - case GAMESCOPE_PANEL_ORIENTATION_270: - tx = *y; - ty = 1.0 - *x; - break; - } - *x = tx; *y = ty; } -- 2.46.0 From 69bae3bffa954251d6a857b1b6928fc4755e40bf Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Fri, 17 May 2024 21:56:55 -0500 Subject: [PATCH 06/21] Add --custom-refresh-rates --- src/Backends/DRMBackend.cpp | 4 ++++ src/main.cpp | 30 ++++++++++++++++++++++++++++++ src/main.hpp | 2 ++ 3 files changed, 36 insertions(+) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 3815b98..e3512a1 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2135,6 +2135,10 @@ namespace gamescope ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "Jupiter"sv ) || ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "Galileo"sv ); + if ( g_customRefreshRates.size() > 0 ) { + m_Mutable.ValidDynamicRefreshRates = std::span(g_customRefreshRates); + return; + } if ( bSteamDeckDisplay ) { static constexpr uint32_t kPIDGalileoSDC = 0x3003; diff --git a/src/main.cpp b/src/main.cpp index dc3e9c8..18eb399 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -132,6 +132,7 @@ const struct option *gamescope_options = (struct option[]){ { "force-panel-type", required_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, { "bypass-steam-resolution", no_argument, nullptr, 0 }, + { "custom-refresh-rates", required_argument, nullptr, 0 }, { "disable-color-management", no_argument, nullptr, 0 }, @@ -210,6 +211,7 @@ const char usage[] = " --hdr-itm-target-nits set the target luminace of the inverse tone mapping process.\n" " Default: 1000 nits, Max: 10000 nits\n" " --framerate-limit Set a simple framerate limit. Used as a divisor of the refresh rate, rounds down eg 60 / 59 -> 60fps, 60 / 25 -> 30fps. Default: 0, disabled.\n" + " --custom-refresh-rates Set custom refresh rates for the output. eg: 60,90,110-120\n" " --mangoapp Launch with the mangoapp (mangohud) performance overlay enabled. You should use this instead of using mangohud on the game or gamescope.\n" "\n" "Nested mode options:\n" @@ -462,6 +464,32 @@ static enum gamescope::GamescopeBackend parse_backend_name(const char *str) fprintf( stderr, "gamescope: invalid value for --backend\n" ); exit(1); } + +std::vector<uint32_t> g_customRefreshRates; +// eg: 60,60,90,110-120 +static std::vector<uint32_t> parse_custom_refresh_rates( const char *str ) +{ + std::vector<uint32_t> rates; + char *token = strtok( strdup(str), ","); + while (token) + { + char *dash = strchr(token, '-'); + if (dash) + { + uint32_t start = atoi(token); + uint32_t end = atoi(dash + 1); + for (uint32_t i = start; i <= end; i++) + { + rates.push_back(i); + } + } + else + { + rates.push_back(atoi(token)); + } + token = strtok(nullptr, ","); + } + return rates; } struct sigaction handle_signal_action = {}; @@ -794,6 +822,8 @@ int main(int argc, char **argv) g_DesiredExternalOrientation = force_external_orientation( optarg ); } else if (strcmp(opt_name, "force-panel-type") == 0) { g_ForcedScreenType = force_panel_type( optarg ); + } else if (strcmp(opt_name, "custom-refresh-rates") == 0) { + g_customRefreshRates = parse_custom_refresh_rates( optarg ); } else if (strcmp(opt_name, "sharpness") == 0 || strcmp(opt_name, "fsr-sharpness") == 0) { g_upscaleFilterSharpness = atoi( optarg ); diff --git a/src/main.hpp b/src/main.hpp index ebd018a..4e09e3b 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -3,6 +3,7 @@ #include <getopt.h> #include <atomic> +#include <vector> extern const char *gamescope_optstring; extern const struct option *gamescope_options; @@ -29,6 +30,7 @@ extern bool g_bGrabbed; extern float g_mouseSensitivity; extern const char *g_sOutputName; extern bool g_bExternalForced; +extern std::vector<uint32_t> g_customRefreshRates; enum class GamescopeUpscaleFilter : uint32_t { -- 2.46.0 From 5125582bc6fdfc651ca5ccb58cb71d956e2c3676 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Sat, 18 May 2024 08:44:38 -0500 Subject: [PATCH 07/21] Add rotation gamescope_control command --- protocol/gamescope-control.xml | 18 ++++++++++++ src/Backends/DRMBackend.cpp | 24 ++++++++++++++-- src/gamescope_shared.h | 18 ++++++++++++ src/main.cpp | 1 + src/wlserver.cpp | 50 ++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 2 deletions(-) diff --git a/protocol/gamescope-control.xml b/protocol/gamescope-control.xml index 012c48c..eab8a84 100644 --- a/protocol/gamescope-control.xml +++ b/protocol/gamescope-control.xml @@ -99,5 +99,23 @@ <arg name="path" type="string" summary="Path to written screenshot"></arg> </event> + + <enum name="display_rotation_flag" bitfield="true" since="2"> + <entry name="normal" value="1"/> + <entry name="left" value="2"/> + <entry name="right" value="3"/> + <entry name="upsidedown" value="4"/> + </enum> + + <enum name="display_target_type" since="2"> + <entry name="internal" value="1"/> + <entry name="external" value="2"/> + </enum> + + <request name="rotate_display" since="2"> + <arg name="orientation" type="uint" enum="display_rotation_flag" summary="Set the orientation of the display output."/> + <arg name="target_type" type="uint" enum="display_target_type" summary="Internal (1) or External (2) target type."/> + </request> + </interface> </protocol> diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index e3512a1..f05c2e8 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2028,7 +2028,9 @@ namespace gamescope void CDRMConnector::UpdateEffectiveOrientation( const drmModeModeInfo *pMode ) { - if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO ) + if ( this->GetScreenType() == ( GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO ) + || ( GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO + && g_bExternalForced ) ) { m_ChosenOrientation = g_DesiredInternalOrientation; } @@ -2960,8 +2962,26 @@ bool drm_update_color_mgmt(struct drm_t *drm) return true; } -int g_nDynamicRefreshHz = 0; +void drm_set_orientation( struct drm_t *drm, bool isRotated) +{ + int width = g_nOutputWidth; + int height = g_nOutputHeight; + g_bRotated = isRotated; + if ( g_bRotated ) { + int tmp = width; + width = height; + height = tmp; + } + if (!drm->pConnector || !drm->pConnector->GetModeConnector()) + return; + + drmModeConnector *connector = drm->pConnector->GetModeConnector(); + const drmModeModeInfo *mode = find_mode(connector, width, height, 0); + update_drm_effective_orientations(drm, mode); +} + +int g_nDynamicRefreshHz = 0; static void drm_unset_mode( struct drm_t *drm ) { drm->pending.mode_id = 0; diff --git a/src/gamescope_shared.h b/src/gamescope_shared.h index d1b7a6e..cffa576 100644 --- a/src/gamescope_shared.h +++ b/src/gamescope_shared.h @@ -65,6 +65,24 @@ enum GamescopePanelOrientation GAMESCOPE_PANEL_ORIENTATION_AUTO, }; +struct GamescopeTimelinePoint +{ + struct wlr_drm_syncobj_timeline *pTimeline = nullptr; + uint64_t ulPoint = 0; + + void Release(); +}; + +enum GamescopePanelExternalOrientation +{ + GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_0, // normal + GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_270, // right + GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_90, // left + GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_180, // upside down + + GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_AUTO, +}; + // Disable partial composition for now until we get // composite priorities working in libliftoff + also // use the proper libliftoff composite plane system. diff --git a/src/main.cpp b/src/main.cpp index 18eb399..675020f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -397,6 +397,7 @@ static gamescope::GamescopeScreenType force_panel_type(const char *str) if (strcmp(str, "internal") == 0) { return gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL; } else if (strcmp(str, "external") == 0) { + g_bExternalForced = true; return gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL; } else { fprintf( stderr, "gamescope: invalid value for --force-panel-type\n" ); diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 26b953a..c37dbc1 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -1042,6 +1042,55 @@ static void gamescope_control_take_screenshot( struct wl_client *client, struct } ); } +static void gamescope_control_rotate_display( struct wl_client *client, struct wl_resource *resource, uint32_t orientation, uint32_t target_type ) +{ + bool isRotated = false; + if (target_type == GAMESCOPE_CONTROL_DISPLAY_TARGET_TYPE_INTERNAL ) + { + switch (orientation) { + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_NORMAL: + //m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_0; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_LEFT: + //m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_90; + isRotated = true; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_RIGHT: + //m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_270; + isRotated = true; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_UPSIDEDOWN: + //m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_180; + break; + default: + wl_log.errorf("Invalid target orientation selected"); + } + } + else if (target_type == GAMESCOPE_CONTROL_DISPLAY_TARGET_TYPE_EXTERNAL ) + { + switch (orientation) { + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_NORMAL: + //m_ChosenOrientation = GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_0; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_LEFT: + //m_ChosenOrientation = GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_90; + isRotated = true; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_RIGHT: + //m_ChosenOrientation = GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_270; + isRotated = true; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_UPSIDEDOWN: + //m_ChosenOrientation = GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_180; + break; + default: + wl_log.errorf("Invalid target orientation selected"); + } + } + //drm_set_orientation(&g_DRM, isRotated); + //g_DRM.out_of_date = 2; +} + static void gamescope_control_handle_destroy( struct wl_client *client, struct wl_resource *resource ) { wl_resource_destroy( resource ); @@ -1051,6 +1100,7 @@ static const struct gamescope_control_interface gamescope_control_impl = { .destroy = gamescope_control_handle_destroy, .set_app_target_refresh_cycle = gamescope_control_set_app_target_refresh_cycle, .take_screenshot = gamescope_control_take_screenshot, + .rotate_display = gamescope_control_rotate_display, }; static uint32_t get_conn_display_info_flags() -- 2.46.0 From 304c747d5eab4b62fe38225d04529ff53142e832 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Sat, 18 May 2024 11:54:50 -0500 Subject: [PATCH 08/21] Fix an issue that caused force-panel to not work --- protocol/gamescope-control.xml | 1 - src/Backends/DRMBackend.cpp | 3 + src/gamescope_shared.h | 10 --- src/wlserver.cpp | 145 ++++++++++++++++++++------------- 4 files changed, 90 insertions(+), 69 deletions(-) diff --git a/protocol/gamescope-control.xml b/protocol/gamescope-control.xml index eab8a84..7f5578b 100644 --- a/protocol/gamescope-control.xml +++ b/protocol/gamescope-control.xml @@ -99,7 +99,6 @@ <arg name="path" type="string" summary="Path to written screenshot"></arg> </event> - <enum name="display_rotation_flag" bitfield="true" since="2"> <entry name="normal" value="1"/> <entry name="left" value="2"/> diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index f05c2e8..663b1e2 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -318,6 +318,9 @@ namespace gamescope GamescopeScreenType GetScreenType() const override { + if ( g_ForcedScreenType != GAMESCOPE_SCREEN_TYPE_AUTO ) + return g_ForcedScreenType; + if ( m_pConnector->connector_type == DRM_MODE_CONNECTOR_eDP || m_pConnector->connector_type == DRM_MODE_CONNECTOR_LVDS || m_pConnector->connector_type == DRM_MODE_CONNECTOR_DSI ) diff --git a/src/gamescope_shared.h b/src/gamescope_shared.h index cffa576..a11f598 100644 --- a/src/gamescope_shared.h +++ b/src/gamescope_shared.h @@ -73,16 +73,6 @@ struct GamescopeTimelinePoint void Release(); }; -enum GamescopePanelExternalOrientation -{ - GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_0, // normal - GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_270, // right - GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_90, // left - GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_180, // upside down - - GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_AUTO, -}; - // Disable partial composition for now until we get // composite priorities working in libliftoff + also // use the proper libliftoff composite plane system. diff --git a/src/wlserver.cpp b/src/wlserver.cpp index c37dbc1..ff534ad 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -82,6 +82,8 @@ extern gamescope::ConVar<bool> cv_drm_debug_disable_explicit_sync; //#define GAMESCOPE_SWAPCHAIN_DEBUG gamescope::ConVar<bool> cv_touch_gestures( "enable_touch_gestures", false, "Enable/Disable the usage of touch gestures" ); +extern GamescopePanelOrientation g_DesiredInternalOrientation; +extern GamescopePanelOrientation g_DesiredExternalOrientation; struct wlserver_t wlserver = { .touch_down_ids = {} @@ -1048,43 +1050,43 @@ static void gamescope_control_rotate_display( struct wl_client *client, struct w if (target_type == GAMESCOPE_CONTROL_DISPLAY_TARGET_TYPE_INTERNAL ) { switch (orientation) { - case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_NORMAL: - //m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_0; - break; - case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_LEFT: - //m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_90; - isRotated = true; - break; - case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_RIGHT: - //m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_270; - isRotated = true; - break; - case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_UPSIDEDOWN: - //m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_180; - break; - default: - wl_log.errorf("Invalid target orientation selected"); + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_NORMAL: + g_DesiredInternalOrientation = GAMESCOPE_PANEL_ORIENTATION_0; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_LEFT: + g_DesiredInternalOrientation = GAMESCOPE_PANEL_ORIENTATION_90; + isRotated = true; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_RIGHT: + g_DesiredInternalOrientation = GAMESCOPE_PANEL_ORIENTATION_270; + isRotated = true; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_UPSIDEDOWN: + g_DesiredInternalOrientation = GAMESCOPE_PANEL_ORIENTATION_180; + break; + default: + wl_log.errorf("Invalid target orientation selected"); } } else if (target_type == GAMESCOPE_CONTROL_DISPLAY_TARGET_TYPE_EXTERNAL ) { switch (orientation) { - case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_NORMAL: - //m_ChosenOrientation = GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_0; - break; - case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_LEFT: - //m_ChosenOrientation = GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_90; - isRotated = true; - break; - case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_RIGHT: - //m_ChosenOrientation = GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_270; - isRotated = true; - break; - case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_UPSIDEDOWN: - //m_ChosenOrientation = GAMESCOPE_PANEL_EXTERNAL_ORIENTATION_180; - break; - default: - wl_log.errorf("Invalid target orientation selected"); + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_NORMAL: + g_DesiredExternalOrientation = GAMESCOPE_PANEL_ORIENTATION_0; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_LEFT: + g_DesiredExternalOrientation = GAMESCOPE_PANEL_ORIENTATION_90; + isRotated = true; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_RIGHT: + g_DesiredExternalOrientation = GAMESCOPE_PANEL_ORIENTATION_270; + isRotated = true; + break; + case GAMESCOPE_CONTROL_DISPLAY_ROTATION_FLAG_UPSIDEDOWN: + g_DesiredExternalOrientation = GAMESCOPE_PANEL_ORIENTATION_180; + break; + default: + wl_log.errorf("Invalid target orientation selected"); } } //drm_set_orientation(&g_DRM, isRotated); @@ -2512,34 +2514,61 @@ const std::shared_ptr<wlserver_vk_swapchain_feedback>& wlserver_surface_swapchai /* Handle the orientation of the touch inputs */ static void apply_touchscreen_orientation(double *x, double *y ) { - double tx = 0; - double ty = 0; + double tx = 0; + double ty = 0; - // Use internal screen always for orientation purposes. - switch ( GetBackend()->GetConnector( gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL )->GetCurrentOrientation() ) - { - default: - case GAMESCOPE_PANEL_ORIENTATION_AUTO: - case GAMESCOPE_PANEL_ORIENTATION_0: - tx = *x; - ty = *y; - break; - case GAMESCOPE_PANEL_ORIENTATION_90: - tx = 1.0 - *y; - ty = *x; - break; - case GAMESCOPE_PANEL_ORIENTATION_180: - tx = 1.0 - *x; - ty = 1.0 - *y; - break; - case GAMESCOPE_PANEL_ORIENTATION_270: - tx = *y; - ty = 1.0 - *x; - break; - } + // Use internal screen always for orientation purposes. + if ( g_ForcedScreenType == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL || g_ForcedScreenType == gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL ) + { + switch ( g_DesiredInternalOrientation ) + { + default: + case GAMESCOPE_PANEL_ORIENTATION_AUTO: + case GAMESCOPE_PANEL_ORIENTATION_0: + tx = *x; + ty = *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_90: + tx = 1.0 - *y; + ty = *x; + break; + case GAMESCOPE_PANEL_ORIENTATION_180: + tx = 1.0 - *x; + ty = 1.0 - *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_270: + tx = *y; + ty = 1.0 - *x; + break; + } + } + else if (g_ForcedScreenType == gamescope::GAMESCOPE_SCREEN_TYPE_AUTO) + { + switch (GetBackend()->GetConnector(gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL)->GetCurrentOrientation()) + { + default: + case GAMESCOPE_PANEL_ORIENTATION_AUTO: + case GAMESCOPE_PANEL_ORIENTATION_0: + tx = *x; + ty = *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_90: + tx = 1.0 - *y; + ty = *x; + break; + case GAMESCOPE_PANEL_ORIENTATION_180: + tx = 1.0 - *x; + ty = 1.0 - *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_270: + tx = *y; + ty = 1.0 - *x; + break; + } + } - *x = tx; - *y = ty; + *x = tx; + *y = ty; } void wlserver_touchmotion( double x, double y, int touch_id, uint32_t time, bool bAlwaysWarpCursor ) -- 2.46.0 From 3efb4df00c1e88219a3ff7c47af99b7217d1fe95 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Sat, 18 May 2024 13:50:57 -0500 Subject: [PATCH 09/21] Fix an arithmetic error --- src/Backends/DRMBackend.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 663b1e2..eafb2f9 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2031,9 +2031,9 @@ namespace gamescope void CDRMConnector::UpdateEffectiveOrientation( const drmModeModeInfo *pMode ) { - if ( this->GetScreenType() == ( GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO ) - || ( GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO - && g_bExternalForced ) ) + if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO + || GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO + && g_bExternalForced ) { m_ChosenOrientation = g_DesiredInternalOrientation; } -- 2.46.0 From dd53e4d18b122cae5383d77fc3f6e79084d8993f Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Sat, 18 May 2024 19:04:48 -0500 Subject: [PATCH 10/21] Rework the touch gestures to be more smooth --- src/wlserver.cpp | 89 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/src/wlserver.cpp b/src/wlserver.cpp index ff534ad..593a074 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -80,6 +80,8 @@ using namespace std::literals; extern gamescope::ConVar<bool> cv_drm_debug_disable_explicit_sync; +bool pending_gesture = false; +bool pending_osk = false; //#define GAMESCOPE_SWAPCHAIN_DEBUG gamescope::ConVar<bool> cv_touch_gestures( "enable_touch_gestures", false, "Enable/Disable the usage of touch gestures" ); extern GamescopePanelOrientation g_DesiredInternalOrientation; @@ -362,6 +364,39 @@ void wlserver_open_steam_menu( bool qam ) XTestFakeKeyEvent(server->get_xdisplay(), XKeysymToKeycode( server->get_xdisplay(), XK_Control_L ), False, CurrentTime); } +void wlserver_open_steam_osk(bool osk) +{ + gamescope_xwayland_server_t *server = wlserver_get_xwayland_server( 0 ); + if (!server) + return; + + uint32_t osk_open = osk; + + if (osk_open) + { + const char *command = "xdg-open steam://open/keyboard?"; + int result = system(command); + if (result == 0) { + printf("Command executed successfully.\n"); + } else { + printf("Error executing command.\n"); + } + pending_osk = false; + } + else + { + const char *command = "xdg-open steam://close/keyboard?"; + int result = system(command); + if (result == 0) { + printf("Command executed successfully.\n"); + } else { + printf("Error executing command.\n"); + } + pending_osk = false; + } + +} + static void wlserver_handle_pointer_button(struct wl_listener *listener, void *data) { struct wlserver_pointer *pointer = wl_container_of( listener, pointer, button ); @@ -2607,32 +2642,46 @@ void wlserver_touchmotion( double x, double y, int touch_id, uint32_t time, bool if ( bAlwaysWarpCursor ) wlserver_mousewarp( tx, ty, time, false ); - if (cv_touch_gestures) { - bool start_gesture = false; - - // Round the x-coordinate to the nearest whole number + if ( cv_touch_gestures ) + { uint32_t roundedCursorX = static_cast<int>(std::round(tx)); - // Grab 2% of the display to be used for the edge range - uint32_t edge_range = static_cast<uint32_t>(g_nOutputWidth * 0.02); - - // Determine if the gesture should start - if (roundedCursorX <= edge_range || roundedCursorX >= g_nOutputWidth - edge_range) { - start_gesture = true; - } - - // Handle Home gesture - if (start_gesture && roundedCursorX >= edge_range) { + uint32_t roundedCursorY = static_cast<int>(std::round(ty)); + uint32_t edge_range_x = static_cast<uint32_t>(g_nOutputWidth * 0.02); + uint32_t edge_range_y = static_cast<uint32_t>(g_nOutputWidth * 0.02); + uint32_t gesture_limits_x = edge_range_x * 2; + uint32_t gesture_limits_y = edge_range_y * 2; + + // Left to Right and Right to Left + if (!pending_gesture && roundedCursorX >= 1 && roundedCursorX < edge_range_x || + !pending_gesture && roundedCursorX >= g_nOutputWidth - edge_range_x ) + pending_gesture = true; + + //left + if (pending_gesture && roundedCursorX >= edge_range_x && roundedCursorX < gesture_limits_x) { wlserver_open_steam_menu(0); - start_gesture = false; + pending_gesture = false; } - - // Handle QAM gesture - if (start_gesture && roundedCursorX >= g_nOutputWidth - edge_range && roundedCursorX <= g_nOutputWidth) { + //right + if (pending_gesture && roundedCursorX <= g_nOutputWidth - edge_range_x && roundedCursorX > g_nOutputWidth - gesture_limits_x) { wlserver_open_steam_menu(1); - start_gesture = false; + pending_gesture = false; + } + // Top to Bottom and Bottom to Top + if (!pending_gesture && roundedCursorY >= 1 && roundedCursorY < edge_range_y || + !pending_gesture && roundedCursorY >= g_nOutputHeight - edge_range_y ) + pending_gesture = true; + // Top + if (pending_gesture && roundedCursorY >= edge_range_y && roundedCursorY < gesture_limits_y) { + pending_gesture = false; + // Top to Bottom function to add + } + // Bottom + if (pending_gesture && !pending_osk && roundedCursorY <= g_nOutputWidth - edge_range_y && roundedCursorY > g_nOutputHeight - gesture_limits_y) { + pending_gesture = false; + pending_osk = true; + //wlserver_open_steam_osk(1); } } - } else if ( eMode == gamescope::TouchClickModes::Disabled ) { -- 2.46.0 From 70d4ea8937e43752e1adb32ebbcdd3d1a0bcf23c Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Sun, 19 May 2024 08:55:28 -0500 Subject: [PATCH 11/21] Fix a typo for --bypass-steam-resolution --- src/steamcompmgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 952a5f8..6fceb1d 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -7379,7 +7379,7 @@ steamcompmgr_main(int argc, char **argv) bForceWindowsFullscreen = true; } else if (strcmp(opt_name, "hdr-enabled") == 0) { cv_hdr_enabled = true; - } else if (strcmp(opt_name, "bypass_steam_resolution") == 0) { + } else if (strcmp(opt_name, "bypass-steam-resolution") == 0) { cv_bypass_steam_resolution = true; } else if (strcmp(opt_name, "hdr-debug-force-support") == 0) { g_bForceHDRSupportDebug = true; -- 2.46.0 From be8e56d7f3bf251f75da24aa8a99d2e91aa60812 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Sun, 19 May 2024 11:48:52 -0500 Subject: [PATCH 12/21] Handle gesture cases better to prevent unexpected behavior --- src/wlserver.cpp | 63 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 593a074..833140a 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -80,7 +80,8 @@ using namespace std::literals; extern gamescope::ConVar<bool> cv_drm_debug_disable_explicit_sync; -bool pending_gesture = false; +bool pending_gesture_x = false; +bool pending_gesture_y = false; bool pending_osk = false; //#define GAMESCOPE_SWAPCHAIN_DEBUG gamescope::ConVar<bool> cv_touch_gestures( "enable_touch_gestures", false, "Enable/Disable the usage of touch gestures" ); @@ -2606,6 +2607,16 @@ static void apply_touchscreen_orientation(double *x, double *y ) *y = ty; } +void wlserver_gesture_flush() +{ + pending_gesture_x = false; + pending_gesture_y = false; +} + +// Variables to track the direction of the touch motion +uint32_t previous_tx = 0; +uint32_t previous_ty = 0; + void wlserver_touchmotion( double x, double y, int touch_id, uint32_t time, bool bAlwaysWarpCursor ) { assert( wlserver_is_lock_held() ); @@ -2644,43 +2655,55 @@ void wlserver_touchmotion( double x, double y, int touch_id, uint32_t time, bool if ( cv_touch_gestures ) { - uint32_t roundedCursorX = static_cast<int>(std::round(tx)); - uint32_t roundedCursorY = static_cast<int>(std::round(ty)); - uint32_t edge_range_x = static_cast<uint32_t>(g_nOutputWidth * 0.02); - uint32_t edge_range_y = static_cast<uint32_t>(g_nOutputWidth * 0.02); + uint32_t rounded_tx = static_cast<int>(std::round(tx)); + uint32_t rounded_ty = static_cast<int>(std::round(ty)); + uint32_t edge_range_x = static_cast<uint32_t>(g_nOutputWidth * 0.05); + uint32_t edge_range_y = static_cast<uint32_t>(g_nOutputWidth * 0.05); uint32_t gesture_limits_x = edge_range_x * 2; uint32_t gesture_limits_y = edge_range_y * 2; + uint32_t threshold_distance_x = gesture_limits_x; + uint32_t threshold_distance_y = gesture_limits_y; // Left to Right and Right to Left - if (!pending_gesture && roundedCursorX >= 1 && roundedCursorX < edge_range_x || - !pending_gesture && roundedCursorX >= g_nOutputWidth - edge_range_x ) - pending_gesture = true; + if (!pending_gesture_x && ((rounded_tx >= 1 && rounded_tx < edge_range_x) || (rounded_tx >= g_nOutputWidth - edge_range_x))) { + // Check if the distance moved is greater than the threshold + if (rounded_tx - previous_tx > threshold_distance_x) { + pending_gesture_x = true; + } + } + + // Top to Bottom and Bottom to Top + if (!pending_gesture_y && ((rounded_ty >= 1 && rounded_ty < edge_range_y) || (rounded_ty >= g_nOutputHeight - edge_range_y))) { + // Check if the distance moved is greater than the threshold + if (rounded_ty - previous_ty > threshold_distance_y) { + pending_gesture_y = true; + } + } //left - if (pending_gesture && roundedCursorX >= edge_range_x && roundedCursorX < gesture_limits_x) { + if (pending_gesture_x && previous_tx < rounded_tx && rounded_tx >= edge_range_x && rounded_tx < gesture_limits_x) { wlserver_open_steam_menu(0); - pending_gesture = false; + wlserver_gesture_flush(); } //right - if (pending_gesture && roundedCursorX <= g_nOutputWidth - edge_range_x && roundedCursorX > g_nOutputWidth - gesture_limits_x) { + if (pending_gesture_x && previous_tx > rounded_tx && rounded_tx <= g_nOutputWidth - edge_range_x && rounded_tx > g_nOutputWidth - gesture_limits_x) { wlserver_open_steam_menu(1); - pending_gesture = false; + wlserver_gesture_flush(); } - // Top to Bottom and Bottom to Top - if (!pending_gesture && roundedCursorY >= 1 && roundedCursorY < edge_range_y || - !pending_gesture && roundedCursorY >= g_nOutputHeight - edge_range_y ) - pending_gesture = true; + // Top - if (pending_gesture && roundedCursorY >= edge_range_y && roundedCursorY < gesture_limits_y) { - pending_gesture = false; + if (pending_gesture_y && previous_ty < rounded_ty && rounded_ty >= edge_range_y && rounded_ty < gesture_limits_y) { + wlserver_gesture_flush(); // Top to Bottom function to add } // Bottom - if (pending_gesture && !pending_osk && roundedCursorY <= g_nOutputWidth - edge_range_y && roundedCursorY > g_nOutputHeight - gesture_limits_y) { - pending_gesture = false; + if (pending_gesture_y && previous_ty > rounded_ty && !pending_osk && rounded_ty <= g_nOutputWidth - edge_range_y && rounded_ty > g_nOutputHeight - gesture_limits_y) { + wlserver_gesture_flush(); pending_osk = true; //wlserver_open_steam_osk(1); } + previous_tx = rounded_tx; + previous_ty = rounded_ty; } } else if ( eMode == gamescope::TouchClickModes::Disabled ) -- 2.46.0 From b31ab55d57f0a8b746d4d0fa7939f6473bcad9a4 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Sun, 19 May 2024 18:14:23 -0500 Subject: [PATCH 13/21] Add references to drm_set_orientation() and g_drm in wlserver for rotation gamescope-control --- src/wlserver.cpp | 5 +++-- src/wlserver.hpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 833140a..eb3936a 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -1125,8 +1125,9 @@ static void gamescope_control_rotate_display( struct wl_client *client, struct w wl_log.errorf("Invalid target orientation selected"); } } - //drm_set_orientation(&g_DRM, isRotated); - //g_DRM.out_of_date = 2; + drm_set_orientation(&g_DRM, isRotated); + GetBackend()->DirtyState( true, true ); + } static void gamescope_control_handle_destroy( struct wl_client *client, struct wl_resource *resource ) diff --git a/src/wlserver.hpp b/src/wlserver.hpp index 3304c18..0754ee5 100644 --- a/src/wlserver.hpp +++ b/src/wlserver.hpp @@ -275,7 +275,8 @@ extern std::atomic<bool> g_bPendingTouchMovement; extern gamescope::ConVar<bool> cv_touch_gestures; void wlserver_open_steam_menu( bool qam ); - +extern void drm_set_orientation( struct drm_t *drm, bool isRotated); +extern drm_t g_DRM; uint32_t wlserver_make_new_xwayland_server(); void wlserver_destroy_xwayland_server(gamescope_xwayland_server_t *server); -- 2.46.0 From 8df476a6f7d41157e847ee7c3346c796e674d9fe Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Mon, 20 May 2024 07:02:52 -0500 Subject: [PATCH 14/21] Fix an issue where forced panel type orientations weren't being applied --- src/Backends/DRMBackend.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index eafb2f9..1ea1221 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2031,20 +2031,19 @@ namespace gamescope void CDRMConnector::UpdateEffectiveOrientation( const drmModeModeInfo *pMode ) { - if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO - || GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO - && g_bExternalForced ) - { + if ((this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO) || + (this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO && g_bExternalForced)) { + drm_log.infof("We are rotating the orientation of the internal or faked external display") m_ChosenOrientation = g_DesiredInternalOrientation; - } - else if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO ) - { + } else if (this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO) { + drm_log.infof("We are rotating the orientation of an external display"); m_ChosenOrientation = g_DesiredExternalOrientation; } else { if ( this->GetProperties().panel_orientation ) { + drm_log.infof("We are using a kernel orientation quirk to rotate the display"); switch ( this->GetProperties().panel_orientation->GetCurrentValue() ) { case DRM_MODE_PANEL_ORIENTATION_NORMAL: @@ -2066,6 +2065,7 @@ namespace gamescope if ( this->GetScreenType() == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL && pMode ) { + drm_log.infof("We are using legacy code to rotate the display"); // Auto-detect portait mode for internal displays m_ChosenOrientation = pMode->hdisplay < pMode->vdisplay ? GAMESCOPE_PANEL_ORIENTATION_270 @@ -2073,6 +2073,7 @@ namespace gamescope } else { + drm_log.infof("No orientation quirks have been applied"); m_ChosenOrientation = GAMESCOPE_PANEL_ORIENTATION_0; } } -- 2.46.0 From 5d7781dd8ca41f4d865aa336b4e925beeec9349e Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Mon, 20 May 2024 07:25:29 -0500 Subject: [PATCH 15/21] add missing curly bracket... --- src/Backends/DRMBackend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 1ea1221..8d86df0 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2033,7 +2033,7 @@ namespace gamescope { if ((this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO) || (this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO && g_bExternalForced)) { - drm_log.infof("We are rotating the orientation of the internal or faked external display") + drm_log.infof("We are rotating the orientation of the internal or faked external display"); m_ChosenOrientation = g_DesiredInternalOrientation; } else if (this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO) { drm_log.infof("We are rotating the orientation of an external display"); -- 2.46.0 From 0282352468bb6b99e75eb1c24cb3ed555886fff5 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Mon, 20 May 2024 10:17:55 -0500 Subject: [PATCH 16/21] Fix case where real externals were rotated with faked external panels --- src/Backends/DRMBackend.cpp | 21 +++++++---- src/wlserver.cpp | 72 +++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 8d86df0..0008505 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -318,13 +318,20 @@ namespace gamescope GamescopeScreenType GetScreenType() const override { - if ( g_ForcedScreenType != GAMESCOPE_SCREEN_TYPE_AUTO ) - return g_ForcedScreenType; - if ( m_pConnector->connector_type == DRM_MODE_CONNECTOR_eDP || m_pConnector->connector_type == DRM_MODE_CONNECTOR_LVDS || m_pConnector->connector_type == DRM_MODE_CONNECTOR_DSI ) - return GAMESCOPE_SCREEN_TYPE_INTERNAL; + { + if ( g_bExternalForced ) + { + return g_ForcedScreenType; + } + else + { + return GAMESCOPE_SCREEN_TYPE_INTERNAL; + } + } + return GAMESCOPE_SCREEN_TYPE_EXTERNAL; } @@ -2031,11 +2038,11 @@ namespace gamescope void CDRMConnector::UpdateEffectiveOrientation( const drmModeModeInfo *pMode ) { - if ((this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO) || - (this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO && g_bExternalForced)) { + if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO ) { drm_log.infof("We are rotating the orientation of the internal or faked external display"); m_ChosenOrientation = g_DesiredInternalOrientation; - } else if (this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO) { + } + else if (this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredExternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO) { drm_log.infof("We are rotating the orientation of an external display"); m_ChosenOrientation = g_DesiredExternalOrientation; } diff --git a/src/wlserver.cpp b/src/wlserver.cpp index eb3936a..896ec04 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -2555,29 +2555,57 @@ static void apply_touchscreen_orientation(double *x, double *y ) double ty = 0; // Use internal screen always for orientation purposes. - if ( g_ForcedScreenType == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL || g_ForcedScreenType == gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL ) + if ( g_ForcedScreenType != gamescope::GAMESCOPE_SCREEN_TYPE_AUTO ) { - switch ( g_DesiredInternalOrientation ) - { - default: - case GAMESCOPE_PANEL_ORIENTATION_AUTO: - case GAMESCOPE_PANEL_ORIENTATION_0: - tx = *x; - ty = *y; - break; - case GAMESCOPE_PANEL_ORIENTATION_90: - tx = 1.0 - *y; - ty = *x; - break; - case GAMESCOPE_PANEL_ORIENTATION_180: - tx = 1.0 - *x; - ty = 1.0 - *y; - break; - case GAMESCOPE_PANEL_ORIENTATION_270: - tx = *y; - ty = 1.0 - *x; - break; - } + if ( g_ForcedScreenType == gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL ) + { + switch (GetBackend()->GetConnector(gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL)->GetCurrentOrientation()) + { + default: + case GAMESCOPE_PANEL_ORIENTATION_AUTO: + case GAMESCOPE_PANEL_ORIENTATION_0: + tx = *x; + ty = *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_90: + tx = 1.0 - *y; + ty = *x; + break; + case GAMESCOPE_PANEL_ORIENTATION_180: + tx = 1.0 - *x; + ty = 1.0 - *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_270: + tx = *y; + ty = 1.0 - *x; + break; + } + } + else + { + switch (GetBackend()->GetConnector(gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL)->GetCurrentOrientation()) + { + default: + case GAMESCOPE_PANEL_ORIENTATION_AUTO: + case GAMESCOPE_PANEL_ORIENTATION_0: + tx = *x; + ty = *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_90: + tx = 1.0 - *y; + ty = *x; + break; + case GAMESCOPE_PANEL_ORIENTATION_180: + tx = 1.0 - *x; + ty = 1.0 - *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_270: + tx = *y; + ty = 1.0 - *x; + break; + } + } + } else if (g_ForcedScreenType == gamescope::GAMESCOPE_SCREEN_TYPE_AUTO) { -- 2.46.0 From 276c1220de3542467b6d8e2218dfa1f2ccfc5b79 Mon Sep 17 00:00:00 2001 From: Matthew Anderson <ruinairas1992@gmail.com> Date: Mon, 20 May 2024 16:30:47 -0500 Subject: [PATCH 17/21] Add verbose panel logs and attempt to address all orientation issues --- src/Backends/DRMBackend.cpp | 18 ++++++++++++++-- src/wlserver.cpp | 41 ++++++++++++++++++++----------------- src/wlserver.hpp | 1 + 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 0008505..bd5ffec 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -56,6 +56,7 @@ static constexpr bool k_bUseCursorPlane = false; extern int g_nPreferredOutputWidth; extern int g_nPreferredOutputHeight; +bool panelTypeChanged = false; gamescope::ConVar<bool> cv_drm_single_plane_optimizations( "drm_single_plane_optimizations", true, "Whether or not to enable optimizations for single plane usage." ); @@ -324,6 +325,7 @@ namespace gamescope { if ( g_bExternalForced ) { + panelTypeChanged = true; return g_ForcedScreenType; } else @@ -332,7 +334,7 @@ namespace gamescope } } - + panelTypeChanged = false; return GAMESCOPE_SCREEN_TYPE_EXTERNAL; } @@ -2038,7 +2040,19 @@ namespace gamescope void CDRMConnector::UpdateEffectiveOrientation( const drmModeModeInfo *pMode ) { - if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO ) { + + if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && panelTypeChanged ) + drm_log.infof("Display is internal faked as external"); + if ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && !panelTypeChanged ) + drm_log.infof("Display is real internal"); + if (panelTypeChanged){ + drm_log.infof("Panel type was changed"); + } + + if (( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO ) || + ( this->GetScreenType() == GAMESCOPE_SCREEN_TYPE_EXTERNAL && g_DesiredInternalOrientation != GAMESCOPE_PANEL_ORIENTATION_AUTO + && panelTypeChanged)) { + drm_log.infof("We are rotating the orientation of the internal or faked external display"); m_ChosenOrientation = g_DesiredInternalOrientation; } diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 896ec04..e5bb2e2 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -2559,26 +2559,29 @@ static void apply_touchscreen_orientation(double *x, double *y ) { if ( g_ForcedScreenType == gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL ) { - switch (GetBackend()->GetConnector(gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL)->GetCurrentOrientation()) + if(panelTypeChanged) { - default: - case GAMESCOPE_PANEL_ORIENTATION_AUTO: - case GAMESCOPE_PANEL_ORIENTATION_0: - tx = *x; - ty = *y; - break; - case GAMESCOPE_PANEL_ORIENTATION_90: - tx = 1.0 - *y; - ty = *x; - break; - case GAMESCOPE_PANEL_ORIENTATION_180: - tx = 1.0 - *x; - ty = 1.0 - *y; - break; - case GAMESCOPE_PANEL_ORIENTATION_270: - tx = *y; - ty = 1.0 - *x; - break; + switch (GetBackend()->GetConnector(gamescope::GAMESCOPE_SCREEN_TYPE_EXTERNAL)->GetCurrentOrientation()) + { + default: + case GAMESCOPE_PANEL_ORIENTATION_AUTO: + case GAMESCOPE_PANEL_ORIENTATION_0: + tx = *x; + ty = *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_90: + tx = 1.0 - *y; + ty = *x; + break; + case GAMESCOPE_PANEL_ORIENTATION_180: + tx = 1.0 - *x; + ty = 1.0 - *y; + break; + case GAMESCOPE_PANEL_ORIENTATION_270: + tx = *y; + ty = 1.0 - *x; + break; + } } } else diff --git a/src/wlserver.hpp b/src/wlserver.hpp index 0754ee5..bdf3b0b 100644 --- a/src/wlserver.hpp +++ b/src/wlserver.hpp @@ -277,6 +277,7 @@ extern gamescope::ConVar<bool> cv_touch_gestures; void wlserver_open_steam_menu( bool qam ); extern void drm_set_orientation( struct drm_t *drm, bool isRotated); extern drm_t g_DRM; +extern bool panelTypeChanged; uint32_t wlserver_make_new_xwayland_server(); void wlserver_destroy_xwayland_server(gamescope_xwayland_server_t *server); -- 2.46.0 From 11664b820a9065b597d8655e53ade8dd9a29c4bc Mon Sep 17 00:00:00 2001 From: Bouke Sybren Haarsma <boukehaarsma23@gmail.com> Date: Tue, 28 May 2024 21:56:47 +0200 Subject: [PATCH 18/21] add closing bracket --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 675020f..315b718 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -465,6 +465,7 @@ static enum gamescope::GamescopeBackend parse_backend_name(const char *str) fprintf( stderr, "gamescope: invalid value for --backend\n" ); exit(1); } +} std::vector<uint32_t> g_customRefreshRates; // eg: 60,60,90,110-120 -- 2.46.0 From 1e5c439eb0b1e809a3ec6414e8d0536db22c9601 Mon Sep 17 00:00:00 2001 From: Bouke Sybren Haarsma <boukehaarsma23@gmail.com> Date: Wed, 3 Jan 2024 17:03:04 +0100 Subject: [PATCH 19/21] remove hacky texture This will use more hardware planes, causing some devices to composite yeilding lower framerates --- src/steamcompmgr.cpp | 62 ++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 45 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 6fceb1d..4dbbdaf 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1620,7 +1620,7 @@ bool MouseCursor::getTexture() { pixels[i * image->width + j] = image->pixels[i * image->width + j]; } - } + } std::vector<uint32_t> resizeBuffer( nDesiredWidth * nDesiredHeight ); stbir_resize_uint8_srgb( (unsigned char *)pixels.data(), image->width, image->height, 0, (unsigned char *)resizeBuffer.data(), nDesiredWidth, nDesiredHeight, 0, @@ -2306,7 +2306,7 @@ paint_all(bool async) } } } - + int nOldLayerCount = frameInfo.layerCount; uint32_t flags = 0; @@ -2314,7 +2314,7 @@ paint_all(bool async) flags |= PaintWindowFlag::BasePlane; paint_window(w, w, &frameInfo, global_focus.cursor, flags); update_touch_scaling( &frameInfo ); - + // paint UI unless it's fully hidden, which it communicates to us through opacity=0 // we paint it to extract scaling coefficients above, then remove the layer if one was added if ( w->opacity == TRANSLUCENT && bHasVideoUnderlay && nOldLayerCount < frameInfo.layerCount ) @@ -2327,7 +2327,7 @@ paint_all(bool async) float opacityScale = g_bPendingFade ? 0.0f : ((currentTime - fadeOutStartTime) / (float)g_FadeOutDuration); - + paint_cached_base_layer(g_HeldCommits[HELD_COMMIT_FADE], g_CachedPlanes[HELD_COMMIT_FADE], &frameInfo, 1.0f - opacityScale, false); paint_window(w, w, &frameInfo, global_focus.cursor, PaintWindowFlag::BasePlane | PaintWindowFlag::FadeTarget | PaintWindowFlag::DrawBorders, opacityScale, override); } @@ -2401,34 +2401,6 @@ paint_all(bool async) if ( overlay == global_focus.inputFocusWindow ) update_touch_scaling( &frameInfo ); } - else if ( !GetBackend()->UsesVulkanSwapchain() && GetBackend()->IsSessionBased() ) - { - auto tex = vulkan_get_hacky_blank_texture(); - if ( tex != nullptr ) - { - // HACK! HACK HACK HACK - // To avoid stutter when toggling the overlay on - int curLayer = frameInfo.layerCount++; - - FrameInfo_t::Layer_t *layer = &frameInfo.layers[ curLayer ]; - - - layer->scale.x = g_nOutputWidth == tex->width() ? 1.0f : tex->width() / (float)g_nOutputWidth; - layer->scale.y = g_nOutputHeight == tex->height() ? 1.0f : tex->height() / (float)g_nOutputHeight; - layer->offset.x = 0.0f; - layer->offset.y = 0.0f; - layer->opacity = 1.0f; // BLAH - layer->zpos = g_zposOverlay; - layer->applyColorMgmt = g_ColorMgmt.pending.enabled; - - layer->colorspace = GAMESCOPE_APP_TEXTURE_COLORSPACE_LINEAR; - layer->ctm = nullptr; - layer->tex = tex; - - layer->filter = GamescopeUpscaleFilter::NEAREST; - layer->blackBorder = true; - } - } if (notification) { @@ -3014,7 +2986,7 @@ win_maybe_a_dropdown( steamcompmgr_win_t *w ) // // TODO: Come back to me for original Age of Empires HD launcher. // Does that use it? It wants blending! - // + // // Only do this if we have CONTROLPARENT right now. Some other apps, such as the // Street Fighter V (310950) Splash Screen also use LAYERED and TOOLWINDOW, and we don't // want that to be overlayed. @@ -3029,12 +3001,12 @@ win_maybe_a_dropdown( steamcompmgr_win_t *w ) // Josh: // The logic here is as follows. The window will be treated as a dropdown if: - // + // // If this window has a fixed position on the screen + static gravity: // - If the window has either skipPage or skipTaskbar // - If the window isn't a dialog, always treat it as a dropdown, as it's // probably meant to be some form of popup. - // - If the window is a dialog + // - If the window is a dialog // - If the window has transient for, disregard it, as it is trying to redirecting us elsewhere // ie. a settings menu dialog popup or something. // - If the window has both skip taskbar and pager, treat it as a dialog. @@ -3126,7 +3098,7 @@ static bool is_good_override_candidate( steamcompmgr_win_t *override, steamcompm return false; return override != focus && override->GetGeometry().nX >= 0 && override->GetGeometry().nY >= 0; -} +} static bool pick_primary_focus_and_override(focus_t *out, Window focusControlWindow, const std::vector<steamcompmgr_win_t*>& vecPossibleFocusWindows, bool globalFocus, const std::vector<uint32_t>& ctxFocusControlAppIDs) @@ -3267,7 +3239,7 @@ found:; if ( focus ) { - if ( window_has_commits( focus ) ) + if ( window_has_commits( focus ) ) out->focusWindow = focus; else focus->outdatedInteractiveFocus = true; @@ -3310,9 +3282,9 @@ found:; override_focus = fake_override; goto found2; } - } + } } - + found2:; resolveTransientOverrides( true ); } @@ -4574,7 +4546,7 @@ finish_destroy_win(xwayland_ctx_t *ctx, Window id, bool gone) { if (gone) finish_unmap_win (ctx, w); - + { std::unique_lock lock( ctx->list_mutex ); *prev = w->xwayland().next; @@ -4631,7 +4603,7 @@ destroy_win(xwayland_ctx_t *ctx, Window id, bool gone, bool fade) global_focus.overrideWindow = nullptr; if (x11_win(global_focus.fadeWindow) == id && gone) global_focus.fadeWindow = nullptr; - + MakeFocusDirty(); finish_destroy_win(ctx, id, gone); @@ -5243,7 +5215,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) { get_win_type(ctx, w); MakeFocusDirty(); - } + } } if (ev->atom == ctx->atoms.sizeHintsAtom) { @@ -6153,7 +6125,7 @@ void handle_done_commits_xdg( bool vblank, uint64_t vblank_idx ) commits_before_their_time.push_back( entry ); continue; } - + if (!entry.earliestPresentTime) { entry.earliestPresentTime = next_refresh_time; @@ -7143,7 +7115,7 @@ void update_mode_atoms(xwayland_ctx_t *root_ctx, bool* needs_flush = nullptr) } XChangeProperty(root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeDisplayModeListExternal, XA_STRING, 8, PropModeReplace, (unsigned char *)modes, strlen(modes) + 1 ); - + uint32_t one = 1; XChangeProperty(root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeDisplayIsExternal, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&one, 1 ); @@ -7975,7 +7947,7 @@ void steamcompmgr_send_frame_done_to_focus_window() { wlserver_lock(); wlserver_send_frame_done( global_focus.focusWindow->xwayland().surface.main_surface , &now ); - wlserver_unlock(); + wlserver_unlock(); } } -- 2.46.0 From 672fd75c5ac7bb1226c418270fa134ad6fe07b30 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich <me@kylegospodneti.ch> Date: Tue, 2 Jul 2024 14:12:47 -0700 Subject: [PATCH 20/21] Only change refresh rates on internal displays --- src/Backends/DRMBackend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index bd5ffec..03b9b4c 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2162,7 +2162,7 @@ namespace gamescope ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "Jupiter"sv ) || ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "Galileo"sv ); - if ( g_customRefreshRates.size() > 0 ) { + if ( g_customRefreshRates.size() > 0 && GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL ) { m_Mutable.ValidDynamicRefreshRates = std::span(g_customRefreshRates); return; } -- 2.46.0 From 0cada655064b2bb2c0b5540f4c249a3c6a1254ed Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich <me@kylegospodneti.ch> Date: Tue, 2 Jul 2024 15:14:23 -0700 Subject: [PATCH 21/21] Also check g_bExternalForced --- src/Backends/DRMBackend.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 03b9b4c..24e81b1 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2162,9 +2162,9 @@ namespace gamescope ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "Jupiter"sv ) || ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "Galileo"sv ); - if ( g_customRefreshRates.size() > 0 && GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL ) { - m_Mutable.ValidDynamicRefreshRates = std::span(g_customRefreshRates); - return; + if ( g_customRefreshRates.size() > 0 && ( GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL || g_bExternalForced ) ) { + m_Mutable.ValidDynamicRefreshRates = std::span(g_customRefreshRates); + return; } if ( bSteamDeckDisplay ) { -- 2.46.0