33
44// Implemented features:
55// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
6+ // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
67// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
78
89// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
1213
1314// CHANGELOG
1415// (minor and older changes stripped away, please see git history for details)
16+ // 2022-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
1517// 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).
1618// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
1719// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
@@ -75,6 +77,10 @@ static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
7577 return ImGui::GetCurrentContext () ? (ImGui_ImplDX11_Data*)ImGui::GetIO ().BackendRendererUserData : NULL ;
7678}
7779
80+ // Forward Declarations
81+ static void ImGui_ImplDX11_InitPlatformInterface ();
82+ static void ImGui_ImplDX11_ShutdownPlatformInterface ();
83+
7884// Functions
7985static void ImGui_ImplDX11_SetupRenderState (ImDrawData* draw_data, ID3D11DeviceContext* ctx)
8086{
@@ -547,6 +553,7 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
547553 io.BackendRendererUserData = (void *)bd;
548554 io.BackendRendererName = " imgui_impl_dx11" ;
549555 io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
556+ io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
550557
551558 // Get factory from device
552559 IDXGIDevice* pDXGIDevice = NULL ;
@@ -566,6 +573,9 @@ bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co
566573 bd->pd3dDevice ->AddRef ();
567574 bd->pd3dDeviceContext ->AddRef ();
568575
576+ if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
577+ ImGui_ImplDX11_InitPlatformInterface ();
578+
569579 return true ;
570580}
571581
@@ -575,6 +585,7 @@ void ImGui_ImplDX11_Shutdown()
575585 IM_ASSERT (bd != NULL && " No renderer backend to shutdown, or already shutdown?" );
576586 ImGuiIO& io = ImGui::GetIO ();
577587
588+ ImGui_ImplDX11_ShutdownPlatformInterface ();
578589 ImGui_ImplDX11_InvalidateDeviceObjects ();
579590 if (bd->pFactory ) { bd->pFactory ->Release (); }
580591 if (bd->pd3dDevice ) { bd->pd3dDevice ->Release (); }
@@ -592,3 +603,126 @@ void ImGui_ImplDX11_NewFrame()
592603 if (!bd->pFontSampler )
593604 ImGui_ImplDX11_CreateDeviceObjects ();
594605}
606+
607+ // --------------------------------------------------------------------------------------------------------
608+ // MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
609+ // This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
610+ // If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
611+ // --------------------------------------------------------------------------------------------------------
612+
613+ // Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
614+ struct ImGui_ImplDX11_ViewportData
615+ {
616+ IDXGISwapChain* SwapChain;
617+ ID3D11RenderTargetView* RTView;
618+
619+ ImGui_ImplDX11_ViewportData () { SwapChain = NULL ; RTView = NULL ; }
620+ ~ImGui_ImplDX11_ViewportData () { IM_ASSERT (SwapChain == NULL && RTView == NULL ); }
621+ };
622+
623+ static void ImGui_ImplDX11_CreateWindow (ImGuiViewport* viewport)
624+ {
625+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData ();
626+ ImGui_ImplDX11_ViewportData* vd = IM_NEW (ImGui_ImplDX11_ViewportData)();
627+ viewport->RendererUserData = vd;
628+
629+ // PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
630+ // Some backend will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
631+ HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle ;
632+ IM_ASSERT (hwnd != 0 );
633+
634+ // Create swap chain
635+ DXGI_SWAP_CHAIN_DESC sd;
636+ ZeroMemory (&sd, sizeof (sd));
637+ sd.BufferDesc .Width = (UINT)viewport->Size .x ;
638+ sd.BufferDesc .Height = (UINT)viewport->Size .y ;
639+ sd.BufferDesc .Format = DXGI_FORMAT_R8G8B8A8_UNORM;
640+ sd.SampleDesc .Count = 1 ;
641+ sd.SampleDesc .Quality = 0 ;
642+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
643+ sd.BufferCount = 1 ;
644+ sd.OutputWindow = hwnd;
645+ sd.Windowed = TRUE ;
646+ sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
647+ sd.Flags = 0 ;
648+
649+ IM_ASSERT (vd->SwapChain == NULL && vd->RTView == NULL );
650+ bd->pFactory ->CreateSwapChain (bd->pd3dDevice , &sd, &vd->SwapChain );
651+
652+ // Create the render target
653+ if (vd->SwapChain )
654+ {
655+ ID3D11Texture2D* pBackBuffer;
656+ vd->SwapChain ->GetBuffer (0 , IID_PPV_ARGS (&pBackBuffer));
657+ bd->pd3dDevice ->CreateRenderTargetView (pBackBuffer, NULL , &vd->RTView );
658+ pBackBuffer->Release ();
659+ }
660+ }
661+
662+ static void ImGui_ImplDX11_DestroyWindow (ImGuiViewport* viewport)
663+ {
664+ // The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
665+ if (ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData )
666+ {
667+ if (vd->SwapChain )
668+ vd->SwapChain ->Release ();
669+ vd->SwapChain = NULL ;
670+ if (vd->RTView )
671+ vd->RTView ->Release ();
672+ vd->RTView = NULL ;
673+ IM_DELETE (vd);
674+ }
675+ viewport->RendererUserData = NULL ;
676+ }
677+
678+ static void ImGui_ImplDX11_SetWindowSize (ImGuiViewport* viewport, ImVec2 size)
679+ {
680+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData ();
681+ ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData ;
682+ if (vd->RTView )
683+ {
684+ vd->RTView ->Release ();
685+ vd->RTView = NULL ;
686+ }
687+ if (vd->SwapChain )
688+ {
689+ ID3D11Texture2D* pBackBuffer = NULL ;
690+ vd->SwapChain ->ResizeBuffers (0 , (UINT)size.x , (UINT)size.y , DXGI_FORMAT_UNKNOWN, 0 );
691+ vd->SwapChain ->GetBuffer (0 , IID_PPV_ARGS (&pBackBuffer));
692+ if (pBackBuffer == NULL ) { fprintf (stderr, " ImGui_ImplDX11_SetWindowSize() failed creating buffers.\n " ); return ; }
693+ bd->pd3dDevice ->CreateRenderTargetView (pBackBuffer, NULL , &vd->RTView );
694+ pBackBuffer->Release ();
695+ }
696+ }
697+
698+ static void ImGui_ImplDX11_RenderWindow (ImGuiViewport* viewport, void *)
699+ {
700+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData ();
701+ ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData ;
702+ ImVec4 clear_color = ImVec4 (0 .0f , 0 .0f , 0 .0f , 1 .0f );
703+ bd->pd3dDeviceContext ->OMSetRenderTargets (1 , &vd->RTView , NULL );
704+ if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
705+ bd->pd3dDeviceContext ->ClearRenderTargetView (vd->RTView , (float *)&clear_color);
706+ ImGui_ImplDX11_RenderDrawData (viewport->DrawData );
707+ }
708+
709+ static void ImGui_ImplDX11_SwapBuffers (ImGuiViewport* viewport, void *)
710+ {
711+ ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData ;
712+ vd->SwapChain ->Present (0 , 0 ); // Present without vsync
713+ }
714+
715+ static void ImGui_ImplDX11_InitPlatformInterface ()
716+ {
717+ ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO ();
718+ platform_io.Renderer_CreateWindow = ImGui_ImplDX11_CreateWindow;
719+ platform_io.Renderer_DestroyWindow = ImGui_ImplDX11_DestroyWindow;
720+ platform_io.Renderer_SetWindowSize = ImGui_ImplDX11_SetWindowSize;
721+ platform_io.Renderer_RenderWindow = ImGui_ImplDX11_RenderWindow;
722+ platform_io.Renderer_SwapBuffers = ImGui_ImplDX11_SwapBuffers;
723+ }
724+
725+ static void ImGui_ImplDX11_ShutdownPlatformInterface ()
726+ {
727+ ImGui::DestroyPlatformWindows ();
728+ }
0 commit comments