Sometimes, we want to access framebuffer directly.
Here is template and simple description to do this (on Android as an example.)
(Note: This is just template. Some modification may be required according to driver.)
(Below way works on Android 2.3 ~ 4.1 emulator by turning off 'Use Host GPU' option at AVD Manager.)
Things used in this example. (Refer kernel source code for details - comments in code.) linux/fb.h - struct fb_var_screeninfo xres, yres, xres_virtual, yres_virtual, xoffset, yoffset, bits_per_pixel - struct fb_fix_screeninfo smem_len - FBIOGET_FSCREENINFO, FBIOGET_VSCREENINFO, FBIOPUT_VSCREENINFO - FB_ACTIVATE_NOW, FB_ACTIVATE_FORCE See fbmem.c as your starting point of source analysis. ... int fd; struct fb_var_screeninfo vi; struct fb_fix_screeninfo fi; void* bits; int bpp; /* byte per pixel */ int stride; /* size of stride in pixel */ ... /* Open framebuffer */ if(0 > (fd = open("/dev/graphics/fb0", O_RDWR)) { printf("Fail to open fb\n"); return -1; } /* Get fixed information */ if(0 > ioctl(fd, FBIOGET_FSCREENINFO, &fi)) { printf("Fail to get fixed info\n") return -1; } /* Get variable information */ if(0 > ioctl(fd, FBIOGET_VSCREENINFO, &vi)) { printf("Failed to get variable info\n"); return -1; } /* Get raw bits buffer */ if(MAP_FAILED == (bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0))) { printf("Failed to mmap fb\n"); return -1; } /* Calculate useful information */ bpp = vi.bits_per_pixel >> 3; stride = fi.line_length / bpp; ... /* Getting raw-image snapshot of current framebuffer */ void* curbits; /* current framebuffer raw data */ curbits = (unsigned char*)bits + (vi.xoffset + vi.yoffset*vi.xres_virtual)*bpp; memcpy(raw_image_buffer, curbits, vi.yres*stride*bpp); ... /* Modifying directly */ do_something(curbits...); /* change buffer directly... */ /* Refresh buffer manually */ vi.activate |= FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; if(0 > ioctl(fd, FBIOPUT_VSCREENINFO, &vi)) { printf("Failed to refresh\n"); return -1; }
Linux usually use 'double buffer'.
For this, usually,
vi.yres_virtual == vi.yres * 2 vi.yoffset == 0 or vi.yres (0 for 1st buffer, vi.yres for 2nd buffer)
But, it's totally dependent on driver. So, to get portability, we should not assume those.
'Domain > Linux' 카테고리의 다른 글
[Ubuntu] visual effect doens't work with Nvidia driver... (0) | 2011.01.19 |
---|---|
[Linux] Writing input event directly. (0) | 2010.11.29 |
[Ubuntu] alacarte를 사용하지 않고 GNOME desktop menu수정하기. (0) | 2010.11.10 |
[Linux][Prog] Understanding Standard IO (0) | 2010.11.03 |
[Linux] fork in multi-threaded program. (0) | 2010.08.16 |