• 测试framebuffer


    static GGLContext *gr_context = 0;
    static GGLSurface gr_framebuffer[2];
    static unsigned gr_active_fb = 0;
    
    static int gr_fb_fd = -1;
    static int gr_vt_fd = -1;
    
    static struct fb_var_screeninfo vi;
    struct fb_fix_screeninfo fi;
    // 得到framebuffer的相关信息(可变或固定的)
    // 及映射数据区域
    static int get_framebuffer(GGLSurface *fb)
    {
        int fd;
        void *bits;
         //将尝试打开两个位置的设备文件
        fd = open("/dev/graphics/fb0", O_RDWR);
        if (fd < 0) {
            printf("cannot open /dev/graphics/fb0, retrying with /dev/fb0
    ");
            if ((fd = open("/dev/fb0", O_RDWR)) < 0) {
                perror("cannot open /dev/fb0");
                return -1;
            }
        }
        //得到framebuffer的相关信息
        if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
            perror("failed to get fb0 info");
            return -1;
        }
    
        if(ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
            perror("failed to get fb0 info");
            return -1;
        }
        
        dumpinfo(&fi, &vi);
        // kernel缓冲区映射到用户空间
        bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        if(bits == MAP_FAILED) {
            perror("failed to mmap framebuffer");
            return -1;
        }
    
        fb->version = sizeof(*fb);
        fb->width = vi.xres;
        fb->height = vi.yres;
        fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
        fb->data = bits;
        fb->format = GGL_PIXEL_FORMAT_RGB_565;
        // 双缓冲
        fb++;
    
        fb->version = sizeof(*fb);
        fb->width = vi.xres;
        fb->height = vi.yres;
        fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
        fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2);
        fb->format = GGL_PIXEL_FORMAT_RGB_565;
    
        return fd;
    }
    // 这里假设framebuffer是双缓冲,理论上应当判断下
    // 不能直接断定是否双缓冲
    static void set_active_framebuffer(unsigned n)
    {
        if(n > 1) return;
        // framebuffer的缓冲区大小,至少要可以两张图片的容量
        vi.yres_virtual = vi.yres * 2;
        vi.yoffset = n * vi.yres;
        if(ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
            fprintf(stderr,"active fb swap failed!
    ");
        } else
            printf("active buffer: %d
    ", n);
    }
    // 导出framebuffer的相关信息(x, y , bits_per_pixel等)
    static void dumpinfo(struct fb_fix_screeninfo *fi, struct fb_var_screeninfo *vi)
    {
        fprintf(stderr,"vi.xres = %d
    ", vi->xres);
        fprintf(stderr,"vi.yres = %d
    ", vi->yres);
        fprintf(stderr,"vi.xresv = %d
    ", vi->xres_virtual);
        fprintf(stderr,"vi.yresv = %d
    ", vi->yres_virtual);
        fprintf(stderr,"vi.xoff = %d
    ", vi->xoffset);
        fprintf(stderr,"vi.yoff = %d
    ", vi->yoffset);
        fprintf(stderr, "vi.bits_per_pixel = %d
    ", vi->bits_per_pixel);
    
        fprintf(stderr, "fi.line_length = %d
    ", fi->line_length);
    
    }
    int gr_init(void)
    {
        int fd = -1;
        // 不太明白,为什么要打开tty0,测试的时候不执行也没有影响
        if (!access("/dev/tty0", F_OK)) {
            fd = open("/dev/tty0", O_RDWR | O_SYNC);
            if(fd < 0)
                return -1;
    
            if(ioctl(fd, KDSETMODE, (void*) KD_GRAPHICS)) {
                close(fd);
                return -1;
            }
        }
        //初始化,framebuffer 数据结构
        gr_fb_fd = get_framebuffer(gr_framebuffer);
    
        if(gr_fb_fd < 0) {
            if (fd >= 0) {
                ioctl(fd, KDSETMODE, (void*) KD_TEXT);
                close(fd);
            }
            return -1;
        }
    
        gr_vt_fd = fd;
    
            /* start with 0 as front (displayed) and 1 as back (drawing) */
        gr_active_fb = 0;
        set_active_framebuffer(0);
    
        return 0;
    }
    // 退出,关闭文件等
    void gr_exit(void)
    {
        close(gr_fb_fd);
        gr_fb_fd = -1;
    
        if (gr_vt_fd >= 0) {
            ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT);
            close(gr_vt_fd);
            gr_vt_fd = -1;
        }
    }
    int gr_fb_width(void)
    {
        return gr_framebuffer[0].width;
    }
    
    int gr_fb_height(void)
    {
        return gr_framebuffer[0].height;
    }


     

    uint16_t red = 0xf800;
    uint16_t green = 0x07e0;
    uint16_t blue = 0x001f;
    // 在缓冲区上绘制图片,一共四个区域
    |--|--|
    |  |   |
    |--|--|
    |  |   |
    -----
    void draw_grid(int w, int h, uint16_t* loc) {
      int i, j;
      int v;
      int stride = fi.line_length / (vi.bits_per_pixel >> 3);
    
      for (j = 0; j < h/2; j++) {
        for (i = 0; i < w/2; i++)
          loc[i + j*(stride)] = red;
        for (; i < w; i++)
          loc[i + j*(stride)] = green;
      }
      for (; j < h; j++) {
        for (i = 0; i < w/2; i++)
          loc[i + j*(stride)] = blue;
        for (; i < w; i++)
          loc[i + j*(stride)] = 0xffff;
      }
    
    }
    // 清空缓冲区数据都为00,视觉上表现为纯黑色
    void clear_screen(int w, int h, uint16_t* loc)
    {
        int i,j;
        int stride = fi.line_length / (vi.bits_per_pixel >> 3);
    
      for (j = 0; j < h; j++)
        for (i = 0; i < w; i++)
          loc[i + j*(stride)] = 0x0000;
    }


     

    int main(int argc, char **argv) {
      int w;
      int h;
      int id = 0;
      gr_init();
      w = vi.xres;
      h = vi.yres;
      // 清空缓冲区数据都为00
      clear_screen(w, h, (uint16_t *)gr_framebuffer[0].data);
      clear_screen(w, h, (uint16_t *)gr_framebuffer[1].data);
    
      if (argc > 2) {
        w = atoi(argv[1]);
        h = atoi(argv[2]);
      }
    
      if (argc > 3)
          id = !!atoi(argv[3]);
      // 绘制图片
      draw_grid(w, h, (uint16_t *)gr_framebuffer[id].data);
      //显示双缓冲的内容,中间和最后加个sleep(),效果会更明显
      set_active_framebuffer(!id);
      set_active_framebuffer(id);
    
      return 0;
    }





     


     

  • 相关阅读:
    HDU 4632 CF 245H 区间DP(回文)
    Cloud Foundry中 JasperReports service集成
    Graphs and Minimum Cuts(Karger's Min-Cut Algorithm)
    【大盛】HTC one/M7 ROM 最新本地化OrDroid8.2.6 高级、快速设置 永久root 更多自定义 稳定 流畅
    Android开发工具GenyMotion安装和使用方法
    CF 121E Lucky Array 【树状数组】
    [每日一题] OCP1z0-047 :2013-08-02 权限―――分配系统权限
    iOS 应用程序本地化
    Storm系列(十五)架构分析之Executor-Spout
    Ganglia系列(一)安装
  • 原文地址:https://www.cnblogs.com/riasky/p/3458873.html
Copyright © 2020-2023  润新知