• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag
 

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSScrollView bug or misunderstood behavior?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSScrollView bug or misunderstood behavior?


  • Subject: Re: NSScrollView bug or misunderstood behavior?
  • From: Erik Buck <email@hidden>
  • Date: Sat, 11 Nov 2006 15:01:49 -0500

Short answer: misunderstood behavior.

You are touching on several fundamental aspect of the Quartz Window server architecture and AppKit. There are lots of documents on this subject and several third party books including "Cocoa Programming" which I happen to know describes these things. You aren't reading the available documentation, and I like to describe things without re- reading to refresh my memory, so here is an explanation based on my understanding that may or may not be completely correct. If my answer doesn't appeal to you, I recommend that you consult the aforementioned documentation that I am not consulting :)

The Quartz Window Server manages the graphics card's frame buffer as well as the "backing store" for all windows whether they are visible on screen or not. The backing store for a window is the memory used to store the bitmap representation of the entire window including its frame.

All drawing within a graphics context (with the possible exception of OpenGL contexts) actually modifies the backing store for a window. The Quartz Window Server then "flushes" the visible portions of the backing stores for all on-screen window into the graphics card's frame buffer. Quartz Extreme is a technique that uses hardware accelerated OpenGL texture mapping to perform the copying of backing stores into the frame buffer as opposed to using a CPU for the memory copy. Thus, the Window server manages all window layering. Special effects such as shadows and genie effects are just modifications to the way backing stores are copied into the frame buffer. The rotating cube effect when users are changed is produced by using the frame buffer's of two different screens as the sources for OpenGL textures used by Quartz Extreme.

See the "Flushing graphics" section of the NSWindow documentation for some interesting tips.

There are several advantages to this Quartz Window Server architecture:
Full window drag, window re-layering, window hiding and restoration, window transparency, and neat window miniaturization effects are implemented entirely within the Window Server and individual applications are not bothered with routine drawing needs. For example, the Window Server manages redrawing of window backing stores into the frame buffer when a window is uncovered: the application that owns the window does not need any processor time to handle this. Contrast this to MS Windows XP where when a window is uncovered, the owning application has to redraw the revealed window contents. If the owning application is busy, the screen is not updated correctly and the user sees graphical "turds" e.g. incomplete inconsistent drawing is visible on screen. Heaven forbid the Windows Explorer locks up and practically nothing draws correctly on Windows. On the Mac, even a locked up application's windows can be hidden, revealed, etc.


The primary disadvantage to the Quartz Window Server architecture is that is uses memory for the backing store of every window whether the window is visible or not.

So, Quartz should never leave "turds" on the screen, but it uses more memory that other window servers.

Note: Nextstep used to support unbuffered and "retained" window backing store schemes as well as "buffered". Interface Builder (last time I looked) still preserves these options, but I don't think they do anything on OS X. I think Cocoa buffers all windows regardless of the setting.

Now, given that window backing stores exist, there are several possible optimizations within applications. One is image caching from the backing store. See the "Bracketing temporary drawing" section of the NSWindow documentation. Another is the similar "copies on scroll" optimization.

NSClipView's - (void)setCopiesOnScroll:(BOOL)flag method is used to tell the clip view whether it should implement scrolling by copying a portion of the window's backing store to another location and then asking the document view to redraw only newly revealed areas. The alternative requires the document view to redraw the entire visible area including the areas that were already visible before. Copy on scroll is normally disabled when the clipview does not draw a background and the document view is not opaque. Otherwise, stray bits of the window's backing store might be drawn incorrectly.

So, to answer your question, copy on scroll is implemented using the the window's backing store. The effect you are seeing is presumably caused by trying to use copy on scroll with a document view that is not opaque and no background drawing.

There are several ways you can improve behavior:
1) Triple buffer: Have your document view draw into a bitmap image. When the document view is asked to draw, just composite from the bitmap image rather than redrawing from scratch. Disable copy on scroll. This approach requires more memory because there will be three buffers total: Your custom image, the window's backing store, and the frame buffer. However, it should be as fast as copy on scroll while enabling you to do "strange" things with expensive_to_draw views.
2) Use an overlay window (child window): Let the Window Server do the work for you by using an additional window and therefore an additional backing store. Put whatever transparent drawing you want in a child window that is layered correctly. The Window Server will composite from both layered windows to produce the final result in the frame buffer. You can have a transparent document view layered above the child window or visa versa. It's all good to the Window Server. I use this technique to layer Cocoa controls over pure OpenGL drawing all the time.
3) Take over the tiling of the enclosing scroll view. This is how rulers and scroll bars are implemented already. If you search the net, you will find examples of how to do this that date back to the Nextstep days. Just search for NSScrollView and tile.
4) Add a non-opaque subview to the scroll view and tell the subview - setNeedsDisplay:YES every time the scroll view's -tile method is called. I suspect having a non-opaque subview will defeat the copy on scroll behavior anyway, but it should produce the correct results on screen.
5) Tell us what you are really trying to achieve, and we may be able to suggest other techniques. If this is just about water marking, you are making it all way too hard.


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: NSScrollView bug or misunderstood behavior?
      • From: Ivan Kourtev <email@hidden>
  • Prev by Date: Re: How to get user ID (501, 502, etc.)
  • Next by Date: Modify view animation while running
  • Previous by thread: NSScrollView bug or misunderstood behavior?
  • Next by thread: Re: NSScrollView bug or misunderstood behavior?
  • Index(es):
    • Date
    • Thread