Spec-Zone.ru › Qt

Qt для встраиваемых систем Linux

В системах встраиваемого Linux есть несколько плагинов платформы, которые вы можете использовать: EGLFS, LinuxFB, DirectFB или Wayland. Однако доступность этих плагинов зависит от того, как настроен Qt.

EGLFS — это плагин по умолчанию на многих платах. Если он не подходит, используйте переменную среды QT_QPA_PLATFORM, чтобы запросить другой плагин. В качестве альтернативы для быстрых тестов используйте командную строку -platform с тем же синтаксисом.

Примечание: Начиная с Qt 5.0, Qt больше не имеет собственной реализации системы окон (QWS). Для однопроцессных случаев Qt Platform Abstraction является лучшим решением; многопроцессные случаи поддерживаются через Wayland.

См. Настройка устройства встраиваемого Linux для обзора настройки Qt для кросс-компиляции с помощью инструментария встраиваемой системы Linux.

Плагины платформы для устройств встраиваемого Linux

EGLFS

EGL — это интерфейс между OpenGL и родной системой окон. Qt может использовать EGL для управления контекстом и поверхностью, однако API не содержит платформоспецифичных элементов. Создание родного окна, которое не обязательно будет реальным окном на экране, всё равно должно выполняться с использованием платформоспецифичных средств. Вот почему нам нужен адаптационный код, специфичный для платы или графического процессора. Обычно эти адаптации предоставляются как:

  • Ссылочные данные EGLFS — один исходный файл, скомпилированный в плагин платформы
  • Интеграция устройства EGL — динамически загружаемые плагины

EGLFS — это плагин платформы для запуска приложений Qt поверх EGL и OpenGL ES 2.0 без реальной системы окон, такой как X11 или Wayland. Это рекомендуемый плагин для современных устройств встраиваемого Linux, которые включают графический процессор.

Помимо приложений Qt Quick и нативных приложений OpenGL, EGLFS поддерживает и окна с программной отрисовкой, такие как QWidget. Для QWidget содержимое виджетов отрисовывается процессором в изображения, которые затем загружаются в текстуры и композируются плагином.

EGLFS принудительно делает первое окно верхнего уровня — будь то QWidget или QQuickView — полноэкранным. Это окно также выбирается в качестве корневого окна виджета, в которое композируются все другие виджеты верхнего уровня. Например, диалоговые окна, всплывающие меню или комбинированные поля. Это поведение необходимо, потому что с EGLFS всегда существует ровно одно родное окно и одна поверхность окна EGL; они принадлежат тому виджету или окну, которое создаётся первым. Этот подход хорошо работает, когда существует главное окно, существующее на протяжении всего жизненного цикла приложения, а все другие виджеты являются либо не верхними уровнями, либо создаются позже, после отображения главного окна.

Существуют дополнительные ограничения для окон на основе OpenGL. EGLFS поддерживает одно полноэкранное окно GL (начиная с Qt 5.3), такое как окно OpenGL на основе QWindow, QQuickView или QOpenGLWidget. Открытие дополнительных окон OpenGL или смешивание таких окон с содержимым на основе QWidget не поддерживается; Qt завершает приложение с сообщением об ошибке.

Кроме того, API, разработанные для настольных платформ или сред с системой окон, такие как Перетаскивание, не поддерживаются в EGLFS.

При необходимости eglfs можно настроить с помощью следующих переменных окружения:

Переменная окружения Описание
QT_QPA_EGLFS_INTEGRATION В дополнение к скомпилированным ссылочным данным, также можно использовать динамически загружаемые плагины для предоставления адаптации, специфичной для устройства или поставщика. Эта переменная окружения принудительно использует определённый плагин. Например, установка её в значение eglfs_kms использует бэкэнд KMS/DRM. Это возможно только в том случае, если никакие статические или скомпилированные ссылочные данные не были указаны в устройстве makespecs. На практике традиционные скомпилированные ссылочные данные редко используются, почти все бэкэнды теперь мигрированы в плагины. В файлах описания устройства makespecs всё ещё присутствует соответствующая EGLFS_DEVICE_INTEGRATION запись: имя предпочтительного бэкэнда для этого конкретного устройства. Это необязательно, но очень полезно, чтобы избежать необходимости установки этой переменной окружения, если в целевой системе присутствует более одного плагина. В настольной среде приоритет отдаётся бэкендам KMS или X11, в зависимости от наличия переменной окружения DISPLAY.

