use crate::{
GlFramebufferSource, HostWgpuContext, ImportOptions, ImportedTexture, InteropError,
SyncMechanism, TextureOrigin,
};
use super::SurfmanGlFrameSource;
pub(super) fn import_current_frame(
source: &SurfmanGlFrameSource,
frame: &GlFramebufferSource,
host: &HostWgpuContext,
_options: &ImportOptions,
) -> Result<ImportedTexture, InteropError> {
let device = &source.context.device.borrow();
let mut context = source.context.context.borrow_mut();
device
.make_context_current(&mut context)
.map_err(|err| InteropError::Surfman(format!("{err:?}")))?;
match crate::raw_gl::angle_d3d11::import_angle_d3d11_frame(source.size, host) {
Ok(texture) => {
return Ok(ImportedTexture {
texture,
format: wgpu::TextureFormat::Bgra8Unorm,
size: frame.size(),
origin: TextureOrigin::BottomLeft,
generation: source.generation,
consumer_sync: SyncMechanism::ImplicitGlFlush,
});
}
Err(_) => {
}
}
let surface = device
.unbind_surface_from_context(&mut context)
.map_err(|err| InteropError::Surfman(format!("{err:?}")))?
.ok_or(InteropError::InvalidFrame("no surfman surface available"))?;
device
.make_context_current(&mut context)
.map_err(|err| InteropError::Surfman(format!("{err:?}")))?;
let surface_info = device.surface_info(&surface);
let source_fbo = surface_info
.framebuffer_object
.map(|fb| fb.0.get())
.unwrap_or(0);
let result = crate::raw_gl::windows::import_gl_framebuffer_vulkan_win32(
&source.context.glow_gl,
&|name| device.get_proc_address(&context, name),
source_fbo,
source.size,
host,
);
let rebind = device
.bind_surface_to_context(&mut context, surface)
.map_err(|(err, mut surface)| {
let _ = device.destroy_surface(&mut context, &mut surface);
InteropError::Surfman(format!("rebind after import failed: {err:?}"))
});
let texture = result?;
rebind?;
Ok(ImportedTexture {
texture,
format: wgpu::TextureFormat::Rgba8Unorm,
size: frame.size(),
origin: TextureOrigin::BottomLeft,
generation: source.generation,
consumer_sync: SyncMechanism::ImplicitGlFlush,
})
}
pub(super) fn import_current_frame_dx12(
source: &SurfmanGlFrameSource,
frame: &GlFramebufferSource,
host: &HostWgpuContext,
_options: &ImportOptions,
) -> Result<ImportedTexture, InteropError> {
let device = &source.context.device.borrow();
let mut context = source.context.context.borrow_mut();
device
.make_context_current(&mut context)
.map_err(|err| InteropError::Surfman(format!("{err:?}")))?;
let bound_fbo = surface_fbo(device, &context);
match super::windows_dx12_shared::import_current_frame(
&source.angle_dx12_shared,
device,
&mut context,
&source.context.glow_gl,
bound_fbo,
source.size,
host,
) {
Ok(texture) => {
return Ok(ImportedTexture {
texture,
format: wgpu::TextureFormat::Rgba8Unorm,
size: frame.size(),
origin: TextureOrigin::BottomLeft,
generation: source.generation,
consumer_sync: SyncMechanism::ImplicitGlFlush,
});
}
Err(_) => {
}
}
let surface = device
.unbind_surface_from_context(&mut context)
.map_err(|err| InteropError::Surfman(format!("{err:?}")))?
.ok_or(InteropError::InvalidFrame("no surfman surface available"))?;
device
.make_context_current(&mut context)
.map_err(|err| InteropError::Surfman(format!("{err:?}")))?;
let surface_info = device.surface_info(&surface);
let source_fbo = surface_info
.framebuffer_object
.map(|fb| fb.0.get())
.unwrap_or(0);
let result = crate::raw_gl::dx12::import_gl_framebuffer_dx12(
&source.context.glow_gl,
&|name| device.get_proc_address(&context, name),
source_fbo,
source.size,
host,
);
let rebind = device
.bind_surface_to_context(&mut context, surface)
.map_err(|(err, mut surface)| {
let _ = device.destroy_surface(&mut context, &mut surface);
InteropError::Surfman(format!("rebind after import failed: {err:?}"))
});
let texture = result?;
rebind?;
Ok(ImportedTexture {
texture,
format: wgpu::TextureFormat::Rgba8Unorm,
size: frame.size(),
origin: TextureOrigin::BottomLeft,
generation: source.generation,
consumer_sync: SyncMechanism::ImplicitGlFlush,
})
}
pub(super) fn surface_fbo(device: &surfman::Device, context: &surfman::Context) -> u32 {
device
.context_surface_info(context)
.ok()
.flatten()
.and_then(|info| info.framebuffer_object)
.map(|fb| fb.0.get())
.unwrap_or(0)
}