QT官网关于交叉编译说明

QT官方说明

http://doc.qt.io/qt-5/embedded-linux.html

译文

http://blog.csdn.net/chongzi865458/article/details/54406865

 

自Qt5.0发布以来,Qt不再包含自己的窗口系统(QWS)实现。对于单进程用例,Qt平台抽象是一个优秀的解决方案。Wayland可以支持多种图形流程。有多种平台插件可用于嵌入式Linux系统:EGLFS,LinuxFB,DirectFB,Wayland。这些可用性取决于Qt的配置。在许多电路板上,eglfs被选作默认电路板。如果默认值不合适,则可以使用QT_QPA_PLATFORM环境变量参数来请求另一个插件。或者,对于快速测试,可以使用相同的语法来使用-platform命令行。

配置特定设备,构建给定设备的Qt需要一个工具链和一个sysroot。

此外,有些设备需要针对EGL和OpenGLES2.0支持的特定于供应商的适配代码这与非加速平台无关,例如那些使用LinuxFB插件的插件,仅适用于基于软件的渲染,目录/qtbase/mkspecs/devices

包含许多设备的配置和图形适应代码。例如,linux-rasp-pi2-g ++ mkspec包含构建设置,例如Raspberry Pi 2设备的最佳编译器和链接器标志。 mkspec还包含关于eglfs钩子(供应商特定的适配代码)的实现或者对适当的eglfs设备集成插件的引用的信息。该设备通过配置工具的设备参数进行选择。这个参数后面的名字必须至少部分地与设备下的其中一个子目录相匹配。

以下是Raspberry Pi 2的配置示例。对于大多数嵌入式Linux主板,configure命令看起来类似:

/configure-release -opengl es2 -device linux-rasp-pi2-g++ -device-optionCROSS_COMPILE=$TOOLCHAIN/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf--sysroot $ROOTFS -prefix /usr/local/qt5

最重要的参数是-device和-sysroot。通过指定-sysroot,configure的功能检测测试使用的包含文件和库以及Qt本身都是从指定位置取代,而不是主机PC的标准位置。这意味着在主机上安装开发包没有意义。例如,要获得libinput支持,在主机环境中安装libinput开发头文件和库是不够的或不必要的。相反,目标体系结构的头文件和库(例如ARM)必须存在于sysroot中。

执行交叉编译时也支持pkg-config。 configure会自动设置PKG_CONFIG_LIBDIR以使pkg-config报告编译器和链接器设置基于sysroot而不是主机。这通常运行良好,无需进一步调整。但是,在运行configure之前,必须为主机取消设置环境变量(如PKG_CONFIG_PATH)。否则,Qt构建可能会尝试使用主机系统中不适当的头文件和库。

指定-sysroot会导致在调用编译器时自动设置--sysroot参数。在某些情况下,这是不可取的,可以通过传递-no-gcc-sysroot来禁用。

-prefix,-extprefix和-hostprefix控制Qt构建的预期目标目录。在上面的例子中,Qt的ARM版本预计将放置在目标设备上的/ usr / local / qt5中。请注意,运行make install不会将任何内容部署到设备。相反,安装步骤的目标是由extprefix指定的目录,该目录默认为sysroot +前缀,因此是可选的。但是,在许多情况下,“污染”sysroot并不可取,因此指定-extprefix就变得很重要。最后,-hostprefix允许从目标的二进制文件中分离主机工具,如qmake,rcc,uic。当给定时,这些工具将安装在指定的目录下而不是extprefix。

有关更多信息,请参阅Qt配置选项。

嵌入式Linux设备的平台插件

EGLFS

EGL是OpenGL和本地窗口系统之间的接口。Qt可以使用EGL进行上下文和表面管理,但是API不包含特定平台:本地窗口(不一定是屏幕上的实际窗口)的创建仍然必须通过特定于平台的方式来完成。因此需要板或GPU特定的适配代码。这样的修改既可以作为eglfs hooks来提供,它可以是编译到平台插件中的单个源文件,也可以是动态加载的EGL设备集成插件。

EGLFS是一个平台插件,用于在没有实际窗口系统(如X11或Wayland)的情况下,在EGL和OpenGL ES2.0之上运行Qt5应用程序。除了Qt Quick 2和本机OpenGL应用程序之外,它还支持软件渲染窗口(例如QWidget)。在后一种情况下,小部件的内容使用CPU渲染成图像,然后上传到纹理并由插件合成。

这是适用于包含GPU的现代嵌入式Linux设备的推荐插件。

