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 <[email protected]>
Date: Thu, 9 Jul 2015 10:01:36 +0200
Subject: [PATCH] fbcon wip

Signed-off-by: Sascha Hauer <[email protected]>
---
 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 |

_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to