#![allow(clippy::new_without_default)]
#![allow(clippy::type_complexity)]
use std::sync::{Arc, Mutex};
use irondash_run_loop::{util::Capsule, RunLoop, RunLoopSender};
use platform::PlatformTexture;
mod error;
mod log;
mod platform;
pub use error::*;
pub type Result<T> = std::result::Result<T, Error>;
pub struct Texture<Type> {
platform_texture: PlatformTexture<Type>,
}
impl<Type> Texture<Type> {
pub fn id(&self) -> i64 {
self.platform_texture.id()
}
pub fn mark_frame_available(&self) -> Result<()> {
self.platform_texture.mark_frame_available()
}
pub fn into_sendable_texture(self) -> Arc<SendableTexture<Type>> {
Arc::new(SendableTexture {
sender: RunLoop::current().new_sender(),
texture: Mutex::new(Capsule::new(self)),
})
}
}
pub trait PayloadProvider<Type>: Send + Sync {
fn get_payload(&self) -> Type;
}
impl<Type: PlatformTextureWithProvider> Texture<Type> {
pub fn new_with_provider(
engine_handle: i64,
payload_provider: Arc<dyn PayloadProvider<Type>>,
) -> Result<Self> {
Ok(Self {
platform_texture: Type::create_texture(engine_handle, payload_provider)?,
})
}
}
impl<Type: PlatformTextureWithoutProvider> Texture<Type> {
pub fn new(engine_handle: i64) -> Result<Self> {
Ok(Self {
platform_texture: Type::create_texture(engine_handle)?,
})
}
pub fn get(&self) -> Type {
Type::get(&self.platform_texture)
}
}
pub enum PixelFormat {
BGRA,
RGBA,
}
pub struct PixelData<'a> {
pub width: i32,
pub height: i32,
pub data: &'a [u8],
}
impl<'a> PixelData<'a> {
pub const FORMAT: PixelFormat = platform::PIXEL_DATA_FORMAT;
}
pub trait PixelDataProvider {
fn get(&self) -> PixelData;
}
pub type BoxedPixelData = Box<dyn PixelDataProvider>;
pub struct SimplePixelData {
width: i32,
height: i32,
data: Vec<u8>,
}
impl SimplePixelData {
pub fn new_boxed(width: i32, height: i32, data: Vec<u8>) -> Box<Self> {
Box::new(Self {
width,
height,
data,
})
}
}
impl PixelDataProvider for SimplePixelData {
fn get(&self) -> PixelData {
PixelData {
width: self.width,
height: self.height,
data: &self.data,
}
}
}
#[cfg(target_os = "android")]
mod android {
pub type NativeWindow = super::platform::NativeWindow;
pub type Surface = super::platform::Surface;
}
#[cfg(target_os = "android")]
pub use android::*;
#[cfg(any(target_os = "ios", target_os = "macos"))]
mod darwin {
pub mod io_surface {
pub use crate::platform::io_surface::*;
}
pub trait IOSurfaceProvider {
fn get(&self) -> &io_surface::IOSurface;
}
pub type BoxedIOSurface = Box<dyn IOSurfaceProvider>;
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
pub use darwin::*;
#[cfg(target_os = "linux")]
mod linux {
pub struct GLTexture<'a> {
pub target: u32, pub name: &'a u32, pub width: i32,
pub height: i32,
}
pub trait GLTextureProvider {
fn get(&self) -> GLTexture;
}
pub type BoxedGLTexture = Box<dyn GLTextureProvider>;
}
#[cfg(target_os = "linux")]
pub use linux::*;
#[cfg(target_os = "windows")]
mod windows {
use std::ffi::c_void;
pub struct TextureDescriptor<'a, HandleType> {
pub handle: &'a HandleType,
pub width: i32,
pub height: i32,
pub visible_width: i32,
pub visible_height: i32,
pub pixel_format: super::PixelFormat,
}
pub trait TextureDescriptorProvider<HandleType> {
fn get(&self) -> TextureDescriptor<HandleType>;
}
pub type BoxedTextureDescriptor<HandleType> = Box<dyn TextureDescriptorProvider<HandleType>>;
pub struct ID3D11Texture2D(pub *mut c_void);
pub struct DxgiSharedHandle(pub *mut c_void);
}
#[cfg(target_os = "windows")]
pub use windows::*;
use crate::log::OkLog;
pub struct SendableTexture<T: 'static> {
sender: RunLoopSender,
texture: Mutex<Capsule<Texture<T>>>,
}
impl<T> SendableTexture<T> {
pub fn mark_frame_available(self: &Arc<Self>) {
if self.sender.is_same_thread() {
let texture = self.texture.lock().unwrap();
let texture = texture.get_ref().unwrap();
texture.mark_frame_available().ok_log();
} else {
let texture_clone = self.clone();
self.sender.send(move || {
let texture = texture_clone.texture.lock().unwrap();
let texture = texture.get_ref().unwrap();
texture.mark_frame_available().ok_log();
});
}
}
}
pub trait PlatformTextureWithProvider: Sized {
fn create_texture(
engine_handle: i64,
payload_provider: Arc<dyn PayloadProvider<Self>>,
) -> Result<PlatformTexture<Self>>;
}
pub trait PlatformTextureWithoutProvider: Sized {
fn create_texture(engine_handle: i64) -> Result<PlatformTexture<Self>>;
fn get(texture: &PlatformTexture<Self>) -> Self;
}