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.