EGLFS强制第一个顶层窗口(无论是QWidget还是QQuickView)变为全屏。这个窗口也被选为所有其他顶级窗口小部件(例如对话框,弹出菜单或组合框下拉框)的根窗口小部件窗口。这是必要的,因为对于EGLFS,总是只有一个本地窗口和EGL窗口表面,并且这些属于首先创建的窗口小部件或窗口。当主窗口存在时,应用程序的整个生命周期中存在一个主窗口,并且所有其他窗口小部件都是非顶层窗口或之后创建的主窗口一旦显示主窗口时,此方法运行良好。

基于OpenGL的窗口还有其他限制。从Qt 5.3开始,eglfs支持单个全屏GL窗口(例如,基于OpenGL的QWindow,QQuickView或QGLWidget)。不支持打开额外的OpenGL窗口或将这些窗口与基于QWidget的内容混合在一起,并通过错误消息终止应用程序。

如有必要,可以使用以下环境变量来配置eglfs:

QT_QPA_EGLFS_INTEGRATION - 除了已编译的钩子之外,还可以以动态加载的插件的形式提供设备或供应商特定的适配。这个环境变量强制执行一个特定的插件。例如,将其设置为eglfs_kms使用KMS / DRM后端。这只是在设备makepecs中没有指定静态或编译的钩子时的一个选项。实际上,传统的编译钩子很少被使用,现在几乎所有的后端都被迁移到了插件中。设备makepecs仍包含相关的EGLFS_DEVICE_INTEGRATION条目:该特定设备首选后端的名称。这是可选的,但对于在目标系统中存在多个插件的情况下避免设置此环境变量非常有用。在桌面环境中,根据DISPLAY环境变量的存在情况,将KMS或X11后端分配优先级。请注意,在某些板卡上,使用none的特殊值而不是实际的插件。这表明不需要特殊的集成来将EGL与framebuffer一起使用,因此不需要加载插件。

QT_QPA_EGLFS_PHYSICAL_WIDTH和QT_QPA_EGLFS_PHYSICAL_HEIGHT - 以毫米为单位的物理屏幕宽度和高度。在无法从framebuffer设备/ 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 - 设置后,每次调用eglSwapBuffers()后,eglfs都会在帧缓冲区设备上请求FBIO_WAITFORVSYNC。这只与依赖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 bpp配置。

另外,还有以下 - 不太常用的 - 变量:

QT_QPA_EGLFS_FB - 覆盖帧缓冲设备。缺省值是/ dev / fb0。在大多数嵌入式平台上,这并不相关,因为帧缓冲区仅用于查询显示尺寸等设置。但是,在某些设备上,此参数提供了指定要在多个显示设置中使用的显示的功能,与LinuxFB中的fb参数类似。

QT_QPA_EGLFS_WIDTH和QT_QPA_EGLFS_HEIGHT - 以像素为单位包含屏幕宽度和高度。虽然eglfs试图从framebuffer设备/ 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 -v打开详细输出以查看每个配置测试的编译器和链接器调用。

注意:关于缺少标题,库或看起来神秘的链接程序故障的错误通常是一个不完整或损坏的sysroot的标志,并且与Qt无关并且无法解决。

例如,当使用Broadcom专有图形驱动程序来定位Raspberry Pi时,输出应该包含如下内容。 如果情况并非如此,那么进行进一步构建就没有意义了,因为即使Qt的其余部分编译成功,没有RaspberryPi特定的后端,加速图形也不能运行。

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

LinuxFB

这个插件通过Linux的fbdev子系统直接写入帧缓冲区。仅支持软件呈现的内容。请注意,在某些设置中,显示器性能预计会受到限制。

从Qt 5.9开始,由于fbdev在Linux内核中被弃用,因此也可以使用DRM哑缓冲区支持。这必须通过将QT_QPA_FB_DRM环境变量设置为非零值来请求。设置后,如果系统支持哑缓冲区,则不会访问像/ dev / fb0这样的传统帧缓冲区设备。相反,渲染是通过DRM API设置的,类似于eglfs的eglfs_kms后端。输出将被双缓冲并翻页,为软件呈现的内容提供适当的vsync。

注意:当使用哑缓冲区时,以下所述的选项都不适用,因为所有属性(如物理和逻辑屏幕大小)都会自动查询。

linuxfb插件允许通过将其传递到QT_QPA_PLATFORM环境变量或-platform命令行选项来指定其他设置。例如,QT_QPA_PLATFORM = linuxfb:fb = / dev / fb1指定必须使用framebuffer设备/ 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版本的行为。

