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