Skip to content

Commit

Permalink
Move Scene to Renderer, scroll_offset to Document
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoburns committed Jul 23, 2024
1 parent 030227d commit aa66848
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 43 deletions.
41 changes: 21 additions & 20 deletions packages/blitz/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ pub struct Renderer<'s, W, Doc: DocumentLike> {

pub render_state: RenderState<'s, W>,

// Vello
pub(crate) render_context: RenderContext,
pub(crate) scene: Scene,

/// Our image cache
// pub(crate) images: ImageCache,
Expand All @@ -49,8 +51,6 @@ pub struct Renderer<'s, W, Doc: DocumentLike> {
/// Whenever we encounter new fonts during parsing + mutations, this will become populated
// pub(crate) fonts: FontCache,
pub devtools: Devtools,

scroll_offset: f64,
mouse_pos: (f32, f32),
}

Expand All @@ -73,9 +73,9 @@ where
Self {
render_context,
render_state: RenderState::Suspended(None),
scene: Scene::new(),
dom,
devtools: Default::default(),
scroll_offset: 0.0,
mouse_pos: (0.0, 0.0),
}
}
Expand Down Expand Up @@ -170,7 +170,7 @@ where
};

let x = x / state.viewport.zoom();
let y = (y - self.scroll_offset as f32) / state.viewport.zoom();
let y = (y - self.dom.as_ref().scroll_offset as f32) / state.viewport.zoom();

// println!("Mouse move: ({}, {})", x, y);
// println!("Unscaled: ({}, {})",);
Expand Down Expand Up @@ -210,27 +210,23 @@ where
// Invert scrolling on macos
#[cfg(target_os = "macos")]
{
self.scroll_offset += px;
self.dom.as_mut().scroll_offset += px;
}
#[cfg(not(target_os = "macos"))]
{
self.scroll_offset -= px;
self.dom.as_mut().scroll_offset -= px;
}

self.clamp_scroll();
}

/// Clamp scroll offset
fn clamp_scroll(&mut self) {
let content_height = self.dom.as_ref().root_element().final_layout.size.height as f64;
let viewport_height = self
.dom
.as_mut()
.stylist_device()
.au_viewport_size()
.height
.to_f64_px();
self.scroll_offset = self
let dom = self.dom.as_mut();
let content_height = dom.root_element().final_layout.size.height as f64;
let viewport_height = dom.stylist_device().au_viewport_size().height.to_f64_px();

dom.scroll_offset = dom
.scroll_offset
.max(-(content_height - viewport_height))
.min(0.0);
Expand Down Expand Up @@ -370,13 +366,10 @@ where
}
}

