This file is indexed.

/usr/share/psychtoolbox-3/PsychTests/AlphaMultiplicationAccuracyTest.m is in psychtoolbox-3-common 3.0.11.20131230.dfsg1-1build1.

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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
function [maximumError, roundTypeStr, independentFlag]=AlphaMultiplicationAccuracyTest(screenNumber)

% [maximumError, roundTypeStr, independentFlag]=AlphaMultiplicationAccuracyTest([screenNumber])
%
% Test the accuracy of alpha blending multiplication. OpenGL guarantees
% perfect accuracy of alpha multiplication for values 0 and 1 only.
% TestAlphaMultiplicationAccuracy measures accuracy of intermediate values.
%
% Return argument "maximumError" is the maximum unsigned difference between
% OpenGL alpha multiplication and  simulated alpha blending in MATLAB using
% double-precisions floating point multiplication.
%
% Values of maximumError fall into three categories:
%
% 0 <= maximumError < 0.5   : OpenGL rounds to nearest integer.  No 
%                             accuracy loss for a single multiplication.
%
% 0.5 <= maximumError < 1   : OpenGL truncates or rounds up. For a single 
%                             multiplication, Accuracy is off  0.5 parts
%                             in 255 more than would multiplying luminances 
%                             using floating-point values and rounding.
%
% maximumError >= 1         : Something is wrong.  
% 
% 
% TestAlphaMultiplicationAccuracy tries to determine whether OpenGL alpha
% multiplication rounds to the nearest integer, rounds down or rounds up
% and returns in "roundTypeStr" a string indicating which, either, "round"
% "floor", or "ceil".  If TestAlphaMultiplicationAccuracy can not determine
% the rounding method, then it returns "unknown".
%
% TestAlphaMultiplicationAccuracy also tests that multiplication errors are
% independent of the choice of blending factor string and the blending
% surface, setting return argument "independentFlag" accordingly.     
%
% Because in OpenGL pixel color components are ultimately encoded as 8-bit
% integers in video RAM, the results of OpenGL alpha multiplicaion will be
% less accurate than those predicted by floating-point calculations.  If
% OpenGL rounds to the nearest integer then the alpha multiply error will
% be less than 0.5. This is the limit of precision of the color components
% of a pixel. Therefore, when alpha blending rounds to the nearest integer,
% no more accuracy is lost with OpenGL alpha blending than by calculating
% pixel values in MATLAB with floating point precision then rounding them
% to integer pixel values for display.
%
% Note that errors are cumulative and iterative alpha multiplication, in
% which a product of a prevoius multiplication becomes a factor in a
% subsequent multiplication, can produce large errors, even in the best
% case of rounding where 0 <= maximumError < 0.5.  Note also that A single
% alpha blending operation may result in two multipliations, because both
% source and destination surfaces may be multiplied before they are added. 
%    
% We test blending accuracy becasue OpenGL makes no gurantees.  The OpenGL
% policy on alpha multiplician is summarized here:  
% 
% http://msdn.microsoft.com/library/default.asp?url=/library/en-us/opengl/glfunc01_4vs3.asp
%
%         "Despite the apparent precision of the above equations, blending
%         arithmetic is not exactly specified, because blending operates with
%         imprecise integer color values. However, a blend factor that should be
%         equal to one is guaranteed not to modify its multiplicand, and a blend
%         factor equal to zero reduces its multiplicand to zero." 
%
% See also: AlphaBlendingTest, PsychAlphaBlending


% HISTORY
%
% mm/dd/yy
%
% 1/28/05   awi  Wrote it.


% BUGS
%
% There is possibility that an OpenGL implementation would round
% multiplication to the nearest integer but have a different policy for
% which direction to round 0.5 than does MATLAB.  In that case,
% TestAlphaMultiplicationAccuracy would return a maximumError of 0.5 and
% roundTypeStr 'unknown' instead of 'round'.  


exitOnError= nargout < 1;
if nargin==0
    screenNumber=max(Screen('Screens'));
end



%first test GetImage using PutImage because in later steps we rely on
%GetImage alpha blending.
background=127;
w=Screen('OpenWindow', screenNumber, [], [], [], 2);
Screen('FillRect', w, background);
wRect=Screen('Rect',w);


testPlane1=repmat(0:255, 256, 1);
testPlane2=rot90(testPlane1);
testImage1=repmat(testPlane1, [1, 1, 3]);
testImage2=repmat(testPlane2, [1,1,3]);
testImageRect=RectOfMatrix(testImage1);
imageMat1=testImage1;
imageMat1(:,:,4)=zeros(256);
zerosImage=repmat(zeros(256), [1,1,4]);
matRect=RectOfMatrix(testImage1);


