What does CS_SAVEBITS do?


If you specify the CS_SAVEBITS class style, then the window manager will try to save the bits covered by the window. But the real question is why, because that is your guide to using this power only for good, not for evil.

When a window whose class specifies the CS_SAVEBITS class style is displayed, the window manager takes a snapshot of the pixels on the screen where the window will be displayed. First, it asks the video card to store the pixels in available off-screen video memory (fast). If no video memory is available, then the pixels will be stored in system memory (slower). If the saved pixels have not been discarded in the meantime (see below), then when the window is hidden, the saved pixels are copied back to the screen and validated; in other words, the pixels are marked as "good" and no WM_PAINT message is generated.

What invalidates the saved pixels? Anything that would cause those pixels to be out of sync with what should be on the screen once the popup window is removed. Here are some examples:

  • If the popup window moves, then the saved pixels are discarded, since putting those pixels back on the screen would put them in the wrong place.
  • If an underlying window invalidates itself (most commonly via InvalidateRect), then the saved pixels are also discarded, because the underlying window has indicated that it wants to change its pixels.
  • If any windows beneath the popup change size or position or z-order, then the saved pixels are of no use.
  • If any windows are created or destroyed beneath the popup.
  • If somebody calls GetDC for a window beneath the popup and starts drawing.

You get the idea. If copying the saved pixels back to the screen would result in an inconsistent display, then the saved pixels are discarded.

So how do you use this power for good and not for evil?

