[comp.sys.mac] Follow Up, QuickDraw Performance

pjw@usna.MIL (Prof. Peter Welcher) (02/26/90)

This is a summary of replies I got on QuickDraw performance enhancement,
plus some comments. I ran out of editing time, apologies for
redundancies. Thanks to those who replied.
----------------------------------------------------------------------
1. (More MPW C vs. LSC) There is a port of GNU to MPW in progress. This
   may help some.

2. Offscreen drawing and CopyBits are most often used to reduce "flashing".

   [I redid my benchmark (lotsa text), and offscreen drawing
   apparently helped enough to more than offset the CopyBits cost.]

3. Question someone asked: are regions or polygons faster ? C vs. Pascal ?
   By how much ? [I don't know.]

4. I'll let Robert Dorsett <rdd@walt.cc.utexas.EDU> speak for himself:
	Off-screen bitmaps are mainly useful when:- 
		(a) you don't want to annoy the user with flicker (for example,
		drawing a map from scratch vs. simply copying it to the screen),
		and 
		(b) when you have animation applications (already-prepared bitmaps
		which you have to copy to the screen).  
	In both these cases, using Copybits is faster than drawing an object
	from scratch over and over.
		A third case would be not annoying the user with a time-consuming
	operation:  just display a "wheel" or a clock whenever an image is
	being built, but don't show it to him until it's finished.  Users
	expect to be able to manipulate any object that's visible on the
	screen.
		It all depends on what you're trying to do.  Quickdraw
	line-drawing *is* very fast (just compare it to the Sun graphics
	tools, for example).  Approaches to text can vary.
		Try reading Artwick's "Applied Concepts in Microcomputer Graphics"
	(recently retitled "Microcomputer Displays, Graphics, and
	Animation").  Foley & Van Dam's "Fundamentals of Interactive Computer
	Graphics" has more on the human side of human interfaces.  Rogers'
	"Procedural Elements in Computer Graphics" has various routines--but,
	in general, you won't be able to improve Mac speed much.  Quickdraw IS
	very quick.
		In general, try to differentiate the difference between
		(a) providing the illusion of speed;
	and (b) actually providing quicker options.
		In many cases, (a) is often more impressive than (b).  (b)
	(especially in animation) can be really ugly.
		The Mac is not a high-performance graphics system, period.  You
	won't be able to carry out high-performance animation until the Mac
	supports sprites, DMA, and maintains a separate graphics processor
	(the first two of which the Amiga has supported since 1984, so I can't
	imagine the engineering challenge is that great).

	[Comments: I tend to agree with the remarks about use of off-screen
	bitmaps. I note that they're memory hogs. It is also wise to recognize
	that QuickDraw has a real performance-tuning edge, and degree of
	testing, that would be hard to match. There's also the issue of
	compatibility with various screens, future developments, etc.]

	[The 'illusion of speed' is a point well taken. On looking at my
	code, I realized that cell highlighting was unnecessarily slow,
	and greatly improved it. This in turn makes the whole thing
	feel a lot faster. THANKS !]

5.  Tom Dowdy of Apple points out:

	... For some people, it isn't the speed of drawing exactly, but the
	fact that they would like the drawing to appear all at once for
	animation purposes.  For *really* high end applications that do their
	own rendering into a pixMap, using an offscreen area and then blitting
	it *can* speed up drawing because of NuBus timing, especially when
	using modes such as XOR that require reading of the destination
	pixMap.  It doesn't *sound* like offscreen areas will help you in your
	case, but I can't say for sure.

	1) When you get an update event, *only* draw those objects that are
	within the update area.  Don't draw ALL objects on the page.
	QuickDraw is pretty fast at clipping out unneeded objects (you *DO*
	call BeginUpdate() EndUpdate() don't you?), but better not to draw
	them in the first place.  And remember that accessing your object data
	base adds additional time.  This may be all it takes to speed things
	up.  You don't have to get into region clipping.  Get the rectangular
	bounding box of the update region and use that.  There should be a
	relativly painless way to figure out which of your cells to draw from
	the rectangle.

	[Yes, I'm doing this. But I'm in a situation where whole screen
	redraw is the issue.]

	2) OR mode is faster than COPY for some operations, the other way
	around for others.  Make sure you are doing the minimum amount of
	work.  
	[I'm doing this already.]

	3) If you have constant things, such as grid lines, you might combine them 
	into a picture and draw them with one QuickDraw call.  Another possibility 
	is to create a picture for a single cell (or two sides of the cell), and 
	then DrawPicture into each rectangular area, using QuickDraw picture 
	scaling to get the right size.  I assume that like many spreadsheet type 
	applications, your cells can be of varying sizes.

	4) Always do drawing through the update event.  This avoids two
	problems:  a) dead drawing areas and dropouts due to bugs and b) the
	user can do multiple actions (such as menus) before the update happens.

