Fix to able to recover from GraphicsModeException in the override OnH… (#658)

* Fix to able to recover from GraphicsModeException in the override OnHandleCreated.

* Changes according to comments:
- m_implementation and m_context is now always set. To DummyGLControl if CreateContext fails
- Changed FailedCreateContext -> HasValidContext
- Changed all if{} to short style with braces.
- Added null propagation when applicable
- Renamed member variables to have 'm_' infront.
- and more ...

* Changed 'm_' prefix into '_'
Added braces to be using Allman Style

* Fixed:

  2) SA1003: GLControl.cs(226,47): Operator '(IGraphicsContextInternal)' must not be followed by whitespace.
  3) SA1003: GLControl.cs(412,49): Operator '(float)' must not be followed by whitespace.

* Removed Paket.Restore.targets from sourcecontrol
Added *.Restore.targets to .gitignore

* Fixed comments
Added *.DotSettings to .gitignore

* Removed *.DotSettings from GitIgnore
Moved *.Restore.targets to Paket section
This commit is contained in:
iRon 2018-01-08 22:31:45 +01:00 committed by Jarl Gullberg
parent 0b3f17507c
commit 0a5c346c52
2 changed files with 93 additions and 77 deletions

1
.gitignore vendored
View file

@ -317,6 +317,7 @@ _Pvt_Extensions
# Paket dependency manager # Paket dependency manager
.paket/paket.exe .paket/paket.exe
paket-files/ paket-files/
*.Restore.targets
# FAKE - F# Make # FAKE - F# Make
.fake/ .fake/

View file

