Ejemplo n.º 1
0
BOOL X11DRV_XF86VM_GetGammaRamp(LPDDGAMMARAMP ramp)
{
#ifdef X_XF86VidModeSetGamma
  XF86VidModeGamma gamma;
  Bool ret;

  if (xf86vm_major < 2) return FALSE; /* no gamma control */
#ifdef X_XF86VidModeSetGammaRamp
  else if (xf86vm_use_gammaramp)
  {
      Bool ret;
      wine_tsx11_lock();
      ret = XF86VidModeGetGammaRamp(gdi_display, DefaultScreen(gdi_display), 256,
				    ramp->red, ramp->green, ramp->blue);
      wine_tsx11_unlock();
      return ret;
  }
#endif
  else
  {
      wine_tsx11_lock();
      ret = XF86VidModeGetGamma(gdi_display, DefaultScreen(gdi_display), &gamma);
      wine_tsx11_unlock();
      if (ret) {
	  GenerateRampFromGamma(ramp->red,   gamma.red);
	  GenerateRampFromGamma(ramp->green, gamma.green);
	  GenerateRampFromGamma(ramp->blue,  gamma.blue);
	  return TRUE;
      }
  }
#endif /* X_XF86VidModeSetGamma */
  return FALSE;
}
double xgamma_get_gamma (XF86VidModeGamma *pGamma)
{
	g_return_val_if_fail (pGamma != NULL, 1);
	const Display *dpy = cairo_dock_get_Xdisplay ();
	
	g_return_val_if_fail (XF86VidModeGetGamma != NULL, 1.);
	if (!XF86VidModeGetGamma (dpy, DefaultScreen (dpy), pGamma))
	{
		cd_warning ("Xgamma : unable to query gamma correction");
		return 1.;
	}
	return (pGamma->red + pGamma->blue + pGamma->green) / 3;
}
Ejemplo n.º 3
0
double xgamma_get_gamma (XF86VidModeGamma *pGamma)
{
	g_return_val_if_fail (pGamma != NULL, 1);
	Display *dpy = gdk_x11_get_default_xdisplay ();
	
	g_return_val_if_fail (_xf86vidmode_supported (), 1.);
	if (!XF86VidModeGetGamma (dpy, DefaultScreen (dpy), pGamma))
	{
		cd_warning ("Xgamma : unable to query gamma correction");
		return 1.;
	}
	double fGamma = (pGamma->red + pGamma->blue + pGamma->green) / 3;
	cd_debug ("Gamma: %f, %f, %f, %f",
		pGamma->red, pGamma->blue, pGamma->green, fGamma);
	return fGamma;
}
Ejemplo n.º 4
0
void
UpdateHardwareGamma(void)
{
	float gamma;
	XF86VidModeGamma x11_gamma;

	gamma = vid_gamma->value;

	x11_gamma.red = gamma;
	x11_gamma.green = gamma;
	x11_gamma.blue = gamma;

	XF86VidModeSetGamma(dpy, screen, &x11_gamma);

	/* This forces X11 to update the gamma tables */
	XF86VidModeGetGamma(dpy, screen, &x11_gamma);
}
Ejemplo n.º 5
0
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;
	}
}
Ejemplo n.º 6
0
/*
 * Shuts the SDL render backend down
 */
void
GLimp_Shutdown(void)
{
	/* Clear the backbuffer and make it
	   current. This may help some broken
	   video drivers like the AMD Catalyst
	   to avoid artifacts in unused screen
	   areas. */
	if (SDL_WasInit(SDL_INIT_VIDEO))
	{
		glClearColor(0.0, 0.0, 0.0, 0.0);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		GLimp_EndFrame();
	}

	if (surface)
	{
		SDL_FreeSurface(surface);
	}

	surface = NULL;

	if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_VIDEO)
	{
		SDL_Quit();
	}
	else
	{
		SDL_QuitSubSystem(SDL_INIT_VIDEO);
	}

#ifdef X11GAMMA
	if (gl_state.hwgamma == true)
	{
		XF86VidModeSetGamma(dpy, screen, &x11_oldgamma);

		/* This forces X11 to update the gamma tables */
		XF86VidModeGetGamma(dpy, screen, &x11_oldgamma);
	}
