use std::ffi::c_void;
use std::rc::Rc;
use std::sync::Arc;
use dpi::PhysicalSize;
use crate::{
FrameProducer, GlFramebufferSource, GlFramebufferSourceImpl, HostWgpuContext, ImportOptions,
ImportedTexture, InteropError, NativeFrame, NativeFrameKind, ProducerCapabilities,
SyncMechanism, TextureOrigin, UnsupportedReason,
};
pub struct RawGlFrameProducer {
gl: Arc<glow::Context>,
proc_loader: Rc<dyn Fn(&str) -> *const c_void>,
source_fbo: u32,
size: PhysicalSize<u32>,
generation: u64,
}
impl RawGlFrameProducer {
pub fn new(
gl: Arc<glow::Context>,
proc_loader: impl Fn(&str) -> *const c_void + 'static,
source_fbo: u32,
size: PhysicalSize<u32>,
) -> Self {
Self {
gl,
proc_loader: Rc::new(proc_loader),
source_fbo,
size,
generation: 0,
}
}
pub fn set_source_fbo(&mut self, fbo: u32) {
self.source_fbo = fbo;
}
pub fn set_size(&mut self, size: PhysicalSize<u32>) {
self.size = size;
}
}
impl FrameProducer for RawGlFrameProducer {
fn capabilities(&self) -> ProducerCapabilities {
ProducerCapabilities {
supported_frames: vec![NativeFrameKind::GlFramebufferSource],
}
}
fn acquire_frame(&mut self) -> Result<NativeFrame, InteropError> {
self.generation += 1;
Ok(NativeFrame::GlFramebufferSource(GlFramebufferSource::new(
self.size,
self.generation,
SyncMechanism::None,
Rc::new(RawGlImportImpl {
gl: self.gl.clone(),
proc_loader: self.proc_loader.clone(),
source_fbo: self.source_fbo,
size: self.size,
generation: self.generation,
}),
)))
}
}
#[allow(dead_code)]
struct RawGlImportImpl {
gl: Arc<glow::Context>,
proc_loader: Rc<dyn Fn(&str) -> *const c_void>,
source_fbo: u32,
size: PhysicalSize<u32>,
generation: u64,
}
impl GlFramebufferSourceImpl for RawGlImportImpl {
fn import_into(
&self,
_frame: &GlFramebufferSource,
host: &HostWgpuContext,
_options: &ImportOptions,
) -> Result<ImportedTexture, InteropError> {
let texture = self.import_texture(host)?;
Ok(ImportedTexture {
texture,
format: wgpu::TextureFormat::Rgba8Unorm,
size: self.size,
origin: TextureOrigin::TopLeft,
generation: self.generation,
consumer_sync: SyncMechanism::ImplicitGlFlush,
})
}
}
impl RawGlImportImpl {
#[allow(unused_variables)]
fn import_texture(&self, host: &HostWgpuContext) -> Result<wgpu::Texture, InteropError> {
#[cfg(any(target_os = "linux", target_os = "android"))]
if host.backend == crate::InteropBackend::Vulkan {
return super::linux::import_gl_framebuffer_vulkan(
&self.gl,
&|name| (self.proc_loader)(name),
self.source_fbo,
self.size,
host,
);
}
#[cfg(target_os = "windows")]
if host.backend == crate::InteropBackend::Vulkan {
return super::windows::import_gl_framebuffer_vulkan_win32(
&self.gl,
&|name| (self.proc_loader)(name),
self.source_fbo,
self.size,
host,
);
}
#[cfg(target_os = "windows")]
if host.backend == crate::InteropBackend::Dx12 {
return super::dx12::import_gl_framebuffer_dx12(
&self.gl,
&|name| (self.proc_loader)(name),
self.source_fbo,
self.size,
host,
);
}
Err(InteropError::Unsupported(
UnsupportedReason::HostBackendMismatch,
))
}
}