ISIT: remove api9 compat, IDAM: make Empty4X4 transparent (#1877)

* Remove api9 compat from texture stuff

* Make Empty4X4 actually transparent
This commit is contained in:
srkizer 2024-07-04 01:51:23 +09:00 committed by GitHub
parent bdc4c226d4
commit 7a90921358
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 7 additions and 117 deletions

View file

@ -14,20 +14,20 @@ public enum DalamudAsset
/// <summary>
/// Nothing.
/// </summary>
[DalamudAsset(DalamudAssetPurpose.Empty, data: new byte[0])]
[DalamudAsset(DalamudAssetPurpose.Empty, data: [])]
Unspecified = 0,
/// <summary>
/// <see cref="DalamudAssetPurpose.TextureFromRaw"/>: The fallback empty texture.
/// <see cref="DalamudAssetPurpose.TextureFromRaw"/>: A texture that is completely transparent.
/// </summary>
[DalamudAsset(DalamudAssetPurpose.TextureFromRaw, data: new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 })]
[DalamudAsset(DalamudAssetPurpose.TextureFromRaw, data: [0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF])]
[DalamudAssetRawTexture(4, 4, DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM, 8)]
Empty4X4 = 1000,
/// <summary>
/// <see cref="DalamudAssetPurpose.TextureFromRaw"/>: The fallback empty texture.
/// <see cref="DalamudAssetPurpose.TextureFromRaw"/>: A texture that is completely white.
/// </summary>
[DalamudAsset(DalamudAssetPurpose.TextureFromRaw, data: new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 })]
[DalamudAsset(DalamudAssetPurpose.TextureFromRaw, data: [0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0])]
[DalamudAssetRawTexture(4, 4, DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM, 8)]
White4X4 = 1014,

View file

