-
-
Save FredEckert/3425429 to your computer and use it in GitHub Desktop.
/* | |
To test that the Linux framebuffer is set up correctly, and that the device permissions | |
are correct, use the program below which opens the frame buffer and draws a gradient- | |
filled red square: | |
retrieved from: | |
Testing the Linux Framebuffer for Qtopia Core (qt4-x11-4.2.2) | |
http://cep.xor.aps.anl.gov/software/qt4-x11-4.2.2/qtopiacore-testingframebuffer.html | |
*/ | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <fcntl.h> | |
#include <linux/fb.h> | |
#include <sys/mman.h> | |
#include <sys/ioctl.h> | |
int main() | |
{ | |
int fbfd = 0; | |
struct fb_var_screeninfo vinfo; | |
struct fb_fix_screeninfo finfo; | |
long int screensize = 0; | |
char *fbp = 0; | |
int x = 0, y = 0; | |
long int location = 0; | |
// Open the file for reading and writing | |
fbfd = open("/dev/fb0", O_RDWR); | |
if (fbfd == -1) { | |
perror("Error: cannot open framebuffer device"); | |
exit(1); | |
} | |
printf("The framebuffer device was opened successfully.\n"); | |
// Get fixed screen information | |
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) { | |
perror("Error reading fixed information"); | |
exit(2); | |
} | |
// Get variable screen information | |
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) { | |
perror("Error reading variable information"); | |
exit(3); | |
} | |
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); | |
// Figure out the size of the screen in bytes | |
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; | |
// Map the device to memory | |
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); | |
if ((int)fbp == -1) { | |
perror("Error: failed to map framebuffer device to memory"); | |
exit(4); | |
} | |
printf("The framebuffer device was mapped to memory successfully.\n"); | |
x = 100; y = 100; // Where we are going to put the pixel | |
// Figure out where in memory to put the pixel | |
for (y = 100; y < 300; y++) | |
for (x = 100; x < 300; x++) { | |
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + | |
(y+vinfo.yoffset) * finfo.line_length; | |
if (vinfo.bits_per_pixel == 32) { | |
*(fbp + location) = 100; // Some blue | |
*(fbp + location + 1) = 15+(x-100)/2; // A little green | |
*(fbp + location + 2) = 200-(y-100)/5; // A lot of red | |
*(fbp + location + 3) = 0; // No transparency | |
//location += 4; | |
} else { //assume 16bpp | |
int b = 10; | |
int g = (x-100)/6; // A little green | |
int r = 31-(y-100)/16; // A lot of red | |
unsigned short int t = r<<11 | g << 5 | b; | |
*((unsigned short int*)(fbp + location)) = t; | |
} | |
} | |
munmap(fbp, screensize); | |
close(fbfd); | |
return 0; | |
} |
Hey BartekLew,
the location += 4 is commented because it has no actual use, it will be reset the next run anyway. I guess this is a relict of not using the alpha-channel and skipping it for the next calculation of location?!
Your code here will segfault, because you take line_length from finfo, but that is based on x/yres_virtual, which may differ from the normal resolution.
If you switch to xres_virtual, the code will (likely) never segfault.
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
<-- this will give different results each time you run it.
screensize = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
<-- will always work
You can still write in only the "real" part (i have 2 screens diff. resolution) but you need to map it to the virtual resolution or it will segfault.
Can you add example for 1 bits per pixel fb?
This code makes assumptions which may be false:
Probably more
plus, I don't know why
location+=4
is commented. This stuff is generally very hardware/mode specific. Better be careful.There is also another detail, when you run it, the console will override your changes. If you enter graphic mode, you'll get an exclusive access to the framebuffer and the console will come back to the original state when the program closes. Another good thing is that opening TTY will fail in X11 so the user won't be confused that nothing happens. Here's my implementation of a similar program with all above details taken into account:
https://github.com/BartekLew/fblib/tree/fb-example