The event loop roughly loops like this:
loop {
update_timers_and_animations();
render();
sleep_or_dispatch_events();
}
sleep_or_dispatch_events() will wake up when we receive a queued callback from invoke_from_event_loop, and we would
run the callback right away. If that callback sets animated properties, the start time for animations would be incorrect, as we haven't called update_timers_and_animations() yet.
So instead, let's keep track of any received callbacks per sleep cycle, update the animation tick, and then invoke the callbacks.
We call set_fullscreen(None) on startup for windows that aren't fullscreen (normally), and winit compiled for the web unconditionally calls canvas.exitFullscreen(), which
may produces warnings about exitFullscreen()
being called when not in fullscreen mode.
We trigger update_timers_and_animations() every time the event loop wakes up.
If there's a real animation in the UI going on, that'll also trigger a
request_redraw() call and all will be well.
But when the only source of animation is set_has_active_animations() from
RenderingMetricsCollector, then we might end up in a situation where the event
loop is woken up before the rendered frame is on the screen, which means we
invoke update_timers_and_animations(), but we won't render because the
previous frame isn't shown yet. When it is shown and our presentation callback
is invoked, has_active_animations() is false again.
So instead, remember if we need to re-render once after rendering()
and use that to decide if we need to re-render in the presentation callback.
Move the set_fullscreen function added to the WindowAdapter trait in 779aff0b39
to be a function in WindowProperties instead.
That way it'll be easier in the future to extend this with other window states without
having to modify or break the WindowAdapter trait API.
This is the initial implementation based on DRM dumb buffers,
which cleans up various things at the same time:
- DRM output is separate from GBM and DRM dumb buffer displays.
The latter two re-use the former.
- The timer refresh for the Vulkan KHR Display rendering lives
now with the KHR display code, in hope to be replaced with a
better mechanism in the future.
What's missing still is support for partial updates as well as
rendering with our own software renderer.
Remove the hack of calling present() from our swap_buffers() forwarder (and let it really only forward),
and instead call it explicitly through the shared egl_display member.
The way we can pass along the callback instead of storing it separately.
Move this back out of render() again and make it stateful in the renderer. Reduces the amount of book-keeping required and it's always the same callback anyway.
Calling request_request() during RedrawRequested would not work on
Windows and wasm. Commit 372e6b0ffc worked
around this, but that can be reverted now, as this is fixed in winit.
For windows that was https://github.com/rust-windowing/winit/pull/3165
and for wasm I couldn't find the change, but could verify that it still
works.
I checked that #1574 does not regress.
Besides the cleanup, this is also needed for #1695.
We don't need to wait 16ms, we could render right away. In theory this could also use invoke_from_event_loop, but then
the callback needs to be sync, which is an unnecessary
complication.
That's less boiler plate for us and better error handling (note how the receive_events()
call on the DRM device now propagates the error). And this also unregisters automatically
on drop.
... instead pass the fd into the calloop event loop and change state when we receive activity on it.
This improves performance slightly, and is a necessary to be able to implement refresh rate throttled rendering (in the next commits).
This patch adds support for the `SLINT_KMS_ROTATION` environment
variable, that instructs the Skia/FemtoVG renderers to rotate
the scene before rendering.