diff options
Diffstat (limited to 'wgpu/src/window')
-rw-r--r-- | wgpu/src/window/compositor.rs | 208 |
1 files changed, 105 insertions, 103 deletions
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 53af19bf..500458e8 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -1,9 +1,12 @@ -use crate::{Backend, Color, Error, Renderer, Settings, Viewport}; +//! Connect a window with a renderer. +use crate::core::Color; +use crate::graphics; +use crate::graphics::compositor; +use crate::graphics::{Error, Primitive, Viewport}; +use crate::{Backend, Renderer, Settings}; use futures::stream::{self, StreamExt}; -use iced_graphics::compositor; -use iced_native::futures; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; @@ -16,14 +19,11 @@ pub struct Compositor<Theme> { adapter: wgpu::Adapter, device: wgpu::Device, queue: wgpu::Queue, - staging_belt: wgpu::util::StagingBelt, format: wgpu::TextureFormat, theme: PhantomData<Theme>, } impl<Theme> Compositor<Theme> { - const CHUNK_SIZE: u64 = 10 * 1024; - /// Requests a new [`Compositor`] with the given [`Settings`]. /// /// Returns `None` if no compatible graphics adapter could be found. @@ -53,11 +53,12 @@ impl<Theme> Compositor<Theme> { let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { - power_preference: if settings.antialiasing.is_none() { - wgpu::PowerPreference::LowPower - } else { - wgpu::PowerPreference::HighPerformance - }, + power_preference: wgpu::util::power_preference_from_env() + .unwrap_or(if settings.antialiasing.is_none() { + wgpu::PowerPreference::LowPower + } else { + wgpu::PowerPreference::HighPerformance + }), compatible_surface: compatible_surface.as_ref(), force_fallback_adapter: false, }) @@ -112,15 +113,12 @@ impl<Theme> Compositor<Theme> { .next() .await?; - let staging_belt = wgpu::util::StagingBelt::new(Self::CHUNK_SIZE); - Some(Compositor { instance, settings, adapter, device, queue, - staging_belt, format, theme: PhantomData, }) @@ -128,11 +126,82 @@ impl<Theme> Compositor<Theme> { /// Creates a new rendering [`Backend`] for this [`Compositor`]. pub fn create_backend(&self) -> Backend { - Backend::new(&self.device, self.settings, self.format) + Backend::new(&self.device, &self.queue, self.settings, self.format) + } +} + +/// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and +/// window. +pub fn new<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>( + settings: Settings, + compatible_window: Option<&W>, +) -> Result<(Compositor<Theme>, Backend), Error> { + let compositor = futures::executor::block_on(Compositor::request( + settings, + compatible_window, + )) + .ok_or(Error::GraphicsAdapterNotFound)?; + + let backend = compositor.create_backend(); + + Ok((compositor, backend)) +} + +/// Presents the given primitives with the given [`Compositor`] and [`Backend`]. +pub fn present<Theme, T: AsRef<str>>( + compositor: &mut Compositor<Theme>, + backend: &mut Backend, + surface: &mut wgpu::Surface, + primitives: &[Primitive], + viewport: &Viewport, + background_color: Color, + overlay: &[T], +) -> Result<(), compositor::SurfaceError> { + match surface.get_current_texture() { + Ok(frame) => { + let mut encoder = compositor.device.create_command_encoder( + &wgpu::CommandEncoderDescriptor { + label: Some("iced_wgpu encoder"), + }, + ); + + let view = &frame + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + + backend.present( + &compositor.device, + &compositor.queue, + &mut encoder, + Some(background_color), + view, + primitives, + viewport, + overlay, + ); + + // Submit work + let _submission = compositor.queue.submit(Some(encoder.finish())); + frame.present(); + + Ok(()) + } + Err(error) => match error { + wgpu::SurfaceError::Timeout => { + Err(compositor::SurfaceError::Timeout) + } + wgpu::SurfaceError::Outdated => { + Err(compositor::SurfaceError::Outdated) + } + wgpu::SurfaceError::Lost => Err(compositor::SurfaceError::Lost), + wgpu::SurfaceError::OutOfMemory => { + Err(compositor::SurfaceError::OutOfMemory) + } + }, } } -impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> { +impl<Theme> graphics::Compositor for Compositor<Theme> { type Settings = Settings; type Renderer = Renderer<Theme>; type Surface = wgpu::Surface; @@ -141,13 +210,7 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> { settings: Self::Settings, compatible_window: Option<&W>, ) -> Result<(Self, Self::Renderer), Error> { - let compositor = futures::executor::block_on(Self::request( - settings, - compatible_window, - )) - .ok_or(Error::GraphicsAdapterNotFound)?; - - let backend = compositor.create_backend(); + let (compositor, backend) = new(settings, compatible_window)?; Ok((compositor, Renderer::new(backend))) } @@ -155,13 +218,16 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> { fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( &mut self, window: &W, + width: u32, + height: u32, ) -> wgpu::Surface { #[allow(unsafe_code)] - unsafe { - self.instance - .create_surface(window) - .expect("Create surface") - } + let mut surface = unsafe { self.instance.create_surface(window) } + .expect("Create surface"); + + self.configure_surface(&mut surface, width, height); + + surface } fn configure_surface( @@ -201,80 +267,16 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> { background_color: Color, overlay: &[T], ) -> Result<(), compositor::SurfaceError> { - match surface.get_current_texture() { - Ok(frame) => { - let mut encoder = self.device.create_command_encoder( - &wgpu::CommandEncoderDescriptor { - label: Some("iced_wgpu encoder"), - }, - ); - - let view = &frame - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - - let _ = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some( - "iced_wgpu::window::Compositor render pass", - ), - color_attachments: &[Some( - 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, - }); - - renderer.with_primitives(|backend, primitives| { - backend.present( - &self.device, - &mut self.staging_belt, - &mut encoder, - view, - primitives, - viewport, - overlay, - ); - }); - - // Submit work - self.staging_belt.finish(); - let _submission = self.queue.submit(Some(encoder.finish())); - frame.present(); - - // Recall staging buffers - self.staging_belt.recall(); - - Ok(()) - } - Err(error) => match error { - wgpu::SurfaceError::Timeout => { - Err(compositor::SurfaceError::Timeout) - } - wgpu::SurfaceError::Outdated => { - Err(compositor::SurfaceError::Outdated) - } - wgpu::SurfaceError::Lost => Err(compositor::SurfaceError::Lost), - wgpu::SurfaceError::OutOfMemory => { - Err(compositor::SurfaceError::OutOfMemory) - } - }, - } + renderer.with_primitives(|backend, primitives| { + present( + self, + backend, + surface, + primitives, + viewport, + background_color, + overlay, + ) + }) } } |