Skip to content

Commit d628c80

Browse files
committed
linux framebuffer device
1 parent 6c907f9 commit d628c80

9 files changed

Lines changed: 155 additions & 0 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ C and C++ minimal examples. Asserts used wherever possible. Hello worlds for coo
4242
1. Utility libraries
4343
1. [Boost](boost/)
4444
1. [glibc](glibc/)
45+
1. [Linux](linux/)
4546
1. GUI
4647
1. [GTK](gtk/)
4748
1. [Open GL](opengl/)

‎linux/Makefile‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../Makefile_many

‎linux/README.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Linux
2+
3+
Programs that use userland exported Linux kernel APIs, e.g. `/dev` filesystem.
4+
5+
Syscalls may be included here if they don't have glibc wrappers.

‎linux/configure‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bash
2+
sudo apt-get update
3+
sudo apt-get install -y libXXX-dev

‎linux/fb.c‎

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
Framebuffer device /dev/fb0
3+
4+
https://en.wikipedia.org/wiki/Linux_framebuffer
5+
6+
To run this, you must:
7+
8+
- be on a TTY, e.g. Ctrl + Alt + F2 on Ubuntu
9+
- add yourself to the `video` group (the group of /dev/fb0 on Ubuntu 16.04) with `sudo usermod -aG video "$USER"`,
10+
logout and login again , or use sudo
11+
- have kernel support, I think with `CONFIG_FB=y` and related options.
12+
http://unix.stackexchange.com/questions/33596/no-framebuffer-device-how-to-enable-it
13+
14+
Expected outcome: pink square is printed on screen.
15+
If any terminal text scrolls over it, those square get overwritten.
16+
Get rid of terminal for good: http://stackoverflow.com/questions/32620019/c-linux-how-to-takeover-the-framebuffer
17+
18+
Adapted from:
19+
http://stackoverflow.com/questions/4996777/paint-pixels-to-screen-via-linux-framebuffer
20+
21+
Other things to try:
22+
23+
printf 'a\nb' sudo tee /dev/fb0 /dev/null
24+
25+
Prints text to current cursor position, thus same as stdout. So we see that fb0 can also do text oriented drawing.
26+
This is different from this program, since here the mmap syscall is used.
27+
28+
TODO: why a single /dev/fb0 on my laptop? Because a single display?
29+
30+
Video and images:
31+
32+
- http://askubuntu.com/questions/46871/how-can-i-play-videos-in-a-framebuffer
33+
- http://unix.stackexchange.com/questions/226995/how-to-watch-films-images-without-x
34+
35+
General apps: not possible if they pass through X11: http://unix.stackexchange.com/questions/22757/how-to-run-an-app-in-a-framebuffer
36+
37+
But SDL 1 notably can render to fbdev. And you could make a GUI in it with AntTweakBar,
38+
which is a platform agnostic pixel manipulation library.
39+
But it looks like SDL2 cannot anymore: http://forums.libsdl.org/viewtopic.php?t=9661&sid=47b3f4fde203ea5710a798bb6093b8dd
40+
41+
Related:
42+
43+
- http://raspberrypi.stackexchange.com/questions/42628/has-anyone-managed-to-get-sdl-2-3-working-without-x-in-raspbian
44+
- http://stackoverflow.com/questions/14615732/how-to-get-sdl-to-use-fbcon-not-caca
45+
- http://stackoverflow.com/questions/26110581/is-there-a-way-to-config-xorg-to-use-a-framebuffer-device-as-the-primary-monitor
46+
47+
There is the NetSurf browser which is implemented like that: TODO failing in Ubuntu 16.04 with:
48+
http://askubuntu.com/questions/817937/how-to-run-netsurf-fb-fails-with-unable-to-set-video-could-not-set-console-s
49+
*/
50+
51+
#include <stdlib.h>
52+
#include <unistd.h>
53+
#include <stdio.h>
54+
#include <fcntl.h>
55+
#include <linux/fb.h>
56+
#include <sys/mman.h>
57+
#include <sys/ioctl.h>
58+
59+
int main(void) {
60+
char *fbp = 0;
61+
int fbfd = 0;
62+
int x = 0, y = 0;
63+
long int location = 0;
64+
long int screensize = 0;
65+
struct fb_fix_screeninfo finfo;
66+
struct fb_var_screeninfo vinfo;
67+
68+
/* Open the file for reading and writing */
69+
fbfd = open("/dev/fb0", O_RDWR);
70+
if (fbfd == -1) {
71+
perror("Error: cannot open framebuffer device");
72+
exit(1);
73+
}
74+
printf("The framebuffer device was opened successfully.\n");
75+
76+
/* Get fixed screen information */
77+
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
78+
perror("Error reading fixed information");
79+
exit(2);
80+
}
81+
82+
/* Get variable screen information */
83+
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
84+
perror("Error reading variable information");
85+
exit(3);
86+
}
87+
88+
printf(
89+
"vinfo.xres = %d\n"
90+
"vinfo.yres = %d\n"
91+
"vinfo.bits_per_pixel = %d\n"
92+
"vinfo.xoffset = %d\n"
93+
"vinfo.yoffset = %d\n"
94+
"finfo.line_length = %d\n",
95+
vinfo.xres,
96+
vinfo.yres,
97+
vinfo.bits_per_pixel,
98+
vinfo.xoffset,
99+
vinfo.yoffset,
100+
finfo.line_length
101+
);
102+
103+
/* Figure out the size of the screen in bytes */
104+
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
105+
106+
/* Map the device to memory */
107+
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
108+
if (fbp == (void *)-1) {
109+
perror("Error: failed to map framebuffer device to memory");
110+
exit(4);
111+
}
112+
113+
/* Where we are going to put the pixel */
114+
x = 100; y = 100;
115+
116+
/* Figure out where in memory to put the pixel */
117+
for (y = 100; y < 300; y++) {
118+
for (x = 100; x < 300; x++) {
119+
location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel / 8) +
120+
(y + vinfo.yoffset) * finfo.line_length;
121+
if (vinfo.bits_per_pixel == 32) {
122+
/* Blue. */
123+
*(fbp + location) = 100;
124+
/* Green. */
125+
*(fbp + location + 1) = 15 + (x - 100) / 2;
126+
/* Red. */
127+
*(fbp + location + 2) = 200 - (y - 100) / 5;
128+
/* No transparency. */
129+
*(fbp + location + 3) = 0;
130+
//location += 4;
131+
} else {
132+
/* assume 16bpp */
133+
int b = 10;
134+
int g = (x - 100) / 6;
135+
int r = 31 - (y - 100) / 16;
136+
unsigned short int t = r << 11 | g << 5 | b;
137+
*((unsigned short int*)(fbp + location)) = t;
138+
}
139+
140+
}
141+
}
142+
munmap(fbp, screensize);
143+
close(fbfd);
144+
return 0;
145+
}

‎linux/screenshot1.bmp‎

900 KB
Binary file not shown.

‎linux/screenshot2.bmp‎

900 KB
Binary file not shown.

‎linux/screenshot3.bmp‎

900 KB
Binary file not shown.

‎linux/screenshot4.bmp‎

900 KB
Binary file not shown.

0 commit comments

Comments
 (0)