Permalink
Browse files

Merge pull request #80 from Psychtoolbox-3/master

PTB BETA RELEASE "Death by a thousand paper cuts"

Release highlights:

Speak() command now supported on all operating systems, and made more flexible. Linux support by MK, MS-Windows support by Vishal Shah.

Improved correctness tests and wokarounds for graphics driver bugs on Intel gpus under Linux, but also improvements to general graphics driver sync tests. Some warning clutter removed.

Make Screen startup more artifact free on Intel gpus on Linux with triple-buffering enabled.

Make Linux Screen() compatible to apitrace utility.

Bugfixes and enhancements to Screen('Resolution') on Linux and Screen('Resolutions') on 64-Bit OSX.

Enhancements to the PsychPortAudio backed Snd() legacy sound command.

Some improvements to DKL color functions by David Brainard.
  • Loading branch information...
kleinerm committed Oct 9, 2012
2 parents cdeaee7 + d957f9f commit 759f023b86fb3632b2a7e3959d60e32c6b9df7e5
@@ -725,6 +725,9 @@ psych_bool PsychOpenOnscreenWindow(PsychScreenSettingsType *screenSettings, Psyc
printf("\n\nOpenGL-Extensions are: %s\n\n", (char*) glGetString(GL_EXTENSIONS));
}
// Activate syncing to onset of vertical retrace (VBL) for double-buffered windows:
if (numBuffers > 1) PsychOSSetVBLSyncLevel(*windowRecord, 1);
// Perform generic inquiry for interesting renderer capabilities and limitations/quirks
// and setup the proper status bits for the windowRecord:
PsychDetectAndAssignGfxCapabilities(*windowRecord);
@@ -850,9 +853,6 @@ psych_bool PsychOpenOnscreenWindow(PsychScreenSettingsType *screenSettings, Psyc
}
// Everything below this line is only for double-buffered contexts!
// Activate syncing to onset of vertical retrace (VBL) for double-buffered windows:
PsychOSSetVBLSyncLevel(*windowRecord, 1);
// Setup of initial interframe-interval by multiple methods, for comparison:
@@ -863,8 +863,8 @@ psych_bool PsychOpenOnscreenWindow(PsychScreenSettingsType *screenSettings, Psyc
}
// This is pure eye-candy: We clear both framebuffers to a background color,
// just to get rid of the junk that's in the framebuffers...
// If visual debuglevel < 4 then we clear to black background...
// just to get rid of the junk that's in the framebuffers.
// If visual debuglevel < 4 then we clear to black background.
if (visual_debuglevel >= 4) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@@ -885,27 +885,37 @@ psych_bool PsychOpenOnscreenWindow(PsychScreenSettingsType *screenSettings, Psyc
glClearColor(0,0,0,1);
}
glPixelZoom(1, -1);
glDrawBuffer(GL_BACK_LEFT);
// Draw and swapbuffers the startup screen 3 times, so everything works with single-/double-/triple-buffered framebuffer setups:
glClear(GL_COLOR_BUFFER_BIT);
if (visual_debuglevel>=4) { glRasterPos2i(logo_x, logo_y); glDrawPixels(splash_image.width, splash_image.height, splash_image.bytes_per_pixel, GL_UNSIGNED_BYTE, (void*) &splash_image.pixel_data[0]); }
PsychOSFlipWindowBuffers(*windowRecord);
glPixelZoom(1, -1);
glClear(GL_COLOR_BUFFER_BIT);
if (visual_debuglevel>=4) { glRasterPos2i(logo_x, logo_y); glDrawPixels(splash_image.width, splash_image.height, splash_image.bytes_per_pixel, GL_UNSIGNED_BYTE, (void*) &splash_image.pixel_data[0]); }
PsychOSFlipWindowBuffers(*windowRecord);
glClear(GL_COLOR_BUFFER_BIT);
if (visual_debuglevel>=4) { glRasterPos2i(logo_x, logo_y); glDrawPixels(splash_image.width, splash_image.height, splash_image.bytes_per_pixel, GL_UNSIGNED_BYTE, (void*) &splash_image.pixel_data[0]); }
PsychOSFlipWindowBuffers(*windowRecord);
// We do it twice to clear possible stereo-contexts as well...
// We do it again for right backbuffer to clear possible stereo-contexts as well...
if ((*windowRecord)->stereomode==kPsychOpenGLStereo) {
glDrawBuffer(GL_BACK_RIGHT);
glClear(GL_COLOR_BUFFER_BIT);
if (visual_debuglevel>=4) { glRasterPos2i(logo_x, logo_y); glDrawPixels(splash_image.width, splash_image.height, splash_image.bytes_per_pixel, GL_UNSIGNED_BYTE, (void*) &splash_image.pixel_data[0]); }
PsychOSFlipWindowBuffers(*windowRecord);
glClear(GL_COLOR_BUFFER_BIT);
if (visual_debuglevel>=4) { glRasterPos2i(logo_x, logo_y); glDrawPixels(splash_image.width, splash_image.height, splash_image.bytes_per_pixel, GL_UNSIGNED_BYTE, (void*) &splash_image.pixel_data[0]); }
PsychOSFlipWindowBuffers(*windowRecord);
glDrawBuffer(GL_BACK_RIGHT);
glClear(GL_COLOR_BUFFER_BIT);
if (visual_debuglevel>=4) { glRasterPos2i(logo_x, logo_y); glDrawPixels(splash_image.width, splash_image.height, splash_image.bytes_per_pixel, GL_UNSIGNED_BYTE, (void*) &splash_image.pixel_data[0]); }
PsychOSFlipWindowBuffers(*windowRecord);
glClear(GL_COLOR_BUFFER_BIT);
if (visual_debuglevel>=4) { glRasterPos2i(logo_x, logo_y); glDrawPixels(splash_image.width, splash_image.height, splash_image.bytes_per_pixel, GL_UNSIGNED_BYTE, (void*) &splash_image.pixel_data[0]); }
PsychOSFlipWindowBuffers(*windowRecord);
glClear(GL_COLOR_BUFFER_BIT);
if (visual_debuglevel>=4) { glRasterPos2i(logo_x, logo_y); glDrawPixels(splash_image.width, splash_image.height, splash_image.bytes_per_pixel, GL_UNSIGNED_BYTE, (void*) &splash_image.pixel_data[0]); }
PsychOSFlipWindowBuffers(*windowRecord);
}
glPixelZoom(1, 1);
glPixelZoom(1, 1);
glDrawBuffer(GL_BACK);
// Release dynamically allocated splash image buffer:
@@ -966,12 +976,19 @@ psych_bool PsychOpenOnscreenWindow(PsychScreenSettingsType *screenSettings, Psyc
sync_trouble = true;
if(PsychPrefStateGet_Verbosity()>1) {
if (i >=-1) {
printf("\nWARNING: Querying rasterbeam-position doesn't work on your setup! (Returns a constant value %i)\n", i);
printf("WARNING: This can happen if Psychtoolbox gets the mapping of connected displays to graphics card\n");
printf("WARNING: outputs wrong. See 'help DisplayOutputMappings' for tips on how to resolve this problem.\n\n");
printf("\nPTB-WARNING: Querying rasterbeam-position doesn't work on your setup! (Returns a constant value %i)\n", i);
printf("PTB-WARNING: This can happen if Psychtoolbox gets the mapping of connected displays to graphics card\n");
printf("PTB-WARNING: outputs wrong. See 'help DisplayOutputMappings' for tips on how to resolve this problem.\n");
}
if (i < -1) printf("\nWARNING: Querying rasterbeam-position doesn't work on your setup! (Returns a negative value %i)\n", i);
if (i < -1) printf("\nPTB-WARNING: Querying rasterbeam-position doesn't work on your setup! (Returns a negative value %i)\n", i);
if ((PsychPrefStateGet_VBLTimestampingMode() == 4) && !((*windowRecord)->gfxcaps & kPsychOpenMLDefective)) {
printf("PTB-WARNING: However, this probably doesn't really matter on your setup for most purposes, as i can use OpenML\n");
printf("PTB-WARNING: timestamping instead, which is even more precise. Only few applications need beampos queries in this case.\n");
}
printf("\n");
}
}
else {
@@ -1033,12 +1050,12 @@ psych_bool PsychOpenOnscreenWindow(PsychScreenSettingsType *screenSettings, Psyc
if ((VBL_Endline < (int) vbl_startline - 1) || ((VBL_Endline > vbl_startline * 1.25) && ((VBL_Endline > vbl_startline * 2.25) || (VBL_Endline < vbl_startline * 2.0)))) {
// Completely bogus VBL_Endline detected! Warn the user and mark VBL_Endline
// as invalid so it doesn't get used anywhere:
if(!sync_trouble && PsychPrefStateGet_Verbosity()>1) {
printf("\nPTB-WARNING: Couldn't determine end-line of vertical blanking interval for your display! Trouble with beamposition queries?!?\n");
printf("PTB-WARNING: Detected end-line is %i, which is either lower or more than 25%% higher than vbl startline %i --> Out of sane range!\n", VBL_Endline, vbl_startline);
}
sync_trouble = true;
ifi_beamestimate = 0;
if(PsychPrefStateGet_Verbosity()>1) {
printf("\nWARNING: Couldn't determine end-line of vertical blanking interval for your display! Trouble with beamposition queries?!?\n");
printf("\nWARNING: Detected end-line is %i, which is either lower or more than 25%% higher than vbl startline %i --> Out of sane range!\n", VBL_Endline, vbl_startline);
}
}
else {
// Check if VBL_Endline is greater than 2 * vbl_startline. This would indicate the backend is running in
@@ -1443,15 +1460,18 @@ psych_bool PsychOpenOnscreenWindow(PsychScreenSettingsType *screenSettings, Psyc
// This would indicate that the beam position is reported from a different display device
// than the one we are VBL syncing to. -> Trouble!
if ((ifi_beamestimate < 0.8 * ifi_estimate || ifi_beamestimate > 1.2 * ifi_estimate) && (ifi_beamestimate > 0)) {
if(PsychPrefStateGet_Verbosity()>1)
printf("\nWARNING: Mismatch between measured monitor refresh intervals! This indicates problems with rasterbeam position queries.\n");
if(!sync_trouble && PsychPrefStateGet_Verbosity()>1)
printf("\nWARNING: Mismatch between measured monitor refresh intervals! This indicates problems with rasterbeam position queries.\n");
sync_trouble = true;
}
if (sync_trouble) {
// Fail-Safe: Mark VBL-Endline as invalid, so a couple of mechanisms get disabled in Screen('Flip') aka PsychFlipWindowBuffers().
VBL_Endline = -1;
if(PsychPrefStateGet_Verbosity()>1){
// Only warn user and flash the warning triangle if we can't use OpenML timestamping because it is disabled or broken.
// If OpenML timestamping is available then beamposition queries are not needed anyway, so no reason to make a big fuss...
if((PsychPrefStateGet_Verbosity() > 1) && ((PsychPrefStateGet_VBLTimestampingMode() != 4) || ((*windowRecord)->gfxcaps & kPsychOpenMLDefective))){
printf("\n\n");
printf("----- ! PTB - WARNING: SYNCHRONIZATION TROUBLE ! ----\n\n");
printf("One or more internal checks (see Warnings above) indicate that\n");
@@ -1883,7 +1903,7 @@ void* PsychFlipperThreadMain(void* windowRecordToCast)
// Get a handle to our info structs: These pointers must not be NULL!!!
PsychWindowRecordType* windowRecord = (PsychWindowRecordType*) windowRecordToCast;
PsychFlipInfoStruct* flipRequest = windowRecord->flipInfo;
psych_bool useOpenML = (windowRecord->gfxcaps & kPsychGfxCapSupportsOpenML) ? TRUE : FALSE;
psych_bool useOpenML = (windowRecord->gfxcaps & kPsychOpenMLDefective) ? FALSE : TRUE;
// Try to lock, block until available if not available:
if ((rc=PsychLockMutex(&(flipRequest->performFlipLock)))) {
@@ -3906,7 +3926,7 @@ double PsychGetMonitorRefreshInterval(PsychWindowRecordType *windowRecord, int*
int fallthroughcount=0;
double* samples = NULL;
int maxlogsamples = 0;
psych_bool useOpenML = ((PsychPrefStateGet_VBLTimestampingMode() == 4) && (windowRecord->gfxcaps & kPsychGfxCapSupportsOpenML));
psych_bool useOpenML = ((PsychPrefStateGet_VBLTimestampingMode() == 4) && !(windowRecord->gfxcaps & kPsychOpenMLDefective));
// Child protection: We only work on double-buffered onscreen-windows...
if (windowRecord->windowType != kPsychDoubleBufferOnscreen) {
@@ -4161,12 +4181,15 @@ void PsychVisualBell(PsychWindowRecordType *windowRecord, double duration, int b
w = (float) PsychGetWidthFromRect(windowRecord->rect);
h = (float) PsychGetHeightFromRect(windowRecord->rect);
// Clear out both buffers so it doesn't lool like junk:
// Clear out all potentially 3 buffers so it doesn't look like junk,
// even if on a triple-buffered graphics system:
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
PsychOSFlipWindowBuffers(windowRecord);
glClear(GL_COLOR_BUFFER_BIT);
PsychOSFlipWindowBuffers(windowRecord);
glClear(GL_COLOR_BUFFER_BIT);
PsychOSFlipWindowBuffers(windowRecord);
if (belltype==3) {
// Test-Sheet mode: Need smaller warning triangle...
@@ -98,7 +98,7 @@ PsychError SCREENGetFlipInfo(void)
// Type 3: Fetch logged swap completion events:
if (infoType == 3) {
PsychOSSwapCompletionLogging(windowRecord, 2, 1);
PsychOSSwapCompletionLogging(windowRecord, 3, 1);
return(PsychError_none);
}
#else
@@ -466,7 +466,7 @@ PsychError SCREENOpenWindow(void)
PsychSetupClientRect(windowRecord);
// Initialize internal image processing pipeline if requested:
PsychInitializeImagingPipeline(windowRecord, imagingmode, multiSample);
if (numWindowBuffers > 0) PsychInitializeImagingPipeline(windowRecord, imagingmode, multiSample);
// On OS-X, if we are in quad-buffered frame sequential stereo mode, we automatically generate
// blue-line-sync style sync lines for use with stereo shutter glasses. We don't do this
@@ -501,9 +501,11 @@ PsychError SCREENOpenWindow(void)
// the user selected background color instead of staying at the blue screen or
// logo display until the Matlab script first calls 'Flip'.
if (((PsychPrefStateGet_VisualDebugLevel()>=4) || (windowRecord->stereomode > 0)) && numWindowBuffers>=2) {
// Do immediate bufferswap by an internal call to Screen('Flip'). This will also
// Do three immediate bufferswaps by an internal call to Screen('Flip'). This will also
// take care of clearing the backbuffer in preparation of first userspace drawing
// commands and such...
// commands and such. We need up-to 3 calls to clear triple-buffered setups from framebuffer junk.
PsychFlipWindowBuffers(windowRecord, 0, 0, 0, 0, &dummy1, &dummy2, &dummy3, &dummy4);
PsychFlipWindowBuffers(windowRecord, 0, 0, 0, 0, &dummy1, &dummy2, &dummy3, &dummy4);
PsychFlipWindowBuffers(windowRecord, 0, 0, 0, 0, &dummy1, &dummy2, &dummy3, &dummy4);
// Display now shows background color, so user knows that PTB's 'OpenWindow'
// procedure is successfully finished.
@@ -338,6 +338,8 @@ typedef struct _PsychWindowRecordType_{
psych_int64 reference_sbc; // SBC reference swapbuffers count from OpenML. (Optional)
psych_int64 target_sbc; // Target SBC value for next glXWaitForSbcOML() call from OpenML. (Optional)
psych_int64 lastSwaptarget_msc; // Target MSC value for which most recent swap was scheduled by DRM/DRI2 from OpenML. (Optional)
int swapevents_enabled; // State of swap events: 0 = Disabled/Unsupported, 1 = Enabled for use by usercode, 2 = Enabled for use by us.
int swapcompletiontype; // Type of last completed swap: 0 = Unknown, 1 = Pageflip, 2 = Exchange, 3 = Copy.
// Pointers to temporary arrays with gamma tables to upload to the gfx-card at next Screen('Flip'):
// They default to NULL and get possibly set in Screen('LoadNormalizedGammaTable'):
@@ -726,7 +726,7 @@ static void GetRandRScreenConfig(CGDirectDisplayID dpy, int idx)
// Select screen configuration notify events to get delivered to us:
Window root = RootWindow(dpy, displayX11Screens[idx]);
XRRSelectInput(dpy, root, xr_event + RRScreenChangeNotify);
XRRSelectInput(dpy, root, RRScreenChangeNotifyMask);
// Fetch current screen configuration info for this screen and display:
XRRScreenResources* res = XRRGetScreenResourcesCurrent(dpy, root);
@@ -1299,12 +1299,20 @@ int PsychGetAllSupportedScreenSettings(int screenNumber, int outputId, long** wi
*/
psych_bool PsychGetCGModeFromVideoSetting(CFDictionaryRef *cgMode, PsychScreenSettingsType *setting)
{
int i, j, nsizes, nrates;
int i, j, nsizes = 0, nrates = 0;
// No op on system without RandR:
if (!has_xrandr_1_2) {
// Dummy assignment:
*cgMode = 1;
*cgMode = -1;
// Also cannot restore display settings at Window / Screen / Runtime close time, so disable it:
displayOriginalCGSettingsValid[setting->screenNumber] = FALSE;
// Some info for the reader:
if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-INFO: Getting or setting display video modes unsupported on this graphics driver due to lack of RandR v1.2 support.\n");
// Return success in good faith that its ok.
return(TRUE);
}
@@ -1314,21 +1322,28 @@ psych_bool PsychGetCGModeFromVideoSetting(CFDictionaryRef *cgMode, PsychScreenSe
int height = (int) PsychGetHeightFromRect(setting->rect);
int fps = (int) (setting->nominalFrameRate + 0.5);
if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-INFO: Trying to validate/find closest video mode for requested spec: width = %i x height = %i, rate %i Hz.\n", width, height, fps);
// Find matching mode:
int size_index = -1;
XRRScreenSize *scs = XRRSizes(dpy, PsychGetXScreenIdForScreen(setting->screenNumber), &nsizes);
for (i = 0; i < nsizes; i++) {
if ((width == scs[i].width) && (height == scs[i].height)) {
short *rates = XRRRates(dpy, PsychGetXScreenIdForScreen(setting->screenNumber), i, &nrates);
for (j = 0; j < nrates; j++) {
if (rates[j] == (short) fps) {
// Our requested size x fps combo is supported:
size_index = i;
}
}
}
if (PsychPrefStateGet_Verbosity() > 3) printf("PTB-INFO: Testing against mode of resolution w x h = %i x %i with refresh rates: ", scs[i].width, scs[i].height);
if ((width == scs[i].width) && (height == scs[i].height)) {
short *rates = XRRRates(dpy, PsychGetXScreenIdForScreen(setting->screenNumber), i, &nrates);
for (j = 0; j < nrates; j++) {
if (PsychPrefStateGet_Verbosity() > 3) printf("%i ", (int) rates[j]);
if (rates[j] == (short) fps) {
// Our requested size x fps combo is supported:
size_index = i;
if (PsychPrefStateGet_Verbosity() > 3) printf("--> Got it! Mode id %i. ", size_index);
}
}
}
if (PsychPrefStateGet_Verbosity() > 3) printf("\n");
}
if ((nsizes == 0 || nrates == 0) && (PsychPrefStateGet_Verbosity() > 1)) printf("PTB-WARNING: Getting or setting display video modes unsupported on this graphics driver despite advertised RandR v1.2 support.\n");
// Found valid settings?
if (size_index == -1) return(FALSE);
@@ -1819,9 +1834,9 @@ psych_bool PsychSetScreenSettings(psych_bool cacheSettings, PsychScreenSettingsT
//Find core graphics video settings which correspond to settings as specified withing by an abstracted psychsettings structure.
isValid = PsychGetCGModeFromVideoSetting(&cgMode, settings);
if(!isValid){
if (!isValid || cgMode < 0){
// This is an internal error because the caller is expected to check first.
PsychErrorExitMsg(PsychError_internal, "Attempt to set invalid video settings");
PsychErrorExitMsg(PsychError_user, "Attempt to set invalid video settings or function unsupported with this graphics-driver.");
}
// Change the display mode.
@@ -1889,9 +1904,9 @@ psych_bool PsychRestoreScreenSettings(int screenNumber)
//Find core graphics video settings which correspond to settings as specified withing by an abstracted psychsettings structure.
isValid = PsychGetCGModeFromVideoSetting(&cgMode, settings);
if(!isValid) {
// This is an internal error because the caller is expected to check first.
PsychErrorExitMsg(PsychError_internal, "Attempt to restore now invalid video settings");
if (!isValid || cgMode < 0){
// This is an internal error because the caller is expected to check first.
PsychErrorExitMsg(PsychError_user, "Attempt to restore invalid video settings or function unsupported with this graphics-driver.");
}
//Change the display mode.
Oops, something went wrong.

0 comments on commit 759f023

Please sign in to comment.