Variations in OpenGL Functionality


Introduction

If you try using the demos referred to in this article and have problems getting them to work as expected it could be because of the fact that some of the OpenGL functions used by Psychtoolbox do not run in a consistent way on different graphics cards, due to bugs in the different operating systems and vendor supplied graphics device drivers. I have listed all the problems we know about here. It is probably advisable to read this section before seriously attempting to write stimuli. Readers are welcome to contribute to this section if they discover other issues.

Problem

In Bits++ mode, animated stimuli don't work. I just get a line of dancing pixels along the top of the screen.

Explanation

This means that the T-Lock code has not been recognised. The line of pixels you see is the T-Lock code followed by the CLUT which is supposed to be loaded into the Bits++. If the T-Lock code were being properly recognised by the Bits++ it would know that this line is not supposed to be displayed, but should be used to set its CLUT.

Possible Solution 1

Sometimes you just need to reset everything. Unplug the the Bits++ and restart the computer. Then startup Matlab and run the LoadIdentityClut.m script in the Bits++ demos. This will ensure that your graphics card doesn't interfere with the pixels passing through it by loading an identity gamma table into the graphics card. Now try running one of the Bits++ mode demos.

If you use calls to setup subfunctions in the PsychImaging.m script, as recommended for all new stimulus presentation scripts, loading identity gamma tables and other setup steps will be performed automatically for you. See, e.g., BitsPlusCSFDemo for an example of setting up for Mono++ mode, AdditiveBlendingForLinearSuperpositionTutorial('Color++') as an example of setting up Color++ mode, or MinimumMotionExp for a full example experiment in Bits++ mode.

Possible Solution 2

You are in the wrong mode. Only in Bits++ mode does the Bits++ use CLUTs. If you are in Colour++ mode or Mono++ mode CLUTs won't work. However, in Mono++ mode, CLUTs will be used to define the colors of the color overlay.

Possible Solution 3

At some screen resolutions your secondary screen might not be properly lined up. Sometimes you can see some of it spilling over onto the primary screen. If the T-Lock code is being written to the top left corner of the secondary screen some of it may be missed out, and it might cause this problem. If you suspect that this is the case you could try drawing the T-Lock code to a different part of the screen. Look at the BitsPlusPlusEncodeClutRow.m to see how to do this. This should not be a problem if you use calls to setup subfunctions in the PsychImaging.m script, as recommended for all new stimulus presentation scripts, as this will try to automatically compensate for such variations.

Possible Solution 4

The Screen('DrawTexture'...) Psychtoolbox/OpenGL function can be used to draw images to the screen and/or to change the Bits++'s CLUT by drawing the T-Lock code. As with most codes, changing the numbers even slightly will break it completely. This is in contrast to image data, where changing the value of one or two of the pixels very slightly will only change the colour of those pixels very slightly and probably won't even be noticed.

The Screen('DrawTexture'...) function is designed for drawing images to the screen and it can, if desired, reduce or enlarge those images before drawing them. When it does this it needs to do some interpolation or extrapolation when it reduces or increases the number of pixels in the image. You get a choice of two methods for this interpolation/extrapolation and they are set in the 'filterMode' parameter of the function. (Type Screen DrawTexture? at the Matlab prompt to see this for yourself.) You can choose 'nearest neighbour' or 'bilinear' filtering. If you do not specify a mode, the default is 'bilinear'.

When using this function to draw the T-Lock code and CLUT, you obviously don't want to reduce or enlarge, so this should not be an issue. But, actually, in 'bilinear' mode, some residual interpolation does still sometimes occur, probably because of rounding errors in the OpenGL. The result is that one or two of the pixels sometimes change their values by a very small amount. If this happens in an image it's not noticeable. But if it happens in the T-Lock code it breaks.

One solution is to use 'nearest neighbour' mode. This effectively means that no interpolation occurs and the problem goes away.

A better solution, if you have used PsychImaging to setup your display, is to use the Screen('LoadNormalizedGammaTable', wptr, Clut, 2); function to assign a new Clut to the window wptr.

