qstbak/Auspex/Auspex.Rendering.Direct3D/HighResFontAtlas.cs
2026-08-17 20:25:32 +10:00

146 lines
3.5 KiB
C#

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Dalamud.Bindings.ImGui;
using TerraFX.Interop.DirectX;
namespace Auspex.Rendering.Direct3D;
internal sealed class HighResFontAtlas : IDisposable
{
private struct ImFontConfigHead
{
public IntPtr FontData;
public int FontDataSize;
public byte FontDataOwnedByAtlas;
private byte _pad1;
private byte _pad2;
private byte _pad3;
public int FontNo;
public float SizePixels;
}
private const float HighResFontSize = 64f;
private IntPtr _atlas;
private unsafe ID3D11Texture2D* _texture;
private unsafe ID3D11ShaderResourceView* _srv;
public ImFontPtr Font { get; }
public unsafe IntPtr TextureSRV => (nint)_srv;
public unsafe HighResFontAtlas(FrameRenderContext ctx)
{
_atlas = ImFontAtlas_ImFontAtlas();
try
{
IntPtr intPtr = ImFontConfig_ImFontConfig();
try
{
((ImFontConfigHead*)intPtr)->SizePixels = 64f;
IntPtr intPtr2 = ImFontAtlas_AddFontDefault(_atlas, intPtr);
Font = Unsafe.As<IntPtr, ImFontPtr>(ref intPtr2);
}
finally
{
ImFontConfig_destroy(intPtr);
}
if (!ImFontAtlas_Build(_atlas))
{
throw new InvalidOperationException("Failed to build high-res font atlas");
}
byte* pSysMem = default(byte*);
int num = default(int);
int height = default(int);
int num2 = default(int);
ImFontAtlas_GetTexDataAsRGBA32(_atlas, 0, &pSysMem, &num, &height, &num2);
D3D11_TEXTURE2D_DESC d3D11_TEXTURE2D_DESC = new D3D11_TEXTURE2D_DESC
{
Width = (uint)num,
Height = (uint)height,
MipLevels = 1u,
ArraySize = 1u,
Format = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM,
SampleDesc = new DXGI_SAMPLE_DESC
{
Count = 1u,
Quality = 0u
},
Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT,
BindFlags = 8u
};
D3D11_SUBRESOURCE_DATA d3D11_SUBRESOURCE_DATA = new D3D11_SUBRESOURCE_DATA
{
pSysMem = pSysMem,
SysMemPitch = (uint)(num * num2)
};
ID3D11Texture2D* texture = default(ID3D11Texture2D*);
Marshal.ThrowExceptionForHR(ctx.Device->CreateTexture2D(&d3D11_TEXTURE2D_DESC, &d3D11_SUBRESOURCE_DATA, &texture));
_texture = texture;
ID3D11ShaderResourceView* srv = default(ID3D11ShaderResourceView*);
Marshal.ThrowExceptionForHR(ctx.Device->CreateShaderResourceView((ID3D11Resource*)_texture, null, &srv));
_srv = srv;
ImFontAtlas_ClearTexData(_atlas);
}
catch
{
Dispose();
throw;
}
}
public unsafe void Dispose()
{
if (_srv != null)
{
_srv->Release();
_srv = null;
}
if (_texture != null)
{
_texture->Release();
_texture = null;
}
if (_atlas != (IntPtr)0)
{
ImFontAtlas_destroy(_atlas);
_atlas = (IntPtr)0;
}
GC.SuppressFinalize(this);
}
[DllImport("cimgui")]
private static extern IntPtr ImFontAtlas_ImFontAtlas();
[DllImport("cimgui")]
private static extern void ImFontAtlas_destroy(IntPtr self);
[DllImport("cimgui")]
private static extern IntPtr ImFontAtlas_AddFontDefault(IntPtr self, IntPtr font_cfg);
[DllImport("cimgui")]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool ImFontAtlas_Build(IntPtr self);
[DllImport("cimgui")]
private unsafe static extern void ImFontAtlas_GetTexDataAsRGBA32(IntPtr self, int texture_index, byte** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel);
[DllImport("cimgui")]
private static extern void ImFontAtlas_ClearTexData(IntPtr self);
[DllImport("cimgui")]
private static extern IntPtr ImFontConfig_ImFontConfig();
[DllImport("cimgui")]
private static extern void ImFontConfig_destroy(IntPtr self);
}