Exemplo n.º 1
0
/*!
 * \brief Ends RandR support
 * \warning !!! DO NOT CALL THIS METHOD !!!
 *
 * This method is designed to be called from iContext::destroy() or
 * from the destructor of this class. Calling this method will end
 * the RandR support.
 */
void iRandR::endRandR() {
   if ( !vIsRandRSupported_B )
      return;

   XCloseDisplay( vDisplay_X11 );

   if ( GlobConf.win.restoreOldScreenRes && vWasScreenChanged_B )
      restore( vDefaultConfig_RandR );


   for ( auto &elem : vDefaultConfig_RandR.gamma )
      XRRFreeGamma( elem );

   vDefaultConfig_RandR.gamma.clear();
   vDefaultConfig_RandR.CRTCInfo.clear();


   for ( auto &elem : vLatestConfig_RandR.gamma )
      XRRFreeGamma( elem );


   vLatestConfig_RandR.gamma.clear();


   XRRFreeScreenConfigInfo( vConfig_XRR );
   XRRFreeScreenResources( vResources_XRR );

   vCRTC_V_RandR.clear();
   vOutput_V_RandR.clear();
   vMode_V_RandR.clear();

   vIsRandRSupported_B = false;
}
Exemplo n.º 2
0
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
    if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
    {
        XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);

        memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short));
        memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
        memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short));

        XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
        XRRFreeGamma(gamma);
    }
#if defined(_GLFW_HAS_XF86VM)
    else if (_glfw.x11.vidmode.available)
    {
        XF86VidModeSetGammaRamp(_glfw.x11.display,
                                _glfw.x11.screen,
                                ramp->size,
                                (unsigned short*) ramp->red,
                                (unsigned short*) ramp->green,
                                (unsigned short*) ramp->blue);
    }
#endif /*_GLFW_HAS_XF86VM*/
}
Exemplo n.º 3
0
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
    if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
    {
        const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display,
                                                monitor->x11.crtc);
        XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display,
                                              monitor->x11.crtc);

        _glfwAllocGammaArrays(ramp, size);

        memcpy(ramp->red, gamma->red, size * sizeof(unsigned short));
        memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
        memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));

        XRRFreeGamma(gamma);
    }
#if defined(_GLFW_HAS_XF86VM)
    else if (_glfw.x11.vidmode.available)
    {
        int size;
        XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);

        _glfwAllocGammaArrays(ramp, size);

        XF86VidModeGetGammaRamp(_glfw.x11.display,
                                _glfw.x11.screen,
                                ramp->size, ramp->red, ramp->green, ramp->blue);
    }
