Skip to content

Commit

Permalink
ISIT: remove api9 compat, IDAM: make Empty4X4 transparent (#1877)
Browse files Browse the repository at this point in the history
* Remove api9 compat from texture stuff

* Make Empty4X4 actually transparent
  • Loading branch information
Soreepeong authored Jul 3, 2024
1 parent bdc4c22 commit 7a90921
Show file tree
Hide file tree
Showing 4 changed files with 7 additions and 117 deletions.
10 changes: 5 additions & 5 deletions Dalamud/DalamudAsset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
4 changes: 0 additions & 4 deletions Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,6 @@ private unsafe void DrawLoadedTextures(ICollection<SharedImmediateTexture> textu
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,
Expand Down Expand Up @@ -582,9 +581,6 @@ private unsafe void DrawLoadedTextures(ICollection<SharedImmediateTexture> textu
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))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -67,10 +66,6 @@ protected SharedImmediateTexture(string sourcePathForDebug)
/// <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; }

Expand All @@ -91,16 +86,6 @@ protected SharedImmediateTexture(string sourcePathForDebug)
/// 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
{
Expand Down Expand Up @@ -180,7 +165,6 @@ public int ReleaseSelfReference(bool immediate)
if (exp != Interlocked.CompareExchange(ref this.selfReferenceExpiry, SelfReferenceExpiryExpired, exp))
continue;

this.availableOnAccessWrapForApi9 = null;
return this.Release();
}
}
Expand Down Expand Up @@ -255,35 +239,6 @@ public async Task<IDalamudTextureWrap> RentAsync(CancellationToken cancellationT
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)
Expand Down Expand Up @@ -383,9 +338,6 @@ private IRefCountable.RefCountResult TryAddRef(out int newRefCount)
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;
Expand Down Expand Up @@ -468,12 +420,6 @@ public bool TryGetWrap([NotNullWhen(true)] out IDalamudTextureWrap? texture, out
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) =>
Expand Down Expand Up @@ -562,56 +508,4 @@ protected override void Dispose(bool disposing)
}
}
}

/// <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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public void FlushFromGameCache(string path)
{
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);
Expand Down Expand Up @@ -201,7 +201,7 @@ static void RemoveFinalReleased<T>(ConcurrentDictionary<T, SharedImmediateTextur

[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool TextureFinalReleasePredicate(SharedImmediateTexture v) =>
v.ContentQueried && v.ReleaseSelfReference(false) == 0 && !v.HasRevivalPossibility;
v.ContentQueried && v.ReleaseSelfReference(false) == 0;
}
}
}

0 comments on commit 7a90921

Please sign in to comment.