From 00cc8736f10098dedf6b856b9ad8bd0094211263 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Thu, 18 Feb 2021 11:56:08 -0500 Subject: vbe support, truecolor window manager pixbufs --- src/kernel/log.c | 10 ++++- src/kernel/main.c | 28 ++++++++++++ src/kernel/vbe.h | 71 +++++++++++++++++++++++++++++ src/kernel/window.c | 126 ++++++++++++++++++++++++++++++---------------------- src/kernel/window.h | 13 ++++-- 5 files changed, 191 insertions(+), 57 deletions(-) create mode 100644 src/kernel/vbe.h (limited to 'src/kernel') diff --git a/src/kernel/log.c b/src/kernel/log.c index 6bad1cc..2819a2e 100644 --- a/src/kernel/log.c +++ b/src/kernel/log.c @@ -52,8 +52,16 @@ void logf(enum log_level level, const char *format, ...) { while (*s) logch(*(s++)); break; + case 'n':; + uint32_t d = va_arg(args, uint32_t); + if (d >= 0x80000000) { + logch('-'); + d = -d; + } + goto put_dec; case 'd':; - const uint32_t d = va_arg(args, uint32_t); + d = va_arg(args, uint32_t); + put_dec: if (d == 0) { logch('0'); break; diff --git a/src/kernel/main.c b/src/kernel/main.c index 92315ce..43778d4 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -15,6 +15,7 @@ #include "kbd.h" #include "log.h" #include "pci.h" +#include "vbe.h" void _start_user_mode() __attribute__ ((noreturn)); @@ -46,12 +47,16 @@ void main() { logf(LOG_INFO, "Available kernel memory: %dk", kernel_pages_left * 4); logf(LOG_INFO, "Available user memory: %dk", user_pages_left * 4); + logf(LOG_INFO, ""); + logf(LOG_INFO, "PCI devices:"); for (uint16_t i = 0; i < n_pci_devices; ++i) { const struct pci_device *dev = nth_pci_device(i); logf(LOG_INFO, " %hw:%hw (%hb:%hb)", dev->id_vendor, dev->id_device, dev->class, dev->subclass); } + logf(LOG_INFO, ""); + logf(LOG_INFO, "Drives:"); for (uint8_t i = 0; i < n_drives; ++i) { const struct drive *d = &drives[i]; @@ -59,6 +64,29 @@ void main() { logf(LOG_INFO, " %s: %d%sk, %s (%d%sk free)", d->drive_type, d->n_sectors / 2, d->n_sectors % 2 ? ".5" : "", d->fs_type, free / 2, free % 2 ? ".5" : ""); } + logf(LOG_INFO, ""); + + logf(LOG_INFO, "VBE info:"); + logf(LOG_INFO, " Implemention: %s", RM_PTR(char, VBE_INFO->oem_name)); + logf(LOG_INFO, " Video memory: %dk", VBE_INFO->total_memory * 64); + logf(LOG_INFO, " Standard: %d.%d.%d", VBE_INFO->major_version, VBE_INFO->minor_version, VBE_INFO->version_rev); + logf(LOG_INFO, " Vendor: %s", RM_PTR(char, VBE_INFO->vendor_name)); + logf(LOG_INFO, " Product: %s", RM_PTR(char, VBE_INFO->product_name)); + logf(LOG_INFO, " Version: %s", RM_PTR(char, VBE_INFO->product_rev_name)); + + logf(LOG_INFO, ""); + + #define MASK(offset, length) ((~((1 << offset) - 1)) - (offset + length == 32 ? 0 : (~((1 << (offset + length)) - 1)))) + logf(LOG_INFO, "Active video mode:"); + logf(LOG_INFO, " Resolution: %dx%dx%d", VBE_MODE_INFO->width, VBE_MODE_INFO->height, VBE_MODE_INFO->bpp); + logf(LOG_INFO, " Red mask: 0x%h", MASK(VBE_MODE_INFO->red_off, VBE_MODE_INFO->red_len)); + logf(LOG_INFO, " Green mask: 0x%h", MASK(VBE_MODE_INFO->green_off, VBE_MODE_INFO->green_len)); + logf(LOG_INFO, " Blue mask: 0x%h", MASK(VBE_MODE_INFO->blue_off, VBE_MODE_INFO->blue_len)); + logf(LOG_INFO, " Alpha mask: 0x%h", MASK(VBE_MODE_INFO->alpha_off, VBE_MODE_INFO->alpha_len)); + logf(LOG_INFO, " Framebuffer address: 0x%h", VBE_MODE_INFO->frame_buf); + + logf(LOG_INFO, ""); + logf(LOG_INFO, "Loading init program."); if (!try_elf_run(drives, "bin/init", "", 0)) diff --git a/src/kernel/vbe.h b/src/kernel/vbe.h new file mode 100644 index 0000000..6fcdb56 --- /dev/null +++ b/src/kernel/vbe.h @@ -0,0 +1,71 @@ +#ifndef VBE_H +#define VBE_H + +#include + +struct segoff { + uint16_t offset; + uint16_t segment; +} __attribute__ ((__packed__)); + +#define RM_PTR(type, segoff) ((type *)((segoff).segment * 16 + (segoff).offset)) + +enum vbe_capabilities { + VBE_CAP_SWITCHABLE_DAC = 0x1, + VBE_CAP_NON_VGA = 0x2, + VBE_CAP_WEIRD_RAMDAC = 0x4 +}; + +#define VBE_INFO \ + ((struct { \ + uint8_t signature[4]; \ + uint8_t minor_version; \ + uint8_t major_version; \ + struct segoff oem_name; \ + uint32_t capabilities; \ + struct segoff mode_list; \ + /*in units of 64kiB*/ \ + uint16_t total_memory; \ + uint16_t version_rev; \ + struct segoff vendor_name; \ + struct segoff product_name; \ + struct segoff product_rev_name; \ + } __attribute__ ((__packed__)) *)0x4200) + +#define VBE_MODE_INFO \ + ((struct { \ + uint16_t attribs; \ + uint8_t wina_attribs; \ + uint8_t winb_attribs; \ + uint16_t win_gran; \ + uint16_t win_size; \ + uint16_t wina_seg; \ + uint16_t winb_seg; \ + struct segoff win_func; \ + uint16_t pitch;/*in bytes*/ \ + uint16_t width; \ + uint16_t height; \ + uint8_t char_width; \ + uint8_t char_height; \ + uint8_t n_planes; \ + uint8_t bpp; \ + uint8_t n_banks; \ + uint8_t mem_model; \ + uint8_t bank_size;/*in kiB*/\ + uint8_t image_pages; \ + uint8_t reserved; \ + uint8_t red_len; \ + uint8_t red_off; \ + uint8_t green_len; \ + uint8_t green_off; \ + uint8_t blue_len; \ + uint8_t blue_off; \ + uint8_t alpha_len; \ + uint8_t alpha_off; \ + uint8_t color_attribs; \ + void *frame_buf; \ + void *off_screen; \ + uint16_t off_screen_length; \ + } __attribute__ ((__packed__)) *)0x4400) + +#endif \ No newline at end of file diff --git a/src/kernel/window.c b/src/kernel/window.c index 74273fb..10c573f 100644 --- a/src/kernel/window.c +++ b/src/kernel/window.c @@ -7,18 +7,21 @@ #include "pmap.h" #include "elf.h" #include "log.h" +#include "vbe.h" #define MAX_WINDOWS 64 #define ACTION_BUFFER_PAGES 1 #define AB_END(buf) (buf + (ACTION_BUFFER_PAGES * 4096) / sizeof(struct window_action)) -#define BACKGROUND(x, y) ((x / 16 + y / 16) % 2 ? 0x14 : 0x07) +#define GSC(x, y) (x / 4 + y / 4 >= 256 ? 255 : x / 4 + y / 4) +#define BACKGROUND(x, y) ((struct pixel){.r = GSC(x / 2, y / 3), .g = GSC(x, y), .b = GSC(x, y / 2)}) -#define BORDER_LIGHT 0x1c -#define BORDER_DARK 0x08 +#define BORDER_COLOR ((struct pixel){.r = 0x11, .g = 0x11, .b = 0x11}) + +#define MOVE_BY 5 static struct window { - const volatile void *pixel_buffer_pma; + const volatile struct pixel *pixel_buffer_pma; uint16_t width; uint16_t height; @@ -38,65 +41,74 @@ static struct window { static struct window *bottom_window = 0; static struct window *top_window = 0; -#define SCREEN_HEIGHT 200 -#define SCREEN_WIDTH 320 -#define VGA_MEMORY ((uint8_t *)0xa0000) +uint32_t pix_clear_mask; + +static inline void put_pix(uint16_t y, uint16_t x, struct pixel px) { + uint32_t *const fbp = VBE_MODE_INFO->frame_buf + y * VBE_MODE_INFO->pitch + x * VBE_MODE_INFO->bpp / 8; +//logf(LOG_INFO, "-- fbp = 0x%h", fbp); +//logf(LOG_INFO, "-- *fbp -> 0x%h", *fbp); + *fbp &= pix_clear_mask; + *fbp |= (px.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off; + *fbp |= (px.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off; + *fbp |= (px.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off; +//logf(LOG_INFO, "-- *fbp <- 0x%h", *fbp); +} -static inline void draw_hz_line(uint16_t y, uint16_t xs, uint16_t xm, uint8_t color) { - if (y >= SCREEN_HEIGHT) +static inline void draw_hz_line(uint16_t y, uint16_t xs, uint16_t xm, struct pixel color) { + if (y >= VBE_MODE_INFO->height) return; - if (xs >= SCREEN_WIDTH) + if (xs >= VBE_MODE_INFO->width) xs = 0; - if (xm > SCREEN_WIDTH) - xm = SCREEN_WIDTH; - uint8_t *const line_start = VGA_MEMORY + y * SCREEN_WIDTH; - for (uint8_t *p = line_start + xs; p < line_start + xm; ++p) - *p = color; + if (xm > VBE_MODE_INFO->width) + xm = VBE_MODE_INFO->width; + for (uint16_t x = xs; x < xm; ++x) + put_pix(y, x, color); } -static inline void draw_vt_line(uint16_t x, uint16_t ys, uint16_t ym, uint8_t color) { - if (x >= SCREEN_WIDTH) +static inline void draw_vt_line(uint16_t x, uint16_t ys, uint16_t ym, struct pixel color) { + if (x >= VBE_MODE_INFO->width) return; - if (ys >= SCREEN_HEIGHT) + if (ys >= VBE_MODE_INFO->height) ys = 0; - if (ym > SCREEN_HEIGHT) - ym = SCREEN_HEIGHT; - uint8_t *const line_start = VGA_MEMORY + x; - for (uint8_t *p = line_start + ys * SCREEN_WIDTH; p < line_start + ym * SCREEN_WIDTH; p += SCREEN_WIDTH) - *p = color; + if (ym > VBE_MODE_INFO->height) + ym = VBE_MODE_INFO->height; + for (uint16_t y = ys; y < ym; ++y) + put_pix(y, x, color); } static void paint_and_above(const struct window *w) { switch_to_kernel_cr3(); for (const struct window *i = w; i; i = i->above) { - const uint16_t ys = i->ypos < SCREEN_HEIGHT ? 0 : -i->ypos; - const uint16_t xs = i->xpos < SCREEN_WIDTH ? 0 : -i->xpos; - const uint16_t ym = i->ypos + i->height <= SCREEN_HEIGHT ? i->height : SCREEN_HEIGHT - i->ypos; - const uint16_t xm = i->xpos + i->width <= SCREEN_WIDTH ? i->width : SCREEN_WIDTH - i->xpos; + const uint16_t ys = i->ypos < VBE_MODE_INFO->height ? 0 : -i->ypos; + const uint16_t xs = i->xpos < VBE_MODE_INFO->width ? 0 : -i->xpos; + const uint16_t ym = ((i->ypos + i->height) & 0xffff) <= VBE_MODE_INFO->height ? i->height : VBE_MODE_INFO->height - i->ypos; + const uint16_t xm = ((i->xpos + i->width) & 0xffff) <= VBE_MODE_INFO->width ? i->width : VBE_MODE_INFO->width - i->xpos; - for (uint16_t y = ys; y < ym; ++y) - for (uint16_t x = xs; x < xm; ++x) { - const uint8_t pixel = ((uint8_t *)i->pixel_buffer_pma)[y * i->width + x]; - if (pixel) - VGA_MEMORY[(y + i->ypos) * SCREEN_WIDTH + x + i->xpos] = pixel; - } + //logf(LOG_INFO, "y: %n .. %n", ys, ym - 1); + //logf(LOG_INFO, "x: %n .. %n", xs, xm - 1); - draw_hz_line(i->ypos - 2, i->xpos - 2, i->xpos + i->width + 2, BORDER_LIGHT); - draw_vt_line(i->xpos - 2, i->ypos - 1, i->ypos + i->height + 2, BORDER_LIGHT); - draw_hz_line(i->ypos - 1, i->xpos - 1, i->xpos + i->width + 2, BORDER_DARK); - draw_vt_line(i->xpos - 1, i->ypos, i->ypos + i->height + 2, BORDER_DARK); - draw_hz_line(i->ypos + i->height, i->xpos, i->xpos + i->width + 1, BORDER_LIGHT); - draw_vt_line(i->xpos + i->width, i->ypos, i->ypos + i->height, BORDER_LIGHT); - draw_hz_line(i->ypos + i->height + 1, i->xpos, i->xpos + i->width + 2, BORDER_DARK); - draw_vt_line(i->xpos + i->width + 1, i->ypos, i->ypos + i->height + 1, BORDER_DARK); + for (uint16_t y = ys; y < ym; ++y) + for (uint16_t x = xs; x < xm; ++x) + put_pix(y + i->ypos, x + i->xpos, i->pixel_buffer_pma[y * i->width + x]); + + draw_hz_line(i->ypos - 2, i->xpos - 2, i->xpos + i->width + 2, BORDER_COLOR); + draw_hz_line(i->ypos - 1, i->xpos - 2, i->xpos + i->width + 2, BORDER_COLOR); + draw_hz_line(i->ypos + i->height, i->xpos - 2, i->xpos + i->width + 2, BORDER_COLOR); + draw_hz_line(i->ypos + i->height + 1, i->xpos - 2, i->xpos + i->width + 2, BORDER_COLOR); + draw_vt_line(i->xpos - 2, i->ypos, i->ypos + i->height, BORDER_COLOR); + draw_vt_line(i->xpos - 1, i->ypos, i->ypos + i->height, BORDER_COLOR); + draw_vt_line(i->xpos + i->width, i->ypos, i->ypos + i->height, BORDER_COLOR); + draw_vt_line(i->xpos + i->width + 1, i->ypos, i->ypos + i->height, BORDER_COLOR); } switch_to_task_cr3(); } static void paint_bg() { - for (uint16_t y = 0; y < SCREEN_HEIGHT; ++y) - for (uint16_t x = 0; x < SCREEN_WIDTH; ++x) - VGA_MEMORY[y * SCREEN_WIDTH + x] = BACKGROUND(x, y); + switch_to_kernel_cr3(); + for (uint16_t y = 0; y < VBE_MODE_INFO->height; ++y) + for (uint16_t x = 0; x < VBE_MODE_INFO->width; ++x) + put_pix(y, x, BACKGROUND(x, y)); + switch_to_task_cr3(); } static void paint_all() { @@ -104,7 +116,7 @@ static void paint_all() { paint_and_above(bottom_window); } -struct window *new_window(uint16_t width, uint16_t height, const void *pixel_buffer) { +struct window *new_window(uint16_t width, uint16_t height, const struct pixel *pixel_buffer) { if (!pixel_buffer) { logf(LOG_WARN, "Refusing to create window with null pixel buffer for task %s.", active_task->name); return 0; @@ -122,8 +134,8 @@ got_window: w->pixel_buffer_pma = vma_to_pma(active_task->page_directory, pixel_buffer); w->width = width; w->height = height; - w->xpos = 10; - w->ypos = 10; + w->xpos = (VBE_MODE_INFO->width / 2) - (width / 2); + w->ypos = (VBE_MODE_INFO->height / 2) - (height / 2); struct window_action *const ab = allocate_kernel_pages(ACTION_BUFFER_PAGES); w->action_buffer = ab; @@ -174,7 +186,7 @@ void delete_any_windows_from(struct task_state *tstate) { paint_all(); } -void resize_window(struct window *w, uint16_t width, uint16_t height, const void *pixel_buffer) { +void resize_window(struct window *w, uint16_t width, uint16_t height, const struct pixel *pixel_buffer) { const bool smaller = (width < w->width) || (height < w->height); w->width = width; @@ -187,7 +199,7 @@ void resize_window(struct window *w, uint16_t width, uint16_t height, const void paint_and_above(w); } -void reassign_pixel_buffer(struct window *w, const void *pixel_buffer) { +void reassign_pixel_buffer(struct window *w, const struct pixel *pixel_buffer) { w->pixel_buffer_pma = vma_to_pma(active_task->page_directory, pixel_buffer); } @@ -259,6 +271,14 @@ static char *run_command; static char *run_command_pass = ""; void init_win() { + #define MASK(offset, length) ((~((1 << offset) - 1)) - (offset + length == 32 ? 0 : (~((1 << (offset + length)) - 1)))) + pix_clear_mask = ~( + MASK(VBE_MODE_INFO->red_off, VBE_MODE_INFO->red_len) | + MASK(VBE_MODE_INFO->green_off, VBE_MODE_INFO->green_len) | + MASK(VBE_MODE_INFO->blue_off, VBE_MODE_INFO->blue_len) | + MASK(VBE_MODE_INFO->alpha_off, VBE_MODE_INFO->alpha_len) + ); + paint_bg(); const file_id_t fid = drives->get_file(drives, RUN_COMMAND_FILE); @@ -323,25 +343,25 @@ void on_action(struct window_action packet) { break; case WM_MOVE_LEFT: if (top_window) { - --top_window->xpos; + top_window->xpos -= MOVE_BY; paint_all(); } break; case WM_MOVE_RIGHT: if (top_window) { - ++top_window->xpos; + top_window->xpos += MOVE_BY; paint_all(); } break; case WM_MOVE_UP: if (top_window) { - --top_window->ypos; + top_window->ypos -= MOVE_BY; paint_all(); } break; case WM_MOVE_DOWN: if (top_window) { - ++top_window->ypos; + top_window->ypos += MOVE_BY; paint_all(); } break; diff --git a/src/kernel/window.h b/src/kernel/window.h index a226c11..ebd0496 100644 --- a/src/kernel/window.h +++ b/src/kernel/window.h @@ -9,13 +9,20 @@ struct window; +struct pixel { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t pad; +} __attribute__ ((__packed__)); + void init_win(); -struct window *new_window(uint16_t width, uint16_t height, const void *pixel_buffer); +struct window *new_window(uint16_t width, uint16_t height, const struct pixel *pixel_buffer); void del_window(struct window *w); -void resize_window(struct window *w, uint16_t width, uint16_t height, const void *pixel_buffer); -void reassign_pixel_buffer(struct window *w, const void *pixel_buffer); +void resize_window(struct window *w, uint16_t width, uint16_t height, const struct pixel *pixel_buffer); +void reassign_pixel_buffer(struct window *w, const struct pixel *pixel_buffer); void push_window_paint(const struct window *w); struct window_action next_window_action(struct window *w); void wait_window_action(); -- cgit v1.2.3