Skip to content

Commit

Permalink
Add Uninitialized variant to Renderer (#608)
Browse files Browse the repository at this point in the history
* Add Uninitialized variant to Renderer

Thereby we don't need to panic when PaintState is uninitialized.

* Remove now redundant is_initialized check

* Make Renderer own the size

* Add some doc comments

* Improve wording
  • Loading branch information
timsueberkrueb authored Oct 11, 2024
1 parent 4510c4b commit d22a037
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 25 deletions.
6 changes: 0 additions & 6 deletions src/app_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,6 @@ impl ApplicationHandle {
None => return,
};

// We only start reacting to events once the window is ready
// I.e. once the renderer has acquired the necessary GPU resources (if any) and is initialized.
if !window_handle.is_initialized() {
return;
}

let start = window_handle.profile.is_some().then(|| {
let name = match event {
WindowEvent::ActivationTokenDone { .. } => "ActivationTokenDone",
Expand Down
30 changes: 16 additions & 14 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use web_time::{Duration, Instant};
use taffy::prelude::NodeId;

use crate::animate::{AnimStateKind, RepeatMode};
use crate::renderer::Renderer;
use crate::style::DisplayProp;
use crate::view_state::IsHiddenState;
use crate::{
Expand Down Expand Up @@ -1194,13 +1195,20 @@ impl<'a> PaintCx<'a> {

// TODO: should this be private?
pub enum PaintState {
/// The renderer is not yet initialized. This state is used to wait for the GPU resources to be acquired.
PendingGpuResources {
window: Arc<dyn wgpu::WindowHandle>,
rx: crossbeam::channel::Receiver<Result<GpuResources, GpuResourceError>>,
scale: f64,
size: Size,
font_embolden: f32,
/// This field holds an instance of `Renderer::Uninitialized` until the GPU resources are acquired,
/// which will be returned in `PaintState::renderer` and `PaintState::renderer_mut`.
/// All calls to renderer methods will be no-ops until the renderer is initialized.
///
/// Previously, `PaintState::renderer` and `PaintState::renderer_mut` would panic if called when the renderer was uninitialized.
/// However, this turned out to be hard to handle properly and led to panics, especially since the rest of the application code can't control when the renderer is initialized.
renderer: crate::renderer::Renderer<Arc<dyn wgpu::WindowHandle>>,
},
/// The renderer is initialized and ready to paint.
Initialized {
renderer: crate::renderer::Renderer<Arc<dyn wgpu::WindowHandle>>,
},
Expand All @@ -1216,28 +1224,26 @@ impl PaintState {
) -> Self {
Self::PendingGpuResources {
window,
scale,
size,
rx,
font_embolden,
renderer: Renderer::Uninitialized { scale, size },
}
}

pub(crate) fn init_renderer(&mut self) {
if let PaintState::PendingGpuResources {
window,
rx,
scale,
size,
font_embolden,
renderer,
} = self
{
let gpu_resources = rx.recv().unwrap().unwrap();
let renderer = crate::renderer::Renderer::new(
window.clone(),
gpu_resources,
*scale,
*size,
renderer.scale(),
renderer.size(),
*font_embolden,
);
*self = PaintState::Initialized { renderer };
Expand All @@ -1248,9 +1254,7 @@ impl PaintState {

pub(crate) fn renderer(&self) -> &crate::renderer::Renderer<Arc<dyn wgpu::WindowHandle>> {
match self {
PaintState::PendingGpuResources { .. } => {
panic!("Tried to access renderer before it was initialized")
}
PaintState::PendingGpuResources { renderer, .. } => renderer,
PaintState::Initialized { renderer } => renderer,
}
}
Expand All @@ -1259,9 +1263,7 @@ impl PaintState {
&mut self,
) -> &mut crate::renderer::Renderer<Arc<dyn wgpu::WindowHandle>> {
match self {
PaintState::PendingGpuResources { .. } => {
panic!("Tried to access renderer before it was initialized")
}
PaintState::PendingGpuResources { renderer, .. } => renderer,
PaintState::Initialized { renderer } => renderer,
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ use peniko::BrushRef;
pub enum Renderer<W> {
Vger(VgerRenderer),
TinySkia(TinySkiaRenderer<W>),
/// Uninitialized renderer, used to allow the renderer to be created lazily
/// All operations on this renderer are no-ops
Uninitialized {
scale: f64,
size: Size,
},
}

impl<W: wgpu::WindowHandle> Renderer<W> {
Expand Down Expand Up @@ -118,20 +124,35 @@ impl<W: wgpu::WindowHandle> Renderer<W> {
match self {
Renderer::Vger(r) => r.resize(size.width as u32, size.height as u32, scale),
Renderer::TinySkia(r) => r.resize(size.width as u32, size.height as u32, scale),
Renderer::Uninitialized { .. } => {}
}
}

pub fn set_scale(&mut self, scale: f64) {
match self {
Renderer::Vger(r) => r.set_scale(scale),
Renderer::TinySkia(r) => r.set_scale(scale),
Renderer::Uninitialized {
scale: old_scale, ..
} => {
*old_scale = scale;
}
}
}

pub fn scale(&self) -> f64 {
match self {
Renderer::Vger(r) => r.scale(),
Renderer::TinySkia(r) => r.scale(),
Renderer::Uninitialized { scale, .. } => *scale,
}
}

pub fn size(&self) -> Size {
match self {
Renderer::Vger(r) => r.size(),
Renderer::TinySkia(r) => r.size(),
Renderer::Uninitialized { size, .. } => *size,
}
}
}
Expand All @@ -145,6 +166,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(r) => {
r.begin(capture);
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -156,6 +178,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.clip(shape);
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -167,6 +190,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.clear_clip();
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -178,6 +202,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.stroke(shape, brush, width);
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -194,6 +219,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.fill(path, brush, blur_radius);
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -205,6 +231,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.draw_text(layout, pos);
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -216,6 +243,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.draw_img(img, rect);
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -232,6 +260,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.draw_svg(svg, rect, brush);
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -243,6 +272,7 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.transform(transform);
}
Renderer::Uninitialized { .. } => {}
}
}

Expand All @@ -254,13 +284,15 @@ impl<W: wgpu::WindowHandle> floem_renderer::Renderer for Renderer<W> {
Renderer::TinySkia(v) => {
v.set_z_index(z_index);
}
Renderer::Uninitialized { .. } => {}
}
}

fn finish(&mut self) -> Option<DynamicImage> {
match self {
Renderer::Vger(r) => r.finish(),
Renderer::TinySkia(r) => r.finish(),
Renderer::Uninitialized { .. } => None,
}
}
}
4 changes: 0 additions & 4 deletions src/window_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,6 @@ impl WindowHandle {
self.render_frame();
}

pub(crate) fn is_initialized(&self) -> bool {
matches!(self.paint_state, PaintState::Initialized { .. })
}

pub fn event(&mut self, event: Event) {
set_current_view(self.id);
let event = event.scale(self.app_state.scale);
Expand Down
6 changes: 5 additions & 1 deletion tiny_skia/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use floem_renderer::tiny_skia::{
use floem_renderer::Img;
use floem_renderer::Renderer;
use image::DynamicImage;
use peniko::kurbo::PathEl;
use peniko::kurbo::{PathEl, Size};
use peniko::{
kurbo::{Affine, Point, Rect, Shape},
BrushRef, Color, GradientKind,
Expand Down Expand Up @@ -115,6 +115,10 @@ impl<W: raw_window_handle::HasWindowHandle + raw_window_handle::HasDisplayHandle
pub fn scale(&self) -> f64 {
self.scale
}

pub fn size(&self) -> Size {
Size::new(self.pixmap.width() as f64, self.pixmap.height() as f64)
}
}

fn to_color(color: Color) -> tiny_skia::Color {
Expand Down
5 changes: 5 additions & 0 deletions vger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use floem_renderer::text::{CacheKey, TextLayout};
use floem_renderer::{tiny_skia, Img, Renderer};
use floem_vger_rs::{Image, PaintIndex, PixelFormat, Vger};
use image::{DynamicImage, EncodableLayout, RgbaImage};
use peniko::kurbo::Size;
use peniko::{
kurbo::{Affine, Point, Rect, Shape},
BrushRef, Color, GradientKind,
Expand Down Expand Up @@ -117,6 +118,10 @@ impl VgerRenderer {
pub fn scale(&self) -> f64 {
self.scale
}

pub fn size(&self) -> Size {
Size::new(self.config.width as f64, self.config.height as f64)
}
}

impl VgerRenderer {
Expand Down

0 comments on commit d22a037

Please sign in to comment.