mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Turn ImFontLocked into a class
As `ImFontLocked` utilizes a reference counter, changed it to a class so that at worst case we still got the destructor to decrease the reference count.
This commit is contained in:
parent
df89472d4c
commit
68dc16803c
5 changed files with 75 additions and 34 deletions
|
|
@ -79,7 +79,7 @@ internal class InterfaceManager : IDisposable, IServiceType
|
|||
private Hook<ResizeBuffersDelegate>? resizeBuffersHook;
|
||||
|
||||
private IFontAtlas? dalamudAtlas;
|
||||
private IFontHandle.ImFontLocked defaultFontResourceLock;
|
||||
private IFontHandle.ImFontLocked? defaultFontResourceLock;
|
||||
|
||||
// can't access imgui IO before first present call
|
||||
private bool lastWantCapture = false;
|
||||
|
|
@ -243,6 +243,8 @@ internal class InterfaceManager : IDisposable, IServiceType
|
|||
Disposer();
|
||||
|
||||
this.wndProcHookManager.PreWndProc -= this.WndProcHookManagerOnPreWndProc;
|
||||
this.defaultFontResourceLock?.Dispose(); // lock outlives handle and atlas
|
||||
this.defaultFontResourceLock = null;
|
||||
this.dalamudAtlas?.Dispose();
|
||||
this.scene?.Dispose();
|
||||
return;
|
||||
|
|
@ -727,22 +729,26 @@ internal class InterfaceManager : IDisposable, IServiceType
|
|||
tk.GetFont(this.MonoFontHandle),
|
||||
missingOnly: true);
|
||||
});
|
||||
this.DefaultFontHandle.ImFontChanged += (_, font) => Service<Framework>.Get().RunOnFrameworkThread(
|
||||
this.DefaultFontHandle.ImFontChanged += (_, font) =>
|
||||
{
|
||||
var fontLocked = font.NewRef();
|
||||
Service<Framework>.Get().RunOnFrameworkThread(
|
||||
() =>
|
||||
{
|
||||
// Update the ImGui default font.
|
||||
unsafe
|
||||
{
|
||||
ImGui.GetIO().NativePtr->FontDefault = font;
|
||||
ImGui.GetIO().NativePtr->FontDefault = fontLocked;
|
||||
}
|
||||
|
||||
// Update the reference to the resources of the default font.
|
||||
this.defaultFontResourceLock.Dispose();
|
||||
this.defaultFontResourceLock = font.NewRef();
|
||||
this.defaultFontResourceLock?.Dispose();
|
||||
this.defaultFontResourceLock = fontLocked;
|
||||
|
||||
// Broadcast to auto-rebuilding instances.
|
||||
this.AfterBuildFonts?.Invoke();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// This will wait for scene on its own. We just wait for this.dalamudAtlas.BuildTask in this.InitScene.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Utility;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Dalamud.Interface.ManagedFontAtlas;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -80,26 +85,23 @@ public interface IFontHandle : IDisposable
|
|||
/// The wrapper for <see cref="ImFontPtr"/>, guaranteeing that the associated data will be available as long as
|
||||
/// this struct is not disposed.
|
||||
/// </summary>
|
||||
public struct ImFontLocked : IDisposable
|
||||
public class ImFontLocked : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated <see cref="ImFontPtr"/>.
|
||||
/// </summary>
|
||||
public ImFontPtr ImFont;
|
||||
// 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>
|
||||
/// Initializes a new instance of the <see cref="ImFontLocked"/> struct.
|
||||
/// Ownership of reference of <paramref name="owner"/> is transferred.
|
||||
/// Finalizes an instance of the <see cref="ImFontLocked"/> class.
|
||||
/// </summary>
|
||||
/// <param name="imFont">The contained font.</param>
|
||||
/// <param name="owner">The owner.</param>
|
||||
internal ImFontLocked(ImFontPtr imFont, IRefCountable owner)
|
||||
{
|
||||
this.ImFont = imFont;
|
||||
this.owner = owner;
|
||||
}
|
||||
~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;
|
||||
|
||||
|
|
@ -109,16 +111,47 @@ public interface IFontHandle : IDisposable
|
|||
/// Creates a new instance of <see cref="ImFontLocked"/> with an additional reference to the owner.
|
||||
/// </summary>
|
||||
/// <returns>The new locked instance.</returns>
|
||||
public readonly ImFontLocked NewRef()
|
||||
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 new(this.ImFont, this.owner);
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -557,7 +557,9 @@ internal sealed partial class FontAtlasFactory
|
|||
foreach (var fontHandle in substance.RelevantHandles)
|
||||
{
|
||||
substance.DataRoot.AddRef();
|
||||
var locked = new IFontHandle.ImFontLocked(substance.GetFontPtr(fontHandle), substance.DataRoot);
|
||||
var locked = IFontHandle.ImFontLocked.Rent(
|
||||
substance.GetFontPtr(fontHandle),
|
||||
substance.DataRoot);
|
||||
fontsAndLocks.Add((fontHandle, garbage.Add(locked)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ internal abstract class FontHandle : IFontHandle
|
|||
|
||||
// Transfer the ownership of reference.
|
||||
errorMessage = null;
|
||||
return new(fontPtr, substance.DataRoot);
|
||||
return IFontHandle.ImFontLocked.Rent(fontPtr, substance.DataRoot);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ internal sealed class SimplePushedFont : IDisposable
|
|||
/// </summary>
|
||||
/// <param name="stack">The <see cref="IFontHandle"/>-private stack.</param>
|
||||
/// <param name="fontPtr">The font pointer being pushed.</param>
|
||||
/// <returns><c>this</c>.</returns>
|
||||
/// <returns>The rented instance of <see cref="SimplePushedFont"/>.</returns>
|
||||
public static SimplePushedFont Rent(List<IDisposable> stack, ImFontPtr fontPtr)
|
||||
{
|
||||
var rented = Pool.Get();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue