:: commit 1ea09891bcb303d01b77d6d659424b40479475bb

mintsuki <mintsuki@protonmail.com> — 2020-09-30 15:29

parents: 53eb16b835

VBE: Add margin gradient

diff --git a/limine.bin b/limine.bin
index d95d865b..79fd1a85 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/drivers/vbe.c b/stage2/drivers/vbe.c
index 08d8f831..b57148f5 100644
--- a/stage2/drivers/vbe.c
+++ b/stage2/drivers/vbe.c
@@ -55,6 +55,7 @@ static uint32_t text_bg;
 
 static int rows;
 static int cols;
+static int margin_gradient;
 
 #define A(rgb) (uint8_t)(rgb >> 24)
 #define R(rgb) (uint8_t)(rgb >> 16)
@@ -85,11 +86,49 @@ static void _vbe_plot_bg_blent_px(int x, int y, uint32_t hex) {
 
 void (*vbe_plot_bg_blent_px)(int x, int y, uint32_t hex) = vbe_plot_px;
 
+static uint32_t blend_gradient_from_box(int x, int y, uint32_t hex) {
+    if (x >= frame_width  && x < frame_width  + VGA_FONT_WIDTH  * cols
+     && y >= frame_height && y < frame_height + VGA_FONT_HEIGHT * rows) {
+        return hex;
+    }
+
+    int distance, x_distance, y_distance;
+
+    if (x < frame_width)
+        x_distance = frame_width - x;
+    else
+        x_distance = x - (frame_width + VGA_FONT_WIDTH * cols);
+
+    if (y < frame_height)
+        y_distance = frame_height - y;
+    else
+        y_distance = y - (frame_height + VGA_FONT_HEIGHT * rows);
+
+    if (x >= frame_width && x < frame_width + VGA_FONT_WIDTH * cols) {
+        distance = y_distance;
+    } else if (y >= frame_height && y < frame_height + VGA_FONT_HEIGHT * rows) {
+        distance = x_distance;
+    } else {
+        distance = sqrt((uint64_t)x_distance * (uint64_t)x_distance
+                      + (uint64_t)y_distance * (uint64_t)y_distance);
+    }
+
+    uint32_t bg_px = background->get_pixel(background, x, y);
+
+    if (distance > margin_gradient)
+        return bg_px;
+
+    uint8_t gradient_step = (0xff - A(hex)) / margin_gradient;
+    uint8_t new_alpha     = A(hex) + gradient_step * distance;
+
+    return colour_blend((hex & 0xffffff) | (new_alpha << 24), bg_px);
+}
+
 void vbe_plot_background(int x, int y, int width, int height) {
     if (background) {
         for (int yy = 0; yy < height; yy++) {
             for (int xx = 0; xx < width; xx++) {
-                vbe_plot_px(x + xx, y + yy, background->get_pixel(background, x + xx, y + yy));
+                vbe_plot_px(x + xx, y + yy, blend_gradient_from_box(xx, yy, text_bg));
             }
         }
     } else {
@@ -273,7 +312,7 @@ void vbe_putchar(char c) {
     }
 }
 
-void vbe_tty_init(int *_rows, int *_cols, uint32_t *_colours, int _margin, struct image *_background) {
+void vbe_tty_init(int *_rows, int *_cols, uint32_t *_colours, int _margin, int _margin_gradient, struct image *_background) {
     init_vbe(&vbe_framebuffer, &vbe_pitch, &vbe_width, &vbe_height, &vbe_bpp);
 
     mtrr_set_range((uint64_t)(size_t)vbe_framebuffer,
@@ -292,6 +331,8 @@ void vbe_tty_init(int *_rows, int *_cols, uint32_t *_colours, int _margin, struc
     text_bg = ansi_colours[0];
     text_fg = ansi_colours[7];
 
+    margin_gradient = _margin_gradient;
+
     frame_height = vbe_height / 2 - (VGA_FONT_HEIGHT * rows) / 2;
     frame_width  = vbe_width  / 2 - (VGA_FONT_WIDTH  * cols) / 2;
 
diff --git a/stage2/drivers/vbe.h b/stage2/drivers/vbe.h
index 1150e11c..faefe05a 100644
--- a/stage2/drivers/vbe.h
+++ b/stage2/drivers/vbe.h
@@ -7,7 +7,7 @@
 
 int init_vbe(uint32_t **framebuffer, uint16_t *pitch, uint16_t *target_width, uint16_t *target_height, uint16_t *target_bpp);
 
-void vbe_tty_init(int *rows, int *cols, uint32_t *colours, int margin, struct image *background);
+void vbe_tty_init(int *rows, int *cols, uint32_t *colours, int margin, int margin_gradient, struct image *background);
 
 void vbe_putchar(char c);
 void vbe_clear(bool move);
diff --git a/stage2/lib/blib.c b/stage2/lib/blib.c
index d98014ef..b74a3b57 100644
--- a/stage2/lib/blib.c
+++ b/stage2/lib/blib.c
@@ -10,6 +10,30 @@
 #include <sys/e820.h>
 #include <lib/print.h>
 
+// This integer sqrt implementation has been adapted from:
+// https://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2
+uint64_t sqrt(uint64_t a_nInput) {
+    uint64_t op  = a_nInput;
+    uint64_t res = 0;
+    uint64_t one = (uint64_t)1 << 62;
+
+    // "one" starts at the highest power of four <= than the argument.
+    while (one > op) {
+        one >>= 2;
+    }
+
+    while (one != 0) {
+        if (op >= res + one) {
+            op = op - (res + one);
+            res = res +  2 * one;
+        }
+        res >>= 1;
+        one >>= 2;
+    }
+
+    return res;
+}
+
 uint8_t bcd_to_int(uint8_t val) {
     return (val & 0x0f) + ((val & 0xf0) >> 4) * 10;
 }
diff --git a/stage2/lib/blib.h b/stage2/lib/blib.h
index 015d5839..49577df1 100644
--- a/stage2/lib/blib.h
+++ b/stage2/lib/blib.h
@@ -4,6 +4,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+uint64_t sqrt(uint64_t a_nInput);
+
 uint8_t bcd_to_int(uint8_t val);
 
 int cpuid(uint32_t leaf, uint32_t subleaf,
diff --git a/stage2/lib/term.c b/stage2/lib/term.c
index 51a0c555..2eb660a4 100644
--- a/stage2/lib/term.c
+++ b/stage2/lib/term.c
@@ -24,9 +24,9 @@ void (*set_text_bg)(int bg);
 
 static int rows, cols;
 
-void term_vbe(uint32_t *colours, int margin, struct image *background) {
+void term_vbe(uint32_t *colours, int margin, int margin_gradient, struct image *background) {
     term_deinit();
-    vbe_tty_init(&rows, &cols, colours, margin, background);
+    vbe_tty_init(&rows, &cols, colours, margin, margin_gradient, background);
 
     raw_putchar    = vbe_putchar;
     clear          = vbe_clear;
diff --git a/stage2/lib/term.h b/stage2/lib/term.h
index ba7e8d67..9d7e967d 100644
--- a/stage2/lib/term.h
+++ b/stage2/lib/term.h
@@ -14,7 +14,7 @@ extern void (*get_cursor_pos)(int *x, int *y);
 extern void (*set_text_fg)(int fg);
 extern void (*set_text_bg)(int bg);
 
-void term_vbe(uint32_t *colours, int margin, struct image *background);
+void term_vbe(uint32_t *colours, int margin, int margin_gradient, struct image *background);
 void term_textmode(void);
 void term_deinit(void);
 void term_write(const char *buf, size_t count);
diff --git a/stage2/menu.c b/stage2/menu.c
index 636ef501..180eea1f 100644
--- a/stage2/menu.c
+++ b/stage2/menu.c
@@ -38,6 +38,7 @@ char *menu(int boot_drive) {
     if (config_get_value(buf, 0, 16, "GRAPHICS") && !strcmp(buf, "yes")) {
         // default scheme
         int margin = 64;
+        int margin_gradient = 20;
         uint32_t colourscheme[] = {
             0x00000000, // black
             0x00aa0000, // red
@@ -85,6 +86,10 @@ char *menu(int boot_drive) {
             margin = (int)strtoui(buf);
         }
 
+        if (config_get_value(buf, 0, 16, "THEME_MARGIN_GRADIENT")) {
+            margin_gradient = (int)strtoui(buf);
+        }
+
         int bg_drive;
         if (!config_get_value(buf, 0, 16, "BACKGROUND_DRIVE")) {
             bg_drive = boot_drive;
@@ -108,11 +113,11 @@ char *menu(int boot_drive) {
         if (open_image(bg, bg_file))
             goto nobg;
 
-        term_vbe(colourscheme, margin, bg);
+        term_vbe(colourscheme, margin, margin_gradient, bg);
         goto yesbg;
 
     nobg:
-        term_vbe(colourscheme, margin, NULL);
+        term_vbe(colourscheme, margin, margin_gradient, NULL);
 
     yesbg:;
     }
tab: 248 wrap: offon