summaryrefslogtreecommitdiff
path: root/src/kernel/window.c
diff options
context:
space:
mode:
authorBenji Dial <benji6283@gmail.com>2021-02-18 14:44:06 -0500
committerBenji Dial <benji6283@gmail.com>2021-02-18 14:44:06 -0500
commit8e120a5c7270fcf4a524dea404c0f2cdcdda3714 (patch)
treee3c6cfb57ad241139d0712c819e657a23f72f12a /src/kernel/window.c
parent947dfe3e41ec36393b709abc1f38b8ab9340114b (diff)
downloadportland-os-8e120a5c7270fcf4a524dea404c0f2cdcdda3714.tar.gz
making graphics double-buffered so there isn't flicker when windows paint
Diffstat (limited to 'src/kernel/window.c')
-rw-r--r--src/kernel/window.c69
1 files changed, 45 insertions, 24 deletions
diff --git a/src/kernel/window.c b/src/kernel/window.c
index 10c573f..9d3db28 100644
--- a/src/kernel/window.c
+++ b/src/kernel/window.c
@@ -41,17 +41,42 @@ static struct window {
static struct window *bottom_window = 0;
static struct window *top_window = 0;
-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 struct pixel *buffer;
+static uint32_t buffer_pages;
+static uint32_t pix_clear_mask;
+
+static void load_mode_params() {
+ if (buffer)
+ free_pages(buffer, buffer_pages);
+
+ const uint32_t fb_len = VBE_MODE_INFO->width * VBE_MODE_INFO->height;
+ buffer_pages = (fb_len * sizeof(struct pixel) - 1) / 4096 + 1;
+ buffer = allocate_kernel_pages(buffer_pages);
+
+ #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)
+ );
+}
+
+static void blit() {
+ void *row = VBE_MODE_INFO->frame_buf;
+ const struct pixel *from = buffer;
+ for (uint16_t y = 0; y < VBE_MODE_INFO->height; ++y) {
+ uint32_t *out_pix = row;
+ for (uint16_t x = 0; x < VBE_MODE_INFO->width; ++x) {
+ *out_pix &= pix_clear_mask;
+ *out_pix |= (from->r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off;
+ *out_pix |= (from->g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off;
+ *out_pix |= (from->b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off;
+ out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8);
+ ++from;
+ }
+ row += VBE_MODE_INFO->pitch;
+ }
}
static inline void draw_hz_line(uint16_t y, uint16_t xs, uint16_t xm, struct pixel color) {
@@ -62,7 +87,7 @@ static inline void draw_hz_line(uint16_t y, uint16_t xs, uint16_t xm, struct pix
if (xm > VBE_MODE_INFO->width)
xm = VBE_MODE_INFO->width;
for (uint16_t x = xs; x < xm; ++x)
- put_pix(y, x, color);
+ buffer[y * VBE_MODE_INFO->width + x] = color;
}
static inline void draw_vt_line(uint16_t x, uint16_t ys, uint16_t ym, struct pixel color) {
@@ -73,7 +98,7 @@ static inline void draw_vt_line(uint16_t x, uint16_t ys, uint16_t ym, struct pix
if (ym > VBE_MODE_INFO->height)
ym = VBE_MODE_INFO->height;
for (uint16_t y = ys; y < ym; ++y)
- put_pix(y, x, color);
+ buffer[y * VBE_MODE_INFO->width + x] = color;
}
static void paint_and_above(const struct window *w) {
@@ -89,7 +114,7 @@ static void paint_and_above(const struct window *w) {
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]);
+ buffer[(y + i->ypos) * VBE_MODE_INFO->width + 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);
@@ -100,15 +125,15 @@ static void paint_and_above(const struct window *w) {
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);
}
+
+ blit();
switch_to_task_cr3();
}
static void paint_bg() {
- 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();
+ buffer[y * VBE_MODE_INFO->width + x] = BACKGROUND(x, y);
}
static void paint_all() {
@@ -271,15 +296,11 @@ 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)
- );
+ buffer = 0;
+ load_mode_params();
paint_bg();
+ blit();
const file_id_t fid = drives->get_file(drives, RUN_COMMAND_FILE);
if (!fid)