Введение
Большинство embedded-устройств не запускают полноценную систему рабочих столов с X11 или Wayland — Qt-приложение часто является единственным графическим приложением на устройстве, рисующим прямо в фреймбуфер или напрямую через EGL без промежуточного оконного менеджера. В статье разберём платформенные плагины Qt, спроектированные именно для таких сценариев — eglfs (для устройств с поддержкой OpenGL ES через EGL) и linuxfb (для устройств без аппаратного ускорения графики вовсе, рисующих напрямую в Linux framebuffer).
Концепция
Платформенный плагин Qt (QPA, Qt Platform Abstraction) определяет, как Qt взаимодействует с нижележащей графической системой — на десктопе это обычно xcb (X11) или wayland, а для embedded без полноценной оконной системы — eglfs или linuxfb. eglfs даёт полноэкранное Qt-приложение, использующее аппаратное ускорение GPU через EGL/OpenGL ES напрямую, без посредничества оконного менеджера — это обеспечивает максимальную производительность для embedded-устройств с GPU. linuxfb — более простой, программный рендеринг прямо в буфер кадра Linux без использования GPU вовсе, подходящий для устройств без графического ускорителя или для совсем простых интерфейсов.
Пример кода: Работа без X11/Wayland
# Запуск приложения с явным указанием платформенного плагина eglfs
./EmbeddedDashboard -platform eglfs
# Альтернатива через переменную окружения (удобно для systemd-сервисов)
export QT_QPA_PLATFORM=eglfs
./EmbeddedDashboard
# linuxfb — для устройств без GPU, с указанием конкретного устройства фреймбуфера
./EmbeddedDashboard -platform linuxfb:fb=/dev/fb0
# /etc/systemd/system/embedded-dashboard.service —
# типичный способ автозапуска Qt-приложения как единственного "композитора" на устройстве
[Unit]
Description=Embedded Dashboard Qt Application
After=multi-user.target
[Service]
Environment=QT_QPA_PLATFORM=eglfs
Environment=QT_QPA_EGLFS_INTEGRATION=eglfs_kms # для устройств без X/Wayland, прямой доступ к DRM/KMS
ExecStart=/opt/embedded-dashboard/EmbeddedDashboard
Restart=always
User=root
[Install]
WantedBy=multi-user.target
// main.cpp — определение фактически используемого платформенного плагина в коде,
// полезно для условной логики, специфичной для embedded-режима без оконной системы
#include <QGuiApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
const QString platformName = QGuiApplication::platformName();
qDebug() << "Используемый платформенный плагин:" << platformName;
if (platformName == "eglfs" || platformName == "linuxfb") {
qDebug() << "Запуск в embedded-режиме без оконной системы — "
"приложение является единственным на экране устройства";
// здесь может быть логика, специфичная для полноэкранного embedded-режима,
// например, отключение возможности свернуть/переместить окно
}
return app.exec();
}
Пояснения к коду
Запуск через -platform eglfs (или эквивалентную переменную окружения QT_QPA_PLATFORM) переключает Qt на работу без оконного менеджера — приложение становится единственным, занимающим весь экран устройства, что характерно для большинства embedded-сценариев (киоски, бортовые дисплеи, панели управления оборудованием). QT_QPA_EGLFS_INTEGRATION=eglfs_kms — пример дополнительной переменной окружения, конкретизирующей, как именно eglfs взаимодействует с графическим железом — kms (Kernel Mode Setting) означает прямой доступ к DRM-подсистеме ядра Linux, без устаревшего и менее предсказуемого пути через старые механизмы настройки видеорежима.
Пример systemd-юнита показывает типичный способ автозапуска embedded Qt-приложения сразу при загрузке устройства, без интерактивного входа пользователя — Restart=always гарантирует, что приложение, единственное отображаемое на устройстве, автоматически перезапустится при неожиданном завершении, что критично для embedded-устройств, где нет пользователя, способного вручную перезапустить приложение. Проверка QGuiApplication::platformName() в коде приложения позволяет логике приложения адаптироваться в зависимости от того, запущено ли оно в полноценной десктопной оконной системе (для отладки на машине разработчика) или в «голом» embedded-режиме без оконного менеджера.
Подводные камни
- Попытка использовать
eglfsна устройстве без правильно настроенного DRM/KMS драйвера или без соответствующих прав доступа (/dev/dri/*устройств) приводит к ошибкам инициализации графики при запуске — для нового, ещё не до конца настроенного embedded-окружения это частая первая проблема, требующая проверки корректности видеодрайвера ядра Linux на конкретной плате до попытки запуска Qt-приложения. - Несколько процессов, одновременно пытающихся захватить
eglfs/прямой доступ к DRM-устройству. В отличие от X11/Wayland, спроектированных для множества одновременно работающих графических клиентов,eglfsожидает единственного «владельца» экрана — попытка запустить второй Qt-процесс сeglfsодновременно с уже работающим первым обычно завершается ошибкой захвата устройства, а не корректным совместным использованием экрана. - Использование
linuxfbдля современных, графически насыщенных QML-интерфейсов с анимациями. Посколькуlinuxfbне использует GPU вовсе, весь рендеринг выполняется программно на CPU — для сложного, анимированного QML-интерфейса это может быть значительно медленнее, чем ожидается, иlinuxfbлучше подходит для простых, статичных или редко обновляемых интерфейсов на устройствах без графического ускорителя вообще. - Отсутствие тестирования отрисовки и обработки ввода (touch/мышь) специфично для конкретной комбинации платформенного плагина и используемого железа. Поведение обработки сенсорного ввода через
eglfsзависит от правильной настройки соответствующих input-плагинов Qt (evdevtouchи аналогичных), и без явной их настройки сенсорный экран может не работать вовсе, даже если визуальный рендеринг черезeglfsфункционирует корректно — калибровка и настройка сенсорного ввода разбираются отдельно в следующей статье цикла.