Android圖形系統分析與移植–六、framebuffer研究

來源:互聯網
上載者:User
1  FrameBuffer的發展曆史

電腦研究者從很早開始已經開始討論理論上FrameBuffer的優點,但卻一直苦於沒有能力生產一台擁有足夠記憶體的電腦。1969年,貝爾實驗室的JoanMiller實驗了第一個已知的FrameBuffer。該裝置顯示了一幅3位位深的圖片。然而,直到20世紀70年代,整合電路的記憶體晶片上的進展才使得製造一個可以顯示標準視頻映像的FrameBuffer成為可能。

1972年,Richard Shoup在施樂帕洛阿爾托研究所裡設計了SuperPaint系統,該系統擁有311,040位元組的記憶體,並能儲存640*480像素8位位深的圖片。這些記憶體分散在16個迴路電板上,每個電板上裝有多個2千位元的片選晶片。要使得整個系統可以正常工作,Richard Shoup的設計必須保證整個FrameBuffer實現為307,200位元組的片選註冊晶片並保證能和電視訊號同步。這種設計最初的缺點已經顯露出來,即記憶體不能隨機訪問。當然,指定位置的記憶體在要求的掃描線開始掃描的時候可以訪問。這樣使得該系統存在著極大的潛在缺陷,導致寫入資料到FrameBuffer時有33毫秒的延遲。

同時,Richard Shoup可以用SuperPaint系統製造一個早期的數位視訊捕獲系統。通過將輸出訊號同步到輸入訊號,Richard Shoup可以重寫每個像素點的資料。Richard Shoup還曾經實驗用色彩表來修改輸出訊號,這些色彩表允許SuperPaint系統產生多種多樣的超出8位元據所包含色彩限制之外的顏色。這種體制在不久的將來成為電腦框架緩衝區中司空見慣的體制。

1974年,Evans和Sutherland發布了第一個商業版的FrameBuffer,花費15,000美元。它能夠在8位灰階級模式下產生512*512個像素點的解析度,並成為那些沒有資源為自己建立FrameBuffer的研究者們的福利。不久的將來,美國紐約理工大學用3個Evans和Sutherland的系統製造了第一個24位的色彩系統,每一個FrameBuffer被串連到一個RGB色彩輸出,用一個微電腦控制三個裝置作為一個裝置。

20世紀70年代末,整合電路技術的飛速發展使得家用電腦包含低色彩FrameBuffer成為可能。雖然相比在某些電腦中使用的類似於Atari 400這種更加精確的圖形裝置,低色彩FrameBuffer因其差勁的表現總是被嘲笑,FrameBuffer卻因此在個人電腦中成為一種標準。今天,幾乎所有有圖形處理能力的電腦都利用FrameBuffer來產生視頻訊號。

80年代,FrameBuffer在高端智能終端開始流行。SGI公司,Sun公司,HP公司,DEC公司,IBM公司都為他們的電腦發布了FrameBuffer版本,這些FrameBuffer通常情況下比大部分家用電腦具有更高的品質,應用於電視,印刷,電腦建模和3D圖形技術等。

Amiga電腦由於其在圖形處理方面的出色能力,創造了一個基於圖形卡的廣闊的FrameBuffer市場。值得一提的是,在Amiga A2500 Unix電腦中使用的圖形卡,它是1991年出現的第一台實現以X11伺服器作為圖形環境和Open Look GUI高解析度(1024*1024或1024*768,256色)圖形介面的宿主機伺服器的電腦。這塊被裝在A2500 Unix上的圖形卡被稱作A2400,它是以德州儀器公司TMS34010圖形處理器為基礎的圖形板,時鐘頻率為50MHz,是一個完全只能的副處理器。A2410圖形卡是Amiga公司和Lowell大學共同研發的。其他值得一提的是,Amiga的FrameBuffer是基於GVP公司的一個很有趣的視頻整合系列中的Impact
Vision IV24圖形卡實現的,它有能力將同步鎖訊號、色度和電視訊號混合到24位的FrameBuffer中,直到今天,它還一直在市場中活躍著,形卡視頻捕獲系統DCTV,32位元影像形卡Firecracker,Harlequin卡等等一直還在使用它。

