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_isfullscreen;
static qbool vid_usingvsync = false;
static SDL_Joystick *vid_sdljoystick = NULL;
static SDL_GameController *vid_sdlgamecontroller = NULL;
static int win_half_width = 50;
static int win_half_height = 50;
-static int video_bpp;
static SDL_GLContext context;
static SDL_Window *window;
-static int window_flags;
-static vid_mode_t desktop_mode;
// Input handling
{
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;
#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)
{
};
//#define DEBUGSDLEVENTS
-
-// SDL2
-void Sys_SendKeyEvents( void )
+void Sys_SDL_HandleEvents(void)
{
static qbool sound_active = true;
int keycode;
int i;
+ const char *chp;
qbool isdown;
Uchar unicode;
SDL_Event event;
#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;
return SDL_GL_ExtensionSupported(name);
}
-static qbool vid_sdl_initjoysticksystem = false;
-
void VID_Init (void)
{
#ifndef __IPHONEOS__
if (SDL_Init(SDL_INIT_VIDEO) < 0)
Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError());
- vid_sdl_initjoysticksystem = SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0;
- if (!vid_sdl_initjoysticksystem)
+ if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
Con_Printf(CON_ERROR "Failed to init SDL joystick subsystem: %s\n", SDL_GetError());
- vid_isfullscreen = false;
}
static int vid_sdljoystickindex = -1;
}
#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 qbool VID_InitModeGL(viddef_mode_t *mode)
{
int windowflags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL;
int yPos = SDL_WINDOWPOS_UNDEFINED;
int i;
#ifndef USE_GLES2
- const char *drivername;
+ // SDL usually knows best
+ const char *drivername = NULL;
#endif
win_half_width = mode->width>>1;
VID_OutputVersion();
#ifndef USE_GLES2
- // SDL usually knows best
- drivername = NULL;
-
// COMMANDLINEOPTION: SDL GL: -gl_driver <drivername> 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 = Sys_CheckParm("-gl_driver");
if (i && i < sys.argc - 1)
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);
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));
- video_bpp = mode->bitsperpixel;
- window_flags = windowflags;
window = SDL_CreateWindow(gamename, xPos, yPos, mode->width, mode->height, windowflags);
if (window == NULL)
{
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();
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
- Con_DPrintf("\nQuakeC extensions for server and client:");
- for (i = 0; vm_sv_extensions[i]; i++)
- Con_DPrintf(" %s", vm_sv_extensions[i]);
- Con_DPrintf("\n");
-#ifdef CONFIG_MENU
- Con_DPrintf("\nQuakeC extensions for menu:");
- for (i = 0; vm_m_extensions[i]; i++)
- Con_DPrintf(" %s", vm_m_extensions[i]);
- Con_DPrintf("\n");
-#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;
-
qbool VID_InitMode(viddef_mode_t *mode)
{
// GAME_STEELSTORM specific
VID_EnableJoystick(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)
}
}
-vid_mode_t *VID_GetDesktopMode(void)
+vid_mode_t VID_GetDesktopMode(void)
{
SDL_DisplayMode mode;
int bpp;
Uint32 rmask, gmask, bmask, amask;
+ vid_mode_t desktop_mode;
+
SDL_GetDesktopDisplayMode(0, &mode);
SDL_PixelFormatEnumToMasks(mode.format, &bpp, &rmask, &gmask, &bmask, &amask);
desktop_mode.width = mode.w;
// TODO check whether this actually works, or whether we do still need
// a read-window-size-after-entering-desktop-fullscreen hack for
// multiscreen setups.
- return &desktop_mode;
+ return desktop_mode;
}
size_t VID_ListModes(vid_mode_t *modes, size_t maxcount)