function PropixxImageUndistortionThrowaway(calibfilename, flipmethod, corrmethod, imagefilename) % PropixxImageUndistortionThrowaway(calibfilename [, flipmethod=0][, corrmethod=0][, imagefilename]) % % A preliminary throwaway demo of how to use PropPixx in fast 4x or 12x % display mode. This demo is EXPERIMENTAL and subject to change % without warning, potentially even removal, in future Psychtoolbox % releases. Make a private copy of it and the PsychProPixx.m file % if you want to keep it as is for production use! % % You will need a powerful, fast graphics card and a well configured % operating system and machine for this to work reliably at 12x mode. % % The demo can be stopped via the ESCAPE key. % % Parameters and their meaning: % % 'calibfilename' mandatory name of a display geometry calibration file % created via DisplayUndistortionBVL() iff corrmethod is >= 0. % % flipmethod = 0 -> Sync flips. [ Slow but easy ] % flipmethod = 1 -> Async flips for some sort of triplebuffering. [ Potentially faster but more difficult ] % flipmethod = 2 -> Fastest method, but only available on Linux with open-source graphics drivers. % % corrmethod = -1 -> No correction. % corrmethod = 0 -> Global correction for whole image. [Fastest and default] % corrmethod = 1 -> Separate correction for each quadrant. % % 'imagefilename' optional name of image file to display - see code. % % Performance/Stability tips: % % On Linux with the open-source graphics drivers, flipmethod 2 will % increase stability due to the ability to do non-blocking but still % vsynced flips without the overhead of AsyncFlipBegin et al. % % On Linux with the proprietary NVidia graphics driver, or on macOS or Windows, % where you can't use flipmethod 2, flipmethod 1 for use of 'AsyncFlipBegin' % flips should get you a bit of extra stability if you are lucky, although not % as good as flipmethod 2 with Linux + FOSS drivers. % % On Linux with proprietary NVidia driver, or on Windows, you may be able to % get a bit more stability if your graphics driver supports triplebuffering. % However, time stamping and other correctness tests wouldn't work anymore, % so you'd need some other means to verify timing. % % Another method to get reliability and proper timestamping on any % operating system without much tweaking or configuration is of course % to simply buy the fastest graphics card money can buy and then make % your stimuli simple enough so it can cope with them. % % In general, your graphics card must be able to do all processing within % much less than 8.33 msecs for Propixx fast modes to work, so reasonable % stimulus design and a fast graphics card is important. Above special % flipmethod's or the use of properly setup Linux can buy you a few msecs % of extra safety margin to compensate for occassional timing glitches, ie., % if the graphics card occassionally overshoots its 8.3 msecs budget, but is % capable of meeting it on average - in such cases those tricks help. % History: % 14-Mar-2015 mk Initial incomplete prototype for testing. % 17-Mar-2015 mk Bits of tweaking, some performance tips in help. % 25-Feb-2023 mk Bits of help text updates. if nargin < 2 || isempty(flipmethod) % flipmethod 0 is the most safe, but also the least % efficient: flipmethod = 0; end if nargin < 3 || isempty(corrmethod) % corrmethod 0 is the most efficient one: corrmethod = 0; end % Initialize for unified KbName's and normalized 0 - 1 color range: PsychDefaultSetup(2); % Only check ESCAPE key via KbCheck for ending the demo. % KbCheck is expensive especially on OSX, so minimize its % impact to the absolute minimum: RestrictKeysForKbCheck(KbName('ESCAPE')); % Choose output screen as usual: screenid = max(Screen('Screens')); PsychImaging('PrepareConfiguration'); if flipmethod >= 1 % For drawing during async flip - aka effective triplebuffering - % to work, we need a virtual framebuffer. This also helps for % flipmethod == 2 on Linux with double-buffering, because it % decouples swap completion aka availability of the backbuffer % from stimulus rendering and composition for 4 quadrant 3 RGB % channels, so those steps can run while a bufferswap is still % pending. PsychImaging('AddTask', 'General', 'UseVirtualFramebuffer'); end if corrmethod == 0 % Use global geometry correction, with identical correction % applied to all 4 quadrants of the onscreen window, ie., use % a 2 by 2 tiling [2,2]. This is currently only implemented for % the DisplayUndistortionBVL method. Subdivide warp mesh into % a 73 x 73 grid. This may be much finer than needed and lowering % the number may increase performance at a loss of precision. PsychImaging('AddTask', 'AllViews', 'GeometryCorrection', calibfilename, 0, 73, 73, [2, 2]); end w = PsychImaging('OpenWindow', screenid, 0); if nargin < 4 imagefilename = []; end if isempty(imagefilename) imagefilename = [PsychtoolboxRoot 'PsychDemos/konijntjes1024x768gray.jpg']; end % Use our standard bunny picture as some test case: img = imread(imagefilename); mytex=Screen('MakeTexture', w, img); % Try to present at 12x rate ie. 1440 Hz stimulus update rate: rate = 12 if corrmethod <= 0 % For global correction (method 0) clear calibfilename, so local % correction gets disabled: Global correction is faster on all % tested systems. calibfilename = []; end % Setup for fast display mode, producing the final image in onscreen window % 'w', for presentation at rate 'rate' (4 or 12), with 'flipmethod'. % Replace 0 with 1 for GPU load benchmarking - has some performance impact % itself, but allows assessment of how much we make the graphics card sweat: PsychProPixx('SetupFastDisplayMode', w, rate, flipmethod, calibfilename, 0); % Get a suitable offscreen window 'myimg' for drawing our stimulus: myimg = PsychProPixx('GetImageBuffer'); % We want text to be big: Screen('TextSize', myimg, 128); % Setup for procedural gabor - stolen from ProceduralGaborDemo: res = [500 500]; phase = 0; sc = 50.0; freq = .1; tilt = 0; contrast = 100.0; aspectratio = 1.0; tw = res(1); th = res(2); % Build a procedural gabor texture for a gabor with a support of tw x th % pixels, and a RGB color offset of 0.5 -- a 50% gray. gabortex = CreateProceduralGabor(myimg, tw, th, 0, [0.5 0.5 0.5 0.0]); % Draw the gabor once, just to make sure the gfx-hardware is ready for the % benchmark run below and doesn't do one time setup work inside the % benchmark loop: Screen('DrawTexture', myimg, gabortex, [], [], 90+tilt, [], [], [], [], kPsychDontDoRotation, [phase+180, freq, sc, contrast, aspectratio, 0, 0, 0]); % Realtime scheduling: Priority(MaxPriority(w)); % Prepare the benchmark / demo run: count = 0; KbReleaseWait; tstart = Screen('Flip', w); while 1 if 0 % Draw bunnies into exampleImage: Screen('DrawTexture', myimg, mytex); else % Use a gabor shader for fast procedural drawing of Gabor stim: Screen('DrawTexture', myimg, gabortex, [], [], 90+count, [], [], [], [], kPsychDontDoRotation, [count+180, freq, sc, contrast, aspectratio, 0, 0, 0]); end % Some centered text for illustration... Text drawing is % relatively expensive, especially so on OSX and Windows! Screen('DrawText', myimg, sprintf('%i', count), 200, 80, 1); count = count + 1; % Queue this stimulus for presentation at soonest video % refresh cycle of the graphics card. % Call KbCheck only on QueueImage calls which actually % trigger a stimulus image update, ie. every 4th or 12th % call. KbCheck calls are relatively expensive and can % really spoil the timing on excessive use: if PsychProPixx('QueueImage', myimg) && KbCheck % ESCape key pressed, end this demo: break; end end % Final flip for time measurement: tend = Screen('Flip', w); % Done with realtime: Priority(0); % Retrieve timing samples, mostly useful for flipmethod 2: PsychProPixx('GetTimingSamples'); % Reenable KbCheck for all keys: RestrictKeysForKbCheck([]); % Disable driver, plot some timing plots: PsychProPixx('DisableFastDisplayMode', 1); % Close all windows and ressources: sca; avgframetimemsecs = 1000 * (tend - tstart) / (count / rate) return;