-
Notifications
You must be signed in to change notification settings - Fork 601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
internal: Remove the winit dependency from the renderers in the winit backend #1956
Conversation
window_builder: winit::window::WindowBuilder, | ||
_window: &dyn raw_window_handle::HasRawWindowHandle, | ||
_display: &dyn raw_window_handle::HasRawDisplayHandle, | ||
_size: PhysicalSize, | ||
#[cfg(target_arch = "wasm32")] canvas_id: &str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is somewhat of a kludge. It would be better if RawWindowHandle
would have a better way of identifying the canvas element. ALAS the int id in the web handle is local to winit and not unique in the DOM. But when a future version of raw-window-handle hopefully improves this, we can remove this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an upstream issue for that? Maybe rust-windowing/raw-window-handle#102 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's the one I saw as well. Wasn't sure about creating a backlink heh, but that's done now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But i think that could be good enough actually.
We can set the data-raw-handle
to some unique value somewhere else. Possibly in our js specific API.
Anyway, this is unrelated to this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that we can set this value, unless we re-implement HasRawWindowHandle and return our own id. Winit creates an event-loop local integer id and sets the attribute. We can find the DOM element then - that's fine. But if you think of our future JS API then this might become an issue:
If somebody uses the JS API and wasm module for one HTML canvas and a second instance (and was module) for another, then both would share the same IDs.
We could of course decide to ignore that and say that there must be only one.
(And yes, agreed, this is unrelated :)
window: &dyn raw_window_handle::HasRawWindowHandle, | ||
display: &dyn raw_window_handle::HasRawDisplayHandle, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These could be combined into one impl
as well, but I think for the public API of the renderer later we'll end up with dyn
anyway - so I went for two dyn.
internal/backends/winit/glcontext.rs
Outdated
) | ||
.unwrap() | ||
let window = crate::event_loop::with_window_target(|event_loop| { | ||
window_builder.build(event_loop.event_loop_target()).unwrap() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we really should unwrap()
here or give a better, more actionable error message.
Is that not what people will see if there is a problem with the display or something?
Or is it the following unwrap.
(Ideally, we should have made our API so slint user would be able to catch that error)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, this something to consider for the API. So before this PR we unwrapped and still do after this, but I agree that we should consider passing this to the caller in the public API.
window_builder: winit::window::WindowBuilder, | ||
_window: &dyn raw_window_handle::HasRawWindowHandle, | ||
_display: &dyn raw_window_handle::HasRawDisplayHandle, | ||
_size: PhysicalSize, | ||
#[cfg(target_arch = "wasm32")] canvas_id: &str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an upstream issue for that? Maybe rust-windowing/raw-window-handle#102 ?
display: &dyn raw_window_handle::HasRawDisplayHandle, | ||
size: PhysicalWindowSize, | ||
) -> Self::Canvas { | ||
let opengl_context = crate::OpenGLContext::new_context(window, display, size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated, but is there still no way to create a software context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean a software OpenGL context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean something onto which the software renderer could render without requiring femtovg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah no, this remains a missing piece / missing crate - unfortunately. That said, I think for improved compatibility on Windows I think it would make sense to switch that over to Skia.
Ok, on Windows this creates a window resize loop 🤪 |
d9582cb
to
7602d58
Compare
Rebased to include commit e573f5b |
internal/backends/winit/glwindow.rs
Outdated
@@ -202,7 +202,9 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WinitWindow for GLWindow<Rende | |||
|
|||
self.pending_redraw.set(false); | |||
|
|||
self.renderer.render(&window.canvas); | |||
let inner_size = window.window.inner_size(); | |||
let physical_size = PhysicalSize::new(inner_size.width, inner_size.height); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit sad that we lose type safety there. Looking at this snippet of code, i don't know that inner_size is indeed a physical size. Maybe the type could be made explicit. Or going through a conversion function that do the conversion in a type safe manner.
But feel free to ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No no, you have a valid point! I can clean this up with a helper trait I think, that converts winit’s physical size to our physical. Then it’s safe and less LOC here.
@@ -433,7 +431,6 @@ impl super::WinitCompatibleCanvas for FemtoVGCanvas { | |||
} | |||
|
|||
fn resize_event(&mut self, size: PhysicalWindowSize) { | |||
self.size = size; | |||
self.opengl_context.ensure_resized(size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does that mean that the opengl_context might have the wrong size?
But it is really strange that we don't get the resize_event before a draw.
Maybe this is the queue of events:
- draw (previous frame)
- resize event
- draw (current frame)
but when we process the draw event, the window already has been resized.
Just a theory, but a bit strange that window.inner_size() is already updated before we have time to draw, i thought it would be done in a single thread so events should be mixed like that. unless the call to inner_size() actually do a call to the display server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does that mean that the opengl_context might have the wrong size?
Yes, using the last value from the resize event results in the OpenGL context having the wrong size.
But it is really strange that we don't get the resize_event before a draw.
Maybe this is the queue of events:
- draw (previous frame)
- resize event
- draw (current frame)
but when we process the draw event, the window already has been resized.
Just a theory, but a bit strange that window.inner_size() is already updated before we have time to draw, i thought it would be done in a single thread so events should be mixed like that. unless the call to inner_size() actually do a call to the display server.
Yes, it's strange. And it's worse on wayland, see #1671 .
@@ -34,17 +34,33 @@ fn position_to_winit(pos: &corelib::api::WindowPosition) -> winit::dpi::Position | |||
} | |||
} | |||
|
|||
fn size_to_winit(pos: &corelib::api::WindowSize) -> winit::dpi::Size { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of using trait for this kind of stuff where you just add one function to a type. I kind of prefer free floating function as before. I don't really know why though. But if you prefer trait, i'm ok with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question, in reverse I don't know why I prefer a trait when ... your suggestion is literally less lines of code. I'll squash some of the other changes and change this one to use a free standing function. Thanks for the nudge :)
…ument We can unwrap internally.
GLWindow (yes, misnomed) is now responsible to creating and owing the winit::window::Window.
Encapsulate the direct conversion between physical sizes in functions, so that the conversion remains type safe and the code remains easy to read.
fc42f60
to
0c43c7b
Compare
This prepares for the ability to move renderers into a separate crate and let them have their own API, for advanced embedding of Slint.