From 02faa2e3acdbdce04af735ca1aad45e5eea7c48b Mon Sep 17 00:00:00 2001 From: mstr2 Date: Mon, 31 Dec 2018 05:37:57 +0100 Subject: [PATCH] Added the option to include the OpenGL error code description when constructing OpenGlException --- src/Avalonia.OpenGL/EglContext.cs | 6 ++-- src/Avalonia.OpenGL/EglDisplay.cs | 17 ++++++------ src/Avalonia.OpenGL/EglInterface.cs | 7 +++-- src/Avalonia.OpenGL/GlInterface.cs | 5 +++- src/Avalonia.OpenGL/OpenGlException.cs | 38 ++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/Avalonia.OpenGL/EglContext.cs b/src/Avalonia.OpenGL/EglContext.cs index 27b1abe411..17caf84179 100644 --- a/src/Avalonia.OpenGL/EglContext.cs +++ b/src/Avalonia.OpenGL/EglContext.cs @@ -31,14 +31,14 @@ namespace Avalonia.OpenGL public void MakeCurrent() { if (!_egl.MakeCurrent(_disp.Handle, IntPtr.Zero, IntPtr.Zero, Context)) - throw new OpenGlException("eglMakeCurrent failed"); + throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl); } public void MakeCurrent(EglSurface surface) { - var surf = ((EglSurface)surface)?.DangerousGetHandle() ?? OffscreenSurface; + var surf = surface?.DangerousGetHandle() ?? OffscreenSurface; if (!_egl.MakeCurrent(_disp.Handle, surf, surf, Context)) - throw new OpenGlException("eglMakeCurrent failed"); + throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl); } } } diff --git a/src/Avalonia.OpenGL/EglDisplay.cs b/src/Avalonia.OpenGL/EglDisplay.cs index 90a70adcb7..2a75e9458e 100644 --- a/src/Avalonia.OpenGL/EglDisplay.cs +++ b/src/Avalonia.OpenGL/EglDisplay.cs @@ -1,5 +1,4 @@ using System; -using System.ComponentModel; using System.Runtime.InteropServices; using Avalonia.Platform.Interop; using static Avalonia.OpenGL.EglConsts; @@ -34,11 +33,11 @@ namespace Avalonia.OpenGL if (_display == IntPtr.Zero) _display = _egl.GetDisplay(IntPtr.Zero); - if(_display == IntPtr.Zero) - throw new OpenGlException("eglGetDisplay failed"); - + if (_display == IntPtr.Zero) + throw OpenGlException.GetFormattedException("eglGetDisplay", _egl); + if (!_egl.Initialize(_display, out var major, out var minor)) - throw new OpenGlException("eglInitialize failed"); + throw OpenGlException.GetFormattedException("eglInitialize", _egl); foreach (var cfg in new[] { @@ -113,7 +112,7 @@ namespace Avalonia.OpenGL var shareCtx = (EglContext)share; var ctx = _egl.CreateContext(_display, _config, shareCtx?.Context ?? IntPtr.Zero, _contextAttributes); if (ctx == IntPtr.Zero) - throw new OpenGlException("eglCreateContext failed"); + throw OpenGlException.GetFormattedException("eglCreateContext", _egl); var surf = _egl.CreatePBufferSurface(_display, _config, new[] { EGL_WIDTH, 1, @@ -121,7 +120,7 @@ namespace Avalonia.OpenGL EGL_NONE }); if (surf == IntPtr.Zero) - throw new OpenGlException("eglCreatePbufferSurface failed"); + throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl); var rv = new EglContext(this, _egl, ctx, surf); rv.MakeCurrent(null); return rv; @@ -130,14 +129,14 @@ namespace Avalonia.OpenGL public void ClearContext() { if (!_egl.MakeCurrent(_display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) - throw new OpenGlException("eglMakeCurrent failed"); + throw OpenGlException.GetFormattedException("eglMakeCurrent", _egl); } public EglSurface CreateWindowSurface(IntPtr window) { var s = _egl.CreateWindowSurface(_display, _config, window, new[] {EGL_NONE, EGL_NONE}); if (s == IntPtr.Zero) - throw new OpenGlException("eglCreateWindowSurface failed"); + throw OpenGlException.GetFormattedException("eglCreateWindowSurface", _egl); return new EglSurface(this, _egl, s); } diff --git a/src/Avalonia.OpenGL/EglInterface.cs b/src/Avalonia.OpenGL/EglInterface.cs index 535f66ee1f..c41a01340c 100644 --- a/src/Avalonia.OpenGL/EglInterface.cs +++ b/src/Avalonia.OpenGL/EglInterface.cs @@ -1,7 +1,6 @@ using System; using Avalonia.Platform; using Avalonia.Platform.Interop; -using static Avalonia.OpenGL.EglConsts; namespace Avalonia.OpenGL { @@ -32,8 +31,12 @@ namespace Avalonia.OpenGL var lib = dyn.LoadLibrary(library); return (s, o) => dyn.GetProcAddress(lib, s, o); } - + // ReSharper disable UnassignedGetOnlyAutoProperty + public delegate int EglGetError(); + [EntryPoint("eglGetError")] + public EglGetError GetError { get; } + public delegate IntPtr EglGetDisplay(IntPtr nativeDisplay); [EntryPoint("eglGetDisplay")] public EglGetDisplay GetDisplay { get; } diff --git a/src/Avalonia.OpenGL/GlInterface.cs b/src/Avalonia.OpenGL/GlInterface.cs index 60dc5381d4..f23e1c5829 100644 --- a/src/Avalonia.OpenGL/GlInterface.cs +++ b/src/Avalonia.OpenGL/GlInterface.cs @@ -19,7 +19,10 @@ namespace Avalonia.OpenGL public T GetProcAddress(string proc) => Marshal.GetDelegateForFunctionPointer(GetProcAddress(proc)); // ReSharper disable UnassignedGetOnlyAutoProperty - + public delegate int GlGetError(); + [EntryPoint("glGetError")] + public GlGetError GetError { get; } + public delegate void GlClearStencil(int s); [EntryPoint("glClearStencil")] public GlClearStencil ClearStencil { get; } diff --git a/src/Avalonia.OpenGL/OpenGlException.cs b/src/Avalonia.OpenGL/OpenGlException.cs index 7ba539a2b2..9d9940949b 100644 --- a/src/Avalonia.OpenGL/OpenGlException.cs +++ b/src/Avalonia.OpenGL/OpenGlException.cs @@ -1,12 +1,50 @@ using System; +using System.Reflection; namespace Avalonia.OpenGL { public class OpenGlException : Exception { + public int? ErrorCode { get; private set; } + public OpenGlException(string message) : base(message) { + } + + private OpenGlException(string message, int errorCode) : base(message) + { + ErrorCode = errorCode; + } + + public static OpenGlException GetFormattedException(string funcName, EglInterface egl) + { + return GetFormattedException(typeof(EglConsts).GetFields(), funcName, 0x3000, 0x301F, egl.GetError()); + } + + public static OpenGlException GetFormattedException(string funcName, GlInterface gl) + { + return GetFormattedException(typeof(GlConsts).GetFields(), funcName, 0x0500, 0x0505, gl.GetError()); + } + + private static OpenGlException GetFormattedException( + FieldInfo[] fields, string funcName, int minValue, int maxValue, int errorCode) + { + foreach (var field in fields) + { + int value = (int)field.GetValue(null); + if (value < minValue || value > maxValue) + { + continue; + } + + if (value == errorCode) + { + return new OpenGlException( + $"{funcName} failed with error {field.Name} (0x{errorCode.ToString("X")})", errorCode); + } + } + return new OpenGlException($"{funcName} failed with error 0x{errorCode.ToString("X")}", errorCode); } } }