~ubuntu-branches/debian/sid/fbterm/sid

« back to all changes in this revision

Viewing changes to src/screen_render.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2009-12-01 23:12:53 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20091201231253-0t86i1w6d7t8nhgi
Tags: 1.6-1
* New upstream release
* Change e-mail address.
* Remove DM-Upload-Allowed field.
* Update Standards-Version.
* Add README.source file.
* Update patch.
  patches/01_add_terminfo_path.dpatch

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 */
20
20
 
21
21
#include <stdlib.h>
22
 
 
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))
29
 
 
30
 
typedef void (*fillFun)(u32 offset, u32 width, u8 color);
31
 
typedef void (*drawFun)(u32 offset, u8 *pixmap, u32 width, u8 fc, u8 bc);
32
 
 
33
 
static fillFun fill;
34
 
static drawFun draw;
35
 
 
 
22
#include <string.h>
 
23
#include "screen.h"
 
24
#include "fbconfig.h"
 
25
 
 
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))
 
29
 
 
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;
39
33
 
40
34
static u8 *bgimage_mem;
41
35
static u8 bgcolor;
42
36
 
43
 
void Screen::setPalette(const Color *_palette)
 
37
void Screen::setPalette(const Color *palette)
44
38
{
45
 
        if (palette == _palette) return;
46
 
        palette = _palette;
 
39
        if (mPalette == palette) return;
 
40
        mPalette = palette;
47
41
 
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) {
 
44
                case 8:
50
45
                        fillColors[i] = (i << 24) | (i << 16) | (i << 8) | i;
51
 
                } else {
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);
55
 
 
56
 
                        if (vinfo.bits_per_pixel == 16 || vinfo.bits_per_pixel == 15) {
57
 
                                fillColors[i] |= fillColors[i] << 16;
58
 
                        }
 
46
                        break;
 
47
                case 15:
 
48
                        fillColors[i] = ((palette[i].red >> 3) << 10) | ((palette[i].green >> 3) << 5) | (palette[i].blue >> 3);
 
49
                        fillColors[i] |= fillColors[i] << 16;
 
50
                        break;
 
51
                case 16:
 
52
                        fillColors[i] = ((palette[i].red >> 3) << 11) | ((palette[i].green >> 2) << 5) | (palette[i].blue >> 3);
 
53
                        fillColors[i] |= fillColors[i] << 16;
 
54
                        break;
 
55
                case 32:
 
56
                        fillColors[i] = (palette[i].red << 16) | (palette[i].green << 8) | palette[i].blue;
 
57
                        break;
59
58
                }
60
59
        }
61
60
 
62
 
        setupSysPalette(false);
 
61
        setupPalette(false);
63
62
        eraseMargin(true, mRows);
64
63
}
65
64
 
66
 
void Screen::setupSysPalette(bool restore)
67
 
{
68
 
        if (finfo.visual == FB_VISUAL_TRUECOLOR || (!restore && !palette)) return;
69
 
 
70
 
        static bool palette_saved = false;
71
 
        static u16 saved_red[256], saved_green[256], saved_blue[256];
72
 
        u32 cols, rcols, gcols, bcols;
73
 
        fb_cmap cmap;
74
 
 
75
 
        #define INIT_CMAP(_red, _green, _blue) \
76
 
        do { \
77
 
                cmap.start = 0; \
78
 
                cmap.len = cols; \
79
 
                cmap.red = _red; \
80
 
                cmap.green = _green; \
81
 
                cmap.blue = _blue; \
82
 
                cmap.transp = 0; \
83
 
        } while (0)
84
 
 
85
 
        if (finfo.visual == FB_VISUAL_PSEUDOCOLOR) cols = NR_COLORS;
86
 
        else {
87
 
                rcols = 1 << vinfo.red.length;
88
 
                gcols = 1 << vinfo.green.length;
89
 
                bcols = 1 << vinfo.blue.length;
90
 
 
91
 
                cols = MAX(rcols, MAX(gcols, bcols));
92
 
        }
93
 
 
94
 
        if (restore) {
95
 
                if (!palette_saved) return;
96
 
 
97
 
                INIT_CMAP(saved_red, saved_green, saved_blue);
98
 
                ioctl(fbdev_fd, FBIOPUTCMAP, &cmap);
99
 
        } else {
100
 
                if (!palette_saved) {
101
 
                        palette_saved = true;
102
 
 
103
 
                        INIT_CMAP(saved_red, saved_green, saved_blue);
104
 
                        ioctl(fbdev_fd, FBIOGETCMAP, &cmap);
105
 
                }
106
 
 
107
 
                u16 red[cols], green[cols], blue[cols];
108
 
 
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;
114
 
                        }
115
 
                } else {
116
 
                        for (u32 i = 0; i < rcols; i++) {
117
 
                                red[i] = (65535 / (rcols - 1)) * i;
118
 
                        }
119
 
 
120
 
                        for (u32 i = 0; i < gcols; i++) {
121
 
                                green[i] = (65535 / (gcols - 1)) * i;
122
 
                        }
123
 
 
124
 
                        for (u32 i = 0; i < bcols; i++) {
125
 
                                blue[i] = (65535 / (bcols - 1)) * i;
126
 
                        }
127
 
                }
