locked
What's the state of the art for VSync with GDI+ / Windows Forms? RRS feed

  • Question

  • It appears that there is still no trivial way to sync to vertical refresh for GDI+ animation in windows forms.  Why not?  In my mind, this is such a fundamental service to be provided by an OS.  Why is it not there yet?  (Or is it?)  It seems that decades have rolled by and there's still nothing simple available to do animation.
    Sunday, August 14, 2011 12:26 AM

All replies

  • The OS APIs are for you to automate the OS and nothing else. Windows trust programmers to be smart enough to write their own code or find a component if there is one available. e.g. you don't get an API to do simple math, which is much more fundamental than GDI+ animation.

    GDI+ is performed on Direct3D surface provided by DWM on modern versions of Windows, that is, if desktop composition is not disabled. So you should not worry about vsync by yourself. If there is a problem between the hardware and DWM, there is not much you can do. You can opt-out desktop composition but that slows down the whole system.

    I have seen approaches that depends on spending frame time on extra polling or want for sync, not something I would do because the double-buffering performed by DWM.



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP

    • Marked as answer by Wyck Sunday, August 14, 2011 10:51 PM
    • Unmarked as answer by Wyck Thursday, November 29, 2012 5:00 PM
    Sunday, August 14, 2011 10:27 PM
  • Although it has been quite some time (about a year) I find Sheng Jiang's response unsatisfying.

    There is no explanation of how you do draw something in an animated way with windows forms.  ... and by that I mean, how can you draw a bouncing ball or something simple but still be sync'd to the vertical refresh so as to eliminate tearing?

    Thursday, November 29, 2012 6:48 PM
  • You'd switch to DirectX-based UI technology if you want to get vsync. In modern versions of Windows, if desktop composition is not turned off, your GDI program would draw to a memory surface where there is no refresh rate. Windows then decides when to flip the surface to the video memory. This problem isn't fixable as long as you are using GDI-based UI technology such as Windows Forms.


    Visual C++ MVP

    Thursday, November 29, 2012 8:40 PM
  • Greg Schechter's article was informative.

    But what's the state of the art technology to use then for a UI that does animation?  Every application that wants to have tearing free animation should be written with ... what?  DirectX?  That's cumbersome!

    So what about Windows forms then?  Is it just a waste of my time?  I mean, it would be nice if a form could scroll or paint without tearing.  Why is this problem not fixable?

    Saturday, December 1, 2012 9:15 PM
  • Yeah other people do have animation in Winform applications, but not to the vsync rate you demanded. Your problem is not fixable because DWM refreshes composed desktops, not individual windows, at a rate it saw fit. If Windows can't get the desktop to refresh at the rate you requested (CPU too slow? Low end Video card?Too many window opened?), your winform app can't get more update frequency than the desktop. The walkaround would be either upgrade the computer or make your application more efficient, for example have less work to begin (what is the difference between 60fps and 30fps to a human eye?), move calculation to another thread or even a server, or have GPU to do some of the drawing work (use DirectX based GUI frameworks like WPF), and reduce the less than ideal situation where application paint cycle takes longer than a monitor refresh cycle. As DWM max out at the VSync rate (DWM is smart enough to not compose more frequently than what the screen is capable of drawing), you won't see a refresh rate at vsync rate unless you make a full screen exclusive mode application, so the ultimate solution requires you to abandon Windows Forms. 



    Visual C++ MVP




    Saturday, December 1, 2012 10:06 PM
  • Are you saying that, thanks to the DWM, it's now impossible to update the contents of a window without tearing?
    Sunday, December 2, 2012 3:08 PM
  • "without tearing" is not the same as refreshing at vsync rate. You won't notice a tearing occur if you miss a frame or two. Remember human eye can only recognize 24fps, so even if you miss the 36 frames out of 60 you are still OK. And it can happen even if you are drawing once per second, if your GPU is occupied by another program or simply has a buggy driver that even switching to DirectX won't help in improving the tearing situation.


    Visual C++ MVP

    Sunday, December 2, 2012 4:00 PM
  • "without tearing" is not the same as refreshing at vsync rate. You won't notice a tearing occur if you miss a frame or two. Remember human eye can only recognize 24fps, so even if you miss the 36 frames out of 60 you are still OK. And it can happen even if you are drawing once per second, if your GPU is occupied by another program or simply has a buggy driver that even switching to DirectX won't help in improving the tearing situation.


    Visual C++ MVP

    I never said anything about frame rate.  I said "vsync", which is literally an event synchronized to the vertical blanking interval, and "animation", which, in this case, is the updating of the contents of a window. I only need to avoiding tearing.  Please stop talking about frame rate.  I'm talking about tearing, which is the act up updating the frame buffer (the bitmap data from which the video generator is generating a video signal), after part of the bitmap has already been rasterized to the current frame of video, resulting in a horizontal tear in the video.  To overcome this you have to coordinate the updating of the bitmap data used by the video generator with the timing of the video generator, meaning that you should not end up with fragments of image data from two different moments in time generated to the same frame of video.  The preferred way to do this is to update the framebuffer data/pointer during the vertical blanking interval (a.k.a. vertical refresh.)

    [OFF TOPIC:  And for what it's worth, it's very well known that people can perceive the difference between 24 and 60 frames per second.  See for yourself.]

    What you were saying about the DWM is interesting, but it actually sounds like it solves the problem, as opposed to making what I'm talking about impossible.  I can't believe there's a design flaw of Windows or the DWM that somehow makes this impossible.  So you're not getting the point of what I'm saying.  I feel misunderstood and I'm not finding those last responses helpful.  I'm particularly frustrated by your response about 24 fps vs 60 fps.  It's wrong and now I'm having a hard time trusting what you're telling me.

    I'll try to explain one more time.  Because you did say that "other people do have animation in Winform applications, but not to the vsync rate you demanded".  So I'm hoping you can focus on the part where "other people do have animation" and hopefully you can tell me how they do it in such a way that it's free of tearing.

    It's possible to update the pixels on the screen (even in just a window) such that you don't get data from two different moments in time rasterized to the same frame of output video.  I'm wondering what way to access that functionality through Windows Forms or GDI.  [Or, if no such mechanism exists, why it's impossible for Microsoft to have created one?]


    Monday, December 3, 2012 2:30 PM
  • I suggest you use WPF instead of winforms. And in combination to WPF use slimDX to do the drawing, which will enable you to use vSync. And give you a 'relative' easy way to get some animations on your screen.
    Monday, December 3, 2012 2:44 PM
  • I can't imagine that this question is still relevant to you, but hopefully it might help someone else in the future. I'm not sure if this answers the GDI+ part of your question, but here's a method I found for VSynching a windows form:

    The solution I found was to use OpenTK (which is OpenGL's C++CLI API). Once installted, this gives you a design mode component called GLContent. This object is effectively a panel whose paint function you can manipulate using OpenGL-esque functions.

    Throw this into the form that needs Vsynching, then can go to this component's options in design view and set the vsync value to true. This doesn't actually work by itself, since the auto-generated constructor for your GLContent is shoddy, but if you change the constructor of the GLContent from this (in initialize component):

    this->image = gcnew OpenTK::GLControl();

    to This:

    OpenTK::Graphics::GraphicsMode^ temp;
    temp = gcnew OpenTK::Graphics::GraphicsMode(ColorFormat(16,16, 16,16), 16, 0, 0, ColorFormat(16, 16, 16, 16), 3 , false);
    //this->image = gcnew OpenTK::GLControl();
    this->image = gcnew OpenTK::GLControl(temp);

    ..You'll break design mode (Just posted my own question about this part). However, you'll also have a vsynched windows form. At least I think you do; I tested this by running a loop with no blocking statement other than Form1->Refresh, which caused the entire GLControl's color to change. Without the above code, it ran 260 or so times and had noticeable tearing. With this code, it ran at whatever refresh rate I set my monitor to, and showed no tearing.

    Hopefully this helps.

     
    Friday, July 11, 2014 3:04 PM