[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