use crate::metal::RafxPresentableFrameMetal;
use crate::RafxResult;
use metal::CGSize;
use raw_window_handle::HasRawWindowHandle;
pub struct RafxSurfaceMetal {
layer: metal::CoreAnimationLayer,
}
impl RafxSurfaceMetal {
pub fn new(
device: &metal::Device,
raw_window_handle: &dyn HasRawWindowHandle,
width: u32,
height: u32,
) -> RafxResult<Self> {
let layer = match raw_window_handle.raw_window_handle() {
#[cfg(target_os = "macos")]
raw_window_handle::RawWindowHandle::MacOS(handle) => unsafe {
raw_window_metal::macos::metal_layer_from_handle(handle)
},
#[cfg(target_os = "ios")]
raw_window_handle::RawWindowHandle::IOS(handle) => unsafe {
raw_window_metal::ios::metal_layer_from_handle(handle)
},
_ => return Err("Cannot create RafxSurfaceMetal on this operating system".into()),
};
let layer = match layer {
raw_window_metal::Layer::Allocated(x) => Some(x),
raw_window_metal::Layer::Existing(x) => Some(x),
raw_window_metal::Layer::None => None,
}
.unwrap();
let layer =
unsafe { std::mem::transmute::<_, &metal::CoreAnimationLayerRef>(layer).to_owned() };
layer.set_device(device);
layer.set_pixel_format(metal::MTLPixelFormat::BGRA8Unorm);
layer.set_presents_with_transaction(false);
layer.set_drawable_size(metal::CGSize::new(width as f64, height as f64));
Ok(RafxSurfaceMetal { layer })
}
pub fn layer(&self) -> &metal::CoreAnimationLayer {
&self.layer
}
pub fn begin_frame(
&self,
window_width: u32,
window_height: u32,
) -> RafxResult<RafxPresentableFrameMetal> {
let drawable = self
.layer
.next_drawable()
.ok_or("Timed out while trying to acquire drawable".to_string())?
.to_owned();
self.layer.set_drawable_size(CGSize {
width: window_width as f64,
height: window_height as f64,
});
Ok(RafxPresentableFrameMetal::new(drawable))
}
}