1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <stdio.h> 25bf215546Sopenharmony_ci#include <stdlib.h> 26bf215546Sopenharmony_ci#include <stdint.h> 27bf215546Sopenharmony_ci#include <getopt.h> 28bf215546Sopenharmony_ci#include <unistd.h> 29bf215546Sopenharmony_ci#include <fcntl.h> 30bf215546Sopenharmony_ci#include <string.h> 31bf215546Sopenharmony_ci#include <errno.h> 32bf215546Sopenharmony_ci#include <sys/stat.h> 33bf215546Sopenharmony_ci#include <sys/mman.h> 34bf215546Sopenharmony_ci#include <sys/types.h> 35bf215546Sopenharmony_ci#include <ctype.h> 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#include "util/macros.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "aub_read.h" 40bf215546Sopenharmony_ci#include "aub_mem.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include "common/intel_disasm.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci#define xtzalloc(name) ((decltype(&name)) calloc(1, sizeof(name))) 45bf215546Sopenharmony_ci#define xtalloc(name) ((decltype(&name)) malloc(sizeof(name))) 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistruct aub_file { 48bf215546Sopenharmony_ci uint8_t *map, *end, *cursor; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci uint16_t pci_id; 51bf215546Sopenharmony_ci char app_name[33]; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci /* List of batch buffers to process */ 54bf215546Sopenharmony_ci struct { 55bf215546Sopenharmony_ci const uint8_t *start; 56bf215546Sopenharmony_ci const uint8_t *end; 57bf215546Sopenharmony_ci } *execs; 58bf215546Sopenharmony_ci int n_execs; 59bf215546Sopenharmony_ci int n_allocated_execs; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci uint32_t idx_reg_write; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci /* Device state */ 64bf215546Sopenharmony_ci struct intel_device_info devinfo; 65bf215546Sopenharmony_ci struct brw_isa_info isa; 66bf215546Sopenharmony_ci struct intel_spec *spec; 67bf215546Sopenharmony_ci}; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic void 70bf215546Sopenharmony_cistore_exec_begin(struct aub_file *file) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci if (unlikely(file->n_execs >= file->n_allocated_execs)) { 73bf215546Sopenharmony_ci file->n_allocated_execs = MAX2(2U * file->n_allocated_execs, 74bf215546Sopenharmony_ci 4096 / sizeof(file->execs[0])); 75bf215546Sopenharmony_ci file->execs = (decltype(file->execs)) 76bf215546Sopenharmony_ci realloc(static_cast<void *>(file->execs), 77bf215546Sopenharmony_ci file->n_allocated_execs * sizeof(file->execs[0])); 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci file->execs[file->n_execs++].start = file->cursor; 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_cistatic void 84bf215546Sopenharmony_cistore_exec_end(struct aub_file *file) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci if (file->n_execs > 0 && file->execs[file->n_execs - 1].end == NULL) 87bf215546Sopenharmony_ci file->execs[file->n_execs - 1].end = file->cursor; 88bf215546Sopenharmony_ci} 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_cistatic void 91bf215546Sopenharmony_cihandle_mem_write(void *user_data, uint64_t phys_addr, 92bf215546Sopenharmony_ci const void *data, uint32_t data_len) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci struct aub_file *file = (struct aub_file *) user_data; 95bf215546Sopenharmony_ci file->idx_reg_write = 0; 96bf215546Sopenharmony_ci store_exec_end(file); 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_cistatic void 100bf215546Sopenharmony_cihandle_ring_write(void *user_data, enum drm_i915_gem_engine_class engine, 101bf215546Sopenharmony_ci const void *ring_data, uint32_t ring_data_len) 102bf215546Sopenharmony_ci{ 103bf215546Sopenharmony_ci struct aub_file *file = (struct aub_file *) user_data; 104bf215546Sopenharmony_ci file->idx_reg_write = 0; 105bf215546Sopenharmony_ci store_exec_begin(file); 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_cistatic void 109bf215546Sopenharmony_cihandle_reg_write(void *user_data, uint32_t reg_offset, uint32_t reg_value) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci struct aub_file *file = (struct aub_file *) user_data; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci /* Only store the first register write of a series (execlist writes take 114bf215546Sopenharmony_ci * involve 2 dwords). 115bf215546Sopenharmony_ci */ 116bf215546Sopenharmony_ci if (file->idx_reg_write++ == 0) 117bf215546Sopenharmony_ci store_exec_begin(file); 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_cistatic void 121bf215546Sopenharmony_cihandle_info(void *user_data, int pci_id, const char *app_name) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci struct aub_file *file = (struct aub_file *) user_data; 124bf215546Sopenharmony_ci store_exec_end(file); 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci file->pci_id = pci_id; 127bf215546Sopenharmony_ci snprintf(file->app_name, sizeof(app_name), "%s", app_name); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (!intel_get_device_info_from_pci_id(file->pci_id, &file->devinfo)) { 130bf215546Sopenharmony_ci fprintf(stderr, "can't find device information: pci_id=0x%x\n", file->pci_id); 131bf215546Sopenharmony_ci exit(EXIT_FAILURE); 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci brw_init_isa_info(&file->isa, &file->devinfo); 134bf215546Sopenharmony_ci file->spec = intel_spec_load(&file->devinfo); 135bf215546Sopenharmony_ci} 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_cistatic void 138bf215546Sopenharmony_cihandle_error(void *user_data, const void *aub_data, const char *msg) 139bf215546Sopenharmony_ci{ 140bf215546Sopenharmony_ci fprintf(stderr, "ERROR: %s", msg); 141bf215546Sopenharmony_ci} 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_cistatic struct aub_file * 144bf215546Sopenharmony_ciaub_file_open(const char *filename) 145bf215546Sopenharmony_ci{ 146bf215546Sopenharmony_ci struct aub_file *file; 147bf215546Sopenharmony_ci struct stat sb; 148bf215546Sopenharmony_ci int fd; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci file = xtzalloc(*file); 151bf215546Sopenharmony_ci fd = open(filename, O_RDWR); 152bf215546Sopenharmony_ci if (fd == -1) { 153bf215546Sopenharmony_ci fprintf(stderr, "open %s failed: %s\n", filename, strerror(errno)); 154bf215546Sopenharmony_ci exit(EXIT_FAILURE); 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci if (fstat(fd, &sb) == -1) { 158bf215546Sopenharmony_ci fprintf(stderr, "stat failed: %s\n", strerror(errno)); 159bf215546Sopenharmony_ci exit(EXIT_FAILURE); 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci file->map = (uint8_t *) mmap(NULL, sb.st_size, 163bf215546Sopenharmony_ci PROT_READ, MAP_SHARED, fd, 0); 164bf215546Sopenharmony_ci if (file->map == MAP_FAILED) { 165bf215546Sopenharmony_ci fprintf(stderr, "mmap failed: %s\n", strerror(errno)); 166bf215546Sopenharmony_ci exit(EXIT_FAILURE); 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci close(fd); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci file->cursor = file->map; 172bf215546Sopenharmony_ci file->end = file->map + sb.st_size; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci struct aub_read aub_read = {}; 175bf215546Sopenharmony_ci aub_read.user_data = file; 176bf215546Sopenharmony_ci aub_read.info = handle_info; 177bf215546Sopenharmony_ci aub_read.error = handle_error; 178bf215546Sopenharmony_ci aub_read.reg_write = handle_reg_write; 179bf215546Sopenharmony_ci aub_read.ring_write = handle_ring_write; 180bf215546Sopenharmony_ci aub_read.local_write = handle_mem_write; 181bf215546Sopenharmony_ci aub_read.phys_write = handle_mem_write; 182bf215546Sopenharmony_ci aub_read.ggtt_write = handle_mem_write; 183bf215546Sopenharmony_ci aub_read.ggtt_entry_write = handle_mem_write; 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci int consumed; 186bf215546Sopenharmony_ci while (file->cursor < file->end && 187bf215546Sopenharmony_ci (consumed = aub_read_command(&aub_read, file->cursor, 188bf215546Sopenharmony_ci file->end - file->cursor)) > 0) { 189bf215546Sopenharmony_ci file->cursor += consumed; 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci /* Ensure we have an end on the last register write. */ 193bf215546Sopenharmony_ci if (file->n_execs > 0 && file->execs[file->n_execs - 1].end == NULL) 194bf215546Sopenharmony_ci file->execs[file->n_execs - 1].end = file->end; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci return file; 197bf215546Sopenharmony_ci} 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci/**/ 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_cistatic void 202bf215546Sopenharmony_ciupdate_mem_for_exec(struct aub_mem *mem, struct aub_file *file, int exec_idx) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci struct aub_read read = {}; 205bf215546Sopenharmony_ci read.user_data = mem; 206bf215546Sopenharmony_ci read.local_write = aub_mem_local_write; 207bf215546Sopenharmony_ci read.phys_write = aub_mem_phys_write; 208bf215546Sopenharmony_ci read.ggtt_write = aub_mem_ggtt_write; 209bf215546Sopenharmony_ci read.ggtt_entry_write = aub_mem_ggtt_entry_write; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci /* Replay the aub file from the beginning up to just before the 212bf215546Sopenharmony_ci * commands we want to read. where the context setup happens. 213bf215546Sopenharmony_ci */ 214bf215546Sopenharmony_ci const uint8_t *iter = file->map; 215bf215546Sopenharmony_ci while (iter < file->execs[exec_idx].start) { 216bf215546Sopenharmony_ci iter += aub_read_command(&read, iter, file->execs[exec_idx].start - iter); 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci} 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci/* UI */ 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci#include <epoxy/gl.h> 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci#include "imgui/imgui.h" 225bf215546Sopenharmony_ci#include "imgui/imgui_memory_editor.h" 226bf215546Sopenharmony_ci#include "imgui_impl_gtk3.h" 227bf215546Sopenharmony_ci#include "imgui_impl_opengl3.h" 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci#include "aubinator_viewer.h" 230bf215546Sopenharmony_ci#include "aubinator_viewer_urb.h" 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_cistruct window { 233bf215546Sopenharmony_ci struct list_head link; /* link in the global list of windows */ 234bf215546Sopenharmony_ci struct list_head parent_link; /* link in parent window list of children */ 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci struct list_head children_windows; /* list of children windows */ 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci char name[128]; 239bf215546Sopenharmony_ci bool opened; 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci ImVec2 position; 242bf215546Sopenharmony_ci ImVec2 size; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci void (*display)(struct window*); 245bf215546Sopenharmony_ci void (*destroy)(struct window*); 246bf215546Sopenharmony_ci}; 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_cistruct edit_window { 249bf215546Sopenharmony_ci struct window base; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci struct aub_mem *mem; 252bf215546Sopenharmony_ci uint64_t address; 253bf215546Sopenharmony_ci uint32_t len; 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci struct intel_batch_decode_bo aub_bo; 256bf215546Sopenharmony_ci uint64_t aub_offset; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci struct intel_batch_decode_bo gtt_bo; 259bf215546Sopenharmony_ci uint64_t gtt_offset; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci struct MemoryEditor editor; 262bf215546Sopenharmony_ci}; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_cistruct pml4_window { 265bf215546Sopenharmony_ci struct window base; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci struct aub_mem *mem; 268bf215546Sopenharmony_ci}; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_cistruct shader_window { 271bf215546Sopenharmony_ci struct window base; 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci uint64_t address; 274bf215546Sopenharmony_ci char *shader; 275bf215546Sopenharmony_ci size_t shader_size; 276bf215546Sopenharmony_ci}; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_cistruct urb_window { 279bf215546Sopenharmony_ci struct window base; 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci uint32_t end_urb_offset; 282bf215546Sopenharmony_ci struct aub_decode_urb_stage_state urb_stages[AUB_DECODE_N_STAGE]; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci AubinatorViewerUrb urb_view; 285bf215546Sopenharmony_ci}; 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_cistruct batch_window { 288bf215546Sopenharmony_ci struct window base; 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci struct aub_mem mem; 291bf215546Sopenharmony_ci struct aub_read read; 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci bool uses_ppgtt; 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci bool collapsed; 296bf215546Sopenharmony_ci int exec_idx; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci struct aub_viewer_decode_cfg decode_cfg; 299bf215546Sopenharmony_ci struct aub_viewer_decode_ctx decode_ctx; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci struct pml4_window pml4_window; 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci char edit_address[20]; 304bf215546Sopenharmony_ci}; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_cistatic struct Context { 307bf215546Sopenharmony_ci struct aub_file *file; 308bf215546Sopenharmony_ci char *input_file; 309bf215546Sopenharmony_ci char *xml_path; 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci GtkWidget *gtk_window; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci /* UI state*/ 314bf215546Sopenharmony_ci bool show_commands_window; 315bf215546Sopenharmony_ci bool show_registers_window; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci struct aub_viewer_cfg cfg; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci struct list_head windows; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci struct window file_window; 322bf215546Sopenharmony_ci struct window commands_window; 323bf215546Sopenharmony_ci struct window registers_window; 324bf215546Sopenharmony_ci} context; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_cithread_local ImGuiContext* __MesaImGui; 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_cistatic int 329bf215546Sopenharmony_cimap_key(int k) 330bf215546Sopenharmony_ci{ 331bf215546Sopenharmony_ci return ImGuiKey_COUNT + k; 332bf215546Sopenharmony_ci} 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_cistatic bool 335bf215546Sopenharmony_cihas_ctrl_key(int key) 336bf215546Sopenharmony_ci{ 337bf215546Sopenharmony_ci return ImGui::GetIO().KeyCtrl && ImGui::IsKeyPressed(map_key(key)); 338bf215546Sopenharmony_ci} 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_cistatic bool 341bf215546Sopenharmony_ciwindow_has_ctrl_key(int key) 342bf215546Sopenharmony_ci{ 343bf215546Sopenharmony_ci return ImGui::IsRootWindowOrAnyChildFocused() && has_ctrl_key(key); 344bf215546Sopenharmony_ci} 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_cistatic void 347bf215546Sopenharmony_cidestroy_window_noop(struct window *win) 348bf215546Sopenharmony_ci{ 349bf215546Sopenharmony_ci} 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci/* Shader windows */ 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_cistatic void 354bf215546Sopenharmony_cidisplay_shader_window(struct window *win) 355bf215546Sopenharmony_ci{ 356bf215546Sopenharmony_ci struct shader_window *window = (struct shader_window *) win; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci if (window->shader) { 359bf215546Sopenharmony_ci ImGui::InputTextMultiline("Assembly", 360bf215546Sopenharmony_ci window->shader, window->shader_size, 361bf215546Sopenharmony_ci ImGui::GetContentRegionAvail(), 362bf215546Sopenharmony_ci ImGuiInputTextFlags_ReadOnly); 363bf215546Sopenharmony_ci } else { 364bf215546Sopenharmony_ci ImGui::Text("Shader not available"); 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci} 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_cistatic void 369bf215546Sopenharmony_cidestroy_shader_window(struct window *win) 370bf215546Sopenharmony_ci{ 371bf215546Sopenharmony_ci struct shader_window *window = (struct shader_window *) win; 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci free(window->shader); 374bf215546Sopenharmony_ci free(window); 375bf215546Sopenharmony_ci} 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_cistatic struct shader_window * 378bf215546Sopenharmony_cinew_shader_window(struct aub_mem *mem, uint64_t address, const char *desc) 379bf215546Sopenharmony_ci{ 380bf215546Sopenharmony_ci struct shader_window *window = xtzalloc(*window); 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci snprintf(window->base.name, sizeof(window->base.name), 383bf215546Sopenharmony_ci "%s (0x%" PRIx64 ")##%p", desc, address, window); 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci list_inithead(&window->base.parent_link); 386bf215546Sopenharmony_ci window->base.position = ImVec2(-1, -1); 387bf215546Sopenharmony_ci window->base.size = ImVec2(700, 300); 388bf215546Sopenharmony_ci window->base.opened = true; 389bf215546Sopenharmony_ci window->base.display = display_shader_window; 390bf215546Sopenharmony_ci window->base.destroy = destroy_shader_window; 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci struct intel_batch_decode_bo shader_bo = 393bf215546Sopenharmony_ci aub_mem_get_ppgtt_bo(mem, address); 394bf215546Sopenharmony_ci if (shader_bo.map) { 395bf215546Sopenharmony_ci FILE *f = open_memstream(&window->shader, &window->shader_size); 396bf215546Sopenharmony_ci if (f) { 397bf215546Sopenharmony_ci intel_disassemble(&context.file->isa, 398bf215546Sopenharmony_ci (const uint8_t *) shader_bo.map + 399bf215546Sopenharmony_ci (address - shader_bo.addr), 0, f); 400bf215546Sopenharmony_ci fclose(f); 401bf215546Sopenharmony_ci } 402bf215546Sopenharmony_ci } 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci list_addtail(&window->base.link, &context.windows); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci return window; 407bf215546Sopenharmony_ci} 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci/* URB windows */ 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_cistatic void 412bf215546Sopenharmony_cidisplay_urb_window(struct window *win) 413bf215546Sopenharmony_ci{ 414bf215546Sopenharmony_ci struct urb_window *window = (struct urb_window *) win; 415bf215546Sopenharmony_ci static const char *stages[] = { 416bf215546Sopenharmony_ci [AUB_DECODE_STAGE_VS] = "VS", 417bf215546Sopenharmony_ci [AUB_DECODE_STAGE_HS] = "HS", 418bf215546Sopenharmony_ci [AUB_DECODE_STAGE_DS] = "DS", 419bf215546Sopenharmony_ci [AUB_DECODE_STAGE_GS] = "GS", 420bf215546Sopenharmony_ci [AUB_DECODE_STAGE_PS] = "PS", 421bf215546Sopenharmony_ci [AUB_DECODE_STAGE_CS] = "CS", 422bf215546Sopenharmony_ci }; 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci ImGui::Text("URB allocation:"); 425bf215546Sopenharmony_ci window->urb_view.DrawAllocation("##urb", 426bf215546Sopenharmony_ci ARRAY_SIZE(window->urb_stages), 427bf215546Sopenharmony_ci window->end_urb_offset, 428bf215546Sopenharmony_ci stages, 429bf215546Sopenharmony_ci &window->urb_stages[0]); 430bf215546Sopenharmony_ci} 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_cistatic void 433bf215546Sopenharmony_cidestroy_urb_window(struct window *win) 434bf215546Sopenharmony_ci{ 435bf215546Sopenharmony_ci struct urb_window *window = (struct urb_window *) win; 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci free(window); 438bf215546Sopenharmony_ci} 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_cistatic struct urb_window * 441bf215546Sopenharmony_cinew_urb_window(struct aub_viewer_decode_ctx *decode_ctx, uint64_t address) 442bf215546Sopenharmony_ci{ 443bf215546Sopenharmony_ci struct urb_window *window = xtzalloc(*window); 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci snprintf(window->base.name, sizeof(window->base.name), 446bf215546Sopenharmony_ci "URB view (0x%" PRIx64 ")##%p", address, window); 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci list_inithead(&window->base.parent_link); 449bf215546Sopenharmony_ci window->base.position = ImVec2(-1, -1); 450bf215546Sopenharmony_ci window->base.size = ImVec2(700, 300); 451bf215546Sopenharmony_ci window->base.opened = true; 452bf215546Sopenharmony_ci window->base.display = display_urb_window; 453bf215546Sopenharmony_ci window->base.destroy = destroy_urb_window; 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci window->end_urb_offset = decode_ctx->end_urb_offset; 456bf215546Sopenharmony_ci memcpy(window->urb_stages, decode_ctx->urb_stages, sizeof(window->urb_stages)); 457bf215546Sopenharmony_ci window->urb_view = AubinatorViewerUrb(); 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci list_addtail(&window->base.link, &context.windows); 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci return window; 462bf215546Sopenharmony_ci} 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci/* Memory editor windows */ 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_cistatic uint8_t 467bf215546Sopenharmony_ciread_edit_window(const uint8_t *data, size_t off) 468bf215546Sopenharmony_ci{ 469bf215546Sopenharmony_ci struct edit_window *window = (struct edit_window *) data; 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci return *((const uint8_t *) window->gtt_bo.map + window->gtt_offset + off); 472bf215546Sopenharmony_ci} 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_cistatic void 475bf215546Sopenharmony_ciwrite_edit_window(uint8_t *data, size_t off, uint8_t d) 476bf215546Sopenharmony_ci{ 477bf215546Sopenharmony_ci struct edit_window *window = (struct edit_window *) data; 478bf215546Sopenharmony_ci uint8_t *gtt = (uint8_t *) window->gtt_bo.map + window->gtt_offset + off; 479bf215546Sopenharmony_ci uint8_t *aub = (uint8_t *) window->aub_bo.map + window->aub_offset + off; 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci *gtt = *aub = d; 482bf215546Sopenharmony_ci} 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_cistatic void 485bf215546Sopenharmony_cidisplay_edit_window(struct window *win) 486bf215546Sopenharmony_ci{ 487bf215546Sopenharmony_ci struct edit_window *window = (struct edit_window *) win; 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci if (window->aub_bo.map && window->gtt_bo.map) { 490bf215546Sopenharmony_ci ImGui::BeginChild(ImGui::GetID("##block")); 491bf215546Sopenharmony_ci window->editor.DrawContents((uint8_t *) window, 492bf215546Sopenharmony_ci MIN3(window->len, 493bf215546Sopenharmony_ci window->gtt_bo.size - window->gtt_offset, 494bf215546Sopenharmony_ci window->aub_bo.size - window->aub_offset), 495bf215546Sopenharmony_ci window->address); 496bf215546Sopenharmony_ci ImGui::EndChild(); 497bf215546Sopenharmony_ci } else { 498bf215546Sopenharmony_ci ImGui::Text("Memory view at 0x%" PRIx64 " not available", window->address); 499bf215546Sopenharmony_ci } 500bf215546Sopenharmony_ci} 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_cistatic void 503bf215546Sopenharmony_cidestroy_edit_window(struct window *win) 504bf215546Sopenharmony_ci{ 505bf215546Sopenharmony_ci struct edit_window *window = (struct edit_window *) win; 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci if (window->aub_bo.map) 508bf215546Sopenharmony_ci mprotect((void *) window->aub_bo.map, 4096, PROT_READ); 509bf215546Sopenharmony_ci free(window); 510bf215546Sopenharmony_ci} 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_cistatic struct edit_window * 513bf215546Sopenharmony_cinew_edit_window(struct aub_mem *mem, uint64_t address, uint32_t len) 514bf215546Sopenharmony_ci{ 515bf215546Sopenharmony_ci struct edit_window *window = xtzalloc(*window); 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci snprintf(window->base.name, sizeof(window->base.name), 518bf215546Sopenharmony_ci "Editing aub at 0x%" PRIx64 "##%p", address, window); 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci list_inithead(&window->base.parent_link); 521bf215546Sopenharmony_ci window->base.position = ImVec2(-1, -1); 522bf215546Sopenharmony_ci window->base.size = ImVec2(500, 600); 523bf215546Sopenharmony_ci window->base.opened = true; 524bf215546Sopenharmony_ci window->base.display = display_edit_window; 525bf215546Sopenharmony_ci window->base.destroy = destroy_edit_window; 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci window->mem = mem; 528bf215546Sopenharmony_ci window->address = address; 529bf215546Sopenharmony_ci window->aub_bo = aub_mem_get_ppgtt_addr_aub_data(mem, address); 530bf215546Sopenharmony_ci window->gtt_bo = aub_mem_get_ppgtt_addr_data(mem, address); 531bf215546Sopenharmony_ci window->len = len; 532bf215546Sopenharmony_ci window->editor = MemoryEditor(); 533bf215546Sopenharmony_ci window->editor.OptShowDataPreview = true; 534bf215546Sopenharmony_ci window->editor.OptShowAscii = false; 535bf215546Sopenharmony_ci window->editor.ReadFn = read_edit_window; 536bf215546Sopenharmony_ci window->editor.WriteFn = write_edit_window; 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci if (window->aub_bo.map) { 539bf215546Sopenharmony_ci uint64_t unaligned_map = (uint64_t) window->aub_bo.map; 540bf215546Sopenharmony_ci window->aub_bo.map = (const void *)(unaligned_map & ~0xffful); 541bf215546Sopenharmony_ci window->aub_offset = unaligned_map - (uint64_t) window->aub_bo.map; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci if (mprotect((void *) window->aub_bo.map, window->aub_bo.size, PROT_READ | PROT_WRITE) != 0) { 544bf215546Sopenharmony_ci window->aub_bo.map = NULL; 545bf215546Sopenharmony_ci } 546bf215546Sopenharmony_ci } 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci window->gtt_offset = address - window->gtt_bo.addr; 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci list_addtail(&window->base.link, &context.windows); 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci return window; 553bf215546Sopenharmony_ci} 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci/* 4 level page table walk windows */ 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_cistatic void 558bf215546Sopenharmony_cidisplay_pml4_level(struct aub_mem *mem, uint64_t table_addr, uint64_t table_virt_addr, int level) 559bf215546Sopenharmony_ci{ 560bf215546Sopenharmony_ci if (level == 0) 561bf215546Sopenharmony_ci return; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci struct intel_batch_decode_bo table_bo = 564bf215546Sopenharmony_ci aub_mem_get_phys_addr_data(mem, table_addr); 565bf215546Sopenharmony_ci const uint64_t *table = (const uint64_t *) ((const uint8_t *) table_bo.map + 566bf215546Sopenharmony_ci table_addr - table_bo.addr); 567bf215546Sopenharmony_ci if (!table) { 568bf215546Sopenharmony_ci ImGui::TextColored(context.cfg.missing_color, "Page not available"); 569bf215546Sopenharmony_ci return; 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci uint64_t addr_increment = 1ULL << (12 + 9 * (level - 1)); 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci if (level == 1) { 575bf215546Sopenharmony_ci for (int e = 0; e < 512; e++) { 576bf215546Sopenharmony_ci bool available = (table[e] & 1) != 0; 577bf215546Sopenharmony_ci uint64_t entry_virt_addr = table_virt_addr + e * addr_increment; 578bf215546Sopenharmony_ci if (!available) 579bf215546Sopenharmony_ci continue; 580bf215546Sopenharmony_ci ImGui::Text("Entry%03i - phys_addr=0x%" PRIx64 " - virt_addr=0x%" PRIx64, 581bf215546Sopenharmony_ci e, table[e], entry_virt_addr); 582bf215546Sopenharmony_ci } 583bf215546Sopenharmony_ci } else { 584bf215546Sopenharmony_ci for (int e = 0; e < 512; e++) { 585bf215546Sopenharmony_ci bool available = (table[e] & 1) != 0; 586bf215546Sopenharmony_ci uint64_t entry_virt_addr = table_virt_addr + e * addr_increment; 587bf215546Sopenharmony_ci if (available && 588bf215546Sopenharmony_ci ImGui::TreeNodeEx(&table[e], 589bf215546Sopenharmony_ci available ? ImGuiTreeNodeFlags_Framed : 0, 590bf215546Sopenharmony_ci "Entry%03i - phys_addr=0x%" PRIx64 " - virt_addr=0x%" PRIx64, 591bf215546Sopenharmony_ci e, table[e], entry_virt_addr)) { 592bf215546Sopenharmony_ci display_pml4_level(mem, table[e] & ~0xffful, entry_virt_addr, level -1); 593bf215546Sopenharmony_ci ImGui::TreePop(); 594bf215546Sopenharmony_ci } 595bf215546Sopenharmony_ci } 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci} 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_cistatic void 600bf215546Sopenharmony_cidisplay_pml4_window(struct window *win) 601bf215546Sopenharmony_ci{ 602bf215546Sopenharmony_ci struct pml4_window *window = (struct pml4_window *) win; 603bf215546Sopenharmony_ci 604bf215546Sopenharmony_ci ImGui::Text("pml4: %" PRIx64, window->mem->pml4); 605bf215546Sopenharmony_ci ImGui::BeginChild(ImGui::GetID("##block")); 606bf215546Sopenharmony_ci display_pml4_level(window->mem, window->mem->pml4, 0, 4); 607bf215546Sopenharmony_ci ImGui::EndChild(); 608bf215546Sopenharmony_ci} 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_cistatic void 611bf215546Sopenharmony_cishow_pml4_window(struct pml4_window *window, struct aub_mem *mem) 612bf215546Sopenharmony_ci{ 613bf215546Sopenharmony_ci if (window->base.opened) { 614bf215546Sopenharmony_ci window->base.opened = false; 615bf215546Sopenharmony_ci return; 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci snprintf(window->base.name, sizeof(window->base.name), 619bf215546Sopenharmony_ci "4-Level page tables##%p", window); 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci list_inithead(&window->base.parent_link); 622bf215546Sopenharmony_ci window->base.position = ImVec2(-1, -1); 623bf215546Sopenharmony_ci window->base.size = ImVec2(500, 600); 624bf215546Sopenharmony_ci window->base.opened = true; 625bf215546Sopenharmony_ci window->base.display = display_pml4_window; 626bf215546Sopenharmony_ci window->base.destroy = destroy_window_noop; 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci window->mem = mem; 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci list_addtail(&window->base.link, &context.windows); 631bf215546Sopenharmony_ci} 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ci/* Batch decoding windows */ 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_cistatic void 636bf215546Sopenharmony_cidisplay_decode_options(struct aub_viewer_decode_cfg *cfg) 637bf215546Sopenharmony_ci{ 638bf215546Sopenharmony_ci char name[40]; 639bf215546Sopenharmony_ci snprintf(name, sizeof(name), "command filter##%p", &cfg->command_filter); 640bf215546Sopenharmony_ci cfg->command_filter.Draw(name); ImGui::SameLine(); 641bf215546Sopenharmony_ci snprintf(name, sizeof(name), "field filter##%p", &cfg->field_filter); 642bf215546Sopenharmony_ci cfg->field_filter.Draw(name); ImGui::SameLine(); 643bf215546Sopenharmony_ci if (ImGui::Button("Dwords")) cfg->show_dwords ^= 1; 644bf215546Sopenharmony_ci} 645bf215546Sopenharmony_ci 646bf215546Sopenharmony_cistatic void 647bf215546Sopenharmony_cibatch_display_shader(void *user_data, const char *shader_desc, uint64_t address) 648bf215546Sopenharmony_ci{ 649bf215546Sopenharmony_ci struct batch_window *window = (struct batch_window *) user_data; 650bf215546Sopenharmony_ci struct shader_window *shader_window = 651bf215546Sopenharmony_ci new_shader_window(&window->mem, address, shader_desc); 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci list_add(&shader_window->base.parent_link, &window->base.children_windows); 654bf215546Sopenharmony_ci} 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_cistatic void 657bf215546Sopenharmony_cibatch_display_urb(void *user_data, const struct aub_decode_urb_stage_state *stages) 658bf215546Sopenharmony_ci{ 659bf215546Sopenharmony_ci struct batch_window *window = (struct batch_window *) user_data; 660bf215546Sopenharmony_ci struct urb_window *urb_window = new_urb_window(&window->decode_ctx, 0); 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_ci list_add(&urb_window->base.parent_link, &window->base.children_windows); 663bf215546Sopenharmony_ci} 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_cistatic void 666bf215546Sopenharmony_cibatch_edit_address(void *user_data, uint64_t address, uint32_t len) 667bf215546Sopenharmony_ci{ 668bf215546Sopenharmony_ci struct batch_window *window = (struct batch_window *) user_data; 669bf215546Sopenharmony_ci struct edit_window *edit_window = 670bf215546Sopenharmony_ci new_edit_window(&window->mem, address, len); 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci list_add(&edit_window->base.parent_link, &window->base.children_windows); 673bf215546Sopenharmony_ci} 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_cistatic struct intel_batch_decode_bo 676bf215546Sopenharmony_cibatch_get_bo(void *user_data, bool ppgtt, uint64_t address) 677bf215546Sopenharmony_ci{ 678bf215546Sopenharmony_ci struct batch_window *window = (struct batch_window *) user_data; 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci if (window->uses_ppgtt && ppgtt) 681bf215546Sopenharmony_ci return aub_mem_get_ppgtt_bo(&window->mem, address); 682bf215546Sopenharmony_ci else 683bf215546Sopenharmony_ci return aub_mem_get_ggtt_bo(&window->mem, address); 684bf215546Sopenharmony_ci} 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_cistatic void 687bf215546Sopenharmony_ciupdate_batch_window(struct batch_window *window, bool reset, int exec_idx) 688bf215546Sopenharmony_ci{ 689bf215546Sopenharmony_ci if (reset) 690bf215546Sopenharmony_ci aub_mem_fini(&window->mem); 691bf215546Sopenharmony_ci aub_mem_init(&window->mem); 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci window->exec_idx = MAX2(MIN2(context.file->n_execs - 1, exec_idx), 0); 694bf215546Sopenharmony_ci update_mem_for_exec(&window->mem, context.file, window->exec_idx); 695bf215546Sopenharmony_ci} 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_cistatic void 698bf215546Sopenharmony_cidisplay_batch_ring_write(void *user_data, enum drm_i915_gem_engine_class engine, 699bf215546Sopenharmony_ci const void *data, uint32_t data_len) 700bf215546Sopenharmony_ci{ 701bf215546Sopenharmony_ci struct batch_window *window = (struct batch_window *) user_data; 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci window->uses_ppgtt = false; 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ci aub_viewer_render_batch(&window->decode_ctx, data, data_len, 0, false); 706bf215546Sopenharmony_ci} 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_cistatic void 709bf215546Sopenharmony_cidisplay_batch_execlist_write(void *user_data, 710bf215546Sopenharmony_ci enum drm_i915_gem_engine_class engine, 711bf215546Sopenharmony_ci uint64_t context_descriptor) 712bf215546Sopenharmony_ci{ 713bf215546Sopenharmony_ci struct batch_window *window = (struct batch_window *) user_data; 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci const uint32_t pphwsp_size = 4096; 716bf215546Sopenharmony_ci uint32_t pphwsp_addr = context_descriptor & 0xfffff000; 717bf215546Sopenharmony_ci struct intel_batch_decode_bo pphwsp_bo = 718bf215546Sopenharmony_ci aub_mem_get_ggtt_bo(&window->mem, pphwsp_addr); 719bf215546Sopenharmony_ci uint32_t *context_img = (uint32_t *)((uint8_t *)pphwsp_bo.map + 720bf215546Sopenharmony_ci (pphwsp_addr - pphwsp_bo.addr) + 721bf215546Sopenharmony_ci pphwsp_size); 722bf215546Sopenharmony_ci 723bf215546Sopenharmony_ci uint32_t ring_buffer_head = context_img[5]; 724bf215546Sopenharmony_ci uint32_t ring_buffer_tail = context_img[7]; 725bf215546Sopenharmony_ci uint32_t ring_buffer_start = context_img[9]; 726bf215546Sopenharmony_ci uint32_t ring_buffer_length = (context_img[11] & 0x1ff000) + 4096; 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_ci window->mem.pml4 = (uint64_t)context_img[49] << 32 | context_img[51]; 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci struct intel_batch_decode_bo ring_bo = 731bf215546Sopenharmony_ci aub_mem_get_ggtt_bo(&window->mem, ring_buffer_start); 732bf215546Sopenharmony_ci assert(ring_bo.size > 0); 733bf215546Sopenharmony_ci void *commands = (uint8_t *)ring_bo.map + (ring_buffer_start - ring_bo.addr) + ring_buffer_head; 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_ci window->uses_ppgtt = true; 736bf215546Sopenharmony_ci 737bf215546Sopenharmony_ci window->decode_ctx.engine = engine; 738bf215546Sopenharmony_ci aub_viewer_render_batch(&window->decode_ctx, commands, 739bf215546Sopenharmony_ci MIN2(ring_buffer_tail - ring_buffer_head, ring_buffer_length), 740bf215546Sopenharmony_ci ring_buffer_start + ring_buffer_head, true); 741bf215546Sopenharmony_ci} 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_cistatic void 744bf215546Sopenharmony_cidisplay_batch_window(struct window *win) 745bf215546Sopenharmony_ci{ 746bf215546Sopenharmony_ci struct batch_window *window = (struct batch_window *) win; 747bf215546Sopenharmony_ci 748bf215546Sopenharmony_ci ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() / (2 * 2)); 749bf215546Sopenharmony_ci if (window_has_ctrl_key('f')) ImGui::SetKeyboardFocusHere(); 750bf215546Sopenharmony_ci display_decode_options(&window->decode_cfg); 751bf215546Sopenharmony_ci ImGui::PopItemWidth(); 752bf215546Sopenharmony_ci 753bf215546Sopenharmony_ci if (ImGui::InputInt("Execbuf", &window->exec_idx)) 754bf215546Sopenharmony_ci update_batch_window(window, true, window->exec_idx); 755bf215546Sopenharmony_ci 756bf215546Sopenharmony_ci if (window_has_ctrl_key('p')) 757bf215546Sopenharmony_ci update_batch_window(window, true, window->exec_idx - 1); 758bf215546Sopenharmony_ci if (window_has_ctrl_key('n')) 759bf215546Sopenharmony_ci update_batch_window(window, true, window->exec_idx + 1); 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci ImGui::Text("execbuf %i", window->exec_idx); 762bf215546Sopenharmony_ci if (ImGui::Button("Show PPGTT")) { show_pml4_window(&window->pml4_window, &window->mem); } 763bf215546Sopenharmony_ci 764bf215546Sopenharmony_ci ImGui::BeginChild(ImGui::GetID("##block")); 765bf215546Sopenharmony_ci 766bf215546Sopenharmony_ci struct aub_read read = {}; 767bf215546Sopenharmony_ci read.user_data = window; 768bf215546Sopenharmony_ci read.ring_write = display_batch_ring_write; 769bf215546Sopenharmony_ci read.execlist_write = display_batch_execlist_write; 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci const uint8_t *iter = context.file->execs[window->exec_idx].start; 772bf215546Sopenharmony_ci while (iter < context.file->execs[window->exec_idx].end) { 773bf215546Sopenharmony_ci iter += aub_read_command(&read, iter, 774bf215546Sopenharmony_ci context.file->execs[window->exec_idx].end - iter); 775bf215546Sopenharmony_ci } 776bf215546Sopenharmony_ci 777bf215546Sopenharmony_ci ImGui::EndChild(); 778bf215546Sopenharmony_ci} 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_cistatic void 781bf215546Sopenharmony_cidestroy_batch_window(struct window *win) 782bf215546Sopenharmony_ci{ 783bf215546Sopenharmony_ci struct batch_window *window = (struct batch_window *) win; 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci aub_mem_fini(&window->mem); 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci /* This works because children windows are inserted at the back of the 788bf215546Sopenharmony_ci * list, ensuring the deletion loop goes through the children after calling 789bf215546Sopenharmony_ci * this function. 790bf215546Sopenharmony_ci */ 791bf215546Sopenharmony_ci list_for_each_entry(struct window, child_window, 792bf215546Sopenharmony_ci &window->base.children_windows, parent_link) 793bf215546Sopenharmony_ci child_window->opened = false; 794bf215546Sopenharmony_ci window->pml4_window.base.opened = false; 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_ci free(window); 797bf215546Sopenharmony_ci} 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_cistatic void 800bf215546Sopenharmony_cinew_batch_window(int exec_idx) 801bf215546Sopenharmony_ci{ 802bf215546Sopenharmony_ci struct batch_window *window = xtzalloc(*window); 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci snprintf(window->base.name, sizeof(window->base.name), 805bf215546Sopenharmony_ci "Batch view##%p", window); 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci list_inithead(&window->base.parent_link); 808bf215546Sopenharmony_ci list_inithead(&window->base.children_windows); 809bf215546Sopenharmony_ci window->base.position = ImVec2(-1, -1); 810bf215546Sopenharmony_ci window->base.size = ImVec2(600, 700); 811bf215546Sopenharmony_ci window->base.opened = true; 812bf215546Sopenharmony_ci window->base.display = display_batch_window; 813bf215546Sopenharmony_ci window->base.destroy = destroy_batch_window; 814bf215546Sopenharmony_ci 815bf215546Sopenharmony_ci window->collapsed = true; 816bf215546Sopenharmony_ci window->decode_cfg = aub_viewer_decode_cfg(); 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci aub_viewer_decode_ctx_init(&window->decode_ctx, 819bf215546Sopenharmony_ci &context.cfg, 820bf215546Sopenharmony_ci &window->decode_cfg, 821bf215546Sopenharmony_ci &context.file->devinfo, 822bf215546Sopenharmony_ci context.file->spec, 823bf215546Sopenharmony_ci batch_get_bo, 824bf215546Sopenharmony_ci NULL, 825bf215546Sopenharmony_ci window); 826bf215546Sopenharmony_ci window->decode_ctx.display_shader = batch_display_shader; 827bf215546Sopenharmony_ci window->decode_ctx.display_urb = batch_display_urb; 828bf215546Sopenharmony_ci window->decode_ctx.edit_address = batch_edit_address; 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ci update_batch_window(window, false, exec_idx); 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci list_addtail(&window->base.link, &context.windows); 833bf215546Sopenharmony_ci} 834bf215546Sopenharmony_ci 835bf215546Sopenharmony_ci/**/ 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_cistatic void 838bf215546Sopenharmony_cidisplay_registers_window(struct window *win) 839bf215546Sopenharmony_ci{ 840bf215546Sopenharmony_ci static struct ImGuiTextFilter filter; 841bf215546Sopenharmony_ci if (window_has_ctrl_key('f')) ImGui::SetKeyboardFocusHere(); 842bf215546Sopenharmony_ci filter.Draw(); 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ci ImGui::BeginChild(ImGui::GetID("##block")); 845bf215546Sopenharmony_ci hash_table_foreach(context.file->spec->registers_by_name, entry) { 846bf215546Sopenharmony_ci struct intel_group *reg = (struct intel_group *) entry->data; 847bf215546Sopenharmony_ci if (filter.PassFilter(reg->name) && 848bf215546Sopenharmony_ci ImGui::CollapsingHeader(reg->name)) { 849bf215546Sopenharmony_ci const struct intel_field *field = reg->fields; 850bf215546Sopenharmony_ci while (field) { 851bf215546Sopenharmony_ci ImGui::Text("%s : %i -> %i\n", field->name, field->start, field->end); 852bf215546Sopenharmony_ci field = field->next; 853bf215546Sopenharmony_ci } 854bf215546Sopenharmony_ci } 855bf215546Sopenharmony_ci } 856bf215546Sopenharmony_ci ImGui::EndChild(); 857bf215546Sopenharmony_ci} 858bf215546Sopenharmony_ci 859bf215546Sopenharmony_cistatic void 860bf215546Sopenharmony_cishow_register_window(void) 861bf215546Sopenharmony_ci{ 862bf215546Sopenharmony_ci struct window *window = &context.registers_window; 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_ci if (window->opened) { 865bf215546Sopenharmony_ci window->opened = false; 866bf215546Sopenharmony_ci return; 867bf215546Sopenharmony_ci } 868bf215546Sopenharmony_ci 869bf215546Sopenharmony_ci snprintf(window->name, sizeof(window->name), "Registers"); 870bf215546Sopenharmony_ci 871bf215546Sopenharmony_ci list_inithead(&window->parent_link); 872bf215546Sopenharmony_ci window->position = ImVec2(-1, -1); 873bf215546Sopenharmony_ci window->size = ImVec2(200, 400); 874bf215546Sopenharmony_ci window->opened = true; 875bf215546Sopenharmony_ci window->display = display_registers_window; 876bf215546Sopenharmony_ci window->destroy = destroy_window_noop; 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci list_addtail(&window->link, &context.windows); 879bf215546Sopenharmony_ci} 880bf215546Sopenharmony_ci 881bf215546Sopenharmony_cistatic void 882bf215546Sopenharmony_cidisplay_commands_window(struct window *win) 883bf215546Sopenharmony_ci{ 884bf215546Sopenharmony_ci static struct ImGuiTextFilter cmd_filter; 885bf215546Sopenharmony_ci if (window_has_ctrl_key('f')) ImGui::SetKeyboardFocusHere(); 886bf215546Sopenharmony_ci cmd_filter.Draw("name filter"); 887bf215546Sopenharmony_ci static struct ImGuiTextFilter field_filter; 888bf215546Sopenharmony_ci field_filter.Draw("field filter"); 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci static char opcode_str[9] = { 0, }; 891bf215546Sopenharmony_ci ImGui::InputText("opcode filter", opcode_str, sizeof(opcode_str), 892bf215546Sopenharmony_ci ImGuiInputTextFlags_CharsHexadecimal); 893bf215546Sopenharmony_ci size_t opcode_len = strlen(opcode_str); 894bf215546Sopenharmony_ci uint64_t opcode = strtol(opcode_str, NULL, 16); 895bf215546Sopenharmony_ci 896bf215546Sopenharmony_ci static bool show_dwords = true; 897bf215546Sopenharmony_ci if (ImGui::Button("Dwords")) show_dwords ^= 1; 898bf215546Sopenharmony_ci 899bf215546Sopenharmony_ci ImGui::BeginChild(ImGui::GetID("##block")); 900bf215546Sopenharmony_ci hash_table_foreach(context.file->spec->commands, entry) { 901bf215546Sopenharmony_ci struct intel_group *cmd = (struct intel_group *) entry->data; 902bf215546Sopenharmony_ci if ((cmd_filter.PassFilter(cmd->name) && 903bf215546Sopenharmony_ci (opcode_len == 0 || (opcode & cmd->opcode_mask) == cmd->opcode)) && 904bf215546Sopenharmony_ci ImGui::CollapsingHeader(cmd->name)) { 905bf215546Sopenharmony_ci const struct intel_field *field = cmd->fields; 906bf215546Sopenharmony_ci int32_t last_dword = -1; 907bf215546Sopenharmony_ci while (field) { 908bf215546Sopenharmony_ci if (show_dwords && field->start / 32 != last_dword) { 909bf215546Sopenharmony_ci for (last_dword = MAX2(0, last_dword + 1); 910bf215546Sopenharmony_ci last_dword < field->start / 32; last_dword++) { 911bf215546Sopenharmony_ci ImGui::TextColored(context.cfg.dwords_color, 912bf215546Sopenharmony_ci "Dword %d", last_dword); 913bf215546Sopenharmony_ci } 914bf215546Sopenharmony_ci ImGui::TextColored(context.cfg.dwords_color, "Dword %d", last_dword); 915bf215546Sopenharmony_ci } 916bf215546Sopenharmony_ci if (field_filter.PassFilter(field->name)) 917bf215546Sopenharmony_ci ImGui::Text("%s : %i -> %i\n", field->name, field->start, field->end); 918bf215546Sopenharmony_ci field = field->next; 919bf215546Sopenharmony_ci } 920bf215546Sopenharmony_ci } 921bf215546Sopenharmony_ci } 922bf215546Sopenharmony_ci hash_table_foreach(context.file->spec->structs, entry) { 923bf215546Sopenharmony_ci struct intel_group *cmd = (struct intel_group *) entry->data; 924bf215546Sopenharmony_ci if (cmd_filter.PassFilter(cmd->name) && opcode_len == 0 && 925bf215546Sopenharmony_ci ImGui::CollapsingHeader(cmd->name)) { 926bf215546Sopenharmony_ci const struct intel_field *field = cmd->fields; 927bf215546Sopenharmony_ci int32_t last_dword = -1; 928bf215546Sopenharmony_ci while (field) { 929bf215546Sopenharmony_ci if (show_dwords && field->start / 32 != last_dword) { 930bf215546Sopenharmony_ci last_dword = field->start / 32; 931bf215546Sopenharmony_ci ImGui::TextColored(context.cfg.dwords_color, 932bf215546Sopenharmony_ci "Dword %d", last_dword); 933bf215546Sopenharmony_ci } 934bf215546Sopenharmony_ci if (field_filter.PassFilter(field->name)) 935bf215546Sopenharmony_ci ImGui::Text("%s : %i -> %i\n", field->name, field->start, field->end); 936bf215546Sopenharmony_ci field = field->next; 937bf215546Sopenharmony_ci } 938bf215546Sopenharmony_ci } 939bf215546Sopenharmony_ci } 940bf215546Sopenharmony_ci ImGui::EndChild(); 941bf215546Sopenharmony_ci} 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_cistatic void 944bf215546Sopenharmony_cishow_commands_window(void) 945bf215546Sopenharmony_ci{ 946bf215546Sopenharmony_ci struct window *window = &context.commands_window; 947bf215546Sopenharmony_ci 948bf215546Sopenharmony_ci if (window->opened) { 949bf215546Sopenharmony_ci window->opened = false; 950bf215546Sopenharmony_ci return; 951bf215546Sopenharmony_ci } 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ci snprintf(window->name, sizeof(window->name), "Commands & structs"); 954bf215546Sopenharmony_ci 955bf215546Sopenharmony_ci list_inithead(&window->parent_link); 956bf215546Sopenharmony_ci window->position = ImVec2(-1, -1); 957bf215546Sopenharmony_ci window->size = ImVec2(300, 400); 958bf215546Sopenharmony_ci window->opened = true; 959bf215546Sopenharmony_ci window->display = display_commands_window; 960bf215546Sopenharmony_ci window->destroy = destroy_window_noop; 961bf215546Sopenharmony_ci 962bf215546Sopenharmony_ci list_addtail(&window->link, &context.windows); 963bf215546Sopenharmony_ci} 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci/* Main window */ 966bf215546Sopenharmony_ci 967bf215546Sopenharmony_cistatic const char * 968bf215546Sopenharmony_cihuman_size(size_t size) 969bf215546Sopenharmony_ci{ 970bf215546Sopenharmony_ci unsigned divisions = 0; 971bf215546Sopenharmony_ci double v = size; 972bf215546Sopenharmony_ci double divider = 1024; 973bf215546Sopenharmony_ci while (v >= divider) { 974bf215546Sopenharmony_ci v /= divider; 975bf215546Sopenharmony_ci divisions++; 976bf215546Sopenharmony_ci } 977bf215546Sopenharmony_ci 978bf215546Sopenharmony_ci static const char *units[] = { "Bytes", "Kilobytes", "Megabytes", "Gigabytes" }; 979bf215546Sopenharmony_ci static char result[20]; 980bf215546Sopenharmony_ci snprintf(result, sizeof(result), "%.2f %s", 981bf215546Sopenharmony_ci v, divisions >= ARRAY_SIZE(units) ? "Too much!" : units[divisions]); 982bf215546Sopenharmony_ci return result; 983bf215546Sopenharmony_ci} 984bf215546Sopenharmony_ci 985bf215546Sopenharmony_cistatic void 986bf215546Sopenharmony_cidisplay_aubfile_window(struct window *win) 987bf215546Sopenharmony_ci{ 988bf215546Sopenharmony_ci ImGuiColorEditFlags cflags = (ImGuiColorEditFlags_NoAlpha | 989bf215546Sopenharmony_ci ImGuiColorEditFlags_NoLabel | 990bf215546Sopenharmony_ci ImGuiColorEditFlags_NoInputs); 991bf215546Sopenharmony_ci struct aub_viewer_cfg *cfg = &context.cfg; 992bf215546Sopenharmony_ci 993bf215546Sopenharmony_ci ImGui::ColorEdit3("background", (float *)&cfg->clear_color, cflags); ImGui::SameLine(); 994bf215546Sopenharmony_ci ImGui::ColorEdit3("missing", (float *)&cfg->missing_color, cflags); ImGui::SameLine(); 995bf215546Sopenharmony_ci ImGui::ColorEdit3("error", (float *)&cfg->error_color, cflags); ImGui::SameLine(); 996bf215546Sopenharmony_ci ImGui::ColorEdit3("highlight", (float *)&cfg->highlight_color, cflags); ImGui::SameLine(); 997bf215546Sopenharmony_ci ImGui::ColorEdit3("dwords", (float *)&cfg->dwords_color, cflags); ImGui::SameLine(); 998bf215546Sopenharmony_ci ImGui::ColorEdit3("booleans", (float *)&cfg->boolean_color, cflags); ImGui::SameLine(); 999bf215546Sopenharmony_ci 1000bf215546Sopenharmony_ci if (ImGui::Button("Commands list") || has_ctrl_key('c')) { show_commands_window(); } ImGui::SameLine(); 1001bf215546Sopenharmony_ci if (ImGui::Button("Registers list") || has_ctrl_key('r')) { show_register_window(); } ImGui::SameLine(); 1002bf215546Sopenharmony_ci if (ImGui::Button("Help") || has_ctrl_key('h')) { ImGui::OpenPopup("Help"); } 1003bf215546Sopenharmony_ci 1004bf215546Sopenharmony_ci if (ImGui::Button("New batch window") || has_ctrl_key('b')) { new_batch_window(0); } 1005bf215546Sopenharmony_ci 1006bf215546Sopenharmony_ci ImGui::Text("File name: %s", context.input_file); 1007bf215546Sopenharmony_ci ImGui::Text("File size: %s", human_size(context.file->end - context.file->map)); 1008bf215546Sopenharmony_ci ImGui::Text("Execbufs %u", context.file->n_execs); 1009bf215546Sopenharmony_ci ImGui::Text("PCI ID: 0x%x", context.file->pci_id); 1010bf215546Sopenharmony_ci ImGui::Text("Application name: %s", context.file->app_name); 1011bf215546Sopenharmony_ci ImGui::Text("%s", context.file->devinfo.name); 1012bf215546Sopenharmony_ci 1013bf215546Sopenharmony_ci ImGui::SetNextWindowContentWidth(500); 1014bf215546Sopenharmony_ci if (ImGui::BeginPopupModal("Help", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { 1015bf215546Sopenharmony_ci ImGui::Text("Some global keybindings:"); 1016bf215546Sopenharmony_ci ImGui::Separator(); 1017bf215546Sopenharmony_ci 1018bf215546Sopenharmony_ci static const char *texts[] = { 1019bf215546Sopenharmony_ci "Ctrl-h", "show this screen", 1020bf215546Sopenharmony_ci "Ctrl-c", "show commands list", 1021bf215546Sopenharmony_ci "Ctrl-r", "show registers list", 1022bf215546Sopenharmony_ci "Ctrl-b", "new batch window", 1023bf215546Sopenharmony_ci "Ctrl-p/n", "switch to previous/next batch buffer", 1024bf215546Sopenharmony_ci "Ctrl-Tab", "switch focus between window", 1025bf215546Sopenharmony_ci "Ctrl-left/right", "align window to the side of the screen", 1026bf215546Sopenharmony_ci }; 1027bf215546Sopenharmony_ci float align = 0.0f; 1028bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(texts); i += 2) 1029bf215546Sopenharmony_ci align = MAX2(align, ImGui::CalcTextSize(texts[i]).x); 1030bf215546Sopenharmony_ci align += ImGui::GetStyle().WindowPadding.x + 10; 1031bf215546Sopenharmony_ci 1032bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(texts); i += 2) { 1033bf215546Sopenharmony_ci ImGui::Text("%s", texts[i]); ImGui::SameLine(align); ImGui::Text("%s", texts[i + 1]); 1034bf215546Sopenharmony_ci } 1035bf215546Sopenharmony_ci 1036bf215546Sopenharmony_ci if (ImGui::Button("Done") || ImGui::IsKeyPressed(ImGuiKey_Escape)) 1037bf215546Sopenharmony_ci ImGui::CloseCurrentPopup(); 1038bf215546Sopenharmony_ci ImGui::EndPopup(); 1039bf215546Sopenharmony_ci } 1040bf215546Sopenharmony_ci} 1041bf215546Sopenharmony_ci 1042bf215546Sopenharmony_cistatic void 1043bf215546Sopenharmony_cishow_aubfile_window(void) 1044bf215546Sopenharmony_ci{ 1045bf215546Sopenharmony_ci struct window *window = &context.file_window; 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci if (window->opened) 1048bf215546Sopenharmony_ci return; 1049bf215546Sopenharmony_ci 1050bf215546Sopenharmony_ci snprintf(window->name, sizeof(window->name), 1051bf215546Sopenharmony_ci "Aubinator Viewer: Intel AUB file decoder/editor"); 1052bf215546Sopenharmony_ci 1053bf215546Sopenharmony_ci list_inithead(&window->parent_link); 1054bf215546Sopenharmony_ci window->size = ImVec2(-1, 250); 1055bf215546Sopenharmony_ci window->position = ImVec2(0, 0); 1056bf215546Sopenharmony_ci window->opened = true; 1057bf215546Sopenharmony_ci window->display = display_aubfile_window; 1058bf215546Sopenharmony_ci window->destroy = NULL; 1059bf215546Sopenharmony_ci 1060bf215546Sopenharmony_ci list_addtail(&window->link, &context.windows); 1061bf215546Sopenharmony_ci} 1062bf215546Sopenharmony_ci 1063bf215546Sopenharmony_ci/* Main redrawing */ 1064bf215546Sopenharmony_ci 1065bf215546Sopenharmony_cistatic void 1066bf215546Sopenharmony_cidisplay_windows(void) 1067bf215546Sopenharmony_ci{ 1068bf215546Sopenharmony_ci /* Start by disposing closed windows, we don't want to destroy windows that 1069bf215546Sopenharmony_ci * have already been scheduled to be painted. So destroy always happens on 1070bf215546Sopenharmony_ci * the next draw cycle, prior to any drawing. 1071bf215546Sopenharmony_ci */ 1072bf215546Sopenharmony_ci list_for_each_entry_safe(struct window, window, &context.windows, link) { 1073bf215546Sopenharmony_ci if (window->opened) 1074bf215546Sopenharmony_ci continue; 1075bf215546Sopenharmony_ci 1076bf215546Sopenharmony_ci /* Can't close this one. */ 1077bf215546Sopenharmony_ci if (window == &context.file_window) { 1078bf215546Sopenharmony_ci window->opened = true; 1079bf215546Sopenharmony_ci continue; 1080bf215546Sopenharmony_ci } 1081bf215546Sopenharmony_ci 1082bf215546Sopenharmony_ci list_del(&window->link); 1083bf215546Sopenharmony_ci list_del(&window->parent_link); 1084bf215546Sopenharmony_ci if (window->destroy) 1085bf215546Sopenharmony_ci window->destroy(window); 1086bf215546Sopenharmony_ci } 1087bf215546Sopenharmony_ci 1088bf215546Sopenharmony_ci list_for_each_entry_safe(struct window, window, &context.windows, link) { 1089bf215546Sopenharmony_ci ImGui::SetNextWindowPos(window->position, ImGuiCond_FirstUseEver); 1090bf215546Sopenharmony_ci ImGui::SetNextWindowSize(window->size, ImGuiCond_FirstUseEver); 1091bf215546Sopenharmony_ci if (ImGui::Begin(window->name, &window->opened)) { 1092bf215546Sopenharmony_ci window->display(window); 1093bf215546Sopenharmony_ci window->position = ImGui::GetWindowPos(); 1094bf215546Sopenharmony_ci window->size = ImGui::GetWindowSize(); 1095bf215546Sopenharmony_ci } 1096bf215546Sopenharmony_ci if (window_has_ctrl_key('w')) 1097bf215546Sopenharmony_ci window->opened = false; 1098bf215546Sopenharmony_ci ImGui::End(); 1099bf215546Sopenharmony_ci } 1100bf215546Sopenharmony_ci} 1101bf215546Sopenharmony_ci 1102bf215546Sopenharmony_cistatic void 1103bf215546Sopenharmony_cirepaint_area(GtkGLArea *area, GdkGLContext *gdk_gl_context) 1104bf215546Sopenharmony_ci{ 1105bf215546Sopenharmony_ci ImGui_ImplOpenGL3_NewFrame(); 1106bf215546Sopenharmony_ci ImGui_ImplGtk3_NewFrame(); 1107bf215546Sopenharmony_ci ImGui::NewFrame(); 1108bf215546Sopenharmony_ci 1109bf215546Sopenharmony_ci display_windows(); 1110bf215546Sopenharmony_ci 1111bf215546Sopenharmony_ci ImGui::EndFrame(); 1112bf215546Sopenharmony_ci ImGui::Render(); 1113bf215546Sopenharmony_ci 1114bf215546Sopenharmony_ci glClearColor(context.cfg.clear_color.Value.x, 1115bf215546Sopenharmony_ci context.cfg.clear_color.Value.y, 1116bf215546Sopenharmony_ci context.cfg.clear_color.Value.z, 1.0); 1117bf215546Sopenharmony_ci glClear(GL_COLOR_BUFFER_BIT); 1118bf215546Sopenharmony_ci ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); 1119bf215546Sopenharmony_ci} 1120bf215546Sopenharmony_ci 1121bf215546Sopenharmony_cistatic void 1122bf215546Sopenharmony_cirealize_area(GtkGLArea *area) 1123bf215546Sopenharmony_ci{ 1124bf215546Sopenharmony_ci ImGui::CreateContext(); 1125bf215546Sopenharmony_ci ImGui_ImplGtk3_Init(GTK_WIDGET(area), true); 1126bf215546Sopenharmony_ci ImGui_ImplOpenGL3_Init("#version 130"); 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_ci list_inithead(&context.windows); 1129bf215546Sopenharmony_ci 1130bf215546Sopenharmony_ci ImGui::StyleColorsDark(); 1131bf215546Sopenharmony_ci context.cfg = aub_viewer_cfg(); 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci ImGuiIO& io = ImGui::GetIO(); 1134bf215546Sopenharmony_ci io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; 1135bf215546Sopenharmony_ci} 1136bf215546Sopenharmony_ci 1137bf215546Sopenharmony_cistatic void 1138bf215546Sopenharmony_ciunrealize_area(GtkGLArea *area) 1139bf215546Sopenharmony_ci{ 1140bf215546Sopenharmony_ci gtk_gl_area_make_current(area); 1141bf215546Sopenharmony_ci 1142bf215546Sopenharmony_ci ImGui_ImplOpenGL3_Shutdown(); 1143bf215546Sopenharmony_ci ImGui_ImplGtk3_Shutdown(); 1144bf215546Sopenharmony_ci ImGui::DestroyContext(); 1145bf215546Sopenharmony_ci} 1146bf215546Sopenharmony_ci 1147bf215546Sopenharmony_cistatic void 1148bf215546Sopenharmony_cisize_allocate_area(GtkGLArea *area, 1149bf215546Sopenharmony_ci GdkRectangle *allocation, 1150bf215546Sopenharmony_ci gpointer user_data) 1151bf215546Sopenharmony_ci{ 1152bf215546Sopenharmony_ci if (!gtk_widget_get_realized(GTK_WIDGET(area))) 1153bf215546Sopenharmony_ci return; 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ci /* We want to catch only initial size allocate. */ 1156bf215546Sopenharmony_ci g_signal_handlers_disconnect_by_func(area, 1157bf215546Sopenharmony_ci (gpointer) size_allocate_area, 1158bf215546Sopenharmony_ci user_data); 1159bf215546Sopenharmony_ci show_aubfile_window(); 1160bf215546Sopenharmony_ci} 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_cistatic void 1163bf215546Sopenharmony_ciprint_help(const char *progname, FILE *file) 1164bf215546Sopenharmony_ci{ 1165bf215546Sopenharmony_ci fprintf(file, 1166bf215546Sopenharmony_ci "Usage: %s [OPTION]... FILE\n" 1167bf215546Sopenharmony_ci "Decode aub file contents from FILE.\n\n" 1168bf215546Sopenharmony_ci " --help display this help and exit\n" 1169bf215546Sopenharmony_ci " -x, --xml=DIR load hardware xml description from directory DIR\n", 1170bf215546Sopenharmony_ci progname); 1171bf215546Sopenharmony_ci} 1172bf215546Sopenharmony_ci 1173bf215546Sopenharmony_ciint main(int argc, char *argv[]) 1174bf215546Sopenharmony_ci{ 1175bf215546Sopenharmony_ci int c, i; 1176bf215546Sopenharmony_ci bool help = false; 1177bf215546Sopenharmony_ci const struct option aubinator_opts[] = { 1178bf215546Sopenharmony_ci { "help", no_argument, (int *) &help, true }, 1179bf215546Sopenharmony_ci { "xml", required_argument, NULL, 'x' }, 1180bf215546Sopenharmony_ci { NULL, 0, NULL, 0 } 1181bf215546Sopenharmony_ci }; 1182bf215546Sopenharmony_ci 1183bf215546Sopenharmony_ci memset(&context, 0, sizeof(context)); 1184bf215546Sopenharmony_ci 1185bf215546Sopenharmony_ci i = 0; 1186bf215546Sopenharmony_ci while ((c = getopt_long(argc, argv, "x:s:", aubinator_opts, &i)) != -1) { 1187bf215546Sopenharmony_ci switch (c) { 1188bf215546Sopenharmony_ci case 'x': 1189bf215546Sopenharmony_ci context.xml_path = strdup(optarg); 1190bf215546Sopenharmony_ci break; 1191bf215546Sopenharmony_ci default: 1192bf215546Sopenharmony_ci break; 1193bf215546Sopenharmony_ci } 1194bf215546Sopenharmony_ci } 1195bf215546Sopenharmony_ci 1196bf215546Sopenharmony_ci if (optind < argc) 1197bf215546Sopenharmony_ci context.input_file = argv[optind]; 1198bf215546Sopenharmony_ci 1199bf215546Sopenharmony_ci if (help || !context.input_file) { 1200bf215546Sopenharmony_ci print_help(argv[0], stderr); 1201bf215546Sopenharmony_ci exit(0); 1202bf215546Sopenharmony_ci } 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_ci context.file = aub_file_open(context.input_file); 1205bf215546Sopenharmony_ci 1206bf215546Sopenharmony_ci gtk_init(NULL, NULL); 1207bf215546Sopenharmony_ci 1208bf215546Sopenharmony_ci context.gtk_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 1209bf215546Sopenharmony_ci gtk_window_set_title(GTK_WINDOW(context.gtk_window), "Aubinator Viewer"); 1210bf215546Sopenharmony_ci g_signal_connect(context.gtk_window, "delete-event", G_CALLBACK(gtk_main_quit), NULL); 1211bf215546Sopenharmony_ci gtk_window_resize(GTK_WINDOW(context.gtk_window), 1280, 720); 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci GtkWidget* gl_area = gtk_gl_area_new(); 1214bf215546Sopenharmony_ci g_signal_connect(gl_area, "render", G_CALLBACK(repaint_area), NULL); 1215bf215546Sopenharmony_ci g_signal_connect(gl_area, "realize", G_CALLBACK(realize_area), NULL); 1216bf215546Sopenharmony_ci g_signal_connect(gl_area, "unrealize", G_CALLBACK(unrealize_area), NULL); 1217bf215546Sopenharmony_ci g_signal_connect(gl_area, "size_allocate", G_CALLBACK(size_allocate_area), NULL); 1218bf215546Sopenharmony_ci gtk_container_add(GTK_CONTAINER(context.gtk_window), gl_area); 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci gtk_widget_show_all(context.gtk_window); 1221bf215546Sopenharmony_ci 1222bf215546Sopenharmony_ci gtk_main(); 1223bf215546Sopenharmony_ci 1224bf215546Sopenharmony_ci free(context.xml_path); 1225bf215546Sopenharmony_ci 1226bf215546Sopenharmony_ci return EXIT_SUCCESS; 1227bf215546Sopenharmony_ci} 1228