Skip to content

Commit 1444deb

Browse files
committed
Add IDetachedSurfaceLifecycle
1 parent 5375e53 commit 1444deb

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

documentation/proposals/Proposal - Windowing 3.0.md

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ of the target platforms. It is expected that platform differentiation is done by
112112
`net8.0-ios`, etc) but this could include runtime identifier based differentiation in the future. The Silk.NET team
113113
reserves all rights to determine implementation details such as this.
114114

115-
Silk.NET 3.0 aims to support Windows, Linux (X/11 and Wayland), macOS, iOS, and macOS. The goal of this proposal is to
115+
Silk.NET 3.0 aims to support Windows, Linux (X/11 and Wayland), macOS, iOS, and Android. The goal of this proposal is to
116116
do so in a way that requires no _modification_ of user code. It is highly likely that _additional_ boilerplate code will
117117
be needed on some platforms (e.g. `MainActivity`) but this should not be variant based on the user's specific
118118
application i.e. it should work as is when copied and pasted into the user's application.
@@ -1548,6 +1548,87 @@ public abstract partial class Surface
15481548
Implementations are expected to be aware of the resource sharing/validity requirements set forth at numerous points
15491549
throughout this document - search for occurrences of ISurfaceChildren.
15501550

1551+
# Detached Surfaces
1552+
1553+
When reviewing this proposal, we noticed that we hadn't accounted for the use case wherein users may want to take
1554+
advantage of desktop features (e.g. the ability to run one's own timing/game loop logic) if they are available. Up until
1555+
now, `ISurfaceApplication.Run` (or an alternative implementation's equivalent) is the only way to obtain a `Surface`
1556+
which involves taking control of the entire application and only giving the user control through the exposed callbacks.
1557+
For most use cases, this is fine as we've exposed fundamentals like calling into user code as fast as possible (`Tick`)
1558+
or on regular intervals (`Render`/`Update`). However, there will be some power users that will want to retain the
1559+
ability to control their own timing if possible, for which we propose the concept of "detached surfaces".
1560+
1561+
"Detached surfaces" have a lifetime that is detached from that of the `ISurfaceApplication` they're associated with.
1562+
That is, the implementation's usual handling of an `ISurfaceApplication` and its lifecycle is instead user controlled.
1563+
This is notable as creation and destruction of a `Surface` is usually controlled by the implementation, whereas with
1564+
this API the destruction shall be delegated to the user. This is exposed as follows:
1565+
1566+
```cs
1567+
namespace Silk.NET.Windowing;
1568+
1569+
/// <summary>
1570+
/// Represents a surface with a user-controlled lifecycle.
1571+
/// </summary>
1572+
/// <remarks>
1573+
/// This API is <b>not guaranteed to be supported</b> on all platforms and you should only use it if you know what
1574+
/// you're doing and know you need the granular control this API provides! Please use
1575+
/// <see cref="ISurfaceApplication.Run{T}" /> instead where possible. If you insist on using this API, please fall back
1576+
/// to <see cref="ISurfaceApplication.Run{T}" /> if <see cref="TryCreate{T}" /> returns <c>false</c> indicating a lack
1577+
/// of support.
1578+
/// </remarks>
1579+
public interface IDetachedSurfaceLifecycle : IDisposable
1580+
{
1581+
/// <summary>
1582+
/// Gets the surface with which this lifecycle is associated. The destruction of this surface is handled by
1583+
/// the <see cref="IDisposable.Dispose" /> method of this <see cref="IDetachedSurfaceLifecycle" /> implementation.
1584+
/// </summary>
1585+
Surface Surface { get; }
1586+
1587+
/// <summary>
1588+
/// Gets a value indicating whether the surface is indicating that its lifecycle should conclude as a result of
1589+
/// its current configuration e.g. an entire tick passing with <see cref="ISurfaceWindow.IsCloseRequested" /> being
1590+
/// <c>true</c>.
1591+
/// </summary>
1592+
/// <remarks>
1593+
/// It is expected that <see cref="Tick" /> shall not be called if this property is <c>true</c>.
1594+
/// <remarks>
1595+
bool ShouldTerminate { get; }
1596+
1597+
/// <summary>
1598+
/// Steps the underlying implementation's surface lifecycle (i.e. event loop), running a single tick on the
1599+
/// <see cref="Surface" />.
1600+
/// </summary>
1601+
/// <remarks>
1602+
/// It is expected that implementations shall return after doing as little work as possible. For instance, if the
1603+
/// underlying implementation exposes one-by-one event retrieval or otherwise allows customisation of the extent to
1604+
/// which the event pump is run, it is expected that a single event shall be pumped in this case. Note that this is
1605+
/// just an example and the exact details of this is implementation-defined.
1606+
/// </remarks>
1607+
void Tick();
1608+
1609+
/// <summary>
1610+
/// Attempts to create a <see cref="IDetachedSurfaceLifecycle" /> using the reference implementation.
1611+
/// </summary>
1612+
/// <param name="lifecycle">The created surface lifecycle on success, <c>null</c> otherwise.</param>
1613+
/// <typeparam name="T">
1614+
/// The application that shall be associated with the surface. Note that even with this API,
1615+
/// <see cref="ISurfaceApplication.Initialize{T}"> shall still be called for consistency and portability. However,
1616+
/// unlike <see cref="ISurfaceApplication.Run{T}" />, this method shall not block and will instead return an
1617+
/// <see cref="IDetachedSurfaceLifecycle" /> on which <see cref="Tick" /> is expected to be continuously called to
1618+
/// enact the same behaviour on the surface. The associated application is also used for any additional global
1619+
/// configuration, such as <see cref="ISurfaceApplication.WindowClass" />.
1620+
/// </typeparam>
1621+
/// <returns>
1622+
/// <c>true</c> if <paramref name="lifecycle" /> has been populated with an <see cref="IDetachedSurfaceLifecycle" />
1623+
/// object containing a valid <see cref="Surface" />, <c>false</c> otherwise.
1624+
/// </returns>
1625+
/// <remarks>
1626+
/// This is the same reference implementation that <see cref="ISurfaceApplication.Run{T}" /> would otherwise use.
1627+
/// </remarks>
1628+
sealed static bool TryCreate<T>([NotNullWhen(true)] out IDetachedSurfaceLifecycle? lifecycle) where T : ISurfaceApplication;
1629+
}
1630+
```
1631+
15511632
# Meeting Notes
15521633

15531634
## 25/02/2022

0 commit comments

Comments
 (0)