/* ** GLimp_SetMode */ rserr_t GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ) { int width, height; const char *win_fs[] = { "W", "FS" }; Com_Printf ( "Initializing OpenGL display\n"); Com_Printf ("...setting mode %d:", mode ); if ( !R_GetModeInfo( &width, &height, mode ) ) { Com_Printf ( " invalid mode\n" ); return rserr_invalid_mode; } Com_Printf ( " %d %d %s\n", width, height, win_fs[fullscreen] ); // destroy the existing window if (glw_state.hWnd) GLimp_Shutdown (); // do a CDS if needed if ( fullscreen ) { if (GLimp_SetFSMode(&width, &height)) { *pwidth = width; *pheight = height; if (!VID_CreateWindow (width, height, true)) { Com_Printf("...restoring display settings\n"); ChangeDisplaySettings( 0, 0 ); gl_state.fullscreen = false; return rserr_invalid_mode; } EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &fullScreenMode); gl_state.fullscreen = true; return rserr_ok; } } *pwidth = width; *pheight = height; Com_Printf ( "...setting windowed mode\n" ); if (gl_state.fullscreen) { ChangeDisplaySettings( 0, 0 ); gl_state.fullscreen = false; } if (!VID_CreateWindow (width, height, false)) return rserr_invalid_mode; return (fullscreen) ? rserr_invalid_fullscreen : rserr_ok; }
/* =============== GLimp_SetMode =============== */ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) { const char* glstring; int sdlcolorbits; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int samples; int i = 0; SDL_Surface *vidscreen = NULL; Uint32 flags = SDL_OPENGL; ri.Printf( PRINT_ALL, "Initializing OpenGL display\n"); if ( r_allowResize->integer ) flags |= SDL_RESIZABLE; if( videoInfo == NULL ) { static SDL_VideoInfo sVideoInfo; static SDL_PixelFormat sPixelFormat; videoInfo = SDL_GetVideoInfo( ); // Take a copy of the videoInfo Com_Memcpy( &sPixelFormat, videoInfo->vfmt, sizeof( SDL_PixelFormat ) ); sPixelFormat.palette = NULL; // Should already be the case Com_Memcpy( &sVideoInfo, videoInfo, sizeof( SDL_VideoInfo ) ); sVideoInfo.vfmt = &sPixelFormat; videoInfo = &sVideoInfo; if( videoInfo->current_h > 0 ) { // Guess the display aspect ratio through the desktop resolution // by assuming (relatively safely) that it is set at or close to // the display's native aspect ratio displayAspect = (float)videoInfo->current_w / (float)videoInfo->current_h; ri.Printf( PRINT_ALL, "Estimated display aspect: %.3f\n", displayAspect ); #ifdef __ANDROID__ R_SetNativeModeInfo( videoInfo->current_w, videoInfo->current_h ); #endif } else { ri.Printf( PRINT_ALL, "Cannot estimate display aspect, assuming 1.333\n" ); } } ri.Printf (PRINT_ALL, "...setting mode %d:", mode ); if (mode == -2) { // use desktop video resolution if( videoInfo->current_h > 0 ) { glConfig.vidWidth = videoInfo->current_w; glConfig.vidHeight = videoInfo->current_h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; ri.Printf( PRINT_ALL, "Cannot determine display resolution, assuming 640x480\n" ); } glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); if (fullscreen) { flags |= SDL_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if (noborder) flags |= SDL_NOFRAME; glConfig.isFullscreen = qfalse; } colorbits = r_colorbits->value; if ((!colorbits) || (colorbits >= 32)) colorbits = 24; if (!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; samples = r_ext_multisample->value; for (i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorbits == 24) colorbits = 16; break; case 1 : if (depthbits == 24) depthbits = 16; else if (depthbits == 16) depthbits = 8; case 3 : if (stencilbits == 24) stencilbits = 16; else if (stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ((i % 4) == 3) { // reduce colorbits if (tcolorbits == 24) tcolorbits = 16; } if ((i % 4) == 2) { // reduce depthbits if (tdepthbits == 24) tdepthbits = 16; else if (tdepthbits == 16) tdepthbits = 8; } if ((i % 4) == 1) { // reduce stencilbits if (tstencilbits == 24) tstencilbits = 16; else if (tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } sdlcolorbits = 4; if (tcolorbits == 24) sdlcolorbits = 8; #ifdef __sgi /* Fix for SGIs grabbing too many bits of color */ if (sdlcolorbits == 4) sdlcolorbits = 0; /* Use minimum size for 16-bit color */ /* Need alpha or else SGIs choose 36+ bit RGB mode */ SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 1); #endif SDL_GL_SetAttribute( SDL_GL_RED_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, tdepthbits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, tstencilbits ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); if(r_stereoEnabled->integer) { glConfig.stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); #if 0 // See http://bugzilla.icculus.org/show_bug.cgi?id=3526 // If not allowing software GL, demand accelerated if( !r_allowSoftwareGL->integer ) { if( SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ) < 0 ) { ri.Printf( PRINT_ALL, "Unable to guarantee accelerated " "visual with libSDL < 1.2.10\n" ); } } #endif if( SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, r_swapInterval->integer ) < 0 ) ri.Printf( PRINT_ALL, "r_swapInterval requires libSDL >= 1.2.10\n" ); #ifdef USE_ICON { SDL_Surface *icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); SDL_WM_SetIcon( icon, NULL ); SDL_FreeSurface( icon ); } #endif SDL_WM_SetCaption(CLIENT_WINDOW_TITLE, CLIENT_WINDOW_MIN_TITLE); SDL_ShowCursor(0); if (!(vidscreen = SDL_SetVideoMode(glConfig.vidWidth, glConfig.vidHeight, colorbits, flags))) { ri.Printf( PRINT_DEVELOPER, "SDL_SetVideoMode failed: %s\n", SDL_GetError( ) ); continue; } opengl_context = GLimp_GetCurrentContext(); ri.Printf( PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } GLimp_DetectAvailableModes(); if (!vidscreen) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } screen = vidscreen; glstring = (char *) qglGetString (GL_RENDERER); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); return RSERR_OK; }
int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) { int sdlcolorbits; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int i = 0; Uint32 flags = SDL_OPENGL; ri.Printf(PRINT_ALL, "Initializing OpenGL display\n"); if (videoInfo == NULL) { static SDL_VideoInfo sVideoInfo; static SDL_PixelFormat sPixelFormat; videoInfo = SDL_GetVideoInfo(); // Take a copy of the videoInfo Com_Memcpy(&sPixelFormat, videoInfo->vfmt, sizeof(SDL_PixelFormat)); sPixelFormat.palette = NULL; // Should already be the case Com_Memcpy(&sVideoInfo, videoInfo, sizeof(SDL_VideoInfo)); sVideoInfo.vfmt = &sPixelFormat; videoInfo = &sVideoInfo; } if (mode == -2) { // use desktop video resolution if ( videoInfo->current_w > 0) { glConfig.vidWidth = videoInfo->current_w; glConfig.vidHeight = videoInfo->current_h; } else { glConfig.vidWidth = 800; glConfig.vidHeight = 600; ri.Printf(PRINT_ALL, "Cannot determine display resolution, assuming 800x600\n"); } glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if (!R_GetModeInfo(&glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode)) { ri.Printf(PRINT_ALL, " invalid mode\n"); return RSERR_INVALID_MODE; } ri.Printf(PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); if (fullscreen) { flags |= SDL_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if (noborder) flags |= SDL_NOFRAME; glConfig.isFullscreen = qfalse; } SDL_WM_SetCaption(WINDOW_CLASS_NAME, WINDOW_CLASS_NAME_MIN); SDL_ShowCursor(0); colorbits = r_colorbits->value; if ((!colorbits) || (colorbits >= 32)) colorbits = 24; if (!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; for (i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2: if (colorbits == 24) colorbits = 16; break; case 1: if (depthbits == 24) depthbits = 16; else if (depthbits == 16) depthbits = 8; case 3: if (stencilbits == 24) stencilbits = 16; else if (stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ((i % 4) == 3) // reduce colorbits { if (tcolorbits == 24) tcolorbits = 16; } if ((i % 4) == 2) // reduce depthbits { if (tdepthbits == 24) tdepthbits = 16; else if (tdepthbits == 16) tdepthbits = 8; } if ((i % 4) == 1) // reduce stencilbits { if (tstencilbits == 24) tstencilbits = 16; else if (tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } sdlcolorbits = 4; if (tcolorbits == 24) sdlcolorbits = 8; SDL_GL_SetAttribute(SDL_GL_RED_SIZE, sdlcolorbits); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, sdlcolorbits); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, sdlcolorbits); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, tdepthbits); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, tstencilbits); glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if (!(SDLvidscreen = SDL_SetVideoMode(glConfig.vidWidth, glConfig.vidHeight, colorbits, flags))) continue; ri.Printf(PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } if (!SDLvidscreen) { ri.Printf(PRINT_ALL, "Couldn't get a visual\n"); return RSERR_INVALID_MODE; } return RSERR_OK; }
static qbool GLW_SetMode( qbool cdsFullscreen ) { HDC hDC = GetDC( GetDesktopWindow() ); glw_state.desktopBPP = GetDeviceCaps( hDC, BITSPIXEL ); glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES ); glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES ); ReleaseDC( GetDesktopWindow(), hDC ); glInfo.isFullscreen = cdsFullscreen; if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect ) ) { if (!glInfo.isFullscreen) { Cvar_SetValue( "vid_xpos", 0 ); Cvar_SetValue( "vid_ypos", 0 ); } glConfig.vidWidth = glw_state.desktopWidth; glConfig.vidHeight = glw_state.desktopHeight; glConfig.windowAspect = (float)glConfig.vidWidth / glConfig.vidHeight; cdsFullscreen = qfalse; } //ri.Printf( PRINT_DEVELOPER, "...setting mode %dx%d %s\n", glConfig.vidWidth, glConfig.vidHeight, cdsFullscreen ? "FS" : "W" ); DEVMODE dm; memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); if (cdsFullscreen != glw_state.cdsFullscreen) { if (cdsFullscreen) { dm.dmPelsWidth = glConfig.vidWidth; dm.dmPelsHeight = glConfig.vidHeight; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if ( r_displayRefresh->integer ) { dm.dmDisplayFrequency = r_displayRefresh->integer; dm.dmFields |= DM_DISPLAYFREQUENCY; } if ( r_colorbits->integer ) { dm.dmBitsPerPel = r_colorbits->integer; dm.dmFields |= DM_BITSPERPEL; } glInfo.isFullscreen = qtrue; glw_state.cdsFullscreen = qtrue; if (!GLW_Fullscreen( dm )) { glInfo.isFullscreen = qfalse; glw_state.cdsFullscreen = qfalse; } } else { ChangeDisplaySettings( 0, 0 ); glw_state.cdsFullscreen = qfalse; } } if (!GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, glConfig.colorBits )) return qfalse; if (EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm )) glInfo.displayFrequency = dm.dmDisplayFrequency; GLW_AttemptFSAA(); return qtrue; }
/* =============== GLimp_SetMode =============== */ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) { const char *glstring; int sdlcolorbits; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int i = 0; SDL_Surface *vidscreen = NULL; Uint32 flags = SDL_OPENGL; GLenum glewResult; ri.Printf(PRINT_ALL, "Initializing OpenGL display\n"); if(r_allowResize->integer) flags |= SDL_RESIZABLE; if(videoInfo == NULL) { static SDL_VideoInfo sVideoInfo; static SDL_PixelFormat sPixelFormat; videoInfo = SDL_GetVideoInfo(); // Take a copy of the videoInfo Com_Memcpy(&sPixelFormat, videoInfo->vfmt, sizeof(SDL_PixelFormat)); sPixelFormat.palette = NULL; // Should already be the case Com_Memcpy(&sVideoInfo, videoInfo, sizeof(SDL_VideoInfo)); sVideoInfo.vfmt = &sPixelFormat; videoInfo = &sVideoInfo; if(videoInfo->current_h > 0) { // Guess the display aspect ratio through the desktop resolution // by assuming (relatively safely) that it is set at or close to // the display's native aspect ratio displayAspect = (float)videoInfo->current_w / (float)videoInfo->current_h; ri.Printf(PRINT_ALL, "Estimated display aspect: %.3f\n", displayAspect); } else { ri.Printf(PRINT_ALL, "Cannot estimate display aspect, assuming 1.333\n"); } } ri.Printf(PRINT_ALL, "...setting mode %d:", mode); if(!R_GetModeInfo(&glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode)) { ri.Printf(PRINT_ALL, " invalid mode\n"); return RSERR_INVALID_MODE; } ri.Printf(PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); if(fullscreen) { flags |= SDL_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if(noborder) flags |= SDL_NOFRAME; glConfig.isFullscreen = qfalse; } colorbits = r_colorbits->value; if((!colorbits) || (colorbits >= 32)) colorbits = 24; if(!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; for(i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2: if(colorbits == 24) colorbits = 16; break; case 1: if(depthbits == 24) depthbits = 16; else if(depthbits == 16) depthbits = 8; case 3: if(stencilbits == 24) stencilbits = 16; else if(stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if((i % 4) == 3) { // reduce colorbits if(tcolorbits == 24) tcolorbits = 16; } if((i % 4) == 2) { // reduce depthbits if(tdepthbits == 24) tdepthbits = 16; else if(tdepthbits == 16) tdepthbits = 8; } if((i % 4) == 1) { // reduce stencilbits if(tstencilbits == 24) tstencilbits = 16; else if(tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } sdlcolorbits = 4; if(tcolorbits == 24) sdlcolorbits = 8; SDL_GL_SetAttribute(SDL_GL_RED_SIZE, sdlcolorbits); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, sdlcolorbits); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, sdlcolorbits); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, tdepthbits); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, tstencilbits); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if(SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, r_swapInterval->integer) < 0) ri.Printf(PRINT_ALL, "r_swapInterval requires libSDL >= 1.2.10\n"); #ifdef USE_ICON { SDL_Surface *icon = SDL_CreateRGBSurfaceFrom((void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); SDL_WM_SetIcon(icon, NULL); SDL_FreeSurface(icon); } #endif SDL_WM_SetCaption(CLIENT_WINDOW_TITLE, CLIENT_WINDOW_MIN_TITLE); SDL_ShowCursor(0); if(!(vidscreen = SDL_SetVideoMode(glConfig.vidWidth, glConfig.vidHeight, colorbits, flags))) { ri.Printf(PRINT_DEVELOPER, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); continue; } ri.Printf(PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } glewResult = glewInit(); if(GLEW_OK != glewResult) { // glewInit failed, something is seriously wrong ri.Error(ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem: %s", glewGetErrorString(glewResult)); } else { ri.Printf(PRINT_ALL, "Using GLEW %s\n", glewGetString(GLEW_VERSION)); } GLimp_InitOpenGL3xContext(); GLimp_DetectAvailableModes(); if(!vidscreen) { ri.Printf(PRINT_ALL, "Couldn't get a visual\n"); return RSERR_INVALID_MODE; } screen = vidscreen; glstring = (char *)glGetString(GL_RENDERER); ri.Printf(PRINT_ALL, "GL_RENDERER: %s\n", glstring); return RSERR_OK; }
/* ** GLW_SetMode */ static rserr_t GLW_SetMode( const char *drivername, int mode, int colorbits, qboolean cdsFullscreen ) { HDC hDC; const char *win_fs[] = { "W", "FS" }; int cdsRet; DEVMODE dm; // // print out informational messages // ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, win_fs[cdsFullscreen] ); // // check our desktop attributes // hDC = GetDC( GetDesktopWindow() ); glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES ); glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES ); ReleaseDC( GetDesktopWindow(), hDC ); // // verify desktop bit depth // if ( glConfig.driverType != GLDRV_VOODOO ) { if ( glw_state.desktopBitsPixel < 15 || glw_state.desktopBitsPixel == 24 ) { if ( colorbits == 0 || ( !cdsFullscreen && colorbits >= 15 ) ) { if ( MessageBox( NULL, "It is highly unlikely that a correct\n" "windowed display can be initialized with\n" "the current desktop display depth. Select\n" "'OK' to try anyway. Press 'Cancel' if you\n" "have a 3Dfx Voodoo, Voodoo-2, or Voodoo Rush\n" "3D accelerator installed, or if you otherwise\n" "wish to quit.", "Low Desktop Color Depth", MB_OKCANCEL | MB_ICONEXCLAMATION ) != IDOK ) { return RSERR_INVALID_MODE; } } } } // do a CDS if needed if ( cdsFullscreen ) { memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); dm.dmPelsWidth = glConfig.vidWidth; dm.dmPelsHeight = glConfig.vidHeight; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if ( r_displayRefresh->integer != 0 ) { dm.dmDisplayFrequency = r_displayRefresh->integer; dm.dmFields |= DM_DISPLAYFREQUENCY; } // try to change color depth if possible if ( colorbits != 0 ) { if ( glw_state.allowdisplaydepthchange ) { dm.dmBitsPerPel = colorbits; dm.dmFields |= DM_BITSPERPEL; ri.Printf( PRINT_ALL, "...using colorsbits of %d\n", colorbits ); } else { ri.Printf( PRINT_ALL, "WARNING:...changing depth not supported on Win95 < pre-OSR 2.x\n" ); } } else { ri.Printf( PRINT_ALL, "...using desktop display depth of %d\n", glw_state.desktopBitsPixel ); } // // if we're already in fullscreen then just create the window // if ( glw_state.cdsFullscreen ) { ri.Printf( PRINT_ALL, "...already fullscreen, avoiding redundant CDS\n" ); if ( !GLW_CreateWindow ( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue ) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } } // // need to call CDS // else { ri.Printf( PRINT_ALL, "...calling CDS: " ); // try setting the exact mode requested, because some drivers don't report // the low res modes in EnumDisplaySettings, but still work if ( ( cdsRet = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { ri.Printf( PRINT_ALL, "ok\n" ); if ( !GLW_CreateWindow ( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } glw_state.cdsFullscreen = qtrue; } else { // // the exact mode failed, so scan EnumDisplaySettings for the next largest mode // DEVMODE devmode; int modeNum; ri.Printf( PRINT_ALL, "failed, " ); PrintCDSError( cdsRet ); ri.Printf( PRINT_ALL, "...trying next higher resolution:" ); // we could do a better matching job here... for ( modeNum = 0 ; ; modeNum++ ) { if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { modeNum = -1; break; } if ( devmode.dmPelsWidth >= glConfig.vidWidth && devmode.dmPelsHeight >= glConfig.vidHeight && devmode.dmBitsPerPel >= 15 ) { break; } } if ( modeNum != -1 && ( cdsRet = ChangeDisplaySettings( &devmode, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { ri.Printf( PRINT_ALL, " ok\n" ); if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } glw_state.cdsFullscreen = qtrue; } else { ri.Printf( PRINT_ALL, " failed, " ); PrintCDSError( cdsRet ); ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); glw_state.cdsFullscreen = qfalse; glConfig.isFullscreen = qfalse; if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse) ) { return RSERR_INVALID_MODE; } return RSERR_INVALID_FULLSCREEN; } } } } else { if ( glw_state.cdsFullscreen ) { ChangeDisplaySettings( 0, 0 ); } glw_state.cdsFullscreen = qfalse; if ( !GLW_CreateWindow( drivername, glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse ) ) { return RSERR_INVALID_MODE; } } // // success, now check display frequency, although this won't be valid on Voodoo(2) // memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); if ( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm ) ) { glConfig.displayFrequency = dm.dmDisplayFrequency; } // NOTE: this is overridden later on standalone 3Dfx drivers glConfig.isFullscreen = cdsFullscreen; return RSERR_OK; }
rserr_t GLimp_SetMode( int mode, int colorbits, bool fullscreen ) { if ( !XInitThreads() ) { common->Printf( "...XInitThreads() failed, disabling r_smp\n" ); Cvar_Set( "r_smp", "0" ); } // set up our custom error handler for X failures XSetErrorHandler( &qXErrorHandler ); if ( fullscreen && in_nograb->value ) { common->Printf( "Fullscreen not allowed with in_nograb 1\n" ); Cvar_Set( "r_fullscreen", "0" ); r_fullscreen->modified = false; fullscreen = false; } common->Printf( "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { common->Printf( " invalid mode\n" ); return RSERR_INVALID_MODE; } common->Printf( " %d %d\n", glConfig.vidWidth, glConfig.vidHeight ); // open the display if ( !( dpy = XOpenDisplay( NULL ) ) ) { fprintf( stderr, "Error couldn't open the X display\n" ); return RSERR_INVALID_MODE; } scrnum = DefaultScreen( dpy ); Window root = RootWindow( dpy, scrnum ); // Get video mode list if ( !XF86VidModeQueryVersion( dpy, &vidmode_MajorVersion, &vidmode_MinorVersion ) ) { vidmode_ext = false; } else { common->Printf( "Using XFree86-VidModeExtension Version %d.%d\n", vidmode_MajorVersion, vidmode_MinorVersion ); vidmode_ext = true; } // Check for DGA int dga_MajorVersion = 0; int dga_MinorVersion = 0; if ( in_dgamouse->value ) { if ( !XF86DGAQueryVersion( dpy, &dga_MajorVersion, &dga_MinorVersion ) ) { // unable to query, probalby not supported common->Printf( "Failed to detect XF86DGA Mouse\n" ); Cvar_Set( "in_dgamouse", "0" ); } else { common->Printf( "XF86DGA Mouse (Version %d.%d) initialized\n", dga_MajorVersion, dga_MinorVersion ); } } int actualWidth = glConfig.vidWidth; int actualHeight = glConfig.vidHeight; if ( vidmode_ext ) { int best_fit, best_dist, dist, x, y; XF86VidModeGetAllModeLines( dpy, scrnum, &num_vidmodes, &vidmodes ); // Are we going fullscreen? If so, let's change video mode if ( fullscreen ) { best_dist = 9999999; best_fit = -1; for ( int i = 0; i < num_vidmodes; i++ ) { if ( glConfig.vidWidth > vidmodes[ i ]->hdisplay || glConfig.vidHeight > vidmodes[ i ]->vdisplay ) { continue; } x = glConfig.vidWidth - vidmodes[ i ]->hdisplay; y = glConfig.vidHeight - vidmodes[ i ]->vdisplay; dist = ( x * x ) + ( y * y ); if ( dist < best_dist ) { best_dist = dist; best_fit = i; } } if ( best_fit != -1 ) { actualWidth = vidmodes[ best_fit ]->hdisplay; actualHeight = vidmodes[ best_fit ]->vdisplay; // change to the mode XF86VidModeSwitchToMode( dpy, scrnum, vidmodes[ best_fit ] ); vidmode_active = true; // Move the viewport to top left XF86VidModeSetViewPort( dpy, scrnum, 0, 0 ); common->Printf( "XFree86-VidModeExtension Activated at %dx%d\n", actualWidth, actualHeight ); } else { fullscreen = 0; common->Printf( "XFree86-VidModeExtension: No acceptable modes found\n" ); } } else { common->Printf( "XFree86-VidModeExtension: Ignored on non-fullscreen\n" ); } } if ( !colorbits ) { colorbits = !r_colorbits->value ? 24 : r_colorbits->value; } int depthbits = !r_depthbits->value ? 24 : r_depthbits->value; int stencilbits = r_stencilbits->value; XVisualInfo* visinfo = NULL; for ( int i = 0; i < 16; i++ ) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ( ( i % 4 ) == 0 && i ) { // one pass, reduce switch ( i / 4 ) { case 2: if ( colorbits == 24 ) { colorbits = 16; } break; case 1: if ( depthbits == 24 ) { depthbits = 16; } else if ( depthbits == 16 ) { depthbits = 8; } break; case 3: if ( stencilbits == 24 ) { stencilbits = 16; } else if ( stencilbits == 16 ) { stencilbits = 8; } break; } } int tcolorbits = colorbits; int tdepthbits = depthbits; int tstencilbits = stencilbits; if ( ( i % 4 ) == 3 ) { // reduce colorbits if ( tcolorbits == 24 ) { tcolorbits = 16; } } if ( ( i % 4 ) == 2 ) { // reduce depthbits if ( tdepthbits == 24 ) { tdepthbits = 16; } else if ( tdepthbits == 16 ) { tdepthbits = 8; } } if ( ( i % 4 ) == 1 ) { // reduce stencilbits if ( tstencilbits == 24 ) { tstencilbits = 16; } else if ( tstencilbits == 16 ) { tstencilbits = 8; } else { tstencilbits = 0; } } int attrib[] = { GLX_RGBA, // 0 GLX_RED_SIZE, 4, // 1, 2 GLX_GREEN_SIZE, 4, // 3, 4 GLX_BLUE_SIZE, 4, // 5, 6 GLX_DOUBLEBUFFER, // 7 GLX_DEPTH_SIZE, 1, // 8, 9 GLX_STENCIL_SIZE, 1, // 10, 11 //GLX_SAMPLES_SGIS, 4, /* for better AA */ None }; // these match in the array enum { ATTR_RED_IDX = 2, ATTR_GREEN_IDX = 4, ATTR_BLUE_IDX = 6, ATTR_DEPTH_IDX = 9, ATTR_STENCIL_IDX = 11 }; if ( tcolorbits == 24 ) { attrib[ ATTR_RED_IDX ] = 8; attrib[ ATTR_GREEN_IDX ] = 8; attrib[ ATTR_BLUE_IDX ] = 8; } else { // must be 16 bit attrib[ ATTR_RED_IDX ] = 4; attrib[ ATTR_GREEN_IDX ] = 4; attrib[ ATTR_BLUE_IDX ] = 4; } attrib[ ATTR_DEPTH_IDX ] = tdepthbits; // default to 24 depth attrib[ ATTR_STENCIL_IDX ] = tstencilbits; visinfo = glXChooseVisual( dpy, scrnum, attrib ); if ( !visinfo ) { continue; } common->Printf( "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", attrib[ ATTR_RED_IDX ], attrib[ ATTR_GREEN_IDX ], attrib[ ATTR_BLUE_IDX ], attrib[ ATTR_DEPTH_IDX ], attrib[ ATTR_STENCIL_IDX ] ); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } if ( !visinfo ) { common->Printf( "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } // Window attributes XSetWindowAttributes attr; unsigned long mask; attr.background_pixel = BlackPixel( dpy, scrnum ); attr.border_pixel = 0; attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone ); attr.event_mask = X_MASK; if ( vidmode_active ) { mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | CWEventMask | CWOverrideRedirect; attr.override_redirect = True; attr.backing_store = NotUseful; attr.save_under = False; } else { mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; } win = XCreateWindow( dpy, root, 0, 0, actualWidth, actualHeight, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr ); XStoreName( dpy, win, R_GetTitleForWindow() ); /* GH: Don't let the window be resized */ XSizeHints sizehints; sizehints.flags = PMinSize | PMaxSize; sizehints.min_width = sizehints.max_width = actualWidth; sizehints.min_height = sizehints.max_height = actualHeight; XSetWMNormalHints( dpy, win, &sizehints ); XMapWindow( dpy, win ); if ( vidmode_active ) { XMoveWindow( dpy, win, 0, 0 ); //XRaiseWindow(dpy, win); //XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); //XFlush(dpy); // Move the viewport to top left //XF86VidModeSetViewPort(dpy, scrnum, 0, 0); } // hook to window close wm_protocols = XInternAtom( dpy, "WM_PROTOCOLS", False ); wm_delete_window = XInternAtom( dpy, "WM_DELETE_WINDOW", False ); XSetWMProtocols( dpy, win, &wm_delete_window, 1 ); XFlush( dpy ); XSync( dpy, False ); // bk001130 - from cvs1.17 (mkv) ctx = glXCreateContext( dpy, visinfo, NULL, True ); XSync( dpy, False ); // bk001130 - from cvs1.17 (mkv) /* GH: Free the visinfo after we're done with it */ XFree( visinfo ); glXMakeCurrent( dpy, win, ctx ); glConfig.deviceSupportsGamma = false; if ( vidmode_ext ) { if ( vidmode_MajorVersion < GAMMA_MINMAJOR || ( vidmode_MajorVersion == GAMMA_MINMAJOR && vidmode_MinorVersion < GAMMA_MINMINOR ) ) { common->Printf( "XF86 Gamma extension not supported in this version\n" ); } else { XF86VidModeGetGamma( dpy, scrnum, &vidmode_InitialGamma ); common->Printf( "XF86 Gamma extension initialized\n" ); glConfig.deviceSupportsGamma = true; } } // Check for software GL implementation. const char* glstring = ( char* )glGetString( GL_RENDERER ); if ( !String::ICmp( glstring, "Mesa X11" ) || !String::ICmp( glstring, "Mesa GLX Indirect" ) ) { if ( !r_allowSoftwareGL->integer ) { common->Printf( "\n\n***********************************************************\n" ); common->Printf( " You are using software Mesa (no hardware acceleration)!\n" ); common->Printf( " If this is intentional, add\n" ); common->Printf( " \"+set r_allowSoftwareGL 1\"\n" ); common->Printf( " to the command line when starting the game.\n" ); common->Printf( "***********************************************************\n" ); GLimp_Shutdown(); return RSERR_INVALID_MODE; } else { common->Printf( "...using software Mesa (r_allowSoftwareGL==1).\n" ); } } GLW_GenDefaultLists(); return RSERR_OK; }
/* =============== GLimp_SetMode =============== */ static int GLimp_SetMode(int mode, bool fullscreen, bool noborder) { const char *glstring; int perChannelColorBits; int colorBits, depthBits, stencilBits; int samples; int i = 0; SDL_Surface *icon = NULL; Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL; SDL_DisplayMode desktopMode; int display = 0; int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED; ri->Printf( PRINT_ALL, "Initializing OpenGL display\n"); if ( r_allowResize->integer ) flags |= SDL_WINDOW_RESIZABLE; #ifdef USE_ICON icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); #endif // If a window exists, note its display index if( SDL_window != NULL ) display = SDL_GetWindowDisplayIndex( SDL_window ); if( SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) { displayAspect = (float)desktopMode.w / (float)desktopMode.h; ri.Printf( PRINT_ALL, "Display aspect: %.3f\n", displayAspect ); } else { Com_Memset( &desktopMode, 0, sizeof( SDL_DisplayMode ) ); ri.Printf( PRINT_ALL, "Cannot determine display aspect, assuming 1.333\n" ); } ri->Printf (PRINT_ALL, "...setting mode %d:", mode ); if (mode == -2) { // use desktop video resolution if( desktopMode.h > 0 ) { glConfig.vidWidth = desktopMode.w; glConfig.vidHeight = desktopMode.h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; ri->Printf( PRINT_ALL, "Cannot determine display resolution, assuming 640x480\n" ); } glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri->Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri->Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); // Center window if( r_centerWindow->integer && !fullscreen ) { x = ( desktopMode.w / 2 ) - ( glConfig.vidWidth / 2 ); y = ( desktopMode.h / 2 ) - ( glConfig.vidHeight / 2 ); } // Destroy existing state if it exists if( SDL_glContext != NULL ) { SDL_GL_DeleteContext( SDL_glContext ); SDL_glContext = NULL; } if( SDL_window != NULL ) { SDL_GetWindowPosition( SDL_window, &x, &y ); ri->Printf( PRINT_DEVELOPER, "Existing window at %dx%d before being destroyed\n", x, y ); SDL_DestroyWindow( SDL_window ); SDL_window = NULL; } if( fullscreen ) { flags |= SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if( noborder ) flags |= SDL_WINDOW_BORDERLESS; glConfig.isFullscreen = false; } colorBits = r_colorbits->value; if ((!colorBits) || (colorBits >= 32)) colorBits = 24; if (!r_depthbits->value) depthBits = 24; else depthBits = r_depthbits->value; stencilBits = r_stencilbits->value; samples = r_ext_multisample->value; for (i = 0; i < 16; i++) { int testColorBits, testDepthBits, testStencilBits; // 0 - default // 1 - minus colorBits // 2 - minus depthBits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorBits == 24) colorBits = 16; break; case 1 : if (depthBits == 24) depthBits = 16; else if (depthBits == 16) depthBits = 8; case 3 : if (stencilBits == 24) stencilBits = 16; else if (stencilBits == 16) stencilBits = 8; } } testColorBits = colorBits; testDepthBits = depthBits; testStencilBits = stencilBits; if ((i % 4) == 3) { // reduce colorBits if (testColorBits == 24) testColorBits = 16; } if ((i % 4) == 2) { // reduce depthBits if (testDepthBits == 24) testDepthBits = 16; else if (testDepthBits == 16) testDepthBits = 8; } if ((i % 4) == 1) { // reduce stencilBits if (testStencilBits == 24) testStencilBits = 16; else if (testStencilBits == 16) testStencilBits = 8; else testStencilBits = 0; } if (testColorBits == 24) perChannelColorBits = 8; else perChannelColorBits = 4; #ifdef __sgi /* Fix for SGIs grabbing too many bits of color */ if (perChannelColorBits == 4) perChannelColorBits = 0; /* Use minimum size for 16-bit color */ /* Need alpha or else SGIs choose 36+ bit RGB mode */ SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 1); #endif SDL_GL_SetAttribute( SDL_GL_RED_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, testDepthBits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, testStencilBits ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); if(r_stereoEnabled->integer) { glConfig.stereoEnabled = true; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { glConfig.stereoEnabled = false; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); #if 0 // if multisampling is enabled on X11, this causes create window to fail. // If not allowing software GL, demand accelerated if( !r_allowSoftwareGL->integer ) SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); #endif if( ( SDL_window = SDL_CreateWindow( CLIENT_WINDOW_TITLE, x, y, glConfig.vidWidth, glConfig.vidHeight, flags ) ) == 0 ) { ri->Printf( PRINT_DEVELOPER, "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; } if( fullscreen ) { SDL_DisplayMode mode; switch( testColorBits ) { case 16: mode.format = SDL_PIXELFORMAT_RGB565; break; case 24: mode.format = SDL_PIXELFORMAT_RGB24; break; default: ri.Printf( PRINT_DEVELOPER, "testColorBits is %d, can't fullscreen\n", testColorBits ); continue; } mode.w = glConfig.vidWidth; mode.h = glConfig.vidHeight; mode.refresh_rate = glConfig.displayFrequency = ri->Cvar_VariableIntegerValue( "r_displayRefresh" ); mode.driverdata = NULL; if( SDL_SetWindowDisplayMode( SDL_window, &mode ) < 0 ) { ri.Printf( PRINT_DEVELOPER, "SDL_SetWindowDisplayMode failed: %s\n", SDL_GetError( ) ); continue; } } SDL_SetWindowIcon( SDL_window, icon ); if( ( SDL_glContext = SDL_GL_CreateContext( SDL_window ) ) == NULL ) { ri->Printf( PRINT_DEVELOPER, "SDL_GL_CreateContext failed: %s\n", SDL_GetError( ) ); continue; } SDL_GL_SetSwapInterval( r_swapInterval->integer ); glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; glConfig.stencilBits = testStencilBits; ri->Printf( PRINT_ALL, "Using %d color bits, %d depth, %d stencil display.\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); break; } SDL_FreeSurface( icon ); if( !SDL_window ) { ri->Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } GLimp_DetectAvailableModes(); glstring = (char *) qglGetString (GL_RENDERER); ri->Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); return RSERR_OK; }
/* =============== GLimp_SetMode =============== */ static rserr_t GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) { const char *glstring; int perChannelColorBits; int colorBits, depthBits, stencilBits; int samples; int i = 0; SDL_Surface *icon = NULL; Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL; SDL_DisplayMode desktopMode; int display = 0; int x = 0, y = 0; Com_Printf( "Initializing OpenGL display\n"); if ( r_allowResize->integer ) flags |= SDL_WINDOW_RESIZABLE; /*icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif );*/ // If a window exists, note its display index if( screen != NULL ) display = SDL_GetWindowDisplayIndex( screen ); if( SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) { displayAspect = (float)desktopMode.w / (float)desktopMode.h; Com_Printf( "Display aspect: %.3f\n", displayAspect ); } else { Com_Memset( &desktopMode, 0, sizeof( SDL_DisplayMode ) ); Com_Printf( "Cannot determine display aspect, assuming 1.333\n" ); } Com_Printf( "...setting mode %d:", mode ); if (mode == -2) { // use desktop video resolution if( desktopMode.h > 0 ) { glConfig.vidWidth = desktopMode.w; glConfig.vidHeight = desktopMode.h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; Com_Printf( "Cannot determine display resolution, assuming 640x480\n" ); } //glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, /*&glConfig.windowAspect,*/ mode ) ) { Com_Printf( " invalid mode\n" ); return RSERR_INVALID_MODE; } Com_Printf( " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); // Center window if( r_centerWindow->integer && !fullscreen ) { x = ( desktopMode.w / 2 ) - ( glConfig.vidWidth / 2 ); y = ( desktopMode.h / 2 ) - ( glConfig.vidHeight / 2 ); } // Destroy existing state if it exists if( opengl_context != NULL ) { SDL_GL_DeleteContext( opengl_context ); opengl_context = NULL; } if( screen != NULL ) { SDL_GetWindowPosition( screen, &x, &y ); ri.Printf( PRINT_DEVELOPER, "Existing window at %dx%d before being destroyed\n", x, y ); SDL_DestroyWindow( screen ); screen = NULL; } if( fullscreen ) { flags |= SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if( noborder ) flags |= SDL_WINDOW_BORDERLESS; glConfig.isFullscreen = qfalse; } colorBits = r_colorbits->value; if ((!colorBits) || (colorBits >= 32)) colorBits = 24; if (!r_depthbits->value) depthBits = 24; else depthBits = r_depthbits->value; stencilBits = r_stencilbits->value; //samples = r_ext_multisample->value; for (i = 0; i < 16; i++) { int testColorBits, testDepthBits, testStencilBits; // 0 - default // 1 - minus colorBits // 2 - minus depthBits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorBits == 24) colorBits = 16; break; case 1 : if (depthBits == 24) depthBits = 16; else if (depthBits == 16) depthBits = 8; case 3 : if (stencilBits == 24) stencilBits = 16; else if (stencilBits == 16) stencilBits = 8; } } testColorBits = colorBits; testDepthBits = depthBits; testStencilBits = stencilBits; if ((i % 4) == 3) { // reduce colorBits if (testColorBits == 24) testColorBits = 16; } if ((i % 4) == 2) { // reduce depthBits if (testDepthBits == 24) testDepthBits = 16; else if (testDepthBits == 16) testDepthBits = 8; } if ((i % 4) == 1) { // reduce stencilBits if (testStencilBits == 24) testStencilBits = 16; else if (testStencilBits == 16) testStencilBits = 8; else testStencilBits = 0; } if (testColorBits == 24) perChannelColorBits = 8; else perChannelColorBits = 4; #ifdef __sgi /* Fix for SGIs grabbing too many bits of color */ if (perChannelColorBits == 4) perChannelColorBits = 0; /* Use minimum size for 16-bit color */ /* Need alpha or else SGIs choose 36+ bit RGB mode */ SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 1); #endif SDL_GL_SetAttribute( SDL_GL_RED_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, testDepthBits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, testStencilBits ); /*SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples );*/ if(r_stereo->integer) { glConfig.stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // If not allowing software GL, demand accelerated if( !r_allowSoftwareGL->integer ) SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); if( ( screen = SDL_CreateWindow( CLIENT_WINDOW_TITLE, x, y, glConfig.vidWidth, glConfig.vidHeight, flags ) ) == 0 ) { ri.Printf( PRINT_DEVELOPER, "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; } if( fullscreen ) { SDL_DisplayMode mode; switch( testColorBits ) { case 16: mode.format = SDL_PIXELFORMAT_RGB565; break; case 24: mode.format = SDL_PIXELFORMAT_RGB24; break; default: ri.Printf( PRINT_DEVELOPER, "testColorBits is %d, can't fullscreen\n", testColorBits ); continue; } mode.w = glConfig.vidWidth; mode.h = glConfig.vidHeight; mode.refresh_rate = glConfig.displayFrequency = ri.Cvar_VariableIntegerValue( "r_displayRefresh" ); mode.driverdata = NULL; if( SDL_SetWindowDisplayMode( screen, &mode ) < 0 ) { ri.Printf( PRINT_DEVELOPER, "SDL_SetWindowDisplayMode failed: %s\n", SDL_GetError( ) ); continue; } } SDL_SetWindowTitle( screen, CLIENT_WINDOW_TITLE ); SDL_SetWindowIcon( screen, icon ); if( ( opengl_context = (QGLContext)SDL_GL_CreateContext( screen ) ) == NULL ) { Com_Printf( "SDL_GL_CreateContext failed: %s\n", SDL_GetError( ) ); continue; } if( SDL_GL_MakeCurrent( screen, opengl_context ) < 0 ) { Com_Printf( "SDL_GL_MakeCurrent failed: %s\n", SDL_GetError( ) ); continue; } SDL_GL_SetSwapInterval( r_swapInterval->integer ); glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; glConfig.stencilBits = testStencilBits; Com_Printf( "Using %d color bits, %d depth, %d stencil display.\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); break; } /*SDL_FreeSurface( icon );*/ GLimp_DetectAvailableModes(); glstring = (char *) qglGetString (GL_RENDERER); Com_Printf( "GL_RENDERER: %s\n", glstring ); return RSERR_OK; #if 0 const char* glstring; int sdlcolorbits; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int samples; int i = 0; Uint32 flags = SDL_WINDOW_OPENGL; Com_Printf( "Initializing OpenGL display\n"); if ( r_allowResize->integer ) flags |= SDL_WINDOW_RESIZABLE; if( videoInfo == NULL ) { static SDL_DisplayMode sVideoInfo; static SDL_PixelFormat sPixelFormat; if (SDL_GetCurrentDisplayMode( 0, &sVideoInfo ) < 0) Com_Error(ERR_FATAL, "SDL_GetCurrentDisplayMode failed : %s\n", SDL_GetError()); // Take a copy of the videoInfo sPixelFormat.format = sVideoInfo.format; sPixelFormat.palette = NULL; // Should already be the case //Com_Memcpy( &sVideoInfo, videoInfo, sizeof( SDL_DisplayMode ) ); sVideoInfo.format = sPixelFormat.format; videoInfo = &sVideoInfo; if( videoInfo->h > 0 ) { glConfig.displayWidth = videoInfo->w; glConfig.displayHeight = videoInfo->h; // Guess the display aspect ratio through the desktop resolution // by assuming (relatively safely) that it is set at or close to // the display's native aspect ratio glConfig.displayAspect = (float)videoInfo->w / (float)videoInfo->h; Com_Printf( "Estimated display aspect: %.3f\n", glConfig.displayAspect ); } else { glConfig.displayWidth = 480; glConfig.displayHeight = 640; glConfig.displayAspect = 1.333f; Com_Printf( "Cannot estimate display resolution/aspect, assuming 640x480/1.333\n" ); } } Com_Printf( "...setting mode %d:", mode ); if (mode == -2) { // use desktop video resolution if( videoInfo->h > 0 ) { glConfig.vidWidth = videoInfo->w; glConfig.vidHeight = videoInfo->h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; Com_Printf( "Cannot determine display resolution, assuming 640x480\n" ); } glConfig.displayAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, /*&glConfig.displayAspect,*/ mode ) ) { Com_Printf( " invalid mode\n" ); return RSERR_INVALID_MODE; } Com_Printf( " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); if (fullscreen) { flags |= SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { if (noborder) flags |= SDL_WINDOW_BORDERLESS; glConfig.isFullscreen = qfalse; } colorbits = r_colorbits->value; if ((!colorbits) || (colorbits >= 32)) colorbits = 24; if (!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; //samples = r_ext_multisample->value; for (i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorbits == 24) colorbits = 16; break; case 1 : if (depthbits == 24) depthbits = 16; else if (depthbits == 16) depthbits = 8; case 3 : if (stencilbits == 24) stencilbits = 16; else if (stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ((i % 4) == 3) { // reduce colorbits if (tcolorbits == 24) tcolorbits = 16; } if ((i % 4) == 2) { // reduce depthbits if (tdepthbits == 24) tdepthbits = 16; else if (tdepthbits == 16) tdepthbits = 8; } if ((i % 4) == 1) { // reduce stencilbits if (tstencilbits == 24) tstencilbits = 16; else if (tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } sdlcolorbits = 4; if (tcolorbits == 24) sdlcolorbits = 8; #ifdef __sgi /* Fix for SGIs grabbing too many bits of color */ if (sdlcolorbits == 4) sdlcolorbits = 0; /* Use minimum size for 16-bit color */ /* Need alpha or else SGIs choose 36+ bit RGB mode */ SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 1); #endif SDL_GL_SetAttribute( SDL_GL_RED_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, tdepthbits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, tstencilbits ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); /*if(r_stereoEnabled->integer) { glConfig.stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else {*/ glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); //} SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); #if 0 // See http://bugzilla.icculus.org/show_bug.cgi?id=3526 // If not allowing software GL, demand accelerated if( !r_allowSoftwareGL->integer ) { if( SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ) < 0 ) { Com_Printf( "Unable to guarantee accelerated " "visual with libSDL < 1.2.10\n" ); } } #endif if( SDL_GL_SetSwapInterval(r_swapInterval->integer ) < 0 ) Com_Printf( "SDL_GL_SetSwapInterval not supported\n" ); #ifdef USE_ICON { SDL_Surface *icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); SDL_WM_SetIcon( icon, NULL ); SDL_FreeSurface( icon ); } #endif SDL_ShowCursor(0); if (!(window = SDL_CreateWindow(CLIENT_WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, glConfig.vidWidth, glConfig.vidHeight, flags))) { Com_Printf( "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; } opengl_context = SDL_GL_CreateContext(window); Com_Printf( "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } GLimp_DetectAvailableModes(); if (!window) { Com_Printf( "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } screen = window; // FIXME: Defines needed here glstring = (char *) qglGetString (GL_RENDERER); Com_Printf( "GL_RENDERER: %s\n", glstring ); return RSERR_OK; #endif }
rserr_t GLimp_SetMode( int mode, int colorbits, bool fullscreen ) { const char* win_fs[] = { "W", "FS" }; // // print out informational messages // common->Printf( "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { common->Printf( " invalid mode\n" ); return RSERR_INVALID_MODE; } common->Printf( " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, win_fs[ fullscreen ] ); // // check our desktop attributes // HDC hDC = GetDC( GetDesktopWindow() ); desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); desktopWidth = GetDeviceCaps( hDC, HORZRES ); desktopHeight = GetDeviceCaps( hDC, VERTRES ); ReleaseDC( GetDesktopWindow(), hDC ); // // verify desktop bit depth // if ( desktopBitsPixel < 15 || desktopBitsPixel == 24 ) { if ( colorbits == 0 || ( !cdsFullscreen && colorbits >= 15 ) ) { if ( MessageBox( NULL, "It is highly unlikely that a correct\n" "windowed display can be initialized with\n" "the current desktop display depth. Select\n" "'OK' to try anyway. Press 'Cancel' if you otherwise\n" "wish to quit.", "Low Desktop Color Depth", MB_OKCANCEL | MB_ICONEXCLAMATION ) != IDOK ) { return RSERR_INVALID_MODE; } } } DEVMODE dm; // do a CDS if needed if ( fullscreen ) { Com_Memset( &dm, 0, sizeof ( dm ) ); dm.dmSize = sizeof ( dm ); dm.dmPelsWidth = glConfig.vidWidth; dm.dmPelsHeight = glConfig.vidHeight; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if ( r_displayRefresh->integer != 0 ) { dm.dmDisplayFrequency = r_displayRefresh->integer; dm.dmFields |= DM_DISPLAYFREQUENCY; } // try to change color depth if possible if ( colorbits != 0 ) { dm.dmBitsPerPel = colorbits; dm.dmFields |= DM_BITSPERPEL; common->Printf( "...using colorsbits of %d\n", colorbits ); } else { common->Printf( "...using desktop display depth of %d\n", desktopBitsPixel ); } // // If we're already in fullscreen then just create the window. // if ( cdsFullscreen ) { common->Printf( "...already fullscreen, avoiding redundant CDS\n" ); if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, true ) ) { common->Printf( "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); cdsFullscreen = false; return RSERR_INVALID_MODE; } } // // need to call CDS // else { common->Printf( "...calling CDS: " ); // try setting the exact mode requested, because some drivers don't report // the low res modes in EnumDisplaySettings, but still work int cdsRet = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ); if ( cdsRet == DISP_CHANGE_SUCCESSFUL ) { common->Printf( "ok\n" ); if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, true ) ) { common->Printf( "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } cdsFullscreen = true; } else { common->Printf( "failed, " ); PrintCDSError( cdsRet ); // // the exact mode failed, so scan EnumDisplaySettings for the next largest mode // common->Printf( "...trying next higher resolution:" ); // we could do a better matching job here... DEVMODE devmode; int modeNum; for ( modeNum = 0;; modeNum++ ) { if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { modeNum = -1; break; } if ( devmode.dmPelsWidth >= glConfig.vidWidth && devmode.dmPelsHeight >= glConfig.vidHeight && devmode.dmBitsPerPel >= 15 ) { break; } } if ( modeNum != -1 ) { cdsRet = ChangeDisplaySettings( &devmode, CDS_FULLSCREEN ); } if ( modeNum != -1 && cdsRet == DISP_CHANGE_SUCCESSFUL ) { common->Printf( " ok\n" ); if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, true ) ) { common->Printf( "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } cdsFullscreen = true; } else { common->Printf( " failed, " ); PrintCDSError( cdsRet ); common->Printf( "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); cdsFullscreen = false; glConfig.isFullscreen = false; if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, false ) ) { return RSERR_INVALID_MODE; } return RSERR_INVALID_FULLSCREEN; } } } } else { if ( cdsFullscreen ) { ChangeDisplaySettings( 0, 0 ); } cdsFullscreen = false; if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, false ) ) { return RSERR_INVALID_MODE; } } // // success, now check display frequency // Com_Memset( &dm, 0, sizeof ( dm ) ); dm.dmSize = sizeof ( dm ); if ( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm ) ) { glConfig.displayFrequency = dm.dmDisplayFrequency; } glConfig.isFullscreen = fullscreen; return RSERR_OK; }
/* ** GLW_SetMode */ int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen ) { int attrib[] = { GLX_RGBA, // 0 GLX_RED_SIZE, 4, // 1, 2 GLX_GREEN_SIZE, 4, // 3, 4 GLX_BLUE_SIZE, 4, // 5, 6 GLX_DOUBLEBUFFER, // 7 GLX_DEPTH_SIZE, 1, // 8, 9 GLX_STENCIL_SIZE, 1, // 10, 11 None }; // these match in the array #define ATTR_RED_IDX 2 #define ATTR_GREEN_IDX 4 #define ATTR_BLUE_IDX 6 #define ATTR_DEPTH_IDX 9 #define ATTR_STENCIL_IDX 11 Window root; XVisualInfo *visinfo; XSetWindowAttributes attr; unsigned long mask; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int MajorVersion, MinorVersion; int actualWidth, actualHeight; int i; r_fakeFullscreen = ri.Cvar_Get( "r_fakeFullscreen", "0", CVAR_ARCHIVE); ri.Printf( PRINT_ALL, "Initializing OpenGL display\n"); ri.Printf (PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); if (!(dpy = XOpenDisplay(NULL))) { fprintf(stderr, "Error couldn't open the X display\n"); return RSERR_INVALID_MODE; } scrnum = DefaultScreen(dpy); root = RootWindow(dpy, scrnum); actualWidth = glConfig.vidWidth; actualHeight = glConfig.vidHeight; // Get video mode list MajorVersion = MinorVersion = 0; if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { vidmode_ext = qfalse; } else { ri.Printf(PRINT_ALL, "Using XFree86-VidModeExtension Version %d.%d\n", MajorVersion, MinorVersion); vidmode_ext = qtrue; } if (vidmode_ext) { int best_fit, best_dist, dist, x, y; XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes); // Are we going fullscreen? If so, let's change video mode if (fullscreen && !r_fakeFullscreen->integer) { best_dist = 9999999; best_fit = -1; for (i = 0; i < num_vidmodes; i++) { if (glConfig.vidWidth > vidmodes[i]->hdisplay || glConfig.vidHeight > vidmodes[i]->vdisplay) continue; x = glConfig.vidWidth - vidmodes[i]->hdisplay; y = glConfig.vidHeight - vidmodes[i]->vdisplay; dist = (x * x) + (y * y); if (dist < best_dist) { best_dist = dist; best_fit = i; } } if (best_fit != -1) { actualWidth = vidmodes[best_fit]->hdisplay; actualHeight = vidmodes[best_fit]->vdisplay; // change to the mode XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]); vidmode_active = qtrue; // Move the viewport to top left XF86VidModeSetViewPort(dpy, scrnum, 0, 0); } else fullscreen = 0; } } if (!r_colorbits->value) colorbits = 24; else colorbits = r_colorbits->value; if ( !Q_stricmp( r_glDriver->string, _3DFX_DRIVER_NAME ) ) colorbits = 16; if (!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; for (i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorbits == 24) colorbits = 16; break; case 1 : if (depthbits == 24) depthbits = 16; else if (depthbits == 16) depthbits = 8; case 3 : if (stencilbits == 24) stencilbits = 16; else if (stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ((i % 4) == 3) { // reduce colorbits if (tcolorbits == 24) tcolorbits = 16; } if ((i % 4) == 2) { // reduce depthbits if (tdepthbits == 24) tdepthbits = 16; else if (tdepthbits == 16) tdepthbits = 8; } if ((i % 4) == 1) { // reduce stencilbits if (tstencilbits == 24) tstencilbits = 16; else if (tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } if (tcolorbits == 24) { attrib[ATTR_RED_IDX] = 8; attrib[ATTR_GREEN_IDX] = 8; attrib[ATTR_BLUE_IDX] = 8; } else { // must be 16 bit attrib[ATTR_RED_IDX] = 4; attrib[ATTR_GREEN_IDX] = 4; attrib[ATTR_BLUE_IDX] = 4; } attrib[ATTR_DEPTH_IDX] = tdepthbits; // default to 24 depth attrib[ATTR_STENCIL_IDX] = tstencilbits; #if 0 ri.Printf( PRINT_DEVELOPER, "Attempting %d/%d/%d Color bits, %d depth, %d stencil display...", attrib[ATTR_RED_IDX], attrib[ATTR_GREEN_IDX], attrib[ATTR_BLUE_IDX], attrib[ATTR_DEPTH_IDX], attrib[ATTR_STENCIL_IDX]); #endif visinfo = qglXChooseVisual(dpy, scrnum, attrib); if (!visinfo) { #if 0 ri.Printf( PRINT_DEVELOPER, "failed\n"); #endif continue; } #if 0 ri.Printf( PRINT_DEVELOPER, "Successful\n"); #endif ri.Printf( PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", attrib[ATTR_RED_IDX], attrib[ATTR_GREEN_IDX], attrib[ATTR_BLUE_IDX], attrib[ATTR_DEPTH_IDX], attrib[ATTR_STENCIL_IDX]); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } if (!visinfo) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } /* window attributes */ attr.background_pixel = BlackPixel(dpy, scrnum); attr.border_pixel = 0; attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); attr.event_mask = X_MASK; if (vidmode_active) { mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | CWEventMask | CWOverrideRedirect; attr.override_redirect = True; attr.backing_store = NotUseful; attr.save_under = False; } else mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(dpy, root, 0, 0, actualWidth, actualHeight, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); XMapWindow(dpy, win); if (vidmode_active) XMoveWindow(dpy, win, 0, 0); // Check for DGA if (in_dgamouse->value) { if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { // unable to query, probalby not supported ri.Printf( PRINT_ALL, "Failed to detect XF86DGA Mouse\n" ); ri.Cvar_Set( "in_dgamouse", "0" ); } else ri.Printf( PRINT_ALL, "XF86DGA Mouse (Version %d.%d) initialized\n", MajorVersion, MinorVersion); } XFlush(dpy); ctx = qglXCreateContext(dpy, visinfo, NULL, True); qglXMakeCurrent(dpy, win, ctx); return RSERR_OK; }
/* =============== GLimp_SetMode =============== */ static int GLimp_SetMode( int mode, bool fullscreen, bool noborder ) { const char *glstring; int perChannelColorBits; int alphaBits, depthBits, stencilBits; int samples; int i = 0; SDL_Surface *icon = nullptr; SDL_DisplayMode desktopMode; Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL; int x, y; GLenum glewResult; ri.Printf( PRINT_ALL, "Initializing OpenGL display\n" ); if ( r_allowResize->integer ) { flags |= SDL_WINDOW_RESIZABLE; } if ( r_centerWindow->integer ) { // center window on specified display x = SDL_WINDOWPOS_CENTERED_DISPLAY( r_displayIndex->integer ); y = SDL_WINDOWPOS_CENTERED_DISPLAY( r_displayIndex->integer ); } else { x = SDL_WINDOWPOS_UNDEFINED_DISPLAY( r_displayIndex->integer ); y = SDL_WINDOWPOS_UNDEFINED_DISPLAY( r_displayIndex->integer ); } icon = SDL_CreateRGBSurfaceFrom( ( void * ) CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); if ( SDL_GetDesktopDisplayMode( r_displayIndex->integer, &desktopMode ) == 0 ) { displayAspect = ( float ) desktopMode.w / ( float ) desktopMode.h; ri.Printf( PRINT_ALL, "Display aspect: %.3f\n", displayAspect ); } else { Com_Memset( &desktopMode, 0, sizeof( SDL_DisplayMode ) ); ri.Printf( PRINT_ALL, "Cannot determine display aspect (%s), assuming 1.333\n", SDL_GetError() ); } ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( mode == -2 ) { // use desktop video resolution if ( desktopMode.h > 0 ) { glConfig.vidWidth = desktopMode.w; glConfig.vidHeight = desktopMode.h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; ri.Printf( PRINT_ALL, "Cannot determine display resolution, assuming 640x480\n" ); } glConfig.windowAspect = ( float ) glConfig.vidWidth / ( float ) glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight ); Cvar_Set( "r_customwidth", va("%d", glConfig.vidWidth ) ); Cvar_Set( "r_customheight", va("%d", glConfig.vidHeight ) ); do { if ( glContext != nullptr ) { SDL_GL_DeleteContext( glContext ); glContext = nullptr; } if ( window != nullptr ) { SDL_GetWindowPosition( window, &x, &y ); ri.Printf( PRINT_DEVELOPER, "Existing window at %dx%d before being destroyed\n", x, y ); SDL_DestroyWindow( window ); window = nullptr; } // we come back here if we couldn't get a visual and there's // something we can switch off if ( fullscreen ) { flags |= SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = true; } else { if ( noborder ) { flags |= SDL_WINDOW_BORDERLESS; } glConfig.isFullscreen = false; } colorBits = r_colorbits->integer; if ( ( !colorBits ) || ( colorBits >= 32 ) ) { colorBits = 24; } alphaBits = r_alphabits->integer; if ( alphaBits < 0 ) { alphaBits = 0; } depthBits = r_depthbits->integer; if ( !depthBits ) { depthBits = 24; } stencilBits = r_stencilbits->integer; samples = r_ext_multisample->integer; for ( i = 0; i < 16; i++ ) { int testColorBits, testDepthBits, testStencilBits; // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ( ( i % 4 ) == 0 && i ) { // one pass, reduce switch ( i / 4 ) { case 2: if ( colorBits == 24 ) { colorBits = 16; } break; case 1: if ( depthBits == 24 ) { depthBits = 16; } else if ( depthBits == 16 ) { depthBits = 8; } case 3: if ( stencilBits == 24 ) { stencilBits = 16; } else if ( stencilBits == 16 ) { stencilBits = 8; } } } testColorBits = colorBits; testDepthBits = depthBits; testStencilBits = stencilBits; if ( ( i % 4 ) == 3 ) { // reduce colorbits if ( testColorBits == 24 ) { testColorBits = 16; } } if ( ( i % 4 ) == 2 ) { // reduce depthbits if ( testDepthBits == 24 ) { testDepthBits = 16; } else if ( testDepthBits == 16 ) { testDepthBits = 8; } } if ( ( i % 4 ) == 1 ) { // reduce stencilbits if ( testStencilBits == 24 ) { testStencilBits = 16; } else if ( testStencilBits == 16 ) { testStencilBits = 8; } else { testStencilBits = 0; } } if ( testColorBits == 24 ) { perChannelColorBits = 8; } else { perChannelColorBits = 4; } SDL_GL_SetAttribute( SDL_GL_RED_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, alphaBits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, testDepthBits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, testStencilBits ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); if ( !r_glAllowSoftware->integer ) { SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); } if ( r_glCoreProfile->integer || r_glDebugProfile->integer ) { int major = r_glMajorVersion->integer; int minor = r_glMinorVersion->integer; SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, major ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, minor ); if ( r_glCoreProfile->integer ) { SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); } else { SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY ); } if ( r_glDebugProfile->integer ) { SDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG ); } } window = SDL_CreateWindow( CLIENT_WINDOW_TITLE, x, y, glConfig.vidWidth, glConfig.vidHeight, flags ); if ( !window ) { ri.Printf( PRINT_DEVELOPER, "SDL_CreateWindow failed: %s\n", SDL_GetError() ); continue; } SDL_SetWindowIcon( window, icon ); glContext = SDL_GL_CreateContext( window ); if ( !glContext ) { ri.Printf( PRINT_DEVELOPER, "SDL_GL_CreateContext failed: %s\n", SDL_GetError() ); continue; } SDL_GL_SetSwapInterval( r_swapInterval->integer ); glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; glConfig.stencilBits = testStencilBits; ri.Printf( PRINT_ALL, "Using %d Color bits, %d depth, %d stencil display.\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); break; } if ( samples && ( !glContext || !window ) ) { r_ext_multisample->integer = 0; } } while ( ( !glContext || !window ) && samples ); SDL_FreeSurface( icon ); glewResult = glewInit(); if ( glewResult != GLEW_OK ) { // glewInit failed, something is seriously wrong ri.Error( ERR_FATAL, "GLW_StartOpenGL() - could not load OpenGL subsystem: %s", glewGetErrorString( glewResult ) ); } else { ri.Printf( PRINT_ALL, "Using GLEW %s\n", glewGetString( GLEW_VERSION ) ); } int GLmajor, GLminor; sscanf( ( const char * ) glGetString( GL_VERSION ), "%d.%d", &GLmajor, &GLminor ); if ( GLmajor < 2 || ( GLmajor == 2 && GLminor < 1 ) ) { // missing shader support, switch to 1.x renderer return RSERR_OLD_GL; } if ( GLmajor < 3 || ( GLmajor == 3 && GLminor < 2 ) ) { // shaders are supported, but not all GL3.x features ri.Printf( PRINT_ALL, "Using enhanced (GL3) Renderer in GL 2.x mode...\n" ); } else { ri.Printf( PRINT_ALL, "Using enhanced (GL3) Renderer in GL 3.x mode...\n" ); glConfig.driverType = GLDRV_OPENGL3; } GLimp_DetectAvailableModes(); glstring = ( char * ) glGetString( GL_RENDERER ); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); return RSERR_OK; }
/* ** GLW_SetMode */ int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen ) { int attrib[] = { GLX_RGBA, // 0 GLX_RED_SIZE, 4, // 1, 2 GLX_GREEN_SIZE, 4, // 3, 4 GLX_BLUE_SIZE, 4, // 5, 6 GLX_DOUBLEBUFFER, // 7 GLX_DEPTH_SIZE, 1, // 8, 9 GLX_STENCIL_SIZE, 1, // 10, 11 None }; // these match in the array #define ATTR_RED_IDX 2 #define ATTR_GREEN_IDX 4 #define ATTR_BLUE_IDX 6 #define ATTR_DEPTH_IDX 9 #define ATTR_STENCIL_IDX 11 Window root; XVisualInfo *visinfo; XSetWindowAttributes attr; XSizeHints sizehints; unsigned long mask; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int dga_MajorVersion, dga_MinorVersion; int actualWidth, actualHeight; int i; const char* glstring; // bk001130 - from cvs1.17 (mkv) ri.Printf( PRINT_ALL, "Initializing OpenGL display\n" ); ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight ); if ( !( dpy = XOpenDisplay( NULL ) ) ) { fprintf( stderr, "Error couldn't open the X display\n" ); return RSERR_INVALID_MODE; } scrnum = DefaultScreen( dpy ); root = RootWindow( dpy, scrnum ); actualWidth = glConfig.vidWidth; actualHeight = glConfig.vidHeight; // Get video mode list if ( !XF86VidModeQueryVersion( dpy, &vidmode_MajorVersion, &vidmode_MinorVersion ) ) { vidmode_ext = qfalse; } else { ri.Printf( PRINT_ALL, "Using XFree86-VidModeExtension Version %d.%d\n", vidmode_MajorVersion, vidmode_MinorVersion ); vidmode_ext = qtrue; } // Check for DGA dga_MajorVersion = 0, dga_MinorVersion = 0; if ( in_dgamouse->value ) { if ( !XF86DGAQueryVersion( dpy, &dga_MajorVersion, &dga_MinorVersion ) ) { // unable to query, probalby not supported ri.Printf( PRINT_ALL, "Failed to detect XF86DGA Mouse\n" ); ri.Cvar_Set( "in_dgamouse", "0" ); } else { ri.Printf( PRINT_ALL, "XF86DGA Mouse (Version %d.%d) initialized\n", dga_MajorVersion, dga_MinorVersion ); } } if ( vidmode_ext ) { int best_fit, best_dist, dist, x, y; XF86VidModeGetAllModeLines( dpy, scrnum, &num_vidmodes, &vidmodes ); // Are we going fullscreen? If so, let's change video mode if ( fullscreen ) { best_dist = 9999999; best_fit = -1; for ( i = 0; i < num_vidmodes; i++ ) { if ( glConfig.vidWidth > vidmodes[i]->hdisplay || glConfig.vidHeight > vidmodes[i]->vdisplay ) { continue; } x = glConfig.vidWidth - vidmodes[i]->hdisplay; y = glConfig.vidHeight - vidmodes[i]->vdisplay; dist = ( x * x ) + ( y * y ); if ( dist < best_dist ) { best_dist = dist; best_fit = i; } } if ( best_fit != -1 ) { actualWidth = vidmodes[best_fit]->hdisplay; actualHeight = vidmodes[best_fit]->vdisplay; // change to the mode XF86VidModeSwitchToMode( dpy, scrnum, vidmodes[best_fit] ); vidmode_active = qtrue; // Move the viewport to top left XF86VidModeSetViewPort( dpy, scrnum, 0, 0 ); ri.Printf( PRINT_ALL, "XFree86-VidModeExtension Activated at %dx%d\n", actualWidth, actualHeight ); } else { fullscreen = 0; ri.Printf( PRINT_ALL, "XFree86-VidModeExtension: No acceptable modes found\n" ); } } else { ri.Printf( PRINT_ALL, "XFree86-VidModeExtension: Ignored on non-fullscreen/Voodoo\n" ); } } if ( !r_colorbits->value ) { colorbits = 24; } else { colorbits = r_colorbits->value; } if ( !Q_stricmp( r_glDriver->string, _3DFX_DRIVER_NAME ) ) { colorbits = 16; } if ( !r_depthbits->value ) { depthbits = 24; } else { depthbits = r_depthbits->value; } stencilbits = r_stencilbits->value; for ( i = 0; i < 16; i++ ) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ( ( i % 4 ) == 0 && i ) { // one pass, reduce switch ( i / 4 ) { case 2: if ( colorbits == 24 ) { colorbits = 16; } break; case 1: if ( depthbits == 24 ) { depthbits = 16; } else if ( depthbits == 16 ) { depthbits = 8; } case 3: if ( stencilbits == 24 ) { stencilbits = 16; } else if ( stencilbits == 16 ) { stencilbits = 8; } } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ( ( i % 4 ) == 3 ) { // reduce colorbits if ( tcolorbits == 24 ) { tcolorbits = 16; } } if ( ( i % 4 ) == 2 ) { // reduce depthbits if ( tdepthbits == 24 ) { tdepthbits = 16; } else if ( tdepthbits == 16 ) { tdepthbits = 8; } } if ( ( i % 4 ) == 1 ) { // reduce stencilbits if ( tstencilbits == 24 ) { tstencilbits = 16; } else if ( tstencilbits == 16 ) { tstencilbits = 8; } else { tstencilbits = 0; } } if ( tcolorbits == 24 ) { attrib[ATTR_RED_IDX] = 8; attrib[ATTR_GREEN_IDX] = 8; attrib[ATTR_BLUE_IDX] = 8; } else { // must be 16 bit attrib[ATTR_RED_IDX] = 4; attrib[ATTR_GREEN_IDX] = 4; attrib[ATTR_BLUE_IDX] = 4; } attrib[ATTR_DEPTH_IDX] = tdepthbits; // default to 24 depth attrib[ATTR_STENCIL_IDX] = tstencilbits; visinfo = qglXChooseVisual( dpy, scrnum, attrib ); if ( !visinfo ) { continue; } ri.Printf( PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", attrib[ATTR_RED_IDX], attrib[ATTR_GREEN_IDX], attrib[ATTR_BLUE_IDX], attrib[ATTR_DEPTH_IDX], attrib[ATTR_STENCIL_IDX] ); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } if ( !visinfo ) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } /* window attributes */ attr.background_pixel = BlackPixel( dpy, scrnum ); attr.border_pixel = 0; attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone ); attr.event_mask = X_MASK; if ( vidmode_active ) { mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | CWEventMask | CWOverrideRedirect; attr.override_redirect = True; attr.backing_store = NotUseful; attr.save_under = False; } else { mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; } win = XCreateWindow( dpy, root, 0, 0, actualWidth, actualHeight, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr ); XStoreName( dpy, win, WINDOW_CLASS_NAME ); /* GH: Don't let the window be resized */ sizehints.flags = PMinSize | PMaxSize; sizehints.min_width = sizehints.max_width = actualWidth; sizehints.min_height = sizehints.max_height = actualHeight; XSetWMNormalHints( dpy, win, &sizehints ); XMapWindow( dpy, win ); if ( vidmode_active ) { XMoveWindow( dpy, win, 0, 0 ); } XFlush( dpy ); XSync( dpy,False ); // bk001130 - from cvs1.17 (mkv) ctx = qglXCreateContext( dpy, visinfo, NULL, True ); XSync( dpy,False ); // bk001130 - from cvs1.17 (mkv) /* GH: Free the visinfo after we're done with it */ XFree( visinfo ); qglXMakeCurrent( dpy, win, ctx ); // bk001130 - from cvs1.17 (mkv) glstring = qglGetString( GL_RENDERER ); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); // bk010122 - new software token (Indirect) if ( !Q_stricmp( glstring, "Mesa X11" ) || !Q_stricmp( glstring, "Mesa GLX Indirect" ) ) { if ( !r_allowSoftwareGL->integer ) { ri.Printf( PRINT_ALL, "\n\n***********************************************************\n" ); ri.Printf( PRINT_ALL, " You are using software Mesa (no hardware acceleration)! \n" ); ri.Printf( PRINT_ALL, " Driver DLL used: %s\n", drivername ); ri.Printf( PRINT_ALL, " If this is intentional, add\n" ); ri.Printf( PRINT_ALL, " \"+set r_allowSoftwareGL 1\"\n" ); ri.Printf( PRINT_ALL, " to the command line when starting the game.\n" ); ri.Printf( PRINT_ALL, "***********************************************************\n" ); GLimp_Shutdown(); return RSERR_INVALID_MODE; } else { ri.Printf( PRINT_ALL, "...using software Mesa (r_allowSoftwareGL==1).\n" ); } } return RSERR_OK; }
static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) { int perChannelColorBits; int colorBits, depthBits, stencilBits; int samples; int i = 0; SDL_Surface *icon = NULL; SDL_DisplayMode desktopMode; int display = 0; int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED; Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_INPUT_GRABBED; #ifndef FEATURE_RENDERER_GLES GLenum glewResult; #endif Ren_Print("Initializing OpenGL display\n"); if (r_allowResize->integer && !fullscreen) { flags |= SDL_WINDOW_RESIZABLE; } icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); // If a window exists, note its display index if (main_window != NULL) { display = SDL_GetWindowDisplayIndex(main_window); } if (SDL_GetDesktopDisplayMode(display, &desktopMode) == 0) { displayAspect = (float)desktopMode.w / (float)desktopMode.h; Ren_Print("Estimated display aspect: %.3f\n", displayAspect); } else { Com_Memset(&desktopMode, 0, sizeof(SDL_DisplayMode)); Ren_Print("Cannot estimate display aspect, assuming 1.333\n"); } Ren_Print("...setting mode %d: ", mode); if (mode == -2) { // use desktop video resolution if (desktopMode.h > 0) { glConfig.vidWidth = desktopMode.w; glConfig.vidHeight = desktopMode.h; } else { glConfig.vidWidth = 640; glConfig.vidHeight = 480; Ren_Print("Cannot determine display resolution, assuming 640x480\n"); } glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if (!R_GetModeInfo(&glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode)) { Ren_Print("invalid mode\n"); return RSERR_INVALID_MODE; } Ren_Print("%dx%d\n", glConfig.vidWidth, glConfig.vidHeight); // Center window if (r_centerWindow->integer && !fullscreen) { x = (desktopMode.w / 2) - (glConfig.vidWidth / 2); y = (desktopMode.h / 2) - (glConfig.vidHeight / 2); } // Destroy existing state if it exists if (SDL_glContext != NULL) { SDL_GL_DeleteContext(SDL_glContext); SDL_glContext = NULL; } if (main_window != NULL) { SDL_GetWindowPosition(main_window, &x, &y); Ren_Developer("Existing window at %dx%d before being destroyed\n", x, y); SDL_DestroyWindow(main_window); main_window = NULL; } if (fullscreen) { if (r_mode->integer == -2) { flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } else { flags |= SDL_WINDOW_FULLSCREEN; } glConfig.isFullscreen = qtrue; } else { if (noborder) { flags |= SDL_WINDOW_BORDERLESS; } glConfig.isFullscreen = qfalse; } colorBits = r_colorbits->value; if ((!colorBits) || (colorBits >= 32)) { colorBits = 24; } if (!r_depthbits->value) { depthBits = 24; } else { depthBits = r_depthbits->value; } stencilBits = r_stencilbits->value; samples = r_ext_multisample->value; for (i = 0; i < 16; i++) { int testColorBits, testDepthBits, testStencilBits; // 0 - default // 1 - minus colorBits // 2 - minus depthBits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2: if (colorBits == 24) { colorBits = 16; } break; case 1: if (depthBits == 32) { depthBits = 24; } else if (depthBits == 24) { depthBits = 16; } else if (depthBits == 16) { depthBits = 8; } case 3: // fall through if (stencilBits == 24) { stencilBits = 16; } else if (stencilBits == 16) { stencilBits = 8; } } } testColorBits = colorBits; testDepthBits = depthBits; testStencilBits = stencilBits; if ((i % 4) == 3) // reduce colorbits { if (testColorBits == 24) { testColorBits = 16; } } if ((i % 4) == 2) // reduce depthbits { if (testDepthBits == 24) { testDepthBits = 16; } else if (testDepthBits == 16) { testDepthBits = 8; } } if ((i % 4) == 1) // reduce stencilbits { if (testStencilBits == 24) { testStencilBits = 16; } else if (testStencilBits == 16) { testStencilBits = 8; } else { testStencilBits = 0; } } if (testColorBits == 24) { perChannelColorBits = 8; } else { perChannelColorBits = 4; } #ifdef __sgi // Fix for SGIs grabbing too many bits of color if (perChannelColorBits == 4) { perChannelColorBits = 0; /* Use minimum size for 16-bit color */ } // Need alpha or else SGIs choose 36+ bit RGB mode SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1); #endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, perChannelColorBits); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, perChannelColorBits); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, perChannelColorBits); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, testDepthBits); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, testStencilBits); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples); // SDL2 uses opengl by default, if we want opengl es we need to set this attribute //SDL_GL_SetAttribute(SDL_GL_CONTEXT_EGL, 1); if (r_stereoEnabled->integer) { glConfig.stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { glConfig.stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // If not allowing software GL, demand accelerated if (!r_allowSoftwareGL->integer) { SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); } main_window = SDL_CreateWindow(CLIENT_WINDOW_TITLE, x, y, glConfig.vidWidth, glConfig.vidHeight, flags | SDL_WINDOW_SHOWN); if (!main_window) { Ren_Developer("SDL_CreateWindow failed: %s\n", SDL_GetError()); continue; } //This is disabled since at least now we have no use for this /* if (!Glimp_Create2DRenderer(main_window)) { continue; } */ if (fullscreen) { SDL_DisplayMode mode; switch (testColorBits) { case 16: mode.format = SDL_PIXELFORMAT_RGB565; break; case 24: mode.format = SDL_PIXELFORMAT_RGB24; break; default: Ren_Developer("testColorBits is %d, can't fullscreen\n", testColorBits); continue; } mode.w = glConfig.vidWidth; mode.h = glConfig.vidHeight; mode.refresh_rate = glConfig.displayFrequency = ri.Cvar_VariableIntegerValue("r_displayRefresh"); mode.driverdata = NULL; if (SDL_SetWindowDisplayMode(main_window, &mode) < 0) { Ren_Developer("SDL_SetWindowDisplayMode failed: %s\n", SDL_GetError()); continue; } } SDL_SetWindowIcon(main_window, icon); #if defined(FEATURE_RENDERER2) glewExperimental = GL_TRUE; SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); #endif if ((SDL_glContext = SDL_GL_CreateContext(main_window)) == NULL) { Ren_Developer("SDL_GL_CreateContext failed: %s\n", SDL_GetError()); continue; } SDL_GL_MakeCurrent(main_window, SDL_glContext); SDL_GL_SetSwapInterval(r_swapInterval->integer); glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; glConfig.stencilBits = testStencilBits; ri.Printf(PRINT_ALL, "Using %d color bits, %d depth, %d stencil display.\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits); break; } GLimp_DetectAvailableModes(); #if !defined(FEATURE_RENDERER_GLES) glewResult = glewInit(); if (GLEW_OK != glewResult) { // glewInit failed, something is seriously wrong Ren_Fatal("GLW_StartOpenGL() - could not load OpenGL subsystem: %s", glewGetErrorString(glewResult)); } else { Ren_Print("Using GLEW %s\n", glewGetString(GLEW_VERSION)); } #endif if (!GLimp_InitOpenGLContext()) { return RSERR_OLD_GL; } if (!main_window) //|| !main_renderer) { Ren_Print("Couldn't get a visual\n"); return RSERR_INVALID_MODE; } SDL_FreeSurface(icon); return RSERR_OK; }
/* =============== GLimp_SetMode =============== */ static int GLimp_SetMode( int mode, int fullscreen, int noborder ) { int sdlcolorbits; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int i = 0; SDL_Surface *vidscreen = NULL; Uint32 flags = 0; const SDL_VideoInfo *videoInfo; ri.Printf( PRINT_ALL, "Initializing Direct3D display\n" ); if ( r_allowResize->integer ) { flags |= SDL_RESIZABLE; } if ( displayAspect == 0.0f ) { #if !SDL_VERSION_ATLEAST(1, 2, 10) // 1.2.10 is needed to get the desktop resolution displayAspect = 4.0f / 3.0f; #else // Guess the display aspect ratio through the desktop resolution // by assuming (relatively safely) that it is set at or close to // the display's native aspect ratio videoInfo = SDL_GetVideoInfo(); displayAspect = ( float ) videoInfo->current_w / ( float ) videoInfo->current_h; #endif ri.Printf( PRINT_ALL, "Estimated display aspect: %.3f\n", displayAspect ); } ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight ); if ( fullscreen ) { flags |= SDL_FULLSCREEN; glConfig.isFullscreen = qtrue; } else { glConfig.isFullscreen = qfalse; } if ( !r_colorbits->value ) { colorbits = 24; } else { colorbits = r_colorbits->value; } if ( !r_depthbits->value ) { depthbits = 24; } else { depthbits = r_depthbits->value; } stencilbits = r_stencilbits->value; for ( i = 0; i < 16; i++ ) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ( ( i % 4 ) == 0 && i ) { // one pass, reduce switch ( i / 4 ) { case 2: if ( colorbits == 24 ) { colorbits = 16; } break; case 1: if ( depthbits == 24 ) { depthbits = 16; } else if ( depthbits == 16 ) { depthbits = 8; } case 3: if ( stencilbits == 24 ) { stencilbits = 16; } else if ( stencilbits == 16 ) { stencilbits = 8; } } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ( ( i % 4 ) == 3 ) { // reduce colorbits if ( tcolorbits == 24 ) { tcolorbits = 16; } } if ( ( i % 4 ) == 2 ) { // reduce depthbits if ( tdepthbits == 24 ) { tdepthbits = 16; } else if ( tdepthbits == 16 ) { tdepthbits = 8; } } if ( ( i % 4 ) == 1 ) { // reduce stencilbits if ( tstencilbits == 24 ) { tstencilbits = 16; } else if ( tstencilbits == 16 ) { tstencilbits = 8; } else { tstencilbits = 0; } } sdlcolorbits = 4; if ( tcolorbits == 24 ) { sdlcolorbits = 8; } SDL_GL_SetAttribute( SDL_GL_RED_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, tdepthbits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, tstencilbits ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); if ( SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, r_swapInterval->integer ) < 0 ) { ri.Printf( PRINT_ALL, "r_swapInterval requires libSDL >= 1.2.10\n" ); } #ifdef USE_ICON { SDL_Surface *icon = SDL_CreateRGBSurfaceFrom( ( void * ) CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); SDL_WM_SetIcon( icon, NULL ); SDL_FreeSurface( icon ); } #endif SDL_WM_SetCaption( CLIENT_WINDOW_TITLE, CLIENT_WINDOW_MIN_TITLE ); SDL_ShowCursor( 0 ); if ( !( vidscreen = SDL_SetVideoMode( glConfig.vidWidth, glConfig.vidHeight, colorbits, flags ) ) ) { ri.Printf( PRINT_DEVELOPER, "SDL_SetVideoMode failed: %s\n", SDL_GetError() ); continue; } //GLimp_GetCurrentContext(); ri.Printf( PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits ); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } GLimp_DetectAvailableModes(); if ( !vidscreen ) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } screen = vidscreen; //glstring = (char *)qglGetString(GL_RENDERER); //ri.Printf(PRINT_ALL, "GL_RENDERER: %s\n", glstring); return RSERR_OK; }
/* ** GLW_SetMode */ static int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen ) { const char* glstring; // bk001130 - from cvs1.17 (mkv) int sdlcolorbits; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int i = 0; SDL_Surface *vidscreen = NULL; ri.Printf( PRINT_ALL, "Initializing OpenGL display\n"); ri.Printf (PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight); Uint32 flags = SDL_OPENGL; if (fullscreen) { flags |= SDL_FULLSCREEN; glConfig.isFullscreen = qtrue; } else glConfig.isFullscreen = qfalse; if (!r_colorbits->value) colorbits = 24; else colorbits = r_colorbits->value; if ( !Q_stricmp( r_glDriver->string, _3DFX_DRIVER_NAME ) ) colorbits = 16; if (!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; for (i = 0; i < 16; i++) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorbits == 24) colorbits = 16; break; case 1 : if (depthbits == 24) depthbits = 16; else if (depthbits == 16) depthbits = 8; case 3 : if (stencilbits == 24) stencilbits = 16; else if (stencilbits == 16) stencilbits = 8; } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ((i % 4) == 3) { // reduce colorbits if (tcolorbits == 24) tcolorbits = 16; } if ((i % 4) == 2) { // reduce depthbits if (tdepthbits == 24) tdepthbits = 16; else if (tdepthbits == 16) tdepthbits = 8; } if ((i % 4) == 1) { // reduce stencilbits if (tstencilbits == 24) tstencilbits = 16; else if (tstencilbits == 16) tstencilbits = 8; else tstencilbits = 0; } sdlcolorbits = 4; if (tcolorbits == 24) sdlcolorbits = 8; SDL_GL_SetAttribute( SDL_GL_RED_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, sdlcolorbits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, tdepthbits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, tstencilbits ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); #if SDL_VERSION_ATLEAST( 1, 2, 10 ) if( SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, r_swapInterval->integer ) ) ri.Printf( PRINT_ALL, "r_swapInterval requires libSDL >= 1.2.10\n" ); #else #warning libSDL >= 1.2.10 required for r_swapInterval support #endif // SDL_GL_SWAP_CONTROL SDL_WM_SetCaption(CLIENT_WINDOW_TITLE, CLIENT_WINDOW_ICON); SDL_ShowCursor(0); SDL_EnableUNICODE(1); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); sdlrepeatenabled = qtrue; if (!(vidscreen = SDL_SetVideoMode(glConfig.vidWidth, glConfig.vidHeight, colorbits, flags))) { fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); continue; } opengl_context = GLimp_GetCurrentContext(); ri.Printf( PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } if (!vidscreen) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } screen = vidscreen; // bk001130 - from cvs1.17 (mkv) glstring = (char *) qglGetString (GL_RENDERER); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); // bk010122 - new software token (Indirect) if ( !Q_stricmp( glstring, "Mesa X11") || !Q_stricmp( glstring, "Mesa GLX Indirect") ) { if ( !r_allowSoftwareGL->integer ) { ri.Printf( PRINT_ALL, "\n\n***********************************************************\n" ); ri.Printf( PRINT_ALL, " You are using software Mesa (no hardware acceleration)! \n" ); ri.Printf( PRINT_ALL, " Driver DLL used: %s\n", drivername ); ri.Printf( PRINT_ALL, " If this is intentional, add\n" ); ri.Printf( PRINT_ALL, " \"+set r_allowSoftwareGL 1\"\n" ); ri.Printf( PRINT_ALL, " to the command line when starting the game.\n" ); ri.Printf( PRINT_ALL, "***********************************************************\n"); GLimp_Shutdown( ); return RSERR_INVALID_MODE; } else { ri.Printf( PRINT_ALL, "...using software Mesa (r_allowSoftwareGL==1).\n" ); } } return RSERR_OK; }
/* ** GLW_SetMode */ int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen ) { #ifdef HAVE_GLES glConfig.vidWidth = 800; glConfig.vidHeight = 480; // glConfig.windowAspect = 800.0 / 480.0; long event_mask=X_MASK; dpy = XOpenDisplay(0); if(!dpy) { ri.Printf( PRINT_ALL, "couldn't open display\n"); return qfalse; } scrnum = DefaultScreen(dpy); ri.Printf( PRINT_ALL, "using default screen %d\n", scrnum); ri.Printf( PRINT_ALL, "setting up EGL window\n"); XSetWindowAttributes attr = { 0 }; attr.event_mask = event_mask; // attr.colormap = colormap; attr.override_redirect = qtrue; win = XCreateWindow(dpy, RootWindow(dpy, scrnum), 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &attr); if(!win) { return qfalse; } Atom wmState = XInternAtom(dpy, "_NET_WM_STATE", False); Atom wmFullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); XChangeProperty(dpy, win, wmState, XA_ATOM, 32, PropModeReplace, (unsigned char *)&wmFullscreen, 1); XMapRaised(dpy, win); g_EGLWindow = (NativeWindowType)win; #ifdef PANDORA g_EGLDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); #else g_EGLDisplay = eglGetDisplay((EGLNativeDisplayType)dpy); #endif if(g_EGLDisplay == EGL_NO_DISPLAY) { ri.Printf( PRINT_ALL, "error getting EGL display\n"); return qfalse; } if(!eglInitialize(g_EGLDisplay, NULL, NULL)) { ri.Printf( PRINT_ALL, "error initializing EGL"); return 0; } const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_ALPHA_SIZE, 0, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_PBUFFER_BIT, EGL_DEPTH_SIZE, 16, EGL_NONE, 0, }; EGLint configs = 0; eglChooseConfig(g_EGLDisplay, attribs, &g_EGLConfig, 1, &configs); if(!configs) { static const EGLint eglAttrWinLowColor[] = { EGL_NONE }; ri.Printf( PRINT_ALL, "falling back to lowest color config\n"); eglChooseConfig(g_EGLDisplay, eglAttrWinLowColor, &g_EGLConfig, 1, &configs); if(!configs) { ri.Printf( PRINT_ALL, "no valid EGL configs found\n"); return qfalse; } } #ifdef PANDORA g_EGLWindowSurface = eglCreateWindowSurface(g_EGLDisplay, g_EGLConfig, NULL, NULL); #else g_EGLWindowSurface = eglCreateWindowSurface(g_EGLDisplay, g_EGLConfig, g_EGLWindow, NULL); #endif if(g_EGLWindowSurface == EGL_NO_SURFACE) { ri.Printf( PRINT_ALL, "error creating window surface: 0x%X\n", (int)eglGetError()); return qfalse; } EGLint ctxAttr[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE }; g_EGLContext = eglCreateContext(g_EGLDisplay, g_EGLConfig, EGL_NO_CONTEXT, ctxAttr); if(g_EGLContext == EGL_NO_CONTEXT) { ri.Printf( PRINT_ALL, "error creating context: 0x%X\n", (int)eglGetError()); return qfalse; } eglMakeCurrent(g_EGLDisplay, g_EGLWindowSurface, g_EGLWindowSurface, g_EGLContext); { EGLint width, height, color, depth, stencil; eglQuerySurface(g_EGLDisplay, g_EGLWindowSurface, EGL_WIDTH, &width); eglQuerySurface(g_EGLDisplay, g_EGLWindowSurface, EGL_HEIGHT, &height); ri.Printf(PRINT_ALL, "Window size: %dx%d\n", width, height); eglGetConfigAttrib(g_EGLDisplay, g_EGLConfig, EGL_BUFFER_SIZE, &color); eglGetConfigAttrib(g_EGLDisplay, g_EGLConfig, EGL_DEPTH_SIZE, &depth); eglGetConfigAttrib(g_EGLDisplay, g_EGLConfig, EGL_STENCIL_SIZE, &stencil); /* glConfig.vidWidth = width; glConfig.vidHeight = height;*/ glConfig.colorBits = color; glConfig.depthBits = depth; glConfig.stencilBits = stencil; } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); #else int attrib[] = { GLX_RGBA, // 0 GLX_RED_SIZE, 4, // 1, 2 GLX_GREEN_SIZE, 4, // 3, 4 GLX_BLUE_SIZE, 4, // 5, 6 GLX_DOUBLEBUFFER, // 7 GLX_DEPTH_SIZE, 1, // 8, 9 GLX_STENCIL_SIZE, 1, // 10, 11 None }; // these match in the array #define ATTR_RED_IDX 2 #define ATTR_GREEN_IDX 4 #define ATTR_BLUE_IDX 6 #define ATTR_DEPTH_IDX 9 #define ATTR_STENCIL_IDX 11 Window root; XVisualInfo *visinfo; XSetWindowAttributes attr; unsigned long mask; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; int dga_MajorVersion, dga_MinorVersion; int actualWidth, actualHeight; int i; const char* glstring; // bk001130 - from cvs1.17 (mkv) ri.Printf( PRINT_ALL, "Initializing OpenGL display\n" ); ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight ); if ( !( dpy = XOpenDisplay( NULL ) ) ) { fprintf( stderr, "Error couldn't open the X display\n" ); return RSERR_INVALID_MODE; } scrnum = DefaultScreen( dpy ); root = RootWindow( dpy, scrnum ); actualWidth = glConfig.vidWidth; actualHeight = glConfig.vidHeight; // Get video mode list if ( !XF86VidModeQueryVersion( dpy, &vidmode_MajorVersion, &vidmode_MinorVersion ) ) { vidmode_ext = qfalse; } else { ri.Printf( PRINT_ALL, "Using XFree86-VidModeExtension Version %d.%d\n", vidmode_MajorVersion, vidmode_MinorVersion ); vidmode_ext = qtrue; } // Check for DGA dga_MajorVersion = 0, dga_MinorVersion = 0; if ( in_dgamouse->value ) { if ( !XF86DGAQueryVersion( dpy, &dga_MajorVersion, &dga_MinorVersion ) ) { // unable to query, probalby not supported ri.Printf( PRINT_ALL, "Failed to detect XF86DGA Mouse\n" ); ri.Cvar_Set( "in_dgamouse", "0" ); } else { ri.Printf( PRINT_ALL, "XF86DGA Mouse (Version %d.%d) initialized\n", dga_MajorVersion, dga_MinorVersion ); } } if ( vidmode_ext ) { int best_fit, best_dist, dist, x, y; XF86VidModeGetAllModeLines( dpy, scrnum, &num_vidmodes, &vidmodes ); // Are we going fullscreen? If so, let's change video mode if ( fullscreen ) { best_dist = 9999999; best_fit = -1; for ( i = 0; i < num_vidmodes; i++ ) { if ( glConfig.vidWidth > vidmodes[i]->hdisplay || glConfig.vidHeight > vidmodes[i]->vdisplay ) { continue; } x = glConfig.vidWidth - vidmodes[i]->hdisplay; y = glConfig.vidHeight - vidmodes[i]->vdisplay; dist = ( x * x ) + ( y * y ); if ( dist < best_dist ) { best_dist = dist; best_fit = i; } } if ( best_fit != -1 ) { actualWidth = vidmodes[best_fit]->hdisplay; actualHeight = vidmodes[best_fit]->vdisplay; // change to the mode XF86VidModeSwitchToMode( dpy, scrnum, vidmodes[best_fit] ); vidmode_active = qtrue; // Move the viewport to top left XF86VidModeSetViewPort( dpy, scrnum, 0, 0 ); ri.Printf( PRINT_ALL, "XFree86-VidModeExtension Activated at %dx%d\n", actualWidth, actualHeight ); } else { fullscreen = 0; ri.Printf( PRINT_ALL, "XFree86-VidModeExtension: No acceptable modes found\n" ); } } else { ri.Printf( PRINT_ALL, "XFree86-VidModeExtension: Ignored on non-fullscreen/Voodoo\n" ); } } if ( !r_colorbits->value ) { colorbits = 24; } else { colorbits = r_colorbits->value; } if ( !Q_stricmp( r_glDriver->string, _3DFX_DRIVER_NAME ) ) { colorbits = 16; } if ( !r_depthbits->value ) { depthbits = 24; } else { depthbits = r_depthbits->value; } stencilbits = r_stencilbits->value; for ( i = 0; i < 16; i++ ) { // 0 - default // 1 - minus colorbits // 2 - minus depthbits // 3 - minus stencil if ( ( i % 4 ) == 0 && i ) { // one pass, reduce switch ( i / 4 ) { case 2: if ( colorbits == 24 ) { colorbits = 16; } break; case 1: if ( depthbits == 24 ) { depthbits = 16; } else if ( depthbits == 16 ) { depthbits = 8; } case 3: if ( stencilbits == 24 ) { stencilbits = 16; } else if ( stencilbits == 16 ) { stencilbits = 8; } } } tcolorbits = colorbits; tdepthbits = depthbits; tstencilbits = stencilbits; if ( ( i % 4 ) == 3 ) { // reduce colorbits if ( tcolorbits == 24 ) { tcolorbits = 16; } } if ( ( i % 4 ) == 2 ) { // reduce depthbits if ( tdepthbits == 24 ) { tdepthbits = 16; } else if ( tdepthbits == 16 ) { tdepthbits = 8; } } if ( ( i % 4 ) == 1 ) { // reduce stencilbits if ( tstencilbits == 24 ) { tstencilbits = 16; } else if ( tstencilbits == 16 ) { tstencilbits = 8; } else { tstencilbits = 0; } } if ( tcolorbits == 24 ) { attrib[ATTR_RED_IDX] = 8; attrib[ATTR_GREEN_IDX] = 8; attrib[ATTR_BLUE_IDX] = 8; } else { // must be 16 bit attrib[ATTR_RED_IDX] = 4; attrib[ATTR_GREEN_IDX] = 4; attrib[ATTR_BLUE_IDX] = 4; } attrib[ATTR_DEPTH_IDX] = tdepthbits; // default to 24 depth attrib[ATTR_STENCIL_IDX] = tstencilbits; visinfo = qglXChooseVisual( dpy, scrnum, attrib ); if ( !visinfo ) { continue; } ri.Printf( PRINT_ALL, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", attrib[ATTR_RED_IDX], attrib[ATTR_GREEN_IDX], attrib[ATTR_BLUE_IDX], attrib[ATTR_DEPTH_IDX], attrib[ATTR_STENCIL_IDX] ); glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } if ( !visinfo ) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); return RSERR_INVALID_MODE; } /* window attributes */ attr.background_pixel = BlackPixel( dpy, scrnum ); attr.border_pixel = 0; attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone ); attr.event_mask = X_MASK; if ( vidmode_active ) { mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | CWEventMask | CWOverrideRedirect; attr.override_redirect = True; attr.backing_store = NotUseful; attr.save_under = False; } else { mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; } win = XCreateWindow( dpy, root, 0, 0, actualWidth, actualHeight, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr ); XStoreName( dpy, win, WINDOW_CLASS_NAME ); XMapWindow( dpy, win ); if ( vidmode_active ) { XMoveWindow( dpy, win, 0, 0 ); } XFlush( dpy ); XSync( dpy,False ); // bk001130 - from cvs1.17 (mkv) ctx = qglXCreateContext( dpy, visinfo, NULL, True ); XSync( dpy,False ); // bk001130 - from cvs1.17 (mkv) qglXMakeCurrent( dpy, win, ctx ); // bk001130 - from cvs1.17 (mkv) glstring = qglGetString( GL_RENDERER ); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glstring ); // bk010122 - new software token (Indirect) if ( !Q_stricmp( glstring, "Mesa X11" ) || !Q_stricmp( glstring, "Mesa GLX Indirect" ) ) { if ( !r_allowSoftwareGL->integer ) { ri.Printf( PRINT_ALL, "\n\n***********************************************************\n" ); ri.Printf( PRINT_ALL, " You are using software Mesa (no hardware acceleration)! \n" ); ri.Printf( PRINT_ALL, " Driver DLL used: %s\n", drivername ); ri.Printf( PRINT_ALL, " If this is intentional, add\n" ); ri.Printf( PRINT_ALL, " \"+set r_allowSoftwareGL 1\"\n" ); ri.Printf( PRINT_ALL, " to the command line when starting the game.\n" ); ri.Printf( PRINT_ALL, "***********************************************************\n" ); GLimp_Shutdown(); return RSERR_INVALID_MODE; } else { ri.Printf( PRINT_ALL, "...using software Mesa (r_allowSoftwareGL==1).\n" ); } } #endif //HAVE_GLES return RSERR_OK; }
static void GLW_CreateGLWnd( void ) { int x, y, w, h; HWND hParent; float aspect; DWORD s, es; skinDef_t *skin; int refresh = 0; int colorDepth = 0; WinVars_t *winVars = (WinVars_t*)ri.PlatformGetVars(); if( winVars->hWnd ) return; x = 0; y = 0; if( r_fullscreen->integer ) { int mode_id; char * res = r_fsmode->string; w = atoi( COM_Parse( &res ) ); h = atoi( COM_Parse( &res ) ); aspect = (float)w / (float)h; sql_prepare( &com_db, "SELECT x, y FROM monitors SEARCH dev_name ?" ); sql_bindtext( &com_db, 1, r_fsmonitor->string ); if( sql_step( &com_db ) ) { x = sql_columnasint( &com_db, 0 ); y = sql_columnasint( &com_db, 1 ); } sql_done( &com_db ); //find the settings mode id mode_id = -1; sql_prepare( &com_db, "SELECT id FROM fsmodes SEARCH dev_name ?1 WHERE w=?2 AND h=?3" ); sql_bindtext( &com_db, 1, r_fsmonitor->string ); sql_bindint( &com_db, 2, w ); sql_bindint( &com_db, 3, h ); if( sql_step( &com_db ) ) mode_id = sql_columnasint( &com_db, 0 ); sql_done( &com_db ); //get a matching color mode sql_prepare( &com_db, "SELECT bpp FROM fsmodes_ext SEARCH id ?1" ); sql_bindint( &com_db, 1, mode_id ); while( sql_step( &com_db ) ) { int bpp = sql_columnasint( &com_db, 0 ); if( r_colorbits->integer ) { if( bpp == r_colorbits->integer ) { //take an exact match colorDepth = bpp; break; } if( bpp > r_colorbits->integer ) { if( colorDepth < r_colorbits->integer || bpp < colorDepth ) //if we must go over, take the smallest value that goes over colorDepth = bpp; } else if( bpp > colorDepth ) colorDepth = bpp; } else if( bpp > colorDepth ) colorDepth = bpp; } sql_done( &com_db ); //get a matching refresh rate sql_prepare( &com_db, "SELECT hz FROM fsmodes_ext SEARCH id ?1 WHERE bpp=?2" ); sql_bindint( &com_db, 1, mode_id ); sql_bindint( &com_db, 2, colorDepth ); while( sql_step( &com_db ) ) { int hz = sql_columnasint( &com_db, 0 ); if( r_displayRefresh->integer ) { if( hz == r_displayRefresh->integer ) { //take an exact match refresh = hz; break; } if( hz > r_displayRefresh->integer ) { if( refresh < r_displayRefresh->integer || hz < refresh ) //if we must go over, take the smallest value that goes over refresh = hz; } else if( hz > refresh ) refresh = hz; } else if( hz > refresh ) //take the highest refresh rate refresh = hz; } sql_done( &com_db ); } else { if( !R_GetModeInfo( &w, &h, &aspect, r_mode->integer ) ) { //fall back to special modes w = 0; h = 0; } } /* Clean out old display mode changes. Note that we *don't* skip this when we're going back into fullscreen as it tends to produce some aweful bugs on some Windows installations. */ if( glw_state.cdsFullscreen ) ChangeDisplaySettings( NULL, 0 ); //window style bits es = 0; s = 0; skin = NULL; if( r_fullscreen->integer ) { //go into full screen mode RECT rc; HMONITOR monitor; MONITORINFOEX monitorInfo; hParent = 0; //make sure we're set up for multimon goodness if( winVars->hWndHost ) { GetWindowRect( winVars->hWndHost, &rc ); } else { rc.left = x; rc.top = y; rc.right = x + w; rc.bottom = y + h; } monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST ); monitorInfo.cbSize = sizeof( monitorInfo ); GetMonitorInfo( monitor, (LPMONITORINFO)&monitorInfo ); //if we got an invalid mode then use desktop resolution if( w == 0 ) w = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; if( h == 0 ) h = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; //change that monitor's display size to <w, h> //set the window rect to cover the display //skip the festival of desktop flickering if not changing resolution if( (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left) != w || (monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top) != h ) { DEVMODE dm; memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); dm.dmPelsWidth = w; dm.dmPelsHeight = h; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if( refresh != 0 ) { dm.dmDisplayFrequency = refresh; dm.dmFields |= DM_DISPLAYFREQUENCY; } if( colorDepth != 0 ) { dm.dmBitsPerPel = colorDepth; dm.dmFields |= DM_BITSPERPEL; } if( ChangeDisplaySettingsEx( monitorInfo.szDevice, &dm, NULL, CDS_FULLSCREEN, NULL ) != DISP_CHANGE_SUCCESSFUL ) { //try again without color bits and frequency dm.dmFields &= ~(DM_BITSPERPEL | DM_DISPLAYFREQUENCY); dm.dmBitsPerPel = 0; dm.dmDisplayFrequency = 0; if( ChangeDisplaySettingsEx( monitorInfo.szDevice, &dm, NULL, CDS_FULLSCREEN, NULL ) != DISP_CHANGE_SUCCESSFUL ) //failed... ri.Printf( PRINT_WARNING, "Invalid fullscreen resolution, running at desktop resolution" ); } } //get the new monitor info monitorInfo.cbSize = sizeof( monitorInfo ); GetMonitorInfo( monitor, (LPMONITORINFO)&monitorInfo ); x = monitorInfo.rcMonitor.left; y = monitorInfo.rcMonitor.top; w = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; h = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; s = WS_POPUP; es = WS_EX_APPWINDOW | WS_EX_TOPMOST; glw_state.cdsFullscreen = qtrue; } else if( winVars->hWndHost ) { RECT rc; hParent = winVars->hWndHost; GetClientRect( winVars->hWndHost, &rc ); x = rc.left; y = rc.top; w = rc.right - rc.left; h = rc.bottom - rc.top; s = WS_CHILD; es = WS_EX_NOPARENTNOTIFY; } else { RECT rc; HMONITOR monitor; MONITORINFO monitorInfo; qboolean usedefault = qfalse; if( w == 0 ) w = 640; if( h == 0 ) h = 480; vid_xpos = ri.Cvar_Get( "vid_xpos", va("%d",CW_USEDEFAULT), CVAR_ARCHIVE ); vid_ypos = ri.Cvar_Get( "vid_ypos", "0", CVAR_ARCHIVE ); x = vid_xpos->integer; y = vid_ypos->integer; if ( x == CW_USEDEFAULT ) { x = 0; usedefault = qtrue; } rc.left = x; rc.top = y; rc.right = x + w; rc.bottom = y + h; hParent = 0; if( r_skin->string[0] ) skin = Skin_Load( r_skin->string ); //account for the border frame if( skin ) { s = WS_POPUP; es = WS_EX_APPWINDOW; Skin_AdjustWindowRect( &rc, skin ); AdjustWindowRectEx( &rc, s, FALSE, es ); } else { s = WS_OVERLAPPED | WS_SYSMENU | WS_BORDER | WS_CAPTION; es = WS_EX_APPWINDOW; AdjustWindowRectEx( &rc, s, FALSE, es ); } x = rc.left; y = rc.top; w = rc.right - rc.left; h = rc.bottom - rc.top; //constrain to a monitor //this is important as we can't get a //pixel format if we're entirely off screen monitor = MonitorFromRect( &rc, MONITOR_DEFAULTTONEAREST ); monitorInfo.cbSize = sizeof( monitorInfo ); GetMonitorInfo( monitor, &monitorInfo ); //if we're not actually intersecting the monitor //(shoved off of the screen I guess) move back onto it if( x > monitorInfo.rcWork.right ) //left window edge past right screen edge x = monitorInfo.rcWork.right - w; if( x + w < monitorInfo.rcWork.left ) //right window edge past left screen edge x = monitorInfo.rcWork.left; if( y > monitorInfo.rcWork.bottom ) //top window edge past bottom screen edge y = monitorInfo.rcWork.bottom - h; if( y + h < monitorInfo.rcWork.top ) //bottom window edge past top screen edge y = monitorInfo.rcWork.top; glw_state.cdsFullscreen = qfalse; if ( usedefault ) { x = monitorInfo.rcMonitor.left + ((monitorInfo.rcMonitor.right-monitorInfo.rcMonitor.left)-w)/2; y = monitorInfo.rcMonitor.top + ((monitorInfo.rcMonitor.bottom-monitorInfo.rcMonitor.top)-h)/2; } } winVars->hWnd = NULL; if( skin ) { Skin_RegisterClass(); winVars->hWnd = Skin_CreateWnd( skin, x, y, w, h ); } if( !winVars->hWnd ) { GLW_RegisterClass(); winVars->hWnd = CreateWindowEx( es, WINDOW_CLASS_NAME, WINDOW_CAPTION, s, x, y, w, h, hParent, NULL, winVars->hInstance, NULL ); } //the window now owns the skin and will free it if( !winVars->hWnd ) ri.Error( ERR_FATAL, "GLW: could not create window" ); SetWindowPos( winVars->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW ); ShowWindow( winVars->hWnd, SW_SHOWNORMAL ); SetFocus( winVars->hWnd ); //get the window to draw once (get rid of graphical clutter) UpdateWindow( winVars->hWnd ); //fire up the GL glw_state.hDC = GetDC( winVars->hWnd ); if( !glw_state.hDC ) ri.Error( ERR_FATAL, "GLW: could not get window DC" ); //set up the pixel format { int pixelFormat; PIXELFORMATDESCRIPTOR pfd; GLW_CreatePFD( &pfd ); pixelFormat = GLW_ChoosePFDEx( &pfd ); if( !pixelFormat ) { pixelFormat = GLW_ChoosePFD( glw_state.hDC, &pfd ); glConfig.fsaaSamples = 1; } if( !pixelFormat ) ri.Error( ERR_FATAL, "GLW: no valid pixel format" ); pfd.nSize = sizeof( pfd ); DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( pfd ), &pfd ); if( !SetPixelFormat( glw_state.hDC, pixelFormat, &pfd ) ) ri.Error( ERR_FATAL, "GLW: could not set pixel format" ); glConfig.colorBits = pfd.cColorBits; glConfig.depthBits = pfd.cDepthBits; glConfig.stencilBits = pfd.cStencilBits; glConfig.stereoEnabled = (pfd.dwFlags & PFD_STEREO) ? qtrue : qfalse; ri.Printf( PRINT_ALL, "Using Pixel Format %i\n", pixelFormat ); } glw_state.hGLRC = wglCreateContext( glw_state.hDC ); if( !glw_state.hGLRC || !wglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) ri.Error( ERR_FATAL, "GLW: could not initialize GL" ); GLW_CheckExtensions(); //R_PerfInit(); { //get the actual sizes, in case Windows constrained our window RECT rc; GetClientRect( winVars->hWnd, &rc ); w = rc.right - rc.left; h = rc.bottom - rc.top; //fill in some glConfig stuff which *will* be referenced //by various subsystem init functions (i.e. Cg, bloom) glConfig.vidWidth = w; glConfig.vidHeight = h; glConfig.windowAspect = aspect; } glConfig.deviceSupportsGamma = qfalse; glConfig.isFullscreen = glw_state.cdsFullscreen ? qtrue : qfalse; glConfig.xscale = glConfig.vidWidth / 640.0f; glConfig.yscale = glConfig.vidHeight / 480.0f; if( glConfig.vidWidth * 480 > glConfig.vidHeight * 640 ) { // wide screen glConfig.xscale = glConfig.yscale; glConfig.xbias = ((float)glConfig.vidWidth - (640.0F * glConfig.xscale)) * 0.5F; } else { // no wide screen glConfig.xbias = 0.0f; } }
/* =============== GLimp_SetMode =============== */ static rserr_t GLimp_SetMode(glconfig_t *glConfig, const windowDesc_t *windowDesc, const char *windowTitle, int mode, qboolean fullscreen, qboolean noborder) { int perChannelColorBits; int colorBits, depthBits, stencilBits; int samples; int i = 0; SDL_Surface *icon = NULL; Uint32 flags = SDL_WINDOW_SHOWN; SDL_DisplayMode desktopMode; int display = 0; int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED; if ( windowDesc->api == GRAPHICS_API_OPENGL ) { flags |= SDL_WINDOW_OPENGL; } Com_Printf( "Initializing display\n"); icon = SDL_CreateRGBSurfaceFrom( (void *)CLIENT_WINDOW_ICON.pixel_data, CLIENT_WINDOW_ICON.width, CLIENT_WINDOW_ICON.height, CLIENT_WINDOW_ICON.bytes_per_pixel * 8, CLIENT_WINDOW_ICON.bytes_per_pixel * CLIENT_WINDOW_ICON.width, #ifdef Q3_LITTLE_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); // If a window exists, note its display index if( screen != NULL ) display = SDL_GetWindowDisplayIndex( screen ); if( SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) { displayAspect = (float)desktopMode.w / (float)desktopMode.h; Com_Printf( "Display aspect: %.3f\n", displayAspect ); } else { Com_Memset( &desktopMode, 0, sizeof( SDL_DisplayMode ) ); Com_Printf( "Cannot determine display aspect, assuming 1.333\n" ); } Com_Printf( "...setting mode %d:", mode ); if (mode == -2) { // use desktop video resolution if( desktopMode.h > 0 ) { glConfig->vidWidth = desktopMode.w; glConfig->vidHeight = desktopMode.h; } else { glConfig->vidWidth = 640; glConfig->vidHeight = 480; Com_Printf( "Cannot determine display resolution, assuming 640x480\n" ); } //glConfig.windowAspect = (float)glConfig.vidWidth / (float)glConfig.vidHeight; } else if ( !R_GetModeInfo( &glConfig->vidWidth, &glConfig->vidHeight, /*&glConfig.windowAspect,*/ mode ) ) { Com_Printf( " invalid mode\n" ); SDL_FreeSurface( icon ); return RSERR_INVALID_MODE; } Com_Printf( " %d %d\n", glConfig->vidWidth, glConfig->vidHeight); // Center window if( r_centerWindow->integer && !fullscreen ) { x = ( desktopMode.w / 2 ) - ( glConfig->vidWidth / 2 ); y = ( desktopMode.h / 2 ) - ( glConfig->vidHeight / 2 ); } // Destroy existing state if it exists if( opengl_context != NULL ) { SDL_GL_DeleteContext( opengl_context ); opengl_context = NULL; } if( screen != NULL ) { SDL_GetWindowPosition( screen, &x, &y ); Com_DPrintf( "Existing window at %dx%d before being destroyed\n", x, y ); SDL_DestroyWindow( screen ); screen = NULL; } if( fullscreen ) { flags |= SDL_WINDOW_FULLSCREEN; glConfig->isFullscreen = qtrue; } else { if( noborder ) flags |= SDL_WINDOW_BORDERLESS; glConfig->isFullscreen = qfalse; } colorBits = r_colorbits->integer; if ((!colorBits) || (colorBits >= 32)) colorBits = 24; if (!r_depthbits->integer) depthBits = 24; else depthBits = r_depthbits->integer; stencilBits = r_stencilbits->integer; samples = r_ext_multisample->integer; if ( windowDesc->api == GRAPHICS_API_OPENGL ) { for (i = 0; i < 16; i++) { int testColorBits, testDepthBits, testStencilBits; // 0 - default // 1 - minus colorBits // 2 - minus depthBits // 3 - minus stencil if ((i % 4) == 0 && i) { // one pass, reduce switch (i / 4) { case 2 : if (colorBits == 24) colorBits = 16; break; case 1 : if (depthBits == 24) depthBits = 16; else if (depthBits == 16) depthBits = 8; case 3 : if (stencilBits == 24) stencilBits = 16; else if (stencilBits == 16) stencilBits = 8; } } testColorBits = colorBits; testDepthBits = depthBits; testStencilBits = stencilBits; if ((i % 4) == 3) { // reduce colorBits if (testColorBits == 24) testColorBits = 16; } if ((i % 4) == 2) { // reduce depthBits if (testDepthBits == 24) testDepthBits = 16; else if (testDepthBits == 16) testDepthBits = 8; } if ((i % 4) == 1) { // reduce stencilBits if (testStencilBits == 24) testStencilBits = 16; else if (testStencilBits == 16) testStencilBits = 8; else testStencilBits = 0; } if (testColorBits == 24) perChannelColorBits = 8; else perChannelColorBits = 4; SDL_GL_SetAttribute( SDL_GL_RED_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, perChannelColorBits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, testDepthBits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, testStencilBits ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); if ( windowDesc->gl.majorVersion ) { int compactVersion = windowDesc->gl.majorVersion * 100 + windowDesc->gl.minorVersion * 10; SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, windowDesc->gl.majorVersion ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, windowDesc->gl.minorVersion ); if ( windowDesc->gl.profile == GLPROFILE_ES || compactVersion >= 320 ) { int profile; switch ( windowDesc->gl.profile ) { default: case GLPROFILE_COMPATIBILITY: profile = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY; break; case GLPROFILE_CORE: profile = SDL_GL_CONTEXT_PROFILE_CORE; break; case GLPROFILE_ES: profile = SDL_GL_CONTEXT_PROFILE_ES; break; } SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, profile ); } } if ( windowDesc->gl.contextFlags & GLCONTEXT_DEBUG ) { SDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG ); } if(r_stereo->integer) { glConfig->stereoEnabled = qtrue; SDL_GL_SetAttribute(SDL_GL_STEREO, 1); } else { glConfig->stereoEnabled = qfalse; SDL_GL_SetAttribute(SDL_GL_STEREO, 0); } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); if( ( screen = SDL_CreateWindow( windowTitle, x, y, glConfig->vidWidth, glConfig->vidHeight, flags ) ) == NULL ) { Com_DPrintf( "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; } #ifndef MACOS_X SDL_SetWindowIcon( screen, icon ); #endif if( fullscreen ) { SDL_DisplayMode mode; switch( testColorBits ) { case 16: mode.format = SDL_PIXELFORMAT_RGB565; break; case 24: mode.format = SDL_PIXELFORMAT_RGB24; break; default: Com_DPrintf( "testColorBits is %d, can't fullscreen\n", testColorBits ); continue; } mode.w = glConfig->vidWidth; mode.h = glConfig->vidHeight; mode.refresh_rate = glConfig->displayFrequency = r_displayRefresh->integer; mode.driverdata = NULL; if( SDL_SetWindowDisplayMode( screen, &mode ) < 0 ) { Com_DPrintf( "SDL_SetWindowDisplayMode failed: %s\n", SDL_GetError( ) ); continue; } } if( ( opengl_context = SDL_GL_CreateContext( screen ) ) == NULL ) { Com_Printf( "SDL_GL_CreateContext failed: %s\n", SDL_GetError( ) ); continue; } SDL_GL_SetSwapInterval( r_swapInterval->integer ); glConfig->colorBits = testColorBits; glConfig->depthBits = testDepthBits; glConfig->stencilBits = testStencilBits; Com_Printf( "Using %d color bits, %d depth, %d stencil display.\n", glConfig->colorBits, glConfig->depthBits, glConfig->stencilBits ); break; } } else { // Just create a regular window if( ( screen = SDL_CreateWindow( windowTitle, x, y, glConfig->vidWidth, glConfig->vidHeight, flags ) ) == NULL ) { Com_DPrintf( "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); } else { #ifndef MACOS_X SDL_SetWindowIcon( screen, icon ); #endif if( fullscreen ) { if( SDL_SetWindowDisplayMode( screen, NULL ) < 0 ) { Com_DPrintf( "SDL_SetWindowDisplayMode failed: %s\n", SDL_GetError( ) ); } } } } SDL_FreeSurface( icon ); if (!GLimp_DetectAvailableModes()) { return RSERR_UNKNOWN; } return RSERR_OK; }
/* ** GLW_SetMode */ static rserr_t GLW_SetMode( int mode, int colorbits, qboolean cdsFullscreen ) { HDC hDC; const char *win_fs[] = { "W", "FS" }; int cdsRet; DEVMODE dm; // // print out informational messages // ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) { ri.Printf( PRINT_ALL, " invalid mode\n" ); return RSERR_INVALID_MODE; } ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, win_fs[cdsFullscreen] ); // // check our desktop attributes // hDC = GetDC( GetDesktopWindow() ); glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES ); glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES ); ReleaseDC( GetDesktopWindow(), hDC ); // // verify desktop bit depth // if ( glw_state.desktopBitsPixel < 15 || glw_state.desktopBitsPixel == 24 ) { if ( colorbits == 0 || ( !cdsFullscreen && colorbits >= 15 ) ) { // since I can't be bothered trying to mess around with asian codepages and MBCS stuff for a windows // error box that'll only appear if something's seriously f****d then I'm going to fallback to // english text when these would otherwise be used... // char sErrorHead[1024]; // ott extern qboolean Language_IsAsian(void); Q_strncpyz(sErrorHead, Language_IsAsian() ? "Low Desktop Color Depth" : SP_GetStringTextString("CON_TEXT_LOW_DESKTOP_COLOUR_DEPTH"), sizeof(sErrorHead) ); const char *psErrorBody = Language_IsAsian() ? "It is highly unlikely that a correct windowed\n" "display can be initialized with the current\n" "desktop display depth. Select 'OK' to try\n" "anyway. Select 'Cancel' to try a fullscreen\n" "mode instead." : SP_GetStringTextString("CON_TEXT_TRY_ANYWAY"); if ( MessageBox( NULL, psErrorBody, sErrorHead, MB_OKCANCEL | MB_ICONEXCLAMATION ) != IDOK ) { return RSERR_INVALID_MODE; } } } // do a CDS if needed if ( cdsFullscreen ) { memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); dm.dmPelsWidth = glConfig.vidWidth; dm.dmPelsHeight = glConfig.vidHeight; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; if ( r_displayRefresh->integer != 0 ) { dm.dmDisplayFrequency = r_displayRefresh->integer; dm.dmFields |= DM_DISPLAYFREQUENCY; } // try to change color depth if possible if ( colorbits != 0 ) { if ( glw_state.allowdisplaydepthchange ) { dm.dmBitsPerPel = colorbits; dm.dmFields |= DM_BITSPERPEL; ri.Printf( PRINT_ALL, "...using colorsbits of %d\n", colorbits ); } else { ri.Printf( PRINT_ALL, "WARNING:...changing depth not supported on Win95 < pre-OSR 2.x\n" ); } } else { ri.Printf( PRINT_ALL, "...using desktop display depth of %d\n", glw_state.desktopBitsPixel ); } // // if we're already in fullscreen then just create the window // if ( glw_state.cdsFullscreen ) { ri.Printf( PRINT_ALL, "...already fullscreen, avoiding redundant CDS\n" ); if ( !GLW_CreateWindow ( glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue ) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } } // // need to call CDS // else { ri.Printf( PRINT_ALL, "...calling CDS: " ); // try setting the exact mode requested, because some drivers don't report // the low res modes in EnumDisplaySettings, but still work if ( ( cdsRet = ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { ri.Printf( PRINT_ALL, "ok\n" ); if ( !GLW_CreateWindow ( glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } glw_state.cdsFullscreen = qtrue; } else { // // the exact mode failed, so scan EnumDisplaySettings for the next largest mode // DEVMODE devmode; int modeNum; ri.Printf( PRINT_ALL, "failed, " ); PrintCDSError( cdsRet ); ri.Printf( PRINT_ALL, "...trying next higher resolution:" ); // we could do a better matching job here... for ( modeNum = 0 ; ; modeNum++ ) { if ( !EnumDisplaySettings( NULL, modeNum, &devmode ) ) { modeNum = -1; break; } if ( devmode.dmPelsWidth >= glConfig.vidWidth && devmode.dmPelsHeight >= glConfig.vidHeight && devmode.dmBitsPerPel >= 15 ) { break; } } if ( modeNum != -1 && ( cdsRet = ChangeDisplaySettings( &devmode, CDS_FULLSCREEN ) ) == DISP_CHANGE_SUCCESSFUL ) { ri.Printf( PRINT_ALL, " ok\n" ); if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, qtrue) ) { ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); return RSERR_INVALID_MODE; } glw_state.cdsFullscreen = qtrue; } else { ri.Printf( PRINT_ALL, " failed, " ); PrintCDSError( cdsRet ); ri.Printf( PRINT_ALL, "...restoring display settings\n" ); ChangeDisplaySettings( 0, 0 ); /* jfm: i took out the following code to allow fallback to mode 3, with this code it goes half windowed and just doesn't work. glw_state.cdsFullscreen = qfalse; glConfig.isFullscreen = qfalse; if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse) ) { return RSERR_INVALID_MODE; } */ return RSERR_INVALID_FULLSCREEN; } } } } else { if ( glw_state.cdsFullscreen ) { ChangeDisplaySettings( 0, 0 ); } glw_state.cdsFullscreen = qfalse; if ( !GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, colorbits, qfalse ) ) { return RSERR_INVALID_MODE; } } // // success, now check display frequency, although this won't be valid on Voodoo(2) // memset( &dm, 0, sizeof( dm ) ); dm.dmSize = sizeof( dm ); if ( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm ) ) { glConfig.displayFrequency = dm.dmDisplayFrequency; } // NOTE: this is overridden later on standalone 3Dfx drivers glConfig.isFullscreen = cdsFullscreen; return RSERR_OK; }