输入

当不存在窗口系统时,鼠标,键盘和触摸输入通过evdev或使用诸如libinput或tslib之类的帮助程序库直接读取。请注意,这要求用户可读取设备节点/ dev / input / event *。 eglfs和linuxfb包含所有输入处理代码。

使用libinput

libinput是处理输入设备的库。它提供了Qt自己的evdev输入支持的替代方案。要启用libinput,请确保在配置和构建Qt时可以使用libudev和libinput的开发文件。如果需要键盘支持,xkbcommon也是必需的。使用eglfs和linuxfb时,不需要进一步的操作,因为这些插件默认使用libinput。如果libinput支持不可用或设置了环境变量QT_QPA_EGLFS_NO_LIBINPUT,则Qt自己的evdev处理程序将进入工作状态。

在没有libinput的情况下输入eglfs和linuxfb

像设备节点名称这样的参数可以在环境变量QT_QPA_EVDEV_MOUSE_PARAMETERS,QT_QPA_EVDEV_KEYBOARD_PARAMETERS和QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS中设置。用冒号分隔条目。这些参数可以替代传递-plugin命令行参数中的设置,并且在一些后端它们是必不可少的:eglfs和linuxfb使用内置的输入处理程序,因此没有使用单独的-plugin参数。

此外,可以通过将QT_QPA_EGLFS_DISABLE_INPUT或QT_QPA_FB_DISABLE_INPUT设置为1来禁用内置输入处理程序

 

鼠标

每当QT_QPA_EGLFS_HIDECURSOR(对于eglfs)或QT_QPA_FB_HIDECURSOR(对于linuxfb)未设置且Qt的基于libudev的设备发现报告至少有一个鼠标可用时,鼠标光标就会显示出来。当libudev支持不存在时,除非通过环境变量显式禁用,否则鼠标光标始终显示。

支持热插拔,但只有在Qt配置了libudev支持(也就是说,如果配置时sysroot中存在libudev开发头文件)。这允许在应用程序运行时连接或断开输入设备。

evdev鼠标处理程序支持以下额外参数:

/ dev / input / ... - 指定输入设备的名称。如果没有给出,Qt会通过libudev或遍历可用节点来查找合适的设备。

nocompress - 默认情况下,与最后一次Qt鼠标事件相比,不会导致位置变化的输入事件被压缩;只有在位置或按钮状态发生变化后才会发送新的Qt鼠标事件。这可以通过设置nocompress参数来禁用。

去抖动 - 指定抖动限制。默认情况下,dejittering被禁用。

抓取 - 当1时,Qt将抓取设备专用。

abs - 某些触摸屏报告绝对坐标,无法与触摸板区分。在这种特殊情况下,通过绝对值来指示设备正在使用绝对事件。

键盘

e vdev键盘处理程序支持以下额外参数:

/ dev / input / ... - 指定输入设备的名称。如果没有给出,Qt会通过libudev或遍历可用节点来查找合适的设备。

抓取 - 使抓取输入设备。

keymap - 指定自定义键盘映射文件的名称。

enable-compose - 启用合成。

repeat-delay - 设置自定义键重复延迟。

repeat-rate - 设置自定义键重复率。

在没有禁用其终端会话的嵌入式Linux系统上,由于输入事件由Qt应用程序和tty处理,按键行为可能会造成混淆。为了克服这个问题,可以使用以下选项:

EGLFS和LinuxFB尝试通过将tty的键盘模式设置为K_OFF来禁用应用程序启动时的终端键盘。这可以防止按键进入终端。如果由于某种原因需要恢复标准行为,请将环境变量QT_QPA_ENABLE_TERMINAL_KEYBOARD设置为1.请注意,这仅适用于从远程控制台启动应用程序(例如,通过ssh)并且终端键盘输入保持启用状态时才起作用。

另一种方法是通过在QT_QPA_EVDEV_KEYBOARD_PARAMETERS中传递grab = 1来使用evdev键盘处理程序的grab参数。这导致试图抓住输入设备。如果抓取成功,只要Qt应用程序正在运行,系统中没有其他组件会接收到事件。这种方法更适合远程启动的应用程序,因为它不需要访问tty设备。

最后,对于许多专用的嵌入式Linux映像,首先启用标准终端会话是没有意义的。请参阅您的构建环境的文档,了解如何禁用它们。例如,当使用Yocto项目生成图像时,取消设置SYSVINIT_ENABLED_GETTYS会导致没有getty进程在任何虚拟终端上运行,因此没有输入。