Примечание: На некоторых платах вместо фактического плагина используется специальное значение none. Это указывает на то, что специальная интеграция для использования EGL с буфером кадров не требуется; не нужно загружать плагины.

QT_QPA_EGLFS_PHYSICAL_WIDTH и QT_QPA_EGLFS_PHYSICAL_HEIGHT Указывают ширину и высоту физического экрана в миллиметрах. Обратите внимание, что с Qt 6 физический размер экрана больше не используется для определения логического разрешения DPI.
QT_QPA_EGLFS_ROTATION Указывает поворот, применяемый к содержимому с программной отрисовкой в приложениях на основе QWidget. Поддерживаемые значения: 180, 90 и -90. Эта переменная не применяется к окнам на основе OpenGL, включая Qt Quick. Приложения Qt Quick могут применять преобразования в своей сцене QML вместо этого. Стандартный eglfs курсор мыши всегда учитывает это значение, с соответствующим по положению и повернутым изображением указателя, независимо от типа приложения. Однако специальные реализации курсора, такие как аппаратный курсор бэкэнда KMS/DRM, могут не поддерживать поворот.
QT_QPA_EGLFS_FORCEVSYNC При установке этого значения eglfs запрашивает FBIO_WAITFORVSYNC на устройстве буфера кадров после каждого вызова eglSwapBuffers(). Эта переменная актуальна только для бэкэндов, которые полагаются на устаревшую подсистему Linux fbdev. Обычно, при стандартном интервале переключения 1, Qt предполагает, что вызов eglSwapBuffers() обрабатывает vsync; если это не так (например, из-за ошибок драйвера), попробуйте установить QT_QPA_EGLFS_FORCEVSYNC на ненулевое значение.
QT_QPA_EGLFS_FORCE888 При установке этого значения размеры каналов цвета красный, зелёный и синий игнорируются при создании нового контекста, окна или оффскрин-поверхности eglfs. Вместо этого плагин запрашивает конфигурацию с 8 битами на канал. Это может быть полезно на устройствах, где конфигурации с менее чем 32 или 24 битами на пиксель (например, 5-6-5 или 4-4-4) выбираются по умолчанию, несмотря на то, что они не являются идеальными, например, из-за эффектов полос. Вместо изменения кода приложения эта переменная предоставляет обходной путь для принудительного использования конфигураций с 24 или 32 битами на пиксель.

Кроме того, доступны следующие менее часто используемые переменные:

Переменная окружения Описание
QT_QPA_EGLFS_FB Заменяет устройство буфера кадров. По умолчанию /dev/fb0. На большинстве встраиваемых платформ эта переменная не очень актуальна, так как буфер кадров используется только для запроса настроек, таких как размеры дисплея. Однако на некоторых устройствах эта переменная позволяет указать, какой дисплей использовать в конфигурациях с несколькими дисплеями, аналогично параметру fb в LinuxFB.
QT_QPA_EGLFS_WIDTH и QT_QPA_EGLFS_HEIGHT Содержат ширину и высоту экрана в пикселях. Хотя eglfs пытается определить размеры из устройства буфера кадров /dev/fb0, это не всегда срабатывает. Может потребоваться вручную указать размеры.
QT_QPA_EGLFS_DEPTH Заменяет битовую глубину цвета для экрана. На платформах, где устройство буфера кадров /dev/fb0 недоступно или запрос не выполняется, используется значение по умолчанию 32. Используйте эту переменную для переопределения любых таких значений по умолчанию.

Примечание: Эта переменная влияет только на значение битовой глубины цвета, сообщённое QScreen. Она не связана с конфигурациями EGL и битовой глубиной, используемой для рендеринга OpenGL.

QT_QPA_EGLFS_SWAPINTERVAL По умолчанию запрашивается интервал переключения 1. Эта переменная позволяет синхронизировать работу с вертикальной разверткой дисплея. Используйте эту переменную для переопределения значения интервала переключения. Например, передача 0 отключает блокирование при переключении, что приводит к работе с максимальной скоростью без какой-либо синхронизации.
QT_QPA_EGLFS_DEBUG При установке этого значения печатается дополнительная отладочная информация в выходные данные отладки. Например, входной параметр QSurfaceFormat и свойства выбранной конфигурации EGL печатаются при создании нового контекста. При совместном использовании с переменной QSG_INFO Qt Quick вы можете получить полезную информацию для устранения проблем, связанных с конфигурацией EGL.

