[comp.windows.x] fast, flicker-free animation, how?

robert@shangri-la.gatech.edu (Robert Viduya) (11/02/90)

I'm working on a program that animates some simple geometric entities and
displays them in a window and I'm having trouble getting X to update quickly.
The environment is a Sun SparcStation I with a cg3 (8-bit plain framebuffer)
running OpenWindows 2.0.  Drawing the entities doesn't take any significant
time but getting X to display them quickly seems to be a big stumbling block.
I've tried three different methods:

	Draw directly into the window, clearing it to the background color
	before starting to draw.  This is the fastest and I get about 14
	frames per second.  However, because of the clearing and redrawing,
	the window flickers rather annoyingly.

	Draw into an offscreen pixmap and then use XCopyArea to put it
	into the window.  This is the slowest and I get about 4 frames
	per second.  It does, however, produce no annoying flicker.

	Split the 8-bit deep window into two overlapped 4-bit deep buffers
	and create two colormaps; the first displays the first 4-bit deep buffer
	and maps the second to the background color and the second colormap
	displays the second 4-bit deep buffer and maps the first to the
	background color.  To draw an image, first load the colormap that
	displays the buffer you are NOT going to draw into, then set the
	gc planemasks to the buffer your are going to draw into.  When done,
	swap the colormaps and planemasks.  This produced about 6 frames
	per second with the annoying side effect of causing all other
	windows on the X screen to flicker like crazy because of the colormap
	switching.  It may have worked even faster if the window manager
	wasn't involved (the window manager is the program who's responsible
	for installing colormaps into the server, X clients submit requests
	to the window manager to have their colormaps installed).

Has anyone got any other techniques to try?

			robert
--
Robert Viduya					   robert@shangri-la.gatech.edu
Technical Services / Office of Information Technology
Georgia Institute of Technology					 (404) 894-6296
Atlanta, Georgia	30332-0275

asente@adobe.com (Paul Asente) (11/02/90)

In article <16223@hydra.gatech.EDU> robert@shangri-la.gatech.edu (Robert Viduya) writes:
>I'm working on a program that animates some simple geometric entities and
>displays them in a window...
>Drawing the entities doesn't take any significant
>time but getting X to display them quickly seems to be a big stumbling block.
>I've tried three different methods:
>
>	Draw into an offscreen pixmap and then use XCopyArea to put it
>	into the window.  This is the slowest and I get about 4 frames
>	per second.  It does, however, produce no annoying flicker.

How big is your image?  Unless your X implementation is extremely bad, you
should be able to do much better than 4 frames per second this way for
"moderate" sized windows (say, 400x400).

I have an application that essentially bounces around a 100x100 object within
a 400x400 window, and I get about 72 frames per second on a DECstation
5000, using Display PostScript to do the imaging into the pixmap.  You have to 
be a little bit clever and set the clipping region not to update parts of the
window you're not changing.  I can update an animation where the entire 400x400
window is changing at about 36 frames per second.

	-paul asente
		asente@adobe.com	...decwrl!adobe!asente

robert@shangri-la.gatech.edu (Robert Viduya) (11/02/90)

>asente@adobe.com (Paul Asente) (asente@adobe.com, <7898@adobe.UUCP>):
> In article <16223@hydra.gatech.EDU> robert@shangri-la.gatech.edu (Robert Viduya) writes:
> >
> >	Draw into an offscreen pixmap and then use XCopyArea to put it
> >	into the window.  This is the slowest and I get about 4 frames
> >	per second.  It does, however, produce no annoying flicker.
> 
> How big is your image?  Unless your X implementation is extremely bad, you
> should be able to do much better than 4 frames per second this way for
> "moderate" sized windows (say, 400x400).