如果默认的内置键盘映射不足,则可以通过keymap参数或使用eglfs特定的loadKeymap()函数指定不同的键盘映射。后者允许在运行时切换键盘映射。但请注意,这需要使用eglfs的内置键盘处理程序;当通过-plugin命令行参数加载键盘处理程序时,它不受支持。

注意:当前不支持特殊系统组合键,例如控制台切换(Ctrl + Alt + Fx)或zap(Ctrl + Alt + Backspace),并且会被忽略。

要生成自定义键盘映射,可以使用kmap2qmap实用程序。这可以在qttools模块中找到。源文件必须采用标准Linux kmap格式,这可以通过内核的loadkeys命令来理解。这意味着可以使用以下来源生成qmap文件:

Linux控制台工具(LCT)项目。

可以使用ckbcomp实用程序将Xorg X11键盘映射转换为kmap格式。

由于kmap文件是纯文本文件,因此也可以手工制作。

kmap2qmap是一个命令行程序,需要至少2个文件作为参数。最后一个是生成的.qmap文件,而其他所有文件都被解析为输入.kmap文件。  例如:

kmap2qmapi386/qwertz/de-latin1-nodeadkeys.kmap include/compose.latin1.incde-latin1-nodeadkeys.qm

 

注意:kmap2qmap不支持Linux内核支持的所有(伪)符号。 转换标准键盘映射时,会显示许多关于Show_Registers,Hex_A等的警告; 这些消息可以安全地被忽略。

触摸

对于一些电阻式单触式触摸屏,可能需要退回到使用tslib,而不是依赖于Linux多点触控协议和事件设备。对于现代触摸屏,这不是必需的。可以通过将环境变量QT_QPA_EGLFS_TSLIB或QT_QPA_FB_TSLIB设置为1来启用tslib支持。要更改设备,请设置环境变量TSLIB_TSDEVICE或在命令行上传递设备名称。请注意,tslib输入处理程序生成鼠标事件并仅支持单点触摸,与evdevtouch相反,它也会生成真正的多点触摸QTouchEvent事件。

evdev touch处理程序支持以下额外参数:

/ dev / input / ... - 指定输入设备的名称。如果没有给出,Qt会通过libudev或遍历可用节点来查找合适的设备。

旋转 - 在某些触摸屏上,坐标必须旋转,通过将旋转设置为90,180或270来完成。

invertx和inverty - 要反转输入事件中的X或Y坐标,请传递invertx或inverty。例如,在启动应用程序之前,导出QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS = / dev/ input / event5:rotate = 180会导致显式指定的触摸设备和翻转坐标 - 当实际屏幕和触摸屏的方向不匹配时很有用。

基于笔的平板​​电脑

evdevtablet插件为Wacom和类似的笔式平板电脑提供基本支持。它仅生成QTabletEvent事件。要启用它,请在环境中传递QT_QPA_GENERIC_PLUGINS = evdevtablet,或者在命令行上传递-plugin evdevtablet参数。如果Qt的自动设备发现(基于libudev或基于/ dev / input / event *的漫游)不起作用或行为不当,该插件可以采用设备节点参数,例如QT_QPA_GENERIC_PLUGINS = evdevtablet:/ dev / event1。

调试输入设备

通过启用qt.qpa.input记录规则,可以将一些信息输出到调试输出,例如通过将QT_LOGGING_RULES环境变量设置为qt.qpa.input = true。这对于检测正在使用哪个设备或解决设备发现问题很有用。

使用自定义鼠标光标图像

eglfs自带一套32x32大小的鼠标光标图像。如果这些不足,则可以通过将QT_QPA_EGLFS_CURSOR环境变量设置为JSON文件的名称来提供自定义游标图集。该文件也可以通过Qt的资源系统嵌入到应用程序中。

例如,每行有8个游标图像的嵌入式游标图集可以如下指定:

{

  "image":":/cursor-atlas.png",

  "cursorsPerRow": 8,

  "hotSpots": [

      [7, 2],

      [12, 3],

      [12, 12],

      ...

  ]

}

 

请注意,图像预计会紧紧包装在图集中:光标的宽度和高度取决于总图像大小和cursorsPerRow设置。地图必须为所有支持的游标提供图像。

显示输出

当连接多个显示器时,针对单个Qt应用程序中的一个或多个应用程序的支持级别因平台插件而异,并且通常取决于设备及其图形堆栈。

带有eglfs_kms后端的eglfs

