Track shared textures

This commit is contained in:
Soreepeong 2024-03-05 01:37:46 +09:00
parent 7f12e3f3da
commit e9b903b2a7
4 changed files with 112 additions and 39 deletions

View file

@ -1,9 +1,12 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Interface.Internal;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Storage.Assets;
using Dalamud.Utility;
@ -42,6 +45,9 @@ internal abstract class SharedImmediateTexture
this.FirstRequestedTick = this.LatestRequestedTick = Environment.TickCount64;
}
/// <summary>Gets the list of owner plugins.</summary>
public List<LocalPlugin> OwnerPlugins { get; } = new();
/// <summary>Gets the instance ID. Debug use only.</summary>
public long InstanceIdForDebug { get; }
@ -274,6 +280,26 @@ internal abstract class SharedImmediateTexture
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)
{
lock (this.OwnerPlugins)
{
if (!this.OwnerPlugins.Contains(plugin))
{
this.OwnerPlugins.Add(plugin);
this.UnderlyingWrap?.ContinueWith(
r =>
{
if (r.IsCompletedSuccessfully)
Service<TextureManager>.Get().Blame(r.Result, plugin);
},
default(CancellationToken));
}
}
}
/// <inheritdoc/>
public override string ToString() => $"{this.GetType().Name}#{this.InstanceIdForDebug}({this.SourcePathForDebug})";
@ -285,11 +311,31 @@ internal abstract class SharedImmediateTexture
}
/// <summary>Attempts to restore the reference to this texture.</summary>
protected void LoadUnderlyingWrap() =>
this.UnderlyingWrap = Service<TextureManager>.Get().DynamicPriorityTextureLoader.LoadAsync(
this,
this.CreateTextureAsync,
this.LoadCancellationToken);
protected void LoadUnderlyingWrap()
{
int addLen;
lock (this.OwnerPlugins)
{
this.UnderlyingWrap = Service<TextureManager>.Get().DynamicPriorityTextureLoader.LoadAsync(
this,
this.CreateTextureAsync,
this.LoadCancellationToken);
addLen = this.OwnerPlugins.Count;
}
if (addLen == 0)
return;
this.UnderlyingWrap.ContinueWith(
r =>
{
if (!r.IsCompletedSuccessfully)
return;
foreach (var op in this.OwnerPlugins.Take(addLen))
Service<TextureManager>.Get().Blame(r.Result, op);
},
default(CancellationToken));
}
/// <summary>Creates the texture.</summary>
/// <param name="cancellationToken">The cancellation token.</param>

View file

@ -48,6 +48,16 @@ internal sealed partial class TextureManager
if (!this.dalamudConfiguration.UseTexturePluginTracking)
return textureWrap;
try
{
if (textureWrap.ImGuiHandle == nint.Zero)
return textureWrap;
}
catch (ObjectDisposedException)
{
return textureWrap;
}
using var wrapAux = new WrapAux(textureWrap, true);
var blame = BlameTag.From(wrapAux.ResPtr, out var isNew);
@ -75,6 +85,16 @@ internal sealed partial class TextureManager
if (!this.dalamudConfiguration.UseTexturePluginTracking)
return textureWrap;
try
{
if (textureWrap.ImGuiHandle == nint.Zero)
return textureWrap;
}
catch (ObjectDisposedException)
{
return textureWrap;
}
using var wrapAux = new WrapAux(textureWrap, true);
var blame = BlameTag.From(wrapAux.ResPtr, out var isNew);
blame.Name = name;

View file

@ -14,43 +14,42 @@ internal sealed partial class TextureManagerPluginScoped
/// <inheritdoc/>
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[Obsolete("See interface definition.")]
public IDalamudTextureWrap? GetIcon(
string? ITextureProvider.GetIconPath(uint iconId, ITextureProvider.IconFlags flags, ClientLanguage? language)
=> this.TryGetIconPath(
new(
iconId,
(flags & ITextureProvider.IconFlags.ItemHighQuality) != 0,
(flags & ITextureProvider.IconFlags.HiRes) != 0,
language),
out var path)
? path
: null;
/// <inheritdoc/>
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[Obsolete("See interface definition.")]
IDalamudTextureWrap? ITextureProvider.GetIcon(
uint iconId,
ITextureProvider.IconFlags flags = ITextureProvider.IconFlags.HiRes,
ClientLanguage? language = null,
bool keepAlive = false)
{
throw new NotImplementedException();
}
ITextureProvider.IconFlags flags,
ClientLanguage? language,
bool keepAlive) =>
this.ManagerOrThrow.Shared.GetFromGameIcon(
new(
iconId,
(flags & ITextureProvider.IconFlags.ItemHighQuality) != 0,
(flags & ITextureProvider.IconFlags.HiRes) != 0,
language))
.GetAvailableOnAccessWrapForApi9();
/// <inheritdoc/>
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[Obsolete("See interface definition.")]
public string? GetIconPath(
uint iconId,
ITextureProvider.IconFlags flags = ITextureProvider.IconFlags.HiRes,
ClientLanguage? language = null)
{
throw new NotImplementedException();
}
IDalamudTextureWrap? ITextureProvider.GetTextureFromGame(string path, bool keepAlive) =>
this.ManagerOrThrow.Shared.GetFromGame(path).GetAvailableOnAccessWrapForApi9();
/// <inheritdoc/>
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[Obsolete("See interface definition.")]
public IDalamudTextureWrap? GetTextureFromGame(
string path,
bool keepAlive = false)
{
throw new NotImplementedException();
}
/// <inheritdoc/>
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[Obsolete("See interface definition.")]
public IDalamudTextureWrap? GetTextureFromFile(
FileInfo file,
bool keepAlive = false)
{
throw new NotImplementedException();
}
IDalamudTextureWrap? ITextureProvider.GetTextureFromFile(FileInfo file, bool keepAlive) =>
this.ManagerOrThrow.Shared.GetFromFile(file.FullName).GetAvailableOnAccessWrapForApi9();
}

View file

@ -257,25 +257,33 @@ internal sealed partial class TextureManagerPluginScoped
/// <inheritdoc/>
public ISharedImmediateTexture GetFromGameIcon(in GameIconLookup lookup)
{
return this.ManagerOrThrow.Shared.GetFromGameIcon(lookup);
var shared = this.ManagerOrThrow.Shared.GetFromGameIcon(lookup);
shared.AddOwnerPlugin(this.plugin);
return shared;
}
/// <inheritdoc/>
public ISharedImmediateTexture GetFromGame(string path)
{
return this.ManagerOrThrow.Shared.GetFromGame(path);
var shared = this.ManagerOrThrow.Shared.GetFromGame(path);
shared.AddOwnerPlugin(this.plugin);
return shared;
}
/// <inheritdoc/>
public ISharedImmediateTexture GetFromFile(string path)
{
return this.ManagerOrThrow.Shared.GetFromFile(path);
var shared = this.ManagerOrThrow.Shared.GetFromFile(path);
shared.AddOwnerPlugin(this.plugin);
return shared;
}
/// <inheritdoc/>
public ISharedImmediateTexture GetFromManifestResource(Assembly assembly, string name)
{
return this.ManagerOrThrow.Shared.GetFromManifestResource(assembly, name);
var shared = this.ManagerOrThrow.Shared.GetFromManifestResource(assembly, name);
shared.AddOwnerPlugin(this.plugin);
return shared;
}
/// <inheritdoc/>