Spec-Zone.ru › Qt 5.15

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

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

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

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

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

EGLFS

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

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

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

EGLFS рекомендуется для современных устройств встраиваемого Linux, оснащённых графическим процессором.

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

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

При необходимости 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 Указывает ширину и высоту физического экрана в миллиметрах. На платформах, где значение нельзя получить из устройства буфера кадров /dev/fb0 или другими способами, используется значение DPI по умолчанию 100. Используйте эту переменную для переопределения таких значений по умолчанию. Установка этой переменной важна, потому что приложения на основе QWidget или Qt Quick Controls полагаются на эти значения. Запуск этих приложений со значениями по умолчанию может привести к отображению элементов пользовательского интерфейса с размерами, не подходящими для используемого дисплея.
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 При установке, размеры каналов цветов красный, зелёный и синий игнорируются при создании нового контекста, окна или оффскрин-поверхности. Вместо этого, плагин запрашивает конфигурацию с 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 выводятся при создании нового контекста. При использовании вместе с переменной Qt Quick QSG_INFO вы можете получить полезную информацию для решения проблем, связанных с конфигурацией 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
  • Эмулятор
  • Виртуальная клавиатура Qt
  • Qt Quick WebGL

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

Spec-Zone.ru

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