1. 程式人生 > >Qt5.7 Qt for Embedded Linux

Qt5.7 Qt for Embedded Linux

從Qt5.0開始,Qt不再包含自己的視窗系統了(QWS)。對於單螢幕的情況,使用QtPlatform Abstraction是一個很好的選擇。多屏的情況可以通過Wayland實現。

         有許多跨平臺的外掛可以使用:EGLFS,LinuxFB,KMS,DirectFB,Wayland。可以通過配置Qt使用這些外掛。預設的平臺外掛是特殊裝置。例如,許多板子預設使用eglfs。如果預設的不合適,可以通過修改QT_QPA_PLATFORM環境變數來設定另一個外掛。可選的,使用-platform 命令列也可以達到相同的效果。

配置一個特殊的裝置

針對一個給定的裝置平臺編譯Qt需要提供一個工具鏈和一個檔案系統。另外,為了支援EGL和OpenGL ES2.0,一些裝置需要特殊廠商修改的程式碼。這和非加速平臺無關,例如,有些人使用LinuxFB,僅僅用於一些軟體渲染。這就意味著Qt Quick 2的功能不可用,因為Qt Quick 2 使用OpenGL渲染。

qtbase/mkspecs/devices目錄包含配置和圖形配置程式碼。例如,linux-rasp-pi2-g++ mkspec目錄包含編譯設定使用可選的編譯器和連結器標誌用於Raspberry Pi 2裝置。Mkspec還包含關於eglfs鉤子的一些資訊或者一個適合eglfs裝置整合外掛的一個參考。通過指定配置工具選項-device引數指定裝置。後面的名稱必須和devices目錄下的一個子目錄匹配。

下面是一個Raspberry Pi 2的配置示範。對於大多數嵌入式Linux板,配置命令是相似的:

./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,標頭檔案和庫檔案用於配置的特徵檢測測試,也包含Qt本身,指定的路徑是特定的目錄,而不是主機PC標準路徑。這就意味著安裝開發包到哪一個主機環境沒有關係。例如,為了獲得libinput支援沒有必要在主機上安裝libinput開發標頭檔案和庫檔案。取而代之,對應目標結構的標頭檔案和庫檔案需要安裝在sysroot中。

交叉編譯的時候Pkg-config也是被支援的。Configure自動設定PKG_CONFIG_LIBDIR來使pkg-config報告基於sysroot的編譯器和連結器設定而不是主機的設定。這通常不需要其它更多 的適配就可以工作得很好。然後,在執行configure之前,主機上的PKG_CONFIG_PATH環境變數必須unset。否則Qt組建可能會嘗試使用主機上的不合適的標頭檔案和庫檔案。

指定-sysroot自動的導致設定—sysroot引數。在一些情況下,這並不是希望的,這可以通過傳遞-no-gcc-sysroot 給configure來使之失效。

-prefix,-extprefix和-hostprefix控制qt組建時的目標目錄。在上面的例子中,編譯Arm上的Qt的目標板上的目錄為/usr/local/qt5。注意,執行make install不部署任何東西到裝置上。如果不設定extprefix,預設的安裝目錄為sysroot+prefix,然而有些時候我們不希望放到sysroot目錄下,可以通過指定-extprefix目錄來指定目標目錄。最後,-hostprefix允許指定生成的主機工具比如:qmake,rcc uic,如果不指定-hostprefix 將會安裝在extprefix目錄下。

嵌入式linux裝置的平臺外掛

EGLFS

EGL是OpenGL和本地視窗系統中間的一個介面。Qt可以使用EGL作為context和surface管理,然而,API包含非指定平臺部分:本地視窗的建立必須通過特定平臺的方式建立。因此,就需要對板子或者指定GPU修改程式碼。有兩種修改的方式:一種是通過eglfs hooks,這種方式可以是一個單原始檔編譯進平臺外掛中,第二種方式就是動態載入EGL裝置整合外掛。

EGLFS是一個為了Qt5應用執行的平臺外掛,Qt5執行在EGL和OpenGL ES2.0之上而且沒有真實的視窗系統(比如 X11 Wayland)。對於Qt Quick 2和本地OpenGL應用,它也支援軟體渲染視窗(例如QWidget)。在OpenGL應用中,widget的內容是使用CPU轉化為影象渲染的,然後通過這個外掛上傳到紋理和混合。

這就是為什麼當代嵌入式Linuxy裝置建議包含一個GPU的原因。EGLFS強制第一個頂級視窗(QWidget或者QQucikView)為全屏。這個視窗也被選擇成為根widget視窗,其它的頂級視窗(例如對話方塊,彈出選單或者下拉選單)都放入第一個視窗中。這很有必要,因為使用EGLFS總有一個真實存在的本地視窗和EGL視窗外觀,並且其它的都屬於第一個建立的widget或者window. 這種方式可以工作得很好,有一個主視窗存在在整個應用的生命週期裡,其它的後來建立的所有的視窗都屬於第一個視窗。

