rntviewer/src/render.cpp
2024-07-12 10:07:27 +02:00

167 lines
5.9 KiB
C++

internal
void accum_dt_ms(Delta_Time_Accum &accum, f32 dt)
{
if (accum.count < accum.max) {
assert(accum.start == 0);
accum.base[accum.count++] = dt;
} else {
accum.base[accum.start++] = dt;
if (accum.start == accum.max)
accum.start = 0;
}
}
internal
f32 calc_avg_dt_ms(const Delta_Time_Accum &accum)
{
f32 res = 0;
for (u16 idx = 0; idx < accum.count; ++idx)
res += accum.base[idx];
if (accum.count) res /= accum.count;
return res;
}
internal
String8 to_pretty_size(Arena *arena, u64 bytes)
{
if (bytes >= GiB(1)) return push_str8f(arena, "%.1f GiB", (f32)bytes / GiB(1));
if (bytes >= MiB(1)) return push_str8f(arena, "%.1f MiB", (f32)bytes / MiB(1));
if (bytes >= KiB(1)) return push_str8f(arena, "%.1f KiB", (f32)bytes / KiB(1));
return push_str8f(arena, "%zu B", bytes);
}
internal
u32 mem_edit_bg_color_fn(const u8 *, u64 off, const void *user_data)
{
const App_State *app = reinterpret_cast<const App_State *>(user_data);
const RNTuple_Info &rinfo = app->rntinfo;
u64 rblob_sz = rinfo.rblob_header_size;
off += app->vsettings.base_display_addr;
#define COL(c) (ImColor((c)[0], (c)[1], (c)[2]))
if (off <= rinfo.root_file_header_size) return COL(app->vsettings.col_tfile);
if (rinfo.rng_anchor_key.start <= off && off <= rinfo.rng_anchor_key.end()) return COL(app->vsettings.col_key);
if (rinfo.rng_header.start - rblob_sz <= off && off <= rinfo.rng_header.start) return COL(app->vsettings.col_key);
if (rinfo.rng_footer.start - rblob_sz <= off && off <= rinfo.rng_footer.start) return COL(app->vsettings.col_key);
if (rinfo.rng_anchor.start <= off && off <= rinfo.rng_anchor.end()) return COL(app->vsettings.col_anchor);
if (rinfo.rng_header.start <= off && off <= rinfo.rng_header.end()) return COL(app->vsettings.col_header);
if (rinfo.rng_footer.start <= off && off <= rinfo.rng_footer.end()) return COL(app->vsettings.col_footer);
#undef COL
return IM_COL32(0, 0, 0, 0);
}
internal
MemoryEditor make_memory_editor(const App_State &app)
{
MemoryEditor mem_edit;
// mem_edit.ReadOnly = true;
mem_edit.Cols = 32;
mem_edit.OptShowDataPreview = true;
mem_edit.BgColorFn = mem_edit_bg_color_fn;
mem_edit.BgColorFnUserData = &app;
return mem_edit;
}
internal
Viewer_Settings make_viewer_settings()
{
Viewer_Settings settings {};
#define COL(c, r, g, b) settings.c[0] = r/255.0, settings.c[1] = g/255.0, settings.c[2] = b/255.0
COL(col_anchor, 150, 150, 0);
COL(col_header, 150, 0, 50);
COL(col_footer, 50, 0, 150);
COL(col_key, 0, 100, 50);
COL(col_tfile, 90, 90, 90);
#undef COL
return settings;
}
internal
void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
{
accum_dt_ms(app.delta_time_accum, delta_time_ms);
ImGui::SetNextWindowPos({ 0, 0 });
ImGui::SetNextWindowSize({ (f32)app.win_data.width, (f32)app.win_data.height });
Temp scratch = temp_begin(arena);
defer { temp_end(scratch); };
const u64 inspected_max_size = 2048;
u64 text_buf_size = min(app.inspected_file_size * 2, inspected_max_size);
char *text_buf = arena_push_array_no_zero<char>(scratch.arena, text_buf_size + 1);
// Convert file content to human readable
// @Speed: maybe do this only when the file changes
for (u64 i = 0; i < text_buf_size / 2; ++i)
sprintf(&text_buf[2 * i], "%02X", app.inspected_fmem[i]);
text_buf[text_buf_size] = 0;
const auto main_win_flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDecoration;
if (ImGui::Begin("main", nullptr, main_win_flags)) {
String8 ntpl_desc = rntuple_description(scratch.arena, app.rntinfo.anchor);
ImGui::Text("RNTuple '%s' (%s) from file \"%s\"", app.ntpl_name, ntpl_desc.c(), app.inspected_fname);
// Draw stats
{
ImGui::SameLine();
u64 mem_used = arena_mem_used(arena);
f32 avg_dt = calc_avg_dt_ms(app.delta_time_accum);
String8 stat_txt = push_str8f(scratch.arena, "mem used: %s | avg dt: %.1f",
to_pretty_size(scratch.arena, mem_used), avg_dt);
f32 pos_x = (ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(stat_txt.c()).x
- ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
if (pos_x > ImGui::GetCursorPosX())
ImGui::SetCursorPosX(pos_x);
ImGui::Text("%s", stat_txt.c());
}
ImGui::Separator();
// Draw main content
{
static MemoryEditor mem_edit = make_memory_editor(app);
ImGui::BeginTable("Hex View", 2);
ImGui::TableNextColumn();
assert(app.vsettings.base_display_addr < app.inspected_file_size);
void *content = app.inspected_fmem + app.vsettings.base_display_addr;
u64 content_size = app.inspected_file_size - app.vsettings.base_display_addr;
mem_edit.DrawContents(content, content_size, app.vsettings.base_display_addr);
ImGui::TableNextColumn();
ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoLabel;
ImGui::ColorEdit3("_TFile", app.vsettings.col_tfile, flags);
ImGui::SameLine();
if (ImGui::Button("TFile")) app.vsettings.base_display_addr = 0;
ImGui::ColorEdit3("_RNTuple Anchor", app.vsettings.col_anchor, flags);
ImGui::SameLine();
if (ImGui::Button("RNTuple Anchor")) app.vsettings.base_display_addr = app.rntinfo.rng_anchor.start;
ImGui::ColorEdit3("_RNTuple Header", app.vsettings.col_header, flags);
ImGui::SameLine();
if (ImGui::Button("RNTuple Header")) app.vsettings.base_display_addr = app.rntinfo.rng_header.start;
ImGui::ColorEdit3("_RNTuple Footer", app.vsettings.col_footer, flags);
ImGui::SameLine();
if (ImGui::Button("RNTuple Footer")) app.vsettings.base_display_addr = app.rntinfo.rng_footer.start;
ImGui::ColorEdit3("_TKey Header", app.vsettings.col_key, flags);
ImGui::SameLine();
if (ImGui::Button("TKey Header")) {} // TODO app.vsettings.base_display_addr = app.rntinfo.rng_footer.start;
ImGui::EndTable();
}
ImGui::End();
}
}