1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-27 17:15:00 +02:00

kernel-3.0: add fbcon color fonts patch

This commit is contained in:
kyak 2011-09-24 11:13:52 +04:00 committed by Xiangfu Liu
parent 1c406daf95
commit 5d26452fa3

View File

@ -0,0 +1,300 @@
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4034,6 +4034,7 @@ static int con_font_set(struct vc_data *
struct console_font font;
int rc = -EINVAL;
int size;
+ u8 std_font = *((u32*)op->data) != 0x6a127efd;
if (vc->vc_mode != KD_TEXT)
return -EINVAL;
@@ -4063,7 +4064,7 @@ static int con_font_set(struct vc_data *
}
if (op->width <= 0 || op->width > 32 || op->height > 32)
return -EINVAL;
- size = (op->width+7)/8 * 32 * op->charcount;
+ size = ( std_font ? (op->width+7)/8 * 32 : 4 * op->width * op->height) * op->charcount;
if (size > max_font_size)
return -ENOSPC;
font.charcount = op->charcount;
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -105,6 +105,12 @@ static inline void bit_putcs_aligned(str
info->fbops->fb_imageblit(info, image);
}
+/* info: details of the framebuffer
+ * image: the off-screen image in which the character (sub)string is being
+ * prepared
+ * dst: a pointer to the top-left pixel in the off-screen image where the
+ * character (sub)string should go
+ */
static inline void bit_putcs_unaligned(struct vc_data *vc,
struct fb_info *info, const u16 *s,
u32 attr, u32 cnt, u32 d_pitch,
@@ -140,12 +146,62 @@ static inline void bit_putcs_unaligned(s
}
+void inline draw_glyph_row_inv( int pixels_across_glyph, u8 *src, u8 *target) {
+ u32 *pixel_on_glyph_sheet = (u32*) src;
+ u32 *pixel_on_screen = (u32*) target;
+
+ while( pixels_across_glyph--) {
+ *pixel_on_screen = ~(*pixel_on_glyph_sheet);
+ ++ pixel_on_glyph_sheet;
+ ++ pixel_on_screen;
+ }
+}
+
+void inline draw_glyph_row_75( int pixels_across_glyph, u8 *src, u8 *target) {
+ u32 pixel;
+ u32 *pixel_on_glyph_sheet = (u32*) src;
+ u32 *pixel_on_screen = (u32*) target;
+ /* Copy the pixels at 75% brightness */
+ while( pixels_across_glyph--) {
+ pixel = *pixel_on_glyph_sheet;
+ /* This is a cheeky way of multiplying by 0.75 */
+ pixel = ( pixel >> 1) & 0x7f7f7f7f;
+ pixel += ( pixel >> 1) & 0x7f7f7f7f;
+ *pixel_on_screen = pixel;
+ ++ pixel_on_glyph_sheet;
+ ++ pixel_on_screen;
+ }
+}
+
+/*
+ * width: the number of bytes required to store a single row of pixels from
+ * a glyph
+ * cellsize: the number of bytes required to store the pixels for a single
+ * glyph
+ * maxcnt: the maximum number of characters that can be blasted to the screen
+ * at one time ( limited by the amount of video RAM available for a
+ * (sub)string of characters)
+ * The NanoNote has 32-bits per pixel arranged BGRA
+ * info->fix.line_length: the number of bytes to advance through the frame
+ * buffer in order to get from the address of a pixel to
+ * the address of the pixel directly below it
+ * screen_row_hop: the number of 32-bit words to advance through the frame
+ * buffer in order to get from the address of a pixel to the
+ * address of the pixel directly below it on the screen
+ * glyph_on_screen: the address of the pixel on screen where the top-left of
+ * the next glyph should go
+ * row_on_screen: the address of the pixel on screen where the next row of
+ * pixels from the glyph should go
+ * row_on_glyph_sheet: pointer within font.data ( the glyph sheet) of the
+ * left-most pixel from the next row to be drawn
+ */
static void bit_putcs(struct vc_data *vc, struct fb_info *info,
const unsigned short *s, int count, int yy, int xx,
int fg, int bg)
{
struct fb_image image;
- u32 width = DIV_ROUND_UP(vc->vc_font.width, 8);
+ u8 std_font = *((u32*)vc->vc_font.data) != 0x6a127efd;
+ u32 width = std_font ? DIV_ROUND_UP(vc->vc_font.width, 8) : 4 * vc->vc_font.width;
u32 cellsize = width * vc->vc_font.height;
u32 maxcnt = info->pixmap.size/cellsize;
u32 scan_align = info->pixmap.scan_align - 1;
@@ -153,6 +209,10 @@ static void bit_putcs(struct vc_data *vc
u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL;
+ u32 screen_row_hop;
+ u16 charmask;
+ u8 *row_on_glyph_sheet, *glyph_on_screen, *row_on_screen;
+ u8 code_point, rows_left;
image.fg_color = fg;
image.bg_color = bg;
@@ -167,31 +227,73 @@ static void bit_putcs(struct vc_data *vc
return;
}
- while (count) {
- if (count > maxcnt)
- cnt = maxcnt;
- else
- cnt = count;
-
- image.width = vc->vc_font.width * cnt;
- pitch = DIV_ROUND_UP(image.width, 8) + scan_align;
- pitch &= ~scan_align;
- size = pitch * image.height + buf_align;
- size &= ~buf_align;
- dst = fb_get_buffer_offset(info, &info->pixmap, size);
- image.data = dst;
-
- if (!mod)
- bit_putcs_aligned(vc, info, s, attribute, cnt, pitch,
- width, cellsize, &image, buf, dst);
- else
- bit_putcs_unaligned(vc, info, s, attribute, cnt,
- pitch, width, cellsize, &image,
- buf, dst);
-
- image.dx += cnt * vc->vc_font.width;
- count -= cnt;
- s += cnt;
+ if ( std_font) {
+ while (count) {
+ if (count > maxcnt)
+ cnt = maxcnt;
+ else
+ cnt = count;
+
+ image.width = vc->vc_font.width * cnt;
+ pitch = DIV_ROUND_UP(image.width, 8) + scan_align;
+ pitch &= ~scan_align;
+ size = pitch * image.height + buf_align;
+ size &= ~buf_align;
+ dst = fb_get_buffer_offset(info, &info->pixmap, size);
+ image.data = dst;
+
+ if (!mod)
+ bit_putcs_aligned(vc, info, s, attribute, cnt,
+ pitch, width, cellsize,
+ &image, buf, dst);
+ else
+ bit_putcs_unaligned(vc, info, s, attribute, cnt,
+ pitch, width, cellsize,
+ &image, buf, dst);
+
+ image.dx += cnt * vc->vc_font.width;
+ count -= cnt;
+ s += cnt;
+ }
+ }
+ else { /* The font is not a standard 1-bit font */
+ charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ screen_row_hop = info->fix.line_length;
+ glyph_on_screen = info->screen_base +
+ screen_row_hop * image.dy +
+ 4 * image.dx;
+ /* While there are still characters to draw.. */
+ while (count--) {
+ code_point = scr_readw(s++) & charmask;
+ row_on_glyph_sheet = vc->vc_font.data +
+ cellsize * code_point;
+ /* Draw every row of the glyph */
+ row_on_screen = glyph_on_screen;
+ rows_left = vc->vc_font.height;
+ while( rows_left--)
+ {
+ /* If the background color is NOT black then do
+ * reverse video */
+ if ( 0 < bg) {
+ draw_glyph_row_inv( vc->vc_font.width,
+ row_on_glyph_sheet,
+ row_on_screen);
+ }
+ /* If the foreground color is high-intensity */
+ else if ( 8 <= fg) {
+ memcpy( row_on_screen,
+ row_on_glyph_sheet, width);
+ }
+ else {
+ draw_glyph_row_75( vc->vc_font.width,
+ row_on_glyph_sheet,
+ row_on_screen);
+ }
+ row_on_glyph_sheet += width;
+ row_on_screen += screen_row_hop;
+ }
+ glyph_on_screen += width;
+ }
}
/* buf is always NULL except when in monochrome mode, so in this case
@@ -234,6 +336,29 @@ static void bit_clear_margins(struct vc_
}
}
+static void bgra_cursor( struct vc_data *vc, struct fb_info *info, short c,
+ struct fb_cursor *cursor)
+{
+ u32 x = cursor->image.dx;
+ u32 y = cursor->image.dy;
+ u32 gw = vc->vc_font.width;
+ u32 gh = vc->vc_font.height;
+ u32 *pixel;
+
+ /* Draw the glyph to the screen */
+ bit_putcs( vc, info, &c, 1, y/gh, x/gw, 0, 0);
+
+ if ( cursor->enable) {
+ /* Invert the last row of pixels */
+ pixel = (u32*) ( info->screen_base +
+ info->fix.line_length * ( y + gh - 1) + 4 * x);
+ while ( gw--) {
+ *pixel ^= 0xffffffff;
+ ++ pixel;
+ }
+ }
+}
+
static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
int softback_lines, int fg, int bg)
{
@@ -245,6 +370,7 @@ static void bit_cursor(struct vc_data *v
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1;
char *src;
+ u8 std_font = *((u32*)vc->vc_font.data) != 0x6a127efd;
cursor.set = 0;
@@ -383,8 +509,14 @@ static void bit_cursor(struct vc_data *v
if (info->fbops->fb_cursor)
err = info->fbops->fb_cursor(info, &cursor);
- if (err)
- soft_cursor(info, &cursor);
+ if (err) {
+ if ( std_font) {
+ soft_cursor(info, &cursor);
+ }
+ else {
+ bgra_cursor( vc, info, c, &cursor);
+ }
+ }
ops->cursor_reset = 0;
}
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2552,7 +2552,8 @@ static int fbcon_set_font(struct vc_data
int size;
int i, csum;
u8 *new_data, *data = font->data;
- int pitch = (font->width+7) >> 3;
+ u8 std_font = *((u32*)data) != 0x6a127efd;
+ int pitch = std_font ? (font->width+7) >> 3 : 4 * font->width;
/* Is there a reason why fbconsole couldn't handle any charcount >256?
* If not this check should be changed to charcount < 256 */
@@ -2571,6 +2572,7 @@ static int fbcon_set_font(struct vc_data
size = h * pitch * charcount;
new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
+ DPRINTK(KERN_INFO "fbcon_set_font size:%d\n", size);
if (!new_data)
return -ENOMEM;
@@ -2579,8 +2581,14 @@ static int fbcon_set_font(struct vc_data
FNTSIZE(new_data) = size;
FNTCHARCNT(new_data) = charcount;
REFCOUNT(new_data) = 0; /* usage counter */
- for (i=0; i< charcount; i++) {
- memcpy(new_data + i*h*pitch, data + i*32*pitch, h*pitch);
+ if ( std_font) {
+ for (i=0; i< charcount; i++) {
+ memcpy(new_data + i*h*pitch, data + i*32*pitch,
+ h*pitch);
+ }
+ }
+ else {
+ memcpy( new_data, data, size);
}
/* Since linux has a nice crc32 function use it for counting font