В дополнение к QT_QPA_EGLFS_DEBUG, eglfs также поддерживает современную систему категорированного логгирования Qt. Доступны следующие категории логгирования:

  • qt.qpa.egldeviceintegration — Включает логгирование динамически загруженных бэкэндов. Используйте эту категорию, чтобы проверить, какой бэкэнд используется.
  • qt.qpa.input — Включает вывод отладки как из обработчиков evdev и libinput. Используйте эту категорию, чтобы проверить, было ли распознано и открыто данное устройство ввода.
  • qt.qpa.eglfs.kms — Включает подробное логгирование в бэкэнде KMS/DRM.

После запуска configure убедитесь, что вы проверили его выходные данные. Это самый простой и быстрый способ определить, включены ли необходимые бэкэнд EGLFS, libudev или libinput. Короче говоря, если в выходных данных configure присутствует нежелательное «нет», выполните:

./configure -v

чтобы включить подробный вывод, так что вы сможете увидеть вызовы компилятора и компоновщика для каждого тестового случая конфигурации.

Примечание: Если вы столкнётесь с ошибками о недостающих заголовках, библиотеках или кажущихся непонятными ошибках компоновщика, то это часто признак неполного или повреждённого sysroot, а не проблемы с Qt.

Например, при нацеливании на Raspberry Pi с собственными драйверами графики Broadcom, вывод должен содержать что-то вроде следующего:

QPA backends:
EGLFS ................................ yes
EGLFS details:
  EGLFS i.Mx6 ........................ no
  EGLFS i.Mx6 Wayland ................ no
  EGLFS EGLDevice .................... no
  EGLFS GBM .......................... no
  EGLFS Mali ......................... no
  EGLFS Rasberry Pi .................. yes
  EGL on X11 ......................... no

Если это не так, не рекомендуется продолжать сборку, поскольку ускоренная графика не будет функциональной без бэкэнда, специфичного для Raspberry Pi, даже если остальная часть Qt будет успешно скомпилирована.

LinuxFB

Этот плагин записывает данные напрямую в буфер кадров через подсистему fbdev Linux. Поддерживается только содержимое с программной отрисовкой. Обратите внимание, что в некоторых конфигурациях производительность отображения может быть ограниченной.

Однако, поскольку fbdev устаревает в ядре Linux, поддержка буферов без интеллекта DRM также доступна начиная с Qt 5.9. Чтобы использовать ее, установите переменную окружения QT_QPA_FB_DRM в ненулевое значение. При установке, при условии, что буферы без интеллекта поддерживаются вашей системой, к устаревшим устройствам фреймбуфера, таким как /dev/fb0, доступ не будет. Вместо этого отрисовка настраивается через API DRM, аналогично бэкенду eglfs_kms в EGLFS. Вывод является двухбуферным и с переворачиванием страницы, обеспечивая правильный vsync для содержимого, отрисовываемого программным обеспечением.

Примечание: При использовании буферов без интеллекта ни один из описанных ниже параметров не применимы, поскольку такие свойства, как физические и логические размеры экрана, все запрашиваются автоматически.

Плагин linuxfb позволяет вам указать дополнительные параметры через переменную окружения QT_QPA_PLATFORM или параметр командной строки -platform. Например, QT_QPA_PLATFORM=linuxfb:fb=/dev/fb1 указывает, что устройство фреймбуфера /dev/fb1 должно использоваться вместо стандартного fb0. Для указания нескольких параметров разделяйте их двоеточием (:).

Настройки Описание
fb=/dev/fbN Указывает устройства фреймбуфера. При настройке с несколькими дисплеями эта настройка позволяет запускать приложение на разных дисплеях. В настоящее время нет способа использовать несколько фреймбуферов из одного приложения Qt.
size=<width>x<height> Указывает размер экрана в пикселях. Плагин пытается запросить размеры дисплея, как физические, так и логические, из устройства фреймбуфера. Однако этот запрос может не всегда давать корректные результаты; может потребоваться указать значения явно.
mmsize=<width>x<height> Указывает физическую ширину и высоту в миллиметрах.
offset=<width>x<height> Указывает смещение левого верхнего угла экрана в пикселях. Значение по умолчанию — (0, 0).
nographicsmodeswitch Указывает, что не нужно переключать виртуальную консоль в графический режим (KD_GRAPHICS). Как правило, включение графического режима отключает мигание курсора и затемнение экрана. Однако при установке этого параметра эти две функции также пропускаются.
tty=/dev/ttyN Переопределяет виртуальную консоль. Используется только тогда, когда nographicsmodeswitch не задано.

