Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Uninitialized variant to Renderer #608

Merged
merged 5 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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