@ -41,22 +41,24 @@ namespace OpenTK
/// </summary> /// </summary>
public partial class GLControl : UserControl public partial class GLControl : UserControl
{ {
private IGraphicsContext context; private IGraphicsContext _context;
private IGLControl implementation; private IGLControl _implementation;
private GraphicsMode format; private readonly GraphicsMode _format;
private int major, minor; private readonly int _major;
private GraphicsContextFlags flags; private readonly int _minor;
private readonly GraphicsContextFlags _flags;
private bool? _initialVsyncValue;
private bool? initial_vsync_value;
// Indicates that OnResize was called before OnHandleCreated. // Indicates that OnResize was called before OnHandleCreated.
// To avoid issues with missing OpenGL contexts, we suppress // To avoid issues with missing OpenGL contexts, we suppress
// the premature Resize event and raise it as soon as the handle // the premature Resize event and raise it as soon as the handle
// is ready. // is ready.
private bool resize_event_suppressed; private bool _resizeEventSuppressed;
// Indicates whether the control is in design mode. Due to issues // Indicates whether the control is in design mode. Due to issues
// wiith the DesignMode property and nested controls,we need to // with the DesignMode property and nested controls,we need to
// evaluate this in the constructor. // evaluate this in the constructor.
private readonly bool design_mode; private readonly bool _designMode;
/// <summary> /// <summary>
/// Constructs a new instance. /// Constructs a new instance.
@ -84,7 +86,7 @@ namespace OpenTK
{ {
if (mode == null) if (mode == null)
{ {
throw new ArgumentNullException("mode"); throw new ArgumentNullException(nameof(mode));
} }
// SDL does not currently support embedding // SDL does not currently support embedding
@ -104,28 +106,37 @@ namespace OpenTK
SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true);
DoubleBuffered = false; DoubleBuffered = false;
this.format = mode; _format = mode;
this.major = major; _major = major;
this.minor = minor; _minor = minor;
this.flags = flags; _flags = flags;
// Note: the DesignMode property may be incorrect when nesting controls. // Note: the DesignMode property may be incorrect when nesting controls.
// We use LicenseManager.UsageMode as a workaround (this only works in // We use LicenseManager.UsageMode as a workaround (this only works in
// the constructor). // the constructor).
design_mode = _designMode =
DesignMode || DesignMode ||
LicenseManager.UsageMode == LicenseUsageMode.Designtime; LicenseManager.UsageMode == LicenseUsageMode.Designtime;
InitializeComponent(); InitializeComponent();
} }
/// <summary>
/// Gets a value indicating whether [failed to create OpenGL context].
/// So that the application stays running and is able to recover.
/// </summary>
/// <value>
/// <c>true</c> if [failed create context]; otherwise, <c>false</c>.
/// </value>
public bool HasValidContext { get; private set; }
private IGLControl Implementation private IGLControl Implementation
{ {
get get
{ {
ValidateState(); ValidateState();
return implementation; return _implementation;
} }
} }
@ -150,7 +161,7 @@ namespace OpenTK
CreateControl(); CreateControl();
} }
if (implementation == null || context == null || context.IsDisposed) if (_implementation == null || _context == null || _context.IsDisposed)
{ {
RecreateHandle(); RecreateHandle();
} }
@ -167,7 +178,7 @@ namespace OpenTK
const int CS_HREDRAW = 0x2; const int CS_HREDRAW = 0x2;
const int CS_OWNDC = 0x20; const int CS_OWNDC = 0x20;
CreateParams cp = base.CreateParams; var cp = base.CreateParams;
if (Configuration.RunningOnWindows) if (Configuration.RunningOnWindows)
{ {
// Setup necessary class style for OpenGL on windows // Setup necessary class style for OpenGL on windows
@ -181,46 +192,54 @@ namespace OpenTK
/// <param name="e">Not used.</param> /// <param name="e">Not used.</param>
protected override void OnHandleCreated(EventArgs e) protected override void OnHandleCreated(EventArgs e)
{ {
if (context != null) if (!(_implementation is DummyGLControl))
{ { // No need to recreate our DummyGLControl
context.Dispose(); _context?.Dispose();
} _implementation?.WindowInfo.Dispose();
if (implementation != null) if (_designMode)
{ {
implementation.WindowInfo.Dispose(); _implementation = new DummyGLControl();
} _context = _implementation.CreateContext(_major, _minor, _flags);
HasValidContext = false;
}
else
{
try
{
_implementation = new GLControlFactory().CreateGLControl(_format, this);
_context = _implementation.CreateContext(_major, _minor, _flags);
HasValidContext = true;
}
catch (GraphicsModeException)
{
_implementation = new DummyGLControl();
_context = _implementation.CreateContext(_major, _minor, _flags);
HasValidContext = false;
}
}
if (design_mode) MakeCurrent();
{
implementation = new DummyGLControl();
}
else
{
implementation = new GLControlFactory().CreateGLControl(format, this);
}
context = implementation.CreateContext(major, minor, flags); if (HasValidContext)
MakeCurrent(); {
((IGraphicsContextInternal)_context).LoadAll();
}
if (!design_mode) // Deferred setting of vsync mode. See VSync property for more information.
{ if (_initialVsyncValue.HasValue)
((IGraphicsContextInternal)Context).LoadAll(); {
} _context.SwapInterval = _initialVsyncValue.Value ? 1 : 0;
_initialVsyncValue = null;
// Deferred setting of vsync mode. See VSync property for more information. }
if (initial_vsync_value.HasValue)
{
Context.SwapInterval = initial_vsync_value.Value ? 1 : 0;
initial_vsync_value = null;
} }
base.OnHandleCreated(e); base.OnHandleCreated(e);
if (resize_event_suppressed) if (_resizeEventSuppressed)
{ {
OnResize(EventArgs.Empty); OnResize(EventArgs.Empty);
resize_event_suppressed = false; _resizeEventSuppressed = false;
} }
} }
@ -232,18 +251,23 @@ namespace OpenTK
// => This allows to perform cleanup operations in OnHandleDestroyed handlers // => This allows to perform cleanup operations in OnHandleDestroyed handlers
base.OnHandleDestroyed(e); base.OnHandleDestroyed(e);
if (context != null) if (_implementation is DummyGLControl)
{ {
context.Dispose(); // No need to destroy our DummyGLControl
context = null; return;
} }
if (implementation != null) if (_context != null)
{ {
implementation.WindowInfo.Dispose(); _context.Dispose();
implementation = null; _context = null;
} }
if (_implementation != null)
{
_implementation.WindowInfo.Dispose();
_implementation = null;
}
} }
/// <summary> /// <summary>
@ -254,7 +278,7 @@ namespace OpenTK
{ {
ValidateState(); ValidateState();
if (design_mode) if (_designMode)
{ {
e.Graphics.Clear(BackColor); e.Graphics.Clear(BackColor);
} }
@ -273,7 +297,7 @@ namespace OpenTK
// Do not raise OnResize event before the handle and context are created. // Do not raise OnResize event before the handle and context are created.
if (!IsHandleCreated) if (!IsHandleCreated)
{ {
resize_event_suppressed = true; _resizeEventSuppressed = true;
return; return;
} }
@ -282,9 +306,9 @@ namespace OpenTK
DelayUpdate delay = PerformContextUpdate; DelayUpdate delay = PerformContextUpdate;
BeginInvoke(delay); //Need the native window to resize first otherwise our control will be in the wrong place. BeginInvoke(delay); //Need the native window to resize first otherwise our control will be in the wrong place.
} }
else if (context != null) else
{ {
context.Update (Implementation.WindowInfo); _context?.Update(Implementation.WindowInfo);
} }
base.OnResize(e); base.OnResize(e);
@ -294,15 +318,13 @@ namespace OpenTK
/// Needed to delay the invoke on OS X. Also needed because OpenTK is .NET 2, otherwise I'd use an inline Action. /// Needed to delay the invoke on OS X. Also needed because OpenTK is .NET 2, otherwise I'd use an inline Action.
/// </summary> /// </summary>
public delegate void DelayUpdate(); public delegate void DelayUpdate();
/// <summary> /// <summary>
/// Execute the delayed context update /// Execute the delayed context update
/// </summary> /// </summary>
public void PerformContextUpdate() public void PerformContextUpdate()
{ {
if (context != null) _context?.Update(Implementation.WindowInfo);
{
context.Update (Implementation.WindowInfo);
}
} }
/// <summary> /// <summary>
@ -311,10 +333,7 @@ namespace OpenTK
/// <param name="e">A System.EventArgs that contains the event data.</param> /// <param name="e">A System.EventArgs that contains the event data.</param>
protected override void OnParentChanged(EventArgs e) protected override void OnParentChanged(EventArgs e)
{ {
if (context != null) _context?.Update(Implementation.WindowInfo);
{
context.Update(Implementation.WindowInfo);
}
base.OnParentChanged(e); base.OnParentChanged(e);
} }
@ -377,9 +396,8 @@ namespace OpenTK
get get
{ {
ValidateState(); ValidateState();
return context; return _context;
} }
private set { context = value; }
} }
/// <summary> /// <summary>
@ -409,12 +427,12 @@ namespace OpenTK
{ {
if (!IsHandleCreated) if (!IsHandleCreated)
{ {
return initial_vsync_value.HasValue ? return !_initialVsyncValue.HasValue || _initialVsyncValue.Value;
initial_vsync_value.Value : true;
} }
ValidateState(); ValidateState();
ValidateContext("VSync"); ValidateContext(@"VSync");
return Context.SwapInterval != 0; return Context.SwapInterval != 0;
} }
set set
@ -425,12 +443,12 @@ namespace OpenTK
// Work around this issue by deferring VSync mode setting to the HandleCreated event. // Work around this issue by deferring VSync mode setting to the HandleCreated event.
if (!IsHandleCreated) if (!IsHandleCreated)
{ {
initial_vsync_value = value; _initialVsyncValue = value;
return; return;
} }
ValidateState(); ValidateState();
ValidateContext("VSync"); ValidateContext(@"VSync");
Context.SwapInterval = value ? 1 : 0; Context.SwapInterval = value ? 1 : 0;
} }
} }
@ -452,9 +470,6 @@ namespace OpenTK
/// <summary> /// <summary>
/// Gets the <see cref="OpenTK.Platform.IWindowInfo"/> for this instance. /// Gets the <see cref="OpenTK.Platform.IWindowInfo"/> for this instance.
/// </summary> /// </summary>
public IWindowInfo WindowInfo public IWindowInfo WindowInfo => _implementation.WindowInfo;
{
get { return implementation.WindowInfo; }
}
} }
} }