From 1a32b8a72d88530133bc31eb19632f0b353408f8 Mon Sep 17 00:00:00 2001
From: Mateusz Zalega <mateusz@appliedsourcery.com>
Date: Sun, 11 Aug 2019 16:08:48 +0200
Subject: [PATCH] bootloader: moved RLE decoding code to lib/gfx
Signed-off-by: Mateusz Zalega <mateusz@appliedsourcery.com>
---
bootloader/bootloader-display.c | 25 +--------
epicardium/main.c | 5 +-
hw-tests/dual-core/main.c | 5 +-
hw-tests/hello-world/main.c | 5 +-
hw-tests/ips/main.c | 10 ++--
lib/gfx/gfx.c | 96 ++++++++++++++++++++++++++++++++-
lib/gfx/gfx.h | 11 +++-
7 files changed, 120 insertions(+), 37 deletions(-)
diff --git a/bootloader/bootloader-display.c b/bootloader/bootloader-display.c
index 7bdbc4e1..45010943 100644
--- a/bootloader/bootloader-display.c
+++ b/bootloader/bootloader-display.c
@@ -6,31 +6,10 @@
#include "gfx.h"
#include "display.h"
-/*
- * "Decompress" splash-screen image. The algorithm works as follows:
- *
- * Each byte encodes up to 127 pixels in either white or black. The most
- * significant bit determines the color, the remaining 7 bits determine the
- * amount.
- */
static void bootloader_display_splash(void)
{
- int idx = 0;
-
- Color white = gfx_color(&display_screen, WHITE);
- Color black = gfx_color(&display_screen, BLACK);
- for (int i = 0; i < sizeof(splash); i++) {
- Color color = (splash[i] & 0x80) ? white : black;
- uint8_t length = splash[i] & 0x7f;
-
- for (int j = 0; j < length; j++) {
- uint16_t x = idx % 160;
- uint16_t y = idx / 160;
- gfx_setpixel(&display_screen, x, y, color);
- idx++;
- }
- }
-
+ gfx_copy_region(&display_screen, 0, 0, 160, 80, GFX_RLE_MONO,
+ sizeof(splash), (const void *)(splash));
gfx_update(&display_screen);
}
diff --git a/epicardium/main.c b/epicardium/main.c
index 56f532a6..249ff109 100644
--- a/epicardium/main.c
+++ b/epicardium/main.c
@@ -53,8 +53,9 @@ int main(void)
card10_init();
card10_diag();
- gfx_copy_region_raw(
- &display_screen, 0, 0, 160, 80, 2, (const void *)(Heart)
+ gfx_copy_region(
+ &display_screen, 0, 0, 160, 80, GFX_RAW, sizeof(Heart),
+ (const void *)(Heart)
);
gfx_update(&display_screen);
diff --git a/hw-tests/dual-core/main.c b/hw-tests/dual-core/main.c
index 60636833..b8450343 100644
--- a/hw-tests/dual-core/main.c
+++ b/hw-tests/dual-core/main.c
@@ -22,8 +22,9 @@ int main(void)
card10_init();
card10_diag();
- gfx_copy_region_raw(
- &display_screen, 0, 0, 160, 80, 2, (const void *)(Heart)
+ gfx_copy_region(
+ &display_screen, 0, 0, 160, 80, GFX_RAW, sizeof(Heart),
+ (const void *)(Heart)
);
gfx_update(&display_screen);
diff --git a/hw-tests/hello-world/main.c b/hw-tests/hello-world/main.c
index 87fdab3b..79007e14 100644
--- a/hw-tests/hello-world/main.c
+++ b/hw-tests/hello-world/main.c
@@ -30,8 +30,9 @@ int main(void)
card10_init();
card10_diag();
- gfx_copy_region_raw(
- &display_screen, 0, 0, 160, 80, 2, (const void *)(Heart)
+ gfx_copy_region(
+ &display_screen, 0, 0, 160, 80, GFX_RAW, sizeof(Heart),
+ (const void *)(Heart)
);
gfx_update(&display_screen);
diff --git a/hw-tests/ips/main.c b/hw-tests/ips/main.c
index 6aa51eae..b638a783 100644
--- a/hw-tests/ips/main.c
+++ b/hw-tests/ips/main.c
@@ -37,22 +37,24 @@ int main(void)
gfx_line(&display_screen, 100, 10, 70, 40, 2, yellow);
gfx_circle(&display_screen, 85, 25, 22, 2, green);
- gfx_copy_region_raw(
+ gfx_copy_region(
&display_screen,
120,
0,
40,
40,
- 2,
+ GFX_RAW,
+ 40 * 40 * 2,
(const void *)(gImage_40X40)
);
- gfx_copy_region_raw(
+ gfx_copy_region(
&display_screen,
0,
0,
160,
80,
- 2,
+ GFX_RAW,
+ 160 * 80 * 2,
(const void *)(gImage_160X80)
);
gfx_update(&display_screen);
diff --git a/lib/gfx/gfx.c b/lib/gfx/gfx.c
index 72a5d67f..704fb9af 100644
--- a/lib/gfx/gfx.c
+++ b/lib/gfx/gfx.c
@@ -265,15 +265,17 @@ Color gfx_color(struct gfx_region *reg, enum gfx_color color)
return gfx_color_rgb(reg, c->r, c->g, c->b);
}
-void gfx_copy_region_raw(
+static void gfx_copy_region_raw(
struct gfx_region *reg,
int x,
int y,
int w,
int h,
- size_t bpp,
+ size_t size,
const void *p
) {
+ size_t bpp = size / (w * h);
+
for (int y_ = 0; y_ < h; y_++) {
for (int x_ = 0; x_ < w; x_++) {
Color c;
@@ -291,6 +293,96 @@ void gfx_copy_region_raw(
}
}
+static void gfx_copy_region_mono(
+ struct gfx_region *reg,
+ int x,
+ int y,
+ int w,
+ int h,
+ size_t size,
+ const void *p
+) {
+ const char *bp = p;
+ int bit = 0;
+ Color white = gfx_color(reg, WHITE);
+ Color black = gfx_color(reg, BLACK);
+
+ for (int y_ = 0; y_ < h; y_++) {
+ for (int x_ = 0; x_ < w; x_++) {
+ int value = *bp & (1 << bit);
+ if (++bit >= 8) {
+ bp++;
+ bit %= 8;
+
+ if ((const void *)(bp) >= (p + size))
+ return;
+ }
+
+ Color c = value ? white : black;
+ gfx_setpixel(reg, x + x_, y + y_, c);
+ }
+ }
+}
+
+/*
+ * "Decompress" the image. The algorithm works as follows:
+ *
+ * Each byte encodes up to 127 pixels in either white or black. The most
+ * significant bit determines the color, the remaining 7 bits determine the
+ * amount.
+ */
+static void gfx_copy_region_rle_mono(
+ struct gfx_region *reg,
+ int x,
+ int y,
+ int w,
+ int h,
+ size_t size,
+ const void *p
+) {
+ const char *data = p;
+ int idx = 0;
+ Color white = gfx_color(reg, WHITE);
+ Color black = gfx_color(reg, BLACK);
+
+ for (int i = 0; i < size; i++) {
+ Color color = (data[i] & 0x80) ? white : black;
+ uint8_t length = data[i] & 0x7f;
+
+ for (int j = 0; j < length; j++) {
+ uint16_t x = idx % w;
+ uint16_t y = idx / w;
+ gfx_setpixel(reg, x, y, color);
+ idx++;
+ }
+ }
+}
+
+void gfx_copy_region(
+ struct gfx_region *reg,
+ int x,
+ int y,
+ int w,
+ int h,
+ enum gfx_encoding encoding,
+ size_t size,
+ const void *p
+) {
+ switch (encoding) {
+ case GFX_RAW:
+ gfx_copy_region_raw(reg, x, y, w, h, size, p);
+ break;
+ case GFX_MONO:
+ gfx_copy_region_mono(reg, x, y, w, h, size, p);
+ break;
+ case GFX_RLE_MONO:
+ gfx_copy_region_rle_mono(reg, x, y, w, h, size, p);
+ break;
+ default:
+ break;
+ }
+}
+
void gfx_copy_raw(struct gfx_region *reg, const void *p, size_t size)
{
fb_copy_raw(reg->fb, p, size);
diff --git a/lib/gfx/gfx.h b/lib/gfx/gfx.h
index 428b196c..fda9d845 100644
--- a/lib/gfx/gfx.h
+++ b/lib/gfx/gfx.h
@@ -43,6 +43,12 @@ enum gfx_color {
COLORS
};
+enum gfx_encoding {
+ GFX_RAW,
+ GFX_MONO,
+ GFX_RLE_MONO
+};
+
struct gfx_color_rgb {
uint8_t r;
uint8_t g;
@@ -51,8 +57,9 @@ struct gfx_color_rgb {
Color gfx_color(struct gfx_region *reg, enum gfx_color color);
-void gfx_copy_region_raw(struct gfx_region *reg, int x, int y, int w, int h,
- size_t bpp, const void *p);
+void gfx_copy_region(struct gfx_region *reg, int x, int y, int w, int h,
+ enum gfx_encoding encoding, size_t size,
+ const void *p);
void gfx_copy_raw(struct gfx_region *reg, const void *p, size_t size);
#endif
--
GitLab