-
Notifications
You must be signed in to change notification settings - Fork 612
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
Add support for direct fullscreen rendering on Linux #712
Comments
If you're okay depending on Qt you can accomplish this with the EGLFS platform plugin on Linux. If your version of Qt was built with the EGLFS plugin you should be able to set
|
Kind contributor @StratusFearMe21 is working on supporting direct rendering in winit and glutin: rust-windowing/winit#2272 🚀 This would enable Slint as well. |
I made a proof of concept to do this directly in Slint, using Vulkan's extension to access the display directly, calloop, and libinput. I've uploaded the code into https://github.com/slint-ui/slint/tree/simon/vulkanfs |
For anyone trying to do this in an embedded environment: #!/bin/sh
export SLINT_BACKEND=Qt
export QT_QPA_PLATFORM=eglfs
export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
export QT_QPA_EGLFS_ALWAYS_SET_MODE=1
export QT_QPA_EGLFS_KMS_ATOMIC=1
export QT_AUTO_SCREEN_SCALE_FACTOR=0
export QT_QPA_EGLFS_KMS_CONFIG=/opt/evolve-hmi/eglfs-tj028.conf
/usr/bin/evolve-hmi 2>&1
A good reason to use QT for this is that startup time is much faster. The difference between using weston and eglfs is approx 2-5s depending on if clean boot. |
The winit code mentioned above was forked due to inaction by the original author to rust-windowing/winit#2795 |
@tronical are you planning to have a go at doing this with egl at all? Reason I ask is that vulkan on embedded GPU (vivante series) isn't supported until GC8000 model. I've found that QT eglfs is adequate, but would love to drop that dependency from the build - and weston isn't really a good alternative due to it adding additional seconds to the startup time. |
My embedded device runs linux but it doesn't have a GPU. So QT eglfs doesn't seem to fit. Is there any other way for slint ui to achieve direct framebuffer rendering on linux without a GPU ? |
Yes, I read up a little about the gbm surface handling, creating EGL window surfaces from it, and how to do page flipping - I'd like to implement this, too. I have a local WIP for this that renders a few frames with egl instead of Vulkan, but it's not cleaned up yet. On the upside, it's just ~200 lines of code. I'd like to finish that yes and once it works prepare a PR that adds Vulkan or egl rendering on top of kms as an experimental backend for Slint. |
@tronical that's excellent news mate. As soon as you need testing ping me and I'll put it through its paces. |
You might look at linuxfb backend of QT maybe. Mileage will vary depending on your environment and what is available. |
Okay, I have something that might be worth testing. It's highly experimental and I've merely tested this on my laptop. There's a simon/linuxkms branch in the repo. In your Slint crate feature selection, disable default features, select the The application then needs to run as root unfortunately - no libseat support yet. There should be touch support, but I'm not entirely sure it works. Mouse support works, but there's no mouse cursor rendered. Otherwise this uses a gbm surface to render and non-atomic mode setting for page flips. |
Additional notes for testing: Set the environment variable The preferred mode of the output is selected. If there is no preferred mode, the highest resolution will be chose. Both of these need additional fixing to make them more usable, like for specific mode selection and persistence via a file instead of environment variables. |
Hi @tronical I did a quick test build:
With |
My bad, when I test the feature combination I still had another backend in there so I didn't notice this :(. I pushed a fix. |
Alright, quick test on the STM32MP157:
This is due to: pub fn create_egl_display() -> Result<EglDisplay, PlatformError> {
let drm_device = SharedFd(Arc::new(
std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/dri/card0")
.map_err(|err| format!("Error opening /dev/dri/card0: {}", err))?,
)); It would be best to try each available card in that directory - for my device Awesome work! |
This photo just made my day! Yep, hardcoding /dev/dri/card0 is incorrect. I'll fix that :) |
Hmm, A persistent issue seems to be that things aren't as smooth as I would have liked - this was true on qt-eglfs as well as weston. Even though the app does feel a bit more responsive with KMS. It manifests as looking perhaps a little like missing frames? What EGL calls does the stack make? I did some experimenting a little while ago and one GL call in particular was dead slow on this GC400 (vivante). |
I see the libinput error on my laptop, too - I think it may be a bug in the way I implemented the event loop. Performance wise there are two things:
|
Skia has been the biggest PIA to build at all. Do you have any tips? Specifically, cross-platform builds for it are the worst experience and last time I tried it fell over on ring (crypto). I had two places with drop-shadow, removing those and the radius on a clipped rectangle worked wonders! Thank you for the pointers. Right now this appears to be faster and more responsive than the eglfs build. And it is so very much faster than our QT version with all its QML and FFI overhead. I don't have any animations yet, so I'm entirely unsure about if it seems to drop frames, or if it's input lag that I'm seeing. I will animate something for a test tomorrow and see how it performs. |
There is one more optimization to femtovg that I did a while ago (fast image blit if I clipped), but unfortunately it regressed. A few weeks ago I fixed it in femtovg/femtovg@2b05b93 but this isn't released yet. I'll do that in the next days and then cargo update should get you that one. The screenshot looks like it's blitting images. (You'd be shocked about the amount of instructions femtovg used to apply in the fragment shader for that :) On the Skia side: Yeah, the ring build issue I had as well. It's a little iffy to cross-compile :(, but it is possible. I documented the environment variables needed a while ago here. It gets a little more complicated with Yocto. How are you building Slint/your app? |
Blimey... Okay that is a noticeable improvement @tronical. Well done! (for femtovg update). |
I suggest the following plan going forward:
|
Just a quick test report: I just tried syncing to the I was able to build this for reTerminal (an Rpi CM4 development board) by building a cross image based on
Also adding
After the FROM directive was helpful when updating the docker image as sometimes it would try to stop me to ask about the timezone but hang since there's no shell attached. I then built the printer demo with:
scp'd the resulting binary to the RPI CM4 and started it via ssh with
Unfortunately the reTerminal has a quirk where noone has seemed to be able to rotate the screen to horizontal in kms mode (I guess they assume you'll use a window manager that can paper over this.) Anyhow I'm assuming if I were building an app in slint I could have slint do the 90 degree rotation for me? One other issue I experienced is that tap targets were very hard to hit. At first I thought the screen wasn't responding to touch at all but after about 10 taps I can usally finally get it to recognize what I'm trying to hit. This may be a calibration issue, but on some screens like the "USB" screen in the printer demo where the filename targets are long enough it is quite easy to tap. As long as the tap is recognized it actually seems very snappy. (Much snappier than the reTerminal demo apps which are made in QT python.) |
Thanks @jakerr for testing - much appreciated. The install steps you mentioned make sense. Now that the changes are merged into master, there's also libseat support, which means you also need Performance wise I noticed a difference between debug and release builds. With debug builds I get the warning from libinput that events are sometimes processed too slowly, but with release it feels snappy. The touch input is something that's a little concerning. @ogoffart how well does it work on your laptop with touch screen? |
Is keyboard support planned? |
Yes. At the moment there's only support for ctrl-alt-delete/ctrl-alt-backspace as shortcuts to terminate the process (so that's just an escape hatch), but I'd like to support proper keyboard input. The mechanics for that are in place in |
Olivier was kind enough to implement keyboard support today ❤️ |
It would be great if it was possible to run an application on Linux in full screen without a windowing system (wayland or x11). In some systems the multi-window or multi-seat capability the windowing systems offer is not needed.
In practice on Linux this can be achieved on many hardware platforms using the Mesa's GBM interface, the EGL GBM extension and then the EGL API to get a GL context. There may also be some platforms where GBM is replaced with a vendor specific interface, but in practice those do eventually lead to an EGL window surface. For example when using the proprietary video core driver on the Raspberry PI, the Dispmanx interface provides the
EGLNativeWindowType
. The libinput provides support for keyboard/mouse/touch input.These are all traditionally C interfaces, but fortunately the Smithay project provides great APIs to access these components with idiomatic Rust APIs, along with an event loop interface to tie them together. In Smithay this is used to implement the anvil wayland compositor.
This could either be a separate rendering backend, where we'd have to re-organize the GL renderer for code sharing. Or alternatively the existing GL backend could be changed to add support for a module that utilises smithay's backend modules and event loop, besides winit.
The text was updated successfully, but these errors were encountered: