use a vtable instead of direct linking
This commit is contained in:
parent
41e747d9c2
commit
96c75c3571
|
|
@ -4,54 +4,13 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace ffi {
|
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" ICore* 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
|
} // 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) {
|
BoxCore BoxCore::from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height) {
|
||||||
if (!connection)
|
if (!connection)
|
||||||
throw std::logic_error("attempt to use a null connection");
|
throw std::logic_error("attempt to use a null connection");
|
||||||
if (!window)
|
if (!window)
|
||||||
throw std::logic_error("attempt to use a null window");
|
throw std::logic_error("attempt to use a null window");
|
||||||
BoxCore out;
|
return BoxCore{ffi::rt4_viewport_create(connection, window, width, height)};
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,32 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
struct xcb_connection_t;
|
struct xcb_connection_t;
|
||||||
|
|
||||||
|
class IBoxed {
|
||||||
|
friend struct BoxDeleter;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~IBoxed() = delete;
|
||||||
|
virtual void destroy() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BoxDeleter {
|
||||||
|
void operator()(IBoxed* obj) {
|
||||||
|
obj->destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using Box = std::unique_ptr<T, BoxDeleter>;
|
||||||
|
|
||||||
struct alignas(16) Vec4 {
|
struct alignas(16) Vec4 {
|
||||||
float x, y, z, w;
|
float x, y, z, w;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ffi {
|
namespace ffi {
|
||||||
struct Core;
|
|
||||||
|
|
||||||
struct RedrawArgs {
|
struct RedrawArgs {
|
||||||
float cam_yaw;
|
float cam_yaw;
|
||||||
float cam_pitch;
|
float cam_pitch;
|
||||||
|
|
@ -21,36 +38,14 @@ struct RedrawArgs {
|
||||||
|
|
||||||
using ffi::RedrawArgs;
|
using ffi::RedrawArgs;
|
||||||
|
|
||||||
class MutCore {
|
class ICore : public IBoxed {
|
||||||
friend class BoxCore;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit operator bool() const { return ptr; }
|
virtual void configure(std::uint32_t width, std::uint32_t height) = 0;
|
||||||
|
virtual void redraw(const RedrawArgs& args) = 0;
|
||||||
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 {
|
class BoxCore : public Box<ICore> {
|
||||||
public:
|
public:
|
||||||
BoxCore() = default;
|
using Box<ICore>::Box;
|
||||||
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);
|
static BoxCore from_xcb(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height);
|
||||||
|
|
||||||
private:
|
|
||||||
MutCore ptr;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,74 @@ use PROJECT_NAME::{Core, RedrawArgs, init_gpu_inner};
|
||||||
use glam::{UVec2, uvec2};
|
use glam::{UVec2, uvec2};
|
||||||
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle};
|
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle};
|
||||||
|
|
||||||
|
use crate::vtable::ICoreImpl;
|
||||||
|
|
||||||
|
mod vtable {
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
use PROJECT_NAME::{Core, RedrawArgs};
|
||||||
|
use glam::uvec2;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct ICoreVTable {
|
||||||
|
destroy: unsafe extern "C" fn(this: Box<ICoreImpl>),
|
||||||
|
configure: unsafe extern "C" fn(this: &mut ICoreImpl, width: u32, height: u32),
|
||||||
|
redraw: unsafe extern "C" fn(this: &mut ICoreImpl, args: &RedrawArgs),
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn destroy(this: Box<ICoreImpl>) {
|
||||||
|
drop(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn configure(this: &mut ICoreImpl, width: u32, height: u32) {
|
||||||
|
this.core.configure(uvec2(width, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn redraw(this: &mut ICoreImpl, args: &RedrawArgs) {
|
||||||
|
this.core.redraw(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VTABLE: ICoreVTable = ICoreVTable {
|
||||||
|
destroy: destroy,
|
||||||
|
configure: configure,
|
||||||
|
redraw: redraw,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub(crate) struct ICoreImpl {
|
||||||
|
vtable: &'static ICoreVTable,
|
||||||
|
core: Core,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ICoreImpl {
|
||||||
|
pub(crate) fn new(core: Core) -> Box<Self> {
|
||||||
|
Box::new(ICoreImpl {
|
||||||
|
vtable: &VTABLE,
|
||||||
|
core,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for ICoreImpl {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.core
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for ICoreImpl {
|
||||||
|
type Target = Core;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.core
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_viewport(
|
unsafe fn create_viewport(
|
||||||
display: impl Into<RawDisplayHandle>,
|
display: impl Into<RawDisplayHandle>,
|
||||||
window: impl Into<RawWindowHandle>,
|
window: impl Into<RawWindowHandle>,
|
||||||
size: UVec2,
|
size: UVec2,
|
||||||
) -> Box<Core> {
|
) -> Box<ICoreImpl> {
|
||||||
let target = wgpu::SurfaceTargetUnsafe::RawHandle {
|
let target = wgpu::SurfaceTargetUnsafe::RawHandle {
|
||||||
raw_display_handle: display.into(),
|
raw_display_handle: display.into(),
|
||||||
raw_window_handle: window.into(),
|
raw_window_handle: window.into(),
|
||||||
|
|
@ -17,7 +80,7 @@ unsafe fn create_viewport(
|
||||||
instance.create_surface_unsafe(target)
|
instance.create_surface_unsafe(target)
|
||||||
}))
|
}))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Box::new(Core::new(gpu, size))
|
ICoreImpl::new(Core::new(gpu, size))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
|
|
@ -26,23 +89,8 @@ unsafe extern "C" fn rt4_viewport_create(
|
||||||
window: NonZero<u32>,
|
window: NonZero<u32>,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Box<Core> {
|
) -> Box<ICoreImpl> {
|
||||||
let display = XcbDisplayHandle::new(Some(connection), 0);
|
let display = XcbDisplayHandle::new(Some(connection), 0);
|
||||||
let window = XcbWindowHandle::new(window);
|
let window = XcbWindowHandle::new(window);
|
||||||
unsafe { create_viewport(display, window, uvec2(width, height)) }
|
unsafe { create_viewport(display, window, uvec2(width, height)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
|
||||||
unsafe extern "C" fn rt4_viewport_destroy(viewport: Box<Core>) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user