mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
DataManager.GetImGuiTexture: skip converting to bgra8888 when possible (#1333)
This commit is contained in:
parent
5a4be696c5
commit
b1211fe5d1
3 changed files with 88 additions and 1 deletions
|
|
@ -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);
|
||||
|
||||
/// <inheritdoc/>
|
||||
[return: NotNullIfNotNull(nameof(tex))]
|
||||
public TextureWrap? GetImGuiTexture(TexFile? tex)
|
||||
=> tex == null ? null : Service<InterfaceManager>.Get().LoadImageRaw(tex.GetRgbaImageData(), tex.Header.Width, tex.Header.Height, 4);
|
||||
{
|
||||
if (tex is null)
|
||||
return null;
|
||||
|
||||
var im = Service<InterfaceManager>.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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TextureWrap? GetImGuiTexture(string path)
|
||||
=> this.GetImGuiTexture(this.GetFile<TexFile>(path));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether the current D3D11 Device supports the given DXGI format.
|
||||
/// </summary>
|
||||
/// <param name="dxgiFormat">DXGI format to check.</param>
|
||||
/// <returns>Whether it is supported.</returns>
|
||||
public bool SupportsDxgiFormat(Format dxgiFormat) => this.scene is null
|
||||
? throw new InvalidOperationException("Scene isn't ready.")
|
||||
: this.scene.Device.CheckFormatSupport(dxgiFormat).HasFlag(FormatSupport.Texture2D);
|
||||
|
||||
/// <summary>
|
||||
/// Load an image from a span of bytes of specified format.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to load.</param>
|
||||
/// <param name="pitch">The pitch(stride) in bytes.</param>
|
||||
/// <param name="width">The width in pixels.</param>
|
||||
/// <param name="height">The height in pixels.</param>
|
||||
/// <param name="dxgiFormat">Format of the texture.</param>
|
||||
/// <returns>A texture, ready to use in ImGui.</returns>
|
||||
public TextureWrap LoadImageFromDxgiFormat(Span<byte> 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
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
using ImGuiScene;
|
||||
using Lumina;
|
||||
|
|
@ -139,6 +140,7 @@ public interface IDataManager
|
|||
/// </summary>
|
||||
/// <param name="tex">The Lumina <see cref="TexFile"/>.</param>
|
||||
/// <returns>A <see cref="TextureWrap"/> that can be used to draw the texture.</returns>
|
||||
[return: NotNullIfNotNull(nameof(tex))]
|
||||
public TextureWrap? GetImGuiTexture(TexFile? tex);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue