commit 260fe9bf03b2f554a46b5d8f3775c8eb2722b097
parent 2aee99583589e1bbc9133b45b039ae038bd35a68
Author: Brian Swetland <swetland@frotz.net>
Date: Wed, 11 May 2022 23:24:20 -0700
libgfx: add a very simple drawing library
- only handles one pixel format for now
- can draw points, horizontal lines, or 8x16 bitmap characters
Diffstat:
3 files changed, 158 insertions(+), 0 deletions(-)
diff --git a/libgfx/inc/gfx/gfx.h b/libgfx/inc/gfx/gfx.h
@@ -0,0 +1,44 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+#pragma once
+
+#include <stdint.h>
+
+typedef struct gfx_surface gfx_surface_t;
+
+struct gfx_surface {
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ void *pixels;
+
+ uint32_t pixfmt;
+ uint32_t fgcolor;
+ uint32_t bgcolor;
+ uint32_t reserved;
+
+ void (*plot)(gfx_surface_t* gs, uint32_t x, uint32_t y);
+ void (*hline)(gfx_surface_t* gs, uint32_t x0, uint32_t y, uint32_t x1);
+ void (*putc)(gfx_surface_t* gs, uint32_t x, uint32_t y, uint32_t ch);
+};
+
+#define PIXFMT_RGB565 0x03000565
+
+void gfx_init_display(gfx_surface_t *gs);
+void gfx_init(gfx_surface_t* gs);
+
+static inline void gfx_plot(gfx_surface_t* gs, uint32_t x, uint32_t y) {
+ gs->plot(gs, x, y);
+}
+
+static inline void gfx_hline(gfx_surface_t* gs, uint32_t x0, uint32_t y, uint32_t x1) {
+ gs->hline(gs, x0, y, x1);
+}
+
+static inline void gfx_putc(gfx_surface_t* gs, uint32_t x, uint32_t y, uint32_t ch) {
+ gs->putc(gs, x, y, ch);
+}
+
+void gfx_puts(gfx_surface_t* gs, uint32_t x, uint32_t y, const char* s);
+void gfx_printf(gfx_surface_t* gs, uint32_t x, uint32_t y, const char* fmt, ...);
diff --git a/libgfx/src/gfx.c b/libgfx/src/gfx.c
@@ -0,0 +1,107 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <gfx/gfx.h>
+#include <compiler.h>
+#include <hw/platform.h>
+
+extern uint8_t vga_rom_16[256 * 16];
+
+#define CH_ROM vga_rom_16
+#define CH_WIDTH 8
+#define CH_HEIGHT 16
+
+// drawing routines for unknown pixfmt
+static void plot0(gfx_surface_t *gs, uint32_t x, uint32_t y) {}
+static void hline0(gfx_surface_t *gs, uint32_t x0, uint32_t y, uint32_t x1) {}
+static void putc0(gfx_surface_t *gs, uint32_t x, uint32_t y, uint32_t c) {}
+
+// drawing routines for 16bpp pixfmt
+static void plot16(gfx_surface_t *gs, uint32_t x, uint32_t y) {
+ if (unlikely((x >= gs->width) || (y >= gs->height))) {
+ return;
+ }
+ ((uint16_t*) (gs->pixels))[x + y * gs->stride] = gs->fgcolor;
+}
+
+static void hline16(gfx_surface_t *gs, uint32_t x0, uint32_t y, uint32_t x1) {
+ if (unlikely((x0 >= gs->width) || (y >= gs->height) || (x1 <= x0))) {
+ return;
+ }
+ if (unlikely((x1 > gs->width))) {
+ x1 = gs->width;
+ }
+ uint16_t *pixels = gs->pixels + x0 + y * gs->stride;
+ uint16_t *end = pixels + x1 - x0;
+ uint32_t c = gs->fgcolor;
+ while (pixels < end) {
+ *pixels++ = c;
+ }
+}
+
+static void putc16(gfx_surface_t *gs, uint32_t x, uint32_t y, uint32_t ch) {
+ if (unlikely((x >= gs->width) || ((x + CH_WIDTH) > gs->width) ||
+ (y >= gs->height) || ((y + CH_HEIGHT) > gs->height))) {
+ return;
+ }
+
+ ch = (ch & 0xFF) * CH_HEIGHT;
+ uint32_t fg = gs->fgcolor;
+ uint32_t bg = gs->bgcolor;
+ uint16_t *pixels = ((uint16_t*)gs->pixels) + x + y * gs->stride;
+ uint32_t stride = gs->stride - CH_WIDTH;
+ for (y = 0; y < CH_HEIGHT; y++) {
+ uint32_t bits = CH_ROM[ch++];
+ for (x = 0; x < CH_WIDTH; x++) {
+ *pixels++ = (bits & 0x80) ? fg : bg;
+ bits <<= 1;
+ }
+ pixels += stride;
+ }
+}
+
+void gfx_init(gfx_surface_t *gs) {
+ switch (gs->pixfmt) {
+ case PIXFMT_RGB565:
+ gs->plot = plot16;
+ gs->hline = hline16;
+ gs->putc = putc16;
+ break;
+ default:
+ gs->plot = plot0;
+ gs->hline = hline0;
+ gs->putc = putc0;
+ break;
+ }
+}
+
+void gfx_init_display(gfx_surface_t *gs) {
+ gs->width = 640;
+ gs->height = 480;
+ gs->stride = 640;
+ gs->pixels = (void*) FRAMEBUFFER_BASE;
+ gs->pixfmt = PIXFMT_RGB565;
+ gs->fgcolor = 0xFFFF;
+ gs->bgcolor = 0x0000;
+ gfx_init(gs);
+}
+
+void gfx_puts(gfx_surface_t *gs, uint32_t x, uint32_t y, const char* s) {
+ while (*s) {
+ gs->putc(gs, x, y, *s++);
+ x += CH_WIDTH;
+ }
+}
+
+void gfx_printf(gfx_surface_t* gs, uint32_t x, uint32_t y, const char* fmt, ...) {
+ char msg[128];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(msg, sizeof(msg), fmt, ap);
+ va_end(ap);
+ gfx_puts(gs, x, y, msg);
+}
+
diff --git a/project/gfx.lib.mk b/project/gfx.lib.mk
@@ -0,0 +1,7 @@
+
+MOD_NAME := gfx
+MOD_SRC := libgfx/src/gfx.c
+MOD_SRC += external/vgafonts.c
+MOD_LIB := c
+
+include make/lib.mk