128
 
 
129
 
                INIT_CMAP(red, green, blue);
130
 
                ioctl(fbdev_fd, FBIOPUTCMAP, &cmap);
131
 
        }
132
 
}
133
 
 
134
 
static void fillX(u32 offset, u32 width, u8 color)
 
65
void Screen::initFillDraw()
 
66
{
 
67
        if (mBitsPerPixel == 15) bytes_per_pixel = 2;
 
68
        else bytes_per_pixel = (mBitsPerPixel >> 3);
 
69
 
 
70
        ppl = 4 / bytes_per_pixel;
 
71
        ppw = ppl >> 1;
 
72
        ppb = ppl >> 2;
 
73
 
 
74
        bool bg = false;
 
75
        if (getenv("FBTERM_BACKGROUND_IMAGE")) {
 
76
                bg = true;
 
77
                mScrollType = Redraw;
 
78
 
 
79
                u32 color = 0;
 
80
                Config::instance()->getOption("color-background", color);
 
81
                if (color > 7) color = 0;
 
82
                bgcolor = color;
 
83
 
 
84
                u32 size = mBytesPerLine * ((mRotateType == Rotate0 || mRotateType == Rotate180) ? mHeight : mWidth);
 
85
                bgimage_mem = new u8[size];
 
86
                memcpy(bgimage_mem, mVMemBase, size);
 
87
        }
 
88
 
 
89
        fill = bg ? &Screen::fillXBg : &Screen::fillX;
 
90
 
 
91
        switch (mBitsPerPixel) {
 
92
        case 8:
 
93
                draw = bg ? &Screen::draw8Bg : &Screen::draw8;
 
94
                break;
 
95
        case 15:
 
96
                draw = bg ? &Screen::draw15Bg : &Screen::draw15;
 
97
                break;
 
98
        case 16:
 
99
                draw = bg ? &Screen::draw16Bg : &Screen::draw16;
 
100
                break;
 
101
        case 32:
 
102
                draw = bg ? &Screen::draw32Bg : &Screen::draw32;
 
103
                break;
 
104
        }
 
105
}
 
106
 
 
107
void Screen::endFillDraw()
 
108
{
 
109
        if (bgimage_mem) delete[] bgimage_mem;
 
110
}
 
111
 
 
112
void Screen::fillX(u32 x, u32 y, u32 w, u8 color)
135
113
{
136
114
        u32 c = fillColors[color];
137
 
        u8 *dst = fbdev_mem + offset;
 
115
        u8 *dst = mVMemBase + y * mBytesPerLine + x * bytes_per_pixel;
138
116
 
139
117
        // get better performance if write-combining not enabled for video memory
140
 
        for (u32 i = width / ppl; i--; dst += 4) {
141
 
                fb_writel(dst, c);
 
118
        for (u32 i = w / ppl; i--; dst += 4) {
 
119
                writel(dst, c);
142
120
        }
143
121
 
144
 
        if (width & ppw) {
145
 
                fb_writew(dst, c);
 
122
        if (w & ppw) {
 
123
                writew(dst, c);
146
124
                dst += 2;
147
125
        }
148
126
 
149
 
        if (width & ppb) {
150
 
                fb_writeb(dst, c);
 
127
        if (w & ppb) {
 
128
                writeb(dst, c);
151
129
        }
152
130
}
153
131
 
154
 
static void fillXBg(u32 offset, u32 width, u8 color)
 
132
void Screen::fillXBg(u32 x, u32 y, u32 w, u8 color)
155
133
{
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);
158
137
        } else {
159
 
                fillX(offset, width, color);
 
138
                fillX(x, y, w, color);
160
139
        }
161
140
}
162
141
 
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)
164
143
{
165
144
        bool isfg;
166
 
        u8 *dst = fbdev_mem + offset;
 
145
        u8 *dst = mVMemBase + y * mBytesPerLine + x * bytes_per_pixel;
167
146
 
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]);
171
150
        }
172
151
}
173
152
 
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)
175
154
{
176
155
        if (bc != bgcolor) {
177
 
                draw8(offset, pixmap, width, fc, bc);
 
156
                draw8(x, y, w, fc, bc, pixmap);
178
157
                return;
179
158
        }
180
159
 
181
160
        bool isfg;
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;
184
164
 
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));
188
168
        }
189
169
}
190
170
 
