From 79cb130dcceda94700d8977e817cb1a9de561d1e Mon Sep 17 00:00:00 2001 From: "Pierre-Loup A. Griffais" Date: Tue, 1 Sep 2020 21:36:48 -0700 Subject: [PATCH] sdlwindow: put all the SDL I/O code in the same spot. --- meson.build | 2 +- src/inputsdl.hpp | 5 - src/main.cpp | 34 +--- src/main.hpp | 7 +- src/rendervulkan.cpp | 3 +- src/{inputsdl.cpp => sdlscancodetable.hpp} | 163 ---------------- src/sdlwindow.cpp | 204 +++++++++++++++++++++ src/sdlwindow.hpp | 13 ++ 8 files changed, 226 insertions(+), 205 deletions(-) delete mode 100644 src/inputsdl.hpp rename src/{inputsdl.cpp => sdlscancodetable.hpp} (75%) create mode 100644 src/sdlwindow.cpp create mode 100644 src/sdlwindow.hpp diff --git a/meson.build b/meson.build index 5c2be78..905dfb9 100644 --- a/meson.build +++ b/meson.build @@ -70,7 +70,7 @@ executable( 'src/main.cpp', 'src/wlserver.cpp', 'src/drm.cpp', - 'src/inputsdl.cpp', + 'src/sdlwindow.cpp', 'src/vblankmanager.cpp', [ 'src/rendervulkan.cpp', spirv_shader ], dependencies : [ diff --git a/src/inputsdl.hpp b/src/inputsdl.hpp deleted file mode 100644 index a3f38f8..0000000 --- a/src/inputsdl.hpp +++ /dev/null @@ -1,5 +0,0 @@ -// For the nested case, reads input from the SDL window and send to wayland - -#pragma once - -bool inputsdl_init( void ); diff --git a/src/main.cpp b/src/main.cpp index cd8ef1d..edc609c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -10,14 +11,12 @@ #include "steamcompmgr.hpp" #include "drm.hpp" #include "rendervulkan.hpp" -#include "inputsdl.hpp" +#include "sdlwindow.hpp" #include "wlserver.hpp" int ac; char **av; -SDL_Window *window; - int g_nNestedWidth = 1280; int g_nNestedHeight = 720; int g_nNestedRefresh = 60; @@ -156,34 +155,7 @@ int initOutput(void) { if ( g_bIsNested == true ) { - inputsdl_init(); - - uint32_t nSDLWindowFlags = SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE; - - if ( g_bBorderlessOutputWindow == true ) - { - nSDLWindowFlags |= SDL_WINDOW_BORDERLESS; - } - - window = SDL_CreateWindow( "gamescope", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - g_nOutputWidth, - g_nOutputHeight, - nSDLWindowFlags ); - if ( window == nullptr ) - { - fprintf(stderr, "Failed to create SDL window\n"); - return -1; - } - - unsigned int extCount = 0; - SDL_Vulkan_GetInstanceExtensions( window, &extCount, nullptr ); - - g_vecSDLInstanceExts.resize( extCount ); - - SDL_Vulkan_GetInstanceExtensions( window, &extCount, g_vecSDLInstanceExts.data() ); - return 0; + return sdlwindow_init() == false; } else { diff --git a/src/main.hpp b/src/main.hpp index a3675ed..e68fec3 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -1,7 +1,4 @@ -#include -#include - -extern SDL_Window *window; +#pragma once int initOutput(void); @@ -21,6 +18,8 @@ extern int g_nOutputRefresh; extern bool g_bFilterGameWindow; +extern bool g_bBorderlessOutputWindow; + extern bool g_bTakeScreenshot; extern uint32_t g_nSubCommandArg; diff --git a/src/rendervulkan.cpp b/src/rendervulkan.cpp index 5642928..1682cc0 100644 --- a/src/rendervulkan.cpp +++ b/src/rendervulkan.cpp @@ -7,6 +7,7 @@ #include "rendervulkan.hpp" #include "main.hpp" #include "steamcompmgr.hpp" +#include "sdlwindow.hpp" #include "composite.h" @@ -962,7 +963,7 @@ bool vulkan_make_output( VulkanOutput_t *pOutput ) if ( BIsNested() == true ) { - SDL_Vulkan_CreateSurface( window, instance, &pOutput->surface ); + SDL_Vulkan_CreateSurface( g_SDLWindow, instance, &pOutput->surface ); if ( pOutput->surface == VK_NULL_HANDLE ) return false; diff --git a/src/inputsdl.cpp b/src/sdlscancodetable.hpp similarity index 75% rename from src/inputsdl.cpp rename to src/sdlscancodetable.hpp index a49605f..b33bd31 100644 --- a/src/inputsdl.cpp +++ b/src/sdlscancodetable.hpp @@ -1,22 +1,4 @@ -// For the nested case, reads input from the SDL window and send to wayland -#include -#include - -#include -#include - -#include - -#include "inputsdl.hpp" -#include "wlserver.hpp" -#include "main.hpp" - -std::mutex g_SDLInitLock; - -//----------------------------------------------------------------------------- -// Adapted from the key table in SDL/src/input/evdev/SDL_evdev.c -//----------------------------------------------------------------------------- static uint32_t s_ScancodeTable[] = { KEY_RESERVED, /* SDL_SCANCODE_UNKNOWN 0 */ @@ -305,148 +287,3 @@ static uint32_t s_ScancodeTable[] = KEY_PROG1, /* SDL_SCANCODE_APP1 283 */ KEY_RESERVED, /* SDL_SCANCODE_APP2 284 */ }; - - -//----------------------------------------------------------------------------- -// Purpose: Convert from the remote scancode to a Linux event keycode -//----------------------------------------------------------------------------- -static inline uint32_t SDLScancodeToLinuxKey( uint32_t nScancode ) -{ - if ( nScancode < sizeof( s_ScancodeTable ) / sizeof( s_ScancodeTable[0] ) ) - { - return s_ScancodeTable[ nScancode ]; - } - return KEY_RESERVED; -} - -static inline int SDLButtonToLinuxButton( int SDLButton ) -{ - switch ( SDLButton ) - { - case SDL_BUTTON_LEFT: return BTN_LEFT; - case SDL_BUTTON_MIDDLE: return BTN_MIDDLE; - case SDL_BUTTON_RIGHT: return BTN_RIGHT; - case SDL_BUTTON_X1: return BTN_FORWARD; - case SDL_BUTTON_X2: return BTN_BACK; - default: return 0; - } -} - -void updateOutputRefresh( void ) -{ - int display_index = 0; - SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; - - display_index = SDL_GetWindowDisplayIndex( window ); - if ( SDL_GetDesktopDisplayMode( display_index, &mode ) == 0 ) - { - g_nOutputRefresh = mode.refresh_rate; - } -} - -void inputSDLThreadRun( void ) -{ - // see wlroots xwayland startup and how wl_event_loop_add_signal works - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - sigprocmask(SIG_BLOCK, &mask, NULL); - - SDL_Event event; - SDL_Keymod mod; - uint32_t key; - static bool bFullscreen = false; - - SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS ); - SDL_SetRelativeMouseMode(SDL_TRUE); - - g_SDLInitLock.unlock(); - - while( SDL_WaitEvent( &event ) ) - { - switch( event.type ) - { - case SDL_MOUSEMOTION: - wlserver_lock(); - wlserver_mousemotion( event.motion.xrel, event.motion.yrel, event.motion.timestamp ); - wlserver_unlock(); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - wlserver_lock(); - wlserver_mousebutton( SDLButtonToLinuxButton( event.button.button ), - event.button.state == SDL_PRESSED, - event.button.timestamp ); - wlserver_unlock(); - break; - case SDL_MOUSEWHEEL: - wlserver_lock(); - wlserver_mousewheel( -event.wheel.x, -event.wheel.y, event.wheel.timestamp ); - wlserver_unlock(); - break; - case SDL_KEYDOWN: - case SDL_KEYUP: - mod = SDL_GetModState(); - key = SDLScancodeToLinuxKey( event.key.keysym.scancode ); - - if ( event.type == SDL_KEYUP && mod & KMOD_LGUI ) - { - switch ( key ) - { - case KEY_F: - bFullscreen = !bFullscreen; - SDL_SetWindowFullscreen( window, bFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 ); - break; - case KEY_N: - g_bFilterGameWindow = !g_bFilterGameWindow; - break; - case KEY_S: - g_bTakeScreenshot = true; - break; - default: - goto client; - - } - break; - } -client: - wlserver_lock(); - wlserver_key( key, event.type == SDL_KEYDOWN, event.key.timestamp ); - wlserver_unlock(); - break; - case SDL_WINDOWEVENT: - switch( event.window.event ) - { - default: - break; - case SDL_WINDOWEVENT_MOVED: - case SDL_WINDOWEVENT_SHOWN: - updateOutputRefresh(); - break; - case SDL_WINDOWEVENT_SIZE_CHANGED: - g_nOutputWidth = event.window.data1; - g_nOutputHeight = event.window.data2; - - updateOutputRefresh(); - - break; - } - break; - default: - break; - } - } -} - -bool inputsdl_init( void ) -{ - g_SDLInitLock.lock(); - - std::thread inputSDLThread( inputSDLThreadRun ); - inputSDLThread.detach(); - - // When this returns SDL_Init should be over - g_SDLInitLock.lock(); - - return true; -} diff --git a/src/sdlwindow.cpp b/src/sdlwindow.cpp new file mode 100644 index 0000000..6310fe1 --- /dev/null +++ b/src/sdlwindow.cpp @@ -0,0 +1,204 @@ +// For the nested case, reads input from the SDL window and send to wayland + +#include +#include + +#include +#include + +#include "main.hpp" +#include "wlserver.hpp" +#include "sdlwindow.hpp" +#include "rendervulkan.hpp" + +#include "sdlscancodetable.hpp" + +bool g_bSDLInitOK = false; +std::mutex g_SDLInitLock; + +SDL_Window *g_SDLWindow; +uint32_t g_unSDLUserEventID; +SDL_Event g_SDLUserEvent; + +//----------------------------------------------------------------------------- +// Purpose: Convert from the remote scancode to a Linux event keycode +//----------------------------------------------------------------------------- +static inline uint32_t SDLScancodeToLinuxKey( uint32_t nScancode ) +{ + if ( nScancode < sizeof( s_ScancodeTable ) / sizeof( s_ScancodeTable[0] ) ) + { + return s_ScancodeTable[ nScancode ]; + } + return KEY_RESERVED; +} + +static inline int SDLButtonToLinuxButton( int SDLButton ) +{ + switch ( SDLButton ) + { + case SDL_BUTTON_LEFT: return BTN_LEFT; + case SDL_BUTTON_MIDDLE: return BTN_MIDDLE; + case SDL_BUTTON_RIGHT: return BTN_RIGHT; + case SDL_BUTTON_X1: return BTN_FORWARD; + case SDL_BUTTON_X2: return BTN_BACK; + default: return 0; + } +} + +void updateOutputRefresh( void ) +{ + int display_index = 0; + SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; + + display_index = SDL_GetWindowDisplayIndex( g_SDLWindow ); + if ( SDL_GetDesktopDisplayMode( display_index, &mode ) == 0 ) + { + g_nOutputRefresh = mode.refresh_rate; + } +} + +void inputSDLThreadRun( void ) +{ + // see wlroots xwayland startup and how wl_event_loop_add_signal works + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + sigprocmask(SIG_BLOCK, &mask, NULL); + + SDL_Event event; + SDL_Keymod mod; + uint32_t key; + static bool bFullscreen = false; + + SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS ); + + g_unSDLUserEventID = SDL_RegisterEvents( 1 ); + + g_SDLUserEvent.type = g_unSDLUserEventID; + g_SDLUserEvent.user.code = 32; + + uint32_t nSDLWindowFlags = SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE; + + if ( g_bBorderlessOutputWindow == true ) + { + nSDLWindowFlags |= SDL_WINDOW_BORDERLESS; + } + + g_SDLWindow = SDL_CreateWindow( "gamescope", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + g_nOutputWidth, + g_nOutputHeight, + nSDLWindowFlags ); + + if ( g_SDLWindow == nullptr ) + { + g_SDLInitLock.unlock(); + return; + } + + unsigned int extCount = 0; + SDL_Vulkan_GetInstanceExtensions( g_SDLWindow, &extCount, nullptr ); + + g_vecSDLInstanceExts.resize( extCount ); + + SDL_Vulkan_GetInstanceExtensions( g_SDLWindow, &extCount, g_vecSDLInstanceExts.data() ); + + SDL_SetRelativeMouseMode(SDL_TRUE); + + g_bSDLInitOK = true; + g_SDLInitLock.unlock(); + + while( SDL_WaitEvent( &event ) ) + { + switch( event.type ) + { + case SDL_MOUSEMOTION: + wlserver_lock(); + wlserver_mousemotion( event.motion.xrel, event.motion.yrel, event.motion.timestamp ); + wlserver_unlock(); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + wlserver_lock(); + wlserver_mousebutton( SDLButtonToLinuxButton( event.button.button ), + event.button.state == SDL_PRESSED, + event.button.timestamp ); + wlserver_unlock(); + break; + case SDL_MOUSEWHEEL: + wlserver_lock(); + wlserver_mousewheel( -event.wheel.x, -event.wheel.y, event.wheel.timestamp ); + wlserver_unlock(); + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + mod = SDL_GetModState(); + key = SDLScancodeToLinuxKey( event.key.keysym.scancode ); + + if ( event.type == SDL_KEYUP && mod & KMOD_LGUI ) + { + switch ( key ) + { + case KEY_F: + bFullscreen = !bFullscreen; + SDL_SetWindowFullscreen( g_SDLWindow, bFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 ); + break; + case KEY_N: + g_bFilterGameWindow = !g_bFilterGameWindow; + break; + case KEY_S: + g_bTakeScreenshot = true; + break; + default: + goto client; + + } + break; + } +client: + wlserver_lock(); + wlserver_key( key, event.type == SDL_KEYDOWN, event.key.timestamp ); + wlserver_unlock(); + break; + case SDL_WINDOWEVENT: + switch( event.window.event ) + { + default: + break; + case SDL_WINDOWEVENT_MOVED: + case SDL_WINDOWEVENT_SHOWN: + updateOutputRefresh(); + break; + case SDL_WINDOWEVENT_SIZE_CHANGED: + g_nOutputWidth = event.window.data1; + g_nOutputHeight = event.window.data2; + + updateOutputRefresh(); + + break; + } + break; + default: + break; + } + } +} + +bool sdlwindow_init( void ) +{ + g_SDLInitLock.lock(); + + std::thread inputSDLThread( inputSDLThreadRun ); + inputSDLThread.detach(); + + // When this returns SDL_Init should be over + g_SDLInitLock.lock(); + + return g_bSDLInitOK; +} + +void sdlwindow_update( void ) +{ + SDL_PushEvent( &g_SDLUserEvent ); +} diff --git a/src/sdlwindow.hpp b/src/sdlwindow.hpp new file mode 100644 index 0000000..2d4ae36 --- /dev/null +++ b/src/sdlwindow.hpp @@ -0,0 +1,13 @@ +// For the nested case, manages SDL window for input/output + +#pragma once + +#include +#include + +bool sdlwindow_init( void ); + +// called from other threads with interesting things have happened with clients that might warrant updating the nested window +void sdlwindow_update( void ); + +extern SDL_Window *g_SDLWindow;