mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-15 21:24:16 +01:00
Add ForwardingTextureWrap
This commit is contained in:
parent
6c8c42ca05
commit
5fd7457df4
5 changed files with 120 additions and 77 deletions
81
Dalamud/Interface/Textures/ForwardingTextureWrap.cs
Normal file
81
Dalamud/Interface/Textures/ForwardingTextureWrap.cs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.Interface.Textures.Internal;
|
||||
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Dalamud.Interface.Textures;
|
||||
|
||||
/// <summary>Base class for implementations of <see cref="IDalamudTextureWrap"/> that forwards to another.</summary>
|
||||
public abstract class ForwardingTextureWrap : IDalamudTextureWrap
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public IntPtr ImGuiHandle
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => this.GetWrap().ImGuiHandle;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Width
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => this.GetWrap().Width;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Height
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => this.GetWrap().Height;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Vector2 Size
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => new(this.Width, this.Height);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual unsafe IDalamudTextureWrap CreateWrapSharingLowLevelResource()
|
||||
{
|
||||
// Dalamud specific: IDalamudTextureWrap always points to an ID3D11ShaderResourceView.
|
||||
var handle = (IUnknown*)this.ImGuiHandle;
|
||||
return new UnknownTextureWrap(handle, this.Width, this.Height, true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"{this.GetType()}({(this.TryGetWrap(out var wrap) ? wrap : null)})";
|
||||
|
||||
/// <summary>Called on <see cref="IDisposable.Dispose"/>.</summary>
|
||||
/// <param name="disposing"><c>true</c> if called from <see cref="IDisposable.Dispose"/>.</param>
|
||||
/// <remarks>
|
||||
/// <para>Base implementation will not dispose the result of <see cref="TryGetWrap"/>.</para>
|
||||
/// <para>If you need to implement a finalizer, then make it call this function with <c>false</c>.</para>
|
||||
/// </remarks>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Gets the inner wrap.</summary>
|
||||
/// <param name="wrap">The inner wrap.</param>
|
||||
/// <returns><c>true</c> if not disposed and <paramref name="wrap"/> is available.</returns>
|
||||
protected abstract bool TryGetWrap([NotNullWhen(true)] out IDalamudTextureWrap? wrap);
|
||||
|
||||
/// <summary>Gets the inner wrap.</summary>
|
||||
/// <returns>The inner wrap.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected IDalamudTextureWrap GetWrap() =>
|
||||
this.TryGetWrap(out var wrap) ? wrap : throw new ObjectDisposedException(this.GetType().Name);
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Numerics;
|
||||
|
||||
using Dalamud.Interface.Textures;
|
||||
using Dalamud.Interface.Textures.Internal;
|
||||
|
||||
using TerraFX.Interop.Windows;
|
||||
|
|
@ -12,6 +13,8 @@ namespace Dalamud.Interface.Internal;
|
|||
/// Base TextureWrap interface for all Dalamud-owned texture wraps.
|
||||
/// Used to avoid referencing ImGuiScene.
|
||||
/// </summary>
|
||||
/// <remarks>If you want to implement this, see if you're actually wrapping an existing instance of
|
||||
/// <see cref="IDalamudTextureWrap"/>; if you are, then use <see cref="ForwardingTextureWrap"/>.</remarks>
|
||||
public interface IDalamudTextureWrap : IDisposable
|
||||
{
|
||||
/// <summary>Gets a texture handle suitable for direct use with ImGui functions.</summary>
|
||||
|
|
|
|||
|
|
@ -2,31 +2,19 @@ using Dalamud.Interface.Internal;
|
|||
|
||||
namespace Dalamud.Interface.Textures.Internal;
|
||||
|
||||
/// <summary>
|
||||
/// A texture wrap that ignores <see cref="IDisposable.Dispose"/> calls.
|
||||
/// </summary>
|
||||
internal sealed class DisposeSuppressingTextureWrap : IDalamudTextureWrap
|
||||
/// <summary>A texture wrap that ignores <see cref="IDisposable.Dispose"/> calls.</summary>
|
||||
internal class DisposeSuppressingTextureWrap : ForwardingTextureWrap
|
||||
{
|
||||
private readonly IDalamudTextureWrap innerWrap;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DisposeSuppressingTextureWrap"/> class.
|
||||
/// </summary>
|
||||
/// <summary>Initializes a new instance of the <see cref="DisposeSuppressingTextureWrap"/> class.</summary>
|
||||
/// <param name="wrap">The inner wrap.</param>
|
||||
public DisposeSuppressingTextureWrap(IDalamudTextureWrap wrap) => this.innerWrap = wrap;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IntPtr ImGuiHandle => this.innerWrap.ImGuiHandle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Width => this.innerWrap.Width;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Height => this.innerWrap.Height;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
protected override bool TryGetWrap(out IDalamudTextureWrap? wrap)
|
||||
{
|
||||
// suppressed
|
||||
wrap = this.innerWrap;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,46 +363,35 @@ internal abstract class SharedImmediateTexture
|
|||
}
|
||||
}
|
||||
|
||||
private sealed class NotOwnedTextureWrap : IDalamudTextureWrap
|
||||
/// <summary>Same with <see cref="DisposeSuppressingTextureWrap"/>, but with a custom implementation of
|
||||
/// <see cref="CreateWrapSharingLowLevelResource"/>.</summary>
|
||||
private sealed class NotOwnedTextureWrap : DisposeSuppressingTextureWrap
|
||||
{
|
||||
private readonly IDalamudTextureWrap innerWrap;
|
||||
private readonly IRefCountable owner;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="NotOwnedTextureWrap"/> class.</summary>
|
||||
/// <param name="wrap">The inner wrap.</param>
|
||||
/// <param name="owner">The reference counting owner.</param>
|
||||
public NotOwnedTextureWrap(IDalamudTextureWrap wrap, IRefCountable owner)
|
||||
: base(wrap)
|
||||
{
|
||||
this.innerWrap = wrap;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IntPtr ImGuiHandle => this.innerWrap.ImGuiHandle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Width => this.innerWrap.Width;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Height => this.innerWrap.Height;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IDalamudTextureWrap CreateWrapSharingLowLevelResource()
|
||||
public override IDalamudTextureWrap CreateWrapSharingLowLevelResource()
|
||||
{
|
||||
var wrap = this.GetWrap();
|
||||
this.owner.AddRef();
|
||||
return new RefCountableWrappingTextureWrap(this.innerWrap, this.owner);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
return new RefCountableWrappingTextureWrap(wrap, this.owner);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"{nameof(NotOwnedTextureWrap)}({this.owner})";
|
||||
}
|
||||
|
||||
private sealed class RefCountableWrappingTextureWrap : IDalamudTextureWrap
|
||||
/// <summary>Reference counting texture wrap, to be used with <see cref="RentAsync"/>.</summary>
|
||||
private sealed class RefCountableWrappingTextureWrap : ForwardingTextureWrap
|
||||
{
|
||||
private IDalamudTextureWrap? innerWrap;
|
||||
private IRefCountable? owner;
|
||||
|
|
@ -416,22 +405,11 @@ internal abstract class SharedImmediateTexture
|
|||
this.owner = owner;
|
||||
}
|
||||
|
||||
~RefCountableWrappingTextureWrap() => this.Dispose();
|
||||
/// <summary>Finalizes an instance of the <see cref="RefCountableWrappingTextureWrap"/> class.</summary>
|
||||
~RefCountableWrappingTextureWrap() => this.Dispose(false);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IntPtr ImGuiHandle => this.InnerWrapNonDisposed.ImGuiHandle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Width => this.InnerWrapNonDisposed.Width;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Height => this.InnerWrapNonDisposed.Height;
|
||||
|
||||
private IDalamudTextureWrap InnerWrapNonDisposed =>
|
||||
this.innerWrap ?? throw new ObjectDisposedException(nameof(RefCountableWrappingTextureWrap));
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IDalamudTextureWrap CreateWrapSharingLowLevelResource()
|
||||
public override IDalamudTextureWrap CreateWrapSharingLowLevelResource()
|
||||
{
|
||||
var ownerCopy = this.owner;
|
||||
var wrapCopy = this.innerWrap;
|
||||
|
|
@ -443,7 +421,13 @@ internal abstract class SharedImmediateTexture
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
public override string ToString() => $"{nameof(RefCountableWrappingTextureWrap)}({this.owner})";
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool TryGetWrap(out IDalamudTextureWrap? wrap) => (wrap = this.innerWrap) is not null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -455,32 +439,22 @@ internal abstract class SharedImmediateTexture
|
|||
// Note: do not dispose this; life of the wrap is managed by the owner.
|
||||
this.innerWrap = null;
|
||||
ownerCopy.Release();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"{nameof(RefCountableWrappingTextureWrap)}({this.owner})";
|
||||
}
|
||||
|
||||
/// <summary>A texture wrap that revives and waits for the underlying texture as needed on every access.</summary>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
private sealed class AvailableOnAccessTextureWrap : IDalamudTextureWrap
|
||||
private sealed class AvailableOnAccessTextureWrap : ForwardingTextureWrap
|
||||
{
|
||||
private readonly SharedImmediateTexture inner;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AvailableOnAccessTextureWrap"/> class.</summary>
|
||||
/// <param name="inner">The shared texture.</param>
|
||||
public AvailableOnAccessTextureWrap(SharedImmediateTexture inner) => this.inner = inner;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IntPtr ImGuiHandle => this.WaitGet().ImGuiHandle;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Width => this.WaitGet().Width;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Height => this.WaitGet().Height;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IDalamudTextureWrap CreateWrapSharingLowLevelResource()
|
||||
public override IDalamudTextureWrap CreateWrapSharingLowLevelResource()
|
||||
{
|
||||
this.inner.AddRef();
|
||||
try
|
||||
|
|
@ -506,22 +480,18 @@ internal abstract class SharedImmediateTexture
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => $"{nameof(AvailableOnAccessTextureWrap)}({this.inner})";
|
||||
|
||||
private IDalamudTextureWrap WaitGet()
|
||||
/// <inheritdoc/>
|
||||
protected override bool TryGetWrap(out IDalamudTextureWrap? wrap)
|
||||
{
|
||||
if (this.inner.TryGetWrapCore(out var t, out _))
|
||||
return t;
|
||||
wrap = t;
|
||||
|
||||
this.inner.UnderlyingWrap?.Wait();
|
||||
return this.inner.nonOwningWrap ?? Service<DalamudAssetManager>.Get().Empty4X4;
|
||||
wrap = this.inner.nonOwningWrap ?? Service<DalamudAssetManager>.Get().Empty4X4;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ internal sealed class ViewportTextureWrap : IDalamudTextureWrap, IDeferredDispos
|
|||
_ = this.FirstUpdateTask.Exception;
|
||||
this.tex.Reset();
|
||||
this.srv.Reset();
|
||||
this.rtv.Reset();
|
||||
}
|
||||
|
||||
private static unsafe ComPtr<ID3D11Texture2D> GetImGuiViewportBackBuffer(uint viewportId)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue