I have two glControls. Each have it's on paint event. But before completely running the functions of paint1 event, system calls paint2 event. I thought the functions inside each event will be called completely synchronously. Can I make that way. Means, paint2 event should be called after completing paint1 event?
private void Form3_Load(object sender, EventArgs e)
{
glControl1.Visible = true;
glControl2.Visible = true;
GL.Enable(EnableCap.DepthTest);
}
private void glControl1_Load(object sender, EventArgs e)
{
if (glControl2.Created &&
glControl2.Context.IsCurrent)
{ glControl2.Context.MakeCurrent(null); }
if (glControl1.Context.IsCurrent == false)
{
glControl1.MakeCurrent();
}
obj_openTK.Init();
}
private void glControl2_Load(object sender, EventArgs e)
{
if (glControl1.Created &&
glControl1.Context.IsCurrent)
{ glControl1.Context.MakeCurrent(null); }
if (glControl2.Context.IsCurrent == false)
{ glControl2.MakeCurrent(); }
obj_openTK.Init();
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (glControl2.Created &&
glControl2.Context.IsCurrent)
{ glControl2.Context.MakeCurrent(null); }
if (glControl1.Context.IsCurrent == false)
{ glControl1.MakeCurrent(); }
Render();
}
private void glControl2_Paint(object sender, PaintEventArgs e)
{
try{
if (glControl1.Created &&
glControl1.Context.IsCurrent)
{ glControl1.Context.MakeCurrent(null); }
if (glControl2.Context.IsCurrent == false)
{ glControl2.MakeCurrent(); }
Render2();
}
catch(Exception ex)
{
string exx = ex.ToString();
string stacktrace = ex.StackTrace.ToString();
}
}
private void Render()//for first image
{
GL.DeleteTextures(1, ref texture);
texture = obj_openTK.LoadTexture(image);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
obj_openTK.DrawImage(texture,glControl1);
GL.Flush();
glControl1.SwapBuffers();
}
private void Render2()// for second image
{
GL.DeleteTextures(1, ref texture);
texture = obj_openTK.LoadTexture(image2);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
obj_openTK.DrawImage(texture, glControl2);
GL.Flush();
glControl2.SwapBuffers();
}
===============openTK class========================
class openTK
{
int positionLocation1;
int program;
int positionLocation;
int vertShader;
int fragShader;
int buffer;
float[] vertices = {
// Left bottom triangle
-1f, -1f, 0f,
1f, -1f, 0f,
1f, 1f, 0f,
// Right top triangle
1f, 1f, 0f,
-1f, 1f, 0f,
-1f, -1f, 0f
};
public int LoadTexture(Bitmap bitmap)
{
int tex = -1;
if (bitmap != null)
{
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
GL.GenTextures(1, out tex);
GL.BindTexture(TextureTarget.Texture2D, tex);
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
bitmap.UnlockBits(data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
}
return tex;
}
public void DrawImage(int image, GLControl glControl)
{
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
GL.Disable(EnableCap.Lighting);
GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, image);
GL.Uniform1(positionLocation1, 0);
RunShaders();
GL.Disable(EnableCap.Texture2D);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
private void RunShaders()
{
GL.UseProgram(program);
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
private void Init()
{
CreateShaders();
CreateProgram();
InitBuffers();
}
private void CreateProgram()
{
program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
}
private void InitBuffers()
{
buffer = GL.GenBuffer();
positionLocation = GL.GetAttribLocation(program, "a_position");
positionLocation1 = GL.GetUniformLocation(program, "sTexture");
GL.EnableVertexAttribArray(positionLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 0, 0);
}
private void CreateShaders()
{
/***********Vert Shader********************/
vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, @"attribute vec3 a_position;
varying vec2 vTexCoord;
void main() {
vTexCoord = (a_position.xy+1)/2 ;
gl_Position = vec4(a_position, 1);
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, @"precision highp float;
uniform sampler2D sTexture;varying vec2 vTexCoord;
void main ()
{
vec4 color = texture2D (sTexture, vTexCoord);
gl_FragColor = color;
}");
GL.CompileShader(fragShader);
}
}
Now when running this code , paint1 throws below exception. It is because render2() is calling before completing render().
OpenTK.Graphics.GraphicsContextException: 'Failed to swap buffers for context 131072 current.
A quick and simple way would be by adding a
lockto your code...When one block of code gets a lock on
locker, then any other attempt to lock will be delayed until the first lock is cleared.If you need to control further the order of the lock, you could use a queue to hold an identifier on which block of code is trying to get a lock, if it isn't the one you want first, delay that lock until the correct one locks first. This could cause issues however, if for some reason the expected "first" lock does not happen. Then the second will not, unless you add a wait timeout.
EDIT:
In your
Renderfunctions...I believe you are calling
GL.Clear()too much. It really only needs to be called once per loop. Also, I do not thinkGL.Flush()is doing anything for you since you are double buffering.Beyond that, I do not believe the problem lies in the code you have provided, but likely something with the construction or configuration of your
glControl1andglControl2.