summaryrefslogtreecommitdiffstats
path: root/glow
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-05-21 00:37:47 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-05-21 00:44:35 +0200
commite0e4ee73feead3f05730625c7e1917b63f0b384e (patch)
tree5cd934cc474a5aacc60359f6fe69a5b9d31fe45b /glow
parenta1a5fcfd46622d5b18d1716aa2adb4659835ccf3 (diff)
downloadiced-e0e4ee73feead3f05730625c7e1917b63f0b384e.tar.gz
iced-e0e4ee73feead3f05730625c7e1917b63f0b384e.tar.bz2
iced-e0e4ee73feead3f05730625c7e1917b63f0b384e.zip
Implement `iced_glutin` :tada:
Diffstat (limited to 'glow')
-rw-r--r--glow/Cargo.toml13
-rw-r--r--glow/src/backend.rs29
-rw-r--r--glow/src/widget.rs11
-rw-r--r--glow/src/widget/canvas.rs194
-rw-r--r--glow/src/window/compositor.rs170
5 files changed, 65 insertions, 352 deletions
diff --git a/glow/Cargo.toml b/glow/Cargo.toml
index 72ed8758..148f4fd5 100644
--- a/glow/Cargo.toml
+++ b/glow/Cargo.toml
@@ -7,8 +7,12 @@ description = "A glow renderer for iced"
license = "MIT AND OFL-1.1"
repository = "https://github.com/hecrj/iced"
+[features]
+canvas = ["iced_graphics/canvas"]
+image = []
+svg = []
+
[dependencies]
-raw-window-handle = "0.3"
euclid = "0.20"
glow = "0.4"
bytemuck = "1.2"
@@ -23,12 +27,7 @@ path = "../native"
[dependencies.iced_graphics]
version = "0.1"
path = "../graphics"
-features = ["font-source", "font-fallback", "font-icons"]
-
-[dependencies.surfman]
-path = "../../surfman/surfman"
-default-features = false
-features = ["sm-raw-window-handle", "sm-x11"]
+features = ["font-source", "font-fallback", "font-icons", "opengl"]
[dependencies.glow_glyph]
path = "../../glow_glyph"
diff --git a/glow/src/backend.rs b/glow/src/backend.rs
index 5e2aa837..8c578d5e 100644
--- a/glow/src/backend.rs
+++ b/glow/src/backend.rs
@@ -36,12 +36,6 @@ impl Backend {
}
}
- /// 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,
gl: &glow::Context,
@@ -50,6 +44,7 @@ impl Backend {
overlay_text: &[T],
) -> mouse::Interaction {
let viewport_size = viewport.physical_size();
+ let scale_factor = viewport.scale_factor() as f32;
let projection = viewport.projection();
let mut layers = Layer::generate(primitive, viewport);
@@ -58,7 +53,7 @@ impl Backend {
for layer in layers {
self.flush(
gl,
- viewport.scale_factor() as f32,
+ scale_factor,
projection,
&layer,
viewport_size.width,
@@ -78,7 +73,8 @@ impl Backend {
target_width: u32,
target_height: u32,
) {
- let bounds = (layer.bounds * scale_factor).round();
+ let mut bounds = (layer.bounds * scale_factor).round();
+ bounds.height = bounds.height.min(target_height);
if !layer.quads.is_empty() {
self.quad_pipeline.draw(
@@ -204,3 +200,20 @@ impl backend::Text for Backend {
self.text_pipeline.space_width(size)
}
}
+
+#[cfg(feature = "image")]
+impl backend::Image for Backend {
+ fn dimensions(&self, _handle: &iced_native::image::Handle) -> (u32, u32) {
+ (50, 50)
+ }
+}
+
+#[cfg(feature = "svg")]
+impl backend::Svg for Backend {
+ fn viewport_dimensions(
+ &self,
+ _handle: &iced_native::svg::Handle,
+ ) -> (u32, u32) {
+ (50, 50)
+ }
+}
diff --git a/glow/src/widget.rs b/glow/src/widget.rs
index 16e7ca88..362465f4 100644
--- a/glow/src/widget.rs
+++ b/glow/src/widget.rs
@@ -38,7 +38,16 @@ pub use slider::Slider;
#[doc(no_inline)]
pub use text_input::TextInput;
-pub use iced_native::{Image, Space, Text};
+#[cfg(feature = "canvas")]
+#[cfg_attr(docsrs, doc(cfg(feature = "canvas")))]
+pub mod canvas;
+
+#[cfg(feature = "canvas")]
+#[doc(no_inline)]
+pub use canvas::Canvas;
+
+pub use iced_native::{Image, Space};
pub type Column<'a, Message> = iced_native::Column<'a, Message, Renderer>;
pub type Row<'a, Message> = iced_native::Row<'a, Message, Renderer>;
+pub type Text = iced_native::Text<Renderer>;
diff --git a/glow/src/widget/canvas.rs b/glow/src/widget/canvas.rs
index 325f90ce..bef34857 100644
--- a/glow/src/widget/canvas.rs
+++ b/glow/src/widget/canvas.rs
@@ -6,196 +6,4 @@
//!
//! [`Canvas`]: struct.Canvas.html
//! [`Frame`]: struct.Frame.html
-use crate::{Defaults, Primitive, Renderer};
-
-use iced_native::{
- layout, Element, Hasher, Layout, Length, MouseCursor, Point, Size, Widget,
-};
-use std::hash::Hash;
-
-pub mod layer;
-pub mod path;
-
-mod drawable;
-mod fill;
-mod frame;
-mod stroke;
-mod text;
-
-pub use drawable::Drawable;
-pub use fill::Fill;
-pub use frame::Frame;
-pub use layer::Layer;
-pub use path::Path;
-pub use stroke::{LineCap, LineJoin, Stroke};
-pub use text::Text;
-
-/// A widget capable of drawing 2D graphics.
-///
-/// A [`Canvas`] may contain multiple layers. A [`Layer`] is drawn using the
-/// painter's algorithm. In other words, layers will be drawn on top of each
-/// other in the same order they are pushed into the [`Canvas`].
-///
-/// [`Canvas`]: struct.Canvas.html
-/// [`Layer`]: layer/trait.Layer.html
-///
-/// # Examples
-/// The repository has a couple of [examples] showcasing how to use a
-/// [`Canvas`]:
-///
-/// - [`clock`], an application that uses the [`Canvas`] widget to draw a clock
-/// and its hands to display the current time.
-/// - [`solar_system`], an animated solar system drawn using the [`Canvas`] widget
-/// and showcasing how to compose different transforms.
-///
-/// [examples]: https://github.com/hecrj/iced/tree/0.1/examples
-/// [`clock`]: https://github.com/hecrj/iced/tree/0.1/examples/clock
-/// [`solar_system`]: https://github.com/hecrj/iced/tree/0.1/examples/solar_system
-///
-/// ## Drawing a simple circle
-/// If you want to get a quick overview, here's how we can draw a simple circle:
-///
-/// ```no_run
-/// # mod iced {
-/// # pub use iced_wgpu::canvas;
-/// # pub use iced_native::Color;
-/// # }
-/// use iced::canvas::{self, layer, Canvas, Drawable, Fill, Frame, Path};
-/// use iced::Color;
-///
-/// // First, we define the data we need for drawing
-/// #[derive(Debug)]
-/// struct Circle {
-/// radius: f32,
-/// }
-///
-/// // Then, we implement the `Drawable` trait
-/// impl Drawable for Circle {
-/// fn draw(&self, frame: &mut Frame) {
-/// // We create a `Path` representing a simple circle
-/// let circle = Path::new(|p| p.circle(frame.center(), self.radius));
-///
-/// // And fill it with some color
-/// frame.fill(&circle, Fill::Color(Color::BLACK));
-/// }
-/// }
-///
-/// // We can use a `Cache` to avoid unnecessary re-tessellation
-/// let cache: layer::Cache<Circle> = layer::Cache::new();
-///
-/// // Finally, we simply provide the data to our `Cache` and push the resulting
-/// // layer into a `Canvas`
-/// let canvas = Canvas::new()
-/// .push(cache.with(&Circle { radius: 50.0 }));
-/// ```
-#[derive(Debug)]
-pub struct Canvas<'a> {
- width: Length,
- height: Length,
- layers: Vec<Box<dyn Layer + 'a>>,
-}
-
-impl<'a> Canvas<'a> {
- const DEFAULT_SIZE: u16 = 100;
-
- /// Creates a new [`Canvas`] with no layers.
- ///
- /// [`Canvas`]: struct.Canvas.html
- pub fn new() -> Self {
- Canvas {
- width: Length::Units(Self::DEFAULT_SIZE),
- height: Length::Units(Self::DEFAULT_SIZE),
- layers: Vec::new(),
- }
- }
-
- /// Sets the width of the [`Canvas`].
- ///
- /// [`Canvas`]: struct.Canvas.html
- pub fn width(mut self, width: Length) -> Self {
- self.width = width;
- self
- }
-
- /// Sets the height of the [`Canvas`].
- ///
- /// [`Canvas`]: struct.Canvas.html
- pub fn height(mut self, height: Length) -> Self {
- self.height = height;
- self
- }
-
- /// Adds a [`Layer`] to the [`Canvas`].
- ///
- /// It will be drawn on top of previous layers.
- ///
- /// [`Layer`]: layer/trait.Layer.html
- /// [`Canvas`]: struct.Canvas.html
- pub fn push(mut self, layer: impl Layer + 'a) -> Self {
- self.layers.push(Box::new(layer));
- self
- }
-}
-
-impl<'a, Message> Widget<Message, Renderer> for Canvas<'a> {
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- self.height
- }
-
- fn layout(
- &self,
- _renderer: &Renderer,
- limits: &layout::Limits,
- ) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
- let size = limits.resolve(Size::ZERO);
-
- layout::Node::new(size)
- }
-
- fn draw(
- &self,
- _renderer: &mut Renderer,
- _defaults: &Defaults,
- layout: Layout<'_>,
- _cursor_position: Point,
- ) -> (Primitive, MouseCursor) {
- let bounds = layout.bounds();
- let origin = Point::new(bounds.x, bounds.y);
- let size = Size::new(bounds.width, bounds.height);
-
- (
- Primitive::Group {
- primitives: self
- .layers
- .iter()
- .map(|layer| Primitive::Cached {
- origin,
- cache: layer.draw(size),
- })
- .collect(),
- },
- MouseCursor::Idle,
- )
- }
-
- fn hash_layout(&self, state: &mut Hasher) {
- std::any::TypeId::of::<Canvas<'static>>().hash(state);
-
- self.width.hash(state);
- self.height.hash(state);
- }
-}
-
-impl<'a, Message> From<Canvas<'a>> for Element<'a, Message, Renderer>
-where
- Message: 'static,
-{
- fn from(canvas: Canvas<'a>) -> Element<'a, Message, Renderer> {
- Element::new(canvas)
- }
-}
+pub use iced_graphics::canvas::*;
diff --git a/glow/src/window/compositor.rs b/glow/src/window/compositor.rs
index 514904a8..1117166f 100644
--- a/glow/src/window/compositor.rs
+++ b/glow/src/window/compositor.rs
@@ -1,180 +1,64 @@
-use crate::{Renderer, Settings, Viewport};
+use crate::{Backend, Renderer, Settings, Viewport};
+use core::ffi::c_void;
use glow::HasContext;
+use iced_graphics::Size;
use iced_native::mouse;
-use raw_window_handle::HasRawWindowHandle;
/// A window graphics backend for iced powered by `glow`.
#[allow(missing_debug_implementations)]
pub struct Compositor {
- connection: surfman::Connection,
- device: surfman::Device,
- gl_context: surfman::Context,
- gl: Option<glow::Context>,
+ gl: glow::Context,
}
-impl iced_graphics::window::Compositor for Compositor {
+impl iced_graphics::window::GLCompositor for Compositor {
type Settings = Settings;
type Renderer = Renderer;
- type Surface = ();
- type SwapChain = ();
- fn new(_settings: Self::Settings) -> Self {
- let connection = surfman::Connection::new().expect("Create connection");
+ unsafe fn new(
+ settings: Self::Settings,
+ loader_function: impl FnMut(&str) -> *const c_void,
+ ) -> (Self, Self::Renderer) {
+ let gl = glow::Context::from_loader_function(loader_function);
- let adapter = connection
- .create_hardware_adapter()
- .expect("Create adapter");
+ gl.clear_color(1.0, 1.0, 1.0, 1.0);
- let mut device =
- connection.create_device(&adapter).expect("Create device");
+ // Enable auto-conversion from/to sRGB
+ gl.enable(glow::FRAMEBUFFER_SRGB);
- let context_descriptor = device
- .create_context_descriptor(&surfman::ContextAttributes {
- version: surfman::GLVersion::new(3, 0),
- flags: surfman::ContextAttributeFlags::empty(),
- })
- .expect("Create context descriptor");
+ // Enable alpha blending
+ gl.enable(glow::BLEND);
+ gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
- let gl_context = device
- .create_context(&context_descriptor)
- .expect("Create context");
+ let renderer = Renderer::new(Backend::new(&gl, settings));
- Self {
- connection,
- device,
- gl_context,
- gl: None,
- }
- }
-
- fn create_renderer(&mut self, settings: Settings) -> Renderer {
- self.device
- .make_context_current(&self.gl_context)
- .expect("Make context current");
-
- Renderer::new(crate::Backend::new(self.gl.as_ref().unwrap(), settings))
- }
-
- fn create_surface<W: HasRawWindowHandle>(
- &mut self,
- window: &W,
- ) -> Self::Surface {
- let native_widget = self
- .connection
- .create_native_widget_from_rwh(window.raw_window_handle())
- .expect("Create widget");
-
- let surface = self
- .device
- .create_surface(
- &self.gl_context,
- surfman::SurfaceAccess::GPUOnly,
- surfman::SurfaceType::Widget { native_widget },
- )
- .expect("Create surface");
-
- let surfman::SurfaceInfo { .. } = self.device.surface_info(&surface);
-
- self.device
- .bind_surface_to_context(&mut self.gl_context, surface)
- .expect("Bind surface to context");
-
- self.device
- .make_context_current(&self.gl_context)
- .expect("Make context current");
-
- self.gl = Some(glow::Context::from_loader_function(|s| {
- self.device.get_proc_address(&self.gl_context, s)
- }));
-
- //let mut framebuffer =
- // skia_safe::gpu::gl::FramebufferInfo::from_fboid(framebuffer_object);
-
- //framebuffer.format = gl::RGBA8;
-
- //framebuffer
+ (Self { gl }, renderer)
}
- fn create_swap_chain(
- &mut self,
- _surface: &Self::Surface,
- width: u32,
- height: u32,
- ) -> Self::SwapChain {
- let mut surface = self
- .device
- .unbind_surface_from_context(&mut self.gl_context)
- .expect("Unbind surface")
- .expect("Active surface");
-
- self.device
- .resize_surface(
- &self.gl_context,
- &mut surface,
- euclid::Size2D::new(width as i32, height as i32),
- )
- .expect("Resize surface");
-
- self.device
- .bind_surface_to_context(&mut self.gl_context, surface)
- .expect("Bind surface to context");
-
- let gl = self.gl.as_ref().unwrap();
-
+ fn resize_viewport(&mut self, physical_size: Size<u32>) {
unsafe {
- gl.viewport(0, 0, width as i32, height as i32);
- gl.clear_color(1.0, 1.0, 1.0, 1.0);
-
- // Enable auto-conversion from/to sRGB
- gl.enable(glow::FRAMEBUFFER_SRGB);
-
- // Enable alpha blending
- gl.enable(glow::BLEND);
- gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
+ self.gl.viewport(
+ 0,
+ 0,
+ physical_size.width as i32,
+ physical_size.height as i32,
+ );
}
}
fn draw<T: AsRef<str>>(
&mut self,
renderer: &mut Self::Renderer,
- swap_chain: &mut Self::SwapChain,
viewport: &Viewport,
output: &<Self::Renderer as iced_native::Renderer>::Output,
overlay: &[T],
) -> mouse::Interaction {
- let gl = self.gl.as_ref().unwrap();
+ let gl = &self.gl;
unsafe {
gl.clear(glow::COLOR_BUFFER_BIT);
}
- let mouse = renderer.backend_mut().draw(gl, viewport, output, overlay);
-
- {
- let mut surface = self
- .device
- .unbind_surface_from_context(&mut self.gl_context)
- .expect("Unbind surface")
- .expect("Active surface");
-
- self.device
- .present_surface(&self.gl_context, &mut surface)
- .expect("Present surface");
-
- self.device
- .bind_surface_to_context(&mut self.gl_context, surface)
- .expect("Bind surface to context");
- }
-
- mouse
- }
-}
-
-impl Drop for Compositor {
- fn drop(&mut self) {
- self.device
- .destroy_context(&mut self.gl_context)
- .expect("Destroy context");
+ renderer.backend_mut().draw(gl, viewport, output, overlay)
}
}