From 02faa2e3acdbdce04af735ca1aad45e5eea7c48b Mon Sep 17 00:00:00 2001 From: mstr2 Date: Mon, 31 Dec 2018 05:37:57 +0100 Subject: [PATCH 1/2] 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); } } } From 4c4e72ab862fd29889059918d038c9db5bf3ca9b Mon Sep 17 00:00:00 2001 From: mstr2 Date: Tue, 15 Jan 2019 18:24:21 +0100 Subject: [PATCH 2/2] Moved GL/EGL errors to separate enumeration --- src/Avalonia.OpenGL/EglErrors.cs | 21 ++++++++++++++++++ src/Avalonia.OpenGL/GlConsts.cs | 3 +++ src/Avalonia.OpenGL/GlErrors.cs | 15 +++++++++++++ src/Avalonia.OpenGL/OpenGlException.cs | 30 ++++++++++---------------- 4 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 src/Avalonia.OpenGL/EglErrors.cs create mode 100644 src/Avalonia.OpenGL/GlErrors.cs diff --git a/src/Avalonia.OpenGL/EglErrors.cs b/src/Avalonia.OpenGL/EglErrors.cs new file mode 100644 index 0000000000..bfe46f2b69 --- /dev/null +++ b/src/Avalonia.OpenGL/EglErrors.cs @@ -0,0 +1,21 @@ +namespace Avalonia.OpenGL +{ + public enum EglErrors + { + EGL_SUCCESS = EglConsts.EGL_SUCCESS, + EGL_NOT_INITIALIZED = EglConsts.EGL_NOT_INITIALIZED, + EGL_BAD_ACCESS = EglConsts.EGL_BAD_ACCESS, + EGL_BAD_ALLOC = EglConsts.EGL_BAD_ALLOC, + EGL_BAD_ATTRIBUTE = EglConsts.EGL_BAD_ATTRIBUTE, + EGL_BAD_CONTEXT = EglConsts.EGL_BAD_CONTEXT, + EGL_BAD_CONFIG = EglConsts.EGL_BAD_CONFIG, + EGL_BAD_CURRENT_SURFACE = EglConsts.EGL_BAD_CURRENT_SURFACE, + EGL_BAD_DISPLAY = EglConsts.EGL_BAD_DISPLAY, + EGL_BAD_SURFACE = EglConsts.EGL_BAD_SURFACE, + EGL_BAD_MATCH = EglConsts.EGL_BAD_MATCH, + EGL_BAD_PARAMETER = EglConsts.EGL_BAD_PARAMETER, + EGL_BAD_NATIVE_PIXMAP = EglConsts.EGL_BAD_NATIVE_PIXMAP, + EGL_BAD_NATIVE_WINDOW = EglConsts.EGL_BAD_NATIVE_WINDOW, + EGL_CONTEXT_LOST = EglConsts.EGL_CONTEXT_LOST + } +} diff --git a/src/Avalonia.OpenGL/GlConsts.cs b/src/Avalonia.OpenGL/GlConsts.cs index 3084a6f958..275f351e3e 100644 --- a/src/Avalonia.OpenGL/GlConsts.cs +++ b/src/Avalonia.OpenGL/GlConsts.cs @@ -456,12 +456,15 @@ namespace Avalonia.OpenGL public const int GL_RENDERER = 0x1F01; public const int GL_VERSION = 0x1F02; public const int GL_EXTENSIONS = 0x1F03; + public const int GL_NO_ERROR = 0; public const int GL_INVALID_ENUM = 0x0500; public const int GL_INVALID_VALUE = 0x0501; public const int GL_INVALID_OPERATION = 0x0502; public const int GL_STACK_OVERFLOW = 0x0503; public const int GL_STACK_UNDERFLOW = 0x0504; public const int GL_OUT_OF_MEMORY = 0x0505; + public const int GL_INVALID_FRAMEBUFFER_OPERATION = 0x0506; + public const int GL_CONTEXT_LOST = 0x0507; public const int GL_CURRENT_BIT = 0x00000001; public const int GL_POINT_BIT = 0x00000002; public const int GL_LINE_BIT = 0x00000004; diff --git a/src/Avalonia.OpenGL/GlErrors.cs b/src/Avalonia.OpenGL/GlErrors.cs new file mode 100644 index 0000000000..ecc7d21c7a --- /dev/null +++ b/src/Avalonia.OpenGL/GlErrors.cs @@ -0,0 +1,15 @@ +namespace Avalonia.OpenGL +{ + public enum GlErrors + { + GL_NO_ERROR = GlConsts.GL_NO_ERROR, + GL_INVALID_ENUM = GlConsts.GL_INVALID_ENUM, + GL_INVALID_VALUE = GlConsts.GL_INVALID_VALUE, + GL_INVALID_OPERATION = GlConsts.GL_INVALID_OPERATION, + GL_INVALID_FRAMEBUFFER_OPERATION = GlConsts.GL_INVALID_FRAMEBUFFER_OPERATION, + GL_STACK_OVERFLOW = GlConsts.GL_STACK_OVERFLOW, + GL_STACK_UNDERFLOW = GlConsts.GL_STACK_UNDERFLOW, + GL_OUT_OF_MEMORY = GlConsts.GL_OUT_OF_MEMORY, + GL_CONTEXT_LOST = GlConsts.GL_CONTEXT_LOST + } +} diff --git a/src/Avalonia.OpenGL/OpenGlException.cs b/src/Avalonia.OpenGL/OpenGlException.cs index 9d9940949b..d3cd7d059e 100644 --- a/src/Avalonia.OpenGL/OpenGlException.cs +++ b/src/Avalonia.OpenGL/OpenGlException.cs @@ -1,5 +1,4 @@ using System; -using System.Reflection; namespace Avalonia.OpenGL { @@ -18,33 +17,26 @@ namespace Avalonia.OpenGL public static OpenGlException GetFormattedException(string funcName, EglInterface egl) { - return GetFormattedException(typeof(EglConsts).GetFields(), funcName, 0x3000, 0x301F, egl.GetError()); + return GetFormattedException(typeof(EglErrors), funcName, egl.GetError()); } public static OpenGlException GetFormattedException(string funcName, GlInterface gl) { - return GetFormattedException(typeof(GlConsts).GetFields(), funcName, 0x0500, 0x0505, gl.GetError()); + return GetFormattedException(typeof(GlErrors), funcName, gl.GetError()); } - private static OpenGlException GetFormattedException( - FieldInfo[] fields, string funcName, int minValue, int maxValue, int errorCode) + private static OpenGlException GetFormattedException(Type consts, string funcName, int errorCode) { - foreach (var field in fields) + try { - 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); - } + string errorName = Enum.GetName(consts, errorCode); + return new OpenGlException( + $"{funcName} failed with error {errorName} (0x{errorCode.ToString("X")})", errorCode); + } + catch (ArgumentException) + { + return new OpenGlException($"{funcName} failed with error 0x{errorCode.ToString("X")}", errorCode); } - - return new OpenGlException($"{funcName} failed with error 0x{errorCode.ToString("X")}", errorCode); } } }