OpenGL.Net icon indicating copy to clipboard operation
OpenGL.Net copied to clipboard

Other control not refreshed

Open antoinecla opened this issue 6 years ago • 8 comments

Steps to reproduce:

  • Open HelloTriangle WinForm sample
  • Set OpenGl control Dock to None
  • Add a TextBox to the Form
  • Run
  • Focus on TextBox: the caret is not flashing

This is a simple example but in my own application with a complex user interface most of the other controls are not refreshed at all.

I just discovered the issue when integrating to my main application the GlControl / Scene I developed separately. Problem: I am due to present the prototype at the end of the week!!

This presentation is critical for me and I am stuck. I am unable to debug the issue and have no enough time to switch to an other binding.

Let me know if you can look into this issue.

antoinecla avatar Oct 04 '17 13:10 antoinecla

This seems related to other issue #70. Tonight I'll investigate on this.

luca-piccioni avatar Oct 04 '17 13:10 luca-piccioni

Are you setting Animation to true? Do you have tried to use a Forms.Timer calling Invalidate() on GlControl?

luca-piccioni avatar Oct 04 '17 13:10 luca-piccioni

Many thanks for replying so quickly.

Just tried to disable Animation and use a Timer instead. This solve the issue.

What I don't understand is that the first thing I tried is to disable Animation and still had the refresh issue on the rest of the UI. Now, it seems to work.

In between, I tried many different things. Maybe I changed something else that had a positive side effect. In any case, try the steps above to reproduce the issue.

At least, I now have a working solution! Thanks again for your feedback.

antoinecla avatar Oct 04 '17 14:10 antoinecla

I am not sure this is related.

I have a strange behavior when using two GlControl in the same form. Both controls use the OwnContext property. It seems anyway that setting a texture in one control affects the other one. Is this expected?

On a side note, I have checked the ContextSharing/SimpleSharing sample and get an exception on start:

