生活随笔
收集整理的這篇文章主要介紹了
【Linux】FrameBuffer操作入门
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
所有的這些操作,都是在控制臺界面下,root登錄。
一,先變一個魔法
???????? $ cat /dev/fb0?> sreensnap????? /*獲取一屏的數(shù)據(jù)*/ ?
???????? $ clear???????????????????????????????????????? /*清楚屏幕的輸出*/
???????? $ cat sreensnap > /dev/fb0 ? ? /*將剛才的屏幕數(shù)據(jù)顯示*/
二,操作/dev/fb0?
??????? 1)查看/dev/fb0 的信息
[html]?view plaincopy
#include?<unistd.h>?? #include?<stdio.h>?? #include?<fcntl.h>?? #include?<linux/fb.h>?? #include?<sys/mman.h>?? #include?<stdlib.h>?? ?? int?main?()??? {?? ?????int?fp=0;?? ?????struct?fb_var_screeninfo?vinfo;?? ?????struct?fb_fix_screeninfo?finfo;?? ?????fp?=?open?("/dev/fb0",O_RDWR);?? ?? ?????if?(fp?<?0){?? ??????printf("Error?:?Can?not?open?framebuffer?device/n");?? ??????exit(1);?? ?????}?? ?? ?????if?(ioctl(fp,FBIOGET_FSCREENINFO,&finfo)){?? ??????printf("Error?reading?fixed?information/n");?? ??????exit(2);?? ?????}?? ??????? ?????if?(ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){?? ??????printf("Error?reading?variable?information/n");?? ??????exit(3);?? ?????}?? ?? ?????printf("The?mem?is?:%d\n",finfo.smem_len);?? ?????printf("The?line_length?is?:%d\n",finfo.line_length);?? ?????printf("The?xres?is?:%d\n",vinfo.xres);?? ?????printf("The?yres?is?:%d\n",vinfo.yres);?? ?????printf("bits_per_pixel?is?:%d\n",vinfo.bits_per_pixel);?? ?????close?(fp);?? }??
??????? 2)改變屏幕上某一個點的顏色
[html]?view plaincopy
#include?<unistd.h>?? #include?<stdio.h>?? #include?<stdlib.h>?? #include?<fcntl.h>?? #include?<linux/fb.h>?? #include?<sys/mman.h>?? ?? int?main?()??? {?? ?????int?fp=0;?? ?????struct?fb_var_screeninfo??vinfo;?? ?????struct?fb_fix_screeninfo??finfo;?? ?????long?screensize=0;?? ?????char?*fbp?=?0;?? ?????int?x?=?0,?y?=?0;?? ?????long?location?=?0;?? ?????fp?=?open?("/dev/fb0",O_RDWR);?? ?? ?????if?(fp?<?0)?? ?????{?? ??????????printf("Error?:?Can?not?open?framebuffer?device/n");?? ??????????exit(1);?? ?????}?? ?? ?????if?(ioctl(fp,FBIOGET_FSCREENINFO,&finfo))?? ?????{?? ??????????printf("Error?reading?fixed?information/n");?? ??????????exit(2);?? ?????}?? ??????? ?????if?(ioctl(fp,FBIOGET_VSCREENINFO,&vinfo))?? ?????{?? ??????????printf("Error?reading?variable?information/n");?? ??????????exit(3);?? ?????}?? ?? ??????screensize?=?vinfo.xres?*?vinfo.yres?*?vinfo.bits_per_pixel?/?8;?? ?????/*這就是把fp所指的文件中從開始到screensize大小的內(nèi)容給映射出來,得到一個指向這塊空間的指針*/?? ?????fbp?=(char?*)?mmap?(0,?screensize,?PROT_READ?|?PROT_WRITE,?MAP_SHARED,?fp,0);?? ?????if?((int)?fbp?==?-1)?? ?????{?? ????????printf?("Error:?failed?to?map?framebuffer?device?to?memory./n");?? ????????exit?(4);?? ?????}?? ?????/*這是你想畫的點的位置坐標,(0,0)點在屏幕左上角*/?? ?????x?=?100;?? ?????y?=?100;?? ?????location?=?x?*?(vinfo.bits_per_pixel?/?8)?+?y??*??finfo.line_length;?? ?? ?????*(fbp?+?location)?=?100;??/*?藍色的色深?*/??/*直接賦值來改變屏幕上某點的顏色*/?? ?????*(fbp?+?location?+?1)?=?15;?/*?綠色的色深*/???? ?????*(fbp?+?location?+?2)?=?200;?/*?紅色的色深*/???? ?????*(fbp?+?location?+?3)?=?0;??/*?是否透明*/??? ?? ?????munmap?(fbp,?screensize);?/*解除映射*/?? ?????close?(fp);????/*關(guān)閉文件*/?? ?????return?0;?? ?? }??
三,framebuffer 內(nèi)部結(jié)構(gòu)
? ? 數(shù)據(jù)結(jié)構(gòu):framebuffer 設(shè)備很大程度上依靠了下面四個數(shù)據(jù)結(jié)構(gòu)。這三個結(jié)構(gòu)在fb.h 中聲明。
?????????????????????? Struct fb_var_screeninfo?? //用來描述圖形卡的特性的。通常是被用戶設(shè)置的。
?????????????????????? Struct fb_fix_screeninfo??? //?定義了圖形卡的硬件特性, 是不能改變的,用戶選定了哪一個圖形卡,那么它的硬件特性也就定下來了。
?????????????????????? Struct fb_info????????????????????? //定義了當前圖形卡framebuffer 設(shè)備的獨立狀態(tài),一個圖形卡可能有兩個framebuffer, 在這種情況下,就需要兩個fb_info 結(jié)構(gòu)。這個結(jié)構(gòu)是唯一在內(nèi)核空間可見的。
? ??
???
? ??1)fb_var_screeninfo解析
?
[html]?view plaincopy
struct?fb_var_screeninfo?{?? ????__u32?xres;?/*?visible?resolution?*/?? ????__u32?yres;?? ?? ????__u32?xres_virtual;?/*?virtual?resolution?*/?? ????__u32?yres_virtual;?? ?? ????__u32?xoffset;?/*?offset?from?virtual?to?visible?*/?? ????__u32?yoffset;?/*?resolution?*/?? ?? ????__u32?bits_per_pixel;?/*?guess?what?*/?? ????__u32?grayscale;?/*?!=?0?Graylevels?instead?of?colors*/?? ?? ????struct?fb_bitfield?red;?/*bitfield?in?fb?mem?if?true?color,?*/?? ????struct?fb_bitfield?green;?/*else?only?length?is?significant?*/?? ????struct?fb_bitfield?blue;?? ????struct?fb_bitfield?transp;?/*transparency?*/?? ?? ????__u32?nonstd;?????/*?!=?0?Non?standard?pixel?format?*/?? ????__u32?activate;?/*?see?FB_ACTIVATE_*?*/?? ?? ????__u32?height;?/*?height?of?picture?in?mm???*/?? ????__u32?width;?/*?width?of?picture?in?mm????*/?? ?? ????__u32?accel_flags;?/*?acceleration?flags?(hints)?*/?? ?? ????/*?Timing:?All?values?in?pixclocks,?except?pixclock?(of?course)?*/?? ?? ????__u32?pixclock;?/*?pixel?clock?in?ps?(pico?seconds)?*/?? ?? ????__u32?left_margin;?/*?time?from?sync?to?picture?*/?? ????__u32?right_margin;?/*?time?from?picture?to?sync?*/?? ????__u32?upper_margin;?/*?time?from?sync?to?picture?*/?? ????__u32?lower_margin;?? ?? ????__u32?hsync_len;?/*?length?of?horizontal?sync?*/?? ????__u32?vsync_len;?/*?length?of?vertical?sync?*/?? ?? ????__u32?sync;?/*?see?FB_SYNC_*?*/?? ????__u32?vmode;?/*?see?FB_VMODE_*?*/?? ?? ????__u32?reserved[6];?/*?Reserved?for?future?compatibility*/?? ?? };??
前幾個成員決定了分辨率。
??????? ?? xres和yres是在屏幕上可見的實際分辨率,
????????? xres-virtual決定了構(gòu)建屏幕時視頻卡讀取屏幕內(nèi)存的方式。
????????? bits_per_pixel 設(shè)為1,2,4,8,16,24或32來改變顏色深度
??????? 2)? fb_fix_screeninfo
[html]?view plaincopy
struct?fb_fix_screeninfo?{?? ?? ????char?id[16];?/*?identification?string?eg?"TT?Builtin"?*/?? ?? ????unsigned?long?smem_start;?/*?Start?of?frame?buffer?mem?*/?? ?? ????/*?(physical?address)?*/?? ?? ????__u32?smem_len;?/*?Length?of?frame?buffer?mem?*/?? ?? ????__u32?type;?/*?see?FB_TYPE_*?*/?? ?? ????__u32?type_aux;?/*?Interleave?for?interleaved?Planes?*/?? ?? ????__u32?visual;?/*?see?FB_VISUAL_*?*/?? ?? ????__u16?xpanstep;?/*?zero?if?no?hardware?panning?*/?? ?? ????__u16?ypanstep;?/*?zero?if?no?hardware?panning?*/?? ?? ????__u16?ywrapstep;?/*?zero?if?no?hardware?ywrap?*/?? ?? ????__u32?line_length;?/*?length?of?a?line?in?bytes?*/?? ?? ????unsigned?long?mmio_start;?/*?Start?of?Memory?Mapped?I/O?*/?? ?? ????/*?(physical?address)?*/?? ?? ????__u32?mmio_len;?/*?Length?of?Memory?Mapped?I/O?*/?? ?? ????__u32?accel;?/*?Type?of?acceleration?available?*/?? ?? ????__u16?reserved[3];?/*?Reserved?for?future?compatibility?*/?? ?? };??
????????????????? 3) 顯示說明
【雙顯示器例子】
? ? ? ? ?? 一個例子,可能就是雙顯示,最近剛剛看到實際某開發(fā)者的系統(tǒng),就是兩個顯示器,鼠標移動超過單個顯示器,到最右邊的時候,就跑到另一個顯示器了。對于常常用多系統(tǒng)或者需要打開很多東西的開發(fā)人員,這個功能很實用。
? ??????? 幀緩沖可以用于?頁面交換page flipping(也常叫做?雙緩沖double buffering),許多游戲都是采用此技術(shù),以實現(xiàn)更流暢的視頻輸出,以便用戶獲得更好的游戲體驗。此技術(shù)也被用于3D圖形加速。
【雙緩沖的主要實現(xiàn)原理】
? ? ? ? ? 假如你的顯示器是VGA模式,640×400,也就是虛擬的分辨率是640X800,也就是800線(每一行的數(shù)據(jù),稱為一條線,也就是640X1的數(shù)據(jù)了)。800線的數(shù)據(jù)存儲于Framebuffer,而實際的顯示內(nèi)容,只是400線,
???????? Linux內(nèi)核中的Framebuffer模型中,對應(yīng)有個變量yoffset,就是表示的這個具體的縱坐標,默認是0,所以顯示的內(nèi)容就是,0-399線,由于和實際顯示 頁面大小等同,所以此處可以簡稱為第一幀。
???????? 如果yoffset改變了,比如此例中變?yōu)?00,那就是顯示剩余的部分,400-799線。此處簡稱為第二幀。
? ? ? ???在系統(tǒng)顯示第一幀的時候,系統(tǒng)在后臺悄悄地準備第二幀的數(shù)據(jù),所以,等第一幀顯示完成,多數(shù)時候,第二幀的數(shù)據(jù)也準備好了,就可以直接顯示,同時系統(tǒng)又在準備接下來的一幀的數(shù)據(jù),這樣就可以大大提高顯示效率。
【平滑地滾動頁面的實現(xiàn)原理】
? ? ? ? ?? 同上,在顯示完第一幀數(shù)據(jù)的時候,也就是0-399線的時候,將yoffset設(shè)置為1,就可以顯示1-400線的數(shù)據(jù)了,顯示完成后,再設(shè)置yoffset為2,就顯示2-401線的數(shù)據(jù),這樣,就可以一點點地,平滑地顯示整個滾動畫面了。其實也就是畫面在垂直方向的滾動。其中yoffset的增加,可以使用定時器,各個一段時間,比如10us,增加1,系統(tǒng)自動會更新顯示對應(yīng)的內(nèi)容,這樣我們所看到的內(nèi)容就是滾動的畫面了。
? ??????? 此外,Linux中的Framebuffer模型中,提供了一些ioctl功能,給定一些參數(shù),然后系統(tǒng)可以實現(xiàn)對應(yīng)的功能,其中有個參數(shù)就是FBIOPAN_DISPLAY。具體也就是類似如下調(diào)用:
? ? ? ? ? ioctl (framebuffer_handler, FBIOPAN_DISPLAY, &variable_info);
? ? ? ? ? 而這個調(diào)用,如果顯示不支持framebuffer的雙緩沖的話,那么其framebuffer的緩沖大小,就是和物理上的顯示器大小等同,那么對應(yīng)的yoffset也就不會像雙緩沖那樣變化了。
? ??????? 也就是說,如果顯卡/顯示屏控制器不支持雙緩沖,那么yoffset就應(yīng)該一直為0,并且在運行時候,也不應(yīng)該改變,也不應(yīng)該去給FBIOPAN_DISPLAY的參數(shù)調(diào)用ioctl。
總結(jié)
以上是生活随笔為你收集整理的【Linux】FrameBuffer操作入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。