Announcing piet-glow

John Nunley · March 6, 2023

Right now, there isn’t a good drawing framework for Rust. Actually, I lie, there is a good one; piet. However, it’s pretty tightly tied to the druid ecosystem. However, adapting it to other frameworks is relatively dfficult.

winit is a fantastic crate, but it doesn’t come with a real way to draw to the screen. This is intentional; it prevents the winit team from needing to maintain a drawing library in addition to the already-very-large windowing library. However, it means that, when it comes to drawing, there’s no real “out of the box” solution. When you Google “winit drawing”, the first post recommends using druid-shell instead of winit. There are other drawing frameworks, but they’re usually tightly integrated into a GUI framework, and are often difficult to extract into something useful.

The piet-glow crate is a step towards solving this problem. It’s standalone and not tied to any particular GUI framework. It’s also hardware-accelerated, using the glow crate as an interface to OpenGL.

Usage

First, you need to create a GlContext, which is just a wrapper around a glow::Context.

let context = unsafe {
    let gl = glow::Context::from_loader_function(/* ... */);
    piet_glow::GlContext::new(gl)
};

Note that creating a GlContext is unsafe, since it assumes that the context is current.

Once you have a GlContext, you can call the render_context method to get a type that implements piet::RenderContext.

unsafe {
    let mut ctx = context.render_context(window_width, window_height);

    ctx.clear(Color::WHITE);
    ctx.finish().unwrap();
}

Implementation

I built piet-glow on top of another crate I wrote, piet-hardware. piet-hardware does all of the heavy lifting; it converts the higher-level drawing operations to rendering textured triangles. From there, piet-glow only implements the interface to OpenGL that piet-hardware expects.

It is definitely possible to implement piet-hardware for other GPU backends. Most notably, this would be nice for wgpu drawing, but Vulkan and DirectX are also possible. However, I’m not familiar with those APIs. I could become familiar with them, but I’d rather move at a fast velocity with what I want to do rather than implement GPU APIs when I already know OpenGL. To clarify, it’s on the to-do list, but I’d rather move onto other things first. That being said, if you’d like to implement support for one of these APIs, I’m always open to PRs!

Thanks

piet-glow, like any open-source project, is built on the sholders of giants. In that respect, I’d like to thank the following people:

  • Raph Levien and the Druid team for creating the piet and kurbo crates. Being able to build on top of an existing, robust drawing framework is a huge boon.
  • Josh Groves for creating glow, which has acted as a great abstraction over OpenGL.
  • Nicolas Silva for two important crates: lyon-tesselation and etagere. lyon-tesselation powers the tesselation process that converts shapes to triangles. etagere is the allocation strategy for the text rendering code. Without these two crates, piet-hardware would be much more difficult to implement.
  • Jeremy Soller and others for creating cosmic_text, which is used for font loading and text layout.
  • Yevhenii Reizner for creating tiny-skia, which is used for rendering gradients and clipping masks.
  • Alex Butler for creating ab-glyph, which is used to render text.
  • Many, many more people who have contributed to the above projects, among others. I’m grateful for all of you.

Twitter, Facebook

This website's source code is hosted via Codeberg