/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { if (_Handle != IntPtr.Zero) { if (Wgl.CurrentExtensions.Pbuffer_ARB) { bool res = Wgl.DestroyPbufferARB(_Handle); Debug.Assert(res); } else { bool res = Wgl.DestroyPbufferEXT(_Handle); Debug.Assert(res); } _Handle = IntPtr.Zero; } if (_DeviceContext != IntPtr.Zero) { Wgl.ReleaseDC(IntPtr.Zero, _DeviceContext); _DeviceContext = IntPtr.Zero; } }
/// <summary> /// Set the device pixel format. /// </summary> /// <param name="pixelFormat"> /// A <see cref="DevicePixelFormat"/> that specifies the pixel format to set. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="pixelFormat"/> is null. /// </exception> public override void SetPixelFormat(DevicePixelFormat pixelFormat) { if (pixelFormat == null) { throw new ArgumentNullException("pixelFormat"); } if (_PixelFormatSet == true) { throw new InvalidOperationException("pixel format already set"); } #if CHOOSE_PIXEL_FORMAT_FALLBACK try { #endif Wgl.PIXELFORMATDESCRIPTOR pDescriptor = new Wgl.PIXELFORMATDESCRIPTOR(); // Note (from MSDN): Setting the pixel format of a window more than once can lead to significant complications for the Window Manager // and for multithread applications, so it is not allowed. An application can only set the pixel format of a window one time. Once a // window's pixel format is set, it cannot be changed. if (!Wgl.DescribePixelFormat(_DeviceContext, pixelFormat.FormatIndex, (uint)pDescriptor.nSize, ref pDescriptor)) { throw new InvalidOperationException(String.Format("unable to describe pixel format {0}", pixelFormat.FormatIndex), GetPlatformException()); } // Set choosen pixel format if (!Wgl.SetPixelFormat(_DeviceContext, pixelFormat.FormatIndex, ref pDescriptor)) { throw new InvalidOperationException(String.Format("unable to set pixel format {0}: {1}", pixelFormat.FormatIndex), GetPlatformException()); } #if CHOOSE_PIXEL_FORMAT_FALLBACK } catch (InvalidOperationException) { // Try using default ChoosePixelFormat* SetDisplayablePixelFormat(pixelFormat); } #endif // Unable to set pixel format again _PixelFormatSet = true; }
private DevicePixelFormatCollection GetPixelFormats_Win32() { DevicePixelFormatCollection pixelFormats = new DevicePixelFormatCollection(); Wgl.PIXELFORMATDESCRIPTOR pixelDescr = new Wgl.PIXELFORMATDESCRIPTOR(); int pixelFormatsCount = Wgl.DescribePixelFormat(_DeviceContext, 0, 0, ref pixelDescr); for (int i = 1; i <= pixelFormatsCount; i++) { Wgl.DescribePixelFormat(_DeviceContext, i, (uint)Marshal.SizeOf(typeof(Wgl.PIXELFORMATDESCRIPTOR)), ref pixelDescr); if ((pixelDescr.dwFlags & Wgl.PixelFormatDescriptorFlags.SupportOpenGL) == 0) continue; DevicePixelFormat pixelFormat = new DevicePixelFormat(); pixelFormat.FormatIndex = i; pixelFormat.RgbaUnsigned = true; pixelFormat.RgbaFloat = false; pixelFormat.RenderWindow = true; pixelFormat.RenderBuffer = false; pixelFormat.DoubleBuffer = (pixelDescr.dwFlags & Wgl.PixelFormatDescriptorFlags.Doublebuffer) != 0; pixelFormat.SwapMethod = 0; pixelFormat.StereoBuffer = (pixelDescr.dwFlags & Wgl.PixelFormatDescriptorFlags.Stereo) != 0; pixelFormat.ColorBits = pixelDescr.cColorBits; pixelFormat.DepthBits = pixelDescr.cDepthBits; pixelFormat.StencilBits = pixelDescr.cStencilBits; pixelFormat.MultisampleBits = 0; pixelFormat.RenderPBuffer = false; pixelFormat.SRGBCapable = false; pixelFormats.Add(pixelFormat); } return (pixelFormats); }
/// <summary> /// Initializes a new instance of the <see cref="WindowsDeviceContext"/> class. /// </summary> /// <param name='window'> /// Window. /// </param> /// <exception cref='ArgumentNullException'> /// Is thrown when an argument passed to a method is invalid because it is <see langword="null" /> . /// </exception> /// <exception cref='InvalidOperationException'> /// Is thrown when an operation cannot be performed. /// </exception> public WindowsDeviceContext(Control window) { if (window == null) { throw new ArgumentNullException("window"); } // "Force" handle creation if (!window.IsHandleCreated && window.Handle != IntPtr.Zero) { throw new InvalidOperationException("invalid handle"); } _WindowHandle = window.Handle; _DeviceContext = Wgl.GetDC(window.Handle); if (DeviceContext == IntPtr.Zero) { throw new InvalidOperationException("unable to get any video device context"); } }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting managed/unmanaged resources. /// </summary> /// <param name="disposing"> /// A <see cref="System.Boolean"/> indicating whether the disposition is requested explictly. /// </param> protected override void Dispose(bool disposing) { if (disposing) { // Release device context if (_DeviceContext != IntPtr.Zero) { if (_DeviceContextPBuffer == false) { bool res = Wgl.ReleaseDC(_WindowHandle, _DeviceContext); Debug.Assert(res); } else { int res = Wgl.ReleasePbufferDCARB(_WindowHandle, _DeviceContext); Debug.Assert(res == 1); } _DeviceContext = IntPtr.Zero; _WindowHandle = IntPtr.Zero; } } // Base implementation base.Dispose(disposing); }
/// <summary> /// Construct a NativePBuffer with a specific pixel format and size. /// </summary> /// <param name="pixelFormat"> /// A <see cref="DevicePixelFormat"/> that specifies the pixel format and the ancillary buffers required. /// </param> /// <param name="width"> /// A <see cref="UInt32"/> that specifies the width of the P-Buffer, in pixels. /// </param> /// <param name="height"> /// A <see cref="UInt32"/> that specifies the height of the P-Buffer, in pixels. /// </param> public NativePBuffer(DevicePixelFormat pixelFormat, uint width, uint height) { if (pixelFormat == null) { throw new ArgumentNullException("pixelFormat"); } if (!Wgl.CurrentExtensions.Pbuffer_ARB && !Wgl.CurrentExtensions.Pbuffer_EXT) { throw new NotSupportedException("WGL_(ARB|EXT)_pbuffer not implemented"); } try { // Uses screen device context _DeviceContext = Wgl.GetDC(Gl._NativeWindow.Handle); // Choose appropriate pixel format pixelFormat.RenderWindow = false; // XXX pixelFormat.RenderPBuffer = true; pixelFormat.DoubleBuffer = true; int pixelFormatIndex = ChoosePixelFormat(_DeviceContext, pixelFormat); if (Wgl.CurrentExtensions.Pbuffer_ARB) { _Handle = Wgl.CreatePbufferARB(_DeviceContext, pixelFormatIndex, (int)width, (int)height, new int[] { 0 }); } else { _Handle = Wgl.CreatePbufferEXT(_DeviceContext, pixelFormatIndex, (int)width, (int)height, new int[] { 0 }); } if (_Handle == IntPtr.Zero) { throw new InvalidOperationException("unable to create P-Buffer", GetPlatformExceptionCore()); } } catch { Dispose(); throw; } }
/// <summary> /// Set the device pixel format. /// </summary> /// <param name="pixelFormat"> /// A <see cref="DevicePixelFormat"/> that specifies the pixel format to set. /// </param> private static int ChoosePixelFormat(IntPtr deviceContext, DevicePixelFormat pixelFormat) { if (pixelFormat == null) throw new ArgumentNullException("pixelFormat"); List<int> attribIList = new List<int>(); List<float> attribFList = new List<float>(); uint[] countFormatAttribsValues = new uint[1]; int[] choosenFormats = new int[4]; attribIList.AddRange(new int[] { Wgl.SUPPORT_OPENGL_ARB, Gl.TRUE }); if (pixelFormat.RenderWindow) attribIList.AddRange(new int[] { Wgl.DRAW_TO_WINDOW_ARB, Gl.TRUE }); if (pixelFormat.RenderPBuffer) attribIList.AddRange(new int[] { Wgl.DRAW_TO_PBUFFER_ARB, Gl.TRUE }); if (pixelFormat.RgbaUnsigned) attribIList.AddRange(new int[] { Wgl.PIXEL_TYPE_ARB, Wgl.TYPE_RGBA_ARB }); if (pixelFormat.RgbaFloat) attribIList.AddRange(new int[] { Wgl.PIXEL_TYPE_ARB, Wgl.TYPE_RGBA_FLOAT_ARB }); if (pixelFormat.ColorBits > 0) attribIList.AddRange(new int[] { Wgl.COLOR_BITS_ARB, pixelFormat.ColorBits }); if (pixelFormat.DepthBits > 0) attribIList.AddRange(new int[] { Wgl.DEPTH_BITS_ARB, pixelFormat.DepthBits }); if (pixelFormat.StencilBits > 0) attribIList.AddRange(new int[] { Wgl.STENCIL_BITS_ARB, pixelFormat.StencilBits }); if (pixelFormat.DoubleBuffer) attribIList.AddRange(new int[] { Wgl.DOUBLE_BUFFER_ARB, pixelFormat.StencilBits }); attribIList.Add(0); // Let choose pixel formats if (!Wgl.ChoosePixelFormatARB(deviceContext, attribIList.ToArray(), attribFList.ToArray(), (uint)choosenFormats.Length, choosenFormats, countFormatAttribsValues)) throw new InvalidOperationException("unable to choose pixel format", GetPlatformExceptionCore()); return (choosenFormats[0]); }
/// <summary> /// Initialize LTS information for the calling thread. /// </summary> public static void InitializeThread() { #if !MONODROID if (Egl.IsRequired == false) { switch (Platform.CurrentPlatformId) { case Platform.Id.WindowsNT: Wgl.BindAPI(); break; case Platform.Id.Linux: Glx.BindAPI(); break; case Platform.Id.MacOS: if (Glx.IsRequired) { Glx.BindAPI(); } else { throw new NotSupportedException("platform MacOS not supported without Glx.IsRequired=true"); } break; case Platform.Id.Android: Egl.BindAPI(); break; default: throw new NotSupportedException(String.Format("platform {0} not supported", Platform.CurrentPlatformId)); } } else #endif Egl.BindAPI(); }
/// <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) { IntPtr renderContext = IntPtr.Zero; try { renderContext = Wgl.CreateContext(DeviceContext); if ((renderContext != IntPtr.Zero) && (sharedContext != IntPtr.Zero)) { bool res = Wgl.ShareLists(renderContext, sharedContext); Debug.Assert(res); } return(renderContext); } catch { if (renderContext != IntPtr.Zero) { bool res = Wgl.DeleteContext(renderContext); Debug.Assert(res); } throw; } }
/// <summary> /// Set pixel format by letting the driver choose the best pixel format following the criteria. /// </summary> /// <param name="pixelFormat"> /// /// </param> private void SetDisplayablePixelFormat(DevicePixelFormat pixelFormat) { if (pixelFormat == null) throw new ArgumentNullException("pixelFormat"); List<int> attribIList = new List<int>(); List<float> attribFList = new List<float>(); Wgl.PIXELFORMATDESCRIPTOR pDescriptor = new Wgl.PIXELFORMATDESCRIPTOR(); uint[] countFormatAttribsValues = new uint[1]; int[] choosenFormats = new int[4]; // Let choose pixel formats if (!Wgl.ChoosePixelFormatARB(_DeviceContext, attribIList.ToArray(), attribFList.ToArray(), (uint)choosenFormats.Length, choosenFormats, countFormatAttribsValues)) { Win32Exception innerException = new Win32Exception(Marshal.GetLastWin32Error()); throw new InvalidOperationException(String.Format("unable to choose pixel format: {0}", innerException.Message), innerException); } // Set choosen pixel format if (Wgl.SetPixelFormat(_DeviceContext, choosenFormats[0], ref pDescriptor) == false) { Win32Exception innerException = new Win32Exception(Marshal.GetLastWin32Error()); throw new InvalidOperationException(String.Format("unable to set pixel format {0}: {1}", pixelFormat.FormatIndex, innerException.Message), innerException); } }
/// <summary> /// Initializes a new instance of the <see cref="DeviceContextWGL"/> class. /// </summary> /// <param name='nativeBuffer'> /// A <see cref="INativePBuffer"/> that specifies the P-Buffer used to create the device context. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="nativeBuffer"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// Exception thrown if <paramref name="nativeBuffer"/> is not an instance created by /// <see cref="DeviceContext.CreatePBuffer(DevicePixelFormat, uint, uint)"/>. /// </exception> /// <exception cref='InvalidOperationException'> /// Is thrown when an operation cannot be performed. /// </exception> public DeviceContextWGL(INativePBuffer nativeBuffer) { if (nativeBuffer == null) { throw new ArgumentNullException("nativeBuffer"); } NativePBuffer nativePBuffer = nativeBuffer as NativePBuffer; if (nativePBuffer == null) { throw new ArgumentException("INativePBuffer not created with DeviceContext.CreatePBuffer"); } if (!Wgl.CurrentExtensions.Pbuffer_ARB && !Wgl.CurrentExtensions.Pbuffer_EXT) { throw new InvalidOperationException("WGL_(ARB|EXT)_pbuffer not supported"); } _WindowHandle = nativePBuffer.Handle; if (Wgl.CurrentExtensions.Pbuffer_ARB) { _DeviceContext = Wgl.GetPbufferDCARB(nativePBuffer.Handle); } else { _DeviceContext = Wgl.GetPbufferDCEXT(nativePBuffer.Handle); } if (_DeviceContext == IntPtr.Zero) { throw new InvalidOperationException("unable to get device context"); } _DeviceContextPBuffer = true; }
/// <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> /// <param name="api"> /// A <see cref="KhronosVersion"/> that specifies the API to be implemented by the returned context. It can be null indicating the /// default API for this DeviceContext implementation. If it is possible, try to determine the API version also. /// </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, KhronosVersion api) { if ((attribsList != null) && (attribsList.Length == 0)) { throw new ArgumentException("zero length array", "attribsList"); } if ((attribsList != null) && (attribsList[attribsList.Length - 1] != 0)) { throw new ArgumentException("not zero-terminated array", "attribsList"); } if (api != null && api.Api != KhronosVersion.ApiGl) { List <int> adulteredAttribs = new List <int>(attribsList); // Support check switch (api.Api) { case KhronosVersion.ApiGles1: case KhronosVersion.ApiGles2: if (Wgl.CurrentExtensions.CreateContextEsProfile_EXT == false) { throw new NotSupportedException("OpenGL ES API not supported"); } break; default: throw new NotSupportedException(String.Format("'{0}' API not supported", api.Api)); } // Remove trailing 0 if (adulteredAttribs.Count > 0 && adulteredAttribs[adulteredAttribs.Count - 1] == Gl.NONE) { adulteredAttribs.RemoveAt(adulteredAttribs.Count - 1); } // Add required attributes int majorVersionIndex = adulteredAttribs.FindIndex(delegate(int item) { return(item == Wgl.CONTEXT_MAJOR_VERSION_ARB); }); int minorVersionIndex = adulteredAttribs.FindIndex(delegate(int item) { return(item == Wgl.CONTEXT_MINOR_VERSION_ARB); }); int profileMaskIndex = adulteredAttribs.FindIndex(delegate(int item) { return(item == Wgl.CONTEXT_PROFILE_MASK_ARB); }); if (majorVersionIndex < 0) { adulteredAttribs.AddRange(new int[] { Gl.MAJOR_VERSION, api.Major }); majorVersionIndex = adulteredAttribs.Count - 2; } if (minorVersionIndex < 0) { adulteredAttribs.AddRange(new int[] { Gl.MINOR_VERSION, api.Minor }); minorVersionIndex = adulteredAttribs.Count - 2; } if (profileMaskIndex < 0) { adulteredAttribs.AddRange(new int[] { Gl.CONTEXT_PROFILE_MASK, 0 }); profileMaskIndex = adulteredAttribs.Count - 2; } switch (api.Api) { case KhronosVersion.ApiGles1: // Ignore API version: force always to 1.0 adulteredAttribs[majorVersionIndex + 1] = 1; adulteredAttribs[minorVersionIndex + 1] = 0; adulteredAttribs[profileMaskIndex + 1] |= (int)Wgl.CONTEXT_ES_PROFILE_BIT_EXT; break; case KhronosVersion.ApiGles2: // Uses API version: it may be greater than 2.0(?) adulteredAttribs[majorVersionIndex + 1] = 2; adulteredAttribs[minorVersionIndex + 1] = 0; adulteredAttribs[profileMaskIndex + 1] |= (int)Wgl.CONTEXT_ES_PROFILE_BIT_EXT; break; default: Debug.Fail("API not implemented"); throw new NotSupportedException(String.Format("'{0}' API not supported", api.Api)); } // Restore trailing 0 adulteredAttribs.Add(Gl.NONE); return(Wgl.CreateContextAttribsARB(_DeviceContext, sharedContext, adulteredAttribs.ToArray())); } else { return(Wgl.CreateContextAttribsARB(_DeviceContext, sharedContext, attribsList)); } }
/// <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) { return(Wgl.SwapIntervalEXT(interval)); }
private DevicePixelFormatCollection GetPixelFormats_ARB_pixel_format(Wgl.Extensions wglExtensions) { // Get the number of pixel formats int[] countFormatAttribsCodes = new int[] { Wgl.NUMBER_PIXEL_FORMATS_ARB }; int[] countFormatAttribsValues = new int[countFormatAttribsCodes.Length]; Wgl.GetPixelFormatAttribARB(_DeviceContext, 1, 0, (uint)countFormatAttribsCodes.Length, countFormatAttribsCodes, countFormatAttribsValues); // Request configurations List<int> pixelFormatAttribsCodes = new List<int>(12); // Minimum requirements pixelFormatAttribsCodes.Add(Wgl.SUPPORT_OPENGL_ARB); // Required to be Gl.TRUE pixelFormatAttribsCodes.Add(Wgl.ACCELERATION_ARB); // Required to be Wgl.FULL_ACCELERATION or Wgl.ACCELERATION_ARB pixelFormatAttribsCodes.Add(Wgl.PIXEL_TYPE_ARB); // Buffer destination pixelFormatAttribsCodes.Add(Wgl.DRAW_TO_WINDOW_ARB); pixelFormatAttribsCodes.Add(Wgl.DRAW_TO_BITMAP_ARB); // Multiple buffers pixelFormatAttribsCodes.Add(Wgl.DOUBLE_BUFFER_ARB); pixelFormatAttribsCodes.Add(Wgl.SWAP_METHOD_ARB); pixelFormatAttribsCodes.Add(Wgl.STEREO_ARB); // Pixel description pixelFormatAttribsCodes.Add(Wgl.COLOR_BITS_ARB); pixelFormatAttribsCodes.Add(Wgl.DEPTH_BITS_ARB); pixelFormatAttribsCodes.Add(Wgl.STENCIL_BITS_ARB); #if SUPPORT_MULTISAMPLE // Multisample extension if (wglExtensions.Multisample_ARB || wglExtensions.Multisample_EXT) { pixelFormatAttribsCodes.Add(Wgl.SAMPLE_BUFFERS_ARB); pixelFormatAttribsCodes.Add(Wgl.SAMPLES_ARB); } int pixelFormatAttribMultisampleIndex = pixelFormatAttribsCodes.Count - 1; #endif #if SUPPORT_PBUFFER if (wglExtensions.Pbuffer_ARB || wglExtensions.Pbuffer_EXT) { pixelFormatAttribsCodes.Add(Wgl.DRAW_TO_PBUFFER_ARB); } int pixelFormatAttribPBufferIndex = pixelFormatAttribsCodes.Count - 1; #endif #if SUPPORT_FRAMEBUFFER_SRGB // Framebuffer sRGB extension if (wglExtensions.FramebufferSRGB_ARB || wglExtensions.FramebufferSRGB_EXT) pixelFormatAttribsCodes.Add(Wgl.FRAMEBUFFER_SRGB_CAPABLE_ARB); int pixelFormatAttribFramebufferSrgbIndex = pixelFormatAttribsCodes.Count - 1; #endif // Create pixel format collection DevicePixelFormatCollection pixelFormats = new DevicePixelFormatCollection(); // Retrieve information about available pixel formats int[] pixelFormatAttribValues = new int[pixelFormatAttribsCodes.Count]; for (int pixelFormatIndex = 1; pixelFormatIndex < countFormatAttribsValues[0]; pixelFormatIndex++) { DevicePixelFormat pixelFormat = new DevicePixelFormat(); Wgl.GetPixelFormatAttribARB(_DeviceContext, pixelFormatIndex, 0, (uint)pixelFormatAttribsCodes.Count, pixelFormatAttribsCodes.ToArray(), pixelFormatAttribValues); // Check minimum requirements if (pixelFormatAttribValues[0] != Gl.TRUE) continue; // No OpenGL support if (pixelFormatAttribValues[1] != Wgl.FULL_ACCELERATION_ARB) continue; // No hardware acceleration switch (pixelFormatAttribValues[2]) { case Wgl.TYPE_RGBA_ARB: #if SUPPORT_PIXEL_FORMAT_FLOAT case Wgl.TYPE_RGBA_FLOAT_ARB: #endif #if SUPPORT_PIXEL_FORMAT_PACKED_FLOAT case Wgl.TYPE_RGBA_UNSIGNED_FLOAT_EXT: #endif break; default: continue; // Ignored pixel type } // Collect pixel format attributes pixelFormat.FormatIndex = pixelFormatIndex; switch (pixelFormatAttribValues[2]) { case Wgl.TYPE_RGBA_ARB: pixelFormat.RgbaUnsigned = true; break; case Wgl.TYPE_RGBA_FLOAT_ARB: pixelFormat.RgbaFloat = true; break; case Wgl.TYPE_RGBA_UNSIGNED_FLOAT_EXT: pixelFormat.RgbaFloat = pixelFormat.RgbaUnsigned = true; break; } pixelFormat.RenderWindow = pixelFormatAttribValues[3] == Gl.TRUE; pixelFormat.RenderBuffer = pixelFormatAttribValues[4] == Gl.TRUE; pixelFormat.DoubleBuffer = pixelFormatAttribValues[5] == Gl.TRUE; pixelFormat.SwapMethod = pixelFormatAttribValues[6]; pixelFormat.StereoBuffer = pixelFormatAttribValues[7] == Gl.TRUE; pixelFormat.ColorBits = pixelFormatAttribValues[8]; pixelFormat.DepthBits = pixelFormatAttribValues[9]; pixelFormat.StencilBits = pixelFormatAttribValues[10]; #if SUPPORT_MULTISAMPLE if (wglExtensions.Multisample_ARB || wglExtensions.Multisample_EXT) { Debug.Assert(pixelFormatAttribMultisampleIndex >= 0); pixelFormat.MultisampleBits = pixelFormatAttribValues[pixelFormatAttribMultisampleIndex]; } #endif #if SUPPORT_PBUFFER if (wglExtensions.Pbuffer_ARB || wglExtensions.Pbuffer_EXT) { Debug.Assert(pixelFormatAttribPBufferIndex >= 0); pixelFormat.RenderPBuffer = pixelFormatAttribValues[pixelFormatAttribPBufferIndex] == Gl.TRUE; } #endif #if SUPPORT_FRAMEBUFFER_SRGB if (wglExtensions.FramebufferSRGB_ARB || wglExtensions.FramebufferSRGB_EXT) { Debug.Assert(pixelFormatAttribFramebufferSrgbIndex >= 0); pixelFormat.SRGBCapable = pixelFormatAttribValues[pixelFormatAttribFramebufferSrgbIndex] != 0; } #endif pixelFormats.Add(pixelFormat); } return (pixelFormats); }
/// <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> /// <param name="api"> /// A <see cref="KhronosVersion"/> that specifies the API to be implemented by the returned context. It can be null indicating the /// default API for this DeviceContext implementation. If it is possible, try to determine the API version also. /// </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, KhronosVersion api) { if (Wgl.CurrentExtensions != null && Wgl.CurrentExtensions.CreateContext_ARB == false) throw new InvalidOperationException("WGL_ARB_create_context not supported"); if ((attribsList != null) && (attribsList.Length == 0)) throw new ArgumentException("zero length array", "attribsList"); if ((attribsList != null) && (attribsList[attribsList.Length - 1] != Gl.NONE)) throw new ArgumentException("not zero-terminated array", "attribsList"); // Defaults null attributes if (attribsList == null) attribsList = new int[] { Gl.NONE }; if (api != null) { List<int> adulteredAttribs = new List<int>(attribsList); // Support check switch (api.Api) { case KhronosVersion.ApiGl: break; case KhronosVersion.ApiGles1: case KhronosVersion.ApiGles2: case KhronosVersion.ApiGlsc2: if (Wgl.CurrentExtensions.CreateContextEsProfile_EXT == false) throw new NotSupportedException("OpenGL ES API not supported"); break; default: throw new NotSupportedException(String.Format("'{0}' API not supported", api.Api)); } // Remove trailing 0 if (adulteredAttribs.Count > 0 && adulteredAttribs[adulteredAttribs.Count - 1] == Gl.NONE) adulteredAttribs.RemoveAt(adulteredAttribs.Count - 1); // Add required attributes int major = api.Major, minor = api.Minor, profileMask = 0; switch (api.Api) { case KhronosVersion.ApiGl: switch (api.Profile) { case KhronosVersion.ProfileCompatibility: profileMask |= (int)Wgl.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; break; case KhronosVersion.ProfileCore: profileMask |= (int)Wgl.CONTEXT_CORE_PROFILE_BIT_ARB; break; case null: // No specific profile required, leaving the default (core profile) break; default: throw new NotSupportedException(String.Format("'{0}' Profile not supported", api.Profile)); } break; case KhronosVersion.ApiGles1: // Ignore API version: force always to 1.0 major = 1; minor = 0; profileMask |= (int)Wgl.CONTEXT_ES_PROFILE_BIT_EXT; break; case KhronosVersion.ApiGles2: case KhronosVersion.ApiGlsc2: major = 2; minor = 0; profileMask |= (int)Wgl.CONTEXT_ES_PROFILE_BIT_EXT; break; default: Debug.Fail("API not implemented"); throw new NotSupportedException(String.Format("'{0}' API not supported", api.Api)); } // Add/Replace attributes int majorVersionIndex, minorVersionIndex, profileMaskIndex; if ((majorVersionIndex = adulteredAttribs.FindIndex(delegate (int item) { return (item == Wgl.CONTEXT_MAJOR_VERSION_ARB); })) >= 0) adulteredAttribs[majorVersionIndex + 1] = major; else adulteredAttribs.AddRange(new int[] { Wgl.CONTEXT_MAJOR_VERSION_ARB, major }); if ((minorVersionIndex = adulteredAttribs.FindIndex(delegate (int item) { return (item == Wgl.CONTEXT_MINOR_VERSION_ARB); })) >= 0) adulteredAttribs[minorVersionIndex + 1] = minor; else adulteredAttribs.AddRange(new int[] { Wgl.CONTEXT_MINOR_VERSION_ARB, api.Minor }); if (profileMask != 0) { if ((profileMaskIndex = adulteredAttribs.FindIndex(delegate (int item) { return (item == Wgl.CONTEXT_PROFILE_MASK_ARB); })) >= 0) adulteredAttribs[profileMaskIndex + 1] = profileMask; else adulteredAttribs.AddRange(new int[] { Wgl.CONTEXT_PROFILE_MASK_ARB, profileMask }); } // Restore trailing 0 adulteredAttribs.Add(Gl.NONE); return (Wgl.CreateContextAttribsARB(_DeviceContext, sharedContext, adulteredAttribs.ToArray())); } else return (Wgl.CreateContextAttribsARB(_DeviceContext, sharedContext, attribsList)); }
/// <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> protected override bool MakeCurrentCore(IntPtr ctx) { return(Wgl.MakeCurrent(_DeviceContext, ctx)); }
/// <summary> /// Initialize OpenGL namespace static environment. This method shall be called before any other classes methods. /// </summary> public static void Initialize() { if (_Initialized == true) { return; // Already initialized } _Initialized = true; #if !NETSTANDARD1_1 // Optional initialization string envGlInit = Environment.GetEnvironmentVariable("OPENGL_NET_INIT"); if (envGlInit != null && envGlInit == "NO") { return; } #endif // Environment options LogComment("OpenGL.Net is initializing"); // Loader function OS API GL API // ------------------------------------------------------ // Supported platform: Windows // wglGetProcAddress WGL GL // wglGetProcAddress WGL GLES2+ (with WGL_create_context_es(2)?_profile_EXT) // eglGetProcAddress EGL(Angle) GLES2+ // ------------------------------------------------------ // Supported platform: Linux // glXGetProcAddress GLX GL // glXGetProcAddress GLX GLES2+ (with GLX_create_context_es(2)?_profile_EXT) // eglGetProcAddress EGL GLES2+ // ------------------------------------------------------ // Supported platform: Android // eglGetProcAddress EGL GL // eglGetProcAddress EGL GLES2+ try { #if !MONODROID // Determine whether use EGL as device context backend if (Egl.IsAvailable) { switch (Platform.CurrentPlatformId) { case Platform.Id.Linux: if (Glx.IsAvailable == false) { Egl.IsRequired = true; } break; } } #endif // Create native window for getting preliminary information on desktop systems // This instance will be used for creating contexts without explictly specify a window _NativeWindow = DeviceContext.CreateHiddenWindow(); // Create device context using (DeviceContext windowDevice = DeviceContext.Create()) { // Create basic OpenGL context IntPtr renderContext = windowDevice.CreateSimpleContext(); if (renderContext == IntPtr.Zero) { throw new NotImplementedException("unable to create a simple context"); } // Make contect current if (windowDevice.MakeCurrent(renderContext) == false) { throw new InvalidOperationException("unable to make current", windowDevice.GetPlatformException()); } #if !MONODROID // Reload platform function pointers, if required if (Egl.IsRequired == false) { switch (Platform.CurrentPlatformId) { case Platform.Id.WindowsNT: Wgl.BindAPI(); break; } } #endif // Query OpenGL informations string glVersion = GetString(StringName.Version); _CurrentVersion = KhronosVersion.Parse(glVersion); // Query OpenGL extensions (current OpenGL implementation, CurrentCaps) _CurrentExtensions = new Extensions(); _CurrentExtensions.Query(); // Query platform extensions windowDevice.QueryPlatformExtensions(); // Query OpenGL limits _CurrentLimits = Limits.Query(Gl.CurrentVersion, _CurrentExtensions); // Obtain current OpenGL Shading Language version string glslVersion = null; switch (_CurrentVersion.Api) { case KhronosVersion.ApiGl: if (_CurrentVersion >= Version_200 || _CurrentExtensions.ShadingLanguage100_ARB) { glslVersion = GetString(StringName.ShadingLanguageVersion); } break; case KhronosVersion.ApiGles2: glslVersion = GetString(StringName.ShadingLanguageVersion); break; } if (glslVersion != null) { _CurrentShadingVersion = GlslVersion.Parse(glslVersion, _CurrentVersion.Api); } // Vendor/Render information _Vendor = GetString(StringName.Vendor); _Renderer = GetString(StringName.Renderer); if (EnvDebug || EnvExperimental) { Debug.Assert(CurrentVersion != null && CurrentExtensions != null); CheckExtensionCommands <Gl>(CurrentVersion, CurrentExtensions, EnvExperimental); } // Before deletion, make uncurrent windowDevice.MakeCurrent(IntPtr.Zero); // Detroy context if (windowDevice.DeleteContext(renderContext) == false) { throw new InvalidOperationException("unable to delete OpenGL context"); } } LogComment("OpenGL.Net has been initialized"); } catch (Exception excepton) { _InitializationException = excepton; LogComment("Unable to initialize OpenGL.Net: {0}", _InitializationException.ToString()); } }
/// <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) { return(Wgl.MakeCurrent(DeviceContext, ctx)); }