Начиная с Qt 5.9, поведение EGLFS и LinuxFB было синхронизировано в отношении политики изменения размера окна: первое окно верхнего уровня принудительно занимает весь экран с обоими платформами-плагинами. Если этого не требуется, установите переменную окружения QT_QPA_FB_FORCE_FULLSCREEN в 0, чтобы восстановить поведение предыдущих версий Qt.

Вывод на дисплей

Когда подключено несколько дисплеев, уровень поддержки одновременного использования одного или нескольких из этих дисплеев из одного приложения Qt варьируется между платформами-плагинами и часто зависит от устройства и его графической подсистемы.

EGLFS с бэкендом eglfs_kms

При использовании бэкенда KMS/DRM EGLFS сообщает обо всех доступных экранах в QGuiApplication::screens(). Приложения могут использовать разные экраны с разными окнами через QWindow::setScreen().

Примечание: Ограничение одного единственного полноэкранного окна на экран по-прежнему сохраняется. Изменение экрана после отображения QWindow также не поддерживается. Поэтому крайне важно, чтобы встроенные приложения выполнили все необходимые вызовы QWindow::setScreen() перед вызовом QWindow::show().

При разработке на определённом встроенном устройстве зачастую необходимо проверить поведение устройства и драйверов, а также то, что подключенные дисплеи работают должным образом. Один из простых способов — использовать пример hellowindow. Запуск с аргументами -platform eglfs --multiscreen --timeout отображает вращающийся логотип Qt на каждом подключенном экране в течение нескольких секунд.

Бэкенд KMS/DRM также поддерживает пользовательские конфигурации через файл JSON. Для этого установите переменную окружения QT_QPA_EGLFS_KMS_CONFIG в имя файла. Вы также можете встроить этот файл в приложение через систему ресурсов Qt.

Большинство этих параметров конфигурации относятся ко всем бэкендам, основанным на KMS/DRM, независимо от технологии управления буферами (GBM или EGLStreams).

Вот пример конфигурации:

{
  "device": "/dev/dri/card1",
  "hwcursor": false,
  "pbuffers": true,
  "outputs": [
    {
      "name": "VGA1",
      "mode": "off"
    },
    {
      "name": "HDMI1",
      "mode": "1024x768"
    }
  ]
}

Здесь мы настраиваем указанное устройство так, чтобы:

  • Оно не использовало аппаратный курсор (возвращается к отрисовке курсора мыши через OpenGL; по умолчанию аппаратные курсоры включены, так как они более эффективны).
  • Оно поддерживало QOffscreenSurface с стандартными поверхностями EGL pbuffer (по умолчанию это выключено, и вместо этого используется поверхность gbm).
  • Вывод на VGA-разъём отключён, а HDMI активен с разрешением 1024x768.

Кроме того, такая конфигурация также отключает поиск устройства через libudev; вместо этого используется указанное устройство.

Когда mode не определено, выбирается предпочтительный режим системы. Допустимые значения для mode — off, current, preferred, skip, widthxheight, widthxheight@vrefresh или строка описания режима.

Указание current выбирает режим с разрешением, соответствующим текущему. Поскольку переключение режимов выполняется только тогда, когда желаемый режим фактически отличается от активного (если не принуждено через переменную окружения QT_QPA_EGLFS_ALWAYS_SET_MODE), это значение полезно для сохранения текущего режима и любого содержимого на плоскостях, не затронутых Qt.

skip игнорирует соединитель для вывода, как будто он отключен. off аналогичен, но изменяет режим и выключает дисплей.

По умолчанию все экраны, сообщённые слоем DRM, рассматриваются как один большой виртуальный рабочий стол. Реализация курсора мыши учитывает это и перемещается по экранам как ожидается. Хотя не рекомендуется, вы можете отключить виртуальный рабочий стол, установив separateScreens в false в конфигурации.

По умолчанию виртуальный рабочий стол формируется слева направо, основываясь на порядке разъёмов, сообщённых системой. Чтобы изменить это, установите virtualIndex в значение, начиная с 0.

Например, следующая конфигурация использует предпочтительное разрешение, но гарантирует, что левая сторона виртуального рабочего стола — экран, подключённый к порту HDMI, а правая — экран, подключённый к DisplayPort:

