Skip to content

Commit

Permalink
Enable partial rendering with Skia's software renderer by default
Browse files Browse the repository at this point in the history
  • Loading branch information
tronical committed Jan 30, 2025
1 parent a4ff057 commit ac7c2dd
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 36 deletions.
3 changes: 1 addition & 2 deletions api/rs/slint/tests/partial_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,9 @@ struct SkiaTestWindow {
impl SkiaTestWindow {
fn new() -> Rc<Self> {
let render_buffer = Rc::new(SkiaTestSoftwareBuffer::default());
let mut renderer = SkiaRenderer::new_with_surface(Box::new(
let renderer = SkiaRenderer::new_with_surface(Box::new(
i_slint_renderer_skia::software_surface::SoftwareSurface::from(render_buffer.clone()),
));
i_slint_renderer_skia::SkiaRendererExt::enable_partial_rendering(&mut renderer);
Rc::new_cyclic(|w: &Weak<Self>| Self {
window: slint::Window::new(w.clone()),
renderer,
Expand Down
71 changes: 37 additions & 34 deletions internal/renderers/skia/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,25 @@ enum DirtyRegionDebugMode {
Log,
}

fn create_partial_renderer_state() -> (Option<PartialRenderingState>, DirtyRegionDebugMode) {
let dirty_region_debug_mode = match std::env::var("SLINT_SKIA_PARTIAL_RENDERING").as_deref() {
Ok("visualize") => DirtyRegionDebugMode::Visualize,
Ok("log") => DirtyRegionDebugMode::Log,
Ok(_) => DirtyRegionDebugMode::NoDebug,
_ => return (None, DirtyRegionDebugMode::NoDebug),
};

(Some(PartialRenderingState::default()), dirty_region_debug_mode)
impl Default for DirtyRegionDebugMode {
fn default() -> Self {
match std::env::var("SLINT_SKIA_PARTIAL_RENDERING").as_deref() {
Ok("visualize") => DirtyRegionDebugMode::Visualize,
Ok("log") => DirtyRegionDebugMode::Log,
_ => DirtyRegionDebugMode::NoDebug,
}
}
}

fn create_partial_renderer_state(
maybe_surface: Option<&dyn Surface>,
) -> Option<PartialRenderingState> {
maybe_surface
.map_or_else(
|| std::env::var("SLINT_SKIA_PARTIAL_RENDERING").as_deref().is_ok(),
|surface| surface.use_partial_rendering(),
)
.then(|| PartialRenderingState::default())
}

/// Use the SkiaRenderer when implementing a custom Slint platform where you deliver events to
Expand Down Expand Up @@ -132,7 +142,6 @@ pub struct SkiaRenderer {

impl Default for SkiaRenderer {
fn default() -> Self {
let (partial_rendering_state, dirty_region_debug_mode) = create_partial_renderer_state();
Self {
maybe_window_adapter: Default::default(),
rendering_notifier: Default::default(),
Expand All @@ -143,8 +152,8 @@ impl Default for SkiaRenderer {
surface: Default::default(),
surface_factory: create_default_surface,
pre_present_callback: Default::default(),
partial_rendering_state,
dirty_region_debug_mode,
partial_rendering_state: create_partial_renderer_state(None),
dirty_region_debug_mode: Default::default(),
dirty_region_history: Default::default(),
}
}
Expand All @@ -154,7 +163,6 @@ impl SkiaRenderer {
#[cfg(skia_backend_software)]
/// Creates a new SkiaRenderer that will always use Skia's software renderer.
pub fn default_software() -> Self {
let (partial_rendering_state, dirty_region_debug_mode) = create_partial_renderer_state();
Self {
maybe_window_adapter: Default::default(),
rendering_notifier: Default::default(),
Expand All @@ -173,16 +181,15 @@ impl SkiaRenderer {
.map(|r| Box::new(r) as Box<dyn Surface>)
},
pre_present_callback: Default::default(),
partial_rendering_state,
dirty_region_debug_mode,
partial_rendering_state: PartialRenderingState::default().into(),
dirty_region_debug_mode: Default::default(),
dirty_region_history: Default::default(),
}
}

#[cfg(not(target_os = "ios"))]
/// Creates a new SkiaRenderer that will always use Skia's OpenGL renderer.
pub fn default_opengl() -> Self {
let (partial_rendering_state, dirty_region_debug_mode) = create_partial_renderer_state();
Self {
maybe_window_adapter: Default::default(),
rendering_notifier: Default::default(),
Expand All @@ -201,16 +208,15 @@ impl SkiaRenderer {
.map(|r| Box::new(r) as Box<dyn Surface>)
},
pre_present_callback: Default::default(),
partial_rendering_state,
dirty_region_debug_mode,
partial_rendering_state: create_partial_renderer_state(None),
dirty_region_debug_mode: Default::default(),
dirty_region_history: Default::default(),
}
}

#[cfg(target_vendor = "apple")]
/// Creates a new SkiaRenderer that will always use Skia's Metal renderer.
pub fn default_metal() -> Self {
let (partial_rendering_state, dirty_region_debug_mode) = create_partial_renderer_state();
Self {
maybe_window_adapter: Default::default(),
rendering_notifier: Default::default(),
Expand All @@ -229,16 +235,15 @@ impl SkiaRenderer {
.map(|r| Box::new(r) as Box<dyn Surface>)
},
pre_present_callback: Default::default(),
partial_rendering_state,
dirty_region_debug_mode,
partial_rendering_state: create_partial_renderer_state(None),
dirty_region_debug_mode: Default::default(),
dirty_region_history: Default::default(),
}
}

#[cfg(skia_backend_vulkan)]
/// Creates a new SkiaRenderer that will always use Skia's Vulkan renderer.
pub fn default_vulkan() -> Self {
let (partial_rendering_state, dirty_region_debug_mode) = create_partial_renderer_state();
Self {
maybe_window_adapter: Default::default(),
rendering_notifier: Default::default(),
Expand All @@ -257,16 +262,15 @@ impl SkiaRenderer {
.map(|r| Box::new(r) as Box<dyn Surface>)
},
pre_present_callback: Default::default(),
partial_rendering_state,
dirty_region_debug_mode,
partial_rendering_state: create_partial_renderer_state(None),
dirty_region_debug_mode: Default::default(),
dirty_region_history: Default::default(),
}
}

#[cfg(target_family = "windows")]
/// Creates a new SkiaRenderer that will always use Skia's Direct3D renderer.
pub fn default_direct3d() -> Self {
let (partial_rendering_state, dirty_region_debug_mode) = create_partial_renderer_state();
Self {
maybe_window_adapter: Default::default(),
rendering_notifier: Default::default(),
Expand All @@ -285,8 +289,8 @@ impl SkiaRenderer {
.map(|r| Box::new(r) as Box<dyn Surface>)
},
pre_present_callback: Default::default(),
partial_rendering_state,
dirty_region_debug_mode,
partial_rendering_state: create_partial_renderer_state(None),
dirty_region_debug_mode: Default::default(),
dirty_region_history: Default::default(),
}
}
Expand All @@ -307,7 +311,7 @@ impl SkiaRenderer {

/// Creates a new renderer with the given surface trait implementation.
pub fn new_with_surface(surface: Box<dyn Surface + 'static>) -> Self {
let (partial_rendering_state, dirty_region_debug_mode) = create_partial_renderer_state();
let partial_rendering_state = create_partial_renderer_state(Some(surface.as_ref())).into();
Self {
maybe_window_adapter: Default::default(),
rendering_notifier: Default::default(),
Expand All @@ -321,7 +325,7 @@ impl SkiaRenderer {
},
pre_present_callback: Default::default(),
partial_rendering_state,
dirty_region_debug_mode,
dirty_region_debug_mode: Default::default(),
dirty_region_history: Default::default(),
}
}
Expand Down Expand Up @@ -966,6 +970,10 @@ pub trait Surface {
) -> Result<(), i_slint_core::platform::PlatformError>;
fn bits_per_pixel(&self) -> Result<u8, PlatformError>;

fn use_partial_rendering(&self) -> bool {
false
}

/// Implementations should return self to allow upcasting.
fn as_any(&self) -> &dyn core::any::Any {
&()
Expand All @@ -980,8 +988,6 @@ pub trait SkiaRendererExt {
surface_size: PhysicalWindowSize,
post_render_cb: Option<&dyn Fn(&mut dyn ItemRenderer)>,
) -> Result<(), i_slint_core::platform::PlatformError>;
/// Remove this when partial rendering becomes enabled by default.
fn enable_partial_rendering(&mut self);
}

impl SkiaRendererExt for SkiaRenderer {
Expand All @@ -999,7 +1005,4 @@ impl SkiaRendererExt for SkiaRenderer {
post_render_cb,
)
}
fn enable_partial_rendering(&mut self) {
self.partial_rendering_state = Some(PartialRenderingState::default())
}
}
4 changes: 4 additions & 0 deletions internal/renderers/skia/software_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ impl super::Surface for SoftwareSurface {
fn bits_per_pixel(&self) -> Result<u8, i_slint_core::platform::PlatformError> {
Ok(24)
}

fn use_partial_rendering(&self) -> bool {
true
}
}

impl<T: RenderBuffer + 'static> From<T> for SoftwareSurface {
Expand Down

0 comments on commit ac7c2dd

Please sign in to comment.