#endif

	//gl_state.hwgamma = false;
}
Ejemplo n.º 7
0
int
main(int argc, char *argv[])
{
    int i, ret;
    char *displayname = NULL;
    Display *dpy;
    float gam = -1., rgam = -1., ggam = -1., bgam = -1.;
    XF86VidModeGamma gamma;
    Bool quiet = False;
    int screen = -1;

    ProgramName = argv[0];
    for (i = 1; i < argc; i++) {
	char *arg = argv[i];

	if (arg[0] == '-') {
	    if (isabbreviation ("-display", arg, 1)) {
		if (++i >= argc) Syntax ("-display requires an argument");
		displayname = argv[i];
		continue;
	    } else if (isabbreviation ("-quiet", arg, 1)) {
		quiet = True;
		continue;
	    } else if (isabbreviation ("-version", arg, 1)) {
		puts(PACKAGE_STRING);
		exit(0);
	    } else if (isabbreviation ("-screen", arg, 1)) {
		if (++i >= argc) Syntax ("-screen requires an argument");
		screen = atoi(argv[i]);
		continue;
	    } else if (isabbreviation ("-gamma", arg, 2)) {
		if (++i >= argc) Syntax ("-gamma requires an argument");
		if ((rgam >= 0.) || (ggam >= 0.) || (bgam >= 0.))
		    Syntax ("-gamma cannot be used with -rgamma, -ggamma, or -bgamma");
		gam = (float)atof(argv[i]);
		if ((gam < GAMMA_MIN) || (gam > GAMMA_MAX)) {
		    fprintf(stderr,
			    "Gamma values must be between %6.3f and %6.3f\n",
			    GAMMA_MIN, GAMMA_MAX);
		    exit(1);
		}
		continue;
	    } else if (isabbreviation ("-rgamma", arg, 2)) {
		if (++i >= argc) Syntax ("-rgamma requires an argument");
		if (gam >= 0.) Syntax ("cannot set both -gamma and -rgamma");
		rgam = (float)atof(argv[i]);
		if ((rgam < GAMMA_MIN) || (rgam > GAMMA_MAX)) {
		    fprintf(stderr,
			    "Gamma values must be between %6.3f and %6.3f\n",
			    GAMMA_MIN, GAMMA_MAX);
		    exit(1);
		}
		continue;
	    } else if (isabbreviation ("-ggamma", arg, 2)) {
		if (++i >= argc) Syntax ("-ggamma requires an argument");
		if (gam >= 0.) Syntax ("cannot set both -gamma and -ggamma");
		ggam = (float)atof(argv[i]);
		if ((ggam < GAMMA_MIN) || (ggam > GAMMA_MAX)) {
		    fprintf(stderr,
			    "Gamma values must be between %6.3f and %6.3f\n",
			    GAMMA_MIN, GAMMA_MAX);
		    exit(1);
		}
		continue;
	    } else if (isabbreviation ("-bgamma", arg, 2)) {
		if (++i >= argc) Syntax ("-bgamma requires an argument");
		if (gam >= 0.) Syntax ("cannot set both -gamma and -bgamma");
		bgam = (float)atof(argv[i]);
		if ((bgam < GAMMA_MIN) || (bgam > GAMMA_MAX)) {
		    fprintf(stderr,
			    "Gamma values must be between %6.3f and %6.3f\n",
			    GAMMA_MIN, GAMMA_MAX);
		    exit(1);
		}
		continue;
	    } else {
		if (!isabbreviation ("-help", arg, 1))
		    fprintf (stderr, "%s: unrecognized argument %s\n\n",
			     ProgramName, arg);
		Syntax (NULL);
	    }
	} else {
	    fprintf (stderr, "%s: unrecognized argument %s\n\n",
		     ProgramName, arg);
	    Syntax (NULL);
	}
    }

    if ((dpy = XOpenDisplay(displayname)) == NULL) {
	fprintf (stderr, "%s:  unable to open display '%s'\n",
		 ProgramName, XDisplayName (displayname));
	exit(1);
    } else if (screen == -1)
	screen = DefaultScreen(dpy);

    if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
	fprintf(stderr, "Unable to query video extension version\n");
	exit(2);
    }

    if (!XF86VidModeQueryExtension(dpy, &EventBase, &ErrorBase)) {
	fprintf(stderr, "Unable to query video extension information\n");
	exit(2);
    }

    /* Fail if the extension version in the server is too old */
    if (MajorVersion < MINMAJOR || 
	(MajorVersion == MINMAJOR && MinorVersion < MINMINOR)) {
	fprintf(stderr,
		"Xserver is running an old XFree86-VidModeExtension version"
		" (%d.%d)\n", MajorVersion, MinorVersion);
	fprintf(stderr, "Minimum required version is %d.%d\n",
		MINMAJOR, MINMINOR);
	exit(2);
    }

    if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
	fprintf(stderr, "Unable to query gamma correction\n");
	XCloseDisplay (dpy);
	exit (2);
    } else if (!quiet)
	fprintf(stderr, "-> Red %6.3f, Green %6.3f, Blue %6.3f\n", gamma.red,
		gamma.green, gamma.blue);

    ret = 0;
    if (gam >= 0.) {
	gamma.red = gam;
	gamma.green = gam;
	gamma.blue = gam;
	if (!XF86VidModeSetGamma(dpy, screen, &gamma)) {
	    fprintf(stderr, "Unable to set gamma correction\n");
	    ret = 2;
	} else {
	    if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
		fprintf(stderr, "Unable to query gamma correction\n");
		ret = 2;
	    } else if (!quiet)
		fprintf(stderr, "<- Red %6.3f, Green %6.3f, Blue %6.3f\n",
		        gamma.red, gamma.green, gamma.blue);
	}
    } else if ((rgam >= 0.) || (ggam >= 0.) || (bgam >= 0.)) {
	if (rgam >= 0.) gamma.red = rgam;
	if (ggam >= 0.) gamma.green = ggam;
	if (bgam >= 0.) gamma.blue = bgam;
	if (!XF86VidModeSetGamma(dpy, screen, &gamma)) {
	    fprintf(stderr, "Unable to set gamma correction\n");
	    ret = 2;
	} else {
	    if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
		fprintf(stderr, "Unable to query gamma correction\n");
		ret = 2;
	    } else if (!quiet)
		fprintf(stderr, "<- Red %6.3f, Green %6.3f, Blue %6.3f\n",
		        gamma.red, gamma.green, gamma.blue);
	}
    }

    XCloseDisplay (dpy);
    exit (ret);
}
Ejemplo n.º 8
0
/*
 * Initializes the OpenGL window
 */
