Drawing performance with doublebuffering;

MattB

New member
Joined
Dec 16, 2003
Messages
1
Hello.

I am exploring .NET programming using C# and GDI+. My end program is going to be a vector drawing program (similiar to Adobe Illustrator, although not that complex). Ive started learning about GDI+, and it seems to have all the functions I want (alpha, gradients, beziers, antialiasing, etc.), but I am struggling with this performance problem when I used doublebuffering. Whenever my form is large (i.e. maximized), there is a noticable effort when refreshing the screen. Ive tried without doublebuffering, but the screen flicker is also unacceptable.

Here is some sample code that demonstrates this (not complete code, only what youd have to add to a new project):


Code:
using System.Drawing;
using System.Drawing.Drawing2D;

namespace GDI__Test
{
    public class Form1 : Form
    {
        private GraphicsPath _oShape;
        private Pen _oPen;
        private SolidBrush _oBrush;

        public Form1()
        {
            base.SetStyle(ControlStyles.DoubleBuffer, true);
            base.SetStyle(ControlStyles.UserPaint, true);
            base.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

            _oShape = new GraphicsPath();
            _oPen = new Pen(Color.Black, 2.0F);
            _oBrush = new SolidBrush(Color.Yellow);
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            _oShape.Dispose();
            _oShape = new GraphicsPath();
            _oShape.AddEllipse(e.X, e.Y, 100, 150);
            _oShape.CloseFigure();

            this.Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
        
        Graphics loGraphics = e.Graphics;
        
            loGraphics.SmoothingMode = SmoothingMode.AntiAlias;
            loGraphics.FillPath(_oBrush, _oShape);
            loGraphics.DrawPath(_oPen, _oShape);
        }

    }
}


When you move the shape with the maximized window, it isnt locked to the mouse, its jumpy and laggs behind and then catches up (like its on a chain). The cause seems to be the amount of time it takes to redraw the form. I have tried this on several computers (all of which we would hope to support in the end product), and it seems that the CPU is the only thing that makes a difference. Ive ran it on a) P4, 1.6GHz, 256MB RAM, 64MB Video; b) P3, 1.1GHz, 512MB RAM, 64MB Video, this is my development machine; c) P3, 733MHz, 384MB RAM, 128MB Video. On computer a) best performance; b) unacceptable drawing delays; c) brutal.

This seems to be a common problem with DoubleBuffering. Ive downloaded and ran Bob Powells example (from http://www.bobpowell.net/doublebuffer.htm), and it too has this problem when I run it maximized (his rotations are very choppy as opposed to when running in the initial window size)...and hes doing his own manual double buffering in that example. Ive also found this newsgroup post (http://groups.google.ca/groups?hl=e...&seekm=#22klulACHA.2228@tkmsftngp02&frame=off) about the same problem with no real solution (I tried the PixelFormat.Format32bppPArgb with no luck). And I cant revert to using GDI, because I need the alpha and antialising stuff, right?

Ive heard a suggestion that I should not be repainting (invalidating) the entire form all the time and that this might be a cause of the problem. Using the above example as an example, it would be more efficient if I only invalidated the union of the shapes original bounding rect and the shapes new bounding rect. My question is how do I do this? Ive tried using the System.Drawing.Region class, but I could only fill the region..I want to be able to tell the form to actually only repaint a part of the display. Could someone point me in the right direction so I can try this out to see if this will solve my problem.

Alternatively, does anyone have any other suggestions? I am thinking about investigating DirectX as I hear that it is much faster (although does it have all the capabilities, like anti-aliasing and alpha?). I would really like to stick with GDI+ as it seems to be a good and simple object model to follow.

Thanks for any info...
- Matt Budd
 
Hi, Create a bitmap. Apply all of your various graphics to that bitmap in memory. Then apply it to your form. It is fast and you will have no flicker at all. Hope it helps.


Jason
 
Hi,
I have also found the same thing, using the SetStyle(....) commands, although it is supposed to work, in fact doesnt work all that well.

I think you may need to completely ovveride the OnPaint method, and handle that yourself.

I am also interested in anyones opinion of Managed DirectX for .NET and the performance of that, if anyone has had any experience with that.

Peter
 
GDI+ is just ungodly slow. Use GDI instead, and if thats still not good enough, use DirectDraw.
 
as far as i know you can change how the app paints everything on screen, but i dont have the variables in mind at the moment, i just can tell you if you want to have fast graphics there is no way around dx, but normally you should also get it to work with gdi+ just use doublebuffering, so create a bitmap with same size as your drawing surface and then just draw all in that hidden bitmap at the onpaint you just draw this one bitmap
 
How to apply the bitmap?

How can I apply such a bitmap to my control? Using the graphics.DrawImage() on my control method causes already the unwanted flickering with GDI+. Can I do something like.

MyControl.Graphics = myBitmap.Graphics ?

Thanks,

Franz
 
Back
Top