Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors the Skia example to use proper error handling with thiserror, removes unnecessary complexity, and modernizes the code structure. The example is now more maintainable and easier to understand.
Changes:
- Introduced a comprehensive
AppErrorenum usingthiserrorfor proper error handling - Converted
main()to returnResult<(), AppError>instead of panicking - Simplified the code structure by removing unnecessary abstractions (
AppSettings, frame rate control, trait-based rendering) - Refactored GL context creation into a dedicated function with proper documentation
- Changed event loop to use
ControlFlow::Waitfor better efficiency (event-driven instead of time-based)
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| examples/skia.rs | Complete refactoring with proper error handling, simplified structure, and cleaner event handling |
| examples/Cargo.toml | Added thiserror = "2" dependency for error handling |
| Cargo.lock | Updated lock file with thiserror 2.0.12 dependency |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| match self | ||
| .gpu_state | ||
| .create_target_surface(size.width as i32, size.height as i32) | ||
| { | ||
| Ok(s) => self.surface = s, | ||
| Err(e) => { | ||
| self.render_error = Some(e.into()); | ||
| event_loop.exit(); | ||
| return; | ||
| } | ||
| } | ||
| if let (Some(w), Some(h)) = | ||
| (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) | ||
| { | ||
| self.gl_surface.resize(&self.gl_context, w, h); | ||
| } | ||
| self.window.request_redraw(); |
There was a problem hiding this comment.
The GL surface resize is only performed when both width and height are non-zero, but the Skia target surface is always recreated regardless of dimensions. This inconsistency could lead to a mismatch between the GL surface and Skia surface dimensions when the window is minimized (resulting in zero dimensions). Consider either skipping both operations when dimensions are zero, or handling the zero-dimension case consistently for both surfaces.
| match self | |
| .gpu_state | |
| .create_target_surface(size.width as i32, size.height as i32) | |
| { | |
| Ok(s) => self.surface = s, | |
| Err(e) => { | |
| self.render_error = Some(e.into()); | |
| event_loop.exit(); | |
| return; | |
| } | |
| } | |
| if let (Some(w), Some(h)) = | |
| (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) | |
| { | |
| self.gl_surface.resize(&self.gl_context, w, h); | |
| } | |
| self.window.request_redraw(); | |
| if let (Some(w), Some(h)) = | |
| (NonZeroU32::new(size.width), NonZeroU32::new(size.height)) | |
| { | |
| match self | |
| .gpu_state | |
| .create_target_surface(w.get() as i32, h.get() as i32) | |
| { | |
| Ok(s) => self.surface = s, | |
| Err(e) => { | |
| self.render_error = Some(e.into()); | |
| event_loop.exit(); | |
| return; | |
| } | |
| } | |
| self.gl_surface.resize(&self.gl_context, w, h); | |
| self.window.request_redraw(); | |
| } |
examples/skia.rs
Outdated
| /// # Safety | ||
| /// | ||
| /// This function uses unsafe internally because OpenGL context creation and |
There was a problem hiding this comment.
The # Safety section in the documentation is typically reserved for unsafe functions to document their safety requirements for callers. Since create_gl_context_and_surface is not an unsafe function, this section might confuse readers. Consider rephrasing this as a regular documentation comment explaining that the function encapsulates unsafe OpenGL operations, or using a different heading like # Implementation Notes.
| /// # Safety | |
| /// | |
| /// This function uses unsafe internally because OpenGL context creation and | |
| /// # Implementation Notes | |
| /// | |
| /// This function uses `unsafe` internally because OpenGL context creation and |
| let dominated = b.supports_transparency().unwrap_or(false) | ||
| && !a.supports_transparency().unwrap_or(false); | ||
| if dominated || b.num_samples() < a.num_samples() { |
There was a problem hiding this comment.
The variable name dominated is unclear in this context. The logic is selecting a GL config where b has transparency and a doesn't, which could be more clearly named as b_has_better_transparency or prefer_b_transparency to make the selection criteria more obvious.
| let dominated = b.supports_transparency().unwrap_or(false) | |
| && !a.supports_transparency().unwrap_or(false); | |
| if dominated || b.num_samples() < a.num_samples() { | |
| let b_has_preferred_transparency = b.supports_transparency().unwrap_or(false) | |
| && !a.supports_transparency().unwrap_or(false); | |
| if b_has_preferred_transparency || b.num_samples() < a.num_samples() { |
No description provided.