diff --git a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs index 9978a19165..5339744378 100644 --- a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs +++ b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs @@ -12,6 +12,21 @@ using System.ComponentModel; namespace Avalonia.OpenGL.Controls { + /// + /// Base class for controls that render using OpenGL. + /// Provides infrastructure for OpenGL context management, surface creation, and rendering lifecycle. + /// + /// + /// The control automatically manages OpenGL context creation, surface setup, and cleanup. + /// + /// Important: Any interaction with should only happen within the + /// , , or method overrides. + /// + /// + /// Avalonia ensures proper OpenGL context synchronization and makes the context current only during these method calls. + /// Accessing OpenGL functions outside of these methods may result in undefined behavior, crashes, or rendering corruption. + /// + /// public abstract class OpenGlControlBase : Control { private CompositionSurfaceVisual? _visual; @@ -23,8 +38,15 @@ namespace Avalonia.OpenGL.Controls [MemberNotNullWhen(true, nameof(_resources))] private bool IsInitializedSuccessfully => _initialization is { Status: TaskStatus.RanToCompletion, Result: true }; + + /// + /// Gets the OpenGL version information for the current context. + /// protected GlVersion GlVersion => _resources?.Context.Version ?? default; + /// + /// Initializes a new instance of the class. + /// public OpenGlControlBase() { _update = Update; @@ -57,12 +79,14 @@ namespace Avalonia.OpenGL.Controls _initialization = null; } + /// protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) { DoCleanup(); base.OnDetachedFromVisualTree(e); } + /// protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { base.OnAttachedToVisualTree(e); @@ -114,7 +138,8 @@ namespace Avalonia.OpenGL.Controls return true; } - + + /// protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { if (_visual != null && change.Property == BoundsProperty) @@ -220,10 +245,14 @@ namespace Avalonia.OpenGL.Controls return true; } + /// [Obsolete("Use RequestNextFrameRendering()"), EditorBrowsable(EditorBrowsableState.Never)] // ReSharper disable once MemberCanBeProtected.Global public new void InvalidateVisual() => RequestNextFrameRendering(); + /// + /// Requests that the control be rendered on the next frame. + /// public void RequestNextFrameRendering() { if ((_initialization == null || IsInitializedSuccessfully) && @@ -240,22 +269,38 @@ namespace Avalonia.OpenGL.Controls return new PixelSize(Math.Max(1, (int)(Bounds.Width * scaling)), Math.Max(1, (int)(Bounds.Height * scaling))); } - + + /// + /// Called when the OpenGL context is first created. + /// + /// The interface for making OpenGL calls. Use to access additional APIs not covered by . protected virtual void OnOpenGlInit(GlInterface gl) { } + /// + /// Called when the OpenGL context is being destroyed. + /// + /// The OpenGL interface for making OpenGL calls. Use to access additional APIs not covered by . protected virtual void OnOpenGlDeinit(GlInterface gl) { } - + + /// + /// Called when the OpenGL context is lost and cannot be recovered. + /// protected virtual void OnOpenGlLost() { } - + + /// + /// Called to render the OpenGL content for the current frame. + /// + /// The OpenGL interface for making OpenGL calls. Use to access additional APIs not covered by . + /// The framebuffer ID to render into. protected abstract void OnOpenGlRender(GlInterface gl, int fb); } } diff --git a/src/Avalonia.OpenGL/GlInterface.cs b/src/Avalonia.OpenGL/GlInterface.cs index 26bea6206d..12a5ef733e 100644 --- a/src/Avalonia.OpenGL/GlInterface.cs +++ b/src/Avalonia.OpenGL/GlInterface.cs @@ -2,12 +2,20 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; +using Avalonia.Metadata; using Avalonia.Platform.Interop; using Avalonia.SourceGenerator; using static Avalonia.OpenGL.GlConsts; namespace Avalonia.OpenGL { + /// + /// GlInterface only includes essential members and members necessary for Avalonia itself. + /// It is not a general-purpose interface for OpenGL API. + /// + /// + /// Use to get GL procedures you need, or integrate it with third-party GL wrappers. + /// public unsafe partial class GlInterface : GlBasicInfoInterface { private readonly Func _getProcAddress; @@ -50,6 +58,11 @@ namespace Avalonia.OpenGL { } + /// + /// Returns an OpenGL function by name. + /// + /// Function name. + /// Handle of function, which can be casted to unmanaged function pointer. public IntPtr GetProcAddress(string proc) => _getProcAddress(proc); [GetProcAddress("glClearStencil")]