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

Antony Pavlov antonynpavlov at gmail.com
Thu Jul 9 02:47:06 PDT 2015


On Thu, 9 Jul 2015 10:16:39 +0200
Sascha Hauer <s.hauer at pengutronix.de> wrote:

> 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.


Thanks!

I'll try you patch as soon as possible.

I have not known about EFI console ANSI/VT100 parser until now.
I'll take a look on it too.


> 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 |


-- 
-- 
Best regards,
  Antony Pavlov



More information about the barebox mailing list