mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 21:21:06 +01:00 
			
		
		
		
	Backends: moved global to a data structure to facilitate support for multi-contexts. (#586, #1851, #2004, #3012, #3934, #4141)
This is NOT enable multi-contexts for any backends - in order to make this commit as harmless as possible, while containing all the cruft/renaming -
This commit is contained in:
		| @@ -9,13 +9,14 @@ | |||||||
| //  [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually. | //  [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually. | ||||||
| //  [ ] Platform: Missing gamepad support. | //  [ ] Platform: Missing gamepad support. | ||||||
|  |  | ||||||
| // 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. | ||||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | ||||||
| // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | ||||||
| // Read online: https://github.com/ocornut/imgui/tree/master/docs | // Read online: https://github.com/ocornut/imgui/tree/master/docs | ||||||
|  |  | ||||||
| // 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) | ||||||
|  | //  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: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | //  2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | ||||||
| //  2021-02-18: Change blending equation to preserve alpha in output buffer. | //  2021-02-18: Change blending equation to preserve alpha in output buffer. | ||||||
| //  2020-08-10: Inputs: Fixed horizontal mouse wheel direction. | //  2020-08-10: Inputs: Fixed horizontal mouse wheel direction. | ||||||
| @@ -53,13 +54,24 @@ | |||||||
| #pragma warning (disable: 4127) // condition expression is constant | #pragma warning (disable: 4127) // condition expression is constant | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Data | // Allegro Data | ||||||
| static ALLEGRO_DISPLAY*         g_Display = NULL; | struct ImGui_ImplAllegro5_Data | ||||||
| static ALLEGRO_BITMAP*          g_Texture = NULL; | { | ||||||
| static double                   g_Time = 0.0; |     ALLEGRO_DISPLAY*            Display; | ||||||
| static ALLEGRO_MOUSE_CURSOR*    g_MouseCursorInvisible = NULL; |     ALLEGRO_BITMAP*             Texture; | ||||||
| static ALLEGRO_VERTEX_DECL*     g_VertexDecl = NULL; |     double                      Time; | ||||||
| static char*                    g_ClipboardTextData = NULL; |     ALLEGRO_MOUSE_CURSOR*       MouseCursorInvisible; | ||||||
|  |     ALLEGRO_VERTEX_DECL*        VertexDecl; | ||||||
|  |     char*                       ClipboardTextData; | ||||||
|  |  | ||||||
|  |     ImGui_ImplAllegro5_Data()   { memset(this, 0, sizeof(*this)); } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplAllegro5_Data* g_Data; | ||||||
|  | static ImGui_ImplAllegro5_Data* ImGui_ImplAllegro5_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplAllegro5_Data); return g_Data; } | ||||||
|  | static ImGui_ImplAllegro5_Data* ImGui_ImplAllegro5_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } | ||||||
|  | static void                     ImGui_ImplAllegro5_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| struct ImDrawVertAllegro | struct ImDrawVertAllegro | ||||||
| { | { | ||||||
| @@ -96,6 +108,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) | |||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     // Backup Allegro state that will be modified |     // Backup Allegro state that will be modified | ||||||
|  |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|     ALLEGRO_TRANSFORM last_transform = *al_get_current_transform(); |     ALLEGRO_TRANSFORM last_transform = *al_get_current_transform(); | ||||||
|     ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform(); |     ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform(); | ||||||
|     int last_clip_x, last_clip_y, last_clip_w, last_clip_h; |     int last_clip_x, last_clip_y, last_clip_w, last_clip_h; | ||||||
| @@ -161,7 +174,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) | |||||||
|                 // Draw |                 // Draw | ||||||
|                 ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->GetTexID(); |                 ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->GetTexID(); | ||||||
|                 al_set_clipping_rectangle(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); |                 al_set_clipping_rectangle(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); | ||||||
|                 al_draw_prim(&vertices[0], g_VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST); |                 al_draw_prim(&vertices[0], bd->VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST); | ||||||
|             } |             } | ||||||
|             idx_offset += pcmd->ElemCount; |             idx_offset += pcmd->ElemCount; | ||||||
|         } |         } | ||||||
| @@ -177,6 +190,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) | |||||||
| bool ImGui_ImplAllegro5_CreateDeviceObjects() | bool ImGui_ImplAllegro5_CreateDeviceObjects() | ||||||
| { | { | ||||||
|     // Build texture atlas |     // Build texture atlas | ||||||
|  |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     unsigned char* pixels; |     unsigned char* pixels; | ||||||
|     int width, height; |     int width, height; | ||||||
| @@ -210,12 +224,12 @@ bool ImGui_ImplAllegro5_CreateDeviceObjects() | |||||||
|  |  | ||||||
|     // Store our identifier |     // Store our identifier | ||||||
|     io.Fonts->SetTexID((void*)cloned_img); |     io.Fonts->SetTexID((void*)cloned_img); | ||||||
|     g_Texture = cloned_img; |     bd->Texture = cloned_img; | ||||||
|  |  | ||||||
|     // Create an invisible mouse cursor |     // Create an invisible mouse cursor | ||||||
|     // Because al_hide_mouse_cursor() seems to mess up with the actual inputs.. |     // Because al_hide_mouse_cursor() seems to mess up with the actual inputs.. | ||||||
|     ALLEGRO_BITMAP* mouse_cursor = al_create_bitmap(8, 8); |     ALLEGRO_BITMAP* mouse_cursor = al_create_bitmap(8, 8); | ||||||
|     g_MouseCursorInvisible = al_create_mouse_cursor(mouse_cursor, 0, 0); |     bd->MouseCursorInvisible = al_create_mouse_cursor(mouse_cursor, 0, 0); | ||||||
|     al_destroy_bitmap(mouse_cursor); |     al_destroy_bitmap(mouse_cursor); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| @@ -223,41 +237,48 @@ bool ImGui_ImplAllegro5_CreateDeviceObjects() | |||||||
|  |  | ||||||
| void ImGui_ImplAllegro5_InvalidateDeviceObjects() | void ImGui_ImplAllegro5_InvalidateDeviceObjects() | ||||||
| { | { | ||||||
|     if (g_Texture) |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|  |     if (bd->Texture) | ||||||
|     { |     { | ||||||
|         ImGuiIO& io = ImGui::GetIO(); |  | ||||||
|         io.Fonts->SetTexID(NULL); |         io.Fonts->SetTexID(NULL); | ||||||
|         al_destroy_bitmap(g_Texture); |         al_destroy_bitmap(bd->Texture); | ||||||
|         g_Texture = NULL; |         bd->Texture = NULL; | ||||||
|     } |     } | ||||||
|     if (g_MouseCursorInvisible) |     if (bd->MouseCursorInvisible) | ||||||
|     { |     { | ||||||
|         al_destroy_mouse_cursor(g_MouseCursorInvisible); |         al_destroy_mouse_cursor(bd->MouseCursorInvisible); | ||||||
|         g_MouseCursorInvisible = NULL; |         bd->MouseCursorInvisible = NULL; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #if ALLEGRO_HAS_CLIPBOARD | #if ALLEGRO_HAS_CLIPBOARD | ||||||
| static const char* ImGui_ImplAllegro5_GetClipboardText(void*) | static const char* ImGui_ImplAllegro5_GetClipboardText(void*) | ||||||
| { | { | ||||||
|     if (g_ClipboardTextData) |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|         al_free(g_ClipboardTextData); |     if (bd->ClipboardTextData) | ||||||
|     g_ClipboardTextData = al_get_clipboard_text(g_Display); |         al_free(bd->ClipboardTextData); | ||||||
|     return g_ClipboardTextData; |     bd->ClipboardTextData = al_get_clipboard_text(bd->Display); | ||||||
|  |     return bd->ClipboardTextData; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplAllegro5_SetClipboardText(void*, const char* text) | static void ImGui_ImplAllegro5_SetClipboardText(void*, const char* text) | ||||||
| { | { | ||||||
|     al_set_clipboard_text(g_Display, text); |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|  |     al_set_clipboard_text(bd->Display, text); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) | bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) | ||||||
| { | { | ||||||
|     g_Display = display; |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); | ||||||
|  |  | ||||||
|  |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_CreateBackendData(); | ||||||
|  |     bd->Display = display; | ||||||
|  |  | ||||||
|     // Setup backend capabilities flags |     // Setup backend capabilities flags | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     io.BackendRendererUserData = (void*)bd; | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;       // We can honor GetMouseCursor() values (optional) |     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;       // We can honor GetMouseCursor() values (optional) | ||||||
|     io.BackendPlatformName = io.BackendRendererName = "imgui_impl_allegro5"; |     io.BackendPlatformName = io.BackendRendererName = "imgui_impl_allegro5"; | ||||||
|  |  | ||||||
| @@ -271,7 +292,7 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) | |||||||
|         { ALLEGRO_PRIM_COLOR_ATTR, 0, IM_OFFSETOF(ImDrawVertAllegro, col) }, |         { ALLEGRO_PRIM_COLOR_ATTR, 0, IM_OFFSETOF(ImDrawVertAllegro, col) }, | ||||||
|         { 0, 0, 0 } |         { 0, 0, 0 } | ||||||
|     }; |     }; | ||||||
|     g_VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro)); |     bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro)); | ||||||
|  |  | ||||||
|     io.KeyMap[ImGuiKey_Tab] = ALLEGRO_KEY_TAB; |     io.KeyMap[ImGuiKey_Tab] = ALLEGRO_KEY_TAB; | ||||||
|     io.KeyMap[ImGuiKey_LeftArrow] = ALLEGRO_KEY_LEFT; |     io.KeyMap[ImGuiKey_LeftArrow] = ALLEGRO_KEY_LEFT; | ||||||
| @@ -308,18 +329,20 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) | |||||||
|  |  | ||||||
| void ImGui_ImplAllegro5_Shutdown() | void ImGui_ImplAllegro5_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|     ImGui_ImplAllegro5_InvalidateDeviceObjects(); |     ImGui_ImplAllegro5_InvalidateDeviceObjects(); | ||||||
|  |  | ||||||
|     g_Display = NULL; |     bd->Display = NULL; | ||||||
|     g_Time = 0.0; |     bd->Time = 0.0; | ||||||
|  |  | ||||||
|     if (g_VertexDecl) |     if (bd->VertexDecl) | ||||||
|         al_destroy_vertex_decl(g_VertexDecl); |         al_destroy_vertex_decl(bd->VertexDecl); | ||||||
|     g_VertexDecl = NULL; |     bd->VertexDecl = NULL; | ||||||
|  |  | ||||||
|     if (g_ClipboardTextData) |     if (bd->ClipboardTextData) | ||||||
|         al_free(g_ClipboardTextData); |         al_free(bd->ClipboardTextData); | ||||||
|     g_ClipboardTextData = NULL; |     bd->ClipboardTextData = NULL; | ||||||
|  |     ImGui_ImplAllegro5_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. | ||||||
| @@ -329,11 +352,12 @@ void ImGui_ImplAllegro5_Shutdown() | |||||||
| bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev) | bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev) | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|  |  | ||||||
|     switch (ev->type) |     switch (ev->type) | ||||||
|     { |     { | ||||||
|     case ALLEGRO_EVENT_MOUSE_AXES: |     case ALLEGRO_EVENT_MOUSE_AXES: | ||||||
|         if (ev->mouse.display == g_Display) |         if (ev->mouse.display == bd->Display) | ||||||
|         { |         { | ||||||
|             io.MouseWheel += ev->mouse.dz; |             io.MouseWheel += ev->mouse.dz; | ||||||
|             io.MouseWheelH -= ev->mouse.dw; |             io.MouseWheelH -= ev->mouse.dw; | ||||||
| @@ -342,31 +366,31 @@ bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev) | |||||||
|         return true; |         return true; | ||||||
|     case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: |     case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: | ||||||
|     case ALLEGRO_EVENT_MOUSE_BUTTON_UP: |     case ALLEGRO_EVENT_MOUSE_BUTTON_UP: | ||||||
|         if (ev->mouse.display == g_Display && ev->mouse.button <= 5) |         if (ev->mouse.display == bd->Display && ev->mouse.button <= 5) | ||||||
|             io.MouseDown[ev->mouse.button - 1] = (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN); |             io.MouseDown[ev->mouse.button - 1] = (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN); | ||||||
|         return true; |         return true; | ||||||
|     case ALLEGRO_EVENT_TOUCH_MOVE: |     case ALLEGRO_EVENT_TOUCH_MOVE: | ||||||
|         if (ev->touch.display == g_Display) |         if (ev->touch.display == bd->Display) | ||||||
|             io.MousePos = ImVec2(ev->touch.x, ev->touch.y); |             io.MousePos = ImVec2(ev->touch.x, ev->touch.y); | ||||||
|         return true; |         return true; | ||||||
|     case ALLEGRO_EVENT_TOUCH_BEGIN: |     case ALLEGRO_EVENT_TOUCH_BEGIN: | ||||||
|     case ALLEGRO_EVENT_TOUCH_END: |     case ALLEGRO_EVENT_TOUCH_END: | ||||||
|     case ALLEGRO_EVENT_TOUCH_CANCEL: |     case ALLEGRO_EVENT_TOUCH_CANCEL: | ||||||
|         if (ev->touch.display == g_Display && ev->touch.primary) |         if (ev->touch.display == bd->Display && ev->touch.primary) | ||||||
|             io.MouseDown[0] = (ev->type == ALLEGRO_EVENT_TOUCH_BEGIN); |             io.MouseDown[0] = (ev->type == ALLEGRO_EVENT_TOUCH_BEGIN); | ||||||
|         return true; |         return true; | ||||||
|     case ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY: |     case ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY: | ||||||
|         if (ev->mouse.display == g_Display) |         if (ev->mouse.display == bd->Display) | ||||||
|             io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); |             io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); | ||||||
|         return true; |         return true; | ||||||
|     case ALLEGRO_EVENT_KEY_CHAR: |     case ALLEGRO_EVENT_KEY_CHAR: | ||||||
|         if (ev->keyboard.display == g_Display) |         if (ev->keyboard.display == bd->Display) | ||||||
|             if (ev->keyboard.unichar != 0) |             if (ev->keyboard.unichar != 0) | ||||||
|                 io.AddInputCharacter((unsigned int)ev->keyboard.unichar); |                 io.AddInputCharacter((unsigned int)ev->keyboard.unichar); | ||||||
|         return true; |         return true; | ||||||
|     case ALLEGRO_EVENT_KEY_DOWN: |     case ALLEGRO_EVENT_KEY_DOWN: | ||||||
|     case ALLEGRO_EVENT_KEY_UP: |     case ALLEGRO_EVENT_KEY_UP: | ||||||
|         if (ev->keyboard.display == g_Display) |         if (ev->keyboard.display == bd->Display) | ||||||
|             io.KeysDown[ev->keyboard.keycode] = (ev->type == ALLEGRO_EVENT_KEY_DOWN); |             io.KeysDown[ev->keyboard.keycode] = (ev->type == ALLEGRO_EVENT_KEY_DOWN); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| @@ -379,11 +403,12 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor() | |||||||
|     if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) |     if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|  |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|     ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); |     ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); | ||||||
|     if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) |     if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) | ||||||
|     { |     { | ||||||
|         // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor |         // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor | ||||||
|         al_set_mouse_cursor(g_Display, g_MouseCursorInvisible); |         al_set_mouse_cursor(bd->Display, bd->MouseCursorInvisible); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
| @@ -398,27 +423,28 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor() | |||||||
|         case ImGuiMouseCursor_ResizeNWSE:   cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break; |         case ImGuiMouseCursor_ResizeNWSE:   cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break; | ||||||
|         case ImGuiMouseCursor_NotAllowed:   cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_UNAVAILABLE; break; |         case ImGuiMouseCursor_NotAllowed:   cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_UNAVAILABLE; break; | ||||||
|         } |         } | ||||||
|         al_set_system_mouse_cursor(g_Display, cursor_id); |         al_set_system_mouse_cursor(bd->Display, cursor_id); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplAllegro5_NewFrame() | void ImGui_ImplAllegro5_NewFrame() | ||||||
| { | { | ||||||
|     if (!g_Texture) |     ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); | ||||||
|  |     if (!bd->Texture) | ||||||
|         ImGui_ImplAllegro5_CreateDeviceObjects(); |         ImGui_ImplAllegro5_CreateDeviceObjects(); | ||||||
|  |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |  | ||||||
|     // Setup display size (every frame to accommodate for window resizing) |     // Setup display size (every frame to accommodate for window resizing) | ||||||
|     int w, h; |     int w, h; | ||||||
|     w = al_get_display_width(g_Display); |     w = al_get_display_width(bd->Display); | ||||||
|     h = al_get_display_height(g_Display); |     h = al_get_display_height(bd->Display); | ||||||
|     io.DisplaySize = ImVec2((float)w, (float)h); |     io.DisplaySize = ImVec2((float)w, (float)h); | ||||||
|  |  | ||||||
|     // Setup time step |     // Setup time step | ||||||
|     double current_time = al_get_time(); |     double current_time = al_get_time(); | ||||||
|     io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); |     io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); | ||||||
|     g_Time = current_time; |     bd->Time = current_time; | ||||||
|  |  | ||||||
|     // Setup inputs |     // Setup inputs | ||||||
|     ALLEGRO_KEYBOARD_STATE keys; |     ALLEGRO_KEYBOARD_STATE keys; | ||||||
|   | |||||||
| @@ -5,13 +5,14 @@ | |||||||
| //  [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! | //  [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! | ||||||
| //  [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. | //  [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. | ||||||
|  |  | ||||||
| // 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. | ||||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | ||||||
| // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | ||||||
| // Read online: https://github.com/ocornut/imgui/tree/master/docs | // Read online: https://github.com/ocornut/imgui/tree/master/docs | ||||||
|  |  | ||||||
| // 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) | ||||||
|  | //  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) | //  2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | ||||||
| //  2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer. | //  2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer. | ||||||
| //  2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData(). | //  2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData(). | ||||||
| @@ -40,28 +41,43 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // DirectX data | // DirectX data | ||||||
| static ID3D10Device*            g_pd3dDevice = NULL; | struct ImGui_ImplDX10_Data | ||||||
| static IDXGIFactory*            g_pFactory = NULL; | { | ||||||
| static ID3D10Buffer*            g_pVB = NULL; |     ID3D10Device*               pd3dDevice; | ||||||
| static ID3D10Buffer*            g_pIB = NULL; |     IDXGIFactory*               pFactory; | ||||||
| static ID3D10VertexShader*      g_pVertexShader = NULL; |     ID3D10Buffer*               pVB; | ||||||
| static ID3D10InputLayout*       g_pInputLayout = NULL; |     ID3D10Buffer*               pIB; | ||||||
| static ID3D10Buffer*            g_pVertexConstantBuffer = NULL; |     ID3D10VertexShader*         pVertexShader; | ||||||
| static ID3D10PixelShader*       g_pPixelShader = NULL; |     ID3D10InputLayout*          pInputLayout; | ||||||
| static ID3D10SamplerState*      g_pFontSampler = NULL; |     ID3D10Buffer*               pVertexConstantBuffer; | ||||||
| static ID3D10ShaderResourceView*g_pFontTextureView = NULL; |     ID3D10PixelShader*          pPixelShader; | ||||||
| static ID3D10RasterizerState*   g_pRasterizerState = NULL; |     ID3D10SamplerState*         pFontSampler; | ||||||
| static ID3D10BlendState*        g_pBlendState = NULL; |     ID3D10ShaderResourceView*   pFontTextureView; | ||||||
| static ID3D10DepthStencilState* g_pDepthStencilState = NULL; |     ID3D10RasterizerState*      pRasterizerState; | ||||||
| static int                      g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; |     ID3D10BlendState*           pBlendState; | ||||||
|  |     ID3D10DepthStencilState*    pDepthStencilState; | ||||||
|  |     int                         VertexBufferSize; | ||||||
|  |     int                         IndexBufferSize; | ||||||
|  |  | ||||||
|  |     ImGui_ImplDX10_Data()       { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplDX10_Data* g_Data; | ||||||
|  | static ImGui_ImplDX10_Data* ImGui_ImplDX10_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX10_Data); return g_Data; } | ||||||
|  | static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } | ||||||
|  | static void                 ImGui_ImplDX10_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| struct VERTEX_CONSTANT_BUFFER | struct VERTEX_CONSTANT_BUFFER | ||||||
| { | { | ||||||
|     float   mvp[4][4]; |     float   mvp[4][4]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | // Functions | ||||||
| static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx) | static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx) | ||||||
| { | { | ||||||
|  |     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); | ||||||
|  |  | ||||||
|     // Setup viewport |     // Setup viewport | ||||||
|     D3D10_VIEWPORT vp; |     D3D10_VIEWPORT vp; | ||||||
|     memset(&vp, 0, sizeof(D3D10_VIEWPORT)); |     memset(&vp, 0, sizeof(D3D10_VIEWPORT)); | ||||||
| @@ -75,21 +91,21 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* | |||||||
|     // Bind shader and vertex buffers |     // Bind shader and vertex buffers | ||||||
|     unsigned int stride = sizeof(ImDrawVert); |     unsigned int stride = sizeof(ImDrawVert); | ||||||
|     unsigned int offset = 0; |     unsigned int offset = 0; | ||||||
|     ctx->IASetInputLayout(g_pInputLayout); |     ctx->IASetInputLayout(bd->pInputLayout); | ||||||
|     ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); |     ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset); | ||||||
|     ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); |     ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); | ||||||
|     ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); |     ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); | ||||||
|     ctx->VSSetShader(g_pVertexShader); |     ctx->VSSetShader(bd->pVertexShader); | ||||||
|     ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); |     ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer); | ||||||
|     ctx->PSSetShader(g_pPixelShader); |     ctx->PSSetShader(bd->pPixelShader); | ||||||
|     ctx->PSSetSamplers(0, 1, &g_pFontSampler); |     ctx->PSSetSamplers(0, 1, &bd->pFontSampler); | ||||||
|     ctx->GSSetShader(NULL); |     ctx->GSSetShader(NULL); | ||||||
|  |  | ||||||
|     // Setup render state |     // Setup render state | ||||||
|     const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; |     const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; | ||||||
|     ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); |     ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff); | ||||||
|     ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); |     ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0); | ||||||
|     ctx->RSSetState(g_pRasterizerState); |     ctx->RSSetState(bd->pRasterizerState); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Render function | // Render function | ||||||
| @@ -99,43 +115,44 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) | |||||||
|     if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) |     if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     ID3D10Device* ctx = g_pd3dDevice; |     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); | ||||||
|  |     ID3D10Device* ctx = bd->pd3dDevice; | ||||||
|  |  | ||||||
|     // Create and grow vertex/index buffers if needed |     // Create and grow vertex/index buffers if needed | ||||||
|     if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) |     if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount) | ||||||
|     { |     { | ||||||
|         if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } |         if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; } | ||||||
|         g_VertexBufferSize = draw_data->TotalVtxCount + 5000; |         bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; | ||||||
|         D3D10_BUFFER_DESC desc; |         D3D10_BUFFER_DESC desc; | ||||||
|         memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); |         memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); | ||||||
|         desc.Usage = D3D10_USAGE_DYNAMIC; |         desc.Usage = D3D10_USAGE_DYNAMIC; | ||||||
|         desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); |         desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert); | ||||||
|         desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; |         desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; | ||||||
|         desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; |         desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; | ||||||
|         desc.MiscFlags = 0; |         desc.MiscFlags = 0; | ||||||
|         if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) |         if (ctx->CreateBuffer(&desc, NULL, &bd->pVB) < 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) |     if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount) | ||||||
|     { |     { | ||||||
|         if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } |         if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; } | ||||||
|         g_IndexBufferSize = draw_data->TotalIdxCount + 10000; |         bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; | ||||||
|         D3D10_BUFFER_DESC desc; |         D3D10_BUFFER_DESC desc; | ||||||
|         memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); |         memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); | ||||||
|         desc.Usage = D3D10_USAGE_DYNAMIC; |         desc.Usage = D3D10_USAGE_DYNAMIC; | ||||||
|         desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); |         desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx); | ||||||
|         desc.BindFlags = D3D10_BIND_INDEX_BUFFER; |         desc.BindFlags = D3D10_BIND_INDEX_BUFFER; | ||||||
|         desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; |         desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; | ||||||
|         if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) |         if (ctx->CreateBuffer(&desc, NULL, &bd->pIB) < 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Copy and convert all vertices into a single contiguous buffer |     // Copy and convert all vertices into a single contiguous buffer | ||||||
|     ImDrawVert* vtx_dst = NULL; |     ImDrawVert* vtx_dst = NULL; | ||||||
|     ImDrawIdx* idx_dst = NULL; |     ImDrawIdx* idx_dst = NULL; | ||||||
|     g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); |     bd->pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); | ||||||
|     g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); |     bd->pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); | ||||||
|     for (int n = 0; n < draw_data->CmdListsCount; n++) |     for (int n = 0; n < draw_data->CmdListsCount; n++) | ||||||
|     { |     { | ||||||
|         const ImDrawList* cmd_list = draw_data->CmdLists[n]; |         const ImDrawList* cmd_list = draw_data->CmdLists[n]; | ||||||
| @@ -144,14 +161,14 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) | |||||||
|         vtx_dst += cmd_list->VtxBuffer.Size; |         vtx_dst += cmd_list->VtxBuffer.Size; | ||||||
|         idx_dst += cmd_list->IdxBuffer.Size; |         idx_dst += cmd_list->IdxBuffer.Size; | ||||||
|     } |     } | ||||||
|     g_pVB->Unmap(); |     bd->pVB->Unmap(); | ||||||
|     g_pIB->Unmap(); |     bd->pIB->Unmap(); | ||||||
|  |  | ||||||
|     // Setup orthographic projection matrix into our constant buffer |     // Setup orthographic projection matrix into our constant buffer | ||||||
|     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. |     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. | ||||||
|     { |     { | ||||||
|         void* mapped_resource; |         void* mapped_resource; | ||||||
|         if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) |         if (bd->pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) | ||||||
|             return; |             return; | ||||||
|         VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; |         VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; | ||||||
|         float L = draw_data->DisplayPos.x; |         float L = draw_data->DisplayPos.x; | ||||||
| @@ -166,7 +183,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) | |||||||
|             { (R+L)/(L-R),  (T+B)/(B-T),    0.5f,       1.0f }, |             { (R+L)/(L-R),  (T+B)/(B-T),    0.5f,       1.0f }, | ||||||
|         }; |         }; | ||||||
|         memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); |         memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); | ||||||
|         g_pVertexConstantBuffer->Unmap(); |         bd->pVertexConstantBuffer->Unmap(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) |     // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) | ||||||
| @@ -270,6 +287,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) | |||||||
| static void ImGui_ImplDX10_CreateFontsTexture() | static void ImGui_ImplDX10_CreateFontsTexture() | ||||||
| { | { | ||||||
|     // Build texture atlas |     // Build texture atlas | ||||||
|  |     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     unsigned char* pixels; |     unsigned char* pixels; | ||||||
|     int width, height; |     int width, height; | ||||||
| @@ -294,7 +312,7 @@ static void ImGui_ImplDX10_CreateFontsTexture() | |||||||
|         subResource.pSysMem = pixels; |         subResource.pSysMem = pixels; | ||||||
|         subResource.SysMemPitch = desc.Width * 4; |         subResource.SysMemPitch = desc.Width * 4; | ||||||
|         subResource.SysMemSlicePitch = 0; |         subResource.SysMemSlicePitch = 0; | ||||||
|         g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); |         bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); | ||||||
|         IM_ASSERT(pTexture != NULL); |         IM_ASSERT(pTexture != NULL); | ||||||
|  |  | ||||||
|         // Create texture view |         // Create texture view | ||||||
| @@ -304,12 +322,12 @@ static void ImGui_ImplDX10_CreateFontsTexture() | |||||||
|         srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; |         srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; | ||||||
|         srv_desc.Texture2D.MipLevels = desc.MipLevels; |         srv_desc.Texture2D.MipLevels = desc.MipLevels; | ||||||
|         srv_desc.Texture2D.MostDetailedMip = 0; |         srv_desc.Texture2D.MostDetailedMip = 0; | ||||||
|         g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); |         bd->pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &bd->pFontTextureView); | ||||||
|         pTexture->Release(); |         pTexture->Release(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Store our identifier |     // Store our identifier | ||||||
|     io.Fonts->SetTexID((ImTextureID)g_pFontTextureView); |     io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView); | ||||||
|  |  | ||||||
|     // Create texture sampler |     // Create texture sampler | ||||||
|     { |     { | ||||||
| @@ -323,15 +341,16 @@ static void ImGui_ImplDX10_CreateFontsTexture() | |||||||
|         desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; |         desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; | ||||||
|         desc.MinLOD = 0.f; |         desc.MinLOD = 0.f; | ||||||
|         desc.MaxLOD = 0.f; |         desc.MaxLOD = 0.f; | ||||||
|         g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); |         bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| bool    ImGui_ImplDX10_CreateDeviceObjects() | bool    ImGui_ImplDX10_CreateDeviceObjects() | ||||||
| { | { | ||||||
|     if (!g_pd3dDevice) |     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); | ||||||
|  |     if (!bd->pd3dDevice) | ||||||
|         return false; |         return false; | ||||||
|     if (g_pFontSampler) |     if (bd->pFontSampler) | ||||||
|         ImGui_ImplDX10_InvalidateDeviceObjects(); |         ImGui_ImplDX10_InvalidateDeviceObjects(); | ||||||
|  |  | ||||||
|     // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) |     // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) | ||||||
| @@ -373,7 +392,7 @@ bool    ImGui_ImplDX10_CreateDeviceObjects() | |||||||
|         ID3DBlob* vertexShaderBlob; |         ID3DBlob* vertexShaderBlob; | ||||||
|         if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL))) |         if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL))) | ||||||
|             return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! |             return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! | ||||||
|         if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pVertexShader) != S_OK) |         if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pVertexShader) != S_OK) | ||||||
|         { |         { | ||||||
|             vertexShaderBlob->Release(); |             vertexShaderBlob->Release(); | ||||||
|             return false; |             return false; | ||||||
| @@ -386,7 +405,7 @@ bool    ImGui_ImplDX10_CreateDeviceObjects() | |||||||
|             { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,   0, (UINT)IM_OFFSETOF(ImDrawVert, uv),  D3D10_INPUT_PER_VERTEX_DATA, 0 }, |             { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,   0, (UINT)IM_OFFSETOF(ImDrawVert, uv),  D3D10_INPUT_PER_VERTEX_DATA, 0 }, | ||||||
|             { "COLOR",    0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, |             { "COLOR",    0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, | ||||||
|         }; |         }; | ||||||
|         if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) |         if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK) | ||||||
|         { |         { | ||||||
|             vertexShaderBlob->Release(); |             vertexShaderBlob->Release(); | ||||||
|             return false; |             return false; | ||||||
| @@ -401,7 +420,7 @@ bool    ImGui_ImplDX10_CreateDeviceObjects() | |||||||
|             desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; |             desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; | ||||||
|             desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; |             desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; | ||||||
|             desc.MiscFlags = 0; |             desc.MiscFlags = 0; | ||||||
|             g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); |             bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVertexConstantBuffer); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -426,7 +445,7 @@ bool    ImGui_ImplDX10_CreateDeviceObjects() | |||||||
|         ID3DBlob* pixelShaderBlob; |         ID3DBlob* pixelShaderBlob; | ||||||
|         if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL))) |         if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL))) | ||||||
|             return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! |             return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! | ||||||
|         if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), &g_pPixelShader) != S_OK) |         if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), &bd->pPixelShader) != S_OK) | ||||||
|         { |         { | ||||||
|             pixelShaderBlob->Release(); |             pixelShaderBlob->Release(); | ||||||
|             return false; |             return false; | ||||||
| @@ -447,7 +466,7 @@ bool    ImGui_ImplDX10_CreateDeviceObjects() | |||||||
|         desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; |         desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; | ||||||
|         desc.BlendOpAlpha = D3D10_BLEND_OP_ADD; |         desc.BlendOpAlpha = D3D10_BLEND_OP_ADD; | ||||||
|         desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; |         desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; | ||||||
|         g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); |         bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create the rasterizer state |     // Create the rasterizer state | ||||||
| @@ -458,7 +477,7 @@ bool    ImGui_ImplDX10_CreateDeviceObjects() | |||||||
|         desc.CullMode = D3D10_CULL_NONE; |         desc.CullMode = D3D10_CULL_NONE; | ||||||
|         desc.ScissorEnable = true; |         desc.ScissorEnable = true; | ||||||
|         desc.DepthClipEnable = true; |         desc.DepthClipEnable = true; | ||||||
|         g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); |         bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create depth-stencil State |     // Create depth-stencil State | ||||||
| @@ -472,7 +491,7 @@ bool    ImGui_ImplDX10_CreateDeviceObjects() | |||||||
|         desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP; |         desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP; | ||||||
|         desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS; |         desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS; | ||||||
|         desc.BackFace = desc.FrontFace; |         desc.BackFace = desc.FrontFace; | ||||||
|         g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); |         bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ImGui_ImplDX10_CreateFontsTexture(); |     ImGui_ImplDX10_CreateFontsTexture(); | ||||||
| @@ -482,27 +501,31 @@ bool    ImGui_ImplDX10_CreateDeviceObjects() | |||||||
|  |  | ||||||
| void    ImGui_ImplDX10_InvalidateDeviceObjects() | void    ImGui_ImplDX10_InvalidateDeviceObjects() | ||||||
| { | { | ||||||
|     if (!g_pd3dDevice) |     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); | ||||||
|  |     if (!bd->pd3dDevice) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } |     if (bd->pFontSampler)           { bd->pFontSampler->Release(); bd->pFontSampler = NULL; } | ||||||
|     if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. |     if (bd->pFontTextureView)       { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well. | ||||||
|     if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } |     if (bd->pIB)                    { bd->pIB->Release(); bd->pIB = NULL; } | ||||||
|     if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } |     if (bd->pVB)                    { bd->pVB->Release(); bd->pVB = NULL; } | ||||||
|  |     if (bd->pBlendState)            { bd->pBlendState->Release(); bd->pBlendState = NULL; } | ||||||
|     if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } |     if (bd->pDepthStencilState)     { bd->pDepthStencilState->Release(); bd->pDepthStencilState = NULL; } | ||||||
|     if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } |     if (bd->pRasterizerState)       { bd->pRasterizerState->Release(); bd->pRasterizerState = NULL; } | ||||||
|     if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } |     if (bd->pPixelShader)           { bd->pPixelShader->Release(); bd->pPixelShader = NULL; } | ||||||
|     if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } |     if (bd->pVertexConstantBuffer)  { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = NULL; } | ||||||
|     if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } |     if (bd->pInputLayout)           { bd->pInputLayout->Release(); bd->pInputLayout = NULL; } | ||||||
|     if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } |     if (bd->pVertexShader)          { bd->pVertexShader->Release(); bd->pVertexShader = NULL; } | ||||||
|     if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| bool    ImGui_ImplDX10_Init(ID3D10Device* device) | bool    ImGui_ImplDX10_Init(ID3D10Device* device) | ||||||
| { | { | ||||||
|     // Setup backend capabilities flags |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); | ||||||
|  |  | ||||||
|  |     // Setup backend capabilities flags | ||||||
|  |     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_CreateBackendData(); | ||||||
|  |     io.BackendRendererUserData = (void*)bd; | ||||||
|     io.BackendRendererName = "imgui_impl_dx10"; |     io.BackendRendererName = "imgui_impl_dx10"; | ||||||
|     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. | ||||||
|  |  | ||||||
| @@ -510,30 +533,36 @@ bool    ImGui_ImplDX10_Init(ID3D10Device* device) | |||||||
|     IDXGIDevice* pDXGIDevice = NULL; |     IDXGIDevice* pDXGIDevice = NULL; | ||||||
|     IDXGIAdapter* pDXGIAdapter = NULL; |     IDXGIAdapter* pDXGIAdapter = NULL; | ||||||
|     IDXGIFactory* pFactory = NULL; |     IDXGIFactory* pFactory = NULL; | ||||||
|  |  | ||||||
|     if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) |     if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) | ||||||
|         if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) |         if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) | ||||||
|             if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) |             if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) | ||||||
|             { |             { | ||||||
|                 g_pd3dDevice = device; |                 bd->pd3dDevice = device; | ||||||
|                 g_pFactory = pFactory; |                 bd->pFactory = pFactory; | ||||||
|             } |             } | ||||||
|     if (pDXGIDevice) pDXGIDevice->Release(); |     if (pDXGIDevice) pDXGIDevice->Release(); | ||||||
|     if (pDXGIAdapter) pDXGIAdapter->Release(); |     if (pDXGIAdapter) pDXGIAdapter->Release(); | ||||||
|     g_pd3dDevice->AddRef(); |     bd->pd3dDevice->AddRef(); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplDX10_Shutdown() | void ImGui_ImplDX10_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); | ||||||
|  |  | ||||||
|     ImGui_ImplDX10_InvalidateDeviceObjects(); |     ImGui_ImplDX10_InvalidateDeviceObjects(); | ||||||
|     if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; } |     if (bd->pFactory)       { bd->pFactory->Release(); bd->pFactory = NULL; } | ||||||
|     if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } |     if (bd->pd3dDevice)     { bd->pd3dDevice->Release(); bd->pd3dDevice = NULL; } | ||||||
|  |     io.BackendRendererName = NULL; | ||||||
|  |     io.BackendRendererUserData = NULL; | ||||||
|  |     ImGui_ImplDX10_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplDX10_NewFrame() | void ImGui_ImplDX10_NewFrame() | ||||||
| { | { | ||||||
|     if (!g_pFontSampler) |     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); | ||||||
|  |     if (!bd->pFontSampler) | ||||||
|         ImGui_ImplDX10_CreateDeviceObjects(); |         ImGui_ImplDX10_CreateDeviceObjects(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,13 +5,14 @@ | |||||||
| //  [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! | //  [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! | ||||||
| //  [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. | //  [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. | ||||||
|  |  | ||||||
| // 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. | ||||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | ||||||
| // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | ||||||
| // Read online: https://github.com/ocornut/imgui/tree/master/docs | // Read online: https://github.com/ocornut/imgui/tree/master/docs | ||||||
|  |  | ||||||
| // 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) | ||||||
|  | //  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: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | //  2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | ||||||
| //  2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer. | //  2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer. | ||||||
| //  2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). | //  2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). | ||||||
| @@ -39,30 +40,45 @@ | |||||||
| #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. | #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // DirectX data | // DirectX11 data | ||||||
| static ID3D11Device*            g_pd3dDevice = NULL; | struct ImGui_ImplDX11_Data | ||||||
| static ID3D11DeviceContext*     g_pd3dDeviceContext = NULL; | { | ||||||
| static IDXGIFactory*            g_pFactory = NULL; |     ID3D11Device*               pd3dDevice; | ||||||
| static ID3D11Buffer*            g_pVB = NULL; |     ID3D11DeviceContext*        pd3dDeviceContext; | ||||||
| static ID3D11Buffer*            g_pIB = NULL; |     IDXGIFactory*               pFactory; | ||||||
| static ID3D11VertexShader*      g_pVertexShader = NULL; |     ID3D11Buffer*               pVB; | ||||||
| static ID3D11InputLayout*       g_pInputLayout = NULL; |     ID3D11Buffer*               pIB; | ||||||
| static ID3D11Buffer*            g_pVertexConstantBuffer = NULL; |     ID3D11VertexShader*         pVertexShader; | ||||||
| static ID3D11PixelShader*       g_pPixelShader = NULL; |     ID3D11InputLayout*          pInputLayout; | ||||||
| static ID3D11SamplerState*      g_pFontSampler = NULL; |     ID3D11Buffer*               pVertexConstantBuffer; | ||||||
| static ID3D11ShaderResourceView*g_pFontTextureView = NULL; |     ID3D11PixelShader*          pPixelShader; | ||||||
| static ID3D11RasterizerState*   g_pRasterizerState = NULL; |     ID3D11SamplerState*         pFontSampler; | ||||||
| static ID3D11BlendState*        g_pBlendState = NULL; |     ID3D11ShaderResourceView*   pFontTextureView; | ||||||
| static ID3D11DepthStencilState* g_pDepthStencilState = NULL; |     ID3D11RasterizerState*      pRasterizerState; | ||||||
| static int                      g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; |     ID3D11BlendState*           pBlendState; | ||||||
|  |     ID3D11DepthStencilState*    pDepthStencilState; | ||||||
|  |     int                         VertexBufferSize; | ||||||
|  |     int                         IndexBufferSize; | ||||||
|  |  | ||||||
|  |     ImGui_ImplDX11_Data()       { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplDX11_Data* g_Data; | ||||||
|  | static ImGui_ImplDX11_Data* ImGui_ImplDX11_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX11_Data); return g_Data; } | ||||||
|  | static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } | ||||||
|  | static void                 ImGui_ImplDX11_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| struct VERTEX_CONSTANT_BUFFER | struct VERTEX_CONSTANT_BUFFER | ||||||
| { | { | ||||||
|     float   mvp[4][4]; |     float   mvp[4][4]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | // Functions | ||||||
| static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) | static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) | ||||||
| { | { | ||||||
|  |     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); | ||||||
|  |  | ||||||
|     // Setup viewport |     // Setup viewport | ||||||
|     D3D11_VIEWPORT vp; |     D3D11_VIEWPORT vp; | ||||||
|     memset(&vp, 0, sizeof(D3D11_VIEWPORT)); |     memset(&vp, 0, sizeof(D3D11_VIEWPORT)); | ||||||
| @@ -76,14 +92,14 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC | |||||||
|     // Setup shader and vertex buffers |     // Setup shader and vertex buffers | ||||||
|     unsigned int stride = sizeof(ImDrawVert); |     unsigned int stride = sizeof(ImDrawVert); | ||||||
|     unsigned int offset = 0; |     unsigned int offset = 0; | ||||||
|     ctx->IASetInputLayout(g_pInputLayout); |     ctx->IASetInputLayout(bd->pInputLayout); | ||||||
|     ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); |     ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset); | ||||||
|     ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); |     ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); | ||||||
|     ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); |     ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); | ||||||
|     ctx->VSSetShader(g_pVertexShader, NULL, 0); |     ctx->VSSetShader(bd->pVertexShader, NULL, 0); | ||||||
|     ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); |     ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer); | ||||||
|     ctx->PSSetShader(g_pPixelShader, NULL, 0); |     ctx->PSSetShader(bd->pPixelShader, NULL, 0); | ||||||
|     ctx->PSSetSamplers(0, 1, &g_pFontSampler); |     ctx->PSSetSamplers(0, 1, &bd->pFontSampler); | ||||||
|     ctx->GSSetShader(NULL, NULL, 0); |     ctx->GSSetShader(NULL, NULL, 0); | ||||||
|     ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. |     ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. | ||||||
|     ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. |     ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. | ||||||
| @@ -91,9 +107,9 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC | |||||||
|  |  | ||||||
|     // Setup blend state |     // Setup blend state | ||||||
|     const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; |     const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; | ||||||
|     ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); |     ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff); | ||||||
|     ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); |     ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0); | ||||||
|     ctx->RSSetState(g_pRasterizerState); |     ctx->RSSetState(bd->pRasterizerState); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Render function | // Render function | ||||||
| @@ -103,42 +119,43 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) | |||||||
|     if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) |     if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     ID3D11DeviceContext* ctx = g_pd3dDeviceContext; |     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); | ||||||
|  |     ID3D11DeviceContext* ctx = bd->pd3dDeviceContext; | ||||||
|  |  | ||||||
|     // Create and grow vertex/index buffers if needed |     // Create and grow vertex/index buffers if needed | ||||||
|     if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) |     if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount) | ||||||
|     { |     { | ||||||
|         if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } |         if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; } | ||||||
|         g_VertexBufferSize = draw_data->TotalVtxCount + 5000; |         bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; | ||||||
|         D3D11_BUFFER_DESC desc; |         D3D11_BUFFER_DESC desc; | ||||||
|         memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); |         memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); | ||||||
|         desc.Usage = D3D11_USAGE_DYNAMIC; |         desc.Usage = D3D11_USAGE_DYNAMIC; | ||||||
|         desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); |         desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert); | ||||||
|         desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; |         desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; | ||||||
|         desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; |         desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; | ||||||
|         desc.MiscFlags = 0; |         desc.MiscFlags = 0; | ||||||
|         if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) |         if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVB) < 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
|     if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) |     if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount) | ||||||
|     { |     { | ||||||
|         if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } |         if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; } | ||||||
|         g_IndexBufferSize = draw_data->TotalIdxCount + 10000; |         bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; | ||||||
|         D3D11_BUFFER_DESC desc; |         D3D11_BUFFER_DESC desc; | ||||||
|         memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); |         memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); | ||||||
|         desc.Usage = D3D11_USAGE_DYNAMIC; |         desc.Usage = D3D11_USAGE_DYNAMIC; | ||||||
|         desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); |         desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx); | ||||||
|         desc.BindFlags = D3D11_BIND_INDEX_BUFFER; |         desc.BindFlags = D3D11_BIND_INDEX_BUFFER; | ||||||
|         desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; |         desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; | ||||||
|         if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) |         if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pIB) < 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Upload vertex/index data into a single contiguous GPU buffer |     // Upload vertex/index data into a single contiguous GPU buffer | ||||||
|     D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; |     D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; | ||||||
|     if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) |     if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) | ||||||
|         return; |         return; | ||||||
|     if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) |     if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) | ||||||
|         return; |         return; | ||||||
|     ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; |     ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; | ||||||
|     ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; |     ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; | ||||||
| @@ -150,14 +167,14 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) | |||||||
|         vtx_dst += cmd_list->VtxBuffer.Size; |         vtx_dst += cmd_list->VtxBuffer.Size; | ||||||
|         idx_dst += cmd_list->IdxBuffer.Size; |         idx_dst += cmd_list->IdxBuffer.Size; | ||||||
|     } |     } | ||||||
|     ctx->Unmap(g_pVB, 0); |     ctx->Unmap(bd->pVB, 0); | ||||||
|     ctx->Unmap(g_pIB, 0); |     ctx->Unmap(bd->pIB, 0); | ||||||
|  |  | ||||||
|     // Setup orthographic projection matrix into our constant buffer |     // Setup orthographic projection matrix into our constant buffer | ||||||
|     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. |     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. | ||||||
|     { |     { | ||||||
|         D3D11_MAPPED_SUBRESOURCE mapped_resource; |         D3D11_MAPPED_SUBRESOURCE mapped_resource; | ||||||
|         if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) |         if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) | ||||||
|             return; |             return; | ||||||
|         VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; |         VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; | ||||||
|         float L = draw_data->DisplayPos.x; |         float L = draw_data->DisplayPos.x; | ||||||
| @@ -172,7 +189,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) | |||||||
|             { (R+L)/(L-R),  (T+B)/(B-T),    0.5f,       1.0f }, |             { (R+L)/(L-R),  (T+B)/(B-T),    0.5f,       1.0f }, | ||||||
|         }; |         }; | ||||||
|         memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); |         memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); | ||||||
|         ctx->Unmap(g_pVertexConstantBuffer, 0); |         ctx->Unmap(bd->pVertexConstantBuffer, 0); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) |     // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) | ||||||
| @@ -283,6 +300,7 @@ static void ImGui_ImplDX11_CreateFontsTexture() | |||||||
| { | { | ||||||
|     // Build texture atlas |     // Build texture atlas | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); | ||||||
|     unsigned char* pixels; |     unsigned char* pixels; | ||||||
|     int width, height; |     int width, height; | ||||||
|     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); |     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); | ||||||
| @@ -306,7 +324,7 @@ static void ImGui_ImplDX11_CreateFontsTexture() | |||||||
|         subResource.pSysMem = pixels; |         subResource.pSysMem = pixels; | ||||||
|         subResource.SysMemPitch = desc.Width * 4; |         subResource.SysMemPitch = desc.Width * 4; | ||||||
|         subResource.SysMemSlicePitch = 0; |         subResource.SysMemSlicePitch = 0; | ||||||
|         g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); |         bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); | ||||||
|         IM_ASSERT(pTexture != NULL); |         IM_ASSERT(pTexture != NULL); | ||||||
|  |  | ||||||
|         // Create texture view |         // Create texture view | ||||||
| @@ -316,12 +334,12 @@ static void ImGui_ImplDX11_CreateFontsTexture() | |||||||
|         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; |         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; | ||||||
|         srvDesc.Texture2D.MipLevels = desc.MipLevels; |         srvDesc.Texture2D.MipLevels = desc.MipLevels; | ||||||
|         srvDesc.Texture2D.MostDetailedMip = 0; |         srvDesc.Texture2D.MostDetailedMip = 0; | ||||||
|         g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); |         bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView); | ||||||
|         pTexture->Release(); |         pTexture->Release(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Store our identifier |     // Store our identifier | ||||||
|     io.Fonts->SetTexID((ImTextureID)g_pFontTextureView); |     io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView); | ||||||
|  |  | ||||||
|     // Create texture sampler |     // Create texture sampler | ||||||
|     { |     { | ||||||
| @@ -335,15 +353,16 @@ static void ImGui_ImplDX11_CreateFontsTexture() | |||||||
|         desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; |         desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; | ||||||
|         desc.MinLOD = 0.f; |         desc.MinLOD = 0.f; | ||||||
|         desc.MaxLOD = 0.f; |         desc.MaxLOD = 0.f; | ||||||
|         g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); |         bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| bool    ImGui_ImplDX11_CreateDeviceObjects() | bool    ImGui_ImplDX11_CreateDeviceObjects() | ||||||
| { | { | ||||||
|     if (!g_pd3dDevice) |     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); | ||||||
|  |     if (!bd->pd3dDevice) | ||||||
|         return false; |         return false; | ||||||
|     if (g_pFontSampler) |     if (bd->pFontSampler) | ||||||
|         ImGui_ImplDX11_InvalidateDeviceObjects(); |         ImGui_ImplDX11_InvalidateDeviceObjects(); | ||||||
|  |  | ||||||
|     // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) |     // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) | ||||||
| @@ -385,7 +404,7 @@ bool    ImGui_ImplDX11_CreateDeviceObjects() | |||||||
|         ID3DBlob* vertexShaderBlob; |         ID3DBlob* vertexShaderBlob; | ||||||
|         if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL))) |         if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL))) | ||||||
|             return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! |             return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! | ||||||
|         if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK) |         if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &bd->pVertexShader) != S_OK) | ||||||
|         { |         { | ||||||
|             vertexShaderBlob->Release(); |             vertexShaderBlob->Release(); | ||||||
|             return false; |             return false; | ||||||
| @@ -398,7 +417,7 @@ bool    ImGui_ImplDX11_CreateDeviceObjects() | |||||||
|             { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,   0, (UINT)IM_OFFSETOF(ImDrawVert, uv),  D3D11_INPUT_PER_VERTEX_DATA, 0 }, |             { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,   0, (UINT)IM_OFFSETOF(ImDrawVert, uv),  D3D11_INPUT_PER_VERTEX_DATA, 0 }, | ||||||
|             { "COLOR",    0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, |             { "COLOR",    0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, | ||||||
|         }; |         }; | ||||||
|         if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) |         if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK) | ||||||
|         { |         { | ||||||
|             vertexShaderBlob->Release(); |             vertexShaderBlob->Release(); | ||||||
|             return false; |             return false; | ||||||
| @@ -413,7 +432,7 @@ bool    ImGui_ImplDX11_CreateDeviceObjects() | |||||||
|             desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; |             desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; | ||||||
|             desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; |             desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; | ||||||
|             desc.MiscFlags = 0; |             desc.MiscFlags = 0; | ||||||
|             g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); |             bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVertexConstantBuffer); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -438,7 +457,7 @@ bool    ImGui_ImplDX11_CreateDeviceObjects() | |||||||
|         ID3DBlob* pixelShaderBlob; |         ID3DBlob* pixelShaderBlob; | ||||||
|         if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL))) |         if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL))) | ||||||
|             return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! |             return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! | ||||||
|         if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK) |         if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &bd->pPixelShader) != S_OK) | ||||||
|         { |         { | ||||||
|             pixelShaderBlob->Release(); |             pixelShaderBlob->Release(); | ||||||
|             return false; |             return false; | ||||||
| @@ -459,7 +478,7 @@ bool    ImGui_ImplDX11_CreateDeviceObjects() | |||||||
|         desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; |         desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; | ||||||
|         desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; |         desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; | ||||||
|         desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; |         desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; | ||||||
|         g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); |         bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create the rasterizer state |     // Create the rasterizer state | ||||||
| @@ -470,7 +489,7 @@ bool    ImGui_ImplDX11_CreateDeviceObjects() | |||||||
|         desc.CullMode = D3D11_CULL_NONE; |         desc.CullMode = D3D11_CULL_NONE; | ||||||
|         desc.ScissorEnable = true; |         desc.ScissorEnable = true; | ||||||
|         desc.DepthClipEnable = true; |         desc.DepthClipEnable = true; | ||||||
|         g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); |         bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create depth-stencil State |     // Create depth-stencil State | ||||||
| @@ -484,7 +503,7 @@ bool    ImGui_ImplDX11_CreateDeviceObjects() | |||||||
|         desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; |         desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; | ||||||
|         desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; |         desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; | ||||||
|         desc.BackFace = desc.FrontFace; |         desc.BackFace = desc.FrontFace; | ||||||
|         g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); |         bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ImGui_ImplDX11_CreateFontsTexture(); |     ImGui_ImplDX11_CreateFontsTexture(); | ||||||
| @@ -494,27 +513,31 @@ bool    ImGui_ImplDX11_CreateDeviceObjects() | |||||||
|  |  | ||||||
| void    ImGui_ImplDX11_InvalidateDeviceObjects() | void    ImGui_ImplDX11_InvalidateDeviceObjects() | ||||||
| { | { | ||||||
|     if (!g_pd3dDevice) |     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); | ||||||
|  |     if (!bd->pd3dDevice) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } |     if (bd->pFontSampler)           { bd->pFontSampler->Release(); bd->pFontSampler = NULL; } | ||||||
|     if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. |     if (bd->pFontTextureView)       { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. | ||||||
|     if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } |     if (bd->pIB)                    { bd->pIB->Release(); bd->pIB = NULL; } | ||||||
|     if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } |     if (bd->pVB)                    { bd->pVB->Release(); bd->pVB = NULL; } | ||||||
|  |     if (bd->pBlendState)            { bd->pBlendState->Release(); bd->pBlendState = NULL; } | ||||||
|     if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } |     if (bd->pDepthStencilState)     { bd->pDepthStencilState->Release(); bd->pDepthStencilState = NULL; } | ||||||
|     if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } |     if (bd->pRasterizerState)       { bd->pRasterizerState->Release(); bd->pRasterizerState = NULL; } | ||||||
|     if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } |     if (bd->pPixelShader)           { bd->pPixelShader->Release(); bd->pPixelShader = NULL; } | ||||||
|     if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } |     if (bd->pVertexConstantBuffer)  { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = NULL; } | ||||||
|     if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } |     if (bd->pInputLayout)           { bd->pInputLayout->Release(); bd->pInputLayout = NULL; } | ||||||
|     if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } |     if (bd->pVertexShader)          { bd->pVertexShader->Release(); bd->pVertexShader = NULL; } | ||||||
|     if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| bool    ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) | bool    ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) | ||||||
| { | { | ||||||
|     // Setup backend capabilities flags |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); | ||||||
|  |  | ||||||
|  |     // Setup backend capabilities flags | ||||||
|  |     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_CreateBackendData(); | ||||||
|  |     io.BackendRendererUserData = (void*)bd; | ||||||
|     io.BackendRendererName = "imgui_impl_dx11"; |     io.BackendRendererName = "imgui_impl_dx11"; | ||||||
|     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. | ||||||
|  |  | ||||||
| @@ -527,28 +550,35 @@ bool    ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_co | |||||||
|         if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) |         if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) | ||||||
|             if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) |             if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) | ||||||
|             { |             { | ||||||
|                 g_pd3dDevice = device; |                 bd->pd3dDevice = device; | ||||||
|                 g_pd3dDeviceContext = device_context; |                 bd->pd3dDeviceContext = device_context; | ||||||
|                 g_pFactory = pFactory; |                 bd->pFactory = pFactory; | ||||||
|             } |             } | ||||||
|     if (pDXGIDevice) pDXGIDevice->Release(); |     if (pDXGIDevice) pDXGIDevice->Release(); | ||||||
|     if (pDXGIAdapter) pDXGIAdapter->Release(); |     if (pDXGIAdapter) pDXGIAdapter->Release(); | ||||||
|     g_pd3dDevice->AddRef(); |     bd->pd3dDevice->AddRef(); | ||||||
|     g_pd3dDeviceContext->AddRef(); |     bd->pd3dDeviceContext->AddRef(); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplDX11_Shutdown() | void ImGui_ImplDX11_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); | ||||||
|  |  | ||||||
|     ImGui_ImplDX11_InvalidateDeviceObjects(); |     ImGui_ImplDX11_InvalidateDeviceObjects(); | ||||||
|     if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; } |     if (bd->pFactory)             { bd->pFactory->Release(); bd->pFactory = NULL; } | ||||||
|     if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } |     if (bd->pd3dDevice)           { bd->pd3dDevice->Release(); bd->pd3dDevice = NULL; } | ||||||
|     if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; } |     if (bd->pd3dDeviceContext)    { bd->pd3dDeviceContext->Release(); bd->pd3dDeviceContext = NULL; } | ||||||
|  |     io.BackendRendererName = NULL; | ||||||
|  |     io.BackendRendererUserData = NULL; | ||||||
|  |     ImGui_ImplDX11_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplDX11_NewFrame() | void ImGui_ImplDX11_NewFrame() | ||||||
| { | { | ||||||
|     if (!g_pFontSampler) |     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); | ||||||
|  |     if (!bd->pFontSampler) | ||||||
|         ImGui_ImplDX11_CreateDeviceObjects(); |         ImGui_ImplDX11_CreateDeviceObjects(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,6 +20,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) | ||||||
|  | //  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: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | //  2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | ||||||
| //  2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer. | //  2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer. | ||||||
| //  2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically. | //  2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically. | ||||||
| @@ -48,14 +49,6 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // DirectX data | // DirectX data | ||||||
| static ID3D12Device*                g_pd3dDevice = NULL; |  | ||||||
| static ID3D12RootSignature*         g_pRootSignature = NULL; |  | ||||||
| static ID3D12PipelineState*         g_pPipelineState = NULL; |  | ||||||
| static DXGI_FORMAT                  g_RTVFormat = DXGI_FORMAT_UNKNOWN; |  | ||||||
| static ID3D12Resource*              g_pFontTextureResource = NULL; |  | ||||||
| static D3D12_CPU_DESCRIPTOR_HANDLE  g_hFontSrvCpuDescHandle = {}; |  | ||||||
| static D3D12_GPU_DESCRIPTOR_HANDLE  g_hFontSrvGpuDescHandle = {}; |  | ||||||
|  |  | ||||||
| struct FrameResources | struct FrameResources | ||||||
| { | { | ||||||
|     ID3D12Resource*     IndexBuffer; |     ID3D12Resource*     IndexBuffer; | ||||||
| @@ -63,9 +56,29 @@ struct FrameResources | |||||||
|     int                 IndexBufferSize; |     int                 IndexBufferSize; | ||||||
|     int                 VertexBufferSize; |     int                 VertexBufferSize; | ||||||
| }; | }; | ||||||
| static FrameResources*  g_pFrameResources = NULL; |  | ||||||
| static UINT             g_numFramesInFlight = 0; | struct ImGui_ImplDX12_Data | ||||||
| static UINT             g_frameIndex = UINT_MAX; | { | ||||||
|  |     ID3D12Device*               pd3dDevice; | ||||||
|  |     ID3D12RootSignature*        pRootSignature; | ||||||
|  |     ID3D12PipelineState*        pPipelineState; | ||||||
|  |     DXGI_FORMAT                 RTVFormat; | ||||||
|  |     ID3D12Resource*             pFontTextureResource; | ||||||
|  |     D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle; | ||||||
|  |     D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle; | ||||||
|  |  | ||||||
|  |     FrameResources*             pFrameResources; | ||||||
|  |     UINT                        numFramesInFlight; | ||||||
|  |     UINT                        frameIndex; | ||||||
|  |  | ||||||
|  |     ImGui_ImplDX12_Data()       { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplDX12_Data* g_Data; | ||||||
|  | static ImGui_ImplDX12_Data* ImGui_ImplDX12_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX12_Data); return g_Data; } | ||||||
|  | static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } | ||||||
|  | static void                 ImGui_ImplDX12_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| template<typename T> | template<typename T> | ||||||
| static void SafeRelease(T*& res) | static void SafeRelease(T*& res) | ||||||
| @@ -82,6 +95,8 @@ struct VERTEX_CONSTANT_BUFFER | |||||||
|  |  | ||||||
| static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, FrameResources* fr) | static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, FrameResources* fr) | ||||||
| { | { | ||||||
|  |     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); | ||||||
|  |  | ||||||
|     // Setup orthographic projection matrix into our constant buffer |     // Setup orthographic projection matrix into our constant buffer | ||||||
|     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). |     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). | ||||||
|     VERTEX_CONSTANT_BUFFER vertex_constant_buffer; |     VERTEX_CONSTANT_BUFFER vertex_constant_buffer; | ||||||
| @@ -126,8 +141,8 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic | |||||||
|     ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; |     ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; | ||||||
|     ctx->IASetIndexBuffer(&ibv); |     ctx->IASetIndexBuffer(&ibv); | ||||||
|     ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); |     ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); | ||||||
|     ctx->SetPipelineState(g_pPipelineState); |     ctx->SetPipelineState(bd->pPipelineState); | ||||||
|     ctx->SetGraphicsRootSignature(g_pRootSignature); |     ctx->SetGraphicsRootSignature(bd->pRootSignature); | ||||||
|     ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0); |     ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0); | ||||||
|  |  | ||||||
|     // Setup blend factor |     // Setup blend factor | ||||||
| @@ -144,8 +159,9 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL | |||||||
|  |  | ||||||
|     // FIXME: I'm assuming that this only gets called once per frame! |     // FIXME: I'm assuming that this only gets called once per frame! | ||||||
|     // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. |     // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. | ||||||
|     g_frameIndex = g_frameIndex + 1; |     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); | ||||||
|     FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight]; |     bd->frameIndex = bd->frameIndex + 1; | ||||||
|  |     FrameResources* fr = &bd->pFrameResources[bd->frameIndex % bd->numFramesInFlight]; | ||||||
|  |  | ||||||
|     // Create and grow vertex/index buffers if needed |     // Create and grow vertex/index buffers if needed | ||||||
|     if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount) |     if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount) | ||||||
| @@ -168,7 +184,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL | |||||||
|         desc.SampleDesc.Count = 1; |         desc.SampleDesc.Count = 1; | ||||||
|         desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; |         desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; | ||||||
|         desc.Flags = D3D12_RESOURCE_FLAG_NONE; |         desc.Flags = D3D12_RESOURCE_FLAG_NONE; | ||||||
|         if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->VertexBuffer)) < 0) |         if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->VertexBuffer)) < 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
|     if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount) |     if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount) | ||||||
| @@ -191,7 +207,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL | |||||||
|         desc.SampleDesc.Count = 1; |         desc.SampleDesc.Count = 1; | ||||||
|         desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; |         desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; | ||||||
|         desc.Flags = D3D12_RESOURCE_FLAG_NONE; |         desc.Flags = D3D12_RESOURCE_FLAG_NONE; | ||||||
|         if (g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->IndexBuffer)) < 0) |         if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->IndexBuffer)) < 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -262,6 +278,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() | |||||||
| { | { | ||||||
|     // Build texture atlas |     // Build texture atlas | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); | ||||||
|     unsigned char* pixels; |     unsigned char* pixels; | ||||||
|     int width, height; |     int width, height; | ||||||
|     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); |     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); | ||||||
| @@ -289,7 +306,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() | |||||||
|         desc.Flags = D3D12_RESOURCE_FLAG_NONE; |         desc.Flags = D3D12_RESOURCE_FLAG_NONE; | ||||||
|  |  | ||||||
|         ID3D12Resource* pTexture = NULL; |         ID3D12Resource* pTexture = NULL; | ||||||
|         g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, |         bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, | ||||||
|             D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture)); |             D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture)); | ||||||
|  |  | ||||||
|         UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u); |         UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u); | ||||||
| @@ -311,7 +328,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() | |||||||
|         props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; |         props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; | ||||||
|  |  | ||||||
|         ID3D12Resource* uploadBuffer = NULL; |         ID3D12Resource* uploadBuffer = NULL; | ||||||
|         HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, |         HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, | ||||||
|             D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer)); |             D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer)); | ||||||
|         IM_ASSERT(SUCCEEDED(hr)); |         IM_ASSERT(SUCCEEDED(hr)); | ||||||
|  |  | ||||||
| @@ -346,7 +363,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() | |||||||
|         barrier.Transition.StateAfter  = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; |         barrier.Transition.StateAfter  = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; | ||||||
|  |  | ||||||
|         ID3D12Fence* fence = NULL; |         ID3D12Fence* fence = NULL; | ||||||
|         hr = g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); |         hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); | ||||||
|         IM_ASSERT(SUCCEEDED(hr)); |         IM_ASSERT(SUCCEEDED(hr)); | ||||||
|  |  | ||||||
|         HANDLE event = CreateEvent(0, 0, 0, 0); |         HANDLE event = CreateEvent(0, 0, 0, 0); | ||||||
| @@ -358,15 +375,15 @@ static void ImGui_ImplDX12_CreateFontsTexture() | |||||||
|         queueDesc.NodeMask = 1; |         queueDesc.NodeMask = 1; | ||||||
|  |  | ||||||
|         ID3D12CommandQueue* cmdQueue = NULL; |         ID3D12CommandQueue* cmdQueue = NULL; | ||||||
|         hr = g_pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue)); |         hr = bd->pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue)); | ||||||
|         IM_ASSERT(SUCCEEDED(hr)); |         IM_ASSERT(SUCCEEDED(hr)); | ||||||
|  |  | ||||||
|         ID3D12CommandAllocator* cmdAlloc = NULL; |         ID3D12CommandAllocator* cmdAlloc = NULL; | ||||||
|         hr = g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc)); |         hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc)); | ||||||
|         IM_ASSERT(SUCCEEDED(hr)); |         IM_ASSERT(SUCCEEDED(hr)); | ||||||
|  |  | ||||||
|         ID3D12GraphicsCommandList* cmdList = NULL; |         ID3D12GraphicsCommandList* cmdList = NULL; | ||||||
|         hr = g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList)); |         hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList)); | ||||||
|         IM_ASSERT(SUCCEEDED(hr)); |         IM_ASSERT(SUCCEEDED(hr)); | ||||||
|  |  | ||||||
|         cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL); |         cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL); | ||||||
| @@ -397,9 +414,9 @@ static void ImGui_ImplDX12_CreateFontsTexture() | |||||||
|         srvDesc.Texture2D.MipLevels = desc.MipLevels; |         srvDesc.Texture2D.MipLevels = desc.MipLevels; | ||||||
|         srvDesc.Texture2D.MostDetailedMip = 0; |         srvDesc.Texture2D.MostDetailedMip = 0; | ||||||
|         srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; |         srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; | ||||||
|         g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, g_hFontSrvCpuDescHandle); |         bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, bd->hFontSrvCpuDescHandle); | ||||||
|         SafeRelease(g_pFontTextureResource); |         SafeRelease(bd->pFontTextureResource); | ||||||
|         g_pFontTextureResource = pTexture; |         bd->pFontTextureResource = pTexture; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Store our identifier |     // Store our identifier | ||||||
| @@ -410,15 +427,18 @@ static void ImGui_ImplDX12_CreateFontsTexture() | |||||||
|     // [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like. |     // [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like. | ||||||
|     // [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!) |     // [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!) | ||||||
|     // [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in the example_win32_direct12/build_win32.bat file) |     // [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in the example_win32_direct12/build_win32.bat file) | ||||||
|     static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet."); |     static_assert(sizeof(ImTextureID) >= sizeof(bd->hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet."); | ||||||
|     io.Fonts->SetTexID((ImTextureID)g_hFontSrvGpuDescHandle.ptr); |     io.Fonts->SetTexID((ImTextureID)bd->hFontSrvGpuDescHandle.ptr); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool    ImGui_ImplDX12_CreateDeviceObjects() | bool    ImGui_ImplDX12_CreateDeviceObjects() | ||||||
| { | { | ||||||
|     if (!g_pd3dDevice) |     if (ImGui::GetCurrentContext() == NULL) | ||||||
|         return false; |         return false; | ||||||
|     if (g_pPipelineState) |     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); | ||||||
|  |     if (!bd->pd3dDevice) | ||||||
|  |         return false; | ||||||
|  |     if (bd->pPipelineState) | ||||||
|         ImGui_ImplDX12_InvalidateDeviceObjects(); |         ImGui_ImplDX12_InvalidateDeviceObjects(); | ||||||
|  |  | ||||||
|     // Create the root signature |     // Create the root signature | ||||||
| @@ -499,7 +519,7 @@ bool    ImGui_ImplDX12_CreateDeviceObjects() | |||||||
|         if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK) |         if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK) | ||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
|         g_pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&g_pRootSignature)); |         bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature)); | ||||||
|         blob->Release(); |         blob->Release(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -513,10 +533,10 @@ bool    ImGui_ImplDX12_CreateDeviceObjects() | |||||||
|     memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC)); |     memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC)); | ||||||
|     psoDesc.NodeMask = 1; |     psoDesc.NodeMask = 1; | ||||||
|     psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; |     psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; | ||||||
|     psoDesc.pRootSignature = g_pRootSignature; |     psoDesc.pRootSignature = bd->pRootSignature; | ||||||
|     psoDesc.SampleMask = UINT_MAX; |     psoDesc.SampleMask = UINT_MAX; | ||||||
|     psoDesc.NumRenderTargets = 1; |     psoDesc.NumRenderTargets = 1; | ||||||
|     psoDesc.RTVFormats[0] = g_RTVFormat; |     psoDesc.RTVFormats[0] = bd->RTVFormat; | ||||||
|     psoDesc.SampleDesc.Count = 1; |     psoDesc.SampleDesc.Count = 1; | ||||||
|     psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; |     psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; | ||||||
|  |  | ||||||
| @@ -635,7 +655,7 @@ bool    ImGui_ImplDX12_CreateDeviceObjects() | |||||||
|         desc.BackFace = desc.FrontFace; |         desc.BackFace = desc.FrontFace; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     HRESULT result_pipeline_state = g_pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&g_pPipelineState)); |     HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineState)); | ||||||
|     vertexShaderBlob->Release(); |     vertexShaderBlob->Release(); | ||||||
|     pixelShaderBlob->Release(); |     pixelShaderBlob->Release(); | ||||||
|     if (result_pipeline_state != S_OK) |     if (result_pipeline_state != S_OK) | ||||||
| @@ -648,19 +668,21 @@ bool    ImGui_ImplDX12_CreateDeviceObjects() | |||||||
|  |  | ||||||
| void    ImGui_ImplDX12_InvalidateDeviceObjects() | void    ImGui_ImplDX12_InvalidateDeviceObjects() | ||||||
| { | { | ||||||
|     if (!g_pd3dDevice) |     if (ImGui::GetCurrentContext() == NULL) | ||||||
|  |         return; | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); | ||||||
|  |     if (!bd->pd3dDevice) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     SafeRelease(g_pRootSignature); |     SafeRelease(bd->pRootSignature); | ||||||
|     SafeRelease(g_pPipelineState); |     SafeRelease(bd->pPipelineState); | ||||||
|     SafeRelease(g_pFontTextureResource); |     SafeRelease(bd->pFontTextureResource); | ||||||
|  |     io.Fonts->SetTexID(NULL); // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well. | ||||||
|  |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     for (UINT i = 0; i < bd->numFramesInFlight; i++) | ||||||
|     io.Fonts->SetTexID(NULL); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. |  | ||||||
|  |  | ||||||
|     for (UINT i = 0; i < g_numFramesInFlight; i++) |  | ||||||
|     { |     { | ||||||
|         FrameResources* fr = &g_pFrameResources[i]; |         FrameResources* fr = &bd->pFrameResources[i]; | ||||||
|         SafeRelease(fr->IndexBuffer); |         SafeRelease(fr->IndexBuffer); | ||||||
|         SafeRelease(fr->VertexBuffer); |         SafeRelease(fr->VertexBuffer); | ||||||
|     } |     } | ||||||
| @@ -669,24 +691,28 @@ void    ImGui_ImplDX12_InvalidateDeviceObjects() | |||||||
| bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap, | bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap, | ||||||
|                          D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) |                          D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) | ||||||
| { | { | ||||||
|     // Setup backend capabilities flags |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); | ||||||
|  |  | ||||||
|  |     // Setup backend capabilities flags | ||||||
|  |     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_CreateBackendData(); | ||||||
|  |     io.BackendRendererUserData = (void*)bd; | ||||||
|     io.BackendRendererName = "imgui_impl_dx12"; |     io.BackendRendererName = "imgui_impl_dx12"; | ||||||
|     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. | ||||||
|  |  | ||||||
|     g_pd3dDevice = device; |     bd->pd3dDevice = device; | ||||||
|     g_RTVFormat = rtv_format; |     bd->RTVFormat = rtv_format; | ||||||
|     g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle; |     bd->hFontSrvCpuDescHandle = font_srv_cpu_desc_handle; | ||||||
|     g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle; |     bd->hFontSrvGpuDescHandle = font_srv_gpu_desc_handle; | ||||||
|     g_pFrameResources = new FrameResources[num_frames_in_flight]; |     bd->pFrameResources = new FrameResources[num_frames_in_flight]; | ||||||
|     g_numFramesInFlight = num_frames_in_flight; |     bd->numFramesInFlight = num_frames_in_flight; | ||||||
|     g_frameIndex = UINT_MAX; |     bd->frameIndex = UINT_MAX; | ||||||
|     IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports) |     IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports) | ||||||
|  |  | ||||||
|     // Create buffers with a default size (they will later be grown as needed) |     // Create buffers with a default size (they will later be grown as needed) | ||||||
|     for (int i = 0; i < num_frames_in_flight; i++) |     for (int i = 0; i < num_frames_in_flight; i++) | ||||||
|     { |     { | ||||||
|         FrameResources* fr = &g_pFrameResources[i]; |         FrameResources* fr = &bd->pFrameResources[i]; | ||||||
|         fr->IndexBuffer = NULL; |         fr->IndexBuffer = NULL; | ||||||
|         fr->VertexBuffer = NULL; |         fr->VertexBuffer = NULL; | ||||||
|         fr->IndexBufferSize = 10000; |         fr->IndexBufferSize = 10000; | ||||||
| @@ -698,18 +724,25 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO | |||||||
|  |  | ||||||
| void ImGui_ImplDX12_Shutdown() | void ImGui_ImplDX12_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); | ||||||
|  |  | ||||||
|     ImGui_ImplDX12_InvalidateDeviceObjects(); |     ImGui_ImplDX12_InvalidateDeviceObjects(); | ||||||
|     delete[] g_pFrameResources; |     delete[] bd->pFrameResources; | ||||||
|     g_pFrameResources = NULL; |     bd->pFrameResources = NULL; | ||||||
|     g_pd3dDevice = NULL; |     bd->pd3dDevice = NULL; | ||||||
|     g_hFontSrvCpuDescHandle.ptr = 0; |     bd->hFontSrvCpuDescHandle.ptr = 0; | ||||||
|     g_hFontSrvGpuDescHandle.ptr = 0; |     bd->hFontSrvGpuDescHandle.ptr = 0; | ||||||
|     g_numFramesInFlight = 0; |     bd->numFramesInFlight = 0; | ||||||
|     g_frameIndex = UINT_MAX; |     bd->frameIndex = UINT_MAX; | ||||||
|  |     io.BackendRendererName = NULL; | ||||||
|  |     io.BackendRendererUserData = NULL; | ||||||
|  |     ImGui_ImplDX12_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplDX12_NewFrame() | void ImGui_ImplDX12_NewFrame() | ||||||
| { | { | ||||||
|     if (!g_pPipelineState) |     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); | ||||||
|  |     if (!bd->pPipelineState) | ||||||
|         ImGui_ImplDX12_CreateDeviceObjects(); |         ImGui_ImplDX12_CreateDeviceObjects(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,6 +12,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) | ||||||
|  | //  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-06-25: DirectX9: Explicitly disable texture state stages after >= 1. | //  2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1. | ||||||
| //  2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | //  2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | ||||||
| //  2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states. | //  2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states. | ||||||
| @@ -36,11 +37,23 @@ | |||||||
| #include <d3d9.h> | #include <d3d9.h> | ||||||
|  |  | ||||||
| // DirectX data | // DirectX data | ||||||
| static LPDIRECT3DDEVICE9        g_pd3dDevice = NULL; | struct ImGui_ImplDX9_Data | ||||||
| static LPDIRECT3DVERTEXBUFFER9  g_pVB = NULL; | { | ||||||
| static LPDIRECT3DINDEXBUFFER9   g_pIB = NULL; |     LPDIRECT3DDEVICE9           pd3dDevice; | ||||||
| static LPDIRECT3DTEXTURE9       g_FontTexture = NULL; |     LPDIRECT3DVERTEXBUFFER9     pVB; | ||||||
| static int                      g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; |     LPDIRECT3DINDEXBUFFER9      pIB; | ||||||
|  |     LPDIRECT3DTEXTURE9          FontTexture; | ||||||
|  |     int                         VertexBufferSize; | ||||||
|  |     int                         IndexBufferSize; | ||||||
|  |  | ||||||
|  |     ImGui_ImplDX9_Data()        { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplDX9_Data*  g_Data; | ||||||
|  | static ImGui_ImplDX9_Data*  ImGui_ImplDX9_CreateBackendData()   { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplDX9_Data); return g_Data; } | ||||||
|  | static ImGui_ImplDX9_Data*  ImGui_ImplDX9_GetBackendData()      { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } | ||||||
|  | static void                 ImGui_ImplDX9_DestroyBackendData()  { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| struct CUSTOMVERTEX | struct CUSTOMVERTEX | ||||||
| { | { | ||||||
| @@ -56,8 +69,11 @@ struct CUSTOMVERTEX | |||||||
| #define IMGUI_COL_TO_DX9_ARGB(_COL)     (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16)) | #define IMGUI_COL_TO_DX9_ARGB(_COL)     (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16)) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | // Functions | ||||||
| static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) | static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) | ||||||
| { | { | ||||||
|  |     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); | ||||||
|  |  | ||||||
|     // Setup viewport |     // Setup viewport | ||||||
|     D3DVIEWPORT9 vp; |     D3DVIEWPORT9 vp; | ||||||
|     vp.X = vp.Y = 0; |     vp.X = vp.Y = 0; | ||||||
| @@ -65,41 +81,41 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) | |||||||
|     vp.Height = (DWORD)draw_data->DisplaySize.y; |     vp.Height = (DWORD)draw_data->DisplaySize.y; | ||||||
|     vp.MinZ = 0.0f; |     vp.MinZ = 0.0f; | ||||||
|     vp.MaxZ = 1.0f; |     vp.MaxZ = 1.0f; | ||||||
|     g_pd3dDevice->SetViewport(&vp); |     bd->pd3dDevice->SetViewport(&vp); | ||||||
|  |  | ||||||
|     // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient) |     // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient) | ||||||
|     g_pd3dDevice->SetPixelShader(NULL); |     bd->pd3dDevice->SetPixelShader(NULL); | ||||||
|     g_pd3dDevice->SetVertexShader(NULL); |     bd->pd3dDevice->SetVertexShader(NULL); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); |     bd->pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); |     bd->pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); |     bd->pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); |     bd->pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); |     bd->pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE); |     bd->pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); |     bd->pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); |     bd->pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); |     bd->pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); |     bd->pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); |     bd->pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); |     bd->pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA); |     bd->pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); |     bd->pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); |     bd->pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE); |     bd->pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE); |     bd->pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); |     bd->pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE); |     bd->pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE); | ||||||
|     g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); |     bd->pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); | ||||||
|     g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); |     bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); | ||||||
|     g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); |     bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); | ||||||
|     g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); |     bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); | ||||||
|     g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); |     bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); | ||||||
|     g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); |     bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); | ||||||
|     g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); |     bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); | ||||||
|     g_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); |     bd->pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); | ||||||
|     g_pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); |     bd->pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); | ||||||
|     g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); |     bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); | ||||||
|     g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); |     bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); | ||||||
|  |  | ||||||
|     // Setup orthographic projection matrix |     // Setup orthographic projection matrix | ||||||
|     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. |     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. | ||||||
| @@ -117,9 +133,9 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) | |||||||
|             0.0f,         0.0f,         0.5f,  0.0f, |             0.0f,         0.0f,         0.5f,  0.0f, | ||||||
|             (L+R)/(L-R),  (T+B)/(B-T),  0.5f,  1.0f |             (L+R)/(L-R),  (T+B)/(B-T),  0.5f,  1.0f | ||||||
|         } } }; |         } } }; | ||||||
|         g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); |         bd->pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); | ||||||
|         g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); |         bd->pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); | ||||||
|         g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); |         bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -131,24 +147,25 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) | |||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     // Create and grow buffers if needed |     // Create and grow buffers if needed | ||||||
|     if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) |     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); | ||||||
|  |     if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount) | ||||||
|     { |     { | ||||||
|         if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } |         if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; } | ||||||
|         g_VertexBufferSize = draw_data->TotalVtxCount + 5000; |         bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; | ||||||
|         if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) |         if (bd->pd3dDevice->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, NULL) < 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
|     if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) |     if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount) | ||||||
|     { |     { | ||||||
|         if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } |         if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; } | ||||||
|         g_IndexBufferSize = draw_data->TotalIdxCount + 10000; |         bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; | ||||||
|         if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0) |         if (bd->pd3dDevice->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, NULL) < 0) | ||||||
|             return; |             return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Backup the DX9 state |     // Backup the DX9 state | ||||||
|     IDirect3DStateBlock9* d3d9_state_block = NULL; |     IDirect3DStateBlock9* d3d9_state_block = NULL; | ||||||
|     if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0) |     if (bd->pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0) | ||||||
|         return; |         return; | ||||||
|     if (d3d9_state_block->Capture() < 0) |     if (d3d9_state_block->Capture() < 0) | ||||||
|     { |     { | ||||||
| @@ -158,21 +175,21 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) | |||||||
|  |  | ||||||
|     // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to) |     // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to) | ||||||
|     D3DMATRIX last_world, last_view, last_projection; |     D3DMATRIX last_world, last_view, last_projection; | ||||||
|     g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world); |     bd->pd3dDevice->GetTransform(D3DTS_WORLD, &last_world); | ||||||
|     g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view); |     bd->pd3dDevice->GetTransform(D3DTS_VIEW, &last_view); | ||||||
|     g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection); |     bd->pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection); | ||||||
|  |  | ||||||
|     // Allocate buffers |     // Allocate buffers | ||||||
|     CUSTOMVERTEX* vtx_dst; |     CUSTOMVERTEX* vtx_dst; | ||||||
|     ImDrawIdx* idx_dst; |     ImDrawIdx* idx_dst; | ||||||
|     if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) |     if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) | ||||||
|     { |     { | ||||||
|         d3d9_state_block->Release(); |         d3d9_state_block->Release(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0) |     if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0) | ||||||
|     { |     { | ||||||
|         g_pVB->Unlock(); |         bd->pVB->Unlock(); | ||||||
|         d3d9_state_block->Release(); |         d3d9_state_block->Release(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -199,11 +216,11 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) | |||||||
|         memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); |         memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); | ||||||
|         idx_dst += cmd_list->IdxBuffer.Size; |         idx_dst += cmd_list->IdxBuffer.Size; | ||||||
|     } |     } | ||||||
|     g_pVB->Unlock(); |     bd->pVB->Unlock(); | ||||||
|     g_pIB->Unlock(); |     bd->pIB->Unlock(); | ||||||
|     g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX)); |     bd->pd3dDevice->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX)); | ||||||
|     g_pd3dDevice->SetIndices(g_pIB); |     bd->pd3dDevice->SetIndices(bd->pIB); | ||||||
|     g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); |     bd->pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); | ||||||
|  |  | ||||||
|     // Setup desired DX state |     // Setup desired DX state | ||||||
|     ImGui_ImplDX9_SetupRenderState(draw_data); |     ImGui_ImplDX9_SetupRenderState(draw_data); | ||||||
| @@ -232,9 +249,9 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) | |||||||
|             { |             { | ||||||
|                 const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; |                 const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; | ||||||
|                 const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID(); |                 const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID(); | ||||||
|                 g_pd3dDevice->SetTexture(0, texture); |                 bd->pd3dDevice->SetTexture(0, texture); | ||||||
|                 g_pd3dDevice->SetScissorRect(&r); |                 bd->pd3dDevice->SetScissorRect(&r); | ||||||
|                 g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3); |                 bd->pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         global_idx_offset += cmd_list->IdxBuffer.Size; |         global_idx_offset += cmd_list->IdxBuffer.Size; | ||||||
| @@ -242,9 +259,9 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Restore the DX9 transform |     // Restore the DX9 transform | ||||||
|     g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world); |     bd->pd3dDevice->SetTransform(D3DTS_WORLD, &last_world); | ||||||
|     g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view); |     bd->pd3dDevice->SetTransform(D3DTS_VIEW, &last_view); | ||||||
|     g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection); |     bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection); | ||||||
|  |  | ||||||
|     // Restore the DX9 state |     // Restore the DX9 state | ||||||
|     d3d9_state_block->Apply(); |     d3d9_state_block->Apply(); | ||||||
| @@ -253,26 +270,38 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) | |||||||
|  |  | ||||||
| bool ImGui_ImplDX9_Init(IDirect3DDevice9* device) | bool ImGui_ImplDX9_Init(IDirect3DDevice9* device) | ||||||
| { | { | ||||||
|     // Setup backend capabilities flags |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); | ||||||
|  |  | ||||||
|  |     // Setup backend capabilities flags | ||||||
|  |     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_CreateBackendData(); | ||||||
|  |     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. | ||||||
|  |  | ||||||
|     g_pd3dDevice = device; |     bd->pd3dDevice = device; | ||||||
|     g_pd3dDevice->AddRef(); |     bd->pd3dDevice->AddRef(); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplDX9_Shutdown() | void ImGui_ImplDX9_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); | ||||||
|  |  | ||||||
|     ImGui_ImplDX9_InvalidateDeviceObjects(); |     ImGui_ImplDX9_InvalidateDeviceObjects(); | ||||||
|     if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } |     if (bd->pd3dDevice) { bd->pd3dDevice->Release(); bd->pd3dDevice = NULL; } | ||||||
|  |     io.BackendRendererName = NULL; | ||||||
|  |     io.BackendRendererUserData = NULL; | ||||||
|  |     ImGui_ImplDX9_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| static bool ImGui_ImplDX9_CreateFontsTexture() | static bool ImGui_ImplDX9_CreateFontsTexture() | ||||||
| { | { | ||||||
|     // Build texture atlas |     // Build texture atlas | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); | ||||||
|     unsigned char* pixels; |     unsigned char* pixels; | ||||||
|     int width, height, bytes_per_pixel; |     int width, height, bytes_per_pixel; | ||||||
|     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel); |     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel); | ||||||
| @@ -289,18 +318,18 @@ static bool ImGui_ImplDX9_CreateFontsTexture() | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     // Upload texture to graphics system |     // Upload texture to graphics system | ||||||
|     g_FontTexture = NULL; |     bd->FontTexture = NULL; | ||||||
|     if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0) |     if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, NULL) < 0) | ||||||
|         return false; |         return false; | ||||||
|     D3DLOCKED_RECT tex_locked_rect; |     D3DLOCKED_RECT tex_locked_rect; | ||||||
|     if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) |     if (bd->FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) | ||||||
|         return false; |         return false; | ||||||
|     for (int y = 0; y < height; y++) |     for (int y = 0; y < height; y++) | ||||||
|         memcpy((unsigned char*)tex_locked_rect.pBits + (size_t)tex_locked_rect.Pitch * y, pixels + (size_t)width * bytes_per_pixel * y, (size_t)width * bytes_per_pixel); |         memcpy((unsigned char*)tex_locked_rect.pBits + (size_t)tex_locked_rect.Pitch * y, pixels + (size_t)width * bytes_per_pixel * y, (size_t)width * bytes_per_pixel); | ||||||
|     g_FontTexture->UnlockRect(0); |     bd->FontTexture->UnlockRect(0); | ||||||
|  |  | ||||||
|     // Store our identifier |     // Store our identifier | ||||||
|     io.Fonts->SetTexID((ImTextureID)g_FontTexture); |     io.Fonts->SetTexID((ImTextureID)bd->FontTexture); | ||||||
|  |  | ||||||
| #ifndef IMGUI_USE_BGRA_PACKED_COLOR | #ifndef IMGUI_USE_BGRA_PACKED_COLOR | ||||||
|     if (io.Fonts->TexPixelsUseColors) |     if (io.Fonts->TexPixelsUseColors) | ||||||
| @@ -312,7 +341,8 @@ static bool ImGui_ImplDX9_CreateFontsTexture() | |||||||
|  |  | ||||||
| bool ImGui_ImplDX9_CreateDeviceObjects() | bool ImGui_ImplDX9_CreateDeviceObjects() | ||||||
| { | { | ||||||
|     if (!g_pd3dDevice) |     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); | ||||||
|  |     if (!bd || !bd->pd3dDevice) | ||||||
|         return false; |         return false; | ||||||
|     if (!ImGui_ImplDX9_CreateFontsTexture()) |     if (!ImGui_ImplDX9_CreateFontsTexture()) | ||||||
|         return false; |         return false; | ||||||
| @@ -321,15 +351,17 @@ bool ImGui_ImplDX9_CreateDeviceObjects() | |||||||
|  |  | ||||||
| void ImGui_ImplDX9_InvalidateDeviceObjects() | void ImGui_ImplDX9_InvalidateDeviceObjects() | ||||||
| { | { | ||||||
|     if (!g_pd3dDevice) |     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); | ||||||
|  |     if (!bd || !bd->pd3dDevice) | ||||||
|         return; |         return; | ||||||
|     if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } |     if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; } | ||||||
|     if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } |     if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; } | ||||||
|     if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. |     if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well. | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplDX9_NewFrame() | void ImGui_ImplDX9_NewFrame() | ||||||
| { | { | ||||||
|     if (!g_FontTexture) |     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData(); | ||||||
|  |     if (!bd->FontTexture) | ||||||
|         ImGui_ImplDX9_CreateDeviceObjects(); |         ImGui_ImplDX9_CreateDeviceObjects(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,13 +9,14 @@ | |||||||
| //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). | //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). | ||||||
| //  [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE). | //  [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE). | ||||||
|  |  | ||||||
| // 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. | ||||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | ||||||
| // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | ||||||
| // Read online: https://github.com/ocornut/imgui/tree/master/docs | // Read online: https://github.com/ocornut/imgui/tree/master/docs | ||||||
|  |  | ||||||
| // 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) | ||||||
|  | //  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). | ||||||
| //  2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors. | //  2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors. | ||||||
| //  2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor). | //  2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor). | ||||||
| //  2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown. | //  2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown. | ||||||
| @@ -59,26 +60,39 @@ | |||||||
| #define GLFW_HAS_NEW_CURSORS          (0) | #define GLFW_HAS_NEW_CURSORS          (0) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Data | // GLFW data | ||||||
| enum GlfwClientApi | enum GlfwClientApi | ||||||
| { | { | ||||||
|     GlfwClientApi_Unknown, |     GlfwClientApi_Unknown, | ||||||
|     GlfwClientApi_OpenGL, |     GlfwClientApi_OpenGL, | ||||||
|     GlfwClientApi_Vulkan |     GlfwClientApi_Vulkan | ||||||
| }; | }; | ||||||
| static GLFWwindow*          g_Window = NULL;    // Main window |  | ||||||
| static GlfwClientApi        g_ClientApi = GlfwClientApi_Unknown; |  | ||||||
| static double               g_Time = 0.0; |  | ||||||
| static bool                 g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; |  | ||||||
| static GLFWcursor*          g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; |  | ||||||
| static bool                 g_InstalledCallbacks = false; |  | ||||||
|  |  | ||||||
| // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. | struct ImGui_ImplGlfw_Data | ||||||
| static GLFWmousebuttonfun   g_PrevUserCallbackMousebutton = NULL; | { | ||||||
| static GLFWscrollfun        g_PrevUserCallbackScroll = NULL; |     GLFWwindow*             Window; | ||||||
| static GLFWkeyfun           g_PrevUserCallbackKey = NULL; |     GlfwClientApi           ClientApi; | ||||||
| static GLFWcharfun          g_PrevUserCallbackChar = NULL; |     double                  Time; | ||||||
|  |     bool                    MouseJustPressed[ImGuiMouseButton_COUNT]; | ||||||
|  |     GLFWcursor*             MouseCursors[ImGuiMouseCursor_COUNT]; | ||||||
|  |     bool                    InstalledCallbacks; | ||||||
|  |  | ||||||
|  |     // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. | ||||||
|  |     GLFWmousebuttonfun      PrevUserCallbackMousebutton; | ||||||
|  |     GLFWscrollfun           PrevUserCallbackScroll; | ||||||
|  |     GLFWkeyfun              PrevUserCallbackKey; | ||||||
|  |     GLFWcharfun             PrevUserCallbackChar; | ||||||
|  |  | ||||||
|  |     ImGui_ImplGlfw_Data()   { memset(this, 0, sizeof(*this)); } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplGlfw_Data* g_Data; | ||||||
|  | static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplGlfw_Data); return g_Data; } | ||||||
|  | static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } | ||||||
|  | static void                 ImGui_ImplGlfw_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
|  | // Functions | ||||||
| static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) | static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) | ||||||
| { | { | ||||||
|     return glfwGetClipboardString((GLFWwindow*)user_data); |     return glfwGetClipboardString((GLFWwindow*)user_data); | ||||||
| @@ -91,17 +105,19 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) | |||||||
|  |  | ||||||
| void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) | void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) | ||||||
| { | { | ||||||
|     if (g_PrevUserCallbackMousebutton != NULL) |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||||
|         g_PrevUserCallbackMousebutton(window, button, action, mods); |     if (bd->PrevUserCallbackMousebutton != NULL) | ||||||
|  |         bd->PrevUserCallbackMousebutton(window, button, action, mods); | ||||||
|  |  | ||||||
|     if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed)) |     if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(bd->MouseJustPressed)) | ||||||
|         g_MouseJustPressed[button] = true; |         bd->MouseJustPressed[button] = true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) | void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) | ||||||
| { | { | ||||||
|     if (g_PrevUserCallbackScroll != NULL) |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||||
|         g_PrevUserCallbackScroll(window, xoffset, yoffset); |     if (bd->PrevUserCallbackScroll != NULL) | ||||||
|  |         bd->PrevUserCallbackScroll(window, xoffset, yoffset); | ||||||
|  |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     io.MouseWheelH += (float)xoffset; |     io.MouseWheelH += (float)xoffset; | ||||||
| @@ -110,8 +126,9 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo | |||||||
|  |  | ||||||
| void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) | void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) | ||||||
| { | { | ||||||
|     if (g_PrevUserCallbackKey != NULL) |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||||
|         g_PrevUserCallbackKey(window, key, scancode, action, mods); |     if (bd->PrevUserCallbackKey != NULL) | ||||||
|  |         bd->PrevUserCallbackKey(window, key, scancode, action, mods); | ||||||
|  |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     if (key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)) |     if (key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)) | ||||||
| @@ -135,8 +152,9 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int a | |||||||
|  |  | ||||||
| void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) | void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) | ||||||
| { | { | ||||||
|     if (g_PrevUserCallbackChar != NULL) |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||||
|         g_PrevUserCallbackChar(window, c); |     if (bd->PrevUserCallbackChar != NULL) | ||||||
|  |         bd->PrevUserCallbackChar(window, c); | ||||||
|  |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     io.AddInputCharacter(c); |     io.AddInputCharacter(c); | ||||||
| @@ -144,14 +162,18 @@ void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) | |||||||
|  |  | ||||||
| static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) | static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) | ||||||
| { | { | ||||||
|     g_Window = window; |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     g_Time = 0.0; |     IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); | ||||||
|  |  | ||||||
|  |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_CreateBackendData(); | ||||||
|  |     bd->Window = window; | ||||||
|  |     bd->Time = 0.0; | ||||||
|  |  | ||||||
|     // Setup backend capabilities flags |     // Setup backend capabilities flags | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     io.BackendPlatformUserData = (void*)bd; | ||||||
|  |     io.BackendPlatformName = "imgui_impl_glfw"; | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;         // We can honor GetMouseCursor() values (optional) |     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;         // We can honor GetMouseCursor() values (optional) | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;          // We can honor io.WantSetMousePos requests (optional, rarely used) |     io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;          // We can honor io.WantSetMousePos requests (optional, rarely used) | ||||||
|     io.BackendPlatformName = "imgui_impl_glfw"; |  | ||||||
|  |  | ||||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. |     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. | ||||||
|     io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; |     io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; | ||||||
| @@ -179,9 +201,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw | |||||||
|  |  | ||||||
|     io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; |     io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; | ||||||
|     io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; |     io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; | ||||||
|     io.ClipboardUserData = g_Window; |     io.ClipboardUserData = bd->Window; | ||||||
| #if defined(_WIN32) | #if defined(_WIN32) | ||||||
|     io.ImeWindowHandle = (void*)glfwGetWin32Window(g_Window); |     io.ImeWindowHandle = (void*)glfwGetWin32Window(bd->Window); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     // Create mouse cursors |     // Create mouse cursors | ||||||
| @@ -189,39 +211,39 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw | |||||||
|     // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting. |     // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting. | ||||||
|     // Missing cursors will return NULL and our _UpdateMouseCursor() function will use the Arrow cursor instead.) |     // Missing cursors will return NULL and our _UpdateMouseCursor() function will use the Arrow cursor instead.) | ||||||
|     GLFWerrorfun prev_error_callback = glfwSetErrorCallback(NULL); |     GLFWerrorfun prev_error_callback = glfwSetErrorCallback(NULL); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); | ||||||
| #if GLFW_HAS_NEW_CURSORS | #if GLFW_HAS_NEW_CURSORS | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR); | ||||||
| #else | #else | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); |     bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); | ||||||
| #endif | #endif | ||||||
|     glfwSetErrorCallback(prev_error_callback); |     glfwSetErrorCallback(prev_error_callback); | ||||||
|  |  | ||||||
|     // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. |     // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. | ||||||
|     g_PrevUserCallbackMousebutton = NULL; |     bd->PrevUserCallbackMousebutton = NULL; | ||||||
|     g_PrevUserCallbackScroll = NULL; |     bd->PrevUserCallbackScroll = NULL; | ||||||
|     g_PrevUserCallbackKey = NULL; |     bd->PrevUserCallbackKey = NULL; | ||||||
|     g_PrevUserCallbackChar = NULL; |     bd->PrevUserCallbackChar = NULL; | ||||||
|     if (install_callbacks) |     if (install_callbacks) | ||||||
|     { |     { | ||||||
|         g_InstalledCallbacks = true; |         bd->InstalledCallbacks = true; | ||||||
|         g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); |         bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); | ||||||
|         g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); |         bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); | ||||||
|         g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); |         bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); | ||||||
|         g_PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); |         bd->PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     g_ClientApi = client_api; |     bd->ClientApi = client_api; | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -242,32 +264,40 @@ bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks) | |||||||
|  |  | ||||||
| void ImGui_ImplGlfw_Shutdown() | void ImGui_ImplGlfw_Shutdown() | ||||||
| { | { | ||||||
|     if (g_InstalledCallbacks) |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||||
|  |  | ||||||
|  |     if (bd->InstalledCallbacks) | ||||||
|     { |     { | ||||||
|         glfwSetMouseButtonCallback(g_Window, g_PrevUserCallbackMousebutton); |         glfwSetMouseButtonCallback(bd->Window, bd->PrevUserCallbackMousebutton); | ||||||
|         glfwSetScrollCallback(g_Window, g_PrevUserCallbackScroll); |         glfwSetScrollCallback(bd->Window, bd->PrevUserCallbackScroll); | ||||||
|         glfwSetKeyCallback(g_Window, g_PrevUserCallbackKey); |         glfwSetKeyCallback(bd->Window, bd->PrevUserCallbackKey); | ||||||
|         glfwSetCharCallback(g_Window, g_PrevUserCallbackChar); |         glfwSetCharCallback(bd->Window, bd->PrevUserCallbackChar); | ||||||
|         g_InstalledCallbacks = false; |         bd->InstalledCallbacks = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) |     for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) | ||||||
|     { |     { | ||||||
|         glfwDestroyCursor(g_MouseCursors[cursor_n]); |         glfwDestroyCursor(bd->MouseCursors[cursor_n]); | ||||||
|         g_MouseCursors[cursor_n] = NULL; |         bd->MouseCursors[cursor_n] = NULL; | ||||||
|     } |     } | ||||||
|     g_ClientApi = GlfwClientApi_Unknown; |  | ||||||
|  |     io.BackendPlatformName = NULL; | ||||||
|  |     io.BackendPlatformUserData = NULL; | ||||||
|  |     ImGui_ImplGlfw_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplGlfw_UpdateMousePosAndButtons() | static void ImGui_ImplGlfw_UpdateMousePosAndButtons() | ||||||
| { | { | ||||||
|  |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||||
|  |  | ||||||
|     // Update buttons |     // Update buttons | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) |     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) | ||||||
|     { |     { | ||||||
|         // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. |         // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. | ||||||
|         io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0; |         io.MouseDown[i] = bd->MouseJustPressed[i] || glfwGetMouseButton(bd->Window, i) != 0; | ||||||
|         g_MouseJustPressed[i] = false; |         bd->MouseJustPressed[i] = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Update mouse position |     // Update mouse position | ||||||
| @@ -276,18 +306,18 @@ static void ImGui_ImplGlfw_UpdateMousePosAndButtons() | |||||||
| #ifdef __EMSCRIPTEN__ | #ifdef __EMSCRIPTEN__ | ||||||
|     const bool focused = true; // Emscripten |     const bool focused = true; // Emscripten | ||||||
| #else | #else | ||||||
|     const bool focused = glfwGetWindowAttrib(g_Window, GLFW_FOCUSED) != 0; |     const bool focused = glfwGetWindowAttrib(bd->Window, GLFW_FOCUSED) != 0; | ||||||
| #endif | #endif | ||||||
|     if (focused) |     if (focused) | ||||||
|     { |     { | ||||||
|         if (io.WantSetMousePos) |         if (io.WantSetMousePos) | ||||||
|         { |         { | ||||||
|             glfwSetCursorPos(g_Window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y); |             glfwSetCursorPos(bd->Window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             double mouse_x, mouse_y; |             double mouse_x, mouse_y; | ||||||
|             glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); |             glfwGetCursorPos(bd->Window, &mouse_x, &mouse_y); | ||||||
|             io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); |             io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -296,21 +326,22 @@ static void ImGui_ImplGlfw_UpdateMousePosAndButtons() | |||||||
| static void ImGui_ImplGlfw_UpdateMouseCursor() | static void ImGui_ImplGlfw_UpdateMouseCursor() | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(g_Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||||
|  |     if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); |     ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); | ||||||
|     if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) |     if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) | ||||||
|     { |     { | ||||||
|         // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor |         // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor | ||||||
|         glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); |         glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         // Show OS mouse cursor |         // Show OS mouse cursor | ||||||
|         // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. |         // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. | ||||||
|         glfwSetCursor(g_Window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); |         glfwSetCursor(bd->Window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]); | ||||||
|         glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); |         glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -354,20 +385,21 @@ static void ImGui_ImplGlfw_UpdateGamepads() | |||||||
| void ImGui_ImplGlfw_NewFrame() | void ImGui_ImplGlfw_NewFrame() | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); | ||||||
|  |  | ||||||
|     // Setup display size (every frame to accommodate for window resizing) |     // Setup display size (every frame to accommodate for window resizing) | ||||||
|     int w, h; |     int w, h; | ||||||
|     int display_w, display_h; |     int display_w, display_h; | ||||||
|     glfwGetWindowSize(g_Window, &w, &h); |     glfwGetWindowSize(bd->Window, &w, &h); | ||||||
|     glfwGetFramebufferSize(g_Window, &display_w, &display_h); |     glfwGetFramebufferSize(bd->Window, &display_w, &display_h); | ||||||
|     io.DisplaySize = ImVec2((float)w, (float)h); |     io.DisplaySize = ImVec2((float)w, (float)h); | ||||||
|     if (w > 0 && h > 0) |     if (w > 0 && h > 0) | ||||||
|         io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); |         io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); | ||||||
|  |  | ||||||
|     // Setup time step |     // Setup time step | ||||||
|     double current_time = glfwGetTime(); |     double current_time = glfwGetTime(); | ||||||
|     io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); |     io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); | ||||||
|     g_Time = current_time; |     bd->Time = current_time; | ||||||
|  |  | ||||||
|     ImGui_ImplGlfw_UpdateMousePosAndButtons(); |     ImGui_ImplGlfw_UpdateMousePosAndButtons(); | ||||||
|     ImGui_ImplGlfw_UpdateMouseCursor(); |     ImGui_ImplGlfw_UpdateMouseCursor(); | ||||||
|   | |||||||
| @@ -19,6 +19,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) | ||||||
|  | //  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: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | //  2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | ||||||
| //  2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. | //  2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. | ||||||
| //  2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. | //  2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. | ||||||
| @@ -55,26 +56,47 @@ | |||||||
| #include <GL/gl.h> | #include <GL/gl.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // OpenGL Data | struct ImGui_ImplOpenGL2_Data | ||||||
| static GLuint       g_FontTexture = 0; | { | ||||||
|  |     GLuint       FontTexture; | ||||||
|  |  | ||||||
|  |     ImGui_ImplOpenGL2_Data() { memset(this, 0, sizeof(*this)); } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplOpenGL2_Data*  g_Data; | ||||||
|  | static ImGui_ImplOpenGL2_Data*  ImGui_ImplOpenGL2_CreateBackendData()   { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplOpenGL2_Data); return g_Data; } | ||||||
|  | static ImGui_ImplOpenGL2_Data*  ImGui_ImplOpenGL2_GetBackendData()      { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } | ||||||
|  | static void                     ImGui_ImplOpenGL2_DestroyBackendData()  { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| // Functions | // Functions | ||||||
| bool    ImGui_ImplOpenGL2_Init() | bool    ImGui_ImplOpenGL2_Init() | ||||||
| { | { | ||||||
|     // Setup backend capabilities flags |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); | ||||||
|  |  | ||||||
|  |     // Setup backend capabilities flags | ||||||
|  |     ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_CreateBackendData(); | ||||||
|  |     io.BackendRendererUserData = (void*)bd; | ||||||
|     io.BackendRendererName = "imgui_impl_opengl2"; |     io.BackendRendererName = "imgui_impl_opengl2"; | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void    ImGui_ImplOpenGL2_Shutdown() | void    ImGui_ImplOpenGL2_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |  | ||||||
|     ImGui_ImplOpenGL2_DestroyDeviceObjects(); |     ImGui_ImplOpenGL2_DestroyDeviceObjects(); | ||||||
|  |     io.BackendRendererName = NULL; | ||||||
|  |     io.BackendRendererUserData = NULL; | ||||||
|  |     ImGui_ImplOpenGL2_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void    ImGui_ImplOpenGL2_NewFrame() | void    ImGui_ImplOpenGL2_NewFrame() | ||||||
| { | { | ||||||
|     if (!g_FontTexture) |     ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); | ||||||
|  |     if (!bd->FontTexture) | ||||||
|         ImGui_ImplOpenGL2_CreateDeviceObjects(); |         ImGui_ImplOpenGL2_CreateDeviceObjects(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -215,6 +237,7 @@ bool ImGui_ImplOpenGL2_CreateFontsTexture() | |||||||
| { | { | ||||||
|     // Build texture atlas |     // Build texture atlas | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); | ||||||
|     unsigned char* pixels; |     unsigned char* pixels; | ||||||
|     int width, height; |     int width, height; | ||||||
|     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);   // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. |     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);   // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. | ||||||
| @@ -222,15 +245,15 @@ bool ImGui_ImplOpenGL2_CreateFontsTexture() | |||||||
|     // Upload texture to graphics system |     // Upload texture to graphics system | ||||||
|     GLint last_texture; |     GLint last_texture; | ||||||
|     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); |     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | ||||||
|     glGenTextures(1, &g_FontTexture); |     glGenTextures(1, &bd->FontTexture); | ||||||
|     glBindTexture(GL_TEXTURE_2D, g_FontTexture); |     glBindTexture(GL_TEXTURE_2D, bd->FontTexture); | ||||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||||
|     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | ||||||
|     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | ||||||
|  |  | ||||||
|     // Store our identifier |     // Store our identifier | ||||||
|     io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture); |     io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); | ||||||
|  |  | ||||||
|     // Restore state |     // Restore state | ||||||
|     glBindTexture(GL_TEXTURE_2D, last_texture); |     glBindTexture(GL_TEXTURE_2D, last_texture); | ||||||
| @@ -240,12 +263,13 @@ bool ImGui_ImplOpenGL2_CreateFontsTexture() | |||||||
|  |  | ||||||
| void ImGui_ImplOpenGL2_DestroyFontsTexture() | void ImGui_ImplOpenGL2_DestroyFontsTexture() | ||||||
| { | { | ||||||
|     if (g_FontTexture) |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); | ||||||
|  |     if (bd->FontTexture) | ||||||
|     { |     { | ||||||
|         ImGuiIO& io = ImGui::GetIO(); |         glDeleteTextures(1, &bd->FontTexture); | ||||||
|         glDeleteTextures(1, &g_FontTexture); |  | ||||||
|         io.Fonts->SetTexID(0); |         io.Fonts->SetTexID(0); | ||||||
|         g_FontTexture = 0; |         bd->FontTexture = 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,6 +14,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) | ||||||
|  | //  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-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state. | //  2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state. | ||||||
| //  2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader. | //  2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader. | ||||||
| //  2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version. | //  2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version. | ||||||
| @@ -171,18 +172,37 @@ using namespace gl; | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // OpenGL Data | // OpenGL Data | ||||||
| static GLuint       g_GlVersion = 0;                // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2) | struct ImGui_ImplOpenGL3_Data | ||||||
| static char         g_GlslVersionString[32] = "";   // Specified by user or detected based on compile time GL settings. | { | ||||||
| static GLuint       g_FontTexture = 0; |     GLuint          GlVersion;               // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2) | ||||||
| static GLuint       g_ShaderHandle = 0; |     char            GlslVersionString[32];   // Specified by user or detected based on compile time GL settings. | ||||||
| static GLint        g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;                                // Uniforms location |     GLuint          FontTexture; | ||||||
| static GLuint       g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location |     GLuint          ShaderHandle; | ||||||
| static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; |     GLint           AttribLocationTex;       // Uniforms location | ||||||
| static bool         g_HasClipOrigin = false; |     GLint           AttribLocationProjMtx; | ||||||
|  |     GLuint          AttribLocationVtxPos;    // Vertex attributes location | ||||||
|  |     GLuint          AttribLocationVtxUV; | ||||||
|  |     GLuint          AttribLocationVtxColor; | ||||||
|  |     unsigned int    VboHandle, ElementsHandle; | ||||||
|  |     bool            HasClipOrigin; | ||||||
|  |  | ||||||
|  |     ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplOpenGL3_Data*  g_Data; | ||||||
|  | static ImGui_ImplOpenGL3_Data*  ImGui_ImplOpenGL3_CreateBackendData()   { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplOpenGL3_Data); return g_Data; } | ||||||
|  | static ImGui_ImplOpenGL3_Data*  ImGui_ImplOpenGL3_GetBackendData()      { IM_ASSERT(ImGui::GetCurrentContext() != NULL); return g_Data; } | ||||||
|  | static void                     ImGui_ImplOpenGL3_DestroyBackendData()  { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| // Functions | // Functions | ||||||
| bool    ImGui_ImplOpenGL3_Init(const char* glsl_version) | bool    ImGui_ImplOpenGL3_Init(const char* glsl_version) | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); | ||||||
|  |  | ||||||
|  |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_CreateBackendData(); | ||||||
|  |  | ||||||
|     // Query for GL version (e.g. 320 for GL 3.2) |     // Query for GL version (e.g. 320 for GL 3.2) | ||||||
| #if !defined(IMGUI_IMPL_OPENGL_ES2) | #if !defined(IMGUI_IMPL_OPENGL_ES2) | ||||||
|     GLint major = 0; |     GLint major = 0; | ||||||
| @@ -195,16 +215,16 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version) | |||||||
|         const char* gl_version = (const char*)glGetString(GL_VERSION); |         const char* gl_version = (const char*)glGetString(GL_VERSION); | ||||||
|         sscanf(gl_version, "%d.%d", &major, &minor); |         sscanf(gl_version, "%d.%d", &major, &minor); | ||||||
|     } |     } | ||||||
|     g_GlVersion = (GLuint)(major * 100 + minor * 10); |     bd->GlVersion = (GLuint)(major * 100 + minor * 10); | ||||||
| #else | #else | ||||||
|     g_GlVersion = 200; // GLES 2 |     bd->GlVersion = 200; // GLES 2 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     // Setup backend capabilities flags |     // Setup backend capabilities flags | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     io.BackendRendererUserData = (void*)bd; | ||||||
|     io.BackendRendererName = "imgui_impl_opengl3"; |     io.BackendRendererName = "imgui_impl_opengl3"; | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET | ||||||
|     if (g_GlVersion >= 320) |     if (bd->GlVersion >= 320) | ||||||
|         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. | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -223,9 +243,9 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version) | |||||||
|     if (glsl_version == NULL) |     if (glsl_version == NULL) | ||||||
|         glsl_version = "#version 130"; |         glsl_version = "#version 130"; | ||||||
| #endif | #endif | ||||||
|     IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString)); |     IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString)); | ||||||
|     strcpy(g_GlslVersionString, glsl_version); |     strcpy(bd->GlslVersionString, glsl_version); | ||||||
|     strcat(g_GlslVersionString, "\n"); |     strcat(bd->GlslVersionString, "\n"); | ||||||
|  |  | ||||||
|     // Debugging construct to make it easily visible in the IDE and debugger which GL loader has been selected. |     // Debugging construct to make it easily visible in the IDE and debugger which GL loader has been selected. | ||||||
|     // The code actually never uses the 'gl_loader' variable! It is only here so you can read it! |     // The code actually never uses the 'gl_loader' variable! It is only here so you can read it! | ||||||
| @@ -259,7 +279,7 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version) | |||||||
|     glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); |     glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); | ||||||
|  |  | ||||||
|     // Detect extensions we support |     // Detect extensions we support | ||||||
|     g_HasClipOrigin = (g_GlVersion >= 450); |     bd->HasClipOrigin = (bd->GlVersion >= 450); | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS | ||||||
|     GLint num_extensions = 0; |     GLint num_extensions = 0; | ||||||
|     glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); |     glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); | ||||||
| @@ -267,7 +287,7 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version) | |||||||
|     { |     { | ||||||
|         const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i); |         const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i); | ||||||
|         if (extension != NULL && strcmp(extension, "GL_ARB_clip_control") == 0) |         if (extension != NULL && strcmp(extension, "GL_ARB_clip_control") == 0) | ||||||
|             g_HasClipOrigin = true; |             bd->HasClipOrigin = true; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -276,17 +296,24 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version) | |||||||
|  |  | ||||||
| void    ImGui_ImplOpenGL3_Shutdown() | void    ImGui_ImplOpenGL3_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     ImGui_ImplOpenGL3_DestroyDeviceObjects(); |     ImGui_ImplOpenGL3_DestroyDeviceObjects(); | ||||||
|  |     io.BackendRendererName = NULL; | ||||||
|  |     io.BackendRendererUserData = NULL; | ||||||
|  |     ImGui_ImplOpenGL3_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void    ImGui_ImplOpenGL3_NewFrame() | void    ImGui_ImplOpenGL3_NewFrame() | ||||||
| { | { | ||||||
|     if (!g_ShaderHandle) |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|  |     if (!bd->ShaderHandle) | ||||||
|         ImGui_ImplOpenGL3_CreateDeviceObjects(); |         ImGui_ImplOpenGL3_CreateDeviceObjects(); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) | static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) | ||||||
| { | { | ||||||
|  |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|  |  | ||||||
|     // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill |     // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill | ||||||
|     glEnable(GL_BLEND); |     glEnable(GL_BLEND); | ||||||
|     glBlendEquation(GL_FUNC_ADD); |     glBlendEquation(GL_FUNC_ADD); | ||||||
| @@ -296,7 +323,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid | |||||||
|     glDisable(GL_STENCIL_TEST); |     glDisable(GL_STENCIL_TEST); | ||||||
|     glEnable(GL_SCISSOR_TEST); |     glEnable(GL_SCISSOR_TEST); | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART | ||||||
|     if (g_GlVersion >= 310) |     if (bd->GlVersion >= 310) | ||||||
|         glDisable(GL_PRIMITIVE_RESTART); |         glDisable(GL_PRIMITIVE_RESTART); | ||||||
| #endif | #endif | ||||||
| #ifdef GL_POLYGON_MODE | #ifdef GL_POLYGON_MODE | ||||||
| @@ -306,7 +333,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid | |||||||
|     // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) |     // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) | ||||||
| #if defined(GL_CLIP_ORIGIN) | #if defined(GL_CLIP_ORIGIN) | ||||||
|     bool clip_origin_lower_left = true; |     bool clip_origin_lower_left = true; | ||||||
|     if (g_HasClipOrigin) |     if (bd->HasClipOrigin) | ||||||
|     { |     { | ||||||
|         GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); |         GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); | ||||||
|         if (current_clip_origin == GL_UPPER_LEFT) |         if (current_clip_origin == GL_UPPER_LEFT) | ||||||
| @@ -331,12 +358,12 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid | |||||||
|         { 0.0f,         0.0f,        -1.0f,   0.0f }, |         { 0.0f,         0.0f,        -1.0f,   0.0f }, | ||||||
|         { (R+L)/(L-R),  (T+B)/(B-T),  0.0f,   1.0f }, |         { (R+L)/(L-R),  (T+B)/(B-T),  0.0f,   1.0f }, | ||||||
|     }; |     }; | ||||||
|     glUseProgram(g_ShaderHandle); |     glUseProgram(bd->ShaderHandle); | ||||||
|     glUniform1i(g_AttribLocationTex, 0); |     glUniform1i(bd->AttribLocationTex, 0); | ||||||
|     glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); |     glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); | ||||||
|  |  | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER | ||||||
|     if (g_GlVersion >= 330) |     if (bd->GlVersion >= 330) | ||||||
|         glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. |         glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -346,14 +373,14 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     // Bind vertex/index buffers and setup attributes for ImDrawVert |     // Bind vertex/index buffers and setup attributes for ImDrawVert | ||||||
|     glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); |     glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle); | ||||||
|     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); |     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle); | ||||||
|     glEnableVertexAttribArray(g_AttribLocationVtxPos); |     glEnableVertexAttribArray(bd->AttribLocationVtxPos); | ||||||
|     glEnableVertexAttribArray(g_AttribLocationVtxUV); |     glEnableVertexAttribArray(bd->AttribLocationVtxUV); | ||||||
|     glEnableVertexAttribArray(g_AttribLocationVtxColor); |     glEnableVertexAttribArray(bd->AttribLocationVtxColor); | ||||||
|     glVertexAttribPointer(g_AttribLocationVtxPos,   2, GL_FLOAT,         GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); |     glVertexAttribPointer(bd->AttribLocationVtxPos,   2, GL_FLOAT,         GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); | ||||||
|     glVertexAttribPointer(g_AttribLocationVtxUV,    2, GL_FLOAT,         GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); |     glVertexAttribPointer(bd->AttribLocationVtxUV,    2, GL_FLOAT,         GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); | ||||||
|     glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE,  sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); |     glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE,  sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); | ||||||
| } | } | ||||||
|  |  | ||||||
| // OpenGL3 Render function. | // OpenGL3 Render function. | ||||||
| @@ -367,13 +394,15 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) | |||||||
|     if (fb_width <= 0 || fb_height <= 0) |     if (fb_width <= 0 || fb_height <= 0) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|  |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|  |  | ||||||
|     // Backup GL state |     // Backup GL state | ||||||
|     GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); |     GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); | ||||||
|     glActiveTexture(GL_TEXTURE0); |     glActiveTexture(GL_TEXTURE0); | ||||||
|     GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program); |     GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program); | ||||||
|     GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture); |     GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture); | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER | ||||||
|     GLuint last_sampler; if (g_GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } |     GLuint last_sampler; if (bd->GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } | ||||||
| #endif | #endif | ||||||
|     GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer); |     GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer); | ||||||
| #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY | #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY | ||||||
| @@ -396,7 +425,7 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) | |||||||
|     GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST); |     GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST); | ||||||
|     GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); |     GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART | ||||||
|     GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; |     GLboolean last_enable_primitive_restart = (bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     // Setup desired GL state |     // Setup desired GL state | ||||||
| @@ -450,7 +479,7 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) | |||||||
|                     // Bind texture, Draw |                     // Bind texture, Draw | ||||||
|                     glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()); |                     glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()); | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET | ||||||
|                     if (g_GlVersion >= 320) |                     if (bd->GlVersion >= 320) | ||||||
|                         glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); |                         glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); | ||||||
|                     else |                     else | ||||||
| #endif | #endif | ||||||
| @@ -469,7 +498,7 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) | |||||||
|     glUseProgram(last_program); |     glUseProgram(last_program); | ||||||
|     glBindTexture(GL_TEXTURE_2D, last_texture); |     glBindTexture(GL_TEXTURE_2D, last_texture); | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER | ||||||
|     if (g_GlVersion >= 330) |     if (bd->GlVersion >= 330) | ||||||
|         glBindSampler(0, last_sampler); |         glBindSampler(0, last_sampler); | ||||||
| #endif | #endif | ||||||
|     glActiveTexture(last_active_texture); |     glActiveTexture(last_active_texture); | ||||||
| @@ -485,7 +514,7 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) | |||||||
|     if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); |     if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); | ||||||
|     if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); |     if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); | ||||||
| #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART | ||||||
|     if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } |     if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef GL_POLYGON_MODE | #ifdef GL_POLYGON_MODE | ||||||
| @@ -497,8 +526,10 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) | |||||||
|  |  | ||||||
| bool ImGui_ImplOpenGL3_CreateFontsTexture() | bool ImGui_ImplOpenGL3_CreateFontsTexture() | ||||||
| { | { | ||||||
|     // Build texture atlas |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|  |  | ||||||
|  |     // Build texture atlas | ||||||
|     unsigned char* pixels; |     unsigned char* pixels; | ||||||
|     int width, height; |     int width, height; | ||||||
|     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);   // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. |     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);   // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. | ||||||
| @@ -506,8 +537,8 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture() | |||||||
|     // Upload texture to graphics system |     // Upload texture to graphics system | ||||||
|     GLint last_texture; |     GLint last_texture; | ||||||
|     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); |     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | ||||||
|     glGenTextures(1, &g_FontTexture); |     glGenTextures(1, &bd->FontTexture); | ||||||
|     glBindTexture(GL_TEXTURE_2D, g_FontTexture); |     glBindTexture(GL_TEXTURE_2D, bd->FontTexture); | ||||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||||
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||||
| #ifdef GL_UNPACK_ROW_LENGTH | #ifdef GL_UNPACK_ROW_LENGTH | ||||||
| @@ -516,7 +547,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture() | |||||||
|     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | ||||||
|  |  | ||||||
|     // Store our identifier |     // Store our identifier | ||||||
|     io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture); |     io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); | ||||||
|  |  | ||||||
|     // Restore state |     // Restore state | ||||||
|     glBindTexture(GL_TEXTURE_2D, last_texture); |     glBindTexture(GL_TEXTURE_2D, last_texture); | ||||||
| @@ -526,23 +557,25 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture() | |||||||
|  |  | ||||||
| void ImGui_ImplOpenGL3_DestroyFontsTexture() | void ImGui_ImplOpenGL3_DestroyFontsTexture() | ||||||
| { | { | ||||||
|     if (g_FontTexture) |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|  |     if (bd->FontTexture) | ||||||
|     { |     { | ||||||
|         ImGuiIO& io = ImGui::GetIO(); |         glDeleteTextures(1, &bd->FontTexture); | ||||||
|         glDeleteTextures(1, &g_FontTexture); |  | ||||||
|         io.Fonts->SetTexID(0); |         io.Fonts->SetTexID(0); | ||||||
|         g_FontTexture = 0; |         bd->FontTexture = 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. | // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. | ||||||
| static bool CheckShader(GLuint handle, const char* desc) | static bool CheckShader(GLuint handle, const char* desc) | ||||||
| { | { | ||||||
|  |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|     GLint status = 0, log_length = 0; |     GLint status = 0, log_length = 0; | ||||||
|     glGetShaderiv(handle, GL_COMPILE_STATUS, &status); |     glGetShaderiv(handle, GL_COMPILE_STATUS, &status); | ||||||
|     glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); |     glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); | ||||||
|     if ((GLboolean)status == GL_FALSE) |     if ((GLboolean)status == GL_FALSE) | ||||||
|         fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc); |         fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString); | ||||||
|     if (log_length > 1) |     if (log_length > 1) | ||||||
|     { |     { | ||||||
|         ImVector<char> buf; |         ImVector<char> buf; | ||||||
| @@ -556,11 +589,12 @@ static bool CheckShader(GLuint handle, const char* desc) | |||||||
| // If you get an error please report on GitHub. You may try different GL context version or GLSL version. | // If you get an error please report on GitHub. You may try different GL context version or GLSL version. | ||||||
| static bool CheckProgram(GLuint handle, const char* desc) | static bool CheckProgram(GLuint handle, const char* desc) | ||||||
| { | { | ||||||
|  |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|     GLint status = 0, log_length = 0; |     GLint status = 0, log_length = 0; | ||||||
|     glGetProgramiv(handle, GL_LINK_STATUS, &status); |     glGetProgramiv(handle, GL_LINK_STATUS, &status); | ||||||
|     glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); |     glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); | ||||||
|     if ((GLboolean)status == GL_FALSE) |     if ((GLboolean)status == GL_FALSE) | ||||||
|         fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString); |         fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString); | ||||||
|     if (log_length > 1) |     if (log_length > 1) | ||||||
|     { |     { | ||||||
|         ImVector<char> buf; |         ImVector<char> buf; | ||||||
| @@ -573,6 +607,8 @@ static bool CheckProgram(GLuint handle, const char* desc) | |||||||
|  |  | ||||||
| bool    ImGui_ImplOpenGL3_CreateDeviceObjects() | bool    ImGui_ImplOpenGL3_CreateDeviceObjects() | ||||||
| { | { | ||||||
|  |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|  |  | ||||||
|     // Backup GL state |     // Backup GL state | ||||||
|     GLint last_texture, last_array_buffer; |     GLint last_texture, last_array_buffer; | ||||||
|     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); |     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | ||||||
| @@ -584,7 +620,7 @@ bool    ImGui_ImplOpenGL3_CreateDeviceObjects() | |||||||
|  |  | ||||||
|     // Parse GLSL version string |     // Parse GLSL version string | ||||||
|     int glsl_version = 130; |     int glsl_version = 130; | ||||||
|     sscanf(g_GlslVersionString, "#version %d", &glsl_version); |     sscanf(bd->GlslVersionString, "#version %d", &glsl_version); | ||||||
|  |  | ||||||
|     const GLchar* vertex_shader_glsl_120 = |     const GLchar* vertex_shader_glsl_120 = | ||||||
|         "uniform mat4 ProjMtx;\n" |         "uniform mat4 ProjMtx;\n" | ||||||
| @@ -711,39 +747,39 @@ bool    ImGui_ImplOpenGL3_CreateDeviceObjects() | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create shaders |     // Create shaders | ||||||
|     const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader }; |     const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader }; | ||||||
|     GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER); |     GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER); | ||||||
|     glShaderSource(vert_handle, 2, vertex_shader_with_version, NULL); |     glShaderSource(vert_handle, 2, vertex_shader_with_version, NULL); | ||||||
|     glCompileShader(vert_handle); |     glCompileShader(vert_handle); | ||||||
|     CheckShader(vert_handle, "vertex shader"); |     CheckShader(vert_handle, "vertex shader"); | ||||||
|  |  | ||||||
|     const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader }; |     const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader }; | ||||||
|     GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER); |     GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER); | ||||||
|     glShaderSource(frag_handle, 2, fragment_shader_with_version, NULL); |     glShaderSource(frag_handle, 2, fragment_shader_with_version, NULL); | ||||||
|     glCompileShader(frag_handle); |     glCompileShader(frag_handle); | ||||||
|     CheckShader(frag_handle, "fragment shader"); |     CheckShader(frag_handle, "fragment shader"); | ||||||
|  |  | ||||||
|     // Link |     // Link | ||||||
|     g_ShaderHandle = glCreateProgram(); |     bd->ShaderHandle = glCreateProgram(); | ||||||
|     glAttachShader(g_ShaderHandle, vert_handle); |     glAttachShader(bd->ShaderHandle, vert_handle); | ||||||
|     glAttachShader(g_ShaderHandle, frag_handle); |     glAttachShader(bd->ShaderHandle, frag_handle); | ||||||
|     glLinkProgram(g_ShaderHandle); |     glLinkProgram(bd->ShaderHandle); | ||||||
|     CheckProgram(g_ShaderHandle, "shader program"); |     CheckProgram(bd->ShaderHandle, "shader program"); | ||||||
|  |  | ||||||
|     glDetachShader(g_ShaderHandle, vert_handle); |     glDetachShader(bd->ShaderHandle, vert_handle); | ||||||
|     glDetachShader(g_ShaderHandle, frag_handle); |     glDetachShader(bd->ShaderHandle, frag_handle); | ||||||
|     glDeleteShader(vert_handle); |     glDeleteShader(vert_handle); | ||||||
|     glDeleteShader(frag_handle); |     glDeleteShader(frag_handle); | ||||||
|  |  | ||||||
|     g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); |     bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture"); | ||||||
|     g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); |     bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx"); | ||||||
|     g_AttribLocationVtxPos = (GLuint)glGetAttribLocation(g_ShaderHandle, "Position"); |     bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position"); | ||||||
|     g_AttribLocationVtxUV = (GLuint)glGetAttribLocation(g_ShaderHandle, "UV"); |     bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV"); | ||||||
|     g_AttribLocationVtxColor = (GLuint)glGetAttribLocation(g_ShaderHandle, "Color"); |     bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color"); | ||||||
|  |  | ||||||
|     // Create buffers |     // Create buffers | ||||||
|     glGenBuffers(1, &g_VboHandle); |     glGenBuffers(1, &bd->VboHandle); | ||||||
|     glGenBuffers(1, &g_ElementsHandle); |     glGenBuffers(1, &bd->ElementsHandle); | ||||||
|  |  | ||||||
|     ImGui_ImplOpenGL3_CreateFontsTexture(); |     ImGui_ImplOpenGL3_CreateFontsTexture(); | ||||||
|  |  | ||||||
| @@ -759,9 +795,9 @@ bool    ImGui_ImplOpenGL3_CreateDeviceObjects() | |||||||
|  |  | ||||||
| void    ImGui_ImplOpenGL3_DestroyDeviceObjects() | void    ImGui_ImplOpenGL3_DestroyDeviceObjects() | ||||||
| { | { | ||||||
|     if (g_VboHandle)        { glDeleteBuffers(1, &g_VboHandle); g_VboHandle = 0; } |     ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); | ||||||
|     if (g_ElementsHandle)   { glDeleteBuffers(1, &g_ElementsHandle); g_ElementsHandle = 0; } |     if (bd->VboHandle)      { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; } | ||||||
|     if (g_ShaderHandle)     { glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; } |     if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; } | ||||||
|  |     if (bd->ShaderHandle)   { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; } | ||||||
|     ImGui_ImplOpenGL3_DestroyFontsTexture(); |     ImGui_ImplOpenGL3_DestroyFontsTexture(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,6 +18,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) | ||||||
|  | //  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-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) | //  2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950) | ||||||
| //  2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends. | //  2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends. | ||||||
| //  2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2). | //  2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2). | ||||||
| @@ -59,20 +60,32 @@ | |||||||
| #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE    SDL_VERSION_ATLEAST(2,0,4) | #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE    SDL_VERSION_ATLEAST(2,0,4) | ||||||
| #define SDL_HAS_VULKAN                      SDL_VERSION_ATLEAST(2,0,6) | #define SDL_HAS_VULKAN                      SDL_VERSION_ATLEAST(2,0,6) | ||||||
|  |  | ||||||
| // Data | struct ImGui_ImplSDL2_Data | ||||||
| static SDL_Window*  g_Window = NULL; | { | ||||||
| static Uint64       g_Time = 0; |     SDL_Window* Window; | ||||||
| static bool         g_MousePressed[3] = { false, false, false }; |     Uint64      Time; | ||||||
| static SDL_Cursor*  g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; |     bool        MousePressed[3]; | ||||||
| static char*        g_ClipboardTextData = NULL; |     SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; | ||||||
| static bool         g_MouseCanUseGlobalState = true; |     char*       ClipboardTextData; | ||||||
|  |     bool        MouseCanUseGlobalState; | ||||||
|  |  | ||||||
|  |     ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplSDL2_Data* g_Data; | ||||||
|  | static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_CreateBackendData()  { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplSDL2_Data); return g_Data; } | ||||||
|  | static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()     { return ImGui::GetCurrentContext() != NULL ? g_Data : NULL; } | ||||||
|  | static void                 ImGui_ImplSDL2_DestroyBackendData() { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
|  | // Functions | ||||||
| static const char* ImGui_ImplSDL2_GetClipboardText(void*) | static const char* ImGui_ImplSDL2_GetClipboardText(void*) | ||||||
| { | { | ||||||
|     if (g_ClipboardTextData) |     ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); | ||||||
|         SDL_free(g_ClipboardTextData); |     if (bd->ClipboardTextData) | ||||||
|     g_ClipboardTextData = SDL_GetClipboardText(); |         SDL_free(bd->ClipboardTextData); | ||||||
|     return g_ClipboardTextData; |     bd->ClipboardTextData = SDL_GetClipboardText(); | ||||||
|  |     return bd->ClipboardTextData; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text) | static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text) | ||||||
| @@ -88,6 +101,8 @@ static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text) | |||||||
| bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) | bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); | ||||||
|  |  | ||||||
|     switch (event->type) |     switch (event->type) | ||||||
|     { |     { | ||||||
|     case SDL_MOUSEWHEEL: |     case SDL_MOUSEWHEEL: | ||||||
| @@ -100,9 +115,9 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) | |||||||
|         } |         } | ||||||
|     case SDL_MOUSEBUTTONDOWN: |     case SDL_MOUSEBUTTONDOWN: | ||||||
|         { |         { | ||||||
|             if (event->button.button == SDL_BUTTON_LEFT) g_MousePressed[0] = true; |             if (event->button.button == SDL_BUTTON_LEFT) { bd->MousePressed[0] = true; } | ||||||
|             if (event->button.button == SDL_BUTTON_RIGHT) g_MousePressed[1] = true; |             if (event->button.button == SDL_BUTTON_RIGHT) { bd->MousePressed[1] = true; } | ||||||
|             if (event->button.button == SDL_BUTTON_MIDDLE) g_MousePressed[2] = true; |             if (event->button.button == SDL_BUTTON_MIDDLE) { bd->MousePressed[2] = true; } | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|     case SDL_TEXTINPUT: |     case SDL_TEXTINPUT: | ||||||
| @@ -132,13 +147,17 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) | |||||||
|  |  | ||||||
| static bool ImGui_ImplSDL2_Init(SDL_Window* window) | static bool ImGui_ImplSDL2_Init(SDL_Window* window) | ||||||
| { | { | ||||||
|     g_Window = window; |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); | ||||||
|  |  | ||||||
|  |     ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_CreateBackendData(); | ||||||
|  |     bd->Window = window; | ||||||
|  |  | ||||||
|     // Setup backend capabilities flags |     // Setup backend capabilities flags | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     io.BackendPlatformUserData = (void*)bd; | ||||||
|  |     io.BackendPlatformName = "imgui_impl_sdl"; | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;       // We can honor GetMouseCursor() values (optional) |     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;       // We can honor GetMouseCursor() values (optional) | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;        // We can honor io.WantSetMousePos requests (optional, rarely used) |     io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;        // We can honor io.WantSetMousePos requests (optional, rarely used) | ||||||
|     io.BackendPlatformName = "imgui_impl_sdl"; |  | ||||||
|  |  | ||||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. |     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. | ||||||
|     io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; |     io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; | ||||||
| @@ -169,24 +188,24 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window) | |||||||
|     io.ClipboardUserData = NULL; |     io.ClipboardUserData = NULL; | ||||||
|  |  | ||||||
|     // Load mouse cursors |     // Load mouse cursors | ||||||
|     g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); |     bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); |     bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); |     bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); |     bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); |     bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); |     bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); |     bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); |     bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); | ||||||
|     g_MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); |     bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); | ||||||
|  |  | ||||||
|     // Check and store if we are on a SDL backend that supports global mouse position |     // Check and store if we are on a SDL backend that supports global mouse position | ||||||
|     // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list) |     // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list) | ||||||
|     const char* sdl_backend = SDL_GetCurrentVideoDriver(); |     const char* sdl_backend = SDL_GetCurrentVideoDriver(); | ||||||
|     const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" }; |     const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" }; | ||||||
|     g_MouseCanUseGlobalState = false; |     bd->MouseCanUseGlobalState = false; | ||||||
|     for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++) |     for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++) | ||||||
|         if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0) |         if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0) | ||||||
|             g_MouseCanUseGlobalState = true; |             bd->MouseCanUseGlobalState = true; | ||||||
|  |  | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|     SDL_SysWMinfo wmInfo; |     SDL_SysWMinfo wmInfo; | ||||||
| @@ -202,7 +221,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window) | |||||||
|  |  | ||||||
| bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context) | bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context) | ||||||
| { | { | ||||||
|     (void)sdl_gl_context; // Viewport branch will need this. |     IM_UNUSED(sdl_gl_context); // Viewport branch will need this. | ||||||
|     return ImGui_ImplSDL2_Init(window); |     return ImGui_ImplSDL2_Init(window); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -229,41 +248,48 @@ bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window) | |||||||
|  |  | ||||||
| void ImGui_ImplSDL2_Shutdown() | void ImGui_ImplSDL2_Shutdown() | ||||||
| { | { | ||||||
|     g_Window = NULL; |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); | ||||||
|  |     bd->Window = NULL; | ||||||
|  |  | ||||||
|     // Destroy last known clipboard data |     // Destroy last known clipboard data | ||||||
|     if (g_ClipboardTextData) |     if (bd->ClipboardTextData) | ||||||
|         SDL_free(g_ClipboardTextData); |         SDL_free(bd->ClipboardTextData); | ||||||
|     g_ClipboardTextData = NULL; |     bd->ClipboardTextData = NULL; | ||||||
|  |  | ||||||
|     // Destroy SDL mouse cursors |     // Destroy SDL mouse cursors | ||||||
|     for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) |     for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) | ||||||
|         SDL_FreeCursor(g_MouseCursors[cursor_n]); |         SDL_FreeCursor(bd->MouseCursors[cursor_n]); | ||||||
|     memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); |     memset(bd->MouseCursors, 0, sizeof(bd->MouseCursors)); | ||||||
|  |  | ||||||
|  |     io.BackendPlatformName = NULL; | ||||||
|  |     io.BackendPlatformUserData = NULL; | ||||||
|  |     ImGui_ImplSDL2_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplSDL2_UpdateMousePosAndButtons() | static void ImGui_ImplSDL2_UpdateMousePosAndButtons() | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); | ||||||
|  |  | ||||||
|     // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) |     // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) | ||||||
|     if (io.WantSetMousePos) |     if (io.WantSetMousePos) | ||||||
|         SDL_WarpMouseInWindow(g_Window, (int)io.MousePos.x, (int)io.MousePos.y); |         SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); | ||||||
|     else |     else | ||||||
|         io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); |         io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); | ||||||
|  |  | ||||||
|     int mx, my; |     int mx, my; | ||||||
|     Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); |     Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); | ||||||
|     io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0;  // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. |     io.MouseDown[0] = bd->MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0;  // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. | ||||||
|     io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; |     io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; | ||||||
|     io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; |     io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; | ||||||
|     g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; |     bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false; | ||||||
|  |  | ||||||
| #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) | #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) | ||||||
|     SDL_Window* focused_window = SDL_GetKeyboardFocus(); |     SDL_Window* focused_window = SDL_GetKeyboardFocus(); | ||||||
|     if (g_Window == focused_window) |     if (bd->Window == focused_window) | ||||||
|     { |     { | ||||||
|         if (g_MouseCanUseGlobalState) |         if (bd->MouseCanUseGlobalState) | ||||||
|         { |         { | ||||||
|             // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?) |             // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?) | ||||||
|             // The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally. |             // The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally. | ||||||
| @@ -282,7 +308,7 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons() | |||||||
|     bool any_mouse_button_down = ImGui::IsAnyMouseDown(); |     bool any_mouse_button_down = ImGui::IsAnyMouseDown(); | ||||||
|     SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE); |     SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE); | ||||||
| #else | #else | ||||||
|     if (SDL_GetWindowFlags(g_Window) & SDL_WINDOW_INPUT_FOCUS) |     if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) | ||||||
|         io.MousePos = ImVec2((float)mx, (float)my); |         io.MousePos = ImVec2((float)mx, (float)my); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| @@ -292,6 +318,7 @@ static void ImGui_ImplSDL2_UpdateMouseCursor() | |||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) |     if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) | ||||||
|         return; |         return; | ||||||
|  |     ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); | ||||||
|  |  | ||||||
|     ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); |     ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); | ||||||
|     if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) |     if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) | ||||||
| @@ -302,7 +329,7 @@ static void ImGui_ImplSDL2_UpdateMouseCursor() | |||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         // Show OS mouse cursor |         // Show OS mouse cursor | ||||||
|         SDL_SetCursor(g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); |         SDL_SetCursor(bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]); | ||||||
|         SDL_ShowCursor(SDL_TRUE); |         SDL_ShowCursor(SDL_TRUE); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -351,6 +378,8 @@ static void ImGui_ImplSDL2_UpdateGamepads() | |||||||
| void ImGui_ImplSDL2_NewFrame(SDL_Window* window) | void ImGui_ImplSDL2_NewFrame(SDL_Window* window) | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); | ||||||
|  |     IM_ASSERT(bd->Window == window); // FIXME: Should remove parameter from ImGui_ImplSDL2_NewFrame() | ||||||
|  |  | ||||||
|     // Setup display size (every frame to accommodate for window resizing) |     // Setup display size (every frame to accommodate for window resizing) | ||||||
|     int w, h; |     int w, h; | ||||||
| @@ -366,8 +395,8 @@ void ImGui_ImplSDL2_NewFrame(SDL_Window* window) | |||||||
|     // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) |     // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) | ||||||
|     static Uint64 frequency = SDL_GetPerformanceFrequency(); |     static Uint64 frequency = SDL_GetPerformanceFrequency(); | ||||||
|     Uint64 current_time = SDL_GetPerformanceCounter(); |     Uint64 current_time = SDL_GetPerformanceCounter(); | ||||||
|     io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f); |     io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); | ||||||
|     g_Time = current_time; |     bd->Time = current_time; | ||||||
|  |  | ||||||
|     ImGui_ImplSDL2_UpdateMousePosAndButtons(); |     ImGui_ImplSDL2_UpdateMousePosAndButtons(); | ||||||
|     ImGui_ImplSDL2_UpdateMouseCursor(); |     ImGui_ImplSDL2_UpdateMouseCursor(); | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
| // Missing features: | // Missing features: | ||||||
| //  [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914 | //  [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914 | ||||||
|  |  | ||||||
| // 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. | ||||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | ||||||
| // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. | ||||||
| // Read online: https://github.com/ocornut/imgui/tree/master/docs | // Read online: https://github.com/ocornut/imgui/tree/master/docs | ||||||
| @@ -23,6 +23,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) | ||||||
|  | //  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-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize. | //  2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize. | ||||||
| //  2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer. | //  2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer. | ||||||
| //  2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions(). | //  2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions(). | ||||||
| @@ -77,33 +78,43 @@ struct ImGui_ImplVulkanH_WindowRenderBuffers | |||||||
| }; | }; | ||||||
|  |  | ||||||
| // Vulkan data | // Vulkan data | ||||||
| static ImGui_ImplVulkan_InitInfo g_VulkanInitInfo = {}; | struct ImGui_ImplVulkan_Data | ||||||
| static VkRenderPass             g_RenderPass = VK_NULL_HANDLE; | { | ||||||
| static VkDeviceSize             g_BufferMemoryAlignment = 256; |     ImGui_ImplVulkan_InitInfo   VulkanInitInfo; | ||||||
| static VkPipelineCreateFlags    g_PipelineCreateFlags = 0x00; |     VkRenderPass                RenderPass; | ||||||
| static VkDescriptorSetLayout    g_DescriptorSetLayout = VK_NULL_HANDLE; |     VkDeviceSize                BufferMemoryAlignment; | ||||||
| static VkPipelineLayout         g_PipelineLayout = VK_NULL_HANDLE; |     VkPipelineCreateFlags       PipelineCreateFlags; | ||||||
| static VkDescriptorSet          g_DescriptorSet = VK_NULL_HANDLE; |     VkDescriptorSetLayout       DescriptorSetLayout; | ||||||
| static VkPipeline               g_Pipeline = VK_NULL_HANDLE; |     VkPipelineLayout            PipelineLayout; | ||||||
| static uint32_t                 g_Subpass = 0; |     VkDescriptorSet             DescriptorSet; | ||||||
| static VkShaderModule           g_ShaderModuleVert; |     VkPipeline                  Pipeline; | ||||||
| static VkShaderModule           g_ShaderModuleFrag; |     uint32_t                    Subpass; | ||||||
| #ifdef VK_NO_PROTOTYPES |     VkShaderModule              ShaderModuleVert; | ||||||
| static bool                     g_FunctionsLoaded = false; |     VkShaderModule              ShaderModuleFrag; | ||||||
| #else |  | ||||||
| static bool                     g_FunctionsLoaded = true; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| // Font data |     // Font data | ||||||
| static VkSampler                g_FontSampler = VK_NULL_HANDLE; |     VkSampler                   FontSampler; | ||||||
| static VkDeviceMemory           g_FontMemory = VK_NULL_HANDLE; |     VkDeviceMemory              FontMemory; | ||||||
| static VkImage                  g_FontImage = VK_NULL_HANDLE; |     VkImage                     FontImage; | ||||||
| static VkImageView              g_FontView = VK_NULL_HANDLE; |     VkImageView                 FontView; | ||||||
| static VkDeviceMemory           g_UploadBufferMemory = VK_NULL_HANDLE; |     VkDeviceMemory              UploadBufferMemory; | ||||||
| static VkBuffer                 g_UploadBuffer = VK_NULL_HANDLE; |     VkBuffer                    UploadBuffer; | ||||||
|  |  | ||||||
| // Render buffers |     // Render buffers | ||||||
| static ImGui_ImplVulkanH_WindowRenderBuffers    g_MainWindowRenderBuffers; |     ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers; | ||||||
|  |  | ||||||
|  |     ImGui_ImplVulkan_Data() | ||||||
|  |     { | ||||||
|  |         memset(this, 0, sizeof(*this)); | ||||||
|  |         BufferMemoryAlignment = 256; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplVulkan_Data*   g_Data; | ||||||
|  | static ImGui_ImplVulkan_Data*   ImGui_ImplVulkan_CreateBackendData()    { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplVulkan_Data); return g_Data; } | ||||||
|  | static ImGui_ImplVulkan_Data*   ImGui_ImplVulkan_GetBackendData()       { return ImGui::GetCurrentContext() ? g_Data : NULL; } | ||||||
|  | static void                     ImGui_ImplVulkan_DestroyBackendData()   { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| // Forward Declarations | // Forward Declarations | ||||||
| bool ImGui_ImplVulkan_CreateDeviceObjects(); | bool ImGui_ImplVulkan_CreateDeviceObjects(); | ||||||
| @@ -118,6 +129,11 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi | |||||||
| // Vulkan prototypes for use with custom loaders | // Vulkan prototypes for use with custom loaders | ||||||
| // (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h | // (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h | ||||||
| #ifdef VK_NO_PROTOTYPES | #ifdef VK_NO_PROTOTYPES | ||||||
|  | static bool g_FunctionsLoaded = false; | ||||||
|  | #else | ||||||
|  | static bool g_FunctionsLoaded = true; | ||||||
|  | #endif | ||||||
|  | #ifdef VK_NO_PROTOTYPES | ||||||
| #define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \ | #define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \ | ||||||
|     IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \ |     IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \ | ||||||
|     IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \ |     IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \ | ||||||
| @@ -299,7 +315,8 @@ static uint32_t __glsl_shader_frag_spv[] = | |||||||
|  |  | ||||||
| static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) | static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) | ||||||
| { | { | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     VkPhysicalDeviceMemoryProperties prop; |     VkPhysicalDeviceMemoryProperties prop; | ||||||
|     vkGetPhysicalDeviceMemoryProperties(v->PhysicalDevice, &prop); |     vkGetPhysicalDeviceMemoryProperties(v->PhysicalDevice, &prop); | ||||||
|     for (uint32_t i = 0; i < prop.memoryTypeCount; i++) |     for (uint32_t i = 0; i < prop.memoryTypeCount; i++) | ||||||
| @@ -310,21 +327,25 @@ static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, ui | |||||||
|  |  | ||||||
| static void check_vk_result(VkResult err) | static void check_vk_result(VkResult err) | ||||||
| { | { | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     if (!bd) | ||||||
|  |         return; | ||||||
|  |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     if (v->CheckVkResultFn) |     if (v->CheckVkResultFn) | ||||||
|         v->CheckVkResultFn(err); |         v->CheckVkResultFn(err); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage) | static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage) | ||||||
| { | { | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     VkResult err; |     VkResult err; | ||||||
|     if (buffer != VK_NULL_HANDLE) |     if (buffer != VK_NULL_HANDLE) | ||||||
|         vkDestroyBuffer(v->Device, buffer, v->Allocator); |         vkDestroyBuffer(v->Device, buffer, v->Allocator); | ||||||
|     if (buffer_memory != VK_NULL_HANDLE) |     if (buffer_memory != VK_NULL_HANDLE) | ||||||
|         vkFreeMemory(v->Device, buffer_memory, v->Allocator); |         vkFreeMemory(v->Device, buffer_memory, v->Allocator); | ||||||
|  |  | ||||||
|     VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / g_BufferMemoryAlignment + 1) * g_BufferMemoryAlignment; |     VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / bd->BufferMemoryAlignment + 1) * bd->BufferMemoryAlignment; | ||||||
|     VkBufferCreateInfo buffer_info = {}; |     VkBufferCreateInfo buffer_info = {}; | ||||||
|     buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |     buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | ||||||
|     buffer_info.size = vertex_buffer_size_aligned; |     buffer_info.size = vertex_buffer_size_aligned; | ||||||
| @@ -335,7 +356,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory | |||||||
|  |  | ||||||
|     VkMemoryRequirements req; |     VkMemoryRequirements req; | ||||||
|     vkGetBufferMemoryRequirements(v->Device, buffer, &req); |     vkGetBufferMemoryRequirements(v->Device, buffer, &req); | ||||||
|     g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; |     bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment; | ||||||
|     VkMemoryAllocateInfo alloc_info = {}; |     VkMemoryAllocateInfo alloc_info = {}; | ||||||
|     alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; |     alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; | ||||||
|     alloc_info.allocationSize = req.size; |     alloc_info.allocationSize = req.size; | ||||||
| @@ -350,11 +371,13 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory | |||||||
|  |  | ||||||
| static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) | static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) | ||||||
| { | { | ||||||
|  |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |  | ||||||
|     // Bind pipeline and descriptor sets: |     // Bind pipeline and descriptor sets: | ||||||
|     { |     { | ||||||
|         vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); |         vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | ||||||
|         VkDescriptorSet desc_set[1] = { g_DescriptorSet }; |         VkDescriptorSet desc_set[1] = { bd->DescriptorSet }; | ||||||
|         vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); |         vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, NULL); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Bind Vertex And Index Buffer: |     // Bind Vertex And Index Buffer: | ||||||
| @@ -387,8 +410,8 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline | |||||||
|         float translate[2]; |         float translate[2]; | ||||||
|         translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; |         translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; | ||||||
|         translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; |         translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; | ||||||
|         vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); |         vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); | ||||||
|         vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); |         vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -401,12 +424,13 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm | |||||||
|     if (fb_width <= 0 || fb_height <= 0) |     if (fb_width <= 0 || fb_height <= 0) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     if (pipeline == VK_NULL_HANDLE) |     if (pipeline == VK_NULL_HANDLE) | ||||||
|         pipeline = g_Pipeline; |         pipeline = bd->Pipeline; | ||||||
|  |  | ||||||
|     // Allocate array to store enough vertex/index buffers |     // Allocate array to store enough vertex/index buffers | ||||||
|     ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &g_MainWindowRenderBuffers; |     ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers; | ||||||
|     if (wrb->FrameRenderBuffers == NULL) |     if (wrb->FrameRenderBuffers == NULL) | ||||||
|     { |     { | ||||||
|         wrb->Index = 0; |         wrb->Index = 0; | ||||||
| @@ -519,8 +543,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm | |||||||
|  |  | ||||||
| bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | ||||||
| { | { | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|  |  | ||||||
|     unsigned char* pixels; |     unsigned char* pixels; | ||||||
|     int width, height; |     int width, height; | ||||||
| @@ -545,17 +570,17 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
|         info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |         info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; | ||||||
|         info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |         info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | ||||||
|         info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |         info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; | ||||||
|         err = vkCreateImage(v->Device, &info, v->Allocator, &g_FontImage); |         err = vkCreateImage(v->Device, &info, v->Allocator, &bd->FontImage); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         VkMemoryRequirements req; |         VkMemoryRequirements req; | ||||||
|         vkGetImageMemoryRequirements(v->Device, g_FontImage, &req); |         vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req); | ||||||
|         VkMemoryAllocateInfo alloc_info = {}; |         VkMemoryAllocateInfo alloc_info = {}; | ||||||
|         alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; |         alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; | ||||||
|         alloc_info.allocationSize = req.size; |         alloc_info.allocationSize = req.size; | ||||||
|         alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); |         alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); | ||||||
|         err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &g_FontMemory); |         err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         err = vkBindImageMemory(v->Device, g_FontImage, g_FontMemory, 0); |         err = vkBindImageMemory(v->Device, bd->FontImage, bd->FontMemory, 0); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -563,25 +588,25 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
|     { |     { | ||||||
|         VkImageViewCreateInfo info = {}; |         VkImageViewCreateInfo info = {}; | ||||||
|         info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; |         info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; | ||||||
|         info.image = g_FontImage; |         info.image = bd->FontImage; | ||||||
|         info.viewType = VK_IMAGE_VIEW_TYPE_2D; |         info.viewType = VK_IMAGE_VIEW_TYPE_2D; | ||||||
|         info.format = VK_FORMAT_R8G8B8A8_UNORM; |         info.format = VK_FORMAT_R8G8B8A8_UNORM; | ||||||
|         info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |         info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | ||||||
|         info.subresourceRange.levelCount = 1; |         info.subresourceRange.levelCount = 1; | ||||||
|         info.subresourceRange.layerCount = 1; |         info.subresourceRange.layerCount = 1; | ||||||
|         err = vkCreateImageView(v->Device, &info, v->Allocator, &g_FontView); |         err = vkCreateImageView(v->Device, &info, v->Allocator, &bd->FontView); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Update the Descriptor Set: |     // Update the Descriptor Set: | ||||||
|     { |     { | ||||||
|         VkDescriptorImageInfo desc_image[1] = {}; |         VkDescriptorImageInfo desc_image[1] = {}; | ||||||
|         desc_image[0].sampler = g_FontSampler; |         desc_image[0].sampler = bd->FontSampler; | ||||||
|         desc_image[0].imageView = g_FontView; |         desc_image[0].imageView = bd->FontView; | ||||||
|         desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; |         desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; | ||||||
|         VkWriteDescriptorSet write_desc[1] = {}; |         VkWriteDescriptorSet write_desc[1] = {}; | ||||||
|         write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; |         write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; | ||||||
|         write_desc[0].dstSet = g_DescriptorSet; |         write_desc[0].dstSet = bd->DescriptorSet; | ||||||
|         write_desc[0].descriptorCount = 1; |         write_desc[0].descriptorCount = 1; | ||||||
|         write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; |         write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; | ||||||
|         write_desc[0].pImageInfo = desc_image; |         write_desc[0].pImageInfo = desc_image; | ||||||
| @@ -595,34 +620,34 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
|         buffer_info.size = upload_size; |         buffer_info.size = upload_size; | ||||||
|         buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; |         buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; | ||||||
|         buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |         buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; | ||||||
|         err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &g_UploadBuffer); |         err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &bd->UploadBuffer); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         VkMemoryRequirements req; |         VkMemoryRequirements req; | ||||||
|         vkGetBufferMemoryRequirements(v->Device, g_UploadBuffer, &req); |         vkGetBufferMemoryRequirements(v->Device, bd->UploadBuffer, &req); | ||||||
|         g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; |         bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment; | ||||||
|         VkMemoryAllocateInfo alloc_info = {}; |         VkMemoryAllocateInfo alloc_info = {}; | ||||||
|         alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; |         alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; | ||||||
|         alloc_info.allocationSize = req.size; |         alloc_info.allocationSize = req.size; | ||||||
|         alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); |         alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); | ||||||
|         err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &g_UploadBufferMemory); |         err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->UploadBufferMemory); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         err = vkBindBufferMemory(v->Device, g_UploadBuffer, g_UploadBufferMemory, 0); |         err = vkBindBufferMemory(v->Device, bd->UploadBuffer, bd->UploadBufferMemory, 0); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Upload to Buffer: |     // Upload to Buffer: | ||||||
|     { |     { | ||||||
|         char* map = NULL; |         char* map = NULL; | ||||||
|         err = vkMapMemory(v->Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); |         err = vkMapMemory(v->Device, bd->UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         memcpy(map, pixels, upload_size); |         memcpy(map, pixels, upload_size); | ||||||
|         VkMappedMemoryRange range[1] = {}; |         VkMappedMemoryRange range[1] = {}; | ||||||
|         range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; |         range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; | ||||||
|         range[0].memory = g_UploadBufferMemory; |         range[0].memory = bd->UploadBufferMemory; | ||||||
|         range[0].size = upload_size; |         range[0].size = upload_size; | ||||||
|         err = vkFlushMappedMemoryRanges(v->Device, 1, range); |         err = vkFlushMappedMemoryRanges(v->Device, 1, range); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|         vkUnmapMemory(v->Device, g_UploadBufferMemory); |         vkUnmapMemory(v->Device, bd->UploadBufferMemory); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Copy to Image: |     // Copy to Image: | ||||||
| @@ -634,7 +659,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
|         copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |         copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; | ||||||
|         copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |         copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | ||||||
|         copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |         copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | ||||||
|         copy_barrier[0].image = g_FontImage; |         copy_barrier[0].image = bd->FontImage; | ||||||
|         copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |         copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | ||||||
|         copy_barrier[0].subresourceRange.levelCount = 1; |         copy_barrier[0].subresourceRange.levelCount = 1; | ||||||
|         copy_barrier[0].subresourceRange.layerCount = 1; |         copy_barrier[0].subresourceRange.layerCount = 1; | ||||||
| @@ -646,7 +671,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
|         region.imageExtent.width = width; |         region.imageExtent.width = width; | ||||||
|         region.imageExtent.height = height; |         region.imageExtent.height = height; | ||||||
|         region.imageExtent.depth = 1; |         region.imageExtent.depth = 1; | ||||||
|         vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); |         vkCmdCopyBufferToImage(command_buffer, bd->UploadBuffer, bd->FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); | ||||||
|  |  | ||||||
|         VkImageMemoryBarrier use_barrier[1] = {}; |         VkImageMemoryBarrier use_barrier[1] = {}; | ||||||
|         use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; |         use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; | ||||||
| @@ -656,7 +681,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
|         use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; |         use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; | ||||||
|         use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |         use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | ||||||
|         use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |         use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | ||||||
|         use_barrier[0].image = g_FontImage; |         use_barrier[0].image = bd->FontImage; | ||||||
|         use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |         use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | ||||||
|         use_barrier[0].subresourceRange.levelCount = 1; |         use_barrier[0].subresourceRange.levelCount = 1; | ||||||
|         use_barrier[0].subresourceRange.layerCount = 1; |         use_barrier[0].subresourceRange.layerCount = 1; | ||||||
| @@ -664,7 +689,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Store our identifier |     // Store our identifier | ||||||
|     io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontImage); |     io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontImage); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| @@ -672,29 +697,31 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
| static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) | static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) | ||||||
| { | { | ||||||
|     // Create the shader modules |     // Create the shader modules | ||||||
|     if (g_ShaderModuleVert == NULL) |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     if (bd->ShaderModuleVert == NULL) | ||||||
|     { |     { | ||||||
|         VkShaderModuleCreateInfo vert_info = {}; |         VkShaderModuleCreateInfo vert_info = {}; | ||||||
|         vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; |         vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | ||||||
|         vert_info.codeSize = sizeof(__glsl_shader_vert_spv); |         vert_info.codeSize = sizeof(__glsl_shader_vert_spv); | ||||||
|         vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; |         vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; | ||||||
|         VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &g_ShaderModuleVert); |         VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &bd->ShaderModuleVert); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|     if (g_ShaderModuleFrag == NULL) |     if (bd->ShaderModuleFrag == NULL) | ||||||
|     { |     { | ||||||
|         VkShaderModuleCreateInfo frag_info = {}; |         VkShaderModuleCreateInfo frag_info = {}; | ||||||
|         frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; |         frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | ||||||
|         frag_info.codeSize = sizeof(__glsl_shader_frag_spv); |         frag_info.codeSize = sizeof(__glsl_shader_frag_spv); | ||||||
|         frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; |         frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; | ||||||
|         VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &g_ShaderModuleFrag); |         VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &bd->ShaderModuleFrag); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator) | static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator) | ||||||
| { | { | ||||||
|     if (g_FontSampler) |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     if (bd->FontSampler) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     VkSamplerCreateInfo info = {}; |     VkSamplerCreateInfo info = {}; | ||||||
| @@ -708,17 +735,18 @@ static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocati | |||||||
|     info.minLod = -1000; |     info.minLod = -1000; | ||||||
|     info.maxLod = 1000; |     info.maxLod = 1000; | ||||||
|     info.maxAnisotropy = 1.0f; |     info.maxAnisotropy = 1.0f; | ||||||
|     VkResult err = vkCreateSampler(device, &info, allocator, &g_FontSampler); |     VkResult err = vkCreateSampler(device, &info, allocator, &bd->FontSampler); | ||||||
|     check_vk_result(err); |     check_vk_result(err); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator) | static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator) | ||||||
| { | { | ||||||
|     if (g_DescriptorSetLayout) |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     if (bd->DescriptorSetLayout) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     ImGui_ImplVulkan_CreateFontSampler(device, allocator); |     ImGui_ImplVulkan_CreateFontSampler(device, allocator); | ||||||
|     VkSampler sampler[1] = { g_FontSampler }; |     VkSampler sampler[1] = { bd->FontSampler }; | ||||||
|     VkDescriptorSetLayoutBinding binding[1] = {}; |     VkDescriptorSetLayoutBinding binding[1] = {}; | ||||||
|     binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; |     binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; | ||||||
|     binding[0].descriptorCount = 1; |     binding[0].descriptorCount = 1; | ||||||
| @@ -728,13 +756,14 @@ static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const Vk | |||||||
|     info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; |     info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; | ||||||
|     info.bindingCount = 1; |     info.bindingCount = 1; | ||||||
|     info.pBindings = binding; |     info.pBindings = binding; | ||||||
|     VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &g_DescriptorSetLayout); |     VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &bd->DescriptorSetLayout); | ||||||
|     check_vk_result(err); |     check_vk_result(err); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator) | static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator) | ||||||
| { | { | ||||||
|     if (g_PipelineLayout) |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     if (bd->PipelineLayout) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix |     // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix | ||||||
| @@ -743,29 +772,30 @@ static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAlloc | |||||||
|     push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; |     push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; | ||||||
|     push_constants[0].offset = sizeof(float) * 0; |     push_constants[0].offset = sizeof(float) * 0; | ||||||
|     push_constants[0].size = sizeof(float) * 4; |     push_constants[0].size = sizeof(float) * 4; | ||||||
|     VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout }; |     VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout }; | ||||||
|     VkPipelineLayoutCreateInfo layout_info = {}; |     VkPipelineLayoutCreateInfo layout_info = {}; | ||||||
|     layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |     layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; | ||||||
|     layout_info.setLayoutCount = 1; |     layout_info.setLayoutCount = 1; | ||||||
|     layout_info.pSetLayouts = set_layout; |     layout_info.pSetLayouts = set_layout; | ||||||
|     layout_info.pushConstantRangeCount = 1; |     layout_info.pushConstantRangeCount = 1; | ||||||
|     layout_info.pPushConstantRanges = push_constants; |     layout_info.pPushConstantRanges = push_constants; | ||||||
|     VkResult  err = vkCreatePipelineLayout(device, &layout_info, allocator, &g_PipelineLayout); |     VkResult  err = vkCreatePipelineLayout(device, &layout_info, allocator, &bd->PipelineLayout); | ||||||
|     check_vk_result(err); |     check_vk_result(err); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass) | static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass) | ||||||
| { | { | ||||||
|  |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|     ImGui_ImplVulkan_CreateShaderModules(device, allocator); |     ImGui_ImplVulkan_CreateShaderModules(device, allocator); | ||||||
|  |  | ||||||
|     VkPipelineShaderStageCreateInfo stage[2] = {}; |     VkPipelineShaderStageCreateInfo stage[2] = {}; | ||||||
|     stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |     stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; | ||||||
|     stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; |     stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; | ||||||
|     stage[0].module = g_ShaderModuleVert; |     stage[0].module = bd->ShaderModuleVert; | ||||||
|     stage[0].pName = "main"; |     stage[0].pName = "main"; | ||||||
|     stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |     stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; | ||||||
|     stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; |     stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; | ||||||
|     stage[1].module = g_ShaderModuleFrag; |     stage[1].module = bd->ShaderModuleFrag; | ||||||
|     stage[1].pName = "main"; |     stage[1].pName = "main"; | ||||||
|  |  | ||||||
|     VkVertexInputBindingDescription binding_desc[1] = {}; |     VkVertexInputBindingDescription binding_desc[1] = {}; | ||||||
| @@ -841,7 +871,7 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC | |||||||
|  |  | ||||||
|     VkGraphicsPipelineCreateInfo info = {}; |     VkGraphicsPipelineCreateInfo info = {}; | ||||||
|     info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; |     info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; | ||||||
|     info.flags = g_PipelineCreateFlags; |     info.flags = bd->PipelineCreateFlags; | ||||||
|     info.stageCount = 2; |     info.stageCount = 2; | ||||||
|     info.pStages = stage; |     info.pStages = stage; | ||||||
|     info.pVertexInputState = &vertex_info; |     info.pVertexInputState = &vertex_info; | ||||||
| @@ -852,7 +882,7 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC | |||||||
|     info.pDepthStencilState = &depth_info; |     info.pDepthStencilState = &depth_info; | ||||||
|     info.pColorBlendState = &blend_info; |     info.pColorBlendState = &blend_info; | ||||||
|     info.pDynamicState = &dynamic_state; |     info.pDynamicState = &dynamic_state; | ||||||
|     info.layout = g_PipelineLayout; |     info.layout = bd->PipelineLayout; | ||||||
|     info.renderPass = renderPass; |     info.renderPass = renderPass; | ||||||
|     info.subpass = subpass; |     info.subpass = subpass; | ||||||
|     VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline); |     VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline); | ||||||
| @@ -861,10 +891,11 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC | |||||||
|  |  | ||||||
| bool ImGui_ImplVulkan_CreateDeviceObjects() | bool ImGui_ImplVulkan_CreateDeviceObjects() | ||||||
| { | { | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|  |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     VkResult err; |     VkResult err; | ||||||
|  |  | ||||||
|     if (!g_FontSampler) |     if (!bd->FontSampler) | ||||||
|     { |     { | ||||||
|         VkSamplerCreateInfo info = {}; |         VkSamplerCreateInfo info = {}; | ||||||
|         info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; |         info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; | ||||||
| @@ -877,13 +908,13 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() | |||||||
|         info.minLod = -1000; |         info.minLod = -1000; | ||||||
|         info.maxLod = 1000; |         info.maxLod = 1000; | ||||||
|         info.maxAnisotropy = 1.0f; |         info.maxAnisotropy = 1.0f; | ||||||
|         err = vkCreateSampler(v->Device, &info, v->Allocator, &g_FontSampler); |         err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->FontSampler); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!g_DescriptorSetLayout) |     if (!bd->DescriptorSetLayout) | ||||||
|     { |     { | ||||||
|         VkSampler sampler[1] = {g_FontSampler}; |         VkSampler sampler[1] = {bd->FontSampler}; | ||||||
|         VkDescriptorSetLayoutBinding binding[1] = {}; |         VkDescriptorSetLayoutBinding binding[1] = {}; | ||||||
|         binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; |         binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; | ||||||
|         binding[0].descriptorCount = 1; |         binding[0].descriptorCount = 1; | ||||||
| @@ -893,7 +924,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() | |||||||
|         info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; |         info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; | ||||||
|         info.bindingCount = 1; |         info.bindingCount = 1; | ||||||
|         info.pBindings = binding; |         info.pBindings = binding; | ||||||
|         err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &g_DescriptorSetLayout); |         err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &bd->DescriptorSetLayout); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -903,64 +934,66 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() | |||||||
|         alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; |         alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; | ||||||
|         alloc_info.descriptorPool = v->DescriptorPool; |         alloc_info.descriptorPool = v->DescriptorPool; | ||||||
|         alloc_info.descriptorSetCount = 1; |         alloc_info.descriptorSetCount = 1; | ||||||
|         alloc_info.pSetLayouts = &g_DescriptorSetLayout; |         alloc_info.pSetLayouts = &bd->DescriptorSetLayout; | ||||||
|         err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet); |         err = vkAllocateDescriptorSets(v->Device, &alloc_info, &bd->DescriptorSet); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!g_PipelineLayout) |     if (!bd->PipelineLayout) | ||||||
|     { |     { | ||||||
|         // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix |         // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix | ||||||
|         VkPushConstantRange push_constants[1] = {}; |         VkPushConstantRange push_constants[1] = {}; | ||||||
|         push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; |         push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; | ||||||
|         push_constants[0].offset = sizeof(float) * 0; |         push_constants[0].offset = sizeof(float) * 0; | ||||||
|         push_constants[0].size = sizeof(float) * 4; |         push_constants[0].size = sizeof(float) * 4; | ||||||
|         VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout }; |         VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout }; | ||||||
|         VkPipelineLayoutCreateInfo layout_info = {}; |         VkPipelineLayoutCreateInfo layout_info = {}; | ||||||
|         layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |         layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; | ||||||
|         layout_info.setLayoutCount = 1; |         layout_info.setLayoutCount = 1; | ||||||
|         layout_info.pSetLayouts = set_layout; |         layout_info.pSetLayouts = set_layout; | ||||||
|         layout_info.pushConstantRangeCount = 1; |         layout_info.pushConstantRangeCount = 1; | ||||||
|         layout_info.pPushConstantRanges = push_constants; |         layout_info.pPushConstantRanges = push_constants; | ||||||
|         err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &g_PipelineLayout); |         err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &bd->PipelineLayout); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, g_RenderPass, v->MSAASamples, &g_Pipeline, g_Subpass); |     ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, bd->RenderPass, v->MSAASamples, &bd->Pipeline, bd->Subpass); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void    ImGui_ImplVulkan_DestroyFontUploadObjects() | void    ImGui_ImplVulkan_DestroyFontUploadObjects() | ||||||
| { | { | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|     if (g_UploadBuffer) |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|  |     if (bd->UploadBuffer) | ||||||
|     { |     { | ||||||
|         vkDestroyBuffer(v->Device, g_UploadBuffer, v->Allocator); |         vkDestroyBuffer(v->Device, bd->UploadBuffer, v->Allocator); | ||||||
|         g_UploadBuffer = VK_NULL_HANDLE; |         bd->UploadBuffer = VK_NULL_HANDLE; | ||||||
|     } |     } | ||||||
|     if (g_UploadBufferMemory) |     if (bd->UploadBufferMemory) | ||||||
|     { |     { | ||||||
|         vkFreeMemory(v->Device, g_UploadBufferMemory, v->Allocator); |         vkFreeMemory(v->Device, bd->UploadBufferMemory, v->Allocator); | ||||||
|         g_UploadBufferMemory = VK_NULL_HANDLE; |         bd->UploadBufferMemory = VK_NULL_HANDLE; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void    ImGui_ImplVulkan_DestroyDeviceObjects() | void    ImGui_ImplVulkan_DestroyDeviceObjects() | ||||||
| { | { | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|     ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator); |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|  |     ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); | ||||||
|     ImGui_ImplVulkan_DestroyFontUploadObjects(); |     ImGui_ImplVulkan_DestroyFontUploadObjects(); | ||||||
|  |  | ||||||
|     if (g_ShaderModuleVert)     { vkDestroyShaderModule(v->Device, g_ShaderModuleVert, v->Allocator); g_ShaderModuleVert = VK_NULL_HANDLE; } |     if (bd->ShaderModuleVert)     { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; } | ||||||
|     if (g_ShaderModuleFrag)     { vkDestroyShaderModule(v->Device, g_ShaderModuleFrag, v->Allocator); g_ShaderModuleFrag = VK_NULL_HANDLE; } |     if (bd->ShaderModuleFrag)     { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; } | ||||||
|     if (g_FontView)             { vkDestroyImageView(v->Device, g_FontView, v->Allocator); g_FontView = VK_NULL_HANDLE; } |     if (bd->FontView)             { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; } | ||||||
|     if (g_FontImage)            { vkDestroyImage(v->Device, g_FontImage, v->Allocator); g_FontImage = VK_NULL_HANDLE; } |     if (bd->FontImage)            { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; } | ||||||
|     if (g_FontMemory)           { vkFreeMemory(v->Device, g_FontMemory, v->Allocator); g_FontMemory = VK_NULL_HANDLE; } |     if (bd->FontMemory)           { vkFreeMemory(v->Device, bd->FontMemory, v->Allocator); bd->FontMemory = VK_NULL_HANDLE; } | ||||||
|     if (g_FontSampler)          { vkDestroySampler(v->Device, g_FontSampler, v->Allocator); g_FontSampler = VK_NULL_HANDLE; } |     if (bd->FontSampler)          { vkDestroySampler(v->Device, bd->FontSampler, v->Allocator); bd->FontSampler = VK_NULL_HANDLE; } | ||||||
|     if (g_DescriptorSetLayout)  { vkDestroyDescriptorSetLayout(v->Device, g_DescriptorSetLayout, v->Allocator); g_DescriptorSetLayout = VK_NULL_HANDLE; } |     if (bd->DescriptorSetLayout)  { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; } | ||||||
|     if (g_PipelineLayout)       { vkDestroyPipelineLayout(v->Device, g_PipelineLayout, v->Allocator); g_PipelineLayout = VK_NULL_HANDLE; } |     if (bd->PipelineLayout)       { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; } | ||||||
|     if (g_Pipeline)             { vkDestroyPipeline(v->Device, g_Pipeline, v->Allocator); g_Pipeline = VK_NULL_HANDLE; } |     if (bd->Pipeline)             { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; } | ||||||
| } | } | ||||||
|  |  | ||||||
| bool    ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) | bool    ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) | ||||||
| @@ -988,8 +1021,12 @@ bool    ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend | |||||||
| { | { | ||||||
|     IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!"); |     IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!"); | ||||||
|  |  | ||||||
|     // Setup backend capabilities flags |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!"); | ||||||
|  |  | ||||||
|  |     // Setup backend capabilities flags | ||||||
|  |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_CreateBackendData(); | ||||||
|  |     io.BackendRendererUserData = (void*)bd; | ||||||
|     io.BackendRendererName = "imgui_impl_vulkan"; |     io.BackendRendererName = "imgui_impl_vulkan"; | ||||||
|     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. | ||||||
|  |  | ||||||
| @@ -1002,9 +1039,9 @@ bool    ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend | |||||||
|     IM_ASSERT(info->ImageCount >= info->MinImageCount); |     IM_ASSERT(info->ImageCount >= info->MinImageCount); | ||||||
|     IM_ASSERT(render_pass != VK_NULL_HANDLE); |     IM_ASSERT(render_pass != VK_NULL_HANDLE); | ||||||
|  |  | ||||||
|     g_VulkanInitInfo = *info; |     bd->VulkanInitInfo = *info; | ||||||
|     g_RenderPass = render_pass; |     bd->RenderPass = render_pass; | ||||||
|     g_Subpass = info->Subpass; |     bd->Subpass = info->Subpass; | ||||||
|  |  | ||||||
|     ImGui_ImplVulkan_CreateDeviceObjects(); |     ImGui_ImplVulkan_CreateDeviceObjects(); | ||||||
|  |  | ||||||
| @@ -1013,7 +1050,11 @@ bool    ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend | |||||||
|  |  | ||||||
| void ImGui_ImplVulkan_Shutdown() | void ImGui_ImplVulkan_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     ImGui_ImplVulkan_DestroyDeviceObjects(); |     ImGui_ImplVulkan_DestroyDeviceObjects(); | ||||||
|  |     io.BackendRendererName = NULL; | ||||||
|  |     io.BackendRendererUserData = NULL; | ||||||
|  |     ImGui_ImplVulkan_DestroyBackendData(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui_ImplVulkan_NewFrame() | void ImGui_ImplVulkan_NewFrame() | ||||||
| @@ -1022,15 +1063,16 @@ void ImGui_ImplVulkan_NewFrame() | |||||||
|  |  | ||||||
| void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count) | void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count) | ||||||
| { | { | ||||||
|  |     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); | ||||||
|     IM_ASSERT(min_image_count >= 2); |     IM_ASSERT(min_image_count >= 2); | ||||||
|     if (g_VulkanInitInfo.MinImageCount == min_image_count) |     if (bd->VulkanInitInfo.MinImageCount == min_image_count) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; | ||||||
|     VkResult err = vkDeviceWaitIdle(v->Device); |     VkResult err = vkDeviceWaitIdle(v->Device); | ||||||
|     check_vk_result(err); |     check_vk_result(err); | ||||||
|     ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator); |     ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); | ||||||
|     g_VulkanInitInfo.MinImageCount = min_image_count; |     bd->VulkanInitInfo.MinImageCount = min_image_count; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1300,7 +1342,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V | |||||||
|  |  | ||||||
|         // We do not create a pipeline by default as this is also used by examples' main.cpp, |         // We do not create a pipeline by default as this is also used by examples' main.cpp, | ||||||
|         // but secondary viewport in multi-viewport mode may want to create one with: |         // but secondary viewport in multi-viewport mode may want to create one with: | ||||||
|         //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, g_Subpass); |         //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, bd->Subpass); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create The Image Views |     // Create The Image Views | ||||||
| @@ -1357,7 +1399,7 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic | |||||||
| void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator) | void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator) | ||||||
| { | { | ||||||
|     vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals) |     vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals) | ||||||
|     //vkQueueWaitIdle(g_Queue); |     //vkQueueWaitIdle(bd->Queue); | ||||||
|  |  | ||||||
|     for (uint32_t i = 0; i < wd->ImageCount; i++) |     for (uint32_t i = 0; i < wd->ImageCount; i++) | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); | |||||||
|  |  | ||||||
| // 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) | ||||||
|  | //  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-06-08: Fix ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1). | //  2021-06-08: Fix ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1). | ||||||
| //  2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS). | //  2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS). | ||||||
| //  2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). | //  2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). | ||||||
| @@ -63,35 +64,54 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); | |||||||
| //  2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. | //  2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. | ||||||
| //  2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set. | //  2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set. | ||||||
|  |  | ||||||
| // Win32 Data | struct ImGui_ImplWin32_Data | ||||||
| static HWND                 g_hWnd = NULL; | { | ||||||
| static INT64                g_Time = 0; |     HWND                        hWnd; | ||||||
| static INT64                g_TicksPerSecond = 0; |     INT64                       Time; | ||||||
| static ImGuiMouseCursor     g_LastMouseCursor = ImGuiMouseCursor_COUNT; |     INT64                       TicksPerSecond; | ||||||
| static bool                 g_HasGamepad = false; |     ImGuiMouseCursor            LastMouseCursor; | ||||||
| static bool                 g_WantUpdateHasGamepad = true; |     bool                        HasGamepad; | ||||||
|  |     bool                        WantUpdateHasGamepad; | ||||||
|  |  | ||||||
| // XInput DLL and functions |  | ||||||
| #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | ||||||
| static HMODULE                      g_XInputDLL = NULL; |     HMODULE                     XInputDLL; | ||||||
| static PFN_XInputGetCapabilities    g_XInputGetCapabilities = NULL; |     PFN_XInputGetCapabilities   XInputGetCapabilities; | ||||||
| static PFN_XInputGetState           g_XInputGetState = NULL; |     PFN_XInputGetState          XInputGetState; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |     ImGui_ImplWin32_Data()      { memset(this, 0, sizeof(*this)); } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Wrapping access to backend data (to facilitate multiple-contexts stored in io.BackendPlatformUserData) | ||||||
|  | static ImGui_ImplWin32_Data*    g_Data; | ||||||
|  | static ImGui_ImplWin32_Data*    ImGui_ImplWin32_CreateBackendData()     { IM_ASSERT(g_Data == NULL); g_Data = IM_NEW(ImGui_ImplWin32_Data); return g_Data; } | ||||||
|  | static ImGui_ImplWin32_Data*    ImGui_ImplWin32_GetBackendData()        { return ImGui::GetCurrentContext() ? g_Data : NULL; } | ||||||
|  | static void                     ImGui_ImplWin32_DestroyBackendData()    { IM_DELETE(g_Data); g_Data = NULL; } | ||||||
|  |  | ||||||
| // Functions | // Functions | ||||||
| bool    ImGui_ImplWin32_Init(void* hwnd) | bool    ImGui_ImplWin32_Init(void* hwnd) | ||||||
| { | { | ||||||
|     if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&g_TicksPerSecond)) |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!"); | ||||||
|  |  | ||||||
|  |     INT64 perf_frequency, perf_counter; | ||||||
|  |     if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency)) | ||||||
|         return false; |         return false; | ||||||
|     if (!::QueryPerformanceCounter((LARGE_INTEGER*)&g_Time)) |     if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter)) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|  |     ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_CreateBackendData(); | ||||||
|  |     bd->hWnd = (HWND)hwnd; | ||||||
|  |     bd->WantUpdateHasGamepad = true; | ||||||
|  |     bd->TicksPerSecond = perf_frequency; | ||||||
|  |     bd->Time = perf_counter; | ||||||
|  |     bd->LastMouseCursor = ImGuiMouseCursor_COUNT; | ||||||
|  |  | ||||||
|     // Setup backend capabilities flags |     // Setup backend capabilities flags | ||||||
|     g_hWnd = (HWND)hwnd; |     io.BackendPlatformUserData = (void*)bd; | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     io.BackendPlatformName = "imgui_impl_win32"; | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;         // We can honor GetMouseCursor() values (optional) |     io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;         // We can honor GetMouseCursor() values (optional) | ||||||
|     io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;          // We can honor io.WantSetMousePos requests (optional, rarely used) |     io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;          // We can honor io.WantSetMousePos requests (optional, rarely used) | ||||||
|     io.BackendPlatformName = "imgui_impl_win32"; |  | ||||||
|     io.ImeWindowHandle = hwnd; |     io.ImeWindowHandle = hwnd; | ||||||
|  |  | ||||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. |     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. | ||||||
| @@ -131,9 +151,9 @@ bool    ImGui_ImplWin32_Init(void* hwnd) | |||||||
|     for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++) |     for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++) | ||||||
|         if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n])) |         if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n])) | ||||||
|         { |         { | ||||||
|             g_XInputDLL = dll; |             bd->XInputDLL = dll; | ||||||
|             g_XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities"); |             bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities"); | ||||||
|             g_XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState"); |             bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | ||||||
| @@ -143,21 +163,18 @@ bool    ImGui_ImplWin32_Init(void* hwnd) | |||||||
|  |  | ||||||
| void    ImGui_ImplWin32_Shutdown() | void    ImGui_ImplWin32_Shutdown() | ||||||
| { | { | ||||||
|  |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | ||||||
|  |  | ||||||
|     // Unload XInput library |     // Unload XInput library | ||||||
| #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | ||||||
|     if (g_XInputDLL) |     if (bd->XInputDLL) | ||||||
|         ::FreeLibrary(g_XInputDLL); |         ::FreeLibrary(bd->XInputDLL); | ||||||
|     g_XInputDLL = NULL; |  | ||||||
|     g_XInputGetCapabilities = NULL; |  | ||||||
|     g_XInputGetState = NULL; |  | ||||||
| #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | ||||||
|  |  | ||||||
|     g_hWnd = NULL; |     io.BackendPlatformName = NULL; | ||||||
|     g_Time = 0; |     io.BackendPlatformUserData = NULL; | ||||||
|     g_TicksPerSecond = 0; |     ImGui_ImplWin32_DestroyBackendData(); | ||||||
|     g_LastMouseCursor = ImGuiMouseCursor_COUNT; |  | ||||||
|     g_HasGamepad = false; |  | ||||||
|     g_WantUpdateHasGamepad = true; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static bool ImGui_ImplWin32_UpdateMouseCursor() | static bool ImGui_ImplWin32_UpdateMouseCursor() | ||||||
| @@ -196,13 +213,14 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() | |||||||
| static void ImGui_ImplWin32_UpdateMousePos() | static void ImGui_ImplWin32_UpdateMousePos() | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|     IM_ASSERT(g_hWnd != 0); |     ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | ||||||
|  |     IM_ASSERT(bd->hWnd != 0); | ||||||
|  |  | ||||||
|     // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) |     // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) | ||||||
|     if (io.WantSetMousePos) |     if (io.WantSetMousePos) | ||||||
|     { |     { | ||||||
|         POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; |         POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; | ||||||
|         if (::ClientToScreen(g_hWnd, &pos)) |         if (::ClientToScreen(bd->hWnd, &pos)) | ||||||
|             ::SetCursorPos(pos.x, pos.y); |             ::SetCursorPos(pos.x, pos.y); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -210,8 +228,8 @@ static void ImGui_ImplWin32_UpdateMousePos() | |||||||
|     io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); |     io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); | ||||||
|     POINT pos; |     POINT pos; | ||||||
|     if (HWND active_window = ::GetForegroundWindow()) |     if (HWND active_window = ::GetForegroundWindow()) | ||||||
|         if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd)) |         if (active_window == bd->hWnd || ::IsChild(active_window, bd->hWnd)) | ||||||
|             if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos)) |             if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos)) | ||||||
|                 io.MousePos = ImVec2((float)pos.x, (float)pos.y); |                 io.MousePos = ImVec2((float)pos.x, (float)pos.y); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -220,22 +238,23 @@ static void ImGui_ImplWin32_UpdateGamepads() | |||||||
| { | { | ||||||
| #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | ||||||
|     memset(io.NavInputs, 0, sizeof(io.NavInputs)); |     memset(io.NavInputs, 0, sizeof(io.NavInputs)); | ||||||
|     if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) |     if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. |     // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. | ||||||
|     // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. |     // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. | ||||||
|     if (g_WantUpdateHasGamepad) |     if (bd->WantUpdateHasGamepad) | ||||||
|     { |     { | ||||||
|         XINPUT_CAPABILITIES caps; |         XINPUT_CAPABILITIES caps; | ||||||
|         g_HasGamepad = g_XInputGetCapabilities ? (g_XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; |         bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; | ||||||
|         g_WantUpdateHasGamepad = false; |         bd->WantUpdateHasGamepad = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; |     io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; | ||||||
|     XINPUT_STATE xinput_state; |     XINPUT_STATE xinput_state; | ||||||
|     if (g_HasGamepad && g_XInputGetState && g_XInputGetState(0, &xinput_state) == ERROR_SUCCESS) |     if (bd->HasGamepad && bd->XInputGetState && bd->XInputGetState(0, &xinput_state) == ERROR_SUCCESS) | ||||||
|     { |     { | ||||||
|         const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; |         const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; | ||||||
|         io.BackendFlags |= ImGuiBackendFlags_HasGamepad; |         io.BackendFlags |= ImGuiBackendFlags_HasGamepad; | ||||||
| @@ -267,17 +286,18 @@ static void ImGui_ImplWin32_UpdateGamepads() | |||||||
| void    ImGui_ImplWin32_NewFrame() | void    ImGui_ImplWin32_NewFrame() | ||||||
| { | { | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | ||||||
|  |  | ||||||
|     // Setup display size (every frame to accommodate for window resizing) |     // Setup display size (every frame to accommodate for window resizing) | ||||||
|     RECT rect = { 0, 0, 0, 0 }; |     RECT rect = { 0, 0, 0, 0 }; | ||||||
|     ::GetClientRect(g_hWnd, &rect); |     ::GetClientRect(bd->hWnd, &rect); | ||||||
|     io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); |     io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); | ||||||
|  |  | ||||||
|     // Setup time step |     // Setup time step | ||||||
|     INT64 current_time = 0; |     INT64 current_time = 0; | ||||||
|     ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); |     ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); | ||||||
|     io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; |     io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond; | ||||||
|     g_Time = current_time; |     bd->Time = current_time; | ||||||
|  |  | ||||||
|     // Read keyboard modifiers inputs |     // Read keyboard modifiers inputs | ||||||
|     io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; |     io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; | ||||||
| @@ -291,9 +311,9 @@ void    ImGui_ImplWin32_NewFrame() | |||||||
|  |  | ||||||
|     // Update OS mouse cursor with the cursor requested by imgui |     // Update OS mouse cursor with the cursor requested by imgui | ||||||
|     ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); |     ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); | ||||||
|     if (g_LastMouseCursor != mouse_cursor) |     if (bd->LastMouseCursor != mouse_cursor) | ||||||
|     { |     { | ||||||
|         g_LastMouseCursor = mouse_cursor; |         bd->LastMouseCursor = mouse_cursor; | ||||||
|         ImGui_ImplWin32_UpdateMouseCursor(); |         ImGui_ImplWin32_UpdateMouseCursor(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -327,6 +347,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA | |||||||
|         return 0; |         return 0; | ||||||
|  |  | ||||||
|     ImGuiIO& io = ImGui::GetIO(); |     ImGuiIO& io = ImGui::GetIO(); | ||||||
|  |     ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); | ||||||
|  |  | ||||||
|     switch (msg) |     switch (msg) | ||||||
|     { |     { | ||||||
|     case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: |     case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: | ||||||
| @@ -389,7 +411,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA | |||||||
|         return 0; |         return 0; | ||||||
|     case WM_DEVICECHANGE: |     case WM_DEVICECHANGE: | ||||||
|         if ((UINT)wParam == DBT_DEVNODES_CHANGED) |         if ((UINT)wParam == DBT_DEVNODES_CHANGED) | ||||||
|             g_WantUpdateHasGamepad = true; |             bd->WantUpdateHasGamepad = true; | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
|   | |||||||
| @@ -55,6 +55,8 @@ Other Changes: | |||||||
| - Demo: Fixed requirement in 1.83 to link with imgui_demo.cpp if IMGUI_DISABLE_METRICS_WINDOW is not set. (#4171) | - Demo: Fixed requirement in 1.83 to link with imgui_demo.cpp if IMGUI_DISABLE_METRICS_WINDOW is not set. (#4171) | ||||||
|   Normally the right way to disable compiling the demo is to set IMGUI_DISABLE_DEMO_WINDOWS, but we want to avoid |   Normally the right way to disable compiling the demo is to set IMGUI_DISABLE_DEMO_WINDOWS, but we want to avoid | ||||||
|   implying that the file is required. |   implying that the file is required. | ||||||
|  | - Backends: Reorganized most backends (Win32, SDL, GLFW, OpenGL2/3, DX9/10/11/12, Vulkan, Allegro) to pull data | ||||||
|  |   from a single structure to facilitate usage with multiple-contexts. (#586, #1851, #2004, #3012, #3934, #4141) | ||||||
| - Backends: Win32: Rework to handle certains Windows 8.1/10 features without a manifest. (#4200, #4191) | - Backends: Win32: Rework to handle certains Windows 8.1/10 features without a manifest. (#4200, #4191) | ||||||
|   - ImGui_ImplWin32_GetDpiScaleForMonitor() will handle per-monitor DPI on Windows 10 without a manifest. |   - ImGui_ImplWin32_GetDpiScaleForMonitor() will handle per-monitor DPI on Windows 10 without a manifest. | ||||||
|   - ImGui_ImplWin32_EnableDpiAwareness() will call SetProcessDpiAwareness() fallback on Windows 8.1 without a manifest. |   - ImGui_ImplWin32_EnableDpiAwareness() will call SetProcessDpiAwareness() fallback on Windows 8.1 without a manifest. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user