framebuffer應用程式設計實踐

weixin_30639719發表於2020-04-05

framebuffer的使用主要包括4個部分:

(1):首先需要開啟裝置檔案 /dev/fb0。

(2):獲取裝置的資訊。包括可變資訊和不可變資訊,分別使用兩個結構體來進行封裝,這兩個結構體在 <linux/fb.h> 標頭檔案中定義,所以需要先包含這個標頭檔案。

(3):如果有需要可以對可變的引數進行修改。

(4):做mmap對映。我們需要將驅動中給LCD分配的視訊記憶體空間對映到我們的應用層來,這樣才能在應用層對視訊記憶體進行操作。

(5):填充framebuffer。也就是上面說的操作視訊記憶體。

 

 

資料結構: (include\linux\fb.h)

struct  fb_fix_screeninfo:(不可變資訊)

 1 struct fb_fix_screeninfo {
 2     char id[16];               // 標識字串
 3     unsigned long smem_start;       // FB視訊記憶體的起始地址(實體地址) 
 4                     
 5     __u32 smem_len;                // FB視訊記憶體的長度
 6     __u32 type;            /* see FB_TYPE_*        */
 7     __u32 type_aux;            
 8     __u32 visual;            /* see FB_VISUAL_*        */ 
 9     __u16 xpanstep;            /* zero if no hardware panning  */
10     __u16 ypanstep;            /* zero if no hardware panning  */
11     __u16 ywrapstep;        /* zero if no hardware ywrap    */
12     __u32 line_length;        // 一行的長度(以位元組為單位)
13     unsigned long mmio_start;    /* Start of Memory Mapped I/O   */
14                     /* (physical address) */
15     __u32 mmio_len;            /* Length of Memory Mapped I/O  */
16     __u32 accel;            /* Indicate to driver which    */
17                     /*  specific chip/card we have    */
18     __u16 reserved[3];        /* Reserved for future compatibility */
19 };

 

 

struct  fb_var_screeninfo:(可變資訊)

 1 struct fb_var_screeninfo {
 2     __u32 xres;             // LCD的水平畫素大小
 3     __u32 yres;             // LCD的垂直畫素大小
 4     __u32 xres_virtual;     // LCD的虛擬水平畫素大小
 5     __u32 yres_virtual;     // LCD的虛擬垂直畫素大小
 6     __u32 xoffset;          // 水平畫素偏移量
 7     __u32 yoffset;          // 垂直畫素偏移量
 8 
 9     __u32 bits_per_pixel;            // 畫素深度bpp
10     __u32 grayscale;        /* != 0 Graylevels instead of colors */
11 
12     struct fb_bitfield red;        /* bitfield in fb mem if true color, */
13     struct fb_bitfield green;    /* else only length is significant */
14     struct fb_bitfield blue;
15     struct fb_bitfield transp;    /* transparency            */    
16 
17     __u32 nonstd;            /* != 0 Non standard pixel format */
18 
19     __u32 activate;            /* see FB_ACTIVATE_*        */
20 
21     __u32 height;           // LCD的物理高度 mm
22     __u32 width;            // LCD的物理寬度 mm
23 
24     __u32 accel_flags;        /* (OBSOLETE) see fb_info.flags */
25 
27     __u32 pixclock;            // 畫素時鐘
28 
29     /* 下面是六個時序引數 */
30     __u32 left_margin;        /* time from sync to picture    */
31     __u32 right_margin;        /* time from picture to sync    */  
32     __u32 upper_margin;        /* time from sync to picture    */ 
33     __u32 lower_margin;
34     __u32 hsync_len;        /* length of horizontal sync    */
35     __u32 vsync_len;        /* length of vertical sync    */
36     
37     __u32 sync;            /* see FB_SYNC_*        */
38     __u32 vmode;            /* see FB_VMODE_*        */
39     __u32 rotate;            /* angle we rotate counter clockwise */
40     __u32 reserved[5];        /* Reserved for future compatibility */
41 };

 

相關巨集定義: (include\linux\fb.h)

#define FBIOGET_VSCREENINFO 0x4600      // 傳給ioctl函式,用來獲取可變引數資訊,返回的是一個fb_var_screeninfo結構體
#define FBIOPUT_VSCREENINFO 0x4601      // 傳給ioctl函式,用來設定可變引數,需要傳入一個fb_var_screeninfo結構體,
#define FBIOGET_FSCREENINFO 0x4602      // 傳給ioctl函式,用來獲取不可變資訊,返回的是一個fb_fix_screeninfo結構體

 

/*************************************************************************************************************/

測試程式碼:

平臺:s5pv210 

核心版本:2.6.35.7

/*************************************************************************************************************/

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <linux/fb.h>
  6 #include <sys/ioctl.h>
  7 #include <sys/mman.h>
  8 
  9 
 10 #define  FILE  "/dev/fb0"      // 裝置檔案
 11 
 12 
 13 /*計算機顏色16進製表示符*/
 14 #define  WHITE    0xFFFFFF     //白色
 15 #define  RED      0xFF0000     //紅色
 16 #define  GREEN    0x00FF00     //綠色
 17 #define  BLUE     0x0000FF     //藍色
 18 #define  YELLOW   0xFFFF00     //黃色
 19 #define  BLACK    0x000000     //黑色
 20 #define  AQNA     0xAFDFE4     //水色
 21 #define  NAVE     0x23238E     //海軍藍
 22 #define  ORANGE   0xFF7F00     //橙色
 23 #define  PURPLE   0x871F78     //紫色
 24 #define  Qioke    0x6B4226     //巧克力色
 25 
 26 struct fb_fix_screeninfo finfo = {0};       // 不可變資訊結構體
 27 struct fb_var_screeninfo vinfo = {0};       // 可變資訊結構體
 28 static volatile unsigned int *pMap = NULL;  // 用來指向mmap對映得到的虛擬地址
 29 
 30 
 31 static inline void lcd_draw_pixel(unsigned int x, unsigned int y, unsigned int color);
 32 static void lcd_draw_background(unsigned int color);
 33 void lcd_draw_lline(const unsigned int x, const unsigned int y, const unsigned int length,   // 注意這個函式引數太多了,不應該這樣設計,我們應該把這些引數放在一個結構體中,把結構體變數的指標傳進來即可,這樣效率高
 34                      const unsigned int width, const unsigned int color);
 35                      
 36 static void lcd_draw_image(const unsigned char *pData);      // pData是一個圖片的資料陣列: 這裡是 1024*600 畫素24位真彩色格式的圖片,,陣列的元素個數: 1024*600*3   我們需要將連續的3個1個位元組長度的資料合成一個24位資料
 37 
 38 
 39 int main(void)
 40 {
 41     int fd = 0;
 42     
 43     /* 開啟檔案得到檔案描述符 */
 44     fd = open(FILE, O_RDWR);
 45     if (0 > fd) {
 46         perror("open error");
 47         return -1;
 48     }
 49     printf("%s 開啟成功\n", FILE);
 50     
 51     /* 操作檔案 */
 52     if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo)) {
 53         perror("ioctl error");
 54         close(fd);
 55         return -1;
 56     }    
 57 
 58     if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo)) {
 59         perror("ioctl error");
 60         close(fd);
 61         return -1;
 62     }
 63         
 64       // 列印資訊
 65     printf("不可變資訊smem_start = 0x%x\n", finfo.smem_start);    
 66     printf("不可變資訊smem_len = %ld\n", finfo.smem_len);    
 67     printf("可變資訊xres = %d, yres = %d\n", vinfo.xres, vinfo.yres);
 68     printf("可變資訊xres_virtual = %d, yres_virtual = %d\n", vinfo.xres_virtual, vinfo.yres_virtual);
 69     printf("可變資訊xoffset = %d, yoffset = %d\n", vinfo.xoffset, vinfo.yoffset);
 70     
 71     /* 進行mmap對映 */
 72     pMap = mmap(NULL, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 73     if (NULL == pMap) {
 74         perror("mmap error");
 75         return -1;
 76     }
 77     
 78     /* 背景填充 */
 79     lcd_draw_background(WHITE);
 80     
 81     /* 關閉檔案 */
 82     close(fd);    
 83     
 84     return 0;
 85 }
 86 
 87 /*填充畫素點*/
 88 static inline void lcd_draw_pixel(unsigned int x, unsigned int y, unsigned int color)
 89 {
 90     *(unsigned int *)((unsigned int)pMap + (vinfo.xres*x + y)*4) = color;
 91 }
 92 
 93 /*填充LCD背景*/
 94 static void lcd_draw_background(unsigned int color)
 95 {
 96      unsigned int i = 0;
 97      unsigned int j = 0;
 98      
 99      for (i = 1; i <= vinfo.yres; ++i)
100      {
101          for (j = 0; j <= vinfo.xres; ++j)
102              lcd_draw_pixel(i, j, color);
103      }
104 }
105 
106 //  畫線函式
107 void lcd_draw_lline(const unsigned int x, const unsigned int y, const unsigned int length,
108                      const unsigned int width, const unsigned int color)              
109 {
110     volatile unsigned int i = 0;
111     volatile unsigned int j = 0;
112     
113     for (i = x; i < width+x; i++)
114     {
115         for (j = y; j < length+y; j++)
116         {
117             lcd_draw_pixel(i, j, color);
118         }
119     }    
120 } 
121 
122 
123 //  24位真彩色圖片顯示函式
124 static void lcd_draw_image(const unsigned char *pData)
125 {
126     unsigned int i = 0;
127     unsigned int j = 0;
128     unsigned int color = 0;
129     unsigned int p = 0;
130     
131     for (i = 0; i < vinfo.yres; i++)
132     {
133         for (j = 0; j < vinfo.xres; j++)
134         {
135             color = (pData[p+0] << 16) | (pData[p+1] << 8) | (pData[p+2] << 0);
136             lcd_draw_pixel(i, j, color);
137             p = p+3;
138         }
139     }
140 }

 

轉載於:https://www.cnblogs.com/deng-tao/p/6079704.html

相關文章