Skip to content

Commit

Permalink
chore: minor touches
Browse files Browse the repository at this point in the history
  • Loading branch information
ramezgerges committed Oct 7, 2024
1 parent 10a7945 commit 618bd6b
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 56 deletions.
119 changes: 76 additions & 43 deletions src/AddIns/Uno.WinUI.Graphics3DGL/GLCanvasElement.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Dispatching;
using Silk.NET.OpenGL;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
Expand All @@ -14,10 +15,6 @@
#if WINAPPSDK
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Dispatching;
using Uno.Extensions;
using Uno.Logging;
#else
using Uno.Foundation.Extensibility;
using Uno.Graphics;
Expand Down Expand Up @@ -120,13 +117,12 @@ protected GLCanvasElement(uint width, uint height, Func<Window>? getWindowFunc)
try
{
#if WINAPPSDK
var nativeOpenGlWrapper = new WinUINativeOpenGLWrapper(getWindowFunc);
var nativeOpenGlWrapper = new WinUINativeOpenGLWrapper(xamlRoot, getWindowFunc!);
#else
if (!ApiExtensibility.CreateInstance<INativeOpenGLWrapper>(xamlRoot, out var nativeOpenGlWrapper))
{
throw new InvalidOperationException($"Couldn't create a {nameof(INativeOpenGLWrapper)} object. Make sure you are running on a platform with OpenGL support.");
}
xamlRoot.HostWindow!.Closed += (_, _) => { nativeOpenGlWrapper.Dispose(); };
#endif
return nativeOpenGlWrapper;
}
Expand All @@ -140,6 +136,20 @@ protected GLCanvasElement(uint width, uint height, Func<Window>? getWindowFunc)
}
}

private void OnClosed(object o, WindowEventArgs windowEventArgs)
{
if (GlAvailable!.Value)
{
// OnUnloaded is called after OnClosed, which leads to disposing the context first and then trying to
// delete the framebuffer, etc. and this causes exceptions.
DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
using var _ = _nativeOpenGlWrapper!.MakeCurrent();
_nativeOpenGlWrapper?.Dispose();
});
}
}

/// <summary>
/// Invalidates the rendering, and queues a call to <see cref="RenderOverride"/>.
/// <see cref="RenderOverride"/> will only be called once after <see cref="Invalidate"/> and the output will
Expand All @@ -152,6 +162,7 @@ protected GLCanvasElement(uint width, uint height, Func<Window>? getWindowFunc)
public void Invalidate() => NativeDispatcher.Main.Enqueue(Render, NativeDispatcherPriority.Idle);
#endif

/// <remarks>not null after the first <see cref="GLCanvasElement"/> instance is loaded.</remarks>
private bool? GlAvailable
{
get => _glAvailable;
Expand Down Expand Up @@ -180,51 +191,64 @@ private unsafe void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
GlAvailable = true;
_nativeOpenGlWrapper = glWrapper;
}
}

if (GlAvailable.Value)
{
_gl = GL.GetApi(this);
GlAvailable = true;
if (!GlAvailable!.Value)
{
return;
}

_gl = GL.GetApi(this);
GlAvailable = true;

#if WINAPPSDK
_pixels = Marshal.AllocHGlobal((int)(_width * _height * BytesPerPixel));
_pixels = Marshal.AllocHGlobal((int)(_width * _height * BytesPerPixel));
#endif

using (_nativeOpenGlWrapper!.MakeCurrent())
using (_nativeOpenGlWrapper!.MakeCurrent())
{
_framebuffer = _gl.GenBuffer();
_gl.BindFramebuffer(GLEnum.Framebuffer, _framebuffer);
{
_textureColorBuffer = _gl.GenTexture();
_gl.BindTexture(GLEnum.Texture2D, _textureColorBuffer);
{
_gl.TexImage2D(GLEnum.Texture2D, 0, InternalFormat.Rgb, _width, _height, 0, GLEnum.Rgb,
GLEnum.UnsignedByte, (void*)0);
_gl.TexParameterI(GLEnum.Texture2D, GLEnum.TextureMinFilter, (uint)GLEnum.Linear);
_gl.TexParameterI(GLEnum.Texture2D, GLEnum.TextureMagFilter, (uint)GLEnum.Linear);
_gl.FramebufferTexture2D(GLEnum.Framebuffer, FramebufferAttachment.ColorAttachment0,
GLEnum.Texture2D, _textureColorBuffer, 0);
}
_gl.BindTexture(GLEnum.Texture2D, 0);

_renderBuffer = _gl.GenRenderbuffer();
_gl.BindRenderbuffer(GLEnum.Renderbuffer, _renderBuffer);
{
_gl.RenderbufferStorage(GLEnum.Renderbuffer, InternalFormat.Depth24Stencil8, _width, _height);
_gl.FramebufferRenderbuffer(GLEnum.Framebuffer, GLEnum.DepthStencilAttachment,
GLEnum.Renderbuffer, _renderBuffer);
}
_gl.BindRenderbuffer(GLEnum.Renderbuffer, 0);

if (_gl.CheckFramebufferStatus(GLEnum.Framebuffer) != GLEnum.FramebufferComplete)
{
_framebuffer = _gl.GenBuffer();
_gl.BindFramebuffer(GLEnum.Framebuffer, _framebuffer);
{
_textureColorBuffer = _gl.GenTexture();
_gl.BindTexture(GLEnum.Texture2D, _textureColorBuffer);
{
_gl.TexImage2D(GLEnum.Texture2D, 0, InternalFormat.Rgb, _width, _height, 0, GLEnum.Rgb, GLEnum.UnsignedByte, (void*)0);
_gl.TexParameterI(GLEnum.Texture2D, GLEnum.TextureMinFilter, (uint)GLEnum.Linear);
_gl.TexParameterI(GLEnum.Texture2D, GLEnum.TextureMagFilter, (uint)GLEnum.Linear);
_gl.FramebufferTexture2D(GLEnum.Framebuffer, FramebufferAttachment.ColorAttachment0, GLEnum.Texture2D, _textureColorBuffer, 0);
}
_gl.BindTexture(GLEnum.Texture2D, 0);

_renderBuffer = _gl.GenRenderbuffer();
_gl.BindRenderbuffer(GLEnum.Renderbuffer, _renderBuffer);
{
_gl.RenderbufferStorage(GLEnum.Renderbuffer, InternalFormat.Depth24Stencil8, _width, _height);
_gl.FramebufferRenderbuffer(GLEnum.Framebuffer, GLEnum.DepthStencilAttachment, GLEnum.Renderbuffer, _renderBuffer);
}
_gl.BindRenderbuffer(GLEnum.Renderbuffer, 0);

if (_gl.CheckFramebufferStatus(GLEnum.Framebuffer) != GLEnum.FramebufferComplete)
{
throw new InvalidOperationException("Offscreen framebuffer is not complete");
}

Init(_gl);
}
_gl.BindFramebuffer(GLEnum.Framebuffer, 0);
throw new InvalidOperationException("Offscreen framebuffer is not complete");
}

Init(_gl);
}
_gl.BindFramebuffer(GLEnum.Framebuffer, 0);
}

var window =
#if WINAPPSDK
_getWindowFunc!();
#else
XamlRoot?.HostWindow;
#endif
window!.Closed += OnClosed;

Invalidate();
}

