From 3e713b13a8d83465aa00b941fefc876538783060 Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 24 Jan 2026 21:07:33 +0300 Subject: [PATCH 01/15] Qt+WGPU --- .gitignore | 2 + CMakeLists.txt | 19 + Cargo.lock | 2446 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 24 + README.md | 5 + src/lib.rs | 169 +++ src/main.rs | 82 ++ ui/CMakeLists.txt | 14 + ui/Cargo.toml | 15 + ui/impl.cmake | 22 + ui/src/api.cxx | 57 + ui/src/api.hxx | 53 + ui/src/lib.rs | 48 + ui/src/main.cxx | 15 + ui/src/main_window.cxx | 27 + ui/src/main_window.hxx | 23 + ui/src/main_window.ui | 114 ++ ui/src/viewport.cxx | 74 ++ ui/src/viewport.hxx | 28 + 19 files changed, 3237 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 ui/CMakeLists.txt create mode 100644 ui/Cargo.toml create mode 100644 ui/impl.cmake create mode 100644 ui/src/api.cxx create mode 100644 ui/src/api.hxx create mode 100644 ui/src/lib.rs create mode 100644 ui/src/main.cxx create mode 100644 ui/src/main_window.cxx create mode 100644 ui/src/main_window.hxx create mode 100644 ui/src/main_window.ui create mode 100644 ui/src/viewport.cxx create mode 100644 ui/src/viewport.hxx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..82448cc --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f30e705 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.18) + +project(PROJECT-NAME VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 REQUIRED COMPONENTS Gui Widgets) +find_program(CARGO cargo REQUIRED) +set(CARGO_TARGET_DIR "${CMAKE_BINARY_DIR}/cargo") + +# KDE-specific +find_package(ECM REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) +find_package(KF6 REQUIRED COMPONENTS WidgetsAddons) + +qt_standard_project_setup() + +add_subdirectory(ui) diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..9db39c2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2446 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "PROJECT-NAME" +version = "0.1.0" +dependencies = [ + "glam", + "pollster", + "wgpu", + "winit", +] + +[[package]] +name = "PROJECT-NAME-impl" +version = "0.1.0" +dependencies = [ + "PROJECT-NAME", + "glam", + "pollster", + "raw-window-handle", + "wgpu", +] + +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.10.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2", +] + +[[package]] +name = "bumpalo" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.10.0", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.3", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glam" +version = "0.30.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9" + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.10.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" +dependencies = [ + "log", + "presser", + "thiserror 1.0.69", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.10.0", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "libc" +version = "0.2.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags 2.10.0", + "libc", + "redox_syscall 0.7.0", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memmap2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +dependencies = [ + "libc", +] + +[[package]] +name = "metal" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" +dependencies = [ + "bitflags 2.10.0", + "block", + "core-graphics-types 0.2.0", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "naga" +version = "27.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "hexf-parse", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash", + "spirv", + "thiserror 2.0.18", + "unicode-ident", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.10.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.10.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.10.0", + "block2", + "dispatch", + "libc", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "orbclient" +version = "0.3.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ad2c6bae700b7aa5d1cc30c59bdd3a1c180b09dbaea51e2ae2b8e1cf211fdd" +dependencies = [ + "libc", + "libredox", +] + +[[package]] +name = "ordered-float" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + +[[package]] +name = "quick-xml" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "range-alloc" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.10.0", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "syn" +version = "2.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-backend" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.3", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" +dependencies = [ + "bitflags 2.10.0", + "rustix 1.1.3", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.10.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5864c4b5b6064b06b1e8b74ead4a98a6c45a285fe7a0e784d24735f011fdb078" +dependencies = [ + "rustix 1.1.3", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wgpu" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" +dependencies = [ + "arrayvec", + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "27.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.10.0", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror 2.0.18", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "27.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.10.0", + "block", + "bytemuck", + "cfg-if", + "cfg_aliases", + "core-graphics-types 0.2.0", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.16.1", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "smallvec", + "thiserror 2.0.18", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows", + "windows-core", +] + +[[package]] +name = "wgpu-types" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" +dependencies = [ + "bitflags 2.10.0", + "bytemuck", + "js-sys", + "log", + "thiserror 2.0.18", + "web-sys", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winit" +version = "0.30.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.10.0", + "block2", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation 0.9.4", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 1.1.3", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.10.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "zerocopy" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0d64950 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,24 @@ +[workspace] +members = ["ui"] + +[package] +name = "PROJECT-NAME" +version = "0.1.0" +edition = "2024" + +[profile.dev] +panic = 'abort' + +[profile.dev.package."*"] +debug = false +opt-level = 3 + +[profile.test.package."*"] +debug = false +opt-level = 3 + +[dependencies] +glam = { version = "0.30.9" } +pollster = "0.4.0" +wgpu = "27.0.1" +winit = "0.30.12" diff --git a/README.md b/README.md new file mode 100644 index 0000000..a179901 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Qt6+WGPU skeleton program + +This example combines Qt6 GUI (C++) with WGPU rendering (Rust). It doesn’t do much of either but it’s the bridging what’s relevant. + +Currently only X11 (XCB) is supported but it should be easy to extend to other platforms. diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..2518f00 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,169 @@ +use std::error::Error; + +use glam::{UVec2, Vec4}; + +const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth16Unorm; +const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb; + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct RedrawArgs { + pub background: Vec4, +} + +pub struct Gpu { + device: wgpu::Device, + queue: wgpu::Queue, + surface: wgpu::Surface<'static>, +} + +pub struct Core { + device: wgpu::Device, + queue: wgpu::Queue, + surface: wgpu::Surface<'static>, + + depth: wgpu::Texture, +} + +impl Core { + pub fn new(gpu: Gpu, pixel_size: UVec2) -> Self { + let Gpu { + device, + queue, + surface, + } = gpu; + + let depth = Self::create_depth_buffer(&device, pixel_size); + queue.submit([]); // flush buffer updates + + Self::configure_surface(&surface, &device, pixel_size); + + Self { + device, + queue, + surface, + depth, + } + } + + fn render(&self, output: &wgpu::Texture, args: &RedrawArgs) { + let aspect = { + let size = output.size(); + let w = size.width as f32; + let h = size.height as f32; + w / h + }; + self.queue.submit([]); // flush buffer updates + + let view = output.create_view(&wgpu::TextureViewDescriptor::default()); + let depth_view = self + .depth + .create_view(&wgpu::TextureViewDescriptor::default()); + let mut encoder = self + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); + let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + depth_slice: None, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { + r: args.background.x.into(), + g: args.background.y.into(), + b: args.background.z.into(), + a: args.background.w.into(), + }), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &depth_view, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.), + store: wgpu::StoreOp::Discard, + }), + stencil_ops: None, + }), + ..Default::default() + }); + + drop(pass); + self.queue.submit(std::iter::once(encoder.finish())); + } + + fn create_depth_buffer(device: &wgpu::Device, pixel_size: UVec2) -> wgpu::Texture { + device.create_texture(&wgpu::TextureDescriptor { + label: Some("depth buffer"), + size: wgpu::Extent3d { + width: pixel_size.x, + height: pixel_size.y, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: DEPTH_FORMAT, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], + }) + } + + fn configure_surface(surface: &wgpu::Surface, device: &wgpu::Device, pixel_size: UVec2) { + surface.configure( + device, + &wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST, + format: OUTPUT_FORMAT, + width: pixel_size.x, + height: pixel_size.y, + present_mode: wgpu::PresentMode::Fifo, + alpha_mode: wgpu::CompositeAlphaMode::Auto, + view_formats: vec![], + desired_maximum_frame_latency: 2, + }, + ); + } + + /// Configures the renderer for a given target size. + pub fn configure(&mut self, pixel_size: UVec2) { + Self::configure_surface(&self.surface, &self.device, pixel_size); + self.depth = Self::create_depth_buffer(&self.device, pixel_size); + } + + /// Redraws the entire surface. + /// + /// [`Self::configure`] must be called at least once before this. + pub fn redraw(&mut self, args: &RedrawArgs) { + let output = self.surface.get_current_texture().unwrap(); + self.render(&output.texture, args); + output.present(); + } +} + +pub async fn init_gpu_inner( + make_surface: impl FnOnce(&wgpu::Instance) -> Result, E>, +) -> Result> { + let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor { + backends: wgpu::Backends::PRIMARY, + ..Default::default() + }); + let surface = make_surface(&instance)?; + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + compatible_surface: Some(&surface), + force_fallback_adapter: false, + }) + .await + .unwrap(); + let (device, queue) = adapter + .request_device(&wgpu::DeviceDescriptor::default()) + .await + .unwrap(); + Ok(Gpu { + device, + queue, + surface, + }) +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..aa0bec3 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,82 @@ +use std::sync::Arc; + +use PROJECT_NAME::{Core, RedrawArgs, init_gpu_inner}; +use glam::{uvec2, vec4}; +use winit::{ + application::ApplicationHandler, + event::WindowEvent, + event_loop::{ActiveEventLoop, ControlFlow, EventLoop}, + window::Window, +}; + +const TITLE: &str = "PROJECT NAME"; + +struct MainWindow { + window: Arc, + core: Core, +} + +impl MainWindow { + fn new(event_loop: &ActiveEventLoop) -> Self { + let window = event_loop + .create_window(Window::default_attributes().with_title(TITLE)) + .unwrap(); + let window = Arc::new(window); + let gpu = pollster::block_on(init_gpu_inner(|instance| { + instance.create_surface(Arc::clone(&window)) + })) + .unwrap(); + let core = Core::new(gpu, uvec2(1, 1)); + Self { window, core } + } + + fn event(&mut self, event_loop: &ActiveEventLoop, event: WindowEvent) { + match event { + WindowEvent::CloseRequested => event_loop.exit(), + WindowEvent::Resized(physical_size) => self + .core + .configure(uvec2(physical_size.width, physical_size.height)), + WindowEvent::RedrawRequested => self.core.redraw(&RedrawArgs { + background: vec4(0.05, 0.20, 0.85, 1.00), + }), + _ => {} + } + } +} + +struct Application { + main_window: Option, +} + +impl Application { + fn new() -> Self { + Self { main_window: None } + } +} + +impl ApplicationHandler for Application { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + self.main_window = Some(MainWindow::new(event_loop)); + } + + fn window_event( + &mut self, + event_loop: &ActiveEventLoop, + window_id: winit::window::WindowId, + event: WindowEvent, + ) { + let window = self + .main_window + .as_mut() + .expect("window must exist to recieve events"); + assert_eq!(window.window.id(), window_id); + window.event(event_loop, event); + } +} + +fn main() { + let event_loop = EventLoop::new().unwrap(); + event_loop.set_control_flow(ControlFlow::Wait); + let mut app = Application::new(); + event_loop.run_app(&mut app).unwrap(); +} diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt new file mode 100644 index 0000000..5c3f9f3 --- /dev/null +++ b/ui/CMakeLists.txt @@ -0,0 +1,14 @@ +include(impl.cmake) + +qt_add_executable(PROJECT-NAME + src/api.cxx + src/main.cxx + src/main_window.cxx + src/main_window.ui + src/viewport.cxx +) + +target_link_libraries(PROJECT-NAME PRIVATE Qt6::Gui Qt6::Widgets) +target_link_libraries(PROJECT-NAME PRIVATE KF6::WidgetsAddons) +target_link_libraries(PROJECT-NAME PRIVATE PROJECT_NAME_impl) +target_include_directories(PROJECT-NAME PRIVATE src) diff --git a/ui/Cargo.toml b/ui/Cargo.toml new file mode 100644 index 0000000..6565f4f --- /dev/null +++ b/ui/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "PROJECT-NAME-impl" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +PROJECT-NAME = {path = "../"} + +glam = { version = "0.30" } +pollster = "0.4.0" +raw-window-handle = "0.6.2" +wgpu = "27.0.1" diff --git a/ui/impl.cmake b/ui/impl.cmake new file mode 100644 index 0000000..e2f84e1 --- /dev/null +++ b/ui/impl.cmake @@ -0,0 +1,22 @@ +set(impl_basename "${CARGO_TARGET_DIR}/release/libPROJECT_NAME_impl") + +add_custom_command( + OUTPUT ${impl_basename}.a + COMMAND env CARGO_TARGET_DIR=${CARGO_TARGET_DIR} ${CARGO} build --release --package PROJECT-NAME-impl + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPFILE ${impl_basename}.d + USES_TERMINAL + JOB_SERVER_AWARE + DEPENDS_EXPLICIT_ONLY +) + +# HACK ensure CMake *actually adds* the command above +add_custom_target(build_impl + DEPENDS ${impl_basename}.a +) + +add_library(PROJECT_NAME_impl STATIC IMPORTED) + +set_target_properties(PROJECT_NAME_impl PROPERTIES + IMPORTED_LOCATION ${impl_basename}.a +) diff --git a/ui/src/api.cxx b/ui/src/api.cxx new file mode 100644 index 0000000..aaa2b64 --- /dev/null +++ b/ui/src/api.cxx @@ -0,0 +1,57 @@ +#include "api.hxx" + +#include +#include + +namespace ffi { +extern "C" Core* rt4_viewport_create(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height); +extern "C" void rt4_viewport_destroy(Core* viewport); +extern "C" void rt4_viewport_configure(Core* viewport, std::uint32_t width, std::uint32_t height); +extern "C" void rt4_viewport_redraw(Core* viewport, const RedrawArgs* args); +} // namespace ffi + +BoxCore::BoxCore(BoxCore&& b) + : ptr(std::exchange(b.ptr, {})) { +} + +BoxCore::~BoxCore() { + reset(); +} + +BoxCore& BoxCore::operator=(BoxCore&& b) { + if (&b == this) + return *this; + std::swap(ptr, b.ptr); + b.reset(); + return *this; +} + +BoxCore BoxCore::from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height) { + if (!connection) + throw std::logic_error("attempt to use a null connection"); + if (!window) + throw std::logic_error("attempt to use a null window"); + BoxCore out; + out.ptr.ptr = ffi::rt4_viewport_create(connection, window, width, height); + return out; +} + +void BoxCore::reset() { + auto viewport = std::exchange(ptr, {}); + if (viewport) + ffi::rt4_viewport_destroy(viewport.use()); +} + +ffi::Core* MutCore::use() const { + if (!ptr) + throw std::logic_error("attempt to use a null Core"); + return ptr; +} + +void MutCore::configure(std::uint32_t width, std::uint32_t height) const { + rt4_viewport_configure(use(), width, height); +} + +void MutCore::redraw(const RedrawArgs& args) const { + rt4_viewport_redraw(use(), &args); +} diff --git a/ui/src/api.hxx b/ui/src/api.hxx new file mode 100644 index 0000000..bb946e9 --- /dev/null +++ b/ui/src/api.hxx @@ -0,0 +1,53 @@ +#pragma once + +#include + +struct xcb_connection_t; + +struct alignas(16) Vec4 { + float x, y, z, w; +}; + +namespace ffi { +struct Core; + +struct RedrawArgs { + Vec4 background; +}; +} // namespace ffi + +using ffi::RedrawArgs; + +class MutCore { + friend class BoxCore; + +public: + explicit operator bool() const { return ptr; } + + void configure(std::uint32_t width, std::uint32_t height) const; + void redraw(const RedrawArgs& args) const; + +private: + ffi::Core* ptr = nullptr; + ffi::Core* use() const; +}; + +class BoxCore { +public: + BoxCore() = default; + BoxCore(const BoxCore&) = delete; + BoxCore(BoxCore&&); + BoxCore& operator=(const BoxCore&) = delete; + BoxCore& operator=(BoxCore&&); + ~BoxCore(); + + explicit operator bool() const { return !!ptr; } + const MutCore* operator->() const { return &ptr; } + + void reset(); + + static BoxCore from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height); + +private: + MutCore ptr; +}; diff --git a/ui/src/lib.rs b/ui/src/lib.rs new file mode 100644 index 0000000..571ecd9 --- /dev/null +++ b/ui/src/lib.rs @@ -0,0 +1,48 @@ +use std::{ffi::c_void, num::NonZero, ptr::NonNull}; + +use PROJECT_NAME::{Core, RedrawArgs, init_gpu_inner}; +use glam::{UVec2, uvec2}; +use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle}; + +unsafe fn create_viewport( + display: impl Into, + window: impl Into, + size: UVec2, +) -> Box { + let target = wgpu::SurfaceTargetUnsafe::RawHandle { + raw_display_handle: display.into(), + raw_window_handle: window.into(), + }; + let gpu = pollster::block_on(init_gpu_inner(|instance| unsafe { + instance.create_surface_unsafe(target) + })) + .unwrap(); + Box::new(Core::new(gpu, size)) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn rt4_viewport_create( + connection: NonNull, + window: NonZero, + width: u32, + height: u32, +) -> Box { + let display = XcbDisplayHandle::new(Some(connection), 0); + let window = XcbWindowHandle::new(window); + unsafe { create_viewport(display, window, uvec2(width, height)) } +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn rt4_viewport_destroy(viewport: Box) { + drop(viewport); +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn rt4_viewport_configure(viewport: &mut Core, width: u32, height: u32) { + viewport.configure(uvec2(width, height)); +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn rt4_viewport_redraw(viewport: &mut Core, args: &RedrawArgs) { + viewport.redraw(args); +} diff --git a/ui/src/main.cxx b/ui/src/main.cxx new file mode 100644 index 0000000..a0405ec --- /dev/null +++ b/ui/src/main.cxx @@ -0,0 +1,15 @@ +#include "main_window.hxx" + +#include + +int main(int argc, char* argv[]) { + // only X11 is supported so, use XCB unless overriden + setenv("QT_QPA_PLATFORM", "xcb", 0); + + QApplication app(argc, argv); + + auto w = new PROJECTNAME; + w->show(); + + return app.exec(); +} diff --git a/ui/src/main_window.cxx b/ui/src/main_window.cxx new file mode 100644 index 0000000..723dd57 --- /dev/null +++ b/ui/src/main_window.cxx @@ -0,0 +1,27 @@ +#include "main_window.hxx" + +#include "ui_main_window.h" + +PROJECTNAME::PROJECTNAME(QWidget* parent) + : QMainWindow(parent), + m_ui(new Ui::MainWindow) { + m_ui->setupUi(this); + updateView(); +} + +PROJECTNAME::~PROJECTNAME() = default; + +void PROJECTNAME::updateView() { + const auto color = m_ui->inBackground->color(); + RedrawArgs args{ + .background = { color.redF(), color.greenF(), color.blueF(), 1.00 }, + }; + m_ui->viewport->setView(args); +} + +void PROJECTNAME::updateViewIf(bool update) { + if (update) + updateView(); +} + +#include "moc_main_window.cpp" diff --git a/ui/src/main_window.hxx b/ui/src/main_window.hxx new file mode 100644 index 0000000..1b75e58 --- /dev/null +++ b/ui/src/main_window.hxx @@ -0,0 +1,23 @@ +#pragma once +#include + +#include + +namespace Ui { +class MainWindow; +} + +class PROJECTNAME : public QMainWindow { + Q_OBJECT + +public: + explicit PROJECTNAME(QWidget* parent = nullptr); + ~PROJECTNAME() override; + +public slots: + void updateView(); + void updateViewIf(bool update); // for radio buttons + +private: + const std::unique_ptr m_ui; +}; diff --git a/ui/src/main_window.ui b/ui/src/main_window.ui new file mode 100644 index 0000000..36facd0 --- /dev/null +++ b/ui/src/main_window.ui @@ -0,0 +1,114 @@ + + + MainWindow + + + + 0 + 0 + 1600 + 1200 + + + + PROJECT NAME + + + + + + + + + + + + 0 + 0 + 1600 + 34 + + + + + + + QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable + + + 2 + + + + + + + Background color + + + + + + + + 25 + 220 + 0 + + + + + + + + Qt::Vertical + + + + 20 + 385 + + + + + + + + + + + KColorCombo + QComboBox +
kcolorcombo.h
+
+ + Viewport + QWidget +
viewport.hxx
+ 1 +
+
+ + + + inBackground + highlighted(QColor) + MainWindow + updateView() + + + 1531 + 115 + + + 799 + 599 + + + + + + updateView() + updateViewIf(bool) + +
diff --git a/ui/src/viewport.cxx b/ui/src/viewport.cxx new file mode 100644 index 0000000..e681bd9 --- /dev/null +++ b/ui/src/viewport.cxx @@ -0,0 +1,74 @@ +#include "viewport.hxx" + +#include +#include +#include + +Viewport::Viewport(QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f) { + setAttribute(Qt::WA_DontCreateNativeAncestors); + setAttribute(Qt::WA_NativeWindow); + setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_NoSystemBackground); +} + +Viewport::~Viewport() = default; + +void Viewport::setView(RedrawArgs new_args) { + args = new_args; + update(); +} + +QPaintEngine* Viewport::paintEngine() const { + return nullptr; +} + +bool Viewport::event(QEvent* event) { + switch (event->type()) { + case QEvent::Type::WinIdChange: + recreate(); + break; + default: + break; + } + return QWidget::event(event); +} + +void Viewport::paintEvent(QPaintEvent* event) { + if (!core) + recreate(); + core->redraw(args); +} + +void Viewport::resizeEvent(QResizeEvent* event) { + if (!core) + return; + updateSize(); + QWidget::resizeEvent(event); +} + +void Viewport::recreate() try { + auto* app = qobject_cast(QApplication::instance()); + if (!app) + throw std::runtime_error("not a GUI application (WTF?)"); + + auto* native = app->nativeInterface(); + if (!native) + throw std::runtime_error("X11 interface is not available"); + + auto* xcb_connection = native->connection(); + std::uint32_t x11_window = winId(); + + fprintf(stderr, "connection %p, window %#08x\n", xcb_connection, x11_window); + + const QSize device_size = size() * devicePixelRatio(); + core.reset(); + core = BoxCore::from_xcb(xcb_connection, x11_window, device_size.width(), device_size.height()); +} catch (const std::exception& e) { + fprintf(stderr, "failed to recreate the viewport: %s", e.what()); +} + +void Viewport::updateSize() { + const QSize device_size = size() * devicePixelRatio(); + core->configure(device_size.width(), device_size.height()); +} diff --git a/ui/src/viewport.hxx b/ui/src/viewport.hxx new file mode 100644 index 0000000..95839b9 --- /dev/null +++ b/ui/src/viewport.hxx @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "api.hxx" + +class Viewport : public QWidget { + Q_OBJECT + +public: + explicit Viewport(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + ~Viewport() override; + QPaintEngine* paintEngine() const override; + + void setView(RedrawArgs new_args); + +protected: + bool event(QEvent* event) override; + void paintEvent(QPaintEvent* event) override; + void resizeEvent(QResizeEvent* event) override; + +private: + BoxCore core; + RedrawArgs args = {}; + + void recreate(); + void updateSize(); +}; From 24f3bc5d710bec393e792cbb11b921cb29b22ea6 Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 3 Apr 2026 14:57:51 +0300 Subject: [PATCH 02/15] add usage notes --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index a179901..4c819e4 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,20 @@ This example combines Qt6 GUI (C++) with WGPU rendering (Rust). It doesn’t do much of either but it’s the bridging what’s relevant. Currently only X11 (XCB) is supported but it should be easy to extend to other platforms. + +## Usage + +This program is intended as a starting point rather than a dependency, so just copy it. + +1. Fetch this code: + * clone the repo: `git clone https://gitea.noteuclid.ru/noteuclid/qt-wgpu-skel.git` + * or, download and unpack the [tarball](https://gitea.noteuclid.ru/noteuclid/qt-wgpu-skel/archive/master.tar.gz). +2. Rename the directory to your liking +3. Change the name in all files: + * `PROJECT NAME` to the user-visible project name, + * `PROJECT-NAME` to the technical project name (ASCII, no spaces), + * `PROJECT_NAME` to the same with dashes (`-`) replaced with underscores (`_`), + * `PROJECTNAME` to the same in PascalCase. + +If you want to use Qt5, change the version in both `CMakeLists.txt`, as well as the KF version. +If you don’t want to depend on KDE, remove the ECM and KF5 dependencies, as well as `KColorCombo inBackground` from the UI. You’ll need to replace `inBackground->color()` with something else though. From caa75b5fcfb89bc113bec7b8174e916419302b9f Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 3 Apr 2026 16:42:21 +0300 Subject: [PATCH 03/15] add init script --- README.md | 10 ++++---- init.sh | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 5 deletions(-) create mode 100755 init.sh diff --git a/README.md b/README.md index 4c819e4..5949dc3 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ This program is intended as a starting point rather than a dependency, so just c * clone the repo: `git clone https://gitea.noteuclid.ru/noteuclid/qt-wgpu-skel.git` * or, download and unpack the [tarball](https://gitea.noteuclid.ru/noteuclid/qt-wgpu-skel/archive/master.tar.gz). 2. Rename the directory to your liking -3. Change the name in all files: - * `PROJECT NAME` to the user-visible project name, - * `PROJECT-NAME` to the technical project name (ASCII, no spaces), - * `PROJECT_NAME` to the same with dashes (`-`) replaced with underscores (`_`), - * `PROJECTNAME` to the same in PascalCase. +3. Run `init.sh` with the project name, like: + * `./init.sh 'My FANCY Project'`, or + * `./init.sh 'My FANCY Project' 'fancy-project'`. + +Running `init.sh` without arguments prints the help. If you want to use Qt5, change the version in both `CMakeLists.txt`, as well as the KF version. If you don’t want to depend on KDE, remove the ECM and KF5 dependencies, as well as `KColorCombo inBackground` from the UI. You’ll need to replace `inBackground->color()` with something else though. diff --git a/init.sh b/init.sh new file mode 100755 index 0000000..450f39c --- /dev/null +++ b/init.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +# set -x # debug +set -E # abort on errors +cd "${0%/*}" # where this script is located + +usage() { + { + echo "Usage:" + echo + echo " ./init.sh 'Project Name' [ internal-name ]" + echo + echo "Project name may be anything you like, in any language, with spaces (but not other control characters), etc." + echo + echo "Technical name must be ASCII alphanumeric (a-z, 0-9, also _ and - are allowed), preferably all-lowercase. If omitted, it will be generated from the project name (but that only works if the latter is ASCII too)." + echo + echo "Running this script with no arguments shows this message" + } | fold -s 2>&1 +} + +name="$1" +[ -n "$name" ] || { usage; exit 0; } 2>&1 +echo -n "$name" | LC_ALL=C grep '[[:cntrl:]]' && { echo 'Project name must not contain any control characters'; exit 2; } 2>&1 +name="$(echo -n $name)" # normalize whitespace + +techname="$2" +if [ -z "$techname" ]; then + echo "Technical name not specified; trying to generate from the visible name" >&2 + techname=$( + echo -n $name | + LC_ALL=C tr ' ' '-' | + LC_ALL=C tr -d -c '[:alnum:]-_' | + LC_ALL=C tr '[:upper:]' '[:lower:]' | + cat + ) +fi + +echo -n $techname | LC_ALL=C grep '[^0-9A-Za-z_-]' && { echo 'Technical name must be ASCII alphanumeric (a-z, 0-9, also _ and - are allowed); got:' $techname; exit 2; } 2>&1 +echo -n $techname | LC_ALL=C grep -q '^[A-Za-z]' || { echo 'Technical name must start with an ASCII letter (a-z); got:' $techname; exit 2; } 2>&1 +echo -n $techname | LC_ALL=C grep -q '[A-Za-z0-9]$' || { echo 'Technical name must end with an ASCII letter or digit (a-z, 0-9); got:' $techname; exit 2; } 2>&1 + +echo "Project name: $name" +echo "Internal name: $techname" + +# detach from the skeleton repository +# oldurl="$(git remote -v get-url origin)" +git remote remove origin + +# remove this script from the project (but keep on disk for now) +git rm --cached init.sh + +# escape HTML special characters (&, <, and >), but also sed special characters (& again, \, and /) +htmlname=$(echo -n "$name" | sed 's/&/\&/g; s//\>/g; s:[\\/&]:\\&:g') +sed -i "s/PROJECT NAME/$htmlname/" ui/src/main_window.ui + +# escape Rust special characters (" and \; don't worry of the others as they are unlikely enough and easy to fix manually), and also sed special characters (&, \, and /) +quotname=$(echo -n "$name" | sed 's/"/\\"/g; s:[\\/&]:\\&:g') +sed -i "s/PROJECT NAME/$quotname/" src/main.rs + +# $techname is alphanumeric, nothing to escape +grep -l -r PROJECT-NAME | xargs sed -i "s/PROJECT-NAME/$techname/g" + +# replace - with _ to form a valid snake_case identifier +ident=$(echo -n $techname | LC_ALL=C tr '-' '_') +grep -l -r PROJECT_NAME | xargs sed -i "s/PROJECT_NAME/$ident/g" + +# black magic to convert snake_case to PascalCase +pascal=$(echo -n $ident | LC_ALL=C tr '_' '\n' | LC_ALL=C awk -v FIELDWIDTHS='1 1000' -v ORS='' '{print toupper($1) $2}') +grep -l -r PROJECTNAME | xargs sed -i "s/PROJECTNAME/$pascal/g" From b6899e8537689010066dfa6cd51eb026e86527f6 Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 3 Apr 2026 16:45:08 +0300 Subject: [PATCH 04/15] init.sh: simplify error reporting --- init.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/init.sh b/init.sh index 450f39c..2c4cebc 100755 --- a/init.sh +++ b/init.sh @@ -25,7 +25,6 @@ name="$(echo -n $name)" # normalize whitespace techname="$2" if [ -z "$techname" ]; then - echo "Technical name not specified; trying to generate from the visible name" >&2 techname=$( echo -n $name | LC_ALL=C tr ' ' '-' | @@ -33,11 +32,12 @@ if [ -z "$techname" ]; then LC_ALL=C tr '[:upper:]' '[:lower:]' | cat ) + echo "Technical name not specified; autogenerated: \"$techname\"" >&2 fi -echo -n $techname | LC_ALL=C grep '[^0-9A-Za-z_-]' && { echo 'Technical name must be ASCII alphanumeric (a-z, 0-9, also _ and - are allowed); got:' $techname; exit 2; } 2>&1 -echo -n $techname | LC_ALL=C grep -q '^[A-Za-z]' || { echo 'Technical name must start with an ASCII letter (a-z); got:' $techname; exit 2; } 2>&1 -echo -n $techname | LC_ALL=C grep -q '[A-Za-z0-9]$' || { echo 'Technical name must end with an ASCII letter or digit (a-z, 0-9); got:' $techname; exit 2; } 2>&1 +echo -n $techname | LC_ALL=C grep '[^0-9A-Za-z_-]' && { echo 'Technical name must be ASCII alphanumeric'; exit 2; } 2>&1 +echo -n $techname | LC_ALL=C grep -q '^[A-Za-z]' || { echo 'Technical name must start with an ASCII letter'; exit 2; } 2>&1 +echo -n $techname | LC_ALL=C grep -q '[A-Za-z0-9]$' || { echo 'Technical name must end with an ASCII letter or digit'; exit 2; } 2>&1 echo "Project name: $name" echo "Internal name: $techname" From 6de824c9c2bde2c43adbacae8f58181ee6a48ed0 Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 3 Apr 2026 16:56:05 +0300 Subject: [PATCH 05/15] init.sh: fix error handling --- init.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.sh b/init.sh index 2c4cebc..428f66b 100755 --- a/init.sh +++ b/init.sh @@ -1,7 +1,7 @@ #!/bin/sh # set -x # debug -set -E # abort on errors +set -e # abort on errors cd "${0%/*}" # where this script is located usage() { From 4c8dfa06d44a87b3fe21bf4777f7e475a43a1afb Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 3 Apr 2026 16:56:25 +0300 Subject: [PATCH 06/15] init.sh: fix working with no git --- init.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/init.sh b/init.sh index 428f66b..aad52a1 100755 --- a/init.sh +++ b/init.sh @@ -42,6 +42,10 @@ echo -n $techname | LC_ALL=C grep -q '[A-Za-z0-9]$' || { echo 'Technical name mu echo "Project name: $name" echo "Internal name: $techname" +if ! [ -e .git ]; then + alias git='echo skipping:' +fi + # detach from the skeleton repository # oldurl="$(git remote -v get-url origin)" git remote remove origin From ff3ec96819c5a3835a92ad552de3efd13acc76ba Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 3 Apr 2026 16:58:10 +0300 Subject: [PATCH 07/15] init.sh: mark new project beginning with a commit --- init.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/init.sh b/init.sh index aad52a1..98a011b 100755 --- a/init.sh +++ b/init.sh @@ -71,3 +71,5 @@ grep -l -r PROJECT_NAME | xargs sed -i "s/PROJECT_NAME/$ident/g" # black magic to convert snake_case to PascalCase pascal=$(echo -n $ident | LC_ALL=C tr '_' '\n' | LC_ALL=C awk -v FIELDWIDTHS='1 1000' -v ORS='' '{print toupper($1) $2}') grep -l -r PROJECTNAME | xargs sed -i "s/PROJECTNAME/$pascal/g" + +git commit -a -m "MORPH INTO: $name" From 7baefc958dc26f83430680d05aa3285baf87f1b0 Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 3 Apr 2026 17:01:12 +0300 Subject: [PATCH 08/15] init.sh: add tests (for manual running only for now) --- test/cargo.sh | 5 +++++ test/cmake.sh | 8 ++++++++ test/test-nogit.sh | 17 +++++++++++++++++ test/test-tar.sh | 16 ++++++++++++++++ test/test.sh | 18 ++++++++++++++++++ 5 files changed, 64 insertions(+) create mode 100755 test/cargo.sh create mode 100755 test/cmake.sh create mode 100755 test/test-nogit.sh create mode 100755 test/test-tar.sh create mode 100755 test/test.sh diff --git a/test/cargo.sh b/test/cargo.sh new file mode 100755 index 0000000..4c0e2cc --- /dev/null +++ b/test/cargo.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -E + +exec cargo check diff --git a/test/cmake.sh b/test/cmake.sh new file mode 100755 index 0000000..6d2b548 --- /dev/null +++ b/test/cmake.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -x +set -E + +mkdir build +cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=Debug +ninja -C build diff --git a/test/test-nogit.sh b/test/test-nogit.sh new file mode 100755 index 0000000..1aa4a74 --- /dev/null +++ b/test/test-nogit.sh @@ -0,0 +1,17 @@ +#!/bin/zsh + +set -e +trap 'echo Test failed!' ERR +name=' "Example"' +dir=${0%/*} +root=$dir/.. +tmp=$(mktemp -d) +trap 'rm -rf $tmp' EXIT +rsync -a --exclude=/.git --exclude-from=$root/.gitignore $root/. $tmp/ +cd $tmp +echo "Initializing in $tmp" +./init.sh $name +echo "Starting the shell in $tmp" +echo "Review the files, then exit the shell" +${SHELL:-/bin/sh} -i +echo "Review successful, cleaning up" diff --git a/test/test-tar.sh b/test/test-tar.sh new file mode 100755 index 0000000..8c60732 --- /dev/null +++ b/test/test-tar.sh @@ -0,0 +1,16 @@ +#!/bin/zsh + +set -e +trap 'echo Test failed!' ERR +name=' "Example"' +root=$(realpath ${0%/*}/..) +tmp=$(mktemp -d) +trap 'rm -rf $tmp' EXIT +cd $tmp +git -C $root archive HEAD | tar -x +echo "Initializing in $tmp" +./init.sh $name +echo "Starting the shell in $tmp" +echo "Review the files, then exit the shell" +${SHELL:-/bin/sh} -i +echo "Review successful, cleaning up" diff --git a/test/test.sh b/test/test.sh new file mode 100755 index 0000000..f80950f --- /dev/null +++ b/test/test.sh @@ -0,0 +1,18 @@ +#!/bin/zsh + +set -e +trap 'echo Test failed!' ERR +name=' "Example"' +dir=${0%/*} +root=$dir/.. +tmp=$(mktemp -d) +trap 'rm -rf $tmp' EXIT +rsync -a --exclude-from=$root/.gitignore $root/. $tmp/ +cd $tmp +git clean -fxdq +echo "Initializing in $tmp" +./init.sh $name +echo "Starting the shell in $tmp" +echo "Review the files, then exit the shell" +${SHELL:-/bin/sh} -i +echo "Review successful, cleaning up" From af79b01fff61e5ebd425402df20ebd0ef66f6c49 Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 18 Apr 2026 16:23:47 +0300 Subject: [PATCH 09/15] make sure skeleton tests are separate for (future) project tests --- init.sh | 1 + skel-test/README.md | 3 +++ {test => skel-test}/cargo.sh | 0 {test => skel-test}/cmake.sh | 0 {test => skel-test}/test-nogit.sh | 0 {test => skel-test}/test-tar.sh | 0 {test => skel-test}/test.sh | 0 7 files changed, 4 insertions(+) create mode 100644 skel-test/README.md rename {test => skel-test}/cargo.sh (100%) rename {test => skel-test}/cmake.sh (100%) rename {test => skel-test}/test-nogit.sh (100%) rename {test => skel-test}/test-tar.sh (100%) rename {test => skel-test}/test.sh (100%) diff --git a/init.sh b/init.sh index 98a011b..7e098e7 100755 --- a/init.sh +++ b/init.sh @@ -52,6 +52,7 @@ git remote remove origin # remove this script from the project (but keep on disk for now) git rm --cached init.sh +git rm -r skel-test # escape HTML special characters (&, <, and >), but also sed special characters (& again, \, and /) htmlname=$(echo -n "$name" | sed 's/&/\&/g; s//\>/g; s:[\\/&]:\\&:g') diff --git a/skel-test/README.md b/skel-test/README.md new file mode 100644 index 0000000..c0d80e5 --- /dev/null +++ b/skel-test/README.md @@ -0,0 +1,3 @@ +# Self-tests + +This directory contains self-tests for the skeleton itself. It should be removed when starting a new project. diff --git a/test/cargo.sh b/skel-test/cargo.sh similarity index 100% rename from test/cargo.sh rename to skel-test/cargo.sh diff --git a/test/cmake.sh b/skel-test/cmake.sh similarity index 100% rename from test/cmake.sh rename to skel-test/cmake.sh diff --git a/test/test-nogit.sh b/skel-test/test-nogit.sh similarity index 100% rename from test/test-nogit.sh rename to skel-test/test-nogit.sh diff --git a/test/test-tar.sh b/skel-test/test-tar.sh similarity index 100% rename from test/test-tar.sh rename to skel-test/test-tar.sh diff --git a/test/test.sh b/skel-test/test.sh similarity index 100% rename from test/test.sh rename to skel-test/test.sh From f2b904b5f913938674b25842514bb9d4299448bd Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 4 Jul 2026 22:45:54 +0300 Subject: [PATCH 10/15] replace README on morph --- init.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/init.sh b/init.sh index 98a011b..c93c8b7 100755 --- a/init.sh +++ b/init.sh @@ -53,6 +53,9 @@ git remote remove origin # remove this script from the project (but keep on disk for now) git rm --cached init.sh +# replace the README with a stub +echo "# $name" >| README.md + # escape HTML special characters (&, <, and >), but also sed special characters (& again, \, and /) htmlname=$(echo -n "$name" | sed 's/&/\&/g; s//\>/g; s:[\\/&]:\\&:g') sed -i "s/PROJECT NAME/$htmlname/" ui/src/main_window.ui From 187019a318a0e1f14b199cce36225d68cc4408e0 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 19 Jul 2026 21:42:05 +0300 Subject: [PATCH 11/15] use Default to avoid breaking fallback main --- src/lib.rs | 10 +++++++++- src/main.rs | 6 ++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2518f00..294edfd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ use std::error::Error; -use glam::{UVec2, Vec4}; +use glam::{UVec2, Vec4, vec4}; const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth16Unorm; const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb; @@ -11,6 +11,14 @@ pub struct RedrawArgs { pub background: Vec4, } +impl Default for RedrawArgs { + fn default() -> Self { + Self { + background: vec4(0.05, 0.20, 0.85, 1.00), + } + } +} + pub struct Gpu { device: wgpu::Device, queue: wgpu::Queue, diff --git a/src/main.rs b/src/main.rs index aa0bec3..3021a6a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use PROJECT_NAME::{Core, RedrawArgs, init_gpu_inner}; -use glam::{uvec2, vec4}; +use glam::uvec2; use winit::{ application::ApplicationHandler, event::WindowEvent, @@ -36,9 +36,7 @@ impl MainWindow { WindowEvent::Resized(physical_size) => self .core .configure(uvec2(physical_size.width, physical_size.height)), - WindowEvent::RedrawRequested => self.core.redraw(&RedrawArgs { - background: vec4(0.05, 0.20, 0.85, 1.00), - }), + WindowEvent::RedrawRequested => self.core.redraw(&RedrawArgs::default()), _ => {} } } From 9a695c06b585f8939fdd248fa7694d5fa6e9d756 Mon Sep 17 00:00:00 2001 From: numzero Date: Tue, 4 Aug 2026 22:13:11 +0300 Subject: [PATCH 12/15] update Cargo.lock on morph --- init.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/init.sh b/init.sh index c93c8b7..276fb13 100755 --- a/init.sh +++ b/init.sh @@ -75,4 +75,7 @@ grep -l -r PROJECT_NAME | xargs sed -i "s/PROJECT_NAME/$ident/g" pascal=$(echo -n $ident | LC_ALL=C tr '_' '\n' | LC_ALL=C awk -v FIELDWIDTHS='1 1000' -v ORS='' '{print toupper($1) $2}') grep -l -r PROJECTNAME | xargs sed -i "s/PROJECTNAME/$pascal/g" +# another hack, to update Cargo.lock +cargo tree >/dev/null + git commit -a -m "MORPH INTO: $name" From a5e8e3e2e800c70eb8723ffda8e5cb0032956dc2 Mon Sep 17 00:00:00 2001 From: numzero Date: Tue, 27 Oct 2026 17:14:46 +0300 Subject: [PATCH 13/15] MORPH INTO: Photon Light --- CMakeLists.txt | 2 +- Cargo.lock | 42 ++++++++++----------- Cargo.toml | 2 +- README.md | 23 +----------- init.sh | 82 ----------------------------------------- skel-test/README.md | 3 -- skel-test/cargo.sh | 5 --- skel-test/cmake.sh | 8 ---- skel-test/test-nogit.sh | 17 --------- skel-test/test-tar.sh | 16 -------- skel-test/test.sh | 18 --------- src/main.rs | 4 +- ui/CMakeLists.txt | 10 ++--- ui/Cargo.toml | 4 +- ui/impl.cmake | 8 ++-- ui/src/lib.rs | 2 +- ui/src/main.cxx | 2 +- ui/src/main_window.cxx | 8 ++-- ui/src/main_window.hxx | 6 +-- ui/src/main_window.ui | 2 +- 20 files changed, 47 insertions(+), 217 deletions(-) delete mode 100755 init.sh delete mode 100644 skel-test/README.md delete mode 100755 skel-test/cargo.sh delete mode 100755 skel-test/cmake.sh delete mode 100755 skel-test/test-nogit.sh delete mode 100755 skel-test/test-tar.sh delete mode 100755 skel-test/test.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index f30e705..49b4606 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.18) -project(PROJECT-NAME VERSION 1.0.0 LANGUAGES CXX) +project(photon-light VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/Cargo.lock b/Cargo.lock index 9db39c2..add1bfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,27 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "PROJECT-NAME" -version = "0.1.0" -dependencies = [ - "glam", - "pollster", - "wgpu", - "winit", -] - -[[package]] -name = "PROJECT-NAME-impl" -version = "0.1.0" -dependencies = [ - "PROJECT-NAME", - "glam", - "pollster", - "raw-window-handle", - "wgpu", -] - [[package]] name = "ab_glyph" version = "0.2.32" @@ -1184,6 +1163,27 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "photon-light" +version = "0.1.0" +dependencies = [ + "glam", + "pollster", + "wgpu", + "winit", +] + +[[package]] +name = "photon-light-impl" +version = "0.1.0" +dependencies = [ + "glam", + "photon-light", + "pollster", + "raw-window-handle", + "wgpu", +] + [[package]] name = "pin-project" version = "1.1.10" diff --git a/Cargo.toml b/Cargo.toml index 0d64950..b43459f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ members = ["ui"] [package] -name = "PROJECT-NAME" +name = "photon-light" version = "0.1.0" edition = "2024" diff --git a/README.md b/README.md index 5949dc3..69f2a64 100644 --- a/README.md +++ b/README.md @@ -1,22 +1 @@ -# Qt6+WGPU skeleton program - -This example combines Qt6 GUI (C++) with WGPU rendering (Rust). It doesn’t do much of either but it’s the bridging what’s relevant. - -Currently only X11 (XCB) is supported but it should be easy to extend to other platforms. - -## Usage - -This program is intended as a starting point rather than a dependency, so just copy it. - -1. Fetch this code: - * clone the repo: `git clone https://gitea.noteuclid.ru/noteuclid/qt-wgpu-skel.git` - * or, download and unpack the [tarball](https://gitea.noteuclid.ru/noteuclid/qt-wgpu-skel/archive/master.tar.gz). -2. Rename the directory to your liking -3. Run `init.sh` with the project name, like: - * `./init.sh 'My FANCY Project'`, or - * `./init.sh 'My FANCY Project' 'fancy-project'`. - -Running `init.sh` without arguments prints the help. - -If you want to use Qt5, change the version in both `CMakeLists.txt`, as well as the KF version. -If you don’t want to depend on KDE, remove the ECM and KF5 dependencies, as well as `KColorCombo inBackground` from the UI. You’ll need to replace `inBackground->color()` with something else though. +# Photon Light diff --git a/init.sh b/init.sh deleted file mode 100755 index 6fe9b04..0000000 --- a/init.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/sh - -# set -x # debug -set -e # abort on errors -cd "${0%/*}" # where this script is located - -usage() { - { - echo "Usage:" - echo - echo " ./init.sh 'Project Name' [ internal-name ]" - echo - echo "Project name may be anything you like, in any language, with spaces (but not other control characters), etc." - echo - echo "Technical name must be ASCII alphanumeric (a-z, 0-9, also _ and - are allowed), preferably all-lowercase. If omitted, it will be generated from the project name (but that only works if the latter is ASCII too)." - echo - echo "Running this script with no arguments shows this message" - } | fold -s 2>&1 -} - -name="$1" -[ -n "$name" ] || { usage; exit 0; } 2>&1 -echo -n "$name" | LC_ALL=C grep '[[:cntrl:]]' && { echo 'Project name must not contain any control characters'; exit 2; } 2>&1 -name="$(echo -n $name)" # normalize whitespace - -techname="$2" -if [ -z "$techname" ]; then - techname=$( - echo -n $name | - LC_ALL=C tr ' ' '-' | - LC_ALL=C tr -d -c '[:alnum:]-_' | - LC_ALL=C tr '[:upper:]' '[:lower:]' | - cat - ) - echo "Technical name not specified; autogenerated: \"$techname\"" >&2 -fi - -echo -n $techname | LC_ALL=C grep '[^0-9A-Za-z_-]' && { echo 'Technical name must be ASCII alphanumeric'; exit 2; } 2>&1 -echo -n $techname | LC_ALL=C grep -q '^[A-Za-z]' || { echo 'Technical name must start with an ASCII letter'; exit 2; } 2>&1 -echo -n $techname | LC_ALL=C grep -q '[A-Za-z0-9]$' || { echo 'Technical name must end with an ASCII letter or digit'; exit 2; } 2>&1 - -echo "Project name: $name" -echo "Internal name: $techname" - -if ! [ -e .git ]; then - alias git='echo skipping:' -fi - -# detach from the skeleton repository -# oldurl="$(git remote -v get-url origin)" -git remote remove origin - -# remove this script from the project (but keep on disk for now) -git rm --cached init.sh -git rm -r skel-test - -# replace the README with a stub -echo "# $name" >| README.md - -# escape HTML special characters (&, <, and >), but also sed special characters (& again, \, and /) -htmlname=$(echo -n "$name" | sed 's/&/\&/g; s//\>/g; s:[\\/&]:\\&:g') -sed -i "s/PROJECT NAME/$htmlname/" ui/src/main_window.ui - -# escape Rust special characters (" and \; don't worry of the others as they are unlikely enough and easy to fix manually), and also sed special characters (&, \, and /) -quotname=$(echo -n "$name" | sed 's/"/\\"/g; s:[\\/&]:\\&:g') -sed -i "s/PROJECT NAME/$quotname/" src/main.rs - -# $techname is alphanumeric, nothing to escape -grep -l -r PROJECT-NAME | xargs sed -i "s/PROJECT-NAME/$techname/g" - -# replace - with _ to form a valid snake_case identifier -ident=$(echo -n $techname | LC_ALL=C tr '-' '_') -grep -l -r PROJECT_NAME | xargs sed -i "s/PROJECT_NAME/$ident/g" - -# black magic to convert snake_case to PascalCase -pascal=$(echo -n $ident | LC_ALL=C tr '_' '\n' | LC_ALL=C awk -v FIELDWIDTHS='1 1000' -v ORS='' '{print toupper($1) $2}') -grep -l -r PROJECTNAME | xargs sed -i "s/PROJECTNAME/$pascal/g" - -# another hack, to update Cargo.lock -cargo tree >/dev/null - -git commit -a -m "MORPH INTO: $name" diff --git a/skel-test/README.md b/skel-test/README.md deleted file mode 100644 index c0d80e5..0000000 --- a/skel-test/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Self-tests - -This directory contains self-tests for the skeleton itself. It should be removed when starting a new project. diff --git a/skel-test/cargo.sh b/skel-test/cargo.sh deleted file mode 100755 index 4c0e2cc..0000000 --- a/skel-test/cargo.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -set -E - -exec cargo check diff --git a/skel-test/cmake.sh b/skel-test/cmake.sh deleted file mode 100755 index 6d2b548..0000000 --- a/skel-test/cmake.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -set -x -set -E - -mkdir build -cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=Debug -ninja -C build diff --git a/skel-test/test-nogit.sh b/skel-test/test-nogit.sh deleted file mode 100755 index 1aa4a74..0000000 --- a/skel-test/test-nogit.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/zsh - -set -e -trap 'echo Test failed!' ERR -name=' "Example"' -dir=${0%/*} -root=$dir/.. -tmp=$(mktemp -d) -trap 'rm -rf $tmp' EXIT -rsync -a --exclude=/.git --exclude-from=$root/.gitignore $root/. $tmp/ -cd $tmp -echo "Initializing in $tmp" -./init.sh $name -echo "Starting the shell in $tmp" -echo "Review the files, then exit the shell" -${SHELL:-/bin/sh} -i -echo "Review successful, cleaning up" diff --git a/skel-test/test-tar.sh b/skel-test/test-tar.sh deleted file mode 100755 index 8c60732..0000000 --- a/skel-test/test-tar.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/zsh - -set -e -trap 'echo Test failed!' ERR -name=' "Example"' -root=$(realpath ${0%/*}/..) -tmp=$(mktemp -d) -trap 'rm -rf $tmp' EXIT -cd $tmp -git -C $root archive HEAD | tar -x -echo "Initializing in $tmp" -./init.sh $name -echo "Starting the shell in $tmp" -echo "Review the files, then exit the shell" -${SHELL:-/bin/sh} -i -echo "Review successful, cleaning up" diff --git a/skel-test/test.sh b/skel-test/test.sh deleted file mode 100755 index f80950f..0000000 --- a/skel-test/test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/zsh - -set -e -trap 'echo Test failed!' ERR -name=' "Example"' -dir=${0%/*} -root=$dir/.. -tmp=$(mktemp -d) -trap 'rm -rf $tmp' EXIT -rsync -a --exclude-from=$root/.gitignore $root/. $tmp/ -cd $tmp -git clean -fxdq -echo "Initializing in $tmp" -./init.sh $name -echo "Starting the shell in $tmp" -echo "Review the files, then exit the shell" -${SHELL:-/bin/sh} -i -echo "Review successful, cleaning up" diff --git a/src/main.rs b/src/main.rs index 3021a6a..26c3e2d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use PROJECT_NAME::{Core, RedrawArgs, init_gpu_inner}; +use photon_light::{Core, RedrawArgs, init_gpu_inner}; use glam::uvec2; use winit::{ application::ApplicationHandler, @@ -9,7 +9,7 @@ use winit::{ window::Window, }; -const TITLE: &str = "PROJECT NAME"; +const TITLE: &str = "Photon Light"; struct MainWindow { window: Arc, diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 5c3f9f3..2759ac7 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,6 +1,6 @@ include(impl.cmake) -qt_add_executable(PROJECT-NAME +qt_add_executable(photon-light src/api.cxx src/main.cxx src/main_window.cxx @@ -8,7 +8,7 @@ qt_add_executable(PROJECT-NAME src/viewport.cxx ) -target_link_libraries(PROJECT-NAME PRIVATE Qt6::Gui Qt6::Widgets) -target_link_libraries(PROJECT-NAME PRIVATE KF6::WidgetsAddons) -target_link_libraries(PROJECT-NAME PRIVATE PROJECT_NAME_impl) -target_include_directories(PROJECT-NAME PRIVATE src) +target_link_libraries(photon-light PRIVATE Qt6::Gui Qt6::Widgets) +target_link_libraries(photon-light PRIVATE KF6::WidgetsAddons) +target_link_libraries(photon-light PRIVATE photon_light_impl) +target_include_directories(photon-light PRIVATE src) diff --git a/ui/Cargo.toml b/ui/Cargo.toml index 6565f4f..e12ba36 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "PROJECT-NAME-impl" +name = "photon-light-impl" version = "0.1.0" edition = "2024" @@ -7,7 +7,7 @@ edition = "2024" crate-type = ["staticlib"] [dependencies] -PROJECT-NAME = {path = "../"} +photon-light = {path = "../"} glam = { version = "0.30" } pollster = "0.4.0" diff --git a/ui/impl.cmake b/ui/impl.cmake index e2f84e1..6abf56e 100644 --- a/ui/impl.cmake +++ b/ui/impl.cmake @@ -1,8 +1,8 @@ -set(impl_basename "${CARGO_TARGET_DIR}/release/libPROJECT_NAME_impl") +set(impl_basename "${CARGO_TARGET_DIR}/release/libphoton_light_impl") add_custom_command( OUTPUT ${impl_basename}.a - COMMAND env CARGO_TARGET_DIR=${CARGO_TARGET_DIR} ${CARGO} build --release --package PROJECT-NAME-impl + COMMAND env CARGO_TARGET_DIR=${CARGO_TARGET_DIR} ${CARGO} build --release --package photon-light-impl WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPFILE ${impl_basename}.d USES_TERMINAL @@ -15,8 +15,8 @@ add_custom_target(build_impl DEPENDS ${impl_basename}.a ) -add_library(PROJECT_NAME_impl STATIC IMPORTED) +add_library(photon_light_impl STATIC IMPORTED) -set_target_properties(PROJECT_NAME_impl PROPERTIES +set_target_properties(photon_light_impl PROPERTIES IMPORTED_LOCATION ${impl_basename}.a ) diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 571ecd9..b9f9137 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -1,6 +1,6 @@ use std::{ffi::c_void, num::NonZero, ptr::NonNull}; -use PROJECT_NAME::{Core, RedrawArgs, init_gpu_inner}; +use photon_light::{Core, RedrawArgs, init_gpu_inner}; use glam::{UVec2, uvec2}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle}; diff --git a/ui/src/main.cxx b/ui/src/main.cxx index a0405ec..03115ce 100644 --- a/ui/src/main.cxx +++ b/ui/src/main.cxx @@ -8,7 +8,7 @@ int main(int argc, char* argv[]) { QApplication app(argc, argv); - auto w = new PROJECTNAME; + auto w = new PhotonLight; w->show(); return app.exec(); diff --git a/ui/src/main_window.cxx b/ui/src/main_window.cxx index 723dd57..208325e 100644 --- a/ui/src/main_window.cxx +++ b/ui/src/main_window.cxx @@ -2,16 +2,16 @@ #include "ui_main_window.h" -PROJECTNAME::PROJECTNAME(QWidget* parent) +PhotonLight::PhotonLight(QWidget* parent) : QMainWindow(parent), m_ui(new Ui::MainWindow) { m_ui->setupUi(this); updateView(); } -PROJECTNAME::~PROJECTNAME() = default; +PhotonLight::~PhotonLight() = default; -void PROJECTNAME::updateView() { +void PhotonLight::updateView() { const auto color = m_ui->inBackground->color(); RedrawArgs args{ .background = { color.redF(), color.greenF(), color.blueF(), 1.00 }, @@ -19,7 +19,7 @@ void PROJECTNAME::updateView() { m_ui->viewport->setView(args); } -void PROJECTNAME::updateViewIf(bool update) { +void PhotonLight::updateViewIf(bool update) { if (update) updateView(); } diff --git a/ui/src/main_window.hxx b/ui/src/main_window.hxx index 1b75e58..27b63ff 100644 --- a/ui/src/main_window.hxx +++ b/ui/src/main_window.hxx @@ -7,12 +7,12 @@ namespace Ui { class MainWindow; } -class PROJECTNAME : public QMainWindow { +class PhotonLight : public QMainWindow { Q_OBJECT public: - explicit PROJECTNAME(QWidget* parent = nullptr); - ~PROJECTNAME() override; + explicit PhotonLight(QWidget* parent = nullptr); + ~PhotonLight() override; public slots: void updateView(); diff --git a/ui/src/main_window.ui b/ui/src/main_window.ui index 36facd0..8e9ae8b 100644 --- a/ui/src/main_window.ui +++ b/ui/src/main_window.ui @@ -11,7 +11,7 @@ - PROJECT NAME + Photon Light From 991d672f3a754c25273b52ea0ceb3b959768a4de Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 12 Sep 2026 16:25:14 +0300 Subject: [PATCH 14/15] remove the KDE dependency --- CMakeLists.txt | 5 ----- ui/CMakeLists.txt | 1 - 2 files changed, 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49b4606..097b292 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,11 +9,6 @@ find_package(Qt6 REQUIRED COMPONENTS Gui Widgets) find_program(CARGO cargo REQUIRED) set(CARGO_TARGET_DIR "${CMAKE_BINARY_DIR}/cargo") -# KDE-specific -find_package(ECM REQUIRED NO_MODULE) -set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) -find_package(KF6 REQUIRED COMPONENTS WidgetsAddons) - qt_standard_project_setup() add_subdirectory(ui) diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 2759ac7..191380f 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -9,6 +9,5 @@ qt_add_executable(photon-light ) target_link_libraries(photon-light PRIVATE Qt6::Gui Qt6::Widgets) -target_link_libraries(photon-light PRIVATE KF6::WidgetsAddons) target_link_libraries(photon-light PRIVATE photon_light_impl) target_include_directories(photon-light PRIVATE src) From 9a8dc8fe34069756b1874479ed96ea286a2c289d Mon Sep 17 00:00:00 2001 From: numzero Date: Tue, 27 Oct 2026 18:24:04 +0300 Subject: [PATCH 15/15] cargo fmt --- src/camera.rs | 13 +++++++------ src/main.rs | 3 ++- ui/src/lib.rs | 3 ++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/camera.rs b/src/camera.rs index a91e1a7..72560ea 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -31,12 +31,13 @@ impl OrbitalCamera { [-1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 0., 1.], - ]) * Mat4::from_euler( - glam::EulerRot::ZYZ, - 0., - self.position_pitch, - -self.position_yaw, - ) + ]) + * Mat4::from_euler( + glam::EulerRot::ZYZ, + 0., + self.position_pitch, + -self.position_yaw, + ) } } diff --git a/src/main.rs b/src/main.rs index 26c3e2d..da72f20 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ use std::sync::Arc; -use photon_light::{Core, RedrawArgs, init_gpu_inner}; use glam::uvec2; use winit::{ application::ApplicationHandler, @@ -9,6 +8,8 @@ use winit::{ window::Window, }; +use photon_light::{Core, RedrawArgs, init_gpu_inner}; + const TITLE: &str = "Photon Light"; struct MainWindow { diff --git a/ui/src/lib.rs b/ui/src/lib.rs index b9f9137..ed5dce1 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -1,9 +1,10 @@ use std::{ffi::c_void, num::NonZero, ptr::NonNull}; -use photon_light::{Core, RedrawArgs, init_gpu_inner}; use glam::{UVec2, uvec2}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle}; +use photon_light::{Core, RedrawArgs, init_gpu_inner}; + unsafe fn create_viewport( display: impl Into, window: impl Into,