diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs
index 407a1b0da..f450175f7 100644
--- a/Dalamud/Data/DataManager.cs
+++ b/Dalamud/Data/DataManager.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading;
@@ -16,9 +17,11 @@ using JetBrains.Annotations;
using Lumina;
using Lumina.Data;
using Lumina.Data.Files;
+using Lumina.Data.Parsing.Tex.Buffers;
using Lumina.Excel;
using Newtonsoft.Json;
using Serilog;
+using SharpDX.DXGI;
namespace Dalamud.Data;
@@ -261,9 +264,31 @@ public sealed class DataManager : IDisposable, IServiceType, IDataManager
=> this.GetIcon(true, iconId);
///
+ [return: NotNullIfNotNull(nameof(tex))]
public TextureWrap? GetImGuiTexture(TexFile? tex)
- => tex == null ? null : Service.Get().LoadImageRaw(tex.GetRgbaImageData(), tex.Header.Width, tex.Header.Height, 4);
+ {
+ if (tex is null)
+ return null;
+ var im = Service.Get();
+ var buffer = tex.TextureBuffer;
+ var bpp = 1 << (((int)tex.Header.Format & (int)TexFile.TextureFormat.BppMask) >>
+ (int)TexFile.TextureFormat.BppShift);
+
+ var (dxgiFormat, conversion) = TexFile.GetDxgiFormatFromTextureFormat(tex.Header.Format, false);
+ if (conversion != TexFile.DxgiFormatConversion.NoConversion || !im.SupportsDxgiFormat((Format)dxgiFormat))
+ {
+ dxgiFormat = (int)Format.B8G8R8A8_UNorm;
+ buffer = buffer.Filter(0, 0, TexFile.TextureFormat.B8G8R8A8);
+ bpp = 32;
+ }
+
+ var pitch = buffer is BlockCompressionTextureBuffer
+ ? Math.Max(1, (buffer.Width + 3) / 4) * 2 * bpp
+ : ((buffer.Width * bpp) + 7) / 8;
+ return im.LoadImageFromDxgiFormat(buffer.RawData, pitch, buffer.Width, buffer.Height, (Format)dxgiFormat);
+ }
+
///
public TextureWrap? GetImGuiTexture(string path)
=> this.GetImGuiTexture(this.GetFile(path));
diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs
index 6bb45b325..42402ed97 100644
--- a/Dalamud/Interface/Internal/InterfaceManager.cs
+++ b/Dalamud/Interface/Internal/InterfaceManager.cs
@@ -26,6 +26,10 @@ using ImGuiNET;
using ImGuiScene;
using PInvoke;
using Serilog;
+using SharpDX;
+using SharpDX.Direct3D;
+using SharpDX.Direct3D11;
+using SharpDX.DXGI;
// general dev notes, here because it's easiest
@@ -303,6 +307,62 @@ internal class InterfaceManager : IDisposable, IServiceType
return null;
}
+ ///
+ /// Check whether the current D3D11 Device supports the given DXGI format.
+ ///
+ /// DXGI format to check.
+ /// Whether it is supported.
+ public bool SupportsDxgiFormat(Format dxgiFormat) => this.scene is null
+ ? throw new InvalidOperationException("Scene isn't ready.")
+ : this.scene.Device.CheckFormatSupport(dxgiFormat).HasFlag(FormatSupport.Texture2D);
+
+ ///
+ /// Load an image from a span of bytes of specified format.
+ ///
+ /// The data to load.
+ /// The pitch(stride) in bytes.
+ /// The width in pixels.
+ /// The height in pixels.
+ /// Format of the texture.
+ /// A texture, ready to use in ImGui.
+ public TextureWrap LoadImageFromDxgiFormat(Span data, int pitch, int width, int height, Format dxgiFormat)
+ {
+ if (this.scene == null)
+ throw new InvalidOperationException("Scene isn't ready.");
+
+ ShaderResourceView resView;
+ unsafe
+ {
+ fixed (void* pData = data)
+ {
+ var texDesc = new Texture2DDescription
+ {
+ Width = width,
+ Height = height,
+ MipLevels = 1,
+ ArraySize = 1,
+ Format = dxgiFormat,
+ SampleDescription = new(1, 0),
+ Usage = ResourceUsage.Immutable,
+ BindFlags = BindFlags.ShaderResource,
+ CpuAccessFlags = CpuAccessFlags.None,
+ OptionFlags = ResourceOptionFlags.None,
+ };
+
+ using var texture = new Texture2D(this.Device, texDesc, new DataRectangle(new(pData), pitch));
+ resView = new(this.Device, texture, new()
+ {
+ Format = texDesc.Format,
+ Dimension = ShaderResourceViewDimension.Texture2D,
+ Texture2D = { MipLevels = texDesc.MipLevels },
+ });
+ }
+ }
+
+ // no sampler for now because the ImGui implementation we copied doesn't allow for changing it
+ return new D3DTextureWrap(resView, width, height);
+ }
+
#nullable restore
///
diff --git a/Dalamud/Plugin/Services/IDataManager.cs b/Dalamud/Plugin/Services/IDataManager.cs
index fa8c5bf43..e79a58fd5 100644
--- a/Dalamud/Plugin/Services/IDataManager.cs
+++ b/Dalamud/Plugin/Services/IDataManager.cs
@@ -1,4 +1,5 @@
using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
using ImGuiScene;
using Lumina;
@@ -139,6 +140,7 @@ public interface IDataManager
///
/// The Lumina .
/// A that can be used to draw the texture.
+ [return: NotNullIfNotNull(nameof(tex))]
public TextureWrap? GetImGuiTexture(TexFile? tex);
///