有更多的基於OpenGL視窗的限制。Qt 5.3,eglfs支援一個單全屏GL視窗(比如,一個基於OpenGL的QWindow,QQuickView或者QGLWidget)。開啟另外的OpenGL視窗或者混合有基於QWidget內容的視窗就不被支援了。它會關閉這個應用然後報一個錯誤訊息。

如果有必要,eglfs可以通過使用以下環境變數進行配置:

l  QT_QPA_EGLFS_FB-覆蓋Framebuffer裝置。預設的配置是/dev/fb0。在很多嵌入式平臺上這不是非常適宜的了,因為framebuffer僅用於查詢設定比如顯示尺寸。然而在有一些裝置上,多屏顯示設定中這些引數提供設定顯示引數的能力,引數和LinuxFB中fb的引數相似。

l  QT_QPA_EGLFS_WIDTH和QT_QPA_EGLFS_HEIGHT-螢幕畫素寬度和螢幕畫素高度。當然eglfs嘗試從framebuffer裝置/dev/fb0中讀取這些引數,但是有時會不工作,所以手動設定尺寸變得很有必要。

l  QT_QPA_EGLFS_PHYSICAL_WIDTH和QT_QPA_EGLFS_PHYSICAL_HEIGHT-螢幕寬度和高度物理尺寸,單位是毫米。有些平臺沒有/dev/fb0或者查詢失敗的情況,這些值使用預設的DPI=100計算寬和高,這個變數可以用於覆蓋任何預設值。

l  QT_QPA_EGLFS_DEPTH-重置螢幕的顏色深度。在沒有/dev/fb0裝置結點的平臺上或者查詢失敗的平臺上,顏色的預設深度為32.這個變數可以用於修改預設值。注意這僅僅會影響QScreen報告的顏色深度值。它和EGL配置或者OpenGL的顏色深度無關。

l  QT_QPA_EGLFS_SWAPINTERVAL-預設的交換值為1。這將會同步垂直重新整理。例如,設定間隔為0,將會盡最快的方式執行不帶任何同步。

l  QT_QPA_EGLFS_FORCEVSYNC-設定該變數,eglfs請求RBIO_WAITFORVSYNC。

l  QT_QPA_EGLFS_FORCE888-設定該變數時,紅綠藍通道大小被忽略。強制設定每一個通道為8位。

l  QT_QPA_EGLFS_DEBUG-如果設定該變數,除錯資訊將會列印到除錯輸出口。

l  QT_QPA_EGLFS_INTERGRATION-除了編譯進的hooks,能夠提供裝置或者廠商修改的可動態載入的外掛。該環境變數指定一個特定的外掛。

除了QT_QPA_EGLFS_DEBUG,eglfs還提供更多的日誌系統。有以下幾種日誌方式:

l  qt.qpa.egldeviceintegration – Enables logging for dynamically loaded backends. Veryuseful to check what backend is in use.

l  qt.qpa.input – Enables debug output both from the evdev and libinput input handlers.Very useful to check if a given input device was recognized and opened.

l  qt.qpa.eglfs.kms – Enables verbose logging in the KMS/DRM backend.

 

LinuxFB

這個外掛直接寫framebuffer.僅支援軟體渲染內容。注意在一些設定上,顯示效能將被限制。

         Linuxfb外掛允許指定額外的設定,傳遞引數QT_QPA_PLATFORM環境變數或者通過-platform命令列選項。例如,QT_QPA_PLATFORM=linuxfb:fb=/dev/fb1指定framebuffer裝置/dev/fb1而不是fb0.可以指定多設定通過冒號分割。

l  fb=/dev/fbN –指定framebuffer裝置。在多顯示器設定上,這通常允許執行應用在不同的顯示器上。

l  size=<width>x<height> -

l  mmsize=<width>x<height>

l  offset=<width>x<height>

l  nographicsmodeswitch –禁止切換虛擬終端到圖形模式(KD_GRAPHICS),另外,切換到圖形模式,閃爍的游標和空白屏也同樣無效。當設定這個引數時,這些會被跳過。

l  tty=/dev/ttyN –重置虛擬控制檯。僅當nographicsmodeswitch未設定時使用

Input

相對於沒有視窗系統,滑鼠、鍵盤、觸控板輸入直接從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將會使用它自己的evdevhandlers處理。

Eglfs和linuxfb不使用libinput

有一些環境變數可以進行設定,QT_QPA_EVDEV_MOUSE_PARAMETERS, QT_QPA_EVDEV_KEYBOARD_PARAMETERS以及QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS.

QT_QPA_EGLFS_DISABLE_INPUT 禁用輸入

QT_QPA_FB_DISABLE_INPUT禁用輸入

QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS

滑鼠輸入

滑鼠游標會一直顯示,除非設定QT_QPA_EGLFS_HIDECURSOR (for eglfs) 或者QT_QPA_FB_HIDECURSOR (for linuxfb),Qt的基於libudev的裝置會檢視報告,報告中至少有一個滑鼠可用。如果不使用libudev,滑鼠箭頭會一直顯示除非通過修改環境變數禁止顯示。

