2

Is double-buffering still required when Desktop Composition is enabled?

In Microsoft's Application Compatibility Guide:

Graphical Device Interface (GDI)

Prior to Windows Vista and Windows Server 2008, a window handle (HWND) was painted directly to the screen, which had certain benefits, but limited how Windows could display and manage top-level windows. In Windows Vista and Windows Server 2008, all top-level windows are rendered to an off-screen bitmap (similar to WS_EX_LAYERED), and the Desktop Window Manager combines the images together to draw the desktop.

It sounds like all rendering is now done to an off-screen bitmap:

windows are rendered to an off-screen bitmap

Is this correct?

The reason i ask is because i still see flickering during the standard paint cycle:

  • WM_ERASEBKGND
  • WM_PAINT

while desktop composition is enabled:

alt text

i would have assumed that between the calls to

   BeginPaint(hWnd, paintStructure);
   ...
   EndPaint(hWnd, paintStructure);

that all painting would happen to a back buffer:

windows are rendered to an off-screen bitmap

Meanwhile the a front buffer would stay unaffected.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219

3 Answers3

2

Well, painting to an off-screen bitmap just enables the DWM to composite the windows as it likes to without having to wait for the application to redraw (as is the case in XP when you move windows over another, for example).

This does not mean that drawing to that off-screen surface automagically reduces flickering. If you erase the window and then redraw it and between both actions the DWM redraws the screen (which it does around 60 times per second), then of course you will see flickering.

It does solve the "white windows" problem when an application doesn't redraw fast enough and it also reduces redraw due to overlapping windows. But it doesn't help against flickering. The DWM has no way of knowing that your paint operation wasn't complete yet and that you wish to have the old image of the window displayed until after you have drawn the contents again.

Joey
  • 344,408
  • 85
  • 689
  • 683
  • 1
    Given that painting on windows is nicely bracketed between calls to BeginPaint, and EndPaint you would think that the DWM *could* know when its safe to grab an update. – Chris Becke Feb 08 '10 at 21:56
  • 1
    It would have to keep track of this. I suspect, performance considerations are put above possibly half-painted content. – Joey Feb 09 '10 at 13:07
  • 1
    @Chris: There is no requirement for an application to call `BeginPaint` and `EndPaint`. You are describing, how a system could be implemented in a perfect world. This world isn't. – IInspectable May 15 '15 at 12:16
  • 1
    Things go pretty sideways if you DON'T call BeginPaint / EndPaint in response to WM_PAINT. – Chris Becke May 15 '15 at 18:21
  • 1
    @Chris: No, they don't. As long as you make sure to validate the dirty region, through a call to [ValidateRect](https://msdn.microsoft.com/en-us/library/dd145194.aspx). – IInspectable May 15 '15 at 18:38
2

Is this correct?

Yup (which is how the thumbnails can show you parts of the window that are currently obscured).

DWM's rendering of the screen is double-buffered. However, if it grabs your buffer betewen erasing and painting... it's going to show up as a visible artefact. So you still need to double buffer. The double buffering occurs on the desktop (i.e. it draws the next desktop view completely and then flips), not on the off-screen buffers that each window is drawn to.

DrPizza
  • 17,882
  • 7
  • 41
  • 53
  • You both pointed out the same thing: which probably makes it the correct answer. i paint directly to a buffer which is used for painting. If DWM grabs that buffer while i'm half-painted, i'll see half-painted content. – Ian Boyd Dec 03 '09 at 22:09
1

This has changed in Windows 10 (1903, at least).

When DWM is enabled, everything is properly double-buffered now by default. There is no flicker on repaint/resize, even when moving and resizing controls in the most basic way.

The DWM now appears to only present a new bitmap once painting has finished, and not before.

Leo Davidson
  • 6,093
  • 1
  • 27
  • 29
  • 2
    How does DWM know when some painting has finished? I am curious. I'd imagine it'd have to be something `EndPaint` would do -- although then applications not using `EndPaint` (of which there are very many, for better or worse) would be "broken" by DWM. Or perhaps, DWM knows some painting has finished when a window procedure call returns after being passed `WM_PAINT`? Or maybe when `ReleaseDC` is called (which, again, would leave out a number of applications which hold on to their DC(s))? – Armen Michaeli Jun 25 '21 at 19:28