pub fn render(&mut self, scene: &mut Scene) {
self.generate_vello_scene(scene);

pub fn render(&mut self) {
let RenderState::Active(state) = &mut self.render_state else {
return;
};

let surface_texture = match state.surface.surface.get_current_texture() {
Ok(surface) => surface,
// When resizing too aggresively, the surface can get outdated (another resize) before being rendered into
Expand All @@ -393,12 +386,20 @@ where
antialiasing_method: vello::AaConfig::Msaa16,
};

// Regenerate the vello scene
render::generate_vello_scene(
&mut self.scene,
self.dom.as_ref(),
state.viewport.scale_f64(),
self.devtools,
);

state
.renderer
.render_to_surface(
&device.device,
&device.queue,
scene,
&self.scene,
&surface_texture,
&render_params,
)
Expand Down
51 changes: 38 additions & 13 deletions packages/blitz/src/renderer/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ use crate::{
devtools::Devtools,
util::{GradientSlice, StyloGradient, ToVelloColor},
};
use blitz_dom::node::{TextBrush, TextInputData};
use blitz_dom::{
node::{NodeData, TextNodeData},
DocumentLike, Node,
Node,
};
use blitz_dom::{
node::{TextBrush, TextInputData},
Document,
};
use html5ever::local_name;
use image::{imageops::FilterType, DynamicImage};
Expand Down Expand Up @@ -41,9 +44,38 @@ use vello::{
};

use super::multicolor_rounded_rect::{Edge, ElementFrame};
use super::{RenderState, Renderer};

impl<'a, W: 'a, Doc: DocumentLike> Renderer<'a, W, Doc> {
/// Draw the current tree to current render surface
/// Eventually we'll want the surface itself to be passed into the render function, along with things like the viewport
///
/// This assumes styles are resolved and layout is complete.
/// Make sure you do those before trying to render
pub fn generate_vello_scene(
scene: &mut Scene,
dom: &Document,
scale: f64,
devtool_config: Devtools,
) {
let generator = VelloSceneGenerator {
dom,
scale,
devtools: devtool_config,
scroll_offset: dom.scroll_offset,
};
generator.generate_vello_scene(scene)
}

/// A short-lived struct which holds a bunch of parameters for rendering a vello scene so
/// that we don't have to pass them down as parameters
pub struct VelloSceneGenerator<'dom> {
/// Input parameters (read only) for generating the Scene
dom: &'dom Document,
scale: f64,
devtools: Devtools,
scroll_offset: f64,
}

impl<'dom> VelloSceneGenerator<'dom> {
fn node_position(&self, node: usize, location: Point) -> (Layout, Point) {
let layout = self.layout(node);
let pos = location + Vec2::new(layout.location.x as f64, layout.location.y as f64);
Expand Down Expand Up @@ -83,10 +115,7 @@ impl<'a, W: 'a, Doc: DocumentLike> Renderer<'a, W, Doc> {
/// Renders a layout debugging overlay which visualises the content size, padding and border
/// of the node with a transparent overlay.
fn render_debug_overlay(&self, scene: &mut Scene, node_id: usize) {
let RenderState::Active(state) = &self.render_state else {
return;
};
let scale = state.viewport.scale_f64();
let scale = self.scale;

let mut node = &self.dom.as_ref().tree()[node_id];

Expand Down Expand Up @@ -354,10 +383,6 @@ impl<'a, W: 'a, Doc: DocumentLike> Renderer<'a, W, Doc> {
}

fn element_cx<'w>(&'w self, element: &'w Node, location: Point) -> ElementCx {
let RenderState::Active(state) = &self.render_state else {
panic!("Renderer is not active");
};

let style = element
.stylo_element_data
.borrow()
Expand All @@ -366,7 +391,7 @@ impl<'a, W: 'a, Doc: DocumentLike> Renderer<'a, W, Doc> {
.unwrap_or(ComputedValues::initial_values().to_arc());

let (layout, pos) = self.node_position(element.id, location);
let scale = state.viewport.scale_f64();
let scale = self.scale;

// the bezpaths for every element are (potentially) cached (not yet, tbd)
// By performing the transform, we prevent the cache from becoming invalid when the page shifts around
Expand Down
11 changes: 5 additions & 6 deletions packages/dioxus-blitz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,14 @@ fn launch_with_window<Doc: DocumentLike + 'static>(window: View<'static, Doc>) {
event_loop.set_control_flow(ControlFlow::Wait);

let mut on_resume = || {
// Resume existing windows
for (_, view) in windows.iter_mut() {
view.resume(event_loop, &proxy, &rt);
}

for view in pending_windows.iter_mut() {
view.resume(event_loop, &proxy, &rt);
}

for window in pending_windows.drain(..) {
// Initialise pending windows
for mut window in pending_windows.drain(..) {
window.resume(event_loop, &proxy, &rt);
let RenderState::Active(state) = &window.renderer.render_state else {
continue;
};
Expand Down Expand Up @@ -189,7 +188,7 @@ fn launch_with_window<Doc: DocumentLike + 'static>(window: View<'static, Doc>) {
} => {
if let Some(window) = windows.get_mut(&window_id) {
window.renderer.dom.as_mut().resolve();
window.renderer.render(&mut window.scene);
window.renderer.render();
};
}

Expand Down
5 changes: 1 addition & 4 deletions packages/dioxus-blitz/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use wgpu::rwh::HasWindowHandle;

use std::sync::Arc;
use std::task::Waker;
use vello::Scene;
use winit::dpi::LogicalSize;
use winit::event::{ElementState, MouseButton};
use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
Expand All @@ -26,7 +25,6 @@ struct State {

pub(crate) struct View<'s, Doc: DocumentLike> {
pub(crate) renderer: Renderer<'s, Window, Doc>,
pub(crate) scene: Scene,
pub(crate) waker: Option<Waker>,
/// The state of the keyboard modifiers (ctrl, shift, etc). Winit/Tao don't track these for us so we
/// need to store them in order to have access to them when processing keypress events
Expand All @@ -40,7 +38,6 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> {
pub(crate) fn new(doc: Doc) -> Self {
Self {
renderer: Renderer::new(doc),
scene: Scene::new(),
waker: None,
keyboard_modifiers: Default::default(),
#[cfg(any(feature = "accessibility", feature = "menu"))]
Expand Down Expand Up @@ -362,7 +359,7 @@ impl<'a, Doc: DocumentLike> View<'a, Doc> {
};

self.waker = Some(crate::waker::tao_waker(proxy, state.window.id()));
self.renderer.render(&mut self.scene);
self.renderer.render();
}

pub fn suspend(&mut self) {
Expand Down
4 changes: 4 additions & 0 deletions packages/dom/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ pub struct Document {
/// The node which is currently focussed (if any)
pub(crate) focus_node_id: Option<usize>,

// TODO: move to nodes
pub scroll_offset: f64,

pub changed: HashSet<usize>,
}

Expand Down Expand Up @@ -127,6 +130,7 @@ impl Document {

hover_node_id: None,
focus_node_id: None,
scroll_offset: 0.0,
changed: HashSet::new(),
};

Expand Down

0 comments on commit aa66848

Please sign in to comment.