📄 linux_glimp.c
字号:
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;
}
/*
** GLW_InitExtensions
*/
static void GLW_InitExtensions( void )
{
if ( !r_allowExtensions->integer )
{
ri.Printf( PRINT_ALL, "*** IGNORING OPENGL EXTENSIONS ***\n" );
return;
}
ri.Printf( PRINT_ALL, "Initializing OpenGL extensions\n" );
// GL_S3_s3tc
if ( Q_stristr( glConfig.extensions_string, "GL_S3_s3tc" ) )
{
if ( r_ext_compressed_textures->value )
{
glConfig.textureCompression = TC_S3TC;
ri.Printf( PRINT_ALL, "...using GL_S3_s3tc\n" );
} else
{
glConfig.textureCompression = TC_NONE;
ri.Printf( PRINT_ALL, "...ignoring GL_S3_s3tc\n" );
}
} else
{
glConfig.textureCompression = TC_NONE;
ri.Printf( PRINT_ALL, "...GL_S3_s3tc not found\n" );
}
// GL_EXT_texture_env_add
glConfig.textureEnvAddAvailable = qfalse;
if ( Q_stristr( glConfig.extensions_string, "EXT_texture_env_add" ) )
{
if ( r_ext_texture_env_add->integer )
{
glConfig.textureEnvAddAvailable = qtrue;
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
} else
{
glConfig.textureEnvAddAvailable = qfalse;
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" );
}
} else
{
ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" );
}
// GL_ARB_multitexture
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
if ( Q_stristr( glConfig.extensions_string, "GL_ARB_multitexture" ) )
{
if ( r_ext_multitexture->value )
{
qglMultiTexCoord2fARB = ( PFNGLMULTITEXCOORD2FARBPROC ) dlsym( glw_state.OpenGLLib, "glMultiTexCoord2fARB" );
qglActiveTextureARB = ( PFNGLACTIVETEXTUREARBPROC ) dlsym( glw_state.OpenGLLib, "glActiveTextureARB" );
qglClientActiveTextureARB = ( PFNGLCLIENTACTIVETEXTUREARBPROC ) dlsym( glw_state.OpenGLLib, "glClientActiveTextureARB" );
if ( qglActiveTextureARB )
{
qglGetIntegerv( GL_MAX_ACTIVE_TEXTURES_ARB, &glConfig.maxActiveTextures );
if ( glConfig.maxActiveTextures > 1 )
{
ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
} else
{
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, < 2 texture units\n" );
}
}
} else
{
ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
}
} else
{
ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
}
// GL_EXT_compiled_vertex_array
if ( Q_stristr( glConfig.extensions_string, "GL_EXT_compiled_vertex_array" ) )
{
if ( r_ext_compiled_vertex_array->value )
{
ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" );
qglLockArraysEXT = ( void ( APIENTRY * )( int, int ) ) dlsym( glw_state.OpenGLLib, "glLockArraysEXT" );
qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) ) dlsym( glw_state.OpenGLLib, "glUnlockArraysEXT" );
if (!qglLockArraysEXT || !qglUnlockArraysEXT)
{
ri.Error (ERR_FATAL, "bad getprocaddress");
}
} else
{
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" );
}
} else
{
ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
}
}
static void GLW_InitGamma()
{
/* Minimum extension version required */
#define GAMMA_MINMAJOR 2
#define GAMMA_MINMINOR 0
glConfig.deviceSupportsGamma = qfalse;
if (vidmode_ext)
{
if (vidmode_MajorVersion < GAMMA_MINMAJOR ||
(vidmode_MajorVersion == GAMMA_MINMAJOR && vidmode_MinorVersion < GAMMA_MINMINOR)) {
ri.Printf( PRINT_ALL, "XF86 Gamma extension not supported in this version\n");
return;
}
XF86VidModeGetGamma(dpy, scrnum, &vidmode_InitialGamma);
ri.Printf( PRINT_ALL, "XF86 Gamma extension initialized\n");
glConfig.deviceSupportsGamma = qtrue;
}
}
/*
** GLW_LoadOpenGL
**
** GLimp_win.c internal function that that attempts to load and use
** a specific OpenGL DLL.
*/
static qboolean GLW_LoadOpenGL( const char *name )
{
qboolean fullscreen;
ri.Printf( PRINT_ALL, "...loading %s: ", name );
// disable the 3Dfx splash screen and set gamma
// we do this all the time, but it shouldn't hurt anything
// on non-3Dfx stuff
putenv("FX_GLIDE_NO_SPLASH=0");
// Mesa VooDoo hacks
putenv("MESA_GLX_FX=fullscreen\n");
// load the QGL layer
if ( QGL_Init( name ) )
{
fullscreen = r_fullscreen->integer;
// create the window and set up the context
if ( !GLW_StartDriverAndSetMode( name, r_mode->integer, fullscreen ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -