11 #define MIN(a, b) ((a) < (b) ? (a) : (b))
12 #define MAX(a, b) ((a) > (b) ? (a) : (b))
13 #define FBDEV_PATH "/dev/fb0"
14 #define MAXFBWIDTH (1 << 12)
15 #define BPP sizeof(fbval_t)
16 #define NLEVELS (1 << 8)
19 static unsigned char *fb
;
20 static struct fb_var_screeninfo vinfo
;
21 static struct fb_fix_screeninfo finfo
;
22 static int rl
, rr
, gl
, gr
, bl
, br
;
23 static int nr
, ng
, nb
;
27 return vinfo
.xres_virtual
* vinfo
.yres_virtual
* BPP
;
30 static void fb_cmap_save(int save
)
32 static unsigned short red
[NLEVELS
], green
[NLEVELS
], blue
[NLEVELS
];
34 if (finfo
.visual
== FB_VISUAL_TRUECOLOR
)
37 cmap
.len
= MAX(nr
, MAX(ng
, nb
));
42 ioctl(fd
, save
? FBIOGETCMAP
: FBIOPUTCMAP
, &cmap
);
47 unsigned short red
[NLEVELS
], green
[NLEVELS
], blue
[NLEVELS
];
50 if (finfo
.visual
== FB_VISUAL_TRUECOLOR
)
53 for (i
= 0; i
< nr
; i
++)
54 red
[i
] = (65535 / (nr
- 1)) * i
;
55 for (i
= 0; i
< ng
; i
++)
56 green
[i
] = (65535 / (ng
- 1)) * i
;
57 for (i
= 0; i
< nb
; i
++)
58 blue
[i
] = (65535 / (nb
- 1)) * i
;
61 cmap
.len
= MAX(nr
, MAX(ng
, nb
));
67 ioctl(fd
, FBIOPUTCMAP
, &cmap
);
70 static void xerror(char *msg
)
76 static void xdie(char *msg
)
78 fprintf(stderr
, "%s\n", msg
);
82 static void init_colors(void)
84 nr
= 1 << vinfo
.red
.length
;
85 ng
= 1 << vinfo
.green
.length
;
86 nb
= 1 << vinfo
.blue
.length
;
87 rr
= 8 - vinfo
.red
.length
;
88 rl
= vinfo
.red
.offset
;
89 gr
= 8 - vinfo
.green
.length
;
90 gl
= vinfo
.green
.offset
;
91 br
= 8 - vinfo
.blue
.length
;
92 bl
= vinfo
.blue
.offset
;
97 fd
= open(FBDEV_PATH
, O_RDWR
);
99 xerror("can't open " FBDEV_PATH
);
100 if (ioctl(fd
, FBIOGET_VSCREENINFO
, &vinfo
) == -1)
101 xerror("ioctl failed");
102 if (ioctl(fd
, FBIOGET_FSCREENINFO
, &finfo
) == -1)
103 xerror("ioctl failed");
104 if ((vinfo
.bits_per_pixel
+ 7) >> 3 != BPP
)
105 xdie("fbval_t does not match framebuffer depth");
107 fb
= mmap(NULL
, fb_len(), PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0);
108 if (fb
== MAP_FAILED
)
109 xerror("can't map the framebuffer");
114 void fb_set(int r
, int c
, fbval_t
*mem
, int len
)
116 long loc
= (c
+ vinfo
.xoffset
) * BPP
+
117 (r
+ vinfo
.yoffset
) * finfo
.line_length
;
118 memcpy(fb
+ loc
, mem
, len
* BPP
);
124 munmap(fb
, fb_len());
128 fbval_t
fb_color(unsigned char r
, unsigned char g
, unsigned char b
)
130 return ((r
>> rr
) << rl
) | ((g
>> gr
) << gl
) | ((b
>> br
) << bl
);
143 static unsigned char *rowaddr(int r
)
145 return fb
+ (r
+ vinfo
.yoffset
) * finfo
.line_length
;
148 static unsigned long cache
[MAXFBWIDTH
];
149 void fb_box(int sr
, int sc
, int er
, int ec
, fbval_t val
)
152 int pc
= sizeof(cache
[0]) / sizeof(val
);
153 int cn
= MIN((ec
- sc
) / pc
+ 1, MAXFBWIDTH
);
154 unsigned long nv
= val
;
155 for (i
= 1; i
< pc
; i
++)
156 nv
= (nv
<< (sizeof(val
) * 8)) | val
;
157 for (i
= 0; i
< cn
; i
++)
159 for (i
= sr
; i
< er
; i
++)
160 memcpy(rowaddr(i
) + sc
* BPP
, cache
, (ec
- sc
) * BPP
);