Possible Solution 5

If you use Mac OS X 10.5 or 10.6 and NVIDIA graphics (this may also be necessary for newer ATI cards according to Mario), the Apple driver appears to permanently enable temporal dithering, which means that the T-Lock unlock code only gets recognised on 25% of frames. This behaviour is consistent with an 8-bit pixel that is temporally modulated via an 8/6 LUT to achieve 8-bit resolution on a 6-bit capable display (e.g. a laptop LCD screen). Trust us about this: we built a DVI logic analyser to capture the DVI output so we can see the raw digital pixel data.

To disable the temporal dithering feature, you need to install a third-party OS X kernel extension called "NVinject" which adds arbitrary keys into the OS X IORegistry at boot time, before the actual NVIDIA graphics driver starts. The driver accepts the keys when it starts and configures the graphics pipeline in the required way. This requires a 32bit kernel, newer Macs default to 64bit and you can swap between them using the information contained in this Apple KB article.

To install:

1. Download this customised version: "NVinject"

2. In a terminal: sudo cp -R NVinject.kext /System/Library/Extensions/

3. Reboot.

4. The system console log will show some messages from it, reporting that it injected a AAPL00,Dither key and a AAPL01,Dither key, one for each display head:

OS X System Console

The kernel extension is configured so that it doesn't get loaded on a safe-boot (hold down the shift key while starting up the computer). This means you always have an option to prevent the driver from loading if something should go wrong.

You can also verify that the IORegistry has been changed using the Xcode I/O Registry Explorer tool:

Xcode IORegistryExplorer

To verify that your Bits++ is working correctly, load the Mono++ firmware and run the Psychtoolbox script BitsPlusIdentityClutTest. This test script is distributed with Psychtoolbox-3 release 27.10.2009 or later. If you are using an earlier version of PTB-3, run the UpdatePsychtoolbox command at the MATLAB command prompt. This version is described in message 10197 posted to the Psychtoolbox forum and also contains a revised LoadIdentityClut implementation.

You may encounter the same problem on some modern ATI graphics cards under Microsoft Windows or Linux due to the same graphics driver bug. The Psychtoolbox function PsychGPUControl('SetDitheringEnabled', 0); should get rid of the problem.

Problem

In some stimulus scripts I get an error like this:

Error in function Flip: Usage error
OpenGL AUX buffers unavailable! dontclear=1 in Screen-Flip doesn't work without them.
Either unsupported by your graphics card, or you disabled them via call to Screen('Preference', 'ConserveVRAM')?


Explanation

Some graphics cards don't implement the OpenGL AUX buffers mechanism.

Possible Solution

Update to a recent version of the Psychtoolbox. As of November 2009, Psychtoolbox will work around the lack of AUX buffers, with a minimal decrease in performance.

If for some reason this isn't an option for you, you can try the following:

Actually, I've already written alternative versions of the demo scripts that don't do a flip with the dontclear flag equal to 1. So you can try basing your script on one of these. Let's take, as an example, the demos called BlueYellowTemporalGrating.m and BlueYellowTemporalGrating_NoDoubleBuffering.m:

Both scripts display a grating on the screen and vary its contrast by re-loading a different CLUT to the Bits++ every frame. They use the Screen('DrawTexture'...) function both for drawing the grating and for drawing the T-Lock code and CLUT, because it is fast. The trouble is, as I've said, this command draws onto the back screen so you have to do a 'flip' afterwards to display what you've drawn.

BlueYellowTemporalGrating.m draws the grating onto both back and front screens and then, when drawing the T-Lock code and CLUT, keeps flipping between the two. But it has to set the dontclear flag to 2 to avoid erasing the gratings.

BlueYellowTemporalGrating_NoDoubleBuffering.m draws the grating onto just one screen but it draws it every frame. This is acceptably fast because it has already prepared the texture which represents the grating so it only has to call Screen('DrawTexture'...).


Valid XHTML :: Valid CSS: :: Powered by WikkaWiki