@ -525,7 +525,6 @@ internal class TexWidget : IDataWindowWidget
ImGui.TableSetupColumn("Source", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableSetupColumn("RefCount", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("RefCount__").X);
ImGui.TableSetupColumn("SelfRef", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("00.000___").X);
ImGui.TableSetupColumn("CanRevive", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize("CanRevive__").X);
ImGui.TableSetupColumn(
"Actions",
ImGuiTableColumnFlags.WidthFixed,
@ -582,9 +581,6 @@ internal class TexWidget : IDataWindowWidget
ImGui.TableNextColumn();
this.TextCopiable(remain <= 0 ? "-" : $"{remain:00.000}", true, true);
ImGui.TableNextColumn();
ImGui.TextUnformatted(texture.HasRevivalPossibility ? "Yes" : "No");
ImGui.TableNextColumn();
if (ImGuiComponents.IconButton(FontAwesomeIcon.Save))
{

View file

@ -29,7 +29,6 @@ internal abstract class SharedImmediateTexture
private bool resourceReleased;
private int refCount;
private long selfReferenceExpiry;
private IDalamudTextureWrap? availableOnAccessWrapForApi9;
private CancellationTokenSource? cancellationTokenSource;
private NotOwnedTextureWrap? nonOwningWrap;
@ -67,10 +66,6 @@ internal abstract class SharedImmediateTexture
/// <summary>Gets the source path. Debug use only.</summary>
public string SourcePathForDebug { get; }
/// <summary>Gets a value indicating whether this instance of <see cref="SharedImmediateTexture"/> supports revival.
/// </summary>
public bool HasRevivalPossibility => this.RevivalPossibility?.TryGetTarget(out _) is true;
/// <summary>Gets or sets the underlying texture wrap.</summary>
public Task<IDalamudTextureWrap>? UnderlyingWrap { get; set; }
@ -91,16 +86,6 @@ internal abstract class SharedImmediateTexture
/// Intended to be called from implementors' constructors and <see cref="LoadUnderlyingWrap"/>.</summary>
protected CancellationToken LoadCancellationToken => this.cancellationTokenSource?.Token ?? default;
/// <summary>Gets or sets a weak reference to an object that demands this objects to be alive.</summary>
/// <remarks>
/// TextureManager must keep references to all shared textures, regardless of whether textures' contents are
/// flushed, because API9 functions demand that the returned textures may be stored so that they can used anytime,
/// possibly reviving a dead-inside object. The object referenced by this property is given out to such use cases,
/// which gets created from <see cref="GetAvailableOnAccessWrapForApi9"/>. If this no longer points to an alive
/// object, and <see cref="availableOnAccessWrapForApi9"/> is null, then this object is not used from API9 use case.
/// </remarks>
private WeakReference<IDalamudTextureWrap>? RevivalPossibility { get; set; }
/// <inheritdoc/>
public int AddRef() => this.TryAddRef(out var newRefCount) switch
{
@ -180,7 +165,6 @@ internal abstract class SharedImmediateTexture
if (exp != Interlocked.CompareExchange(ref this.selfReferenceExpiry, SelfReferenceExpiryExpired, exp))
continue;
this.availableOnAccessWrapForApi9 = null;
return this.Release();
}
}
@ -255,35 +239,6 @@ internal abstract class SharedImmediateTexture
return new RefCountableWrappingTextureWrap(dtw, this);
}
/// <summary>Gets a texture wrap which ensures that the values will be populated on access.</summary>
/// <returns>The texture wrap, or null if failed.</returns>
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
public IDalamudTextureWrap? GetAvailableOnAccessWrapForApi9()
{
if (this.availableOnAccessWrapForApi9 is not null)
return this.availableOnAccessWrapForApi9;
lock (this.reviveLock)
{
if (this.availableOnAccessWrapForApi9 is not null)
return this.availableOnAccessWrapForApi9;
if (this.RevivalPossibility?.TryGetTarget(out this.availableOnAccessWrapForApi9) is true)
return this.availableOnAccessWrapForApi9;
var newRefTask = this.RentAsync(this.LoadCancellationToken);
newRefTask.Wait(this.LoadCancellationToken);
if (!newRefTask.IsCompletedSuccessfully)
return null;
newRefTask.Result.Dispose();
this.availableOnAccessWrapForApi9 = new AvailableOnAccessTextureWrap(this);
this.RevivalPossibility = new(this.availableOnAccessWrapForApi9);
}
return this.availableOnAccessWrapForApi9;
}
/// <summary>Adds a plugin to <see cref="ownerPlugins"/>, in a thread-safe way.</summary>
/// <param name="plugin">The plugin to add.</param>
public void AddOwnerPlugin(LocalPlugin plugin)
@ -383,9 +338,6 @@ internal abstract class SharedImmediateTexture
throw;
}
if (this.RevivalPossibility?.TryGetTarget(out var target) is true)
this.availableOnAccessWrapForApi9 = target;
Interlocked.Increment(ref this.refCount);
this.resourceReleased = false;
return IRefCountable.RefCountResult.StillAlive;
@ -468,12 +420,6 @@ internal abstract class SharedImmediateTexture
public Task<IDalamudTextureWrap> RentAsync(CancellationToken cancellationToken = default) =>
this.inner.RentAsync(cancellationToken);
/// <inheritdoc cref="SharedImmediateTexture.GetAvailableOnAccessWrapForApi9"/>
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IDalamudTextureWrap? GetAvailableOnAccessWrapForApi9() =>
this.inner.GetAvailableOnAccessWrapForApi9();
/// <inheritdoc cref="SharedImmediateTexture.AddOwnerPlugin"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddOwnerPlugin(LocalPlugin plugin) =>
@ -562,56 +508,4 @@ internal abstract class SharedImmediateTexture
}
}
}
/// <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 : 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 override IDalamudTextureWrap CreateWrapSharingLowLevelResource()
{
this.inner.AddRef();
try
{
if (!this.inner.TryGetWrapCore(out var wrap, out _))
{
this.inner.UnderlyingWrap?.Wait();
if (!this.inner.TryGetWrapCore(out wrap, out _))
{
// Calling dispose on Empty4x4 is a no-op, so we can just return that.
this.inner.Release();
return Service<DalamudAssetManager>.Get().Empty4X4;
}
}
return new RefCountableWrappingTextureWrap(wrap, this.inner);
}
catch
{
this.inner.Release();
throw;
}
}
/// <inheritdoc/>
public override string ToString() => $"{nameof(AvailableOnAccessTextureWrap)}({this.inner})";
/// <inheritdoc/>
protected override bool TryGetWrap(out IDalamudTextureWrap? wrap)
{
if (this.inner.TryGetWrapCore(out var t, out _))
wrap = t;
this.inner.UnderlyingWrap?.Wait();
wrap = this.inner.nonOwningWrap ?? Service<DalamudAssetManager>.Get().Empty4X4;
return true;
}
}
}

View file

@ -159,7 +159,7 @@ internal sealed partial class TextureManager
{
if (this.gameDict.TryRemove(path, out var r))
{
if (r.ReleaseSelfReference(true) != 0 || r.HasRevivalPossibility)
if (r.ReleaseSelfReference(true) != 0)
{
lock (this.invalidatedTextures)
this.invalidatedTextures.Add(r);
@ -201,7 +201,7 @@ internal sealed partial class TextureManager
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool TextureFinalReleasePredicate(SharedImmediateTexture v) =>
v.ContentQueried && v.ReleaseSelfReference(false) == 0 && !v.HasRevivalPossibility;
v.ContentQueried && v.ReleaseSelfReference(false) == 0;
}
}
}