当KMS / DRM后端正在使用时,eglfs报告QGuiApplication:: screens()中的所有可用屏幕。应用程序可以通过QWindow :: setScreen()以不同的窗口定位不同的屏幕。

注意:每个屏幕的单个全屏窗口的限制仍然适用。使QWindow可见后更改屏幕也不受支持。因此,在调用QWindow :: show()之前,嵌入式应用程序必须完成所有必需的QWindow :: setScreen()调用。

当开始在给定的嵌入式设备上开发时,通常需要验证设备和驱动程序的行为,并确保连接的显示器正常工作。一个简单的方法是使用hellowindow示例。使用-platform eglfs启动它--multiscreen --timeout参数在每个连接的屏幕上显示一个旋转Qt标志几秒钟。

注意:下面介绍的大多数配置选项适用于所有基于KMS / DRM的后端,而不管缓冲区管理技术(GBM或EGLStreams)如何。

KMS / DRM后端还通过JSON文件支持自定义配置。将环境变量QT_QPA_EGLFS_KMS_CONFIG设置为文件的名称以启用该功能。该文件也可以通过Qt资源系统嵌入到应用程序中。示例配置如下:

{

  "device":"/dev/dri/card1",

  "hwcursor": false,

  "pbuffers": true,

  "outputs": [

    {

      "name": "VGA1",

      "mode": "off"

    },

    {

      "name": "HDMI1",

      "mode": "1024x768"

    }

  ]

}

 

在这里我们配置指定的设备,它不会使用硬件光标(回退到通过OpenGL呈现鼠标光标;默认情况下启用硬件光标,因为它们更高效),

它将返回标准EGL pbuffer曲面的QOffscreenSurface(默认情况下,这是禁用的,而是使用gbm曲面),VGA连接器上的输出被禁用,而HDMI处于活动状态并且分辨率为1024x768。

此外,这样的配置还禁止通过libudev查找设备,而是使用指定的设备。

未定义模式时,将选择报告为系统首选的模式。可接受的模式值包括:off,current,preferred,widthxheight或modeline字符串。

DRM层报告的所有屏幕默认会被视为一个大型虚拟桌面。鼠标光标实现将考虑到这一点,并按照预期在屏幕上移动。虽然不推荐,但如果需要,可以通过在配置中将分离屏幕设置为false来禁用虚拟桌面模式。

默认情况下,虚拟桌面根据系统报告的连接器顺序从左到右形成。这可以通过将virtualIndex设置为从0开始的值来更改。例如,以下配置使用首选分辨率,但确保虚拟桌面的左侧是连接到HDMI端口的屏幕​​,而右侧是屏幕连接到DisplayPort:

{

  "device": "drm-nvdc",

  "outputs": [

    {

      "name": "HDMI1",

      "virtualIndex": 0

    },

    {

      "name": "DP1",

      "virtualIndex": 1

    }

  ]

}

数组中元素的顺序不相关。 具有未指定虚拟索引的输出将放置在其他节点之后,并保留DRM连接器列表中的原始顺序。要创建一个垂直桌面空间(即从顶部到底部而不是从左到右堆叠),请在设备后面添加virtualDesktopLayout属性,使其值为vertical。

注意:建议虚拟桌面中的所有屏幕使用相同的分辨率,否则像鼠标光标这样的元素在输入只存在于一个给定屏幕上的区域时可能会以意想不到的方式运行。

当virtualIndex不足时,可以使用virtualPos属性显式指定所讨论的屏幕的左上角位置。 以前面的例子为例,假设HDMI1的分辨率为1080p,下面将第二个基于HDMI的屏幕放在第一个以下:

{

   ...

  "outputs": [

    ...

    {

      "name": "HDMI2",

      "virtualPos": "0, 1080"

    }

  ]

}

注意:当需要鼠标支持时,避免这种配置。对于非线性布局,鼠标光标的行为可能是意想不到的。然而,触摸应该没有问题。

在某些情况下,通过DRM自动查询物理屏幕大小可能会失败。通常情况下,QT_QPA_EGLFS_PHYSICAL_WIDTH和QT_QPA_EGLFS_PHYSICAL_HEIGHT环境变量将用于提供缺失值,但当多个屏幕出现时,这不再适用。而是使用输出列表中的physicalWidth和physicalHeight属性来指定以毫米为单位的大小。

注意:由于一些图形堆栈组件不知道多个屏幕并仅依赖于第一个屏幕的值,可能会导致意外问题,因此不鼓励不同的物理尺寸和不同的逻辑DPI。