static qboolean
GLimp_InitGraphics(qboolean fullscreen)
{
	int counter = 0;
	int flags;
	int stencil_bits;
	char title[24];

	//QUAKETOON: forcing window
	fullscreen = false;

	if (surface && (surface->w == vid.width) && (surface->h == vid.height))
	{
		/* Are we running fullscreen? */
		int isfullscreen = (surface->flags & SDL_FULLSCREEN) ? 1 : 0;

		/* We should, but we don't */
		if (fullscreen != isfullscreen)
		{
			SDL_WM_ToggleFullScreen(surface);
		}

		/* Do we now? */
		isfullscreen = (surface->flags & SDL_FULLSCREEN) ? 1 : 0;

		if (fullscreen == isfullscreen)
		{
			return true;
		}
	}

	/* Is the surface used? */
	if (surface)
	{
		SDL_FreeSurface(surface);
	}

	/* Create the window */
	VID_NewWindow(vid.width, vid.height);

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);

	/* Initiate the flags */
	flags = SDL_OPENGL;

	if (fullscreen)
	{
		flags |= SDL_FULLSCREEN;
	}

	/* Set the icon */
	SetSDLIcon();

	/* Enable vsync */
	/*
	if (gl_swapinterval->value)
	{
		SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
	}
	*/

	while (1)
	{
		if ((surface = SDL_SetVideoMode(vid.width, vid.height, 0, flags)) == NULL)
		{
			if (counter == 1)
			{
				VID_Error(ERR_FATAL, "Failed to revert to gl_mode 4. Exiting...\n");
				return false;
			}

			VID_Printf(PRINT_ALL, "SDL SetVideoMode failed: %s\n",
					SDL_GetError());
			VID_Printf(PRINT_ALL, "Reverting to gl_mode 4 (640x480) and windowed mode.\n");

			/* Try to recover */
			Cvar_SetValue("gl_mode", 4);
			Cvar_SetValue("vid_fullscreen", 0);
			vid.width = 640;
			vid.height = 480;

			counter++;
			continue;
		}
		else
		{
			break;
		}
	}

	/* Initialize the stencil buffer */
	if (!SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil_bits))
	{
		VID_Printf(PRINT_ALL, "Got %d bits of stencil.\n", stencil_bits);

		if (stencil_bits >= 1)
		{
			have_stencil = true;
		}
	}

	/* Initialize hardware gamma */
