PsychError SCREENTexturizeOffscreenWindows(void) 
{
	PsychWindowRecordType	**windowRecordArray;
	int						i, numWindows; 

    
    //all subfunctions should have these two lines.  
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
	
	//check for superfluous or missing arguments
	PsychErrorExit(PsychCapNumInputArgs(0));   	
    PsychErrorExit(PsychRequireNumInputArgs(0)); 	

   	PsychCreateVolatileWindowRecordPointerList(&numWindows, &windowRecordArray);
	for(i=0;i<numWindows;i++){
			if(PsychIsOffscreenWindow(windowRecordArray[i])){
				PsychUpdateTargetWindowFromTargetDisplay(windowRecordArray[i]);
				PsychAllocateTexture(windowRecordArray[i]);
				PsychBindTexture(windowRecordArray[i]);
				PsychUpdateTexture(windowRecordArray[i]);
			}
	}
	PsychDestroyVolatileWindowRecordPointerList(windowRecordArray);

	
    return(PsychError_none);

}
PsychError SCREENGetCapturedImage(void) 
{
    PsychWindowRecordType		*windowRecord;
    PsychWindowRecordType		*textureRecord;
    PsychRectType				rect;
    double                      summed_intensity;
    int                         capturehandle = -1;
    int                         waitForImage = TRUE;
    int                         specialmode = 0;
	double						timeout, tnow;
    double                      presentation_timestamp = 0;
    int							rc=-1;
    double						targetmemptr = 0;
	double*						tsummed = NULL;
	psych_uint8					*targetmatrixptr = NULL;
	static rawcapimgdata		rawCaptureBuffer = {0, 0, 0, NULL};

    // All sub functions should have these two lines
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()) {PsychGiveHelp(); return(PsychError_none);};
    
    PsychErrorExit(PsychCapNumInputArgs(6));            // Max. 6 input args.
    PsychErrorExit(PsychRequireNumInputArgs(2));        // Min. 2 input args required.
    PsychErrorExit(PsychCapNumOutputArgs(4));           // Max. 4 output args.
    
    // Get the window record from the window record argument and get info from the window record
    PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord);
    // Only onscreen windows allowed:
    if(!PsychIsOnscreenWindow(windowRecord) && !PsychIsOffscreenWindow(windowRecord)) {
        PsychErrorExitMsg(PsychError_user, "GetCapturedImage called on something else than an onscreen window or offscreen window.");
    }
    
    // Get the handle:
    PsychCopyInIntegerArg(2, TRUE, &capturehandle);
    if (capturehandle==-1) {
        PsychErrorExitMsg(PsychError_user, "GetCapturedImage called without valid handle to a capture object.");
    }

    // Get the 'waitForImage' flag: If waitForImage == true == 1, we'll do a blocking wait for
    // arrival of a new image. Otherwise we will return with a 0-Handle if there
    // isn't any new image available.
    PsychCopyInIntegerArg(3, FALSE, &waitForImage);

	// Special case waitForImage == 4? This would ask to call into the capture driver, but
	// not wait for any image to arrive and not return any information. This is only useful
	// on OS/X and Windows when using the capture engine for video recording to harddisk. In
	// that case we are not interested at all in the captured live video, we just want it to
	// get written to harddisk in the background. To keep the video encoder going, we need to
	// call its SGIdle() routine and waitForImage==4 does just that, call SGIdle().
	if (waitForImage == 4) {
		// Perform the null-call to the capture engine, ie a SGIdle() on OS/X and Windows:
		PsychGetTextureFromCapture(windowRecord, capturehandle, 4, 0.0, NULL, NULL, NULL, NULL);
		// Done. Nothing to return...
		return(PsychError_none);
	}
	
    // Get the optional textureRecord for the optional texture handle. If the calling script
    // provides the texture handle of an existing Psychtoolbox texture that has a matching
    // format, then that texture is recycled by overwriting its previous content with the
    // image data from the new captured image. This can save some overhead for texture destruction
    // and recreation. While this is probably not noticeable on mid- to high-end gfx cards with
    // rectangle texture support, it can provide a significant speedup on low-end gfx cards with
    // only power-of-two texture support.
    textureRecord = NULL;
    if ((PsychGetNumInputArgs()>=4) && PsychIsWindowIndexArg(4)) PsychAllocInWindowRecordArg(4, FALSE, &textureRecord);
    
    // Get the optional specialmode flag:
    PsychCopyInIntegerArg(5, FALSE, &specialmode);

	// Set a 10 second maximum timeout for waiting for new frames:
	PsychGetAdjustedPrecisionTimerSeconds(&timeout);
	timeout+=10;

    while (rc==-1) {		
      // We pass a checkForImage value of 2 if waitForImage>0. This way we can signal if we are in polling or blocking mode.
      // With the libdc1394 engine this allows to do a real blocking wait in the driver -- much more efficient than the spin-waiting approach!
      rc = PsychGetTextureFromCapture(windowRecord, capturehandle, ((waitForImage>0 && waitForImage<3) ? 2 : 1), 0.0, NULL, &presentation_timestamp, NULL, &rawCaptureBuffer);
		PsychGetAdjustedPrecisionTimerSeconds(&tnow);
        if (rc==-2 || (tnow > timeout)) {
            // No image available and there won't be any in the future, because capture has been stopped or there is a timeout:
			if (tnow > timeout) printf("PTB-WARNING: In Screen('GetCapturedImage') timed out waiting for a new frame. No video data in over 10 seconds!\n");

            // No new texture available: Return a negative handle:
            PsychCopyOutDoubleArg(1, TRUE, -1);
            // ...and an invalid timestamp:
            PsychCopyOutDoubleArg(2, FALSE, -1);
            PsychCopyOutDoubleArg(3, FALSE, 0);
            PsychCopyOutDoubleArg(4, FALSE, 0);

            // Ready!
            return(PsychError_none);
        }
        else if (rc==-1 && (waitForImage == 0 || waitForImage == 3)) {
            // We should just poll once and no new texture available: Return a null-handle:
            PsychCopyOutDoubleArg(1, TRUE, 0);
            // ...and the current timestamp:
            PsychCopyOutDoubleArg(2, FALSE, presentation_timestamp);
            PsychCopyOutDoubleArg(3, FALSE, 0);
            PsychCopyOutDoubleArg(4, FALSE, 0);

            // Ready!
            return(PsychError_none);
        }
        else if (rc==-1 && waitForImage != 0) {
            // No new texture available yet. Just sleep a bit and then retry...
            PsychYieldIntervalSeconds(0.002);
        }
    }

    // rc == 0 --> New image available: Go ahead...
    if (waitForImage!=2 && waitForImage!=3) {
      // Ok, we need a texture for the image. Did script provide an old one for recycling?
      if (textureRecord) {
	// Old texture provided for reuse? Some basic sanity check: Everything else is
	// up to the lower level PsychGetTextureFromCapture() routine.
        if(!PsychIsOffscreenWindow(textureRecord)) {
	  PsychErrorExitMsg(PsychError_user, "GetCapturedImage provided with something else than a texture as fourth call parameter.");
        }	
      }
      else {
        // No old texture provided: Create a new texture record:
        PsychCreateWindowRecord(&textureRecord);

        // Set mode to 'Texture':
        textureRecord->windowType=kPsychTexture;

        // We need to assign the screen number of the onscreen-window.
        textureRecord->screenNumber=windowRecord->screenNumber;

        // It defaults to a 32 bit texture for captured images. On Linux, this will be overriden,
		// if optimized formats exist for our purpose:
        textureRecord->depth=32;
		textureRecord->nrchannels = 4;

        // Create default rectangle which describes the dimensions of the image. Will be overwritten
        // later on.
        PsychMakeRect(rect, 0, 0, 10, 10);
        PsychCopyRect(textureRecord->rect, rect);
        
        // Other setup stuff:
        textureRecord->textureMemorySizeBytes= 0;
        textureRecord->textureMemory=NULL;
        
        // Assign parent window and copy its inheritable properties:
		PsychAssignParentWindow(textureRecord, windowRecord);

        // Set textureNumber to zero, which means "Not cached, do not recycle"
        // Todo: Texture recycling like in PsychMovieSupport for higher efficiency!
        textureRecord->textureNumber = 0;
      }

      // Power-of-two texture requested?
      if (specialmode & 0x01) {
		// Yes. Spec it:
		textureRecord->texturetarget = GL_TEXTURE_2D;
      }
    }
    else {
        // Just want to return summed_intensity and timestamp, not real texture...
        textureRecord = NULL;
    }

	// Default to no calculation of summed image intensity:
	tsummed = NULL;
    if ((PsychGetNumOutputArgs() > 3) && !(specialmode & 0x2)) {
        // Return sum of pixel intensities for all channels of this image: Need to
		// assign the output pointer for this to happen:
		tsummed = &summed_intensity;
	}

    // Try to fetch an image from the capture object and return it as texture:
	targetmatrixptr = NULL;
	
	// Shall we return a Matlab matrix?
	if ((PsychGetNumOutputArgs() > 3) && (specialmode & 0x2)) {
		// We shall return a matrix with raw image data. Allocate a uint8 matrix
		// of sufficient size:
		PsychAllocOutUnsignedByteMatArg(4, TRUE, rawCaptureBuffer.depth, rawCaptureBuffer.w, rawCaptureBuffer.h, &targetmatrixptr);
		tsummed = NULL;
	}
	
	// Shall we return data into preallocated memory buffer?
	if (specialmode & 0x4) {
		// Copy in memory address (which itself is encoded in a double value):
		PsychCopyInDoubleArg(6, TRUE, &targetmemptr);
		targetmatrixptr = (psych_uint8*) PsychDoubleToPtr(targetmemptr);
	}
	
	if (targetmatrixptr == NULL) {
		// Standard fetch of a texture and its timestamp:
		rc = PsychGetTextureFromCapture(windowRecord, capturehandle, 0, 0.0, textureRecord, &presentation_timestamp, tsummed, NULL);
	}
	else {
		// Fetch of a memory raw image buffer + timestamp + possibly a texture:
		rawCaptureBuffer.data = (void*) targetmatrixptr;
		rc = PsychGetTextureFromCapture(windowRecord, capturehandle, 0, 0.0, textureRecord, &presentation_timestamp, tsummed, &rawCaptureBuffer);			
	}
	
    if (tsummed) {
        // Return sum of pixel intensities for all channels of this image:
        PsychCopyOutDoubleArg(4, FALSE, summed_intensity);
    }

    // Real texture requested?
    if (textureRecord) {
        // Texture ready for consumption.

		// Assign GLSL filter-/lookup-shaders if needed: usefloatformat is always == 0 as
		// our current capture engine implementations only return 8 bpc fixed textures.
		// The 'userRequest' flag is set if specialmode flag is set to 8.
		PsychAssignHighPrecisionTextureShaders(textureRecord, windowRecord, 0, (specialmode & 8) ? 1 : 0);

        // specialmode setting 16? Disable auto-mipmap generation:
        if (specialmode & 16) textureRecord->specialflags |= kPsychDontAutoGenMipMaps;    

		// Mark it valid and return handle to userspace:
        PsychSetWindowRecordValid(textureRecord);
        PsychCopyOutDoubleArg(1, TRUE, textureRecord->windowIndex);
    }
    else {
        PsychCopyOutDoubleArg(1, TRUE, 0);
    }
    
    // Return presentation timestamp for this image:
    PsychCopyOutDoubleArg(2, FALSE, presentation_timestamp);

    // Return count of pending frames in buffers or of dropped frames:
    PsychCopyOutDoubleArg(3, FALSE, (double) rc);

    // Ready!
    return(PsychError_none);
}
PsychError SCREENOpenOffscreenWindow(void) 
{
    int						screenNumber, depth, targetScreenNumber;
    PsychRectType			rect;
    PsychColorType			color;
    PsychWindowRecordType	*exampleWindowRecord, *windowRecord, *targetWindow;
    psych_bool				wasColorSupplied;
    char*					texturePointer;
    size_t					xSize, ySize, nbytes;
    psych_bool				bigendian;
	GLubyte					*rpb;
    int						ix;
	GLenum					fboInternalFormat;
	psych_bool				needzbuffer;
	psych_bool				overridedepth = FALSE;
	int						usefloatformat = 0;
	int						specialFlags = 0;
	int						multiSample = 0;
	
    // Detect endianity (byte-order) of machine:
    ix=255;
    rpb=(GLubyte*) &ix;
    bigendian = ( *rpb == 255 ) ? FALSE : TRUE;
    ix = 0; rpb = NULL;

    //all sub functions should have these two lines
    PsychPushHelp(useString, synopsisString, seeAlsoString);
    if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

    //cap the number of inputs
    PsychErrorExit(PsychCapNumInputArgs(6));   //The maximum number of inputs
    PsychErrorExit(PsychCapNumOutputArgs(2));  //The maximum number of outputs

    //1-User supplies a window ptr 2-User supplies a screen number 3-User supplies rect and pixel size
    if(PsychIsWindowIndexArg(1)){
        PsychAllocInWindowRecordArg(1, TRUE, &exampleWindowRecord);
		// Assign normalized copy of example windows rect -- Top-Left corner is always (0,0)
		PsychNormalizeRect(exampleWindowRecord->clientrect, rect);

        // We copy depth only from exampleWindow if it is a offscreen window (=texture). Copying from
        // onscreen windows doesn't make sense, e.g. depth=16 for onscreen means RGBA8 window, but it
        // would map onto a LUMINANCE+ALPHA texture for the offscreen window! We always use 32 bit RGBA8
        // in such a case.
        depth=(PsychIsOffscreenWindow(exampleWindowRecord)) ? exampleWindowRecord->depth : 32;
		// unless it is a FBO backed onscreen window in imaging mode: Then we can use the depth from it.
		if (exampleWindowRecord->imagingMode & kPsychNeedFastBackingStore || exampleWindowRecord->imagingMode & kPsychNeedFastOffscreenWindows) depth = exampleWindowRecord->depth;
        targetScreenNumber=exampleWindowRecord->screenNumber;
        targetWindow=exampleWindowRecord;
    } else if(PsychIsScreenNumberArg(1)){
        PsychCopyInScreenNumberArg(1, TRUE, &screenNumber);
        PsychGetScreenRect(screenNumber, rect);
        depth=32; // Always use RGBA8 in this case! See above...
        targetScreenNumber=screenNumber;
        targetWindow=NULL;
    } else if(PsychIsUnaffiliatedScreenNumberArg(1)){  //that means -1 or maybe also NaN if we add that option.  
        // Default to a depth of 32 bpp:
        depth = 32;
        targetWindow = NULL;
        // Get first open onscreen window as target window:
        PsychFindScreenWindowFromScreenNumber(kPsychUnaffiliatedWindow, &targetWindow);
		if (targetWindow == NULL) PsychErrorExitMsg(PsychError_user, "Could not find any open onscreen window to act as parent for this offscreen window. Open an onscreen window first!");
		targetScreenNumber = targetWindow->screenNumber;
        PsychGetScreenRect(targetScreenNumber, rect);
    } else {
        targetScreenNumber = 0; // Make compiler happy.
        PsychErrorExit(PsychError_invalidNumdex);
    }

    if (targetWindow==NULL) {
        // Get target window of screen:
        PsychFindScreenWindowFromScreenNumber(targetScreenNumber, &targetWindow);
		if (targetWindow == NULL) PsychErrorExitMsg(PsychError_user, "Could not find any open onscreen window to act as parent for this offscreen window. Open an onscreen window first!");
		targetScreenNumber = targetWindow->screenNumber;
    }
    
    //Depth and rect argument supplied as arguments override those inherited from reference screen or window.
    //Note that PsychCopyIn* prefix means that value will not be overwritten if the arguments are not present.
    PsychCopyInRectArg(3,FALSE, rect);
    if (IsPsychRectEmpty(rect)) PsychErrorExitMsg(PsychError_user, "Invalid rect value provided: Empty rects are not allowed.");

	// Copy in optional depth: This gets overriden in many ways if imaging pipeline is on:
    if (PsychCopyInIntegerArg(4,FALSE, &depth)) overridedepth = TRUE;

    // If any of the no longer supported values 0, 1, 2 or 4 is provided, we
    // silently switch to 32 bits per pixel, which is the safest and fastest setting:
    if (depth==0 || depth==1 || depth==2 || depth==4) depth=32;

    // Final sanity check:
	if (!(targetWindow->imagingMode & kPsychNeedFastOffscreenWindows) && !(targetWindow->imagingMode & kPsychNeedFastBackingStore) && (depth==64 || depth==128)) {
      PsychErrorExitMsg(PsychError_user, "Invalid depth value provided. Must be 8 bpp, 16 bpp, 24 bpp or 32 bpp, unless you enable the imaging pipeline, which provides you with more options!");
	}
	
    if (depth!=8 && depth!=16 && depth!=24 && depth!=32 && depth!=64 && depth!=128) {
      PsychErrorExitMsg(PsychError_user, "Invalid depth value provided. Must be 8 bpp, 16 bpp, 24 bpp, 32 bpp, or if imagingmode is enabled also 64 bpp or 128 bpp!");
    }

	// If the imaging pipeline is enabled for the associated onscreen window and fast backing store, aka FBO's
	// is requested, then we only accept depths of at least 32 bit, i.e. RGBA windows. We override any lower
	// precision spec. This is because some common hardware only supports rendering to RGBA textures, not to
	// RGB, LA or Luminance textures.
	if ((targetWindow->imagingMode & kPsychNeedFastBackingStore || targetWindow->imagingMode & kPsychNeedFastOffscreenWindows) && (depth < 32)) depth = 32;

    // Find the color for the window background.  
    wasColorSupplied=PsychCopyInColorArg(kPsychUseDefaultArgPosition, FALSE, &color);
	
	// If none provided, use a proper white-value for this window:
    if(!wasColorSupplied) PsychLoadColorStruct(&color, kPsychIndexColor, PsychGetWhiteValueFromWindow(targetWindow));  

    // Get the optional specialmode flag:
    PsychCopyInIntegerArg(5, FALSE, &specialFlags);

    // OpenGL-ES only supports GL_TEXTURE_2D targets, so enforce these via flags setting 1:
    if (PsychIsGLES(targetWindow)) specialFlags |= 1;

	// This command converts whatever color we got into RGBA format:
    PsychCoerceColorMode(&color);

    // printf("R=%i G=%i B=%i A=%i I=%i", color.value.rgba.r, color.value.rgba.g,color.value.rgba.b,color.value.rgba.a,color.value.index); 
    // First allocate the offscreen window record to store stuff into. If we exit with an error PsychErrorExit() should
    // call PsychPurgeInvalidWindows which will clean up the window record. 
    PsychCreateWindowRecord(&windowRecord);  // This also fills the window index field.

    // This offscreen window is implemented as a Psychtoolbox texture:
    windowRecord->windowType=kPsychTexture;

    // We need to assign the screen number of the onscreen-window, so PsychCreateTexture()
    // can query the size of the screen/onscreen-window...
    windowRecord->screenNumber = targetScreenNumber;

    // Assign the computed depth:
    windowRecord->depth=depth;

	// Default number of channels:
	windowRecord->nrchannels=depth / 8;

    // Assign the computed rect, but normalize it to start with top-left at (0,0):
    PsychNormalizeRect(rect, windowRecord->rect);

    // Client rect of an offscreen window is always == rect of it:
    PsychCopyRect(windowRecord->clientrect, windowRecord->rect);
    
	// Until here no OpenGL commands executed. Now we need a valid context: Set targetWindow
	// as drawing target. This will perform neccessary context-switch and all backbuffer
	// backup/restore/whatever operations to make sure we can do what we want without
	// possibly screwing any offscreen windows and bindings:
	if (PsychIsOnscreenWindow(targetWindow) || PsychIsOffscreenWindow(targetWindow)) {
		// This is a possible on-/offscreen drawingtarget:
		PsychSetDrawingTarget(targetWindow);
	}
	else {
		// This must be a proxy-window object: Can't transition to it!
		
		// But we can safe-reset the current drawingtarget...
		PsychSetDrawingTarget((PsychWindowRecordType*) 0x1);
		
		// ...and then switch to the OpenGL context of the 'targetWindow' proxy object:
		PsychSetGLContext(targetWindow);

		// Ok, framebuffer and bindings are safe and disabled, context is set. We
		// should be safe to continue with the proxy...
	}
	
	// From here on we have a defined context and state. We can detach the drawing target whenever
	// we want, as everything is backed up somewhere for later reinit.
	
	// Create offscreen window either new style as FBO, or old style as texture:
	if ((targetWindow->imagingMode & kPsychNeedFastBackingStore) || (targetWindow->imagingMode & kPsychNeedFastOffscreenWindows)) {
		// Imaging mode for this window enabled: Use new way of creating the offscreen window:
		
		// We safely unbind any FBO bindings and drawingtargets:
		PsychSetDrawingTarget((PsychWindowRecordType*) 0x1);
		
		// Overriden for imagingmode: There we always have 4 channels...
		windowRecord->nrchannels=4;

		// Start off with standard 8 bpc fixed point:
		fboInternalFormat = GL_RGBA8; windowRecord->depth=32; usefloatformat = 0;
		
		// Need 16 bpc fixed point precision?
		if (targetWindow->imagingMode & kPsychNeed16BPCFixed) {
			fboInternalFormat = (targetWindow->gfxcaps & kPsychGfxCapSNTex16) ? GL_RGBA16_SNORM : GL_RGBA16;
			windowRecord->depth=64;
			usefloatformat = 0;
		}
		
		// Need 16 bpc floating point precision?
		if (targetWindow->imagingMode & kPsychNeed16BPCFloat) { fboInternalFormat = GL_RGBA_FLOAT16_APPLE; windowRecord->depth=64; usefloatformat = 1; }
		
		// Need 32 bpc floating point precision?
		if (targetWindow->imagingMode & kPsychNeed32BPCFloat) { fboInternalFormat = GL_RGBA_FLOAT32_APPLE; windowRecord->depth=128; usefloatformat = 2; }
		
		// Override depth value provided?
		if (overridedepth) {
			// Manual depth specified: Override with that depth:
			switch(depth) {
				case 32:
					fboInternalFormat = GL_RGBA8; windowRecord->depth=32; usefloatformat = 0;
				break;

				case 64:
					fboInternalFormat = GL_RGBA_FLOAT16_APPLE; windowRecord->depth=64; usefloatformat = 1;
					// Need fallback for lack of float 16 support?
					if (!(targetWindow->gfxcaps & kPsychGfxCapFPTex16) && !PsychIsGLES(targetWindow)) {
						// Yes. Try 16 bit signed normalized texture instead:
						if (PsychPrefStateGet_Verbosity() > 4)
							printf("PTB-INFO:OpenOffscreenWindow: Code requested 16 bpc float precision, but this is unsupported. Trying to use 15 bit snorm precision instead.\n");
						fboInternalFormat = GL_RGBA16_SNORM; windowRecord->depth=64; usefloatformat = 0;
						if (!(targetWindow->gfxcaps & kPsychGfxCapSNTex16)) {
							printf("PTB-ERROR:OpenOffscreenWindow: Code requested 16 bpc float precision, but this is unsupported by this graphics card.\n");
							printf("PTB-ERROR:OpenOffscreenWindow: Tried to use 16 bit snorm format instead, but failed as this is unsupported as well.\n");
						}
					}
				break;

				case 128:
					fboInternalFormat = GL_RGBA_FLOAT32_APPLE; windowRecord->depth=128; usefloatformat = 2;
				break;
				
				default:
					fboInternalFormat = GL_RGBA8; windowRecord->depth=32; usefloatformat = 0;
			}			
		}
		
        // Floating point framebuffer on OpenGL-ES requested?
        if (PsychIsGLES(targetWindow) && (usefloatformat > 0)) {
            // Yes. We only support 32 bpc float framebuffers with alpha-blending. On less supportive hardware we fail:
            if (!(targetWindow->gfxcaps & kPsychGfxCapFPTex32) || !(targetWindow->gfxcaps & kPsychGfxCapFPFBO32)) {
                PsychErrorExitMsg(PsychError_user, "Sorry, the requested offscreen window color resolution of 32 bpc floating point is not supported by your graphics card. Game over.");
            }

            // Supported. Upgrade requested format to 32 bpc float, whatever it was before:
            fboInternalFormat = GL_RGBA_FLOAT32_APPLE; windowRecord->depth=128; usefloatformat = 2;
        }

		// Do we need additional depth buffer attachments?
		needzbuffer = (PsychPrefStateGet_3DGfx()>0) ? TRUE : FALSE;
		
		// Copy in optional multiSample argument: It defaults to zero, aka multisampling disabled.
		PsychCopyInIntegerArg(6, FALSE, &multiSample);
		if (multiSample < 0) PsychErrorExitMsg(PsychError_user, "Invalid negative multiSample level provided!");

		// Multisampled anti-aliasing requested?
		if (multiSample > 0) {
			// Yep. Supported by GPU?
			if (!(targetWindow->gfxcaps & kPsychGfxCapFBOMultisample)) {
				// No. We fall back to non-multisampled mode:
				multiSample = 0;
				
				// Tell user if warnings enabled:
				if (PsychPrefStateGet_Verbosity() > 1) {
					printf("PTB-WARNING: You requested stimulus anti-aliasing via multisampling by setting the multiSample parameter of Screen('OpenOffscreenWindow', ...) to a non-zero value.\n");
					printf("PTB-WARNING: You also requested use of the imaging pipeline. Unfortunately, your combination of operating system, graphics hardware and driver does not\n");
					printf("PTB-WARNING: support simultaneous use of the imaging pipeline and multisampled anti-aliasing.\n");
					printf("PTB-WARNING: Will therefore continue without anti-aliasing...\n\n");
					printf("PTB-WARNING: A driver upgrade may resolve this issue. Users of MacOS-X need at least OS/X 10.5.2 Leopard for support on recent ATI hardware.\n\n");
				}
			}
		}

		// Allocate framebuffer object for this Offscreen window:
		if (!PsychCreateFBO(&(windowRecord->fboTable[0]), fboInternalFormat, needzbuffer, (int) PsychGetWidthFromRect(rect), (int) PsychGetHeightFromRect(rect), multiSample, specialFlags)) {
			// Failed!
			PsychErrorExitMsg(PsychError_user, "Creation of Offscreen window in imagingmode failed for some reason :(");
		}

		// Assign this FBO as drawBuffer for mono channel of our Offscreen window:
		windowRecord->drawBufferFBO[0] = 0;
		windowRecord->fboCount = 1;
		
		// Assign it as texture as well:
		windowRecord->textureNumber = windowRecord->fboTable[0]->coltexid;
		windowRecord->textureMemorySizeBytes = 0;
		windowRecord->textureMemory = NULL;
		windowRecord->texturetarget = (specialFlags & 0x1) ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_EXT;
		windowRecord->surfaceSizeBytes = (size_t) (PsychGetWidthFromRect(rect) * PsychGetHeightFromRect(rect) * (windowRecord->depth / 8));

		// Set bpc for FBO backed offscreen window:
		windowRecord->bpc = (int) (windowRecord->depth / 4);

		// Initial setup done, continues below after some shared code...
	}
	else {
		// Traditional texture creation code:
		
		// Special case for alpha-channel: DBL_MAX signals maximum alpha
		// value requested. In our own code we need to manually map this to
		// the maximum uint8 alpha value of 255:
		if (color.value.rgba.a == DBL_MAX) color.value.rgba.a = 255;
		
		// Allocate the texture memory:
		// We only allocate the amount really needed for given format, aka numMatrixPlanes - Bytes per pixel.
		xSize = (size_t) PsychGetWidthFromRect(rect);
		ySize = (size_t) PsychGetHeightFromRect(rect);
		windowRecord->textureMemorySizeBytes = ((size_t) (depth/8)) * xSize * ySize;
		windowRecord->textureMemory = malloc(windowRecord->textureMemorySizeBytes);
		texturePointer=(char*) windowRecord->textureMemory;
		// printf("depth=%i xsize=%i ysize=%i mem=%i ptr=%p", depth, xSize, ySize, windowRecord->textureMemorySizeBytes, texturePointer);
		// Fill with requested background color:
		nbytes=0;
		switch (depth) {
			case 8: // Pure LUMINANCE texture:
				memset((void*) texturePointer, (int) color.value.rgba.r, windowRecord->textureMemorySizeBytes);
				break;
				
			case 16: // LUMINANCE + ALPHA
				while (nbytes < windowRecord->textureMemorySizeBytes) {
					*(texturePointer++) = (psych_uint8) color.value.rgba.r;
					*(texturePointer++) = (psych_uint8) color.value.rgba.a;
					nbytes+=2;
				}
				break;
				
			case 24: // RGB:
				while (nbytes < windowRecord->textureMemorySizeBytes) {
					*(texturePointer++) = (psych_uint8) color.value.rgba.r;
					*(texturePointer++) = (psych_uint8) color.value.rgba.g;
					*(texturePointer++) = (psych_uint8) color.value.rgba.b;
					nbytes+=3;
				}
				break;        
				
			case 32: // RGBA
				if (bigendian) {
					// Code for big-endian machines, e.g., PowerPC:
					while (nbytes < windowRecord->textureMemorySizeBytes) {
						*(texturePointer++) = (psych_uint8) color.value.rgba.a;
						*(texturePointer++) = (psych_uint8) color.value.rgba.r;
						*(texturePointer++) = (psych_uint8) color.value.rgba.g;
						*(texturePointer++) = (psych_uint8) color.value.rgba.b;
						nbytes+=4;
					}
				}
				else {
					// Code for little-endian machines, e.g., IntelPC, IntelMAC, aka Pentium.
					while (nbytes < windowRecord->textureMemorySizeBytes) {
						*(texturePointer++) = (psych_uint8) color.value.rgba.b;
						*(texturePointer++) = (psych_uint8) color.value.rgba.g;
						*(texturePointer++) = (psych_uint8) color.value.rgba.r;
						*(texturePointer++) = (psych_uint8) color.value.rgba.a;
						nbytes+=4;
					}
				}
				break;
		}
	}
	
	// Shared setup code for FBO vs. non-FBO Offscreen windows:
	
	// Assign parent window and copy its inheritable properties:
	PsychAssignParentWindow(windowRecord, targetWindow);
	
    // Texture orientation is type 2 aka upright, non-transposed aka Offscreen window:
    windowRecord->textureOrientation = 2;
    
	if ((windowRecord->imagingMode & kPsychNeedFastBackingStore) || (windowRecord->imagingMode & kPsychNeedFastOffscreenWindows)) {
		// Last step for FBO backed Offscreen window: Clear it to its background color:
		PsychSetDrawingTarget(windowRecord);

		// Set default draw shader:
		PsychSetShader(windowRecord, -1);
	
		// Set background fill color:
		PsychSetGLColor(&color, windowRecord);

		// Setup alpha-blending:
		PsychUpdateAlphaBlendingFactorLazily(windowRecord);

		// Fullscreen fill of a non-onscreen window:
		PsychGLRect(windowRecord->rect);

		// Multisampling requested? If so, we need to enable it:
		if (multiSample > 0) {
			glEnable(GL_MULTISAMPLE);
			while (glGetError() != GL_NO_ERROR);
		}
		
		// Ready. Unbind it.
		PsychSetDrawingTarget(NULL);		
	}
	else {
		// Old-style setup for non-FBO Offscreen windows:
        
        // Special texture format?
		if (specialFlags & 0x1) windowRecord->texturetarget = GL_TEXTURE_2D;
        
		// Let's create and bind a new texture object and fill it with our new texture data.
		PsychCreateTexture(windowRecord);
    }

	// Assign GLSL filter-/lookup-shaders if needed:
	PsychAssignHighPrecisionTextureShaders(windowRecord, targetWindow, usefloatformat, (specialFlags & 2) ? 1 : 0);
	
    // specialFlags setting 8? Disable auto-mipmap generation:
    if (specialFlags & 0x8) windowRecord->specialflags |= kPsychDontAutoGenMipMaps;    

    // A specialFlags setting of 32? Protect texture against deletion via Screen('Close') without providing a explicit handle:
    if (specialFlags & 32) windowRecord->specialflags |= kPsychDontDeleteOnClose;    

    // Window ready. Mark it valid and return handle to userspace:
    PsychSetWindowRecordValid(windowRecord);
    
    //Return the window index and the rect argument.
    PsychCopyOutDoubleArg(1, FALSE, windowRecord->windowIndex);
    PsychCopyOutRectArg(2, FALSE, rect);

    // Ready.
    return(PsychError_none);
}
PsychError SCREENCopyWindow(void) 
{
	PsychRectType			sourceRect, targetRect, targetRectInverted;
	PsychWindowRecordType	*sourceWin, *targetWin;
	GLdouble				sourceVertex[2], targetVertex[2]; 
	double					t1;
	double					sourceRectWidth, sourceRectHeight;
	GLuint					srcFBO, dstFBO;
	GLenum					glerr;
	
	//all sub functions should have these two lines
	PsychPushHelp(useString, synopsisString, seeAlsoString);
	if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

	//cap the number of inputs
	PsychErrorExit(PsychCapNumInputArgs(5));   //The maximum number of inputs
	PsychErrorExit(PsychCapNumOutputArgs(0));  //The maximum number of outputs
        
	//get parameters for the source window:
	PsychAllocInWindowRecordArg(1, TRUE, &sourceWin);
	PsychCopyRect(sourceRect, sourceWin->rect);

	// Special case for stereo: Only half the real window width:
	PsychMakeRect(&sourceRect, sourceWin->rect[kPsychLeft], sourceWin->rect[kPsychTop],
				  sourceWin->rect[kPsychLeft] + PsychGetWidthFromRect(sourceWin->rect)/((sourceWin->specialflags & kPsychHalfWidthWindow) ? 2 : 1),
				  sourceWin->rect[kPsychTop] + PsychGetHeightFromRect(sourceWin->rect)/((sourceWin->specialflags & kPsychHalfHeightWindow) ? 2 : 1));
	
	PsychCopyInRectArg(3, FALSE, sourceRect);
	if (IsPsychRectEmpty(sourceRect)) return(PsychError_none);

	//get paramters for the target window:
	PsychAllocInWindowRecordArg(2, TRUE, &targetWin);

	// By default, the targetRect is equal to the sourceRect, but centered in
	// the target window.
	PsychCopyRect(targetRect, targetWin->rect);

	// Special case for stereo: Only half the real window width:
	PsychMakeRect(&targetRect, targetWin->rect[kPsychLeft], targetWin->rect[kPsychTop],
				  targetWin->rect[kPsychLeft] + PsychGetWidthFromRect(targetWin->rect)/((targetWin->specialflags & kPsychHalfWidthWindow) ? 2 : 1),
				  targetWin->rect[kPsychTop] + PsychGetHeightFromRect(targetWin->rect)/((targetWin->specialflags & kPsychHalfHeightWindow) ? 2 : 1));

	PsychCopyInRectArg(4, FALSE, targetRect);
	if (IsPsychRectEmpty(targetRect)) return(PsychError_none);

	if (0) {
		printf("SourceRect: %f %f %f %f  ---> TargetRect: %f %f %f %f\n", sourceRect[0], sourceRect[1],
             sourceRect[2], sourceRect[3], targetRect[0], targetRect[1],targetRect[2],targetRect[3]);
	}

	// Validate rectangles:
	if (!ValidatePsychRect(sourceRect) || sourceRect[kPsychLeft]<sourceWin->rect[kPsychLeft] ||
		sourceRect[kPsychTop]<sourceWin->rect[kPsychTop] || sourceRect[kPsychRight]>sourceWin->rect[kPsychRight] ||
		sourceRect[kPsychBottom]>sourceWin->rect[kPsychBottom]) {
		PsychErrorExitMsg(PsychError_user, "Invalid source rectangle specified - (Partially) outside of source window.");
	}
	
	if (!ValidatePsychRect(targetRect) || targetRect[kPsychLeft]<targetWin->rect[kPsychLeft] ||
		targetRect[kPsychTop]<targetWin->rect[kPsychTop] || targetRect[kPsychRight]>targetWin->rect[kPsychRight] ||
		targetRect[kPsychBottom]>targetWin->rect[kPsychBottom]) {
		PsychErrorExitMsg(PsychError_user, "Invalid target rectangle specified - (Partially) outside of target window.");
	}
	
	if (!(PsychPrefStateGet_ConserveVRAM() & kPsychAvoidCPUGPUSync)) PsychTestForGLErrors();

	// Does this GL implementation support the EXT_framebuffer_blit extension for fast blitting between
	// framebuffers? And is the imaging pipeline active? And is the kPsychAvoidFramebufferBlitIfPossible not set?
	if ((sourceWin->gfxcaps & kPsychGfxCapFBOBlit) && (targetWin->gfxcaps & kPsychGfxCapFBOBlit) &&
		(sourceWin->imagingMode > 0) && (targetWin->imagingMode > 0) && !(PsychPrefStateGet_ConserveVRAM() & kPsychAvoidFramebufferBlitIfPossible)) {
		// Yes :-) -- This simplifies the CopyWindow implementation to a simple framebuffer blit op,
		// regardless what the source- or destination is:
		
		// Set each windows framebuffer as a drawingtarget once: This is just to make sure all of them
		// have proper FBO's attached:
		PsychSetDrawingTarget(sourceWin);
		PsychSetDrawingTarget(targetWin);
		
		// Soft-Reset drawing target - Detach anything bound or setup:
		PsychSetDrawingTarget(0x1);
		
		// Find source framebuffer:
		if (sourceWin->fboCount == 0) {
			// No FBO's attached to sourceWin: Must be a system framebuffer, e.g., if imagingMode == kPsychNeedFastOffscreenWindows and
			// this is the onscreen window system framebuffer. Assign system framebuffer handle:
			srcFBO = 0;
		}
		else {
			// FBO's attached: Want drawBufferFBO 0 or 1 - 1 for right eye view in stereomode, 0 for
			// everything else: left eye view, monoscopic buffer, offscreen windows / textures:
			if ((sourceWin->stereomode > 0) && (sourceWin->stereodrawbuffer == 1)) {
				// We are in stereo mode and want to access the right-eye channel. Bind FBO-1
				srcFBO = sourceWin->fboTable[sourceWin->drawBufferFBO[1]]->fboid;
			}
			else {
				srcFBO = sourceWin->fboTable[sourceWin->drawBufferFBO[0]]->fboid;
			}
		}

		// Find target framebuffer:
		if (targetWin->fboCount == 0) {
			// No FBO's attached to targetWin: Must be a system framebuffer, e.g., if imagingMode == kPsychNeedFastOffscreenWindows and
			// this is the onscreen window system framebuffer. Assign system framebuffer handle:
			dstFBO = 0;
		}
		else {
			// FBO's attached: Want drawBufferFBO 0 or 1 - 1 for right eye view in stereomode, 0 for
			// everything else: left eye view, monoscopic buffer, offscreen windows / textures:
			if ((targetWin->stereomode > 0) && (targetWin->stereodrawbuffer == 1)) {
				// We are in stereo mode and want to access the right-eye channel. Bind FBO-1
				dstFBO = targetWin->fboTable[targetWin->drawBufferFBO[1]]->fboid;
			}
			else {
				dstFBO = targetWin->fboTable[targetWin->drawBufferFBO[0]]->fboid;
			}
		}

		// Bind read- / write- framebuffers:
		glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, srcFBO);
		glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dstFBO);

		// Perform blit-operation: If blitting from a multisampled FBO into a non-multisampled one, this will also perform the
		// multisample resolve operation:
		glBlitFramebufferEXT(sourceRect[kPsychLeft], PsychGetHeightFromRect(sourceWin->rect) - sourceRect[kPsychBottom], sourceRect[kPsychRight], PsychGetHeightFromRect(sourceWin->rect) - sourceRect[kPsychTop],
							 targetRect[kPsychLeft], PsychGetHeightFromRect(targetWin->rect) - targetRect[kPsychBottom], targetRect[kPsychRight], PsychGetHeightFromRect(targetWin->rect) - targetRect[kPsychTop],
							 GL_COLOR_BUFFER_BIT, GL_NEAREST);

		if (PsychPrefStateGet_Verbosity() > 5) {
			printf("FBB-SRC: X0 = %f Y0 = %f X1 = %f Y1 = %f \n", sourceRect[kPsychLeft], PsychGetHeightFromRect(sourceWin->rect) - sourceRect[kPsychBottom], sourceRect[kPsychRight], PsychGetHeightFromRect(sourceWin->rect) - sourceRect[kPsychTop]);
			printf("FBB-DST: X0 = %f Y0 = %f X1 = %f Y1 = %f \n", targetRect[kPsychLeft], PsychGetHeightFromRect(targetWin->rect) - targetRect[kPsychBottom], targetRect[kPsychRight], PsychGetHeightFromRect(targetWin->rect) - targetRect[kPsychTop]);
		}
		
		if (!(PsychPrefStateGet_ConserveVRAM() & kPsychAvoidCPUGPUSync)) {
			if ((glerr = glGetError())!=GL_NO_ERROR) {			

				// Reset framebuffer binding to something safe - The system framebuffer:
				glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
			
				if((glerr == GL_INVALID_OPERATION) && (PsychGetWidthFromRect(sourceRect) != PsychGetWidthFromRect(targetRect) ||
													   PsychGetHeightFromRect(sourceRect) != PsychGetHeightFromRect(targetRect))) {
					// Non-matching sizes. Make sure we do not operate on multisampled stuff
					PsychErrorExitMsg(PsychError_user, "CopyWindow failed: Most likely cause: You tried to copy a multi-sampled window into a non-multisampled window, but there is a size mismatch of sourceRect and targetRect. Matching size is required for such copies.");
				}
				else {
					if (glerr == GL_INVALID_OPERATION) {
						PsychErrorExitMsg(PsychError_user, "CopyWindow failed: Most likely cause: You tried to copy from a multi-sampled window into another multisampled window, but there is a mismatch between the multiSample levels of both. Identical multiSample values are required for such copies.");
					}
					else {
						printf("CopyWindow failed for unresolved reason: OpenGL says after call to glBlitFramebufferEXT(): %s\n", gluErrorString(glerr));
						PsychErrorExitMsg(PsychError_user, "CopyWindow failed for unresolved reason.");
					}
				}
			}
		}
		
		// Reset framebuffer binding to something safe - The system framebuffer:
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
		
		// Just to make sure we catch invalid values:
		if (!(PsychPrefStateGet_ConserveVRAM() & kPsychAvoidCPUGPUSync)) PsychTestForGLErrors();
		
		// Done.
		return(PsychError_none);
	}

	// We have four possible combinations for copy ops:
	// Onscreen -> Onscreen
	// Onscreen -> Texture
	// Texture  -> Texture
	// Texture  -> Onscreen
        
	// Texture -> something copy? (Offscreen to Offscreen or Offscreen to Onscreen)
	// This should work for both, copies from a texture/offscreen window to a different texture/offscreen window/onscreen window,
	// and for copies of a subregion of a texture/offscreen window into a non-overlapping subregion of the texture/offscreen window
	// itself:
	if (sourceWin->windowType == kPsychTexture) {
		// Bind targetWin (texture or onscreen windows framebuffer) as
		// drawing target and just blit texture into it. Binding is done implicitely
		
		if ((sourceWin == targetWin) && (targetWin->imagingMode > 0)) {
			// Copy of a subregion of an offscreen window into itself while imaging pipe active, ie. FBO storage: This is actually the same
			// as on onscreen -> onscreen copy, just with the targetWin FBO bound.
			
			// Set target windows framebuffer as drawing target:
			PsychSetDrawingTarget(targetWin);

			// Disable alpha-blending:
			glDisable(GL_BLEND);
			
			// Disable any shading during copy-op:
			PsychSetShader(targetWin, 0);

			// Start position for pixel write is:
			glRasterPos2f(targetRect[kPsychLeft], targetRect[kPsychBottom]);
			
			// Zoom factor if rectangle sizes don't match:
			glPixelZoom(PsychGetWidthFromRect(targetRect) / PsychGetWidthFromRect(sourceRect), PsychGetHeightFromRect(targetRect) / PsychGetHeightFromRect(sourceRect));
			
			// Perform pixel copy operation:
			glCopyPixels(sourceRect[kPsychLeft], PsychGetHeightFromRect(sourceWin->rect) - sourceRect[kPsychBottom], (int) PsychGetWidthFromRect(sourceRect), (int) PsychGetHeightFromRect(sourceRect), GL_COLOR);
			
			// That's it.
			glPixelZoom(1,1);
			
			// Flush drawing commands and wait for render-completion in single-buffer mode:
			PsychFlushGL(targetWin);				
		}
		else {
				// Sourcewin != Targetwin and/or imaging pipe (FBO storage) not used. We blit the
				// backing texture into itself, aka into its representation inside the system
				// backbuffer. The blit routine will setup proper bindings:

				// Disable alpha-blending:
				glDisable(GL_BLEND);

				// We use filterMode == 1 aka Bilinear filtering, so we get nice texture copies
				// if size of sourceRect and targetRect don't match and some scaling is needed.
				// We maybe could map the copyMode argument into some filterMode settings, but
				// i don't know the spec of copyMode, so ...
				PsychBlitTextureToDisplay(sourceWin, targetWin, sourceRect, targetRect, 0, 1, 1);
				
				// That's it.
				
				// Flush drawing commands and wait for render-completion in single-buffer mode:
				PsychFlushGL(targetWin);
		}
	}

	// Onscreen to texture copy?
	if (PsychIsOnscreenWindow(sourceWin) && PsychIsOffscreenWindow(targetWin)) {
		// With the current implemenation we can't zoom if sizes of sourceRect and targetRect don't
		// match: Only one-to-one copy possible...
		if(PsychGetWidthFromRect(sourceRect) != PsychGetWidthFromRect(targetRect) ||
		   PsychGetHeightFromRect(sourceRect) != PsychGetHeightFromRect(targetRect)) {
				// Non-matching sizes. We can't perform requested scaled copy :(
				PsychErrorExitMsg(PsychError_user, "Size mismatch of sourceRect and targetRect. Matching size is required for Onscreen to Offscreen copies. Sorry.");
		}
		
		// Update selected textures content:
		// Looks weird but we need the framebuffer of sourceWin:
		PsychSetDrawingTarget(sourceWin);

		// Disable alpha-blending:
		glDisable(GL_BLEND);
		
		// Disable any shading during copy-op:
		PsychSetShader(sourceWin, 0);

		// Texture objects are shared across contexts, so doesn't matter if targetWin's texture actually
		// belongs to the bound context of sourceWin:
		glBindTexture(PsychGetTextureTarget(targetWin), targetWin->textureNumber);
		
		// Copy into texture:
		glCopyTexSubImage2D(PsychGetTextureTarget(targetWin), 0, targetRect[kPsychLeft], PsychGetHeightFromRect(targetWin->rect) - targetRect[kPsychBottom], sourceRect[kPsychLeft], PsychGetHeightFromRect(sourceWin->rect) - sourceRect[kPsychBottom],
							(int) PsychGetWidthFromRect(sourceRect), (int) PsychGetHeightFromRect(sourceRect));
		
		// Unbind texture object:
		glBindTexture(PsychGetTextureTarget(targetWin), 0);
		
		// That's it.
		glPixelZoom(1,1);
	}

	// Onscreen to Onscreen copy?
	if (PsychIsOnscreenWindow(sourceWin) && PsychIsOnscreenWindow(targetWin)) {
		// Currently only works for copies of subregion -> subregion inside same onscreen window,
		// not across different onscreen windows! TODO: Only possible with EXT_framebuffer_blit
		if (sourceWin != targetWin) PsychErrorExitMsg(PsychError_user, "Sorry, the current implementation only supports copies within the same onscreen window, not accross onscreen windows.");

		// Set target windows framebuffer as drawing target:
		PsychSetDrawingTarget(targetWin);
		
		// Disable alpha-blending:
		glDisable(GL_BLEND);
		
		// Disable any shading during copy-op:
		PsychSetShader(targetWin, 0);

		// Start position for pixel write is:
		glRasterPos2f(targetRect[kPsychLeft], targetRect[kPsychBottom]);
		
		// Zoom factor if rectangle sizes don't match:
		glPixelZoom(PsychGetWidthFromRect(targetRect) / PsychGetWidthFromRect(sourceRect), PsychGetHeightFromRect(targetRect) / PsychGetHeightFromRect(sourceRect));
		
		// Perform pixel copy operation:
		glCopyPixels(sourceRect[kPsychLeft], PsychGetHeightFromRect(sourceWin->rect) - sourceRect[kPsychBottom], (int) PsychGetWidthFromRect(sourceRect), (int) PsychGetHeightFromRect(sourceRect), GL_COLOR);
		
		// That's it.
		glPixelZoom(1,1);
		
		// Flush drawing commands and wait for render-completion in single-buffer mode:
		PsychFlushGL(targetWin);
	}

	// Just to make sure we catch invalid values:
	if (!(PsychPrefStateGet_ConserveVRAM() & kPsychAvoidCPUGPUSync)) PsychTestForGLErrors();

	// Done.
	return(PsychError_none);
}