mirror of
https://github.com/ocornut/imgui.git
synced 2025-09-06 03:18:21 +00:00
Backends: DirectX9: added ImGuiBackendFlags_RendererHasTextures support
# Conflicts: # backends/imgui_impl_dx9.cpp
This commit is contained in:
@@ -2,8 +2,9 @@
|
|||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||||
|
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||||
// [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
|
// [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2025-06-11: DirectX9: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
|
||||||
// 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
// 2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
|
||||||
// 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575)
|
// 2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575)
|
||||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||||
@@ -50,7 +52,6 @@ struct ImGui_ImplDX9_Data
|
|||||||
LPDIRECT3DDEVICE9 pd3dDevice;
|
LPDIRECT3DDEVICE9 pd3dDevice;
|
||||||
LPDIRECT3DVERTEXBUFFER9 pVB;
|
LPDIRECT3DVERTEXBUFFER9 pVB;
|
||||||
LPDIRECT3DINDEXBUFFER9 pIB;
|
LPDIRECT3DINDEXBUFFER9 pIB;
|
||||||
LPDIRECT3DTEXTURE9 FontTexture;
|
|
||||||
int VertexBufferSize;
|
int VertexBufferSize;
|
||||||
int IndexBufferSize;
|
int IndexBufferSize;
|
||||||
bool HasRgbaSupport;
|
bool HasRgbaSupport;
|
||||||
@@ -163,6 +164,13 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
|||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||||
LPDIRECT3DDEVICE9 device = bd->pd3dDevice;
|
LPDIRECT3DDEVICE9 device = bd->pd3dDevice;
|
||||||
|
|
||||||
|
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||||
|
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||||
|
if (draw_data->Textures != nullptr)
|
||||||
|
for (ImTextureData* tex : *draw_data->Textures)
|
||||||
|
if (tex->Status != ImTextureStatus_OK)
|
||||||
|
ImGui_ImplDX9_UpdateTexture(tex);
|
||||||
|
|
||||||
// Create and grow buffers if needed
|
// Create and grow buffers if needed
|
||||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||||
{
|
{
|
||||||
@@ -322,6 +330,10 @@ bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
|||||||
io.BackendRendererUserData = (void*)bd;
|
io.BackendRendererUserData = (void*)bd;
|
||||||
io.BackendRendererName = "imgui_impl_dx9";
|
io.BackendRendererName = "imgui_impl_dx9";
|
||||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||||
|
|
||||||
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = 4096;
|
||||||
|
|
||||||
bd->pd3dDevice = device;
|
bd->pd3dDevice = device;
|
||||||
bd->pd3dDevice->AddRef();
|
bd->pd3dDevice->AddRef();
|
||||||
@@ -340,12 +352,12 @@ void ImGui_ImplDX9_Shutdown()
|
|||||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||||
io.BackendRendererName = nullptr;
|
io.BackendRendererName = nullptr;
|
||||||
io.BackendRendererUserData = nullptr;
|
io.BackendRendererUserData = nullptr;
|
||||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||||
IM_DELETE(bd);
|
IM_DELETE(bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
||||||
static void ImGui_ImplDX9_CopyTextureRegion(bool tex_use_colors, ImU32* src, int src_pitch, ImU32* dst, int dst_pitch, int w, int h)
|
static void ImGui_ImplDX9_CopyTextureRegion(bool tex_use_colors, const ImU32* src, int src_pitch, ImU32* dst, int dst_pitch, int w, int h)
|
||||||
{
|
{
|
||||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||||
@@ -366,28 +378,61 @@ static void ImGui_ImplDX9_CopyTextureRegion(bool tex_use_colors, ImU32* src, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ImGui_ImplDX9_CreateFontsTexture()
|
void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex)
|
||||||
{
|
{
|
||||||
// Build texture atlas
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||||
unsigned char* pixels;
|
|
||||||
int width, height, bytes_per_pixel;
|
|
||||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
|
|
||||||
|
|
||||||
// Upload texture to graphics system
|
if (tex->Status == ImTextureStatus_WantCreate)
|
||||||
bd->FontTexture = nullptr;
|
{
|
||||||
if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, bd->HasRgbaSupport ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
|
// Create and upload new texture to graphics system
|
||||||
return false;
|
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||||
D3DLOCKED_RECT tex_locked_rect;
|
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||||
if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
|
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||||
return false;
|
LPDIRECT3DTEXTURE9 dx_tex = nullptr;
|
||||||
ImGui_ImplDX9_CopyTextureRegion(io.Fonts->TexPixelsUseColors, (ImU32*)pixels, width * bytes_per_pixel, (ImU32*)tex_locked_rect.pBits, (int)tex_locked_rect.Pitch, width, height);
|
HRESULT hr = bd->pd3dDevice->CreateTexture(tex->Width, tex->Height, 1, D3DUSAGE_DYNAMIC, bd->HasRgbaSupport ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dx_tex, nullptr);
|
||||||
bd->FontTexture->UnlockRect(0);
|
if (hr < 0)
|
||||||
|
{
|
||||||
|
IM_ASSERT(hr >= 0 && "Backend failed to create texture!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Store our identifier
|
D3DLOCKED_RECT locked_rect;
|
||||||
io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
|
if (dx_tex->LockRect(0, &locked_rect, nullptr, 0) == D3D_OK)
|
||||||
return true;
|
{
|
||||||
|
ImGui_ImplDX9_CopyTextureRegion(tex->UseColors, (ImU32*)tex->GetPixels(), tex->Width * 4, (ImU32*)locked_rect.pBits, (ImU32)locked_rect.Pitch, tex->Width, tex->Height);
|
||||||
|
dx_tex->UnlockRect(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store identifiers
|
||||||
|
tex->SetTexID((ImTextureID)(intptr_t)dx_tex);
|
||||||
|
tex->SetStatus(ImTextureStatus_OK);
|
||||||
|
}
|
||||||
|
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||||
|
{
|
||||||
|
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||||
|
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||||
|
LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)(intptr_t)tex->TexID;
|
||||||
|
RECT update_rect = { (LONG)tex->UpdateRect.x, (LONG)tex->UpdateRect.y, (LONG)(tex->UpdateRect.x + tex->UpdateRect.w), (LONG)(tex->UpdateRect.y + tex->UpdateRect.h) };
|
||||||
|
D3DLOCKED_RECT locked_rect;
|
||||||
|
if (backend_tex->LockRect(0, &locked_rect, &update_rect, 0) == D3D_OK)
|
||||||
|
for (ImTextureRect& r : tex->Updates)
|
||||||
|
ImGui_ImplDX9_CopyTextureRegion(tex->UseColors, (ImU32*)tex->GetPixelsAt(r.x, r.y), tex->Width * 4,
|
||||||
|
(ImU32*)locked_rect.pBits + (r.x - update_rect.left) + (r.y - update_rect.top) * (locked_rect.Pitch / 4), (int)locked_rect.Pitch, r.w, r.h);
|
||||||
|
backend_tex->UnlockRect(0);
|
||||||
|
tex->SetStatus(ImTextureStatus_OK);
|
||||||
|
}
|
||||||
|
else if (tex->Status == ImTextureStatus_WantDestroy)
|
||||||
|
{
|
||||||
|
LPDIRECT3DTEXTURE9 backend_tex = (LPDIRECT3DTEXTURE9)tex->TexID;
|
||||||
|
if (backend_tex == nullptr)
|
||||||
|
return;
|
||||||
|
IM_ASSERT(tex->TexID == (ImTextureID)(intptr_t)backend_tex);
|
||||||
|
backend_tex->Release();
|
||||||
|
|
||||||
|
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||||
|
tex->SetTexID(ImTextureID_Invalid);
|
||||||
|
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui_ImplDX9_CreateDeviceObjects()
|
bool ImGui_ImplDX9_CreateDeviceObjects()
|
||||||
@@ -395,8 +440,6 @@ bool ImGui_ImplDX9_CreateDeviceObjects()
|
|||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||||
if (!bd || !bd->pd3dDevice)
|
if (!bd || !bd->pd3dDevice)
|
||||||
return false;
|
return false;
|
||||||
if (!ImGui_ImplDX9_CreateFontsTexture())
|
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,18 +448,23 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
|
|||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||||
if (!bd || !bd->pd3dDevice)
|
if (!bd || !bd->pd3dDevice)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Destroy all textures
|
||||||
|
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||||
|
if (tex->RefCount == 1)
|
||||||
|
{
|
||||||
|
tex->SetStatus(ImTextureStatus_WantDestroy);
|
||||||
|
ImGui_ImplDX9_UpdateTexture(tex);
|
||||||
|
}
|
||||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||||
if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui_ImplDX9_NewFrame()
|
void ImGui_ImplDX9_NewFrame()
|
||||||
{
|
{
|
||||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX9_Init()?");
|
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX9_Init()?");
|
||||||
|
IM_UNUSED(bd);
|
||||||
if (!bd->FontTexture)
|
|
||||||
ImGui_ImplDX9_CreateDeviceObjects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@@ -2,8 +2,9 @@
|
|||||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||||
|
|
||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||||
|
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||||
// [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
|
// [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
|
||||||
|
|
||||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
@@ -30,4 +31,7 @@ IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
|
|||||||
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
|
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
|
||||||
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
|
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||||
|
|
||||||
|
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplDX9_UpdateTexture(ImTextureData* tex);
|
||||||
|
|
||||||
#endif // #ifndef IMGUI_DISABLE
|
#endif // #ifndef IMGUI_DISABLE
|
||||||
|
Reference in New Issue
Block a user