/* =============== GLimp_SetMode =============== */ static int 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 = 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 = 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_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 // 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; } qglClearColor( 0, 0, 0, 1 ); qglClear( GL_COLOR_BUFFER_BIT ); SDL_GL_SwapWindow( SDL_window ); 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; }
/* ================ GfxInfo_f ================ */ void GfxInfo_f(void) { const char *enablestrings[] = { "disabled", "enabled" }; const char *fsstrings[] = { "windowed", "fullscreen" }; Ren_Print("\nGL_VENDOR: %s\n", glConfig.vendor_string); Ren_Print("GL_VERSION: %s\n", glConfig.version_string); if (r_gfxInfo->integer > 0) { Ren_Print("GL_RENDERER: %s\n", glConfig.renderer_string); // GLEW already reports this Ren_Print("GL_EXTENSIONS: "); R_PrintLongString((char *)qglGetString(GL_EXTENSIONS)); } Ren_Print("\nGL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize); Ren_Print("GL_MAX_ACTIVE_TEXTURES_ARB: %d\n", glConfig.maxActiveTextures); Ren_Print("PIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits); Ren_Print("MODE: %d, SCREEN: %d x %d %s (ratio %.4f) Hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1], glConfig.windowAspect); if (glConfig.displayFrequency) { Ren_Print("%d\n", glConfig.displayFrequency); } else { Ren_Print("N/A\n"); } if (glConfig.deviceSupportsGamma) { Ren_Print("GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits); } else { Ren_Print("GAMMA: software w/ %d overbright bits\n", tr.overbrightBits); } // rendering primitives { int primitives; // default is to use triangles if compiled vertex arrays are present Ren_Print("rendering primitives: "); primitives = r_primitives->integer; if (primitives == 0) { if (qglLockArraysEXT) { primitives = 2; } else { primitives = 1; } } if (primitives == -1) { Ren_Print("none\n"); } else if (primitives == 2) { Ren_Print("single glDrawElements\n"); } else if (primitives == 1) { Ren_Print("multiple glArrayElement\n"); } else if (primitives == 3) { Ren_Print("multiple glColor4ubv + glTexCoord2fv + glVertex3fv\n"); } } Ren_Print("texturemode: %s\n", r_textureMode->string); Ren_Print("picmip: %d\n", r_picmip->integer); Ren_Print("texture bits: %d\n", r_texturebits->integer); Ren_Print("multitexture: %s\n", enablestrings[qglActiveTextureARB != 0]); Ren_Print("compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0]); Ren_Print("texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0]); Ren_Print("compressed textures: %s\n", enablestrings[glConfig.textureCompression != TC_NONE]); if (r_finish->integer) { Ren_Print("Forcing glFinish\n"); } Ren_Print("Renderer: vanilla+\n"); }
/* ================= R_LoadARBProgram ================= */ void R_LoadARBProgram( int progIndex ) { int ofs; int err; idStr fullPath = "glprogs/"; fullPath += progs[progIndex].name; char *fileBuffer; char *buffer; char *start, *end; common->Printf( "%s", fullPath.c_str() ); // load the program even if we don't support it, so // fs_copyfiles can generate cross-platform data dumps fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL ); if ( !fileBuffer ) { common->Printf( ": File not found\n" ); return; } // copy to stack memory and free buffer = (char *)_alloca( strlen( fileBuffer ) + 1 ); strcpy( buffer, fileBuffer ); fileSystem->FreeFile( fileBuffer ); if ( !glConfig.isInitialized ) { return; } // // submit the program string at start to GL // if ( progs[progIndex].ident == 0 ) { // allocate a new identifier for this program progs[progIndex].ident = PROG_USER + progIndex; } // vertex and fragment programs can both be present in a single file, so // scan for the proper header to be the start point, and stamp a 0 in after the end if ( progs[progIndex].target == GL_VERTEX_PROGRAM_ARB ) { if ( !glConfig.ARBVertexProgramAvailable ) { common->Printf( ": GL_VERTEX_PROGRAM_ARB not available\n" ); return; } start = strstr( (char *)buffer, "!!ARBvp" ); } if ( progs[progIndex].target == GL_FRAGMENT_PROGRAM_ARB ) { if ( !glConfig.ARBFragmentProgramAvailable ) { common->Printf( ": GL_FRAGMENT_PROGRAM_ARB not available\n" ); return; } start = strstr( (char *)buffer, "!!ARBfp" ); } if ( !start ) { common->Printf( ": !!ARB not found\n" ); return; } end = strstr( start, "END" ); if ( !end ) { common->Printf( ": END not found\n" ); return; } end[3] = 0; qglBindProgramARB( progs[progIndex].target, progs[progIndex].ident ); qglGetError(); qglProgramStringARB( progs[progIndex].target, GL_PROGRAM_FORMAT_ASCII_ARB, strlen( start ), (unsigned char *)start ); err = qglGetError(); qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, (GLint *)&ofs ); if ( err == GL_INVALID_OPERATION ) { const GLubyte *str = qglGetString( GL_PROGRAM_ERROR_STRING_ARB ); common->Printf( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str ); if ( ofs < 0 ) { common->Printf( "GL_PROGRAM_ERROR_POSITION_ARB < 0 with error\n" ); } else if ( ofs >= (int)strlen( (char *)start ) ) { common->Printf( "error at end of program\n" ); } else { common->Printf( "error at %i:\n%s", ofs, start + ofs ); } return; } if ( ofs != -1 ) { common->Printf( "\nGL_PROGRAM_ERROR_POSITION_ARB != -1 without error\n" ); return; } common->Printf( "\n" ); }
void GLimp_Init( void ) { ri.Cvar_Get( "r_restartOnResize", "1", CVAR_ARCHIVE ); ri.Cvar_Get( "r_resizeDelay", "1000", CVAR_ARCHIVE ); r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH ); r_sdlDriver = ri.Cvar_Get( "r_sdlDriver", "", CVAR_ROM ); r_allowResize = ri.Cvar_Get( "r_allowResize", "0", CVAR_ARCHIVE ); /* if( ri.Cvar_VariableIntegerValue( "com_abnormalExit" ) ) { ri.Cvar_Set( "r_mode", va( "%d", R_MODE_FALLBACK ) ); ri.Cvar_Set( "r_picmap", "1" ); ri.Cvar_Set( "r_texturebits", "0" ); ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST" ); ri.Cvar_Set( "r_fullscreen", "0" ); ri.Cvar_Set( "r_centerWindow", "0" ); ri.Cvar_Set( "com_abnormalExit", "0" ); }*/ Sys_SetEnv( "SDL_VIDEO_CENTERED", r_centerWindow->integer ? "1" : "" ); // Create the window and set up the context if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, r_noborder->integer)) goto success; // Try again, this time in a platform specific "safe mode" /* Sys_GLimpSafeInit( ); if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, qfalse)) goto success; */ /* // Finally, try the default screen resolution if( r_mode->integer != R_MODE_FALLBACK ) { Com_Printf( "Setting r_mode %d failed, falling back on r_mode %d\n", r_mode->integer, R_MODE_FALLBACK ); if(GLimp_StartDriverAndSetMode(R_MODE_FALLBACK, qfalse, qfalse)) goto success; }*/ // Nothing worked, give up Com_Error( ERR_FATAL, "GLimp_Init() - could not load OpenGL subsystem" ); success: // This values force the UI to disable driver selection // glConfig.driverType = GLDRV_ICD; // glConfig.hardwareType = GLHW_GENERIC; glConfig.deviceSupportsGamma = (qboolean)(SDL_SetGamma( screen, 1.0f, 1.0f, 1.0f ) >= 0); // Mysteriously, if you use an NVidia graphics card and multiple monitors, // SDL_SetGamma will incorrectly return false... the first time; ask // again and you get the correct answer. This is a suspected driver bug, see // http://bugzilla.icculus.org/show_bug.cgi?id=4316 glConfig.deviceSupportsGamma = (qboolean)(SDL_SetGamma( screen, 1.0f, 1.0f, 1.0f ) >= 0); if ( -1 == r_ignorehwgamma->integer) glConfig.deviceSupportsGamma = 1; if ( 1 == r_ignorehwgamma->integer) glConfig.deviceSupportsGamma = 0; // get our config strings glConfig.vendor_string = (const char *) qglGetString (GL_VENDOR); glConfig.renderer_string = (const char *) qglGetString (GL_RENDERER); glConfig.version_string = (const char *) qglGetString (GL_VERSION); glConfig.extensions_string = (const char *) qglGetString (GL_EXTENSIONS); // OpenGL driver constants qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &glConfig.maxTextureSize ); // stubbed or broken drivers may have reported 0... if ( glConfig.maxTextureSize <= 0 ) { glConfig.maxTextureSize = 0; } // initialize extensions GLimp_InitExtensions( ); ri.Cvar_Get( "r_availableModes", "", CVAR_ROM ); // This depends on SDL_INIT_VIDEO, hence having it here ri.IN_Init( screen ); }
/* =============== 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 && !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( 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 { 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 ); 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->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 ) ) == NULL ) { Com_DPrintf( "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: Com_DPrintf( "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 ) { Com_DPrintf( "SDL_SetWindowDisplayMode failed: %s\n", SDL_GetError( ) ); continue; } } SDL_SetWindowTitle( screen, CLIENT_WINDOW_TITLE ); //SDL_SetWindowIcon( screen, icon ); if( ( opengl_context = 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 );*/ if (!GLimp_DetectAvailableModes()) { return RSERR_UNKNOWN; } 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 // FIXME: Product name cvar_t *com_productName = ri.Cvar_Get("com_productName", "OpenJK" /* PRODUCT_NAME */, CVAR_ROM); //SDL_SetWindowTitle(com_productName->string, com_productName->string); SDL_ShowCursor(0); if (!(window = SDL_CreateWindow(com_productName->string, 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 }
/* =============== GLimp_Init This routine is responsible for initializing the OS specific portions of OpenGL =============== */ void GLimp_Init( void ) { ri.Printf( PRINT_DEVELOPER, "Glimp_Init( )\n" ); r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH ); r_sdlDriver = ri.Cvar_Get( "r_sdlDriver", "", CVAR_ROM ); r_allowResize = ri.Cvar_Get( "r_allowResize", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_centerWindow = ri.Cvar_Get( "r_centerWindow", "0", CVAR_ARCHIVE | CVAR_LATCH ); if( ri.Cvar_VariableIntegerValue( "com_abnormalExit" ) ) { ri.Cvar_Set( "r_mode", va( "%d", R_MODE_FALLBACK ) ); ri.Cvar_Set( "r_fullscreen", "0" ); ri.Cvar_Set( "r_centerWindow", "0" ); ri.Cvar_Set( "com_abnormalExit", "0" ); } ri.Sys_GLimpInit( ); // Create the window and set up the context if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, r_noborder->integer)) goto success; // Try again, this time in a platform specific "safe mode" ri.Sys_GLimpSafeInit( ); if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, qfalse)) goto success; // Finally, try the default screen resolution if( r_mode->integer != R_MODE_FALLBACK ) { ri.Printf( PRINT_ALL, "Setting r_mode %d failed, falling back on r_mode %d\n", r_mode->integer, R_MODE_FALLBACK ); if(GLimp_StartDriverAndSetMode(R_MODE_FALLBACK, qfalse, qfalse)) goto success; } // Nothing worked, give up ri.Error( ERR_FATAL, "GLimp_Init() - could not load OpenGL subsystem" ); success: // These values force the UI to disable driver selection glConfig.driverType = GLDRV_ICD; glConfig.hardwareType = GLHW_GENERIC; // Only using SDL_SetWindowBrightness to determine if hardware gamma is supported glConfig.deviceSupportsGamma = !r_ignorehwgamma->integer && SDL_SetWindowBrightness( SDL_window, 1.0f ) >= 0; // get our config strings Q_strncpyz( glConfig.vendor_string, (char *) qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) ); Q_strncpyz( glConfig.renderer_string, (char *) qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) ); if (*glConfig.renderer_string && glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] == '\n') glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] = 0; Q_strncpyz( glConfig.version_string, (char *) qglGetString (GL_VERSION), sizeof( glConfig.version_string ) ); Q_strncpyz( glConfig.extensions_string, (char *) qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) ); // initialize extensions GLimp_InitExtensions( ); ri.Cvar_Get( "r_availableModes", "", CVAR_ROM ); // This depends on SDL_INIT_VIDEO, hence having it here ri.IN_Init( SDL_window ); }
/* ** GLimp_Init ** ** This is the platform specific OpenGL initialization function. It ** is responsible for loading OpenGL, initializing it, setting ** extensions, creating a window of the appropriate size, doing ** fullscreen manipulations, etc. Its overall responsibility is ** to make sure that a functional OpenGL subsystem is operating ** when it returns to the ref. */ void GLimp_Init( void ) { char buf[1024]; cvar_t *lastValidRenderer = ri.Cvar_Get( "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE ); cvar_t *cv; ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" ); // // check OS version to see if we can do fullscreen display changes // if ( !GLW_CheckOSVersion() ) { ri.Error( ERR_VID_FATAL, "GLimp_Init() - incorrect operating system\n" ); } // save off hInstance and wndproc cv = ri.Cvar_Get( "win_hinstance", "", 0 ); sscanf( cv->string, "%i", (int *)&g_wv.hInstance ); cv = ri.Cvar_Get( "win_wndproc", "", 0 ); sscanf( cv->string, "%i", (int *)&glw_state.wndproc ); r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH ); r_maskMinidriver = ri.Cvar_Get( "r_maskMinidriver", "0", CVAR_LATCH ); // load appropriate DLL and initialize subsystem GLW_StartOpenGL(); // get our config strings Q_strncpyz( glConfig.vendor_string, qglGetString( GL_VENDOR ), sizeof( glConfig.vendor_string ) ); Q_strncpyz( glConfig.renderer_string, qglGetString( GL_RENDERER ), sizeof( glConfig.renderer_string ) ); Q_strncpyz( glConfig.version_string, qglGetString( GL_VERSION ), sizeof( glConfig.version_string ) ); Q_strncpyz( glConfig.extensions_string, qglGetString( GL_EXTENSIONS ), sizeof( glConfig.extensions_string ) ); // TTimo - safe check if ( strlen( qglGetString( GL_EXTENSIONS ) ) >= sizeof( glConfig.extensions_string ) ) { Com_Printf( S_COLOR_YELLOW "WARNNING: GL extensions string too long (%d), truncated to %d\n", strlen( qglGetString( GL_EXTENSIONS ) ), sizeof( glConfig.extensions_string ) ); } // // chipset specific configuration // Q_strncpyz( buf, glConfig.renderer_string, sizeof( buf ) ); Q_strlwr( buf ); // // NOTE: if changing cvars, do it within this block. This allows them // to be overridden when testing driver fixes, etc. but only sets // them to their default state when the hardware is first installed/run. // if ( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) ) { glConfig.hardwareType = GLHW_GENERIC; ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST" ); // VOODOO GRAPHICS w/ 2MB if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) ) { ri.Cvar_Set( "r_picmip", "2" ); ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH ); } else { //----(SA) FIXME: RETURN TO DEFAULT Another id build change for DK/DM ri.Cvar_Set( "r_picmip", "1" ); //----(SA) was "1" // JPW NERVE back to 1 //----(SA) if ( strstr( buf, "rage 128" ) || strstr( buf, "rage128" ) ) { ri.Cvar_Set( "r_finish", "0" ); } // Savage3D and Savage4 should always have trilinear enabled else if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) ) { ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); } } } // // this is where hardware specific workarounds that should be // detected/initialized every startup should go. // if ( strstr( buf, "banshee" ) || strstr( buf, "voodoo3" ) ) { glConfig.hardwareType = GLHW_3DFX_2D3D; } // VOODOO GRAPHICS w/ 2MB else if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) ) { } else if ( strstr( buf, "glzicd" ) ) { } else if ( strstr( buf, "rage pro" ) /*|| strstr( buf, "Rage Pro")*/ || strstr( buf, "ragepro" ) ) { glConfig.hardwareType = GLHW_RAGEPRO; ri.Printf( PRINT_WARNING, "WARNING: Rage Pro hardware is unsupported. Rendering errors may occur.\n" ); } else if ( strstr( buf, "rage 128" ) ) { } else if ( strstr( buf, "permedia2" ) ) { glConfig.hardwareType = GLHW_PERMEDIA2; ri.Printf( PRINT_WARNING, "WARNING: Permedia hardware is unsupported. Rendering errors may occur.\n" ); } else if ( strstr( buf, "riva 128" ) ) { glConfig.hardwareType = GLHW_RIVA128; ri.Printf( PRINT_WARNING, "WARNING: Riva 128 hardware is unsupported. Rendering errors may occur.\n" ); } else if ( strstr( buf, "matrox" ) ) { } else if ( strstr( buf, "riva tnt " ) ) { } if ( strstr( buf, "geforce3" ) || strstr( buf, "geforce4 ti" ) || strstr( buf, "geforce fx 5600" ) || strstr( buf, "geforce fx 5800" ) || strstr( buf, "radeon 8500" ) || strstr( buf, "radeon 9000" ) || strstr( buf, "radeon 9500" ) || strstr( buf, "radeon 9600" ) || strstr( buf, "radeon 9700" ) || strstr( buf, "radeon 9800" ) || strstr( buf, "nv20" ) || strstr( buf, "nv30" ) ) { ri.Cvar_Set( "r_highQualityVideo", "1" ); } else { ri.Cvar_Set( "r_highQualityVideo", "0" ); } ri.Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string ); GLW_InitExtensions(); WG_CheckHardwareGamma(); // initialise default lists GLW_GenDefaultLists(); }
/* * @brief This routine is responsible for initializing the OS specific portions of OpenGL */ void GLimp_Init(void) { r_allowSoftwareGL = ri.Cvar_Get("r_allowSoftwareGL", "0", CVAR_LATCH); r_sdlDriver = ri.Cvar_Get("r_sdlDriver", "", CVAR_ROM); r_allowResize = ri.Cvar_Get("r_allowResize", "0", CVAR_ARCHIVE); r_centerWindow = ri.Cvar_Get("r_centerWindow", "0", CVAR_ARCHIVE); if (Cvar_VariableIntegerValue("com_abnormalExit")) { ri.Cvar_Set("r_mode", va("%d", R_MODE_FALLBACK)); ri.Cvar_Set("r_fullscreen", "0"); ri.Cvar_Set("r_centerWindow", "0"); ri.Cvar_Set("com_abnormalExit", "0"); } Sys_SetEnv("SDL_VIDEO_CENTERED", r_centerWindow->integer ? "1" : ""); Sys_GLimpInit(); // Create the window and set up the context if (GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, r_noborder->integer)) { goto success; } // Try again, this time in a platform specific "safe mode" Sys_GLimpSafeInit(); if (GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, qfalse)) { goto success; } // Finally, try the default screen resolution if (r_mode->integer != R_MODE_FALLBACK) { ri.Printf(PRINT_ALL, "Setting r_mode %d failed, falling back on r_mode %d\n", r_mode->integer, R_MODE_FALLBACK); if (GLimp_StartDriverAndSetMode(R_MODE_FALLBACK, qfalse, qfalse)) { goto success; } } // Nothing worked, give up ri.Error(ERR_FATAL, "GLimp_Init() - could not load OpenGL subsystem\n"); success: // This values force the UI to disable driver selection glConfig.driverType = GLDRV_ICD; glConfig.hardwareType = GLHW_GENERIC; glConfig.deviceSupportsGamma = SDL_SetGamma(1.0f, 1.0f, 1.0f) >= 0; // Mysteriously, if you use an NVidia graphics card and multiple monitors, // SDL_SetGamma will incorrectly return false... the first time; ask // again and you get the correct answer. This is a suspected driver bug, see // http://bugzilla.icculus.org/show_bug.cgi?id=4316 glConfig.deviceSupportsGamma = SDL_SetGamma(1.0f, 1.0f, 1.0f) >= 0; if (-1 == r_ignorehwgamma->integer) { glConfig.deviceSupportsGamma = 1; } if (1 == r_ignorehwgamma->integer) { glConfig.deviceSupportsGamma = 0; } // get our config strings Q_strncpyz(glConfig.vendor_string, (char *) qglGetString(GL_VENDOR), sizeof(glConfig.vendor_string)); Q_strncpyz(glConfig.renderer_string, (char *) qglGetString(GL_RENDERER), sizeof(glConfig.renderer_string)); if (*glConfig.renderer_string && glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] == '\n') { glConfig.renderer_string[strlen(glConfig.renderer_string) - 1] = 0; } Q_strncpyz(glConfig.version_string, (char *) qglGetString(GL_VERSION), sizeof(glConfig.version_string)); Q_strncpyz(glConfig.extensions_string, (char *) qglGetString(GL_EXTENSIONS), sizeof(glConfig.extensions_string)); // initialize extensions GLimp_InitExtensions(); ri.Cvar_Get("r_availableModes", "", CVAR_ROM); // This depends on SDL_INIT_VIDEO, hence having it here IN_Init(); }
/* =============== 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); } else { ri.Printf(PRINT_ALL, "Cannot estimate display aspect, assuming 1.333\n"); } } ri.Printf(PRINT_ALL, "...setting mode %d:\n", 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 // TODO: SDL_GL_ACCELERATED_VISUAL is broken on ATI cards // This code can be enabled once we move to SDL >= 1.3 // 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; }
/* ** GLimp_Init ** ** This is the platform specific OpenGL initialization function. It ** is responsible for loading OpenGL, initializing it, setting ** extensions, creating a window of the appropriate size, doing ** fullscreen manipulations, etc. Its overall responsibility is ** to make sure that a functional OpenGL subsystem is operating ** when it returns to the ref. */ void GLimp_Init( void ) { char buf[MAX_STRING_CHARS]; cvar_t *lastValidRenderer = ri.Cvar_Get( "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE ); cvar_t *cv; ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" ); // // check OS version to see if we can do fullscreen display changes // if ( !GLW_CheckOSVersion() ) { ri.Error( ERR_FATAL, "GLimp_Init() - incorrect operating system\n" ); } // save off hInstance and wndproc cv = ri.Cvar_Get( "win_hinstance", "", 0 ); sscanf( cv->string, "%i", (int *)&g_wv.hInstance ); cv = ri.Cvar_Get( "win_wndproc", "", 0 ); sscanf( cv->string, "%i", (int *)&glw_state.wndproc ); r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH ); // load appropriate DLL and initialize subsystem GLW_StartOpenGL(); // get our config strings const char* glstring; glstring = (const char *)qglGetString (GL_VENDOR); if (!glstring) { glstring = "invalid driver"; } Q_strncpyz( glConfig.vendor_string, glstring, sizeof( glConfig.vendor_string ) ); glstring = (const char *)qglGetString (GL_RENDERER); if (!glstring) { glstring = "invalid driver"; } Q_strncpyz( glConfig.renderer_string, glstring, sizeof( glConfig.renderer_string ) ); glstring = (const char *)qglGetString (GL_VERSION); if (!glstring) { glstring = "invalid driver"; } Q_strncpyz( glConfig.version_string, glstring, sizeof( glConfig.version_string ) ); glstring = (const char *)qglGetString (GL_EXTENSIONS); if (!glstring) { glstring = "invalid driver"; } Q_strncpyz( glConfig.extensions_string, glstring, sizeof( glConfig.extensions_string ) ); // OpenGL driver constants qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &glConfig.maxTextureSize ); // stubbed or broken drivers may have reported 0... if ( glConfig.maxTextureSize <= 0 ) { glConfig.maxTextureSize = 0; } GLW_InitExtensions(); // // chipset specific configuration // Q_strncpyz( buf, glConfig.renderer_string, sizeof(buf) ); Q_strlwr( buf ); // // NOTE: if changing cvars, do it within this block. This allows them // to be overridden when testing driver fixes, etc. but only sets // them to their default state when the hardware is first installed/run. // extern qboolean Sys_LowPhysicalMemory(); if ( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) ) { if (Sys_LowPhysicalMemory()) { ri.Cvar_Set("s_khz", "11");// this will get called before S_Init } //reset to defaults ri.Cvar_Set( "r_picmip", "1" ); // Savage3D and Savage4 should always have trilinear enabled if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) || strstr( buf, "geforce" )) { ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); } else { ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST" ); } if ( strstr( buf, "kyro" ) ) { ri.Cvar_Set( "r_ext_texture_filter_anisotropic", "0"); //KYROs have it avail, but suck at it! ri.Cvar_Set( "r_ext_preferred_tc_method", "1"); //(Use DXT1 instead of DXT5 - same quality but much better performance on KYRO) } //this must be a really sucky card! if ( (glConfig.textureCompression == TC_NONE) || (glConfig.maxActiveTextures < 2) || (glConfig.maxTextureSize <= 512) ) { ri.Cvar_Set( "r_picmip", "2"); ri.Cvar_Set( "r_lodbias", "2"); ri.Cvar_Set( "r_detailtextures", "0"); ri.Cvar_Set( "r_colorbits", "16"); ri.Cvar_Set( "r_texturebits", "16"); ri.Cvar_Set( "cg_shadows", "0"); ri.Cvar_Set( "r_mode", "3"); //force 640 } } ri.Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string ); WG_CheckHardwareGamma(); }
void GLimp_InitExtraExtensions() { char *extension; const char* result[3] = { "...ignoring %s\n", "...using %s\n", "...%s not found\n" }; // GL_EXT_draw_range_elements extension = "GL_EXT_draw_range_elements"; glRefConfig.drawRangeElements = qfalse; qglMultiDrawArraysEXT = NULL; qglMultiDrawElementsEXT = NULL; if( GLimp_HaveExtension( extension ) ) { qglDrawRangeElementsEXT = (void *) SDL_GL_GetProcAddress("glDrawRangeElementsEXT"); if ( r_ext_draw_range_elements->integer) glRefConfig.drawRangeElements = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.drawRangeElements], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_EXT_multi_draw_arrays extension = "GL_EXT_multi_draw_arrays"; glRefConfig.multiDrawArrays = qfalse; qglMultiDrawArraysEXT = NULL; qglMultiDrawElementsEXT = NULL; if( GLimp_HaveExtension( extension ) ) { qglMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawArraysEXT"); qglMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawElementsEXT"); if ( r_ext_multi_draw_arrays->integer ) glRefConfig.multiDrawArrays = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.multiDrawArrays], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_vertex_program //glRefConfig.vertexProgram = qfalse; extension = "GL_ARB_vertex_program"; qglVertexAttrib4fARB = NULL; qglVertexAttrib4fvARB = NULL; qglVertexAttribPointerARB = NULL; qglEnableVertexAttribArrayARB = NULL; qglDisableVertexAttribArrayARB = NULL; if( GLimp_HaveExtension( extension ) ) { qglVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fARB"); qglVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fvARB"); qglVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) SDL_GL_GetProcAddress("glVertexAttribPointerARB"); qglEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glEnableVertexAttribArrayARB"); qglDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glDisableVertexAttribArrayARB"); ri.Printf(PRINT_ALL, result[1], extension); //glRefConfig.vertexProgram = qtrue; } else { ri.Error(ERR_FATAL, result[2], extension); } // GL_ARB_vertex_buffer_object //glRefConfig.vertexBufferObject = qfalse; extension = "GL_ARB_vertex_buffer_object"; qglBindBufferARB = NULL; qglDeleteBuffersARB = NULL; qglGenBuffersARB = NULL; qglIsBufferARB = NULL; qglBufferDataARB = NULL; qglBufferSubDataARB = NULL; qglGetBufferSubDataARB = NULL; qglGetBufferParameterivARB = NULL; qglGetBufferPointervARB = NULL; if( GLimp_HaveExtension( extension ) ) { qglBindBufferARB = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB"); qglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB"); qglGenBuffersARB = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB"); qglIsBufferARB = (PFNGLISBUFFERARBPROC) SDL_GL_GetProcAddress("glIsBufferARB"); qglBufferDataARB = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB"); qglBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glBufferSubDataARB"); qglGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glGetBufferSubDataARB"); qglGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetBufferParameterivARB"); qglGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) SDL_GL_GetProcAddress("glGetBufferPointervARB"); ri.Printf(PRINT_ALL, result[1], extension); //glRefConfig.vertexBufferObject = qtrue; } else { ri.Error(ERR_FATAL, result[2], extension); } // GL_ARB_shader_objects extension = "GL_ARB_shader_objects"; //glRefConfig.shaderObjects = qfalse; qglDeleteObjectARB = NULL; qglGetHandleARB = NULL; qglDetachObjectARB = NULL; qglCreateShaderObjectARB = NULL; qglShaderSourceARB = NULL; qglCompileShaderARB = NULL; qglCreateProgramObjectARB = NULL; qglAttachObjectARB = NULL; qglLinkProgramARB = NULL; qglUseProgramObjectARB = NULL; qglValidateProgramARB = NULL; qglUniform1fARB = NULL; qglUniform2fARB = NULL; qglUniform3fARB = NULL; qglUniform4fARB = NULL; qglUniform1iARB = NULL; qglUniform2iARB = NULL; qglUniform3iARB = NULL; qglUniform4iARB = NULL; qglUniform1fvARB = NULL; qglUniform2fvARB = NULL; qglUniform3fvARB = NULL; qglUniform4fvARB = NULL; qglUniform2ivARB = NULL; qglUniform3ivARB = NULL; qglUniform4ivARB = NULL; qglUniformMatrix2fvARB = NULL; qglUniformMatrix3fvARB = NULL; qglUniformMatrix4fvARB = NULL; qglGetObjectParameterfvARB = NULL; qglGetObjectParameterivARB = NULL; qglGetInfoLogARB = NULL; qglGetAttachedObjectsARB = NULL; qglGetUniformLocationARB = NULL; qglGetActiveUniformARB = NULL; qglGetUniformfvARB = NULL; qglGetUniformivARB = NULL; qglGetShaderSourceARB = NULL; if( GLimp_HaveExtension( extension ) ) { qglDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB"); qglGetHandleARB = (PFNGLGETHANDLEARBPROC) SDL_GL_GetProcAddress("glGetHandleARB"); qglDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) SDL_GL_GetProcAddress("glDetachObjectARB"); qglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB"); qglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB"); qglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB"); qglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB"); qglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB"); qglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB"); qglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB"); qglValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) SDL_GL_GetProcAddress("glValidateProgramARB"); qglUniform1fARB = (PFNGLUNIFORM1FARBPROC) SDL_GL_GetProcAddress("glUniform1fARB"); qglUniform2fARB = (PFNGLUNIFORM2FARBPROC) SDL_GL_GetProcAddress("glUniform2fARB"); qglUniform3fARB = (PFNGLUNIFORM3FARBPROC) SDL_GL_GetProcAddress("glUniform3fARB"); qglUniform4fARB = (PFNGLUNIFORM4FARBPROC) SDL_GL_GetProcAddress("glUniform4fARB"); qglUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB"); qglUniform2iARB = (PFNGLUNIFORM2IARBPROC) SDL_GL_GetProcAddress("glUniform2iARB"); qglUniform3iARB = (PFNGLUNIFORM3IARBPROC) SDL_GL_GetProcAddress("glUniform3iARB"); qglUniform4iARB = (PFNGLUNIFORM4IARBPROC) SDL_GL_GetProcAddress("glUniform4iARB"); qglUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) SDL_GL_GetProcAddress("glUniform1fvARB"); qglUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) SDL_GL_GetProcAddress("glUniform2fvARB"); qglUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) SDL_GL_GetProcAddress("glUniform3fvARB"); qglUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) SDL_GL_GetProcAddress("glUniform4fvARB"); qglUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) SDL_GL_GetProcAddress("glUniform2ivARB"); qglUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) SDL_GL_GetProcAddress("glUniform3ivARB"); qglUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) SDL_GL_GetProcAddress("glUniform4ivARB"); qglUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix2fvARB"); qglUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix3fvARB"); qglUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix4fvARB"); qglGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterfvARB"); qglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB"); qglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB"); qglGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) SDL_GL_GetProcAddress("glGetAttachedObjectsARB"); qglGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB"); qglGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) SDL_GL_GetProcAddress("glGetActiveUniformARB"); qglGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) SDL_GL_GetProcAddress("glGetUniformfvARB"); qglGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) SDL_GL_GetProcAddress("glGetUniformivARB"); qglGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glGetShaderSourceARB"); ri.Printf(PRINT_ALL, result[1], extension); //glRefConfig.shaderObjects = qtrue; } else { ri.Error(ERR_FATAL, result[2], extension); } // GL_ARB_vertex_shader //glRefConfig.vertexShader = qfalse; extension = "GL_ARB_vertex_shader"; qglBindAttribLocationARB = NULL; qglGetActiveAttribARB = NULL; qglGetAttribLocationARB = NULL; if( GLimp_HaveExtension( extension ) ) { //int reservedComponents; //qglGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &glConfig.maxVertexUniforms); //qglGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &glConfig.maxVaryingFloats); //qglGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &glConfig.maxVertexAttribs); //reservedComponents = 16 * 10; // approximation how many uniforms we have besides the bone matrices #if 0 if(glConfig.driverType == GLDRV_MESA) { // HACK // restrict to number of vertex uniforms to 512 because of: // xreal.x86_64: nv50_program.c:4181: nv50_program_validate_data: Assertion `p->param_nr <= 512' failed glConfig.maxVertexUniforms = Q_bound(0, glConfig.maxVertexUniforms, 512); } #endif //glConfig.maxVertexSkinningBones = (int) Q_bound(0.0, (Q_max(glConfig.maxVertexUniforms - reservedComponents, 0) / 16), MAX_BONES); //glConfig.vboVertexSkinningAvailable = r_vboVertexSkinning->integer && ((glConfig.maxVertexSkinningBones >= 12) ? qtrue : qfalse); qglBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glBindAttribLocationARB"); qglGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) SDL_GL_GetProcAddress("glGetActiveAttribARB"); qglGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetAttribLocationARB"); ri.Printf(PRINT_ALL, result[1], extension); //glRefConfig.vertexShader = qtrue; } else { ri.Error(ERR_FATAL, result[2], extension); } // GL_ARB_shading_language_100 extension = "GL_ARB_shading_language_100"; glRefConfig.textureFloat = qfalse; if( GLimp_HaveExtension( extension ) ) { char version[256]; Q_strncpyz( version, (char *) qglGetString (GL_SHADING_LANGUAGE_VERSION_ARB), sizeof( version ) ); sscanf(version, "%d.%d", &glRefConfig.glslMajorVersion, &glRefConfig.glslMinorVersion); ri.Printf(PRINT_ALL, "...using GLSL version %s\n", version); } else { ri.Error(ERR_FATAL, result[2], extension); } glRefConfig.memInfo = MI_NONE; if( GLimp_HaveExtension( "GL_NVX_gpu_memory_info" ) ) { glRefConfig.memInfo = MI_NVX; } else if( GLimp_HaveExtension( "GL_ATI_meminfo" ) ) { glRefConfig.memInfo = MI_ATI; } extension = "GL_ARB_texture_non_power_of_two"; glRefConfig.textureNonPowerOfTwo = qfalse; if( GLimp_HaveExtension( extension ) ) { if(1) //(r_ext_texture_non_power_of_two->integer) { glRefConfig.textureNonPowerOfTwo = qtrue; } ri.Printf(PRINT_ALL, result[glRefConfig.textureNonPowerOfTwo], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_texture_float extension = "GL_ARB_texture_float"; glRefConfig.textureFloat = qfalse; if( GLimp_HaveExtension( extension ) ) { if( r_ext_texture_float->integer ) { glRefConfig.textureFloat = qtrue; } ri.Printf(PRINT_ALL, result[glRefConfig.textureFloat], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_half_float_pixel extension = "GL_ARB_half_float_pixel"; glRefConfig.halfFloatPixel = qfalse; if( GLimp_HaveExtension( extension ) ) { if( r_arb_half_float_pixel->integer ) glRefConfig.halfFloatPixel = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.halfFloatPixel], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_EXT_framebuffer_object extension = "GL_EXT_framebuffer_object"; glRefConfig.framebufferObject = qfalse; if( GLimp_HaveExtension( extension ) ) { glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &glRefConfig.maxRenderbufferSize); glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &glRefConfig.maxColorAttachments); qglIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glIsRenderbufferEXT"); qglBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glBindRenderbufferEXT"); qglDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) SDL_GL_GetProcAddress("glDeleteRenderbuffersEXT"); qglGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) SDL_GL_GetProcAddress("glGenRenderbuffersEXT"); qglRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) SDL_GL_GetProcAddress("glRenderbufferStorageEXT"); qglGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) SDL_GL_GetProcAddress("glGetRenderbufferParameterivEXT"); qglIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) SDL_GL_GetProcAddress("glIsFramebufferEXT"); qglBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) SDL_GL_GetProcAddress("glBindFramebufferEXT"); qglDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) SDL_GL_GetProcAddress("glDeleteFramebuffersEXT"); qglGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) SDL_GL_GetProcAddress("glGenFramebuffersEXT"); qglCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT"); qglFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture1DEXT"); qglFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture2DEXT"); qglFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture3DEXT"); qglFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT"); qglGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameterivEXT"); qglGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) SDL_GL_GetProcAddress("glGenerateMipmapEXT"); if(r_ext_framebuffer_object->value) glRefConfig.framebufferObject = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.framebufferObject], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_EXT_packed_depth_stencil extension = "GL_EXT_packed_depth_stencil"; glRefConfig.packedDepthStencil = qfalse; if( GLimp_HaveExtension(extension)) { glRefConfig.packedDepthStencil = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.packedDepthStencil], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_occlusion_query extension = "GL_ARB_occlusion_query"; glRefConfig.occlusionQuery = qfalse; if (GLimp_HaveExtension(extension)) { qglGenQueriesARB = (PFNGLGENQUERIESARBPROC) SDL_GL_GetProcAddress("glGenQueriesARB"); qglDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC) SDL_GL_GetProcAddress("glDeleteQueriesARB"); qglIsQueryARB = (PFNGLISQUERYARBPROC) SDL_GL_GetProcAddress("glIsQueryARB"); qglBeginQueryARB = (PFNGLBEGINQUERYARBPROC) SDL_GL_GetProcAddress("glBeginQueryARB"); qglEndQueryARB = (PFNGLENDQUERYARBPROC) SDL_GL_GetProcAddress("glEndQueryARB"); qglGetQueryivARB = (PFNGLGETQUERYIVARBPROC) SDL_GL_GetProcAddress("glGetQueryivARB"); qglGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC) SDL_GL_GetProcAddress("glGetQueryObjectivARB"); qglGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC) SDL_GL_GetProcAddress("glGetQueryObjectuivARB"); glRefConfig.occlusionQuery = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.occlusionQuery], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_EXT_framebuffer_blit extension = "GL_EXT_framebuffer_blit"; glRefConfig.framebufferBlit = qfalse; if (GLimp_HaveExtension(extension)) { qglBlitFramebufferEXT = (void *)SDL_GL_GetProcAddress("glBlitFramebufferEXT"); glRefConfig.framebufferBlit = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.framebufferBlit], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_EXT_framebuffer_multisample extension = "GL_EXT_framebuffer_multisample"; glRefConfig.framebufferMultisample = qfalse; if (GLimp_HaveExtension(extension)) { qglRenderbufferStorageMultisampleEXT = (void *)SDL_GL_GetProcAddress("glRenderbufferStorageMultisampleEXT"); glRefConfig.framebufferMultisample = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.framebufferMultisample], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } glRefConfig.textureCompression = TCR_NONE; // GL_EXT_texture_compression_latc extension = "GL_EXT_texture_compression_latc"; if (GLimp_HaveExtension(extension)) { if (r_ext_compressed_textures->integer) glRefConfig.textureCompression |= TCR_LATC; ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_texture_compression_bptc extension = "GL_ARB_texture_compression_bptc"; if (GLimp_HaveExtension(extension)) { if (r_ext_compressed_textures->integer >= 2) glRefConfig.textureCompression |= TCR_BPTC; ri.Printf(PRINT_ALL, result[(r_ext_compressed_textures->integer >= 2) ? 1 : 0], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_draw_buffers extension = "GL_ARB_draw_buffers"; qglDrawBuffersARB = NULL; if( GLimp_HaveExtension( extension ) ) { qglDrawBuffersARB = (void *) SDL_GL_GetProcAddress("glDrawBuffersARB"); ri.Printf(PRINT_ALL, result[1], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_depth_clamp extension = "GL_ARB_depth_clamp"; glRefConfig.depthClamp = qfalse; if( GLimp_HaveExtension( extension ) ) { glRefConfig.depthClamp = qtrue; ri.Printf(PRINT_ALL, result[1], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_seamless_cube_map extension = "GL_ARB_seamless_cube_map"; glRefConfig.seamlessCubeMap = qfalse; if( GLimp_HaveExtension( extension ) ) { if (r_arb_seamless_cube_map->integer) glRefConfig.seamlessCubeMap = qtrue; ri.Printf(PRINT_ALL, result[glRefConfig.seamlessCubeMap], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // GL_ARB_vertex_type_2_10_10_10_rev extension = "GL_ARB_vertex_type_2_10_10_10_rev"; glRefConfig.packedNormalDataType = GL_UNSIGNED_BYTE; if( GLimp_HaveExtension( extension ) ) { if (r_arb_vertex_type_2_10_10_10_rev->integer) glRefConfig.packedNormalDataType = GL_UNSIGNED_INT_2_10_10_10_REV; ri.Printf(PRINT_ALL, result[r_arb_vertex_type_2_10_10_10_rev->integer ? 1 : 0], extension); } else { ri.Printf(PRINT_ALL, result[2], extension); } // use float lightmaps? glRefConfig.floatLightmap = (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer && r_hdr->integer); }
static int GLimp_SetMode( void ) { const char* glstring; //int sdlcolorbits; int /*colorbits, depthbits, stencilbits, */stereo; //int tcolorbits, tdepthbits, tstencilbits; int samples; int i = 0; SDL_DisplayMode displayMode; //SDL_Surface *vidscreen = NULL; Uint32 flags = SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE; static int desktop_w, desktop_h; // desktop resolution /*if(window) { return RSERR_INVALID_MODE; }*/ ri.Printf( PRINT_DEVELOPER, "Initializing OpenGL display\n"); //if ( r_allowResize->integer ) // flags |= SDL_WINDOW_RESIZABLE; // 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(); //if( videoInfo->current_h == 0 ) if( SDL_GetDesktopDisplayMode( 0, &displayMode ) == 0 )//FIXME: Use SDL_GetWindowDisplayIndex instead of 0? { if( !desktop_w ) { // first time through, resolve desktop resolution desktop_w = displayMode.w; desktop_h = displayMode.h; } } else { ri.Printf( PRINT_ALL, "Cannot get display info, assuming 800x600\n" ); if( !desktop_w ) { // first time through, resolve desktop resolution desktop_w = 800; desktop_h = 600; } } glConfig.displayAspect = (float)desktop_w / (float)desktop_h; ri.Printf( PRINT_DEVELOPER, "Estimated display aspect: %.3f\n", glConfig.displayAspect ); //if( !failSafe ) //{ if ( r_width->modified || r_height->modified || r_pixelAspect->modified ) { for ( i = 0; i < 12; i++ ) { if ( r_width->integer == vidModes[ i ].width && r_height->integer == vidModes[ i ].height && r_pixelAspect->integer == vidModes[ i ].pixelAspect ) { Cvar_SetValue( "r_mode", i ); break; } } if ( i == 12 ) Cvar_Set( "r_mode", "-1" ); } else if ( r_mode->modified && r_mode->integer >= 0 ) { Cvar_SetValue( "r_width", vidModes[ r_mode->integer ].width ); Cvar_SetValue( "r_height", vidModes[ r_mode->integer ].height ); Cvar_SetValue( "r_pixelAspect", vidModes[ r_mode->integer ].pixelAspect ); } r_width->modified = qfalse; r_height->modified = qfalse; r_pixelAspect->modified = qfalse; r_mode->modified = qfalse; glConfig.vidWidth = ( r_width->integer ? r_width->integer : desktop_w ); glConfig.vidHeight = ( r_height->integer ? r_height->integer : desktop_h ); if(glConfig.vidWidth > desktop_w) { glConfig.vidWidth = desktop_w; } if(glConfig.vidHeight > desktop_h) { glConfig.vidHeight = desktop_h; } glConfig.windowAspect = glConfig.vidWidth / ( (float)glConfig.vidHeight * r_pixelAspect->value ); /*} else if( glConfig.vidWidth != R_FAILSAFE_WIDTH && glConfig.vidHeight != R_FAILSAFE_HEIGHT ) { ri.Printf( PRINT_ALL, "Setting mode %dx%d failed, falling back on mode %dx%d\n", glConfig.vidWidth, glConfig.vidHeight, R_FAILSAFE_WIDTH, R_FAILSAFE_HEIGHT ); glConfig.vidWidth = R_FAILSAFE_WIDTH; glConfig.vidHeight = R_FAILSAFE_HEIGHT; glConfig.windowAspect = 1.0f; } else return RSERR_INVALID_MODE;*/ ri.Printf (PRINT_DEVELOPER, "...setting mode %dx%d\n", glConfig.vidWidth, glConfig.vidHeight); if (r_fullscreen->integer) { glConfig.vidWidth = desktop_w; glConfig.vidHeight = desktop_h; flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } /*colorbits = r_colorbits->value; if (!colorbits || colorbits > 32) colorbits = 32; if (!r_depthbits->value) depthbits = 24; else depthbits = r_depthbits->value; stencilbits = r_stencilbits->value; samples = r_ext_multisample->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 == 32) colorbits = 24; else 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 == 32) tcolorbits = 24; 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) sdlcolorbits = 8; else sdlcolorbits = 4;*/ //#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, colorbits ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, colorbits ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, colorbits ); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, colorbits ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, depthbits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, stencilbits ); */ 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 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); if ( !(window = SDL_CreateWindow( CLIENT_WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, glConfig.vidWidth, glConfig.vidHeight, flags )) ) //if (!(vidscreen = SDL_SetVideoMode(glConfig.vidWidth, glConfig.vidHeight, colorbits, flags))) { ri.Printf( PRINT_ALL, "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); return RSERR_INVALID_MODE; } if ( !(context = SDL_GL_CreateContext( window )) ) { ri.Printf( PRINT_ALL, "SDL_GL_CreateContext failed: %s\n", SDL_GetError( ) ); SDL_DestroyWindow( window ); window = NULL; return RSERR_INVALID_MODE; } //if( SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, r_swapInterval->integer ) < 0 ) if( SDL_GL_SetSwapInterval( r_swapInterval->integer ) != 0 ) ri.Printf( PRINT_ALL, "r_swapInterval failed (%s)\n", SDL_GetError( ) ); #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_SetWindowIcon( window, icon ); SDL_FreeSurface( icon ); } #endif //SDL_WM_SetCaption(CLIENT_WINDOW_TITLE, CLIENT_WINDOW_MIN_TITLE); //SDL_ShowCursor(0); //SDL_ShowCursor(0); GLimp_GetCurrentContext(); //ri.Printf( PRINT_DEVELOPER, "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n", // sdlcolorbits, sdlcolorbits, sdlcolorbits, tdepthbits, tstencilbits); SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &glConfig.colorBits ); SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &glConfig.depthBits ); SDL_GL_GetAttribute( SDL_GL_STENCIL_SIZE, &glConfig.stencilBits ); SDL_GL_GetAttribute( SDL_GL_STEREO, &stereo ); if(stereo) { glConfig.stereoEnabled = qtrue; } else { glConfig.stereoEnabled = qfalse; } if(SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) { glConfig.isFullscreen = qtrue; } else { if(r_fullscreen->integer) { Cvar_Set( "r_fullscreen", "0" ); } glConfig.isFullscreen = qfalse; } /*glConfig.colorBits = tcolorbits; glConfig.depthBits = tdepthbits; glConfig.stencilBits = tstencilbits; break; } */ GLimp_DetectAvailableModes(); if (!window || !context) { 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; }