2  FrameBuffer相關概念

FrameBuffer中文譯名為幀緩衝驅動,它是出現在2.2.xx核心中的一種驅動程式介面。

Linux是工作在保護模式下,所以使用者態進程是無法象DOS那樣使用顯卡BIOS裡提供的中斷調用來實現直接寫屏,Linux抽象出FrameBuffer這個裝置來供使用者態進程實現直接寫屏。FrameBuffer機制模仿顯卡的功能,將顯卡硬體結構抽象掉,可以通過FrameBuffer的讀寫直接對顯存進行操作。使用者可以將FrameBuffer看成是顯示記憶體的一個映像,將其映射到進程地址空間之後,就可以直接進行讀寫操作,而寫操作可以立即反應在螢幕上。這種操作是抽象的,統一的。使用者不必關心物理顯存的位置、換頁機制等等具體細節,這些都是由FrameBuffer裝置驅動來完成的。

但FrameBuffer本身不具備任何運算資料的能力,就只好比是一個暫時存放水的水池。CPU將運算後的結果放到這個水池,水池再將結果流到顯示器,中間不會對資料做處理。應用程式也可以直接讀寫這個水池的內容在這種機制下,儘管FrameBuffer需要真正的顯卡驅動的支援,但所有顯示任務都有CPU完成,因此CPU負擔很重。

幀緩衝驅動應用廣泛,在 linux 的案頭系統中,X window 伺服器就是利用幀緩衝進行視窗的繪製。尤其是通過幀緩衝可顯示漢字點陣,成為Linux 漢化的唯一可行方案。

在開發人員看來,FrameBuffer 本質上是一塊顯示緩衝,往顯示緩衝中寫入特定格式的資料就意味著向螢幕輸出內容。所以說FrameBuffer就是一塊白板。例如對於初始化為16位色的FrameBuffer來說,FrameBuffer 中的兩個位元組代表螢幕上一個點,從上到下,從左至右,螢幕位置與記憶體位址是順序的線性關係。

幀緩衝可以在系統儲存空間(記憶體)的任意位置,視頻控制器通過訪問幀緩衝來重新整理螢幕。幀緩衝也叫重新整理緩衝FrameBuffer或RefreshBuffer,這裡的幀(frame)是指整個螢幕範圍。

幀緩衝有個地址,是在記憶體裡。我們通過不停的向 FrameBuffer 中寫入資料, 顯示控制器就自動的從FrameBuffer中取資料並顯示出來。全部的圖形都共用記憶體中同一個幀緩衝。

CPU 指定顯示控制器工作,則顯示控制器根據CPU的控制到指定的地方去取資料和指令,目前的資料一般是從顯存裡取,如果顯存裡存不下,則從記憶體裡取, 記憶體也放不下,則從硬碟裡取,當然也不是記憶體放不下,而是為了節省記憶體的話, 可以放在硬碟裡,然後通過指令控制顯示控制器去取。幀緩衝 FrameBuffer裡面儲存的東西是一幀一幀的, 顯卡會不停的重新整理 FrameBuffer, 這每一幀如果不捕獲的話,則會被丟棄,也就是說是即時的。這每一幀不管是儲存在記憶體還是顯存裡, 都是一個顯性的資訊,這每一幀假設是800x600的解析度,則儲存的是800x600個像素點和顏色值。

3  FrameBuffer使用基礎

framebuffer的裝置檔案一般是 /dev/fb0、/dev/fb1 等等。

可以用命令: #dd if=/dev/zero of=/dev/fb 清空螢幕。

如果顯示模式是 1024x768-8 位色,用命令:$ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768 清空螢幕;

用命令: #dd if=/dev/fb of=fbfile 可以將fb中的內容儲存下來;

可以重新寫回螢幕: #dd if=fbfile of=/dev/fb;

在使用Framebuffer時,Linux是將顯卡置於圖形模式下的。

在應用程式中,一般通過將 FrameBuffer 裝置映射到進程地址空間的方式使用,比如下面的程式就開啟 /dev/fb0 裝置,並通過 mmap 系統調用進行地址映射,隨後用memset 將螢幕清空(這裡假設顯示模式是 1024x768-8 位色模式,線性記憶體模式):

