Allow iced_wgpu
to render to any TextureView
This commit is contained in:
parent
95880ca74b
commit
f1e20a61f1
@ -1,6 +1,6 @@
|
||||
//! Build window-based GUI applications.
|
||||
mod backend;
|
||||
mod event;
|
||||
mod renderer;
|
||||
|
||||
pub use backend::Backend;
|
||||
pub use event::Event;
|
||||
pub use renderer::{Renderer, Target};
|
||||
|
55
native/src/window/backend.rs
Normal file
55
native/src/window/backend.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use crate::MouseCursor;
|
||||
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
|
||||
/// A graphics backend that can render to windows.
|
||||
pub trait Backend: Sized {
|
||||
/// The settings of the backend.
|
||||
type Settings: Default;
|
||||
|
||||
/// The iced renderer of the backend.
|
||||
type Renderer: crate::Renderer;
|
||||
|
||||
/// The surface of the backend.
|
||||
type Surface;
|
||||
|
||||
/// The swap chain of the backend.
|
||||
type SwapChain;
|
||||
|
||||
/// Creates a new [`Backend`] and an associated iced renderer.
|
||||
///
|
||||
/// [`Backend`]: trait.Backend.html
|
||||
fn new(settings: Self::Settings) -> (Self, Self::Renderer);
|
||||
|
||||
/// Crates a new [`Surface`] for the given window.
|
||||
///
|
||||
/// [`Surface`]: #associatedtype.Surface
|
||||
fn create_surface<W: HasRawWindowHandle>(
|
||||
&mut self,
|
||||
window: &W,
|
||||
) -> Self::Surface;
|
||||
|
||||
/// Crates a new [`SwapChain`] for the given [`Surface`].
|
||||
///
|
||||
/// [`SwapChain`]: #associatedtype.SwapChain
|
||||
/// [`Surface`]: #associatedtype.Surface
|
||||
fn create_swap_chain(
|
||||
&mut self,
|
||||
surface: &Self::Surface,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f64,
|
||||
) -> Self::SwapChain;
|
||||
|
||||
/// Draws the output primitives to the next frame of the given [`SwapChain`].
|
||||
///
|
||||
/// [`SwapChain`]: #associatedtype.SwapChain
|
||||
/// [`Surface`]: #associatedtype.Surface
|
||||
fn draw<T: AsRef<str>>(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
swap_chain: &mut Self::SwapChain,
|
||||
output: &<Self::Renderer as crate::Renderer>::Output,
|
||||
overlay: &[T],
|
||||
) -> MouseCursor;
|
||||
}
|
@ -2,57 +2,54 @@ use crate::MouseCursor;
|
||||
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
|
||||
/// A renderer that can target windows.
|
||||
pub trait Renderer: crate::Renderer + Sized {
|
||||
/// The settings of the renderer.
|
||||
/// A graphics backend that can render to windows.
|
||||
pub trait Backend: Sized {
|
||||
/// The settings of the backend.
|
||||
type Settings: Default;
|
||||
|
||||
/// The type of target.
|
||||
type Target: Target<Renderer = Self>;
|
||||
/// The iced renderer of the backend.
|
||||
type Renderer: crate::Renderer;
|
||||
|
||||
/// Creates a new window [`Renderer`].
|
||||
///
|
||||
/// [`Renderer`]: trait.Renderer.html
|
||||
fn new(settings: Self::Settings) -> Self;
|
||||
/// The surface of the backend.
|
||||
type Surface;
|
||||
|
||||
/// Performs the drawing operations described in the output on the given
|
||||
/// target.
|
||||
/// The target of the backend.
|
||||
type Target;
|
||||
|
||||
/// Creates a new [`Gpu`] and an associated iced renderer.
|
||||
///
|
||||
/// The overlay can be a bunch of debug text logs. It should be rendered on
|
||||
/// top of the GUI on most scenarios.
|
||||
/// [`Gpu`]: trait.Gpu.html
|
||||
fn new(settings: Self::Settings) -> (Self, Self::Renderer);
|
||||
|
||||
/// Crates a new [`Surface`] for the given window.
|
||||
///
|
||||
/// [`Surface`]: #associatedtype.Surface
|
||||
fn create_surface<W: HasRawWindowHandle>(
|
||||
&mut self,
|
||||
window: &W,
|
||||
) -> Self::Surface;
|
||||
|
||||
/// Crates a new [`Target`] for the given [`Surface`].
|
||||
///
|
||||
/// [`Target`]: #associatedtype.Target
|
||||
/// [`Surface`]: #associatedtype.Surface
|
||||
fn create_target(
|
||||
&mut self,
|
||||
surface: &Self::Surface,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f64,
|
||||
) -> Self::Target;
|
||||
|
||||
/// Draws the output primitives to the given [`Target`].
|
||||
///
|
||||
/// [`Target`]: #associatedtype.Target
|
||||
/// [`Surface`]: #associatedtype.Surface
|
||||
fn draw<T: AsRef<str>>(
|
||||
&mut self,
|
||||
output: &Self::Output,
|
||||
overlay: &[T],
|
||||
renderer: &mut Self::Renderer,
|
||||
target: &mut Self::Target,
|
||||
output: &<Self::Renderer as crate::Renderer>::Output,
|
||||
overlay: &[T],
|
||||
) -> MouseCursor;
|
||||
}
|
||||
|
||||
/// A rendering target.
|
||||
pub trait Target {
|
||||
/// The renderer of this target.
|
||||
type Renderer;
|
||||
|
||||
/// Creates a new rendering [`Target`] from the given window handle, width,
|
||||
/// height and dpi factor.
|
||||
///
|
||||
/// [`Target`]: trait.Target.html
|
||||
fn new<W: HasRawWindowHandle>(
|
||||
window: &W,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f64,
|
||||
renderer: &Self::Renderer,
|
||||
) -> Self;
|
||||
|
||||
/// Resizes the current [`Target`].
|
||||
///
|
||||
/// [`Target`]: trait.Target.html
|
||||
fn resize(
|
||||
&mut self,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f64,
|
||||
renderer: &Self::Renderer,
|
||||
);
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ impl<A> iced_winit::Application for Instance<A>
|
||||
where
|
||||
A: Application,
|
||||
{
|
||||
type Renderer = iced_wgpu::Renderer;
|
||||
type Backend = iced_wgpu::window::Backend;
|
||||
type Executor = A::Executor;
|
||||
type Message = A::Message;
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
//! [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
|
||||
//! [WebGPU API]: https://gpuweb.github.io/gpuweb/
|
||||
//! [`wgpu_glyph`]: https://github.com/hecrj/wgpu_glyph
|
||||
#![deny(missing_docs)]
|
||||
//#![deny(missing_docs)]
|
||||
#![deny(missing_debug_implementations)]
|
||||
#![deny(unused_results)]
|
||||
#![forbid(unsafe_code)]
|
||||
@ -27,19 +27,25 @@
|
||||
pub mod defaults;
|
||||
pub mod triangle;
|
||||
pub mod widget;
|
||||
pub mod window;
|
||||
|
||||
mod image;
|
||||
mod primitive;
|
||||
mod quad;
|
||||
mod renderer;
|
||||
mod settings;
|
||||
mod target;
|
||||
mod text;
|
||||
mod transformation;
|
||||
mod viewport;
|
||||
|
||||
pub use defaults::Defaults;
|
||||
pub use primitive::Primitive;
|
||||
pub use renderer::{Renderer, Target};
|
||||
pub use renderer::Renderer;
|
||||
pub use settings::Settings;
|
||||
pub use target::Target;
|
||||
pub use viewport::Viewport;
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use widget::*;
|
||||
|
||||
|
@ -1,29 +1,20 @@
|
||||
use crate::{
|
||||
image, quad, text, triangle, Defaults, Image, Primitive, Quad, Settings,
|
||||
Transformation,
|
||||
Target, Transformation,
|
||||
};
|
||||
use iced_native::{
|
||||
layout, window, Background, Color, Layout, MouseCursor, Point, Rectangle,
|
||||
Vector, Widget,
|
||||
layout, Background, Color, Layout, MouseCursor, Point, Rectangle, Vector,
|
||||
Widget,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use wgpu::{
|
||||
Adapter, BackendBit, CommandEncoderDescriptor, Device, DeviceDescriptor,
|
||||
Extensions, Limits, PowerPreference, Queue, RequestAdapterOptions,
|
||||
};
|
||||
|
||||
mod target;
|
||||
mod widget;
|
||||
|
||||
pub use target::Target;
|
||||
|
||||
/// A [`wgpu`] renderer.
|
||||
///
|
||||
/// [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
|
||||
#[derive(Debug)]
|
||||
pub struct Renderer {
|
||||
device: Device,
|
||||
queue: Queue,
|
||||
quad_pipeline: quad::Pipeline,
|
||||
image_pipeline: image::Pipeline,
|
||||
text_pipeline: text::Pipeline,
|
||||
@ -53,29 +44,16 @@ impl<'a> Layer<'a> {
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
fn new(settings: Settings) -> Self {
|
||||
let adapter = Adapter::request(&RequestAdapterOptions {
|
||||
power_preference: PowerPreference::Default,
|
||||
backends: BackendBit::all(),
|
||||
})
|
||||
.expect("Request adapter");
|
||||
|
||||
let (mut device, queue) = adapter.request_device(&DeviceDescriptor {
|
||||
extensions: Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
limits: Limits { max_bind_groups: 2 },
|
||||
});
|
||||
|
||||
let text_pipeline =
|
||||
text::Pipeline::new(&mut device, settings.default_font);
|
||||
let quad_pipeline = quad::Pipeline::new(&mut device);
|
||||
let image_pipeline = crate::image::Pipeline::new(&mut device);
|
||||
let triangle_pipeline = triangle::Pipeline::new(&mut device);
|
||||
/// Creates a new [`Renderer`].
|
||||
///
|
||||
/// [`Renderer`]: struct.Renderer.html
|
||||
pub fn new(settings: Settings, device: &mut wgpu::Device) -> Self {
|
||||
let text_pipeline = text::Pipeline::new(device, settings.default_font);
|
||||
let quad_pipeline = quad::Pipeline::new(device);
|
||||
let image_pipeline = crate::image::Pipeline::new(device);
|
||||
let triangle_pipeline = triangle::Pipeline::new(device);
|
||||
|
||||
Self {
|
||||
device,
|
||||
queue,
|
||||
quad_pipeline,
|
||||
image_pipeline,
|
||||
text_pipeline,
|
||||
@ -83,38 +61,25 @@ impl Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
fn draw<T: AsRef<str>>(
|
||||
/// Draws the provided primitives in the given [`Target`].
|
||||
///
|
||||
/// The text provided as overlay will be renderer on top of the primitives.
|
||||
/// This is useful for rendering debug information.
|
||||
///
|
||||
/// [`Target`]: struct.Target.html
|
||||
pub fn draw<T: AsRef<str>>(
|
||||
&mut self,
|
||||
device: &mut wgpu::Device,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
target: Target<'_>,
|
||||
(primitive, mouse_cursor): &(Primitive, MouseCursor),
|
||||
overlay: &[T],
|
||||
target: &mut Target,
|
||||
) -> MouseCursor {
|
||||
log::debug!("Drawing");
|
||||
|
||||
let (width, height) = target.dimensions();
|
||||
let scale_factor = target.scale_factor();
|
||||
let transformation = target.transformation();
|
||||
let frame = target.next_frame();
|
||||
|
||||
let mut encoder = self
|
||||
.device
|
||||
.create_command_encoder(&CommandEncoderDescriptor { todo: 0 });
|
||||
|
||||
let _ = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &frame.view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 1.0,
|
||||
g: 1.0,
|
||||
b: 1.0,
|
||||
a: 1.0,
|
||||
},
|
||||
}],
|
||||
depth_stencil_attachment: None,
|
||||
});
|
||||
let (width, height) = target.viewport.dimensions();
|
||||
let scale_factor = target.viewport.scale_factor();
|
||||
let transformation = target.viewport.transformation();
|
||||
|
||||
let mut layers = Vec::new();
|
||||
|
||||
@ -133,15 +98,15 @@ impl Renderer {
|
||||
|
||||
for layer in layers {
|
||||
self.flush(
|
||||
device,
|
||||
scale_factor,
|
||||
transformation,
|
||||
&layer,
|
||||
&mut encoder,
|
||||
&frame.view,
|
||||
encoder,
|
||||
target.texture,
|
||||
);
|
||||
}
|
||||
|
||||
self.queue.submit(&[encoder.finish()]);
|
||||
self.image_pipeline.trim_cache();
|
||||
|
||||
*mouse_cursor
|
||||
@ -336,6 +301,7 @@ impl Renderer {
|
||||
|
||||
fn flush(
|
||||
&mut self,
|
||||
device: &mut wgpu::Device,
|
||||
scale_factor: f32,
|
||||
transformation: Transformation,
|
||||
layer: &Layer<'_>,
|
||||
@ -352,7 +318,7 @@ impl Renderer {
|
||||
);
|
||||
|
||||
self.triangle_pipeline.draw(
|
||||
&mut self.device,
|
||||
device,
|
||||
encoder,
|
||||
target,
|
||||
translated,
|
||||
@ -364,7 +330,7 @@ impl Renderer {
|
||||
|
||||
if layer.quads.len() > 0 {
|
||||
self.quad_pipeline.draw(
|
||||
&mut self.device,
|
||||
device,
|
||||
encoder,
|
||||
&layer.quads,
|
||||
transformation,
|
||||
@ -383,7 +349,7 @@ impl Renderer {
|
||||
);
|
||||
|
||||
self.image_pipeline.draw(
|
||||
&mut self.device,
|
||||
device,
|
||||
encoder,
|
||||
&layer.images,
|
||||
translated_and_scaled,
|
||||
@ -429,7 +395,7 @@ impl Renderer {
|
||||
}
|
||||
|
||||
self.text_pipeline.draw_queued(
|
||||
&mut self.device,
|
||||
device,
|
||||
encoder,
|
||||
target,
|
||||
transformation,
|
||||
@ -461,24 +427,6 @@ impl iced_native::Renderer for Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
impl window::Renderer for Renderer {
|
||||
type Settings = Settings;
|
||||
type Target = Target;
|
||||
|
||||
fn new(settings: Settings) -> Self {
|
||||
Self::new(settings)
|
||||
}
|
||||
|
||||
fn draw<T: AsRef<str>>(
|
||||
&mut self,
|
||||
output: &Self::Output,
|
||||
overlay: &[T],
|
||||
target: &mut Target,
|
||||
) -> MouseCursor {
|
||||
self.draw(output, overlay, target)
|
||||
}
|
||||
}
|
||||
|
||||
impl layout::Debugger for Renderer {
|
||||
fn explain<Message>(
|
||||
&mut self,
|
||||
|
@ -1,91 +0,0 @@
|
||||
use crate::{Renderer, Transformation};
|
||||
use iced_native::window;
|
||||
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
|
||||
/// A rendering target.
|
||||
#[derive(Debug)]
|
||||
pub struct Target {
|
||||
surface: wgpu::Surface,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f32,
|
||||
transformation: Transformation,
|
||||
swap_chain: wgpu::SwapChain,
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub(crate) fn dimensions(&self) -> (u32, u32) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
|
||||
pub(crate) fn scale_factor(&self) -> f32 {
|
||||
self.scale_factor
|
||||
}
|
||||
|
||||
pub(crate) fn transformation(&self) -> Transformation {
|
||||
self.transformation
|
||||
}
|
||||
|
||||
pub(crate) fn next_frame(&mut self) -> wgpu::SwapChainOutput<'_> {
|
||||
self.swap_chain.get_next_texture()
|
||||
}
|
||||
}
|
||||
|
||||
impl window::Target for Target {
|
||||
type Renderer = Renderer;
|
||||
|
||||
fn new<W: HasRawWindowHandle>(
|
||||
window: &W,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f64,
|
||||
renderer: &Renderer,
|
||||
) -> Target {
|
||||
let surface = wgpu::Surface::create(window);
|
||||
let swap_chain =
|
||||
new_swap_chain(&surface, width, height, &renderer.device);
|
||||
|
||||
Target {
|
||||
surface,
|
||||
width,
|
||||
height,
|
||||
scale_factor: scale_factor as f32,
|
||||
transformation: Transformation::orthographic(width, height),
|
||||
swap_chain,
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f64,
|
||||
renderer: &Renderer,
|
||||
) {
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
self.scale_factor = scale_factor as f32;
|
||||
self.transformation = Transformation::orthographic(width, height);
|
||||
self.swap_chain =
|
||||
new_swap_chain(&self.surface, width, height, &renderer.device);
|
||||
}
|
||||
}
|
||||
|
||||
fn new_swap_chain(
|
||||
surface: &wgpu::Surface,
|
||||
width: u32,
|
||||
height: u32,
|
||||
device: &wgpu::Device,
|
||||
) -> wgpu::SwapChain {
|
||||
device.create_swap_chain(
|
||||
&surface,
|
||||
&wgpu::SwapChainDescriptor {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
width,
|
||||
height,
|
||||
present_mode: wgpu::PresentMode::Vsync,
|
||||
},
|
||||
)
|
||||
}
|
8
wgpu/src/target.rs
Normal file
8
wgpu/src/target.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use crate::Viewport;
|
||||
|
||||
/// A rendering target.
|
||||
#[derive(Debug)]
|
||||
pub struct Target<'a> {
|
||||
pub texture: &'a wgpu::TextureView,
|
||||
pub viewport: &'a Viewport,
|
||||
}
|
32
wgpu/src/viewport.rs
Normal file
32
wgpu/src/viewport.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::Transformation;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Viewport {
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f32,
|
||||
transformation: Transformation,
|
||||
}
|
||||
|
||||
impl Viewport {
|
||||
pub fn new(width: u32, height: u32, scale_factor: f64) -> Viewport {
|
||||
Viewport {
|
||||
width,
|
||||
height,
|
||||
scale_factor: scale_factor as f32,
|
||||
transformation: Transformation::orthographic(width, height),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dimensions(&self) -> (u32, u32) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
|
||||
pub fn scale_factor(&self) -> f32 {
|
||||
self.scale_factor
|
||||
}
|
||||
|
||||
pub(crate) fn transformation(&self) -> Transformation {
|
||||
self.transformation
|
||||
}
|
||||
}
|
5
wgpu/src/window.rs
Normal file
5
wgpu/src/window.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod backend;
|
||||
mod swap_chain;
|
||||
|
||||
pub use backend::Backend;
|
||||
pub use swap_chain::SwapChain;
|
99
wgpu/src/window/backend.rs
Normal file
99
wgpu/src/window/backend.rs
Normal file
@ -0,0 +1,99 @@
|
||||
use crate::{window::SwapChain, Renderer, Settings, Target};
|
||||
|
||||
use iced_native::MouseCursor;
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Backend {
|
||||
device: wgpu::Device,
|
||||
queue: wgpu::Queue,
|
||||
}
|
||||
|
||||
impl iced_native::window::Backend for Backend {
|
||||
type Settings = Settings;
|
||||
type Renderer = Renderer;
|
||||
type Surface = wgpu::Surface;
|
||||
type SwapChain = SwapChain;
|
||||
|
||||
fn new(settings: Self::Settings) -> (Backend, Renderer) {
|
||||
let adapter = wgpu::Adapter::request(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
backends: wgpu::BackendBit::all(),
|
||||
})
|
||||
.expect("Request adapter");
|
||||
|
||||
let (mut device, queue) =
|
||||
adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
limits: wgpu::Limits { max_bind_groups: 2 },
|
||||
});
|
||||
|
||||
let renderer = Renderer::new(settings, &mut device);
|
||||
|
||||
(Backend { device, queue }, renderer)
|
||||
}
|
||||
|
||||
fn create_surface<W: HasRawWindowHandle>(
|
||||
&mut self,
|
||||
window: &W,
|
||||
) -> wgpu::Surface {
|
||||
wgpu::Surface::create(window)
|
||||
}
|
||||
|
||||
fn create_swap_chain(
|
||||
&mut self,
|
||||
surface: &Self::Surface,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f64,
|
||||
) -> SwapChain {
|
||||
SwapChain::new(&self.device, surface, width, height, scale_factor)
|
||||
}
|
||||
|
||||
fn draw<T: AsRef<str>>(
|
||||
&mut self,
|
||||
renderer: &mut Self::Renderer,
|
||||
swap_chain: &mut SwapChain,
|
||||
output: &<Self::Renderer as iced_native::Renderer>::Output,
|
||||
overlay: &[T],
|
||||
) -> MouseCursor {
|
||||
let (frame, viewport) = swap_chain.next_frame();
|
||||
|
||||
let mut encoder = self.device.create_command_encoder(
|
||||
&wgpu::CommandEncoderDescriptor { todo: 0 },
|
||||
);
|
||||
|
||||
let _ = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &frame.view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 1.0,
|
||||
g: 1.0,
|
||||
b: 1.0,
|
||||
a: 1.0,
|
||||
},
|
||||
}],
|
||||
depth_stencil_attachment: None,
|
||||
});
|
||||
|
||||
let mouse_cursor = renderer.draw(
|
||||
&mut self.device,
|
||||
&mut encoder,
|
||||
Target {
|
||||
texture: &frame.view,
|
||||
viewport,
|
||||
},
|
||||
output,
|
||||
overlay,
|
||||
);
|
||||
|
||||
self.queue.submit(&[encoder.finish()]);
|
||||
|
||||
mouse_cursor
|
||||
}
|
||||
}
|
49
wgpu/src/window/swap_chain.rs
Normal file
49
wgpu/src/window/swap_chain.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use crate::Viewport;
|
||||
|
||||
/// The rendering target of a window.
|
||||
///
|
||||
/// It represents a series of virtual framebuffers with a scale factor.
|
||||
#[derive(Debug)]
|
||||
pub struct SwapChain {
|
||||
raw: wgpu::SwapChain,
|
||||
viewport: Viewport,
|
||||
}
|
||||
|
||||
impl SwapChain {}
|
||||
|
||||
impl SwapChain {
|
||||
pub fn new(
|
||||
device: &wgpu::Device,
|
||||
surface: &wgpu::Surface,
|
||||
width: u32,
|
||||
height: u32,
|
||||
scale_factor: f64,
|
||||
) -> SwapChain {
|
||||
SwapChain {
|
||||
raw: new_swap_chain(surface, width, height, device),
|
||||
viewport: Viewport::new(width, height, scale_factor),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_frame(&mut self) -> (wgpu::SwapChainOutput<'_>, &Viewport) {
|
||||
(self.raw.get_next_texture(), &self.viewport)
|
||||
}
|
||||
}
|
||||
|
||||
fn new_swap_chain(
|
||||
surface: &wgpu::Surface,
|
||||
width: u32,
|
||||
height: u32,
|
||||
device: &wgpu::Device,
|
||||
) -> wgpu::SwapChain {
|
||||
device.create_swap_chain(
|
||||
&surface,
|
||||
&wgpu::SwapChainDescriptor {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
width,
|
||||
height,
|
||||
present_mode: wgpu::PresentMode::Vsync,
|
||||
},
|
||||
)
|
||||
}
|
@ -14,10 +14,10 @@ use crate::{
|
||||
/// An [`Application`](trait.Application.html) can execute asynchronous actions
|
||||
/// by returning a [`Command`](struct.Command.html) in some of its methods.
|
||||
pub trait Application: Sized {
|
||||
/// The renderer to use to draw the [`Application`].
|
||||
/// The graphics backend to use to draw the [`Application`].
|
||||
///
|
||||
/// [`Application`]: trait.Application.html
|
||||
type Renderer: window::Renderer;
|
||||
type Backend: window::Backend;
|
||||
|
||||
/// The [`Executor`] that will run commands and subscriptions.
|
||||
///
|
||||
@ -75,7 +75,9 @@ pub trait Application: Sized {
|
||||
/// These widgets can produce __messages__ based on user interaction.
|
||||
///
|
||||
/// [`Application`]: trait.Application.html
|
||||
fn view(&mut self) -> Element<'_, Self::Message, Self::Renderer>;
|
||||
fn view(
|
||||
&mut self,
|
||||
) -> Element<'_, Self::Message, <Self::Backend as window::Backend>::Renderer>;
|
||||
|
||||
/// Returns the current [`Application`] mode.
|
||||
///
|
||||
@ -99,11 +101,11 @@ pub trait Application: Sized {
|
||||
/// [`Application`]: trait.Application.html
|
||||
fn run(
|
||||
settings: Settings,
|
||||
renderer_settings: <Self::Renderer as window::Renderer>::Settings,
|
||||
backend_settings: <Self::Backend as window::Backend>::Settings,
|
||||
) where
|
||||
Self: 'static,
|
||||
{
|
||||
use window::{Renderer as _, Target as _};
|
||||
use window::Backend as _;
|
||||
use winit::{
|
||||
event::{self, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
@ -162,17 +164,18 @@ pub trait Application: Sized {
|
||||
let mut resized = false;
|
||||
|
||||
let clipboard = Clipboard::new(&window);
|
||||
let mut renderer = Self::Renderer::new(renderer_settings);
|
||||
let (mut backend, mut renderer) = Self::Backend::new(backend_settings);
|
||||
|
||||
let mut target = {
|
||||
let surface = backend.create_surface(&window);
|
||||
|
||||
let mut swap_chain = {
|
||||
let physical_size = size.physical();
|
||||
|
||||
<Self::Renderer as window::Renderer>::Target::new(
|
||||
&window,
|
||||
backend.create_swap_chain(
|
||||
&surface,
|
||||
physical_size.width,
|
||||
physical_size.height,
|
||||
size.scale_factor(),
|
||||
&renderer,
|
||||
)
|
||||
};
|
||||
|
||||
@ -306,18 +309,22 @@ pub trait Application: Sized {
|
||||
if resized {
|
||||
let physical_size = size.physical();
|
||||
|
||||
target.resize(
|
||||
swap_chain = backend.create_swap_chain(
|
||||
&surface,
|
||||
physical_size.width,
|
||||
physical_size.height,
|
||||
size.scale_factor(),
|
||||
&renderer,
|
||||
);
|
||||
|
||||
resized = false;
|
||||
}
|
||||
|
||||
let new_mouse_cursor =
|
||||
renderer.draw(&primitive, &debug.overlay(), &mut target);
|
||||
let new_mouse_cursor = backend.draw(
|
||||
&mut renderer,
|
||||
&mut swap_chain,
|
||||
&primitive,
|
||||
&debug.overlay(),
|
||||
);
|
||||
|
||||
debug.render_finished();
|
||||
|
||||
@ -451,10 +458,10 @@ pub trait Application: Sized {
|
||||
fn build_user_interface<'a, A: Application>(
|
||||
application: &'a mut A,
|
||||
cache: Cache,
|
||||
renderer: &mut A::Renderer,
|
||||
renderer: &mut <A::Backend as window::Backend>::Renderer,
|
||||
size: winit::dpi::LogicalSize<f64>,
|
||||
debug: &mut Debug,
|
||||
) -> UserInterface<'a, A::Message, A::Renderer> {
|
||||
) -> UserInterface<'a, A::Message, <A::Backend as window::Backend>::Renderer> {
|
||||
debug.view_started();
|
||||
let view = application.view();
|
||||
debug.view_finished();
|
||||
|
Loading…
x
Reference in New Issue
Block a user