linux framebuffer 例子 (2)

把前面一篇的例了加强一下。上一个例子打开了fbdev设备并一次性地向里面写了一屏的数据,把整个屏幕画成红色。但这个时候如果用Alt+Fi切换一下虚拟终端,画出的红色马上消失。这是因为切换终端之后,这个终端也要维护屏幕的输出,重绘的framebuffer。
  DirectFB和PicoGL在使用framebuffer的时候都避免了这种情况的发生,方法就是操作tty设备。原理很简单,就是打开一个新的终端tty设备,把它激活,并设为图形模式,让它独占framebuffer设备,然后再输出图形,这样,即使用户按Alt+Fi也无法切换终端,framebuffer就不会被重刷,从而实现了稳定的输出。
  那么打开哪一个新的tty设备呢?先用ioctl(ConsoleFD, VT_OPENQRY, &vtnumber)查一下当前打开的虚拟终端数量,一般的发行版都是打开6个,即tty1~tty6,这个可以在/etc/inittab里面控制。另外,tty0是系统自动打开的,但不用于用户登录,所以查询的结果是一共打开7个,vtnumber=7,这个数字也就是下一次可用的终端号,即tty7。

代码如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <fcntl.h>
  5. #include <linux/fb.h>
  6. #include <linux/vt.h>
  7. #include <linux/kd.h>
  8. #include <sys/mman.h>
  9. #include <asm/ioctls.h>
  10. static int OriginalVT = -1;
  11. struct fb_fix_screeninfo FixedInfo;
  12. struct fb_var_screeninfo OrigVarInfo;
  13. static int FrameBufferFD = -1;
  14. void *FrameBuffer = (void *) -1;
  15. static int ConsoleFD = -1;
  16. #define SIGUSR1 10
  17. void openFBDEV(void) {
  18.     int vtnumber, ttyfd;
  19.     char ttystr[1000];
  20.     /* open the framebuffer device */
  21.     FrameBufferFD = open("/dev/fb0", O_RDWR);
  22.     if (FrameBufferFD < 0) {
  23.         fprintf(stderr, "Error opening /dev/fb0/n");
  24.         exit(1);
  25.     }
  26.     /* Get the fixed screen info */
  27.     if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
  28.         fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed/n");
  29.         exit(1);
  30.     }
  31.     /* get the variable screen info */
  32.     if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
  33.         fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed/n");
  34.         exit(1);
  35.     }
  36.        
  37.     if (FixedInfo.visual != FB_VISUAL_TRUECOLOR && FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
  38.         fprintf(stderr, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo./n", FixedInfo.visual);
  39.         exit(1);
  40.     }

  41.     /*
  42.      * fbdev says the frame buffer is at offset zero, and the mmio region
  43.      * is immediately after.
  44.      */
  45.     /* mmap the framebuffer into our address space */
  46.     FrameBuffer = (void *) mmap(0, /* start */
  47.         FixedInfo.smem_len, /* bytes */
  48.         PROT_READ | PROT_WRITE, /* prot */
  49.         MAP_SHARED, /* flags */
  50.         FrameBufferFD, /* fd */
  51.         0 /* offset */);
  52.     if (FrameBuffer == (void *) - 1) {
  53.         fprintf(stderr, "error: unable to mmap framebuffer/n");
  54.         exit(1);
  55.     }
  56.     /* open /dev/tty0 and get the vt number */
  57.     if ((ConsoleFD = open("/dev/tty0", O_WRONLY, 0)) < 0) {
  58.         fprintf(stderr, "error opening /dev/tty0/n");
  59.         exit(1);
  60.     }
  61.     if (ioctl(ConsoleFD, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
  62.         fprintf(stderr, "error: couldn't get a free vt/n");
  63.         exit(1);
  64.     }
  65.     close(ConsoleFD);
  66.     ConsoleFD = -1;
  67.      /* open the console tty */
  68.      sprintf(ttystr, "/dev/tty%d", vtnumber);  /* /dev/tty1-64 */
  69.      ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
  70.      if (ConsoleFD < 0) {
  71.              fprintf(stderr, "error couldn't open console fd %d/n", vtnumber);
  72.          exit(1);
  73.      }
  74.      /* save current vt number */
  75.      {
  76.        struct vt_stat vts;
  77.        if (ioctl(ConsoleFD, VT_GETSTATE, &vts) == 0)
  78.              OriginalVT = vts.v_active;
  79.      }
  80.      /* disconnect from controlling tty */
  81.      ttyfd = open("/dev/tty", O_RDWR);
  82.      if (ttyfd >= 0) {
  83.                 ioctl(ttyfd, TIOCNOTTY, 0);
  84.         close(ttyfd);
  85.      }
  86.      /* some magic to restore the vt when we exit */
  87.      {
  88.        struct vt_mode vt;
  89.        if (ioctl(ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
  90.               fprintf(stderr,"ioctl VT_ACTIVATE/n");
  91.        if (ioctl(ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
  92.               fprintf(stderr,"ioctl VT_WAITACTIVE/n");
  93.        
  94.        if (ioctl(ConsoleFD, VT_GETMODE, &vt) < 0) {
  95.               fprintf(stderr, "error: ioctl VT_GETMODE/n");
  96.           exit(1);
  97.        }
  98.        vt.mode = VT_PROCESS;
  99.        vt.relsig = SIGUSR1;
  100.        vt.acqsig = SIGUSR1;
  101.        if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
  102.                fprintf(stderr, "error: ioctl(VT_SETMODE) failed/n");
  103.            exit(1);
  104.        }
  105.      }
  106.      /* go into graphics mode */
  107.      if (ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
  108.              fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed/n");
  109.          exit(1);
  110.      }
  111. }

  112. void closeFBDEV(void) {
  113.         struct vt_mode VT;
  114.     /* restore original variable screen info */
  115.     if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo)) {
  116.             fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed)/n");
  117.         exit(1);
  118.     }
  119.     munmap(FrameBuffer, FixedInfo.smem_len);
  120.     close(FrameBufferFD);
  121.     /* restore text mode */
  122.     ioctl(ConsoleFD, KDSETMODE, KD_TEXT);
  123.     /* set vt */
  124.     if (ioctl(ConsoleFD, VT_GETMODE, &VT) != -1) {
  125.             VT.mode = VT_AUTO;
  126.         ioctl(ConsoleFD, VT_SETMODE, &VT);
  127.     }
  128.     /* restore original vt */
  129.     if (OriginalVT >= 0) {
  130.             ioctl(ConsoleFD, VT_ACTIVATE, OriginalVT);
  131.         OriginalVT = -1;
  132.     }
  133.     close(ConsoleFD);
  134. }

  135. int main() {
  136.     openFBDEV();
  137.     fprintf(stderr, "openFBDEV finish/n");
  138.     memset(FrameBuffer, 128, FixedInfo.smem_len);
  139.     sleep(5);
  140.     closeFBDEV();
  141.     fprintf(stderr, "closeFBDEV finish/n");
  142.     return 0;
  143. }


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt is a popular cross-platform framework for developing graphical user interfaces (GUI) and applications. It provides support for Linux framebuffer, which allows you to create GUI applications that can run directly on the Linux framebuffer without the need for an X server. To use Qt with Linux framebuffer, you can follow these general steps: 1. Install the required dependencies: Make sure you have the necessary libraries and development packages installed on your Linux system. This may include framebuffer-related libraries like `libdrm` and `libgbm`. 2. Configure Qt with framebuffer support: When building Qt from source, you can enable framebuffer support by passing the `-qt-libinput` flag to the `configure` script. For example: ``` ./configure -qt-libinput ``` 3. Build your Qt application: Once Qt is configured with framebuffer support, you can build your application using the `qmake` and `make` commands as usual. Make sure to set the appropriate target platform, such as `linuxfb`. 4. Run your Qt application on the Linux framebuffer: After building your application, you can run it directly on the Linux framebuffer by setting the appropriate environment variables. For example: ``` export QT_QPA_PLATFORM=linuxfb export QT_QPA_FB_TTY=/dev/fb0 ./your_application ``` By following these steps, you should be able to develop and run Qt applications using the Linux framebuffer as the target platform. Keep in mind that framebuffer support may vary depending on your specific Linux distribution and hardware setup.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值