Expand Down Expand Up @@ -267,6 +291,14 @@ private void OnUnloaded(object sender, RoutedEventArgs routedEventArgs)
#if WINAPPSDK
_pixels = default;
#endif

var window =
#if WINAPPSDK
_getWindowFunc!();
#else
XamlRoot?.HostWindow;
#endif
window!.Closed -= OnClosed;
}

private unsafe void Render()
Expand Down Expand Up @@ -305,6 +337,7 @@ private unsafe void Render()
}
}

public IntPtr GetProcAddress(string proc, int? slot = null) => _nativeOpenGlWrapper!.GetProcAddress(proc);
public bool TryGetProcAddress(string proc, [UnscopedRef] out IntPtr addr, int? slot = null) => _nativeOpenGlWrapper!.TryGetProcAddress(proc, out addr);
IntPtr INativeContext.GetProcAddress(string proc, int? slot) => _nativeOpenGlWrapper!.GetProcAddress(proc);
bool INativeContext.TryGetProcAddress(string proc, [UnscopedRef] out IntPtr addr, int? slot) => _nativeOpenGlWrapper!.TryGetProcAddress(proc, out addr);
void IDisposable.Dispose() { /* Keep this empty. This is only for INativeContext and will be called by Silk.NET, not us. */ }
}
1 change: 0 additions & 1 deletion src/Uno.UI.Runtime.Skia.MacOS/MacOSNativeOpenGLWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ public bool TryGetProcAddress(string proc, out IntPtr addr)

public void Dispose()
{
using var _ = MakeCurrent();
if (_eglDisplay != IntPtr.Zero && _pBufferSurface != IntPtr.Zero)
{
EglDestroySurface(_eglDisplay, _pBufferSurface);
Expand Down
11 changes: 3 additions & 8 deletions src/Uno.UI.Runtime.Skia.Wpf/Extensions/WpfNativeOpenGLWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ internal class WpfNativeOpenGLWrapper
});

#if WINDOWS_UWP || WINAPPSDK
private readonly Func<Window> _getWindowFunc
private readonly Func<Window> _getWindowFunc;
#endif
private nint _hdc;
private nint _glContext;

#if WINDOWS_UWP || WINAPPSDK
public WinUINativeOpenGLWrapper(XamlRoot xamlRoot, Func<Window> getWindowFunc) : base(xamlRoot)
public WinUINativeOpenGLWrapper(XamlRoot xamlRoot, Func<Window> getWindowFunc)
{
_getWindowFunc = getWindowFunc;
#else
Expand Down Expand Up @@ -118,12 +118,7 @@ public WpfNativeOpenGLWrapper(XamlRoot xamlRoot)
// https://sharovarskyi.com/blog/posts/csharp-win32-opengl-silknet/
public bool TryGetProcAddress(string proc, out nint addr)
{
if (_opengl32.Value == IntPtr.Zero)
{
addr = IntPtr.Zero;
return false;
}
if (NativeLibrary.TryGetExport(_opengl32.Value, proc, out addr))
if (_opengl32.Value != IntPtr.Zero && NativeLibrary.TryGetExport(_opengl32.Value, proc, out addr))
{
return true;
}
Expand Down
1 change: 0 additions & 1 deletion src/Uno.UI.Runtime.Skia.X11/X11NativeOpenGLWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ public unsafe X11NativeOpenGLWrapper(XamlRoot xamlRoot)
public void Dispose()
{
using var lockDisposable = X11Helper.XLock(_display);
using var _ = MakeCurrent();

if (_display != IntPtr.Zero && _pBuffer != IntPtr.Zero)
{
Expand Down
3 changes: 0 additions & 3 deletions src/Uno.UI/Graphics/INativeOpenGLWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#nullable enable

using System;
using Microsoft.UI.Xaml;
using Uno.Foundation.Extensibility;
using Uno.Foundation.Logging;

#if WINAPPSDK || WINDOWS_UWP
namespace Uno.WinUI.Graphics3DGL;
Expand Down

0 comments on commit 618bd6b

Please sign in to comment.