来自输出数组的每个活动输出对应于从QGuiApplication :: screens()报告的一个QScreen实例。 QGuiApplication :: primaryScreen()报告的主屏幕默认为首先被注册的屏幕。不使用virtualIndex时,这意味着决定基于DRM连接器顺序。要覆盖它,请在输出列表中的所需条目上将属性主属性设置为true。例如,要确保即使系统刚好报告HDMI时,与VGA输出相对应的屏幕仍是主要屏幕,您可以执行以下操作:

{

  "device":"/dev/dri/card0",

  "outputs": [

      { "name": "HDMI1" },

      { "name": "VGA1","mode": "1280x720", "primary": true },

      { "name": "LVDS1","mode": "off" }

  ]

}

对于故障排除,从KMS / DRM后端启用调试日志可能很有用。 为此,请启用分类日志记录规则qt.qpa.eglfs.kms。

注意:在嵌入式环境中,虚拟桌面比使用完整的窗口系统更受限制。 应避免Windows重叠多个屏幕,非全屏窗口和屏幕之间的移动窗口,并且可能无法按预期运行。

多屏幕设置最常见和最受支持的用例是为每个屏幕打开专用的QQuickWindow或QQuickView。使用Qt Quick场景图的默认线程渲染循环,每个窗口都将获得它自己的专用渲染线程。 这很好,因为这些线程可以根据vsync独立调节,并且不会互相干扰。 使用基本循环时,这可能会产生问题,并且动画可能会因此而降级。

例如,发现所有连接的屏幕并为其中的每个屏幕创建一个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;

}

eglfseglfs_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上的多屏幕系统中触摸输入

触摸屏在多显示器系统中需要额外的考虑,因为触摸事件必须被路由到正确的虚拟屏幕,并且这需要触摸屏和显示器输出之间的正确映射。

该映射通过QT_QPA_EGLFS_KMS_CONFIG中指定的JSON配置文件完成,并在前面的章节中介绍。当outputs元素中存在touchDevice属性时,该值将被视为设备节点,触摸设备与相关显示输出相关联。

例如,假设我们的触摸屏具有/ 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

其他后端(通常基于通过供应商的EGL实现直接定位帧缓冲区或组合API)通常对多个显示器提供有限或不支持。在使用Vivante GPU的基于i.MX6的电路板上,QT_QPA_EGLFS_FB环境变量可用于指定要定向的帧缓冲区,与linuxfb类似。在Raspberry Pi上,可以使用QT_QPA_EGLFS_DISPMANX_ID环境变量指定要输出到的屏幕。该值对应于其中一个DISPMANX_ID_常量,请参阅Dispmanx文档。请注意,与KMS / DRM不同,这些方法通常不允许从同一应用程序输出到多个屏幕。或者,驱动程序特定的环境变量或内核参数也可用于控制使用的帧缓冲区。请参阅嵌入式主板的文档。

视频内存

在运行基于Qt Quick的Qt应用程序或诸如QOpenGLWidget之类之前,需要额外处理具有固定数量的专用视频内存的系统。对于此类应用程序,默认设置可能不足,尤其是在高分辨率(例如全高清)屏幕上显示时。在这种情况下,他们可能会以意想不到的方式开始失败。建议确保至少有128 MB可用的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 for Embedded Linux Fonts。

注意:Qt不再在lib / fonts目录中提供任何字体。这意味着它需要平台(系统映像)来提供必要的字体。

嵌入式Linux设备上窗口化系统的平台插件

XCB

这是常规桌面Linux平台上使用的X11插件。在某些嵌入式环境中,为xcb提供X和必要的开发文件,这个插件的功能就像在普通的PC桌面上一样。

注意:在某些设备上,X下没有EGL和OpenGL支持,因为EGL实现与Xlib不兼容。在这种情况下,XCB插件没有EGL支持,这意味着Qt Quick 2或其他基于OpenGL的应用程序不适用于此平台插件。它仍然可以用来运行软件呈现的应用程序(例如基于QWidget)。

作为一般规则,不建议在嵌入式设备上使用XCB。像eglfs这样的插件可能会提供更好的性能和硬件加速。

Wayland

Wayland是一个轻量级视窗系统;或者更确切地说,它是客户端与显示服务器交谈的协议。

Qt Wayland模块提供了一个允许Qt应用程序连接Wayland合成器的路径平台插件。

注意:在使用Weston参考排字器时,您可能会遇到触摸屏输入问题。有关更多信息,请参阅Qt Wiki。

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值