Spec-Zone.ru › Qt 6.1

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. Это вариант только в том случае, если плагины статической или скомпилированной вставки не были указаны в описании устройства. На практике традиционные скомпилированные вставки редко используются, почти все бэкэнды сейчас перенесены в плагины. В описании устройства всё ещё содержится соответствующая EGLFS_DEVICE_INTEGRATION запись: имя предпочтительного бэкэнда для этого конкретного устройства. Это необязательно, но очень полезно, чтобы избежать необходимости устанавливать эту переменную среды, если в целевой системе присутствует более одного плагина. В среде рабочего стола приоритет отдаётся бэкендам KMS или X11 в зависимости от наличия переменной среды DISPLAY.

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

QT_QPA_EGLFS_PHYSICAL_WIDTH и QT_QPA_EGLFS_PHYSICAL_HEIGHT Указывают ширину и высоту физического экрана в миллиметрах. Обратите внимание, что с Qt 6 физический размер экрана больше не используется для определения логической плотности пикселей.
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 dumb также доступна начиная с Qt 5.9. Чтобы использовать ее, установите переменную среды QT_QPA_FB_DRM в ненулевое значение. При установке, при условии, что ваша система поддерживает буферы dumb, к устаревшим устройствам фреймбуфера, таким как /dev/fb0, доступ не будет предоставляться. Вместо этого, отрисовка настраивается через API DRM, аналогично бэкенду eglfs_kms в EGLFS. Вывод является двойным буферизированным и с перелистыванием страниц, обеспечивая правильную синхронизацию по вертикали (vsync) для содержимого, отрисованного программным способом.

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

Плагин 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, чтобы указать размеры в миллиметрах.

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

Каждый активный вывод из массива 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 mode) с помощью узлов рендеринга DRM. Это позволяет выполнять вычисления на GPU (OpenGL вычислительные шейдеры, OpenCL) или рендеринг OpenGL вне экрана без необходимости привилегий DRM-мастера. В этом режиме приложения могут функционировать, даже если другой процесс уже выводит изображение на экран.

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

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

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

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

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

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

Или типичный подход к рендерингу вне экрана с дополнительным 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 потребовал бы одно обновление плоскости за один кадр.

API atomic полезен, когда приложение должно смешивать контент в наложениях, сохраняя все обновления в одном кадре. Однако не все устройства поддерживают этот 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 в системах, где доступно несколько бэкендов ввода, установите переменную окружения 1 в QT_QPA_EGLFS_NO_LIBINPUT.

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 для Embedded 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.1/embedded-linux.html

Spec-Zone.ru

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