This file is indexed.

/usr/share/psychtoolbox-3/PsychTests/GraphicsDisplaySyncAcrossDualHeadsTest.m is in psychtoolbox-3-common 3.0.9+svn2579.dfsg1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
function GraphicsDisplaySyncAcrossDualHeadsTest(screenids, nrtrials, driftsync)
% GraphicsDisplaySyncAcrossDualHeadsTest([screenids] [, nrtrials=6000] [, driftsync=0])
%
% Test synchronizity between the scanout/refresh cycles of two different
% display heads 'screenids(1)' and 'screenids(2)'. If 'screenids' is
% omitted, we test the two heads with maximal id. 'nrtrial' sample passes
% with a sampling interval of roughly 1 msecs are conducted. 'nrtrials'
% defaults to 6000 samples.
%
% Each sample consists of querying the current rasterbeam position and
% timestamp of last VBL interrupt on each display head. At the end, the
% samples of both heads are plotted against each other and compared.
%
% The help text in the Matlab prompt tells you how to interpret the plots.

% History:
% 12/11/07 Written (MK).

AssertOpenGL;

if nargin < 1
    screenids = [];
end

if isempty(screenids)
    screenids = Screen('Screens');
    if length(screenids)<2
        % Only single head - Nothing to test?!?
        error('Only one display head attached to graphics hardware. How am i supposed to test sync across heads?!?');
    end
    
    if length(screenids)>2
        % If more than two heads available, choose the two heads with
        % maximum id:
        screenids = screenids(end-1:end);
    end
end

if length(screenids) > 2
    error('"screenids" parameter contains indices of more than two screens?!? This is a dual-head sync test!');
end

if nargin < 2
    nrtrials = [];
end

if isempty(nrtrials)
    nrtrials = 6000;
end

if nargin < 3
    driftsync = [];
end

if isempty(driftsync)
    driftsync = 0;
end

driftsync = driftsync * 2;

testvblirqs = 1;

% Open windows:
w(1) = Screen('OpenWindow', screenids(1), 0, []);
w(2) = Screen('OpenWindow', screenids(2), 0, []);

if driftsync > 0
    WaitSecs(2);

    % Query current display settings for 1st display:
    oldResolution(1)=Screen('Resolution', screenids(1));

    % Switch 1st display to 60 Hz refresh rate:
    if oldResolution(1).hz ~=0
        Screen('Resolution', screenids(1), oldResolution(1).width, oldResolution(1).height, 60, oldResolution(1).pixelSize, 1);
    end
    
    % Query current display settings for 2nd display:
    oldResolution(2)=Screen('Resolution', screenids(2));

    % Switch 2nd display to 75 Hz refresh rate:
    Screen('Resolution', screenids(2), oldResolution(2).width, oldResolution(2).height, 75, oldResolution(2).pixelSize, 1);
    
    WaitSecs(2);
end

% Some beauty...
Screen('Flip', w(1), 0, 2);
Screen('Flip', w(2), 0, 2);
Screen('FillRect', w(1), 255);
Screen('FillRect', w(2), 255);
Screen('Flip', w(1), 0, 2);
Screen('Flip', w(2), 0, 2);

if driftsync > 0
    nrtrials = 100000;
end

timinginfo = zeros(2, 2, nrtrials);
syncedattrial = -1;

% Test loop one:
for i=1:nrtrials
    % Sample in roughly 1 msec intervals:
    WaitSecs(0.001);
    
    % Sample in close sync:
    for j=1:2
        winfo(j) = Screen('GetWindowInfo', w(j)); %#ok<AGROW>
    end
    
    for j=1:2
        timinginfo(1, j,i) = winfo(j).Beamposition;
        timinginfo(2, j,i) = winfo(j).LastVBLTime;
    end
    
    if driftsync > 1
        if abs(winfo(1).LastVBLTime - winfo(2).LastVBLTime) < 0.0005
            % Switch display 2 also to 60 Hz refresh:
            Screen('Resolution', screenids(2), oldResolution(2).width, oldResolution(2).height, 60, oldResolution(2).pixelSize, 1);
            driftsync = 1;
            syncedattrial = i %#ok<NOPRT>
            drawnow;
            Beeper;
        end
    end
    
    if (driftsync == 1) & (i > syncedattrial + 6000) %#ok<AND2>
        stoppedattrial = i %#ok<NASGU,NOPRT>
        drawnow;
        break;
    end
end

timinginfo = timinginfo(:,:,1:i);
nrtrials = i;

%Beeper(800);
Screen('CloseAll');
%Beeper(1200);

if driftsync
    % Restore original display settings:
    Screen('Resolution', screenids(1), oldResolution(1).width, oldResolution(1).height, oldResolution(1).hz, oldResolution(1).pixelSize, 0);
    Screen('Resolution', screenids(2), oldResolution(2).width, oldResolution(2).height, oldResolution(2).hz, oldResolution(2).pixelSize, 0);
end

fprintf('What you should see in the following plots for well synchronized displays:\n');
fprintf('The "drift" plots should either show a nice zero flat line or a flat line with\n');
fprintf('a small constant offset. Of course a bit of kind of gaussion noisyness has to be\n');
fprintf('expected in the system. What you should not see is some clear trend in one direction\n');
fprintf('or a sawtooth-like pattern. That would indicate drift between the display heads due\n');
fprintf('to missing sync across the heads.\n\n');

% Some plotting:
close all;
if (range(timinginfo(1, 1, :)) > 0) && (range(timinginfo(1, 2, :)) > 0)
    plot(1:nrtrials, squeeze(timinginfo(1,1,:)), 'r', 1:nrtrials, squeeze(timinginfo(1,2,:)), 'b');
    title('Beampositions for both displays: Red = Head 1, Blue=Head 2');

    figure;
    plot(1:nrtrials, squeeze(timinginfo(1,1,:)) - squeeze(timinginfo(1,2,:)));
    title('Beamposition drift between displays:');
end

if testvblirqs
    figure;
    plot(1:nrtrials, squeeze(timinginfo(2,1,:)), 'r', 1:nrtrials, squeeze(timinginfo(2,2,:)), 'b');
    title('VBL Interrupt timestamps for both displays: Red = Head 1, Blue=Head 2');

    figure;
    plot(1:nrtrials, squeeze(timinginfo(2,1,:)) - squeeze(timinginfo(2,2,:)));
    title('VBL Interrupt timestamp drift between displays:');
end

return;