use super::{dma_require, outcome};
use edgefirst_tensor::{CpuAccess, DType, PixelFormat, TensorDyn, TensorMemory};
fn required_with_gl() -> bool {
let set = |k: &str| std::env::var(k).is_ok_and(|v| v == "1");
if cfg!(target_os = "linux") {
set("HAL_TEST_REQUIRE_GL") && std::path::Path::new("/dev/dma_heap").exists()
} else {
set("HAL_TEST_REQUIRE_GL")
}
}
pub fn expect() -> outcome::Expect {
let served = dma_require::decide(
edgefirst_tensor::is_gpu_buffer_available(),
dma_require::required(),
&outcome::current_test(),
"no platform zero-copy buffer (no usable DMA heap, IOSurface or D3D11 device)",
);
if served || required_with_gl() {
outcome::Expect::Succeeds
} else {
outcome::Expect::MayFail("no platform zero-copy buffer on this host")
}
}
pub fn served_or_skip() -> bool {
match expect() {
outcome::Expect::Succeeds => true,
outcome::Expect::MayFail(why) => {
outcome::report_skip(&format!("{}: {why}", outcome::current_test()));
false
}
}
}
pub struct Failure(String);
impl std::fmt::Debug for Failure {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
pub fn zero_copy_only(
result: Result<TensorDyn, edgefirst_tensor::Error>,
) -> Result<TensorDyn, Failure> {
match result {
Ok(t) if t.memory() == TensorMemory::DmaBuf => Ok(t),
Ok(t) => Err(Failure(format!(
"zero-copy request fell back to {:?}",
t.memory()
))),
Err(e) => Err(Failure(format!("{e:?}"))),
}
}
pub fn image(w: usize, h: usize, fmt: PixelFormat, dtype: DType) -> Option<TensorDyn> {
outcome::allocated(
zero_copy_only(TensorDyn::image(
w,
h,
fmt,
dtype,
Some(TensorMemory::DmaBuf),
CpuAccess::ReadWrite,
)),
&format!("{w}x{h} {fmt:?}/{dtype:?} zero-copy image"),
expect(),
)
}