Linux下Framebuffer驅動簡介

2021-06-19 09:23:27 字數 4117 閱讀 9962

version: v0.1

time:09/06/2008

author:[email protected]

最近接觸了一些關於linux下framebuffer方面的東西和lcd的framebuffer驅動,所以去了解了一些相關基礎知識。為了避免其他人走我走過的彎路,所以就把我的一些很少的心得,和大家分享一下,希望對有些人有幫助。

【什麼是framebuffer】

framebuffer直譯就是,幀緩衝。

frame幀:你所看到的螢幕的影象,或者在乙個視窗中的影象,就叫一幀。

buffer緩衝:一段ram,用來暫存影象資料,這些資料會被直接寫入到顯示裝置。

幀緩衝就相當於介於 圖形操作 和 影象輸出中間的乙個中間人。將程式對圖形資料的處理操作,反饋到顯示輸出上。

顯示卡(視訊記憶體中的資料) <-> 幀緩衝(程式對其中的資料進行處理) <-> 顯示器(輸出影象)

顯示卡可能並不支援你當前某個更大解析度的顯示器,但是可以通過幀緩衝獲取顯示卡的視訊記憶體中的資料,處理之後,實現更大的解析度的影象,然後將資料直接輸出到顯示器上。

【雙顯示器例子】

乙個例子,可能就是雙顯示,最近剛剛看到實際某開發者的系統,就是兩個顯示器,滑鼠移動超過單個顯示器,到最右邊的時候,就跑到另乙個顯示器了。對於常常用多系統或者需要開啟很多東西的開發人員,這個功能很實用。

【雙緩衝的主要實現原理】

假如你的顯示器是vga模式,640×400,也就是虛擬的解析度是640x800,也就是800線(每一行的資料,稱為一條線,也就是640x1的資料了)。800線的資料儲存於framebuffer,而實際的顯示內容,只是400線,linux核心中的framebuffer模型中,對應有個變數yoffset,就是表示的這個具體的縱座標,預設是0,所以顯示的內容就是,0-399線,由於和實際顯示 頁面大小等同,所以此處可以簡稱為第一幀。如果yoffset改變了,比如此例中變為400,那就是顯示剩餘的部分,400-799線。此處簡稱為第二幀。

在系統顯示第一幀的時候,系統在後台悄悄地準備第二幀的資料,所以,等第一幀顯示完成,多數時候,第二幀的資料也準備好了,就可以直接顯示,同時系統又在準備接下來的一幀的資料,這樣就可以大大提高顯示效率。

【平滑地滾動頁面的實現原理】

同上,在顯示完第一幀資料的時候,也就是0-399線的時候,將yoffset設定為1,就可以顯示1-400線的資料了,顯示完成後,再設定yoffset為2,就顯示2-401線的資料,這樣,就可以一點點地,平滑地顯示整個滾動畫面了。其實也就是畫面在垂直方向的滾動。其中yoffset的增加,可以使用定時器,各個一段時間,比如10us,增加1,系統自動會更新顯示對應的內容,這樣我們所看到的內容就是滾動的畫面了。

此外,linux中的framebuffer模型中,提供了一些ioctl功能,給定一些引數,然後系統可以實現對應的功能,其中有個引數就是fbiopan_display。具體也就是類似如下呼叫:

ioctl (framebuffer_handler, fbiopan_display, &variable_info);

而這個呼叫,如果顯示不支援framebuffer的雙緩衝的話,那麼其framebuffer的緩衝大小,就是和物理上的顯示器大小等同,那麼對應的yoffset也就不會像雙緩衝那樣變化了。

也就是說,如果顯示卡/顯示屏控制器不支援雙緩衝,那麼yoffset就應該一直為0,並且在執行時候,也不應該改變,也不應該去給fbiopan_display的引數呼叫ioctl。 

小tip:

【測試顯示屏是否正常工作】

在載入了顯示屏驅動後,不知道是否已經工作正常的話,

可以通過在某個資料夾下有稍微多些檔案的地方,去ls,以便顯示有出來東西,

然後通過

ls > /dev/fb0

將當前資料夾列表出來的一些資料,送到framebuffer的預設裝置/dev/fb0,如果顯示屏驅動已經正常載入,顯示屏可以正常工作的話,那麼你會在顯示屏左上角看到一些亂碼花屏一類的東西,這就是你剛剛ls送過去的資料。

發現其他教程上的命令,效果更好:

cat screenshot >/dev/fb0