只有使用libudev時才支援熱插拔.它允許在應用執行的時候插拔滑鼠。

鍵盤輸入

Evdev鍵盤處理支援以下額外引數:

·                    /dev/input/... – 指定輸入裝置名稱.如果未指定,Qt通過libudev查詢一個合適的裝置,或者遍歷所有的裝置結點查詢一個合適的裝置。

·                    grab – 允許搶佔輸入裝置

·                    keymap – 指定鍵盤對映檔案

·                    enable-compose - Enables compositing.

l  repeat-delay – 設定一個使用者定義的按鍵重複延時

l  repeat-rate -設定一個使用者定義的按鍵重複率.

在嵌入式linux系統的終端處理中,按鍵行為是被誰處理是未知的,因為輸入事件既可以被Qt應用處理也可以被終端處理。為了解決這個問題,可以設定以下選項

l  在應用啟動的時候設定tty鍵盤的模式K_OFF來禁用終端鍵盤處理,這將阻止鍵盤事件進入終端。有些情況下,標準鍵盤行為需要被重新載入,這裡把QT_QPA_ENABLE_TERMINAL_KEYBOARD設定為1.注意:這僅僅從遠端終端(ssh)啟動一個應用時有用,終端鍵盤輸入保持可用。

l  一個可選擇的實現方式是使用udev鍵盤處理的grab引數,QT_QPA_EVDEV_KEYBOARD_PARAMETERS的引數grab=1.這將導致搶佔一次輸入裝置,如果搶佔成功,系統中的其它元件就不會收到鍵盤事件。這種方式更適合於從遠端啟動的應用,因為不需要獲取tty裝置。

 

l  Finally, for many specialized Embedded Linux images it does not makesense to have the standard terminal sessions enabled in the first place. Referto your build environment's documentation on how to disable them. For example,when generating images using the Yocto Project, unsetting SYSVINIT_ENABLED_GETTYS results in having no getty process running, andthus no input, on any of the virtual terminals.

 

如果內建的鍵盤對映不能滿足要求,可以使用eglfs的loadKeymap()函式或者使用keymap引數來載入一個鍵盤對映檔案。LoadKeyMap()允許在程式執行時改變鍵盤對映。注意,這需要使用eglfs內部的鍵盤處理,如果鍵盤處理是通過-plugin命令列引數的方式載入的不可以使用loadkeymap().

    注意:特殊系統的鍵盤組合現在不被支援會被忽略比如(Ctrl+Alt+Fx) (Ctrl+Alt+Backspace

    生成一個自定義鍵盤對映,可以使用kmap2qmap工具。這個工具在qttools模組裡。原始檔必須是標準Linux kmap格式,這種格式可以被核心的loadkeys命令理解。也就是說可以使用以下源來生成qmap檔案:

 

·        The LinuxConsole Tools (LCT) project.

  • Xorg X11 keymaps 通過使用ckbcomp工具轉化 kmap 格式
  • kamp檔案是純文字檔案,可以手動編寫。

Kmap2qmap是一個命令列程式,至少需要兩個檔案引數最後一個是生成的.qmap檔案,其它所有的引數都將作為輸入的.kmap檔案。例如:

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

注意:kmap2qmap並不能支援Linux核心支援的所有的符號,當轉化標準keymap檔案時,會顯示許多的警告資訊Show_Registers, Hex_A等等;忽略這些資訊即可。

觸控

對於一些電阻單點觸控式螢幕,需要退回使用tslib。可以通過設定環境變數QT_QPA_EGLFS_TSLIB or QT_QPA_FB_TSLIB為1來啟動tslib支援。設定TSLIB_TSDEVICE或者通過命令列傳裝置名稱引數來改變裝置。注意:tslib輸入處理產生滑鼠事件並僅支援單點觸控,與之相對的,evdevtouch產生真正的多點觸控QTouchEvent事件。

筆控板

Evdevtablet外掛為Wacom和相似的pen-basedtables提供基礎支援,它產生QTabletEvent事件。QT_QPA_GENERIC_PLUGINS=evdevtablet或者命令列傳遞引數-plugin evdevtablet來使能evdevtablet。該外掛可以有一個裝置結點引數,例如

QT_QPA_GENERIC_PLUGINS=evdevtablet:/dev/event1,這時Qt自動查詢裝置就不進行自動查找了。

除錯輸入裝置

通過使能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],

        ...

   ]

 }

注意:theimages are expected to be tightly packed in the atlas: the width and height ofthe cursors are decided based on the total image size and the cursorsPerRow setting. Atlases have to provide an image for all the supportedcursors.


以上是個人心血來潮翻譯一下Qt的官方說明,這是本人第一次翻譯英文,有很多地方不知道怎麼翻譯,大家湊合看吧。

技術交流群:589805575,歡迎志同道合者加入