Giter Site home page Giter Site logo

luca-piccioni / opengl.net Goto Github PK

View Code? Open in Web Editor NEW
565.0 43.0 106.0 92.47 MB

Modern OpenGL bindings for C#.

License: MIT License

C# 93.11% XSLT 0.05% C 6.30% GLSL 0.46% Batchfile 0.08%
opengl opengl-bindings c-sharp net-framework net-core mono xamarin-android netstandard gtk3 rpi2

opengl.net's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opengl.net's Issues

unable to set pixel format

I'm having trouble getting the GlControl to work. Just adding it to a form and this is all I get:
image

I've tried both the nu-get package and the latest master, both have the same result.

I should also note, I'm running a GTX 1080 FE with up to date drivers.

What is OpenGL.HAL?

I am trying to understand how your library works and was wondering what this project is. For me it looks like some library/framework used to render graphics and geospatial data. Is this somehow closely tied to the OpenGL.NET project? Because I am just looking for C# OpenGL bindings not a graphics framework.

Thanks!

Build instructions don't actually work.

Zaba@ZABA-HUGETOP D:\Dev\libraries\OpenGL.Net

msbuild OpenGL.Net.sln
Microsoft (R) Build Engine version 14.0.25420.1
Copyright (C) Microsoft Corporation. All rights reserved.

Building the projects in this solution one at a time. To enable parallel build, please add the "/m" switch.
Build started 16/10/2016 10:59:27.
D:\Dev\libraries\OpenGL.Net\OpenGL.Net.sln : Solution file error MSB5004: The solution file has two projects named "OpenGL_Net".

Build FAILED.

D:\Dev\libraries\OpenGL.Net\OpenGL.Net.sln : Solution file error MSB5004: The solution file has two projects named "OpenGL_Net" .

0 Warning(s)
1 Error(s)

WindowsFormsHost issue

i am trying to create hellotriangle wpf application and I am getting the error " WindowsFormsHost is not supported on wpf". I have installed opengl.net nugget package into my solution.
Can someone please help me resolve the issue ?

New enumerations for various function options

In the spirit of creating a safe interface to OpenGL, I think the number of currently generated enumerations is too slim; for example, when using FramebufferRenderbuffer It would be nice to use an enumeration to specify the attachment, like BufferAttachment.ColorAttachment0 instead of Gl.COLOR_ATTACHMENT0.

On a bit of a side note, since I am willing to provide some such improvements but I don't really know where to start, could you provide something like a guideline on how to make such additions?

Keep up the great work ๐Ÿ‘

Restrict API to a particular version

Is there a way to restrict the API to use a particular OpenGL version? For example, I want to develop using only OpenGL ES 2. How can I make sure that only OpenGL ES 2 functions are available?

Problem with GTK#

I have tried but it doesn't show Gl-Viewport on Gtk.Window -
It always hide me.

Example code for Window or Container If I don't know that.

using Gtk;
using OpenGL;

namespace GtkGame{
    class GtkGameWindow : Window
    {
        public bool GLinit;

        public GtkGameWindow() : base(WindowType.Toplevel)
        {
            GLinit = false;
            WidgetEvent += new WidgetEventHandler(GtkInitalizeHanlder);
        }

        private void GtkInitalizeHanlder(object sender, WidgetEventArgs we)
        {
            int width = 0, height = 0;
            GetSizeRequest(out width, out height);
            float aspectRatio = width / height;
            Gl.Viewport(0, 0, width, height);
            Gl.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
            Gl.Clear(ClearBufferMask.ColorBufferBit);
            Gl.MatrixMode(MatrixMode.Modelview);
            Gl.LoadIdentity();
            Gl.ShadeModel(ShadingModel.Smooth);
            //Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspectRatio, 1.0f, 64.0f);
            Gl.MatrixMode(MatrixMode.Projection);

            Gl.ClearDepth(1);
            Gl.Disable(EnableCap.DepthTest);
            Gl.Enable(EnableCap.Texture2d);
            Gl.Enable(EnableCap.Blend);
            Gl.DepthFunc(DepthFunction.Always);
            Gl.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
            //add idle event handler to process rendering whenever and as long as time is availble.
            GLinit = true;
        }
    }
}

But I found example but it is old of OpenTK StackOverFlow

I try replace - But OpenGL Matrix4x4 hasn't static method CreatePerspectiveFieldOfView(). How do I fix for replacement of your OpenGL.net

OpenGL.Net crashes on Linux

On systems where the "uname" binary is not present in /usr/bin/, any call to the Gl object causes a crash due to the file not being found. Creating a symbolic link to the real binary (present in /bin/ on some systems) functions as a workaround.

Target .Net 3.5?

Our applications runs on .Net 3.5, we can build a version of OpenGL.Net dll in 3.5 without any problems. Is there a reason why you target .Net 4.5?

DEPTH TEST don't work

Hi Luca,

DEPTH TEST don't work. If you use a cube on your HelloTriangle example you can test this issue.

private void RenderControl_ContextCreated(object sender, GlControlEventArgs e){
.....
Gl.ClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
Gl.ClearDepth(1.0f);
Gl.Enable(EnableCap.DepthTest); // Enables Depth Testing
Gl.DepthFunc(DepthFunction.Lequal); // The Type Of Depth Testing To Do
Gl.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
....

}

//CUBE
private static readonly float[] _ArrayPosition = new float[] {
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f,-1.0f, // triangle 2 : begin
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f, // triangle 2 : end
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};

    /// <summary>
    /// Vertex color array.
    /// </summary>
    private static readonly float[] _ArrayColor = new float[] {
        
0.583f,  0.771f,  0.014f,
0.609f,  0.115f,  0.436f,
0.327f,  0.483f,  0.844f,
0.822f,  0.569f,  0.201f,
0.435f,  0.602f,  0.223f,
0.310f,  0.747f,  0.185f,
0.597f,  0.770f,  0.761f,
0.559f,  0.436f,  0.730f,
0.359f,  0.583f,  0.152f,
0.483f,  0.596f,  0.789f,
0.559f,  0.861f,  0.639f,
0.195f,  0.548f,  0.859f,
0.014f,  0.184f,  0.576f,
0.771f,  0.328f,  0.970f,
0.406f,  0.615f,  0.116f,
0.676f,  0.977f,  0.133f,
0.971f,  0.572f,  0.833f,
0.140f,  0.616f,  0.489f,
0.997f,  0.513f,  0.064f,
0.945f,  0.719f,  0.592f,
0.543f,  0.021f,  0.978f,
0.279f,  0.317f,  0.505f,
0.167f,  0.620f,  0.077f,
0.347f,  0.857f,  0.137f,
0.055f,  0.953f,  0.042f,
0.714f,  0.505f,  0.345f,
0.783f,  0.290f,  0.734f,
0.722f,  0.645f,  0.174f,
0.302f,  0.455f,  0.848f,
0.225f,  0.587f,  0.040f,
0.517f,  0.713f,  0.338f,
0.053f,  0.959f,  0.120f,
0.393f,  0.621f,  0.362f,
0.673f,  0.211f,  0.457f,
0.820f,  0.883f,  0.371f,
0.982f,  0.099f,  0.879f

};

Matrix multiplication

Dear Luca,

Hi again. While trying to do unprojection, I started playing with matrices and came upon the following effect: multiplying a Matrix4x4f with a Matrix1x4f resulted in a Matrix4x4f, rather than in a Matrix1x4f. After installing MathNet.Numerics and using their matrices I was able to unproject successfully.

Also, I compared the results of the multiplication of the projection and modelview 4x4 matrices using the matrices from OpenGL.Net and using MathNet.Numerics.LinearAlgebra. The products contained different numbers, although the source matrices contained the same numbers in the buffers.

Best,
Daniel

0.5.0 nuget release?

I see that a week ago a commit was placed for 0.5.0, but I'm not seeing 0.5.0 in NuGet, only 0.4.2. Need any help?

Issues after switching to current NuGet package

Hi,
I've been using OpenGL.Net for a while now, without any issues. I'm creating the window and the context manually and all worked fine until today, I removed the pre-compiled OpenGL.Net assembly (compiled August 2015) and instead installed the NuGet package (version 0.4.0). Window and context creation still work fine, but Gl.GetString(StringName.Version) now returns NULL. Gl.GetError() says InvalidOperation, but already does so before calling GetString(), right after making the context the current. Here's my code:

