Skip to content

Commit

Permalink
chore: move back to a DP
Browse files Browse the repository at this point in the history
  • Loading branch information
ramezgerges committed Nov 22, 2024
1 parent b054a3d commit 357d30b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
2 changes: 1 addition & 1 deletion doc/articles/controls/GLCanvasElement.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Additionally, `GLCanvasElement` has an `Invalidate` method that requests a redra

## Detecting errors

To detect errors in initializing the OpenGL environment, `GLCanvasElement` exposes an `IsGLInitialized` property that shows whether or nor the loading of the element and its OpenGL setup were successful. This property is only valid when the element is loaded, i.e. its `IsLoaded` property is true. When the element is not loaded, the value of `IsGLInitialized` will be null. `GLCanvasElement` implements `INotifyPropertyChanged`, so you can use this property in a data bindings, for example to set the visibility of a control as a fallback.
To detect errors in initializing the OpenGL environment, `GLCanvasElement` exposes an `IsGLInitializedProperty` dependency property that shows whether or nor the loading of the element and its OpenGL setup were successful. This property is only valid when the element is loaded, i.e. its `IsLoaded` property is true. When the element is not loaded, the value of `IsGLInitialized` will be null. `GLCanvasElement` implements `INotifyPropertyChanged`, so you can use this property in a data bindings, for example to set the visibility of a control as a fallback. Attempting to change this property is illegal.

## How to use Silk.NET

Expand Down
36 changes: 26 additions & 10 deletions src/AddIns/Uno.WinUI.Graphics3DGL/GLCanvasElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace Uno.WinUI.Graphics3DGL;
/// This is only available on WinUI and on skia-based targets running with hardware acceleration.
/// This is currently only available on the WPF and X11 targets (and WinUI).
/// </remarks>
public abstract partial class GLCanvasElement : Grid, INativeContext, INotifyPropertyChanged
public abstract partial class GLCanvasElement : Grid, INativeContext
{
private const int BytesPerPixel = 4;
private static readonly Dictionary<XamlRoot, INativeOpenGLWrapper?> _xamlRootToWrapper = new();
Expand All @@ -48,7 +48,7 @@ public abstract partial class GLCanvasElement : Grid, INativeContext, INotifyPro

private readonly Func<Window>? _getWindowFunc;

private bool? _isGlInitialized;
private bool _changingGlInitialized;

// valid if and only if GLCanvasElement was loaded at least once and OpenGL is available on the running platform
private INativeOpenGLWrapper? _nativeOpenGlWrapper;
Expand Down Expand Up @@ -224,25 +224,41 @@ private void OnClosed(object _, object __)
public void Invalidate() => NativeDispatcher.Main.Enqueue(Render, NativeDispatcherPriority.Idle);
#endif

public static DependencyProperty IsGLInitializedProperty { get; } =
DependencyProperty.Register(
nameof(IsGLInitialized),
typeof(bool?),
typeof(GLCanvasElement),
new PropertyMetadata(null, (PropertyChangedCallback)((dO, _) =>
{
var @this = (GLCanvasElement)dO;
if (!@this._changingGlInitialized)
{
throw new InvalidOperationException($"{nameof(GLCanvasElement)}.{nameof(IsGLInitializedProperty)} is read-only.");
}

// We should have arrived here from set_IsGLInitialized, so we could put this line at the end of the
// setter. Instead, we set it to false here to prevent users from calling SetValue.IsGLInitializedProperty
// _inside_ a call to GLCanvasElement.set_IsGLInitialized. This way, if a user intercepts this
// change (e.g. with SubscribeToPropertyChanged) and attempts to make a nested SetValue call, we still
// explode in their face.
@this._changingGlInitialized = false;
})));

/// <summary>
/// Indicates whether this element was loaded successfully or not, including the OpenGL context creation and setup.
/// This property is only valid when the element is loaded. When the element is not loaded in the visual tree, the value will be null.
/// </summary>
public bool? IsGLInitialized
{
get => _isGlInitialized;
get => (bool?)GetValue(IsGLInitializedProperty);
private set
{
_isGlInitialized = value;
RaisePropertyChanged();
_changingGlInitialized = true;
SetValue(IsGLInitializedProperty, value);
}
}

public event PropertyChangedEventHandler? PropertyChanged;

protected void RaisePropertyChanged([CallerMemberName] string? propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
_nativeOpenGlWrapper = GetOrCreateNativeOpenGlWrapper(XamlRoot!, _getWindowFunc);
Expand Down

0 comments on commit 357d30b

Please sign in to comment.