{
  "device": "drm-nvdc",
  "outputs": [
    {
      "name": "HDMI1",
      "virtualIndex": 0
    },
    {
      "name": "DP1",
      "virtualIndex": 1
    }
  ]
}

Порядок элементов в массиве не важен. Выводы с не указанными виртуальными индексами помещаются после других, сохраняя исходный порядок в списке разъёмов DRM.

Чтобы создать вертикальное пространство рабочего стола (то есть, чтобы слои располагались сверху вниз вместо слева направо), добавьте свойство virtualDesktopLayout после device со значением vertical.

Предупреждение: Рекомендуется, чтобы все экраны в виртуальном рабочем столе имели одинаковое разрешение, иначе элементы, такие как курсор мыши, могут вести себя неожиданным образом при входе в области, существующие только на одном конкретном экране.

Если virtualIndex недостаточно, свойство virtualPos можно использовать для явного указания левого верхнего угла экрана. Взяв предыдущий пример и предположив разрешение 1080p для HDMI1, следующий фрагмент кода помещает второй экран HDMI ниже первого:

{
   ...
  "outputs": [
    ...
    {
      "name": "HDMI2",
      "virtualPos": "0, 1080"
    }
  ]
}

Примечание: Избегайте таких конфигураций, когда требуется поддержка мыши. Поведение курсора мыши может быть непредсказуемым при нелинейных макетах. Однако поддержка сенсорного ввода не должна вызывать проблем.

В некоторых случаях автоматический запрос физического размера экрана через DRM может завершиться ошибкой. Обычно переменные окружения QT_QPA_EGLFS_PHYSICAL_WIDTH и QT_QPA_EGLFS_PHYSICAL_HEIGHT использовались бы для предоставления недостающих значений, однако это больше не подходит при наличии нескольких экранов. Вместо этого используйте свойства physicalWidth и physicalHeight в списке outputs для указания размеров в миллиметрах.

Примечание: Разные физические размеры, а следовательно, и разное логическое разрешение экрана не рекомендуется, так как это может привести к неожиданным проблемам из-за того, что некоторые компоненты графической подсистемы не знают о нескольких экранах и полагаются только на значения первого экрана.

Каждый активный вывод из массива outputs соответствует одному экземпляру QScreen, сообщённому из QGuiApplication::screens(). По умолчанию основной экран, возвращаемый QGuiApplication::primaryScreen(), — это экран, зарегистрированный первым. Если вы не используете virtualIndex, это означает, что решение основано на порядке разъёмов DRM. Чтобы переопределить это, установите свойство primary в true для нужной записи в списке outputs.

Например, чтобы гарантировать, что экран, соответствующий VGA-выводу, является основным, даже если система сообщает о HDMI-выводе первым, сделайте следующее:

{
  "device": "/dev/dri/card0",
  "outputs": [
      { "name": "HDMI1" },
      { "name": "VGA1", "mode": "1280x720", "primary": true },
      { "name": "LVDS1", "mode": "off" }
  ]
}

Для отладки может быть полезно включить отладочные логи из бэкенда KMS/DRM. Для этого включите правило категорированного логирования qt.qpa.eglfs.kms.

Примечание: Во встроенной среде виртуальные рабочие столы более ограничены по сравнению с полной системой окон. Перекрывание окон на нескольких экранах, не полноэкранные окна и перемещение окон между экранами следует избегать, и они могут работать не так, как ожидается.

Наиболее распространённый и лучше всего поддерживаемый случай для многоэкранной настройки — открытие отдельного QQuickWindow или QQuickView для каждого экрана. С циклом отрисовки threaded сцены Qt Quick каждое из этих окон получит свой отдельный поток отрисовки. Это хорошо, потому что потоки можно независимо ограничивать по vsync и они не будут мешать друг другу. С циклом basic это может стать проблематичным, ухудшая анимацию.

Например, обнаружение всех подключенных экранов и создание QQuickView для каждого из них можно выполнить так:

int main(int argc, char **argv)
{
    QGuiApplication app(argc, argv);

    QVector<QQuickView *> views;
    for (QScreen *screen : app.screens()) {
        QQuickView *view = new QQuickView;
        view->setScreen(screen);
        view->setResizeMode(QQuickView::SizeRootObjectToView);
        view->setSource(QUrl("qrc:/main.qml"));
        QObject::connect(view->engine(), &QQmlEngine::quit, qGuiApp, &QCoreApplication::quit);
        views.append(view);
        view->showFullScreen();
    }

    int result = app.exec();

    qDeleteAll(views);
    return result;
}

