From e3001fb986f39c08c661213afa68608774d2a321 Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Mon, 11 Aug 2014 20:43:24 +0430 Subject: [PATCH 1/9] project update --- imgui.cpp | 6 ++++++ libimgui.pro | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 libimgui.pro diff --git a/imgui.cpp b/imgui.cpp index e5aca50c..1242b02e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -161,6 +161,12 @@ #include // vsnprintf #include // memset +#ifdef __GNUC__ + #include + #include +#endif + + #ifdef _MSC_VER #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif diff --git a/libimgui.pro b/libimgui.pro new file mode 100644 index 00000000..c153b4e3 --- /dev/null +++ b/libimgui.pro @@ -0,0 +1,20 @@ +TEMPLATE = lib +CONFIG += static +CONFIG -= app_bundle +CONFIG -= qt +CONFIG -= warn_on + +CONFIG(release, debug|release) { + TARGET = imgui +} + +CONFIG(debug, debug|release) { + TARGET = imgui-dbg +} + +SOURCES += \ + imgui.cpp + +HEADERS += \ + imgui.h \ + imconfig.h From 6d6ee4e1f1ae049e0a818761cbecde515a4e66c9 Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Thu, 14 Aug 2014 19:21:01 +0430 Subject: [PATCH 2/9] revert back to original --- imgui.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 888a43bd..05ef8c1f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -162,12 +162,6 @@ #include // vsnprintf #include // memset -#ifdef __GNUC__ - #include - #include -#endif - - #ifdef _MSC_VER #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif From 1956703c42c1f1dfb04de45b3925ba8323329ab4 Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Sat, 16 Aug 2014 12:58:29 +0430 Subject: [PATCH 3/9] First attempt at memory management --- imgui.cpp | 122 +++++++++++++++++++++++------- imgui.h | 46 ++++++++--- immem.h | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++ libimgui.pro | 3 +- 4 files changed, 341 insertions(+), 40 deletions(-) create mode 100644 immem.h diff --git a/imgui.cpp b/imgui.cpp index 05ef8c1f..54973ba0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -166,6 +166,15 @@ #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif +#include +#define IMGUI_INTERNAL_USE +#include "immem.h" +#undef IMGUI_INTERNAL_USE + +// Block sizes for each memory. Don't really know about the optimized values +#define DRAWLIST_BLOCK_SIZE 128 +#define GUIWINDOW_BLOCK_SIZE 64 + //------------------------------------------------------------------------- // Forward Declarations //------------------------------------------------------------------------- @@ -194,6 +203,9 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs); }; // namespace ImGui +static char* StrDup(const char *str); +static void StrDup_Free(char *str); + //----------------------------------------------------------------------------- // Platform dependant default implementations //----------------------------------------------------------------------------- @@ -262,6 +274,10 @@ ImGuiStyle::ImGuiStyle() ImGuiIO::ImGuiIO() { memset(this, 0, sizeof(*this)); + + MallocFn = malloc; + FreeFn = free; + DeltaTime = 1.0f/60.0f; IniSavingRate = 5.0f; IniFilename = "imgui.ini"; @@ -585,7 +601,7 @@ struct ImGuiIniData bool Collapsed; ImGuiIniData() { memset(this, 0, sizeof(*this)); } - ~ImGuiIniData() { if (Name) { free(Name); Name = NULL; } } + ~ImGuiIniData() { if (Name) { StrDup_Free(Name); Name = NULL; } } }; struct ImGuiState @@ -624,9 +640,13 @@ struct ImGuiState // Logging bool LogEnabled; FILE* LogFile; - ImGuiTextBuffer LogClipboard; + ImGuiTextBuffer LogClipboard; int LogAutoExpandMaxDepth; + // Memory Pools + PoolAlloc DrawListPool; + PoolAlloc GuiWindowPool; + ImGuiState() { Initialized = false; @@ -646,7 +666,7 @@ struct ImGuiState PrivateClipboard = NULL; LogEnabled = false; LogFile = NULL; - LogAutoExpandMaxDepth = 2; + LogAutoExpandMaxDepth = 2; } }; @@ -907,7 +927,7 @@ void ImGuiTextBuffer::append(const char* fmt, ...) ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_size) { - Name = strdup(name); + Name = StrDup(name); ID = GetID(name); IDStack.push_back(ID); @@ -932,14 +952,17 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si FocusIdxRequestCurrent = IM_INT_MAX; FocusIdxRequestNext = IM_INT_MAX; - DrawList = new ImDrawList(); + ImDrawList *buff = GImGui.DrawListPool.alloc(); + IM_ASSERT(buff); + DrawList = new(buff) ImDrawList(); } ImGuiWindow::~ImGuiWindow() { - delete DrawList; + DrawList->~ImDrawList(); + GImGui.DrawListPool.free(DrawList); DrawList = NULL; - free(Name); + StrDup_Free(Name); Name = NULL; } @@ -1019,9 +1042,9 @@ static ImGuiIniData* FindWindowSettings(const char* name) if (ImStricmp(ini->Name, name) == 0) return ini; } - ImGuiIniData* ini = new ImGuiIniData(); - ini->Name = strdup(name); - ini->Collapsed = false; + ImGuiIniData* ini = new ImGuiIniData(); + ini->Name = StrDup(name); + ini->Collapsed = false; ini->Pos = ImVec2(FLT_MAX,FLT_MAX); ini->Size = ImVec2(0,0); g.Settings.push_back(ini); @@ -1156,8 +1179,14 @@ void NewFrame() if (!g.Initialized) { - // Initialize on first frame + // Initialize on first frame IM_ASSERT(g.Settings.empty()); + + g.LogClipboard.init(); + + g.DrawListPool.create(DRAWLIST_BLOCK_SIZE, g.IO.MallocFn, g.IO.FreeFn); + g.GuiWindowPool.create(GUIWINDOW_BLOCK_SIZE, g.IO.MallocFn, g.IO.FreeFn); + LoadSettings(); if (!g.IO.Font) { @@ -1169,6 +1198,7 @@ void NewFrame() g.IO.Font->LoadFromMemory(fnt_data, fnt_size); g.IO.FontHeight = g.IO.Font->GetFontSize(); } + g.Initialized = true; } @@ -1282,8 +1312,10 @@ void Shutdown() SaveSettings(); - for (size_t i = 0; i < g.Windows.size(); i++) - delete g.Windows[i]; + for (size_t i = 0; i < g.Windows.size(); i++) { + g.Windows[i]->~ImGuiWindow(); + g.GuiWindowPool.free(g.Windows[i]); + } g.Windows.clear(); g.CurrentWindowStack.clear(); g.FocusedWindow = NULL; @@ -1292,6 +1324,7 @@ void Shutdown() for (size_t i = 0; i < g.Settings.size(); i++) delete g.Settings[i]; g.Settings.clear(); + g.RenderDrawLists.clear(); g.ColorEditModeStorage.Clear(); if (g.LogFile && g.LogFile != stdout) { @@ -1306,10 +1339,15 @@ void Shutdown() if (g.PrivateClipboard) { - free(g.PrivateClipboard); + GImGui.IO.FreeFn(g.PrivateClipboard); g.PrivateClipboard = NULL; } + g.DrawListPool.destroy(); + g.GuiWindowPool.destroy(); + + g.LogClipboard.destroy(); + g.Initialized = false; } @@ -1783,9 +1821,12 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin ImGuiWindow* window = FindWindow(name); if (!window) { + ImGuiWindow *buff = GImGui.GuiWindowPool.alloc(); + IM_ASSERT(buff); + if (flags & ImGuiWindowFlags_ChildWindow) { - window = new ImGuiWindow(name, ImVec2(0,0), size); + window = new(buff) ImGuiWindow(name, ImVec2(0,0), size); } else { @@ -1793,7 +1834,7 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin if (settings && ImLength(settings->Size) > 0.0f && !(flags & ImGuiWindowFlags_NoResize))// && ImLengthsize) == 0.0f) size = settings->Size; - window = new ImGuiWindow(name, g.NewWindowDefaultPos, size); + window = new(buff) ImGuiWindow(name, g.NewWindowDefaultPos, size); if (settings->Pos.x != FLT_MAX) { @@ -3809,7 +3850,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag { // Remove new-line from pasted buffer size_t clipboard_len = strlen(clipboard); - char* clipboard_filtered = (char*)malloc(clipboard_len+1); + char* clipboard_filtered = (char*)GImGui.IO.MallocFn(clipboard_len+1); int clipboard_filtered_len = 0; for (int i = 0; clipboard[i]; i++) { @@ -3820,7 +3861,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag } clipboard_filtered[clipboard_filtered_len] = 0; stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len); - free(clipboard_filtered); + GImGui.IO.FreeFn(clipboard_filtered); } } else if (g.IO.InputCharacters[0]) @@ -4422,7 +4463,7 @@ static bool ClipAdvance(const ImGuiAabb& bb) window->DC.LastItemHovered = false; return true; } - window->DC.LastItemHovered = ImGui::IsMouseHoveringBox(bb); // this is a sensible default but widgets are free to override it after calling ClipAdvance + window->DC.LastItemHovered = ImGui::IsMouseHoveringBox(bb); // this is a sensible default but widgets are GImGui.IO.FreeFn to override it after calling ClipAdvance return false; } @@ -4941,7 +4982,7 @@ ImBitmapFont::ImBitmapFont() void ImBitmapFont::Clear() { if (Data && DataOwned) - free(Data); + GImGui.IO.FreeFn(Data); Data = NULL; DataOwned = false; Info = NULL; @@ -4964,7 +5005,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename) return false; if (fseek(f, 0, SEEK_SET)) return false; - if ((Data = (unsigned char*)malloc(DataSize)) == NULL) + if ((Data = (unsigned char*)GImGui.IO.MallocFn(DataSize)) == NULL) { fclose(f); return false; @@ -4972,7 +5013,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename) if ((int)fread(Data, 1, DataSize, f) != DataSize) { fclose(f); - free(Data); + GImGui.IO.FreeFn(Data); return false; } fclose(f); @@ -5215,7 +5256,7 @@ static const char* GetClipboardTextFn_DefaultImpl() static char* buf_local = NULL; if (buf_local) { - free(buf_local); + GImGui.IO.FreeFn(buf_local); buf_local = NULL; } if (!OpenClipboard(NULL)) @@ -5224,7 +5265,7 @@ static const char* GetClipboardTextFn_DefaultImpl() if (buf_handle == NULL) return NULL; if (char* buf_global = (char*)GlobalLock(buf_handle)) - buf_local = strdup(buf_global); + buf_local = StrDup(buf_global); GlobalUnlock(buf_handle); CloseClipboard(); return buf_local; @@ -5263,12 +5304,12 @@ static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_en { if (GImGui.PrivateClipboard) { - free(GImGui.PrivateClipboard); + GImGui.IO.FreeFn(GImGui.PrivateClipboard); GImGui.PrivateClipboard = NULL; } if (!text_end) text_end = text + strlen(text); - GImGui.PrivateClipboard = (char*)malloc(text_end - text + 1); + GImGui.PrivateClipboard = (char*)GImGui.IO.MallocFn(text_end - text + 1); memcpy(GImGui.PrivateClipboard, text, text_end - text); GImGui.PrivateClipboard[text_end - text] = 0; } @@ -5718,8 +5759,9 @@ void ShowTestWindow(bool* open) if (ImGui::CollapsingHeader("Long text")) { - static ImGuiTextBuffer log; + /*static*/ ImGuiTextBuffer log; static int lines = 0; + log.init(); ImGui::Text("Printing unusually long amount of text."); ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size()); if (ImGui::Button("Clear")) { log.clear(); lines = 0; } @@ -5741,6 +5783,20 @@ void ShowTestWindow(bool* open) }; // namespace ImGui +static char* StrDup(const char *str) +{ + char *buff = (char*)GImGui.IO.MallocFn(strlen(str) + 1); + IM_ASSERT(buff); + strcpy(buff, str); + return buff; +} + +static void StrDup_Free(char *str) +{ + IM_ASSERT(str); + GImGui.IO.FreeFn(str); +} + //----------------------------------------------------------------------------- // Font data // Bitmap exported from proggy_clean.fon (c) by Tristan Grimmer http://www.proggyfonts.net @@ -5748,7 +5804,7 @@ void ShowTestWindow(bool* open) /* // Copyright (c) 2004, 2005 Tristan Grimmer -// Permission is hereby granted, free of charge, to any person obtaining a copy +// Permission is hereby granted, GImGui.IO.FreeFn of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell @@ -5950,3 +6006,13 @@ void GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const voi }; //----------------------------------------------------------------------------- + +void* ImGui_ProxyMalloc(size_t size) +{ + return GImGui.IO.MallocFn(size); +} + +void ImGui_ProxyFree(void *ptr) +{ + GImGui.IO.FreeFn(ptr); +} diff --git a/imgui.h b/imgui.h index b0063304..b19dd1fe 100644 --- a/imgui.h +++ b/imgui.h @@ -18,6 +18,7 @@ struct ImGuiWindow; #include // FLT_MAX #include // va_list #include // NULL +#include #ifndef IM_ASSERT #include @@ -33,6 +34,9 @@ typedef int ImGuiWindowFlags; // enum ImGuiWindowFlags_ typedef int ImGuiInputTextFlags; // enum ImGuiInputTextFlags_ typedef ImBitmapFont* ImFont; +typedef void* (*ImGui_MallocCallback)(size_t size); +typedef void (*ImGui_FreeCallback)(void *ptr); + struct ImVec2 { float x, y; @@ -58,6 +62,11 @@ struct ImVec4 // std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug). // this implementation does NOT call c++ constructors! we don't need them! also only provide the minimum functionalities we need. #ifndef ImVector + +// Forward declarations for Malloc/Free proxies +void* ImGui_ProxyMalloc(size_t size); +void ImGui_ProxyFree(void *ptr); + template class ImVector { @@ -72,7 +81,7 @@ public: typedef const value_type* const_iterator; ImVector() { _size = _capacity = 0; _data = NULL; } - ~ImVector() { if (_data) free(_data); } + ~ImVector() { if (_data) ImGui_ProxyFree(_data); } inline bool empty() const { return _size == 0; } inline size_t size() const { return _size; } @@ -83,7 +92,7 @@ public: inline value_type& operator[](size_t i) { IM_ASSERT(i < _size); return _data[i]; } inline const value_type& operator[](size_t i) const { IM_ASSERT(i < _size); return _data[i]; } - inline void clear() { if (_data) { _size = _capacity = 0; free(_data); _data = NULL; } } + inline void clear() { if (_data) { _size = _capacity = 0; ImGui_ProxyFree(_data); _data = NULL; } } inline iterator begin() { return _data; } inline const_iterator begin() const { return _data; } inline iterator end() { return _data + _size; } @@ -94,7 +103,18 @@ public: inline const value_type& back() const { IM_ASSERT(_size > 0); return at(_size-1); } inline void swap(ImVector& rhs) { const size_t rhs_size = rhs._size; rhs._size = _size; _size = rhs_size; const size_t rhs_cap = rhs._capacity; rhs._capacity = _capacity; _capacity = rhs_cap; value_type* rhs_data = rhs._data; rhs._data = _data; _data = rhs_data; } - inline void reserve(size_t new_capacity) { _data = (value_type*)realloc(_data, new_capacity * sizeof(value_type)); _capacity = new_capacity; } + inline void reserve(size_t new_capacity) + { + if (!_data) { + _data = (value_type*)ImGui_ProxyMalloc(new_capacity*sizeof(value_type)); + } else { + void *tmp = ImGui_ProxyMalloc(new_capacity*sizeof(value_type)); + memcpy(tmp, _data, sizeof(value_type)*_capacity); + ImGui_ProxyFree(_data); + _data = (value_type*)tmp; + } + _capacity = new_capacity; + } inline void resize(size_t new_size) { if (new_size > _capacity) reserve(new_size); _size = new_size; } inline void push_back(const value_type& v) { if (_size == _capacity) reserve(_capacity ? _capacity * 2 : 4); _data[_size++] = v; } @@ -371,7 +391,9 @@ struct ImGuiStyle struct ImGuiIO { // Settings (fill once) // Default value: - ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. + ImGui_MallocCallback MallocFn; + ImGui_FreeCallback FreeFn; + ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. float IniSavingRate; // = 5.0f // Maximum time between saving .ini file, in seconds. Set to a negative value to disable .ini saving. const char* IniFilename; // = "imgui.ini" // Absolute path to .ini file. @@ -476,13 +498,15 @@ struct ImGuiTextBuffer { ImVector Buf; - ImGuiTextBuffer() { Buf.push_back(0); } - const char* begin() const { return Buf.begin(); } - const char* end() const { return Buf.end()-1; } - size_t size() const { return Buf.size()-1; } - bool empty() { return Buf.empty(); } - void clear() { Buf.clear(); Buf.push_back(0); } - void append(const char* fmt, ...); + ImGuiTextBuffer() { } + void init() { if (Buf.empty()) Buf.push_back(0); } + const char* begin() const { return Buf.begin(); } + const char* end() const { return Buf.end()-1; } + size_t size() const { return Buf.size()-1; } + bool empty() { return Buf.empty(); } + void clear() { Buf.clear(); Buf.push_back(0); } + void append(const char* fmt, ...); + void destroy() { Buf.clear(); } }; // Helper: Key->value storage diff --git a/immem.h b/immem.h new file mode 100644 index 00000000..d37785c6 --- /dev/null +++ b/immem.h @@ -0,0 +1,210 @@ +/*********************************************************************************** + * Author: Sepehr Taghdisian (sep.tagh@gmail.com) + */ + +#ifndef IMMEM_H +#define IMMEM_H + +// Note: This file is meant to included only inside imgui.cpp + +#ifndef IMGUI_INTERNAL_USE + #error "This file is intented for internal use only (as include)" +#endif + +/* Linked-List ************************************************************************************/ +struct LinkedList +{ + LinkedList *next; + LinkedList *prev; + void *data; + + LinkedList() : next(NULL), prev(NULL) {} +}; + + +static void list_add(struct LinkedList** plist, struct LinkedList* item, void* data) +{ + item->next = (*plist); + item->prev = NULL; + if (*plist != NULL) + (*plist)->prev = item; + *plist = item; + item->data = data; +} + +static void list_addlast(struct LinkedList** plist, struct LinkedList* item, void* data) +{ + if (*plist != NULL) { + struct LinkedList* last = *plist; + while (last->next != NULL) last = last->next; + last->next = item; + item->prev = last; + item->next = NULL; + } else { + *plist = item; + item->prev = item->next = NULL; + } + + item->data = data; +} + +static void list_remove(struct LinkedList** plist, struct LinkedList* item) +{ + if (item->next != NULL) item->next->prev = item->prev; + if (item->prev != NULL) item->prev->next = item->next; + if (*plist == item) *plist = item->next; + item->next = item->prev = NULL; +} + +/* PoolAlloc **************************************************************************************/ +template +class PoolAlloc +{ +private: + LinkedList *m_blocks; /* first node of m_blocks */ + int m_block_cnt; + int m_items_max; /* maximum number of items allowed (per block) */ + ImGui_MallocCallback m_malloc; + ImGui_FreeCallback m_free; + +private: + struct Block + { + LinkedList node; /* linked-list node */ + unsigned char *buffer; /* memory buffer that holds all objects */ + void **ptrs; /* pointer references to the buffer */ + int iter; /* iterator for current buffer position */ + }; + +private: + Block* create_block(int block_size) + { + // Allocate in one call + size_t total_sz = + sizeof(Block) + + sizeof(T)*block_size + + sizeof(void*)*block_size; + unsigned char *buff = (unsigned char*)m_malloc(total_sz); + if (buff == NULL) + return NULL; + memset(buff, 0x00, total_sz); + + Block *block = (Block*)buff; + buff += sizeof(Block); + block->buffer = buff; + buff += sizeof(T)*block_size; + block->ptrs = (void**)buff; + + // Assign pointer refs + for (int i = 0; i < block_size; i++) + block->ptrs[block_size-i-1] = block->buffer + i*sizeof(T); + block->iter = block_size; + + /* add to linked-list of the pool */ + list_addlast(&m_blocks, &block->node, block); + m_block_cnt++; + return block; + } + + void destroy_block(Block *block) + { + list_remove(&m_blocks, &block->node); + m_free(block); + m_block_cnt--; + } + +public: + PoolAlloc() + { + m_blocks = NULL; + m_block_cnt = 0; + m_items_max = 0; + m_malloc = NULL; + m_free = NULL; + } + + bool create(int block_sz, ImGui_MallocCallback malloc_fn, ImGui_FreeCallback free_fn) + { + m_items_max = block_sz; + m_malloc = malloc_fn; + m_free = free_fn; + + // First block + Block *block = create_block(block_sz); + if (block == NULL) { + destroy(); + return false; + } + + return true; + } + + void destroy() + { + LinkedList* node = m_blocks; + while (node != NULL) { + LinkedList* next = node->next; + destroy_block((Block*)node->data); + node = next; + } + } + + T* alloc() + { + LinkedList* node = m_blocks; + + while (node != NULL) { + Block *block = (Block*)node->data; + if (block->iter > 0) + return (T*)block->ptrs[--block->iter]; + + node = node->next; + } + + /* couldn't find a free block, create a new one */ + Block *block = create_block(m_items_max); + if (block == NULL) + return NULL; + + return (T*)block->ptrs[--block->iter]; + } + + void free(T *ptr) + { + // find the block that pointer belongs to, and free the pointer from that block + LinkedList *node = m_blocks; + int buffer_sz = m_items_max*sizeof(T); + unsigned char *u8ptr = (unsigned char*)ptr; + + while (node != NULL) { + Block *block = (Block*)node->data; + if (u8ptr >= block->buffer && u8ptr < (block->buffer + buffer_sz)) { + IM_ASSERT(block->iter != m_items_max); + block->ptrs[block->iter++] = ptr; + return; + } + node = node->next; + } + + // Memory block does not belong to the pool?! + IM_ASSERT(0); + } + + void clear() + { + int block_size = m_items_max; + LinkedList* node = m_blocks; + while (node != NULL) { + Block *block = (Block*)node->data; + + /* only re-assign pointer references to buffer */ + for (int i = 0; i < block_size; i++) + block->ptrs[block_size-i-1] = block->buffer + i*sizeof(T); + block->iter = block_size; + + node = node->next; + } + } +}; + +#endif // IMMEM_H diff --git a/libimgui.pro b/libimgui.pro index c153b4e3..bc8579d5 100644 --- a/libimgui.pro +++ b/libimgui.pro @@ -17,4 +17,5 @@ SOURCES += \ HEADERS += \ imgui.h \ - imconfig.h + imconfig.h \ + immem.h From e9b697698a95529fb9594c35c6f53429109b6dc0 Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Sat, 16 Aug 2014 13:12:24 +0430 Subject: [PATCH 4/9] fixed a typo --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 35e28b02..24cdb4e4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5887,7 +5887,7 @@ static void StrDup_Free(char *str) /* // Copyright (c) 2004, 2005 Tristan Grimmer -// Permission is hereby granted, GImGui.IO.FreeFn of charge, to any person obtaining a copy +// Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell From df5a06f1199e3b0fa86116d17e1b6a001d6683a3 Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Sat, 16 Aug 2014 13:34:45 +0430 Subject: [PATCH 5/9] removed memory pools, they dont apply well --- imgui.cpp | 43 +++++------ immem.h | 210 --------------------------------------------------- libimgui.pro | 3 +- 3 files changed, 19 insertions(+), 237 deletions(-) delete mode 100644 immem.h diff --git a/imgui.cpp b/imgui.cpp index 24cdb4e4..b7c135cc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -168,9 +168,6 @@ #endif #include -#define IMGUI_INTERNAL_USE -#include "immem.h" -#undef IMGUI_INTERNAL_USE // Block sizes for each memory. Don't really know about the optimized values #define DRAWLIST_BLOCK_SIZE 128 @@ -645,10 +642,6 @@ struct ImGuiState ImGuiTextBuffer LogClipboard; int LogAutoExpandMaxDepth; - // Memory Pools - PoolAlloc DrawListPool; - PoolAlloc GuiWindowPool; - ImGuiState() { Initialized = false; @@ -954,7 +947,7 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si FocusIdxRequestCurrent = IM_INT_MAX; FocusIdxRequestNext = IM_INT_MAX; - ImDrawList *buff = GImGui.DrawListPool.alloc(); + void *buff = GImGui.IO.MallocFn(sizeof(ImDrawList)); IM_ASSERT(buff); DrawList = new(buff) ImDrawList(); } @@ -962,7 +955,7 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si ImGuiWindow::~ImGuiWindow() { DrawList->~ImDrawList(); - GImGui.DrawListPool.free(DrawList); + GImGui.IO.FreeFn(DrawList); DrawList = NULL; StrDup_Free(Name); Name = NULL; @@ -1044,7 +1037,9 @@ static ImGuiIniData* FindWindowSettings(const char* name) if (ImStricmp(ini->Name, name) == 0) return ini; } - ImGuiIniData* ini = new ImGuiIniData(); + + void *buff = GImGui.IO.MallocFn(sizeof(ImGuiIniData)); + ImGuiIniData* ini = new(buff) ImGuiIniData(); ini->Name = StrDup(name); ini->Collapsed = false; ini->Pos = ImVec2(FLT_MAX,FLT_MAX); @@ -1073,12 +1068,12 @@ static void LoadSettings() return; if (fseek(f, 0, SEEK_SET)) return; - char* f_data = new char[f_size+1]; + char* f_data = (char*)g.IO.MallocFn(f_size+1); f_size = (long)fread(f_data, 1, f_size, f); // Text conversion alter read size so let's not be fussy about return value fclose(f); if (f_size == 0) { - delete[] f_data; + g.IO.FreeFn(f_data); return; } f_data[f_size] = 0; @@ -1112,7 +1107,7 @@ static void LoadSettings() line_start = line_end+1; } - delete[] f_data; + g.IO.FreeFn(f_data); } static void SaveSettings() @@ -1188,9 +1183,6 @@ void NewFrame() g.LogClipboard.init(); - g.DrawListPool.create(DRAWLIST_BLOCK_SIZE, g.IO.MallocFn, g.IO.FreeFn); - g.GuiWindowPool.create(GUIWINDOW_BLOCK_SIZE, g.IO.MallocFn, g.IO.FreeFn); - LoadSettings(); if (!g.IO.Font) { @@ -1198,7 +1190,8 @@ void NewFrame() const void* fnt_data; unsigned int fnt_size; ImGui::GetDefaultFontData(&fnt_data, &fnt_size, NULL, NULL); - g.IO.Font = new ImBitmapFont(); + void *buff = g.IO.MallocFn(sizeof(ImBitmapFont)); + g.IO.Font = new(buff) ImBitmapFont(); g.IO.Font->LoadFromMemory(fnt_data, fnt_size); g.IO.FontHeight = g.IO.Font->GetFontSize(); } @@ -1319,15 +1312,17 @@ void Shutdown() for (size_t i = 0; i < g.Windows.size(); i++) { g.Windows[i]->~ImGuiWindow(); - g.GuiWindowPool.free(g.Windows[i]); + g.IO.FreeFn(g.Windows[i]); } g.Windows.clear(); g.CurrentWindowStack.clear(); g.FocusedWindow = NULL; g.HoveredWindow = NULL; g.HoveredWindowExcludingChilds = NULL; - for (size_t i = 0; i < g.Settings.size(); i++) - delete g.Settings[i]; + for (size_t i = 0; i < g.Settings.size(); i++) { + g.Settings[i]->~ImGuiIniData(); + g.IO.FreeFn(g.Settings[i]); + } g.Settings.clear(); g.RenderDrawLists.clear(); g.ColorEditModeStorage.Clear(); @@ -1338,7 +1333,8 @@ void Shutdown() } if (g.IO.Font) { - delete g.IO.Font; + g.IO.Font->~ImBitmapFont(); + g.IO.FreeFn(g.IO.Font); g.IO.Font = NULL; } @@ -1348,9 +1344,6 @@ void Shutdown() g.PrivateClipboard = NULL; } - g.DrawListPool.destroy(); - g.GuiWindowPool.destroy(); - g.LogClipboard.destroy(); g.Initialized = false; @@ -1831,7 +1824,7 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin ImGuiWindow* window = FindWindow(name); if (!window) { - ImGuiWindow *buff = GImGui.GuiWindowPool.alloc(); + void *buff = g.IO.MallocFn(sizeof(ImGuiWindow)); IM_ASSERT(buff); if (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) diff --git a/immem.h b/immem.h deleted file mode 100644 index d37785c6..00000000 --- a/immem.h +++ /dev/null @@ -1,210 +0,0 @@ -/*********************************************************************************** - * Author: Sepehr Taghdisian (sep.tagh@gmail.com) - */ - -#ifndef IMMEM_H -#define IMMEM_H - -// Note: This file is meant to included only inside imgui.cpp - -#ifndef IMGUI_INTERNAL_USE - #error "This file is intented for internal use only (as include)" -#endif - -/* Linked-List ************************************************************************************/ -struct LinkedList -{ - LinkedList *next; - LinkedList *prev; - void *data; - - LinkedList() : next(NULL), prev(NULL) {} -}; - - -static void list_add(struct LinkedList** plist, struct LinkedList* item, void* data) -{ - item->next = (*plist); - item->prev = NULL; - if (*plist != NULL) - (*plist)->prev = item; - *plist = item; - item->data = data; -} - -static void list_addlast(struct LinkedList** plist, struct LinkedList* item, void* data) -{ - if (*plist != NULL) { - struct LinkedList* last = *plist; - while (last->next != NULL) last = last->next; - last->next = item; - item->prev = last; - item->next = NULL; - } else { - *plist = item; - item->prev = item->next = NULL; - } - - item->data = data; -} - -static void list_remove(struct LinkedList** plist, struct LinkedList* item) -{ - if (item->next != NULL) item->next->prev = item->prev; - if (item->prev != NULL) item->prev->next = item->next; - if (*plist == item) *plist = item->next; - item->next = item->prev = NULL; -} - -/* PoolAlloc **************************************************************************************/ -template -class PoolAlloc -{ -private: - LinkedList *m_blocks; /* first node of m_blocks */ - int m_block_cnt; - int m_items_max; /* maximum number of items allowed (per block) */ - ImGui_MallocCallback m_malloc; - ImGui_FreeCallback m_free; - -private: - struct Block - { - LinkedList node; /* linked-list node */ - unsigned char *buffer; /* memory buffer that holds all objects */ - void **ptrs; /* pointer references to the buffer */ - int iter; /* iterator for current buffer position */ - }; - -private: - Block* create_block(int block_size) - { - // Allocate in one call - size_t total_sz = - sizeof(Block) + - sizeof(T)*block_size + - sizeof(void*)*block_size; - unsigned char *buff = (unsigned char*)m_malloc(total_sz); - if (buff == NULL) - return NULL; - memset(buff, 0x00, total_sz); - - Block *block = (Block*)buff; - buff += sizeof(Block); - block->buffer = buff; - buff += sizeof(T)*block_size; - block->ptrs = (void**)buff; - - // Assign pointer refs - for (int i = 0; i < block_size; i++) - block->ptrs[block_size-i-1] = block->buffer + i*sizeof(T); - block->iter = block_size; - - /* add to linked-list of the pool */ - list_addlast(&m_blocks, &block->node, block); - m_block_cnt++; - return block; - } - - void destroy_block(Block *block) - { - list_remove(&m_blocks, &block->node); - m_free(block); - m_block_cnt--; - } - -public: - PoolAlloc() - { - m_blocks = NULL; - m_block_cnt = 0; - m_items_max = 0; - m_malloc = NULL; - m_free = NULL; - } - - bool create(int block_sz, ImGui_MallocCallback malloc_fn, ImGui_FreeCallback free_fn) - { - m_items_max = block_sz; - m_malloc = malloc_fn; - m_free = free_fn; - - // First block - Block *block = create_block(block_sz); - if (block == NULL) { - destroy(); - return false; - } - - return true; - } - - void destroy() - { - LinkedList* node = m_blocks; - while (node != NULL) { - LinkedList* next = node->next; - destroy_block((Block*)node->data); - node = next; - } - } - - T* alloc() - { - LinkedList* node = m_blocks; - - while (node != NULL) { - Block *block = (Block*)node->data; - if (block->iter > 0) - return (T*)block->ptrs[--block->iter]; - - node = node->next; - } - - /* couldn't find a free block, create a new one */ - Block *block = create_block(m_items_max); - if (block == NULL) - return NULL; - - return (T*)block->ptrs[--block->iter]; - } - - void free(T *ptr) - { - // find the block that pointer belongs to, and free the pointer from that block - LinkedList *node = m_blocks; - int buffer_sz = m_items_max*sizeof(T); - unsigned char *u8ptr = (unsigned char*)ptr; - - while (node != NULL) { - Block *block = (Block*)node->data; - if (u8ptr >= block->buffer && u8ptr < (block->buffer + buffer_sz)) { - IM_ASSERT(block->iter != m_items_max); - block->ptrs[block->iter++] = ptr; - return; - } - node = node->next; - } - - // Memory block does not belong to the pool?! - IM_ASSERT(0); - } - - void clear() - { - int block_size = m_items_max; - LinkedList* node = m_blocks; - while (node != NULL) { - Block *block = (Block*)node->data; - - /* only re-assign pointer references to buffer */ - for (int i = 0; i < block_size; i++) - block->ptrs[block_size-i-1] = block->buffer + i*sizeof(T); - block->iter = block_size; - - node = node->next; - } - } -}; - -#endif // IMMEM_H diff --git a/libimgui.pro b/libimgui.pro index bc8579d5..c153b4e3 100644 --- a/libimgui.pro +++ b/libimgui.pro @@ -17,5 +17,4 @@ SOURCES += \ HEADERS += \ imgui.h \ - imconfig.h \ - immem.h + imconfig.h From ef628a0a9dbbd3b60b9ce8d355939e6b3958edab Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Sat, 16 Aug 2014 13:35:44 +0430 Subject: [PATCH 6/9] argh, removed redundent defines --- imgui.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b7c135cc..a0f27d0c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -169,10 +169,6 @@ #include -// Block sizes for each memory. Don't really know about the optimized values -#define DRAWLIST_BLOCK_SIZE 128 -#define GUIWINDOW_BLOCK_SIZE 64 - //------------------------------------------------------------------------- // Forward Declarations //------------------------------------------------------------------------- From 47fd8431c10e94c2d7e6b34096f3b70a7333f464 Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Mon, 18 Aug 2014 13:19:35 +0430 Subject: [PATCH 7/9] minor fixes --- imgui.cpp | 20 ++++++++++---------- imgui.h | 5 +++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a0f27d0c..4806d853 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -162,12 +162,12 @@ #include // intptr_t #include // vsnprintf #include // memset +#include // new (ptr) #ifdef _MSC_VER #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif -#include //------------------------------------------------------------------------- // Forward Declarations @@ -198,8 +198,8 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs); }; // namespace ImGui -static char* StrDup(const char *str); -static void StrDup_Free(char *str); +static char* ImStrDup(const char *str); +static void ImStrDup_Free(char *str); //----------------------------------------------------------------------------- // Platform dependant default implementations @@ -596,7 +596,7 @@ struct ImGuiIniData bool Collapsed; ImGuiIniData() { memset(this, 0, sizeof(*this)); } - ~ImGuiIniData() { if (Name) { StrDup_Free(Name); Name = NULL; } } + ~ImGuiIniData() { if (Name) { ImStrDup_Free(Name); Name = NULL; } } }; struct ImGuiState @@ -918,7 +918,7 @@ void ImGuiTextBuffer::append(const char* fmt, ...) ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_size) { - Name = StrDup(name); + Name = ImStrDup(name); ID = GetID(name); IDStack.push_back(ID); @@ -953,7 +953,7 @@ ImGuiWindow::~ImGuiWindow() DrawList->~ImDrawList(); GImGui.IO.FreeFn(DrawList); DrawList = NULL; - StrDup_Free(Name); + ImStrDup_Free(Name); Name = NULL; } @@ -1036,7 +1036,7 @@ static ImGuiIniData* FindWindowSettings(const char* name) void *buff = GImGui.IO.MallocFn(sizeof(ImGuiIniData)); ImGuiIniData* ini = new(buff) ImGuiIniData(); - ini->Name = StrDup(name); + ini->Name = ImStrDup(name); ini->Collapsed = false; ini->Pos = ImVec2(FLT_MAX,FLT_MAX); ini->Size = ImVec2(0,0); @@ -5318,7 +5318,7 @@ static const char* GetClipboardTextFn_DefaultImpl() if (buf_handle == NULL) return NULL; if (char* buf_global = (char*)GlobalLock(buf_handle)) - buf_local = StrDup(buf_global); + buf_local = ImStrDup(buf_global); GlobalUnlock(buf_handle); CloseClipboard(); return buf_local; @@ -5855,7 +5855,7 @@ void ShowTestWindow(bool* open) }; // namespace ImGui -static char* StrDup(const char *str) +static char* ImStrDup(const char *str) { char *buff = (char*)GImGui.IO.MallocFn(strlen(str) + 1); IM_ASSERT(buff); @@ -5863,7 +5863,7 @@ static char* StrDup(const char *str) return buff; } -static void StrDup_Free(char *str) +static void ImStrDup_Free(char *str) { IM_ASSERT(str); GImGui.IO.FreeFn(str); diff --git a/imgui.h b/imgui.h index 892d822e..7ed14149 100644 --- a/imgui.h +++ b/imgui.h @@ -25,6 +25,11 @@ struct ImGuiWindow; #define IM_ASSERT(_EXPR) assert(_EXPR) #endif +#ifndef IM_MALLOC +#define IM_MALLOC malloc +#endif + + typedef unsigned int ImU32; typedef ImU32 ImGuiID; typedef int ImGuiCol; // enum ImGuiCol_ From c13c2449bb68e053868a667dffa683f3b7e32d74 Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Mon, 18 Aug 2014 16:09:47 +0430 Subject: [PATCH 8/9] removed libimgui.pro --- libimgui.pro | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 libimgui.pro diff --git a/libimgui.pro b/libimgui.pro deleted file mode 100644 index c153b4e3..00000000 --- a/libimgui.pro +++ /dev/null @@ -1,20 +0,0 @@ -TEMPLATE = lib -CONFIG += static -CONFIG -= app_bundle -CONFIG -= qt -CONFIG -= warn_on - -CONFIG(release, debug|release) { - TARGET = imgui -} - -CONFIG(debug, debug|release) { - TARGET = imgui-dbg -} - -SOURCES += \ - imgui.cpp - -HEADERS += \ - imgui.h \ - imconfig.h From aa7fc37b37dd0181b88971b661b89f9831a1d973 Mon Sep 17 00:00:00 2001 From: Sepehr Taghdisian Date: Mon, 18 Aug 2014 16:19:11 +0430 Subject: [PATCH 9/9] removed malloc/free proxy fwd declares --- imgui.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/imgui.h b/imgui.h index c4fe0ffa..d297a408 100644 --- a/imgui.h +++ b/imgui.h @@ -60,10 +60,6 @@ struct ImVec4 // this implementation does NOT call c++ constructors! we don't need them! also only provide the minimum functionalities we need. #ifndef ImVector -// Forward declarations for Malloc/Free proxies -void* ImGui_ProxyMalloc(size_t size); -void ImGui_ProxyFree(void *ptr); - template class ImVector {