use std::mem::transmute;
use super::super::super::objc::runtime::{Object, Sel};
use super::super::super::render::engine::RenderEngine;
use super::super::super::core::application::ApplicationTrait;
use super::super::metal as mtl;
use super::application::Application as App;
pub const DEVICE_VAR_NAME: &str = "mtl_device";
pub const APP_VAR_NAME: &str = "vukust_os_app";
pub const CLASS_NAME: &str = "GameViewController";
pub const SUPER_CLASS_NAME: &str = "NSViewController";
extern "C" fn metal_view_did_load<CoreApp>(this: &mut Object, _cmd: Sel)
where
CoreApp: ApplicationTrait,
{
let this: mtl::Id = this;
let view: mtl::Id = unsafe { msg_send![this, view] };
let app: *mut App<CoreApp> =
unsafe { transmute(*(*this).get_ivar::<mtl::NSUInteger>(APP_VAR_NAME)) };
let bounds: mtl::NSRect = unsafe { msg_send![view, bounds] };
unsafe {
(*(*app).render_engine).draw_rect_resized(&bounds.size);
}
}
extern "C" fn mtl_view<CoreApp>(this: &mut Object, _cmd: Sel, view: mtl::Id, _size: mtl::NSSize)
where
CoreApp: ApplicationTrait,
{
let bounds: mtl::NSRect = unsafe { msg_send![view, bounds] };
let app: *mut App<CoreApp> =
unsafe { transmute(*(*this).get_ivar::<mtl::NSUInteger>(APP_VAR_NAME)) };
unsafe {
(*(*app).render_engine).draw_rect_resized(&bounds.size);
}
}
extern "C" fn draw_in_mtk_view<CoreApp>(this: &mut Object, _cmd: Sel, _view: mtl::Id)
where
CoreApp: ApplicationTrait,
{
let release_pool = mtl::NsAutoReleasePool::new();
let app: &mut App<CoreApp> =
unsafe { transmute(*this.get_ivar::<mtl::NSUInteger>(APP_VAR_NAME)) };
let renderer: &mut RenderEngine<CoreApp> = unsafe { transmute(app.render_engine) };
renderer.render();
let _ = release_pool;
}
extern "C" fn get_current_render_pass_descriptor(this: &mut Object, _cmd: Sel) -> mtl::Id {
let view: mtl::Id = unsafe { msg_send![this, view] };
let desc: mtl::Id = unsafe { msg_send![view, currentRenderPassDescriptor] };
return desc;
}
extern "C" fn get_color_pixel_format(this: &mut Object, _cmd: Sel) -> mtl::NSUInteger {
let view: mtl::Id = unsafe { msg_send![this, view] };
unsafe { msg_send![view, colorPixelFormat] }
}
extern "C" fn set_color_pixel_format(this: &mut Object, _cmd: Sel, frmt: mtl::NSUInteger) {
let view: mtl::Id = unsafe { msg_send![this, view] };
unsafe {
let _: () = msg_send![view, setColorPixelFormat: frmt];
}
}
extern "C" fn get_depth_stencil_pixel_format(this: &mut Object, _cmd: Sel) -> mtl::NSUInteger {
let view: mtl::Id = unsafe { msg_send![this, view] };
unsafe { msg_send![view, depthStencilPixelFormat] }
}
extern "C" fn set_depth_stencil_pixel_format(this: &mut Object, _cmd: Sel, frmt: mtl::NSUInteger) {
let view: mtl::Id = unsafe { msg_send![this, view] };
unsafe {
let _: () = msg_send![view, setDepthStencilPixelFormat: frmt];
}
}
extern "C" fn get_sample_count(this: &mut Object, _cmd: Sel) -> mtl::NSUInteger {
let view: mtl::Id = unsafe { msg_send![this, view] };
return unsafe { msg_send![view, sampleCount] };
}
extern "C" fn set_sample_count(this: &mut Object, _cmd: Sel, sample_count: mtl::NSUInteger) {
let view: mtl::Id = unsafe { msg_send![this, view] };
unsafe {
let _: () = msg_send![view, setSampleCount: sample_count];
}
}
extern "C" fn get_current_drawable(this: &mut Object, _cmd: Sel) -> mtl::Id {
let view: mtl::Id = unsafe { msg_send![this, view] };
return unsafe { msg_send![view, currentDrawable] };
}
pub fn register<CoreApp>()
where
CoreApp: ApplicationTrait,
{
let mut self_class = mtl::dec_class_s(CLASS_NAME, SUPER_CLASS_NAME);
self_class.add_ivar::<mtl::Id>(DEVICE_VAR_NAME);
self_class.add_ivar::<mtl::NSUInteger>(APP_VAR_NAME);
unsafe {
self_class.add_method(
sel!(metalViewDidLoad),
metal_view_did_load::<CoreApp> as extern "C" fn(&mut Object, Sel),
);
self_class.add_method(
sel!(mtkView:drawableSizeWillChange:),
mtl_view::<CoreApp> as extern "C" fn(&mut Object, Sel, mtl::Id, mtl::NSSize),
);
self_class.add_method(
sel!(drawInMTKView:),
draw_in_mtk_view::<CoreApp> as extern "C" fn(&mut Object, Sel, mtl::Id),
);
self_class.add_method(
sel!(currentRenderPassDescriptor),
get_current_render_pass_descriptor as extern "C" fn(&mut Object, Sel) -> mtl::Id,
);
self_class.add_method(
sel!(colorPixelFormat),
get_color_pixel_format as extern "C" fn(&mut Object, Sel) -> mtl::NSUInteger,
);
self_class.add_method(
sel!(setColorPixelFormat:),
set_color_pixel_format as extern "C" fn(&mut Object, Sel, mtl::NSUInteger),
);
self_class.add_method(
sel!(depthStencilPixelFormat),
get_depth_stencil_pixel_format as extern "C" fn(&mut Object, Sel) -> mtl::NSUInteger,
);
self_class.add_method(
sel!(setDepthStencilPixelFormat:),
set_depth_stencil_pixel_format as extern "C" fn(&mut Object, Sel, mtl::NSUInteger),
);
self_class.add_method(
sel!(sampleCount),
get_sample_count as extern "C" fn(&mut Object, Sel) -> mtl::NSUInteger,
);
self_class.add_method(
sel!(setSampleCount:),
set_sample_count as extern "C" fn(&mut Object, Sel, mtl::NSUInteger),
);
self_class.add_method(
sel!(currentDrawable),
get_current_drawable as extern "C" fn(&mut Object, Sel) -> mtl::Id,
);
}
self_class.register();
}