1

I'm trying to move a small image from the left side to the screen to the right side.

I set the styles for the usercontrol to:

    this.SetStyle(ControlStyles.Opaque, true);
    this.SetStyle(ControlStyles.UserPaint, true);
    this.SetStyle(ControlStyles.ResizeRedraw, true);
    this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

In my OnPaint handler I draw the object to a BufferedGraphics instance, which is my off-screen buffer, and then BitBlt the result to the e.Graphics reference using a single call.

So it seems I did everything by the book, to have ultra-smooth flicker-free drawing, and STILL i can see the object stuttering a little.

So there are bascily two possibilities left: either the Timer that is calling .Invalidate(DirtyRect) is not firing exactly at a constant interval, causing the object appear to stutter, or BitBlt doesn't work as expected.

Does anyone have any idea what could be the problem?

UPDATE: On second thought, it looks more like tearing, than stuttering or flickering. Because sometimes the object seems to miss the last few pixels. I will look into the possibilities to draw on VSYNC.

Maestro
  • 9,046
  • 15
  • 83
  • 116
  • Do you see stutter or flicker? Also, it would be useful to see repro code... – usr Jan 28 '13 at 18:35
  • @usr It's very hard to tell. Currently it's just a red line moving across the screen, and I can see it's not completely smooth. I guess it's tearing, because the line is 2 pixels wide, and during those moments it seems like only 1 pixel wide. I did some research and there is no way to draw on VSYNC in WinForms, so I guess I'm out of luck. – Maestro Jan 28 '13 at 18:43
  • a red line moving on a TFT monitor is probably blurring due to latency of the TFT or eye. Would that be consistent with your observation? Try capturing a screenshot to confirm the line is actually 2px wide for a moment. – usr Jan 28 '13 at 19:20
  • @usr I already tried taking screenshots of the problem, and there it never appears, but it could be Windows captures screenshots on a suitable moment (between vertical-sync). Also, the problem is not that the line seems wider (which would be blurring), but that it looks thinner. – Maestro Jan 28 '13 at 19:50
  • What timer do you use? (the default Timer class is not accurate enough for smooth animations - neither is GDI+ fit for that matter). GDI+ won't let you sync by vsync (or vblank) so you need to go low-level for this. Invalidates ends up in a que that is rendered when possible. You can force the update by using Refresh (invalidate + Update) –  Jan 28 '13 at 20:01
  • @Ken-AbdiasSoftware Im using a default timer, but the interval is only 32 ms, so I didnt expect to need high-accuracy timers. And about the vsync: Im willing to go low level, but I dont know where to start. – Maestro Jan 28 '13 at 20:04
  • @Joshua for a 32ms delay, try calling Update() immediately after the Invalidate(rect). This could help a tad. –  Jan 28 '13 at 20:06
  • @Ken-AbdiasSoftware I just tried a high-resolution multimedia timer instead of the standard timer, but it made no difference. I was already calling Update() after Invalidate(), so that doesn't help much either. I really think this is a vertical-sync problem, because sometimes the problem disappears a few seconds, and then it starts flickering again. – Maestro Jan 28 '13 at 20:33

1 Answers1

1

This could be totally unhelpful but I had a similar problem and it took me forever to figure out so I'll mention it. I had a hardware specific problem that messed up the accuracy of timers because of the way my CPU managed performance counters on multiple cores.

To make I long story short, I had to run my main OpenGL loops on a single core until I upgraded my computer. If running the following code (or similar) before moving your glyph across the screen helps, then you have the same problem. This is the c# version.

Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1;

I hope this helps. But, I also hope this isn't your problem. Take care.

drankin2112
  • 4,715
  • 1
  • 15
  • 20