From 2f6f3ea54ad01f02e68a23345565c34eb47ad365 Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Mon, 8 Aug 2022 21:13:36 +0200
Subject: user: drawmouse for demoing mouse/graphic support

---
 src/user/app/drawmouse/drawmouse.c | 86 ++++++++++++++++++++++++++++++++++++++
 src/user/app/mousedump/mousedump.c | 32 --------------
 src/user/lib/draw/draw.c           | 34 ++++++++++++++-
 src/user/lib/draw/draw.h           |  5 +++
 4 files changed, 124 insertions(+), 33 deletions(-)
 create mode 100644 src/user/app/drawmouse/drawmouse.c
 delete mode 100644 src/user/app/mousedump/mousedump.c

(limited to 'src')

diff --git a/src/user/app/drawmouse/drawmouse.c b/src/user/app/drawmouse/drawmouse.c
new file mode 100644
index 0000000..7e7c55b
--- /dev/null
+++ b/src/user/app/drawmouse/drawmouse.c
@@ -0,0 +1,86 @@
+#include <camellia/syscalls.h>
+#include <shared/container/ring.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <user/lib/draw/draw.h>
+
+#define MOUSE_SIZE 10
+
+#define eprintf(fmt, ...) fprintf(stderr, "drawmouse: "fmt"\n" __VA_OPT__(,) __VA_ARGS__)
+
+struct framebuf fb, lastbehind;
+struct rect dirty;
+
+static uint8_t r_buf[64];
+static ring_t r = {(void*)r_buf, sizeof r_buf, 0, 0};
+static struct {uint32_t x, y;} cursor, lastcur;
+
+
+static void draw_mouse(void) {
+	static bool drawn = false;
+	if (drawn)
+		fb_cpy(&fb, &lastbehind, lastcur.x, lastcur.y, 0, 0, MOUSE_SIZE, MOUSE_SIZE);
+	drawn = true;
+	dirty_mark(&dirty, lastcur.x, lastcur.y);
+	dirty_mark(&dirty, lastcur.x + MOUSE_SIZE, lastcur.y + MOUSE_SIZE);
+	fb_cpy(&lastbehind, &fb, 0, 0, cursor.x, cursor.y, MOUSE_SIZE, MOUSE_SIZE);
+	for (int i = 0; i < MOUSE_SIZE; i++) {
+		for (int j = 0; j < MOUSE_SIZE - i; j++) {
+			uint32_t *px = fb_pixel(&fb, cursor.x + i, cursor.y + j);
+			if (px) {
+				*px ^= 0x808080;
+				dirty_mark(&dirty, cursor.x + i, cursor.y + j);
+			}
+		}
+	}
+	lastcur = cursor;
+}
+
+
+struct packet {
+	uint8_t left     : 1;
+	uint8_t right    : 1;
+	uint8_t middle   : 1;
+	uint8_t _useless : 5;
+	int8_t dx, dy;
+} __attribute__((packed));
+
+int main(void) {
+	char buf[64];
+	handle_t fd = _syscall_open("/kdev/ps2/mouse", 15, 0);
+	if (fd < 0) {
+		eprintf("couldn't open mouse");
+		return 1;
+	}
+
+	if (fb_setup(&fb, "/kdev/video/") < 0) {
+		eprintf("fb_setup error");
+		return 1;
+	}
+	fb_anon(&lastbehind, MOUSE_SIZE, MOUSE_SIZE);
+
+
+	for (;;) {
+		int len = _syscall_read(fd, buf, sizeof buf, 0);
+		if (len == 0) break;
+		ring_put(&r, buf, len);
+		while (ring_size(&r) >= 3) {
+			struct packet p;
+			ring_get(&r, &p, sizeof p);
+			p.dy *= -1;
+			// TODO check mouse click
+			if (-p.dx > (int)cursor.x) p.dx = -cursor.x;
+			if (-p.dy > (int)cursor.y) p.dy = -cursor.y;
+			cursor.x += p.dx;
+			cursor.y += p.dy;
+			if (cursor.x >= fb.width)  cursor.x = fb.width - 1;
+			if (cursor.y >= fb.height) cursor.y = fb.height - 1;
+			draw_mouse();
+			if (p.left && p.right) return 0;
+		}
+		dirty_flush(&dirty, &fb);
+	}
+	return 0;
+}
diff --git a/src/user/app/mousedump/mousedump.c b/src/user/app/mousedump/mousedump.c
deleted file mode 100644
index 04331a3..0000000
--- a/src/user/app/mousedump/mousedump.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <camellia/syscalls.h>
-#include <unistd.h>
-#include <shared/container/ring.h>
-#include <stdio.h>
-
-static uint8_t r_buf[64];
-static ring_t r = {(void*)r_buf, sizeof r_buf, 0, 0};
-
-struct packet {
-	uint8_t stuff;
-	int8_t dx, dy;
-} __attribute__((packed));
-
-int main(void) {
-	char buf[64];
-	handle_t fd = _syscall_open("/kdev/ps2/mouse", 15, 0);
-	if (fd < 0) {
-		fprintf(stderr, "couldn't open mouse\n");
-		exit(1);
-	}
-	for (;;) {
-		int len = _syscall_read(fd, buf, sizeof buf, 0);
-		if (len == 0) break;
-		ring_put(&r, buf, len);
-		while (ring_size(&r) >= 3) {
-			struct packet p;
-			ring_get(&r, &p, sizeof p);
-			printf("%4d %4d\n", p.dx, p.dy);
-		}
-	}
-	return 0;
-}
diff --git a/src/user/lib/draw/draw.c b/src/user/lib/draw/draw.c
index c4508da..27c1d33 100644
--- a/src/user/lib/draw/draw.c
+++ b/src/user/lib/draw/draw.c
@@ -40,11 +40,43 @@ int fb_setup(struct framebuf *fb, const char *base) {
 	fb->height = strtol(spec, &spec, 0);
 	if (*spec++ != 'x') return -EINVAL;
 	fb->bpp = strtol(spec, &spec, 0);
+	if (fb->bpp != 32) return -EINVAL;
+
 	fb->len = _syscall_getsize(fb->fd);
 	fb->pitch = fb->len / fb->height;
 	fb->b = malloc(fb->len);
 
-	if (fb->bpp != 32) return -EINVAL;
+	_syscall_read(fb->fd, fb->b, fb->len, 0);
 
 	return 0;
 }
