summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/window.c105
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)