[RFC] WIP: video: implement quick-n-dirty framebuffer console

Sascha Hauer s.hauer at pengutronix.de
Thu Jul 9 01:16:39 PDT 2015


On Wed, Jul 08, 2015 at 12:15:39PM +0300, Antony Pavlov wrote:
> This patch realizes very simple framebuffer console for barebox.
> Minimal ANSI/VT100 Escape Sequence parser is used to ignore color
> change commands (based on GNU screen parser).
> 
> THere are several ANSI/VT100 parsers:
> 
>   * GNU screen (git://git.savannah.gnu.org/screen.git);
>   * st - simple terminal (http://git.suckless.org/st);
>   * or even mutt (https://github.com/karelzak/mutt-kz).
> 

Here's my WIP state based on your patch. It's probably worth to create a
function that takes a bw bitmap and a color and which renders the bitmap
to the screen with the given color. Also it might be worth to separate
the ANSI/VT100 parser to be able to share it between the EFI console
and fbcon.

Sascha

>From 59211105b2fdcdf6c1891edfa999d915ceba3bb3 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer at pengutronix.de>
Date: Thu, 9 Jul 2015 10:01:36 +0200
Subject: [PATCH] fbcon wip

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/video/fbconsole.c | 172 ++++++++++++++++++++++++++++++++--------------
 lib/gui/graphic_utils.c   |  21 +++++-
 2 files changed, 140 insertions(+), 53 deletions(-)

diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c
index 8ad4c2c..74592c5 100644
--- a/drivers/video/fbconsole.c
+++ b/drivers/video/fbconsole.c
@@ -15,6 +15,8 @@ enum state_t {
 	CSI,				/* Reading arguments in "CSI Pn ;...*/
 };
 
+u32 get_pixel(struct fb_info *info, u32 color);
+
 struct fbc_priv {
 	struct console_device cdev;
 	struct fb_info *fb;
@@ -25,49 +27,13 @@ struct fbc_priv {
 	unsigned int x, y; /* cursor position */
 
 	enum state_t state;
-};
-
-static struct image *char8x16_img(char *inbuf)
-{
-	struct image *img = calloc(1, sizeof(struct image));
-	int i;
-	uint32_t *p;
-
-	if (!img)
-		return ERR_PTR(-ENOMEM);
-
-	img->bits_per_pixel = 4 << 3;
-	img->data = calloc(1, sizeof(uint32_t) * VIDEO_FONT_WIDTH * VIDEO_FONT_HEIGHT);
-	img->height = VIDEO_FONT_HEIGHT;
-	img->width = VIDEO_FONT_WIDTH;
-
-	p = img->data;
-
-	for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
-		uint8_t t = inbuf[i];
-		int j;
 
-		for (j = 0; j < VIDEO_FONT_WIDTH; j++) {
-			if (t & 0x80) {
-				*p = 0xffffffff;
-			}
+	u32 color;
+	bool invert;
 
-			p++;
-			t <<= 1;
-		}
-	}
-
-	return img;
-}
-
-static void init_chars(struct image *chars[], int char_num)
-{
-	int i;
-
-	for (i = 0; i < char_num; i++) {
-		chars[i] = char8x16_img(&video_fontdata[i * VIDEO_FONT_HEIGHT]);
-	}
-}
+	int csipos;
+	u8 csi[20];
+};
 
 static int fbc_getc(struct console_device *cdev)
 {
@@ -82,39 +48,66 @@ static int fbc_tstc(struct console_device *cdev)
 static void drawchar(struct fbc_priv *priv, int x, int y, char c)
 {
 	void *buf;
+	int bpp = priv->fb->bits_per_pixel >> 3;
+	void *adr;
+	int i;
+	char *inbuf;
+	int line_length;
+	u32 color, bgcolor;
 
 	buf = gui_screen_redering_buffer(&priv->sc);
 
-	rgba_blend(priv->fb, priv->chars[(int)c],
-		buf, VIDEO_FONT_HEIGHT, VIDEO_FONT_WIDTH,
-		VIDEO_FONT_WIDTH * x, VIDEO_FONT_HEIGHT * y, 1);
+	inbuf = &video_fontdata[c * VIDEO_FONT_HEIGHT];
+
+	line_length = priv->fb->line_length;
+
+	color = priv->invert ? 0xff000000 : priv->color;
+	bgcolor = priv->invert ? priv->color : 0xff000000;
+
+	for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+		uint8_t t = inbuf[i];
+		int j;
+
+		adr = buf + line_length * (y * VIDEO_FONT_HEIGHT + i) + x * VIDEO_FONT_WIDTH * bpp;
+
+		for (j = 0; j < VIDEO_FONT_WIDTH; j++) {
+			if (t & 0x80)
+				set_pixel(priv->fb, adr, color);
+			else
+				set_pixel(priv->fb, adr, bgcolor);
+
+			adr += priv->fb->bits_per_pixel >> 3;
+			t <<= 1;
+		}
+	}
 }
 
-/* FIXME */
-static void blankchar(struct fbc_priv *priv, int x, int y)
+void invert_area(struct fb_info *info, void *buf, int startx, int starty, int width,
+		int height);
+
+static void video_invertchar(struct fbc_priv *priv, int x, int y)
 {
 	void *buf;
 
 	buf = gui_screen_redering_buffer(&priv->sc);
 
-	rgba_blend(priv->fb, priv->chars[' '],
-		buf, VIDEO_FONT_HEIGHT, VIDEO_FONT_WIDTH,
-		VIDEO_FONT_WIDTH * x, VIDEO_FONT_HEIGHT * y, 0);
+	invert_area(priv->fb, buf, x * VIDEO_FONT_WIDTH, y * VIDEO_FONT_HEIGHT,
+			VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
 }
 
 static void printchar(struct fbc_priv *priv, int c)
 {
+	video_invertchar(priv, priv->x, priv->y);
+
 	switch (c) {
 	case '\007': /* bell: ignore */
 		break;
 	case '\b':
 		if (priv->x > 0) {
 			priv->x--;
-			blankchar(priv, priv->x, priv->y);
 		} else if (priv->y > 0) {
 			priv->x = priv->cols;
 			priv->y--;
-			blankchar(priv, priv->x, priv->y);
 		}
 		break;
 	case '\n':
@@ -126,6 +119,10 @@ static void printchar(struct fbc_priv *priv, int c)
 		priv->x = 0;
 		break;
 
+	case '\t':
+		priv->x = (priv->x + 8) & ~0x3;
+		break;
+
 	default:
 		drawchar(priv, priv->x, priv->y, c);
 		screen_blit(&priv->sc);
@@ -150,9 +147,75 @@ static void printchar(struct fbc_priv *priv, int c)
 		priv->y = priv->rows;
 	}
 
+	video_invertchar(priv, priv->x, priv->y);
+
 	return;
 }
 
+static void fbc_parse_csi(struct fbc_priv *priv)
+{
+	int a, b = -1;
+	char *end;
+
+	a = simple_strtoul(priv->csi, &end, 10);
+	if (*end == ';')
+		b = simple_strtoul(end + 1, &end, 10);
+
+	if (*end == 'm' && b == -1) {
+		switch (a) {
+		case 0:
+			priv->color = 0xffffffff;
+			priv->invert = false;
+			break;
+		case 7:
+			priv->invert = true;
+			break;
+		}
+		return;
+	}
+
+	if (*end == 'J' && a == 2 && b == -1) {
+		void *buf = gui_screen_redering_buffer(&priv->sc);
+
+		memset(buf, 0, priv->fb->line_length * priv->fb->yres);
+
+		priv->x = 0;
+		priv->y = 0;
+		video_invertchar(priv, priv->x, priv->y);
+	}
+
+	if (*end == 'm' && a == 1) {
+		switch (b) {
+		case 32:
+			priv->color = get_pixel(priv->fb, 0xff00ff00);
+			break;
+		case 31:
+			priv->color = get_pixel(priv->fb, 0xffff0000);
+			break;
+		case 34:
+			priv->color = get_pixel(priv->fb, 0xff0000ff);
+			break;
+		case 36:
+			priv->color = get_pixel(priv->fb, 0xff54ffff);
+			break;
+		case 37:
+			priv->color = get_pixel(priv->fb, 0xffffffff);
+			break;
+		default:
+			break;
+		}
+		return;
+	}
+
+	if (*end == 'H') {
+		video_invertchar(priv, priv->x, priv->y);
+		priv->x = b - 1;
+		priv->y = a - 1;
+		video_invertchar(priv, priv->x, priv->y);
+		return;
+	}
+}
+
 static void fbc_putc(struct console_device *cdev, char c)
 {
 	struct fbc_priv *priv = container_of(cdev,
@@ -172,10 +235,14 @@ static void fbc_putc(struct console_device *cdev, char c)
 		switch (c) {
 		case '[':
 			priv->state = CSI;
+			priv->csipos = 0;
+			memset(priv->csi, 0, 6);
 			break;
 		}
 		break;
 	case CSI:
+		priv->csi[priv->csipos++] = c;
+
 		switch (c) {
 		case '0':
 		case '1':
@@ -191,6 +258,7 @@ static void fbc_putc(struct console_device *cdev, char c)
 		case ':':
 			break;
 		default:
+			fbc_parse_csi(priv);
 			priv->state = LIT;
 		}
 		break;
@@ -235,7 +303,7 @@ int register_fbconsole(struct fb_info *fb)
 	priv->fb = fb;
 	priv->x = 0;
 	priv->y = 0;
-	init_chars(priv->chars, VIDEO_FONT_CHARS);
+	priv->color = 0xff00ff00;
 
 	cdev = &priv->cdev;
 	cdev->dev = &fb->dev;
diff --git a/lib/gui/graphic_utils.c b/lib/gui/graphic_utils.c
index 6465f8e..5f492c8 100644
--- a/lib/gui/graphic_utils.c
+++ b/lib/gui/graphic_utils.c
@@ -7,7 +7,7 @@
 #include <fs.h>
 #include <malloc.h>
 
-static u32 get_pixel(struct fb_info *info, u32 color)
+u32 get_pixel(struct fb_info *info, u32 color)
 {
 	u32 px;
 	u8 t = (color >> 24) & 0xff;
@@ -128,6 +128,25 @@ static u8 alpha_mux(int s, int d, int a)
 	return (d * a + s * (255 - a)) >> 8;
 }
 
+void invert_area(struct fb_info *info, void *buf, int startx, int starty, int width,
+		int height)
+{
+	unsigned char *adr;
+	int x, y;
+	int line_length;
+	int bpp = info->bits_per_pixel >> 3;
+
+	line_length = info->line_length;
+
+	for (y = starty; y < starty + height; y++) {
+		adr = buf + line_length * y + startx * bpp;
+
+		for (x = 0; x < width * bpp; x++) {
+			*adr++ ^= 0xff;
+		}
+	}
+}
+
 void set_rgba_pixel(struct fb_info *info, void *adr, u8 r, u8 g, u8 b, u8 a)
 {
 	u32 px = 0x0;
-- 
2.1.4

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



More information about the barebox mailing list