System.InvalidOperationException: no GlControl sharing with TestGroup
   at OpenGL.GlControl.ReuseOtherContext() in GlControl.cs:line 836
   at OpenGL.GlControl.CreateContext() in GlControl.cs:line 668
   at OpenGL.GlControl.OnHandleCreated(EventArgs e) in GlControl.cs:line 1108
   at System.Windows.Forms.Control.WmCreate(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
   at System.Windows.Forms.ContainerControl.WndProc(Message& m)
   at System.Windows.Forms.UserControl.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

antoinecla avatar Oct 04 '17 18:10 antoinecla

I have found an explanation for the first part of my last comment.

Here is what I am doing:

  • Each GlControl has a property to set a Bitmap
  • The passed Bitmap is used to create an OpenGL texture
  • An event in the form is setting these properties

Since everything is happening on the same thread, the approach appeared valid to me. Wrong! Obviously, this cannot work. There is no way to guaranty that an OpenGL resource is created on the DeviceContext of the corresponding GlControl.

A call to MakeCurrentContext() prior to creating the GL resource solve the issue.

What can be confusing is that you do not need to do that inside OnContextCreated(), OnRender(), the related events and all methods called by them. The problem arises when one of this methods is also called from the "outside".

A note in the Common Mistakes section in your wiki could be useful!

antoinecla avatar Oct 04 '17 19:10 antoinecla

I have a strange behavior when using two GlControl in the same form. Both controls use the OwnContext property. It seems anyway that setting a texture in one control affects the other one. Is this expected?

Leaving ContextSharing to OwnContext, creates a GL context for each GlControl; and they share the same namespace using wglShareLists. Indeed textures and other objects exists for every GL context. This behavior is expected: contexts shares resources.

A call to MakeCurrentContext() prior to creating the GL resource solve the issue.

I suspect that the thread executing the event handle is not the UI thread. Normally all UserControl methods are called by the UI thread, which the context is current due the OnPaint override. What is the value of DeviceContext.GetCurrentContext() in the event handler? What is the thread ID?

Normally this issue is solved by having a dirty bit that command a GL operation in ContextUpdate.

luca-piccioni avatar Oct 04 '17 20:10 luca-piccioni

I suspect that the thread executing the event handle is not the UI thread. Normally all UserControl methods are called by the UI thread, which the context is current due the OnPaint override. What is the value of DeviceContext.GetCurrentContext() in the event handler? What is the thread ID?

Remember there are two GlControl in the same form. At any moment, the Context can switch from one to the other. Here is a scenario:

  • GlControl2.OnPaint() => Current context is GlControl2 Context
  • GlControl1.OnPaint() => Current context is GlControl1 Context
  • GlControl1.CreateTexture(aBitmap) => OK
  • GlControl2.CreateTexture(aBitmap) => Error. Current context is still GlControl1 Context. Texture is not created in the right Context.

Normally this issue is solved by having a dirty bit that command a GL operation in ContextUpdate.

Totally agree. I was thinking about something like that.

antoinecla avatar Oct 04 '17 21:10 antoinecla

Assuming a Form with two GlControl and the following code:

	public partial class Form1 : Form
	{
		uint _Shader;

		public Form1()
		{
			InitializeComponent();
		}

		private void glControl1_ContextCreated(object sender, GlControlEventArgs e)
		{
		}

		private void glControl1_ContextDestroying(object sender, GlControlEventArgs e)
		{
		}

		private void glControl2_ContextCreated(object sender, GlControlEventArgs e)
		{
			_Shader = Gl.CreateShader(ShaderType.VertexShader);
		}

		private void glControl2_ContextDestroying(object sender, GlControlEventArgs e)
		{
			IntPtr context = DeviceContext.GetCurrentContext();
			if(context != IntPtr.Zero)
			{
				Gl.DeleteShader(_Shader);
			}
		}
	}

When closing the form and upon deletion of the shader, I get the GL error: InvalidValue (call stack below).

Inspecting the CurrentContext in glControl2_ContextDestroying() shows it is different from both the glControl1 and glControl2 context.

What is this third context? Why the shader cannot be deleted?

If I move the code from glControl2 to glControl1, the shader is deleted without issue.

Partial Call Stack:

>	OpenGL.Net.dll!OpenGL.Gl.CheckErrors() Line 499	C#
 	OpenGL.Net.dll!OpenGL.Gl.DebugCheckErrors(object returnValue) Line 511	C#
 	OpenGL.Net.dll!OpenGL.Gl.DeleteShader(uint shader) Line 1227	C#
 	GlNetDualControlTest.exe!GlNetDualControlTest.Form1.glControl2_ContextDestroying(object sender, OpenGL.GlControlEventArgs e) Line 47	C#
 	OpenGL.Net.WinForms.dll!OpenGL.GlControl.OnContextDestroying() Line 1024	C#
 	OpenGL.Net.WinForms.dll!OpenGL.GlControl.OnHandleDestroyed(System.EventArgs e) Line 1130	C#
 	System.Windows.Forms.dll!System.Windows.Forms.Control.WmDestroy(ref System.Windows.Forms.Message m)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc(ref System.Windows.Forms.Message m)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.WndProc(ref System.Windows.Forms.Message m)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.UserControl.WndProc(ref System.Windows.Forms.Message m)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam)	Unknown
 	[Native to Managed Transition]	
 	[Managed to Native Transition]	
 	System.Windows.Forms.dll!System.Windows.Forms.UnsafeNativeMethods.DestroyWindow(System.Runtime.InteropServices.HandleRef hWnd)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DestroyHandle()	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.Control.DestroyHandle()	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.Control.Dispose(bool disposing)	Unknown
 	System.Windows.Forms.dll!System.Windows.Forms.Form.Dispose(bool disposing)	Unknown

antoinecla avatar Oct 05 '17 09:10 antoinecla