diff options
Diffstat (limited to 'src/kernel/window.c')
-rw-r--r-- | src/kernel/window.c | 105 |
1 files changed, 68 insertions, 37 deletions
diff --git a/src/kernel/window.c b/src/kernel/window.c index 1c4eb26..e7cf30d 100644 --- a/src/kernel/window.c +++ b/src/kernel/window.c @@ -15,7 +15,7 @@ #define AB_END(buf) (buf + (ACTION_BUFFER_PAGES * 4096) / sizeof(struct window_action)) #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 BACKGROUND(x, y) ((struct super_pixel){.from_window = 0, .p = (struct pixel){.r = GSC(x / 2, y / 3), .g = GSC(x, y), .b = GSC(x, y / 2)}}) static struct pixel border_color; @@ -42,7 +42,13 @@ static struct window { static struct window *bottom_window = 0; static struct window *top_window = 0; -static struct pixel *buffer; +struct super_pixel { + struct pixel p; + //0 indicates bg + const struct window *from_window; +}; + +static struct super_pixel *buffer; static uint32_t buffer_pages; static uint32_t pix_clear_mask; @@ -51,7 +57,7 @@ static void load_mode_params() { 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_pages = (fb_len * sizeof(struct super_pixel) - 1) / 4096 + 1; buffer = allocate_kernel_pages(buffer_pages); if (!buffer) PANIC("could not allocate intermediate framebuffer"); @@ -65,20 +71,22 @@ static void load_mode_params() { ); } -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) { +static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max) { + void *row = VBE_MODE_INFO->frame_buf + y_min * VBE_MODE_INFO->pitch + x_min * (VBE_MODE_INFO->bpp / 8); + const struct super_pixel *from_row = buffer + y_min * VBE_MODE_INFO->width + x_min; + for (uint16_t y = y_min; y < y_max; ++y) { uint32_t *out_pix = row; - for (uint16_t x = 0; x < VBE_MODE_INFO->width; ++x) { + const struct super_pixel *from = from_row; + for (uint16_t x = x_min; x < x_max; ++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 |= (from->p.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off; + *out_pix |= (from->p.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off; + *out_pix |= (from->p.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; + from_row += VBE_MODE_INFO->width; } } @@ -119,7 +127,7 @@ static const bool power_off_message[] = { void show_shutdown() { for (uint32_t i = 0; i < VBE_MODE_INFO->height * VBE_MODE_INFO->width; ++i) - buffer[i] = (struct pixel){.r = 0, .g = 0, .b = 0}; + buffer[i].p = (struct pixel){.r = 0, .g = 0, .b = 0}; const uint16_t x_pad = (VBE_MODE_INFO->width - POWER_OFF_MESSAGE_PITCH * POWER_OFF_SCALE) / 2; const uint16_t y_pad = (VBE_MODE_INFO->height - POWER_OFF_MESSAGE_ROWS * POWER_OFF_SCALE) / 2; @@ -130,13 +138,13 @@ void show_shutdown() { const uint32_t o = x_pad + i * POWER_OFF_SCALE + (y_pad + r * POWER_OFF_SCALE) * VBE_MODE_INFO->width; for (uint8_t y = 0; y < POWER_OFF_SCALE; ++y) for (uint8_t x = 0; x < POWER_OFF_SCALE; ++x) - buffer[o + x + y * VBE_MODE_INFO->width] = (struct pixel){.r = 255, .g = 255, .b = 255}; + buffer[o + x + y * VBE_MODE_INFO->width].p = (struct pixel){.r = 255, .g = 255, .b = 255}; } - blit(); + blit(0, VBE_MODE_INFO->width, 0, VBE_MODE_INFO->height); } -static inline void draw_hz_line(uint16_t y, uint16_t xs, uint16_t xm, struct pixel color) { +static inline void draw_hz_line(uint16_t y, uint16_t xs, uint16_t xm, struct super_pixel value) { if (y >= VBE_MODE_INFO->height) return; if (xs >= VBE_MODE_INFO->width) @@ -144,10 +152,10 @@ 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) - buffer[y * VBE_MODE_INFO->width + x] = color; + buffer[y * VBE_MODE_INFO->width + x] = value; } -static inline void draw_vt_line(uint16_t x, uint16_t ys, uint16_t ym, struct pixel color) { +static inline void draw_vt_line(uint16_t x, uint16_t ys, uint16_t ym, struct super_pixel value) { if (x >= VBE_MODE_INFO->width) return; if (ys >= VBE_MODE_INFO->height) @@ -155,35 +163,46 @@ 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) - buffer[y * VBE_MODE_INFO->width + x] = color; + buffer[y * VBE_MODE_INFO->width + x] = value; +} + +static void get_window_edges(const struct window *w, uint16_t *xmin, uint16_t *xmax, uint16_t *ymin, uint16_t *ymax) { + *ymin = w->ypos < VBE_MODE_INFO->height ? 0 : -w->ypos; + *xmin = w->xpos < VBE_MODE_INFO->width ? 0 : -w->xpos; + *ymax = ((w->ypos + w->height) & 0xffff) <= VBE_MODE_INFO->height ? w->height : VBE_MODE_INFO->height - w->ypos; + *xmax = ((w->xpos + w->width) & 0xffff) <= VBE_MODE_INFO->width ? w->width : VBE_MODE_INFO->width - w->xpos; } 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 < 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; + uint16_t xmin, xmax, ymin, ymax; + get_window_edges(i, &xmin, &xmax, &ymin, &ymax); //logf(LOG_INFO, "y: %n .. %n", ys, ym - 1); //logf(LOG_INFO, "x: %n .. %n", xs, xm - 1); - for (uint16_t y = ys; y < ym; ++y) - for (uint16_t x = xs; x < xm; ++x) - buffer[((y + i->ypos) & 0xffff) * VBE_MODE_INFO->width + ((x + i->xpos) & 0xffff)] = 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); + for (uint16_t y = ymin; y < ymax; ++y) + for (uint16_t x = xmin; x < xmax; ++x) { + struct super_pixel *const into = buffer + (((y + i->ypos) & 0xffff) * VBE_MODE_INFO->width + ((x + i->xpos) & 0xffff)); + into->from_window = i; + into->p = i->pixel_buffer_pma[y * i->width + x]; + } + /* buffer[((y + i->ypos) & 0xffff) * VBE_MODE_INFO->width + ((x + i->xpos) & 0xffff)] = + (struct super_pixel){.from_window = i, .p = i->pixel_buffer_pma[y * i->width + x]};*/ + + struct super_pixel super = {.from_window = i, .p = border_color}; + draw_hz_line(i->ypos - 2, i->xpos - 2, i->xpos + i->width + 2, super); + draw_hz_line(i->ypos - 1, i->xpos - 2, i->xpos + i->width + 2, super); + draw_hz_line(i->ypos + i->height, i->xpos - 2, i->xpos + i->width + 2, super); + draw_hz_line(i->ypos + i->height + 1, i->xpos - 2, i->xpos + i->width + 2, super); + draw_vt_line(i->xpos - 2, i->ypos, i->ypos + i->height, super); + draw_vt_line(i->xpos - 1, i->ypos, i->ypos + i->height, super); + draw_vt_line(i->xpos + i->width, i->ypos, i->ypos + i->height, super); + draw_vt_line(i->xpos + i->width + 1, i->ypos, i->ypos + i->height, super); } - blit(); + blit(0, VBE_MODE_INFO->width, 0, VBE_MODE_INFO->height); switch_to_task_cr3(); } @@ -286,7 +305,19 @@ void reassign_pixel_buffer(struct window *w, const struct pixel *pixel_buffer) { } void push_window_paint(const struct window *w) { - paint_and_above(w); + switch_to_kernel_cr3(); + uint16_t xmin, xmax, ymin, ymax; + get_window_edges(w, &xmin, &xmax, &ymin, &ymax); + + for (uint16_t y = ymin; y < ymax; ++y) + for (uint16_t x = xmin; x < xmax; ++x) { + struct super_pixel *const into = buffer + (((y + w->ypos) & 0xffff) * VBE_MODE_INFO->width + ((x + w->xpos) & 0xffff)); + if (into->from_window == w) + into->p = w->pixel_buffer_pma[y * w->width + x]; + } + + blit(w->xpos + xmin, w->xpos + xmax, w->ypos + ymin, w->ypos + ymax); + switch_to_task_cr3(); } struct window_action next_window_action(struct window *w) { @@ -360,7 +391,7 @@ void init_win() { load_mode_params(); paint_bg(); - blit(); + blit(0, VBE_MODE_INFO->width, 0, VBE_MODE_INFO->height); const file_id_t fid = drives->get_file(drives, RUN_COMMAND_FILE); if (!fid) |