Android原生(Native)C(JNI/NDK)开发之二:framebuffer篇

来源:互联网 发布:mac os x leopard下载 编辑:程序博客网 时间:2024/05/21 15:47

为方便以后学习和工作,现转载一批文章,方便以后使用。

 

来源:http://blog.sina.com.cn/s/blog_4a0a39c30100auh9.html   作者:风子

 

如对Android原生(Natvie)C开发还任何疑问,请参阅《Android原生(Native)C开发之一:环境搭建篇》:http://blog.sina.com.cn/s/blog_4a0a39c30100auh9.html  (或者http://android-sz.iteye.com/blog/828246)

 

虽然现在能通过交叉环境编译程序,并push到Android上执行,但那只是console台程序,是不是有些单调呢?下面就要看如何通过Linux的 framebuffer 技术在Android上画图形,关于Linux的framebuffer技术,这里就不再详细讲解了,请大家google一下。

 

操作framebuffer的主要步骤如下:

1、打开一个可用的FrameBuffer设备;
2、通过mmap调用把显卡的物理内存空间映射到用户空间;
3、更改内存空间里的像素数据并显示;

4、退出时关闭framebuffer设备。

 

下面的这个例子简单地用framebuffer画了一个渐变的进度条,代码 framebuf.c 如下:

C代码  收藏代码
  1. #include <unistd.h>  
  2. #include <stdio.h>  
  3. #include <fcntl.h>  
  4. #include <linux/fb.h>  
  5. #include <sys/mman.h>  
  6. inline static unsigned short int make16color(unsigned char r, unsigned char g, unsigned char b)  
  7. {  
  8.     return (  
  9.  (((r >> 3) & 31) << 11) |  
  10.  (((g >> 2) & 63) << 5)  |  
  11.   ((b >> 3) & 31)        );  
  12. }  
  13. int main() {  
  14.     int fbfd = 0;  
  15.     struct fb_var_screeninfo vinfo;  
  16.     struct fb_fix_screeninfo finfo;  
  17.     long int screensize = 0;  
  18.  char *fbp = 0;  
  19.     int x = 0, y = 0;  
  20.     int guage_height = 20, step = 10;  
  21.     long int location = 0;  
  22.     // Open the file for reading and writing  
  23.     fbfd = open("/dev/graphics/fb0", O_RDWR);  
  24.     if (!fbfd) {  
  25.         printf("Error: cannot open framebuffer device.\n");  
  26.         exit(1);  
  27.     }  
  28.     printf("The framebuffer device was opened successfully.\n");  
  29.     // Get fixed screen information  
  30.     if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {  
  31.         printf("Error reading fixed information.\n");  
  32.         exit(2);  
  33.     }  
  34.     // Get variable screen information  
  35.     if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {  
  36.         printf("Error reading variable information.\n");  
  37.         exit(3);  
  38.     }  
  39.  printf("sizeof(unsigned short) = %d\n"sizeof(unsigned short));  
  40.     printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );  
  41.  printf("xoffset:%d, yoffset:%d, line_length: %d\n", vinfo.xoffset, vinfo.yoffset, finfo.line_length );  
  42.     // Figure out the size of the screen in bytes  
  43.     screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;;  
  44.     // Map the device to memory  
  45.     fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,  
  46.                        fbfd, 0);  
  47.     if ((int)fbp == -1) {  
  48.         printf("Error: failed to map framebuffer device to memory.\n");  
  49.         exit(4);  
  50.     }  
  51.     printf("The framebuffer device was mapped to memory successfully.\n");  
  52.  //set to black color first  
  53.  memset(fbp, 0, screensize);  
  54.     //draw rectangle  
  55.     y = (vinfo.yres - guage_height) / 2 - 2;       // Where we are going to put the pixel  
  56.     for (x = step - 2; x < vinfo.xres - step + 2; x++) {  
  57.         location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +  
  58.                        (y+vinfo.yoffset) * finfo.line_length;  
  59.         *((unsigned short int*)(fbp + location)) = 255;  
  60.     }  
  61.     y = (vinfo.yres + guage_height) / 2 + 2;       // Where we are going to put the pixel  
  62.     for (x = step - 2; x < vinfo.xres - step + 2; x++) {  
  63.         location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +  
  64.                        (y+vinfo.yoffset) * finfo.line_length;  
  65.         *((unsigned short int*)(fbp + location)) = 255;  
  66.     }  
  67.     x = step - 2;  
  68.     for (y = (vinfo.yres - guage_height) / 2 - 2; y < (vinfo.yres + guage_height) / 2 + 2; y++) {  
  69.         location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +  
  70.                        (y+vinfo.yoffset) * finfo.line_length;  
  71.         *((unsigned short int*)(fbp + location)) = 255;  
  72.     }  
  73.     x = vinfo.xres - step + 2;  
  74.     for (y = (vinfo.yres - guage_height) / 2 - 2; y < (vinfo.yres + guage_height) / 2 + 2; y++) {  
  75.         location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +  
  76.                        (y+vinfo.yoffset) * finfo.line_length;  
  77.         *((unsigned short int*)(fbp + location)) = 255;  
  78.     }  
  79.     // Figure out where in memory to put the pixel  
  80.     for ( x = step; x < vinfo.xres - step; x++ ) {  
  81.         for ( y = (vinfo.yres - guage_height) / 2; y < (vinfo.yres + guage_height) / 2; y++ ) {  
  82.             location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +  
  83.                        (y+vinfo.yoffset) * finfo.line_length;  
  84.             if ( vinfo.bits_per_pixel == 32 ) {  
  85.                 *(fbp + location) = 100;        // Some blue  
  86.                 *(fbp + location + 1) = 15+(x-100)/2;     // A little green  
  87.                 *(fbp + location + 2) = 200-(y-100)/5;    // A lot of red  
  88.                 *(fbp + location + 3) = 0;      // No transparency  
  89.             } else { //assume 16bpp  
  90.                 unsigned char b = 255 * x / (vinfo.xres - step);  
  91.                 unsigned char g = 255;     // (x - 100)/6 A little green  
  92.                 unsigned char r = 255;    // A lot of red  
  93.                 unsigned short int t = make16color(r, g, b);  
  94.                 *((unsigned short int*)(fbp + location)) = t;  
  95.             }  
  96.         }  
  97.   //printf("x = %d, temp = %d\n", x, temp);  
  98.         //sleep to see it  
  99.         usleep(200);  
  100.     }  
  101.     //clean framebuffer  
  102.     munmap(fbp, screensize);  
  103.     close(fbfd);  
  104.     return 0;  
  105. }  

 

注意,在Android环境,framebuffer设备不是象linux一样的 /dev/fb0,而是 /dev/graphics/fb0 

fbfd = open("/dev/graphics/fb0", O_RDWR);

打开framebuffer设备,

    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
                       fbfd, 0);

 

将设备map到一块内存,然后就可以操作这块内存空间来显示你想画的图形了。

最后别忘了关闭设备:

    munmap(fbp, screensize);
    close(fbfd);

 

效果图如下: