sdlwindow: put all the SDL I/O code in the same spot.

This commit is contained in:
Pierre-Loup A. Griffais 2020-09-01 21:36:48 -07:00
parent 81b8e8c33c
commit 79cb130dcc
8 changed files with 226 additions and 205 deletions

View file

@ -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 : [

View file

@ -1,5 +0,0 @@
// For the nested case, reads input from the SDL window and send to wayland
#pragma once
bool inputsdl_init( void );

View file

@ -3,6 +3,7 @@
#include <thread>
#include <mutex>
#include <vector>
#include <cstring>
#include <unistd.h>
@ -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
{

View file

@ -1,7 +1,4 @@
#include <SDL.h>
#include <SDL_vulkan.h>
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;

View file

@ -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;

View file

@ -1,22 +1,4 @@
// For the nested case, reads input from the SDL window and send to wayland
#include <thread>
#include <mutex>
#include <signal.h>
#include <linux/input-event-codes.h>
#include <SDL.h>
#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;
}

204
src/sdlwindow.cpp Normal file
View file

@ -0,0 +1,204 @@
// For the nested case, reads input from the SDL window and send to wayland
#include <thread>
#include <mutex>
#include <signal.h>
#include <linux/input-event-codes.h>
#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 );
}

13
src/sdlwindow.hpp Normal file
View file

@ -0,0 +1,13 @@
// For the nested case, manages SDL window for input/output
#pragma once
#include <SDL.h>
#include <SDL_vulkan.h>
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;