/// <summary> /// Actually create this GraphicsWindow resources. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for allocating resources. /// </param> protected override void CreateObject(GraphicsContext ctx) { if (ctx != null) { throw new ArgumentException("context not required", "ctx"); } sLog.Info("Create rendering window '{0}'.", _RenderForm != null ? _RenderForm.Text : "untitled"); // Obtain device context (relative to window) _DeviceContext = DeviceContextFactory.Create(_RenderControl); _DeviceContext.IncRef(); // Choose "best" pixel format matching with surface configuration _DeviceFormat = _SurfaceFormat.ChoosePixelFormat(_DeviceContext, ValidPixelFormat); // Set device pixel format _DeviceContext.SetPixelFormat(_DeviceFormat); // Confirm surface configuration _SurfaceFormat.SetBufferConfiguration(_DeviceFormat); // Set swap interval SetSwapInterval(); }
/// <summary> /// Construct a GraphicsContext specifying the implemented OpenGL version. /// </summary> /// <param name="deviceContext"> /// A <see cref="IDeviceContext"/> that specify the device context which has to be linked this /// this Render context. /// </param> /// <param name="sharedContext"> /// A <see cref="GraphicsContext"/> that specify the render context which has to be linked this /// this Render context (to share resource with it). /// </param> /// <param name="version"> /// A <see cref="KhronosVersion"/> that specify the minimum OpenGL version required to implement. /// </param> /// <param name="flags"> /// A <see cref="GraphicsContextFlags"/> that specify special features to enable in the case they are supported. /// </param> /// <exception cref="ArgumentException"> /// Exception thrown in the case <paramref name="version"/> is different from the currently implemented by the derive, /// and the OpenGL extension WGL_ARB_create_context_profile or WGL_ARB_create_context are not implemented. /// </exception> /// <exception cref="ArgumentException"> /// This exception is thrown in the case <paramref name="version"/> specify a forward compatible version (greater than or equal to /// <see cref="GLVersion.Version_3_2"/>), and the OpenGL extension WGL_ARB_create_context_profile or WGL_ARB_create_context /// are not implemented. /// </exception> /// <exception cref="ArgumentException"> /// This exception is thrown in the case <paramref name="devctx"/> is <see cref="IntPtr.Zero"/>. /// </exception> /// <exception cref="InvalidOperationException"> /// This exception is thrown in the case it's not possible to create a valid OpenGL context. /// </exception> /// <exception cref="ArgumentException"> /// This exception is thrown if <paramref name="sharedContext"/> is not null and it was created by a thread different from the calling one. /// </exception> /// <exception cref="ArgumentException"> /// This exception is thrown if <paramref name="sharedContext"/> is not null and it is disposed. /// </exception> public GraphicsContext(IDeviceContext deviceContext, GraphicsContext sharedContext, KhronosVersion version, GraphicsContextFlags flags) { try { IntPtr sharedContextHandle = (sharedContext != null) ? sharedContext._RenderContext : IntPtr.Zero; #if DEBUG _ConstructorStackTrace = Environment.StackTrace; #endif // Store thread ID of the render context _RenderContextThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId; // Store thread ID of the device context _DeviceContextThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId; if (deviceContext == null) throw new ArgumentNullException("deviceContext"); if ((sharedContext != null) && (sharedContext._DeviceContext == null)) throw new ArgumentException("shared context disposed", "hSharedContext"); if ((sharedContext != null) && (sharedContext._RenderContextThreadId != _RenderContextThreadId)) throw new ArgumentException("shared context created from another thread", "hSharedContext"); if ((version != null) && (version != _CurrentVersion) && ((CurrentCaps.PlatformExtensions.CreateContext_ARB == false) && (CurrentCaps.PlatformExtensions.CreateContextProfile_ARB == false))) throw new ArgumentException("unable to specify OpenGL version when GL_ARB_create_context[_profile] is not supported"); // Store device context handle _DeviceContext = deviceContext; _DeviceContext.IncRef(); // Allow version to be null (fallback to current version) version = version ?? _CurrentVersion; // Set flags _ContextFlags = flags; if ((CurrentCaps.PlatformExtensions.CreateContext_ARB || CurrentCaps.PlatformExtensions.CreateContextProfile_ARB) && (version.Major >= 3)) { List<int> cAttributes = new List<int>(); #region Context Version // Requires a specific version Debug.Assert(Wgl.CONTEXT_MAJOR_VERSION_ARB == Glx.CONTEXT_MAJOR_VERSION_ARB); Debug.Assert(Wgl.CONTEXT_MINOR_VERSION_ARB == Glx.CONTEXT_MINOR_VERSION_ARB); cAttributes.AddRange(new int[] { Wgl.CONTEXT_MAJOR_VERSION_ARB, version.Major, Wgl.CONTEXT_MINOR_VERSION_ARB, version.Minor }); #endregion #region Context Profile uint contextProfile = 0; // Check binary compatibility between WGL and GLX Debug.Assert(Wgl.CONTEXT_PROFILE_MASK_ARB == Glx.CONTEXT_PROFILE_MASK_ARB); Debug.Assert(Wgl.CONTEXT_CORE_PROFILE_BIT_ARB == Glx.CONTEXT_CORE_PROFILE_BIT_ARB); Debug.Assert(Wgl.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB == Glx.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); Debug.Assert(Wgl.CONTEXT_ES_PROFILE_BIT_EXT == Glx.CONTEXT_ES_PROFILE_BIT_EXT); // By default, Core profile // Core profile? if ((flags & GraphicsContextFlags.CoreProfile) != 0) contextProfile |= Wgl.CONTEXT_CORE_PROFILE_BIT_ARB; // Compatibility profile? if ((flags & GraphicsContextFlags.CompatibilityProfile) != 0) contextProfile |= Wgl.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; // OpenGL ES profile? if ((flags & GraphicsContextFlags.EmbeddedProfile) != 0) contextProfile |= Wgl.CONTEXT_ES_PROFILE_BIT_EXT; if (contextProfile != 0) { cAttributes.AddRange(new int[] { Wgl.CONTEXT_PROFILE_MASK_ARB, unchecked((int)contextProfile) }); } #endregion #region Context Flags uint contextFlags = 0; // Check binary compatibility between WGL and GLX Debug.Assert(Wgl.CONTEXT_FLAGS_ARB == Glx.CONTEXT_FLAGS_ARB); Debug.Assert(Wgl.CONTEXT_FORWARD_COMPATIBLE_BIT_ARB == Glx.CONTEXT_FORWARD_COMPATIBLE_BIT_ARB); Debug.Assert(Wgl.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB == Glx.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB); Debug.Assert(Wgl.CONTEXT_DEBUG_BIT_ARB == Glx.CONTEXT_DEBUG_BIT_ARB); Debug.Assert(Wgl.CONTEXT_ROBUST_ACCESS_BIT_ARB == Glx.CONTEXT_ROBUST_ACCESS_BIT_ARB); Debug.Assert(Wgl.CONTEXT_RESET_ISOLATION_BIT_ARB == Glx.CONTEXT_RESET_ISOLATION_BIT_ARB); if (((flags & GraphicsContextFlags.CompatibilityProfile) != 0) && (_CurrentCaps.GlExtensions.Compatibility_ARB == false)) throw new NotSupportedException("compatibility profile not supported"); if (((flags & GraphicsContextFlags.Robust) != 0) && (_CurrentCaps.GlExtensions.Robustness_ARB == false && _CurrentCaps.GlExtensions.Robustness_EXT == false)) throw new NotSupportedException("robust profile not supported"); // Context flags: debug context if ((flags & GraphicsContextFlags.Debug) != 0) contextFlags |= Wgl.CONTEXT_DEBUG_BIT_ARB; // Context flags: forward compatible context if ((flags & GraphicsContextFlags.ForwardCompatible) != 0) contextFlags |= Wgl.CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; // Context flags: robust behavior if ((flags & GraphicsContextFlags.Robust) != 0) contextFlags |= Wgl.CONTEXT_ROBUST_ACCESS_BIT_ARB; // Context flags: reset isolation if ((flags & GraphicsContextFlags.ResetIsolation) != 0) contextFlags |= Wgl.CONTEXT_RESET_ISOLATION_BIT_ARB; if (contextFlags != 0) { cAttributes.AddRange(new int[] { Wgl.CONTEXT_FLAGS_ARB, unchecked((int)contextFlags) }); } #endregion // End of attributes cAttributes.Add(0); // Create rendering context int[] contextAttributes = cAttributes.ToArray(); _RenderContext = _DeviceContext.CreateContextAttrib(sharedContextHandle, contextAttributes); Debug.Assert(_RenderContext != IntPtr.Zero); } else { // Create rendering context _RenderContext = _DeviceContext.CreateContext(sharedContextHandle); Debug.Assert(_RenderContext != IntPtr.Zero); } if (_RenderContext == IntPtr.Zero) throw new InvalidOperationException(String.Format("unable to create context {0}", version)); // Allow the creation of a GraphicsContext while another GraphicsContext is currently current to the // calling thread: restore currency after the job get done GraphicsContext prevContext = GetCurrentContext(); IDeviceContext prevContextDevice = (prevContext != null) ? prevContext._CurrentDeviceContext : null; // This will cause OpenGL operation flushed... not too bad MakeCurrent(deviceContext, true); // Get the current OpenGL implementation supported by this GraphicsContext _Version = KhronosVersion.Parse(Gl.GetString(StringName.Version)); // Get the current OpenGL Shading Language implementation supported by this GraphicsContext _ShadingVersion = KhronosVersion.Parse(Gl.GetString(StringName.ShadingLanguageVersion)); // Query context capabilities _CapsStack.Push(GraphicsCapabilities.Query(this, deviceContext)); // Determine this GraphicsContext object namespace if (sharedContext != null) { // Sharing same object name space _ObjectNameSpace = sharedContext._ObjectNameSpace; } else { // Reserved object name space _ObjectNameSpace = Guid.NewGuid(); } // Create shader include library (GLSL #include support) _ShaderIncludeLibrary = new ShaderIncludeLibrary(); _ShaderIncludeLibrary.Create(this); // Restore previous current context, if any. Otherwise, make uncurrent if (prevContext != null) prevContext.MakeCurrent(prevContextDevice, true); else MakeCurrent(deviceContext, false); } catch { // Rethrow the exception throw; } }