【Linux】FrameBuffer操作入門

來源:互聯網
上載者:User

所有的這些操作,都是在控制台介面下,root登入。

一,先變一個魔法

         $ cat /dev/fb0 > sreensnap      /*擷取一屏的資料*/  

         $ clear                                         /*清楚螢幕的輸出*/

         $ cat sreensnap > /dev/fb0     /*將剛才的螢幕資料顯示*/

二,操作/dev/fb0

        1)查看/dev/fb0 的資訊

#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)改變螢幕上某一個點的顏色

#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大小的內容給映射出來,得到一個指向這塊空間的指標*/ 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);    /*關閉檔案*/ return 0;}

三,framebuffer 內部結構

    資料結構:framebuffer 裝置很大程度上依靠了下面四個資料結構。這三個結構在fb.h 中聲明。

                       Struct fb_var_screeninfo   //用來描述圖形卡的特性的。通常是被使用者佈建的。

                       Struct fb_fix_screeninfo    // 定義了圖形卡的硬體特性, 是不能改變的,使用者選定了哪一個圖形卡,那麼它的硬體特性也就定下來了。

                       Struct fb_info                      //定義了當前圖形卡framebuffer 裝置的獨立狀態,一個圖形卡可能有兩個framebuffer, 在這種情況下,就需要兩個fb_info 結構。這個結構是唯一在核心空間可見的。
   
  
    1)fb_var_screeninfo解析

 

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決定了構建螢幕時視訊卡讀取螢幕記憶體的方式。

          bits_per_pixel 設為1,2,4,8,16,24或32來改變色彩深度

        2)  fb_fix_screeninfo

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) 顯示說明


【雙顯示器例子】

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

          幀緩衝可以用於 頁面交換page flipping(也常叫做 雙緩衝double buffering),許多遊戲都是採用此技術,以實現更流暢的視頻輸出,以便使用者獲得更好的遊戲體驗。此技術也被用於3D圖形加速。

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

          假如你的顯示器是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。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.