If your application still uses QuickDraw to render content to the screen, the best way to improve the performance of that code its to port it to Quartz. QuickDraw is a deprecated technology in Mac OS X v10.4 and later, which means no new active development for it is taking place. On the other hand, Quartz performance continues to improve as more and more calls are accelerated, both due to hardware and software changes.
If for some reason you must still support legacy QuickDraw calls, there are some performance penalties you should avoid.
Locking the Port Bits
Accelerating Update Region Marking
In Mac OS X, the window buffer is stored in shared memory and is accessible to both your application and the window server. As a result, before it can safely draw into the window buffer, your application must explicitly lock the window buffer to prevent the window server from making any changes to it. After performing its drawing operations, your application must then unlock the buffer to allow other processes to access the buffer.
Some QuickDraw drawing functions, such as LineTo
and FrameRect
do not require any sort of begin/end calls to acquire and release locks. Instead, these routines lock the window buffer before drawing to it and unlock the window buffer afterwards. If your code calls these routines infrequently, you may not notice an impact on performance. However, if your code calls several of these functions in short succession, you may notice a significant performance drop because of the number of locks being acquired.
Acquiring a lock is an expensive operation that requires an inter-process call from QuickDraw to the window server process. Reducing the number of these calls can improve your application performance significantly. You can reduce the number of acquired locks by eliminating these QuickDraw calls from your code or you can acquire a lock explicitly prior to calling them.
The QuickDraw functions LockPortBits
and UnlockPortBits
are responsible for acquiring and releasing locks on the window buffer. Calls to these functions are nestable, but only the first call to LockPortBits
and the last call to UnlockPortBits
cause an inter-process communication to the window server. Thus, if the port bits have already been locked, they don’t need to be locked again. By bracketing your QuickDraw drawing routines with calls to LockPortBits
and UnlockPortBits
, you can eliminate the overhead of repeated calls to the window server. The following example demonstrates this concept:
LockPortBits(GetWindowPort(window)) |
// your QD drawing sequence . . . |
UnlockPortBits(); |
Note: You should not keep the port bits locked for longer than is absolutely necessary. If your drawing sequence takes more than one or two seconds, you should break up the sequence into separate segments, surrounding each segment of drawing calls with calls to LockPortBits
and UnlockPortBits
.
Every call to a QuickDraw drawing routines updates the dirty region with the new area that was modified. If a drawing sequence consists of several short drawing calls to a particular region of the screen, it is sometimes worthwhile to mark the entire region as dirty prior to doing any drawing. Doing this eliminates the need for QuickDraw to update the dirty region with each function call and might save some time. To mark an explicit region as dirty, use the QDSetDirtyRegion
function.
You should use this technique only when you have a large region being drawn into by many calls to QuickDraw routines. You should also measure the performance of your drawing code prior to implementing this technique and verify that the improvement is warranted. If your code already performs acceptably, it might not be worthwhile to go back and calculate this update region in advance.
© 2003, 2006 Apple Computer, Inc. All Rights Reserved. (Last updated: 2006-04-04)