在 Android 下使用 FrameBuffer 绘图

来源:互联网 发布:什么是js文件 编辑:程序博客网 时间:2024/05/16 09:47
#include
// 操作FrameBuffer 设备文件所需头文件 */
#include
#include
// 使用 mmap 与munmap 函数所需头文件 */
#include

#include

// 生成 RGB565像素值 */
inlinestatic unsigned short int 
make_rgb565(unsigned char r, 
           unsigned charg, 
           unsigned char b )
{
    // r 1.右移 3 位是为了保留字节高 5 位有效,
        2.位与 31是为了将除低 5 位以外的位值变为零,
        3.左移 11位是为了将 r 的移到两字节返回值的高 15 ~ 11 位上去 */
    // g 1.右移 2 位是为了保留字节高 6 位有效,
        2.位与 63是为了将除低 6 位以外的位值变为零,
        3.左移 5 位是为了将 r 的移到两字节返回值的中 10 ~  5位上去 */
    // b 1.右移3 位是为了保留字节高 5 位有效,
        2.位与 31是为了将除低 5 位以外的位值变为零 */
    // 最后将 r、g 、b 三个值组成两字节返回值返回 */
    return ( (( ( r >> 3 ) & 31 ) << 11)| 
           ( ( ( g >> 2 ) & 63) << 5 ) |
             ( ( b>> 3 ) & 31 ) );
}

//<--将< 替换为 * --
//这个结构描述了显示卡的特性
structfb_var_screeninfo
{
    __u32xres;              // visibleresolution
    __u32yres;
    __u32xres_virtual;       // virtualresolution
    __u32yres_virtual;
    __u32xoffset;            // offsetfrom virtual to visible resolution
    __u32yoffset;
    __u32bits_per_pixel;     // guess what
    __u32grayscale;          // != 0 Gray levels insteadof colors
    structfb_bitfield red;    // bitfieldin fb mem if true color,
    structfb_bitfield green;  // else only length issignificant
    structfb_bitfield blue;
    structfb_bitfield transp; // transparency
    __u32nonstd;            // != 0 Non standard pixel format
    __u32activate;           // seeFB_ACTIVATE_* 
    __u32height;            // height of picture in mm
    __u32width;             // width of picture in mm
    __u32accel_flags;        // acceleration flags(hints)
   
    // Timing:All values in pixclocks, except pixclock (of course)
    __u32pixclock;     // pixel clock inps (pico seconds)
    __u32left_margin;  // time from sync topicture
    __u32right_margin; // time from picture to sync
    __u32upper_margin; // time from sync to picture
    __u32lower_margin;
    __u32hsync_len;    // length ofhorizontal sync
    __u32vsync_len;    // length ofvertical sync 
    __u32sync;        // see FB_SYNC_* 
    __u32vmode;       // see FB_VMODE_* 
    __u32reserved[6];  // Reserved for futurecompatibility
};

//这个结构在显卡被设定模式后创建,它描述显示卡的属性,并且系统运行时不能被修改;
// 比如FrameBuffer 内存的起始地址。
//它依赖于被设定的模式,当一个模式被设定后,内存信息由显示卡硬件给出,内存的位置等信息就不可以修改。
structfb_fix_screeninfo 
{
    charid[16];            // identification string eg "TTBuiltin"
    unsignedlong smem_start; // Start of frame buffer mem
   
    //physical address
    __u32smem_len;          // Length of frame buffermem
    __u32type;             // see FB_TYPE_* 
    __u32type_aux;          // Interleave for interleavedPlanes
    __u32visual;            // seeFB_VISUAL_*
    __u16xpanstep;          // zero if no hardwarepanning
    __u16ypanstep;          // zero if no hardwarepanning
    __u16ywrapstep;         // zero if no hardwareywrap
    __u32line_length;       // length of a line inbytes
    unsignedlong mmio_start; // Start of Memory Mapped I/O
   
    //physical address
    __u32mmio_len;    // Length of MemoryMapped I/O
    __u32accel;       //Type of acceleration available
    __u16reserved[3]; // Reserved for future compatibility
};