#ifdef X11GAMMA
	if ((dpy = XOpenDisplay(displayname)) == NULL)
	{
		VID_Printf(PRINT_ALL, "Unable to open display.\n");
	}
	else
	{
		if (screen == -1)
		{
			screen = DefaultScreen(dpy);
		}

		gl_state.hwgamma = true;
		vid_gamma->modified = true;

		XF86VidModeGetGamma(dpy, screen, &x11_oldgamma);

		VID_Printf(PRINT_ALL, "Using hardware gamma via X11.\n");
	}
#else
	//gl_state.hwgamma = true;
	vid_gamma->modified = true;
	VID_Printf(PRINT_ALL, "Using hardware gamma via SDL.\n");
#endif

	/* Window title */
	snprintf(title, sizeof(title), "QuakeToon %f", (float) VERSION);
	SDL_WM_SetCaption(title, title);

	/* No cursor */
	SDL_ShowCursor(0);

	return true;
}
Ejemplo n.º 9
0
/*
 * multithreading notes:
 *
 * This function could be accessed concurrently for different video streams, with
 * the pair dpy,drawable identifying each stream.
 */
int gl_capture_frame(gl_capture_t gl_capture, Display *dpy, GLXDrawable drawable)
{
	struct gl_capture_video_stream_s *video;
	glc_message_header_t msg;
	glc_video_frame_header_t pic;
	glc_utime_t now;
	glc_utime_t before_capture,after_capture;
	char *dma;
	int ret = 0;

	if (!(gl_capture->flags & GL_CAPTURE_CAPTURING))
		return 0; /* capturing not active */

	gl_capture_get_video_stream(gl_capture, &video, dpy, drawable);

	/* get current time */
	if (unlikely(gl_capture->flags & GL_CAPTURE_IGNORE_TIME))
		now = video->last + gl_capture->fps;
	else
		now = glc_state_time(gl_capture->glc);

	/* has gl_capture->fps nanoseconds elapsed since last capture */
	if ((now - video->last < gl_capture->fps) &&
	    !(gl_capture->flags & GL_CAPTURE_LOCK_FPS) &&
	    !(gl_capture->flags & GL_CAPTURE_IGNORE_TIME))
		goto finish;

	/* not really needed until now */
	gl_capture_update_video_stream(gl_capture, video);

	/* if PBO is not active, just start transfer and finish */
	if (unlikely((gl_capture->flags & GL_CAPTURE_USE_PBO) &&
	     __sync_bool_compare_and_swap(&video->pbo_active,0,1))) {
		ret = gl_capture_start_pbo(gl_capture, video);
		video->pbo_time = now;
		goto finish;
	}

	if (unlikely(ps_packet_open(&video->packet,
				((gl_capture->flags & GL_CAPTURE_LOCK_FPS) ||
				(gl_capture->flags & GL_CAPTURE_IGNORE_TIME)) ?
				(PS_PACKET_WRITE) :
				(PS_PACKET_WRITE | PS_PACKET_TRY))))
		goto finish;

	if (unlikely((ret = ps_packet_setsize(&video->packet, video->row * video->ch
						+ sizeof(glc_message_header_t)
						+ sizeof(glc_video_frame_header_t)))))
		goto cancel;

	msg.type = GLC_MESSAGE_VIDEO_FRAME;
	if (unlikely((ret = ps_packet_write(&video->packet,
					    &msg, sizeof(glc_message_header_t)))))
		goto cancel;

	/*
	 * if we are using PBO we will actually write previous picture to buffer.
	 * Also, make sure that pbo_time is not in the future. This could happen if
	 * the state time is reset by reloading the capture between a pbo start
	 * and a pbo read.
	 */
	pic.time = (gl_capture->flags & GL_CAPTURE_USE_PBO &&
		    video->pbo_time < now)?video->pbo_time:now;
	pic.id   = video->id;
	if (unlikely((ret = ps_packet_write(&video->packet,
					    &pic, sizeof(glc_video_frame_header_t)))))
		goto cancel;

	if (video->gather_stats)
		before_capture = glc_state_time(gl_capture->glc);
	if (gl_capture->flags & GL_CAPTURE_USE_PBO) {
		if (unlikely((ret = gl_capture_read_pbo(gl_capture, video))))
			goto cancel;

		ret = gl_capture_start_pbo(gl_capture, video);
		video->pbo_time = now;
	} else {
		if (unlikely((ret = ps_packet_dma(&video->packet, (void *) &dma,
					video->row * video->ch, PS_ACCEPT_FAKE_DMA))))
			goto cancel;

		ret = gl_capture_get_pixels(gl_capture, video, dma);
	}
	if (video->gather_stats) {
		after_capture = glc_state_time(gl_capture->glc);
		video->capture_time_ns += after_capture - before_capture;
	}

	ps_packet_close(&video->packet);
	video->num_frames++;
	now = glc_state_time(gl_capture->glc);

	if (unlikely((gl_capture->flags & GL_CAPTURE_LOCK_FPS) &&
		    !(gl_capture->flags & GL_CAPTURE_IGNORE_TIME))) {
		if (now - video->last < gl_capture->fps) {
			struct timespec ts = { .tv_sec  = (gl_capture->fps + video->last - now)/1000000000,
					       .tv_nsec = (gl_capture->fps + video->last - now)%1000000000 };
			nanosleep(&ts,NULL);
		}
	}

	/* increment by 1/fps seconds */
	video->last += gl_capture->fps;

finish:
	if (unlikely(ret != 0))
		gl_capture_error(gl_capture, ret);

	if (gl_capture->flags & GL_CAPTURE_DRAW_INDICATOR)
		glCallList(video->indicator_list);

	return ret;
cancel:
	if (ret == EBUSY) {
		ret = 0;
		glc_log(gl_capture->glc, GLC_INFO, "gl_capture",
			 "dropped frame, buffer not ready");
	}
	ps_packet_cancel(&video->packet);
	goto finish;
}

