/*! * \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; }
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*/ }
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*/ }
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 */ }
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"); } }
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); }
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"); }
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 */ }
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; } }
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; }
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"); }