The image is 800x800 and since it's an 8-bit deep visual, XCopyArea has to
move 640K bytes of data.  I'm not sure if the cg3 framebuffer is natively
an XYPixmap or a ZPixmap.  I would hope it's a ZPixmap, but the way it updates
windows seems to indicate that it's an XYPixmap.  Whenever an entire window
gets drawn, like when an xterm scrolls or an XCopyArea for the whole window
is done, there are two small areas, one on the extreme left and one on the
extreme right that get updated AFTER the rest of the window is updated.  The
areas extend to the full height of the window and the width seems to vary
depending on where the window is on the screen.  This leads me to suspect
that the server is having to do some sort of data alignment; it moves bytes
when it can and then moves bits when it has to.  It shouldn't have to do this
on an 8-bit deep, ZPixmap type framebuffer since every pixel would be on a
byte boundary.  It WOULD have to do it on an 8-bit deep, XYPixmap type
framebuffer.

Oh yes, the width of the two areas is sometimes larger than 4 pixels, so I
don't think it's aligning bytes to word-moves.

		robert
--
Robert Viduya					   robert@shangri-la.gatech.edu
Technical Services / Office of Information Technology
Georgia Institute of Technology					 (404) 894-6296
Atlanta, Georgia	30332-0275

keith@EXPO.LCS.MIT.EDU (Keith Packard) (11/03/90)

> > How big is your image?  Unless your X implementation is extremely bad, you
> > should be able to do much better than 4 frames per second this way for
> > "moderate" sized windows (say, 400x400).

> The image is 800x800 and since it's an 8-bit deep visual, XCopyArea has to
> move 640K bytes of data.  I'm not sure if the cg3 framebuffer is natively
> an XYPixmap or a ZPixmap.

It looks to me like you're running OpenWindows 1.0, unless you have a GX.  For
raw data copying, you should get about 8 frame per second with the MIT R4
server.  On the CG3, running OpenWindows 2.0, you should get similar
performance.  OpenWindows 1.0 would only have given you about 3 frames per
second on the cg3, or about 5 frames per second on the GX.

Here is the relavant data from x11perf Copy 500x500 pixmap to window:

		MIT	OW1.0	OW2.0
	CG3	22.3	8.4	17.3	
	GX	18.2	13.5	??

(Except for the OW2.0/CG3 number, all of these were measured by me and are
presented here for purposes of illustration only. i.e. your mileage may vary)

I scaled these numbers by the ratio of the areas between the measurement and
the application (500x500 / 800x800) to get estimates on the performance of
your application.

So, you see that the variety of performance available is very dependent on
both the hardware and software available.

Even still, by careful limitation of the region copied, you can drastically
reduce the time it takes to update your image.  Multiple small copies will run
faster than one large one.

mouse@LIGHTNING.MCRCIM.MCGILL.EDU (11/05/90)

> I'm working on a program that animates [...].  Drawing the entities
> doesn't take any significant time but getting X to display them
> quickly seems to be a big stumbling block.  I've tried three
> different methods:

>	Draw directly into the window, clearing it to the background
>	color before starting to draw.  [fast but flickers]

>	Draw into an offscreen pixmap and then use XCopyArea to put it
>	into the window.  This is the slowest and I get about 4 frames
>	per second.  It does, however, produce no annoying flicker.

I hope you are being careful to clear only the bounding box of the
union of the two pictures....

>	Split the 8-bit deep window into two overlapped 4-bit deep
>	buffers and create two colormaps;

Instead of using two colormaps, cut the window manager out of the loop
and use just one colormap, but change its contents.  I don't know
whether this will help or not, but it is probably worth trying.

Also, if you use few enough colors, don't make the pieces a full four
bits deep - you have fewer cells to modify in the colormap if you make
them shallower, like two bits (sixteen colormap cells need changing) or
three bits (64 cells).  If you don't need the whole colormap you can
also allocate out of the default colormap instead, thereby avoiding
technicolor flashing of the rest of the screen.

If you can, fiddle with the GC's function and fg/bg values instead of
using the plane-mask; this may speed things up (I seem to recall that
using nontrivial plane-masks is often very slow).

> Has anyone got any other techniques to try?

Did you try the Multi-Buffering extension?  (I haven't; I suspect it
amounts to your second method, but it may be worth a shot.)

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu