X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=vid_sdl.c;h=065c4607b011026a7ed4f4a4277dd06d319c3f69;hb=fbdc89dc46526ae72e8497433560bdaa8f42367c;hp=b88e6ecb5a8afb55741a0529e9738d7d648027d5;hpb=d1c3f1065fde02ed39b7eecc2d9b9a637388d091;p=xonotic%2Fdarkplaces.git diff --git a/vid_sdl.c b/vid_sdl.c index b88e6ecb..065c4607 100644 --- a/vid_sdl.c +++ b/vid_sdl.c @@ -30,17 +30,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include -static cvar_t apple_mouse_noaccel = {CVAR_CLIENT | CVAR_SAVE, "apple_mouse_noaccel", "1", "disables mouse acceleration while DarkPlaces is active"}; -static qboolean vid_usingnoaccel; +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 120000) + #define IOMainPort IOMasterPort +#endif +static cvar_t apple_mouse_noaccel = {CF_CLIENT | CF_ARCHIVE, "apple_mouse_noaccel", "1", "disables mouse acceleration while DarkPlaces is active"}; +static qbool vid_usingnoaccel; static double originalMouseSpeed = -1.0; -io_connect_t IN_GetIOHandle(void) +static io_connect_t IN_GetIOHandle(void) { io_connect_t iohandle = MACH_PORT_NULL; kern_return_t status; io_service_t iohidsystem = MACH_PORT_NULL; mach_port_t masterport; - status = IOMasterPort(MACH_PORT_NULL, &masterport); + status = IOMainPort(MACH_PORT_NULL, &masterport); if(status != KERN_SUCCESS) return 0; @@ -63,17 +66,16 @@ io_connect_t IN_GetIOHandle(void) // Tell startup code that we have a client int cl_available = true; -qboolean vid_supportrefreshrate = false; +qbool vid_supportrefreshrate = false; -static qboolean vid_usingmouse = false; -static qboolean vid_usingmouse_relativeworks = false; // SDL2 workaround for unimplemented RelativeMouse mode -static qboolean vid_usinghidecursor = false; -static qboolean vid_hasfocus = false; -static qboolean vid_isfullscreen; -static qboolean vid_usingvsync = false; +static qbool vid_usingmouse = false; +static qbool vid_usingmouse_relativeworks = false; // SDL2 workaround for unimplemented RelativeMouse mode +static qbool vid_usinghidecursor = false; +static qbool vid_hasfocus = false; +static qbool vid_usingvsync = false; static SDL_Joystick *vid_sdljoystick = NULL; static SDL_GameController *vid_sdlgamecontroller = NULL; -static cvar_t joy_sdl2_trigger_deadzone = {CVAR_SAVE | CVAR_CLIENT, "joy_sdl2_trigger_deadzone", "0.5", "deadzone for triggers to be registered as key presses"}; +static cvar_t joy_sdl2_trigger_deadzone = {CF_ARCHIVE | CF_CLIENT, "joy_sdl2_trigger_deadzone", "0.5", "deadzone for triggers to be registered as key presses"}; // GAME_STEELSTORM specific static cvar_t *steelstorm_showing_map = NULL; // detect but do not create the cvar static cvar_t *steelstorm_showing_mousecursor = NULL; // detect but do not create the cvar @@ -97,7 +99,8 @@ static int MapKey( unsigned int sdlkey ) { switch(sdlkey) { - default: return 0; + // sdlkey can be Unicode codepoint for non-ascii keys, which are valid + default: return sdlkey & SDLK_SCANCODE_MASK ? 0 : sdlkey; // case SDLK_UNKNOWN: return K_UNKNOWN; case SDLK_RETURN: return K_ENTER; case SDLK_ESCAPE: return K_ESCAPE; @@ -341,12 +344,12 @@ static int MapKey( unsigned int sdlkey ) } } -qboolean VID_HasScreenKeyboardSupport(void) +qbool VID_HasScreenKeyboardSupport(void) { return SDL_HasScreenKeyboardSupport() != SDL_FALSE; } -void VID_ShowKeyboard(qboolean show) +void VID_ShowKeyboard(qbool show) { if (!SDL_HasScreenKeyboardSupport()) return; @@ -363,25 +366,25 @@ void VID_ShowKeyboard(qboolean show) } } -qboolean VID_ShowingKeyboard(void) +qbool VID_ShowingKeyboard(void) { return SDL_IsTextInputActive() != 0; } -void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor) +void VID_SetMouse(qbool relative, qbool hidecursor) { #ifndef DP_MOBILETOUCH #ifdef MACOSX if(relative) if(vid_usingmouse && (vid_usingnoaccel != !!apple_mouse_noaccel.integer)) - VID_SetMouse(false, false, false); // ungrab first! + VID_SetMouse(false, false); // ungrab first! #endif if (vid_usingmouse != relative) { vid_usingmouse = relative; cl_ignoremousemoves = 2; vid_usingmouse_relativeworks = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0; -// Con_Printf("VID_SetMouse(%i, %i, %i) relativeworks = %i\n", (int)fullscreengrab, (int)relative, (int)hidecursor, (int)vid_usingmouse_relativeworks); +// Con_Printf("VID_SetMouse(%i, %i) relativeworks = %i\n", (int)relative, (int)hidecursor, (int)vid_usingmouse_relativeworks); #ifdef MACOSX if(relative) { @@ -455,14 +458,14 @@ float multitouch[MAXFINGERS][3]; int multitouchs[MAXFINGERS]; // modified heavily by ELUAN -static qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth, float pheight, const char *icon, float textheight, const char *text, float *resultmove, qboolean *resultbutton, keynum_t key, const char *typedtext, float deadzone, float oversizepixels_x, float oversizepixels_y, qboolean iamexclusive) +static qbool VID_TouchscreenArea(int corner, float px, float py, float pwidth, float pheight, const char *icon, float textheight, const char *text, float *resultmove, qbool *resultbutton, keynum_t key, const char *typedtext, float deadzone, float oversizepixels_x, float oversizepixels_y, qbool iamexclusive) { int finger; float fx, fy, fwidth, fheight; float overfx, overfy, overfwidth, overfheight; float rel[3]; float sqsum; - qboolean button = false; + qbool button = false; VectorClear(rel); if (pwidth > 0 && pheight > 0) { @@ -568,11 +571,11 @@ static qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth // ELUAN: // not reentrant, but we only need one mouse cursor anyway... -static void VID_TouchscreenCursor(float px, float py, float pwidth, float pheight, qboolean *resultbutton, keynum_t key) +static void VID_TouchscreenCursor(float px, float py, float pwidth, float pheight, qbool *resultbutton, keynum_t key) { int finger; float fx, fy, fwidth, fheight; - qboolean button = false; + qbool button = false; static int cursorfinger = -1; static int cursorfreemovement = false; static int canclick = false; @@ -761,8 +764,8 @@ static void IN_Move_TouchScreen_SteelStorm(void) int i, numfingers; float xscale, yscale; float move[3], aim[3]; - static qboolean oldbuttons[128]; - static qboolean buttons[128]; + static qbool oldbuttons[128]; + static qbool buttons[128]; keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest; memcpy(oldbuttons, buttons, sizeof(oldbuttons)); memset(multitouchs, 0, sizeof(multitouchs)); @@ -874,8 +877,8 @@ static void IN_Move_TouchScreen_Quake(void) { int x, y; float move[3], aim[3], click[3]; - static qboolean oldbuttons[128]; - static qboolean buttons[128]; + static qbool oldbuttons[128]; + static qbool buttons[128]; keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest; memcpy(oldbuttons, buttons, sizeof(oldbuttons)); memset(multitouchs, 0, sizeof(multitouchs)); @@ -894,7 +897,7 @@ static void IN_Move_TouchScreen_Quake(void) if (!VID_ShowingKeyboard()) { // user entered a command, close the console now - Con_ToggleConsole_f(&cmd_client); + Con_ToggleConsole_f(cmd_local); } VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[15], (keynum_t)0, NULL, 0, 0, 0, true); VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, move, &buttons[0], K_MOUSE4, NULL, 0, 0, 0, true); @@ -944,7 +947,7 @@ void IN_Move( void ) static int old_x = 0, old_y = 0; static int stuck = 0; static keydest_t oldkeydest; - static qboolean oldshowkeyboard; + static qbool oldshowkeyboard; int x, y; vid_joystate_t joystate; keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest; @@ -1022,7 +1025,7 @@ void IN_Move( void ) //// #ifdef SDL_R_RESTART -static qboolean sdl_needs_restart; +static qbool sdl_needs_restart; static void sdl_start(void) { } @@ -1060,10 +1063,11 @@ static keynum_t buttonremap[] = // SDL2 void Sys_SendKeyEvents( void ) { - static qboolean sound_active = true; + static qbool sound_active = true; int keycode; int i; - qboolean isdown; + const char *chp; + qbool isdown; Uchar unicode; SDL_Event event; @@ -1076,7 +1080,7 @@ void Sys_SendKeyEvents( void ) #ifdef DEBUGSDLEVENTS Con_DPrintf("SDL_Event: SDL_QUIT\n"); #endif - Sys_Quit(0); + host.state = host_shutdown; break; case SDL_KEYDOWN: case SDL_KEYUP: @@ -1179,7 +1183,7 @@ void Sys_SendKeyEvents( void ) // so, let's better queue it for next frame if(!sdl_needs_restart) { - Cbuf_AddText(&cmd_client, "\nr_restart\n"); + Cbuf_AddText(cmd_local, "\nr_restart\n"); sdl_needs_restart = true; } #endif @@ -1202,7 +1206,7 @@ void Sys_SendKeyEvents( void ) vid_hasfocus = false; break; case SDL_WINDOWEVENT_CLOSE: - Sys_Quit(0); + host.state = host_shutdown; break; } } @@ -1219,9 +1223,14 @@ void Sys_SendKeyEvents( void ) #endif // convert utf8 string to char // NOTE: this code is supposed to run even if utf8enable is 0 - unicode = u8_getchar_utf8_enabled(event.text.text + (int)u8_bytelen(event.text.text, 0), NULL); - Key_Event(K_TEXT, unicode, true); - Key_Event(K_TEXT, unicode, false); + chp = event.text.text; + while (*chp != 0) + { + // input the chars one by one (there can be multiple chars when e.g. using an "input method") + unicode = u8_getchar_utf8_enabled(chp, &chp); + Key_Event(K_TEXT, unicode, true); + Key_Event(K_TEXT, unicode, false); + } break; case SDL_MOUSEMOTION: break; @@ -1311,12 +1320,12 @@ void *GL_GetProcAddress(const char *name) return p; } -qboolean GL_ExtensionSupported(const char *name) +qbool GL_ExtensionSupported(const char *name) { return SDL_GL_ExtensionSupported(name); } -static qboolean vid_sdl_initjoysticksystem = false; +static qbool vid_sdl_initjoysticksystem = false; void VID_Init (void) { @@ -1339,15 +1348,14 @@ void VID_Init (void) vid_sdl_initjoysticksystem = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0; if (!vid_sdl_initjoysticksystem) Con_Printf(CON_ERROR "Failed to init SDL joystick subsystem: %s\n", SDL_GetError()); - vid_isfullscreen = false; } static int vid_sdljoystickindex = -1; -void VID_EnableJoystick(qboolean enable) +void VID_EnableJoystick(qbool enable) { int index = joy_enable.integer > 0 ? joy_index.integer : -1; int numsdljoysticks; - qboolean success = false; + qbool success = false; int sharedcount = 0; int sdlindex = -1; sharedcount = VID_Shared_SetJoystick(index); @@ -1462,22 +1470,17 @@ static void AdjustWindowBounds(viddef_mode_t *mode, RECT *rect) } #endif -extern cvar_t gl_info_vendor; -extern cvar_t gl_info_renderer; -extern cvar_t gl_info_version; -extern cvar_t gl_info_platform; -extern cvar_t gl_info_driver; - -static qboolean VID_InitModeGL(viddef_mode_t *mode) +static qbool VID_InitModeGL(viddef_mode_t *mode) { int windowflags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL; // currently SDL_WINDOWPOS_UNDEFINED behaves exactly like SDL_WINDOWPOS_CENTERED, this might change some day // https://trello.com/c/j56vUcwZ/81-centered-vs-undefined-window-position int xPos = SDL_WINDOWPOS_UNDEFINED; int yPos = SDL_WINDOWPOS_UNDEFINED; -#ifndef USE_GLES2 int i; - const char *drivername; +#ifndef USE_GLES2 + // SDL usually knows best + const char *drivername = NULL; #endif win_half_width = mode->width>>1; @@ -1489,11 +1492,8 @@ static qboolean VID_InitModeGL(viddef_mode_t *mode) VID_OutputVersion(); #ifndef USE_GLES2 - // SDL usually knows best - drivername = NULL; - // COMMANDLINEOPTION: SDL GL: -gl_driver selects a GL driver library, default is whatever SDL recommends, useful only for 3dfxogl.dll/3dfxvgl.dll or fxmesa or similar, if you don't know what this is for, you don't need it - i = COM_CheckParm("-gl_driver"); + i = Sys_CheckParm("-gl_driver"); if (i && i < sys.argc - 1) drivername = sys.argv[i + 1]; if (SDL_GL_LoadLibrary(drivername) < 0) @@ -1510,40 +1510,41 @@ static qboolean VID_InitModeGL(viddef_mode_t *mode) windowflags |= SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS; #endif - vid_isfullscreen = false; + + if (mode->fullscreen) { - if (mode->fullscreen) { - if (vid_desktopfullscreen.integer) - { - vid_mode_t *m = VID_GetDesktopMode(); - mode->width = m->width; - mode->height = m->height; - windowflags |= SDL_WINDOW_FULLSCREEN_DESKTOP; - } - else - windowflags |= SDL_WINDOW_FULLSCREEN; - vid_isfullscreen = true; + if (vid_desktopfullscreen.integer) + { + vid_mode_t *m = VID_GetDesktopMode(); + mode->width = m->width; + mode->height = m->height; + windowflags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } - else { - if (vid_borderless.integer) - windowflags |= SDL_WINDOW_BORDERLESS; + else + windowflags |= SDL_WINDOW_FULLSCREEN; + } + else + { + if (vid_borderless.integer) + windowflags |= SDL_WINDOW_BORDERLESS; #ifdef WIN32 - if (vid_ignore_taskbar.integer) { - xPos = SDL_WINDOWPOS_CENTERED; - yPos = SDL_WINDOWPOS_CENTERED; - } - else { - RECT rect; - AdjustWindowBounds(mode, &rect); - xPos = rect.left; - yPos = rect.top; - } -#endif + if (vid_ignore_taskbar.integer) + { + xPos = SDL_WINDOWPOS_CENTERED; + yPos = SDL_WINDOWPOS_CENTERED; + } + else + { + RECT rect; + AdjustWindowBounds(mode, &rect); + xPos = rect.left; + yPos = rect.top; } +#endif } - //flags |= SDL_HWSURFACE; - if (vid_mouse_clickthrough.integer && !vid_isfullscreen) + + if (vid_mouse_clickthrough.integer) SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1"); SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); @@ -1569,6 +1570,9 @@ static qboolean VID_InitModeGL(viddef_mode_t *mode) SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + /* Requesting a Core profile and 3.2 minimum is mandatory on macOS and older Mesa drivers. + * It works fine on other drivers too except NVIDIA, see HACK below. + */ #endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, (gl_debug.integer > 0 ? SDL_GL_CONTEXT_DEBUG_FLAG : 0)); @@ -1591,10 +1595,39 @@ static qboolean VID_InitModeGL(viddef_mode_t *mode) return false; } + GL_InitFunctions(); + +#if !defined(USE_GLES2) && !defined(MACOSX) + // NVIDIA hates the Core profile and limits the version to the minimum we specified. + // HACK: to detect NVIDIA we first need a context, fortunately replacing it takes a few milliseconds + gl_vendor = (const char *)qglGetString(GL_VENDOR); + if (strncmp(gl_vendor, "NVIDIA", 6) == 0) + { + Con_DPrint("The Way It's Meant To Be Played: replacing OpenGL Core profile with Compatibility profile...\n"); + SDL_GL_DeleteContext(context); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); + context = SDL_GL_CreateContext(window); + if (context == NULL) + { + Con_Printf(CON_ERROR "Failed to initialize OpenGL context: %s\n", SDL_GetError()); + VID_Shutdown(); + return false; + } + } +#endif + SDL_GL_SetSwapInterval(bound(-1, vid_vsync.integer, 1)); vid_usingvsync = (vid_vsync.integer != 0); - gl_platform = "SDL"; + vid_hidden = false; + vid_activewindow = true; + vid_hasfocus = true; + vid_usingmouse = false; + vid_usinghidecursor = false; + + // clear to black (loading plaque will be seen over this) + GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0); + VID_Finish(); // checks vid_hidden GL_Setup(); @@ -1602,36 +1635,13 @@ static qboolean VID_InitModeGL(viddef_mode_t *mode) Cvar_SetQuick(&gl_info_vendor, gl_vendor); Cvar_SetQuick(&gl_info_renderer, gl_renderer); Cvar_SetQuick(&gl_info_version, gl_version); - Cvar_SetQuick(&gl_info_platform, gl_platform ? gl_platform : ""); - Cvar_SetQuick(&gl_info_driver, gl_driver); - - // LadyHavoc: report supported extensions -#ifdef CONFIG_MENU - Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions); -#else - Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions); -#endif - - // clear to black (loading plaque will be seen over this) - GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 0); + Cvar_SetQuick(&gl_info_platform, "SDL"); + Cvar_SetQuick(&gl_info_driver, drivername ? drivername : ""); - vid_hidden = false; - vid_activewindow = false; - vid_hasfocus = true; - vid_usingmouse = false; - vid_usinghidecursor = false; - return true; } -extern cvar_t gl_info_extensions; -extern cvar_t gl_info_vendor; -extern cvar_t gl_info_renderer; -extern cvar_t gl_info_version; -extern cvar_t gl_info_platform; -extern cvar_t gl_info_driver; - -qboolean VID_InitMode(viddef_mode_t *mode) +qbool VID_InitMode(viddef_mode_t *mode) { // GAME_STEELSTORM specific steelstorm_showing_map = Cvar_FindVar(&cvars_all, "steelstorm_showing_map", ~0); @@ -1647,21 +1657,19 @@ qboolean VID_InitMode(viddef_mode_t *mode) void VID_Shutdown (void) { VID_EnableJoystick(false); - VID_SetMouse(false, false, false); + VID_SetMouse(false, false); + SDL_GL_DeleteContext(context); + context = NULL; SDL_DestroyWindow(window); window = NULL; SDL_QuitSubSystem(SDL_INIT_VIDEO); - - gl_driver[0] = 0; - gl_extensions = ""; - gl_platform = ""; } void VID_Finish (void) { - qboolean vid_usevsync; + qbool vid_usevsync; vid_activewindow = !vid_hidden && vid_hasfocus; VID_UpdateGamma();