21
21
#include <stdlib.h>
23
#define fb_readb(addr) (*(volatile u8 *)(addr))
24
#define fb_readw(addr) (*(volatile u16 *)(addr))
25
#define fb_readl(addr) (*(volatile u32 *)(addr))
26
#define fb_writeb(addr, val) (*(volatile u8 *)(addr) = (val))
27
#define fb_writew(addr, val) (*(volatile u16 *)(addr) = (val))
28
#define fb_writel(addr, val) (*(volatile u32 *)(addr) = (val))
30
typedef void (*fillFun)(u32 offset, u32 width, u8 color);
31
typedef void (*drawFun)(u32 offset, u8 *pixmap, u32 width, u8 fc, u8 bc);
26
#define writeb(addr, val) (*(volatile u8 *)(addr) = (val))
27
#define writew(addr, val) (*(volatile u16 *)(addr) = (val))
28
#define writel(addr, val) (*(volatile u32 *)(addr) = (val))
30
static u32 bytes_per_pixel;
36
31
static u32 ppl, ppw, ppb;
37
32
static u32 fillColors[NR_COLORS];
38
static const Color *palette = 0;
40
34
static u8 *bgimage_mem;
43
void Screen::setPalette(const Color *_palette)
37
void Screen::setPalette(const Color *palette)
45
if (palette == _palette) return;
39
if (mPalette == palette) return;
48
for (u32 i = NR_COLORS; i--;) {
49
if (vinfo.bits_per_pixel == 8) {
42
for (u32 i = 0; i < NR_COLORS; i++) {
43
switch (mBitsPerPixel) {
50
45
fillColors[i] = (i << 24) | (i << 16) | (i << 8) | i;
52
fillColors[i] = (palette[i].red >> (8 - vinfo.red.length) << vinfo.red.offset)
53
| ((palette[i].green >> (8 - vinfo.green.length)) << vinfo.green.offset)
54
| ((palette[i].blue >> (8 - vinfo.blue.length)) << vinfo.blue.offset);
56
if (vinfo.bits_per_pixel == 16 || vinfo.bits_per_pixel == 15) {
57
fillColors[i] |= fillColors[i] << 16;
48
fillColors[i] = ((palette[i].red >> 3) << 10) | ((palette[i].green >> 3) << 5) | (palette[i].blue >> 3);
49
fillColors[i] |= fillColors[i] << 16;
52
fillColors[i] = ((palette[i].red >> 3) << 11) | ((palette[i].green >> 2) << 5) | (palette[i].blue >> 3);
53
fillColors[i] |= fillColors[i] << 16;
56
fillColors[i] = (palette[i].red << 16) | (palette[i].green << 8) | palette[i].blue;
62
setupSysPalette(false);
63
62
eraseMargin(true, mRows);
66
void Screen::setupSysPalette(bool restore)
68
if (finfo.visual == FB_VISUAL_TRUECOLOR || (!restore && !palette)) return;
70
static bool palette_saved = false;
71
static u16 saved_red[256], saved_green[256], saved_blue[256];
72
u32 cols, rcols, gcols, bcols;
75
#define INIT_CMAP(_red, _green, _blue) \
80
cmap.green = _green; \
85
if (finfo.visual == FB_VISUAL_PSEUDOCOLOR) cols = NR_COLORS;
87
rcols = 1 << vinfo.red.length;
88
gcols = 1 << vinfo.green.length;
89
bcols = 1 << vinfo.blue.length;
91
cols = MAX(rcols, MAX(gcols, bcols));
95
if (!palette_saved) return;
97
INIT_CMAP(saved_red, saved_green, saved_blue);
98
ioctl(fbdev_fd, FBIOPUTCMAP, &cmap);
100
if (!palette_saved) {
101
palette_saved = true;
103
INIT_CMAP(saved_red, saved_green, saved_blue);
104
ioctl(fbdev_fd, FBIOGETCMAP, &cmap);
107
u16 red[cols], green[cols], blue[cols];
109
if (finfo.visual == FB_VISUAL_PSEUDOCOLOR) {
110
for (u32 i = 0; i < NR_COLORS; i++) {
111
red[i] = (palette[i].red << 8) | palette[i].red;
112
green[i] = (palette[i].green << 8) | palette[i].green;
113
blue[i] = (palette[i].blue << 8) | palette[i].blue;
116
for (u32 i = 0; i < rcols; i++) {
117
red[i] = (65535 / (rcols - 1)) * i;
120
for (u32 i = 0; i < gcols; i++) {
121
green[i] = (65535 / (gcols - 1)) * i;
124
for (u32 i = 0; i < bcols; i++) {
125
blue[i] = (65535 / (bcols - 1)) * i;
129
INIT_CMAP(red, green, blue);
130
ioctl(fbdev_fd, FBIOPUTCMAP, &cmap);
134
static void fillX(u32 offset, u32 width, u8 color)
65
void Screen::initFillDraw()
67
if (mBitsPerPixel == 15) bytes_per_pixel = 2;
68
else bytes_per_pixel = (mBitsPerPixel >> 3);
70
ppl = 4 / bytes_per_pixel;
75
if (getenv("FBTERM_BACKGROUND_IMAGE")) {
80
Config::instance()->getOption("color-background", color);
81
if (color > 7) color = 0;
84
u32 size = mBytesPerLine * ((mRotateType == Rotate0 || mRotateType == Rotate180) ? mHeight : mWidth);
85
bgimage_mem = new u8[size];
86
memcpy(bgimage_mem, mVMemBase, size);
89
fill = bg ? &Screen::fillXBg : &Screen::fillX;
91
switch (mBitsPerPixel) {
93
draw = bg ? &Screen::draw8Bg : &Screen::draw8;
96
draw = bg ? &Screen::draw15Bg : &Screen::draw15;
99
draw = bg ? &Screen::draw16Bg : &Screen::draw16;
102
draw = bg ? &Screen::draw32Bg : &Screen::draw32;
107
void Screen::endFillDraw()
109
if (bgimage_mem) delete[] bgimage_mem;
112
void Screen::fillX(u32 x, u32 y, u32 w, u8 color)
136
114
u32 c = fillColors[color];
137
u8 *dst = fbdev_mem + offset;
115
u8 *dst = mVMemBase + y * mBytesPerLine + x * bytes_per_pixel;
139
117
// get better performance if write-combining not enabled for video memory
140
for (u32 i = width / ppl; i--; dst += 4) {
118
for (u32 i = w / ppl; i--; dst += 4) {
154
static void fillXBg(u32 offset, u32 width, u8 color)
132
void Screen::fillXBg(u32 x, u32 y, u32 w, u8 color)
156
134
if (color == bgcolor) {
157
memcpy(fbdev_mem + offset, bgimage_mem + offset, width * bytes_per_pixel);
135
u32 offset = y * mBytesPerLine + x * bytes_per_pixel;
136
memcpy(mVMemBase + offset, bgimage_mem + offset, w * bytes_per_pixel);
159
fillX(offset, width, color);
138
fillX(x, y, w, color);
163
static void draw8(u32 offset, u8 *pixmap, u32 width, u8 fc, u8 bc)
142
void Screen::draw8(u32 x, u32 y, u32 w, u8 fc, u8 bc, u8 *pixmap)
166
u8 *dst = fbdev_mem + offset;
145
u8 *dst = mVMemBase + y * mBytesPerLine + x * bytes_per_pixel;
168
for (; width--; pixmap++, dst++) {
147
for (; w--; pixmap++, dst++) {
169
148
isfg = (*pixmap & 0x80);
170
fb_writeb(dst, fillColors[isfg ? fc : bc]);
149
writeb(dst, fillColors[isfg ? fc : bc]);
174
static void draw8Bg(u32 offset, u8 *pixmap, u32 width, u8 fc, u8 bc)
153
void Screen::draw8Bg(u32 x, u32 y, u32 w, u8 fc, u8 bc, u8 *pixmap)
176
155
if (bc != bgcolor) {
177
draw8(offset, pixmap, width, fc, bc);
156
draw8(x, y, w, fc, bc, pixmap);
182
u8 *dst = fbdev_mem + offset;
161
u32 offset = y * mBytesPerLine + x * bytes_per_pixel;
162
u8 *dst = mVMemBase + offset;
183
163
u8 *bgimg = bgimage_mem + offset;
185
for (; width--; pixmap++, dst++, bgimg++) {
165
for (; w--; pixmap++, dst++, bgimg++) {
186
166
isfg = (*pixmap & 0x80);
187
fb_writeb(dst, isfg ? fillColors[fc] : (*bgimg));
167
writeb(dst, isfg ? fillColors[fc] : (*bgimg));
191
171
#define drawX(bits, lred, lgreen, lblue, type, fbwrite) \
193
static void draw##bits(u32 offset, u8 *pixmap, u32 width, u8 fc, u8 bc) \
173
void Screen::draw##bits(u32 x, u32 y, u32 w, u8 fc, u8 bc, u8 *pixmap) \
195
175
u8 red, green, blue; \
198
type *dst = (type *)(fbdev_mem + offset); \
178
type *dst = (type *)(mVMemBase + y * mBytesPerLine + x * bytes_per_pixel); \
200
for (; width--; pixmap++, dst++) { \
180
for (; w--; pixmap++, dst++) { \
201
181
pixel = *pixmap; \
203
183
if (!pixel) fbwrite(dst, fillColors[bc]); \
204
184
else if (pixel == 0xff) fbwrite(dst, fillColors[fc]); \
206
red = palette[bc].red + (((palette[fc].red - palette[bc].red) * pixel) >> 8); \
207
green = palette[bc].green + (((palette[fc].green - palette[bc].green) * pixel) >> 8); \
208
blue = palette[bc].blue + (((palette[fc].blue - palette[bc].blue) * pixel) >> 8); \
186
red = mPalette[bc].red + (((mPalette[fc].red - mPalette[bc].red) * pixel) >> 8); \
187
green = mPalette[bc].green + (((mPalette[fc].green - mPalette[bc].green) * pixel) >> 8); \
188
blue = mPalette[bc].blue + (((mPalette[fc].blue - mPalette[bc].blue) * pixel) >> 8); \
210
190
color = ((red >> (8 - lred) << (lgreen + lblue)) | (green >> (8 - lgreen) << lblue) | (blue >> (8 - lblue))); \
211
191
fbwrite(dst, color); \
216
drawX(15, 5, 5, 5, u16, fb_writew)
217
drawX(16, 5, 6, 5, u16, fb_writew)
218
drawX(32, 8, 8, 8, u32, fb_writel)
196
drawX(15, 5, 5, 5, u16, writew)
197
drawX(16, 5, 6, 5, u16, writew)
198
drawX(32, 8, 8, 8, u32, writel)
220
200
#define drawXBg(bits, lred, lgreen, lblue, type, fbwrite) \
222
static void draw##bits##Bg(u32 offset, u8 *pixmap, u32 width, u8 fc, u8 bc) \
202
void Screen::draw##bits##Bg(u32 x, u32 y, u32 w, u8 fc, u8 bc, u8 *pixmap) \
224
204
if (bc != bgcolor) { \
225
draw##bits(offset, pixmap, width, fc, bc); \
205
draw##bits(x, y, w, fc, bc, pixmap); \
229
209
u8 red, green, blue; \
232
type *dst = (type *)(fbdev_mem + offset); \
234
210
u8 redbg, greenbg, bluebg; \
214
u32 offset = y * mBytesPerLine + x * bytes_per_pixel; \
215
type *dst = (type *)(mVMemBase + offset); \
235
216
type *bgimg = (type *)(bgimage_mem + offset); \
237
for (; width--; pixmap++, dst++, bgimg++) { \
218
for (; w--; pixmap++, dst++, bgimg++) { \
238
219
pixel = *pixmap; \
240
221
if (!pixel) fbwrite(dst, *bgimg); \
259
drawXBg(15, 5, 5, 5, u16, fb_writew)
260
drawXBg(16, 5, 6, 5, u16, fb_writew)
261
drawXBg(32, 8, 8, 8, u32, fb_writel)
263
static void initFillDraw()
265
ppl = 4 / bytes_per_pixel;
270
if (getenv("FBTERM_BACKGROUND_IMAGE")) {
274
Config::instance()->getOption("color-background", color);
275
if (color > 7) color = 0;
278
u32 size = finfo.line_length * vinfo.yres;
279
bgimage_mem = new u8[size];
280
memcpy(bgimage_mem, fbdev_mem, size);
282
scroll_type = Redraw;
285
ioctl(fbdev_fd, FBIOPAN_DISPLAY, &vinfo);
289
fill = bg ? fillXBg : fillX;
291
switch (vinfo.bits_per_pixel) {
293
draw = bg ? draw8Bg : draw8;
296
draw = bg ? draw15Bg : draw15;
299
draw = bg ? draw16Bg : draw16;
302
draw = bg ? draw32Bg : draw32;
307
static void endFillDraw()
309
if (bgimage_mem) delete[] bgimage_mem;
240
drawXBg(15, 5, 5, 5, u16, writew)
241
drawXBg(16, 5, 6, 5, u16, writew)
242
drawXBg(32, 8, 8, 8, u32, writel)