Skip to content

Commit f28a9e4

Browse files
authored
Initial refactoring for remote DebugGUI (#28)
1 parent a6e4422 commit f28a9e4

5 files changed

Lines changed: 393 additions & 4 deletions

File tree

DebugGUI/src/DebugGUI.cxx

Lines changed: 161 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <GLFW/glfw3.h>
1010
#include <cstdio>
1111
#include <functional>
12+
#include <ostream>
1213

1314
static void default_error_callback(int error, const char* description)
1415
{
@@ -54,31 +55,187 @@ void* initGUI(const char* name, void(*error_callback)(int, char const*descriptio
5455
return window;
5556
}
5657

57-
/// @return true if we do not need to exit, false if we do.
58-
bool pollGUI(void* context, std::function<void(void)> guiCallback)
58+
// fills a stream with drawing data in JSON format
59+
// the JSON is composed of a list of draw commands
60+
/// FIXME: document the actual schema of the format.
61+
void getFrameJSON(void *data, std::ostream& json_data)
62+
{
63+
ImDrawData* draw_data = (ImDrawData*)data;
64+
65+
json_data << "[";
66+
67+
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
68+
const auto cmd_list = draw_data->CmdLists[cmd_id];
69+
const auto vtx_buffer = cmd_list->VtxBuffer;
70+
const auto idx_buffer = cmd_list->IdxBuffer;
71+
const auto cmd_buffer = cmd_list->CmdBuffer;
72+
73+
json_data << "{\"vtx\":[";
74+
for (int i = 0; i < vtx_buffer.size(); ++i) {
75+
auto v = vtx_buffer[i];
76+
json_data << "[" << v.pos.x << "," << v.pos.y << "," << v.col << ',' << v.uv.x << "," << v.uv.y << "]";
77+
if (i < vtx_buffer.size() - 1) json_data << ",";
78+
}
79+
80+
json_data << "],\"idx\":[";
81+
for (int i = 0; i < idx_buffer.size(); ++i) {
82+
auto id = idx_buffer[i];
83+
json_data << id;
84+
if (i < idx_buffer.size() - 1) json_data << ",";
85+
}
86+
87+
json_data << "],\"cmd\":[";
88+
for (int i = 0; i < cmd_buffer.size(); ++i) {
89+
auto cmd = cmd_buffer[i];
90+
json_data << "{\"cnt\":" << cmd.ElemCount << ", \"clp\":[" << cmd.ClipRect.x << "," << cmd.ClipRect.y << "," << cmd.ClipRect.z << "," << cmd.ClipRect.w << "]}";
91+
if (i < cmd_buffer.size() - 1) json_data << ",";
92+
}
93+
json_data << "]}";
94+
if (cmd_id < draw_data->CmdListsCount - 1) json_data << ",";
95+
}
96+
97+
json_data << "]";
98+
}
99+
100+
101+
struct vtxContainer {
102+
float posX, posY, uvX, uvY;
103+
int col;
104+
};
105+
106+
struct cmdContainer {
107+
int count;
108+
float rectX, rectY, rectZ, rectW;
109+
};
110+
111+
// given draw data, returns a mallocd buffer containing formatted frame data
112+
// ready to be sent and its size.
113+
// the returned buffer must be freed by the caller.
114+
/// FIXME: document actual schema of the format
115+
void getFrameRaw(void *data, void **raw_data, int *size)
116+
{
117+
ImDrawData* draw_data = (ImDrawData*)data;
118+
119+
// compute sizes
120+
int buffer_size = sizeof(int)*3,
121+
vtx_count = 0,
122+
idx_count = 0,
123+
cmd_count = 0;
124+
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
125+
const auto cmd_list = draw_data->CmdLists[cmd_id];
126+
127+
vtx_count += cmd_list->VtxBuffer.size();
128+
buffer_size += cmd_list->VtxBuffer.size() * (sizeof(vtxContainer));
129+
130+
idx_count += cmd_list->IdxBuffer.size();
131+
buffer_size += cmd_list->IdxBuffer.size() * (sizeof(short));
132+
133+
cmd_count += cmd_list->CmdBuffer.size();
134+
buffer_size += cmd_list->CmdBuffer.size() * (sizeof(cmdContainer));
135+
}
136+
137+
void *local_data_base = malloc(buffer_size);
138+
139+
int *data_header_ptr = (int*) local_data_base;
140+
*data_header_ptr = vtx_count; data_header_ptr++;
141+
*data_header_ptr = idx_count; data_header_ptr++;
142+
*data_header_ptr = cmd_count; data_header_ptr++;
143+
144+
vtxContainer* data_vtx_ptr = (vtxContainer*) data_header_ptr;
145+
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
146+
const auto cmd_list = draw_data->CmdLists[cmd_id];
147+
148+
for (auto const& vtx : cmd_list->VtxBuffer) {
149+
data_vtx_ptr->posX = vtx.pos.x;
150+
data_vtx_ptr->posY = vtx.pos.y;
151+
data_vtx_ptr->uvX = vtx.uv.x;
152+
data_vtx_ptr->uvY = vtx.uv.y;
153+
data_vtx_ptr->col = vtx.col;
154+
data_vtx_ptr++;
155+
}
156+
}
157+
158+
int idx_offset = 0;
159+
short* data_idx_ptr = (short*) data_vtx_ptr;
160+
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
161+
const auto cmd_list = draw_data->CmdLists[cmd_id];
162+
163+
for (auto const& idx : cmd_list->IdxBuffer) {
164+
*data_idx_ptr = idx + (short)idx_offset;
165+
data_idx_ptr++;
166+
}
167+
168+
idx_offset += cmd_list->VtxBuffer.size();
169+
}
170+
171+
cmdContainer* data_cmd_ptr = (cmdContainer*) data_idx_ptr;
172+
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
173+
const auto cmd_list = draw_data->CmdLists[cmd_id];
174+
175+
for (auto const& cmd : cmd_list->CmdBuffer) {
176+
data_cmd_ptr->count = cmd.ElemCount;
177+
data_cmd_ptr->rectX = cmd.ClipRect.x;
178+
data_cmd_ptr->rectY = cmd.ClipRect.y;
179+
data_cmd_ptr->rectZ = cmd.ClipRect.z;
180+
data_cmd_ptr->rectW = cmd.ClipRect.w;
181+
data_cmd_ptr++;
182+
}
183+
}
184+
185+
*size = buffer_size;
186+
*raw_data = local_data_base;
187+
}
188+
189+
bool pollGUIPreRender(void* context)
59190
{
60191
GLFWwindow* window = reinterpret_cast<GLFWwindow*>(context);
192+
61193
if (glfwWindowShouldClose(window)) {
62194
return false;
63195
}
64196
glfwPollEvents();
65197
ImGui_ImplGlfwGL3_NewFrame();
66198

67-
68199
// Rendering
69200
int display_w, display_h;
70201
glfwGetFramebufferSize(window, &display_w, &display_h);
71202
glViewport(0, 0, display_w, display_h);
72203
ImVec4 clear_color = ImColor(114, 144, 154);
73204
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
74205
glClear(GL_COLOR_BUFFER_BIT);
206+
207+
return true;
208+
}
209+
210+
/// @return draw data as void* to avoid dependencies
211+
void *pollGUIRender(std::function<void(void)> guiCallback)
212+
{
75213
// This is where the magic actually happens...
76214
if (guiCallback) {
77215
guiCallback();
78216
}
79217
ImGui::Render();
80-
ImGui_ImplGlfwGL3_RenderDrawLists(ImGui::GetDrawData());
218+
219+
return ImGui::GetDrawData();
220+
}
221+
222+
void pollGUIPostRender(void* context, void *draw_data)
223+
{
224+
GLFWwindow* window = reinterpret_cast<GLFWwindow*>(context);
225+
226+
ImGui_ImplGlfwGL3_RenderDrawLists((ImDrawData*)draw_data);
81227
glfwSwapBuffers(window);
228+
}
229+
230+
/// @return true if we do not need to exit, false if we do.
231+
bool pollGUI(void* context, std::function<void(void)> guiCallback)
232+
{
233+
if (!pollGUIPreRender(context)) {
234+
return false;
235+
}
236+
void *draw_data = pollGUIRender(guiCallback);
237+
pollGUIPostRender(context, draw_data);
238+
82239
return true;
83240
}
84241

DebugGUI/src/DebugGUI.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define FRAMEWORK_DEBUGGUI_H
1212

1313
#include <functional>
14+
#include <iosfwd>
1415

1516
namespace o2::framework {
1617

@@ -19,6 +20,11 @@ void default_error_callback(int, const char*);
1920

2021
void* initGUI(const char* name, decltype(default_error_callback) = nullptr);
2122
bool pollGUI(void* context, std::function<void(void)> guiCallback);
23+
void getFrameJSON(void *data, std::ostream& json_data);
24+
void getFrameRaw(void *data, void **raw_data, int *size);
25+
bool pollGUIPreRender(void* context);
26+
void* pollGUIRender(std::function<void(void)> guiCallback);
27+
void pollGUIPostRender(void* context, void* draw_data);
2228
void disposeGUI();
2329

2430
} // namespace o2::framework

0 commit comments

Comments
 (0)