Skip to content

Commit

Permalink
piet-renderer working again
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelselleck committed Oct 29, 2024
1 parent f016c79 commit 1ae3ae5
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 50 deletions.
9 changes: 7 additions & 2 deletions pax-chassis-common/src/core_graphics_c_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

extern crate core;

use std::cell::RefCell;
use std::ffi::c_void;

use std::mem::{transmute, ManuallyDrop};
use std::rc::Rc;

use core_graphics::context::CGContext;
use pax_runtime::api::math::Point2;
Expand Down Expand Up @@ -123,11 +125,14 @@ pub extern "C" fn pax_tick(
let mut render_context = PietRenderer::new(move |_| {
let will_cast_cgContext = cgContext as *mut CGContext;
let ctx = unsafe { &mut *will_cast_cgContext };
CoreGraphicsContext::new_y_up(ctx, height as f64, None)
(
CoreGraphicsContext::new_y_up(ctx, height as f64, None),
Box::new(|| (/* clear screen here */)),
)
});

(*engine).set_viewport_size((width as f64, height as f64));
render_context.resize_layers_to(1);
render_context.resize_layers_to(1, Rc::new(RefCell::new(vec![false])));

let messages = (*engine).tick();
engine.render(&mut render_context as &mut dyn RenderContext);
Expand Down
24 changes: 15 additions & 9 deletions pax-chassis-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub fn wasm_memory() -> JsValue {

#[wasm_bindgen]
pub struct PaxChassisWeb {
drawing_contexts: Box<dyn RenderContext>,
render_context: Box<dyn RenderContext>,
engine: Rc<RefCell<PaxEngine>>,
#[cfg(any(feature = "designtime", feature = "designer"))]
userland_definition_to_instance_traverser:
Expand Down Expand Up @@ -111,7 +111,7 @@ impl PaxChassisWeb {
let engine_container: Rc<RefCell<PaxEngine>> = Rc::new(RefCell::new(engine));
Self {
engine: engine_container,
drawing_contexts: renderer,
render_context: renderer,
userland_definition_to_instance_traverser,
designtime_manager,
}
Expand All @@ -137,7 +137,7 @@ impl PaxChassisWeb {

Self {
engine: engine_container,
drawing_contexts: renderer,
render_context: renderer,
}
}

Expand Down Expand Up @@ -172,7 +172,14 @@ impl PaxChassisWeb {
// canvas.set_width(width as u32);
// canvas.set_height(height as u32);
// let _ = context.scale(dpr, dpr);
// WebRenderContext::new(context, win.clone())
// (
// WebRenderContext::new(context.clone(), win.clone()),
// Box::new(move || {
// let w = canvas.width();
// let h = canvas.height();
// context.clear_rect(0.0, 0.0, w as f64, h as f64);
// }),
// )
// });

let renderer = PaxPixelsRenderer::new(move |layer| {
Expand Down Expand Up @@ -234,8 +241,7 @@ impl PaxChassisWeb {
.borrow()
.runtime_context
.set_all_canvases_dirty();
self.drawing_contexts
.resize(width as usize, height as usize);
self.render_context.resize(width as usize, height as usize);
borrow_mut!(self.engine).set_viewport_size((width, height));
}

Expand Down Expand Up @@ -300,7 +306,7 @@ impl PaxChassisWeb {
ImageLoadInterruptArgs::Reference(_ref_args) => false,
ImageLoadInterruptArgs::Data(data_args) => {
let data = Uint8Array::new(additional_payload).to_vec();
self.drawing_contexts.load_image(
self.render_context.load_image(
&data_args.path,
&data,
data_args.width,
Expand Down Expand Up @@ -773,11 +779,11 @@ impl PaxChassisWeb {
}

pub fn render(&mut self) {
borrow_mut!(self.engine).render(self.drawing_contexts.as_mut());
borrow_mut!(self.engine).render(self.render_context.as_mut());
}

pub fn image_loaded(&mut self, path: &str) -> bool {
self.drawing_contexts.image_loaded(path)
self.render_context.image_loaded(path)
}
}

Expand Down
4 changes: 1 addition & 3 deletions pax-compiler/files/interfaces/web/src/classes/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ export class Layer {
this.occlusionLayerId = occlusionLayerId;
this.chassis = chassis;
this.canvasMap = canvasMap;
let canvas = document.createElement('canvas');
canvas.className = CANVAS_CLASS;
this.canvas = canvas;
this.canvas = this.objectManager.getFromPool(CANVAS);
this.native = this.objectManager.getFromPool(DIV);

this.canvas.style.zIndex = String(occlusionLayerId * 2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export class OcclusionLayerManager {
}

growTo(newOcclusionLayerId: number) {
let occlusionLayerId = newOcclusionLayerId + 1;
if(this.layers!.length <= occlusionLayerId){
for(let i = this.layers!.length; i <= occlusionLayerId; i++) {
let occlusionLayerCount = newOcclusionLayerId + 1;
if(this.layers!.length < occlusionLayerCount) {
for(let i = this.layers!.length; i < occlusionLayerCount; i++) {
let newLayer: Layer = this.objectManager.getFromPool(LAYER, this.objectManager);
newLayer.build(this.parent!, i, this.chassis!, this.canvasMap!);
this.layers!.push(newLayer);
Expand All @@ -43,7 +43,7 @@ export class OcclusionLayerManager {
return
}
if(this.layers.length >= occlusionLayerId) {
for(let i = this.layers!.length - 1; i > occlusionLayerId; i--){
for(let i = this.layers!.length - 1; i >= occlusionLayerId; i--){
this.objectManager.returnToPool(LAYER, this.layers[i]);
this.layers.pop();
}
Expand Down
2 changes: 1 addition & 1 deletion pax-designer/src/project_mode_toggle/mod.pax
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Group x=50% y=50% width={100% - 20px} height={100% - 20px}>
if self.edit_mode {
<Text text="Play" id=text fill=WHITE />
<Path class=play_triangle _raycastable=false/>
<Path id=play_symbol class=play_triangle _raycastable=false/>
}
if self.running_mode {
<Text text="Stop" id=text fill=WHITE />
Expand Down
13 changes: 10 additions & 3 deletions pax-runtime/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ impl PaxEngine {
/// a. find lowest node (last child of last node)
/// b. start rendering, from lowest node on-up, throughout tree
pub fn tick(&mut self) -> Vec<NativeMessage> {
// self.runtime_context.set_all_canvases_dirty();
//
// 1. UPDATE NODES (properties, etc.). This part we should be able to
// completely remove once reactive properties dirty-dag is a thing.
Expand All @@ -290,13 +291,14 @@ impl PaxEngine {
pub fn render(&mut self, rcs: &mut dyn RenderContext) {
static LAST_LAYER_COUNT: AtomicUsize = AtomicUsize::new(0); // last-patch layer_count
let curr_layer_count = self.runtime_context.layer_count.get();
if LAST_LAYER_COUNT.load(Ordering::Relaxed) != curr_layer_count {
let old_layer_count = LAST_LAYER_COUNT.load(Ordering::Relaxed);
if old_layer_count != curr_layer_count {
rcs.resize_layers_to(
curr_layer_count + 1,
curr_layer_count,
Rc::clone(&self.runtime_context.dirty_canvases),
);
self.runtime_context
.resize_canvas_layers_to(curr_layer_count + 1);
.resize_canvas_layers_to(curr_layer_count);
LAST_LAYER_COUNT.store(curr_layer_count, Ordering::Relaxed)
}

Expand All @@ -322,6 +324,11 @@ impl PaxEngine {
rcs.flush(i);
}
self.runtime_context.clear_all_dirty_canvases();

//dirtify the canvases that where created this frame (why is this needed?)
for i in old_layer_count..curr_layer_count {
self.runtime_context.set_canvas_dirty(i);
}
}

pub fn get_expanded_node(&self, id: ExpandedNodeIdentifier) -> Option<Rc<ExpandedNode>> {
Expand Down
19 changes: 15 additions & 4 deletions pax-runtime/src/engine/occlusion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ pub fn update_node_occlusion(root_node: &Rc<ExpandedNode>, ctx: &RuntimeContext)
let mut occlusion_stack = vec![];
let mut z_index = 0;
update_node_occlusion_recursive(root_node, &mut occlusion_stack, ctx, false, &mut z_index);
let max_layer = occlusion_stack.len() - 1;
if ctx.layer_count.get() != max_layer {
ctx.layer_count.set(max_layer);
ctx.enqueue_native_message(pax_message::NativeMessage::ShrinkLayersTo(max_layer as u32));
let new_layer_count = occlusion_stack.len();
if ctx.layer_count.get() != new_layer_count {
ctx.layer_count.set(new_layer_count);
ctx.enqueue_native_message(pax_message::NativeMessage::ShrinkLayersTo(
new_layer_count as u32,
));
}
}

Expand Down Expand Up @@ -117,6 +119,15 @@ fn update_node_occlusion_recursive(
.map(|v| v.to_u32()),
};

let cp = borrow!(node.common_properties);
let cp = borrow!(cp);
if cp
.id
.read(|i| i.as_ref().is_some_and(|i| i == "play_symbol"))
{
log::debug!("new occl: {:#?}", new_occlusion);
}

if (layer == Layer::Native || borrow!(node.instance_node).clips_content(&node))
&& node.occlusion.get() != new_occlusion
{
Expand Down
10 changes: 8 additions & 2 deletions pax-runtime/src/engine/pax_pixels_render_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,17 @@ impl PaxPixelsRenderer {
match backends.get_mut(layer) {
Some(layer_state) => match layer_state {
RenderLayerState::Pending => {
log::warn!("tried to retrieve layer context that wasn't ready")
log::warn!(
"tried to retrieve layer {} context that wasn't ready",
layer
);
}
RenderLayerState::Ready(renderer) => f(renderer),
},
None => log::warn!("tried to retrieve layer context for non-existent layer"),
None => log::warn!(
"tried to retrieve layer {} context for non-existent layer",
layer
),
}
}
}
Expand Down
52 changes: 30 additions & 22 deletions pax-runtime/src/engine/piet_render_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ struct ImgData<R: piet::RenderContext> {
size: (usize, usize),
}

type ClearFn = Box<dyn Fn()>;

pub struct PietRenderer<R: piet::RenderContext> {
backends: Vec<R>,
backends: Vec<(R, ClearFn)>,
image_map: HashMap<String, ImgData<R>>,
layer_factory: Box<dyn Fn(usize) -> R>,
layer_factory: Box<dyn Fn(usize) -> (R, Box<dyn Fn()>)>,
}

impl<R: piet::RenderContext> PietRenderer<R> {
pub fn new(layer_factory: impl Fn(usize) -> R + 'static) -> Self {
pub fn new(layer_factory: impl Fn(usize) -> (R, ClearFn) + 'static) -> Self {
Self {
layer_factory: Box::new(layer_factory),
backends: Vec::new(),
Expand All @@ -32,46 +34,46 @@ impl<R: piet::RenderContext> api::RenderContext for PietRenderer<R> {
fn fill(&mut self, layer: usize, path: kurbo::BezPath, fill: &Fill) {
let rect = path.bounding_box();
let brush = fill_to_piet_brush(fill, rect);
if let Some(layer) = self.backends.get_mut(layer) {
if let Some((layer, _)) = self.backends.get_mut(layer) {
layer.fill(path, &brush);
}
}

fn stroke(&mut self, layer: usize, path: kurbo::BezPath, fill: &Fill, width: f64) {
let rect = path.bounding_box();
let brush = fill_to_piet_brush(fill, rect);
if let Some(layer) = self.backends.get_mut(layer) {
if let Some((layer, _)) = self.backends.get_mut(layer) {
layer.stroke(path, &brush, width);
}
}

fn save(&mut self, layer: usize) {
if let Some(layer) = self.backends.get_mut(layer) {
if let Some((layer, _)) = self.backends.get_mut(layer) {
let _ = layer.save();
}
}

fn transform(&mut self, layer: usize, affine: Affine) {
if let Some(layer) = self.backends.get_mut(layer) {
if let Some((layer, _)) = self.backends.get_mut(layer) {
layer.transform(affine);
}
}

fn clip(&mut self, layer: usize, path: kurbo::BezPath) {
if let Some(layer) = self.backends.get_mut(layer) {
if let Some((layer, _)) = self.backends.get_mut(layer) {
layer.clip(path);
}
}

fn restore(&mut self, layer: usize) {
if let Some(layer) = self.backends.get_mut(layer) {
if let Some((layer, _)) = self.backends.get_mut(layer) {
let _ = layer.restore();
}
}

fn load_image(&mut self, path: &str, buf: &[u8], width: usize, height: usize) {
//is this okay!? we know it's the same kind of backend no matter what layer, but it might be storing data?
let render_context = self.backends.first_mut().unwrap();
let (render_context, _) = self.backends.first_mut().unwrap();
let img = render_context
.make_image(width, height, buf, piet::ImageFormat::RgbaSeparate)
.expect("image creation successful");
Expand All @@ -92,7 +94,7 @@ impl<R: piet::RenderContext> api::RenderContext for PietRenderer<R> {
let Some(data) = self.image_map.get(image_path) else {
return;
};
if let Some(layer) = self.backends.get_mut(layer) {
if let Some((layer, _)) = self.backends.get_mut(layer) {
layer.draw_image(&data.img, rect, InterpolationMode::Bilinear);
}
}
Expand All @@ -101,17 +103,19 @@ impl<R: piet::RenderContext> api::RenderContext for PietRenderer<R> {
self.backends.len()
}

fn resize_layers_to(&mut self, layer_count: usize, _dirty_canvases: Rc<RefCell<Vec<bool>>>) {
match layer_count.cmp(&self.backends.len()) {
fn resize_layers_to(&mut self, layer_count: usize, dirty_canvases: Rc<RefCell<Vec<bool>>>) {
let current_len = self.backends.len();
match layer_count.cmp(&current_len) {
std::cmp::Ordering::Less => {
for _ in self.backends.len()..layer_count {
self.backends.pop();
}
self.backends.truncate(layer_count);
}
std::cmp::Ordering::Equal => return,
std::cmp::Ordering::Greater => {
for i in self.backends.len()..layer_count {
for i in current_len..layer_count {
self.backends.push((self.layer_factory)(i));
if let Some(dirty_bit) = dirty_canvases.borrow_mut().get_mut(i) {
*dirty_bit = true;
}
}
}
}
Expand All @@ -122,15 +126,19 @@ impl<R: piet::RenderContext> api::RenderContext for PietRenderer<R> {
}

fn clear(&mut self, layer: usize) {
todo!()
if let Some((_, clear_fn)) = self.backends.get_mut(layer) {
(clear_fn)();
}
}

fn flush(&mut self, layer: usize) {
todo!()
fn flush(&mut self, _layer: usize) {
// NOTE: used for GPU rendering to flush changes to the screen, not needed
// during CPU rendering
}

fn resize(&mut self, width: usize, height: usize) {
todo!()
fn resize(&mut self, _width: usize, _height: usize) {
// NOTE: resizing of the backing canvas/window is done in chassi,
// no special logic needed here for CPU rendering
}
}

Expand Down
1 change: 1 addition & 0 deletions pax-runtime/src/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ impl RuntimeContext {

pub fn clear_all_dirty_canvases(&self) {
let mut dirty_canvases = borrow_mut!(self.dirty_canvases);
log::debug!("dirty canvases: {:#?}", dirty_canvases);
for v in dirty_canvases.iter_mut() {
*v = false;
}
Expand Down

0 comments on commit 1ae3ae5

Please sign in to comment.