views:

396

answers:

3

I was reading Larry Osterman's latest blog post about debugging a flickering problem in the Windows Vista/7 volume control, and I suddenly realized that I can't recall ever seeing an application flicker on my OS X laptop. Even applications that otherwise seem to be poorly written avoid the flicker problem in my experience. Without this turning into an Apple vs Windows debate (please), why do OS X applications not seem to have the same flickering problem?

I have trouble believing that Apple developers are simply amazing at programming flicker-free GUIs, while Windows programmers suck, so what's the reason? Does the OS X API require all GUIs to implement double-buffering? While some apps have the slightly sluggish double-buffered resize behavior, many don't, and they still avoid flickering. Is the OS X repaint flow somehow fundamentally different from Windows, avoiding the WM_ERASEBKGRND problem entirely? Or is there some other possibility that I'm not seeing?

Update: Thank you for your answers. I wish I could select both ken and cb160's answers, because they are both helpful.

+12  A: 

Mac OS X has double buffered windows.

You don't have to do anything to make it happen. It's behind the scenes.

You (almost always) don't explicitly draw to a window in Cocoa when something changes, you invalidate a region of the window. The framework will later descend the hierarchy of views and draw the dirty regions of the window into a secondary buffer. Then it swaps the buffers.

You can optionally make some promises that allow the framework to take shortcuts when redrawing, but they're all opt-in. Only savvy views are affected.

If your subclass of NSView implements the isOpaque method to return YES, then the framework will never clear anything behind your view or draw any of the views under it.

Implementing preservesContentDuringLiveResize to return YES gives you some extra responsibilities, but can improve performance during window resizing.

10.6 added another two new APIs of this sort, layerContentsRedrawPolicy and layerContentsPlacement.

Last, custom drawing is less common than on Windows. The majority of views you see are framework-supplied and not subclassed. Framework-supplied means optimized-by-apple.

Ken
+1  A: 

Yup, it's all double buffered automagically. Of course, if you are running legacy code from mac os 9, or code ported from windoze, that mean's you're probably triple buffering without knowing it. Hey, cycles are cheap!

ddyer
+4  A: 

Both Windows Vista/7 and OSX use compositing engines to draw rasterised bitmaps on the screen. These compositing engines are responsible for processing output from all windows and drawing the final screen image. This compositing approach is how OSX is able to use the genie effect when minimizing to the dock and how aero draws the translucent borders. They also prevent flickering as if the bitmap to fill a particular area of the screen is not available, it will use the image it has already rather than drawing a blank region.

OSX has had a compositing engine since it first shipped. At the time, lots of people though this was a crazy appraoch as all the video cards shipping at the time wer optimized to draw bitmaps (ie, windows buttons and borders) and not composited images. In later versions of OSX, the compositing was pushed off to the GPU (in Quartz Extreme)and so took significant load off of the CPU and made more effects possible.

Because the Windows compositer was only added in windows Vista and then only when there was a GPU available and you had the right version of the OS, it is not as pervassive as the Quartz Compositer in OSX. Because the compositer is not always used in Windows, flickering will occur when a region is blanked and the application responsible for drawing is not able to redraw the region qucikly enough.

Robert Christie