function MovieTearDemo
% MovieTearDemo
%
% Drifting vertical edge demonstrates "tearing".
% 
% TEARING: You may have seen "tearing" in the movie. The tear is a
% horizontal break, perhaps a third of the way down from the top of the
% screen, jiggling up and down as the movie played. This tear is normal
% and does not indicate anything wrong with your computer or the display
% software. Tearing can occur in any display that isn't double buffered,
% and hardly any of the drivers for Macintosh video cards support double
% buffering. Even so, it's easy to avoid tearing once you understand why
% it happens. 
% 
% The tear is a discontinuity in time. The movie above the tear is delayed
% by one frame relative to what's displayed below the tear. This is
% invisible if the movie is static, but produces a glaring break in a
% moving object. Your video card has enough video memory to store one
% frame. The reading of video memory is an autonomous free-running process
% that drives the intensity and position of the monitor's video beam in a
% raster scan that paints the screen from top to bottom. The tear is the
% result of the computer writing to the same video memory that the video
% beam is reading. The computer is racing with the video beam from the top
% to the bottom of your screen. The beam has a head start, but your
% computer is slightly faster. The tear occurs when your computer passes
% the beam. Below the tear you see the contents of the new frame, just
% written by your computer into the frame store. Above the tear you are
% seeing the contents of the previous frame. 
% 
% You can eliminate the tear by pushing it up off the top of your movie.
% Anything that makes your computer proceed more quickly down the screen
% (e.g. making the movie narrower) will move the tear higher, as will
% moving your movie's window lower, i.e. giving your computer a head start
% in the race from top to bottom of the screen.
% 
% JIGGLING: The relatively stable vertical position of the tear is a
% consequence of the synchrony of the computer and monitor; if they
% weren't synchronized the tear would occur at a different height on each
% frame (which would make it much harder to get rid of). The jiggling up
% and down of the tear reveals the computer's varying latency, due to Mac
% OS and device driver interrupts. This allows you to directly observe the
% effect of using Rush to minimize interruptions.
% 
% DOUBLE BUFFERING: The hardware method of eliminating tearing is double
% buffering; you use two pages of video memory and alternately display
% from one while writing the other. The Mac OS defines driver-level calls
% to support double buffering (multiple pages) and most video cards have
% suitable chips and enough video memory to provide multiple pages, but
% hardly any video-card manufacturers have bothered to program their video
% drivers to support more than one page of video memory. ScreenTest
% reports how many video pages you have. We could add Matlab-level calls
% to control double buffering. Please send us a note if you have a video
% device with more than one video page and you'd like to try double
% buffering: psychtoolbox@yahoogroups.com

% 2/4/98	dgp	 Wrote it, based on MovieDemo. Show sliding vertical line 
%							 instead of growing disk.
% 2/16/98 dgp	 Use edge instead of line. Rewrite explanation.
% 3/10/98	dhb	 Load DefaultClut.
% 7/14/98	dgp	 ClutDefault instead of DefaultClut.
% 7/17/98	dgp  Using enhanced Rush, use easy-to-read cell array for string.
% 2/21/02 dgp  Cosmetic.
% 2/23/02 dgp  Don't touch pixelSize and clut.
% 04/03/02  awi -Changed the screen number to 0.
%               -Conditionally move the Matlab window only on Mac because
%                Screen 'GlobalRect' is not available on Windows yet
%               -Modified so that we generate offscreen windows the max width of 
%                the tearing block and not the width of the onscreen window.
%                This is necessary because under Windows we can not open an
%                onscreen window smaller than the screen size, if our 
%                offscreen windows are the size of the onscreen window 
%                we use way too much memory.
% 4/13/02 dgp Merged some cosmetic changes from old Mac version. 
%                 Use FrameRate() function, unconditionally.
% 2/18/04 awi Adapted to Windows.  Two changes were necessary.  First,
%             windows does not support onscreen windows smaller than the display size.
%             That's not a PTB bug, its limit imposed by the DirectX.
%             Second, there PsychToolbox does not correctly report the screen size 
%             if given a screen number.   


% Open an onscreen window
frames=128;
screenNumber=0;
if(strcmp(computer, 'PCWIN'))
    %the complicated version because Win Screen does not return screen size
    %when given a screen number, it only works with a window pointer.
    w=Screen(0,'OpenWindow');
    screenRect=Screen(w,'Rect');
    Screen(w,'Close');
else
    %the simple version because it works correctly on Mac
    screenRect=Screen(screenNumber,'Rect');
end
rect=screenRect;
rect(RectRight)=128;
black=BlackIndex(screenNumber);
if strcmp(computer,'MAC2')
    window=Screen(screenNumber,'OpenWindow',[],rect);
    screenRect=Rect;
else
    window=Screen(screenNumber,'OpenWindow',[],screenRect);
end
    
if strcmp(computer,'MAC2')
	% Move Matlab Command window to the right of ours
	m=Screen('GetMatlabWindow');
	r=AdjoinRect(Screen(m,'GlobalRect'),Screen(window,'GlobalRect'),RectRight);
	r=OffsetRect(r,7,0);
	Screen(m,'GlobalRect',r);
end 

% Make a movie by drawing an edge into 128 offscreen windows.
r=OffsetRect(rect,1-RectWidth(rect),0);
step=max(1,round((RectWidth(rect)-RectWidth(r))/(frames-1)));
w=zeros(frames,1);
for i=1:frames
	w(i)=Screen(window,'OpenOffscreenWindow',[],rect);
	Screen(w(i),'FillRect',black,OffsetRect(r,(i-1)*step,0));
end
HideCursor;


% Show the movie by looping on CopyWindow.
% The movie is shown forwards, then backwards.
% Use Rush to raise priority to minimize interruptions.
loop={
	'for i=[1:frames frames:-1:1];'
		'Screen(window,''WaitBlanking'');'
		'Screen(''CopyWindow'',w(i),window,rect, rect);'
	'end;'
};
pmax=MaxPriority(screenNumber,'WaitBlanking');
for priorityLevel=[0 pmax]
	Rush(loop,priorityLevel);
end

% Close all the on- and off-screen windows
Screen('CloseAll');
ShowCursor;

fprintf('The movie was shown twice. The second showing used Rush to raise priority\n');
fprintf('to minimize interruptions. See Rush.\n\n')

fprintf('TEARING: You may have seen "tearing" in the movie. The tear is a\n');
fprintf('horizontal break, perhaps a third of the way down from the top of the\n');
fprintf('screen, jiggling up and down as the movie played. This tear is normal\n');
fprintf('and does not indicate anything wrong with your computer or the display\n');
fprintf('software. Tearing can occur in any display that isn''t double buffered,\n');
fprintf('and hardly any of the drivers for Macintosh video cards support double\n');
fprintf('buffering. Even so, it''s easy to avoid tearing once you understand why\n');
fprintf('it happens. For an explanation:\n');
fprintf('help MovieTearDemo\n');
fprintf('\n');

secsPerLine=((1/FrameRate(screenNumber))-0.001)/RectHeight(screenRect);	% allow for 1 ms of blanking

fprintf('JIGGLING: The vertical jiggling of the tear tracks your computer''s\n');
fprintf('synchronization to the display. In your display, each pixel of jiggle \n');
fprintf('up and down corresponds to %.0f microseconds change in the synchrony \n',secsPerLine*1e6);
fprintf('with your computer. Rush improves synchrony, reducing the jiggle. See Rush.\n');