// Find matching pixel format
PixelFormatDescriptor pfd = PixelFormatDescriptor.Build();
pfd.nVersion = 1;
pfd.dwFlags = WinApi.PFD_DOUBLEBUFFER | WinApi.PFD_SUPPORT_OPENGL | WinApi.PFD_DRAW_TO_WINDOW;
pfd.iPixelType = WinApi.PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 32;
pfd.cStencilBits = 8;
pfd.iLayerType = WinApi.PFD_MAIN_PLANE;

IntPtr dc = WinApi.GetDC(_hwnd);
int pixelFormat = WinApi.ChoosePixelFormat(dc, ref pfd);

if (pixelFormat == 0)
  throw new Exception("ChoosePixelFormat failed: " + Marshal.GetLastWin32Error());

//Set the new pixel format
if (!WinApi.SetPixelFormat(dc, pixelFormat, ref pfd))
  throw new Exception("SetPixelFormat failed: " + Marshal.GetLastWin32Error());

//Create temporary GL context
IntPtr tempRc = Wgl.CreateContext(dc);
if (tempRc == IntPtr.Zero)
  throw new Exception("CreateContext failed: " + Marshal.GetLastWin32Error());

if (!Wgl.MakeCurrent(dc, tempRc))
  throw new Exception("MakeCurrent failed: " + Marshal.GetLastWin32Error());

//Get Gl version the old way first
string versionStr = Gl.GetString(StringName.Version);

As written before, all checks pass successful, but Gl.GetString() still returns NULL. Do you have any ideas what could cause this? Using the pre-compiled assembly, the above code works perfectly fine. The issue is only with the NuGet package.

Thanks and regards,
Eric

UWP example

I search for UWP opengl in c# and I found this site as there is underlying ANGLE.
Could you do a simple UWP c# example.

Animation

Hi, could you post an example to show how animate a triangle? thanks

GL methods overload problem in VB.net

Method overloading differences between C# and VB.Net cause errors in VB.Net. To VB byRef and byVal do not differentiate the function and an ambiguous member error occurs.

How to create a debug context

Big thanks for this alternative to OpenTK

Currently I am rendering OpenGL content within a WPF application. I cannot host your GlControl in a WindowsFormsHost, because the entire HAL namespace is not part of the nuget package, and I want to stick to that.

So my way is to create a Window and a OpenGL context on my own and host it in a HwndHost.This works out fine. But I cannot figure out, how to set the callback function for a debug context.

object userParam = someObjectOfInterest;
IntPtr callback = ???;
OpenGL.Gl.DebugMessageCallback(callback, userParam);

How do I obtain an Intptr to my callback function? A delegate for the callback itself does not seem to exist.

NuGet package

Congratulations on reaching your first binary release. It's nice to see that the project has reached that level of maturity.

Could we look at getting the library made available as a NuGet package? It shouldn't be super hard, and would encourage people to start using it.

Render a video from ffmpeg frames

This is not really an issue, but I'm wondering how can I render a video from raw RGB frames computed by ffmpeg?

I'm using a ffmpeg C# wrapper which is working like this

while (ffmpeg.av_read_frame(pFormatContext, pPacket) >= 0)
{
    if (pPacket->stream_index == pStream->index)
    {
        if (ffmpeg.avcodec_send_packet(pCodecContext, pPacket) < 0)
        {
            ffmpeg.av_packet_unref(pPacket);
            ffmpeg.av_frame_unref(pDecodedFrame);
            continue;
        }

        if (ffmpeg.avcodec_receive_frame(pCodecContext, pDecodedFrame) < 0)
        {
            ffmpeg.av_frame_unref(pDecodedFrame);
            continue;
        }

        ffmpeg.av_packet_unref(pPacket);
        var src = &pDecodedFrame->data0;
        var dst = &pConvertedFrame->data0;
        var srcStride = pDecodedFrame->linesize;
        var dstStride = pConvertedFrame->linesize;
        ffmpeg.sws_scale(pConvertContext, src, srcStride, 0, height, dst, dstStride);

        var convertedFrameAddress = pConvertedFrame->data0;

        var imageBufferPtr = new IntPtr(convertedFrameAddress);
        ffmpeg.av_frame_unref(pDecodedFrame);
    }
}

How can I renderer the image from imageBufferPtr variable to an OpenGL texture?

Many thanks

Dll error binding

When I try run my app at WIndows 8.1 RT with opengl-to-directx wrapper, located at System32 or folder with my app, your lib can't find opengl32.dll, but other native(c++) apps can find and use this wrapper.
P.S. Yeah, it's very specific case, Windows RT doesn't support OpenGL and officially don't support run other applications. I can provide some information, if you needed.

Mesa

Wondering if the library works with Mesa and if so how would I set it up?

Adding more Hardware support

I like to have more supported Hardware, not just Raspberry.
At "stb-kodi-vuduo2" there various implementations with sourcecode for ...
VuPlus, Android, Amlogic, Dreambox, IMX, V3D, V3DNXPL.

VuPlus in my case :-)

memory access violation with Gl.DrawArrays but not with Gl.Begin/Gl.End

Installed OpenGL.Net version: 0.3.2

The following code causes memory protection fault (but not always):

        vertexList.Add(cell.gridPoint.x - offset); vertexList.Add(cell.gridPoint.y - offset);       //  bl
        vertexList.Add(cell.gridPoint.x - offset); vertexList.Add(cell.gridPoint.y + offset);       //  tl
        vertexList.Add(cell.gridPoint.x + offset); vertexList.Add(cell.gridPoint.y + offset);       //  tr

        vertexList.Add(cell.gridPoint.x - offset); vertexList.Add(cell.gridPoint.y - offset);       //  bl
        vertexList.Add(cell.gridPoint.x + offset); vertexList.Add(cell.gridPoint.y - offset);       //  br
        vertexList.Add(cell.gridPoint.x + offset); vertexList.Add(cell.gridPoint.y + offset);       //  tr

        var vertexArray = vertexList.ToArray();
        using (MemoryLock vertexArrayLock = new MemoryLock(vertexArray))
        {
            Gl.VertexPointer(2, VertexPointerType.Float, 0, vertexArrayLock.Address);
            Gl.EnableClientState(EnableCap.VertexArray);

            Gl.DrawArrays(PrimitiveType.Triangles, 0, vertexArray.Length);
        }

The following code works fine:

    Gl.Begin(PrimitiveType.Triangles);
    Gl.Vertex2(cell.gridPoint.x - offset, cell.gridPoint.y - offset);
    Gl.Vertex2(cell.gridPoint.x - offset, cell.gridPoint.y + offset);
    Gl.Vertex2(cell.gridPoint.x + offset, cell.gridPoint.y + offset);

    Gl.Vertex2(cell.gridPoint.x - offset, cell.gridPoint.y - offset);
    Gl.Vertex2(cell.gridPoint.x + offset, cell.gridPoint.y - offset);
    Gl.Vertex2(cell.gridPoint.x + offset, cell.gridPoint.y + offset);
    Gl.End();

When the faulty code does not crash, from some point on massive visual artifacts appear.

Please check the attached project
conway-set.zip
.

Problem with Ubuntu/MonoDevelop 5.1 and target Framework above 'net452'