Дополнительные возможности eglfs_kms

Начиная с Qt 5.11, поддерживается клонирование экрана (отображение). Это включается через свойство clones:

{
  "device": "/dev/dri/card0",
  "outputs": [
      { "name": "HDMI1", "mode": "1920x1080" },
      { "name": "DP1", "mode": "1920x1080", "clones": "HDMI1" }
 ]
}

В этом случае содержимое на дисплее, подключенном через DisplayPort, будет таким же, как и на HDMI. Это обеспечивается считыванием одного и того же буфера на обоих.

Однако эта функция может работать только в том случае, если разрешения одинаковы, нет несовместимостей в форматах буферов, и приложение не имеет вывода на QScreen, связанный с клонированным пунктом назначения. На практике это означает, что ни один QWindow, связанный с QScreen в вопросе – DP1 в примере – не должен выполнять операцию QOpenGLContext::swapBuffers(). За обеспечение этого отвечает конфигурация и приложение.

Начиная с Qt 5.11, поддерживается режим headless через узлы отрисовки DRM. Это позволяет выполнять вычисления на GPU (OpenGL compute shaders, OpenCL) или отрисовку OpenGL offscreen без необходимости привилегий DRM-мастера. В этом режиме приложения могут функционировать даже при наличии другого процесса, выводящего изображение на экран.

Простое переключение device с /dev/dri/card0 на /dev/dri/renderD128 само по себе бесполезно, так как в режиме headless нельзя выполнить ряд операций. Поэтому это должно быть сочетаться со свойством headless, например:

{
    "device": "/dev/dri/renderD128",
    "headless": "1024x768"
}

Помните, что окна по-прежнему масштабируются в соответствии с размером экрана – теперь виртуального – поэтому необходимо указать размер в свойстве headless. Также отсутствует регулирование частоты кадров, основанное на vsync.

После включения приложения имеют два типичных варианта для выполнения offscreen-рендеринга в режиме headless:

Использование обычного окна, такого как подкласс QOpenGLWindow, ориентированного на буфер кадра по умолчанию окна, что на практике означает gbm_surface:

MyOpenGLWindow w;
w.show(); // will not actually show up on screen
w.grabFramebuffer().save("output.png");

Или типичный подход offscreen с дополнительным FBO:

QOffscreenSurface s;
s.setFormat(ctx.format());
s.create();
ctx.makeCurrent(&s);
QOpenGLFramebufferObject fbo(1024, 768);
fbo.bind();
ctx.functions()->glClearColor(1, 0, 0, 1);
ctx.functions()->glClear(GL_COLOR_BUFFER_BIT);
fbo.toImage().save("output.png");
ctx.doneCurrent();

KMS/DRM могут использоваться с двумя различными API DRM: legacy и atomic. Основное преимущество API DRM atomic заключается в возможности нескольких обновлений плоскостей DRM в рамках одного цикла рендеринга, тогда как API legacy потребует одного обновления плоскости на каждый vsync.

API atomic полезен, когда ваше приложение нуждается в совмещении содержимого с наложениями, сохраняя все обновления в рамках одного vsync. Тем не менее, не все устройства поддерживают этот API, и он может быть недоступен на некоторых старых устройствах. Бэкенд KMS по умолчанию использует API legacy, но вы можете включить API DRM atomic, установив переменную окружения QT_QPA_EGLFS_KMS_ATOMIC в значение 1.

Использование буфера кадра меньшего размера, чем разрешение экрана, также может быть полезным. Это возможно с помощью DRM atomic, используя параметр size в файле JSON. Пример ниже использует буфер кадра 1280x720 на видеорежиме 3840x2160:

{
  "device": "/dev/dri/card0",
  "outputs": [
    { "name": "HDMI1", "mode": "3840x2160", "size": "1280x720", "format": "argb8888" }
  ]
}

eglfs с бэкэндом eglfs_kms_egldevice

Этот бэкенд, обычно используемый на устройствах Tegra, похож на бэкенд KMS/DRM, упомянутый выше, за исключением того, что он полагается на расширения EGLDevice и EGLStream вместо GBM.

Для получения технических подробностей об этом подходе ознакомьтесь с этой презентацией.