//描述设备无关的颜色映射信息。
// 可以通过FBIOGETCMAP 和 FBIOPUTCMAP 对应的 ioctl 操作设定或获取颜色映射信息。
structfb_cmap 
{
    __u32start;   // First entry
    __u32 len;    // Number ofentries
    __u16*red;    // Redvalues
    __u16*green;
    __u16*blue;
    __u16*transp; // transparency, can be NULL
};


//定义当显卡的当前状态;
// fb_info结构仅在内核中可见,在这个结构中有一个 fb_ops 指针,指向驱动设备工作所需的函数集。
structfb_info 
{
    charmodename[40];          // default video mode
    kdev_tnode;
    intflags;
    int open;                 // Has this been open already ?
    #defineFBINFO_FLAG_MODULE 1  // Low-level driver is amodule
    structfb_var_screeninfo var; // Current var
    structfb_fix_screeninfo fix; // Current fix
    structfb_monspecs monspecs;  // Current Monitorspecs
    structfb_cmap cmap;         // Currentcmap
    structfb_ops *fbops;
    char*screen_base;          // Virtual address
    structdisplay *disp;        // initial displayvariable
    structvc_data *display_fg;   // Console visible on thisdisplay
    charfontname[40];          // default font name
   devfs_handle_t devfs_handle;  // Devfs handle fornew name
   devfs_handle_t devfs_lhandle; // Devfs handle for compat.symlink
    int(*changevar)(int);       // tell console var haschanged
    int(*switch_con)(int, struct fb_info*);
   
    // tell fbto switch consoles
    int(*updatevar)(int, struct fb_info*);
   
    // tell fbto update the vars
    void(*blank)(int, struct fb_info*); // tell fb to (un)blank thescreen
   
    // arg =0: unblank
    // arg> 0: VESA level (arg-1)
    // Fakepalette of 16 colors and the cursor's color for non palettemode
    void*pseudo_palette; 
   
    // Fromhere on everything is device dependent
    void*par;
};


// 用户应用可以使用ioctl() 系统调用来操作设备,这个结构就是用一支持 ioctl() 的这些操作的。
structfb_ops 
{
    //open/release and usage marking
    structmodule *owner;
    int(*fb_open)( struct fb_info *info, 
                       int     user);
    int(*fb_release)( struct fb_info *info, 
                         int     user );
   
    // get nonsettable parameters
    int(*fb_get_fix)( struct fb_fix_screeninfo*fix, 
                         int             con, 
                   struct fb_info         *info );
                   
    // getsettable parameters
    int(*fb_get_var)( struct fb_var_screeninfo*var, 
                         int             con, 
                         struct fb_info   *info);
                         
    // setsettable parameters
    int(*fb_set_var)( struct fb_var_screeninfo*var, 
                         int             con,
                   struct fb_info         *info );
                   
    // getcolormap
    int(*fb_get_cmap)( struct fb_cmap*cmap, 
                          int    kspc, 
                          int    con, 
                    struct fb_info *info );
   
    // setcolormap
    int(*fb_set_cmap)( struct fb_cmap*cmap, 
                          int    kspc, 
                          int    con, 
                    struct fb_info *info );
   
    // pandisplay (optional)
    int(*fb_pan_display)( struct fb_var_screeninfo*var, 
                             int            con, 
                       structfb_info          *info );
   
    // performfb specific ioctl (optional)
    int(*fb_ioctl)( struct inode  *inode, 
                  struct file  *file, 
                  unsignedint   cmd, 
                  unsignedlong   arg, 
                  int          con, 
                  structfb_info *info );
   
    // performfb specific mmap
    int(*fb_mmap)( struct fb_info      *info, 
                 struct file        *file, 
                 struct vm_area_struct *vma);
   
    // switchto/from raster image mode
    int(*fb_rasterimg)( struct fb_info*info, 
                           int     start );
};
*/


