summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2012-10-19 18:00:16 +0400
committerAndrey Nazarov <skuller@skuller.net>2012-10-20 16:32:20 +0400
commitcaa491ceaa1c3c957a0d35b1e47eea345f2c5f70 (patch)
treecc20054b86400a66682bc43282c7ea8f1fceaab9
parentcf94d68530dc5fbfb855a687687c69d56e6e1c05 (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--Makefile10
-rw-r--r--src/unix/sdl/clipboard.c102
-rw-r--r--src/unix/sdl/glimp.c166
-rw-r--r--src/unix/sdl/glx.c209
-rw-r--r--src/unix/sdl/swimp.c80
-rw-r--r--src/unix/sdl/video.c459
-rw-r--r--src/unix/sdl/video.h48
7 files changed, 628 insertions, 446 deletions
diff --git a/Makefile b/Makefile
index e0a89b0..46d9053 100644
--- a/Makefile
+++ b/Makefile
@@ -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);