/*ARGSUSED*/ static void ApplyCallback(Widget w, XtPointer call_data, XtPointer client_data) { hitError = 0; XF86VidModeModModeLine(XtDisplay(w), vidtune->screen, &modeline); XSync(XtDisplay(w), False); if (hitError) { if (repeater != NULL) { XtCallActionProc(repeater, "unset", NULL, NULL, 0); XtCallActionProc(repeater, "stop", NULL, NULL, 0); repeater = NULL; } XBell(XtDisplay(w), 80); if (timeout) StopTestCallback(w, NULL, NULL); GetModeLine(False); SetLabels(); } }
float PsychSetNominalFramerate(int screenNumber, float requestedHz) { // Information returned by/sent to the XF86VidModeExtension: XF86VidModeModeLine mode_line; // The mode line of the current video mode. int dot_clock; // The RAMDAC / TDMS pixel clock frequency. int rc; int event_base; // We start with a default vrefresh of zero, which means "couldn't query refresh from OS": float vrefresh = 0; if(screenNumber>=numDisplays) PsychErrorExitMsg(PsychError_internal, "screenNumber is out of range"); if (!XF86VidModeSetClientVersion(displayCGIDs[screenNumber])) { // Failed to use VidMode-Extension. We just return a vrefresh of zero. return(0); } if (!XF86VidModeQueryExtension(displayCGIDs[screenNumber], &event_base, &x11_errorbase)) { // Failed to use VidMode-Extension. We just return a vrefresh of zero. return(0); } // Attach our error callback handler and reset error-state: x11_errorval = 0; x11_olderrorhandler = XSetErrorHandler(x11VidModeErrorHandler); // Step 1: Query current dotclock and modeline: if (!XF86VidModeGetModeLine(displayCGIDs[screenNumber], PsychGetXScreenIdForScreen(screenNumber), &dot_clock, &mode_line)) { // Restore default error handler: XSetErrorHandler(x11_olderrorhandler); PsychErrorExitMsg(PsychError_internal, "Failed to query video dotclock and modeline!"); } // Step 2: Calculate updated modeline: if (requestedHz > 10) { // Step 2-a: Given current dot-clock and modeline and requested vrefresh, compute // modeline for closest possible match: requestedHz*=1000.0f; vrefresh = (((dot_clock * 1000) / mode_line.htotal) * 1000) / requestedHz; // Assign it to closest modeline setting: mode_line.vtotal = (int)(vrefresh + 0.5f); } else { // Step 2-b: Delta mode. requestedHz represents a direct integral offset // to add or subtract from current modeline setting: mode_line.vtotal+=(int) requestedHz; } // Step 3: Try to set new modeline: if (!XF86VidModeModModeLine(displayCGIDs[screenNumber], PsychGetXScreenIdForScreen(screenNumber), &mode_line)) { // Restore default error handler: XSetErrorHandler(x11_olderrorhandler); // Invalid modeline? Signal this: return(-1); } // We synchronize and wait for X-Request completion. If the modeline was invalid, // this will trigger an invocation of our errorhandler, which in turn will // set the x11_errorval to a non-zero value: XSync(displayCGIDs[screenNumber], FALSE); // Restore default error handler: XSetErrorHandler(x11_olderrorhandler); // Check for error: if (x11_errorval) { // Failed to set new mode! Must be invalid. We return -1 to signal this: return(-1); } // No error... // Step 4: Query new settings and return them: vrefresh = PsychGetNominalFramerate(screenNumber); // Done. return(vrefresh); }