|
|
1.1 root 1: /*
2: ** GLW_IMP.C
3: **
4: ** This file contains ALL Win32 specific stuff having to do with the
5: ** OpenGL refresh. When a port is being made the following functions
6: ** must be implemented by the port:
7: **
8: ** GLimp_EndFrame
9: ** GLimp_Init
10: ** GLimp_Shutdown
11: ** GLimp_SwitchFullscreen
12: **
13: */
14: #include <assert.h>
15: #include <windows.h>
16: #include "../ref_gl/gl_local.h"
17: #include "glw_win.h"
18: #include "winquake.h"
19:
20: static qboolean GLimp_SwitchFullscreen( int width, int height );
21: qboolean GLimp_InitGL (void);
22:
23: glwstate_t glw_state;
24:
25: extern cvar_t *vid_fullscreen;
26: extern cvar_t *vid_ref;
27:
28: static qboolean VerifyDriver( void )
29: {
30: char buffer[1024];
31:
32: strcpy( buffer, qglGetString( GL_RENDERER ) );
33: strlwr( buffer );
34: if ( strcmp( buffer, "gdi generic" ) == 0 )
35: if ( !glw_state.mcd_accelerated )
36: return false;
37: return true;
38: }
39:
40: /*
41: ** VID_CreateWindow
42: */
43: #define WINDOW_CLASS_NAME "Quake 2"
44:
45: qboolean VID_CreateWindow( int width, int height, qboolean fullscreen )
46: {
47: WNDCLASS wc;
48: RECT r;
49: cvar_t *vid_xpos, *vid_ypos;
50: int stylebits;
51: int x, y, w, h;
52: int exstyle;
53:
54: /* Register the frame class */
55: wc.style = 0;
56: wc.lpfnWndProc = (WNDPROC)glw_state.wndproc;
57: wc.cbClsExtra = 0;
58: wc.cbWndExtra = 0;
59: wc.hInstance = glw_state.hInstance;
60: wc.hIcon = 0;
61: wc.hCursor = LoadCursor (NULL,IDC_ARROW);
62: wc.hbrBackground = (void *)COLOR_GRAYTEXT;
63: wc.lpszMenuName = 0;
64: wc.lpszClassName = WINDOW_CLASS_NAME;
65:
66: if (!RegisterClass (&wc) )
67: ri.Sys_Error (ERR_FATAL, "Couldn't register window class");
68:
69: if (fullscreen)
70: {
71: exstyle = WS_EX_TOPMOST;
72: stylebits = WS_POPUP|WS_VISIBLE;
73: }
74: else
75: {
76: exstyle = 0;
77: stylebits = WINDOW_STYLE;
78: }
79:
80: r.left = 0;
81: r.top = 0;
82: r.right = width;
83: r.bottom = height;
84:
85: AdjustWindowRect (&r, stylebits, FALSE);
86:
87: w = r.right - r.left;
88: h = r.bottom - r.top;
89:
90: if (fullscreen)
91: {
92: x = 0;
93: y = 0;
94: }
95: else
96: {
97: vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
98: vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
99: x = vid_xpos->value;
100: y = vid_ypos->value;
101: }
102:
103: glw_state.hWnd = CreateWindowEx (
104: exstyle,
105: WINDOW_CLASS_NAME,
106: "Quake 2",
107: stylebits,
108: x, y, w, h,
109: NULL,
110: NULL,
111: glw_state.hInstance,
112: NULL);
113:
114: if (!glw_state.hWnd)
115: ri.Sys_Error (ERR_FATAL, "Couldn't create window");
116:
117: ShowWindow( glw_state.hWnd, SW_SHOW );
118: UpdateWindow( glw_state.hWnd );
119:
120: // init all the gl stuff for the window
121: if (!GLimp_InitGL ())
122: {
123: ri.Con_Printf( PRINT_ALL, "VID_CreateWindow() - GLimp_InitGL failed\n");
124: return false;
125: }
126:
127: SetForegroundWindow( glw_state.hWnd );
128: SetFocus( glw_state.hWnd );
129:
130: // let the sound and input subsystems know about the new window
131: ri.Vid_NewWindow (width, height);
132:
133: return true;
134: }
135:
136:
137: /*
138: ** GLimp_SetMode
139: */
140: rserr_t GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
141: {
142: int width, height;
143: const char *win_fs[] = { "W", "FS" };
144:
145: ri.Con_Printf( PRINT_ALL, "Initializing OpenGL display\n");
146:
147: ri.Con_Printf (PRINT_ALL, "...setting mode %d:", mode );
148:
149: if ( !ri.Vid_GetModeInfo( &width, &height, mode ) )
150: {
151: ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
152: return rserr_invalid_mode;
153: }
154:
155: ri.Con_Printf( PRINT_ALL, " %d %d %s\n", width, height, win_fs[fullscreen] );
156:
157: // destroy the existing window
158: if (glw_state.hWnd)
159: {
160: GLimp_Shutdown ();
161: }
162:
163: // do a CDS if needed
164: if ( fullscreen )
165: {
166: DEVMODE dm;
167:
168: ri.Con_Printf( PRINT_ALL, "...attempting fullscreen\n" );
169:
170: memset( &dm, 0, sizeof( dm ) );
171:
172: dm.dmSize = sizeof( dm );
173:
174: dm.dmPelsWidth = width;
175: dm.dmPelsHeight = height;
176: dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
177:
178: if ( gl_bitdepth->value != 0 )
179: {
180: dm.dmBitsPerPel = gl_bitdepth->value;
181: dm.dmFields |= DM_BITSPERPEL;
182: ri.Con_Printf( PRINT_ALL, "...using gl_bitdepth of %d\n", ( int ) gl_bitdepth->value );
183: }
184: else
185: {
186: HDC hdc = GetDC( NULL );
187: int bitspixel = GetDeviceCaps( hdc, BITSPIXEL );
188:
189: ri.Con_Printf( PRINT_ALL, "...using desktop display depth of %d\n", bitspixel );
190:
191: ReleaseDC( 0, hdc );
192: }
193:
194: ri.Con_Printf( PRINT_ALL, "...calling CDS: " );
195: if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL )
196: {
197: *pwidth = width;
198: *pheight = height;
199:
200: gl_state.fullscreen = true;
201:
202: ri.Con_Printf( PRINT_ALL, "ok\n" );
203:
204: if ( !VID_CreateWindow (width, height, true) )
205: return rserr_invalid_mode;
206:
207: return rserr_ok;
208: }
209: else
210: {
211: *pwidth = width;
212: *pheight = height;
213:
214: ri.Con_Printf( PRINT_ALL, "failed\n" );
215:
216: ri.Con_Printf( PRINT_ALL, "...calling CDS assuming dual monitors:" );
217:
218: dm.dmPelsWidth = width * 2;
219: dm.dmPelsHeight = height;
220: dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
221:
222: if ( gl_bitdepth->value != 0 )
223: {
224: dm.dmBitsPerPel = gl_bitdepth->value;
225: dm.dmFields |= DM_BITSPERPEL;
226: }
227:
228: /*
229: ** our first CDS failed, so maybe we're running on some weird dual monitor
230: ** system
231: */
232: if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
233: {
234: ri.Con_Printf( PRINT_ALL, " failed\n" );
235:
236: ri.Con_Printf( PRINT_ALL, "...setting windowed mode\n" );
237:
238: ChangeDisplaySettings( 0, 0 );
239:
240: *pwidth = width;
241: *pheight = height;
242: gl_state.fullscreen = false;
243: if ( !VID_CreateWindow (width, height, false) )
244: return rserr_invalid_mode;
245: return rserr_invalid_fullscreen;
246: }
247: else
248: {
249: ri.Con_Printf( PRINT_ALL, " ok\n" );
250: if ( !VID_CreateWindow (width, height, true) )
251: return rserr_invalid_mode;
252:
253: gl_state.fullscreen = true;
254: return rserr_ok;
255: }
256: }
257: }
258: else
259: {
260: ri.Con_Printf( PRINT_ALL, "...setting windowed mode\n" );
261:
262: ChangeDisplaySettings( 0, 0 );
263:
264: *pwidth = width;
265: *pheight = height;
266: gl_state.fullscreen = false;
267: if ( !VID_CreateWindow (width, height, false) )
268: return rserr_invalid_mode;
269: }
270:
271: return rserr_ok;
272: }
273:
274: /*
275: ** GLimp_Shutdown
276: **
277: ** This routine does all OS specific shutdown procedures for the OpenGL
278: ** subsystem. Under OpenGL this means NULLing out the current DC and
279: ** HGLRC, deleting the rendering context, and releasing the DC acquired
280: ** for the window. The state structure is also nulled out.
281: **
282: */
283: void GLimp_Shutdown( void )
284: {
285: if ( qwglMakeCurrent && !qwglMakeCurrent( NULL, NULL ) )
286: ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - wglMakeCurrent failed\n");
287: if ( glw_state.hGLRC )
288: {
289: if ( qwglDeleteContext && !qwglDeleteContext( glw_state.hGLRC ) )
290: ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - wglDeleteContext failed\n");
291: glw_state.hGLRC = NULL;
292: }
293: if (glw_state.hDC)
294: {
295: if ( !ReleaseDC( glw_state.hWnd, glw_state.hDC ) )
296: ri.Con_Printf( PRINT_ALL, "ref_gl::R_Shutdown() - ReleaseDC failed\n" );
297: glw_state.hDC = NULL;
298: }
299: if (glw_state.hWnd)
300: {
301: DestroyWindow ( glw_state.hWnd );
302: glw_state.hWnd = NULL;
303: }
304:
305: if ( glw_state.log_fp )
306: {
307: fclose( glw_state.log_fp );
308: glw_state.log_fp = 0;
309: }
310:
311: UnregisterClass (WINDOW_CLASS_NAME, glw_state.hInstance);
312:
313: if ( gl_state.fullscreen )
314: {
315: ChangeDisplaySettings( 0, 0 );
316: gl_state.fullscreen = false;
317: }
318: }
319:
320:
321: /*
322: ** GLimp_Init
323: **
324: ** This routine is responsible for initializing the OS specific portions
325: ** of OpenGL. Under Win32 this means dealing with the pixelformats and
326: ** doing the wgl interface stuff.
327: */
328: qboolean GLimp_Init( void *hinstance, void *wndproc )
329: {
330: #define OSR2_BUILD_NUMBER 1111
331:
332: OSVERSIONINFO vinfo;
333:
334: vinfo.dwOSVersionInfoSize = sizeof(vinfo);
335:
336: glw_state.allowdisplaydepthchange = false;
337:
338: if ( GetVersionEx( &vinfo) )
339: {
340: if ( vinfo.dwMajorVersion > 4 )
341: {
342: glw_state.allowdisplaydepthchange = true;
343: }
344: else if ( vinfo.dwMajorVersion == 4 )
345: {
346: if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
347: {
348: glw_state.allowdisplaydepthchange = true;
349: }
350: else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
351: {
352: if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER )
353: {
354: glw_state.allowdisplaydepthchange = true;
355: }
356: }
357: }
358: }
359: else
360: {
361: ri.Con_Printf( PRINT_ALL, "GLimp_Init() - GetVersionEx failed\n" );
362: return false;
363: }
364:
365: glw_state.hInstance = ( HINSTANCE ) hinstance;
366: glw_state.wndproc = wndproc;
367:
368: return true;
369: }
370:
371: qboolean GLimp_InitGL (void)
372: {
373: PIXELFORMATDESCRIPTOR pfd =
374: {
375: sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
376: 1, // version number
377: PFD_DRAW_TO_WINDOW | // support window
378: PFD_SUPPORT_OPENGL | // support OpenGL
379: PFD_DOUBLEBUFFER, // double buffered
380: PFD_TYPE_RGBA, // RGBA type
381: 24, // 24-bit color depth
382: 0, 0, 0, 0, 0, 0, // color bits ignored
383: 0, // no alpha buffer
384: 0, // shift bit ignored
385: 0, // no accumulation buffer
386: 0, 0, 0, 0, // accum bits ignored
387: 32, // 32-bit z-buffer
388: 0, // no stencil buffer
389: 0, // no auxiliary buffer
390: PFD_MAIN_PLANE, // main layer
391: 0, // reserved
392: 0, 0, 0 // layer masks ignored
393: };
394: int pixelformat;
395: cvar_t *stereo;
396:
397: stereo = ri.Cvar_Get( "cl_stereo", "0", 0 );
398:
399: /*
400: ** set PFD_STEREO if necessary
401: */
402: if ( stereo->value != 0 )
403: {
404: ri.Con_Printf( PRINT_ALL, "...attempting to use stereo\n" );
405: pfd.dwFlags |= PFD_STEREO;
406: gl_state.stereo_enabled = true;
407: }
408: else
409: {
410: gl_state.stereo_enabled = false;
411: }
412:
413: /*
414: ** figure out if we're running on a minidriver or not
415: */
416: if ( strstr( gl_driver->string, "opengl32" ) != 0 )
417: glw_state.minidriver = false;
418: else
419: glw_state.minidriver = true;
420:
421: /*
422: ** Get a DC for the specified window
423: */
424: if ( glw_state.hDC != NULL )
425: ri.Con_Printf( PRINT_ALL, "GLimp_Init() - non-NULL DC exists\n" );
426:
427: if ( ( glw_state.hDC = GetDC( glw_state.hWnd ) ) == NULL )
428: {
429: ri.Con_Printf( PRINT_ALL, "GLimp_Init() - GetDC failed\n" );
430: return false;
431: }
432:
433: if ( glw_state.minidriver )
434: {
435: if ( (pixelformat = qwglChoosePixelFormat( glw_state.hDC, &pfd)) == 0 )
436: {
437: ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglChoosePixelFormat failed\n");
438: return false;
439: }
440: if ( qwglSetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE )
441: {
442: ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglSetPixelFormat failed\n");
443: return false;
444: }
445: qwglDescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
446: }
447: else
448: {
449: if ( ( pixelformat = ChoosePixelFormat( glw_state.hDC, &pfd)) == 0 )
450: {
451: ri.Con_Printf (PRINT_ALL, "GLimp_Init() - ChoosePixelFormat failed\n");
452: return false;
453: }
454: if ( SetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE )
455: {
456: ri.Con_Printf (PRINT_ALL, "GLimp_Init() - SetPixelFormat failed\n");
457: return false;
458: }
459: DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
460:
461: if ( !( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) )
462: {
463: extern cvar_t *gl_allow_software;
464:
465: if ( gl_allow_software->value )
466: glw_state.mcd_accelerated = true;
467: else
468: glw_state.mcd_accelerated = false;
469: }
470: else
471: {
472: glw_state.mcd_accelerated = true;
473: }
474: }
475:
476: /*
477: ** report if stereo is desired but unavailable
478: */
479: if ( !( pfd.dwFlags & PFD_STEREO ) && ( stereo->value != 0 ) )
480: {
481: ri.Con_Printf( PRINT_ALL, "...failed to select stereo pixel format\n" );
482: ri.Cvar_SetValue( "cl_stereo", 0 );
483: gl_state.stereo_enabled = false;
484: }
485:
486: /*
487: ** startup the OpenGL subsystem by creating a context and making
488: ** it current
489: */
490: if ( ( glw_state.hGLRC = qwglCreateContext( glw_state.hDC ) ) == 0 )
491: {
492: ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglCreateContext failed\n");
493:
494: goto fail;
495: }
496:
497: if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) )
498: {
499: ri.Con_Printf (PRINT_ALL, "GLimp_Init() - qwglMakeCurrent failed\n");
500:
501: goto fail;
502: }
503:
504: if ( !VerifyDriver() )
505: {
506: ri.Con_Printf( PRINT_ALL, "GLimp_Init() - no hardware acceleration detected\n" );
507: goto fail;
508: }
509:
510: /*
511: ** print out PFD specifics
512: */
513: ri.Con_Printf( PRINT_ALL, "GL PFD: color(%d-bits) Z(%d-bit)\n", ( int ) pfd.cColorBits, ( int ) pfd.cDepthBits );
514:
515: return true;
516:
517: fail:
518: if ( glw_state.hGLRC )
519: {
520: qwglDeleteContext( glw_state.hGLRC );
521: glw_state.hGLRC = NULL;
522: }
523:
524: if ( glw_state.hDC )
525: {
526: ReleaseDC( glw_state.hWnd, glw_state.hDC );
527: glw_state.hDC = NULL;
528: }
529: return false;
530: }
531:
532: /*
533: ** GLimp_BeginFrame
534: */
535: void GLimp_BeginFrame( float camera_separation )
536: {
537: if ( gl_bitdepth->modified )
538: {
539: if ( gl_bitdepth->value != 0 && !glw_state.allowdisplaydepthchange )
540: {
541: ri.Cvar_SetValue( "gl_bitdepth", 0 );
542: ri.Con_Printf( PRINT_ALL, "gl_bitdepth requires Win95 OSR2.x or WinNT 4.x\n" );
543: }
544: gl_bitdepth->modified = false;
545: }
546:
547: if ( camera_separation < 0 && gl_state.stereo_enabled )
548: {
549: qglDrawBuffer( GL_BACK_LEFT );
550: }
551: else if ( camera_separation > 0 && gl_state.stereo_enabled )
552: {
553: qglDrawBuffer( GL_BACK_RIGHT );
554: }
555: else
556: {
557: qglDrawBuffer( GL_BACK );
558: }
559: }
560:
561: /*
562: ** GLimp_EndFrame
563: **
564: ** Responsible for doing a swapbuffers and possibly for other stuff
565: ** as yet to be determined. Probably better not to make this a GLimp
566: ** function and instead do a call to GLimp_SwapBuffers.
567: */
568: void GLimp_EndFrame (void)
569: {
570: int err;
571:
572: err = qglGetError();
573: assert( err == GL_NO_ERROR );
574:
575: if ( stricmp( gl_drawbuffer->string, "GL_BACK" ) == 0 )
576: {
577: if ( !qwglSwapBuffers( glw_state.hDC ) )
578: ri.Sys_Error( ERR_FATAL, "GLimp_EndFrame() - SwapBuffers() failed!\n" );
579: }
580: }
581:
582: /*
583: ** GLimp_AppActivate
584: */
585: void GLimp_AppActivate( qboolean active )
586: {
587: if ( active )
588: {
589: SetForegroundWindow( glw_state.hWnd );
590: ShowWindow( glw_state.hWnd, SW_RESTORE );
591: }
592: else
593: {
594: if ( vid_fullscreen->value )
595: ShowWindow( glw_state.hWnd, SW_MINIMIZE );
596: }
597: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.