/// <summary> /// Query the extensions supported by current platform. /// </summary> /// <param name="deviceContext"> /// A <see cref="WindowsDeviceContext"/> that specifies the device context to query extensions for. /// </param> public void Query(XServerDeviceContext deviceContext) { if (deviceContext == null) throw new ArgumentNullException("deviceContext"); LogComment("Query GLX extensions."); string glxExtensions = null; int[] majorArg = new int[1], minorArg = new int[1]; using (Glx.XLock xLock = new Glx.XLock(deviceContext.Display)) { Glx.QueryVersion(deviceContext.Display, majorArg, minorArg); if ((majorArg[0] >= 1) && (minorArg[0] >= 1)) glxExtensions = Glx.QueryExtensionsString(deviceContext.Display, 0); } Query(new KhronosVersion(majorArg[0], minorArg[1]), glxExtensions ?? String.Empty); }
/// <summary> /// Deletes a context. /// </summary> /// <param name="ctx"> /// A <see cref="IntPtr"/> that specify the context to be deleted. /// </param> /// <returns> /// It returns a boolean value indicating whether the operation was successful. If it returns false, /// query the exception by calling <see cref="GetPlatformException"/>. /// </returns> /// <remarks> /// <para>The context <paramref name="ctx"/> must not be current on any thread.</para> /// </remarks> /// <exception cref="ArgumentException"> /// Exception thrown if <paramref name="ctx"/> is IntPtr.Zero. /// </exception> public override bool DeleteContext(IntPtr ctx) { if (ctx == IntPtr.Zero) throw new ArgumentException("ctx"); using (Glx.XLock displayLock = new Glx.XLock(Display)) { Glx.DestroyContext(Display, ctx); } return (true); }
/// <summary> /// Makes the context current on the calling thread. /// </summary> /// <param name="ctx"> /// A <see cref="IntPtr"/> that specify the context to be current on the calling thread, bound to /// thise device context. It can be IntPtr.Zero indicating that no context will be current. /// </param> /// <returns> /// It returns a boolean value indicating whether the operation was successful. /// </returns> /// <exception cref="NotSupportedException"> /// Exception thrown if the current platform is not supported. /// </exception> public override bool MakeCurrent(IntPtr ctx) { using (Glx.XLock displayLock = new Glx.XLock(Display)) { return (Glx.MakeCurrent(Display, ctx != IntPtr.Zero ? WindowHandle : IntPtr.Zero, ctx)); } }
/// <summary> /// Creates a context, specifying attributes. /// </summary> /// <param name="sharedContext"> /// A <see cref="IntPtr"/> that specify a context that will share objects with the returned one. If /// it is IntPtr.Zero, no sharing is performed. /// </param> /// <param name="attribsList"> /// A <see cref="T:Int32[]"/> that specifies the attributes list. /// </param> /// <returns> /// A <see cref="IntPtr"/> that represents the handle of the created context. If the context cannot be /// created, it returns IntPtr.Zero. /// </returns> /// <exception cref="ArgumentNullException"> /// Exception thrown if <see cref="attribsList"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// Exception thrown if <paramref name="attribsList"/> length is zero or if the last item of <paramref name="attribsList"/> /// is not zero. /// </exception> public override IntPtr CreateContextAttrib(IntPtr sharedContext, int[] attribsList) { if (attribsList == null) throw new ArgumentNullException("attribsList"); if (attribsList.Length == 0) throw new ArgumentException("zero length array", "attribsList"); if (attribsList[attribsList.Length - 1] != 0) throw new ArgumentException("not zero-terminated array", "attribsList"); using (Glx.XLock displayLock = new Glx.XLock(Display)) { return (Glx.CreateContextAttribsARB(Display, FBConfig, sharedContext, true, attribsList)); } }
/// <summary> /// Creates a context. /// </summary> /// <param name="sharedContext"> /// A <see cref="IntPtr"/> that specify a context that will share objects with the returned one. If /// it is IntPtr.Zero, no sharing is performed. /// </param> /// <returns> /// A <see cref="IntPtr"/> that represents the handle of the created context. If the context cannot be /// created, it returns IntPtr.Zero. /// </returns> /// <exception cref="InvalidOperationException"> /// Exception thrown in the case <paramref name="sharedContext"/> is different from IntPtr.Zero, and the objects /// cannot be shared with it. /// </exception> public override IntPtr CreateContext(IntPtr sharedContext) { if (XVisualInfo == null) throw new InvalidOperationException("no visual information"); using (Glx.XLock displayLock = new Glx.XLock(Display)) { return (Glx.CreateContext(Display, XVisualInfo, sharedContext, true)); } }
/// <summary> /// Query the GLX version supported by current implementation. /// </summary> private void QueryVersion() { using (Glx.XLock xLock = new Glx.XLock(Display)) { int[] majorArg = new int[1], minorArg = new int[1]; Glx.QueryVersion(Display, majorArg, minorArg); _GlxVersion = new KhronosVersion(majorArg[0], minorArg[0]); } }
/// <summary> /// Control the the buffers swap of a device. /// </summary> /// <param name="deviceContext"> /// A <see cref="IDeviceContext"/> that specifies the device context which buffers will be swapped. /// </param> /// <param name="interval"> /// A <see cref="System.Int32"/> that specifies the minimum number of video frames that are displayed /// before a buffer swap will occur. /// </param> /// <returns> /// It returns a boolean value indicating whether the operation was successful. If it returns false, /// query the exception by calling <see cref="GetPlatformException"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="deviceContext"/> is null. /// </exception> /// <exception cref="NotSupportedException"> /// Exception thrown if the current platform is not supported. /// </exception> public static bool SwapInterval(IDeviceContext deviceContext, int interval) { if (deviceContext == null) throw new ArgumentNullException("deviceContext"); switch (Environment.OSVersion.Platform) { #if OPENGL_NET_SUPPORT_WGL case PlatformID.Win32Windows: case PlatformID.Win32NT: return (Wgl.SwapIntervalEXT(interval)); #endif #if OPENGL_NET_SUPPORT_GLX case PlatformID.Unix: { XServerDeviceContext x11DeviceContext = (XServerDeviceContext)deviceContext; // Keep into account the SwapIntervalEXT and SwapIntervalSGI entry points, relative to // two equivalent GLX extensions using (Glx.XLock displayLock = new Glx.XLock(x11DeviceContext.Display)) { if (Glx.Delegates.pglXSwapIntervalEXT != null) { Glx.SwapIntervalEXT(x11DeviceContext.Display, x11DeviceContext.WindowHandle, interval); return (true); } else if (Glx.Delegates.pglXSwapIntervalSGI != null) return (Glx.SwapIntervalSGI(interval) == 0); else throw new InvalidOperationException("binding point SwapInterval{EXT|SGI} cannot be found"); } } #endif default: throw new NotSupportedException(); } }
/// <summary> /// Creates an OpenGL context from a Windows platform. /// </summary> /// <returns> /// A <see cref="IntPtr"/> /// </returns> private static IntPtr CreateX11SimpleContext(IDeviceContext rDevice) { XServerDeviceContext x11DeviceCtx = (XServerDeviceContext)rDevice; IntPtr rContext; using (Glx.XLock xLock = new Glx.XLock(x11DeviceCtx.Display)) { int[] attributes = new int[] { Glx.RENDER_TYPE, (int)Glx.RGBA_BIT, 0 }; // Get basic visual unsafe { int[] choosenConfigCount = new int[1]; IntPtr* choosenConfigs = Glx.ChooseFBConfig(x11DeviceCtx.Display, x11DeviceCtx.Screen, attributes, choosenConfigCount); if (choosenConfigCount[0] == 0) throw new InvalidOperationException("unable to find basic visual"); IntPtr choosenConfig = *choosenConfigs; x11DeviceCtx.XVisualInfo = Glx.GetVisualFromFBConfig(x11DeviceCtx.Display, choosenConfig); x11DeviceCtx.FBConfig = choosenConfig; Glx.UnsafeNativeMethods.XFree((IntPtr)choosenConfigs); } // Create direct context rContext = x11DeviceCtx.CreateContext(IntPtr.Zero); if (rContext == IntPtr.Zero) { // Fallback to not direct context rContext = Glx.CreateContext(x11DeviceCtx.Display, x11DeviceCtx.XVisualInfo, IntPtr.Zero, false); } if (rContext == IntPtr.Zero) throw new InvalidOperationException("unable to create context"); return (rContext); } }
/// <summary> /// Deletes a context. /// </summary> /// <param name="deviceContext"> /// A <see cref="IDeviceContext"/> that specify the device context used for creating the context <paramref name="ctx"/>. /// </param> /// <param name="ctx"> /// A <see cref="ctx"/> that specify the context to be deleted. /// </param> /// <returns> /// It returns a boolean value indicating whether the operation was successful. If it returns false, /// query the exception by calling <see cref="GetPlatformException"/>. /// </returns> /// <remarks> /// <para>The context <paramref name="ctx"/> must not be current on any thread.</para> /// </remarks> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="deviceContext"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// Exception thrown if <paramref name="ctx"/> is IntPtr.Zero. /// </exception> /// <exception cref="NotSupportedException"> /// Exception thrown if the current platform is not supported. /// </exception> public static bool DeleteContext(IDeviceContext deviceContext, IntPtr ctx) { if (deviceContext == null) throw new ArgumentNullException("deviceContext"); if (ctx == IntPtr.Zero) throw new ArgumentException("ctx"); switch (Environment.OSVersion.Platform) { #if OPENGL_NET_SUPPORT_WGL case PlatformID.Win32Windows: case PlatformID.Win32NT: return (Wgl.DeleteContext(ctx)); #endif #if OPENGL_NET_SUPPORT_GLX case PlatformID.Unix: { XServerDeviceContext x11DeviceContext = (XServerDeviceContext)deviceContext; using (Glx.XLock displayLock = new Glx.XLock(x11DeviceContext.Display)) { Glx.DestroyContext(x11DeviceContext.Display, ctx); } return (true); } #endif default: throw new NotSupportedException(String.Format("platform {0} is not supported", Environment.OSVersion.Platform)); } }
/// <summary> /// Makes the context current on the calling thread. /// </summary> /// <param name="deviceContext"> /// A <see cref="IDeviceContext"/> that specify the device context on which the context has to be current. /// </param> /// <param name="ctx"> /// A <see cref="ctx"/> that specify the context to be current on the calling thread, bound to /// <paramref name="deviceContext"/>. It can be IntPtr.Zero indicating that no context will be current. /// </param> /// <returns> /// It returns a boolean value indicating whether the operation was successful. If it returns false, /// query the exception by calling <see cref="GetPlatformException"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="deviceContext"/> is null. /// </exception> /// <exception cref="NotSupportedException"> /// Exception thrown if the current platform is not supported. /// </exception> public static bool MakeContextCurrent(IDeviceContext deviceContext, IntPtr ctx) { if (deviceContext == null) throw new ArgumentNullException("deviceContext"); switch (Environment.OSVersion.Platform) { #if OPENGL_NET_SUPPORT_WGL case PlatformID.Win32Windows: case PlatformID.Win32NT: { WindowsDeviceContext winDeviceContext = (WindowsDeviceContext)deviceContext; return (Wgl.MakeCurrent(winDeviceContext.DeviceContext, ctx)); } #endif #if OPENGL_NET_SUPPORT_GLX case PlatformID.Unix: { XServerDeviceContext x11DeviceContext = (XServerDeviceContext)deviceContext; using (Glx.XLock displayLock = new Glx.XLock(x11DeviceContext.Display)) { return (Glx.MakeCurrent(x11DeviceContext.Display, ctx != IntPtr.Zero ? x11DeviceContext.WindowHandle : IntPtr.Zero, ctx)); } } #endif default: throw new NotSupportedException(String.Format("platform {0} is not supported", Environment.OSVersion.Platform)); } }
/// <summary> /// Creates a context, specifying attributes. /// </summary> /// <param name="deviceContext"> /// A <see cref="IDeviceContext"/> that specify the device context on which the context has to be created. /// </param> /// <param name="sharedContext"> /// A <see cref="System.IntPtr"/> that specify a context that will share objects with the returned one. If /// it is IntPtr.Zero, no sharing is performed. /// </param> /// <param name="attribsList"> /// A <see cref="T:Int32[]"/> that specifies the attributes list. /// </param> /// <returns> /// A <see cref="System.IntPtr"/> that represents the handle of the created context. If the context cannot be /// created, it returns IntPtr.Zero; if this is the case, query the exception by calling <see cref="GetPlatformException"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="deviceContext"/> or <see cref="attribsList"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// Exception thrown if <paramref name="attribsList"/> length is zero or if the last item of <paramref name="attribsList"/> /// is not zero. /// </exception> /// <exception cref="NotSupportedException"> /// Exception thrown if the current platform is not supported. /// </exception> public static IntPtr CreateContextAttrib(IDeviceContext deviceContext, IntPtr sharedContext, int[] attribsList) { if (deviceContext == null) throw new ArgumentNullException("deviceContext"); if (attribsList == null) throw new ArgumentNullException("attribsList"); if (attribsList.Length == 0) throw new ArgumentException("zero length array", "attribsList"); if (attribsList[attribsList.Length - 1] != 0) throw new ArgumentException("not zero-terminated array", "attribsList"); switch (Environment.OSVersion.Platform) { #if OPENGL_NET_SUPPORT_WGL case PlatformID.Win32Windows: case PlatformID.Win32NT: { WindowsDeviceContext winDeviceContext = (WindowsDeviceContext)deviceContext; return (Wgl.CreateContextAttribsARB(winDeviceContext.DeviceContext, sharedContext, attribsList)); } #endif #if OPENGL_NET_SUPPORT_GLX case PlatformID.Unix: { XServerDeviceContext x11DeviceContext = (XServerDeviceContext)deviceContext; using (Glx.XLock displayLock = new Glx.XLock(x11DeviceContext.Display)) { return (Glx.CreateContextAttribsARB(x11DeviceContext.Display, x11DeviceContext.FBConfig, sharedContext, true, attribsList)); } } #endif default: throw new NotSupportedException(String.Format("platform {0} is not supported", Environment.OSVersion.Platform)); } }
/// <summary> /// Creates a context. /// </summary> /// <param name="deviceContext"> /// A <see cref="IDeviceContext"/> that specify the device context on which the context has to be created. /// </param> /// <param name="sharedContext"> /// A <see cref="System.IntPtr"/> that specify a context that will share objects with the returned one. If /// it is IntPtr.Zero, no sharing is performed. /// </param> /// <returns> /// A <see cref="System.IntPtr"/> that represents the handle of the created context. If the context cannot be /// created, it returns IntPtr.Zero; if this is the case, query the exception by calling <see cref="GetPlatformException"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="deviceContext"/> is null. /// </exception> /// <exception cref="InvalidOperationException"> /// Exception thrown in the case <paramref name="sharedContext"/> is different from IntPtr.Zero, and the objects /// cannot be shared with it. /// </exception> /// <exception cref="NotSupportedException"> /// Exception thrown if the current platform is not supported. /// </exception> public static IntPtr CreateContext(IDeviceContext deviceContext, IntPtr sharedContext) { if (deviceContext == null) throw new ArgumentNullException("deviceContext"); IntPtr renderContext = IntPtr.Zero; switch (Environment.OSVersion.Platform) { #if OPENGL_NET_SUPPORT_WGL case PlatformID.Win32Windows: case PlatformID.Win32NT: try { WindowsDeviceContext winDeviceContext = (WindowsDeviceContext)deviceContext; renderContext = Wgl.CreateContext(winDeviceContext.DeviceContext); if ((renderContext != IntPtr.Zero) && (sharedContext != IntPtr.Zero)) { if (Wgl.ShareLists(renderContext, sharedContext) == false) throw new InvalidOperationException("failed to share object name space"); } return (renderContext); } catch { if (renderContext != IntPtr.Zero) Wgl.DeleteContext(renderContext); throw; } #endif #if OPENGL_NET_SUPPORT_GLX case PlatformID.Unix: { XServerDeviceContext x11DeviceContext = (XServerDeviceContext)deviceContext; if (x11DeviceContext.XVisualInfo == null) throw new InvalidOperationException("no visual information"); using (Glx.XLock displayLock = new Glx.XLock(x11DeviceContext.Display)) { return (Glx.CreateContext(x11DeviceContext.Display, x11DeviceContext.XVisualInfo, sharedContext, true)); } } #endif default: throw new NotSupportedException(String.Format("platform {0} is not supported", Environment.OSVersion.Platform)); } }
/// <summary> /// Set this GraphicsContext current/uncurrent on device different from the one specified at construction time. /// </summary> /// <param name="deviceContext"> /// A <see cref="IDeviceContext"/> that specify the device context involved. /// </param> /// <param name="flag"> /// A <see cref="Boolean"/> that specify the currency of this GraphicsContext on the /// device context <paramref name="rDevice"/>. /// </param> /// <exception cref="ArgumentException"> /// Exception throw in the case <paramref name="rDevice"/> is <see cref="IntPtr.Zero"/>. /// </exception> /// <exception cref="ObjectDisposedException"> /// Exception throw if this GraphicsContext has been disposed. Once the GraphicsContext has been disposed it cannot be current again. /// </exception> /// <exception cref="InvalidOperationException"> /// Exception throw if this GraphicsContext cannot be made current/uncurrent on the device context specified by <paramref name="rDevice"/>. /// </exception> public void MakeCurrent(IDeviceContext deviceContext, bool flag) { if (deviceContext == null) throw new ArgumentNullException("deviceContext"); if (_DeviceContext == null) throw new ObjectDisposedException("no context associated with this GraphicsContext"); int threadId = System.Threading.Thread.CurrentThread.ManagedThreadId; if (flag) { // Make this context current on device if (deviceContext.MakeCurrent(_RenderContext) == false) throw new InvalidOperationException("context cannot be current because error " + Marshal.GetLastWin32Error()); // Cache current device context _CurrentDeviceContext = deviceContext; // Set current context on this thread (only on success) lock (_RenderThreadsLock) { _RenderThreads[threadId] = this; } switch (Environment.OSVersion.Platform) { case PlatformID.Unix: using (Glx.XLock xLock = new Glx.XLock(((XServerDeviceContext)deviceContext).Display)) { Gl.SyncDelegates(); } break; default: Gl.SyncDelegates(); break; } } else { // Make this context uncurrent on device bool res = deviceContext.MakeCurrent(IntPtr.Zero); // Reset current context on this thread (even on error) lock (_RenderThreadsLock) { _RenderThreads[threadId] = null; } if (res == false) throw new InvalidOperationException("context cannot be uncurrent because error " + Marshal.GetLastWin32Error()); } }
/// <summary> /// Swap the buffers of a device. /// </summary> public override void SwapBuffers() { using (Glx.XLock displayLock = new Glx.XLock(Display)) { Glx.SwapBuffers(Display, WindowHandle); } }
/// <summary> /// Swap the buffers of a device. /// </summary> /// <param name="deviceContext"> /// A <see cref="IDeviceContext"/> that specify the device context which buffers will be swapped. /// </param> /// <returns> /// It returns a boolean value indicating whether the operation was successful. If it returns false, /// query the exception by calling <see cref="GetPlatformException"/>. /// </returns> /// <remarks> /// <para>The context <paramref name="ctx"/> must not be current on any thread.</para> /// </remarks> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="deviceContext"/> is null. /// </exception> /// <exception cref="NotSupportedException"> /// Exception thrown if the current platform is not supported. /// </exception> public static void SwapBuffers(IDeviceContext deviceContext) { if (deviceContext == null) throw new ArgumentNullException("deviceContext"); switch (Environment.OSVersion.Platform) { #if OPENGL_NET_SUPPORT_WGL case PlatformID.Win32Windows: case PlatformID.Win32NT: { WindowsDeviceContext winDeviceContext = (WindowsDeviceContext)deviceContext; Wgl.GdiSwapBuffersFast(winDeviceContext.DeviceContext); } break; #endif #if OPENGL_NET_SUPPORT_GLX case PlatformID.Unix: { XServerDeviceContext x11DeviceContext = (XServerDeviceContext)deviceContext; using (Glx.XLock displayLock = new Glx.XLock(x11DeviceContext.Display)) { Glx.SwapBuffers(x11DeviceContext.Display, x11DeviceContext.WindowHandle); } } break; #endif default: throw new NotSupportedException(String.Format("platform {0} is not supported", Environment.OSVersion.Platform)); } }
/// <summary> /// Control the the buffers swap of a device. /// </summary> /// <param name="interval"> /// A <see cref="System.Int32"/> that specifies the minimum number of video frames that are displayed /// before a buffer swap will occur. /// </param> /// <returns> /// It returns a boolean value indicating whether the operation was successful. /// </returns> public override bool SwapInterval(int interval) { // Keep into account the SwapIntervalEXT and SwapIntervalSGI entry points, relative to // two equivalent GLX extensions using (Glx.XLock displayLock = new Glx.XLock(Display)) { if (Glx.Delegates.pglXSwapIntervalEXT != null) { Glx.SwapIntervalEXT(Display, WindowHandle, interval); return (true); } else if (Glx.Delegates.pglXSwapIntervalSGI != null) return (Glx.SwapIntervalSGI(interval) == 0); else throw new InvalidOperationException("binding point SwapInterval{EXT|SGI} cannot be found"); } }
/// <summary> /// Query all X11 extensions supported by current implementation. /// </summary> private void QueryExtensions() { using (Glx.XLock xLock = new Glx.XLock(Display)) { string extString; int[] majorArg = new int[1], minorArg = new int[1]; Glx.QueryVersion(Display, majorArg, minorArg); mGlxMajor = majorArg[0]; mGlxMinor = minorArg[0]; if ((mGlxMajor >= 1) && (mGlxMinor >= 1)) { extString = Glx.QueryExtensionsString(Display, 0); if (!String.IsNullOrEmpty(extString)) { string[] extTokens = extString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string e in extTokens) mExtensions.Add(e, true); } } } }