From 20717cce3da1514ee8515a435a75653b76c5b5a6 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Tue, 21 May 2024 09:27:51 +0900 Subject: [PATCH] more --- .../FilePathNotificationIcon.cs | 15 ++- .../GamePathNotificationIcon.cs | 6 +- .../Interface/Internal/DalamudInterface.cs | 3 +- .../Windows/Data/Widgets/ImGuiWidget.cs | 10 +- .../Windows/Data/Widgets/TexWidget.cs | 34 +------ .../PluginInstaller/PluginInstallerWindow.cs | 1 + .../TextureManager.FromExistingTexture.cs | 99 ++++++++----------- .../Textures/Internal/TextureManager.cs | 53 +++++++++- .../Internal/TextureManagerPluginScoped.cs | 20 +++- .../Textures/RawImageSpecification.cs | 7 ++ Dalamud/Interface/UiBuilder.cs | 84 ---------------- Dalamud/Plugin/Services/ITextureProvider.cs | 15 ++- .../TerraFxCom/TerraFxD3D11Extensions.cs | 65 ++++++++++++ 13 files changed, 213 insertions(+), 199 deletions(-) create mode 100644 Dalamud/Utility/TerraFxCom/TerraFxD3D11Extensions.cs diff --git a/Dalamud/Interface/ImGuiNotification/Internal/NotificationIcon/FilePathNotificationIcon.cs b/Dalamud/Interface/ImGuiNotification/Internal/NotificationIcon/FilePathNotificationIcon.cs index 3aa712160..fe68fa7ba 100644 --- a/Dalamud/Interface/ImGuiNotification/Internal/NotificationIcon/FilePathNotificationIcon.cs +++ b/Dalamud/Interface/ImGuiNotification/Internal/NotificationIcon/FilePathNotificationIcon.cs @@ -1,7 +1,6 @@ -using System.IO; using System.Numerics; -using Dalamud.Interface.Internal; +using Dalamud.Interface.Textures.Internal; namespace Dalamud.Interface.ImGuiNotification.Internal.NotificationIcon; @@ -9,26 +8,26 @@ namespace Dalamud.Interface.ImGuiNotification.Internal.NotificationIcon; /// If there was no texture loaded for any reason, the plugin icon will be displayed instead. internal class FilePathNotificationIcon : INotificationIcon { - private readonly FileInfo fileInfo; + private readonly string filePath; /// Initializes a new instance of the class. /// The path to a .tex file inside the game resources. - public FilePathNotificationIcon(string filePath) => this.fileInfo = new(filePath); + public FilePathNotificationIcon(string filePath) => this.filePath = new(filePath); /// public bool DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color) => NotificationUtilities.DrawIconFrom( minCoord, maxCoord, - Service.Get().GetTextureFromFile(this.fileInfo)); + Service.Get().Shared.GetFromFile(this.filePath).GetWrapOrDefault()); /// public override bool Equals(object? obj) => - obj is FilePathNotificationIcon r && r.fileInfo.FullName == this.fileInfo.FullName; + obj is FilePathNotificationIcon r && r.filePath == this.filePath; /// - public override int GetHashCode() => HashCode.Combine(this.GetType().GetHashCode(), this.fileInfo.FullName); + public override int GetHashCode() => HashCode.Combine(this.GetType().GetHashCode(), this.filePath); /// - public override string ToString() => $"{nameof(FilePathNotificationIcon)}({this.fileInfo.FullName})"; + public override string ToString() => $"{nameof(FilePathNotificationIcon)}({this.filePath})"; } diff --git a/Dalamud/Interface/ImGuiNotification/Internal/NotificationIcon/GamePathNotificationIcon.cs b/Dalamud/Interface/ImGuiNotification/Internal/NotificationIcon/GamePathNotificationIcon.cs index e0699e1b6..93d515ecc 100644 --- a/Dalamud/Interface/ImGuiNotification/Internal/NotificationIcon/GamePathNotificationIcon.cs +++ b/Dalamud/Interface/ImGuiNotification/Internal/NotificationIcon/GamePathNotificationIcon.cs @@ -1,7 +1,6 @@ using System.Numerics; -using Dalamud.Interface.Internal; -using Dalamud.Plugin.Services; +using Dalamud.Interface.Textures.Internal; namespace Dalamud.Interface.ImGuiNotification.Internal.NotificationIcon; @@ -13,7 +12,6 @@ internal class GamePathNotificationIcon : INotificationIcon /// Initializes a new instance of the class. /// The path to a .tex file inside the game resources. - /// Use to get the game path from icon IDs. public GamePathNotificationIcon(string gamePath) => this.gamePath = gamePath; /// @@ -21,7 +19,7 @@ internal class GamePathNotificationIcon : INotificationIcon NotificationUtilities.DrawIconFrom( minCoord, maxCoord, - Service.Get().GetTextureFromGame(this.gamePath)); + Service.Get().Shared.GetFromGame(this.gamePath).GetWrapOrDefault()); /// public override bool Equals(object? obj) => obj is GamePathNotificationIcon r && r.gamePath == this.gamePath; diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index a9e1a0b0c..da5570848 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -19,8 +19,9 @@ using Dalamud.Hooking; using Dalamud.Interface.Animation.EasingFunctions; using Dalamud.Interface.Colors; using Dalamud.Interface.ImGuiFileDialog; +using Dalamud.Interface.ImGuiNotification; +using Dalamud.Interface.ImGuiNotification.Internal; using Dalamud.Interface.Internal.ManagedAsserts; -using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Internal.Windows; using Dalamud.Interface.Internal.Windows.Data; using Dalamud.Interface.Internal.Windows.PluginInstaller; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs index 47f0dde64..c1a44b583 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Dalamud.Game.Text; using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification.Internal; +using Dalamud.Interface.Textures.Internal; using Dalamud.Interface.Windowing; using Dalamud.Storage.Assets; using Dalamud.Utility; @@ -230,12 +231,14 @@ internal class ImGuiWidget : IDataWindowWidget break; case 7: n.SetIconTexture( - DisposeLoggingTextureWrap.Wrap(tm.GetTextureFromGame(this.notificationTemplate.IconText)), + DisposeLoggingTextureWrap.Wrap( + tm.Shared.GetFromGame(this.notificationTemplate.IconText).GetWrapOrDefault()), this.notificationTemplate.LeaveTexturesOpen); break; case 8: n.SetIconTexture( - DisposeLoggingTextureWrap.Wrap(tm.GetTextureFromFile(new(this.notificationTemplate.IconText))), + DisposeLoggingTextureWrap.Wrap( + tm.Shared.GetFromFile(this.notificationTemplate.IconText).GetWrapOrDefault()), this.notificationTemplate.LeaveTexturesOpen); break; } @@ -306,7 +309,8 @@ internal class ImGuiWidget : IDataWindowWidget foreach (var n in this.notifications) { var i = (uint)Random.Shared.NextInt64(0, 200000); - n.IconTexture = DisposeLoggingTextureWrap.Wrap(Service.Get().GetIcon(i)); + n.IconTexture = DisposeLoggingTextureWrap.Wrap( + Service.Get().Shared.GetFromGameIcon(new(i)).GetWrapOrDefault()); } } } diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs index 4713022e6..85b0dc00d 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/TexWidget.cs @@ -8,7 +8,8 @@ using System.Threading.Tasks; using Dalamud.Configuration.Internal; using Dalamud.Interface.Components; -using Dalamud.Interface.Internal.Notifications; +using Dalamud.Interface.ImGuiNotification; +using Dalamud.Interface.ImGuiNotification.Internal; using Dalamud.Interface.Textures; using Dalamud.Interface.Textures.Internal.SharedImmediateTextures; using Dalamud.Interface.Utility; @@ -90,8 +91,6 @@ internal class TexWidget : IDataWindowWidget /// public bool Ready { get; set; } - private ITextureProvider TextureManagerForApi9 => this.textureManager!; - /// public void Load() { @@ -634,17 +633,6 @@ internal class TexWidget : IDataWindowWidget ImGui.InputText("Icon ID", ref this.iconId, 32); ImGui.Checkbox("HQ Item", ref this.hq); ImGui.Checkbox("Hi-Res", ref this.hiRes); -#pragma warning disable CS0618 // Type or member is obsolete - if (ImGui.Button("Load Icon (API9)")) - { - var flags = ITextureProvider.IconFlags.None; - if (this.hq) - flags |= ITextureProvider.IconFlags.ItemHighQuality; - if (this.hiRes) - flags |= ITextureProvider.IconFlags.HiRes; - this.addedTextures.Add(new(Api9: this.TextureManagerForApi9.GetIcon(uint.Parse(this.iconId), flags))); - } -#pragma warning restore CS0618 // Type or member is obsolete ImGui.SameLine(); if (ImGui.Button("Load Icon (Async)")) @@ -668,11 +656,6 @@ internal class TexWidget : IDataWindowWidget { ImGui.InputText("Tex Path", ref this.inputTexPath, 255); -#pragma warning disable CS0618 // Type or member is obsolete - if (ImGui.Button("Load Tex (API9)")) - this.addedTextures.Add(new(Api9: this.TextureManagerForApi9.GetTextureFromGame(this.inputTexPath))); -#pragma warning restore CS0618 // Type or member is obsolete - ImGui.SameLine(); if (ImGui.Button("Load Tex (Async)")) this.addedTextures.Add(new(Api10: this.textureManager.Shared.GetFromGame(this.inputTexPath).RentAsync())); @@ -688,11 +671,6 @@ internal class TexWidget : IDataWindowWidget { ImGui.InputText("File Path", ref this.inputFilePath, 255); -#pragma warning disable CS0618 // Type or member is obsolete - if (ImGui.Button("Load File (API9)")) - this.addedTextures.Add(new(Api9: this.TextureManagerForApi9.GetTextureFromFile(new(this.inputFilePath)))); -#pragma warning restore CS0618 // Type or member is obsolete - ImGui.SameLine(); if (ImGui.Button("Load File (Async)")) this.addedTextures.Add(new(Api10: this.textureManager.Shared.GetFromFile(this.inputFilePath).RentAsync())); @@ -929,7 +907,6 @@ internal class TexWidget : IDataWindowWidget private record TextureEntry( IDalamudTextureWrap? SharedResource = null, - IDalamudTextureWrap? Api9 = null, Task? Api10 = null, GameIconLookup? Api10ImmGameIcon = null, string? Api10ImmGamePath = null, @@ -943,7 +920,6 @@ internal class TexWidget : IDataWindowWidget public void Dispose() { this.SharedResource?.Dispose(); - this.Api9?.Dispose(); _ = this.Api10?.ToContentDisposedTask(); } @@ -951,8 +927,6 @@ internal class TexWidget : IDataWindowWidget { if (this.SharedResource is not null) return "Unknown error"; - if (this.Api9 is not null) - return "Unknown error"; if (this.Api10 is not null) { return !this.Api10.IsCompleted @@ -975,8 +949,6 @@ internal class TexWidget : IDataWindowWidget { if (this.SharedResource is not null) return this.SharedResource; - if (this.Api9 is not null) - return this.Api9; if (this.Api10 is not null) return this.Api10.IsCompletedSuccessfully ? this.Api10.Result : null; if (this.Api10ImmGameIcon is not null) @@ -1014,8 +986,6 @@ internal class TexWidget : IDataWindowWidget { if (this.SharedResource is not null) return $"{nameof(this.SharedResource)}: {this.SharedResource}"; - if (this.Api9 is not null) - return $"{nameof(this.Api9)}: {this.Api9}"; if (this.Api10 is { IsCompletedSuccessfully: true }) return $"{nameof(this.Api10)}: {this.Api10.Result}"; if (this.Api10 is not null) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index 02b5f22a5..c7456db2d 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -17,6 +17,7 @@ using Dalamud.Interface.Colors; using Dalamud.Interface.Components; using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification.Internal; +using Dalamud.Interface.Textures.Internal; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.FromExistingTexture.cs b/Dalamud/Interface/Textures/Internal/TextureManager.FromExistingTexture.cs index 7e9b209cf..eee8c6e52 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManager.FromExistingTexture.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManager.FromExistingTexture.cs @@ -7,6 +7,7 @@ using Dalamud.Interface.Textures.TextureWraps.Internal; using Dalamud.Plugin.Internal.Types; using Dalamud.Plugin.Services; using Dalamud.Utility; +using Dalamud.Utility.TerraFxCom; using TerraFX.Interop.DirectX; using TerraFX.Interop.Windows; @@ -62,18 +63,11 @@ internal sealed partial class TextureManager unsafe { - var srvDesc = new D3D11_SHADER_RESOURCE_VIEW_DESC( + using var srv = this.device.CreateShaderResourceView( tex, - D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D); - using var srv = default(ComPtr); - this.device.Get()->CreateShaderResourceView( - (ID3D11Resource*)tex.Get(), - &srvDesc, - srv.GetAddressOf()) - .ThrowOnError(); + new(tex.Get(), D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D)); - var desc = default(D3D11_TEXTURE2D_DESC); - tex.Get()->GetDesc(&desc); + var desc = tex.GetDesc(); var outWrap = new UnknownTextureWrap( (IUnknown*)srv.Get(), @@ -126,15 +120,10 @@ internal sealed partial class TextureManager TextureModificationArgs args = default, CancellationToken cancellationToken = default) { - using var tex2D = wrapAux.NewTexRef(); - if (!args.IsCompleteSourceCopy(wrapAux.Desc)) - { - using var tmp = await this.NoThrottleCreateFromExistingTextureAsync(wrapAux, args); - unsafe - { - tex2D.Swap(&tmp); - } - } + using var tex2D = + args.IsCompleteSourceCopy(wrapAux.Desc) + ? wrapAux.NewTexRef() + : await this.NoThrottleCreateFromExistingTextureAsync(wrapAux, args); cancellationToken.ThrowIfCancellationRequested(); @@ -147,32 +136,29 @@ internal sealed partial class TextureManager { cancellationToken.ThrowIfCancellationRequested(); - D3D11_TEXTURE2D_DESC desc; - tex2D.Get()->GetDesc(&desc); + var desc = tex2D.GetDesc(); using var device = default(ComPtr); tex2D.Get()->GetDevice(device.GetAddressOf()); using var context = default(ComPtr); device.Get()->GetImmediateContext(context.GetAddressOf()); - using var tmpTex = default(ComPtr); - if ((desc.CPUAccessFlags & (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ) == 0) - { - var tmpTexDesc = desc with - { - MipLevels = 1, - ArraySize = 1, - SampleDesc = new(1, 0), - Usage = D3D11_USAGE.D3D11_USAGE_STAGING, - BindFlags = 0u, - CPUAccessFlags = (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ, - MiscFlags = 0u, - }; - device.Get()->CreateTexture2D(&tmpTexDesc, null, tmpTex.GetAddressOf()).ThrowOnError(); - context.Get()->CopyResource((ID3D11Resource*)tmpTex.Get(), (ID3D11Resource*)tex2D.Get()); - - cancellationToken.ThrowIfCancellationRequested(); - } + using var tmpTex = + (desc.CPUAccessFlags & (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ) == 0 + ? device.CreateTexture2D( + desc with + { + MipLevels = 1, + ArraySize = 1, + SampleDesc = new(1, 0), + Usage = D3D11_USAGE.D3D11_USAGE_STAGING, + BindFlags = 0u, + CPUAccessFlags = (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ, + MiscFlags = 0u, + }, + tex2D) + : default; + cancellationToken.ThrowIfCancellationRequested(); var mapWhat = (ID3D11Resource*)(tmpTex.IsEmpty() ? tex2D.Get() : tmpTex.Get()); @@ -205,25 +191,22 @@ internal sealed partial class TextureManager if (args.NewHeight == 0) args = args with { NewHeight = (int)MathF.Round((args.Uv1Effective.Y - args.Uv0.Y) * wrapAux.Desc.Height) }; - using var tex2DCopyTemp = default(ComPtr); - unsafe - { - var tex2DCopyTempDesc = new D3D11_TEXTURE2D_DESC - { - Width = (uint)args.NewWidth, - Height = (uint)args.NewHeight, - MipLevels = 1, - ArraySize = 1, - Format = args.Format, - SampleDesc = new(1, 0), - Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT, - BindFlags = (uint)(D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE | - D3D11_BIND_FLAG.D3D11_BIND_RENDER_TARGET), - CPUAccessFlags = 0u, - MiscFlags = 0u, - }; - this.device.Get()->CreateTexture2D(&tex2DCopyTempDesc, null, tex2DCopyTemp.GetAddressOf()).ThrowOnError(); - } + using var tex2DCopyTemp = + this.device.CreateTexture2D( + new() + { + Width = (uint)args.NewWidth, + Height = (uint)args.NewHeight, + MipLevels = 1, + ArraySize = 1, + Format = args.Format, + SampleDesc = new(1, 0), + Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT, + BindFlags = (uint)(D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE | + D3D11_BIND_FLAG.D3D11_BIND_RENDER_TARGET), + CPUAccessFlags = 0u, + MiscFlags = 0u, + }); await this.RunDuringPresent(() => DrawSourceTextureToTarget(wrapAux, args, this.SimpleDrawer, tex2DCopyTemp)); diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.cs b/Dalamud/Interface/Textures/Internal/TextureManager.cs index 7510ec7dc..9dffc6853 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManager.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManager.cs @@ -12,6 +12,7 @@ using Dalamud.Interface.Textures.TextureWraps.Internal; using Dalamud.Logging.Internal; using Dalamud.Plugin.Services; using Dalamud.Utility; +using Dalamud.Utility.TerraFxCom; using Lumina.Data; using Lumina.Data.Files; @@ -24,8 +25,7 @@ namespace Dalamud.Interface.Textures.Internal; /// Service responsible for loading and disposing ImGui texture wraps. [ServiceManager.EarlyLoadedService] internal sealed partial class TextureManager - : IServiceType, - IDisposable, + : IInternalDisposableService, ITextureProvider, ITextureSubstitutionProvider, ITextureReadbackProvider @@ -101,7 +101,7 @@ internal sealed partial class TextureManager } /// - public void Dispose() + void IInternalDisposableService.DisposeService() { if (this.disposing) return; @@ -221,6 +221,53 @@ internal sealed partial class TextureManager static T? ForceNullable(T s) => s; } + /// + public unsafe IDalamudTextureWrap CreateEmpty( + RawImageSpecification specs, + bool cpuRead, + bool cpuWrite, + string? debugName = null) + { + if (cpuRead && cpuWrite) + throw new ArgumentException("cpuRead and cpuWrite cannot be set at the same time."); + + var cpuaf = default(D3D11_CPU_ACCESS_FLAG); + if (cpuRead) + cpuaf |= D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_READ; + if (cpuWrite) + cpuaf |= D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE; + + D3D11_USAGE usage; + if (cpuRead) + usage = D3D11_USAGE.D3D11_USAGE_STAGING; + else if (cpuWrite) + usage = D3D11_USAGE.D3D11_USAGE_DYNAMIC; + else + usage = D3D11_USAGE.D3D11_USAGE_DEFAULT; + + using var texture = this.device.CreateTexture2D( + new() + { + Width = (uint)specs.Width, + Height = (uint)specs.Height, + MipLevels = 1, + ArraySize = 1, + Format = specs.Format, + SampleDesc = new(1, 0), + Usage = usage, + BindFlags = (uint)D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE, + CPUAccessFlags = (uint)cpuaf, + MiscFlags = 0, + }); + using var view = this.device.CreateShaderResourceView( + texture, + new(texture, D3D_SRV_DIMENSION.D3D11_SRV_DIMENSION_TEXTURE2D)); + + var wrap = new UnknownTextureWrap((IUnknown*)view.Get(), specs.Width, specs.Height, true); + this.BlameSetName(wrap, debugName ?? $"{nameof(this.CreateEmpty)}({specs})"); + return wrap; + } + /// bool ITextureProvider.IsDxgiFormatSupported(int dxgiFormat) => this.IsDxgiFormatSupported((DXGI_FORMAT)dxgiFormat); diff --git a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs index afdca0f31..9e7544fa2 100644 --- a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs +++ b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs @@ -28,9 +28,8 @@ namespace Dalamud.Interface.Textures.Internal; [ResolveVia] [ResolveVia] #pragma warning restore SA1015 -internal sealed partial class TextureManagerPluginScoped - : IServiceType, - IDisposable, +internal sealed class TextureManagerPluginScoped + : IInternalDisposableService, ITextureProvider, ITextureSubstitutionProvider, ITextureReadbackProvider @@ -114,7 +113,7 @@ internal sealed partial class TextureManagerPluginScoped } /// - public void Dispose() + void IInternalDisposableService.DisposeService() { if (Interlocked.Exchange(ref this.managerTaskNullable, null) is not { } task) return; @@ -134,6 +133,19 @@ internal sealed partial class TextureManagerPluginScoped : $"{nameof(TextureManagerPluginScoped)}({this.plugin.Name})"; } + /// + public IDalamudTextureWrap CreateEmpty( + RawImageSpecification specs, + bool cpuRead, + bool cpuWrite, + string? debugName = null) + { + var manager = this.ManagerOrThrow; + var textureWrap = manager.CreateEmpty(specs, cpuRead, cpuWrite, debugName); + manager.Blame(textureWrap, this.plugin); + return textureWrap; + } + /// public async Task CreateFromExistingTextureAsync( IDalamudTextureWrap wrap, diff --git a/Dalamud/Interface/Textures/RawImageSpecification.cs b/Dalamud/Interface/Textures/RawImageSpecification.cs index e2bad7e5f..6f31cbbf7 100644 --- a/Dalamud/Interface/Textures/RawImageSpecification.cs +++ b/Dalamud/Interface/Textures/RawImageSpecification.cs @@ -31,6 +31,13 @@ public record struct RawImageSpecification this.DxgiFormat = dxgiFormat; } + /// Initializes a new instance of the class. + /// The source texture description. + internal RawImageSpecification(in D3D11_TEXTURE2D_DESC desc) + : this((int)desc.Width, (int)desc.Height, (int)desc.Format) + { + } + /// Initializes a new instance of the class. /// The source texture description. /// The pitch of the raw image in bytes. diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs index 58f4f3cb7..7311b0b91 100644 --- a/Dalamud/Interface/UiBuilder.cs +++ b/Dalamud/Interface/UiBuilder.cs @@ -12,16 +12,11 @@ using Dalamud.Interface.Internal; using Dalamud.Interface.Internal.ManagedAsserts; using Dalamud.Interface.ManagedFontAtlas; using Dalamud.Interface.ManagedFontAtlas.Internals; -using Dalamud.Interface.Textures; -using Dalamud.Interface.Textures.Internal; using Dalamud.Plugin.Internal.Types; -using Dalamud.Plugin.Services; using Dalamud.Utility; using ImGuiNET; -using ImGuiScene; - using Serilog; using SharpDX.Direct3D11; @@ -46,9 +41,6 @@ public sealed class UiBuilder : IDisposable private readonly DisposeSafety.ScopedFinalizer scopedFinalizer = new(); - [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)] - private readonly TextureManagerPluginScoped scopedTextureProvider; - private bool hasErrorWindow = false; private bool lastFrameUiHideState = false; @@ -78,8 +70,6 @@ public sealed class UiBuilder : IDisposable this.interfaceManager.ResizeBuffers += this.OnResizeBuffers; this.scopedFinalizer.Add(() => this.interfaceManager.ResizeBuffers -= this.OnResizeBuffers); - this.scopedFinalizer.Add(this.scopedTextureProvider = new(plugin)); - this.FontAtlas = this.scopedFinalizer .Add( @@ -350,43 +340,6 @@ public sealed class UiBuilder : IDisposable private Task InterfaceManagerWithSceneAsync => Service.GetAsync().ContinueWith(task => task.Result.Manager); - /// - /// Loads an image from the specified file. - /// - /// The full filepath to the image. - /// A object wrapping the created image. Use inside ImGui.Image(). - [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)] - [Obsolete($"Use {nameof(ITextureProvider.GetFromFile)}.")] - public IDalamudTextureWrap LoadImage(string filePath) => - this.scopedTextureProvider.GetFromFile(filePath).RentAsync().Result; - - /// - /// Loads an image from a byte stream, such as a png downloaded into memory. - /// - /// A byte array containing the raw image data. - /// A object wrapping the created image. Use inside ImGui.Image(). - [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)] - [Obsolete($"Use {nameof(ITextureProvider.CreateFromImageAsync)}.")] - public IDalamudTextureWrap LoadImage(byte[] imageData) => - this.scopedTextureProvider.CreateFromImageAsync(imageData).Result; - - /// - /// Loads an image from raw unformatted pixel data, with no type or header information. To load formatted data, use . - /// - /// A byte array containing the raw pixel data. - /// The width of the image contained in . - /// The height of the image contained in . - /// The number of channels (bytes per pixel) of the image contained in . This should usually be 4. - /// A object wrapping the created image. Use inside ImGui.Image(). - [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)] - [Obsolete($"Use {nameof(ITextureProvider.CreateFromRaw)} or {nameof(ITextureProvider.CreateFromRawAsync)}.")] - public IDalamudTextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) => - numChannels switch - { - 4 => this.scopedTextureProvider.CreateFromRaw(RawImageSpecification.Rgba32(width, height), imageData), - _ => throw new NotSupportedException(), - }; - /// /// Loads an ULD file that can load textures containing multiple icons in a single texture. /// @@ -395,43 +348,6 @@ public sealed class UiBuilder : IDisposable public UldWrapper LoadUld(string uldPath) => new(this, uldPath); - /// - /// Asynchronously loads an image from the specified file, when it's possible to do so. - /// - /// The full filepath to the image. - /// A object wrapping the created image. Use inside ImGui.Image(). - [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)] - [Obsolete($"Use {nameof(ITextureProvider.GetFromFile)}.")] - public Task LoadImageAsync(string filePath) => - this.scopedTextureProvider.GetFromFile(filePath).RentAsync(); - - /// - /// Asynchronously loads an image from a byte stream, such as a png downloaded into memory, when it's possible to do so. - /// - /// A byte array containing the raw image data. - /// A object wrapping the created image. Use inside ImGui.Image(). - [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)] - [Obsolete($"Use {nameof(ITextureProvider.CreateFromImageAsync)}.")] - public Task LoadImageAsync(byte[] imageData) => - this.scopedTextureProvider.CreateFromImageAsync(imageData); - - /// - /// Asynchronously loads an image from raw unformatted pixel data, with no type or header information, when it's possible to do so. To load formatted data, use . - /// - /// A byte array containing the raw pixel data. - /// The width of the image contained in . - /// The height of the image contained in . - /// The number of channels (bytes per pixel) of the image contained in . This should usually be 4. - /// A object wrapping the created image. Use inside ImGui.Image(). - [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)] - [Obsolete($"Use {nameof(ITextureProvider.CreateFromRawAsync)}.")] - public Task LoadImageRawAsync(byte[] imageData, int width, int height, int numChannels) => - numChannels switch - { - 4 => this.scopedTextureProvider.CreateFromRawAsync(RawImageSpecification.Rgba32(width, height), imageData), - _ => Task.FromException(new NotSupportedException()), - }; - /// /// Waits for UI to become available for use. /// diff --git a/Dalamud/Plugin/Services/ITextureProvider.cs b/Dalamud/Plugin/Services/ITextureProvider.cs index 61f400a0e..a4fa0d382 100644 --- a/Dalamud/Plugin/Services/ITextureProvider.cs +++ b/Dalamud/Plugin/Services/ITextureProvider.cs @@ -5,7 +5,6 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; -using Dalamud.Interface; using Dalamud.Interface.Internal; using Dalamud.Interface.Internal.Windows.Data.Widgets; using Dalamud.Interface.Textures; @@ -32,8 +31,20 @@ namespace Dalamud.Plugin.Services; /// . /// /// -public partial interface ITextureProvider +public interface ITextureProvider { + /// Creates an empty texture. + /// Texture specifications. + /// Whether to support reading from CPU, while disabling reading from GPU. + /// Whether to support writing from CPU, while disabling writing from GPU. + /// Name for debug display purposes. + /// A new empty texture. + IDalamudTextureWrap CreateEmpty( + RawImageSpecification specs, + bool cpuRead, + bool cpuWrite, + string? debugName = null); + /// Creates a texture from the given existing texture, cropping and converting pixel format as needed. /// /// The source texture wrap. The passed value may be disposed once this function returns, diff --git a/Dalamud/Utility/TerraFxCom/TerraFxD3D11Extensions.cs b/Dalamud/Utility/TerraFxCom/TerraFxD3D11Extensions.cs new file mode 100644 index 000000000..967c1eb1b --- /dev/null +++ b/Dalamud/Utility/TerraFxCom/TerraFxD3D11Extensions.cs @@ -0,0 +1,65 @@ +using TerraFX.Interop.DirectX; +using TerraFX.Interop.Windows; + +namespace Dalamud.Utility.TerraFxCom; + +/// Extension methods for D3D11 TerraFX objects. +internal static class TerraFxD3D11Extensions +{ + /// Creates a 2D texture with the given descriptor. + /// Device to copy from and to. + /// Resource descriptor. + /// Optional initial data for the texture. + /// New copied texture. + public static unsafe ComPtr CreateTexture2D( + this ComPtr device, + D3D11_TEXTURE2D_DESC desc, + ComPtr copyFrom = default) + { + using var tmpTex = default(ComPtr); + device.Get()->CreateTexture2D(&desc, null, tmpTex.GetAddressOf()).ThrowOnError(); + + if (!copyFrom.IsEmpty()) + { + using var context = default(ComPtr); + device.Get()->GetImmediateContext(context.GetAddressOf()); + context.Get()->CopyResource((ID3D11Resource*)tmpTex.Get(), (ID3D11Resource*)copyFrom.Get()); + } + + return new(tmpTex); + } + + /// Creates a shader resource view for a resource. + /// Device to create the resource view into. + /// Resource to create a view on. + /// Resource view descriptor. + /// Type of the resource. + /// New shader resource view. + public static unsafe ComPtr CreateShaderResourceView( + this ComPtr device, + ComPtr resource, + in D3D11_SHADER_RESOURCE_VIEW_DESC desc) + where T : unmanaged, ID3D11Resource.Interface + { + fixed (D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc = &desc) + { + var srv = default(ComPtr); + device.Get()->CreateShaderResourceView( + (ID3D11Resource*)resource.Get(), + pDesc, + srv.GetAddressOf()) + .ThrowOnError(); + return srv; + } + } + + /// Gets the descriptor for a . + /// Texture. + /// Texture descriptor. + public static unsafe D3D11_TEXTURE2D_DESC GetDesc(this ComPtr texture) + { + var desc = default(D3D11_TEXTURE2D_DESC); + texture.Get()->GetDesc(&desc); + return desc; + } +}