/* Put a zoneplate texture on the framebuffer. * * This does work on (my) Linux console, but in X11 it has no visible * effect. */ #include #include #include #include #include #include #include int main() { int fb = open("/dev/fb0", O_RDWR); if (fb < 0) { perror("open /dev/fb0"); return -1; } struct fb_fix_screeninfo fix; if (ioctl(fb, FBIOGET_FSCREENINFO, &fix) < 0) { perror("FBIOGET_FSCREENINFO"); return -1; } int pagesize = sysconf(_SC_PAGESIZE); if (fix.smem_start & (pagesize-1)) { fprintf(stderr, "smem_start %x not %d-aligned\n", (int)fix.smem_start, pagesize); return -1; } if (fix.type != FB_TYPE_PACKED_PIXELS) { fprintf(stderr, "framebuffer type %u isn’t FB_TYPE_PACKED_PIXELS\n", (unsigned)fix.type); return -1; } if (fix.visual != FB_VISUAL_TRUECOLOR) { fprintf(stderr, "visual %u isn’t FB_VISUAL_TRUECOLOR\n", (unsigned)fix.visual); return -1; } struct fb_var_screeninfo var; if (ioctl(fb, FBIOGET_VSCREENINFO, &var) < 0) { perror("FBIOGET_VSCREENINFO"); return -1; } /* e.g. https://www.raspberrypi.org/forums/viewtopic.php?t=29844 suggests that we can enable page-flipping double-buffering with var.yres_virtual = var.yres * 2; ioctl(fb, FBIOPUT_VSCREENINFO, &var); and then to flip: var.activate = FB_ACTIVATE_VBL; var.yoffset = offset; ioctl(fb, FBIOPUT_VSCREENINFO, &var); or at least the author cleverca22 claimed that worked on Android and the RasPi fork of Android in 2013. Also in https://lb.raspberrypi.org/forums/viewtopic.php?t=30720&start=25 hglm claimed that it worked on the RasPi in 2015, but required kernel patches, although now https://github.com/hglm/dgl is using `FBIOPAN_DISPLAY` instead. https://bugs.launchpad.net/qemu/+bug/1777672 describes a different Pi-3-specific way to do page-flipping on Linux in 2018, and explains how QEMU support for emulating it was added. https://unix.stackexchange.com/questions/33596/no-framebuffer-device-how-to-enable-it mentions the DirectFB library. https://github.com/toradex/cairo-fb-examples/blob/master/rectangles/rectangles.c#L51 also uses `FBIOPAN_DISPLAY`, and also `FBIO_WAITFORVSYNC`. */ if (var.bits_per_pixel != 32) { fprintf(stderr, "bits_per_pixel is %d, not 32\n", (int)var.bits_per_pixel); return -1; } if (var.xres_virtual >= 32768 || var.yres_virtual >= 32768) { fprintf(stderr, "%u×%u resolution is unlikely\n", (unsigned)var.xres_virtual, (unsigned)var.yres_virtual); return -1; } char *fb_buf = mmap(NULL, fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); if (!fb_buf || (intptr_t)fb_buf == -1) { perror("mmap"); return -1; } uint32_t *p = (uint32_t*)fb_buf; uint32_t line_len = var.xres_virtual; for (uint32_t y = 0; y != var.yres_virtual; y++) { for (uint32_t x = 0; x != line_len; x++) { p[x + line_len * y] = x*x + y*y; } } return 0; }