Root/
Source at commit dc637c9 created 12 years 4 months ago. By Xiangfu Liu, xburst: ben nanonote: first add WPAN(atben,atusb) driver take from qi-kernel.git thanks to Werner | |
---|---|
1 | From 77de829067262bbe1f7435b087c11ad9a8ea0b06 Mon Sep 17 00:00:00 2001 |
2 | From: Xiangfu Liu <xiangfu@sharism.cc> |
3 | Date: Tue, 18 Oct 2011 09:21:04 +0800 |
4 | Subject: [PATCH 30/32] fbcon-color-fonts |
5 | |
6 | --- |
7 | drivers/tty/vt/vt.c | 3 +- |
8 | drivers/video/console/bitblit.c | 188 +++++++++++++++++++++++++++++++++------ |
9 | drivers/video/console/fbcon.c | 14 +++- |
10 | 3 files changed, 173 insertions(+), 32 deletions(-) |
11 | |
12 | diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c |
13 | index b3915b7..37eaac5 100644 |
14 | --- a/drivers/tty/vt/vt.c |
15 | +++ b/drivers/tty/vt/vt.c |
16 | @@ -4034,6 +4034,7 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op) |
17 | struct console_font font; |
18 | int rc = -EINVAL; |
19 | int size; |
20 | + u8 std_font = *((u32*)op->data) != 0x6a127efd; |
21 | |
22 | if (vc->vc_mode != KD_TEXT) |
23 | return -EINVAL; |
24 | @@ -4063,7 +4064,7 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op) |
25 | } |
26 | if (op->width <= 0 || op->width > 32 || op->height > 32) |
27 | return -EINVAL; |
28 | - size = (op->width+7)/8 * 32 * op->charcount; |
29 | + size = ( std_font ? (op->width+7)/8 * 32 : 4 * op->width * op->height) * op->charcount; |
30 | if (size > max_font_size) |
31 | return -ENOSPC; |
32 | font.charcount = op->charcount; |
33 | diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c |
34 | index 28b1a83..8e559df 100644 |
35 | --- a/drivers/video/console/bitblit.c |
36 | +++ b/drivers/video/console/bitblit.c |
37 | @@ -105,6 +105,12 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info, |
38 | info->fbops->fb_imageblit(info, image); |
39 | } |
40 | |
41 | +/* info: details of the framebuffer |
42 | + * image: the off-screen image in which the character (sub)string is being |
43 | + * prepared |
44 | + * dst: a pointer to the top-left pixel in the off-screen image where the |
45 | + * character (sub)string should go |
46 | + */ |
47 | static inline void bit_putcs_unaligned(struct vc_data *vc, |
48 | struct fb_info *info, const u16 *s, |
49 | u32 attr, u32 cnt, u32 d_pitch, |
50 | @@ -140,12 +146,62 @@ static inline void bit_putcs_unaligned(struct vc_data *vc, |
51 | |
52 | } |
53 | |
54 | +void inline draw_glyph_row_inv( int pixels_across_glyph, u8 *src, u8 *target) { |
55 | + u32 *pixel_on_glyph_sheet = (u32*) src; |
56 | + u32 *pixel_on_screen = (u32*) target; |
57 | + |
58 | + while( pixels_across_glyph--) { |
59 | + *pixel_on_screen = ~(*pixel_on_glyph_sheet); |
60 | + ++ pixel_on_glyph_sheet; |
61 | + ++ pixel_on_screen; |
62 | + } |
63 | +} |
64 | + |
65 | +void inline draw_glyph_row_75( int pixels_across_glyph, u8 *src, u8 *target) { |
66 | + u32 pixel; |
67 | + u32 *pixel_on_glyph_sheet = (u32*) src; |
68 | + u32 *pixel_on_screen = (u32*) target; |
69 | + /* Copy the pixels at 75% brightness */ |
70 | + while( pixels_across_glyph--) { |
71 | + pixel = *pixel_on_glyph_sheet; |
72 | + /* This is a cheeky way of multiplying by 0.75 */ |
73 | + pixel = ( pixel >> 1) & 0x7f7f7f7f; |
74 | + pixel += ( pixel >> 1) & 0x7f7f7f7f; |
75 | + *pixel_on_screen = pixel; |
76 | + ++ pixel_on_glyph_sheet; |
77 | + ++ pixel_on_screen; |
78 | + } |
79 | +} |
80 | + |
81 | +/* |
82 | + * width: the number of bytes required to store a single row of pixels from |
83 | + * a glyph |
84 | + * cellsize: the number of bytes required to store the pixels for a single |
85 | + * glyph |
86 | + * maxcnt: the maximum number of characters that can be blasted to the screen |
87 | + * at one time ( limited by the amount of video RAM available for a |
88 | + * (sub)string of characters) |
89 | + * The NanoNote has 32-bits per pixel arranged BGRA |
90 | + * info->fix.line_length: the number of bytes to advance through the frame |
91 | + * buffer in order to get from the address of a pixel to |
92 | + * the address of the pixel directly below it |
93 | + * screen_row_hop: the number of 32-bit words to advance through the frame |
94 | + * buffer in order to get from the address of a pixel to the |
95 | + * address of the pixel directly below it on the screen |
96 | + * glyph_on_screen: the address of the pixel on screen where the top-left of |
97 | + * the next glyph should go |
98 | + * row_on_screen: the address of the pixel on screen where the next row of |
99 | + * pixels from the glyph should go |
100 | + * row_on_glyph_sheet: pointer within font.data ( the glyph sheet) of the |
101 | + * left-most pixel from the next row to be drawn |
102 | + */ |
103 | static void bit_putcs(struct vc_data *vc, struct fb_info *info, |
104 | const unsigned short *s, int count, int yy, int xx, |
105 | int fg, int bg) |
106 | { |
107 | struct fb_image image; |
108 | - u32 width = DIV_ROUND_UP(vc->vc_font.width, 8); |
109 | + u8 std_font = *((u32*)vc->vc_font.data) != 0x6a127efd; |
110 | + u32 width = std_font ? DIV_ROUND_UP(vc->vc_font.width, 8) : 4 * vc->vc_font.width; |
111 | u32 cellsize = width * vc->vc_font.height; |
112 | u32 maxcnt = info->pixmap.size/cellsize; |
113 | u32 scan_align = info->pixmap.scan_align - 1; |
114 | @@ -153,6 +209,10 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, |
115 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; |
116 | u32 attribute = get_attribute(info, scr_readw(s)); |
117 | u8 *dst, *buf = NULL; |
118 | + u32 screen_row_hop; |
119 | + u16 charmask; |
120 | + u8 *row_on_glyph_sheet, *glyph_on_screen, *row_on_screen; |
121 | + u8 code_point, rows_left; |
122 | |
123 | image.fg_color = fg; |
124 | image.bg_color = bg; |
125 | @@ -167,31 +227,73 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, |
126 | return; |
127 | } |
128 | |
129 | - while (count) { |
130 | - if (count > maxcnt) |
131 | - cnt = maxcnt; |
132 | - else |
133 | - cnt = count; |
134 | - |
135 | - image.width = vc->vc_font.width * cnt; |
136 | - pitch = DIV_ROUND_UP(image.width, 8) + scan_align; |
137 | - pitch &= ~scan_align; |
138 | - size = pitch * image.height + buf_align; |
139 | - size &= ~buf_align; |
140 | - dst = fb_get_buffer_offset(info, &info->pixmap, size); |
141 | - image.data = dst; |
142 | - |
143 | - if (!mod) |
144 | - bit_putcs_aligned(vc, info, s, attribute, cnt, pitch, |
145 | - width, cellsize, &image, buf, dst); |
146 | - else |
147 | - bit_putcs_unaligned(vc, info, s, attribute, cnt, |
148 | - pitch, width, cellsize, &image, |
149 | - buf, dst); |
150 | - |
151 | - image.dx += cnt * vc->vc_font.width; |
152 | - count -= cnt; |
153 | - s += cnt; |
154 | + if ( std_font) { |
155 | + while (count) { |
156 | + if (count > maxcnt) |
157 | + cnt = maxcnt; |
158 | + else |
159 | + cnt = count; |
160 | + |
161 | + image.width = vc->vc_font.width * cnt; |
162 | + pitch = DIV_ROUND_UP(image.width, 8) + scan_align; |
163 | + pitch &= ~scan_align; |
164 | + size = pitch * image.height + buf_align; |
165 | + size &= ~buf_align; |
166 | + dst = fb_get_buffer_offset(info, &info->pixmap, size); |
167 | + image.data = dst; |
168 | + |
169 | + if (!mod) |
170 | + bit_putcs_aligned(vc, info, s, attribute, cnt, |
171 | + pitch, width, cellsize, |
172 | + &image, buf, dst); |
173 | + else |
174 | + bit_putcs_unaligned(vc, info, s, attribute, cnt, |
175 | + pitch, width, cellsize, |
176 | + &image, buf, dst); |
177 | + |
178 | + image.dx += cnt * vc->vc_font.width; |
179 | + count -= cnt; |
180 | + s += cnt; |
181 | + } |
182 | + } |
183 | + else { /* The font is not a standard 1-bit font */ |
184 | + charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; |
185 | + screen_row_hop = info->fix.line_length; |
186 | + glyph_on_screen = info->screen_base + |
187 | + screen_row_hop * image.dy + |
188 | + 4 * image.dx; |
189 | + /* While there are still characters to draw.. */ |
190 | + while (count--) { |
191 | + code_point = scr_readw(s++) & charmask; |
192 | + row_on_glyph_sheet = vc->vc_font.data + |
193 | + cellsize * code_point; |
194 | + /* Draw every row of the glyph */ |
195 | + row_on_screen = glyph_on_screen; |
196 | + rows_left = vc->vc_font.height; |
197 | + while( rows_left--) |
198 | + { |
199 | + /* If the background color is NOT black then do |
200 | + * reverse video */ |
201 | + if ( 0 < bg) { |
202 | + draw_glyph_row_inv( vc->vc_font.width, |
203 | + row_on_glyph_sheet, |
204 | + row_on_screen); |
205 | + } |
206 | + /* If the foreground color is high-intensity */ |
207 | + else if ( 8 <= fg) { |
208 | + memcpy( row_on_screen, |
209 | + row_on_glyph_sheet, width); |
210 | + } |
211 | + else { |
212 | + draw_glyph_row_75( vc->vc_font.width, |
213 | + row_on_glyph_sheet, |
214 | + row_on_screen); |
215 | + } |
216 | + row_on_glyph_sheet += width; |
217 | + row_on_screen += screen_row_hop; |
218 | + } |
219 | + glyph_on_screen += width; |
220 | + } |
221 | } |
222 | |
223 | /* buf is always NULL except when in monochrome mode, so in this case |
224 | @@ -234,6 +336,29 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, |
225 | } |
226 | } |
227 | |
228 | +static void bgra_cursor( struct vc_data *vc, struct fb_info *info, short c, |
229 | + struct fb_cursor *cursor) |
230 | +{ |
231 | + u32 x = cursor->image.dx; |
232 | + u32 y = cursor->image.dy; |
233 | + u32 gw = vc->vc_font.width; |
234 | + u32 gh = vc->vc_font.height; |
235 | + u32 *pixel; |
236 | + |
237 | + /* Draw the glyph to the screen */ |
238 | + bit_putcs( vc, info, &c, 1, y/gh, x/gw, 0, 0); |
239 | + |
240 | + if ( cursor->enable) { |
241 | + /* Invert the last row of pixels */ |
242 | + pixel = (u32*) ( info->screen_base + |
243 | + info->fix.line_length * ( y + gh - 1) + 4 * x); |
244 | + while ( gw--) { |
245 | + *pixel ^= 0xffffffff; |
246 | + ++ pixel; |
247 | + } |
248 | + } |
249 | +} |
250 | + |
251 | static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, |
252 | int softback_lines, int fg, int bg) |
253 | { |
254 | @@ -245,6 +370,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, |
255 | int attribute, use_sw = (vc->vc_cursor_type & 0x10); |
256 | int err = 1; |
257 | char *src; |
258 | + u8 std_font = *((u32*)vc->vc_font.data) != 0x6a127efd; |
259 | |
260 | cursor.set = 0; |
261 | |
262 | @@ -383,8 +509,14 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, |
263 | if (info->fbops->fb_cursor) |
264 | err = info->fbops->fb_cursor(info, &cursor); |
265 | |
266 | - if (err) |
267 | - soft_cursor(info, &cursor); |
268 | + if (err) { |
269 | + if ( std_font) { |
270 | + soft_cursor(info, &cursor); |
271 | + } |
272 | + else { |
273 | + bgra_cursor( vc, info, c, &cursor); |
274 | + } |
275 | + } |
276 | |
277 | ops->cursor_reset = 0; |
278 | } |
279 | diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c |
280 | index 8745637..dea9d2c 100644 |
281 | --- a/drivers/video/console/fbcon.c |
282 | +++ b/drivers/video/console/fbcon.c |
283 | @@ -2552,7 +2552,8 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne |
284 | int size; |
285 | int i, csum; |
286 | u8 *new_data, *data = font->data; |
287 | - int pitch = (font->width+7) >> 3; |
288 | + u8 std_font = *((u32*)data) != 0x6a127efd; |
289 | + int pitch = std_font ? (font->width+7) >> 3 : 4 * font->width; |
290 | |
291 | /* Is there a reason why fbconsole couldn't handle any charcount >256? |
292 | * If not this check should be changed to charcount < 256 */ |
293 | @@ -2571,6 +2572,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne |
294 | size = h * pitch * charcount; |
295 | |
296 | new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER); |
297 | + DPRINTK(KERN_INFO "fbcon_set_font size:%d\n", size); |
298 | |
299 | if (!new_data) |
300 | return -ENOMEM; |
301 | @@ -2579,8 +2581,14 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne |
302 | FNTSIZE(new_data) = size; |
303 | FNTCHARCNT(new_data) = charcount; |
304 | REFCOUNT(new_data) = 0; /* usage counter */ |
305 | - for (i=0; i< charcount; i++) { |
306 | - memcpy(new_data + i*h*pitch, data + i*32*pitch, h*pitch); |
307 | + if ( std_font) { |
308 | + for (i=0; i< charcount; i++) { |
309 | + memcpy(new_data + i*h*pitch, data + i*32*pitch, |
310 | + h*pitch); |
311 | + } |
312 | + } |
313 | + else { |
314 | + memcpy( new_data, data, size); |
315 | } |
316 | |
317 | /* Since linux has a nice crc32 function use it for counting font |
318 | -- |
319 | 1.7.4.1 |
320 | |
321 |