Spec-Zone.ru › Qt 6.0

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

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

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

Примечание: начиная с Qt 5.0, Qt больше не имеет собственной реализации системы окон (QWS). Для однопроцессных случаев использования Абстракция платформы Qt является более предпочтительным решением; многопроцессные случаи использования поддерживаются через 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, физический размер экрана больше не используется для определения логической 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 создании нового контекста, окна или offscreen-поверхности. Вместо этого плагин запрашивает конфигурацию с 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) через узлы рендеринга DRM. Это позволяет выполнять вычисления на GPU (OpenGL compute-шейдеры, 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 потребовал бы одно обновление плоскости на один 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 с GPU 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.0/embedded-linux.html

Spec-Zone.ru

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