191
171
#define drawX(bits, lred, lgreen, lblue, type, fbwrite) \
192
172
 \
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) \
194
174
{ \
195
175
        u8 red, green, blue; \
196
176
        u8 pixel; \
197
177
        type color; \
198
 
        type *dst = (type *)(fbdev_mem + offset); \
 
178
        type *dst = (type *)(mVMemBase + y * mBytesPerLine + x * bytes_per_pixel); \
199
179
 \
200
 
        for (; width--; pixmap++, dst++) { \
 
180
        for (; w--; pixmap++, dst++) { \
201
181
                pixel = *pixmap; \
202
182
 \
203
183
                if (!pixel) fbwrite(dst, fillColors[bc]); \
204
184
                else if (pixel == 0xff) fbwrite(dst, fillColors[fc]); \
205
185
                else { \
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); \
209
189
 \
210
190
                        color = ((red >> (8 - lred) << (lgreen + lblue)) | (green >> (8 - lgreen) << lblue) | (blue >> (8 - lblue))); \
211
191
                        fbwrite(dst, color); \
213
193
        } \
214
194
}
215
195
 
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)
219
199
 
220
200
#define drawXBg(bits, lred, lgreen, lblue, type, fbwrite) \
221
201
 \
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) \
223
203
{ \
224
204
        if (bc != bgcolor) { \
225
 
                draw##bits(offset, pixmap, width, fc, bc); \
 
205
                draw##bits(x, y, w, fc, bc, pixmap); \
226
206
                return; \
227
207
        } \
228
208
 \
229
209
        u8 red, green, blue; \
230
 
        u8 pixel; \
231
 
        type color; \
232
 
        type *dst = (type *)(fbdev_mem + offset); \
233
 
 \
234
210
        u8 redbg, greenbg, bluebg; \
 
211
        u8 pixel; \
 
212
        type color; \
 
213
 \
 
214
        u32 offset = y * mBytesPerLine + x * bytes_per_pixel; \
 
215
        type *dst = (type *)(mVMemBase + offset); \
235
216
        type *bgimg = (type *)(bgimage_mem + offset); \
236
217
 \
237
 
        for (; width--; pixmap++, dst++, bgimg++) { \
 
218
        for (; w--; pixmap++, dst++, bgimg++) { \
238
219
                pixel = *pixmap; \
239
220
 \
240
221
                if (!pixel) fbwrite(dst, *bgimg); \
246
227
                        greenbg = ((color >> lblue) & ((1 << lgreen) - 1)) << (8 - lgreen); \
247
228
                        bluebg = (color & ((1 << lblue) - 1)) << (8 - lblue); \
248
229
 \
249
 
                        red = redbg + (((palette[fc].red - redbg) * pixel) >> 8); \
250
 
                        green = greenbg + (((palette[fc].green - greenbg) * pixel) >> 8); \
251
 
                        blue = bluebg + (((palette[fc].blue - bluebg) * pixel) >> 8); \
 
230
                        red = redbg + (((mPalette[fc].red - redbg) * pixel) >> 8); \
 
231
                        green = greenbg + (((mPalette[fc].green - greenbg) * pixel) >> 8); \
 
232
                        blue = bluebg + (((mPalette[fc].blue - bluebg) * pixel) >> 8); \
252
233
 \
253
234
                        color = ((red >> (8 - lred) << (lgreen + lblue)) | (green >> (8 - lgreen) << lblue) | (blue >> (8 - lblue))); \
254
235
                        fbwrite(dst, color); \
256
237
        } \
257
238
}
258
239
 
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)
262
 
 
263
 
static void initFillDraw()
264
 
{
265
 
        ppl = 4 / bytes_per_pixel;
266
 
        ppw = ppl >> 1;
267
 
        ppb = ppl >> 2;
268
 
 
269
 
        bool bg = false;
270
 
        if (getenv("FBTERM_BACKGROUND_IMAGE")) {
271
 
                bg = true;
272
 
 
273
 
                u32 color = 0;
274
 
                Config::instance()->getOption("color-background", color);
275
 
                if (color > 7) color = 0;
276
 
                bgcolor = color;
277
 
 
278
 
                u32 size = finfo.line_length * vinfo.yres;
279
 
                bgimage_mem = new u8[size];
280
 
                memcpy(bgimage_mem, fbdev_mem, size);
281
 
 
282
 
                scroll_type = Redraw;
283
 
                if (vinfo.yoffset) {
284
 
                        vinfo.yoffset = 0;
285
 
                        ioctl(fbdev_fd, FBIOPAN_DISPLAY, &vinfo);
286
 
                }
287
 
        }
288
 
 
289
 
        fill = bg ? fillXBg : fillX;
290
 
 
291
 
        switch (vinfo.bits_per_pixel) {
292
 
        case 8:
293
 
                draw = bg ? draw8Bg : draw8;
294
 
                break;
295
 
        case 15:
296
 
                draw = bg ? draw15Bg : draw15;
297
 
                break;
298
 
        case 16:
299
 
                draw = bg ? draw16Bg : draw16;
300
 
                break;
301
 
        case 32:
302
 
                draw = bg ? draw32Bg : draw32;
303
 
                break;
304
 
        }
305
 
}
306
 
 
307
 
static void endFillDraw()
308
 
{
309
 
        if (bgimage_mem) delete[] bgimage_mem;
310
 
}
 
240
drawXBg(15, 5, 5, 5, u16, writew)
 
241
drawXBg(16, 5, 6, 5, u16, writew)
 
242
drawXBg(32, 8, 8, 8, u32, writel)