USING_SDL :: OS == .LINUX || OS == .MACOS; USING_WINDOWS :: OS == .WINDOWS; #if !USING_SDL && !USING_WINDOWS #assert false "Invalid configuration"; // The arena and fixed_arena suites live in modules/Basic/tests and arrive with LOAD_TESTS // on the Basic import below. #if COMPILE_TESTS { #load "test/testing.jai"; #load "test/logger_tests.jai"; } #load "app/main.jai"; // entry point #load "app/app_ui.jai"; #load "app/viewer.jai"; #load "app/ocr_ui.jai"; #load "app/exit_shutdown.jai"; #load "base/circle_buffer.jai"; #load "base/debug.jai"; #load "base/fonts.jai"; #load "base/log_queue.jai"; #load "base/logger.jai"; #load "base/prune_files.jai"; #load "ui/imgui.jai"; #load "ui/imgui_keyboard.jai"; #load "ui/imgui_theme.jai"; #load "ui/imgui_theme_file.jai"; #load "ui/imgui_theme_registry.jai"; #load "ui/imgui_theme_editor.jai"; #load "ui/imgui_toast.jai"; #load "ui/imgui_exit_overlay.jai"; #import "Atomics"; #import "Basic"()(MEMORY_DEBUGGER=false,ARENA_DEBUG=DEBUG,LOAD_TESTS=COMPILE_TESTS); #import "Clipboard"; #import "String"; #import "Sort"; #import "Unicode"; #import "File"; #import "File_Utilities"; #import "Math"; #import "System"; #import "Thread"; #import "Hash_Table"; Shared_Channel :: #import "Shared_Memory_Channel"; #import "stb_image"; #import "stb_image_resize"; #import "Capture_File"; // the .mcap format, copied from D:\SnagitIndex\SnagitConverter #import "OCR"; #import "onnxruntime"; // Basic's arenas import Secure_Memory at its defaults; this import adds its test suite. using Secure_Memory :: #import "Secure_Memory"()(LOAD_TESTS=COMPILE_TESTS); Graphics_Backend :: enum s32 { Unknown :: 0; DX11; Vulkan; OpenGL; Metal; DX12; } graphics_backend_from_string :: (name: string) -> Graphics_Backend { if name == { case "vulkan"; return .Vulkan; case "opengl"; return .OpenGL; case "metal"; return .Metal; case "direct3d11"; return .DX11; case "direct3d12"; return .DX12; } assert(false, "Unknown Graphics_Backend!"); return .Unknown; } Memory_Usage :: struct { working_set: s64; virtual_memory: s64; peak_working_set: s64; peak_virtual_memory: s64; } perf: Perf; Perf :: struct { backend: Graphics_Backend; renderer_name: string; adapter_name: string; // e.g. "NVIDIA GeForce RTX 4070"; empty when the adapter could not be queried renderer_is_software: bool; time_to_first_frame_ms: float64; // See #WarpFirstStartup in graphics/DX11.jai. hw_device_ready_ms is measured from app.startup_time. started_on_warp: bool; startup_device_ms: float64; // D3D11CreateDevice for the startup device startup_swap_chain_ms: float64; // its swap chain and render target hw_device_create_ms: float64; hw_device_ready_ms: float64; hw_swap_ms: float64; memory_usage: Memory_Usage; frame_times: Circle_Buffer(Frame_Timing); } Frame_Timing :: struct { work: float32; // seconds from the start of app_frame to just before Present (doesn't include vsync or swapchain waits) delta: float32; // io.DeltaTime: wall time since the previous frame, vsync wait included } PERF_FRAME_TIME_HISTORY :: 1024; load_hardware_information :: () { { // Get CPU information: using cpu_info; physical_cpu_count = get_number_of_processors(.ALL_PHYSICAL); logical_cpu_count = get_number_of_processors(.ALL_LOGICAL); performance_cpu_count = get_number_of_processors(.PERFORMANCE_PHYSICAL); } #if OS == .WINDOWS windows_get_cpu_information(); } load_platform_information :: () { platform_load_platform_information(); } cpu_info: CPU_Info; CPU_Info :: struct { logical_cpu_count: s32; physical_cpu_count: s32; performance_cpu_count: s32; } CPUID_Type :: enum s32 { All :: 0; // All Logical CPUs Performance :: 1; Efficiency :: 2; // Top_Performance :: 64; // Typically two CPUs are marked with this value } platform: Platform; // Windows, MacOS, Linux app: App; App :: struct { frame_count: s64; startup_time: Apollo_Time; frame_time: Apollo_Time; win_scale: float32; minimized_to_tray: bool; was_minimized_to_tray: bool; // as of the last frame; main.jai drops stale input when it changes vsync_on: bool = true; sleep_on_fast_frame: bool = false; should_exit: bool = false; show_debug_panel: bool = DEBUG; show_logger_panel: bool = DEBUG; show_frame_time_graph: bool = DEBUG; show_style_editor: bool; minimize_to_tray_this_frame: bool; restore_window_this_frame: bool; is_master: bool; // Are we the first instance of this app launched? allow_multiple_instances: bool; // Skips the single-instance check, so a dev build can run beside an installed one. should_exit_early: bool; run_tests: bool; headless: bool; // -headless (or a no_crash_dialog build): no message boxes on failures, and run_tests exits when done exit_code: s32; // the process's exit code when the main loop ends last_window_restore_time: Apollo_Time; imgui_context: *ImGui.ImGuiContext; write_channel: Shared_Channel.Write_Channel; read_channel: Shared_Channel.Read_Channel; read_channel_fatal_errors: s32; // the first resets the queue, the second stops polling large_pages_allowed: bool; #if USING_WINDOWS { is_admin: bool; // running with elevated privileges? ui_global_clear_color: [4]float : .[0.45, 0.55, 0.60, 1.00]; } else #if USING_SDL { ui_global_clear_color: SDL_FColor = .{ r=0.45, g=0.55, b=0.60, a=1.0 }; } program_data_dir: string; // "/"; see app_program_data_dir() machine_name: string; username: string; args: []string; } #if USING_SDL { // This uses SDL3 and SDL_GPU ImGui :: #import "imgui-sdl"; #import "sdl3"; #import "freetype"; // Load the backend(s) you want. This *must* be #load because they might rely on other libraries. // In this case, sdl3_gpu3 relies on types from "sdl3", so by importing sdl3 and loading imgui, imgui // gets access to the types it needs. #load "backends/sdl3_gpu3.jai"; #load "freetype/freetype.jai"; #load "base/platform/sdl.jai"; #load "base/platform/platform_posix.jai"; #if OS == .LINUX { #load "base/platform/platform_linux.jai"; POSIX :: #import "POSIX"; } else #if OS == .MACOS { #load "base/platform/platform_macos.jai"; #load "base/platform/macos_bindings.jai"; #load "base/platform/macos_global_hotkeys.jai"; POSIX :: #import "POSIX"; } APP_TRAY_ICON_PATH :: "images/tray_icon.png"; } #if USING_WINDOWS { // This uses Win32 API directly and DX11 for graphics ImGui :: #import "imgui-dx11-win32"()(DEBUG = DEBUG); #import "d3d11"; #import "d3d_compiler"; #import "dxgi"; #import "Windows"; #import "Windows_Utf8"; #load "base/platform/platform_windows.jai"; #load "base/platform/win32_bindings.jai"; #load "graphics/DX11.jai"; APP_TRAY_ICON_PATH :: "images/tray_icon.ico"; } // The folder the app's data, logs and images live in: the executable's, or on macOS the one // holding the .app when run from the bundle, so replacing the bundle leaves the data alone. Ends in // a separator, as path_strip_filename does. Set by the first call, which the logger makes at startup. app_install_directory :: () -> string { if !app_install_directory_path { directory := path_strip_filename(get_path_of_running_executable(,, temp)); #if OS == .MACOS { BUNDLE_EXECUTABLE_FOLDER :: "/Contents/MacOS/"; if ends_with(directory, tprint(".app%", BUNDLE_EXECUTABLE_FOLDER)) { directory = path_strip_filename(slice(directory, 0, directory.count - BUNDLE_EXECUTABLE_FOLDER.count)); app_from_app_bundle = true; } } app_install_directory_path = copy_string(directory,, context.default_allocator); } return app_install_directory_path; } app_running_from_app_bundle :: () -> bool { app_install_directory(); return app_from_app_bundle; } #scope_file app_install_directory_path: string; app_from_app_bundle: bool; #scope_export get_app_tray_icon_path :: () -> string { push_allocator(temp); icon_path := tprint("%1%2", app_install_directory(), APP_TRAY_ICON_PATH); log("icon_path: %", icon_path); return icon_path; } APP_LOG_DIRECTORY :: #run -> string { return tprint("logs/%", VERSION); } APP_USER_SETTINGS_FILE_NAME :: "settings.config"; APP_USER_SETTINGS_VERSION :: 1; // A file at any version from this one through APP_USER_SETTINGS_VERSION is readable. Raise // APP_USER_SETTINGS_VERSION when an action is added to [hotkeys] or [global_hotkeys]; see // hotkeys_missing_lines. APP_USER_SETTINGS_OLDEST_READABLE_VERSION :: 1; APP_SHARED_MEMORY_CHANNEL_HEADER_SIZE :: 2; // 1 byte for message-or-done, 1 byte for the checksum. App_Shared_Memory_Tag :: enum u8 { Done :: 0; Bring_To_Front :: 1; } APP_SHARED_MEMORY_CHANNEL_BYTES :: 4096; // only one page? APP_WINDOW_TITLE :: #run -> string { append_debug := ifx DEBUG then " (DEBUG)\0" else " (RELEASE)\0"; git_info := ifx GIT_BRANCH != "master" && GIT_BRANCH != "main" then tprint(" %-%", GIT_BRANCH, GIT_HASH) else tprint(" %", GIT_HASH); return tprint("%1 %2%3%4", APP_NAME, VERSION, git_info, append_debug); } APP_TRAY_TOOLTIP_TEXT :: #run -> string { return ifx DEBUG tprint("% % (DEBUG)\0", APP_NAME, VERSION) else tprint("% %\0", APP_NAME, VERSION); } #if OS == .LINUX { clipboard_set_text :: (text: string) { ImGui.SetClipboardText(temp_c_string(text)); } } else { clipboard_set_text :: (text: string) { os_clipboard_set_text(text); } }