diff options
author | Andrey Nazarov <skuller@skuller.net> | 2012-10-19 18:00:16 +0400 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2012-10-20 16:32:20 +0400 |
commit | caa491ceaa1c3c957a0d35b1e47eea345f2c5f70 (patch) | |
tree | cc20054b86400a66682bc43282c7ea8f1fceaab9 | |
parent | cf94d68530dc5fbfb855a687687c69d56e6e1c05 (diff) |
Improve SDL video code, add swap interval support.
Split video.c into multiple files. Implement support for
GLX_EXT_swap_control(_tear) extensions. Work around a bug in NVIDIA
binary driver causing glXWaitVideoSyncSGI to block indefinitely when
vsync in enabled. Permit negative values for ‘gl_swapinterval’ only if
GLX_EXT_swap_control_tear extension is advertised.
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | src/unix/sdl/clipboard.c | 102 | ||||
-rw-r--r-- | src/unix/sdl/glimp.c | 166 | ||||
-rw-r--r-- | src/unix/sdl/glx.c | 209 | ||||
-rw-r--r-- | src/unix/sdl/swimp.c | 80 | ||||
-rw-r--r-- | src/unix/sdl/video.c | 459 | ||||
-rw-r--r-- | src/unix/sdl/video.h | 48 |
7 files changed, 628 insertions, 446 deletions
@@ -473,12 +473,22 @@ else CFLAGS_c += -DUSE_SDL=1 $(SDL_CFLAGS) LIBS_c += $(SDL_LIBS) OBJS_c += src/unix/sdl/video.o + OBJS_c += src/unix/sdl/clipboard.o + + ifdef CONFIG_SOFTWARE_RENDERER + OBJS_c += src/unix/sdl/swimp.o + else + OBJS_c += src/unix/sdl/glimp.o + endif ifdef CONFIG_X11 X11_CFLAGS ?= X11_LIBS ?= -lX11 CFLAGS_c += -DUSE_X11=1 $(X11_CFLAGS) LIBS_c += $(X11_LIBS) + ifndef CONFIG_SOFTWARE_RENDERER + OBJS_c += src/unix/sdl/glx.o + endif endif ifdef CONFIG_DIRECT_INPUT diff --git a/src/unix/sdl/clipboard.c b/src/unix/sdl/clipboard.c new file mode 100644 index 0000000..53728f7 --- /dev/null +++ b/src/unix/sdl/clipboard.c @@ -0,0 +1,102 @@ +/* +Copyright (C) 2003-2012 Andrey Nazarov + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "video.h" + +#if USE_X11 +#include <SDL_syswm.h> +#include <X11/Xutil.h> +#endif + +/* +================= +VID_GetClipboardData +================= +*/ +char *VID_GetClipboardData(void) +{ +#if USE_X11 + SDL_SysWMinfo info; + Display *dpy; + Window win, sowner; + Atom type, property; + unsigned long len, bytes_left; + unsigned char *data; + int format, result; + char *ret; + + SDL_VERSION(&info.version); + if (!SDL_GetWMInfo(&info)) { + return NULL; + } + + if (info.subsystem != SDL_SYSWM_X11) { + return NULL; + } + + dpy = info.info.x11.display; + win = info.info.x11.window; + + if (!dpy) { + return NULL; + } + + sowner = XGetSelectionOwner(dpy, XA_PRIMARY); + if (sowner == None) { + return NULL; + } + + property = XInternAtom(dpy, "GETCLIPBOARDDATA_PROP", False); + + XConvertSelection(dpy, XA_PRIMARY, XA_STRING, property, win, CurrentTime); + + XSync(dpy, False); + + result = XGetWindowProperty(dpy, win, property, 0, 0, False, + AnyPropertyType, &type, &format, &len, &bytes_left, &data); + + if (result != Success) { + return NULL; + } + + ret = NULL; + if (bytes_left) { + result = XGetWindowProperty(dpy, win, property, 0, bytes_left, True, + AnyPropertyType, &type, &format, &len, &bytes_left, &data); + if (result == Success) { + ret = Z_CopyString((char *)data); + } + } + + XFree(data); + + return ret; +#else + return NULL; +#endif +} + +/* +================= +VID_SetClipboardData +================= +*/ +void VID_SetClipboardData(const char *data) +{ +} + diff --git a/src/unix/sdl/glimp.c b/src/unix/sdl/glimp.c new file mode 100644 index 0000000..eba0386 --- /dev/null +++ b/src/unix/sdl/glimp.c @@ -0,0 +1,166 @@ +/* +Copyright (C) 2003-2012 Andrey Nazarov + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "video.h" + +#if USE_X11 +void VID_GLX_SurfaceChanged(void); +#endif + +void VID_SDL_SurfaceChanged(void) +{ + int accel; + + SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &accel); + if (accel) { + sdl.flags |= QVF_ACCELERATED; + } + +#if USE_X11 + VID_GLX_SurfaceChanged(); +#endif +} + +#ifdef __OpenBSD__ +#define LIBGL "libGL.so" +#else +#define LIBGL "libGL.so.1" +#endif + +qboolean VID_Init(void) +{ + cvar_t *gl_driver; + cvar_t *gl_colorbits; + cvar_t *gl_depthbits; + cvar_t *gl_stencilbits; + char *s; + int colorbits; + int depthbits; + int stencilbits; + + if (!VID_SDL_Init()) { + return qfalse; + } + + gl_driver = Cvar_Get("gl_driver", LIBGL, CVAR_REFRESH); + gl_colorbits = Cvar_Get("gl_colorbits", "0", CVAR_REFRESH); + gl_depthbits = Cvar_Get("gl_depthbits", "0", CVAR_REFRESH); + gl_stencilbits = Cvar_Get("gl_stencilbits", "8", CVAR_REFRESH); + + // don't allow absolute or relative paths + FS_SanitizeFilenameVariable(gl_driver); + + while (1) { + // ugly hack to work around brain-dead servers that actively + // check and enforce `gl_driver' cvar to `opengl32', unaware + // of other systems than Windows + s = gl_driver->string; + if (!Q_stricmp(s, "opengl32") || !Q_stricmp(s, "opengl32.dll")) { + Com_Printf("...attempting to load %s instead of %s\n", + gl_driver->default_string, s); + s = gl_driver->default_string; + } + + if (SDL_GL_LoadLibrary(s) == 0) { + break; + } + + Com_EPrintf("Couldn't load OpenGL library: %s\n", SDL_GetError()); + if (!strcmp(s, gl_driver->default_string)) { + goto fail; + } + + // attempt to recover + Com_Printf("...falling back to %s\n", gl_driver->default_string); + Cvar_Reset(gl_driver); + } + + colorbits = Cvar_ClampInteger(gl_colorbits, 0, 32); + depthbits = Cvar_ClampInteger(gl_depthbits, 0, 32); + stencilbits = Cvar_ClampInteger(gl_stencilbits, 0, 8); + + if (colorbits == 0) + colorbits = 24; + + if (depthbits == 0) + depthbits = colorbits > 16 ? 24 : 16; + + if (depthbits < 24) + stencilbits = 0; + + if (colorbits > 16) { + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + } else { + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + } + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthbits); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilbits); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + if (!VID_SDL_SetMode(SDL_OPENGL | SDL_RESIZABLE, 0)) { + Com_EPrintf("Couldn't set video mode: %s\n", SDL_GetError()); + goto fail; + } + + return qtrue; + +fail: + VID_SDL_Shutdown(); + return qfalse; +} + +#if !USE_X11 + +void VID_Shutdown(void) +{ + VID_SDL_Shutdown(); +} + +void VID_VideoWait(void) +{ +} + +qboolean VID_VideoSync(void) +{ + return qtrue; +} + +void VID_BeginFrame(void) +{ +} + +void VID_EndFrame(void) +{ + SDL_GL_SwapBuffers(); +} +#endif + +void *VID_GetCoreAddr(const char *sym) +{ + return SDL_GL_GetProcAddress(sym); +} + +void *VID_GetProcAddr(const char *sym) +{ + return SDL_GL_GetProcAddress(sym); +} + diff --git a/src/unix/sdl/glx.c b/src/unix/sdl/glx.c new file mode 100644 index 0000000..4c300c7 --- /dev/null +++ b/src/unix/sdl/glx.c @@ -0,0 +1,209 @@ +/* +Copyright (C) 2003-2012 Andrey Nazarov + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +// +// glx.c -- support for GLX extensions +// + +#include "video.h" +#include <SDL_syswm.h> +#include <GL/glx.h> +#include <GL/glxext.h> + +#define QGLX_EXT_swap_control (1<<0) +#define QGLX_EXT_swap_control_tear (1<<1) +#define QGLX_SGI_video_sync (1<<2) + +// for debugging +#define SHOW_SYNC() \ + Com_DDDDPrintf("%s: %u\n", __func__, glx_sync_count) + +static const char *(*qglXQueryExtensionsString)(Display *, int); +static GLXDrawable (*qglXGetCurrentDrawable)(void); +static int (*qglXSwapIntervalEXT)(Display *, GLXDrawable, int); +static int (*qglXGetVideoSyncSGI)(unsigned int *); +static int (*qglXWaitVideoSyncSGI)(int, int, unsigned int *); + +static Display *glx_dpy; +static unsigned glx_extensions; +static unsigned glx_sync_count; + +static cvar_t *gl_swapinterval; +static cvar_t *gl_video_sync; + +static unsigned GLX_ParseExtensionString(const char *s) +{ + static const char *const extnames[] = { + "GLX_EXT_swap_control", + "GLX_EXT_swap_control_tear", + "GLX_SGI_video_sync", + NULL + }; + + return Com_ParseExtensionString(s, extnames); +} + +static void gl_swapinterval_changed(cvar_t *self) +{ + int drawable; + + if (!qglXSwapIntervalEXT) + return; + if (!qglXGetCurrentDrawable) + return; + + drawable = qglXGetCurrentDrawable(); + if (!drawable) + return; + + if (self->integer < 0 && !(glx_extensions & QGLX_EXT_swap_control_tear)) { + Com_Printf("Negative swap interval is not supported on this system.\n"); + Cvar_Reset(self); + } + + qglXSwapIntervalEXT(glx_dpy, drawable, self->integer); +} + +void VID_GLX_SurfaceChanged(void) +{ + SDL_SysWMinfo info; + const char *extensions; + + SDL_VERSION(&info.version); + if (!SDL_GetWMInfo(&info)) + return; + + if (info.subsystem != SDL_SYSWM_X11) + return; + + glx_dpy = info.info.x11.display; + if (!glx_dpy) + return; + + gl_swapinterval = Cvar_Get("gl_swapinterval", "1", CVAR_ARCHIVE); + gl_video_sync = Cvar_Get("gl_video_sync", "1", CVAR_REFRESH); + + qglXQueryExtensionsString = SDL_GL_GetProcAddress("glXQueryExtensionsString"); + qglXGetCurrentDrawable = SDL_GL_GetProcAddress("glXGetCurrentDrawable"); + + if (qglXQueryExtensionsString) + extensions = qglXQueryExtensionsString(glx_dpy, DefaultScreen(glx_dpy)); + else + extensions = NULL; + + glx_extensions = GLX_ParseExtensionString(extensions); + + if (glx_extensions & QGLX_EXT_swap_control) { + if (glx_extensions & QGLX_EXT_swap_control_tear) + Com_Printf("...enabling GLX_EXT_swap_control(_tear)\n"); + else + Com_Printf("...enabling GLX_EXT_swap_control\n"); + qglXSwapIntervalEXT = SDL_GL_GetProcAddress("glXSwapIntervalEXT"); + gl_swapinterval->changed = gl_swapinterval_changed; + gl_swapinterval_changed(gl_swapinterval); + } else { + Com_Printf("GLX_EXT_swap_control not found\n"); + Cvar_Set("gl_swapinterval", "0"); + } + + if (glx_extensions & QGLX_SGI_video_sync) { + if (gl_video_sync->integer) { + Com_Printf("...enabling GLX_SGI_video_sync\n"); + qglXGetVideoSyncSGI = SDL_GL_GetProcAddress("glXGetVideoSyncSGI"); + qglXWaitVideoSyncSGI = SDL_GL_GetProcAddress("glXWaitVideoSyncSGI"); + if (qglXGetVideoSyncSGI) { + qglXGetVideoSyncSGI(&glx_sync_count); + SHOW_SYNC(); + sdl.flags |= QVF_VIDEOSYNC; + } + } else { + Com_Printf("...ignoring GLX_SGI_video_sync\n"); + } + } else if (gl_video_sync->integer) { + Com_Printf("GLX_SGI_video_sync not found\n"); + Cvar_Set("gl_video_sync", "0"); + } +} + +void VID_Shutdown(void) +{ + glx_dpy = NULL; + glx_extensions = 0; + glx_sync_count = 0; + + if (gl_swapinterval) + gl_swapinterval->changed = NULL; + + qglXQueryExtensionsString = NULL; + qglXGetCurrentDrawable = NULL; + qglXSwapIntervalEXT = NULL; + qglXGetVideoSyncSGI = NULL; + qglXWaitVideoSyncSGI = NULL; + + VID_SDL_Shutdown(); +} + +void VID_VideoWait(void) +{ + if (!qglXGetVideoSyncSGI) + return; + + if (!qglXWaitVideoSyncSGI) + return; + + // work around glXWaitVideoSyncSGI blocking indefinitely if vsync is enabled + if (gl_swapinterval->integer) + qglXGetVideoSyncSGI(&glx_sync_count); + else + qglXWaitVideoSyncSGI(1, 0, &glx_sync_count); + + SHOW_SYNC(); +} + +qboolean VID_VideoSync(void) +{ + unsigned count; + + if (!qglXGetVideoSyncSGI) + return qtrue; + + if (qglXGetVideoSyncSGI(&count)) + return qtrue; + + if (count != glx_sync_count) { + glx_sync_count = count; + SHOW_SYNC(); + return qtrue; + } + + return qfalse; +} + +void VID_BeginFrame(void) +{ +} + +void VID_EndFrame(void) +{ + SDL_GL_SwapBuffers(); + + if (qglXGetVideoSyncSGI) { + qglXGetVideoSyncSGI(&glx_sync_count); + SHOW_SYNC(); + } +} diff --git a/src/unix/sdl/swimp.c b/src/unix/sdl/swimp.c new file mode 100644 index 0000000..bac9143 --- /dev/null +++ b/src/unix/sdl/swimp.c @@ -0,0 +1,80 @@ +/* +Copyright (C) 2003-2012 Andrey Nazarov + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "video.h" + +void VID_SDL_SurfaceChanged(void) +{ +} + +qboolean VID_Init(void) +{ + if (!VID_SDL_Init()) { + return qfalse; + } + + if (!VID_SDL_SetMode(SDL_SWSURFACE | SDL_HWPALETTE | SDL_RESIZABLE, 8)) { + Com_EPrintf("Couldn't set video mode: %s\n", SDL_GetError()); + VID_SDL_Shutdown(); + return qfalse; + } + + return qtrue; +} + +void VID_Shutdown(void) +{ + VID_SDL_Shutdown(); +} + +void VID_UpdatePalette(const byte *palette) +{ + SDL_Color colors[256]; + SDL_Color *c; + + for (c = colors; c < colors + 256; c++) { + c->r = palette[0]; + c->g = palette[1]; + c->b = palette[2]; + palette += 4; + } + + SDL_SetPalette(sdl.surface, SDL_LOGPAL, colors, 0, 256); +} + +void VID_VideoWait(void) +{ +} + +qboolean VID_VideoSync(void) +{ + return qtrue; +} + +void VID_BeginFrame(void) +{ + SDL_LockSurface(sdl.surface); +} + +void VID_EndFrame(void) +{ + SDL_UnlockSurface(sdl.surface); + SDL_Flip(sdl.surface); +} + + diff --git a/src/unix/sdl/video.c b/src/unix/sdl/video.c index a5780eb..3340461 100644 --- a/src/unix/sdl/video.c +++ b/src/unix/sdl/video.c @@ -17,54 +17,13 @@ with this program; if not, write to the Free Software Foundation, Inc., */ // -// vid_sdl.c +// video.c // -#include "shared/shared.h" -#include "common/cvar.h" -#include "common/common.h" -#include "common/files.h" -#include "common/zone.h" -#include "client/client.h" -#include "client/input.h" -#include "client/keys.h" -#include "client/video.h" -#include "refresh/refresh.h" +#include "video.h" #include "../res/q2pro.xbm" -#include <SDL.h> -#if USE_X11 -#include <SDL_syswm.h> -#include <X11/Xutil.h> -#if USE_REF == REF_GL -#include <GL/glx.h> -#include <GL/glxext.h> -typedef const char *(*PFNGLXQUERYEXTENSIONSSTRING)(Display *, int); -#endif -#endif - -typedef struct { - SDL_Surface *surface; - SDL_Surface *icon; - Uint16 gamma[3][256]; - vidFlags_t flags; - struct { - qboolean initialized; - grab_t grabbed; - } mouse; -#if USE_X11 - Display *dpy; - Window win; -#if USE_REF == REF_GL - PFNGLXQUERYEXTENSIONSSTRING glXQueryExtensionsString; - PFNGLXGETVIDEOSYNCSGIPROC glXGetVideoSyncSGI; - PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI; - GLuint sync_count; -#endif -#endif -} sdl_state_t; - -static sdl_state_t sdl; +sdl_state_t sdl; /* =============================================================================== @@ -74,111 +33,7 @@ COMMON SDL VIDEO RELATED ROUTINES =============================================================================== */ -#if USE_REF == REF_GL -static void init_opengl(void); -#endif - -#if USE_X11 -static void init_x11(void) -{ - SDL_SysWMinfo info; - - SDL_VERSION(&info.version); - if (!SDL_GetWMInfo(&info)) { - return; - } - - if (info.subsystem != SDL_SYSWM_X11) { - return; - } - - sdl.dpy = info.info.x11.display; - sdl.win = info.info.x11.window; -} - -static void set_wm_hints(void) -{ - XSizeHints hints; - - if (!sdl.dpy) { - return; - } - - memset(&hints, 0, sizeof(hints)); - hints.flags = PMinSize | PResizeInc; - hints.min_width = 64; - hints.min_height = 64; - hints.width_inc = 8; - hints.height_inc = 2; - - XSetWMSizeHints(sdl.dpy, sdl.win, &hints, XA_WM_SIZE_HINTS); -} -#endif - -/* -================= -VID_GetClipboardData -================= -*/ -char *VID_GetClipboardData(void) -{ -#if USE_X11 - Window sowner; - Atom type, property; - unsigned long len, bytes_left; - unsigned char *data; - int format, result; - char *ret; - - if (!sdl.dpy) { - return NULL; - } - - sowner = XGetSelectionOwner(sdl.dpy, XA_PRIMARY); - if (sowner == None) { - return NULL; - } - - property = XInternAtom(sdl.dpy, "GETCLIPBOARDDATA_PROP", False); - - XConvertSelection(sdl.dpy, XA_PRIMARY, XA_STRING, property, sdl.win, CurrentTime); - - XSync(sdl.dpy, False); - - result = XGetWindowProperty(sdl.dpy, sdl.win, property, 0, 0, False, - AnyPropertyType, &type, &format, &len, &bytes_left, &data); - - if (result != Success) { - return NULL; - } - - ret = NULL; - if (bytes_left) { - result = XGetWindowProperty(sdl.dpy, sdl.win, property, 0, bytes_left, True, - AnyPropertyType, &type, &format, &len, &bytes_left, &data); - if (result == Success) { - ret = Z_CopyString((char *)data); - } - } - - XFree(data); - - return ret; -#else - return NULL; -#endif -} - -/* -================= -VID_SetClipboardData -================= -*/ -void VID_SetClipboardData(const char *data) -{ -} - -static qboolean set_video_mode(int flags, int forcedepth) +qboolean VID_SDL_SetMode(int flags, int forcedepth) { SDL_Surface *surf; vrect_t rc; @@ -216,13 +71,8 @@ success: // init some stuff for the first time if (sdl.surface != surf) { sdl.surface = surf; -#if USE_X11 - init_x11(); - set_wm_hints(); -#endif -#if USE_REF == REF_GL - init_opengl(); -#endif + VID_SDL_SurfaceChanged(); + CL_Activate(ACT_ACTIVATED); } R_ModeChanged(rc.width, rc.height, sdl.flags, surf->pitch, surf->pixels); SCR_ModeChanged(); @@ -241,7 +91,11 @@ VID_SetMode */ void VID_SetMode(void) { - if (!set_video_mode(sdl.surface->flags, sdl.surface->format->BitsPerPixel)) { + if (!sdl.surface) { + Com_Error(ERR_FATAL, "%s: NULL surface", __func__); + } + + if (!VID_SDL_SetMode(sdl.surface->flags, sdl.surface->format->BitsPerPixel)) { Com_Error(ERR_FATAL, "Couldn't change video mode: %s", SDL_GetError()); } } @@ -253,7 +107,7 @@ void VID_FatalShutdown(void) SDL_Quit(); } -static qboolean init_video(void) +qboolean VID_SDL_Init(void) { SDL_Color color; byte *dst; @@ -318,7 +172,7 @@ static qboolean init_video(void) return qtrue; } -void VID_Shutdown(void) +void VID_SDL_Shutdown(void) { if (sdl.flags & QVF_GAMMARAMP) { SDL_SetGammaRamp(sdl.gamma[0], sdl.gamma[1], sdl.gamma[2]); @@ -533,293 +387,6 @@ void VID_PumpEvents(void) /* =============================================================================== -RENDERER SPECIFIC - -=============================================================================== -*/ - -#if USE_REF == REF_SOFT - -qboolean VID_Init(void) -{ - if (!init_video()) { - return qfalse; - } - - if (!set_video_mode(SDL_SWSURFACE | SDL_HWPALETTE | SDL_RESIZABLE, 8)) { - Com_EPrintf("Couldn't set video mode: %s\n", SDL_GetError()); - VID_Shutdown(); - return qfalse; - } - - activate_event(); - return qtrue; -} - -void VID_UpdatePalette(const byte *palette) -{ - SDL_Color colors[256]; - SDL_Color *c; - - for (c = colors; c < colors + 256; c++) { - c->r = palette[0]; - c->g = palette[1]; - c->b = palette[2]; - palette += 4; - } - - SDL_SetPalette(sdl.surface, SDL_LOGPAL, colors, 0, 256); -} - -void VID_VideoWait(void) -{ -} - -qboolean VID_VideoSync(void) -{ - return qtrue; -} - -void VID_BeginFrame(void) -{ - SDL_LockSurface(sdl.surface); -} - -void VID_EndFrame(void) -{ - SDL_UnlockSurface(sdl.surface); - SDL_Flip(sdl.surface); -} - -#else // USE_REF == REF_SOFT - -#if USE_X11 - -// for debugging -#define SHOW_SYNC() \ - Com_DDDDPrintf("%s: %u\n", __func__, sdl.sync_count) - -static unsigned glx_parse_extension_string(const char *s) -{ - static const char *const extnames[] = { - "GLX_SGI_video_sync", - NULL - }; - - return Com_ParseExtensionString(s, extnames); -} - -static void init_glx(void) -{ - const char *extensions; - cvar_t *gl_video_sync; - unsigned mask; - - if (!sdl.dpy) { - return; - } - - sdl.glXQueryExtensionsString = SDL_GL_GetProcAddress("glXQueryExtensionsString"); - if (!sdl.glXQueryExtensionsString) { - return; - } - - gl_video_sync = Cvar_Get("gl_video_sync", "1", 0); - - extensions = sdl.glXQueryExtensionsString(sdl.dpy, DefaultScreen(sdl.dpy)); - mask = glx_parse_extension_string(extensions); - if (mask & 1) { - if (gl_video_sync->integer) { - Com_Printf("...enabling GLX_SGI_video_sync\n"); - sdl.glXGetVideoSyncSGI = SDL_GL_GetProcAddress("glXGetVideoSyncSGI"); - sdl.glXWaitVideoSyncSGI = SDL_GL_GetProcAddress("glXWaitVideoSyncSGI"); - sdl.glXGetVideoSyncSGI(&sdl.sync_count); - sdl.flags |= QVF_VIDEOSYNC; - } else { - Com_Printf("...ignoring GLX_SGI_video_sync\n"); - } - } else if (gl_video_sync->integer) { - Com_Printf("GLX_SGI_video_sync not found\n"); - Cvar_Set("gl_video_sync", "0"); - } -} -#endif - -static void init_opengl(void) -{ - int accel; - - SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &accel); - if (accel) { - sdl.flags |= QVF_ACCELERATED; - } - -#if USE_X11 - init_glx(); -#endif -} - -#ifdef __OpenBSD__ -#define LIBGL "libGL.so" -#else -#define LIBGL "libGL.so.1" -#endif - -qboolean VID_Init(void) -{ - cvar_t *gl_driver; - cvar_t *gl_colorbits; - cvar_t *gl_depthbits; - cvar_t *gl_stencilbits; - char *s; - int colorbits; - int depthbits; - int stencilbits; - - if (!init_video()) { - return qfalse; - } - - gl_driver = Cvar_Get("gl_driver", LIBGL, CVAR_REFRESH); - gl_colorbits = Cvar_Get("gl_colorbits", "0", CVAR_REFRESH); - gl_depthbits = Cvar_Get("gl_depthbits", "0", CVAR_REFRESH); - gl_stencilbits = Cvar_Get("gl_stencilbits", "8", CVAR_REFRESH); - - // don't allow absolute or relative paths - FS_SanitizeFilenameVariable(gl_driver); - - while (1) { - // ugly hack to work around brain-dead servers that actively - // check and enforce `gl_driver' cvar to `opengl32', unaware - // of other systems than Windows - s = gl_driver->string; - if (!Q_stricmp(s, "opengl32") || !Q_stricmp(s, "opengl32.dll")) { - Com_Printf("...attempting to load %s instead of %s\n", - gl_driver->default_string, s); - s = gl_driver->default_string; - } - - if (SDL_GL_LoadLibrary(s) == 0) { - break; - } - - Com_EPrintf("Couldn't load OpenGL library: %s\n", SDL_GetError()); - if (!strcmp(s, gl_driver->default_string)) { - goto fail; - } - - // attempt to recover - Com_Printf("...falling back to %s\n", gl_driver->default_string); - Cvar_Reset(gl_driver); - } - - colorbits = Cvar_ClampInteger(gl_colorbits, 0, 32); - depthbits = Cvar_ClampInteger(gl_depthbits, 0, 32); - stencilbits = Cvar_ClampInteger(gl_stencilbits, 0, 8); - - if (colorbits == 0) - colorbits = 24; - - if (depthbits == 0) - depthbits = colorbits > 16 ? 24 : 16; - - if (depthbits < 24) - stencilbits = 0; - - if (colorbits > 16) { - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - } else { - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); - } - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthbits); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilbits); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - - if (!set_video_mode(SDL_OPENGL | SDL_RESIZABLE, 0)) { - Com_EPrintf("Couldn't set video mode: %s\n", SDL_GetError()); - goto fail; - } - - activate_event(); - return qtrue; - -fail: - VID_Shutdown(); - return qfalse; -} - -void VID_VideoWait(void) -{ -#if USE_X11 - if (!sdl.glXWaitVideoSyncSGI) { - return; - } - - sdl.glXWaitVideoSyncSGI(2, 1, &sdl.sync_count); - SHOW_SYNC(); -#endif -} - -qboolean VID_VideoSync(void) -{ -#if USE_X11 - GLuint count; - - if (!sdl.glXGetVideoSyncSGI) { - return qtrue; - } - - if (sdl.glXGetVideoSyncSGI(&count)) { - return qtrue; - } - - if (count != sdl.sync_count) { - sdl.sync_count = count; - SHOW_SYNC(); - return qtrue; - } - - return qfalse; -#else - return qtrue; -#endif -} - -void VID_BeginFrame(void) -{ -} - -void VID_EndFrame(void) -{ - SDL_GL_SwapBuffers(); -#if USE_X11 - if (sdl.glXGetVideoSyncSGI) { - sdl.glXGetVideoSyncSGI(&sdl.sync_count); - SHOW_SYNC(); - } -#endif -} - -void *VID_GetCoreAddr(const char *sym) -{ - return SDL_GL_GetProcAddress(sym); -} - -void *VID_GetProcAddr(const char *sym) -{ - return SDL_GL_GetProcAddress(sym); -} - -#endif // USE_REF == REF_GL - - -/* -=============================================================================== - MOUSE DRIVER =============================================================================== diff --git a/src/unix/sdl/video.h b/src/unix/sdl/video.h new file mode 100644 index 0000000..f86dc4a --- /dev/null +++ b/src/unix/sdl/video.h @@ -0,0 +1,48 @@ +/* +Copyright (C) 2003-2012 Andrey Nazarov + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "shared/shared.h" +#include "common/cvar.h" +#include "common/common.h" +#include "common/files.h" +#include "common/zone.h" +#include "client/client.h" +#include "client/input.h" +#include "client/keys.h" +#include "client/video.h" +#include "refresh/refresh.h" + +#include <SDL.h> + +typedef struct { + SDL_Surface *surface; + SDL_Surface *icon; + Uint16 gamma[3][256]; + vidFlags_t flags; + struct { + qboolean initialized; + grab_t grabbed; + } mouse; +} sdl_state_t; + +extern sdl_state_t sdl; + +qboolean VID_SDL_Init(void); +void VID_SDL_Shutdown(void); +qboolean VID_SDL_SetMode(int flags, int forcedepth); +void VID_SDL_SurfaceChanged(void); |