Skip to content
Open
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
32 changes: 23 additions & 9 deletions crates/anyrender/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,40 +43,54 @@ pub trait WindowRenderer {
type ScenePainter<'a>: PaintScene
where
Self: 'a;
fn resume(&mut self, window: Arc<dyn WindowHandle>, width: u32, height: u32);
fn resume(
&mut self,
window: Arc<dyn WindowHandle>,
width: u32,
height: u32,
) -> Result<(), Box<dyn std::error::Error>>;
fn suspend(&mut self);
fn is_active(&self) -> bool;
fn set_size(&mut self, width: u32, height: u32);
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(&mut self, draw_fn: F);
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(
&mut self,
draw_fn: F,
) -> Result<(), Box<dyn std::error::Error>>;
}

/// Abstraction for rendering a scene to an image buffer
pub trait ImageRenderer {
type ScenePainter<'a>: PaintScene
where
Self: 'a;
fn new(width: u32, height: u32) -> Self;
fn new(width: u32, height: u32) -> Result<Self, Box<dyn std::error::Error>>
where
Self: Sized;
fn resize(&mut self, width: u32, height: u32);
fn reset(&mut self);
fn render_to_vec<F: FnOnce(&mut Self::ScenePainter<'_>)>(
&mut self,
draw_fn: F,
vec: &mut Vec<u8>,
);
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(&mut self, draw_fn: F, buffer: &mut [u8]);
) -> Result<(), Box<dyn std::error::Error>>;
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(
&mut self,
draw_fn: F,
buffer: &mut [u8],
) -> Result<(), Box<dyn std::error::Error>>;
}

/// Draw a scene to a buffer using an `ImageRenderer`
pub fn render_to_buffer<R: ImageRenderer, F: FnOnce(&mut R::ScenePainter<'_>)>(
draw_fn: F,
width: u32,
height: u32,
) -> Vec<u8> {
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut buf = Vec::with_capacity((width * height * 4) as usize);
let mut renderer = R::new(width, height);
renderer.render_to_vec(draw_fn, &mut buf);
let mut renderer = R::new(width, height)?;
renderer.render_to_vec(draw_fn, &mut buf)?;

buf
Ok(buf)
}

