use std::sync::{Arc, Mutex, Once, PoisonError};
use frust_gpu::RenderContext;
use frust_gpu::import::apple::{MetalImportError, MetalImporter};
use crate::texture_bus::{
ImportError, ImportedTexture, NativeHandle, NativeHandleKind, NativeImporter,
set_native_importer,
};
struct AppleImporter {
importer: Mutex<Option<MetalImporter>>,
}
impl NativeImporter for AppleImporter {
fn import(
&self,
handle: &NativeHandle,
device: &wgpu::Device,
_queue: &wgpu::Queue,
) -> Result<ImportedTexture, ImportError> {
let mut slot = self.importer.lock().unwrap_or_else(PoisonError::into_inner);
let importer = match slot.take() {
Some(importer) if importer.device() == device => importer,
_ => MetalImporter::new(device).map_err(to_import_error)?,
};
let importer = slot.insert(importer);
let (texture, size) = unsafe { importer.import(handle.ptr()) }.map_err(to_import_error)?;
Ok(ImportedTexture {
view: texture.create_view(&wgpu::TextureViewDescriptor::default()),
size,
})
}
}
fn to_import_error(error: MetalImportError) -> ImportError {
match error {
MetalImportError::Unsupported(reason) => ImportError::Unsupported(reason),
other => ImportError::Failed(other.to_string()),
}
}
pub fn install(context: &RenderContext) {
static INSTALLED: Once = Once::new();
if context.caps().is_none() {
return;
}
INSTALLED.call_once(|| {
set_native_importer(
NativeHandleKind::CvPixelBuffer,
Arc::new(AppleImporter {
importer: Mutex::new(None),
}),
);
});
}