Начиная с Qt 5.7, этот бэкенд разделяет многие свои внутренние реализации с бэкэндом на основе GBM. Это означает, что поддерживаются несколько экранов и расширенная конфигурация с помощью QT_QPA_EGLFS_KMS_CONFIG. Однако некоторые настройки, такие как hwcursor и pbuffers, неприменимы.

По умолчанию бэкенд автоматически выберет правильный слой EGL для плоскости по умолчанию каждого вывода. При необходимости это можно переопределить, установив переменную окружения QT_QPA_EGLFS_LAYER_INDEX в индекс желаемого слоя. Этот подход в настоящее время не поддерживает несколько выводов, поэтому его использование следует ограничить системами с одним экраном. Чтобы увидеть доступные слои и отладить возможные проблемы при запуске, включите категорию логирования qt.qpa.eglfs.kms.

В некоторых случаях может потребоваться установка режима видео при запуске приложения, даже если экран сообщает, что желаемое разрешение уже установлено. Обычно это оптимизируется, но если экран остается выключенным, попробуйте установить переменную окружения QT_QPA_EGLFS_ALWAYS_SET_MODE в ненулевое значение и перезапустить приложение.

Для настройки поведения объекта EGLStream, используемого бэкэндом, используйте переменную окружения QT_QPA_EGLFS_STREAM_FIFO_LENGTH. Предполагается, что KHR_stream_fifo поддерживается целевой системой. По умолчанию поток работает в режиме почтового ящика. Чтобы переключиться на режим FIFO, установите значение 1 или больше. Значение определяет максимальное количество кадров, которое может хранить поток.

В некоторых системах может потребоваться нацеливание на определенную плоскость наложения через предварительно определенный соединитель. Просто принудительное задание индекса слоя через QT_QPA_EGLFS_LAYER_INDEX не выполняет конфигурацию плоскости и поэтому не подходит само по себе. Вместо этого в таких особых случаях используйте переменные окружения QT_QPA_EGLFS_KMS_CONNECTOR_INDEX и QT_QPA_EGLFS_KMS_PLANE_INDEX. При их установке будут использоваться только указанный соединитель и плоскость, все остальные выводы будут игнорироваться. Бэкенд позаботится о выборе слоя EGL, соответствующего желаемой плоскости, и о ее конфигурации.

Ввод сенсорного экрана в системах с несколькими экранами на KMS/DRM

Сенсорные экраны требуют дополнительных соображений в системах с несколькими дисплеями, так как события сенсорного ввода должны быть маршрутизированы на правильный виртуальный экран, и это требует правильного сопоставления сенсорных экранов и выводов дисплея.

Сопоставление выполняется с помощью файла конфигурации JSON, указанного в QT_QPA_EGLFS_KMS_CONFIG и описанного в предыдущих разделах. Когда свойство touchDevice присутствует в элементе массива outputs, значение интерпретируется как узел устройства, и сенсорное устройство связывается с выводом дисплея.

Например, предположим, что наш сенсорный экран имеет узел устройства /dev/input/event5 и интегрирован в монитор, подключенный по HDMI, как вторичный экран. Следующая конфигурация гарантирует правильное преобразование событий сенсорного ввода (и синтезированных событий мыши):

 {
    "device": "drm-nvdc",
    "outputs": [
      {
        "name": "HDMI1",
        "touchDevice": "/dev/input/event5",
        "virtualIndex": 1
      },
      {
        "name": "DP1",
        "virtualIndex": 0
      }
    ]
}

Примечание: В случае сомнений включите логирование как из графических, так и из вводных подсистем, установив переменную окружения QT_LOGGING_RULES=qt.qpa.*=true перед запуском приложения. Это поможет определить правильные узлы устройств ввода и может выявить проблемы с конфигурацией вывода, которые в противном случае сложно отладить.

Примечание: Начиная с Qt 5.8, вышесказанное поддерживается только для бэкэнда ввода evdevtouch. Другие варианты, такие как варианты на основе libinput, по-прежнему будут маршрутизировать события на основной экран. Чтобы принудительно использовать evdevtouch в системах, где доступно несколько бэкэндов ввода, установите переменную окружения QT_QPA_EGLFS_NO_LIBINPUT в значение 1.

eglfs с другими бэкендами