+
+int fb_anon(struct framebuf *fb, size_t w, size_t h) {
+	fb->width  = w;
+	fb->height = h;
+	fb->bpp = 32;
+	fb->pitch = fb->width * fb->bpp / 8;
+	fb->len = fb->pitch * fb->height;
+	fb->b = malloc(fb->len);
+	fb->fd = -1;
+	return 0;
+}
+
+uint32_t *fb_pixel(struct framebuf *fb, uint32_t x, uint32_t y) {
+	if (x < fb->width && y < fb->height)
+		return (void*)fb->b + fb->pitch * y + 4 * x;
+	return NULL;
+}
+
+void fb_cpy(
+	struct framebuf *dest, const struct framebuf *src,
+	size_t xd, size_t yd, size_t xs, size_t ys, size_t w, size_t h)
+{
+	for (size_t y = 0; y < h; y++) {
+		memcpy(
+			fb_pixel(      dest, xd, yd + y),
+			fb_pixel((void*)src, xs, ys + y),
+			w * 4
+		);
+	}
+}
diff --git a/src/user/lib/draw/draw.h b/src/user/lib/draw/draw.h
index ba15840..98316fe 100644
--- a/src/user/lib/draw/draw.h
+++ b/src/user/lib/draw/draw.h
@@ -17,3 +17,8 @@ void dirty_mark(struct rect *d, uint32_t x, uint32_t y);
 void dirty_flush(struct rect *d, struct framebuf *fb);
 
 int fb_setup(struct framebuf *fb, const char *base);
+int fb_anon(struct framebuf *fb, size_t w, size_t h);
+uint32_t *fb_pixel(struct framebuf *fb, uint32_t x, uint32_t y);
+void fb_cpy(
+	struct framebuf *dest, const struct framebuf *src,
+	size_t xd, size_t yd, size_t xs, size_t ys, size_t w, size_t h);
-- 
cgit v1.2.3