sourceBlendFactors={ 'GL_ZERO', 'GL_ONE', 'GL_DST_COLOR', 'GL_ONE_MINUS_DST_COLOR', 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA', 'GL_DST_ALPHA', 'GL_ONE_MINUS_DST_ALPHA', 'GL_SRC_ALPHA_SATURATE'};
destinationBlendFactors={'GL_ZERO','GL_ONE', 'GL_SRC_COLOR', 'GL_ONE_MINUS_SRC_COLOR', 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA', 'GL_DST_ALPHA', 'GL_ONE_MINUS_DST_ALPHA'};
numSourceFactors=length(sourceBlendFactors);
numDestinationFactors=length(destinationBlendFactors);

sourceBlendVariableFactors={ 'GL_DST_COLOR', 'GL_ONE_MINUS_DST_COLOR', 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA', 'GL_DST_ALPHA', 'GL_ONE_MINUS_DST_ALPHA', 'GL_SRC_ALPHA_SATURATE'};
destinationBlendVariableFactors={'GL_SRC_COLOR', 'GL_ONE_MINUS_SRC_COLOR', 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA', 'GL_DST_ALPHA', 'GL_ONE_MINUS_DST_ALPHA'};
numSourceBlendVariableFactors=length(sourceBlendVariableFactors);
numDestinationBlendVariableFactors=length(destinationBlendVariableFactors);



% first, check that alpha multiplication gives the same result regardless of
% the mode. We do not test trivial cases of GL_ZERO and GL_ONE.  Those are tested
% elsewhere, by TestAlphaMultiplication.  

%for source blending
for i=1:numSourceBlendVariableFactors
    %make source and destination images
    [sourceImagesA{i}, destinationImagesA{i}]=SetSourceAlpha(sourceBlendVariableFactors{i}, testPlane2, imageMat1, zerosImage);
    %write the destination matrix
    Screen('BlendFunction', w, 'GL_ONE', 'GL_ZERO');
    Screen('PutImage', w, destinationImagesA{i}, matRect);
    %write the source matrix.
    Screen('BlendFunction', w, sourceBlendVariableFactors{i}, 'GL_ZERO');
    Screen('PutImage', w, sourceImagesA{i}, matRect);
    sourceReadbacks{i}=Screen('GetImage',w,matRect);
    Screen('Flip', w);
end


%compare results from every mode to results from every other.  
sourceEqualityMat=zeros(numSourceBlendVariableFactors);
for i=1:numSourceBlendVariableFactors
    for j=1:numSourceBlendVariableFactors
        sourceEqualityMat(i,j)=isempty(find(sourceReadbacks{i}~=sourceReadbacks{j}));
    end
end


%for destination blending
for i=1:numDestinationBlendVariableFactors
    %make source and destination images
    [sourceImagesB{i}, destinationImagesB{i}]=SetDestinationAlpha(destinationBlendVariableFactors{i}, testPlane2, zerosImage, imageMat1);
    %write the destination matrix
    Screen('BlendFunction', w, 'GL_ONE', 'GL_ZERO');
    Screen('PutImage', w, destinationImagesB{i}, matRect);
    %write the source matrix.
    Screen('BlendFunction', w,  'GL_ZERO', destinationBlendVariableFactors{i});
    Screen('PutImage', w, sourceImagesB{i}, matRect);
    destinationReadbacks{i}=Screen('GetImage',w,matRect);
    Screen('Flip', w);
end

%on the destination surface, for each mode compare the product to the products for
%every other mode and for each comparison store a bit into a table indicating a match.  
destinationEqualityMat=zeros(numDestinationBlendVariableFactors);
for i=1:numDestinationBlendVariableFactors
    for j=1:numDestinationBlendVariableFactors
        destinationEqualityMat(i,j)=isempty(find(destinationReadbacks{i}~=destinationReadbacks{j}));
    end
end

%on the source surface, for each mode compare the product to the products for
%every other mode and for each comparison store a bit into a table indicating a match.  
sourceEqualityMat=zeros(numSourceBlendVariableFactors);
for i=1:numSourceBlendVariableFactors
    for j=1:numSourceBlendVariableFactors
        sourceEqualityMat(i,j)=isempty(find(sourceReadbacks{i}~=sourceReadbacks{j}));
    end
end


%As above, but combine both source and destination results into a larger
%table indicating whether source surface product matches destination surface product.
allReadbacks={sourceReadbacks{:} destinationReadbacks{:}};
equalityMat=zeros(length(allReadbacks));
for i=1:length(allReadbacks)
    for j=1:length(allReadbacks)
        equalityMat(i,j)=isempty(find(allReadbacks{i}~=allReadbacks{j}));
    end
end

%Test whether multliplication errors on the source surface are independent
%of the blending factor string
sourceIndependentFlag=isempty(find(sourceEqualityMat ~= 1));

%Test whether multliplication errors on the destination surface are independent
%of blending factor string
destinationIndependentFlag=isempty(find(destinationEqualityMat ~= 1));

%Test whether multliplication errors are independent of both the surface and the blending factor string 
independentFlag=isempty(find(equalityMat ~= 1));


% whatever the multiplication accuracy, we  now know from previous tests in
% this file if accuracy is the same for all modes.  It should be,
% therefore, in the next step when testing that accuracy, we need only test
% one mode and know that those results apply to all others.
predictedReadbackAll=AlphaSourceTerm(sourceBlendVariableFactors{1}, sourceImagesA{1}, destinationImagesA{1});
predictedReadback=predictedReadbackAll(:,:,1:3);
maxFloatDiff=max(max(max(abs(predictedReadback-double(sourceReadbacks{1})))));
maxRoundDiff=max(max(max(abs(round(predictedReadback)-double(sourceReadbacks{1})))));
maxFloorDiff=max(max(max(abs(floor(predictedReadback)-double(sourceReadbacks{1})))));
maxCeilDiff=max(max(max(abs(ceil(predictedReadback)-double(sourceReadbacks{1})))));

maximumError=maxFloatDiff;
if maxRoundDiff==0
    roundTypeStr='round';
elseif maxFloorDiff==0
    roundTypeStr='floor';
elseif maxCeilDiff==0
    roundTypeStr='ceil';
else
    roundTypeStr='unknown';
end


Screen('CloseAll');