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 */fb_var_screeninfo包含了很多具體驅動執行時候的,framebuffer,即顯示內容的具體屬性,包括實際的顯示器上可見的解析度大小,xres和yres,framebuffer的解析度大小xres_virtual和 yres_virtual,如果是上面提到的雙緩衝,那麼這個解析度就是可以顯示的解析度的兩倍了。struct fb_bitfield ;
struct fb_var_screeninfo ;
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;設定了fb和var的各自屬性,是fb_activate_now 立即啟用型別,fb_vmode_noninterlaced非互動模式(不支援雙緩衝?)等等。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;
本人目前了解到的就是這麼多,歡迎其他高手指出不妥之處和互相交流。
【參考資料】
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...