6. From: Dave Green <daveg@APPLE.COM>

	if you have one trap that you call MANY times you can get the address
	of the trap from the dispatch table and call it directly.  This saves
	the overhead of the dispatcher.  (can be helpful in a tight loop)
	[This helped about 1% or less.]

	I have never done comparisons with off-screen stuff.  It has been easy
	enough that I never considered the straight-forward onscreen
	versions.  If nothing else, it is easier to avoid flicker. (you only
	have to synch one copybits to the screen retrace instead of all of the
	graphics primitives)

	[That's a good explanation for my recent benchmarking showing an
	edge of around 10% for offscreen drawing and then CopyBits.]

	that's all that I can come up with off of the top of my head other than the
	normal stuff about algorithms and integer math....  I'm always interested in
	such stuff, so please forward me any new info you come by.

	by all means, take advantage of the new calls available in 32 bit
	quickdraw if feasible for your application.  They really do make the
	off-screen world liveable.  In addition it has things such as
	BitmapToRegion which is way cool.  When you first start, you may be
	tempted to rewrite the whole graphics kernel of the macintosh, but you
	will slowly begin to realize that most of the bottlenecks are
	optimized quite well and by using them you will gain compatibility
	with many many strange systems to come. (ever think about the strange
	things that can happen when you have 2 monitors...  b&white & color??)

	[Definitely !]

7. From: lsr@apple.COM

	...(offscreen bitmaps) ... One use is to eliminate flicker which can
	give the impression that things are running faster. You batch a bunch
	of changes by writing offscreen and doing one CopyBits on screen.
	CopyBits is very fast if the source and destination bitmaps (pixmaps)
	are aligned.

	Then there is a standard space/time tradeoff.  If you maintain your
	entire image offscreen, you can implement scrolling using a single
	CopyBits call rather than a call to ScrollRect followed by processing
	an update event.  

	[Can't, the image changes.]

	ScrollRect is useful because it reuses the bits that have already been 
	drawn on the screen, on the theory that generating the bits takes a long 
	time.  If you cache the entire screen image offscreen than you don't need 
	any time to generate the bits.

	[Am using it to the max.]

	Some things to keep in mind are that each QuickDraw call requires a
	fixed amount of overhead, so if you can minimize the calls you will
	come out better.  (This is why drawing grid lines instead of outlining
	each cell is better.  For the same reason, drawing a bunch of
	characters at once is better than single characters.)

	If the loop overhead of drawing the lines is significant, then you
	could draw them into a QuickDraw picture and just use DrawPicture to
	draw the grid lines.  This eliminates all the loop overhead.  You
	might be able to use pictures in other places, but they can't be
	edited easily, so they are most suitable for static drawing.

	[Exactly: they're only useful if you're going to repeat the same
	drawing a lot.]

7. From: Matthew Hills <c60a-3ec@WEB.berkeley.EDU>

	Re offscreen bitmaps, they are best when:

	1) You are doing relatively simple drawing that
	can be done fastest with your own algorithms.  A good example is point
	plotting in a Mandelbrot set.  Since you can avoid all Quickdraw's
	clipping and recording code you can go
	very fast.

	2) You want to update the screen relatively infrequently when compared
	to how often you want to update the bitmap.  Thus, the high cost of the
	CopyBits (who still has to go through all the clipping/recording/
	translation/ colorization) is infrequent and is amortized over a lot
	of your own drawing.

	Lines can be drawn offscreen quickly.  Text cannot.  Minimize the
	amount of drawing you do, and make sure you're using the fastest
	drawing modes.  For example, TextMode(srcCopy) is significantly slower
	than TextMode(srcOr).  So, it behooves you to arrange things so that
	you can draw in srcOr.  Never re-draw anything that's already correct
	on the screen.

	Or, like Excel, arrange so that your screen update can be interrupted
	by fresh input so that it doesn't matter so much how long it takes.
	The user doesn't have to wait for more than one full update if he's
	willing to run 'blind' for a bit.

	[Draw-it-yourself is admittedly faster, at least in simple cases or
	tight loops, but suffers from some obvious problems. Fonts are the
	real problem with this approach.]

Thanks to all.