One consideration is that the region should cover a relatively small portion of the screen, because the larger the saved bitmap, the less likely it will fit into available off-screen video memory, which means the more likely it will have to travel across the bus in a video-to-system-memory blit, the dreaded "vid-sys blt" that game developers are well familiar with. In the grand scheme of vid/sys blts, "vid-vid" is the fastest (since the video card is very good at shuffling memory around within itself), "sys-sys" is next best (since the motherboard can shuffle memory around within itself, though it'll cost you CPU cache space), "sys-vid" is in third place, and "vid-sys" is the worst: Programs write to video memory much more often than they read from it. As a result, the bandwidth between the video card and system memory is optimized for writing to video, not reading from it.

But the primary concern for deciding when to use the CS_SAVEBITS window class style is not making the window manager go to all the trouble of saving the pixels, only to have to throw them away. A window that is a good candidate for the CS_SAVEBITS style is therefore one that does not move, covers a relatively small portion of the screen, and is visible for only a short time. That the window shouldn't move is obvious: If the window moves, then the saved pixels are useless. The other two rules of thumb try to minimize the opportunity for another window to do something that invalidates the saved pixels. By keeping the window small in area and putting it on the screen for only a short time, you keep the "target" small both spatially and temporally.

Consequently, the best candidates for CS_SAVEBITS are menus, tooltips, and small dialogs, since they aren't too big, they don't typically move around, and they go away pretty quickly.

(Some people appear to be under the mistaken impression that CS_SAVEBITS saves the bits of the window itself. I don't know where people get this impression from since even a modicum of experimentation easily demonstrates it to be false. The Windows drawing model follows the principle of Don't save anything you can recalculate.)

Comments (35)
  1. BryanK says:

    The Windows drawing model follows the principle of Don’t save anything you can recalculate.

    Well, except for the pixels behind a window that specified CS_SAVEBITS, that is.  ;-)

  2. Sean W. says:

    In the world of Vista, where the window manager is saving all the bits of top-level windows anyway for things like glass effects and WM_PAINT-less window dragging, is this flag actually relevant anymore?

  3. oldnewthing says:

    Not all Vista machines will be running glass. For example, when running over TS, glass is disabled I believe. If you have questions about how glass changes the rules, you can ask Nick Kramer or Greg Schechter.

  4. Nawak says:

    Raymond:

    "I don’t know where people get this impression from since even a modicum of experimentation easily demonstrates it to be false"

    I made this mistake too!

    The cause seems to be the misleading name combined with the too short documentation (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windowclasses/aboutwindow.asp)

    Granted, there is another article stating what it does but not in the "reference" part of MSDN

    There are also sometimes ‘translation’ problem when someone reads a vague or complicated text in a documentation that is not is his native language

  5. Nawak says:

    @BrianK:

    Ok, my mistake here! But see how firefox displays the page to me:

    http://nawak.free.fr/oldnewthing/msdn_class_styles.jpg

    (In IE, it is unambiguously displayed though)

    Associating only the second part with CS_SAVEBITS, you can see why I qualified the description as vague!

    The non ambiguous page I was refering to was:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_classy32.asp

    (which shows up fine in Firefox)

    Reading the MSDN now, I cannot see how I made the mistake at the time, but I will have to check my old MSDN CDs to see if the style description has not been enhanced with time.

    The style’s description is quite long compared to other’s, leading me to think that it has been clarified and detailed after many people like me were caught! If not… then I was certainly a stupid programmer just judging flags by their names, and not reading docs!

    The documentation is fine now, so I join up with Raymond and wonder how people can make such misinterpretations! ;-)

  6. 8 says:

    For examples 1 and 2, why are all pixels discarded? Surely the pixels could’ve been mapped to the screen coordinates instead of merely associated with the window? So if for instance the window moves, you don’t have to invalidate the saved pixels?

  7. oldnewthing says:

    8: It’s possible that only some of the bits are discarded. I’m not the expert here.

  8. BryanK says:

    Nawak, the article you linked to says this:

    > CS_SAVEBITS

    >

    > Saves, as a bitmap, the portion of the screen image obscured by a window of this class.  <…>

    To me, it seems obvious from that that the WM is saving the pixels *behind* the window, not the window’s pixels (that’s what "obscured by" implies, anyway).

    But OTOH, I’m a native English speaker; it’s maybe not as obvious for someone who isn’t.  That seems to be your point too, I think.  (Though I don’t think that article is vague or complicated.  However, I’m also used to reading manpages, so for whatever that’s worth…)

  9. Mark Steward says:

    I misunderstood it for a short while, because it could be read as

    > Saves, as a bitmap, the portion of the screen image – obscured by a window – of this class.

    i.e. saves an image of a window of this class, when it’s obscured by *another* window.  So if you’re looking for, say, WS_EX_LAYERED, and find this, you’re likely to try it, guessing it’s just an example of badly written documentation.

  10. Eric TF Bat says:

    I remember years ago, in the eighties perhaps, hearing that IBM had taken out a patent on the concept of "backing store", ie saving the portion of the background that’s about to be obscured by an opening window, and restoring it when the window closes.  I don’t know if the patent was approved, but I think that was the point — years before the noble and respected journalists of Slashdot got on the bandwagon — that I realised that patenting *ideas* rather than *processes* was insane.

    Any idea if the patent is referenced by the CS_SAVEBITS issue?

  11. WikiServer Guy says:

    Hmmm, interesting. I was hacking around with java recently and found it actually disables the CS_SAVEBITS style on the native Win32 file dialog.

    So, I guess you need to be careful about this flag even when you are using native dialogs (especially with race issues as well, I guess) :).

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508670

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4189244

  12. Bob says:

    "I don’t know where people get this impression from since even a modicum of experimentation easily demonstrates it to be false."

    Programmpers should not need to experiment to find out what operating system API’s do. It should all be clearly documented, which in the case of windows it usually isn’t. MSDN is terrible.

  13. oldnewthing says:

    Bob: My point was that even if you’re the sort of person who ignores documentation and prefers experimentation, you still should have figured it out.

  14. Michael Sartain says:
    1. it asks the video card to store the pixels in available off-

      > screen video memory (fast).

      > 2. If no video memory is available, then the pixels will be stored

      > in system memory (slower).

      > 3. … the saved pixels are copied back to the screen and validated;

      >

      > One consideration is that the region should cover a relatively small

      > portion of the screen, because the larger the saved bitmap, the less

      > likely it will fit into available off-screen video memory, which

      > means the more likely it will have to travel across the bus in a

      > video-to-system-memory blit…

      I don’t full understand why you would be copying from video to system memory. If it’s too large a bitmap to fit in video memory, wouldn’t it then be in system memory and require a system to video blit? And from my experience in the gaming world, video to system blits are not only very very slow, they can be quite unreliable as well.

  15. Gabe says:

    I’m not sure, but it looks like Sun’s problem was that they were repainting the window from another thread without invalidating the rectangle. Probably the repainted parts got clipped, and the saved bits were put back the way they were because they are discarded by an invalidation (but not just painting in the saved area).

    The proper thing to do would be to have the thread invalidate the area of the dismissed menu rather than just repainting it. If they’re still using this technique, it may cause problems with the new window manager, too.

  16. 8 says:

    What happens if there’s some overlay in the way? Like the WMP windows or the double buffered windows which don’t show up in screenshots? If the bits are discarded for GDI, but not for DirectDraw, could there be a visual artifact?

  17. Michael Sartain says:

    Ok, I gotcha. I apologize for being stupid there. I’m still rather surprised that involving a vid->sys blit would ever be involved in a performance optimization. In the 3D world companies like nVidia have been telling us game developers to avoid it like the plague.

    For example, search for "dramatically hurting performance" here:

    http://developer.nvidia.com/object/General_FAQ.html

    Part of the problems with games and video readback is due to long pipelines and flushing though which Windows, at least right now, doesn’t have to deal with.

    Thanks Raymond.

  18. oldnewthing says:

    8: The window manager can’t "see" overlays (handled by DirectX) or layered windows (handled by GDI). So whatever happens to those bits is DirectX/GDI’s problem.

  19. oldnewthing says:

    Michael Sartain: As I already wrote, "the window manager takes a snapshot of the pixels on the screen" The pixels are on the screen – they are in video memory already. The question is where you put the *copy* of those pixels. If the copy has to go into system memory, then you have a vid-sys blt.

  20. Nawak says:

    Ok so I reinstalled Visual Studio 97 (My IDE at the time) only to find out that "infoviewer" (the integrated msdn help system of VC97) refuses to work on my computer… (Is Internet Explorer too recent? I don’t know, but it couldn’t display anything!)

    Still I managed to extract the MSDN documentation from its closed IVT format with a tool named ivt2html, and after a little bugfix in it, I finally found the doc I had at the time and… it was the same… :)

    I don’t know how I could have misinterpreted it but I did! Maybe I read it the way noted by "Mark Steward", maybe my english was much worse at the time and I made the sense of the description only with the title ‘SAVEBITS’, maybe I couldn’t accept the idea of a flag causing the bits from *another* window to be saved…

    That makes me think: wouldn’t it have been better to name the flag CS_TMPWND or something like that? And leaving the gory details of the window manager’s behaviour out of the way of the application programmer?

    Anyway, thanks Raymond for clearing that up! I won’t make the mistake again if I ever come back to Win32 programming!

  21. oldnewthing says:

    At the bottom of every MSDN page is a "Contact Us" link. And remember, a polite tone is much more effective than a confrontational one.

  22. BryanK says:

    OK, I figured that was a general "contact Microsoft" link; apparently not.  I’ll try it, thanks.

    (Regarding the confrontational tone; you’re right, of course.  I’m not sure what happened; I’m going to guess that I started getting defensive about what I perceived as a "Firefox is crappy because it doesn’t support this colored background thingy, so we’ll hand it this "other" stylesheet" (even though it does support it) web design.  Not that that’s an excuse, though.)

  23. oldnewthing says:

    The "Contact Us" page sends you to different forms depending on what you are commenting about. (And I wasn’t directing the "confrontational tone" thing at you, just a more general piece of advice for anybody else who wanted to send feedback.)

  24. BryanK says:

    Nawak — regarding your reply to me, I use Firefox as well.  But I forgot about the mental workaround I had put in place when I first started using it to view MSDN and I saw the first table.

    I realized at that point that the stylesheet provided to FF must have been different from that provided to IE.  FF gets an "ns6.css" stylesheet, while IE gets one named "ie4.css".  Some information is in both, but not most.

    When I figured out that I was seeing a table, and basically that the contents of each row were centered vertically, I started mentally figuring out where the break between table rows was supposed to be, and taking that into account whenever I read an MSDN page with a table.

    So, if you change your FF user-agent string to whatever it is that IE6 on win2k provides (I have the User Agent Switcher extension installed), you will get the gray background CSS.  (And note that this CSS works *JUST FINE* with FF; MSDN really has no excuse whatsoever to be preventing FF from getting it.)  Also, if you add:

    table.clsStd {

    border: outset 1px black !important;

    }

    table.clsStd tr td, table.clsStd tr th {

    border: inset 1px black !important;

    }

    to the userContent.css file in the "chrome" subdirectory of your FF profile directory, then you’ll get a "normal" table border around the tables and cells; that would probably help as well.  If you know CSS, you can probably modify this to provide the gray backgrounds.

    Raymond, is there some way to file a bug against MSDN that it should be serving the same stylesheet to FF (and NS6, for that matter) as it sends to IE >=4?  Because otherwise, the docs are confusing to people that use FF but don’t know what’s going on with the HTML.

  25. BryanK says:

    Oops, correction.  The IE CSS does not work perfectly with FF — FF doesn’t get a gradient background in the non-documentation frames in that frameset (top and bottom) when its user-agent is set to IE.  Not that I think that’s a huge deal, but the people that wrote the MSDN page probably do.

    Still, MSDN needs to at *minimum* add the background-color rule to the NS6 stylesheet.  If it was a page I controlled, I’d also factor out all the stuff that works in all (graphical) browsers, so that if it gets updated it won’t be missed in one of the stylesheets.  And obviously background-color on a td/th is supported by any graphical browser, so it’d go in there, not in the IE4 stylesheet.

  26. BryanK says:

    (Well, upon re-reading my own comment, I thought it did sound confrontational.  So I did get *a* hint, even if one wasn’t intended.  ;-)  Anyway, whatever; thanks again.)

  27. Nawak says:

    BrianK:

    Thanks! Your tip did work!

  28. BryanK says:

    Ah, user stylesheets.  Aren’t they great?  ;-)

  29. Norman Diamond says:

    And remember, a polite tone is much more

    > effective than a confrontational one.

    Only sometimes.  I think you’re still not quite aware of how Microsoft as a corporation treats its general customers.  A polite tone still gets us nowhere, and after half a dozen repetitions of garbage it’s pretty hard to keep trying to be polite.

    Your blog and blogs of a few of your colleagues have taught me that Microsoft isn’t as monolithic internally as it is in crushing the marketplace.  It took me a long time to learn that, and I apologize to you (Mr. Chen) personally for the length of time it took me to learn that.

    During the past week I had a series of around 6 e-mails with some of your colleagues who are every bit as dense and dishonest as your company ever was.  A polite tone got me nowhere.  I hardly know how to write my next e-mail to them in anything other than the confrontational tone that they have well earned.  Would you like to help?

  30. oldnewthing says:

    I am not Microsoft as a corporation. I am me.

  31. Nobody says:

    In case anyone is still interested, what Raymond said is true: moving the CS_SAVEBITS window will trash all the bytes, it doesn’t do clever stuff to try and reuse anything.

    It’s strange CS_SAVEBITS is used so often. The "About" dialogs in standard Windows apps use it too. Now that I think about it, it makes some sense to use it on modal windows…

    There are certain performance analysis tools for graphics cards which show the amount of available memory, and these things show easily. I would dare to say that memory is seldom an issue, as it’s rather difficult for Windows to use > 32 megs on its own (at 1600×1200), and I’d assume most modern cards have that at least. I already had to do pretty weird stuff to get it to reach 16 megs, which brings us back to circa 2000.

  32. Norman Diamond says:

    Friday, May 05, 2006 10:52 PM by oldnewthing

    > I am not Microsoft as a corporation. I am me.

    Right, OK, I repeat my apology for the length of time it took me to learn that.

    Meanwhile your company continues to demonstrate that your company is still your company.  Being polite got me nowhere.  I’m still trying to figure out a way to write one more polite e-mail on the issue.

    Then there were a couple of bug reports on the MSDN feedback site which your company resolved not to fix:

    one which your company admitted is a bug (reason:  the same admitted bug has been shipping for multiple generations); and

    one for which I sent a screenshot, your company asked questions but ignored my answers, and your company closed the bug report.  Wonder why anyone observes that Microsoft is still Microsoft?

  33. oldnewthing says:

    Complaining to me about the behavior of other people may make you feel better, but it won’t accomplish much else. I’ll assume that you’re just venting and just let slide all your nasty comments.

  34. Norman Diamond says:

    and just let slide all your nasty comments.

    Well sure.  When your company stated that the reason for not fixing an admitted bug is that the same bug has been shipping for multiple generations, your company did word it politely.  When your company appended a false statement to that one, your company worded the false statement politely too.

    Politeness gets me nowhere, frustration gets me nowhere, and nastiness gets me nowhere.  Nonetheless may I suggest that it is human nature to get frustrated by a lot of that garbage, it is human nature for frustration to turn into nastiness, and some of us aren’t quite sure whether nastiness is really more offensive than lies.  Though it must be admitted that lies will get you somewhere while nastiness won’t.

  35. The background behind a poorly-understood function.

Comments are closed.