mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
Move IFontHandle.ImFontLocked to ILockedImFont+impl
This commit is contained in:
parent
68dc16803c
commit
5161053cb3
9 changed files with 105 additions and 110 deletions
|
|
@ -71,7 +71,7 @@ public sealed class GameFontHandle : IFontHandle
|
||||||
public void Dispose() => this.fontHandle.Dispose();
|
public void Dispose() => this.fontHandle.Dispose();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IFontHandle.ImFontLocked Lock() => this.fontHandle.Lock();
|
public ILockedImFont Lock() => this.fontHandle.Lock();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IDisposable Push() => this.fontHandle.Push();
|
public IDisposable Push() => this.fontHandle.Push();
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
public const float DefaultFontSizePx = (DefaultFontSizePt * 4.0f) / 3.0f;
|
public const float DefaultFontSizePx = (DefaultFontSizePt * 4.0f) / 3.0f;
|
||||||
|
|
||||||
private readonly ConcurrentBag<DalamudTextureWrap> deferredDisposeTextures = new();
|
private readonly ConcurrentBag<DalamudTextureWrap> deferredDisposeTextures = new();
|
||||||
private readonly ConcurrentBag<IFontHandle.ImFontLocked> deferredDisposeImFontLockeds = new();
|
private readonly ConcurrentBag<ILockedImFont> deferredDisposeImFontLockeds = new();
|
||||||
|
|
||||||
[ServiceManager.ServiceDependency]
|
[ServiceManager.ServiceDependency]
|
||||||
private readonly WndProcHookManager wndProcHookManager = Service<WndProcHookManager>.Get();
|
private readonly WndProcHookManager wndProcHookManager = Service<WndProcHookManager>.Get();
|
||||||
|
|
@ -79,7 +79,7 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
private Hook<ResizeBuffersDelegate>? resizeBuffersHook;
|
private Hook<ResizeBuffersDelegate>? resizeBuffersHook;
|
||||||
|
|
||||||
private IFontAtlas? dalamudAtlas;
|
private IFontAtlas? dalamudAtlas;
|
||||||
private IFontHandle.ImFontLocked? defaultFontResourceLock;
|
private ILockedImFont? defaultFontResourceLock;
|
||||||
|
|
||||||
// can't access imgui IO before first present call
|
// can't access imgui IO before first present call
|
||||||
private bool lastWantCapture = false;
|
private bool lastWantCapture = false;
|
||||||
|
|
@ -408,10 +408,10 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enqueue an <see cref="IFontHandle.ImFontLocked"/> to be disposed at the end of the frame.
|
/// Enqueue an <see cref="ILockedImFont"/> to be disposed at the end of the frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="locked">The disposable.</param>
|
/// <param name="locked">The disposable.</param>
|
||||||
public void EnqueueDeferredDispose(in IFontHandle.ImFontLocked locked)
|
public void EnqueueDeferredDispose(in ILockedImFont locked)
|
||||||
{
|
{
|
||||||
this.deferredDisposeImFontLockeds.Add(locked);
|
this.deferredDisposeImFontLockeds.Add(locked);
|
||||||
}
|
}
|
||||||
|
|
@ -738,7 +738,7 @@ internal class InterfaceManager : IDisposable, IServiceType
|
||||||
// Update the ImGui default font.
|
// Update the ImGui default font.
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
ImGui.GetIO().NativePtr->FontDefault = fontLocked;
|
ImGui.GetIO().NativePtr->FontDefault = fontLocked.ImFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the reference to the resources of the default font.
|
// Update the reference to the resources of the default font.
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ internal class GamePrebakedFontsTestWidget : IDataWindowWidget, IDisposable
|
||||||
await handle.WaitAsync();
|
await handle.WaitAsync();
|
||||||
var locked = handle.Lock();
|
var locked = handle.Lock();
|
||||||
garbage.Add(locked);
|
garbage.Add(locked);
|
||||||
fonts.Add(locked);
|
fonts.Add(locked.ImFont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,7 @@
|
||||||
using System.Diagnostics;
|
using System.Threading.Tasks;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using Dalamud.Interface.Utility;
|
|
||||||
using Dalamud.Utility;
|
|
||||||
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
||||||
using Microsoft.Extensions.ObjectPool;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.ManagedFontAtlas;
|
namespace Dalamud.Interface.ManagedFontAtlas;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -21,7 +14,7 @@ public interface IFontHandle : IDisposable
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fontHandle">The relevant font handle.</param>
|
/// <param name="fontHandle">The relevant font handle.</param>
|
||||||
/// <param name="lockedFont">The locked font for this font handle, locked during the call of this delegate.</param>
|
/// <param name="lockedFont">The locked font for this font handle, locked during the call of this delegate.</param>
|
||||||
public delegate void ImFontChangedDelegate(IFontHandle fontHandle, ImFontLocked lockedFont);
|
public delegate void ImFontChangedDelegate(IFontHandle fontHandle, ILockedImFont lockedFont);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the built instance of <see cref="ImFontPtr"/> has been changed.<br />
|
/// Called when the built instance of <see cref="ImFontPtr"/> has been changed.<br />
|
||||||
|
|
@ -48,13 +41,13 @@ public interface IFontHandle : IDisposable
|
||||||
/// <see cref="IFontHandle"/>, for use in any thread.<br />
|
/// <see cref="IFontHandle"/>, for use in any thread.<br />
|
||||||
/// Modification of the font will exhibit undefined behavior if some other thread also uses the font.
|
/// Modification of the font will exhibit undefined behavior if some other thread also uses the font.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An instance of <see cref="ImFontLocked"/> that <b>must</b> be disposed after use.</returns>
|
/// <returns>An instance of <see cref="ILockedImFont"/> that <b>must</b> be disposed after use.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Calling <see cref="IFontHandle"/>.<see cref="IDisposable.Dispose"/> will not unlock the <see cref="ImFontPtr"/>
|
/// Calling <see cref="IFontHandle"/>.<see cref="IDisposable.Dispose"/> will not unlock the <see cref="ImFontPtr"/>
|
||||||
/// locked by this function.
|
/// locked by this function.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <exception cref="InvalidOperationException">If <see cref="Available"/> is <c>false</c>.</exception>
|
/// <exception cref="InvalidOperationException">If <see cref="Available"/> is <c>false</c>.</exception>
|
||||||
ImFontLocked Lock();
|
ILockedImFont Lock();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pushes the current font into ImGui font stack, if available.<br />
|
/// Pushes the current font into ImGui font stack, if available.<br />
|
||||||
|
|
@ -80,85 +73,4 @@ public interface IFontHandle : IDisposable
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A task containing this <see cref="IFontHandle"/>.</returns>
|
/// <returns>A task containing this <see cref="IFontHandle"/>.</returns>
|
||||||
Task<IFontHandle> WaitAsync();
|
Task<IFontHandle> WaitAsync();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The wrapper for <see cref="ImFontPtr"/>, guaranteeing that the associated data will be available as long as
|
|
||||||
/// this struct is not disposed.
|
|
||||||
/// </summary>
|
|
||||||
public class ImFontLocked : IDisposable
|
|
||||||
{
|
|
||||||
// Using constructor instead of DefaultObjectPoolProvider, since we do not want the pool to call Dispose.
|
|
||||||
private static readonly ObjectPool<ImFontLocked> Pool =
|
|
||||||
new DefaultObjectPool<ImFontLocked>(new DefaultPooledObjectPolicy<ImFontLocked>());
|
|
||||||
|
|
||||||
private IRefCountable? owner;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finalizes an instance of the <see cref="ImFontLocked"/> class.
|
|
||||||
/// </summary>
|
|
||||||
~ImFontLocked() => this.FreeOwner();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the associated <see cref="ImFontPtr"/>.
|
|
||||||
/// </summary>
|
|
||||||
public ImFontPtr ImFont { get; private set; }
|
|
||||||
|
|
||||||
public static implicit operator ImFontPtr(ImFontLocked l) => l.ImFont;
|
|
||||||
|
|
||||||
public static unsafe implicit operator ImFont*(ImFontLocked l) => l.ImFont.NativePtr;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of <see cref="ImFontLocked"/> with an additional reference to the owner.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The new locked instance.</returns>
|
|
||||||
public ImFontLocked NewRef()
|
|
||||||
{
|
|
||||||
if (this.owner is null)
|
|
||||||
throw new ObjectDisposedException(nameof(ImFontLocked));
|
|
||||||
|
|
||||||
var rented = Pool.Get();
|
|
||||||
rented.owner = this.owner;
|
|
||||||
rented.ImFont = this.ImFont;
|
|
||||||
|
|
||||||
this.owner.AddRef();
|
|
||||||
return rented;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
[SuppressMessage(
|
|
||||||
"Usage",
|
|
||||||
"CA1816:Dispose methods should call SuppressFinalize",
|
|
||||||
Justification = "Dispose returns this object to the pool.")]
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
this.FreeOwner();
|
|
||||||
Pool.Return(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ImFontLocked"/> class.
|
|
||||||
/// Ownership of reference of <paramref name="owner"/> is transferred.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="font">The contained font.</param>
|
|
||||||
/// <param name="owner">The owner.</param>
|
|
||||||
/// <returns>The rented instance of <see cref="ImFontLocked"/>.</returns>
|
|
||||||
internal static ImFontLocked Rent(ImFontPtr font, IRefCountable owner)
|
|
||||||
{
|
|
||||||
var rented = Pool.Get();
|
|
||||||
Debug.Assert(rented.ImFont.IsNull(), "Rented object must not have its font set");
|
|
||||||
rented.ImFont = font;
|
|
||||||
rented.owner = owner;
|
|
||||||
return rented;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FreeOwner()
|
|
||||||
{
|
|
||||||
if (this.owner is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.owner.Release();
|
|
||||||
this.owner = null;
|
|
||||||
this.ImFont = default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
Dalamud/Interface/ManagedFontAtlas/ILockedImFont.cs
Normal file
21
Dalamud/Interface/ManagedFontAtlas/ILockedImFont.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
using ImGuiNET;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ManagedFontAtlas;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The wrapper for <see cref="ImFontPtr"/>, guaranteeing that the associated data will be available as long as
|
||||||
|
/// this struct is not disposed.
|
||||||
|
/// </summary>
|
||||||
|
public interface ILockedImFont : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the associated <see cref="ImFontPtr"/>.
|
||||||
|
/// </summary>
|
||||||
|
ImFontPtr ImFont { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="ILockedImFont"/> with an additional reference to the owner.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The new locked instance.</returns>
|
||||||
|
ILockedImFont NewRef();
|
||||||
|
}
|
||||||
|
|
@ -534,7 +534,7 @@ internal sealed partial class FontAtlasFactory
|
||||||
private void PromoteBuiltData(int rebuildIndex, FontAtlasBuiltData data, [UsedImplicitly] string source)
|
private void PromoteBuiltData(int rebuildIndex, FontAtlasBuiltData data, [UsedImplicitly] string source)
|
||||||
{
|
{
|
||||||
// Capture the locks inside the lock block, so that the fonts are guaranteed to be the ones just built.
|
// Capture the locks inside the lock block, so that the fonts are guaranteed to be the ones just built.
|
||||||
var fontsAndLocks = new List<(FontHandle FontHandle, IFontHandle.ImFontLocked Lock)>();
|
var fontsAndLocks = new List<(FontHandle FontHandle, ILockedImFont Lock)>();
|
||||||
using var garbage = new DisposeSafety.ScopedFinalizer();
|
using var garbage = new DisposeSafety.ScopedFinalizer();
|
||||||
|
|
||||||
lock (this.syncRoot)
|
lock (this.syncRoot)
|
||||||
|
|
@ -557,7 +557,7 @@ internal sealed partial class FontAtlasFactory
|
||||||
foreach (var fontHandle in substance.RelevantHandles)
|
foreach (var fontHandle in substance.RelevantHandles)
|
||||||
{
|
{
|
||||||
substance.DataRoot.AddRef();
|
substance.DataRoot.AddRef();
|
||||||
var locked = IFontHandle.ImFontLocked.Rent(
|
var locked = new LockedImFont(
|
||||||
substance.GetFontPtr(fontHandle),
|
substance.GetFontPtr(fontHandle),
|
||||||
substance.DataRoot);
|
substance.DataRoot);
|
||||||
fontsAndLocks.Add((fontHandle, garbage.Add(locked)));
|
fontsAndLocks.Add((fontHandle, garbage.Add(locked)));
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ internal abstract class FontHandle : IFontHandle
|
||||||
/// Invokes <see cref="IFontHandle.ImFontChanged"/>.
|
/// Invokes <see cref="IFontHandle.ImFontChanged"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">The font, locked during the call of <see cref="ImFontChanged"/>.</param>
|
/// <param name="font">The font, locked during the call of <see cref="ImFontChanged"/>.</param>
|
||||||
public void InvokeImFontChanged(IFontHandle.ImFontLocked font)
|
public void InvokeImFontChanged(ILockedImFont font)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -133,11 +133,11 @@ internal abstract class FontHandle : IFontHandle
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="errorMessage">The error message, if any.</param>
|
/// <param name="errorMessage">The error message, if any.</param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// An instance of <see cref="IFontHandle.ImFontLocked"/> that <b>must</b> be disposed after use on success;
|
/// An instance of <see cref="ILockedImFont"/> that <b>must</b> be disposed after use on success;
|
||||||
/// <c>null</c> with <paramref name="errorMessage"/> populated on failure.
|
/// <c>null</c> with <paramref name="errorMessage"/> populated on failure.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
/// <exception cref="ObjectDisposedException">Still may be thrown.</exception>
|
/// <exception cref="ObjectDisposedException">Still may be thrown.</exception>
|
||||||
public IFontHandle.ImFontLocked? TryLock(out string? errorMessage)
|
public ILockedImFont? TryLock(out string? errorMessage)
|
||||||
{
|
{
|
||||||
IFontHandleSubstance? prevSubstance = default;
|
IFontHandleSubstance? prevSubstance = default;
|
||||||
while (true)
|
while (true)
|
||||||
|
|
@ -182,12 +182,12 @@ internal abstract class FontHandle : IFontHandle
|
||||||
|
|
||||||
// Transfer the ownership of reference.
|
// Transfer the ownership of reference.
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
return IFontHandle.ImFontLocked.Rent(fontPtr, substance.DataRoot);
|
return new LockedImFont(fontPtr, substance.DataRoot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IFontHandle.ImFontLocked Lock() =>
|
public ILockedImFont Lock() =>
|
||||||
this.TryLock(out var errorMessage) ?? throw new InvalidOperationException(errorMessage);
|
this.TryLock(out var errorMessage) ?? throw new InvalidOperationException(errorMessage);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -238,10 +238,10 @@ internal abstract class FontHandle : IFontHandle
|
||||||
this.ImFontChanged += OnImFontChanged;
|
this.ImFontChanged += OnImFontChanged;
|
||||||
this.Disposed += OnDisposed;
|
this.Disposed += OnDisposed;
|
||||||
if (this.Available)
|
if (this.Available)
|
||||||
OnImFontChanged(this, default);
|
OnImFontChanged(this, null);
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
|
|
||||||
void OnImFontChanged(IFontHandle unused, IFontHandle.ImFontLocked unused2)
|
void OnImFontChanged(IFontHandle unused, ILockedImFont? unused2)
|
||||||
{
|
{
|
||||||
if (tcs.Task.IsCompletedSuccessfully)
|
if (tcs.Task.IsCompletedSuccessfully)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
62
Dalamud/Interface/ManagedFontAtlas/Internals/LockedImFont.cs
Normal file
62
Dalamud/Interface/ManagedFontAtlas/Internals/LockedImFont.cs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
using Dalamud.Utility;
|
||||||
|
|
||||||
|
using ImGuiNET;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ManagedFontAtlas.Internals;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The implementation for <see cref="ILockedImFont"/>.
|
||||||
|
/// </summary>
|
||||||
|
internal class LockedImFont : ILockedImFont
|
||||||
|
{
|
||||||
|
private IRefCountable? owner;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="LockedImFont"/> class.
|
||||||
|
/// Ownership of reference of <paramref name="owner"/> is transferred.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="font">The contained font.</param>
|
||||||
|
/// <param name="owner">The owner.</param>
|
||||||
|
/// <returns>The rented instance of <see cref="LockedImFont"/>.</returns>
|
||||||
|
internal LockedImFont(ImFontPtr font, IRefCountable owner)
|
||||||
|
{
|
||||||
|
this.ImFont = font;
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes an instance of the <see cref="LockedImFont"/> class.
|
||||||
|
/// </summary>
|
||||||
|
~LockedImFont() => this.FreeOwner();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ImFontPtr ImFont { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ILockedImFont NewRef()
|
||||||
|
{
|
||||||
|
if (this.owner is null)
|
||||||
|
throw new ObjectDisposedException(nameof(LockedImFont));
|
||||||
|
|
||||||
|
var newRef = new LockedImFont(this.ImFont, this.owner);
|
||||||
|
this.owner.AddRef();
|
||||||
|
return newRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.FreeOwner();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FreeOwner()
|
||||||
|
{
|
||||||
|
if (this.owner is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.owner.Release();
|
||||||
|
this.owner = null;
|
||||||
|
this.ImFont = default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -761,7 +761,7 @@ public sealed class UiBuilder : IDisposable
|
||||||
// Note: do not dispose w; we do not own it
|
// Note: do not dispose w; we do not own it
|
||||||
}
|
}
|
||||||
|
|
||||||
public IFontHandle.ImFontLocked Lock() =>
|
public ILockedImFont Lock() =>
|
||||||
this.wrapped?.Lock() ?? throw new ObjectDisposedException(nameof(FontHandleWrapper));
|
this.wrapped?.Lock() ?? throw new ObjectDisposedException(nameof(FontHandleWrapper));
|
||||||
|
|
||||||
public IDisposable Push() =>
|
public IDisposable Push() =>
|
||||||
|
|
@ -775,7 +775,7 @@ public sealed class UiBuilder : IDisposable
|
||||||
|
|
||||||
public override string ToString() => $"{nameof(FontHandleWrapper)}({this.wrapped})";
|
public override string ToString() => $"{nameof(FontHandleWrapper)}({this.wrapped})";
|
||||||
|
|
||||||
private void WrappedOnImFontChanged(IFontHandle obj, IFontHandle.ImFontLocked lockedFont) =>
|
private void WrappedOnImFontChanged(IFontHandle obj, ILockedImFont lockedFont) =>
|
||||||
this.ImFontChanged?.Invoke(obj, lockedFont);
|
this.ImFontChanged?.Invoke(obj, lockedFont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue