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 }