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