示例#1
0
/*
===================
GLimp_Init

This is the platform specific OpenGL initialization function.  It
is responsible for loading OpenGL, initializing it,
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.

If there is any failure, the renderer will revert back to safe
parameters and try again.
===================
*/
bool GLimp_Init( glimpParms_t a ) {

	if ( !GLimp_OpenDisplay() ) {
		return false;
	}
	
#ifndef ID_GL_HARDLINK
	if ( !GLimp_dlopen() ) {
		return false;
	}
#endif
	
	if (!GLX_Init(a)) {
		return false;
	}
	
	return true;
}
示例#2
0
/*
===============
GLX_Init
===============
*/
int GLX_Init(glimpParms_t a)
{
    int attrib[] =
    {
        GLX_RGBA,				// 0
        GLX_RED_SIZE, 8,		// 1, 2
        GLX_GREEN_SIZE, 8,		// 3, 4
        GLX_BLUE_SIZE, 8,		// 5, 6
        GLX_DOUBLEBUFFER,		// 7
        GLX_DEPTH_SIZE, 24,		// 8, 9
        GLX_STENCIL_SIZE, 8,	// 10, 11
        GLX_ALPHA_SIZE, 8, // 12, 13
        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
#define ATTR_ALPHA_IDX 13
    Window root;
    XVisualInfo *visinfo;
    XSetWindowAttributes attr;
    XSizeHints sizehints;
    unsigned long mask;
    int colorbits, depthbits, stencilbits;
    int tcolorbits, tdepthbits, tstencilbits;
    int actualWidth, actualHeight;
    int i;
    const char *glstring;

    if ( !GLimp_OpenDisplay() )
    {
        return false;
    }

    common->Printf( "Initializing OpenGL display\n" );

    root = RootWindow( dpy, scrnum );

    actualWidth = glConfig.vidWidth;
    actualHeight = glConfig.vidHeight;

    // Get video mode list
    if ( !XF86VidModeQueryVersion( dpy, &vidmode_MajorVersion, &vidmode_MinorVersion ) )
    {
        vidmode_ext = false;
        common->Printf("XFree86-VidModeExtension not available\n");
    }
    else
    {
        vidmode_ext = true;
        common->Printf("Using XFree86-VidModeExtension Version %d.%d\n",
                       vidmode_MajorVersion, vidmode_MinorVersion);
    }

    GLX_TestDGA();

    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 ( a.fullScreen )
        {
            best_dist = 9999999;
            best_fit = -1;

            for (i = 0; i < num_vidmodes; i++)
            {
                if (a.width > vidmodes[i]->hdisplay ||
                        a.height > vidmodes[i]->vdisplay)
                    continue;

                x = a.width - vidmodes[i]->hdisplay;
                y = a.height - 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
                // FIXME: center?
                XF86VidModeSetViewPort(dpy, scrnum, 0, 0);

                common->Printf( "Free86-VidModeExtension Activated at %dx%d\n", actualWidth, actualHeight );

            }
            else
            {
                a.fullScreen = false;
                common->Printf( "Free86-VidModeExtension: No acceptable modes found\n" );
            }
        }
        else
        {
            common->Printf( "XFree86-VidModeExtension: not fullscreen, ignored\n" );
        }
    }
    // color, depth and stencil
    colorbits = 24;
    depthbits = 24;
    stencilbits = 8;

    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;
        }

        common->Printf( "Using %d/%d/%d Color bits, %d Alpha bits, %d depth, %d stencil display.\n",
                        attrib[ATTR_RED_IDX], attrib[ATTR_GREEN_IDX],
                        attrib[ATTR_BLUE_IDX], attrib[ATTR_ALPHA_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 false;
    }
    // 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, GAME_NAME);

    // don't let the window be resized
    // FIXME: allow resize (win32 does)
    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);
    ctx = qglXCreateContext(dpy, visinfo, NULL, True);
    XSync(dpy, False);

    // Free the visinfo after we're done with it
    XFree(visinfo);

    qglXMakeCurrent(dpy, win, ctx);

    glstring = (const char *) qglGetString(GL_RENDERER);
    common->Printf("GL_RENDERER: %s\n", glstring);

    glstring = (const char *) qglGetString(GL_EXTENSIONS);
    common->Printf("GL_EXTENSIONS: %s\n", glstring);

    // FIXME: here, software GL test

    glConfig.isFullscreen = a.fullScreen;

    if ( glConfig.isFullscreen )
    {
        Sys_GrabMouseCursor( true );
    }

    return true;
}
示例#3
0
/*
================
Sys_GetVideoRam
returns in megabytes
open your own display connection for the query and close it
using the one shared with GLimp_Init is not stable
================
*/
int Sys_GetVideoRam(void)
{
	static int run_once = 0;
	int major, minor, value;
	Display *l_dpy;
	int l_scrnum;

	if (run_once) {
		return run_once;
	}

	if (sys_videoRam.GetInteger()) {
		run_once = sys_videoRam.GetInteger();
		return sys_videoRam.GetInteger();
	}

	// try a few strategies to guess the amount of video ram
	common->Printf("guessing video ram ( use +set sys_videoRam to force ) ..\n");

	if (!GLimp_OpenDisplay()) {
		run_once = 64;
		return run_once;
	}

	l_dpy = dpy;
	l_scrnum = scrnum;

	// try ATI /proc read ( for the lack of a better option )
	int fd;

	if ((fd = open("/proc/dri/0/umm", O_RDONLY)) != -1) {
		int len;
		char umm_buf[ 1024 ];
		char *line;

		if ((len = read(fd, umm_buf, 1024)) != -1) {
			// should be way enough to get the full file
			// grab "free  LFB = " line and "free  Inv = " lines
			umm_buf[ len-1 ] = '\0';
			line = umm_buf;
			line = strtok(umm_buf, "\n");
			int total = 0;

			while (line) {
				if (strlen(line) >= 13 && strstr(line, "max   LFB =") == line) {
					total += atoi(line + 12);
				} else if (strlen(line) >= 13 && strstr(line, "max   Inv =") == line) {
					total += atoi(line + 12);
				}

				line = strtok(NULL, "\n");
			}

			if (total) {
				run_once = total / 1048576;
				// round to the lower 16Mb
				run_once &= ~15;
				return run_once;
			}
		} else {
			common->Printf("read /proc/dri/0/umm failed: %s\n", strerror(errno));
		}
	}

	common->Printf("guess failed, return default low-end VRAM setting ( 64MB VRAM )\n");
	run_once = 64;
	return run_once;
}
示例#4
0
/*
================
Sys_GetVideoRam
returns in megabytes
open your own display connection for the query and close it
using the one shared with GLimp_Init is not stable
================
*/
int Sys_GetVideoRam( void ) {
#ifdef USE_SDL
	return 128;
#else
	static int run_once = 0;
	int major, minor, value;
	Display *l_dpy;
	int l_scrnum;

	if ( run_once ) {
		return run_once;
	}

	if ( sys_videoRam.GetInteger() ) {
		run_once = sys_videoRam.GetInteger();
		return sys_videoRam.GetInteger();
	}

	// try a few strategies to guess the amount of video ram
	common->Printf( "guessing video ram ( use +set sys_videoRam to force ) ..\n" );
	if ( !GLimp_OpenDisplay( ) ) {
		run_once = 64;
		return run_once;
	}

	l_dpy = dpy;
	l_scrnum = scrnum;
	// go for nvidia ext first
	if ( XNVCTRLQueryVersion( l_dpy, &major, &minor ) ) {
		common->Printf( "found XNVCtrl extension %d.%d\n", major, minor );
		if ( XNVCTRLIsNvScreen( l_dpy, l_scrnum ) ) {
			if ( XNVCTRLQueryAttribute( l_dpy, l_scrnum, 0, NV_CTRL_VIDEO_RAM, &value ) ) {
				run_once = value / 1024;
				return run_once;
			} else {
				common->Printf( "XNVCtrlQueryAttribute NV_CTRL_VIDEO_RAM failed\n" );
			}
		} else {
			common->Printf( "default screen %d is not controlled by NVIDIA driver\n", l_scrnum );
		}
	}
	// try ATI /proc read ( for the lack of a better option )
	int fd;
	if ( ( fd = open( "/proc/dri/0/umm", O_RDONLY ) ) != -1 ) {
		int len;
		char umm_buf[ 1024 ];
		char *line;
		if ( ( len = read( fd, umm_buf, 1024 ) ) != -1 ) {
			// should be way enough to get the full file
			// grab "free  LFB = " line and "free  Inv = " lines
			umm_buf[ len-1 ] = '\0';
			line = umm_buf;
			line = strtok( umm_buf, "\n" );
			int total = 0;
			while ( line ) {
				if ( strlen( line ) >= 13 && strstr( line, "max   LFB =" ) == line ) {
					total += atoi( line + 12 );
				} else if ( strlen( line ) >= 13 && strstr( line, "max   Inv =" ) == line ) {
					total += atoi( line + 12 );
				}
				line = strtok( NULL, "\n" );
			}
			if ( total ) {
				run_once = total / 1048576;
				// round to the lower 16Mb
				run_once &= ~15;
				return run_once;
			}
		} else {
			common->Printf( "read /proc/dri/0/umm failed: %s\n", strerror( errno ) );
		}
	}
	common->Printf( "guess failed, return default low-end VRAM setting ( 64MB VRAM )\n" );
	run_once = 64;
	return run_once;
#endif
}