/// Abstraction for drawing a 2D scene
Expand Down
30 changes: 24 additions & 6 deletions crates/anyrender/src/null_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ impl WindowRenderer for NullWindowRenderer {
where
Self: 'a;

fn resume(&mut self, _window: Arc<dyn WindowHandle>, _width: u32, _height: u32) {
fn resume(
&mut self,
_window: Arc<dyn WindowHandle>,
_width: u32,
_height: u32,
) -> Result<(), Box<dyn std::error::Error>> {
self.is_active = true;
Ok(())
}

fn suspend(&mut self) {
Expand All @@ -34,7 +40,12 @@ impl WindowRenderer for NullWindowRenderer {

fn set_size(&mut self, _width: u32, _height: u32) {}

fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(&mut self, _draw_fn: F) {}
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(
&mut self,
_draw_fn: F,
) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
}

#[derive(Copy, Clone, Default)]
Expand All @@ -52,8 +63,8 @@ impl ImageRenderer for NullImageRenderer {
where
Self: 'a;

fn new(_width: u32, _height: u32) -> Self {
Self
fn new(_width: u32, _height: u32) -> Result<Self, Box<dyn std::error::Error>> {
Ok(Self)
}

fn resize(&mut self, _width: u32, _height: u32) {}
Expand All @@ -64,10 +75,17 @@ impl ImageRenderer for NullImageRenderer {
&mut self,
_draw_fn: F,
_vec: &mut Vec<u8>,
) {
) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}

fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(&mut self, _draw_fn: F, _buffer: &mut [u8]) {}
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(
&mut self,
_draw_fn: F,
_buffer: &mut [u8],
) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
}

#[derive(Copy, Clone, Default)]
Expand Down
20 changes: 13 additions & 7 deletions crates/anyrender_skia/src/image_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ impl ImageRenderer for SkiaImageRenderer {
where
Self: 'a;

fn new(width: u32, height: u32) -> Self {
fn new(width: u32, height: u32) -> Result<Self, Box<dyn std::error::Error>> {
graphics::set_font_cache_count_limit(100);
graphics::set_typeface_cache_count_limit(100);
graphics::set_resource_cache_total_bytes_limit(10485760);

Self {
Ok(Self {
image_info: ImageInfo::new(
(width as i32, height as i32),
ColorType::RGBA8888,
Expand All @@ -30,7 +30,7 @@ impl ImageRenderer for SkiaImageRenderer {
),
surface_props: SurfaceProps::default(),
scene_cache: SkiaSceneCache::default(),
}
})
}

fn resize(&mut self, width: u32, height: u32) {
Expand All @@ -48,7 +48,7 @@ impl ImageRenderer for SkiaImageRenderer {
&mut self,
draw_fn: F,
buffer: &mut Vec<u8>,
) {
) -> Result<(), Box<dyn std::error::Error>> {
debug_timer!(timer, feature = "log_frame_times");

let mut surface = surfaces::wrap_pixels(
Expand All @@ -57,7 +57,7 @@ impl ImageRenderer for SkiaImageRenderer {
None,
Some(&self.surface_props),
)
.unwrap();
.ok_or("Invalid surface parameters")?;

surface.canvas().clear(Color::WHITE);

Expand All @@ -71,9 +71,14 @@ impl ImageRenderer for SkiaImageRenderer {
timer.record_time("cache next gen");

timer.print_times("skia_raster: ");
Ok(())
}

fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(&mut self, draw_fn: F, buffer: &mut [u8]) {
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(
&mut self,
draw_fn: F,
buffer: &mut [u8],
) -> Result<(), Box<dyn std::error::Error>> {
debug_timer!(timer, feature = "log_frame_times");

let mut surface = surfaces::wrap_pixels(
Expand All @@ -82,7 +87,7 @@ impl ImageRenderer for SkiaImageRenderer {
None,
Some(&self.surface_props),
)
.unwrap();
.ok_or("Invalid surface parameters")?;

surface.canvas().clear(Color::WHITE);

Expand All @@ -96,5 +101,6 @@ impl ImageRenderer for SkiaImageRenderer {
timer.record_time("cache next gen");

timer.print_times("skia_raster: ");
Ok(())
}
}
28 changes: 11 additions & 17 deletions crates/anyrender_skia/src/opengl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl OpenGLBackend {
window: Arc<dyn anyrender::WindowHandle>,
width: u32,
height: u32,
) -> OpenGLBackend {
) -> Result<OpenGLBackend, Box<dyn std::error::Error>> {
let raw_display_handle = window.display_handle().unwrap().as_raw();
let raw_window_handle = window.window_handle().unwrap().as_raw();

Expand All @@ -44,15 +44,13 @@ impl OpenGLBackend {
DisplayApiPreference::Wgl(Some(raw_window_handle.clone())),
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
DisplayApiPreference::Egl,
)
.unwrap()
)?
};

let gl_config_template = ConfigTemplateBuilder::new().with_transparency(true).build();
let gl_config = unsafe {
gl_display
.find_configs(gl_config_template)
.unwrap()
.find_configs(gl_config_template)?
.reduce(|accum, config| {
let transparency_check = config.supports_transparency().unwrap_or(false)
& !accum.supports_transparency().unwrap_or(false);
Expand All @@ -63,7 +61,7 @@ impl OpenGLBackend {
accum
}
})
.unwrap()
.ok_or("No config available")?
};

let gl_context_attrs = ContextAttributesBuilder::new().build(Some(raw_window_handle));
Expand All @@ -73,20 +71,16 @@ impl OpenGLBackend {
NonZeroU32::new(height).expect("height should be a positive value"),
);

let gl_not_current_context = unsafe {
gl_display
.create_context(&gl_config, &gl_context_attrs)
.unwrap()
};
let gl_not_current_context =
unsafe { gl_display.create_context(&gl_config, &gl_context_attrs)? };

let gl_surface = unsafe {
gl_config
.display()
.create_window_surface(&gl_config, &gl_surface_attrs)
.unwrap()
.create_window_surface(&gl_config, &gl_surface_attrs)?
};

let gl_context = gl_not_current_context.make_current(&gl_surface).unwrap();
let gl_context = gl_not_current_context.make_current(&gl_surface)?;

gl::load_with(|s| {
gl_config
Expand All @@ -113,13 +107,13 @@ impl OpenGLBackend {
}

skia_safe::gpu::gl::FramebufferInfo {
fboid: fboid.try_into().unwrap(),
fboid: fboid.try_into()?,
format: skia_safe::gpu::gl::Format::RGBA8.into(),
..Default::default()
}
};

OpenGLBackend {
Ok(OpenGLBackend {
surface: Some(Self::create_surface(
width,
height,
Expand All @@ -132,7 +126,7 @@ impl OpenGLBackend {
gl_surface,
gl_context,
fb_info,
}
})
}

fn create_surface(
Expand Down
23 changes: 17 additions & 6 deletions crates/anyrender_skia/src/window_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,20 +49,27 @@ impl WindowRenderer for SkiaWindowRenderer {
where
Self: 'a;

fn resume(&mut self, window: Arc<dyn anyrender::WindowHandle>, width: u32, height: u32) {
fn resume(
&mut self,
window: Arc<dyn anyrender::WindowHandle>,
width: u32,
height: u32,
) -> Result<(), Box<dyn std::error::Error>> {
graphics::set_font_cache_count_limit(100);
graphics::set_typeface_cache_count_limit(100);
graphics::set_resource_cache_total_bytes_limit(10485760);

#[cfg(target_os = "macos")]
let backend = crate::metal::MetalBackend::new(window, width, height);
#[cfg(not(target_os = "macos"))]
let backend = crate::opengl::OpenGLBackend::new(window, width, height);
let backend = crate::opengl::OpenGLBackend::new(window, width, height)?;

self.render_state = RenderState::Active(Box::new(ActiveRenderState {
backend: Box::new(backend),
scene_cache: SkiaSceneCache::default(),
}))
}));

Ok(())
}

fn suspend(&mut self) {
Expand All @@ -79,16 +86,19 @@ impl WindowRenderer for SkiaWindowRenderer {
}
}

fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(&mut self, draw_fn: F) {
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(
&mut self,
draw_fn: F,
) -> Result<(), Box<dyn std::error::Error>> {
let RenderState::Active(state) = &mut self.render_state else {
return;
return Ok(());
};

debug_timer!(timer, feature = "log_frame_times");

let mut surface = match state.backend.prepare() {
Some(it) => it,
None => return,
None => return Ok(()),
};

surface.canvas().restore_to_count(1);
Expand All @@ -107,6 +117,7 @@ impl WindowRenderer for SkiaWindowRenderer {
timer.record_time("cache next gen");

timer.print_times("skia: ");
Ok(())
}
}

Expand Down
Loading
Loading