mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-06 04:58:47 +02:00
Tables: Fixed unaligned accesses when using TableSetBgColor(ImGuiTableBgTarget_CellBg). (#3872)
ImSpanAllocator: Support for alignment.
This commit is contained in:
@ -214,6 +214,7 @@ namespace ImStb
|
||||
#define IM_NEWLINE "\n"
|
||||
#endif
|
||||
#define IM_TABSIZE (4)
|
||||
#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + (_ALIGN - 1)) & ~(_ALIGN - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
|
||||
#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
|
||||
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
|
||||
#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds
|
||||
@ -545,20 +546,22 @@ struct ImSpan
|
||||
|
||||
// Helper: ImSpanAllocator<>
|
||||
// Facilitate storing multiple chunks into a single large block (the "arena")
|
||||
// - Usage: call Reserve() N times, allocate GetArenaSizeInBytes() worth, pass it to SetArenaBasePtr(), call GetSpan() N times to retrieve the aligned ranges.
|
||||
template<int CHUNKS>
|
||||
struct ImSpanAllocator
|
||||
{
|
||||
char* BasePtr;
|
||||
int TotalSize;
|
||||
int CurrSpan;
|
||||
int CurrOff;
|
||||
int CurrIdx;
|
||||
int Offsets[CHUNKS];
|
||||
int Sizes[CHUNKS];
|
||||
|
||||
ImSpanAllocator() { memset(this, 0, sizeof(*this)); }
|
||||
inline void ReserveBytes(int n, size_t sz) { IM_ASSERT(n == CurrSpan && n < CHUNKS); IM_UNUSED(n); Offsets[CurrSpan++] = TotalSize; TotalSize += (int)sz; }
|
||||
inline int GetArenaSizeInBytes() { return TotalSize; }
|
||||
inline void Reserve(int n, size_t sz, int a=4) { IM_ASSERT(n == CurrIdx && n < CHUNKS); CurrOff = IM_MEMALIGN(CurrOff, a); Offsets[n] = CurrOff; Sizes[n] = (int)sz; CurrIdx++; CurrOff += (int)sz; }
|
||||
inline int GetArenaSizeInBytes() { return CurrOff; }
|
||||
inline void SetArenaBasePtr(void* base_ptr) { BasePtr = (char*)base_ptr; }
|
||||
inline void* GetSpanPtrBegin(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrSpan == CHUNKS); return (void*)(BasePtr + Offsets[n]); }
|
||||
inline void* GetSpanPtrEnd(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrSpan == CHUNKS); return (n + 1 < CHUNKS) ? BasePtr + Offsets[n + 1] : (void*)(BasePtr + TotalSize); }
|
||||
inline void* GetSpanPtrBegin(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n]); }
|
||||
inline void* GetSpanPtrEnd(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n] + Sizes[n]); }
|
||||
template<typename T>
|
||||
inline void GetSpan(int n, ImSpan<T>* span) { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); }
|
||||
};
|
||||
@ -592,7 +595,7 @@ struct IMGUI_API ImPool
|
||||
// Helper: ImChunkStream<>
|
||||
// Build and iterate a contiguous stream of variable-sized structures.
|
||||
// This is used by Settings to store persistent data while reducing allocation count.
|
||||
// We store the chunk size first, and align the final size on 4 bytes boundaries (this what the '(X + 3) & ~3' statement is for)
|
||||
// We store the chunk size first, and align the final size on 4 bytes boundaries.
|
||||
// The tedious/zealous amount of casting is to avoid -Wcast-align warnings.
|
||||
template<typename T>
|
||||
struct IMGUI_API ImChunkStream
|
||||
@ -602,7 +605,7 @@ struct IMGUI_API ImChunkStream
|
||||
void clear() { Buf.clear(); }
|
||||
bool empty() const { return Buf.Size == 0; }
|
||||
int size() const { return Buf.Size; }
|
||||
T* alloc_chunk(size_t sz) { size_t HDR_SZ = 4; sz = ((HDR_SZ + sz) + 3u) & ~3u; int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); }
|
||||
T* alloc_chunk(size_t sz) { size_t HDR_SZ = 4; sz = IM_MEMALIGN(HDR_SZ + sz, 4u); int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); }
|
||||
T* begin() { size_t HDR_SZ = 4; if (!Buf.Data) return NULL; return (T*)(void*)(Buf.Data + HDR_SZ); }
|
||||
T* next_chunk(T* p) { size_t HDR_SZ = 4; IM_ASSERT(p >= begin() && p < end()); p = (T*)(void*)((char*)(void*)p + chunk_size(p)); if (p == (T*)(void*)((char*)end() + HDR_SZ)) return (T*)0; IM_ASSERT(p < end()); return p; }
|
||||
int chunk_size(const T* p) { return ((const int*)p)[-1]; }
|
||||
|
Reference in New Issue
Block a user