ImDrawList: Clarifying and guarateeing that CmdBuffer.back()->UserCallback should be always be NULL.

This commit is contained in:
ocornut 2020-06-08 19:06:55 +02:00
parent b1f2eacdf3
commit 3bef743df4

View File

@ -451,7 +451,8 @@ void ImDrawList::_PopUnusedDrawCmd()
void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data) void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
{ {
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
if (curr_cmd->ElemCount != 0 || curr_cmd->UserCallback != NULL) IM_ASSERT(curr_cmd->UserCallback == NULL);
if (curr_cmd->ElemCount != 0)
{ {
AddDrawCmd(); AddDrawCmd();
curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
@ -473,11 +474,12 @@ void ImDrawList::_OnChangedClipRect()
{ {
// If current command is used with different settings we need to add a new command // If current command is used with different settings we need to add a new command
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
if ((curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL) if (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0)
{ {
AddDrawCmd(); AddDrawCmd();
return; return;
} }
IM_ASSERT(curr_cmd->UserCallback == NULL);
// Try to merge with previous command if it matches, else use current command // Try to merge with previous command if it matches, else use current command
ImDrawCmd* prev_cmd = curr_cmd - 1; ImDrawCmd* prev_cmd = curr_cmd - 1;
@ -494,11 +496,12 @@ void ImDrawList::_OnChangedTextureID()
{ {
// If current command is used with different settings we need to add a new command // If current command is used with different settings we need to add a new command
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
if ((curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId) || curr_cmd->UserCallback != NULL) if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId)
{ {
AddDrawCmd(); AddDrawCmd();
return; return;
} }
IM_ASSERT(curr_cmd->UserCallback == NULL);
// Try to merge with previous command if it matches, else use current command // Try to merge with previous command if it matches, else use current command
ImDrawCmd* prev_cmd = curr_cmd - 1; ImDrawCmd* prev_cmd = curr_cmd - 1;
@ -1427,6 +1430,11 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list)
if (int sz = ch._IdxBuffer.Size) { memcpy(idx_write, ch._IdxBuffer.Data, sz * sizeof(ImDrawIdx)); idx_write += sz; } if (int sz = ch._IdxBuffer.Size) { memcpy(idx_write, ch._IdxBuffer.Data, sz * sizeof(ImDrawIdx)); idx_write += sz; }
} }
draw_list->_IdxWritePtr = idx_write; draw_list->_IdxWritePtr = idx_write;
// Ensure there's always a non-callback draw command trailing the command-buffer
if (draw_list->CmdBuffer.Size == 0 || draw_list->CmdBuffer.back().UserCallback != NULL)
draw_list->AddDrawCmd();
draw_list->_OnChangedClipRect(); // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call. draw_list->_OnChangedClipRect(); // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call.
draw_list->_OnChangedTextureID(); draw_list->_OnChangedTextureID();
_Count = 1; _Count = 1;
@ -1437,6 +1445,7 @@ void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
IM_ASSERT(idx >= 0 && idx < _Count); IM_ASSERT(idx >= 0 && idx < _Count);
if (_Current == idx) if (_Current == idx)
return; return;
// Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap() // Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap()
memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer)); memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer));
memcpy(&_Channels.Data[_Current]._IdxBuffer, &draw_list->IdxBuffer, sizeof(draw_list->IdxBuffer)); memcpy(&_Channels.Data[_Current]._IdxBuffer, &draw_list->IdxBuffer, sizeof(draw_list->IdxBuffer));