int fb;

unsigned char*fb_mem;

fb = open("/dev/fb0", O_RDWR);

fb_mem = mmap(NULL, 1024*768,                                                                                                            PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);

memset (fb_mem,0, 1024*768); //這個命令應該只有在root可以執

FrameBuffer 裝置還提供了若干 ioctl 命令,通過這些命令,可以獲得顯示裝置的一些固定資訊(比如顯示記憶體大小)、與顯示模式相關的可變資訊(比如解析度、象素結構、每掃描線的位元組寬度),以及偽彩色模式下的調色盤資訊等等。

通過 FrameBuffer 裝置,還可以獲得當前核心所支援的加速顯示卡的類型(通過固定資訊得到),這種類型通常是和特定顯示晶片相關的。比如目前最新的核心(2.4.9)中,就包含有對 S3、Matrox、nVidia、3Dfx 等等流行顯示晶片的加速支援。在獲得了加速晶片類型之後,應用程式就可以將 PCI 裝置的記憶體I/O(memio)映射到進程的地址空間。這些 memio 一般是用來控制顯示卡的寄存器,通過對這些寄存器的操作,應用程式就可以控制特定顯卡的加速功能。

PCI 裝置可以將自己的控制寄存器映射到實體記憶體空間,而後,對這些控制寄存器的訪問,給變成了對實體記憶體的訪問。因此,這些寄存器又被稱為"memio"。一旦被映射到實體記憶體,Linux 的普通進程就可以通過mmap 將這些記憶體 I/O 映射到進程地址空間,這樣就可以直接存取這些寄存器了。

當然,因為不同的顯示晶片具有不同的加速能力,對memio 的使用和定義也各自不同,這時,就需要針對加速晶片的不同類型來編寫實現不同的加速功能。比如大多數晶片都提供了對矩形填充的硬體加速支援,但不同的晶片實現方式不同,這時,就需要針對不同的晶片類型編寫不同的用來完成填充矩形的函數。

FrameBuffer 只是一個提供顯示記憶體和顯示晶片寄存器從實體記憶體映射到進程地址空間中的裝置。所以,對於應用程式而言,如果希望在 FrameBuffer 之上進行圖形編程,還需要自己動手完成其他許多工作。

Framebuffer的具體操作流程如下:

1)開啟/dev/fb裝置檔案;

2)用ioctrl操作取得當前顯示螢幕的參數,如螢幕解析度,每個像素點的位元數。根據螢幕參數可計算螢幕緩衝區的大小。

3)將螢幕緩衝區映射到使用者空間。

4)映射後就可以直接讀寫螢幕緩衝區,進行繪圖和圖片顯示了。

4  FrmaeBuffer內部結構

FrameBuffer裝置驅動基於如下兩個檔案:

1)linux/include/linux/fb.h

2)linux/drivers/video/fbmem.c

下面分析這兩個檔案。

1.       fb.h

幾乎主要的結構都是在這個中檔案定義的。這些結構包括:

1)fb_var_screeninfo

這個結構描述了顯示卡的特性。

2)fb_fix_screeninfon

這個結構在顯卡被設定模式後建立,它描述顯示卡的屬性,並且系統運行時不能被修改;比如FrameBuffer記憶體的起始地址。它依賴於被設定的模式,當一個模式被設定後,記憶體資訊由顯示卡硬體給出,記憶體的位置等資訊就不可以修改。

3) fb_cmap

描述裝置無關的顏色映射資訊。可以通過FBIOGETCMAP 和 FBIOPUTCMAP 對應的ioctl操作設定或擷取顏色映射資訊。

4) fb_info

定義當顯卡的目前狀態;fb_info結構僅在核心中可見,在這個結構中有一個fb_ops指標, 指向驅動裝置工作所需的函數集。

5) struct fb_ops

使用者應用可以使用ioctl()系統調用來操作裝置,這個結構就是用一支援ioctl()的這些操作的。

6) structfbgen_hwswitch

這個結構 fbgen_hwswitch抽象了硬體的操作.雖然它不是必需的,但有時候很有用。

2.       fbmem.c

