直接操作android的/dev/graphics/fb0
看到网友们写了自己的一些对/dev/graphics/fb0操作的例子,自己也跟着模仿了下,效果如下:
这是在android电视上的效果,代码如下:
1 #include <stdlib.h> 2 #include <unistd.h> 3 #include <stdio.h> 4 #include <fcntl.h> 5 #include <linux/fb.h> 6 #include <linux/kd.h> 7 #include <sys/mman.h> 8 #include <sys/ioctl.h> 9 #include <sys/time.h> 10 #include <string.h> 11 #include <errno.h> 12 13 #define FRAMEBUFFER "/dev/graphics/fb0" 14 15 struct fb_var_screeninfo vinfo; 16 struct fb_fix_screeninfo finfo; 17 char *frameBuffer = 0; 18 19 //打印fb驱动中fix结构信息 20 void printFixedInfo() 21 { 22 printf("Fixed screen info:\n" 23 "\t id: %s\n" 24 "\t smem_start: 0x%lx\n" 25 "\t smem_len: %d\n" 26 "\t type: %d\n" 27 "\t type_aux: %d\n" 28 "\t visual: %d\n" 29 "\t xpanstep: %d\n" 30 "\t ypanstep: %d\n" 31 "\t ywrapstep: %d\n" 32 "\t line_length: %d\n" // 33 "\t mmio_start: 0x%lx\n" 34 "\t mmio_len: %d\n" 35 "\t accel: %d\n" 36 "\n", finfo.id, finfo.smem_start, finfo.smem_len, finfo.type, 37 finfo.type_aux, finfo.visual, finfo.xpanstep, finfo.ypanstep, 38 finfo.ywrapstep, finfo.line_length, finfo.mmio_start, 39 finfo.mmio_len, finfo.accel); 40 } 41 42 //打印fb驱动中var结构信息 43 void printVariableInfo() 44 { 45 printf("Variable screen info:\n" 46 "\t xres: %d\n" 47 "\t yres: %d\n" 48 "\t xres_virtual: %d\n" 49 "\t yres_virtual: %d\n" 50 "\t xoffset: %d\n" 51 "\t yoffset: %d\n" 52 "\t bits_per_pixel: %d\n" //每一个像素点 占用内存空间32 为4个字节 53 "\t grayscale: %d\n" 54 "\t red: offset: %d - length : %d - msb_right : %d\n" 55 "\t green: offset: %d - length : %d - msb_right : %d\n" 56 "\t blue: offset: %d - length : %d - msb_right : %d\n" 57 "\t transp: offset: %d - length : %d - msb_right : %d\n" 58 "\t nonstd: %d\n" 59 "\t activate: %d\n" 60 "\t height: %d\n" 61 "\t width: %d\n" 62 "\t accel_flags: 0x%x\n" 63 "\t pixclock: %d\n" 64 "\t left_margin: %d\n" 65 "\t right_margin: %d\n" 66 "\t upper_margin: %d\n" // 67 "\t lower_margin: %d\n" ///帧切换:从绘图到同步之间的延迟 68 "\t hsync_len: %d\n" 69 "\t vsync_len: %d\n" 70 "\t sync: %d\n" 71 "\t vmode: %d\n" 72 "\n", 73 vinfo.xres, vinfo.yres, vinfo.xres_virtual, 74 vinfo.yres_virtual, vinfo.xoffset, vinfo.yoffset, 75 vinfo.bits_per_pixel, vinfo.grayscale, 76 vinfo.red.offset, vinfo.red.length, vinfo.red.msb_right, 77 vinfo.green.offset, vinfo.green.length, vinfo.green.msb_right, 78 vinfo.blue.offset, vinfo.blue.length, vinfo.blue.msb_right, 79 vinfo.transp.offset, vinfo.transp.length, vinfo.transp.msb_right, 80 vinfo.nonstd, vinfo.activate, vinfo.height, vinfo.width, vinfo.accel_flags, 81 vinfo.pixclock, vinfo.left_margin, vinfo.right_margin, 82 vinfo.upper_margin, vinfo.lower_margin, vinfo.hsync_len, 83 vinfo.vsync_len, vinfo.sync, vinfo.vmode); 84 } 85 //图片//画大小为width*height的同色矩阵,8alpha+8reds+8greens+8blues 86 void drawRect_rgb32(int x0, int y0, int width, int height, int color) 87 { 88 const int bytesPerPixel = 4; //每一个像素点 占用内存空间 89 // stride表示一行有多少个像素 90 const int stride = finfo.line_length / bytesPerPixel; //finfo.line_length 以字节数表示,就是屏幕的宽度 91 92 int *dest = (int *) (frameBuffer) + (x0 + vinfo.xoffset) + (y0 + vinfo.yoffset) * stride ; 93 94 int x, y; 95 for (y = 0; y < height; ++y) 96 { 97 for (x = 0; x < width; ++x) 98 { 99 dest[x] = color; 100 } 101 dest += stride; 102 } 103 } 104 105 void draw(int x0, int y0, int width, int height, int color) 106 { 107 const int bytesPerPixel = 4; //每一个像素点 占用内存空间 108 // stride表示一行有多少个像素 109 const int stride = finfo.line_length / bytesPerPixel; //finfo.line_length 以字节数表示,就是屏幕的宽度 110 111 int *dest = (int *) (frameBuffer) + (x0 + vinfo.xoffset) + (y0 + vinfo.yoffset) * stride ; 112 113 int i = 0; 114 int x, y; 115 for (y = 0; y < height; ++y) 116 { 117 for (x = 0; x < width; ++x) 118 { 119 i++; 120 dest[x] = img[i]; 121 if(i == 4229358) 122 i = 0; 123 } 124 dest += stride; 125 } 126 } 127 128 129 //画大小为width*height的同色矩阵,5reds+6greens+5blues 130 void drawRect_rgb16(int x0, int y0, int width, int height, int color) 131 { 132 const int bytesPerPixel = 2; 133 const int stride = finfo.line_length / bytesPerPixel; 134 const int red = (color & 0xff0000) >> (16 + 3); 135 const int green = (color & 0xff00) >> (8 + 2); 136 const int blue = (color & 0xff) >> 3; 137 const short color16 = blue | (green << 5) | (red << (5 + 6)); 138 139 short *dest = (short *) (frameBuffer) + (y0 + vinfo.yoffset) * stride 140 + (x0 + vinfo.xoffset); 141 142 int x, y; 143 for (y = 0; y < height; ++y) 144 { 145 for (x = 0; x < width; ++x) 146 { 147 dest[x] = color16; 148 } 149 dest += stride; 150 } 151 } 152 153 //画大小为width*height的同色矩阵,5reds+5greens+5blues 154 void drawRect_rgb15(int x0, int y0, int width, int height, int color) 155 { 156 const int bytesPerPixel = 2; 157 const int stride = finfo.line_length / bytesPerPixel; 158 const int red = (color & 0xff0000) >> (16 + 3); 159 const int green = (color & 0xff00) >> (8 + 3); 160 const int blue = (color & 0xff) >> 3; 161 const short color15 = blue | (green << 5) | (red << (5 + 5)) | 0x8000; 162 163 short *dest = (short *) (frameBuffer) + (y0 + vinfo.yoffset) * stride 164 + (x0 + vinfo.xoffset); 165 166 int x, y; 167 for (y = 0; y < height; ++y) 168 { 169 for (x = 0; x < width; ++x) 170 { 171 dest[x] = color15; 172 } 173 dest += stride; 174 } 175 } 176 177 void drawRect(int x0, int y0, int width, int height, int color) 178 { 179 switch (vinfo.bits_per_pixel) 180 { 181 case 32: 182 drawRect_rgb32(x0, y0, width, height, color); 183 break; 184 case 16: 185 drawRect_rgb16(x0, y0, width, height, color); 186 break; 187 case 15: 188 drawRect_rgb15(x0, y0, width, height, color); 189 break; 190 default: 191 printf("Warning: drawRect() not implemented for color depth %i\n", 192 vinfo.bits_per_pixel); 193 break; 194 } 195 } 196 197 198 int main(int argc, char **argv) 199 { 200 const char *devfile = FRAMEBUFFER; 201 long int screensize = 0; 202 int fbFd = 0; 203 204 fbFd = open(devfile, O_RDWR); 205 if (fbFd == -1) 206 { 207 perror("Error: cannot open framebuffer device"); 208 exit(1); 209 } 210 211 //获取finfo信息并显示 212 if (ioctl(fbFd, FBIOGET_FSCREENINFO, &finfo) == -1) 213 { 214 perror("Error reading fixed information"); 215 exit(2); 216 } 217 printFixedInfo(); 218 //获取vinfo信息并显示 219 if (ioctl(fbFd, FBIOGET_VSCREENINFO, &vinfo) == -1) 220 { 221 perror("Error reading variable information"); 222 exit(3); 223 } 224 printVariableInfo(); 225 226 screensize = finfo.smem_len; ///dev/graphics/fb0 的大小,也就是内存大小 227 228 frameBuffer = (char *) mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbFd, 0); 229 if (frameBuffer == MAP_FAILED ) 230 { 231 perror("Error: Failed to map framebuffer device to memory"); 232 exit(4); 233 } 234 235 memset(frameBuffer, 0, screensize); 236 237 printf("Will draw 3 rectangles on the screen,\n"); 238 //void drawRect_rgb32(int x0, int y0, int width, int height, int color) 239 240 //drawRect(vinfo.xres / 8 , vinfo.yres / 8 , vinfo.xres / 4, vinfo.yres / 4, 0xffff0000); 241 //drawRect(vinfo.xres * 3 / 8, vinfo.yres * 3 / 8, vinfo.xres / 4, vinfo.yres / 4, 0xff00ff00); 242 //drawRect(vinfo.xres * 5 / 8, vinfo.yres * 5 / 8, vinfo.xres / 4, vinfo.yres / 4, 0xff0000ff) 243 while(1) 244 { 245 //注意,起始坐标x,y的值只能是小于 vinfo.xres ,vinfo.yres ,宽度和高度不能超过 vinfo.xres,vinfo.yres,减去起始坐标x,y的差,否则会出错。 246 //draw(vinfo.xres*3/4,vinfo.yres*3/4, vinfo.xres*1/4,vinfo.yres*1/4 , 0xff); 247 //sleep(3); 248 249 drawRect(0 ,0 , vinfo.xres ,vinfo.yres , 0xff00ff00); //绿色 250 sleep(1); 251 drawRect(vinfo.xres*1/4 ,vinfo.yres*1/4 , vinfo.xres*3/4 ,vinfo.yres*3/4 , 0xff000000); //黑色 252 sleep(1); 253 drawRect(vinfo.xres/2 ,vinfo.yres/2 , vinfo.xres/2 ,vinfo.yres/2 , 0xff0000ff); //红色 254 sleep(5); 255 } 256 257 printf(" Done.\n"); 258 259 munmap(frameBuffer, screensize); //解除内存映射,与mmap对应 260 close(fbFd); 261 return 0; 262 }
由于上传有些问题,所以最后一个图片的部分没有上传,不过不影响其他效果。
代码中有几个自定义判断的swich函数,其中我的机器识别的是32真彩的所以只调用了 drawRect_rgb32(x0, y0, width, height, color);这个函数。
图像显示其实是直接对frameBuffer这个映射的内存进行操作,这个frameBuffer这个指针对应的映射地址其实就是显存,每一个一像素就是4个字节,可以从代码中看到。有什么不对的地方欢迎指出来,希望对你有所帮助。