[net.sources.mac] Flicker-free animation on the mac.

info-mac@uw-beaver (09/12/85)

From: oster%ucblapis.CC@Berkeley

When you do animation, you show the viewer successive frames at a rate high
enough that the viewer percieves the successive frames as continuous motion.
At the movies, you just show successive frames.  On the computer the frame to
frame transition is a little more complex:  You draw a frame, erase it, and
draw the next.  This is ususally optimized to:  You draw a frame, undraw the
parts that change, and draw the parts that change in the next.

If the viewer can percieve the undrawn state, the viewer will call your
animation "flickery".  The flicker problem of animation is to hide the frame to
frame transition from the viewer.  A movie projector hides the frame to frame
transition by concealing the film with a shutter while it is moving the film.

On a TV set, the picture is drawn by sweeping an electron beam across the
surface of a cathode ray tube in many horizontal scan lines.  If you look
closely at the Mac screen, you can see the scan line structure.  The Mac
picture tube, in order to take advantage of the mass production of the TV
industry, follows the TV convention of only drawing while the beam moves from
left to right, and drawing each scan line below the previous one.  (I don't
know why TV was not designed to scan in alternate directions on alternate scan
lines and draw scan lines top down in one frame and bottom up in the next.  I
just know it doesn't.) The beam is deflected by magnetic fields (or electric
fields on some older sets).  These fields behave as if they had inertia - they
can not be changed instantaneously.  It takes time to bring the beam back to
the position of the start of the next scan line.  During that time the Mac can
make multiple changes to screen memory, and only the cumulative results of
those changes will be seen by the viewer.

The Mac circuitry generates an interrupt at the end of each horizontal scan
line and at the end of each frame.

During the horizontal sync interrupt, while the electron beam is moving back
from the right edge of the screen to the left, the Mac may send a byte to the
speaker and the floppy motor.  The horizontal retrace is completed very
quickly, so there isn't time to do much.

During the vertical sync interrupt, while the electron beam is moving from the
lower right corner to the upper left corner, the Mac executes procedures in its
vertical retrace queue.  There are system calls for adding and removing
procedures from the queue.

The standard vertical interrupt procedure increments a global variable called
Ticks, a longInt at location $16A.  If you pause in you screen modification
loop until this changes, your screen modification loop will be synched to the
video.

(Don't depend on $16A for the time.  As I discovered when I wrote my menu bar
clock desk accessory, the value drifts slightly so that after ten hours, it
will be a minute or two slow.)

Synching to the video may not be good enough.  If your graphics commands take
more than about 1/128th second to execute, they will still be in progress while
the beam is scanning out the picture, and syncing to the video will just have
traded you intermitant flicker for continuous flicker.  The other way of hiding
the changes from the viewer is to hide the changes from the viewer - draw where
the viewer can't see them and them quickly put them on the screen.  There are
two ways to do this:

1.) Use the Mac's alternate screen.  There is a bit on the Mac's VIA chip that
changes which memory locations are shown on the screen.  You draw on the hidden
one, and when you are done, you make it visible and draw the next frame on the
other one.  The viewer never sees drawing in progress.  This method has
problems:

a.) The stack is right in the middle of the alternate video page.  To begin to
use it, you must move the stack out of the way, and when you are done, move the
stack back.  (There is a parameter to the Launch system call so that when the
program exits, the cleaning up will be done for you, but the only way to use
that parameter is to write one program that launches a second one, so its
pretty useless.)

b.) It takes 22k of memory.  Any program that uses the alternate video probably
won't run on a thin Mac, because there probably isn't room.

c.) The Mac XL doesn't have an alternate video page and future Macs probably
won't.

The second method is the one I prefer:

2.) Do your drawing off screen and use CopyBits when you are done.  Allocate a
new GrafPort, and change the .bitMap field to point to a new bitMap that you
have allocated elsewhere than in screen memory.  Copy the portion of the screen
that is going to change into it, make the changes, and copy it back.  If the
new bitMap is aligned to a byte boundary on the screen, the transfers are very
fast.

-- David Oster, THE unknown hacker.