Double Buffering - DIBSections

J

James Chapman

Hi,

I am trying to draw a graph using System.Drawing about 5 times a
second. The graph is 700x250 pixels in size. This is proving to be
very slow.

My code currently does this in Form1_Paint:

Bitmap localBitmap = new
Bitmap(ClientRectangle.Width,ClientRectangle.Height);
Graphics bitmapGraphics = Graphics.FromImage(localBitmap);
bitmapGraphics.Clear(BackColor);

.... draws graph

g.DrawImage(localBitmap,0,0);


I have this in my Form constructor:
this.SetStyle(ControlStyles.ResizeRedraw | ControlStyles.Opaque,
true);

Is this the correct approach?

I have read that the best performance to be had from GDI+ involves
allowing it to drop through to GDI and that I should store my
offscreen buffer as a DIBSection. I have also read that it is
important to ensure that no conversion takes place when copying to the
screen due to different image formats.

Is this what I should do? How do I get a DIBSection from HBITMAP
handle into a managed Bitmap object? Or do I need to wrap unmanaged
calls to GDI+ as well as GDI.

Thanks,

James Chapman
 
J

James Chapman

Thanks Pete!
Have you tried using SetStyle to add DoubleBuffer and AllPaintingInWmPaint
and UserPaint? Then do all you drawing in an OnPaint override and don't
worry about clearing it (remember to use e.Graphics).

I have changed my implementation to reflect this and it is certainly
an improvement. It uses far less of the CPU and is much better
behaved generally.

This method actually uses DIBSections I think so what I had previously
envisaged has been more easily accomplished here.

However the actual drawing is stil rather slow.
This is the standard approach. If it still doesn't give you the required
performance then think about using P/Invoke and gdi32.dll to access the
original GDI methods. I advise against messing around inside bitmaps and
then copying them in GDI+ (unless someone here can verify that it will give
a performance gain).

Are there any further performance improvements to be had? I wonder if
my app is actually 'falling through' to GDI? Are there some specific
things I should avoid to unsure that this occurs and hence benefit
from GDIs acceleration?

Thanks,

James
 
P

Pete

Hi,

James said:
Thanks Pete!

No problem.
This method actually uses DIBSections I think so what I had previously
envisaged has been more easily accomplished here.

It probably does. You could always verify it using .NET Reflector (do a
google search for this) and decompiling the necessary classes (not sure
which exactly, maybe part of Control?).
However the actual drawing is stil rather slow.
....

Are there any further performance improvements to be had? I wonder if
my app is actually 'falling through' to GDI? Are there some specific
things I should avoid to unsure that this occurs and hence benefit
from GDIs acceleration?

Using GDI32 instead of GDI+ will almost certainly give a performance
improvement.. the downside is that you need security permissions to run
native code (if this is just a normal winforms app you're probably okay
there), so far as I know anyway -- I'm a little hazy on security stuff.

Before you take the plunge into unmanaged code, make sure you have profiled
and optimised your managed stuff as much as possible. Eg are you redrawing
everything in OnPaint, or just the stuff required by e.ClipRectangle
(preferably)?

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top