If you want/must to develop with MonoDevelop on Ubuntu (C/C++ Project support)
it's not possible to target Framework above 'net452'
:-(
Adding OpenGL.Net...
Attempting to resolve dependency 'System.Numerics.Vectors (โ‰ฅ 4.3.0)'.
Attempting to resolve dependency 'System.Runtime.CompilerServices.Unsafe (โ‰ฅ 4.3.0)'.
The 'System.Runtime.CompilerServices.Unsafe 4.3.0' package requires NuGet client version '2.12' or above, but the current NuGet version is '2.8.7.0'.

Roadmap, license, users, and contributions

A few questions:

Could you please provide a license for this (Preferably in the root of the project)?
Is there any information or background information on the users of this library?
Is there a roadmap or project plan available?
Where can new contributors get involved?

ANGLE DLL's

Hi,

I understand in order to get ANGLE working you need the two dll's libEGL + libGLESv2 however Ive tried adding the dll's from the nugget packages mentioned here https://github.com/Microsoft/angle, however the sample app says they are not correct for application. Do the dll's come from somewhere else?

Possible issue with Gl.Enable(EnableCap.DepthTest);

Hello again,

screenshot_1

I've been trying to use z-buffers, but it seems that the following calls have no effect whatsoever. I mean, the result is always the same, no matter whether the following code is commented, or whether the values are different:

Gl.ClearDepth(1.0f);
Gl.Enable(EnableCap.DepthTest);
Gl.DepthFunc(DepthFunction.Less);

Here is the code that executes from glControl_ContextCreated:

		Gl.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		Gl.ClearDepth(1.0f);
		Gl.Enable(EnableCap.DepthTest);
		Gl.DepthFunc(DepthFunction.Less);
		Gl.ShadeModel(ShadingModel.Smooth);
		Gl.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);

		float aspect = (float)this.size.Height / (float)this.size.Width;
		Gl.Viewport(0, 0, this.size.Width, this.size.Height);

                    Gl.MatrixMode(MatrixMode.Projection);
                    Gl.LoadIdentity();
		//http://stackoverflow.com/questions/2417697/gluperspective-was-removed-in-opengl-3-1-any-replacements
		// The following code is a fancy bit of math that is eqivilant to calling:
		// gluPerspective( fieldOfView/2.0f, width/height , 0.1f, 255.0f )
		// We do it this way simply to avoid requiring glu.h
		float fieldOfView = 90;
		float zNear = 0.1f;
		float zFar = 100.0f;
		float fH = (float)Math.Tan(fieldOfView * 3.14159f / 360.0f) * zNear;
		float fW = fH * aspect;
		Gl.Frustum(-fW, fW, -fH, fH, zNear, zFar);


		Gl.MatrixMode(MatrixMode.Modelview);
		Gl.LoadIdentity();
		Gl.Translate(0f, 0f, -1f);
		Gl.Scale(0.02f, 0.02f, 0.02f);
		Gl.Rotate(45f, 1f, 1f, 1f);

		List<Vertex3f> vertexList = new List<Vertex3f>();
		List<ColorRGBA32> colorList = new List<ColorRGBA32>();

		for(int x = -20; x <= 20; x += 8)
			for (int y = -20; y <= 20; y += 8)
				for (int z = -20; z <= 20; z += 8)
				{
					vertexList.Add(new Vertex3f( 0 + x,  1 + y,  0 + z)); colorList.Add(new ColorRGBA32(Color.Red.R, Color.Red.G, Color.Red.B, Color.Red.A));
					vertexList.Add(new Vertex3f(-1 + x, -1 + y, -1 + z)); colorList.Add(new ColorRGBA32(Color.Green.R, Color.Green.G, Color.Green.B, Color.Green.A));
					vertexList.Add(new Vertex3f( 1 + x, -1 + y, -1 + z)); colorList.Add(new ColorRGBA32(Color.Blue.R, Color.Blue.G, Color.Blue.B, Color.Blue.A));

					vertexList.Add(new Vertex3f( 0 + x,  1 + y,  0 + z)); colorList.Add(new ColorRGBA32(Color.Red.R, Color.Red.G, Color.Red.B, Color.Red.A));
					vertexList.Add(new Vertex3f( 0 + x, -1 + y,  1 + z)); colorList.Add(new ColorRGBA32(Color.Magenta.R, Color.Magenta.G, Color.Magenta.B, Color.Magenta.A));
					vertexList.Add(new Vertex3f(-1 + x, -1 + y, -1 + z)); colorList.Add(new ColorRGBA32(Color.Green.R, Color.Green.G, Color.Green.B, Color.Green.A));

					vertexList.Add(new Vertex3f( 0 + x,  1 + y,  0 + z)); colorList.Add(new ColorRGBA32(Color.Red.R, Color.Red.G, Color.Red.B, Color.Red.A));
					vertexList.Add(new Vertex3f( 1 + x, -1 + y, -1 + z)); colorList.Add(new ColorRGBA32(Color.Blue.R, Color.Blue.G, Color.Blue.B, Color.Blue.A));
					vertexList.Add(new Vertex3f( 0 + x, -1 + y,  1 + z)); colorList.Add(new ColorRGBA32(Color.Magenta.R, Color.Magenta.G, Color.Magenta.B, Color.Magenta.A));

					vertexList.Add(new Vertex3f( 0 + x, -1 + y,  1 + z)); colorList.Add(new ColorRGBA32(Color.Magenta.R, Color.Magenta.G, Color.Magenta.B, Color.Magenta.A));
					vertexList.Add(new Vertex3f(-1 + x, -1 + y, -1 + z)); colorList.Add(new ColorRGBA32(Color.Green.R, Color.Green.G, Color.Green.B, Color.Green.A));
					vertexList.Add(new Vertex3f( 1 + x, -1 + y, -1 + z)); colorList.Add(new ColorRGBA32(Color.Blue.R, Color.Blue.G, Color.Blue.B, Color.Blue.A));
				}

		var vertexArray = vertexList.ToArray();
		var colorArray = colorList.ToArray();
		using (MemoryLock vertexArrayLock = new MemoryLock(vertexArray))
		using (MemoryLock vertexColorLock = new MemoryLock(colorArray))
		{
			Gl.VertexPointer(3, VertexPointerType.Float, 0, vertexArrayLock.Address);
			Gl.EnableClientState(EnableCap.VertexArray);

			Gl.ColorPointer(4, ColorPointerType.UnsignedByte, 0, vertexColorLock.Address);
			Gl.EnableClientState(EnableCap.ColorArray);

			Gl.DrawArrays(PrimitiveType.Triangles, 0, vertexArray.Length);
		}

Thank you,
Daniel

Android - Release build crashes on startup

When I make a release build with shared runtime turned off in the build settings (I could not reproduce with debug builds) the app crashes. The issue is in GetProcAddress line 42:

bool eglOnAndroid = Type.GetType("Android.OS.Build, Mono.Android.dll") != null;

evaluates to false in this case. I have no idea why it happens on release builds only.

Examples of rendering to a hidden window...

Hi been trying to work out how to render to a hidden form as wanting to write a console application that renders content saves the back buffer without a form appearing.

Any examples or pointers to how to manually create the context etc would be appreciated...

Xamarin support

Does this project work with desktop Xamarin, Xamarin.Android and Xamarin.iOS?

Raspberry PI VideoCore IV API Support

Current head revision is able to run on Raspberry PI 2 without X server running. It uses the BCM VideoCore IV API to create a window onto the connected LCD, and instantiate GLES2 context properly without errors.

However, no presentation is visible screen, but the glClear operation is executed correctly. This need more investigation.

Here is a dump of the output of the sample application. No errors are generated and it seems that data is marshalled correctly. I tried to follow the RPi sample application found in /opt/vc/src, but I cannot guarantee the call orders.

    mono HelloTriangle.VideoCore.exe
