commit 6fb64f2d4d18be0a39c8906ca2b5da10f4fed9ad
parent bbb1f60e32f34950397667c50757d3a792eb6852
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 6 Apr 2024 13:54:04 +0900
draw mouse pointer
Diffstat:
5 files changed, 156 insertions(+), 37 deletions(-)
diff --git a/sys/include/draw.h b/sys/include/draw.h
@@ -25,7 +25,7 @@ typedef struct Image {
#define MAX_CHILD_WIN 16 // TODO: dynamically allocate.
typedef struct Window {
- uint32 *fb; // for the root window only.
+ uint32 *fb; // for the root window only. TODO: I think children need fb for optimization.
int ppsl;
RGBA32 fg;
RGBA32 bg;
@@ -36,12 +36,22 @@ typedef struct Window {
int nchildren;
} Window;
+typedef struct Mouse {
+ Point size;
+ Point pos;
+ RGBA32 *hidden;
+ RGBA32 *img;
+} Mouse;
+
int init_root_window(uint32 *fb_base, int hres, int vres, int ppsl, EFI_GRAPHICS_PIXEL_FORMAT pf);
extern void (* pixel)(Window *dst, Point p, RGBA32 col);
+extern RGBA32 (* get_pixel)(Window *win, Point at);
void line(Window *dst, Point p0, Point p1, RGBA32 col);
// i is the thickness of the border.
// i = 0: one pixel line, i > 0: inside the border, i < 0: outside the border.
void border(Window *dst, Rectangle r, int i, RGBA32 col);
void fill(Window *dst, Rectangle r, RGBA32 col);
void clear(Window *dst);
-int make_window(Window *parent, Window *child, Point at, Point size, RGBA32 fg, RGBA32 bg);
-\ No newline at end of file
+int make_window(Window *parent, Window *child, Point at, Point size, RGBA32 fg, RGBA32 bg);
+void draw_mouse(Window *dst, Mouse *mouse);
+void clear_mouse(Window *dst, Mouse *mouse);
+\ No newline at end of file
diff --git a/sys/src/Makefile b/sys/src/Makefile
@@ -1,4 +1,5 @@
TARGETS = boot kernel libc
+ARCH = amd64
BOOTCC = x86_64-w64-mingw32-gcc
BOOTCFLAGS = -I ../include \
@@ -27,12 +28,12 @@ boot/boot.efi: boot/boot.dll
boot/boot.dll: boot/boot.c boot/utils.c
$(BOOTCC) $(BOOTCFLAGS) -o $@ boot/boot.c boot/utils.c
-kernel/main.elf: kernel/start.o kernel/main.o kernel/draw.o kernel/alloc.o kernel/console.o kernel/memmap.ld ../lib/libc.a
+kernel/main.elf: kernel/$(ARCH)/start.o kernel/main.o kernel/draw.o kernel/alloc.o kernel/console.o kernel/memmap.ld ../lib/libc.a
$(LD) $(LDFLAGS) -e kernel_start -T kernel/memmap.ld -o $@ \
- kernel/start.o kernel/main.o kernel/draw.o kernel/alloc.o kernel/console.o \
+ kernel/$(ARCH)/start.o kernel/main.o kernel/draw.o kernel/alloc.o kernel/console.o \
-lc
-kernel/start.o: kernel/start.s
- $(CC) $(CFLAGS) -c -o $@ kernel/start.s
+kernel/$(ARCH)/start.o: kernel/$(ARCH)/start.s
+ $(CC) $(CFLAGS) -c -o $@ kernel/$(ARCH)/start.s
kernel/main.o: kernel/main.c ../include/uefi.h ../include/libc.h ../include/draw.h ../include/console.h
$(CC) $(CFLAGS) -c -o $@ kernel/main.c
kernel/draw.o: kernel/draw.c ../include/uefi.h ../include/libc.h ../include/draw.h ../include/console.h
@@ -70,5 +71,5 @@ gdb: disk.img OVMF.fd
clean:
rm -rf disk.img image
rm -f boot/boot.efi boot/boot.dll
- rm -f kernel/*.o kernel/main.elf
+ rm -f kernel/*.o kernel/$(ARCH)/*.o kernel/main.elf
rm -rf libc/*.o ../lib
diff --git a/sys/src/kernel/draw.c b/sys/src/kernel/draw.c
@@ -6,23 +6,29 @@
Window root_window;
void (* pixel)(Window *dst, Point p, RGBA32 col);
+RGBA32 (*get_pixel)(Window *win, Point at);
+
static void pixelRedGreenBlueReserved(Window *dst, Point p, RGBA32 col);
static void pixelBlueGreenRedReserved(Window *dst, Point p, RGBA32 col);
+static RGBA32 get_pixelRedGreenBlueReserved(Window *win, Point at);
+static RGBA32 get_pixelBlueGreenRedReserved(Window *win, Point at);
int
init_root_window(uint32 *fb_base, int hres, int vres, int ppsl, EFI_GRAPHICS_PIXEL_FORMAT pf)
{
if (pf == PixelRedGreenBlueReserved8BitPerColor) {
pixel = pixelRedGreenBlueReserved;
+ get_pixel = get_pixelRedGreenBlueReserved;
} else if (pf == PixelBlueGreenRedReserved8BitPerColor) {
pixel = pixelBlueGreenRedReserved;
+ get_pixel = get_pixelBlueGreenRedReserved;
} else {
strcpy(err.ename, "pixel format not supported.");
return -1;
}
root_window.fb = fb_base;
root_window.fg = 0x0;
- root_window.bg = 0x55555500;
+ root_window.bg = 0x555555ff;
root_window.ppsl = ppsl;
root_window.parent = &root_window;
root_window.size = (Point){hres, vres};
@@ -36,40 +42,90 @@ static void
pixelRedGreenBlueReserved(Window *dst, Point p, RGBA32 col)
{
Window *parent;
- // TODO: alpha
- // TODO: this order is correct?
- // UEFI-SPEC says that R is at the "byte zero".
- uint32 _col =
- (col & 0xff000000) >> 24 | // R
- (col & 0x00ff0000) >> 8 | // G
- (col & 0x0000ff00) << 8 | // B
- (col & 0x000000ff) << 24; // A
+ uint32 r, g, b, or, og, ob, old_col, alpha;
+
+ if (p.x < 0 || dst->size.x <= p.x || p.y < 0 || dst->size.y <= p.y) {
+ return;
+ }
if ((parent = dst->parent) != dst) {
pixel(parent, (Point) {p.x + dst->pos.x, p.y + dst->pos.y}, col);
return;
}
- if (0 <= p.x && p.x < dst->size.x && 0 <= p.y && p.y < dst->size.y) {
- dst->fb[p.y * dst->ppsl + p.x] = _col;
- }
+ alpha = col & 0x000000ff;
+ r = (col & 0xff000000) >> 24;
+ g = (col & 0x00ff0000) >> 16;
+ b = (col & 0x0000ff00) >> 8;
+ old_col = dst->fb[p.y * dst->ppsl + p.x];
+ or = (old_col & 0x000000ff);
+ og = (old_col & 0x0000ff00) >> 8;
+ ob = (old_col & 0x00ff0000) >> 16;
+ r = (or * (255-alpha) + r*alpha) / 255;
+ g = (og * (255-alpha) + g*alpha) / 255;
+ b = (ob * (255-alpha) + b*alpha) / 255;
+ dst->fb[p.y * dst->ppsl + p.x] = r | g << 8 | b << 16;
}
static void
pixelBlueGreenRedReserved(Window *dst, Point p, RGBA32 col)
{
Window *parent;
- // TODO: alpha
- uint32 _col =
- (col & 0xff000000) >> 8 | // R
- (col & 0x00ff0000) >> 8 | // G
- (col & 0x0000ff00) >> 8 | // B
- (col & 0x000000ff) << 24; // A
+ uint32 r, g, b, or, og, ob, old_col, alpha;
+
+ if (p.x < 0 || dst->size.x <= p.x || p.y < 0 || dst->size.y <= p.y) {
+ return;
+ }
if ((parent = dst->parent) != dst) {
pixel(parent, (Point) {p.x + dst->pos.x, p.y + dst->pos.y}, col);
return;
}
- if (0 <= p.x && p.x < dst->size.x && 0 <= p.y && p.y < dst->size.y) {
- dst->fb[p.y * dst->ppsl + p.x] = _col;
+ alpha = col & 0x000000ff;
+ r = (col & 0xff000000) >> 24;
+ g = (col & 0x00ff0000) >> 16;
+ b = (col & 0x0000ff00) >> 8;
+ old_col = dst->fb[p.y * dst->ppsl + p.x];
+ or = (old_col & 0x00ff0000) >> 16;
+ og = (old_col & 0x0000ff00) >> 8;
+ ob = (old_col & 0x000000ff);
+ r = (or * (255-alpha) + r*alpha) / 255;
+ g = (og * (255-alpha) + g*alpha) / 255;
+ b = (ob * (255-alpha) + b*alpha) / 255;
+ dst->fb[p.y * dst->ppsl + p.x] = r << 16 | g << 8 | b;
+}
+
+static RGBA32
+get_pixelRedGreenBlueReserved(Window *win, Point at)
+{
+ Window *parent;
+ uint32 col;
+ if (at.x < 0 || win->size.x <= at.x || at.y < 0 || win->size.y <= at.y) {
+ return 0;
+ }
+ if ((parent = win->parent) != win) {
+ return get_pixel(parent, (Point) {at.x + win->pos.x, at.y + win->pos.y});
+ }
+ col = win->fb[at.y * win->ppsl + at.x];
+ return 0x000000ff | // A
+ (col & 0x00ff0000) >> 8 | // B
+ (col & 0x0000ff00) << 8 | // G
+ (col & 0x000000ff) << 24 ; // R
+}
+
+static RGBA32
+get_pixelBlueGreenRedReserved(Window *win, Point at)
+{
+ Window *parent;
+ uint32 col;
+ if (at.x < 0 || win->size.x <= at.x || at.y < 0 || win->size.y <= at.y) {
+ return 0;
+ }
+ if ((parent = win->parent) != win) {
+ return get_pixel(parent, (Point) {at.x + win->pos.x, at.y + win->pos.y});
}
+ col = win->fb[at.y * win->ppsl + at.x];
+ return 0x000000ff | // A
+ (col & 0x00ff0000) << 8 | // R
+ (col & 0x0000ff00) << 8 | // G
+ (col & 0x000000ff) << 8 ; // B
}
void
@@ -180,7 +236,32 @@ make_window(Window *parent, Window *child, Point pos, Point size, RGBA32 fg, RGB
parent->nchildren++;
clear(child);
- border(parent, (Rectangle){pos, (Point){pos.x + size.x, pos.y + size.y}}, -4, 0x3f312b00);
+ border(parent, (Rectangle){pos, (Point){pos.x + size.x, pos.y + size.y}}, -4, 0x3f312bff);
return 0;
}
+
+void
+draw_mouse(Window *dst, Mouse *mouse)
+{
+ int i, j;
+ for (i = 0; i < mouse->size.y; i++) {
+ for (j = 0; j < mouse->size.x; j++) {
+ mouse->hidden[j + i*mouse->size.x] = get_pixel(dst, (Point){mouse->pos.x + j, mouse->pos.y + i});
+ pixel(dst, (Point){mouse->pos.x + j, mouse->pos.y + i},
+ mouse->img[j + i*mouse->size.x]);
+ }
+ }
+}
+
+void
+clear_mouse(Window *dst, Mouse *mouse)
+{
+ int i, j;
+ for (i = 0; i < mouse->size.y; i++) {
+ for (j = 0; j < mouse->size.x; j++) {
+ pixel(dst, (Point){mouse->pos.x + j, mouse->pos.y + i},
+ mouse->hidden[j + i*mouse->size.x]);
+ }
+ }
+}
+\ No newline at end of file
diff --git a/sys/src/kernel/main.c b/sys/src/kernel/main.c
@@ -25,7 +25,7 @@ kernel_main(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
root_window.children = root_children;
Window win0;
- make_window(&root_window, &win0, (Point){150, 100}, (Point){400, 300}, 0x0, 0xb9d08b00);
+ make_window(&root_window, &win0, (Point){150, 100}, (Point){400, 300}, 0x0, 0xb9d08bff);
Console con0 = {
.win = &win0,
.font = &asciifont,
@@ -33,7 +33,40 @@ kernel_main(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
.h = 24,
.pos = (Point){0, 0}
};
+ Point p = {0, 0};
+ RGBA32 m_hidden[16*16], m_img[16*16] = {
+ 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0xffffffff, 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff, 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
+ Mouse m = {
+ .size = (Point) {16, 16},
+ .pos = (Point) {143, 150},
+ .hidden = m_hidden,
+ .img = m_img,
+ };
+
cons_printf(&con0, "hello world!\n");
+ cons_printf(&con0, "pixel at {%d, %d}: %x\n", p.x, p.y, get_pixel(&root_window, p));
+ for (;;) {
+ m.pos.x = (m.pos.x + 1) % root_window.size.x;
+ draw_mouse(&root_window, &m);
+ for (int i = 0; i < 0x100000; i++) {
+ }
+ clear_mouse(&root_window, &m);
+ }
halt:
for(;;) { __asm__("hlt"); }
diff --git a/sys/src/kernel/start.s b/sys/src/kernel/start.s
@@ -1,7 +0,0 @@
- .global kernel_start
-kernel_start:
- mov $(kernel_main_stack + 1024 * 1024), %rsp
- call kernel_main
-hlt:
- hlt
- jmp hlt