即將當前截圖內容送給lcd顯示。

【lcd液晶顯示器的座標軸】

左上角為(0,0),水平向左是x軸正向,垂直向下,是y軸正向。即:

(0,0) x→

y【寫驅動前預先要了解的知識】

1.       軟體方面:

要搞懂linux的framebuffer驅動的框架。

其中就包括熟悉linux下,為了framebuffer專門實現的資料結構,尤其是

struct fb_fix_screeninfo ; 

/* more kernel header files copied shamelessly */ 

struct fb_bitfield ; 

struct fb_var_screeninfo ; 

fb_var_screeninfo包含了很多具體驅動執行時候的,framebuffer,即顯示內容的具體屬性,包括實際的顯示器上可見的解析度大小,xres和yres,framebuffer的解析度大小xres_virtual和 yres_virtual,如果是上面提到的雙緩衝,那麼這個解析度就是可以顯示的解析度的兩倍了。

xoffset 和yoffset就是上面提到的,如果是雙緩衝,對應不同的應用,就會在執行時刻,改變對應的xoffset 或yoffset,以實現不同的顯示效果。

其他一些成員,具體看注釋就知道了。

2. 硬體方面

了解自己的開發板上的lcd顯示屏的大小,具體支援的哪些特性,比如是否支援雙緩衝等。

把這些相關資訊,在驅動編寫的時候,進行對應的賦值。

【如何寫framebuffer的lcd驅動】

主要是實現linux的framebuffer框架下的,一些函式,最基本的一些就是,以linux核心中的s3c2410舉例,在s3c2410fb.c中,有個對應的結構體: 

static struct fb_ops s3c2410fb_ops = ; 

可以看到,這裡,將自己實現的那些對framebuffer的操作函式,包括設定lcd的引數,剪下,拷貝,清空等,賦值給那個結構體變數,這樣上層framebuffer框架中的函式呼叫的時候,就會呼叫你自己實現的那些函式了。

有些函式,如fb_pan_display等,如果你沒有實現,那麼系統就會呼叫上層框架中預設實現的函式來去做對應的操作。

上層的預設的函式實現在 drivers/video/fbmem.c中。相關具體的細節,感興趣的自己去看吧。 

關於fb驅動中的probe函式,在insmod對應驅動後執行,主要就是一些初始化,其中就包括了上面提到的幾個全域性變數,結構體的初始化,比如此例中的s3c2410fb_probe()中:

fbinfo->fix.type          = fb_type_packed_pixels; 

fbinfo->fix.type_aux          = 0; 

fbinfo->fix.xpanstep          = 0; 

fbinfo->fix.ypanstep          = 0; 

fbinfo->fix.ywrapstep        = 0; 

fbinfo->fix.accel        = fb_accel_none; 

fbinfo->var.nonstd      = 0; 

fbinfo->var.activate           = fb_activate_now; 

fbinfo->var.accel_flags     = 0; 

fbinfo->var.vmode      = fb_vmode_noninterlaced; 

設定了fb和var的各自屬性,是fb_activate_now 立即啟用型別,fb_vmode_noninterlaced非互動模式(不支援雙緩衝?)等等。

本人目前了解到的就是這麼多,歡迎其他高手指出不妥之處和互相交流。

【參考資料】

what is the framebuffer?

console programming howto - 7. framebuffer

linux framebuffer driver writing howto

frame buffer device驅動程式

(green-waste)

Linux下Redis下安裝

redis安裝 檢查是否安裝redis ps ef grep redis2.檢查gcc服務是否安裝成功 rpm qa grep gcc注 安裝成功則顯示 mkdir redis5.解壓redis安裝包 tar zxvf redis 2.8.17 tar.gz c usr local redis 解壓...

Linux下程式設計

windows下我的環境為 windows10 vs2015 opencv3.4.0 opencv3.4.0 contrib python linux下我的環境為 ubuntu16004 也有ubuntu1804 opencv3.4.0 opencv3.4.0 contrib python gnu ...

linux下萬用字元

萬用字元是一類鍵盤字元,有星號 和問號 當查詢檔案呀資料夾時,可以使用它來代替乙個或多個真正字元 當不知道真正字元或者不想建入完整名字時,常常使用萬用字元代替乙個或多個真正字元。星號 可以使用星號代替0個或多個字元。如果正在查詢以aew開頭的乙個檔案,但不記得檔名其餘部分,可以輸入aew,查詢以ae...