// Querying EGL from libEGL.so
// EGL availability: True
// Querying BCM VideoCore from libbcm_host.so
// BCM VideoCore availability: True
bcm_host_init()
eglGetDisplay(0x00000000) = 00000001
eglInitialize(0x00000001, { null }, { null }) = True
eglGetError() = 12288
eglQueryString(0x00000001, 12372) = 1.4
eglGetError() = 12288
eglQueryString(0x00000001, 12371) = Broadcom
eglGetError() = 12288
eglQueryString(0x00000001, 12429) = OpenGL_ES OpenVG
eglGetError() = 12288
eglTerminate(0x00000001) = True
eglGetError() = 12288
// Creating VideoCore native window
graphics_get_display_size(0, 1920, 1080) = 0
vc_dispmanx_display_open(0) = 268435520
vc_dispmanx_update_start(0) = 1359443983
vc_dispmanx_element_add(1359443983, 268435520, 0, VC_RECT_T={ x=0 y=0 w=1920 h=1080 }, 0, VC_RECT_T={ x=0 y=0 w=125829120 h=70778880 }, 0, 0, 0, DISPMANX_STEREOSCOPIC_NONE) = 536893440
vc_dispmanx_update_submit_sync(1359443983) = 0
// VideoIV Native Window is 0x766170D0
// OpenGL.Net is initializing
eglGetDisplay(0x00000000) = 00000001
eglInitialize(0x00000001, {1}, {4}) = True
eglGetError() = 12288
eglChooseConfig(0x00000001, {12352,4,12339,1,12324,8,12323,8,12322,8,12344}, {8,26,6,4,2,16,14,12}, 8, {8}) = True
eglGetError() = 12288
eglCreatePbufferSurface(0x00000001, 0x00000008, {12375,1,12374,1,12344}) = 00000001
eglGetError() = 12288
eglChooseConfig(0x00000001, {12352,4,12339,5,12324,8,12323,8,12322,8,12344}, {8,26,6,4,2,16,14,12}, 8, {8}) = True
eglGetError() = 12288
eglBindAPI(12448) = True
eglGetError() = 12288
eglCreateContext(0x00000001, 0x00000008, 0x00000000, {12440,2,12344}) = 00000001
eglGetError() = 12288
eglQueryContext(0x00000001, 0x00000001, 12439, {12448}) = True
eglGetError() = 12288
eglBindAPI(12448) = True
eglGetError() = 12288
eglMakeCurrent(0x00000001, 0x00000001, 0x00000001, 0x00000001) = True
eglGetError() = 12288
eglGetCurrentContext() = 00000001
eglGetError() = 12288
glGetString(Version) = OpenGL ES 2.0
glGetError() = NoError
glGetString(Version) = OpenGL ES 2.0
glGetError() = NoError
glGetString(ShadingLanguageVersion) = OpenGL ES GLSL ES 1.00
glGetError() = NoError
glGetString(Vendor) = Broadcom
glGetError() = NoError
glGetString(Renderer) = VideoCore IV HW
glGetError() = NoError
// Query GL extensions.
glGetString(Version) = OpenGL ES 2.0
glGetError() = NoError
glGetString(Extensions) = GL_OES_compressed_ETC1_RGB8_texture GL_OES_compressed_paletted_texture GL_OES_texture_npot GL_OES_depth24 GL_OES_vertex_half_float GL_OES_EGL_image GL_OES_EGL_image_external GL_EXT_discard_framebuffer GL_OES_rgb8_rgba8 GL_OES_depth32 GL_OES_mapbuffer GL_EXT_texture_format_BGRA8888 GL_APPLE_rgb_422 GL_EXT_debug_marker
glGetError() = NoError
// Query OpenGL implementation limits.
glGetIntegerv(0x0D33, 2048)
glGetError() = NoError
glGetIntegerv(0x0D3A, {2048,2048})
glGetError() = NoError
glGetFloatv(0x846E, {0,256})
glGetError() = NoError
glGetIntegerv(0x851C, 2048)
glGetError() = NoError
glGetIntegerv(0x8B4D, 8)
glGetError() = NoError
glGetIntegerv(0x8872, 8)
glGetError() = NoError
glGetIntegerv(0x8869, 8)
glGetError() = NoError
glGetIntegerv(0x8B4C, 8)
glGetError() = NoError
glGetIntegerv(0x84E8, 2048)
glGetError() = NoError
// Query EGL extensions.
eglQueryString(0x00000001, 12373) = EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_KHR_vg_parent_image EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_lock_surface
eglGetError() = 12288
eglMakeCurrent(0x00000001, 0x00000000, 0x00000000, 0x00000000) = True
eglGetError() = 12288
eglDestroyContext(0x00000001, 0x00000001) = True
eglGetError() = 12288
eglDestroySurface(0x00000001, 0x00000001) = True
eglGetError() = 12288
eglTerminate(0x00000001) = True
eglGetError() = 12288
// OpenGL.Net has been initialized
eglGetDisplay(0x00000000) = 00000001
eglInitialize(0x00000001, {1}, {4}) = True
eglGetError() = 12288
eglChooseConfig(0x00000001, {12352,4,12339,4,12324,8,12323,8,12322,8,12321,8,12344}, {7,25,5,3,1,15,13,11}, 8, {8}) = True
eglGetError() = 12288
eglBindAPI(12448) = True
eglGetError() = 12288
eglCreateContext(0x00000001, 0x00000007, 0x00000000, {12440,2,12344}) = 00000001
eglGetError() = 12288
eglCreateWindowSurface(0x00000001, 0x00000007, 0x766170D0, {12344}) = 00000001
eglGetError() = 12288
eglQueryContext(0x00000001, 0x00000001, 12439, {12448}) = True
eglGetError() = 12288
eglBindAPI(12448) = True
eglGetError() = 12288
eglMakeCurrent(0x00000001, 0x00000001, 0x00000001, 0x00000001) = True
eglGetError() = 12288
eglGetCurrentContext() = 00000001
eglGetError() = 12288
glGetString(Version) = OpenGL ES 2.0
glGetError() = NoError
glViewport(0, 0, 1920, 1080)
glGetError() = NoError
glClearColor(1, 0, 0, 0)
glGetError() = NoError
glClear(ColorBufferBit)
glGetError() = NoError
glFlush()
glGetError() = NoError
eglSwapBuffers(0x00000001, 0x00000001) = True
eglGetError() = 12288

Missing IProjectionMatrix interface

The OpenGL.HAL project lists a source file IProjectionMatrix.cs however this file is missing in the repository. Because of this building the project fails. Could you please add this file? In case it's automatiically generated in some way could you please provide building instructions in Readme.md?

Versioning scheme + Release notes

It would probably be a good idea to adopt a reasonable versioning strategy. While not perfect, SEMVER is a pretty good starting point. Feel free to use any scheme you'd like, as long as you can point users to a documentation on what the versions are supposed to mean.

Additionally, and directly related to the versioning is a RELEASE_NOTES.md.file - it would make tracking changes much easier.

To tie all of this (and Issue #5) together, I'd suggest looking at FAKE to manage the build process.

Possible issue regarding some enums and constants

According to the specifications, glTexParameter should accept TextureTarget as the first argument and a TextureParameter as the second, for example GL_TEXTURE_MAX_LEVEL.

However, in OpenGL.NET both GL_TEXTURE_MAX_LEVEL and GL_TEXTURE_2D belong to the TextureTarget enum, making it impossible to set some parameters.

This may be a problem with the code generation system so other constants might be affected as well.

Example code:

// Standard C code
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipMapCount);
// Expected C# code
Gl.TexParameterI(TextureTarget.Texture2d, TextureParameter.TextureMaxLevel, mipMapCount); // TextureParameter doesn't contain the member TextureMaxLevel

Support for glTF

The Opengl.net's Object part seems very closely related to glTF implementation with node based architecture. I think the project should support glTF spec to widen the reach of assets and pipleline which can be readily consumed to help developers fast track their development.

Any Views?

OSX GLFW compatibility

While working on OSX10 with mono runtime a NotImplementedException is thrown while loading the Glx delegates at the Gl initialization.

The 0.2.1 version of this library works correctly.

Is there a way to load context from glfw without using an X11 context which requires an xquartz installation on OSX?

how to solve this

ShaderIncludeLibrary includeLibrary = ctx.IncludeLibrary;
this line shows ctx does not contans the definition of IncludeLibrary
Error 1 โ€œOpenGL.GraphicsContextโ€ do not contains the definition of โ€œIncludeLibraryโ€

have 3D?

How do I present the drawing in 3D?
Do you have an example?

Exception thrown while generating bindings

I've been recently trying to generate bindings without success, as BindingsGen tries to load DTDs from the wrong paths apparently:

System.IO.FileNotFoundException occurred
  HResult=0x80070002
  Message=Impossibile trovare il file 'D:\Documenti\GitHub\OpenGL.Net\RefPages\EN'.
  Source=mscorlib
  StackTrace:
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)
   at BindingsGen.RegistryDocumentationHandler.LocalXhtmlXmlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn) in D:\Documenti\GitHub\OpenGL.Net\BindingsGen\RegistryDocumentationHandler.cs:line 358
   at System.Xml.XmlTextReaderImpl.OpenAndPush(Uri uri)
   at System.Xml.XmlTextReaderImpl.PushExternalEntityOrSubset(String publicId, String systemId, Uri baseUri, String entityName)

