summaryrefslogtreecommitdiffstats
path: root/wgpu/src/window
diff options
context:
space:
mode:
Diffstat (limited to 'wgpu/src/window')
-rw-r--r--wgpu/src/window/compositor.rs185
1 files changed, 114 insertions, 71 deletions
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs
index 36d6ab1a..eca54b6f 100644
--- a/wgpu/src/window/compositor.rs
+++ b/wgpu/src/window/compositor.rs
@@ -13,6 +13,7 @@ pub struct Compositor {
queue: wgpu::Queue,
staging_belt: wgpu::util::StagingBelt,
local_pool: futures::executor::LocalPool,
+ format: wgpu::TextureFormat,
}
impl Compositor {
@@ -21,8 +22,15 @@ impl Compositor {
/// Requests a new [`Compositor`] with the given [`Settings`].
///
/// Returns `None` if no compatible graphics adapter could be found.
- pub async fn request(settings: Settings) -> Option<Self> {
- let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
+ pub async fn request<W: HasRawWindowHandle>(
+ settings: Settings,
+ compatible_window: Option<&W>,
+ ) -> Option<Self> {
+ let instance = wgpu::Instance::new(settings.internal_backend);
+
+ #[allow(unsafe_code)]
+ let compatible_surface = compatible_window
+ .map(|window| unsafe { instance.create_surface(window) });
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@@ -31,10 +39,14 @@ impl Compositor {
} else {
wgpu::PowerPreference::HighPerformance
},
- compatible_surface: None,
+ compatible_surface: compatible_surface.as_ref(),
})
.await?;
+ let format = compatible_surface
+ .as_ref()
+ .and_then(|surface| surface.get_preferred_format(&adapter))?;
+
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
@@ -62,12 +74,13 @@ impl Compositor {
queue,
staging_belt,
local_pool,
+ format,
})
}
/// Creates a new rendering [`Backend`] for this [`Compositor`].
pub fn create_backend(&self) -> Backend {
- Backend::new(&self.device, self.settings)
+ Backend::new(&self.device, self.settings, self.format)
}
}
@@ -75,11 +88,16 @@ impl iced_graphics::window::Compositor for Compositor {
type Settings = Settings;
type Renderer = Renderer;
type Surface = wgpu::Surface;
- type SwapChain = wgpu::SwapChain;
- fn new(settings: Self::Settings) -> Result<(Self, Renderer), Error> {
- let compositor = futures::executor::block_on(Self::request(settings))
- .ok_or(Error::AdapterNotFound)?;
+ fn new<W: HasRawWindowHandle>(
+ settings: Self::Settings,
+ compatible_window: Option<&W>,
+ ) -> Result<(Self, Renderer), Error> {
+ let compositor = futures::executor::block_on(Self::request(
+ settings,
+ compatible_window,
+ ))
+ .ok_or(Error::AdapterNotFound)?;
let backend = compositor.create_backend();
@@ -96,85 +114,110 @@ impl iced_graphics::window::Compositor for Compositor {
}
}
- fn create_swap_chain(
+ fn configure_surface(
&mut self,
- surface: &Self::Surface,
+ surface: &mut Self::Surface,
width: u32,
height: u32,
- ) -> Self::SwapChain {
- self.device.create_swap_chain(
- surface,
- &wgpu::SwapChainDescriptor {
- usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
- format: self.settings.format,
+ ) {
+ surface.configure(
+ &self.device,
+ &wgpu::SurfaceConfiguration {
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
+ format: self.format,
present_mode: self.settings.present_mode,
width,
height,
},
- )
+ );
}
fn draw<T: AsRef<str>>(
&mut self,
renderer: &mut Self::Renderer,
- swap_chain: &mut Self::SwapChain,
+ surface: &mut Self::Surface,
viewport: &Viewport,
background_color: Color,
output: &<Self::Renderer as iced_native::Renderer>::Output,
overlay: &[T],
- ) -> mouse::Interaction {
- let frame = swap_chain.get_current_frame().expect("Next frame");
-
- let mut encoder = self.device.create_command_encoder(
- &wgpu::CommandEncoderDescriptor {
- label: Some("iced_wgpu encoder"),
+ ) -> Result<mouse::Interaction, iced_graphics::window::SurfaceError> {
+ match surface.get_current_frame() {
+ Ok(frame) => {
+ let mut encoder = self.device.create_command_encoder(
+ &wgpu::CommandEncoderDescriptor {
+ label: Some("iced_wgpu encoder"),
+ },
+ );
+
+ let view = &frame
+ .output
+ .texture
+ .create_view(&wgpu::TextureViewDescriptor::default());
+
+ let _ =
+ encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
+ label: Some(
+ "iced_wgpu::window::Compositor render pass",
+ ),
+ color_attachments: &[wgpu::RenderPassColorAttachment {
+ view,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Clear({
+ let [r, g, b, a] =
+ background_color.into_linear();
+
+ wgpu::Color {
+ r: f64::from(r),
+ g: f64::from(g),
+ b: f64::from(b),
+ a: f64::from(a),
+ }
+ }),
+ store: true,
+ },
+ }],
+ depth_stencil_attachment: None,
+ });
+
+ let mouse_interaction = renderer.backend_mut().draw(
+ &mut self.device,
+ &mut self.staging_belt,
+ &mut encoder,
+ view,
+ viewport,
+ output,
+ overlay,
+ );
+
+ // Submit work
+ self.staging_belt.finish();
+ self.queue.submit(Some(encoder.finish()));
+
+ // Recall staging buffers
+ self.local_pool
+ .spawner()
+ .spawn(self.staging_belt.recall())
+ .expect("Recall staging belt");
+
+ self.local_pool.run_until_stalled();
+
+ Ok(mouse_interaction)
+ }
+ Err(error) => match error {
+ wgpu::SurfaceError::Timeout => {
+ Err(iced_graphics::window::SurfaceError::Timeout)
+ }
+ wgpu::SurfaceError::Outdated => {
+ Err(iced_graphics::window::SurfaceError::Outdated)
+ }
+ wgpu::SurfaceError::Lost => {
+ Err(iced_graphics::window::SurfaceError::Lost)
+ }
+ wgpu::SurfaceError::OutOfMemory => {
+ Err(iced_graphics::window::SurfaceError::OutOfMemory)
+ }
},
- );
-
- let _ = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
- label: Some("iced_wgpu::window::Compositor render pass"),
- color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
- attachment: &frame.output.view,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Clear({
- let [r, g, b, a] = background_color.into_linear();
-
- wgpu::Color {
- r: f64::from(r),
- g: f64::from(g),
- b: f64::from(b),
- a: f64::from(a),
- }
- }),
- store: true,
- },
- }],
- depth_stencil_attachment: None,
- });
-
- let mouse_interaction = renderer.backend_mut().draw(
- &mut self.device,
- &mut self.staging_belt,
- &mut encoder,
- &frame.output.view,
- viewport,
- output,
- overlay,
- );
-
- // Submit work
- self.staging_belt.finish();
- self.queue.submit(Some(encoder.finish()));
-
- // Recall staging buffers
- self.local_pool
- .spawner()
- .spawn(self.staging_belt.recall())
- .expect("Recall staging belt");
-
- self.local_pool.run_until_stalled();
-
- mouse_interaction
+ }
}
}