int 
main() 
{
    // 本函数返回值*/
    intiResult = 0;
    //FrameBuffer设备文件描述符 */
    intfdFrameBuffer = -1;
    //屏幕的可变信息结构变量 */
    structfb_var_screeninfo sScreenInfoVar;
    //屏幕的固定信息结构变量 */
    structfb_fix_screeninfo sScreenInfoFix;
    // 显存字节大小*/
    unsignedlong ulVideoMemByteSize = 0;
    // 内存映射地址*/
    unsignedchar* pucMapMem = 0;
    // for循环行计数器 */
    unsignedchar ucForRow = 0;
    // for循环列计数器 */
    unsignedchar ucForCol = 0;
    //屏幕行首地址指针 */
    unsignedchar* pucRow = 0;
    // W 字模*/
    unsignedshort int uiWFont[6][6] = { 63488,    0,     0, 0,    0,    63488, 
                                  63488,     0,63488, 63488, 0,    63488,
                                  63488,     0,63488, 63488, 0,    63488,
                                  63488,     0,63488, 63488, 0,    63488,
                                  63488, 63488,    0, 0,    63488, 63488,
                                      0, 63488,    0, 0,    63488, 0 };


    // Z 字模*/
    unsignedshort int uiZFont[6][6] = { 2016, 2016, 2016, 2016, 2016,2016, 
                                  2016, 2016, 2016, 2016, 2016, 2016,
                                     0,   0,   0,  2016,2016,    0,
                                     0,   0, 2016, 2016,   0,   0,
                                     0, 2016, 2016, 2016, 2016,2016,
                                  2016, 2016, 2016, 2016, 2016, 2016};


    // H 字模*/
    unsignedshort int uiHFont[6][6] = { 31, 31,  0, 0, 31, 31, 
                                  31, 31,  0, 0, 31, 31,
                                  31, 31, 31, 31, 31, 31,
                                  31, 31, 31, 31, 31, 31,
                                  31, 31,  0, 0, 31, 31,
                                  31, 31,  0, 0, 31, 31 };


    // N 字模*/
    unsignedshort int uiNFont[6][6] = { 63488,    0,     0, 0,    63488,63488, 
                                  63488, 63488,    0, 0,    63488, 63488,
                                  63488, 63488, 63488, 0,    63488, 63488,
                                  63488, 63488, 63488, 63488, 63488,63488,
                                  63488, 63488,    0, 63488, 63488, 63488,
                                  63488, 63488,    0, 0,    63488, 63488 };


    // S 字模*/
    unsignedshort int uiSFont[6][6] = {    0,   0, 2016, 2016, 2016,2016, 
                                     0, 2016,   0,    0,   0, 2016,
                                  2016,    0,   0,   0,    0,   0,
                                     0, 2016, 2016, 2016,   0,   0,
                                  2016,    0,   0,   0, 2016,   0,
                                  2016, 2016, 2016, 2016, 2016, 2016};


    // C 字模*/
    unsignedshort int uiCFont[6][6] = {  0, 0, 31,  0, 31,31, 
                                   0, 31, 31,  0, 31,31,
                                  31, 31,  0,  0, 0,  0,
                                  31, 31,  0,  0, 0,  0,
                                   0, 31, 31, 31, 31, 31,
                                   0,  0, 31, 31, 31, 31};
   
    do //非循环,只是为了减少分支缩进 */
   {
       // 1.可读写方式打开 framebuffer 设备文件*/
       fdFrameBuffer = open("/dev/graphics/fb0", O_RDWR );
       if ( -1 == fdFrameBuffer)
       {
          printf( "Error: Don't Open FrameBufferDevice.\n" );
          iResult = -1;
          break;
       }


       // ioctl参数一:设备文件描述符;
              参数二:命令编码,如:
                  FBIOGET_FSCREENINFO -得到屏幕的固定信息(如:显示内存大小) 
                  FBIOGET_VSCREENINFO -得到屏幕的可变信息(如:分辨率、象素结构、每扫描线的字节宽度)
                  FBIOPUT_VSCREENINFO - 设置屏幕的可变信息
                  FBIOGETCMAP        -获取颜色映射信息
                  FBIOPUTCMAP        -设置颜色映射信息
              参数三:与命令编码对应的结构变量指针:
                  FBIOGET_FSCREENINFO                    对应fb_fix_screeninfo 结构体; 
                  FBIOGET_VSCREENINFO 和 FBIOPUT_VSCREENINFO 对应fb_var_screeninfo 结构体;
                  FBIOGETCMAP        和FBIOPUTCMAP        对应 fb_cmap 结构体;
       */
       // 2.得到屏幕的固定信息*/
       if ( -1 == ioctl(fdFrameBuffer, 
                     FBIOGET_FSCREENINFO, 
                      &sScreenInfoFix ))
       {
          printf( "Error: Don't Read Out Fix ScreenInformation.\n" );
          iResult = -2;
          break;
       }


       // 3.得到屏幕的可变信息*/
       if ( -1 == ioctl(fdFrameBuffer, 
                     FBIOGET_VSCREENINFO, 
                      &sScreenInfoVar )) 
       {
          printf( "Error: Don't Read Out Var ScreenInformation.\n" );
          iResult = -3;
          break;
       }
      
       // 显存所需字节大小 = ( 屏幕宽 * 屏幕高 *每像素位数 ) / 8 */
       printf( "xres = %d\nyres =%d\nbits_per_pixel = %d\n", 
             sScreenInfoVar.xres, 
             sScreenInfoVar.yres, 
             sScreenInfoVar.bits_per_pixel );
       printf("xoffset:%d\nyoffset:%d\nline_length:%d\n", 
             sScreenInfoVar.xoffset, 
             sScreenInfoVar.yoffset, 
             sScreenInfoFix.line_length );
       // Android屏幕坐标系如下:
         --------- xres
         |
         |
         |
        yres
       */
ulVideoMemByteSize = ( sScreenInfoVar.xres *sScreenInfoVar.yres * sScreenInfoVar.bits_per_pixel ) /8;
      
       // 将 FrameBuffer设备文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写 */
       pucMapMem = (unsignedchar*)mmap( 0, // 指向欲对应的内存起始地址,
                                        通常设为 0,代表让系统自动选定地址 */
                                   // 将文件中多少字节对应到内存 */
                                  ulVideoMemByteSize, 
                                   // 映射区域可被 读取 和 写入 */
                                   PROT_READ |PROT_WRITE, 
                                   // 映射区域的写入数据会复制回文件内,
                                     而且允许其他映射该文件的进程共享 */
                                   MAP_SHARED, 
                                   // FrameBuffer 文件描述符 */
                                   fdFrameBuffer, 
                                   // 为文件映射的偏移量,
                                     通常设置为0,代表从文件最前方开始对应,
                                      必须是分页大小的整数倍*/
                                   0 );
       if ( -1 == (int)pucMapMem) 
       {
          printf( "Error: Map FrameBuffer Device File toMemory Failed.\n" );
          iResult = -4;
          break;
       }
      
       // 清屏 - 黑屏 */
       memset(pucMapMem, 0,ulVideoMemByteSize);
      
       for ( ucForRow =0;
            ucForRow < 6;
            ucForRow++ )
       {
          // 屏幕第n行首像素对应显存地址 = 行号(基于零) * 一行像素个数 * 每个像素字节个数*/
          pucRow = pucMapMem+ 
                  ( ucForRow* 
                   sScreenInfoVar.xres* 
                   ( sScreenInfoVar.bits_per_pixel / 8 ));
          // W */ 
          memcpy( pucRow, uiWFont + ucForRow, 12);
          
          // Z */
          memcpy( pucRow + 15, uiZFont + ucForRow, 12);
          
          // H */
          memcpy( pucRow + 30, uiHFont + ucForRow, 12);
          
          // N */ 
          memcpy( pucRow + 45, uiNFont + ucForRow, 12);
          
          // S */
          memcpy( pucRow + 60, uiSFont + ucForRow, 12);
          
          // C */
          memcpy( pucRow + 75, uiCFont + ucForRow, 12 );         
       }
   
    }while( 0);


    if ( 0 !=pucMapMem )
   {
       // 解除内存映射 */
       munmap( pucMapMem,          // 映射内存起始地址*/
             ulVideoMemByteSize ); // 欲取消的内存大小 */
       pucMapMem = 0;
   }
   
    if ( -1 !=fdFrameBuffer )
   {
       // 关闭文件 */
       close( fdFrameBuffer);
       fdFrameBuffer =-1;
   }
   
    returniResult;

}

0 0
原创粉丝点击