int gl_capture_refresh_color_correction(gl_capture_t gl_capture)
{
	struct gl_capture_video_stream_s *video;

	if (unlikely(!(gl_capture->flags & GL_CAPTURE_CAPTURING)))
		return 0; /* capturing not active */

	glc_log(gl_capture->glc, GLC_INFO, "gl_capture",
		 "refreshing color correction");

	pthread_rwlock_rdlock(&gl_capture->videolist_lock);
	video = gl_capture->video;
	while (video != NULL) {
		gl_capture_update_color(gl_capture, video);
		video = video->next;
	}
	pthread_rwlock_unlock(&gl_capture->videolist_lock);

	return 0;
}

/** \todo support GammaRamp */
int gl_capture_update_color(gl_capture_t gl_capture, struct gl_capture_video_stream_s *video)
{
	glc_message_header_t msg_hdr;
	glc_color_message_t msg;
	XF86VidModeGamma gamma;
	int ret = 0;

	XF86VidModeGetGamma(video->dpy, video->screen, &gamma);

	if ((gamma.red == video->gamma_red) &&
	    (gamma.green == video->gamma_green) &&
	    (gamma.blue == video->gamma_blue))
		return 0; /* nothing to update */

	msg_hdr.type = GLC_MESSAGE_COLOR;
	msg.id = video->id;
	msg.red = gamma.red;
	msg.green = gamma.green;
	msg.blue = gamma.blue;

	/** \todo figure out brightness and contrast */
	msg.brightness = msg.contrast = 0;

	glc_log(gl_capture->glc, GLC_INFO, "gl_capture",
		 "color correction: brightness=%f, contrast=%f, red=%f, green=%f, blue=%f",
		 msg.brightness, msg.contrast, msg.red, msg.green, msg.blue);

	if (unlikely((ret = ps_packet_open(&video->packet, PS_PACKET_WRITE))))
		goto err;
	if (unlikely((ret = ps_packet_write(&video->packet,
				&msg_hdr, sizeof(glc_message_header_t)))))
		goto err;
	if (unlikely((ret = ps_packet_write(&video->packet,
				&msg, sizeof(glc_color_message_t)))))
		goto err;
	if (unlikely((ret = ps_packet_close(&video->packet))))
		goto err;

	return 0;

err:
	ps_packet_cancel(&video->packet);

	glc_log(gl_capture->glc, GLC_ERROR, "gl_capture",
		 "can't write gamma correction information to buffer: %s (%d)",
		 strerror(ret), ret);
	return ret;
}
Ejemplo n.º 10
0
rserr_t GLimp_SetMode( int mode, int colorbits, bool fullscreen ) {
	if ( !XInitThreads() ) {
		common->Printf( "...XInitThreads() failed, disabling r_smp\n" );
		Cvar_Set( "r_smp", "0" );
	}

	// set up our custom error handler for X failures
	XSetErrorHandler( &qXErrorHandler );

	if ( fullscreen && in_nograb->value ) {
		common->Printf( "Fullscreen not allowed with in_nograb 1\n" );
		Cvar_Set( "r_fullscreen", "0" );
		r_fullscreen->modified = false;
		fullscreen = false;
	}

	common->Printf( "...setting mode %d:", mode );

	if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) {
		common->Printf( " invalid mode\n" );
		return RSERR_INVALID_MODE;
	}
	common->Printf( " %d %d\n", glConfig.vidWidth, glConfig.vidHeight );

	// open the display
	if ( !( dpy = XOpenDisplay( NULL ) ) ) {
		fprintf( stderr, "Error couldn't open the X display\n" );
		return RSERR_INVALID_MODE;
	}

	scrnum = DefaultScreen( dpy );
	Window root = RootWindow( dpy, scrnum );

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

	// Check for DGA
	int dga_MajorVersion = 0;
	int dga_MinorVersion = 0;
	if ( in_dgamouse->value ) {
		if ( !XF86DGAQueryVersion( dpy, &dga_MajorVersion, &dga_MinorVersion ) ) {
			// unable to query, probalby not supported
			common->Printf( "Failed to detect XF86DGA Mouse\n" );
			Cvar_Set( "in_dgamouse", "0" );
		} else {
			common->Printf( "XF86DGA Mouse (Version %d.%d) initialized\n", dga_MajorVersion, dga_MinorVersion );
		}
	}

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

	if ( vidmode_ext ) {
		int best_fit, best_dist, dist, x, y;

		XF86VidModeGetAllModeLines( dpy, scrnum, &num_vidmodes, &vidmodes );

		// Are we going fullscreen?  If so, let's change video mode
		if ( fullscreen ) {
			best_dist = 9999999;
			best_fit = -1;

			for ( int i = 0; i < num_vidmodes; i++ ) {
				if ( glConfig.vidWidth > vidmodes[ i ]->hdisplay ||
					 glConfig.vidHeight > vidmodes[ i ]->vdisplay ) {
					continue;
				}

				x = glConfig.vidWidth - vidmodes[ i ]->hdisplay;
				y = glConfig.vidHeight - vidmodes[ i ]->vdisplay;
				dist = ( x * x ) + ( y * y );
				if ( dist < best_dist ) {
					best_dist = dist;
					best_fit = i;
				}
			}

			if ( best_fit != -1 ) {
				actualWidth = vidmodes[ best_fit ]->hdisplay;
				actualHeight = vidmodes[ best_fit ]->vdisplay;

				// change to the mode
				XF86VidModeSwitchToMode( dpy, scrnum, vidmodes[ best_fit ] );
				vidmode_active = true;

				// Move the viewport to top left
				XF86VidModeSetViewPort( dpy, scrnum, 0, 0 );

				common->Printf( "XFree86-VidModeExtension Activated at %dx%d\n",
					actualWidth, actualHeight );
			} else {
				fullscreen = 0;
				common->Printf( "XFree86-VidModeExtension: No acceptable modes found\n" );
			}
		} else {
			common->Printf( "XFree86-VidModeExtension:  Ignored on non-fullscreen\n" );
		}
	}

	if ( !colorbits ) {
		colorbits = !r_colorbits->value ? 24 : r_colorbits->value;
	}
	int depthbits = !r_depthbits->value ? 24 : r_depthbits->value;
	int stencilbits = r_stencilbits->value;

	XVisualInfo* visinfo = NULL;
	for ( int i = 0; i < 16; i++ ) {
		// 0 - default
		// 1 - minus colorbits
		// 2 - minus depthbits
		// 3 - minus stencil
		if ( ( i % 4 ) == 0 && i ) {
			// one pass, reduce
			switch ( i / 4 ) {
			case 2:
				if ( colorbits == 24 ) {
					colorbits = 16;
				}
				break;
			case 1:
				if ( depthbits == 24 ) {
					depthbits = 16;
				} else if ( depthbits == 16 ) {
					depthbits = 8;
				}
				break;
			case 3:
				if ( stencilbits == 24 ) {
					stencilbits = 16;
				} else if ( stencilbits == 16 ) {
					stencilbits = 8;
				}
				break;
			}
		}

		int tcolorbits = colorbits;
		int tdepthbits = depthbits;
		int tstencilbits = stencilbits;

		if ( ( i % 4 ) == 3 ) {
			// reduce colorbits
			if ( tcolorbits == 24 ) {
				tcolorbits = 16;
			}
		}

		if ( ( i % 4 ) == 2 ) {
			// reduce depthbits
			if ( tdepthbits == 24 ) {
				tdepthbits = 16;
			} else if ( tdepthbits == 16 ) {
				tdepthbits = 8;
			}
		}

		if ( ( i % 4 ) == 1 ) {
			// reduce stencilbits
			if ( tstencilbits == 24 ) {
				tstencilbits = 16;
			} else if ( tstencilbits == 16 ) {
				tstencilbits = 8;
			} else {
				tstencilbits = 0;
			}
		}

		int attrib[] =
		{
			GLX_RGBA,			// 0
			GLX_RED_SIZE, 4,		// 1, 2
			GLX_GREEN_SIZE, 4,		// 3, 4
			GLX_BLUE_SIZE, 4,		// 5, 6
			GLX_DOUBLEBUFFER,		// 7
			GLX_DEPTH_SIZE, 1,		// 8, 9
			GLX_STENCIL_SIZE, 1,	// 10, 11
			//GLX_SAMPLES_SGIS, 4, /* for better AA */
			None
		};
		// these match in the array
		enum
		{
			ATTR_RED_IDX = 2,
			ATTR_GREEN_IDX = 4,
			ATTR_BLUE_IDX = 6,
			ATTR_DEPTH_IDX = 9,
			ATTR_STENCIL_IDX = 11
		};

		if ( tcolorbits == 24 ) {
			attrib[ ATTR_RED_IDX ] = 8;
			attrib[ ATTR_GREEN_IDX ] = 8;
			attrib[ ATTR_BLUE_IDX ] = 8;
		} else {
			// must be 16 bit
			attrib[ ATTR_RED_IDX ] = 4;
			attrib[ ATTR_GREEN_IDX ] = 4;
			attrib[ ATTR_BLUE_IDX ] = 4;
		}

		attrib[ ATTR_DEPTH_IDX ] = tdepthbits;	// default to 24 depth
		attrib[ ATTR_STENCIL_IDX ] = tstencilbits;

		visinfo = glXChooseVisual( dpy, scrnum, attrib );
		if ( !visinfo ) {
			continue;
		}

		common->Printf( "Using %d/%d/%d Color bits, %d depth, %d stencil display.\n",
			attrib[ ATTR_RED_IDX ], attrib[ ATTR_GREEN_IDX ], attrib[ ATTR_BLUE_IDX ],
			attrib[ ATTR_DEPTH_IDX ], attrib[ ATTR_STENCIL_IDX ] );

		glConfig.colorBits = tcolorbits;
		glConfig.depthBits = tdepthbits;
		glConfig.stencilBits = tstencilbits;
		break;
	}

	if ( !visinfo ) {
		common->Printf( "Couldn't get a visual\n" );
		return RSERR_INVALID_MODE;
	}

	//	Window attributes
	XSetWindowAttributes attr;
	unsigned long mask;
	attr.background_pixel = BlackPixel( dpy, scrnum );
	attr.border_pixel = 0;
	attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone );
	attr.event_mask = X_MASK;
	if ( vidmode_active ) {
		mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore |
			   CWEventMask | CWOverrideRedirect;
		attr.override_redirect = True;
		attr.backing_store = NotUseful;
		attr.save_under = False;
	} else {
		mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
	}

	win = XCreateWindow( dpy, root, 0, 0,
		actualWidth, actualHeight,
		0, visinfo->depth, InputOutput,
		visinfo->visual, mask, &attr );

	XStoreName( dpy, win, R_GetTitleForWindow() );

	/* GH: Don't let the window be resized */
	XSizeHints sizehints;
	sizehints.flags = PMinSize | PMaxSize;
	sizehints.min_width = sizehints.max_width = actualWidth;
	sizehints.min_height = sizehints.max_height = actualHeight;

	XSetWMNormalHints( dpy, win, &sizehints );

	XMapWindow( dpy, win );

	if ( vidmode_active ) {
		XMoveWindow( dpy, win, 0, 0 );
		//XRaiseWindow(dpy, win);
		//XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
		//XFlush(dpy);
		// Move the viewport to top left
		//XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
	}

	//	hook to window close
	wm_protocols = XInternAtom( dpy, "WM_PROTOCOLS", False );
	wm_delete_window = XInternAtom( dpy, "WM_DELETE_WINDOW", False );
	XSetWMProtocols( dpy, win, &wm_delete_window, 1 );

	XFlush( dpy );

	XSync( dpy, False );	// bk001130 - from cvs1.17 (mkv)
	ctx = glXCreateContext( dpy, visinfo, NULL, True );
	XSync( dpy, False );	// bk001130 - from cvs1.17 (mkv)

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

	glXMakeCurrent( dpy, win, ctx );

	glConfig.deviceSupportsGamma = false;
	if ( vidmode_ext ) {
		if ( vidmode_MajorVersion < GAMMA_MINMAJOR ||
			 ( vidmode_MajorVersion == GAMMA_MINMAJOR && vidmode_MinorVersion < GAMMA_MINMINOR ) ) {
			common->Printf( "XF86 Gamma extension not supported in this version\n" );
		} else {
			XF86VidModeGetGamma( dpy, scrnum, &vidmode_InitialGamma );
			common->Printf( "XF86 Gamma extension initialized\n" );
			glConfig.deviceSupportsGamma = true;
		}
	}

	//	Check for software GL implementation.
	const char* glstring = ( char* )glGetString( GL_RENDERER );
	if ( !String::ICmp( glstring, "Mesa X11" ) ||
		 !String::ICmp( glstring, "Mesa GLX Indirect" ) ) {
		if ( !r_allowSoftwareGL->integer ) {
			common->Printf( "\n\n***********************************************************\n" );
			common->Printf( " You are using software Mesa (no hardware acceleration)!\n" );
			common->Printf( " If this is intentional, add\n" );
			common->Printf( "       \"+set r_allowSoftwareGL 1\"\n" );
			common->Printf( " to the command line when starting the game.\n" );
			common->Printf( "***********************************************************\n" );
			GLimp_Shutdown();
			return RSERR_INVALID_MODE;
		} else {
			common->Printf( "...using software Mesa (r_allowSoftwareGL==1).\n" );
		}
	}

	GLW_GenDefaultLists();

	return RSERR_OK;
}