The DTD in question is {file:///D:/Documenti/GitHub/OpenGL.Net/BindingsGen/bin/Debug/-/OASIS/DTD DocBook V4.2/EN} according to the debugger.

Encounter NullReferenceException Second Time Gl.Control Window is Opened

I am using OpenGL.Net to display a video stream using the OpenGL.Net.WinForms GlControl. When I open the form window the first time everything works great. However the second time I open the window I get the NullReferenceException shown in the screen capture. I'm not sure why I am encountering the exception. Is it a problem in my code (shown) or a bug in OpenGL.Net? Thanks!

openglnetnullreferenceexception

`
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;

using OpenGL;

/// <summary>
/// Class:
///     OpenGLNetWindowWriter : MediaWindow : MediaOutput : MediaAct
///
/// </summary>
/// <remarks>
/// Thread Safe: Class executes on multiple threads. Constructor executes on calling application
///              thread. A MediaIOThread is created and run from this class.
///              See individual methods. 
/// </remarks>
public class OpenGLNetWindowWriter : MediaWindow
{

    //private static double usPerTick = (double)(1000 * 1000) / (double)Stopwatch.Frequency;

    /// <summary>    
    /// Writes video frames to a window using a SimpleOpenGlControl (Tao OpenGL).
    /// </summary>
    /// <remarks>
    /// Thread Safe: Yes, designed to be called from the main application thread.
    /// </remarks>
    public OpenGLNetWindowWriter()
    {
        MediaActThread = new OpenGLNetWindowWriterMediaIOThread("OpenGL.Net Window Writer", this, ThreadPriority.AboveNormal);
    }

    /// <summary>
    /// Open the media act (parameters must be set before opening).
    /// </summary>
    /// <Param Name="timeTicks">Open time (in ticks).</Param>
    /// <returns></returns>
    /// <remarks>
    /// Thead Safe - Yes
    /// </remarks>
    internal override void ActOpen(long timeTicks, VideoMedia video, AudioMedia audio, MediaScript.ActionEnum action)
    {
        if (!ActOpened)
        {
            videoSizeRatio = (double)video.VideoSize.Width / (double)video.VideoSize.Height;
            windowSize = new Size(video.VideoSize.Width, video.VideoSize.Height);
            windowLocation = new Point(0, 0);   // #### should be passed in?

            base.ActOpen(timeTicks, video, audio, action);
        }
    }

    /// <summary>
    /// Show the window by setting window state to normal (it starts out minimized).
    /// </summary>
    /// <Param Name=""></Param>
    /// <returns></returns>
    /// <remarks>
    /// Thead Safe - Yes, designed to be called from the main application thread.
    /// </remarks>
    private delegate void showDelegate();
    public override void Show()
    {
        OpenGLNetWindowWriterMediaIOThread openGLNetWindowThread = MediaActThread as OpenGLNetWindowWriterMediaIOThread;
        if (openGLNetWindowThread.containerForm.InvokeRequired)
            openGLNetWindowThread.containerForm.BeginInvoke(new showDelegate(SetWindowState));
        else
            SetWindowState();
    }

    private void SetWindowState()
    {
        OpenGLNetWindowWriterMediaIOThread openGLNetWindowThread = MediaActThread as OpenGLNetWindowWriterMediaIOThread;
        if (openGLNetWindowThread.containerForm != null)
            openGLNetWindowThread.containerForm.WindowState = FormWindowState.Normal;
    }

    /// <summary>
    /// Set the size of the window, set the video frame size to fit in the window (scale to maintain aspect ratio).
    /// </summary>
    /// <Param Name="size"> New size of window.</Param>
    /// <returns></returns>
    /// <remarks>
    /// Thead Safe - Yes, intended to be called from the main app thread.
    /// </remarks>
    private delegate void setClientSizeDelegate(Size size);
    public override void SetSize(Size size)
    {
        OpenGLNetWindowWriterMediaIOThread openGLNetWindowThread = MediaActThread as OpenGLNetWindowWriterMediaIOThread;
        if (openGLNetWindowThread.containerForm != null)
            if (openGLNetWindowThread.containerForm.InvokeRequired)
                openGLNetWindowThread.containerForm.BeginInvoke(new setClientSizeDelegate(SetClientSize), size);
            else
                SetClientSize(size);
    }

    /// <summary>
    /// Set the size of the window, set the video frame size to fit in the window (scale to maintain aspect ratio).
    /// </summary>
    /// <Param Name="size"> New size of window.</Param>
    /// <returns></returns>
    /// <remarks>
    /// Thead Safe - No, must be called from the thread the media was opened on (i.e. MediaAct thread).
    /// </remarks>
    private void SetClientSize(Size size)
    {
        OpenGLNetWindowWriterMediaIOThread openGLNetWindowThread = MediaActThread as OpenGLNetWindowWriterMediaIOThread;

        if (openGLNetWindowThread.containerForm != null)
        {
            Size videoSize = size;
            Point videoLocation = new System.Drawing.Point(0, 0);
            windowSize = size;
            openGLNetWindowThread.containerForm.ClientSize = size;

            // keep video size perportional to captured video size
            double windowSizeRatio = (double)size.Width / (double)size.Height;
            if (windowSizeRatio > videoSizeRatio)
            {
                videoSize.Width = (int)((double)size.Height * videoSizeRatio);          // scale video size by height
                videoLocation = new Point((size.Width - videoSize.Width) / 2, 0);       // center video in window
            }
            else if (windowSizeRatio < videoSizeRatio)
            {
                videoSize.Height = (int)((double)size.Width / videoSizeRatio);          // scale video size by width
                videoLocation = new Point(0, (size.Height - videoSize.Height) / 2);       // center video in window
            }

            OpenGL.GlControl openGlControl = openGLNetWindowThread.windowControl as OpenGL.GlControl;
            openGlControl.Size = videoSize;
            openGlControl.Location = videoLocation;
        }

    }

    /// <summary>
    /// Set the screen location of the window.
    /// </summary>
    /// <Param Name="location"> New screen location of window.</Param>
    /// <returns></returns>
    /// <remarks>
    /// Thead Safe - Yes, intended to be called from the main application thread.
    /// </remarks>
    private delegate void setClientLocationDelegate(Point location);
    public override void SetLocation(Point location)
    {
        OpenGLNetWindowWriterMediaIOThread openGLNetWindowThread = MediaActThread as OpenGLNetWindowWriterMediaIOThread;

        if (openGLNetWindowThread.containerForm != null)
            if (openGLNetWindowThread.containerForm.InvokeRequired)
                openGLNetWindowThread.containerForm.BeginInvoke(new setClientLocationDelegate(SetClientLocation), location);
            else
                SetClientLocation(location);
    }

    /// <summary>
    /// Set the screen location of the window.
    /// </summary>
    /// <Param Name="location"> New screen location of window.</Param>
    /// <returns></returns>
    /// <remarks>
    /// Thead Safe - No, must be called from the thread the media was opened on (i.e. MediaAct thread).
    /// </remarks>
    private void SetClientLocation(Point location)
    {
        OpenGLNetWindowWriterMediaIOThread openGLNetWindowThread = MediaActThread as OpenGLNetWindowWriterMediaIOThread;

        if (openGLNetWindowThread.containerForm != null)
        {
            windowLocation = location;
            openGLNetWindowThread.containerForm.Location = location;
        }
    }

    /// <summary>
    /// Set window focus.
    /// </summary>
    /// <Param Name=""></Param>
    /// <returns></returns>
    /// <remarks>
    /// Thead Safe - Yes, intended to be called from the main application thread.
    /// </remarks>
    private delegate void setWindowFocusDelegate();
    public override void SetWindowFocus()
    {
        OpenGLNetWindowWriterMediaIOThread openGLNetWindowThread = MediaActThread as OpenGLNetWindowWriterMediaIOThread;

        if (openGLNetWindowThread.containerForm != null)
            if (openGLNetWindowThread.containerForm.InvokeRequired)
                openGLNetWindowThread.containerForm.BeginInvoke(new setWindowFocusDelegate(SetFocus));
            else
                SetFocus();
    }

    /// <summary>
    /// Set window focus, bring window to top of z-order.
    /// </summary>
    /// <Param Name=""></Param>
    /// <returns></returns>
    /// <remarks>
    /// Thead Safe - No, must be called from the thread the media was opened on (i.e. MediaAct thread).
    /// </remarks>
    private void SetFocus()
    {
        OpenGLNetWindowWriterMediaIOThread openGLNetWindowThread = MediaActThread as OpenGLNetWindowWriterMediaIOThread;
        //System.Diagnostics.Debug.WriteLine("2) openGLNetWindowThread.SetFocus() " + openGLNetWindowThread.containerForm.WindowState.ToString());
        if (openGLNetWindowThread.containerForm != null)
        {
            openGLNetWindowThread.containerForm.TopMost = true;
            openGLNetWindowThread.containerForm.Refresh();
            openGLNetWindowThread.containerForm.TopMost = false;
        }
    }

    /// <summary>
    ///     Class:      OpenGLNetWindowWriterMediaIOThread : MediaIOThread : MediaThread
    ///     
    ///     
    ///     
    ///     
    /// </summary>

    internal class OpenGLNetWindowWriterMediaIOThread : MediaIOThread, IDisposable
    {
        public Control windowControl;
        public Form containerForm;
        private DeviceContext deviceContext;
        private IntPtr renderContext;
        private bool disposed = false;
        private bool delayedStorageCleanup = false;

        public OpenGLNetWindowWriterMediaIOThread(string threadName, MediaAct parent, ThreadPriority priority)
            : base(threadName, parent, priority)
        {
            containerForm = null;
            windowControl = null;
            deviceContext = null;
            renderContext = IntPtr.Zero;
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
                return;

            if (disposing)
            {
                // dispose managed resources
                StopProcessing();
            }
            disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Windows message loop thread.
        /// </summary>
        /// <Param Name=""></Param>
        /// <returns>This method does not return until the Media is closed (Windows form is closed).</returns>
        /// <remarks>
        /// Thead Safe - No, designed to be called from the MediaAct thread.
        /// </remarks>
        protected void WindowsMessageLoop()
        {
            StartProcessing();
        }

        /// <summary>
        /// Open MediaAct media, create windows form, OpenGL.Net windows control, and start Windows message loop thread.
        /// </summary>
        /// <Param Name=""></Param>
        /// <returns>This method does not return until the Media is closed (Windows form is closed).</returns>
        /// <remarks>
        /// Thead Safe - No, designed to be called from the MediaAct thread.
        /// </remarks>
        protected override bool StartProcessing()
        {
            bool success = false;

            try
            {
                OpenGLNetWindowWriter OpenGLNetWindowWriter = ParentMediaAct as OpenGLNetWindowWriter;

                Application.EnableVisualStyles();
                containerForm = new Form();                     // create form as a container for the Open Gl Window

                containerForm.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
                containerForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                containerForm.ControlBox = false;
                containerForm.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
                containerForm.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
                containerForm.Margin = new System.Windows.Forms.Padding(0);
                containerForm.ShowIcon = false;
                containerForm.ShowInTaskbar = false;
                containerForm.ClientSize = OpenGLNetWindowWriter.windowSize;
                containerForm.Location = OpenGLNetWindowWriter.windowLocation;
                containerForm.AutoScaleMode = AutoScaleMode.None;
                containerForm.Cursor = Cursors.Default;
                containerForm.WindowState = FormWindowState.Minimized;
                containerForm.Load += new EventHandler(containerForm_Load);

                // start a windows message loop 
                Application.Run(containerForm);

                // Windows message loop does NOT exit until the form is closed

                success = true;
            }
            catch (System.Exception e)
            {
                System.Diagnostics.Debug.WriteLine("OpenGLNetWindowWriter :" + e.ToString());
            }

            return success;
        }

        /// <summary>
        /// Form load event of the MediaAct thread, used to send MediaAct initialized event.
        /// </summary>
        /// <Param Name=""></Param>
        /// <returns></returns>
        /// <remarks>
        /// Thead Safe - No, must be called from the thread the media was opened on (i.e. MediaAct thread).
        /// </remarks>
        protected void containerForm_Load(object sender, EventArgs e)
        {
            OpenGLNetWindowWriter OpenGLNetWindowWriter = ParentMediaAct as OpenGLNetWindowWriter;

            windowControl = new OpenGL.GlControl();
            OpenGL.GlControl openGlControl = windowControl as OpenGL.GlControl;
            openGlControl.BackColor = System.Drawing.Color.Black;
            openGlControl.Location = new System.Drawing.Point(0, 0);
            openGlControl.Name = "MediaWindowWriter";
            openGlControl.Size = new Size(OpenGLNetWindowWriter.windowSize.Width, OpenGLNetWindowWriter.windowSize.Height);
            openGlControl.AutoScaleMode = AutoScaleMode.None;
            openGlControl.BorderStyle = BorderStyle.None;
            openGlControl.TabStop = false;
            //openGlControl.MouseDown += new System.Windows.Forms.MouseEventHandler(openGlControl_MouseDown);
            //openGlControl.MouseMove += new System.Windows.Forms.MouseEventHandler(openGlControl_MouseMove);
            //openGlControl.MouseUp += new System.Windows.Forms.MouseEventHandler(openGlControl_MouseUp);
            //openGlControl.MouseLeave += new System.EventHandler(openGlControl_MouseLeave);
            openGlControl.MouseClick += new System.Windows.Forms.MouseEventHandler(openGlControl_MouseClick);
            openGlControl.MouseWheel += new System.Windows.Forms.MouseEventHandler(openGlControl_MouseWheel);
            openGlControl.ContextCreated += new EventHandler<GlControlEventArgs>(containerForm_ContextCreated);

            containerForm.Controls.Add(openGlControl);

            OpenGLNetWindowWriter.ActOpened = true;
            OpenGLNetWindowWriter.SendOpenedEvent();
        }

        /// <summary>
        /// OpenGL context created event of the MediaAct thread.
        /// </summary>
        /// <Param Name=""></Param>
        /// <returns></returns>
        /// <remarks>
        /// Thead Safe - No, must be called from the thread the media was opened on (i.e. MediaAct thread).
        /// </remarks>
        protected void containerForm_ContextCreated(object sender, GlControlEventArgs e)
        {
            deviceContext = e.DeviceContext;
            renderContext = e.RenderContext;
            System.Diagnostics.Debug.WriteLine("Context created");
        }

        /// <summary>
        /// OpenGL.Net control mouse click event, send event (back to main application).
        /// </summary>
        /// <Param Name=""></Param>
        /// <returns></returns>
        /// <remarks>
        /// Thead Safe - Yes
        /// </remarks>
        private void openGlControl_MouseClick(object sender, MouseEventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine("openGTKControl_MouseClick()");
            OpenGLNetWindowWriter OpenGLNetWindowWriter = ParentMediaAct as OpenGLNetWindowWriter;
            OpenGLNetWindowWriter.SendWindowMouseClickEvent(e);
        }

        /// <summary>
        /// OpenGL.Net control mouse wheel event, send event (back to main application).
        /// </summary>
        /// <Param Name=""></Param>
        /// <returns></returns>
        /// <remarks>
        /// Thead Safe - No, must be called from the thread the media was opened on (i.e. MediaAct thread).
        /// </remarks>
        private void openGlControl_MouseWheel(object sender, MouseEventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine("openGlControl_MouseWheel()");
            OpenGLNetWindowWriter OpenGLNetWindowWriter = ParentMediaAct as OpenGLNetWindowWriter;
            OpenGLNetWindowWriter.SendWindowMouseWheelEvent(e);
        }

        /// <summary>
        /// CloseMedia
        /// </summary>
        /// <Param Name=""></Param>
        /// <returns></returns>
        /// <remarks>
        /// Thead Safe - No, must be called from the thread the media was opened on (i.e. MediaAct thread). Use
        ///              CloseMediaDelegate() with BeginInvoke() from other threads.
        /// </remarks>
        protected delegate bool CloseMediaDelegate();
        protected override bool StopProcessing()
        {
            bool success = false;

            try
            {
                if (containerForm != null)
                {
                    containerForm.Close();
                    OpenGL.GlControl openGlControl = windowControl as OpenGL.GlControl;
                    openGlControl.Dispose();
                    containerForm = null;
                    deviceContext = null;
                    renderContext = IntPtr.Zero;
                }
                success = true;
            }
            catch (System.Exception e)
            {
                System.Diagnostics.Debug.WriteLine("OpenGLNetWindowWriter.CloseMedia(): " + e.ToString());
            }

            return success;
        }

        /// <summary>
        /// Handle MediaThread events (thread loop).
        /// </summary>
        /// <returns></returns>
        /// <remarks>
        /// Thead Safe - Yes
        /// </remarks>
        protected override void HandleEvents()
        {
            bool started = true;
            ThreadEventsList newEventIndex;
            MediaFrameEventInfo newFrameInfo = null;
            VideoFrame lastOtherFrame = null;
            OpenGLNetWindowWriter OpenGLNetWindowWriter = ParentMediaAct as OpenGLNetWindowWriter;

            // tell anyone who is listening - initialization is complete
            SendInitializedEvent();

            while (started)
            {
                try
                {
                    newEventIndex = (ThreadEventsList)WaitHandle.WaitAny(ThreadEvents);     // ##### need a timeout here ??
                    switch (newEventIndex)
                    {
                        case ThreadEventsList.StartProcessing:

                            // start windows form message loop
                            Thread windowsThread = new Thread(new ThreadStart(WindowsMessageLoop));
                            windowsThread.Name = "OpenGL.Net Window Writer MessageLoop";
                            windowsThread.Start();                                          // #### should add an error event to handle errors in this thread

                            break;

                        case ThreadEventsList.StopProcessing:
                            if (OpenGLNetWindowWriter.ActOpened)
                            {
                                if (containerForm != null)
                                    containerForm.BeginInvoke(new CloseMediaDelegate(StopProcessing));
                                OpenGLNetWindowWriter.ActOpened = false;
                                OpenGLNetWindowWriter.SendClosedEvent();
                            }
                            break;

                        case ThreadEventsList.Shutdown:
                            if (OpenGLNetWindowWriter.ActOpened)
                            {
                                if (containerForm != null)
                                    containerForm.BeginInvoke(new CloseMediaDelegate(StopProcessing));
                                OpenGLNetWindowWriter.ActOpened = false;
                                OpenGLNetWindowWriter.SendClosedEvent();
                            }
                            started = false;
                            break;

                        case ThreadEventsList.Frame:
                            int frameEventQueueCount = 0;
                            lock (FrameEventQueue.SyncRoot)
                                frameEventQueueCount = FrameEventQueue.Count;

                            while (frameEventQueueCount > 0)
                            {
                                lock (FrameEventQueue.SyncRoot)
                                {
                                    newFrameInfo = (MediaFrameEventInfo)FrameEventQueue.Dequeue();
                                    frameEventQueueCount = FrameEventQueue.Count;
                                }
                                MediaScript.ActionEnum action = OpenGLNetWindowWriter.ActAction;

                                if ((OpenGLNetWindowWriter.ActOpened) && (newFrameInfo != null) && (newFrameInfo.Frame != null))
                                {
                                    // see if the frame is a video frame
                                    VideoFrame videoFrame = newFrameInfo.Frame as VideoFrame;

                                    if (videoFrame != null)
                                    {


                                        MediaScript.ActionEnum otherDisplay = (action == MediaScript.ActionEnum.Display1) ? MediaScript.ActionEnum.Display2 : MediaScript.ActionEnum.Display1;

                                        // Frame source and display match (Source1 and Display1 OR Source2 and Display2)
                                        bool frameSourceDisplayMatch = ((videoFrame.Source == MediaScript.ActionEnum.Source1) && (action == MediaScript.ActionEnum.Display1))
                                                                                                                              ||
                                                                       ((videoFrame.Source == MediaScript.ActionEnum.Source2) && (action == MediaScript.ActionEnum.Display2));

                                        //Debug.WriteLine("WindowWriter Action " + action.ToString() + " VideoFrame " + videoFrame.Source.ToString() + " FrameNumber " +
                                        //                videoFrame.FrameNumber.ToString() + " DisplayMatch " + frameSourceDisplayMatch.ToString());

                                        // is swap displays enabled?
                                        if (videoFrame.SwapSource && videoFrame.Script.Is(action, MediaScript.ActionStateEnum.Active) &&
                                            videoFrame.Script.Is(otherDisplay, MediaScript.ActionStateEnum.Active))
                                        {
                                            if (!frameSourceDisplayMatch)
                                                lastOtherFrame = videoFrame;
                                            else if (lastOtherFrame != null)
                                                videoFrame = lastOtherFrame;
                                        }
                                        else if (!frameSourceDisplayMatch)
                                            lastOtherFrame = null;

                                        if (videoFrame.Script.Is(action, MediaScript.ActionStateEnum.Active) && frameSourceDisplayMatch)
                                        {
                                            // write overlay

                                            //string frameTime = ((double)videoFrame.FrameCaptureTimeTicks / (double)Stopwatch.Frequency).ToString("0000.000 ");
                                            //Debug.WriteLine(frameTime + action.ToString() + " " + videoFrame.Source.ToString() + " write overlay
                                            if (videoFrame.DataLock.TryEnterReadLock(videoFrame.DataLockTimeout))
                                            {
                                                // write overlay to display bitmap (only for exam display)
                                                if (videoFrame.Overlay != null)
                                                {
                                                    // draw on the frame bitmap - might want to use a copy here?
                                                    videoFrame.Overlay.Draw(videoFrame.VideoBitmap.RGBBitmap,
                                                        OpenGLNetWindowWriter.ShowSubtitles, OpenGLNetWindowWriter.ShowGraphic);
                                                    if (videoFrame.FilteredVideoBitmap != null)
                                                        videoFrame.Overlay.Draw(videoFrame.FilteredVideoBitmap.RGBBitmap,
                                                            OpenGLNetWindowWriter.ShowSubtitles, OpenGLNetWindowWriter.ShowGraphic);
                                                }
                                                videoFrame.DataLock.ExitReadLock();
                                            }

                                            WriteFrame(videoFrame, OpenGLNetWindowWriter.Video);

                                            // capture image requested ?
                                            if (Interlocked.CompareExchange(ref OpenGLNetWindowWriter.CaptureImageFlag, 0, 1) == 1)
                                                CaptureImage(videoFrame);

                                            if (videoFrame.DataLock.TryEnterWriteLock(videoFrame.DataLockTimeout))
                                            {
                                                // Return video storage to global pool.
                                                if (!delayedStorageCleanup)
                                                {
                                                    videoFrame.ReturnVideoStorage();
                                                    videoFrame.ReturnFilteredVideoStorage();
                                                }
                                                videoFrame.DataLock.ExitWriteLock();
                                            }
                                        }
                                    }

                                    // send audio frame event (i.e. used to display audio level)
                                    AudioFrame audioFrame = newFrameInfo.Frame as AudioFrame;
                                    if (audioFrame != null)
                                    {
                                        if (audioFrame.Script.Is(action, MediaScript.ActionStateEnum.Active))
                                        {
                                            OpenGLNetWindowWriter.SendAudioFrameEvent(new MediaFrameEventInfo(newFrameInfo.Frame));
                                        }
                                    }
                                }

                                if ((newFrameInfo != null) && (newFrameInfo.Frame != null))
                                    OpenGLNetWindowWriter.SendFrameEvent(new MediaFrameEventInfo(newFrameInfo.Frame));
                            }
                            break;
                    }
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine("OpenGLNetWindowWriterMediaIOThread.HandleEvents: " + e.ToString());
                }
            }
        }

        /// <summary>
        /// Writes video frame to the openGl window.
        /// </summary>
        /// <Param Name="frame">Video frame to be written.</Param>
        /// <Param Name="options">Video frame options for writing.</Param>
        /// <returns>true - if no error</returns>
        /// <remarks>
        /// Thead Safe - Yes, intended to be called from the MediaAct thread.
        /// </remarks>
        private bool WriteFrame(VideoFrame frame, VideoMedia options)
        {
            bool result = false;
            delayedStorageCleanup = false;

            if (windowControl != null)
            {
                try
                {
                    if (windowControl.InvokeRequired)
                    {
                        delayedStorageCleanup = true;
                        windowControl.BeginInvoke(new OpenGLNetWindowWriterMediaIOThread.RenderWindowDelegate(Render), frame, options);
                    }
                    else
                        Render(frame, options);
                    result = true;
                }
                catch (System.Exception e)
                {
                    System.Diagnostics.Debug.WriteLine("OpenGLNetWindowWriterMediaIOThread.WriteFrame: " + e.ToString());
                }
            }

            return result;
        }

        /// <summary>
        /// Renders video frame to the openGl window.
        /// </summary>
        /// <Param Name="frame">Video frame to be rendered.</Param>
        /// <Param Name="options">Video frame options for rendering.</Param>
        /// <returns></returns>
        /// <remarks>
        /// Thead Safe - No, must be called from the thread the media was opened on (i.e. MediaAct thread).
        /// </remarks>
        public delegate void RenderWindowDelegate(VideoFrame frame, VideoMedia options);
        public void Render(VideoFrame frame, VideoMedia options)
        {
            RGBStorage videoBitmap;
            BitmapData bmData;
            bool locked = false;

            if (frame != null)
            {
                try
                {
                    frame.FrameDisplayTimeTicks = DateTime.UtcNow.Ticks - frame.FrameCaptureTimeTicks;

                    OpenGL.GlControl openGlControl = windowControl as OpenGL.GlControl;
                    if (openGlControl != null && deviceContext != null)
                    {
                        deviceContext.MakeCurrent(renderContext);
                        Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

                        //Debug.WriteLine("OpenGlWriter.Render TryEnterReadLock Frame");
                        if (frame.DataLock.TryEnterReadLock(frame.DataLockTimeout))
                        {
                            locked = true;

                            videoBitmap = frame.VideoBitmap;
                            //videoBitmap = videoFrame.FilteredVideoBitmap;
                            if (videoBitmap != null)
                            {
                                //System.Diagnostics.Debug.WriteLine("Rendering");
                                if (options.Stereo == VideoMedia.VideoStereoEnum.TopRightBottomLeft)
                                {
                                    Gl.PixelZoom((float)openGlControl.Width / (float)videoBitmap.Width, (float)openGlControl.Height / ((float)videoBitmap.Height) / 2F);
                                    Gl.DrawBuffer(DrawBufferMode.BackLeft);
                                    bmData = videoBitmap.RGBBitmap.LockBits(new Rectangle(0, 0, (int)videoBitmap.Width, (int)videoBitmap.Height / 2),
                                        ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                                    Gl.DrawPixels((int)videoBitmap.Width, (int)videoBitmap.Height, OpenGL.PixelFormat.Bgr, OpenGL.PixelType.UnsignedByte, bmData.Scan0);
                                    videoBitmap.RGBBitmap.UnlockBits(bmData);

                                    Gl.DrawBuffer(DrawBufferMode.BackRight);
                                    bmData = videoBitmap.RGBBitmap.LockBits(new Rectangle(0, (int)videoBitmap.Height, (int)videoBitmap.Width, (int)videoBitmap.Height),
                                        ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                                    Gl.DrawPixels((int)videoBitmap.Width, (int)videoBitmap.Height, OpenGL.PixelFormat.Bgr, OpenGL.PixelType.UnsignedByte, bmData.Scan0);
                                    videoBitmap.RGBBitmap.UnlockBits(bmData);
                                }
                                else if (options.Stereo == VideoMedia.VideoStereoEnum.RightLeft)
                                {
                                    Gl.PixelZoom((float)openGlControl.Width / ((float)videoBitmap.Width) / 2F, (float)openGlControl.Height / (float)videoBitmap.Height);
                                    Gl.DrawBuffer(DrawBufferMode.BackRight);
                                    bmData = videoBitmap.RGBBitmap.LockBits(new Rectangle(0, 0, (int)videoBitmap.Width / 2, (int)videoBitmap.Height),
                                        ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                                    Gl.DrawPixels((int)videoBitmap.Width, (int)videoBitmap.Height, OpenGL.PixelFormat.Bgr, OpenGL.PixelType.UnsignedByte, bmData.Scan0);
                                    videoBitmap.RGBBitmap.UnlockBits(bmData);

                                    Gl.DrawBuffer(DrawBufferMode.BackLeft);
                                    bmData = videoBitmap.RGBBitmap.LockBits(new Rectangle((int)videoBitmap.Width / 2, 0, (int)videoBitmap.Width / 2, (int)videoBitmap.Height),
                                        ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                                    Gl.DrawPixels((int)videoBitmap.Width, (int)videoBitmap.Height, OpenGL.PixelFormat.Bgr, OpenGL.PixelType.UnsignedByte, bmData.Scan0);
                                    videoBitmap.RGBBitmap.UnlockBits(bmData);
                                }
                                else // default to mono (no Stereo)
                                {
                                    Gl.PixelZoom((float)openGlControl.Width / (float)videoBitmap.Width, (float)openGlControl.Height / (float)videoBitmap.Height);
                                    bmData = videoBitmap.RGBBitmap.LockBits(new Rectangle(0, 0, (int)videoBitmap.Width, (int)videoBitmap.Height),
                                        ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                                    Gl.DrawBuffer(DrawBufferMode.BackLeft);
                                    Gl.DrawPixels((int)videoBitmap.Width, (int)videoBitmap.Height, OpenGL.PixelFormat.Bgr, OpenGL.PixelType.UnsignedByte, bmData.Scan0);
                                    videoBitmap.RGBBitmap.UnlockBits(bmData);
                                }

                            }

                            // Return video storage to global pool.
                            if (delayedStorageCleanup)
                            {
                                frame.ReturnVideoStorage();
                                frame.ReturnFilteredVideoStorage();
                            }

                            frame.DataLock.ExitReadLock();
                            locked = false;

                            Gl.Flush();
                            deviceContext.SwapBuffers();
                        }
                        else
                            throw (new Exception("OpenGLNetWindowWriter.Render(): Lock Timeout"));

                        frame.FrameDisplayCompleteTimeTicks = DateTime.UtcNow.Ticks - frame.FrameCaptureTimeTicks;
                    }
                }
                catch (System.Exception e)
                {
                    System.Diagnostics.Debug.WriteLine("OpenGLNetWindowWriter.Render(): " + e.ToString());
                }
                finally
                {
                    if (locked)
                    {
                        //Debug.WriteLine("OpenGlWriter.Render TryEnterReadLock Frame ENTER finally");
                        frame.DataLock.ExitReadLock();
                    }
                }

            }
        }

        /// <summary>
        /// Capture image from video frame and send the capture image event.
        /// </summary>
        /// <Param Name="frame">Current media video frame.</Param>
        /// <returns>true - if no error</returns>
        /// <remarks>
        /// Thead Safe - Yes, intended to be called from the MediaAct thread.
        /// </remarks>
        private bool CaptureImage(VideoFrame videoFrame)
        {
            bool result = false;
            bool locked = false;
            MediaImage newImage = null;
            OpenGLNetWindowWriter openGlWindowWriter = ParentMediaAct as OpenGLNetWindowWriter;

            try
            {
                if ((videoFrame != null) && (videoFrame.DataLock.TryEnterWriteLock(videoFrame.DataLockTimeout)))
                {
                    locked = true;
                    newImage = new MediaImage();
                    newImage.ImageBitmap = (Bitmap)videoFrame.VideoBitmap.RGBBitmap.Clone();
                    if (videoFrame.RawVideoBitmap != null)
                        newImage.RawImageBitmap = (Bitmap)videoFrame.RawVideoBitmap.RGBBitmap.Clone();
                    if (videoFrame.FilteredVideoBitmap != null)
                        newImage.FilteredImageBitmap = (Bitmap)videoFrame.FilteredVideoBitmap.RGBBitmap.Clone();

                }
            }
            catch (Exception e)
            {
                newImage = null;
                System.Diagnostics.Debug.WriteLine("openGlWindowWriterMediaThreadIO.CaptureImage(): " + e.ToString());
            }
            finally
            {
                if (locked)
                    videoFrame.DataLock.ExitWriteLock();
            }

            // post image captured event to anyone who is listening
            if (newImage != null)
            {
                // images need to be flipped (display needs them one way and file needs them another)

                if (newImage.ImageBitmap != null)
                    newImage.ImageBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
                if (newImage.RawImageBitmap != null)
                    newImage.RawImageBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
                if (newImage.FilteredImageBitmap != null)
                    newImage.FilteredImageBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);

                openGlWindowWriter.SendImageEvent(new MediaImageEventInfo(videoFrame.Source, newImage));
            }

            return result;
        }
    }
}

`

Drop WinForms dependency

Following this PR #13, WinForms as a dependency can be completely dropped, and GLControl moved into a separate project, making the wrappers independent of the platform.

Unfortunately, I don't have the time right now to submit a PR for that as well. But, just creating an issue to track it, if that is indeed a forward direction for the project :)

Reconsider approach to choosing Device Contexts to Control

GLControl has a bunch of design time properties that describe the needed pixel format. This was actually a hindrance to getting it working on my machine as the device did not accept the chosen pixel format and the control threw an exception.

I don't know that much about XWindows but is there an equivalent to the wgl ChoosePixelFormat function where the device chooses the pixel format rather than has it imposed on it? This would be more robust.

Game Loop

Hi, I was wondering is there a way to continuously call the render event every frame so that you could essentially make a game editor in windows forms.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.