Другие бэкэнды, обычно основанные на непосредственном целевом наведении на буфер кадра или API композиции через реализацию EGL поставщика, обычно предоставляют ограниченную или никакую поддержку нескольких дисплеев. На платах на базе i.MX6 с графическими процессорами Vivante переменная окружения QT_QPA_EGLFS_FB может использоваться для указания буфера кадра, аналогично linuxfb. На Raspberry Pi переменная окружения QT_QPA_EGLFS_DISPMANX_ID может использоваться для указания экрана, на который необходимо вывести изображение. Значение соответствует одному из констант DISPMANX_ID_, см. документацию Dispmanx. Обратите внимание, что эти подходы, в отличие от KMS/DRM, обычно не позволят выводить изображение на несколько экранов из одного приложения. Кроме того, могут быть доступны специфичные для драйвера переменные окружения или параметры ядра для управления используемым буфером кадра. Обратитесь к документации встраиваемой платы.

Видеопамять

Системы с фиксированным объемом выделенной видеопамяти могут потребовать дополнительного внимания перед запуском приложения Qt, основанного на Qt Quick или классах, таких как QOpenGLWidget. Значение по умолчанию может быть недостаточным для таких приложений, особенно при отображении на экране с высоким разрешением (например, Full HD). В этом случае они могут начать работать непредсказуемым образом. Рекомендуется обеспечить наличие как минимум 128 МБ видеопамяти GPU. Для систем, не имеющих фиксированного объема памяти, зарезервированного для GPU, это не проблема.

linuxfb

Используйте параметр плагина fb для указания устройства буфера кадра для использования.

Обработчики сигналов Unix

Плагины платформ, ориентированные на консоль, такие как eglfs и linuxfb, по умолчанию устанавливают обработчики сигналов для захвата прерываний (SIGINT), приостановки и возобновления (SIGTSTP, SIGCONT) и завершения (SIGTERM). Таким образом, клавиатура, курсор терминала и, возможно, другие графические состояния могут быть восстановлены при завершении или приостановке приложения из-за kill, или Ctrl+C или Ctrl+Z. (хотя завершение или приостановление через клавиатуру возможно только при установке QT_QPA_ENABLE_TERMINAL_KEYBOARD, как описано выше в разделе «Ввод»). Однако в некоторых случаях захват SIGINT может быть нежелательным, так как он может конфликтовать с удаленной отладкой, например. Поэтому предоставляется переменная окружения QT_QPA_NO_SIGNAL_HANDLER для отказа от всех встроенных обработчиков сигналов.

Шрифты

Qt обычно использует fontconfig для доступа к системным шрифтам. Если fontconfig недоступен, Qt переключится на использование QBasicFontDatabase. В этом случае приложения Qt будут искать шрифты в каталоге Qt lib/fonts. Qt автоматически обнаружит предварительно рендеренные шрифты и шрифты TrueType. Этот каталог можно переопределить, установив переменную окружения QT_QPA_FONTDIR.

Дополнительную информацию о поддерживаемых форматах см. в разделе Шрифты Qt для встраиваемой Linux.

Примечание: Qt больше не поставляется со шрифтами в каталоге lib/fonts. Это означает, что платформа (образ системы) должна предоставить необходимые шрифты.

Плагины платформ для систем оконного интерфейса на встраиваемых устройствах Linux

XCB

Это плагин X11, используемый на обычных настольных системах Linux. В некоторых встраиваемых средах, предоставляющих X и необходимые файлы разработки для xcb, этот плагин работает так же, как и на обычном настольном компьютере.

Примечание: На некоторых устройствах EGL и OpenGL недоступны в X, поскольку реализация EGL несовместима с Xlib. В этом случае плагин XCB собирается без поддержки EGL, что означает, что приложения Qt Quick 2 или другие приложения, основанные на OpenGL, не работают с этим плагином платформы. Однако его можно использовать для запуска приложений с программной отрисовкой (например, на основе QWidget).

Как правило, использование XCB на встраиваемых устройствах не рекомендуется. Плагины, такие как eglfs, вероятно, обеспечат лучшую производительность и аппаратное ускорение.

Wayland

Wayland — это лёгкая система окон; точнее, это протокол для взаимодействия клиентов с сервером отображения.

Qt Wayland предоставляет плагин платформы wayland , который позволяет приложениям Qt подключаться к композитору Wayland.

Для получения более подробной информации см. Wayland и Qt.

Связанные темы

  • Qt для создания устройств
  • Настройка устройства с встраиваемой Linux
  • Ввод на устройстве с встраиваемой Linux

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/embedded-linux.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API