android studio 显示图形_显示服务器实现(一)
在一個多窗口的圖形化操作系統(tǒng)中,顯示服務(wù)器的任務(wù)就是組織這些窗口展現(xiàn)給用戶。實際的顯示服務(wù)器有Linux世界基于X11協(xié)議的XServer或者Wayland協(xié)議的Weston,還有Android里的SurfaceFlinger。但是除了顯示,他們同時包含了輸入管理(鼠標(biāo)、鍵盤等)的功能,本文主要還是討論圖形顯示部分,通過將顯示服務(wù)器用到的技術(shù)分解,實際來看看如何實現(xiàn)一個顯示服務(wù)器。
需求分析
在命令行Linux操作系統(tǒng)中實現(xiàn)一個支持GPU圖形應(yīng)用的顯示服務(wù)器:
一個簡單的OpenGL應(yīng)用
這是一個在Linux X11系統(tǒng)下簡單的OpenGL應(yīng)用【1】,效果是在一個X11窗口中繪制一個紅色三角形。我們看看OpenGL應(yīng)用是如何跟顯示服務(wù)器(XServer)交互的。注意這里忽略了無關(guān)參數(shù)和代碼,下同。
Display首先用EGL從X11的Display和Window創(chuàng)建Context,然后用OpenGL進(jìn)行實際繪制,最后用EGL的eglSwapBuffers將繪制好的緩沖交給XServer去顯示。
這個例子的目的,一是看看OpenGL應(yīng)用和顯示服務(wù)器的接口,二是看看在顯示服務(wù)器那邊,我們也想用OpenGL做窗口組裝的話還需要什么。
以下三個例子會展示如何解決:
無顯示服務(wù)器的OpenGL繪制
例二【2】是在沒有顯示服務(wù)器的情況下,用EGL+GBM做OpenGL繪制的例子:
intGBM是一個GPU緩沖管理的API,可以直接從GPU的設(shè)備文件(/dev/dri/renderD128)創(chuàng)建一個gbm_device,然后再創(chuàng)建一個代表GPU緩沖的gbm_surface。支持EGL_MESA_platform_gbm擴展【5】的EGL接口可以利用gbm_device和gbm_surface來創(chuàng)建EGLDisplay和EGLSurface。接下來就和EGL+X11那個例子一樣了。
顯示器顯示幀緩沖
顯示幀緩沖可以參考例三【3】,首先打開GPU設(shè)備文件/dev/dri/card0(這個文件同時支持繪圖和顯示,而/dev/dri/renderD128只有繪圖功能)。然后就能調(diào)用KMS接口獲取當(dāng)前連著顯示器的Connector/Encoder/Crtc,這三個模塊的功能:Crtc從幀緩沖讀取數(shù)據(jù)給Encoder,Encoder編碼數(shù)據(jù)給Connector,Connector輸出HDMI/DP/VGA接口的信號。最后drmModeFBPtr代表Crtc要讀取的幀緩沖。當(dāng)前drmModeFBPtr所指向的幀緩沖里面應(yīng)該是命令行界面,我們需要為自己的繪圖緩沖創(chuàng)建一個新的drmModeFBPtr。
int在上一個例子中我們將圖形繪制在了gbm_surface上,這里就從gbm_surface創(chuàng)建一個新的drmModeFBPtr然后取代原來的命令行drmModeFBPtr給drmModeCrtcPtr顯示:
struct應(yīng)用和顯示服務(wù)器間傳遞緩沖
現(xiàn)在我們知道自己實現(xiàn)的應(yīng)用和顯示服務(wù)器端如何用OpenGL進(jìn)行繪制,而且顯示服務(wù)器如何將繪制好的幀緩沖拿去顯示。最后的一個問題就是應(yīng)用如何將緩沖傳遞給顯示服務(wù)器用于組裝。應(yīng)用和顯示服務(wù)器是兩個獨立進(jìn)程,這個需求只能用進(jìn)程間通信來解決,但是圖形系統(tǒng)所需傳遞的數(shù)據(jù)量巨大(一幀往往需要幾MB,每秒60幀,就是上百MB/s,這還只是一個應(yīng)用), 如果用傳統(tǒng)的進(jìn)程間通信方法比如Socket和System V IPC,性能會很差。所以我們需要一種零拷貝的進(jìn)程間共享緩沖的方式。
例四【4】展示了使用dma-buf+unix local socket達(dá)到應(yīng)用和顯示服務(wù)器間零拷貝傳遞緩沖的實現(xiàn)。里面是應(yīng)用部分的代碼,是顯示服務(wù)器部分的代碼。首先我們創(chuàng)建兩個進(jìn)程分別代表應(yīng)用和顯示服務(wù)器,用socketpair建立unix local socket連接(出于演示方便,真實的顯示服務(wù)器會用完整的socket listen/bind/connect/accept流程):
int然后是應(yīng)用端,我們用GBM接口獲得緩沖的文件描述(File Descriptor),這個文件描述只是一個句柄,在Linux內(nèi)核里代表了一個關(guān)聯(lián)緩沖的dma-buf結(jié)構(gòu)體。我們只需要在進(jìn)程間傳遞這個文件描述就可以共享他所代表的緩沖而不用拷貝。傳遞文件描述的方法就是這個Unix Local Socket的sendmsg函數(shù)。
// 獲得緩沖最后是顯示服務(wù)器端,用recvmsg接收應(yīng)用傳送來的文件描述,然后還原為gbm_bo。支持EGL_KHR_image_pixmap擴展【6】的EGL可以將gbm_bo轉(zhuǎn)換為EGLImageKHR(對于支持EGL_EXT_image_dma_buf_import擴展【7】的EGL可以直接將文件描述轉(zhuǎn)換為EGLImageKHR)。支持GL_OES_EGL_image擴展【8】的OpenGL可以將EGLImageKHR轉(zhuǎn)換為貼圖,這樣就能將應(yīng)用的緩沖作為一個OpengGL的貼圖進(jìn)行組裝成幀緩沖的繪圖操作了。
// 接收dma-buf結(jié)語
本文介紹的這些技術(shù)是顯示服務(wù)器實現(xiàn)的基礎(chǔ),下一篇文章我們會討論更深入的應(yīng)用和顯示服務(wù)器間的同步問題。
引用
總結(jié)
以上是生活随笔為你收集整理的android studio 显示图形_显示服务器实现(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 罗永浩宣布退出所有社交平台!新浪:其微博
- 下一篇: 【转】RAX,eax,ax,ah,al