os-workshop

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Alibgfx/inc/gfx/gfx.h | 44++++++++++++++++++++++++++++++++++++++++++++
Alibgfx/src/gfx.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aproject/gfx.lib.mk | 7+++++++
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