diff --git a/CMakeLists.txt b/CMakeLists.txt index 5470e0c..0db45da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,9 @@ find_package(Qt6 REQUIRED COMPONENTS Gui Widgets) find_program(CARGO cargo REQUIRED) set(CARGO_TARGET_DIR "${CMAKE_SOURCE_DIR}/target" CACHE PATH "Path to the Cargo target directory") +include(diplomat.cmake) + qt_standard_project_setup() +add_subdirectory(src) add_subdirectory(ui) diff --git a/Cargo.lock b/Cargo.lock index 879b203..1cd7292 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,9 +165,9 @@ checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" dependencies = [ "bytemuck_derive", ] @@ -180,7 +180,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -354,6 +354,38 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "diplomat" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a80510e6103d35c5cd031c0e3f21165b32742c301ee3dafdbb5904c6dca46a" +dependencies = [ + "diplomat_core", + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "diplomat-runtime" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9d981121ba76150987fda68185b37853c0b928a55dfdc28897348cd068440be" + +[[package]] +name = "diplomat_core" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5c594efd1d097105255fc325c430a517c97b7b7c69f8727f653593e1ce726" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "smallvec", + "strck", + "syn 3.0.9", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -442,7 +474,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -892,7 +924,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -1182,6 +1214,8 @@ version = "0.1.0" dependencies = [ "approx", "bytemuck", + "diplomat", + "diplomat-runtime", "glam", "pollster", "rand", @@ -1191,17 +1225,6 @@ dependencies = [ "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" @@ -1219,7 +1242,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -1530,7 +1553,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -1609,6 +1632,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strck" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42316e70da376f3d113a68d138a60d8a9883c604fe97942721ec2068dab13a9f" +dependencies = [ + "unicode-ident", +] + [[package]] name = "strict-num" version = "0.1.1" @@ -1626,6 +1658,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -1661,7 +1704,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -1672,7 +1715,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -1841,7 +1884,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.114", "wasm-bindgen-shared", ] @@ -2174,7 +2217,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -2185,7 +2228,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] [[package]] @@ -2517,5 +2560,5 @@ checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.114", ] diff --git a/Cargo.toml b/Cargo.toml index 5c3ab54..95fe38c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ -[workspace] -members = ["ui"] - [package] name = "photon-light" version = "0.1.0" edition = "2024" +[lib] +crate-type = ["lib", "staticlib"] + [profile.dev] panic = 'abort' @@ -18,7 +18,7 @@ debug = false opt-level = 3 [dependencies] -bytemuck = "1.24.0" +bytemuck = "1.25.2" glam = { version = "0.30.9", features = ["bytemuck", "approx"] } pollster = "0.4.0" rand = "0.9.2" @@ -26,6 +26,8 @@ rand_distr = "0.5.1" rand_pcg = "0.9.0" wgpu = "27.0.1" winit = "0.30.12" +diplomat = "0.17.0" +diplomat-runtime = "0.16.1" [dev-dependencies] approx = "0.5.1" diff --git a/diplomat.cmake b/diplomat.cmake new file mode 100644 index 0000000..70a752f --- /dev/null +++ b/diplomat.cmake @@ -0,0 +1,8 @@ +set(crates "${CMAKE_BINARY_DIR}/crates") +set(diplomat "${crates}/bin/diplomat-tool") + +if(NOT IS_EXECUTABLE "${diplomat}") + message(CONFIGURE_LOG "Downloading Diplomat...") + file(MAKE_DIRECTORY "${crates}") + execute_process(COMMAND ${CARGO} install --root "${crates}" diplomat-tool@0.17.0) +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..c366673 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,63 @@ +# build the Rust side as a static library +set(impl_basename "${CARGO_TARGET_DIR}/release/libphoton_light") + +set(cargo_cmake_args) +set(diplomat_cmake_args) + +if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.27") + list(APPEND cargo_cmake_args DEPENDS_EXPLICIT_ONLY) + list(APPEND diplomat_cmake_args DEPENDS_EXPLICIT_ONLY) +endif() + +if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.28") + list(APPEND cargo_cmake_args JOB_SERVER_AWARE TRUE) +endif() + +if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.31") + list(APPEND diplomat_cmake_args CODEGEN) +endif() + +add_custom_command( + OUTPUT "${impl_basename}.a" + COMMAND env "CARGO_TARGET_DIR=${CARGO_TARGET_DIR}" ${CARGO} build --release --package photon-light + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + DEPFILE "${impl_basename}.d" + USES_TERMINAL + VERBATIM + ${cargo_cmake_args} +) + +# HACK ensure CMake *actually adds* the command above +add_custom_target(build_impl + DEPENDS "${impl_basename}.a" +) + +add_library(photon_light_impl STATIC IMPORTED GLOBAL) + +set_target_properties(photon_light_impl PROPERTIES + IMPORTED_LOCATION "${impl_basename}.a" +) + +# generate the bindings +set(bindings_dir "${CMAKE_CURRENT_BINARY_DIR}/include") +file(MAKE_DIRECTORY "${bindings_dir}") +set(bindings + "${bindings_dir}/Core.hpp" +) + +add_custom_command( + OUTPUT ${bindings} + COMMAND ${diplomat} cpp "${bindings_dir}" + MAIN_DEPENDENCY "lib.rs" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + VERBATIM + ${diplomat_cmake_args} +) + +# HACK ensure CMake *actually adds* the command above +add_custom_target(codegen_impl + DEPENDS ${bindings} +) + +target_sources(photon_light_impl INTERFACE ${bindings}) +target_include_directories(photon_light_impl INTERFACE "${bindings_dir}") diff --git a/src/iter.rs b/src/iter.rs new file mode 100644 index 0000000..88be085 --- /dev/null +++ b/src/iter.rs @@ -0,0 +1,22 @@ +use std::convert::identity; + +pub(crate) fn loop_list(iter: impl IntoIterator) -> impl Iterator { + loop_list_ex(iter, identity, identity) +} + +pub(crate) fn loop_list_ex( + iter: impl IntoIterator, + mut fa: impl FnMut(T) -> U, + mut fb: impl FnMut(T) -> U, +) -> impl Iterator { + gen move { + let mut iter = iter.into_iter(); + let Some(first) = iter.next() else { return }; + yield fa(first.clone()); + for item in iter { + yield fb(item.clone()); + yield fa(item); + } + yield fb(first); + } +} diff --git a/src/lib.rs b/src/lib.rs index 0873c0b..942ae73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,14 @@ #![feature(gen_blocks)] -use std::{convert::identity, error::Error, f32::consts::PI}; +use std::{error::Error, f32::consts::PI}; use glam::{Mat4, UVec2, Vec2, Vec3, vec3}; use rand_distr::Distribution as _; +use wgpu::rwh::{RawDisplayHandle, RawWindowHandle}; use crate::{ camera::OrbitalCamera, + iter::loop_list, ray::Ray, render::{ DEPTH_FORMAT, OUTPUT_FORMAT, @@ -15,73 +17,103 @@ use crate::{ trace::{Hit, Lambertian, Reflector, Scene, Source, Sphere}, }; +pub use crate::ffi::{RedrawArgs, SphericalPosition, UseNormal}; + mod camera; +mod iter; mod ray; mod render; mod shape; mod trace; -#[derive(Debug, Clone, Copy, PartialEq)] -#[repr(C)] -pub struct SphericalPosition { - pub yaw: f32, - pub pitch: f32, - pub distance: f32, -} +#[diplomat::bridge] +mod ffi { + use std::{f32::consts::PI, num::NonZero, ptr::NonNull}; -#[derive(Debug, Clone, Copy)] -#[repr(u8)] -pub enum UseNormal { - Light, - Camera, -} + use glam::uvec2; + use wgpu::rwh::{XcbDisplayHandle, XcbWindowHandle}; -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct RedrawArgs { - pub camera_position: SphericalPosition, - pub light_position: SphericalPosition, - pub light_radius: f32, - pub light_spread: f32, - pub accum_sigma: f32, - pub accum_scale: f32, - pub reflections: u8, - pub use_normal: UseNormal, - pub show_axes: bool, - pub show_shapes: bool, - pub show_hit_emission: bool, - pub show_miss_emission: bool, - pub show_direct_hit: bool, - pub show_indirect_hit: bool, - pub show_light: bool, -} + #[derive(Debug, Clone, Copy, PartialEq)] + pub struct SphericalPosition { + pub yaw: f32, + pub pitch: f32, + pub distance: f32, + } -impl Default for RedrawArgs { - fn default() -> Self { - Self { - camera_position: SphericalPosition { - yaw: PI / 4., - pitch: 0.5f32.sqrt().atan(), - distance: 3.0, - }, - light_position: SphericalPosition { - yaw: 0.0, - pitch: PI / 3., - distance: 1.0, - }, - light_radius: 0.125, - light_spread: 0.125, - accum_sigma: 0.025, - accum_scale: 0.01, - reflections: 2, - use_normal: UseNormal::Light, - show_axes: true, - show_shapes: true, - show_hit_emission: false, - show_miss_emission: false, - show_direct_hit: false, - show_indirect_hit: false, - show_light: true, + #[derive(Debug)] + pub enum UseNormal { + Light, + Camera, + } + + #[derive(Debug, Clone, Copy)] + pub struct RedrawArgs { + pub camera_position: SphericalPosition, + pub light_position: SphericalPosition, + pub light_radius: f32, + pub light_spread: f32, + pub accum_sigma: f32, + pub accum_scale: f32, + pub reflections: u8, + pub use_normal: UseNormal, + pub show_axes: bool, + pub show_shapes: bool, + pub show_hit_emission: bool, + pub show_miss_emission: bool, + pub show_direct_hit: bool, + pub show_indirect_hit: bool, + pub show_light: bool, + } + + impl Default for RedrawArgs { + fn default() -> Self { + Self { + camera_position: SphericalPosition { + yaw: PI / 4., + pitch: 0.5f32.sqrt().atan(), + distance: 3.0, + }, + light_position: SphericalPosition { + yaw: 0.0, + pitch: PI / 3., + distance: 1.0, + }, + light_radius: 0.125, + light_spread: 0.125, + accum_sigma: 0.025, + accum_scale: 0.01, + reflections: 2, + use_normal: UseNormal::Light, + show_axes: true, + show_shapes: true, + show_hit_emission: false, + show_miss_emission: false, + show_direct_hit: false, + show_indirect_hit: false, + show_light: true, + } + } + } + + #[diplomat::opaque_mut] + pub struct Core(crate::Core); + + impl Core { + pub fn from_xcb(connection: usize, window: u32, width: u32, height: u32) -> Box { + let display = + XcbDisplayHandle::new(Some(NonNull::new(connection as *mut _).unwrap()), 0); + let window = XcbWindowHandle::new(NonZero::new(window).unwrap()); + let gpu = unsafe { crate::Gpu::new_raw(display, window) }; + let size = uvec2(width, height); + Box::new(Self(crate::Core::new(gpu, size))) + } + + pub fn configure(&mut self, width: u32, height: u32) { + self.0.configure(uvec2(width, height)); + } + + pub fn redraw(&mut self, args: &RedrawArgs) { + self.0.redraw(args); } } } @@ -92,6 +124,23 @@ pub struct Gpu { surface: wgpu::Surface<'static>, } +impl Gpu { + unsafe fn new_raw( + display: impl Into, + window: impl Into, + ) -> Self { + 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(); + gpu + } +} + pub struct Core { device: wgpu::Device, queue: wgpu::Queue, @@ -118,27 +167,6 @@ pub fn new_tripod(device: &wgpu::Device) -> Mesh { ) } -fn loop_list(iter: impl IntoIterator) -> impl Iterator { - loop_list_ex(iter, identity, identity) -} - -fn loop_list_ex( - iter: impl IntoIterator, - mut fa: impl FnMut(T) -> U, - mut fb: impl FnMut(T) -> U, -) -> impl Iterator { - gen move { - let mut iter = iter.into_iter(); - let Some(first) = iter.next() else { return }; - yield fa(first.clone()); - for item in iter { - yield fb(item.clone()); - yield fa(item); - } - yield fb(first); - } -} - impl OrbitalCamera { fn make_ray(&self, rng: &mut impl rand::Rng) -> Ray { let off: f32 = rand_distr::StandardUniform.sample(rng); diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 191380f..c77b221 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,7 +1,4 @@ -include(impl.cmake) - qt_add_executable(photon-light - src/api.cxx src/main.cxx src/main_window.cxx src/main_window.ui diff --git a/ui/Cargo.toml b/ui/Cargo.toml deleted file mode 100644 index e12ba36..0000000 --- a/ui/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "photon-light-impl" -version = "0.1.0" -edition = "2024" - -[lib] -crate-type = ["staticlib"] - -[dependencies] -photon-light = {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 deleted file mode 100644 index de4d266..0000000 --- a/ui/impl.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# build the Rust side as a static library -set(impl_basename "${CARGO_TARGET_DIR}/release/libphoton_light_impl") - -set(cargo_cmake_args) - -if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.27") - list(APPEND cargo_cmake_args DEPENDS_EXPLICIT_ONLY) -endif() - -if("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.28") - list(APPEND cargo_cmake_args JOB_SERVER_AWARE TRUE) -endif() - -add_custom_command( - OUTPUT "${impl_basename}.a" - 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 - VERBATIM - ${cargo_cmake_args} -) - -# HACK ensure CMake *actually adds* the command above -add_custom_target(build_impl - DEPENDS "${impl_basename}.a" -) - -add_library(photon_light_impl STATIC IMPORTED) - -set_target_properties(photon_light_impl PROPERTIES - IMPORTED_LOCATION "${impl_basename}.a" -) diff --git a/ui/src/api.cxx b/ui/src/api.cxx deleted file mode 100644 index aaa2b64..0000000 --- a/ui/src/api.cxx +++ /dev/null @@ -1,57 +0,0 @@ -#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 deleted file mode 100644 index d46272e..0000000 --- a/ui/src/api.hxx +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include - -struct xcb_connection_t; - -namespace ffi { -struct Core; - -struct SphericalPosition { - float yaw = 0.; - float pitch = 0.; - float distance = 1.; -}; - -enum class UseNormal: std::uint8_t { - Light, - Camera, -}; - -struct RedrawArgs { - SphericalPosition camera_position; - SphericalPosition light_position; - float light_radius = 1.; - float light_spread = 0.; - float accum_sigma = 1.; - float accum_scale = 1.; - std::uint8_t reflections = 0; - UseNormal use_normal = UseNormal::Light; - bool show_axes = true; - bool show_shapes = true; - bool show_hit_emission = true; - bool show_miss_emission = true; - bool show_direct_hit = true; - bool show_indirect_hit = true; - bool show_light = true; -}; -} // namespace ffi - -using ffi::UseNormal; -using ffi::RedrawArgs; -using ffi::SphericalPosition; - -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 deleted file mode 100644 index ed5dce1..0000000 --- a/ui/src/lib.rs +++ /dev/null @@ -1,49 +0,0 @@ -use std::{ffi::c_void, num::NonZero, ptr::NonNull}; - -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, - 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/viewport.cxx b/ui/src/viewport.cxx index e681bd9..60d638c 100644 --- a/ui/src/viewport.cxx +++ b/ui/src/viewport.cxx @@ -63,7 +63,7 @@ void Viewport::recreate() try { const QSize device_size = size() * devicePixelRatio(); core.reset(); - core = BoxCore::from_xcb(xcb_connection, x11_window, device_size.width(), device_size.height()); + core = Core::from_xcb((std::uintptr_t)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()); } diff --git a/ui/src/viewport.hxx b/ui/src/viewport.hxx index 95839b9..5d1d738 100644 --- a/ui/src/viewport.hxx +++ b/ui/src/viewport.hxx @@ -2,7 +2,7 @@ #include -#include "api.hxx" +#include "Core.hpp" class Viewport : public QWidget { Q_OBJECT @@ -20,7 +20,7 @@ protected: void resizeEvent(QResizeEvent* event) override; private: - BoxCore core; + std::unique_ptr core; RedrawArgs args = {}; void recreate();