#endif /*_GLFW_HAS_XF86VM*/
}
Exemplo n.º 4
0
void
mate_rr_crtc_set_gamma (MateRRCrtc *crtc, int size,
			 unsigned short *red,
			 unsigned short *green,
			 unsigned short *blue)
{
#ifdef HAVE_RANDR
    int copy_size;
    XRRCrtcGamma *gamma;

    g_return_if_fail (crtc != NULL);
    g_return_if_fail (red != NULL);
    g_return_if_fail (green != NULL);
    g_return_if_fail (blue != NULL);

    if (size != crtc->gamma_size)
	return;

    gamma = XRRAllocGamma (crtc->gamma_size);

    copy_size = crtc->gamma_size * sizeof (unsigned short);
    memcpy (gamma->red, red, copy_size);
    memcpy (gamma->green, green, copy_size);
    memcpy (gamma->blue, blue, copy_size);

    XRRSetCrtcGamma (DISPLAY (crtc), crtc->id, gamma);
    XRRFreeGamma (gamma);
#endif /* HAVE_RANDR */
}
Exemplo n.º 5
0
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
    if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
    {
        if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
        {
            _glfwInputError(GLFW_PLATFORM_ERROR,
                            "X11: Gamma ramp size must match current ramp size");
            return;
        }

        XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);

        memcpy(gamma->red,   ramp->red,   ramp->size * sizeof(unsigned short));
        memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
        memcpy(gamma->blue,  ramp->blue,  ramp->size * sizeof(unsigned short));

        XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
        XRRFreeGamma(gamma);
    }
    else if (_glfw.x11.vidmode.available)
    {
        XF86VidModeSetGammaRamp(_glfw.x11.display,
                                _glfw.x11.screen,
                                ramp->size,
                                (unsigned short*) ramp->red,
                                (unsigned short*) ramp->green,
                                (unsigned short*) ramp->blue);
    }
    else
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "X11: Gamma ramp access not supported by server");
    }
}
Exemplo n.º 6
0
void
UpdateHardwareGamma(void)
{
	float gamma = (vid_gamma->value);
	int i;

	Display* dpy = NULL;
	SDL_SysWMinfo info;

#if SDL_VERSION_ATLEAST(2, 0, 0)
	SDL_VERSION(&info.version);
	if(!SDL_GetWindowWMInfo(window, &info))
#else
	if(SDL_GetWMInfo(&info) != 1)
#endif
	{
		VID_Printf(PRINT_ALL, "Couldn't get Window info from SDL\n");
		return;
	}

	dpy = info.info.x11.display;

	XRRScreenResources* res = XRRGetScreenResources(dpy, info.info.x11.window);
	if(res == NULL)
	{
		VID_Printf(PRINT_ALL, "Unable to get xrandr screen resources.\n");
		return;
	}

	for(i=0; i < res->ncrtc; ++i)
	{
		int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]);
		size_t rampSize = len*sizeof(Uint16);
		Uint16* ramp = malloc(rampSize); // TODO: check for NULL
		if(ramp == NULL)
		{
			VID_Printf(PRINT_ALL, "Couldn't allocate &zd byte of memory for gamma ramp - OOM?!\n", rampSize);
			return;
		}

		CalculateGammaRamp(gamma, ramp, len);

		XRRCrtcGamma* gamma = XRRAllocGamma(len);

		memcpy(gamma->red, ramp, rampSize);
		memcpy(gamma->green, ramp, rampSize);
		memcpy(gamma->blue, ramp, rampSize);

		free(ramp);

		XRRSetCrtcGamma(dpy, res->crtcs[i], gamma);

		XRRFreeGamma(gamma);
	}

	XRRFreeScreenResources(res);
}
Exemplo n.º 7
0
static void RestoreGamma()
{
	int i=0;
	SDL_SysWMinfo info;
	Display* dpy = NULL;

	if(gammaRamps == NULL)
			return;

#if SDL_VERSION_ATLEAST(2, 0, 0)
	SDL_VERSION(&info.version);
	if(!SDL_GetWindowWMInfo(window, &info))
#else
	if(SDL_GetWMInfo(&info) != 1)
#endif
	{
		VID_Printf(PRINT_ALL, "Couldn't get Window info from SDL\n");
		return;
	}

	dpy = info.info.x11.display;

	XRRScreenResources* res = XRRGetScreenResources(dpy, info.info.x11.window);
	if(res == NULL)
	{
		VID_Printf(PRINT_ALL, "Unable to get xrandr screen resources.\n");
		return;
	}

	for(i=0; i < noGammaRamps; ++i)
	{
		// in case a display was unplugged or something, noGammaRamps may be > res->ncrtc
		if(i < res->ncrtc)
		{
			int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]);
			if(len != gammaRamps[i]->size) {
				VID_Printf(PRINT_ALL, "WTF, gamma ramp size for display %d has changed from %d to %d!\n",
							   i, gammaRamps[i]->size, len);

				continue;
			}

			XRRSetCrtcGamma(dpy, res->crtcs[i], gammaRamps[i]);
		}

		// the ramp needs to be free()d either way
		XRRFreeGamma(gammaRamps[i]);
		gammaRamps[i] = NULL;

	}
	XRRFreeScreenResources(res);
	free(gammaRamps);
	gammaRamps = NULL;

	VID_Printf(PRINT_ALL, "Restored original Gamma\n");
}
Exemplo n.º 8
0
gboolean
mate_rr_crtc_get_gamma (MateRRCrtc *crtc, int *size,
			 unsigned short **red, unsigned short **green,
			 unsigned short **blue)
{
#ifdef HAVE_RANDR
    int copy_size;
    unsigned short *r, *g, *b;
    XRRCrtcGamma *gamma;

    g_return_val_if_fail (crtc != NULL, FALSE);

    gamma = XRRGetCrtcGamma (DISPLAY (crtc), crtc->id);
    if (!gamma)
	return FALSE;

    copy_size = crtc->gamma_size * sizeof (unsigned short);

    if (red) {
	r = g_new0 (unsigned short, crtc->gamma_size);
	memcpy (r, gamma->red, copy_size);
	*red = r;
    }

    if (green) {
	g = g_new0 (unsigned short, crtc->gamma_size);
	memcpy (g, gamma->green, copy_size);
	*green = g;
    }

    if (blue) {
	b = g_new0 (unsigned short, crtc->gamma_size);
	memcpy (b, gamma->blue, copy_size);
	*blue = b;
    }

    XRRFreeGamma (gamma);

    if (size)
	*size = crtc->gamma_size;

    return TRUE;
#else
    return FALSE;
#endif /* HAVE_RANDR */
}
Exemplo n.º 9
0
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
    if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
    {
        const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display,
                                                monitor->x11.crtc);
        XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display,
                                              monitor->x11.crtc);

        _glfwAllocGammaArrays(ramp, size);

        memcpy(ramp->red,   gamma->red,   size * sizeof(unsigned short));
        memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
        memcpy(ramp->blue,  gamma->blue,  size * sizeof(unsigned short));

        XRRFreeGamma(gamma);
        return GLFW_TRUE;
    }
    else if (_glfw.x11.vidmode.available)
    {
        int size;
        XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);

        _glfwAllocGammaArrays(ramp, size);

        XF86VidModeGetGammaRamp(_glfw.x11.display,
                                _glfw.x11.screen,
                                ramp->size, ramp->red, ramp->green, ramp->blue);
        return GLFW_TRUE;
    }
    else
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "X11: Gamma ramp access not supported by server");
        return GLFW_FALSE;
    }
}
Exemplo n.º 10
0
bool iRandR::reload( bool _overwriteLatest, bool _overwriteDefaults ) {
   if ( !vIsRandRSupported_B )
      return false;

   SizeID lTemoID_suI;
   int lTempSizes_I;

   Rotation lTempRotate_XRR; // Exists only for XRRConfigCurrentConfiguration(...); to make it happy

   vConfig_XRR    = XRRGetScreenInfo( vDisplay_X11, vRootWindow_X11 );
   vResources_XRR = XRRGetScreenResources( vDisplay_X11, vRootWindow_X11 );

   lTemoID_suI                   = XRRConfigCurrentConfiguration( vConfig_XRR, &lTempRotate_XRR );
   XRRScreenSize *lTempSizes_XRR = XRRSizes( vDisplay_X11, 0, &lTempSizes_I );

   if ( lTemoID_suI < lTempSizes_I ) {
      vScreenWidth_uI  = static_cast<unsigned>( lTempSizes_XRR[lTemoID_suI].width );
      vScreenHeight_uI = static_cast<unsigned>( lTempSizes_XRR[lTemoID_suI].height );
   }

   if ( _overwriteLatest ) {
      vLatestConfig_RandR.primary = XRRGetOutputPrimary( vDisplay_X11, vRootWindow_X11 );

      for ( auto &elem : vLatestConfig_RandR.gamma )
         XRRFreeGamma( elem );

      vLatestConfig_RandR.gamma.clear();

      for ( int i = 0; i < vResources_XRR->ncrtc; ++i ) {
         vLatestConfig_RandR.gamma.push_back(
               XRRGetCrtcGamma( vDisplay_X11, vResources_XRR->crtcs[i] ) );
      }
   }

   if ( _overwriteDefaults ) {
      vDefaultConfig_RandR.primary = XRRGetOutputPrimary( vDisplay_X11, vRootWindow_X11 );

      for ( auto &elem : vDefaultConfig_RandR.gamma )
         XRRFreeGamma( elem );

      vDefaultConfig_RandR.gamma.clear();

      for ( int i = 0; i < vResources_XRR->ncrtc; ++i ) {
         vDefaultConfig_RandR.gamma.push_back(
               XRRGetCrtcGamma( vDisplay_X11, vResources_XRR->crtcs[i] ) );
      }
   }

   // Clear old data
   vCRTC_V_RandR.clear();
   vOutput_V_RandR.clear();
   vMode_V_RandR.clear();
   vLatestConfig_RandR.CRTCInfo.clear();


   // CRTC
   for ( int i = 0; i < vResources_XRR->ncrtc; ++i ) {
      internal::_crtc lTempCRTC_RandR;

      XRRCrtcInfo *lTempCRTCInfo_XRR =
            XRRGetCrtcInfo( vDisplay_X11, vResources_XRR, vResources_XRR->crtcs[i] );

      lTempCRTC_RandR.id        = vResources_XRR->crtcs[i];
      lTempCRTC_RandR.timestamp = lTempCRTCInfo_XRR->timestamp;
      lTempCRTC_RandR.posX      = lTempCRTCInfo_XRR->x;
      lTempCRTC_RandR.posY      = lTempCRTCInfo_XRR->y;
      lTempCRTC_RandR.width     = lTempCRTCInfo_XRR->width;
      lTempCRTC_RandR.height    = lTempCRTCInfo_XRR->height;
      lTempCRTC_RandR.mode      = lTempCRTCInfo_XRR->mode;
      lTempCRTC_RandR.rotation  = lTempCRTCInfo_XRR->rotation;
      lTempCRTC_RandR.rotations = lTempCRTCInfo_XRR->rotations;

      for ( int j = 0; j < lTempCRTCInfo_XRR->noutput; ++j ) {
         lTempCRTC_RandR.outputs.push_back( lTempCRTCInfo_XRR->outputs[j] );
      }

      for ( int j = 0; j < lTempCRTCInfo_XRR->npossible; ++j ) {
         lTempCRTC_RandR.possibleOutputs.push_back( lTempCRTCInfo_XRR->possible[j] );
      }

      vCRTC_V_RandR.push_back( lTempCRTC_RandR );
      XRRFreeCrtcInfo( lTempCRTCInfo_XRR );
   }


   // Output
   for ( int i = 0; i < vResources_XRR->noutput; ++i ) {
      internal::_output lTempOutput_RandR;

      XRROutputInfo *lTempOutputInfo_XRR =
            XRRGetOutputInfo( vDisplay_X11, vResources_XRR, vResources_XRR->outputs[i] );

      lTempOutput_RandR.id             = vResources_XRR->outputs[i];
      lTempOutput_RandR.timestamp      = lTempOutputInfo_XRR->timestamp;
      lTempOutput_RandR.crtc           = lTempOutputInfo_XRR->crtc;
      lTempOutput_RandR.name           = lTempOutputInfo_XRR->name;
      lTempOutput_RandR.mm_width       = lTempOutputInfo_XRR->mm_width;
      lTempOutput_RandR.mm_height      = lTempOutputInfo_XRR->mm_height;
      lTempOutput_RandR.connection     = lTempOutputInfo_XRR->connection;
      lTempOutput_RandR.subpixel_order = lTempOutputInfo_XRR->subpixel_order;
      lTempOutput_RandR.npreferred     = lTempOutputInfo_XRR->npreferred;

      for ( int j = 0; j < lTempOutputInfo_XRR->ncrtc; ++j ) {
         lTempOutput_RandR.crtcs.push_back( lTempOutputInfo_XRR->crtcs[j] );
      }

      for ( int j = 0; j < lTempOutputInfo_XRR->nclone; ++j ) {
         lTempOutput_RandR.clones.push_back( lTempOutputInfo_XRR->clones[j] );
      }

      for ( int j = 0; j < lTempOutputInfo_XRR->nmode; ++j ) {
         lTempOutput_RandR.modes.push_back( lTempOutputInfo_XRR->modes[j] );
      }

      vOutput_V_RandR.push_back( lTempOutput_RandR );
      XRRFreeOutputInfo( lTempOutputInfo_XRR );
   }


   // Modes
   for ( int i = 0; i < vResources_XRR->nmode; ++i ) {
      internal::_mode lTempMode_RandR;

      XRRModeInfo lTempModeInfo_XRR = vResources_XRR->modes[i];

      lTempMode_RandR.id         = lTempModeInfo_XRR.id;
      lTempMode_RandR.width      = lTempModeInfo_XRR.width;
      lTempMode_RandR.height     = lTempModeInfo_XRR.height;
      lTempMode_RandR.dotClock   = lTempModeInfo_XRR.dotClock;
      lTempMode_RandR.hSyncStart = lTempModeInfo_XRR.hSyncStart;
      lTempMode_RandR.hSyncEnd   = lTempModeInfo_XRR.hSyncEnd;
      lTempMode_RandR.hTotal     = lTempModeInfo_XRR.hTotal;
      lTempMode_RandR.hSkew      = lTempModeInfo_XRR.hSkew;
      lTempMode_RandR.vSyncStart = lTempModeInfo_XRR.vSyncStart;
      lTempMode_RandR.vSyncEnd   = lTempModeInfo_XRR.vSyncEnd;
      lTempMode_RandR.vTotal     = lTempModeInfo_XRR.vTotal;
      lTempMode_RandR.name       = lTempModeInfo_XRR.name;
      lTempMode_RandR.modeFlags  = lTempModeInfo_XRR.modeFlags;


      /* v refresh frequency in Hz */
      unsigned int lVTotalTemp = lTempMode_RandR.vTotal;

      if ( lTempMode_RandR.modeFlags & RR_DoubleScan )
         lVTotalTemp *= 2;

      if ( lTempMode_RandR.modeFlags & RR_Interlace )
         lVTotalTemp /= 2;

      if ( lTempMode_RandR.hTotal && lVTotalTemp )
         lTempMode_RandR.refresh = ( static_cast<double>( lTempMode_RandR.dotClock ) /
                                     ( static_cast<double>( lTempMode_RandR.hTotal ) *
                                       static_cast<double>( lVTotalTemp ) ) );
      else
         lTempMode_RandR.refresh = 0;


      /* h sync frequency in Hz */
      if ( lTempMode_RandR.hTotal )
         lTempMode_RandR.syncFreq = lTempMode_RandR.dotClock / lTempMode_RandR.hTotal;
      else
         lTempMode_RandR.syncFreq = 0;

      vMode_V_RandR.push_back( lTempMode_RandR );
   }


   vLatestConfig_RandR.CRTCInfo = vCRTC_V_RandR;

   if ( _overwriteLatest )
      vDefaultConfig_RandR.CRTCInfo = vCRTC_V_RandR;

   vMode_V_RandR.sort();

   return true;
}
Exemplo n.º 11
0
int
main (int argc, char *argv[])
{
  char in_name[256] = { '\000' };
  char tag_name[40] = { '\000' };
  int found;
  u_int16_t *r_ramp = NULL, *g_ramp = NULL, *b_ramp = NULL;
  int i;
  int clear = 0;
  int alter = 0;
  int donothing = 0;
  int printramps = 0;
  int calcloss = 0;
  int invert = 0;
  int correction = 0;
  u_int16_t tmpRampVal = 0;
  unsigned int r_res, g_res, b_res;
  int screen = -1;

#ifdef FGLRX
  unsigned
#endif
           int ramp_size = 256;

#ifndef _WIN32
  /* X11 */
  XF86VidModeGamma gamma;
  Display *dpy = NULL;
  char *displayname = NULL;
#ifdef FGLRX
  int controller = -1;
  FGLRX_X11Gamma_C16native fglrx_gammaramps;
#endif
#else
  char win_default_profile[MAX_PATH+1];
  DWORD win_profile_len;
  typedef struct _GAMMARAMP {
    WORD  Red[256];
    WORD  Green[256];
    WORD  Blue[256];
  } GAMMARAMP; 
  GAMMARAMP winGammaRamp;
  HDC hDc = NULL;
#endif

  xcalib_state.verbose = 0;

  /* begin program part */
#ifdef _WIN32
  for(i=0; i< ramp_size; i++) {
    winGammaRamp.Red[i] = i << 8;
    winGammaRamp.Blue[i] = i << 8;
    winGammaRamp.Green[i] = i << 8;
  }
#endif

  /* command line parsing */
  
#ifndef _WIN32
  if (argc < 2)
    usage ();
#endif

  for (i = 1; i < argc; ++i) {
    /* help */
    if (!strcmp (argv[i], "-h") || !strcmp (argv[i], "-help")) {
      usage ();
      exit (0);
    }
    /* verbose mode */
    if (!strcmp (argv[i], "-v") || !strcmp (argv[i], "-verbose")) {
      xcalib_state.verbose = 1;
      continue;
    }
    /* version */
    if (!strcmp (argv[i], "-version")) {
        fprintf(stdout, "xcalib " XCALIB_VERSION "\n");
        exit (0);
    }
#ifndef _WIN32
    /* X11 display */
    if (!strcmp (argv[i], "-d") || !strcmp (argv[i], "-display")) {
      if (++i >= argc)
        usage ();
        displayname = argv[i];
        continue;
    }
#endif
    /* X11 screen / Win32 monitor index */
    if (!strcmp (argv[i], "-s") || !strcmp (argv[i], "-screen")) {
      if (++i >= argc)
        usage ();
      screen = atoi (argv[i]);
      continue;
    }
#ifdef FGLRX
    /* ATI controller index (for FGLRX only) */
    if (!strcmp (argv[i], "-x") || !strcmp (argv[i], "-controller")) {
      if (++i >= argc)
        usage ();
      controller = atoi (argv[i]);
      continue;
    }
#endif
    /* print ramps to stdout */
    if (!strcmp (argv[i], "-p") || !strcmp (argv[i], "-printramps")) {
      printramps = 1;
      continue;
    }
    /* print error introduced by applying ramps to stdout */
    if (!strcmp (argv[i], "-l") || !strcmp (argv[i], "-loss")) {
      calcloss = 1;
      continue;
    }
    /* invert the LUT */
    if (!strcmp (argv[i], "-i") || !strcmp (argv[i], "-invert")) {
      invert = 1;
      continue;
    }
    /* clear gamma lut */
    if (!strcmp (argv[i], "-c") || !strcmp (argv[i], "-clear")) {
      clear = 1;
      continue;
    }
#ifndef FGLRX
    /* alter existing lut */
    if (!strcmp (argv[i], "-a") || !strcmp (argv[i], "-alter")) {
      alter = 1;
      continue;
    }
#endif
    /* do not alter video-LUTs : work's best in conjunction with -v! */
    if (!strcmp (argv[i], "-n") || !strcmp (argv[i], "-noaction")) {
      donothing = 1;
      if (++i >= argc)
        usage();
      ramp_size = atoi(argv[i]);
      continue;
    }
    /* global gamma correction value (use 2.2 for WinXP Color Control-like behaviour) */
    if (!strcmp (argv[i], "-gc") || !strcmp (argv[i], "-gammacor")) {
      if (++i >= argc)
        usage();
      xcalib_state.gamma_cor = atof (argv[i]);
      correction = 1;
      continue;
    }
    /* take additional brightness into account */
    if (!strcmp (argv[i], "-b") || !strcmp (argv[i], "-brightness")) {
      double brightness = 0.0;
      if (++i >= argc)
        usage();
      brightness = atof(argv[i]);
      if(brightness < 0.0 || brightness > 99.0)
      {
        warning("brightness is out of range 0.0-99.0");
        continue;
      }
      xcalib_state.redMin = xcalib_state.greenMin = xcalib_state.blueMin = brightness / 100.0;
      xcalib_state.redMax = xcalib_state.greenMax = xcalib_state.blueMax =
        (1.0 - xcalib_state.blueMin) * xcalib_state.blueMax + xcalib_state.blueMin;
      
      correction = 1;
      continue;
    }
    /* take additional contrast into account */
    if (!strcmp (argv[i], "-co") || !strcmp (argv[i], "-contrast")) {
      double contrast = 100.0;
      if (++i >= argc)
        usage();
      contrast = atof(argv[i]);
      if(contrast < 1.0 || contrast > 100.0)
      {
        warning("contrast is out of range 1.0-100.0");
        continue;
      }
      xcalib_state.redMax = xcalib_state.greenMax = xcalib_state.blueMax = contrast / 100.0;
      xcalib_state.redMax = xcalib_state.greenMax = xcalib_state.blueMax =
        (1.0 - xcalib_state.blueMin) * xcalib_state.blueMax + xcalib_state.blueMin;
 
      correction = 1;
      continue;
    }
    /* additional red calibration */ 
    if (!strcmp (argv[i], "-red")) {
      double gamma = 1.0, brightness = 0.0, contrast = 100.0;
      if (++i >= argc)
        usage();
      gamma = atof(argv[i]);
      if(gamma < 0.1 || gamma > 5.0)
      {
        warning("gamma is out of range 0.1-5.0");
        continue;
      }
      if (++i >= argc)
        usage();
      brightness = atof(argv[i]);
      if(brightness < 0.0 || brightness > 99.0)
      {
        warning("brightness is out of range 0.0-99.0");
        continue;
      }
      if (++i >= argc)
        usage();
      contrast = atof(argv[i]);
      if(contrast < 1.0 || contrast > 100.0)
      {
        warning("contrast is out of range 1.0-100.0");
        continue;
      }
 
      xcalib_state.redMin = brightness / 100.0;
      xcalib_state.redMax =
        (1.0 - xcalib_state.redMin) * (contrast / 100.0) + xcalib_state.redMin;
      xcalib_state.redGamma = gamma;
 
      correction = 1;
      continue;
    }
    /* additional green calibration */
    if (!strcmp (argv[i], "-green")) {
      double gamma = 1.0, brightness = 0.0, contrast = 100.0;
      if (++i >= argc)
        usage();
      gamma = atof(argv[i]);
      if(gamma < 0.1 || gamma > 5.0)
      {
        warning("gamma is out of range 0.1-5.0");
        continue;
      }
      if (++i >= argc)
        usage();
      brightness = atof(argv[i]);
      if(brightness < 0.0 || brightness > 99.0)
      {
        warning("brightness is out of range 0.0-99.0");
        continue;
      }
      if (++i >= argc)
        usage();
      contrast = atof(argv[i]);
      if(contrast < 1.0 || contrast > 100.0)
      {
        warning("contrast is out of range 1.0-100.0");
        continue;
      }
 
      xcalib_state.greenMin = brightness / 100.0;
      xcalib_state.greenMax =
        (1.0 - xcalib_state.greenMin) * (contrast / 100.0) + xcalib_state.greenMin;
      xcalib_state.greenGamma = gamma;
 
      correction = 1;
      continue;
    }
    /* additional blue calibration */
    if (!strcmp (argv[i], "-blue")) {
      double gamma = 1.0, brightness = 0.0, contrast = 100.0;
      if (++i >= argc)
        usage();
      gamma = atof(argv[i]);
      if(gamma < 0.1 || gamma > 5.0)
      {
        warning("gamma is out of range 0.1-5.0");
        continue;
      }
      if (++i >= argc)
        usage();
      brightness = atof(argv[i]);
      if(brightness < 0.0 || brightness > 99.0)
      {
        warning("brightness is out of range 0.0-99.0");
        continue;
      }
      if (++i >= argc)
        usage();
      contrast = atof(argv[i]);
      if(contrast < 1.0 || contrast > 100.0)
      {
        warning("contrast is out of range 1.0-100.0");
        continue;
      }
 
      xcalib_state.blueMin = brightness / 100.0;
      xcalib_state.blueMax =
        (1.0 - xcalib_state.blueMin) * (contrast / 100.0) + xcalib_state.blueMin;
      xcalib_state.blueGamma = gamma;
 
      correction = 1;
      continue;
    }
 
    if (i != argc - 1 && !clear && i) {
      usage ();
    }
    if(!clear || !alter)
    {
      if(strlen(argv[i]) < 255)
        strcpy (in_name, argv[i]);
      else
        usage ();
    }
  }

#ifdef _WIN32
  if ((!clear || !alter) && (in_name[0] == '\0')) {
    hDc = FindMonitor(screen);
    win_profile_len = MAX_PATH;
    win_default_profile[0] = '\0';
    SetICMMode(hDc, ICM_ON);
    if(GetICMProfileA(hDc, (LPDWORD) &win_profile_len, (LPSTR)win_default_profile))
    {
      if(strlen(win_default_profile) < 255)
        strcpy (in_name, win_default_profile);
      else
        usage();
    }
    else
      usage();
  }
#endif

#ifndef _WIN32
  /* X11 initializing */
  if ((dpy = XOpenDisplay (displayname)) == NULL) {
    if(!donothing)
      error ("Can't open display %s", XDisplayName (displayname));
    else
      warning("Can't open display %s", XDisplayName (displayname));
  }
  else if (screen == -1)
    screen = DefaultScreen (dpy);

  int xrr_version = -1;
  int crtc = 0;
  int major_versionp = 0;
  int minor_versionp = 0;
  int n = 0;
  Window root = RootWindow(dpy, DefaultScreen( dpy )); 

  XRRQueryVersion( dpy, &major_versionp, &minor_versionp );
  xrr_version = major_versionp*100 + minor_versionp;

  if(xrr_version >= 102)
  {                           
    XRRScreenResources * res = XRRGetScreenResources( dpy, root );
    int ncrtc = 0;

    n = res->noutput;
    for( i = 0; i < n; ++i )
    {
      RROutput output = res->outputs[i];
      XRROutputInfo * output_info = XRRGetOutputInfo( dpy, res,
                                                        output);
      if(output_info->crtc)
        if(ncrtc++ == screen)
        {
          crtc = output_info->crtc;
          ramp_size = XRRGetCrtcGammaSize( dpy, crtc );
          message ("XRandR output:      \t%s\n", output_info->name);
        }

      XRRFreeOutputInfo( output_info ); output_info = 0;
    }
    //XRRFreeScreenResources(res); res = 0;
  }

  /* clean gamma table if option set */
  gamma.red = 1.0;
  gamma.green = 1.0;
  gamma.blue = 1.0;
  if (clear) {
#ifndef FGLRX
    if(xrr_version >= 102)
    {
      XRRCrtcGamma * gamma = XRRAllocGamma (ramp_size);
      if(!gamma)
        warning ("Unable to clear screen gamma");
      else
      {
        for(i=0; i < ramp_size; ++i)
          gamma->red[i] = gamma->green[i] = gamma->blue[i] = i * 65535 / ramp_size;
        XRRSetCrtcGamma (dpy, crtc, gamma);
        XRRFreeGamma (gamma);
      }
    } else
    if (!XF86VidModeSetGamma (dpy, screen, &gamma))
    {
#else
    for(i = 0; i < 256; i++) {
      fglrx_gammaramps.RGamma[i] = i << 2;
      fglrx_gammaramps.GGamma[i] = i << 2;
      fglrx_gammaramps.BGamma[i] = i << 2;
    }
    if (!FGLRX_X11SetGammaRamp_C16native_1024(dpy, screen, controller, 256, &fglrx_gammaramps)) {
#endif
      XCloseDisplay (dpy);
      error ("Unable to reset display gamma");
    }
    goto cleanupX;
  }
  
  /* get number of entries for gamma ramps */
  if(!donothing)
  {
#ifndef FGLRX
    if (xrr_version < 102 && !XF86VidModeGetGammaRampSize (dpy, screen, &ramp_size)) {
#else
    if (!FGLRX_X11GetGammaRampSize(dpy, screen, &ramp_size)) {
#endif
      XCloseDisplay (dpy);
      if(!donothing)
        error ("Unable to query gamma ramp size");
      else {
        warning ("Unable to query gamma ramp size - assuming 256");
        ramp_size = 256;
      }
    }
  }
#else /* _WIN32 */
  if(!donothing) {
    if(!hDc)
      hDc = FindMonitor(screen);
    if (clear) {
      if (!SetDeviceGammaRamp(hDc, &winGammaRamp))
        error ("Unable to reset display gamma");
      goto cleanupX;
    }
  }
#endif

  /* check for ramp size being a power of 2 and inside the supported range */
  switch(ramp_size)
  {
    case 16:
    case 32:
    case 64:
    case 128:
    case 256:
    case 512:
    case 1024:
    case 2048:
    case 4096:
    case 8192:
    case 16384:
    case 32768:
    case 65536:
      break;
    default:
      error("unsupported ramp size %u", ramp_size);
  }
  
  r_ramp = (unsigned short *) malloc (ramp_size * sizeof (unsigned short));
  g_ramp = (unsigned short *) malloc (ramp_size * sizeof (unsigned short));
  b_ramp = (unsigned short *) malloc (ramp_size * sizeof (unsigned short));

  if(!alter)
  {
    if( (i = read_vcgt_internal(in_name, r_ramp, g_ramp, b_ramp, ramp_size)) <= 0) {
      if(i<0)
        warning ("Unable to read file '%s'", in_name);
      if(i == 0)
        warning ("No calibration data in ICC profile '%s' found", in_name);
      free(r_ramp);
      free(g_ramp);
      free(b_ramp);
      exit(0);
    }
  } else {
#ifndef _WIN32
    if (xrr_version >= 102)
    {
      XRRCrtcGamma * gamma = 0;
      if((gamma = XRRGetCrtcGamma(dpy, crtc)) != 0 )
        warning ("Unable to get display calibration");

      for (i = 0; i < ramp_size; i++) {
        r_ramp[i] = gamma->red[i];
        g_ramp[i] = gamma->green[i];
        b_ramp[i] = gamma->blue[i];
      }
    }
    else if (!XF86VidModeGetGammaRamp (dpy, screen, ramp_size, r_ramp, g_ramp, b_ramp))
      warning ("Unable to get display calibration");
#else
    if (!GetDeviceGammaRamp(hDc, &winGammaRamp))
      warning ("Unable to get display calibration");

    for (i = 0; i < ramp_size; i++) {
      r_ramp[i] = winGammaRamp.Red[i];
      g_ramp[i] = winGammaRamp.Green[i];
      b_ramp[i] = winGammaRamp.Blue[i];
    }
#endif
  }

  {
    float redBrightness = 0.0;
    float redContrast = 100.0;
    float redMin = 0.0;
    float redMax = 1.0;

    redMin = (double)r_ramp[0] / 65535.0;
    redMax = (double)r_ramp[ramp_size - 1] / 65535.0;
    redBrightness = redMin * 100.0;
    redContrast = (redMax - redMin) / (1.0 - redMin) * 100.0; 
    message("Red Brightness: %f   Contrast: %f  Max: %f  Min: %f\n", redBrightness, redContrast, redMax, redMin);
  }

  {
    float greenBrightness = 0.0;
    float greenContrast = 100.0;
    float greenMin = 0.0;
    float greenMax = 1.0;

    greenMin = (double)g_ramp[0] / 65535.0;
    greenMax = (double)g_ramp[ramp_size - 1] / 65535.0;
    greenBrightness = greenMin * 100.0;
    greenContrast = (greenMax - greenMin) / (1.0 - greenMin) * 100.0; 
    message("Green Brightness: %f   Contrast: %f  Max: %f  Min: %f\n", greenBrightness, greenContrast, greenMax, greenMin);
  }

  {
    float blueBrightness = 0.0;
    float blueContrast = 100.0;
    float blueMin = 0.0;
    float blueMax = 1.0;

    blueMin = (double)b_ramp[0] / 65535.0;
    blueMax = (double)b_ramp[ramp_size - 1] / 65535.0;
    blueBrightness = blueMin * 100.0;
    blueContrast = (blueMax - blueMin) / (1.0 - blueMin) * 100.0; 
    message("Blue Brightness: %f   Contrast: %f  Max: %f  Min: %f\n", blueBrightness, blueContrast, blueMax, blueMin);
  }

  if(correction != 0)
  {
    for(i=0; i<ramp_size; i++)
    {
      r_ramp[i] =  65536.0 * (((double) pow (((double) r_ramp[i]/65536.0),
                                xcalib_state.redGamma * (double) xcalib_state.gamma_cor
                  ) * (xcalib_state.redMax - xcalib_state.redMin)) + xcalib_state.redMin);
      g_ramp[i] =  65536.0 * (((double) pow (((double) g_ramp[i]/65536.0),
                                xcalib_state.greenGamma * (double) xcalib_state.gamma_cor
                  ) * (xcalib_state.greenMax - xcalib_state.greenMin)) + xcalib_state.greenMin);
      b_ramp[i] =  65536.0 * (((double) pow (((double) b_ramp[i]/65536.0),
                                xcalib_state.blueGamma * (double) xcalib_state.gamma_cor
                  ) * (xcalib_state.blueMax - xcalib_state.blueMin)) + xcalib_state.blueMin); 
    }
    message("Altering Red LUTs with   Gamma %f   Min %f   Max %f\n",
       xcalib_state.redGamma, xcalib_state.redMin, xcalib_state.redMax);
    message("Altering Green LUTs with   Gamma %f   Min %f   Max %f\n",
       xcalib_state.greenGamma, xcalib_state.greenMin, xcalib_state.greenMax);
    message("Altering Blue LUTs with   Gamma %f   Min %f   Max %f\n",
       xcalib_state.blueGamma, xcalib_state.blueMin, xcalib_state.blueMax);
  }

  if(!invert) {
    /* ramps should be monotonic - otherwise content is nonsense! */
    for (i = 0; i < ramp_size - 1; i++) {
      if (r_ramp[i + 1] < r_ramp[i])
        warning ("red gamma table not monotonic");
      if (g_ramp[i + 1] < g_ramp[i])
        warning ("green gamma table not monotonic");
      if (b_ramp[i + 1] < b_ramp[i])
        warning ("blue gamma table not monotonic");
    }
  } else {
    for (i = 0; i < ramp_size; i++) {
      if(i >= ramp_size / 2)
        break;
      tmpRampVal = r_ramp[i];
      r_ramp[i] = r_ramp[ramp_size - i - 1];
      r_ramp[ramp_size - i - 1] = tmpRampVal;
      tmpRampVal = g_ramp[i];
      g_ramp[i] = g_ramp[ramp_size - i - 1];
      g_ramp[ramp_size - i - 1] = tmpRampVal;
      tmpRampVal = b_ramp[i];
      b_ramp[i] = b_ramp[ramp_size - i - 1];
      b_ramp[ramp_size - i - 1] = tmpRampVal;
    }
  }
  if(calcloss) {
    fprintf(stdout, "Resolution loss for %d entries:\n", ramp_size);
    r_res = 0;
    g_res = 0;
    b_res = 0;
    tmpRampVal = 0xffff;
    for(i = 0; i < ramp_size; i++) {
      if ((r_ramp[i] & 0xff00) != (tmpRampVal & 0xff00)) {
        r_res++;
      }
      tmpRampVal = r_ramp[i];
    }
    tmpRampVal = 0xffff;
    for(i = 0; i < ramp_size; i++) {
      if ((g_ramp[i] & 0xff00) != (tmpRampVal & 0xff00)) {
        g_res++;
      }
      tmpRampVal = g_ramp[i];
    }
    tmpRampVal = 0xffff;
    for(i = 0; i < ramp_size; i++) {
      if ((b_ramp[i] & 0xff00) != (tmpRampVal & 0xff00)) {
        b_res++;
      }
      tmpRampVal = b_ramp[i];
    }
    fprintf(stdout, "R: %d\tG: %d\t B: %d\t colors lost\n", ramp_size - r_res, ramp_size - g_res, ramp_size - b_res );
  }
#ifdef _WIN32
  for (i = 0; i < ramp_size; i++) {
    winGammaRamp.Red[i] = r_ramp[i];
    winGammaRamp.Green[i] = g_ramp[i];
    winGammaRamp.Blue[i] = b_ramp[i];
  }

#endif
 
  if(printramps)
    for(i=0; i<ramp_size; i++)
      fprintf(stdout,"%d %d %d\n", r_ramp[i], g_ramp[i], b_ramp[i]);

  if(!donothing) {
    /* write gamma ramp to X-server */
#ifndef _WIN32
# ifdef FGLRX
    for(i = 0; i < ramp_size; i++) {
      fglrx_gammaramps.RGamma[i] = r_ramp[i] >> 6;
      fglrx_gammaramps.GGamma[i] = g_ramp[i] >> 6;
      fglrx_gammaramps.BGamma[i] = b_ramp[i] >> 6;
    }
    if (!FGLRX_X11SetGammaRamp_C16native_1024(dpy, screen, controller, ramp_size, &fglrx_gammaramps))
# else
    if(xrr_version >= 102)
    {
      XRRCrtcGamma * gamma = XRRAllocGamma (ramp_size);
      if(!gamma)
        warning ("Unable to calibrate display");
      else
      {
        for(i=0; i < ramp_size; ++i)
        {
          gamma->red[i] = r_ramp[i];
          gamma->green[i] = g_ramp[i];
          gamma->blue[i] = b_ramp[i];
        }
        XRRSetCrtcGamma (dpy, crtc, gamma);
        XRRFreeGamma (gamma);
      }
    } else
    if (!XF86VidModeSetGammaRamp (dpy, screen, ramp_size, r_ramp, g_ramp, b_ramp))
# endif
#else
    if (!SetDeviceGammaRamp(hDc, &winGammaRamp))
#endif
      warning ("Unable to calibrate display");
  }

  message ("X-LUT size:      \t%d\n", ramp_size);

  free(r_ramp);
  free(g_ramp);
  free(b_ramp);

cleanupX:
#ifndef _WIN32
  if(dpy)
    if(!donothing)
      XCloseDisplay (dpy);
#endif

  return 0;
}

/* Basic printf type error() and warning() routines */

/* errors are printed to stderr */
void
error (char *fmt, ...)
{
  va_list args;

  fprintf (stderr, "Error - ");
  va_start (args, fmt);
  vfprintf (stderr, fmt, args);
  va_end (args);
  fprintf (stderr, "\n");
  exit (-1);
}

/* warnings are printed to stdout */
void
warning (char *fmt, ...)
{
  va_list args;

  fprintf (stdout, "Warning - ");
  va_start (args, fmt);
  vfprintf (stdout, fmt, args);
  va_end (args);
  fprintf (stdout, "\n");
}