| 1346 | } |
| 1347 | |
| 1348 | void ImDrawListSplitter::Merge(ImDrawList* draw_list) |
| 1349 | { |
| 1350 | // Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use. |
| 1351 | if (_Count <= 1) |
| 1352 | return; |
| 1353 | |
| 1354 | SetCurrentChannel(draw_list, 0); |
| 1355 | if (draw_list->CmdBuffer.Size != 0 && draw_list->CmdBuffer.back().ElemCount == 0) |
| 1356 | draw_list->CmdBuffer.pop_back(); |
| 1357 | |
| 1358 | // Calculate our final buffer sizes. Also fix the incorrect IdxOffset values in each command. |
| 1359 | int new_cmd_buffer_count = 0; |
| 1360 | int new_idx_buffer_count = 0; |
| 1361 | ImDrawCmd* last_cmd = (_Count > 0 && draw_list->CmdBuffer.Size > 0) ? &draw_list->CmdBuffer.back() : NULL; |
| 1362 | int idx_offset = last_cmd ? last_cmd->IdxOffset + last_cmd->ElemCount : 0; |
| 1363 | for (int i = 1; i < _Count; i++) |
| 1364 | { |
| 1365 | ImDrawChannel& ch = _Channels[i]; |
| 1366 | if (ch._CmdBuffer.Size > 0 && ch._CmdBuffer.back().ElemCount == 0) |
| 1367 | ch._CmdBuffer.pop_back(); |
| 1368 | if (ch._CmdBuffer.Size > 0 && last_cmd != NULL && CanMergeDrawCommands(last_cmd, &ch._CmdBuffer[0])) |
| 1369 | { |
| 1370 | // Merge previous channel last draw command with current channel first draw command if matching. |
| 1371 | last_cmd->ElemCount += ch._CmdBuffer[0].ElemCount; |
| 1372 | idx_offset += ch._CmdBuffer[0].ElemCount; |
| 1373 | ch._CmdBuffer.erase(ch._CmdBuffer.Data); // FIXME-OPT: Improve for multiple merges. |
| 1374 | } |
| 1375 | if (ch._CmdBuffer.Size > 0) |
| 1376 | last_cmd = &ch._CmdBuffer.back(); |
| 1377 | new_cmd_buffer_count += ch._CmdBuffer.Size; |
| 1378 | new_idx_buffer_count += ch._IdxBuffer.Size; |
| 1379 | for (int cmd_n = 0; cmd_n < ch._CmdBuffer.Size; cmd_n++) |
| 1380 | { |
| 1381 | ch._CmdBuffer.Data[cmd_n].IdxOffset = idx_offset; |
| 1382 | idx_offset += ch._CmdBuffer.Data[cmd_n].ElemCount; |
| 1383 | } |
| 1384 | } |
| 1385 | draw_list->CmdBuffer.resize(draw_list->CmdBuffer.Size + new_cmd_buffer_count); |
| 1386 | draw_list->IdxBuffer.resize(draw_list->IdxBuffer.Size + new_idx_buffer_count); |
| 1387 | |
| 1388 | // Write commands and indices in order (they are fairly small structures, we don't copy vertices only indices) |
| 1389 | ImDrawCmd* cmd_write = draw_list->CmdBuffer.Data + draw_list->CmdBuffer.Size - new_cmd_buffer_count; |
| 1390 | ImDrawIdx* idx_write = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size - new_idx_buffer_count; |
| 1391 | for (int i = 1; i < _Count; i++) |
| 1392 | { |
| 1393 | ImDrawChannel& ch = _Channels[i]; |
| 1394 | if (int sz = ch._CmdBuffer.Size) { memcpy(cmd_write, ch._CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; } |
| 1395 | if (int sz = ch._IdxBuffer.Size) { memcpy(idx_write, ch._IdxBuffer.Data, sz * sizeof(ImDrawIdx)); idx_write += sz; } |
| 1396 | } |
| 1397 | draw_list->_IdxWritePtr = idx_write; |
| 1398 | draw_list->UpdateClipRect(); // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call. |
| 1399 | draw_list->UpdateTextureID(); |
| 1400 | _Count = 1; |
| 1401 | } |
| 1402 | |
| 1403 | void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx) |
| 1404 | { |
no test coverage detected