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 _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"); }
int main(int argc, char **argv) { Display *dpy = XOpenDisplay(NULL); int screen = DefaultScreen(dpy); Window root = RootWindow(dpy, screen); XRRScreenResources *res = XRRGetScreenResourcesCurrent(dpy, root); int temp = 6500; if (argc > 1) temp = atoi(argv[1]); if (temp < 1000 || temp > 10000) temp = 6500; temp -= 1000; double ratio = temp % 500 / 500.0; #define AVG(c) whitepoints[temp / 500].c * (1 - ratio) + whitepoints[temp / 500 + 1].c * ratio double gammar = AVG(r); double gammag = AVG(g); double gammab = AVG(b); int num_crtcs = res->ncrtc; for (int c = 0; c < num_crtcs; c++) { int crtcxid = res->crtcs[c]; int size = XRRGetCrtcGammaSize(dpy, crtcxid); XRRCrtcGamma *crtc_gamma = XRRAllocGamma(size); for (int i = 0; i < size; i++) { double g = 65535.0 * i / size; crtc_gamma->red[i] = g * gammar; crtc_gamma->green[i] = g * gammag; crtc_gamma->blue[i] = g * gammab; } XRRSetCrtcGamma(dpy, crtcxid, crtc_gamma); size = XRRGetCrtcGammaSize(dpy, crtcxid); XFree(crtc_gamma); } }
// Detect gamma ramp support // void _glfwInitGammaRamp(void) { // RandR gamma support is only available with version 1.2 and above if (_glfw.x11.randr.available && (_glfw.x11.randr.versionMajor > 1 || (_glfw.x11.randr.versionMajor == 1 && _glfw.x11.randr.versionMinor >= 2))) { // FIXME: Assumes that all monitors have the same size gamma tables // This is reasonable as I suspect the that if they did differ, it // would imply that setting the gamma size to an arbitary size is // possible as well. XRRScreenResources *rr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); if (XRRGetCrtcGammaSize(_glfw.x11.display, rr->crtcs[0]) == 0) { // This is probably older Nvidia RandR with broken gamma support // Flag it as useless and try Xf86VidMode below, if available _glfw.x11.randr.gammaBroken = GL_TRUE; } XRRFreeScreenResources(rr); } }
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; } }
JNIEXPORT jint JNICALL Java_org_lwjgl_system_linux_Xrandr_nXRRGetCrtcGammaSize(JNIEnv *__env, jclass clazz, jlong displayAddress, jlong crtc) { Display *display = (Display *)(intptr_t)displayAddress; UNUSED_PARAMS(__env, clazz) return (jint)XRRGetCrtcGammaSize(display, (RRCrtc)crtc); }
// Initialize X11 display and look for supported X11 extensions // static GLFWbool initExtensions(void) { // Find or create window manager atoms _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); #if defined(_GLFW_HAS_XF86VM) // Check for XF86VidMode extension _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); #endif /*_GLFW_HAS_XF86VM*/ // Check for RandR extension if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase)) { if (XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.major, &_glfw.x11.randr.minor)) { // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) _glfw.x11.randr.available = GLFW_TRUE; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); } } if (_glfw.x11.randr.available) { XRRScreenResources* sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) { // This is either a headless system or an older Nvidia binary driver // with broken gamma support // Flag it as useless and fall back to Xf86VidMode gamma, if // available _glfwInputError(GLFW_PLATFORM_ERROR, "X11: RandR gamma ramp support seems broken"); _glfw.x11.randr.gammaBroken = GLFW_TRUE; } XRRFreeScreenResources(sr); XRRSelectInput(_glfw.x11.display, _glfw.x11.root, RROutputChangeNotifyMask); } if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display)) _glfw.x11.xinerama.available = GLFW_TRUE; } #if defined(_GLFW_HAS_XINPUT) if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.major = 2; _glfw.x11.xi.minor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.major, &_glfw.x11.xi.minor) != BadRequest) { _glfw.x11.xi.available = GLFW_TRUE; } } #endif /*_GLFW_HAS_XINPUT*/ // Check if Xkb is supported on this display _glfw.x11.xkb.major = 1; _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.major, &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) { Bool supported; if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. createKeyTables(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // Find or create string format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.COMPOUND_STRING = XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Find or create selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // Find or create standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Find or create clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); // Find Xdnd (drag and drop) atoms, if available _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", True); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", True); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", True); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", True); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", True); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", True); _glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", True); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", True); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", True); return GLFW_TRUE; }
static gboolean crtc_initialize (MateRRCrtc *crtc, XRRScreenResources *res, GError **error) { XRRCrtcInfo *info = XRRGetCrtcInfo (DISPLAY (crtc), res, crtc->id); GPtrArray *a; int i; #if 0 g_print ("CRTC %lx Timestamp: %u\n", crtc->id, (guint32)info->timestamp); #endif if (!info) { /* FIXME: We need to reaquire the screen resources */ /* FIXME: can we actually catch BadRRCrtc, and does it make sense to emit that? */ /* Translators: CRTC is a CRT Controller (this is X terminology). * It is *very* unlikely that you'll ever get this error, so it is * only listed for completeness. */ g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_RANDR_ERROR, _("could not get information about CRTC %d"), (int) crtc->id); return FALSE; } /* MateRRMode */ crtc->current_mode = mode_by_id (crtc->info, info->mode); crtc->x = info->x; crtc->y = info->y; /* Current outputs */ a = g_ptr_array_new (); for (i = 0; i < info->noutput; ++i) { MateRROutput *output = mate_rr_output_by_id (crtc->info, info->outputs[i]); if (output) g_ptr_array_add (a, output); } g_ptr_array_add (a, NULL); crtc->current_outputs = (MateRROutput **)g_ptr_array_free (a, FALSE); /* Possible outputs */ a = g_ptr_array_new (); for (i = 0; i < info->npossible; ++i) { MateRROutput *output = mate_rr_output_by_id (crtc->info, info->possible[i]); if (output) g_ptr_array_add (a, output); } g_ptr_array_add (a, NULL); crtc->possible_outputs = (MateRROutput **)g_ptr_array_free (a, FALSE); /* Rotations */ crtc->current_rotation = mate_rr_rotation_from_xrotation (info->rotation); crtc->rotations = mate_rr_rotation_from_xrotation (info->rotations); XRRFreeCrtcInfo (info); /* get an store gamma size */ crtc->gamma_size = XRRGetCrtcGammaSize (DISPLAY (crtc), crtc->id); return TRUE; }
// Look for and initialize supported X11 extensions // static GLFWbool initExtensions(void) { _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1"); if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); } #if defined(__CYGWIN__) _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so"); #else _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6"); #endif if (_glfw.x11.xi.handle) { _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents"); if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.major = 2; _glfw.x11.xi.minor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.major, &_glfw.x11.xi.minor) == Success) { _glfw.x11.xi.available = GLFW_TRUE; } } } #if defined(__CYGWIN__) _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so"); #else _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2"); #endif if (_glfw.x11.randr.handle) { _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources) _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources"); _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo"); _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent) _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension) _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension"); _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion) _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion"); _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput"); _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma) _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration) _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase)) { if (XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.major, &_glfw.x11.randr.minor)) { // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) _glfw.x11.randr.available = GLFW_TRUE; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); } } } if (_glfw.x11.randr.available) { XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) { // This is likely an older Nvidia driver with broken gamma support // Flag it as useless and fall back to xf86vm gamma, if available _glfw.x11.randr.gammaBroken = GLFW_TRUE; } if (!sr->ncrtc) { // A system without CRTCs is likely a system with broken RandR // Disable the RandR monitor path and fall back to core functions _glfw.x11.randr.monitorBroken = GLFW_TRUE; } XRRFreeScreenResources(sr); } if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRSelectInput(_glfw.x11.display, _glfw.x11.root, RROutputChangeNotifyMask); } #if defined(__CYGWIN__) _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so"); #else _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1"); #endif if (_glfw.x11.xcursor.handle) { _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate"); _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor) _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); } #if defined(__CYGWIN__) _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so"); #else _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1"); #endif if (_glfw.x11.xinerama.handle) { _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive"); _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens) _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display)) _glfw.x11.xinerama.available = GLFW_TRUE; } } _glfw.x11.xkb.major = 1; _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.major, &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) { Bool supported; if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } } #if defined(__CYGWIN__) _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so"); #else _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1"); #endif if (_glfw.x11.x11xcb.handle) { _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection) _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); } #if defined(__CYGWIN__) _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so"); #else _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1"); #endif if (_glfw.x11.xrender.handle) { _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension"); _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion"); _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat) _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); if (XRenderQueryExtension(_glfw.x11.display, &_glfw.x11.xrender.errorBase, &_glfw.x11.xrender.eventBase)) { if (XRenderQueryVersion(_glfw.x11.display, &_glfw.x11.xrender.major, &_glfw.x11.xrender.minor)) { _glfw.x11.xrender.available = GLFW_TRUE; } } } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. createKeyTables(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // String format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Custom selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // ICCCM standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False); _glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); // Xdnd (drag and drop) atoms _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False); _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False); // ICCCM, EWMH and Motif window property atoms // These can be set safely even without WM support // The EWMH atoms that require WM support are handled in detectEWMH _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.NET_WM_ICON = XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False); _glfw.x11.NET_WM_PING = XInternAtom(_glfw.x11.display, "_NET_WM_PING", False); _glfw.x11.NET_WM_PID = XInternAtom(_glfw.x11.display, "_NET_WM_PID", False); _glfw.x11.NET_WM_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False); _glfw.x11.NET_WM_ICON_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False); _glfw.x11.NET_WM_BYPASS_COMPOSITOR = XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False); _glfw.x11.NET_WM_WINDOW_OPACITY = XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); // The compositing manager selection name contains the screen number { char name[32]; snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen); _glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False); } return GLFW_TRUE; }
static void InitGamma() { #ifdef X11GAMMA int i=0; SDL_SysWMinfo info; Display* dpy = NULL; if(gammaRamps != NULL) // already saved gamma 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; } noGammaRamps = res->ncrtc; gammaRamps = calloc(noGammaRamps, sizeof(XRRCrtcGamma*)); if(gammaRamps == NULL) { VID_Printf(PRINT_ALL, "Couldn't allocate memory for %d gamma ramps - OOM?!\n", noGammaRamps); return; } for(i=0; i < noGammaRamps; ++i) { int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]); size_t rampSize = len*sizeof(Uint16); XRRCrtcGamma* origGamma = XRRGetCrtcGamma(dpy, res->crtcs[i]); XRRCrtcGamma* gammaCopy = XRRAllocGamma(len); memcpy(gammaCopy->red, origGamma->red, rampSize); memcpy(gammaCopy->green, origGamma->green, rampSize); memcpy(gammaCopy->blue, origGamma->blue, rampSize); gammaRamps[i] = gammaCopy; } XRRFreeScreenResources(res); VID_Printf(PRINT_ALL, "Using hardware gamma via X11/xRandR.\n"); #else VID_Printf(PRINT_ALL, "Using hardware gamma via SDL.\n"); #endif gl_state.hwgamma = true; vid_gamma->modified = 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"); }
// Initialize X11 display and look for supported X11 extensions // static GLFWbool initExtensions(void) { _glfw.x11.vidmode.handle = dlopen("libXxf86vm.so.1", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, &_glfw.x11.vidmode.eventBase, &_glfw.x11.vidmode.errorBase); } _glfw.x11.xi.handle = dlopen("libXi.so", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.xi.handle) { _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) dlsym(_glfw.x11.xi.handle, "XISelectEvents"); if (XQueryExtension(_glfw.x11.display, "XInputExtension", &_glfw.x11.xi.majorOpcode, &_glfw.x11.xi.eventBase, &_glfw.x11.xi.errorBase)) { _glfw.x11.xi.major = 2; _glfw.x11.xi.minor = 0; if (XIQueryVersion(_glfw.x11.display, &_glfw.x11.xi.major, &_glfw.x11.xi.minor) == Success) { _glfw.x11.xi.available = GLFW_TRUE; } } } // Check for RandR extension if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, &_glfw.x11.randr.errorBase)) { if (XRRQueryVersion(_glfw.x11.display, &_glfw.x11.randr.major, &_glfw.x11.randr.minor)) { // The GLFW RandR path requires at least version 1.3 if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3) _glfw.x11.randr.available = GLFW_TRUE; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query RandR version"); } } if (_glfw.x11.randr.available) { XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) { // This is either a headless system or an older Nvidia binary driver // with broken gamma support // Flag it as useless and fall back to Xf86VidMode gamma, if // available _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Detected broken RandR gamma ramp support"); _glfw.x11.randr.gammaBroken = GLFW_TRUE; } if (!sr->ncrtc || !sr->noutput || !sr->nmode) { // This is either a headless system or broken Cygwin/X RandR // Flag it as useless and fall back to Xlib display functions _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Detected broken RandR monitor support"); _glfw.x11.randr.monitorBroken = GLFW_TRUE; } XRRFreeScreenResources(sr); XRRSelectInput(_glfw.x11.display, _glfw.x11.root, RROutputChangeNotifyMask); } if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display)) _glfw.x11.xinerama.available = GLFW_TRUE; } // Check if Xkb is supported on this display _glfw.x11.xkb.major = 1; _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase, &_glfw.x11.xkb.major, &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) { Bool supported; if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported) _glfw.x11.xkb.detectable = GLFW_TRUE; } } _glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so.1", RTLD_LAZY | RTLD_GLOBAL); if (_glfw.x11.x11xcb.handle) { _glfw.x11.x11xcb.XGetXCBConnection = (PFN_XGetXCBConnection) dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); } // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. createKeyTables(); // Detect whether an EWMH-conformant window manager is running detectEWMH(); // String format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.COMPOUND_STRING = XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); // Custom selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); // ICCCM standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); // Clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); // Xdnd (drag and drop) atoms _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False); _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False); _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False); _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False); _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False); _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False); _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False); // ICCCM, EWMH and Motif window property atoms // These can be set safely even without WM support // The EWMH atoms that require WM support are handled in detectEWMH _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False); _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False); _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); _glfw.x11.NET_WM_ICON = XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False); _glfw.x11.NET_WM_PING = XInternAtom(_glfw.x11.display, "_NET_WM_PING", False); _glfw.x11.NET_WM_PID = XInternAtom(_glfw.x11.display, "_NET_WM_PID", False); _glfw.x11.NET_WM_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False); _glfw.x11.NET_WM_ICON_NAME = XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False); _glfw.x11.NET_WM_BYPASS_COMPOSITOR = XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); return GLFW_TRUE; }