13 changed files with 635 additions and 21 deletions
@ -0,0 +1,62 @@ |
|||||
|
namespace Avalonia.Win32.OpenGl |
||||
|
{ |
||||
|
internal class WglConsts |
||||
|
{ |
||||
|
public const int WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091; |
||||
|
public const int WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092; |
||||
|
public const int WGL_CONTEXT_LAYER_PLANE_ARB = 0x2093; |
||||
|
public const int WGL_CONTEXT_FLAGS_ARB = 0x2094; |
||||
|
public const int WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126; |
||||
|
public const int WGL_NUMBER_PIXEL_FORMATS_ARB = 0x2000; |
||||
|
|
||||
|
public const int WGL_DRAW_TO_WINDOW_ARB = 0x2001; |
||||
|
public const int WGL_DRAW_TO_BITMAP_ARB = 0x2002; |
||||
|
public const int WGL_ACCELERATION_ARB = 0x2003; |
||||
|
public const int WGL_NEED_PALETTE_ARB = 0x2004; |
||||
|
public const int WGL_NEED_SYSTEM_PALETTE_ARB = 0x2005; |
||||
|
public const int WGL_SWAP_LAYER_BUFFERS_ARB = 0x2006; |
||||
|
public const int WGL_SWAP_METHOD_ARB = 0x2007; |
||||
|
public const int WGL_NUMBER_OVERLAYS_ARB = 0x2008; |
||||
|
public const int WGL_NUMBER_UNDERLAYS_ARB = 0x2009; |
||||
|
public const int WGL_TRANSPARENT_ARB = 0x200A; |
||||
|
public const int WGL_TRANSPARENT_RED_VALUE_ARB = 0x2037; |
||||
|
public const int WGL_TRANSPARENT_GREEN_VALUE_ARB = 0x2038; |
||||
|
public const int WGL_TRANSPARENT_BLUE_VALUE_ARB = 0x2039; |
||||
|
public const int WGL_TRANSPARENT_ALPHA_VALUE_ARB = 0x203A; |
||||
|
public const int WGL_TRANSPARENT_INDEX_VALUE_ARB = 0x203B; |
||||
|
public const int WGL_SHARE_DEPTH_ARB = 0x200C; |
||||
|
public const int WGL_SHARE_STENCIL_ARB = 0x200D; |
||||
|
public const int WGL_SHARE_ACCUM_ARB = 0x200E; |
||||
|
public const int WGL_SUPPORT_GDI_ARB = 0x200F; |
||||
|
public const int WGL_SUPPORT_OPENGL_ARB = 0x2010; |
||||
|
public const int WGL_DOUBLE_BUFFER_ARB = 0x2011; |
||||
|
public const int WGL_STEREO_ARB = 0x2012; |
||||
|
public const int WGL_PIXEL_TYPE_ARB = 0x2013; |
||||
|
public const int WGL_COLOR_BITS_ARB = 0x2014; |
||||
|
public const int WGL_RED_BITS_ARB = 0x2015; |
||||
|
public const int WGL_RED_SHIFT_ARB = 0x2016; |
||||
|
public const int WGL_GREEN_BITS_ARB = 0x2017; |
||||
|
public const int WGL_GREEN_SHIFT_ARB = 0x2018; |
||||
|
public const int WGL_BLUE_BITS_ARB = 0x2019; |
||||
|
public const int WGL_BLUE_SHIFT_ARB = 0x201A; |
||||
|
public const int WGL_ALPHA_BITS_ARB = 0x201B; |
||||
|
public const int WGL_ALPHA_SHIFT_ARB = 0x201C; |
||||
|
public const int WGL_ACCUM_BITS_ARB = 0x201D; |
||||
|
public const int WGL_ACCUM_RED_BITS_ARB = 0x201E; |
||||
|
public const int WGL_ACCUM_GREEN_BITS_ARB = 0x201F; |
||||
|
public const int WGL_ACCUM_BLUE_BITS_ARB = 0x2020; |
||||
|
public const int WGL_ACCUM_ALPHA_BITS_ARB = 0x2021; |
||||
|
public const int WGL_DEPTH_BITS_ARB = 0x2022; |
||||
|
public const int WGL_STENCIL_BITS_ARB = 0x2023; |
||||
|
public const int WGL_AUX_BUFFERS_ARB = 0x2024; |
||||
|
public const int WGL_NO_ACCELERATION_ARB = 0x2025; |
||||
|
public const int WGL_GENERIC_ACCELERATION_ARB = 0x2026; |
||||
|
public const int WGL_FULL_ACCELERATION_ARB = 0x2027; |
||||
|
public const int WGL_SWAP_EXCHANGE_ARB = 0x2028; |
||||
|
public const int WGL_SWAP_COPY_ARB = 0x2029; |
||||
|
public const int WGL_SWAP_UNDEFINED_ARB = 0x202A; |
||||
|
public const int WGL_TYPE_RGBA_ARB = 0x202B; |
||||
|
public const int WGL_TYPE_COLORINDEX_ARB = 0x202C; |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
using System; |
||||
|
using System.Reactive.Disposables; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.Win32.Interop; |
||||
|
using static Avalonia.Win32.Interop.UnmanagedMethods; |
||||
|
using static Avalonia.Win32.OpenGl.WglConsts; |
||||
|
|
||||
|
namespace Avalonia.Win32.OpenGl |
||||
|
{ |
||||
|
class WglContext : IGlContext |
||||
|
{ |
||||
|
private object _lock = new object(); |
||||
|
private readonly WglContext _sharedWith; |
||||
|
private readonly IntPtr _context; |
||||
|
private readonly IntPtr _hWnd; |
||||
|
private readonly IntPtr _dc; |
||||
|
private readonly int _pixelFormat; |
||||
|
private readonly PixelFormatDescriptor _formatDescriptor; |
||||
|
public IntPtr Handle => _context; |
||||
|
|
||||
|
public WglContext(WglContext sharedWith, GlVersion version, IntPtr context, IntPtr hWnd, IntPtr dc, int pixelFormat, |
||||
|
PixelFormatDescriptor formatDescriptor) |
||||
|
{ |
||||
|
Version = version; |
||||
|
_sharedWith = sharedWith; |
||||
|
_context = context; |
||||
|
_hWnd = hWnd; |
||||
|
_dc = dc; |
||||
|
_pixelFormat = pixelFormat; |
||||
|
_formatDescriptor = formatDescriptor; |
||||
|
StencilSize = formatDescriptor.StencilBits; |
||||
|
using (MakeCurrent()) |
||||
|
GlInterface = new GlInterface(version, proc => |
||||
|
{ |
||||
|
var ext = wglGetProcAddress(proc); |
||||
|
if (ext != IntPtr.Zero) |
||||
|
return ext; |
||||
|
return GetProcAddress(WglDisplay.OpenGl32Handle, proc); |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
wglDeleteContext(_context); |
||||
|
ReleaseDC(_hWnd, _dc); |
||||
|
DestroyWindow(_hWnd); |
||||
|
} |
||||
|
|
||||
|
public GlVersion Version { get; } |
||||
|
public GlInterface GlInterface { get; } |
||||
|
public int SampleCount { get; } |
||||
|
public int StencilSize { get; } |
||||
|
|
||||
|
private bool IsCurrent => wglGetCurrentContext() == _context && wglGetCurrentDC() == _dc; |
||||
|
public IDisposable MakeCurrent() |
||||
|
{ |
||||
|
if(IsCurrent) |
||||
|
return Disposable.Empty; |
||||
|
return new WglRestoreContext(_dc, _context, _lock); |
||||
|
} |
||||
|
|
||||
|
public IDisposable EnsureCurrent() => MakeCurrent(); |
||||
|
|
||||
|
|
||||
|
public IntPtr CreateConfiguredDeviceContext(IntPtr hWnd) |
||||
|
{ |
||||
|
var dc = GetDC(hWnd); |
||||
|
var fmt = _formatDescriptor; |
||||
|
SetPixelFormat(dc, _pixelFormat, ref fmt); |
||||
|
return dc; |
||||
|
} |
||||
|
|
||||
|
public IDisposable MakeCurrent(IntPtr hdc) => new WglRestoreContext(hdc, _context, _lock); |
||||
|
|
||||
|
public bool IsSharedWith(IGlContext context) |
||||
|
{ |
||||
|
var c = (WglContext)context; |
||||
|
return c == this |
||||
|
|| c._sharedWith == this |
||||
|
|| _sharedWith == context |
||||
|
|| _sharedWith != null && _sharedWith == c._sharedWith; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,183 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.Win32.Interop; |
||||
|
using static Avalonia.Win32.Interop.UnmanagedMethods; |
||||
|
using static Avalonia.Win32.OpenGl.WglConsts; |
||||
|
namespace Avalonia.Win32.OpenGl |
||||
|
{ |
||||
|
internal class WglDisplay |
||||
|
{ |
||||
|
private static bool? _initialized; |
||||
|
private static ushort _windowClass; |
||||
|
private static readonly WndProc _wndProcDelegate = WndProc; |
||||
|
private static readonly DebugCallbackDelegate _debugCallback = DebugCallback; |
||||
|
|
||||
|
private static IntPtr _bootstrapContext; |
||||
|
private static IntPtr _bootstrapWindow; |
||||
|
private static IntPtr _bootstrapDc; |
||||
|
private static PixelFormatDescriptor _defaultPfd; |
||||
|
private static int _defaultPixelFormat; |
||||
|
public static IntPtr OpenGl32Handle = LoadLibrary("opengl32"); |
||||
|
|
||||
|
private delegate bool WglChoosePixelFormatARBDelegate(IntPtr hdc, int[] piAttribIList, float[] pfAttribFList, |
||||
|
int nMaxFormats, int[] piFormats, out int nNumFormats); |
||||
|
|
||||
|
private static WglChoosePixelFormatARBDelegate WglChoosePixelFormatArb; |
||||
|
|
||||
|
private delegate IntPtr WglCreateContextAttribsARBDelegate(IntPtr hDC, IntPtr hShareContext, int[] attribList); |
||||
|
|
||||
|
private static WglCreateContextAttribsARBDelegate WglCreateContextAttribsArb; |
||||
|
|
||||
|
private delegate void GlDebugMessageCallbackDelegate(IntPtr callback, IntPtr userParam); |
||||
|
|
||||
|
private static GlDebugMessageCallbackDelegate GlDebugMessageCallback; |
||||
|
|
||||
|
private delegate void DebugCallbackDelegate(int source, int type, int id, int severity, int len, IntPtr message, |
||||
|
IntPtr userParam); |
||||
|
|
||||
|
static bool Initialize() |
||||
|
{ |
||||
|
if (!_initialized.HasValue) |
||||
|
_initialized = InitializeCore(); |
||||
|
return _initialized.Value; |
||||
|
} |
||||
|
static bool InitializeCore() |
||||
|
{ |
||||
|
var wndClassEx = new WNDCLASSEX |
||||
|
{ |
||||
|
cbSize = Marshal.SizeOf<WNDCLASSEX>(), |
||||
|
hInstance = GetModuleHandle(null), |
||||
|
lpfnWndProc = _wndProcDelegate, |
||||
|
lpszClassName = "AvaloniaGlWindow-" + Guid.NewGuid(), |
||||
|
style = (int)ClassStyles.CS_OWNDC |
||||
|
}; |
||||
|
|
||||
|
_windowClass = RegisterClassEx(ref wndClassEx); |
||||
|
_bootstrapWindow = CreateOffscreenWindow(); |
||||
|
_bootstrapDc = GetDC(_bootstrapWindow); |
||||
|
_defaultPfd = new PixelFormatDescriptor |
||||
|
{ |
||||
|
Size = (ushort)Marshal.SizeOf<PixelFormatDescriptor>(), |
||||
|
Version = 1, |
||||
|
Flags = PixelFormatDescriptorFlags.PFD_DRAW_TO_WINDOW | |
||||
|
PixelFormatDescriptorFlags.PFD_SUPPORT_OPENGL | PixelFormatDescriptorFlags.PFD_DOUBLEBUFFER, |
||||
|
DepthBits = 24, |
||||
|
StencilBits = 8, |
||||
|
ColorBits = 32 |
||||
|
}; |
||||
|
_defaultPixelFormat = ChoosePixelFormat(_bootstrapDc, ref _defaultPfd); |
||||
|
SetPixelFormat(_bootstrapDc, _defaultPixelFormat, ref _defaultPfd); |
||||
|
|
||||
|
_bootstrapContext = wglCreateContext(_bootstrapDc); |
||||
|
if (_bootstrapContext == IntPtr.Zero) |
||||
|
return false; |
||||
|
|
||||
|
wglMakeCurrent(_bootstrapDc, _bootstrapContext); |
||||
|
WglCreateContextAttribsArb = Marshal.GetDelegateForFunctionPointer<WglCreateContextAttribsARBDelegate>( |
||||
|
wglGetProcAddress("wglCreateContextAttribsARB")); |
||||
|
|
||||
|
WglChoosePixelFormatArb = |
||||
|
Marshal.GetDelegateForFunctionPointer<WglChoosePixelFormatARBDelegate>( |
||||
|
wglGetProcAddress("wglChoosePixelFormatARB")); |
||||
|
|
||||
|
GlDebugMessageCallback = |
||||
|
Marshal.GetDelegateForFunctionPointer<GlDebugMessageCallbackDelegate>( |
||||
|
wglGetProcAddress("glDebugMessageCallback")); |
||||
|
|
||||
|
|
||||
|
var formats = new int[1]; |
||||
|
WglChoosePixelFormatArb(_bootstrapDc, new int[] |
||||
|
{ |
||||
|
WGL_DRAW_TO_WINDOW_ARB, 1, |
||||
|
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, |
||||
|
WGL_SUPPORT_OPENGL_ARB, 1, |
||||
|
WGL_DOUBLE_BUFFER_ARB, 1, |
||||
|
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, |
||||
|
WGL_COLOR_BITS_ARB, 32, |
||||
|
WGL_DEPTH_BITS_ARB, 0, |
||||
|
WGL_STENCIL_BITS_ARB, 0, |
||||
|
0, // End
|
||||
|
}, null, 1, formats, out int numFormats); |
||||
|
if (numFormats != 0) |
||||
|
{ |
||||
|
DescribePixelFormat(_bootstrapDc, formats[0], Marshal.SizeOf<PixelFormatDescriptor>(), ref _defaultPfd); |
||||
|
_defaultPixelFormat = formats[0]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
wglMakeCurrent(IntPtr.Zero, IntPtr.Zero); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
static IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) |
||||
|
{ |
||||
|
return DefWindowProc(hWnd, msg, wParam, lParam); |
||||
|
} |
||||
|
|
||||
|
private static void DebugCallback(int source, int type, int id, int severity, int len, IntPtr message, IntPtr userparam) |
||||
|
{ |
||||
|
var err = Marshal.PtrToStringAnsi(message, len); |
||||
|
Console.Error.WriteLine(err); |
||||
|
} |
||||
|
|
||||
|
public static WglContext CreateContext(GlVersion[] versions, IGlContext share) |
||||
|
{ |
||||
|
if (!Initialize()) |
||||
|
return null; |
||||
|
|
||||
|
var shareContext = (WglContext)share; |
||||
|
|
||||
|
using (new WglRestoreContext(_bootstrapDc, _bootstrapContext, null)) |
||||
|
{ |
||||
|
var window = CreateOffscreenWindow(); |
||||
|
var dc = GetDC(window); |
||||
|
SetPixelFormat(dc, _defaultPixelFormat, ref _defaultPfd); |
||||
|
foreach (var version in versions) |
||||
|
{ |
||||
|
if(version.Type != GlProfileType.OpenGL) |
||||
|
continue; |
||||
|
var context = WglCreateContextAttribsArb(dc, shareContext?.Handle ?? IntPtr.Zero, |
||||
|
new[] |
||||
|
{ |
||||
|
// major
|
||||
|
WGL_CONTEXT_MAJOR_VERSION_ARB, version.Major, |
||||
|
// minor
|
||||
|
WGL_CONTEXT_MINOR_VERSION_ARB, version.Minor, |
||||
|
// core profile
|
||||
|
WGL_CONTEXT_PROFILE_MASK_ARB, 1, |
||||
|
// debug
|
||||
|
WGL_CONTEXT_FLAGS_ARB, 1, |
||||
|
// end
|
||||
|
0, 0 |
||||
|
}); |
||||
|
using(new WglRestoreContext(dc, context, null)) |
||||
|
GlDebugMessageCallback(Marshal.GetFunctionPointerForDelegate(_debugCallback), IntPtr.Zero); |
||||
|
if (context != IntPtr.Zero) |
||||
|
return new WglContext(shareContext, version, context, window, dc, |
||||
|
_defaultPixelFormat, _defaultPfd); |
||||
|
} |
||||
|
|
||||
|
ReleaseDC(window, dc); |
||||
|
DestroyWindow(window); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static IntPtr CreateOffscreenWindow() => |
||||
|
CreateWindowEx( |
||||
|
0, |
||||
|
_windowClass, |
||||
|
null, |
||||
|
(int)WindowStyles.WS_OVERLAPPEDWINDOW, |
||||
|
0, |
||||
|
0, |
||||
|
640, |
||||
|
480, |
||||
|
IntPtr.Zero, |
||||
|
IntPtr.Zero, |
||||
|
IntPtr.Zero, |
||||
|
IntPtr.Zero); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
using System; |
||||
|
using System.Diagnostics; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.OpenGL.Egl; |
||||
|
using Avalonia.OpenGL.Surfaces; |
||||
|
using Avalonia.Win32.Interop; |
||||
|
using static Avalonia.OpenGL.GlConsts; |
||||
|
using static Avalonia.Win32.Interop.UnmanagedMethods; |
||||
|
namespace Avalonia.Win32.OpenGl |
||||
|
{ |
||||
|
class WglGlPlatformSurface: IGlPlatformSurface |
||||
|
{ |
||||
|
|
||||
|
private readonly WglContext _context; |
||||
|
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info; |
||||
|
|
||||
|
public WglGlPlatformSurface(WglContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info) |
||||
|
{ |
||||
|
_context = context; |
||||
|
_info = info; |
||||
|
} |
||||
|
|
||||
|
public IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() |
||||
|
{ |
||||
|
return new RenderTarget(_context, _info); |
||||
|
} |
||||
|
|
||||
|
class RenderTarget : IGlPlatformSurfaceRenderTarget |
||||
|
{ |
||||
|
private readonly WglContext _context; |
||||
|
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info; |
||||
|
private IntPtr _hdc; |
||||
|
public RenderTarget(WglContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info) |
||||
|
{ |
||||
|
_context = context; |
||||
|
_info = info; |
||||
|
_hdc = context.CreateConfiguredDeviceContext(info.Handle); |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
UnmanagedMethods.ReleaseDC(_hdc, _info.Handle); |
||||
|
} |
||||
|
|
||||
|
public IGlPlatformSurfaceRenderingSession BeginDraw() |
||||
|
{ |
||||
|
var oldContext = _context.MakeCurrent(_hdc); |
||||
|
|
||||
|
// Reset to default FBO first
|
||||
|
_context.GlInterface.BindFramebuffer(GL_FRAMEBUFFER, 0); |
||||
|
|
||||
|
return new Session(_context, _hdc, _info, oldContext); |
||||
|
} |
||||
|
|
||||
|
class Session : IGlPlatformSurfaceRenderingSession |
||||
|
{ |
||||
|
private readonly WglContext _context; |
||||
|
private readonly IntPtr _hdc; |
||||
|
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info; |
||||
|
private readonly IDisposable _clearContext; |
||||
|
public IGlContext Context => _context; |
||||
|
|
||||
|
public Session(WglContext context, IntPtr hdc, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info, |
||||
|
IDisposable clearContext) |
||||
|
{ |
||||
|
_context = context; |
||||
|
_hdc = hdc; |
||||
|
_info = info; |
||||
|
_clearContext = clearContext; |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
_context.GlInterface.Flush(); |
||||
|
UnmanagedMethods.SwapBuffers(_hdc); |
||||
|
_clearContext.Dispose(); |
||||
|
} |
||||
|
|
||||
|
public PixelSize Size => _info.Size; |
||||
|
public double Scaling => _info.Scaling; |
||||
|
public bool IsYFlipped { get; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using Avalonia.Logging; |
||||
|
using Avalonia.OpenGL; |
||||
|
|
||||
|
namespace Avalonia.Win32.OpenGl |
||||
|
{ |
||||
|
class WglPlatformOpenGlInterface : IPlatformOpenGlInterface |
||||
|
{ |
||||
|
public WglContext PrimaryContext { get; } |
||||
|
IGlContext IPlatformOpenGlInterface.PrimaryContext => PrimaryContext; |
||||
|
public IGlContext CreateSharedContext() => WglDisplay.CreateContext(new[] { PrimaryContext.Version }, PrimaryContext); |
||||
|
|
||||
|
public bool CanShareContexts => true; |
||||
|
public bool CanCreateContexts => true; |
||||
|
public IGlContext CreateContext() => WglDisplay.CreateContext(new[] { PrimaryContext.Version }, null); |
||||
|
|
||||
|
private WglPlatformOpenGlInterface(WglContext primary) |
||||
|
{ |
||||
|
PrimaryContext = primary; |
||||
|
} |
||||
|
|
||||
|
public static WglPlatformOpenGlInterface TryCreate() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
var opts = AvaloniaLocator.Current.GetService<Win32PlatformOptions>() ?? new Win32PlatformOptions(); |
||||
|
var primary = WglDisplay.CreateContext(opts.WglProfiles.ToArray(), null); |
||||
|
return new WglPlatformOpenGlInterface(primary); |
||||
|
} |
||||
|
catch (Exception e) |
||||
|
{ |
||||
|
Logger.TryGet(LogEventLevel.Error, "OpenGL")?.Log("WGL", "Unable to initialize WGL: " + e); |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using Avalonia.OpenGL; |
||||
|
using static Avalonia.Win32.Interop.UnmanagedMethods; |
||||
|
|
||||
|
namespace Avalonia.Win32.OpenGl |
||||
|
{ |
||||
|
internal class WglRestoreContext : IDisposable |
||||
|
{ |
||||
|
private readonly object _monitor; |
||||
|
private readonly IntPtr _oldDc; |
||||
|
private readonly IntPtr _oldContext; |
||||
|
|
||||
|
public WglRestoreContext(IntPtr gc, IntPtr context, object monitor, bool takeMonitor = true) |
||||
|
{ |
||||
|
_monitor = monitor; |
||||
|
_oldDc = wglGetCurrentDC(); |
||||
|
_oldContext = wglGetCurrentContext(); |
||||
|
|
||||
|
if (monitor != null && takeMonitor) |
||||
|
Monitor.Enter(monitor); |
||||
|
|
||||
|
if (!wglMakeCurrent(gc, context)) |
||||
|
{ |
||||
|
if(monitor != null && takeMonitor) |
||||
|
Monitor.Exit(monitor); |
||||
|
throw new OpenGlException("Unable to make the context current"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
if (!wglMakeCurrent(_oldDc, _oldContext)) |
||||
|
wglMakeCurrent(IntPtr.Zero, IntPtr.Zero); |
||||
|
if (_monitor != null) |
||||
|
Monitor.Exit(_monitor); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue