示例#1
0
void StimulusDisplay::stateSystemCallback(const Datum &data, MWorksTime time) {
    unique_lock lock(display_lock);

    int newState = data.getInteger();

    if (IDLE == newState) {
        
        if (CVDisplayLinkIsRunning(displayLink)) {
            // If another thread is waiting for a display refresh, allow it to complete before stopping
            // the display link
            while (waitingForRefresh) {
                refreshCond.wait(lock);
            }

            // We need to release the lock before calling CVDisplayLinkStop, because
            // StimulusDisplay::displayLinkCallback could be blocked waiting for the lock, and
            // CVDisplayLinkStop won't return until displayLinkCallback exits, leading to deadlock.
            lock.unlock();
            
            if (kCVReturnSuccess != CVDisplayLinkStop(displayLink)) {
                merror(M_DISPLAY_MESSAGE_DOMAIN, "Unable to stop display updates");
            } else {
                currentOutputTimeUS = -1;
                mprintf(M_DISPLAY_MESSAGE_DOMAIN, "Display updates stopped");
            }
        }
        
    } else if (RUNNING == newState) {

        if (!CVDisplayLinkIsRunning(displayLink)) {

            lastFrameTime = 0;

            if (kCVReturnSuccess != CVDisplayLinkStart(displayLink)) {
                merror(M_DISPLAY_MESSAGE_DOMAIN, "Unable to start display updates");
            } else {
                // Wait for a refresh to complete, so we know that getCurrentOutputTimeUS() will return a valid time
                ensureRefresh(lock);
                
                mprintf(M_DISPLAY_MESSAGE_DOMAIN,
                        "Display updates started (main = %d, current = %d)",
                        CGMainDisplayID(),
                        CVDisplayLinkGetCurrentCGDisplay(displayLink));
            }

        }
        
    }
}
示例#2
0
void StimulusDisplay::ensureRefresh(unique_lock &lock) {
    if (!CVDisplayLinkIsRunning(displayLink)) {
        // Need to do the refresh here
        refreshDisplay();
    } else {
        // Wait for next display refresh to complete
        waitingForRefresh = true;
        do {
            refreshCond.wait(lock);
        } while (waitingForRefresh);
    }
}
void PsychOSCloseWindow(PsychWindowRecordType *windowRecord)
{
    CGDirectDisplayID   cgDisplayID;

    // Disable rendering context:
    CGLSetCurrentContext(NULL);

    // Destroy pixelformat object:
    CGLDestroyPixelFormat(windowRecord->targetSpecific.pixelFormatObject);

    // Destroy rendering context:
    CGLReleaseContext(windowRecord->targetSpecific.contextObject);
    if (windowRecord->targetSpecific.glusercontextObject) CGLReleaseContext(windowRecord->targetSpecific.glusercontextObject);
    if (windowRecord->targetSpecific.glswapcontextObject) CGLReleaseContext(windowRecord->targetSpecific.glswapcontextObject);

    // Last reference to this screen? In that case we have to shutdown the fallback
    // vbl timestamping and vblank counting facilities for this screen:
    if (screenRefCount[windowRecord->screenNumber] == 1) {
        // Last one on this screen will be gone in a second.
        // Shutdown and release CVDisplayLink for this windows screen, if any:
        if (cvDisplayLink[windowRecord->screenNumber]) {
            if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-INFO: Releasing CVDisplayLink for screen %i.\n", windowRecord->screenNumber);

            if (CVDisplayLinkIsRunning(cvDisplayLink[windowRecord->screenNumber])) CVDisplayLinkStop(cvDisplayLink[windowRecord->screenNumber]);
            PsychYieldIntervalSeconds(0.1);
            CVDisplayLinkRelease(cvDisplayLink[windowRecord->screenNumber]);
            cvDisplayLink[windowRecord->screenNumber] = NULL;
            PsychYieldIntervalSeconds(0.1);

            // Teardown shared data structure and mutex:
            PsychDestroyMutex(&(cvDisplayLinkData[windowRecord->screenNumber].mutex));
        }
    }

    // Release reference of this window to its screen:
    screenRefCount[windowRecord->screenNumber]--;

    // Destroy Cocoa onscreen window, if any:
    if (windowRecord->targetSpecific.windowHandle) PsychCocoaDisposeWindow(windowRecord);
    windowRecord->targetSpecific.windowHandle = NULL;

    return;
}