int main(int argc, char *argv[]) { CGSDebugOptions options; CGSGetDebugOptions(&options); options ^= kCGSDebugOptionNoShadows; CGSSetDebugOptions(options); return 0; }
PsychError SCREENGetWindowInfo(void) { const char *FieldNames[]={ "Beamposition", "LastVBLTimeOfFlip", "LastVBLTime", "VBLCount", "TimeAtSwapRequest", "TimePostSwapRequest", "RawSwapTimeOfFlip", "VBLTimePostFlip", "OSSwapTimestamp", "GPULastFrameRenderTime", "StereoMode", "ImagingMode", "MultiSampling", "MissedDeadlines", "FlipCount", "StereoDrawBuffer", "GuesstimatedMemoryUsageMB", "VBLStartline", "VBLEndline", "VideoRefreshFromBeamposition", "GLVendor", "GLRenderer", "GLVersion", "GPUCoreId", "GLSupportsFBOUpToBpc", "GLSupportsBlendingUpToBpc", "GLSupportsTexturesUpToBpc", "GLSupportsFilteringUpToBpc", "GLSupportsPrecisionColors", "GLSupportsFP32Shading", "BitsPerColorComponent", "IsFullscreen", "SpecialFlags", "SwapGroup", "SwapBarrier" }; const int fieldCount = 35; PsychGenericScriptType *s; PsychWindowRecordType *windowRecord; double beamposition, lastvbl; int infoType = 0, retIntArg; double auxArg1, auxArg2, auxArg3; CGDirectDisplayID displayId; psych_uint64 postflip_vblcount; double vbl_startline; long scw, sch; psych_bool onscreen; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumInputArgs(5)); //The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(1)); //The required number of inputs PsychErrorExit(PsychCapNumOutputArgs(1)); //The maximum number of outputs // Query infoType flag: Defaults to zero. PsychCopyInIntegerArg(2, FALSE, &infoType); if (infoType < 0 || infoType > 5) PsychErrorExitMsg(PsychError_user, "Invalid 'infoType' argument specified! Valid are 0, 1, 2, 3, 4 and 5."); // Windowserver info requested? if (infoType == 2 || infoType == 3) { // Return info about WindowServer: #if PSYCH_SYSTEM == PSYCH_OSX const char *CoreGraphicsFieldNames[]={ "CGSFps", "CGSValue1", "CGSValue2", "CGSValue3", "CGSDebugOptions" }; const int CoreGraphicsFieldCount = 5; float cgsFPS, val1, val2, val3; // This (undocumented) Apple call retrieves information about performance statistics of // the Core graphics server, also known as WindowServer or Quartz compositor: CGSGetPerformanceData(_CGSDefaultConnection(), &cgsFPS, &val1, &val2, &val3); if (CGSGetDebugOptions(&retIntArg)) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: GetWindowInfo: Call to CGSGetDebugOptions() failed!\n"); } PsychAllocOutStructArray(1, FALSE, 1, CoreGraphicsFieldCount, CoreGraphicsFieldNames, &s); PsychSetStructArrayDoubleElement("CGSFps", 0 , cgsFPS, s); PsychSetStructArrayDoubleElement("CGSValue1", 0, val1, s); PsychSetStructArrayDoubleElement("CGSValue2", 0, val2, s); PsychSetStructArrayDoubleElement("CGSValue3", 0, val3, s); PsychSetStructArrayDoubleElement("CGSDebugOptions", 0, (double) retIntArg, s); if ( (infoType == 3) && PsychCopyInDoubleArg(3, FALSE, &auxArg1) ) { // Type 3 setup request with auxArg1 provided. Apple auxArg1 as debugFlag setting // for the CoreGraphics server: DANGEROUS! if (CGSSetDebugOptions((unsigned int) auxArg1)) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: GetWindowInfo: Call to CGSSetDebugOptions() failed!\n"); } } #endif #if PSYCH_SYSTEM == PSYCH_WINDOWS psych_uint64 onsetVBLCount, frameId; double onsetVBLTime, compositionRate; psych_uint64 targetVBL; PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); // Query all DWM presentation timing info, return full info as struct in optional return argument '1': if (PsychOSGetPresentationTimingInfo(windowRecord, TRUE, 0, &onsetVBLCount, &onsetVBLTime, &frameId, &compositionRate, 1)) { // Query success: Info struct has been created and returned by PsychOSGetPresentationTimingInfo()... auxArg1 = auxArg2 = 0; auxArg3 = 2; // Want us to change settings? if ( (infoType == 3) && PsychCopyInDoubleArg(3, FALSE, &auxArg1) && PsychCopyInDoubleArg(4, FALSE, &auxArg2) && PsychCopyInDoubleArg(5, FALSE, &auxArg3)) { if (auxArg1 < 0) auxArg1 = 0; targetVBL = auxArg1; if (PsychOSSetPresentParameters(windowRecord, targetVBL, (int) auxArg3, auxArg2)) { if (PsychPrefStateGet_Verbosity() > 5) printf("PTB-DEBUG: GetWindowInfo: Call to PsychOSSetPresentParameters(%i, %i, %f) SUCCESS!\n", (int) auxArg1, (int) auxArg3, auxArg2); } else { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: GetWindowInfo: Call to PsychOSSetPresentParameters() failed!\n"); } } } else { // Unsupported / Failed: PsychCopyOutDoubleArg(1, FALSE, -1); } #endif #if PSYCH_SYSTEM == PSYCH_LINUX if (infoType == 2) { // MMIO register Read for screenid "auxArg1", register offset "auxArg2": PsychCopyInDoubleArg(3, TRUE, &auxArg1); PsychCopyInDoubleArg(4, TRUE, &auxArg2); PsychCopyOutDoubleArg(1, FALSE, (double) PsychOSKDReadRegister((int) auxArg1, (unsigned int) auxArg2, NULL)); } if (infoType == 3) { // MMIO register Write for screenid "auxArg1", register offset "auxArg2", to value "auxArg3": PsychCopyInDoubleArg(3, TRUE, &auxArg1); PsychCopyInDoubleArg(4, TRUE, &auxArg2); PsychCopyInDoubleArg(5, TRUE, &auxArg3); PsychOSKDWriteRegister((int) auxArg1, (unsigned int) auxArg2, (unsigned int) auxArg3, NULL); } #endif // Done. return(PsychError_none); } // Get the window record: PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); onscreen = PsychIsOnscreenWindow(windowRecord); if (onscreen) { // Query rasterbeam position: Will return -1 if unsupported. PsychGetCGDisplayIDFromScreenNumber(&displayId, windowRecord->screenNumber); beamposition = (double) PsychGetDisplayBeamPosition(displayId, windowRecord->screenNumber); } else { beamposition = -1; } if (infoType == 1) { // Return the measured beamposition: PsychCopyOutDoubleArg(1, FALSE, beamposition); } else if (infoType == 4) { // Return async flip state: 1 = Active, 0 = Inactive. PsychCopyOutDoubleArg(1, FALSE, (((NULL != windowRecord->flipInfo) && (0 != windowRecord->flipInfo->asyncstate)) ? 1 : 0)); } else if (infoType == 5) { // Create a GL_EXT_timer_query object for this window: if (glewIsSupported("GL_EXT_timer_query")) { // Pending queries finished? if (windowRecord->gpuRenderTimeQuery > 0) { PsychErrorExitMsg(PsychError_user, "Tried to create a new GPU rendertime query, but last query not yet finished! Call Screen('Flip') first!"); } // Enable our rendering context by selecting this window as drawing target: PsychSetDrawingTarget(windowRecord); // Generate Query object: glGenQueries(1, &windowRecord->gpuRenderTimeQuery); // Emit Query: GPU will measure elapsed processing time in Nanoseconds, starting // with the first GL command executed after this command: glBeginQuery(GL_TIME_ELAPSED_EXT, windowRecord->gpuRenderTimeQuery); // Reset last measurement: windowRecord->gpuRenderTime = 0; } else { if (PsychPrefStateGet_Verbosity() > 4) printf("PTB-INFO: GetWindowInfo for infoType 5: GPU timer query objects are unsupported on this platform and GPU. Call ignored!\n"); } } else { // Return all information: PsychAllocOutStructArray(1, FALSE, 1, fieldCount, FieldNames, &s); // Rasterbeam position: PsychSetStructArrayDoubleElement("Beamposition", 0, beamposition, s); // Time of last vertical blank when a double-buffer swap occured: if ((windowRecord->flipCount > 0) && (windowRecord->time_at_last_vbl == 0) && (PsychPrefStateGet_VBLTimestampingMode() == 4)) { // If time_at_last_vbl for an already finished or at least pending flip isn't available and // we have support for OS-Builtin timestamping enabled, we try to employ OS-Builtin timestamping // to get a timestamp for the most recent pending or finished flip. If this fails or is unsupported, // it will have no effect: PsychOSGetSwapCompletionTimestamp(windowRecord, 0, &(windowRecord->time_at_last_vbl)); } // Return it - or the value zero if it is (still) undefined/unavailable: PsychSetStructArrayDoubleElement("LastVBLTimeOfFlip", 0, windowRecord->time_at_last_vbl, s); // Uncorrected timestamp of flip swap completion: PsychSetStructArrayDoubleElement("RawSwapTimeOfFlip", 0, windowRecord->rawtime_at_swapcompletion, s); // Timestamp immediately prior to call to PsychOSFlipWindowBuffers(), i.e., time at swap request submission: PsychSetStructArrayDoubleElement("TimeAtSwapRequest", 0, windowRecord->time_at_swaprequest, s); // Timestamp immediately after call to PsychOSFlipWindowBuffers() returns, i.e., time at swap request submission completion: PsychSetStructArrayDoubleElement("TimePostSwapRequest", 0, windowRecord->time_post_swaprequest, s); // Timestamp immediately after call to PsychOSFlipWindowBuffers() returns, i.e., time at swap request submission completion: PsychSetStructArrayDoubleElement("VBLTimePostFlip", 0, windowRecord->postflip_vbltimestamp, s); // Swap completion timestamp for most recently completed swap, according to OS-builtin PsychOSGetSwapCompletionTimestamp() method: PsychSetStructArrayDoubleElement("OSSwapTimestamp", 0, windowRecord->osbuiltin_swaptime, s); // Result from last GPU rendertime query as triggered by infoType 5: Zero if undefined. PsychSetStructArrayDoubleElement("GPULastFrameRenderTime", 0, windowRecord->gpuRenderTime, s); // Try to determine system time of last VBL on display, independent of any // flips / bufferswaps. lastvbl = -1; postflip_vblcount = 0; // On supported systems, we can query the OS for the system time of last VBL, so we can // use the most recent VBL timestamp as baseline for timing calculations, // instead of one far in the past. if (onscreen) { lastvbl = PsychOSGetVBLTimeAndCount(windowRecord, &postflip_vblcount); } // If we couldn't determine this information we just set lastvbl to the last known // vbl timestamp of last flip -- better than nothing... if (lastvbl < 0) lastvbl = windowRecord->time_at_last_vbl; PsychSetStructArrayDoubleElement("LastVBLTime", 0, lastvbl, s); PsychSetStructArrayDoubleElement("VBLCount", 0, (double) (psych_int64) postflip_vblcount, s); // Misc. window parameters: PsychSetStructArrayDoubleElement("StereoMode", 0, windowRecord->stereomode, s); PsychSetStructArrayDoubleElement("ImagingMode", 0, windowRecord->imagingMode, s); PsychSetStructArrayDoubleElement("SpecialFlags", 0, windowRecord->specialflags, s); PsychSetStructArrayDoubleElement("IsFullscreen", 0, (windowRecord->specialflags & kPsychIsFullscreenWindow) ? 1 : 0, s); PsychSetStructArrayDoubleElement("MultiSampling", 0, windowRecord->multiSample, s); PsychSetStructArrayDoubleElement("MissedDeadlines", 0, windowRecord->nr_missed_deadlines, s); PsychSetStructArrayDoubleElement("FlipCount", 0, windowRecord->flipCount, s); PsychSetStructArrayDoubleElement("StereoDrawBuffer", 0, windowRecord->stereodrawbuffer, s); PsychSetStructArrayDoubleElement("GuesstimatedMemoryUsageMB", 0, (double) windowRecord->surfaceSizeBytes / 1024 / 1024, s); PsychSetStructArrayDoubleElement("BitsPerColorComponent", 0, (double) windowRecord->bpc, s); // Query real size of the underlying display in order to define the vbl_startline: PsychGetScreenSize(windowRecord->screenNumber, &scw, &sch); vbl_startline = (double) sch; PsychSetStructArrayDoubleElement("VBLStartline", 0, vbl_startline, s); // And VBL endline: PsychSetStructArrayDoubleElement("VBLEndline", 0, windowRecord->VBL_Endline, s); // Video refresh interval duration from beamposition method: PsychSetStructArrayDoubleElement("VideoRefreshFromBeamposition", 0, windowRecord->ifi_beamestimate, s); // Swap group assignment and swap barrier assignment, if any: PsychSetStructArrayDoubleElement("SwapGroup", 0, windowRecord->swapGroup, s); PsychSetStructArrayDoubleElement("SwapBarrier", 0, windowRecord->swapBarrier, s); // Which basic GPU architecture is this? PsychSetStructArrayStringElement("GPUCoreId", 0, windowRecord->gpuCoreId, s); // FBO's supported, and how deep? if (windowRecord->gfxcaps & kPsychGfxCapFBO) { if (windowRecord->gfxcaps & kPsychGfxCapFPFBO32) { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPFBO16) { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 8, s); } else { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 0, s); } // How deep is alpha blending supported? if (windowRecord->gfxcaps & kPsychGfxCapFPBlend32) { PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPBlend16) { PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 8, s); // How deep is texture mapping supported? if (windowRecord->gfxcaps & kPsychGfxCapFPTex32) { PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPTex16) { PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 8, s); // How deep is texture filtering supported? if (windowRecord->gfxcaps & kPsychGfxCapFPFilter32) { PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPFilter16) { PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 8, s); if (windowRecord->gfxcaps & kPsychGfxCapVCGood) { PsychSetStructArrayDoubleElement("GLSupportsPrecisionColors", 0, 1, s); } else PsychSetStructArrayDoubleElement("GLSupportsPrecisionColors", 0, 0, s); if (windowRecord->gfxcaps & kPsychGfxCapFP32Shading) { PsychSetStructArrayDoubleElement("GLSupportsFP32Shading", 0, 1, s); } else PsychSetStructArrayDoubleElement("GLSupportsFP32Shading", 0, 0, s); // Renderer information: This comes last, and would fail if async flips // are active, because it needs PsychSetDrawingTarget, which in turn needs async // flips to be inactive: PsychSetDrawingTarget(windowRecord); PsychSetStructArrayStringElement("GLVendor", 0, (char*) glGetString(GL_VENDOR), s); PsychSetStructArrayStringElement("GLRenderer", 0, (char*) glGetString(GL_RENDERER), s); PsychSetStructArrayStringElement("GLVersion", 0, (char*) glGetString(GL_VERSION), s); } // Done. return(PsychError_none); }