Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an ability to update font atlas texture #3761

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
25 changes: 24 additions & 1 deletion backends/imgui_impl_allegro5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2024-XX-XX: Renderer: Add support for ImGuiBackendFlags_RendererHasTexReload.
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
Expand Down Expand Up @@ -227,14 +228,15 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
al_use_projection_transform(&last_projection_transform);
}

bool ImGui_ImplAllegro5_CreateDeviceObjects()
static bool ImGui_ImplAllegro5_UpdateFontsTexture()
{
// Build texture atlas
ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
io.Fonts->MarkClean();

// Create texture
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
Expand Down Expand Up @@ -263,10 +265,27 @@ bool ImGui_ImplAllegro5_CreateDeviceObjects()
if (!cloned_img)
return false;

if (bd->Texture)
{
al_destroy_bitmap(bd->Texture);
io.Fonts->SetTexID(0);
bd->Texture = nullptr;
}

// Store our identifier
io.Fonts->SetTexID((ImTextureID)(intptr_t)cloned_img);
bd->Texture = cloned_img;

return true;
}

bool ImGui_ImplAllegro5_CreateDeviceObjects()
{
if (!ImGui_ImplAllegro5_UpdateFontsTexture())
return false;

ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();

// Create an invisible mouse cursor
// Because al_hide_mouse_cursor() seems to mess up with the actual inputs..
ALLEGRO_BITMAP* mouse_cursor = al_create_bitmap(8, 8);
Expand Down Expand Up @@ -435,6 +454,7 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = io.BackendRendererName = "imgui_impl_allegro5";
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_RendererHasTexReload; // We can update font atlas textures (optional)

bd->Display = display;

Expand Down Expand Up @@ -599,6 +619,9 @@ void ImGui_ImplAllegro5_NewFrame()

ImGuiIO& io = ImGui::GetIO();

if (io.Fonts->IsDirty())
ImGui_ImplAllegro5_UpdateFontsTexture();

// Setup display size (every frame to accommodate for window resizing)
int w, h;
w = al_get_display_width(bd->Display);
Expand Down
102 changes: 70 additions & 32 deletions backends/imgui_impl_dx10.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: DirectX10: Add support for ImGuiBackendFlags_RendererHasTexReload.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
Expand Down Expand Up @@ -57,6 +58,9 @@ struct ImGui_ImplDX10_Data
ID3D10Buffer* pVertexConstantBuffer;
ID3D10PixelShader* pPixelShader;
ID3D10SamplerState* pFontSampler;
ID3D10Texture2D* pFontTexture;
int FontTextureWidth;
int FontTextureHeight;
ID3D10ShaderResourceView* pFontTextureView;
ID3D10RasterizerState* pRasterizerState;
ID3D10BlendState* pBlendState;
Expand Down Expand Up @@ -296,53 +300,81 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
}

static void ImGui_ImplDX10_CreateFontsTexture()
static void ImGui_ImplDX10_UpdateFontsTexture()
{
// Build texture atlas
ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
ImGuiIO& io = ImGui::GetIO();

unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
io.Fonts->MarkClean();

// Upload texture to graphics system
if ((!bd->pFontTextureView) || (bd->FontTextureWidth != width) || (bd->FontTextureHeight != height))
{
D3D10_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;

ID3D10Texture2D* pTexture = nullptr;
D3D10_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
IM_ASSERT(pTexture != nullptr);

// Create texture view
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
ZeroMemory(&srv_desc, sizeof(srv_desc));
srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
srv_desc.Texture2D.MipLevels = desc.MipLevels;
srv_desc.Texture2D.MostDetailedMip = 0;
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &bd->pFontTextureView);
pTexture->Release();
// Either we have no texture or the size has changed, so (re-)create the texture

// Release old texture
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->pFontTexture) { bd->pFontTexture->Release(); bd->pFontTexture = nullptr; }

// Create new texture
{
D3D10_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;

D3D10_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &bd->pFontTexture);
IM_ASSERT(bd->pFontTexture != nullptr);

// Create texture view
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
ZeroMemory(&srv_desc, sizeof(srv_desc));
srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
srv_desc.Texture2D.MipLevels = desc.MipLevels;
srv_desc.Texture2D.MostDetailedMip = 0;
bd->pd3dDevice->CreateShaderResourceView(bd->pFontTexture, &srv_desc, &bd->pFontTextureView);
}

// Store size
bd->FontTextureWidth = width;
bd->FontTextureHeight = height;
}
else
{
// Upload new atlas data

D3D10_BOX box;
box.left = 0;
box.right = width;
box.top = 0;
box.bottom = height;
box.front = 0;
box.back = 1;

bd->pd3dDevice->UpdateSubresource(bd->pFontTexture, 0, &box, pixels, bd->FontTextureWidth * 4, 0);
}

// Store our identifier
io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);

// Create texture sampler
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
if (!bd->pFontSampler)
{
D3D10_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
Expand Down Expand Up @@ -507,7 +539,7 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
}

ImGui_ImplDX10_CreateFontsTexture();
ImGui_ImplDX10_UpdateFontsTexture();

return true;
}
Expand All @@ -520,6 +552,7 @@ void ImGui_ImplDX10_InvalidateDeviceObjects()

if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->pFontTexture) { bd->pFontTexture->Release(); bd->pFontTexture = nullptr; }
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
Expand All @@ -542,6 +575,7 @@ bool ImGui_ImplDX10_Init(ID3D10Device* device)
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_dx10";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasTexReload; // We support font atlas texture reloading (IsDirty() check in ImGui_ImplDX10_NewFrame)

// Get factory from device
IDXGIDevice* pDXGIDevice = nullptr;
Expand Down Expand Up @@ -583,6 +617,10 @@ void ImGui_ImplDX10_NewFrame()

if (!bd->pFontSampler)
ImGui_ImplDX10_CreateDeviceObjects();

ImGuiIO& io = ImGui::GetIO();
if (io.Fonts->IsDirty())
ImGui_ImplDX10_UpdateFontsTexture();
}

//-----------------------------------------------------------------------------
Expand Down
Loading
Loading