Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to efficiently render double buffered window without any tearing effect?

I want to create my own tiny windowless GUI system, for that I am using GDI+. I cannot post code here because it got huge(c++) but bellow is the main steps I am following...

  1. Create a bitmap of size equal to the application window.
  2. For all mouse and keyboard events update the custom control states (eg. if mouse is currently held over a particular control e.t.c.)
  3. For WM_PAINT event paint the background to offscreen bitmap and then paint all the updated controls on top of it and finally copy entire offscreen image to the front buffer via Graphics::DrawImage(..) call.
  4. For WM_SIZE/WM_SIZING delete the previous offscreen bitmap and create another one with new window size.

Also there are some checks to prevent repeated drawing of controls i.e. controls are drawn only when it needs repainting in other words when the state of a control is changed only then it is painted e.t.c.

The system is working fine but only with one exception...when window is being resizing something sort of tearing effect appears. Now what I mean by tearing effect I shall try to explain ...

On the sizing edge/border there is a flickering gap as I drag the border.It is as if my DrawImage() function returns immediately and while one swap operation is half done another image drawing starts up.

Now you may think that it is common artifact that happens in many other application for the fact that resizing backbuffer is not always as fast as resizing window are but in other applications I noticed in other applications that although there is a leg between window size and client area size as window grows in size nothing flickers near the edge (its usually just white background that shows up as thin uniform strips along the border). Also the dynamic controls which move with window resize acts jerky during sizing.

At first it seemed to me that using a constant fullscreen size offscreen surface could minimize the artifact but when I tried it results are not that satisfactory. I also tried to call Sleep() during sizing so that the flipping is done completely before another flip starts but strangely even that won't worked for me!

I have heard that GDI on vista is not hardware accelerated, could that might be the problem?

Also I wonder how frameworks such as Qt renders windowless GUI so smoothly, even if you size a complex Qt GUI window very fast negligibly little artifact appears. As far as I know Qt can use opengl for GUI rendering but that is second option.

If I use directx then real time resizing is even harder, opengl on the other hand seems to be nice for resizing without any problem but I will loose all the 2d drawing capability of GDI+.

If any of you have done anything like this before please guide me. Also if you have any pointer that I should consider for custom user interface design then provide me the links.

Thanks!

I always wished to design interfaces like windows media player 11 but can someone tell me that there is a straight forward solution for a c++ programmer (I want to know how rather than use some existing framework etc.)? Subclassing, owner drawing, custom drawing nothing seems to give you such level of control, I dont know a way to draw semitransparent control with common controls, so I think this question deserves some special attention . Thanks again.

like image 584
smit Avatar asked Mar 27 '12 12:03

smit


1 Answers

Could it be a WM_ERASEBKGND message that's causing it?

see this question: GDI+ double buffering in C++

Also, if you need fast response from your GUI I would advise against GDI+.

like image 56
Seb Avatar answered Sep 24 '22 18:09

Seb