gfx.c (3398B)
1 // Copyright 2022, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0 3 4 #include <stdio.h> 5 #include <stdarg.h> 6 7 #include <gfx/gfx.h> 8 #include <compiler.h> 9 #include <hw/platform.h> 10 11 extern uint8_t vga_rom_16[256 * 16]; 12 13 #define CH_ROM vga_rom_16 14 #define CH_WIDTH 8 15 #define CH_HEIGHT 16 16 17 // drawing routines for unknown pixfmt 18 static uint32_t color0(gfx_surface_t *gs, uint32_t c) { return 0; } 19 static void plot0(gfx_surface_t *gs, uint32_t x, uint32_t y, uint32_t pxl) {} 20 static void hline0(gfx_surface_t *gs, uint32_t x0, uint32_t y, uint32_t x1, uint32_t pxl) {} 21 static void putc0(gfx_surface_t *gs, uint32_t x, uint32_t y, uint32_t c) {} 22 23 // drawing routines for 16bpp pixfmt 24 static uint32_t color16(gfx_surface_t *gs, uint32_t c) { 25 return ((c >> 3) & 0x1F) | 26 (((c >> 10) & 0x3F) << 5) | 27 (((c >> 19) & 0x1F) << 11); 28 } 29 30 static void plot16(gfx_surface_t *gs, uint32_t x, uint32_t y, uint32_t pxl) { 31 if (unlikely((x >= gs->width) || (y >= gs->height))) { 32 return; 33 } 34 ((uint16_t*) (gs->pixels))[x + y * gs->stride] = pxl; 35 } 36 37 static void hline16(gfx_surface_t *gs, uint32_t x0, uint32_t y, uint32_t x1, uint32_t pxl) { 38 if (unlikely((x0 >= gs->width) || (y >= gs->height) || (x1 <= x0))) { 39 return; 40 } 41 if (unlikely((x1 > gs->width))) { 42 x1 = gs->width; 43 } 44 uint16_t *pixels = ((uint16_t*)gs->pixels) + x0 + y * gs->stride; 45 uint16_t *end = pixels + x1 - x0; 46 while (pixels < end) { 47 *pixels++ = pxl; 48 } 49 } 50 51 static void putc16(gfx_surface_t *gs, uint32_t x, uint32_t y, uint32_t ch) { 52 if (unlikely((x >= gs->width) || ((x + CH_WIDTH) > gs->width) || 53 (y >= gs->height) || ((y + CH_HEIGHT) > gs->height))) { 54 return; 55 } 56 57 ch = (ch & 0xFF) * CH_HEIGHT; 58 uint32_t fg = gs->fgcolor; 59 uint32_t bg = gs->bgcolor; 60 uint16_t *pixels = ((uint16_t*)gs->pixels) + x + y * gs->stride; 61 uint32_t stride = gs->stride - CH_WIDTH; 62 for (y = 0; y < CH_HEIGHT; y++) { 63 uint32_t bits = CH_ROM[ch++]; 64 for (x = 0; x < CH_WIDTH; x++) { 65 *pixels++ = (bits & 0x80) ? fg : bg; 66 bits <<= 1; 67 } 68 pixels += stride; 69 } 70 } 71 72 void gfx_init(gfx_surface_t *gs) { 73 switch (gs->pixfmt) { 74 case PIXFMT_RGB565: 75 gs->plot = plot16; 76 gs->hline = hline16; 77 gs->putc = putc16; 78 gs->color = color16; 79 break; 80 default: 81 gs->plot = plot0; 82 gs->hline = hline0; 83 gs->putc = putc0; 84 gs->color = color0; 85 break; 86 } 87 } 88 89 void gfx_init_display(gfx_surface_t *gs) { 90 gs->width = 640; 91 gs->height = 480; 92 gs->stride = 640; 93 gs->pixels = (void*) FRAMEBUFFER_BASE; 94 gs->pixfmt = PIXFMT_RGB565; 95 gfx_init(gs); 96 gs->fgcolor = gs->color(gs, C_WHITE); 97 gs->bgcolor = gs->color(gs, C_BLACK); 98 } 99 100 void gfx_setcolor(gfx_surface_t* gs, uint32_t fg_argb8888, uint32_t bg_argb8888) { 101 gs->fgcolor = gs->color(gs, fg_argb8888); 102 gs->bgcolor = gs->color(gs, bg_argb8888); 103 } 104 105 void gfx_fill(gfx_surface_t* gs, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t pxl) { 106 while (y0 < y1) { 107 gs->hline(gs, x0, y0, x1, pxl); 108 y0++; 109 } 110 } 111 112 void gfx_clear(gfx_surface_t* gs, uint32_t pxl) { 113 gfx_fill(gs, 0, 0, gs->width, gs->height, pxl); 114 } 115 116 void gfx_puts(gfx_surface_t *gs, uint32_t x, uint32_t y, const char* s) { 117 while (*s) { 118 gs->putc(gs, x, y, *s++); 119 x += CH_WIDTH; 120 } 121 } 122 123 void gfx_printf(gfx_surface_t* gs, uint32_t x, uint32_t y, const char* fmt, ...) { 124 char msg[128]; 125 va_list ap; 126 va_start(ap, fmt); 127 vsnprintf(msg, sizeof(msg), fmt, ap); 128 va_end(ap); 129 gfx_puts(gs, x, y, msg); 130 } 131