hesojam's picture

WPF designer crashes when using GLControl

Hello

I made a new UserControl in WPF, containing a WindowsFormHost and a GLControl in it.
When I initialize the GLControl when it is loaded, I use the GL methods.
As soon as I call one of these methods, the designer crashes.

When I run the application, it works flawless.

Can somebody tell me, if there's a method, that the GLControl can also work inside the visual studio wpf designer (Version 2012)?

My code is:

public partial class GLViewport : UserControl
{
    private bool isGlLoaded;        
 
    public Scene Scene { get; set; }
 
    public GLViewport()
    {
        InitializeComponent();
 
        this.glControl1.Load += this.glControl1_Load;
        this.glControl1.Paint += this.GLControl_Paint;
 
        this.Scene = new Scene();
    }      
 
    private void SetupViewport()
    {        
        GL.ClearColor(Color.Black);
 
        int w = this.glControl1.Width;
        int h = this.glControl1.Height;
        GL.Ortho(0, w, 0, h, -1, 1); // Bottom-left corner pixel has coordinate (0, 0)
        GL.Viewport(0, 0, w, h); // Use all of the glControl painting area
 
        GL.Enable(EnableCap.DepthTest);
        GL.Enable(EnableCap.Blend);
        GL.DepthMask(true);
        GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
 
        GL.Enable(EnableCap.LineSmooth);
        GL.Enable(EnableCap.PointSmooth);
 
        isGlLoaded = true;
    }
 
    private void GLControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
    {
        this.Paint();
    }
 
    private void Paint()
    {
        if (!this.isGlLoaded || this.Scene == null)
        {
            return;
        }
 
        this.glControl1.MakeCurrent();
        this.Scene.PaintScene(this.glControl1.Width, this.glControl1.Height);
 
        this.glControl1.SwapBuffers();
    }
 
    private void glControl1_Load(object sender, System.EventArgs e)
    {
        this.SetupViewport();
    }
 
    private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (!this.isGlLoaded)
        {
            return;
        }
 
        this.SetupViewport();
    }
}

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

GLControl does not create an OpenGL context when running in design mode, hence the crash. (The reason is that any OpenGL bug could potentially crash Visual Studio, making debugging extremely difficult.)

Add the following check to any events calling OpenGL commands:

bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if (designMode)
    return;
hesojam's picture

Thank you.
Your code works perfectly for me.

Is there a way to create a OpenGL context in design time?
That would be usefull, for when I've tested the functionality of my code.

Greetings
Hesojam

the Fiddler's picture

You would have to modify GLControl.cs:198 to remove the checks for design mode.

In my experience, the WinForms designer in Visual Studio does not call Dispose() and will leak the OpenGL context, causing instability after running for a while. I do not know if WPF is better behaved, but I would recommend testing that thoroughly before releasing a custom control that uses OpenGL directly inside the designer. If you decide to do this, keep in mind the following:

  1. Your code should fail gracefully if the OpenGL context cannot be constructed or GLControl.MakeCurrent() fails. In that case, calling any OpenGL functions may crash the designer or even Visual Studio itself.
  2. Your code should be able to cope with multiple instances of your control. Only one OpenGL context may be current on the UI thread, so each control will have to ensure it is current before using any OpenGL functions. (This can reduce performance.)
  3. You should test the software on different GPUs - at the very least covering Amd, Intel and Nvidia GPUs in both 32bit and 64bit mode. Each driver has its own peculiarities and, odd as this may seem, code that appears to run correctly on e.g. Amd 32bit may fail on Nvidia 64bit or vice versa. (This is from personal experience.)
  4. Test your control on a system without OpenGL drivers installed, or running through remote desktop. Your code should be able to cope with that, or at least fail gracefully.

This advice is applicable in the general case, but especially so if you wish to distribute a reusable designer component. A normal desktop application can always fallback to a generic error message ("OpenGL initialization failed, please download new drivers from xyz"), but this will not work in the Visual Studio designer.

hesojam's picture

Ok, thank you very much

I'm not yet planing to release something, but I'm working on a high-level implementation for my own projects.
I will keep your points in mind and will test them as good as possible.

Greetings
Hesojam