Skip to content

Commit

Permalink
Fixed issue ocornut#2600
Browse files Browse the repository at this point in the history
Each window created in imgui_impl_win32.cpp now creates an openGL
context which shares its display list space with the primary window's.
IMGUI_IMPL_WIN32_OPENGL3 must be defined to use this fix.
  • Loading branch information
theOtherMichael committed Apr 5, 2022
1 parent 505f19e commit 4955f4b
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
83 changes: 82 additions & 1 deletion backends/imgui_impl_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
static void ImGui_ImplWin32_InitPlatformInterface();
static void ImGui_ImplWin32_ShutdownPlatformInterface();
static void ImGui_ImplWin32_UpdateMonitors();
static void ImGui_ImplWin32_SetWindowFocus(ImGuiViewport* viewport);
static void ImGui_ImplWin32_ShowWindow(ImGuiViewport* viewport);

struct ImGui_ImplWin32_Data
{
Expand All @@ -96,6 +98,10 @@ struct ImGui_ImplWin32_Data
bool WantUpdateHasGamepad;
bool WantUpdateMonitors;

#ifdef IMGUI_IMPL_WIN32_OPENGL3
HGLRC HgLrc;
#endif //IMGUI_IMPL_WIN32_OPENGL3

#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
HMODULE XInputDLL;
PFN_XInputGetCapabilities XInputGetCapabilities;
Expand All @@ -115,7 +121,11 @@ static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData()
}

// Functions
#ifdef IMGUI_IMPL_WIN32_OPENGL3
bool ImGui_ImplWin32_Init(void* hwnd, void* hglrc)
#else
bool ImGui_ImplWin32_Init(void* hwnd)
#endif
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
Expand All @@ -142,6 +152,10 @@ bool ImGui_ImplWin32_Init(void* hwnd)
bd->Time = perf_counter;
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;

#ifdef IMGUI_IMPL_WIN32_OPENGL3
bd->HgLrc = (HGLRC)hglrc;
#endif //IMGUI_IMPL_WIN32_OPENGL3

// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)bd->hWnd;
Expand Down Expand Up @@ -846,7 +860,23 @@ struct ImGui_ImplWin32_ViewportData
DWORD DwStyle;
DWORD DwExStyle;

ImGui_ImplWin32_ViewportData() { Hwnd = NULL; HwndOwned = false; DwStyle = DwExStyle = 0; }
#ifdef IMGUI_IMPL_WIN32_OPENGL3
HDC Hdc;
HGLRC HgLrc;
#endif //IMGUI_IMPL_WIN32_OPENGL3

ImGui_ImplWin32_ViewportData()
{
Hwnd = NULL;
HwndOwned = false;
DwStyle = 0;
DwExStyle = 0;

#ifdef IMGUI_IMPL_WIN32_OPENGL3
Hdc = NULL;
HgLrc = NULL;
#endif //IMGUI_IMPL_WIN32_OPENGL3
}
~ImGui_ImplWin32_ViewportData() { IM_ASSERT(Hwnd == NULL); }
};

Expand Down Expand Up @@ -888,6 +918,27 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
vd->HwndOwned = true;
viewport->PlatformRequestResize = false;
viewport->PlatformHandle = viewport->PlatformHandleRaw = vd->Hwnd;

#ifdef IMGUI_IMPL_WIN32_OPENGL3
vd->Hdc = GetDC(vd->Hwnd);
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();

// Set pixel format to match base window
HDC Hdc = GetDC(bd->hWnd);
int pf = GetPixelFormat(Hdc);
PIXELFORMATDESCRIPTOR pfd;
DescribePixelFormat(Hdc, pf, sizeof(pfd), &pfd);
SetPixelFormat(vd->Hdc, pf, &pfd);

// Create OpenGL context for new window
vd->HgLrc = wglCreateContext(vd->Hdc);
wglMakeCurrent(vd->Hdc, vd->HgLrc);
wglShareLists(bd->HgLrc, vd->HgLrc);

// Present new window
ImGui_ImplWin32_SetWindowFocus(viewport);
ImGui_ImplWin32_ShowWindow(viewport);
#endif //IMGUI_IMPL_WIN32_OPENGL3
}

static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport)
Expand All @@ -902,7 +953,13 @@ static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport)
::SetCapture(bd->hWnd);
}
if (vd->Hwnd && vd->HwndOwned)
{
#ifdef IMGUI_IMPL_WIN32_OPENGL3
wglDeleteContext(vd->HgLrc);
#endif //IMGUI_IMPL_WIN32_OPENGL3

::DestroyWindow(vd->Hwnd);
}
vd->Hwnd = NULL;
IM_DELETE(vd);
}
Expand Down Expand Up @@ -1062,6 +1119,21 @@ static void ImGui_ImplWin32_OnChangedViewport(ImGuiViewport* viewport)
#endif
}

#ifdef IMGUI_IMPL_WIN32_OPENGL3
static void ImGui_ImplWin32_RenderWindow(ImGuiViewport* viewport, void*)
{
ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData;
wglMakeCurrent(vd->Hdc, vd->HgLrc);
}

static void ImGui_ImplWin32_SwapBuffers(ImGuiViewport* viewport, void*)
{
ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData;
wglMakeCurrent(vd->Hdc, vd->HgLrc);
SwapBuffers(vd->Hdc);
}
#endif //IMGUI_IMPL_WIN32_OPENGL3

static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
Expand All @@ -1071,6 +1143,10 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd,
{
switch (msg)
{
#ifdef IMGUI_IMPL_WIN32_OPENGL3
case WM_ERASEBKGND:
return 0; // Prevent flickering on window invalidation
#endif //IMGUI_IMPL_WIN32_OPENGL3
case WM_CLOSE:
viewport->PlatformRequestClose = true;
return 0;
Expand Down Expand Up @@ -1134,6 +1210,11 @@ static void ImGui_ImplWin32_InitPlatformInterface()
platform_io.Platform_UpdateWindow = ImGui_ImplWin32_UpdateWindow;
platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; // FIXME-DPI
platform_io.Platform_OnChangedViewport = ImGui_ImplWin32_OnChangedViewport; // FIXME-DPI

#ifdef IMGUI_IMPL_WIN32_OPENGL3
platform_io.Platform_RenderWindow = ImGui_ImplWin32_RenderWindow;
platform_io.Platform_SwapBuffers = ImGui_ImplWin32_SwapBuffers;
#endif //IMGUI_IMPL_WIN32_OPENGL3

// Register main window handle (which is owned by the main application, not by us)
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
Expand Down
4 changes: 4 additions & 0 deletions backends/imgui_impl_win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
#pragma once
#include "imgui.h" // IMGUI_IMPL_API

#ifdef IMGUI_IMPL_WIN32_OPENGL3
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd, void* hglrc);
#else
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
#endif
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();

Expand Down

0 comments on commit 4955f4b

Please sign in to comment.