Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 161 additions & 4 deletions DebugGUI/src/DebugGUI.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <GLFW/glfw3.h>
#include <cstdio>
#include <functional>
#include <ostream>

static void default_error_callback(int error, const char* description)
{
Expand Down Expand Up @@ -54,31 +55,187 @@ void* initGUI(const char* name, void(*error_callback)(int, char const*descriptio
return window;
}

/// @return true if we do not need to exit, false if we do.
bool pollGUI(void* context, std::function<void(void)> guiCallback)
// fills a stream with drawing data in JSON format
// the JSON is composed of a list of draw commands
/// FIXME: document the actual schema of the format.
void getFrameJSON(void *data, std::ostream& json_data)
{
ImDrawData* draw_data = (ImDrawData*)data;

json_data << "[";

for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
const auto cmd_list = draw_data->CmdLists[cmd_id];
const auto vtx_buffer = cmd_list->VtxBuffer;
const auto idx_buffer = cmd_list->IdxBuffer;
const auto cmd_buffer = cmd_list->CmdBuffer;

json_data << "{\"vtx\":[";
for (int i = 0; i < vtx_buffer.size(); ++i) {
auto v = vtx_buffer[i];
json_data << "[" << v.pos.x << "," << v.pos.y << "," << v.col << ',' << v.uv.x << "," << v.uv.y << "]";
if (i < vtx_buffer.size() - 1) json_data << ",";
}

json_data << "],\"idx\":[";
for (int i = 0; i < idx_buffer.size(); ++i) {
auto id = idx_buffer[i];
json_data << id;
if (i < idx_buffer.size() - 1) json_data << ",";
}

json_data << "],\"cmd\":[";
for (int i = 0; i < cmd_buffer.size(); ++i) {
auto cmd = cmd_buffer[i];
json_data << "{\"cnt\":" << cmd.ElemCount << ", \"clp\":[" << cmd.ClipRect.x << "," << cmd.ClipRect.y << "," << cmd.ClipRect.z << "," << cmd.ClipRect.w << "]}";
if (i < cmd_buffer.size() - 1) json_data << ",";
}
json_data << "]}";
if (cmd_id < draw_data->CmdListsCount - 1) json_data << ",";
}

json_data << "]";
}


struct vtxContainer {
float posX, posY, uvX, uvY;
int col;
};

struct cmdContainer {
int count;
float rectX, rectY, rectZ, rectW;
};

// given draw data, returns a mallocd buffer containing formatted frame data
// ready to be sent and its size.
// the returned buffer must be freed by the caller.
/// FIXME: document actual schema of the format
void getFrameRaw(void *data, void **raw_data, int *size)
{
ImDrawData* draw_data = (ImDrawData*)data;

// compute sizes
int buffer_size = sizeof(int)*3,
vtx_count = 0,
idx_count = 0,
cmd_count = 0;
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
const auto cmd_list = draw_data->CmdLists[cmd_id];

vtx_count += cmd_list->VtxBuffer.size();
buffer_size += cmd_list->VtxBuffer.size() * (sizeof(vtxContainer));

idx_count += cmd_list->IdxBuffer.size();
buffer_size += cmd_list->IdxBuffer.size() * (sizeof(short));

cmd_count += cmd_list->CmdBuffer.size();
buffer_size += cmd_list->CmdBuffer.size() * (sizeof(cmdContainer));
}

void *local_data_base = malloc(buffer_size);

int *data_header_ptr = (int*) local_data_base;
*data_header_ptr = vtx_count; data_header_ptr++;
*data_header_ptr = idx_count; data_header_ptr++;
*data_header_ptr = cmd_count; data_header_ptr++;

vtxContainer* data_vtx_ptr = (vtxContainer*) data_header_ptr;
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
const auto cmd_list = draw_data->CmdLists[cmd_id];

for (auto const& vtx : cmd_list->VtxBuffer) {
data_vtx_ptr->posX = vtx.pos.x;
data_vtx_ptr->posY = vtx.pos.y;
data_vtx_ptr->uvX = vtx.uv.x;
data_vtx_ptr->uvY = vtx.uv.y;
data_vtx_ptr->col = vtx.col;
data_vtx_ptr++;
}
}

int idx_offset = 0;
short* data_idx_ptr = (short*) data_vtx_ptr;
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
const auto cmd_list = draw_data->CmdLists[cmd_id];

for (auto const& idx : cmd_list->IdxBuffer) {
*data_idx_ptr = idx + (short)idx_offset;
data_idx_ptr++;
}

idx_offset += cmd_list->VtxBuffer.size();
}

cmdContainer* data_cmd_ptr = (cmdContainer*) data_idx_ptr;
for (int cmd_id = 0; cmd_id < draw_data->CmdListsCount; ++cmd_id) {
const auto cmd_list = draw_data->CmdLists[cmd_id];

for (auto const& cmd : cmd_list->CmdBuffer) {
data_cmd_ptr->count = cmd.ElemCount;
data_cmd_ptr->rectX = cmd.ClipRect.x;
data_cmd_ptr->rectY = cmd.ClipRect.y;
data_cmd_ptr->rectZ = cmd.ClipRect.z;
data_cmd_ptr->rectW = cmd.ClipRect.w;
data_cmd_ptr++;
}
}

*size = buffer_size;
*raw_data = local_data_base;
}

bool pollGUIPreRender(void* context)
{
GLFWwindow* window = reinterpret_cast<GLFWwindow*>(context);

if (glfwWindowShouldClose(window)) {
return false;
}
glfwPollEvents();
ImGui_ImplGlfwGL3_NewFrame();


// Rendering
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
ImVec4 clear_color = ImColor(114, 144, 154);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);

return true;
}

/// @return draw data as void* to avoid dependencies
void *pollGUIRender(std::function<void(void)> guiCallback)
{
// This is where the magic actually happens...
if (guiCallback) {
guiCallback();
}
ImGui::Render();
ImGui_ImplGlfwGL3_RenderDrawLists(ImGui::GetDrawData());

return ImGui::GetDrawData();
}

void pollGUIPostRender(void* context, void *draw_data)
{
GLFWwindow* window = reinterpret_cast<GLFWwindow*>(context);

ImGui_ImplGlfwGL3_RenderDrawLists((ImDrawData*)draw_data);
glfwSwapBuffers(window);
}

/// @return true if we do not need to exit, false if we do.
bool pollGUI(void* context, std::function<void(void)> guiCallback)
{
if (!pollGUIPreRender(context)) {
return false;
}
void *draw_data = pollGUIRender(guiCallback);
pollGUIPostRender(context, draw_data);

return true;
}

Expand Down
6 changes: 6 additions & 0 deletions DebugGUI/src/DebugGUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define FRAMEWORK_DEBUGGUI_H

#include <functional>
#include <iosfwd>

namespace o2::framework {

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

void* initGUI(const char* name, decltype(default_error_callback) = nullptr);
bool pollGUI(void* context, std::function<void(void)> guiCallback);
void getFrameJSON(void *data, std::ostream& json_data);
Comment thread
ktf marked this conversation as resolved.
void getFrameRaw(void *data, void **raw_data, int *size);
bool pollGUIPreRender(void* context);
void* pollGUIRender(std::function<void(void)> guiCallback);
void pollGUIPostRender(void* context, void* draw_data);
void disposeGUI();

} // namespace o2::framework
Expand Down
Loading