fbmem.c 處於FrameBuffer裝置驅動技術的中心位置。它為上層應用程式提供系統調用也為下一層的特定硬體驅動提供介面;那些底層硬體驅動需要用到這兒的介面來向系統核心註冊它們自己。fbmem.c 為所有支援FrameBuffer的裝置驅動提供了通用的介面,避免重複工作。

1) 全域變數

struct fb_info*registered_fb[FB_MAX];

intnum_registered_fb;

這兩變數記錄了所有fb_info 結構的執行個體,fb_info 結構描述顯卡的目前狀態,所有裝置對應的fb_info 結構都儲存在這個數組中,當一個FrameBuffer裝置驅動向系統註冊自己時,其對應的fb_info 結構就會添加到這個結構中,同時num_registered_fb 為自動加1。

2)fbmem.c 實現了如下函數

register_framebuffer(structfb_info *fb_info);

unregister_framebuffer(structfb_info *fb_info);

這兩個是提供給下層FrameBuffer裝置驅動的介面,裝置驅動通過這兩函數向系統註冊或登出自己。幾乎底層裝置驅動所要做的所有事情就是填充fb_info結構然後向系統註冊或登出它。

5  雙緩衝機制

最早解釋多緩衝區如何工作的方式,是通過一個現實生活中的執行個體來解釋的。在一個陽光明媚的日子,你想將水池裡的水換掉,而又找不到水管的時候,你就只能用木桶來灌滿水池。當木桶被水龍頭注滿的,關掉水龍頭,走到水池旁邊,將水到進去,然後走回到水龍頭旁邊繼續重複上述工作,如此往複直到將水池灌滿。這就類似單緩衝工作過程。當你想將木桶裡的水倒出的時候,你必須關掉水龍頭。

現在假設你用兩個木桶來做上面的工作。你會注滿第一個木桶然後將第二個木桶換到水龍頭下面,這樣,在第二個水桶注滿的時間內,你就可以將第一個木桶裡面的水倒進水池裡面,當你回來的時候,你只需要再將第一個木桶換下第二個注滿水木桶,當第一個木桶開始注水的時候你就將第二個木桶裡面的水倒進水池裡面。重複這個過程直到水池被注滿。很容易看得到用這種技術注滿水池將會更快,同時也節省了很多等待木桶被注滿的時間,而這段時間裡你什麼也做不了,而水龍頭也就不用等待從木桶被注滿到你回來的這段時間了。

當你僱傭另外一個人來搬運一個被注滿的木桶時,這就有點類似於三個緩衝區的工作原理。如果將搬運木桶的的時間很長,你可以用更多的木桶,僱傭更多的人,這樣水龍頭就會一直開著注滿木桶了。

在電腦圖形學中,雙緩衝是一種畫圖技術,使用這種技術可以使得畫圖沒有(至少是減少)閃爍、撕裂等不良效果,並減少等待時間。

雙緩衝機制的原理大概是:所有畫圖操作將它們畫圖的結果儲存在一塊系統記憶體地區中,這塊地區通常被稱作“後緩衝區(back buffer)”,當所有的繪圖操作結束之後,將整塊地區複製到顯示記憶體中,這個複製操作通常要跟顯示器的光棧束同步,以避免撕裂。雙緩衝機制必須要求有比單緩衝更多的顯示記憶體和CPU消耗時間,因為“後緩衝區”需要顯示記憶體,而複製操作和等待同步需要CPU時間。

基於雙緩衝機制可以實現頁交換。

頁交換初始狀態:

如所示,此時由於處於初始狀態,畫圖操作的結果都在後緩衝區中,而螢幕上顯示的則是前緩衝區中的內容。此時畫圖操作尚未完成。

畫圖操作完成之後,頁轉換操作開始執行,:

如所示,畫圖操作結束,下一個畫圖操作的結果儲存對象指向前緩衝區,螢幕的顯示對象指向後緩衝區,此時前緩衝區變成實際意義上的後緩衝區,後緩衝區變成實際意義上的前緩衝去,即實現“頁交換”操作。

有時候也在頁交換鏈結中設定多個“後緩衝區”,這是就需要多緩衝區機制的支援。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.