Quake II RTX doxygen  1.0 dev
glimp.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 /*
20 GLW_IMP.C
21 
22 This file contains ALL Win32 specific stuff having to do with the
23 OpenGL refresh. When a port is being made the following functions
24 must be implemented by the port:
25 
26 GLimp_EndFrame
27 GLimp_Init
28 GLimp_Shutdown
29 GLimp_SwitchFullscreen
30 */
31 #include "client.h"
32 #include "glimp.h"
33 #include "wgl.h"
34 
36 
37 static cvar_t *gl_driver;
38 static cvar_t *gl_drawbuffer;
39 static cvar_t *gl_swapinterval;
40 static cvar_t *gl_allow_software;
41 static cvar_t *gl_colorbits;
42 static cvar_t *gl_depthbits;
43 static cvar_t *gl_stencilbits;
44 static cvar_t *gl_multisamples;
45 
46 /*
47 VID_Shutdown
48 
49 This routine does all OS specific shutdown procedures for the OpenGL
50 subsystem. Under OpenGL this means NULLing out the current DC and
51 HGLRC, deleting the rendering context, and releasing the DC acquired
52 for the window. The state structure is also nulled out.
53 */
54 void VID_Shutdown(void)
55 {
56  if (qwglMakeCurrent) {
57  qwglMakeCurrent(NULL, NULL);
58  }
59 
60  if (glw.hGLRC && qwglDeleteContext) {
61  qwglDeleteContext(glw.hGLRC);
62  glw.hGLRC = NULL;
63  }
64 
65  WGL_Shutdown();
66  Win_Shutdown();
67 
68  if (gl_swapinterval) {
69  gl_swapinterval->changed = NULL;
70  }
71  if (gl_drawbuffer) {
72  gl_drawbuffer->changed = NULL;
73  }
74 
75  memset(&glw, 0, sizeof(glw));
76 }
77 
78 static void ReportLastError(const char *what)
79 {
80  Com_EPrintf("%s failed with error %lu\n", what, GetLastError());
81 }
82 
83 static void ReportPixelFormat(int pixelformat, PIXELFORMATDESCRIPTOR *pfd)
84 {
85  Com_DPrintf("GL_FPD(%d): flags(%#lx) color(%d) Z(%d) stencil(%d)\n",
86  pixelformat, pfd->dwFlags, pfd->cColorBits, pfd->cDepthBits,
87  pfd->cStencilBits);
88 }
89 
90 #define FAIL_OK 0
91 #define FAIL_SOFT -1
92 #define FAIL_HARD -2
93 
94 static int SetupGL(int colorbits, int depthbits, int stencilbits, int multisamples)
95 {
96  PIXELFORMATDESCRIPTOR pfd;
97  int pixelformat;
98 
99  // create the main window
100  Win_Init();
101 
102  if (colorbits == 0)
103  colorbits = 24;
104 
105  if (depthbits == 0)
106  depthbits = colorbits > 16 ? 24 : 16;
107 
108  if (depthbits < 24)
109  stencilbits = 0;
110 
111  // choose pixel format
112  if (qwglChoosePixelFormatARB && multisamples > 1) {
113  int iAttributes[20];
114  UINT numFormats;
115 
116  iAttributes[0] = WGL_DRAW_TO_WINDOW_ARB;
117  iAttributes[1] = TRUE;
118  iAttributes[2] = WGL_SUPPORT_OPENGL_ARB;
119  iAttributes[3] = TRUE;
120  iAttributes[4] = WGL_DOUBLE_BUFFER_ARB;
121  iAttributes[5] = TRUE;
122  iAttributes[6] = WGL_PIXEL_TYPE_ARB;
123  iAttributes[7] = WGL_TYPE_RGBA_ARB;
124  iAttributes[8] = WGL_COLOR_BITS_ARB;
125  iAttributes[9] = colorbits;
126  iAttributes[10] = WGL_DEPTH_BITS_ARB;
127  iAttributes[11] = depthbits;
128  iAttributes[12] = WGL_STENCIL_BITS_ARB;
129  iAttributes[13] = stencilbits;
130  iAttributes[14] = WGL_SAMPLE_BUFFERS_ARB;
131  iAttributes[15] = 1;
132  iAttributes[16] = WGL_SAMPLES_ARB;
133  iAttributes[17] = multisamples;
134  iAttributes[18] = 0;
135  iAttributes[19] = 0;
136 
137  if (qwglChoosePixelFormatARB(win.dc, iAttributes, NULL, 1, &pixelformat, &numFormats) == FALSE) {
138  ReportLastError("wglChoosePixelFormatARB");
139  goto soft;
140  }
141  if (numFormats == 0) {
142  Com_EPrintf("No suitable OpenGL pixelformat found for %d multisamples\n", multisamples);
143  goto soft;
144  }
145  } else {
146  memset(&pfd, 0, sizeof(pfd));
147  pfd.nSize = sizeof(pfd);
148  pfd.nVersion = 1;
149  pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
150  pfd.iPixelType = PFD_TYPE_RGBA;
151  pfd.cColorBits = colorbits;
152  pfd.cDepthBits = depthbits;
153  pfd.cStencilBits = stencilbits;
154  pfd.iLayerType = PFD_MAIN_PLANE;
155 
156  if (glw.minidriver) {
157  if ((pixelformat = qwglChoosePixelFormat(win.dc, &pfd)) == 0) {
158  ReportLastError("wglChoosePixelFormat");
159  goto soft;
160  }
161  } else {
162  if ((pixelformat = ChoosePixelFormat(win.dc, &pfd)) == 0) {
163  ReportLastError("ChoosePixelFormat");
164  goto soft;
165  }
166  }
167  }
168 
169  // set pixel format
170  if (glw.minidriver) {
171  qwglDescribePixelFormat(win.dc, pixelformat, sizeof(pfd), &pfd);
172  ReportPixelFormat(pixelformat, &pfd);
173 
174  if (qwglSetPixelFormat(win.dc, pixelformat, &pfd) == FALSE) {
175  ReportLastError("wglSetPixelFormat");
176  goto soft;
177  }
178  } else {
179  DescribePixelFormat(win.dc, pixelformat, sizeof(pfd), &pfd);
180  ReportPixelFormat(pixelformat, &pfd);
181 
182  if (SetPixelFormat(win.dc, pixelformat, &pfd) == FALSE) {
183  ReportLastError("SetPixelFormat");
184  goto soft;
185  }
186  }
187 
188  // check for software emulation
189  if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
190  if (!gl_allow_software->integer) {
191  Com_EPrintf("No hardware OpenGL acceleration detected\n");
192  goto soft;
193  }
194  Com_WPrintf("...using software emulation\n");
195  } else if (pfd.dwFlags & PFD_GENERIC_ACCELERATED) {
196  Com_DPrintf("...MCD acceleration found\n");
197  win.flags |= QVF_ACCELERATED;
198  } else {
199  Com_DPrintf("...ICD acceleration found\n");
200  win.flags |= QVF_ACCELERATED;
201  }
202 
203  // startup the OpenGL subsystem by creating a context and making it current
204  if ((glw.hGLRC = qwglCreateContext(win.dc)) == NULL) {
205  ReportLastError("wglCreateContext");
206  goto hard;
207  }
208 
209  if (qwglMakeCurrent(win.dc, glw.hGLRC) == FALSE) {
210  ReportLastError("wglMakeCurrent");
211  qwglDeleteContext(glw.hGLRC);
212  glw.hGLRC = NULL;
213  goto hard;
214  }
215 
216  return FAIL_OK;
217 
218 soft:
219  // it failed, clean up
220  Win_Shutdown();
221  return FAIL_SOFT;
222 
223 hard:
224  Win_Shutdown();
225  return FAIL_HARD;
226 }
227 
228 #define FAKE_WINDOW_CLASS "Q2PRO FAKE WINDOW CLASS"
229 #define FAKE_WINDOW_NAME "Q2PRO FAKE WINDOW NAME"
230 
231 static unsigned GetFakeWindowExtensions(void)
232 {
233  WNDCLASSEX wc;
234  PIXELFORMATDESCRIPTOR pfd;
235  int pixelformat;
236  HWND wnd;
237  HDC dc;
238  HGLRC rc;
239  unsigned extensions = 0;
240 
241  memset(&wc, 0, sizeof(wc));
242  wc.cbSize = sizeof(wc);
243  wc.lpfnWndProc = DefWindowProc;
244  wc.hInstance = hGlobalInstance;
245  wc.lpszClassName = FAKE_WINDOW_CLASS;
246 
247  if (!RegisterClassEx(&wc))
248  goto fail0;
249 
250  wnd = CreateWindow(
253  0,
254  0, 0, 0, 0,
255  NULL,
256  NULL,
258  NULL);
259  if (!wnd)
260  goto fail1;
261 
262  if ((dc = GetDC(wnd)) == NULL)
263  goto fail2;
264 
265  memset(&pfd, 0, sizeof(pfd));
266  pfd.nSize = sizeof(pfd);
267  pfd.nVersion = 1;
268  pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
269  pfd.iPixelType = PFD_TYPE_RGBA;
270  pfd.cColorBits = 24;
271  pfd.cDepthBits = 24;
272  pfd.cStencilBits = 8;
273  pfd.iLayerType = PFD_MAIN_PLANE;
274 
275  if (glw.minidriver) {
276  if ((pixelformat = qwglChoosePixelFormat(dc, &pfd)) == 0)
277  goto fail3;
278 
279  if (qwglSetPixelFormat(dc, pixelformat, &pfd) == FALSE)
280  goto fail3;
281  } else {
282  if ((pixelformat = ChoosePixelFormat(dc, &pfd)) == 0)
283  goto fail3;
284 
285  if (SetPixelFormat(dc, pixelformat, &pfd) == FALSE)
286  goto fail3;
287  }
288 
289  if ((rc = qwglCreateContext(dc)) == NULL)
290  goto fail3;
291 
292  if (qwglMakeCurrent(dc, rc) == FALSE)
293  goto fail4;
294 
296 
298  goto fail5;
299 
301 
302  if (extensions & QWGL_ARB_pixel_format) {
303  Com_Printf("...enabling WGL_ARB_pixel_format\n");
305  }
306 
307 fail5:
308  qwglMakeCurrent(NULL, NULL);
309 fail4:
310  qwglDeleteContext(rc);
311 fail3:
312  ReleaseDC(wnd, dc);
313 fail2:
314  DestroyWindow(wnd);
315 fail1:
316  UnregisterClass(FAKE_WINDOW_CLASS, hGlobalInstance);
317 fail0:
318  return extensions;
319 }
320 
321 static int LoadGL(const char *driver)
322 {
323  int colorbits = Cvar_ClampInteger(gl_colorbits, 0, 32);
324  int depthbits = Cvar_ClampInteger(gl_depthbits, 0, 32);
325  int stencilbits = Cvar_ClampInteger(gl_stencilbits, 0, 8);
326  int multisamples = Cvar_ClampInteger(gl_multisamples, 0, 32);
327  int ret;
328 
329  // figure out if we're running on a minidriver or not
330  if (!Q_stricmp(driver, "opengl32") ||
331  !Q_stricmp(driver, "opengl32.dll")) {
332  glw.minidriver = qfalse;
333  } else {
334  Com_Printf("...running a minidriver: %s\n", driver);
335  glw.minidriver = qtrue;
336  }
337 
338  // load the OpenGL library and bind to it
339  if (!WGL_Init(driver)) {
340  ReportLastError("WGL_Init");
341  return FAIL_SOFT;
342  }
343 
344  // check if basic WGL entry points are present
345  if (!qwglCreateContext || !qwglMakeCurrent || !qwglDeleteContext) {
346  Com_EPrintf("Required WGL entry points are missing\n");
347  goto fail;
348  }
349 
350  if (glw.minidriver) {
351  // check if MCD entry points are present if using a minidriver
352  if (!qwglChoosePixelFormat || !qwglSetPixelFormat ||
353  !qwglDescribePixelFormat || !qwglSwapBuffers) {
354  Com_EPrintf("Required MCD entry points are missing\n");
355  goto fail;
356  }
357  }
358 
359  // check for WGL_ARB_multisample by creating a fake window
360  if (multisamples > 1) {
361  unsigned extensions = GetFakeWindowExtensions();
362 
363  if (extensions & QWGL_ARB_multisample) {
364  if (qwglChoosePixelFormatARB) {
365  Com_Printf("...enabling WGL_ARB_multisample\n");
366  } else {
367  Com_Printf("...ignoring WGL_ARB_multisample, WGL_ARB_pixel_format not found\n");
368  Cvar_Set("gl_multisamples", "0");
369  multisamples = 0;
370  }
371  } else {
372  Com_Printf("WGL_ARB_multisample not found\n");
373  Cvar_Set("gl_multisamples", "0");
374  multisamples = 0;
375  }
376  }
377 
378  // create window, choose PFD, setup OpenGL context
379  ret = SetupGL(colorbits, depthbits, stencilbits, multisamples);
380 
381  // attempt to recover
382  if (ret == FAIL_SOFT && (colorbits || depthbits || stencilbits || multisamples > 1)) {
383  Cvar_Set("gl_multisamples", "0");
384  ret = SetupGL(0, 0, 0, 0);
385  }
386 
387  if (ret)
388  goto fail;
389 
390  return FAIL_OK;
391 
392 fail:
393  // it failed, clean up
394  WGL_Shutdown();
395  return FAIL_SOFT;
396 }
397 
398 static void gl_swapinterval_changed(cvar_t *self)
399 {
400  if (self->integer < 0 && !(glw.extensions & QWGL_EXT_swap_control_tear)) {
401  Com_Printf("Negative swap interval is not supported on this system.\n");
402  Cvar_Reset(self);
403  }
404 
405  if (qwglSwapIntervalEXT && !qwglSwapIntervalEXT(self->integer))
406  ReportLastError("wglSwapIntervalEXT");
407 }
408 
409 static void gl_drawbuffer_changed(cvar_t *self)
410 {
411  if (!Q_stricmp(self->string, "GL_FRONT")) {
412  glw.drawbuffer = GL_FRONT;
413  } else if (!Q_stricmp(self->string, "GL_BACK")) {
414  glw.drawbuffer = GL_BACK;
415  } else {
416  Cvar_Reset(self);
417  glw.drawbuffer = GL_BACK;
418  }
419 
420  qwglDrawBuffer(glw.drawbuffer);
421 }
422 
423 /*
424 VID_Init
425 
426 This routine is responsible for initializing the OS specific portions
427 of OpenGL. Under Win32 this means dealing with the pixelformats and
428 doing the wgl interface stuff.
429 */
430 qboolean VID_Init(void)
431 {
432  const char *extensions;
433  int ret;
434 
435  gl_driver = Cvar_Get("gl_driver", "opengl32", CVAR_ARCHIVE | CVAR_REFRESH);
436  gl_drawbuffer = Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
437  gl_swapinterval = Cvar_Get("gl_swapinterval", "1", CVAR_ARCHIVE);
438  gl_allow_software = Cvar_Get("gl_allow_software", "0", 0);
439  gl_colorbits = Cvar_Get("gl_colorbits", "0", CVAR_REFRESH);
440  gl_depthbits = Cvar_Get("gl_depthbits", "0", CVAR_REFRESH);
441  gl_stencilbits = Cvar_Get("gl_stencilbits", "8", CVAR_REFRESH);
442  gl_multisamples = Cvar_Get("gl_multisamples", "0", CVAR_REFRESH);
443 
444  // don't allow absolute or relative paths
446 
447  // load and initialize the OpenGL driver
448  ret = LoadGL(gl_driver->string);
449 
450  // attempt to recover if this was a minidriver
451  if (ret == FAIL_SOFT && glw.minidriver) {
452  Com_Printf("...falling back to opengl32\n");
453  Cvar_Reset(gl_driver);
454  ret = LoadGL(gl_driver->string);
455  }
456 
457  // it failed, abort
458  if (ret)
459  return qfalse;
460 
461  // initialize WGL extensions
463 
465  extensions = qwglGetExtensionsStringARB(win.dc);
466  else
467  extensions = NULL;
468 
469  // fall back to GL_EXTENSIONS for legacy drivers
470  if (!extensions || !*extensions)
471  extensions = (const char *)qwglGetString(GL_EXTENSIONS);
472 
474 
477  Com_Printf("...enabling WGL_EXT_swap_control(_tear)\n");
478  else
479  Com_Printf("...enabling WGL_EXT_swap_control\n");
483  } else {
484  Com_Printf("WGL_EXT_swap_control not found\n");
485  Cvar_Set("gl_swapinterval", "0");
486  }
487 
490 
491  VID_SetMode();
492 
493  return qtrue;
494 }
495 
496 void VID_VideoWait(void)
497 {
498 }
499 
500 qboolean VID_VideoSync(void)
501 {
502  return qtrue;
503 }
504 
505 void VID_BeginFrame(void)
506 {
507 }
508 
509 /*
510 VID_EndFrame
511 
512 Responsible for doing a swapbuffers and possibly for other stuff
513 as yet to be determined. Probably better not to make this a VID_
514 function and instead do a call to VID_SwapBuffers.
515 */
516 void VID_EndFrame(void)
517 {
518  BOOL ret;
519 
520  // don't flip if drawing to front buffer
521  if (glw.drawbuffer == GL_FRONT) {
522  return;
523  }
524 
525  if (glw.minidriver) {
526  ret = qwglSwapBuffers(win.dc);
527  } else {
528  ret = SwapBuffers(win.dc);
529  }
530 
531  if (!ret) {
532  DWORD error = GetLastError();
533 
534  // this happens sometimes when the window is iconified
535  if (!IsIconic(win.wnd)) {
536  Com_Error(ERR_FATAL, "%s failed with error %lu",
537  glw.minidriver ? "wglSwapBuffers" : "SwapBuffers", error);
538  }
539  }
540 }
541 
542 void *VID_GetCoreAddr(const char *sym)
543 {
544  void *entry;
545 
546  if (glw.hinstOpenGL)
547  entry = (void *)GetProcAddress(glw.hinstOpenGL, sym);
548  else
549  entry = NULL;
550 
551  if (!entry)
552  Com_EPrintf("Couldn't get OpenGL entry point: %s\n", sym);
553 
554  return entry;
555 }
556 
557 void *VID_GetProcAddr(const char *sym)
558 {
559  void *entry;
560 
561  if (qwglGetProcAddress)
562  entry = (void *)qwglGetProcAddress(sym);
563  else
564  entry = NULL;
565 
566  if (!entry)
567  Com_EPrintf("Couldn't get OpenGL entry point: %s\n", sym);
568 
569  return entry;
570 }
571 
Win_Init
void Win_Init(void)
Definition: client.c:1014
Cvar_Set
cvar_t * Cvar_Set(const char *var_name, const char *value)
Definition: cvar.c:466
FAIL_OK
#define FAIL_OK
Definition: glimp.c:90
VID_SetMode
void VID_SetMode(void)
Definition: client.c:960
wgl.h
glwstate_t::extensions
unsigned extensions
Definition: glimp.h:31
glwstate_t::drawbuffer
GLenum drawbuffer
Definition: glimp.h:30
gl_depthbits
static cvar_t * gl_depthbits
Definition: glimp.c:42
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
gl_driver
static cvar_t * gl_driver
Definition: glimp.c:37
gl_multisamples
static cvar_t * gl_multisamples
Definition: glimp.c:44
gl_allow_software
static cvar_t * gl_allow_software
Definition: glimp.c:40
QWGL_ARB_pixel_format
#define QWGL_ARB_pixel_format
Definition: wgl.h:25
VID_EndFrame
void VID_EndFrame(void)
Definition: glimp.c:516
glwstate_t
Definition: glimp.h:26
gl_drawbuffer
static cvar_t * gl_drawbuffer
Definition: glimp.c:38
FAKE_WINDOW_CLASS
#define FAKE_WINDOW_CLASS
Definition: glimp.c:228
hGlobalInstance
HINSTANCE hGlobalInstance
Definition: system.c:28
QWGL_ARB_extensions_string
#define QWGL_ARB_extensions_string
Definition: wgl.h:23
WGL_ParseExtensionString
unsigned WGL_ParseExtensionString(const char *s)
Definition: wgl.c:120
glw
glwstate_t glw
Definition: glimp.c:35
QWGL_EXT_swap_control_tear
#define QWGL_EXT_swap_control_tear
Definition: wgl.h:27
BOOL
BOOL(WINAPI *qwglSetPixelFormat)(HDC
glimp.h
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
WGL_Shutdown
void WGL_Shutdown(void)
Definition: wgl.c:41
gl_colorbits
static cvar_t * gl_colorbits
Definition: glimp.c:41
glwstate_t::hGLRC
HGLRC hGLRC
Definition: glimp.h:27
gl_swapinterval
static cvar_t * gl_swapinterval
Definition: glimp.c:39
gl_stencilbits
static cvar_t * gl_stencilbits
Definition: glimp.c:43
client.h
WGL_Init
qboolean WGL_Init(const char *dllname)
Definition: wgl.c:66
VID_Shutdown
void VID_Shutdown(void)
Definition: glimp.c:54
glwstate_t::minidriver
qboolean minidriver
Definition: glimp.h:29
QWGL_EXT_swap_control
#define QWGL_EXT_swap_control
Definition: wgl.h:26
Win_Shutdown
void Win_Shutdown(void)
Definition: client.c:1091
QWGL_ARB_multisample
#define QWGL_ARB_multisample
Definition: wgl.h:24
WGL_InitExtensions
void WGL_InitExtensions(unsigned mask)
Definition: wgl.c:105
VID_Init
qboolean VID_Init(void)
Definition: glimp.c:430
UINT
CONST PIXELFORMATDESCRIPTOR UINT
Definition: wgl.c:26
FAIL_SOFT
#define FAIL_SOFT
Definition: glimp.c:91
ReportLastError
static void ReportLastError(const char *what)
Definition: glimp.c:78
FS_SanitizeFilenameVariable
void FS_SanitizeFilenameVariable(cvar_t *var)
Definition: files.c:294
gl_drawbuffer_changed
static void gl_drawbuffer_changed(cvar_t *self)
Definition: glimp.c:409
VID_GetCoreAddr
void * VID_GetCoreAddr(const char *sym)
Definition: glimp.c:542
gl_swapinterval_changed
static void gl_swapinterval_changed(cvar_t *self)
Definition: glimp.c:398
Cvar_ClampInteger
int Cvar_ClampInteger(cvar_t *var, int min, int max)
Definition: cvar.c:549
LoadGL
static int LoadGL(const char *driver)
Definition: glimp.c:321
HGLRC
HGLRC
Definition: wgl.c:33
FAKE_WINDOW_NAME
#define FAKE_WINDOW_NAME
Definition: glimp.c:229
qwglGetString
const GLubyte *APIENTRY * qwglGetString(GLenum name)
VID_BeginFrame
void VID_BeginFrame(void)
Definition: glimp.c:505
ReportPixelFormat
static void ReportPixelFormat(int pixelformat, PIXELFORMATDESCRIPTOR *pfd)
Definition: glimp.c:83
SetupGL
static int SetupGL(int colorbits, int depthbits, int stencilbits, int multisamples)
Definition: glimp.c:94
glwstate_t::hinstOpenGL
HINSTANCE hinstOpenGL
Definition: glimp.h:28
FAIL_HARD
#define FAIL_HARD
Definition: glimp.c:92
VID_VideoWait
void VID_VideoWait(void)
Definition: glimp.c:496
GetFakeWindowExtensions
static unsigned GetFakeWindowExtensions(void)
Definition: glimp.c:231
win
win_state_t win
Definition: client.c:33
qwglGetExtensionsStringARB
const char *WINAPI * qwglGetExtensionsStringARB(HDC hdc)
VID_VideoSync
qboolean VID_VideoSync(void)
Definition: glimp.c:500
VID_GetProcAddr
void * VID_GetProcAddr(const char *sym)
Definition: glimp.c:557