summaryrefslogtreecommitdiff
path: root/applications/goldman
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-07-29 11:27:22 -0400
committerBenji Dial <benji@benjidial.net>2024-07-29 11:27:22 -0400
commitbe691582ee12613278af24cb5a824eeb357f6324 (patch)
tree5982ca3aad5257f515c93f62735ff3d630aa3ab3 /applications/goldman
parent3636fd21e079c47bd8d62e773e178f68fe9c2052 (diff)
downloadhilbert-os-be691582ee12613278af24cb5a824eeb357f6324.tar.gz
some work on compositor
Diffstat (limited to 'applications/goldman')
-rw-r--r--applications/goldman/makefile2
-rw-r--r--applications/goldman/source/input.cpp21
-rw-r--r--applications/goldman/source/input.hpp3
-rw-r--r--applications/goldman/source/main.cpp84
-rw-r--r--applications/goldman/source/main.hpp5
-rw-r--r--applications/goldman/source/renderer.cpp102
-rw-r--r--applications/goldman/source/renderer.hpp61
-rw-r--r--applications/goldman/source/socket.cpp162
-rw-r--r--applications/goldman/source/socket.hpp5
-rw-r--r--applications/goldman/source/window.hpp14
10 files changed, 395 insertions, 64 deletions
diff --git a/applications/goldman/makefile b/applications/goldman/makefile
index 56f633d..c6de0e7 100644
--- a/applications/goldman/makefile
+++ b/applications/goldman/makefile
@@ -1,5 +1,5 @@
SOURCES = \
- main.cpp
+ main.cpp renderer.cpp input.cpp socket.cpp
build/%.cpp.o: source/%.cpp
@mkdir -p $(@D)
diff --git a/applications/goldman/source/input.cpp b/applications/goldman/source/input.cpp
new file mode 100644
index 0000000..0cd6922
--- /dev/null
+++ b/applications/goldman/source/input.cpp
@@ -0,0 +1,21 @@
+#include "input.hpp"
+#include "main.hpp"
+
+[[noreturn]] void input_thread_main() {
+
+ euler::syscall::set_thread_name("input thread");
+
+ while (true) {
+
+ auto result = euler::syscall::get_input_packet();
+ if (std::holds_alternative<euler::syscall::mouse_packet>(result)) {
+ auto packet = std::get<euler::syscall::mouse_packet>(result);
+ r->lock();
+ r->bump_cursor(packet.x_changed, packet.y_changed);
+ r->unlock();
+ r->dispatch_render();
+ }
+
+ }
+
+}
diff --git a/applications/goldman/source/input.hpp b/applications/goldman/source/input.hpp
new file mode 100644
index 0000000..108cdad
--- /dev/null
+++ b/applications/goldman/source/input.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+[[noreturn]] void input_thread_main();
diff --git a/applications/goldman/source/main.cpp b/applications/goldman/source/main.cpp
index d74eaad..475129f 100644
--- a/applications/goldman/source/main.cpp
+++ b/applications/goldman/source/main.cpp
@@ -1,79 +1,37 @@
#include <daguerre/framebuffer.hpp>
#include <daguerre/ppm.hpp>
+#include "renderer.hpp"
+#include "socket.hpp"
+#include "input.hpp"
+#include "main.hpp"
-daguerre::hilbert_color trans_color;
+//TODO: handle errors
-void convert_pointer(
- daguerre::hilbert_color &dest, const daguerre::hilbert_color &src) {
- if (src != trans_color)
- dest = src;
-}
+renderer *r;
int main(int, char **) {
- trans_color = euler::syscall::encode_color(0xff, 0x00, 0xff);
-
- daguerre::image<daguerre::hilbert_color> framebuffer =
- daguerre::get_hilbert_framebuffer();
-
- int fw = framebuffer.width;
- int fh = framebuffer.height;
-
- daguerre::image<daguerre::hilbert_color> double_buffer(fw, fh);
+ euler::syscall::listener_handle listener;
+ euler::syscall::create_socket_listener("hilbert.compositor", listener);
- std::optional<daguerre::image<daguerre::hilbert_color>>
- background_original = daguerre::try_load_ppm("/assets/background.ppm");
-
- daguerre::image<daguerre::hilbert_color> background;
-
- if (background_original.has_value())
- background = background_original->stretch(fw, fh);
- else {
- background = daguerre::image<daguerre::hilbert_color>(fw, fh);
- background.fill(euler::syscall::encode_color(0, 0, 0));
- }
+ r = new renderer(
+ daguerre::get_hilbert_framebuffer(),
+ *daguerre::try_load_ppm("/assets/background.ppm"),
+ euler::syscall::encode_color(0x00, 0x00, 0x00),
+ *daguerre::try_load_ppm("/assets/pointer.ppm"),
+ euler::syscall::encode_color(0xff, 0x00, 0xff));
- std::optional<daguerre::image<daguerre::hilbert_color>>
- pointer_original = daguerre::try_load_ppm("/assets/pointer.ppm");
+ euler::syscall::start_thread([]() { r->render_thread_main(); });
+ euler::syscall::start_thread(input_thread_main);
- if (!pointer_original.has_value())
- //TODO
- while (1)
- ;
+ r->dispatch_render();
- daguerre::image<daguerre::hilbert_color>
- pointer = std::move(*pointer_original);
-
- int mouse_x = fw / 2;
- int mouse_y = fh / 2;
+ euler::syscall::set_thread_name("socket listener thread");
while (true) {
-
- double_buffer.copy_from(background, 0, 0);
- double_buffer.convert_from(pointer, mouse_x, mouse_y, 0, 0,
- std::min(pointer. width, double_buffer. width - mouse_x),
- std::min(pointer.height, double_buffer.height - mouse_y),
- &convert_pointer);
-
- framebuffer.copy_from(double_buffer, 0, 0);
-
- auto result = euler::syscall::get_input_packet();
- if (std::holds_alternative<euler::syscall::mouse_packet>(result)) {
- const auto &packet = std::get<euler::syscall::mouse_packet>(result);
- mouse_x += packet.x_changed;
- mouse_y += packet.y_changed;
- if (mouse_x < 0)
- mouse_x = 0;
- else if (mouse_x >= fw)
- mouse_x = fw - 1;
- if (mouse_y < 0)
- mouse_y = 0;
- else if (mouse_y >= fh)
- mouse_y = fh - 1;
- }
-
+ euler::syscall::stream_handle socket;
+ euler::syscall::accept_socket_connection(listener, socket);
+ euler::syscall::start_thread(socket_thread_main, socket);
}
- return 0;
-
}
diff --git a/applications/goldman/source/main.hpp b/applications/goldman/source/main.hpp
new file mode 100644
index 0000000..57de676
--- /dev/null
+++ b/applications/goldman/source/main.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "renderer.hpp"
+
+extern renderer *r;
diff --git a/applications/goldman/source/renderer.cpp b/applications/goldman/source/renderer.cpp
new file mode 100644
index 0000000..629c375
--- /dev/null
+++ b/applications/goldman/source/renderer.cpp
@@ -0,0 +1,102 @@
+#include "renderer.hpp"
+
+renderer::renderer(
+ daguerre::image<daguerre::hilbert_color> &&fb,
+ daguerre::image<daguerre::hilbert_color> &&bg,
+ daguerre::hilbert_color bgc,
+ daguerre::image<daguerre::hilbert_color> &&c,
+ daguerre::hilbert_color cbg)
+
+: framebuffer(std::move(fb)),
+ double_buffer(framebuffer.width, framebuffer.height),
+ background(std::move(bg)), cursor(std::move(c)), cursor_background(cbg),
+ cursor_x(framebuffer.width / 2), cursor_y(framebuffer.height / 2) {
+
+ euler::syscall::create_private_socket(dispatcher_handle_1, dispatcher_handle_2);
+
+ if (background.width != framebuffer.width ||
+ background.height != framebuffer.height) {
+
+ daguerre::image<daguerre::hilbert_color>
+ new_background(framebuffer.width, framebuffer.height);
+
+ new_background.fill(bgc);
+
+ int from_x = 0;
+ int from_y = 0;
+ int to_x = framebuffer.width / 2 - background.width / 2;
+ int to_y = framebuffer.height / 2 - background.height / 2;
+ int width = background.width;
+ int height = background.height;
+
+ daguerre::make_safe(to_x, from_x, width, 0, framebuffer.width);
+ daguerre::make_safe(to_y, from_y, height, 0, framebuffer.height);
+
+ new_background.copy_from(background, to_x, to_y, from_x, from_y, width, height);
+ background = std::move(new_background);
+
+ }
+
+}
+
+template <class color_t>
+void overlay_trans(color_t &to, const color_t &from, const color_t &param) {
+ if (from != param)
+ to = from;
+}
+
+void renderer::do_render() {
+
+ double_buffer.copy_from(background, 0, 0);
+
+ for (auto it = windows.begin(); it != windows.end(); ++it)
+
+ double_buffer.copy_from(
+ (*it)->contents, (*it)->x, (*it)->y, 0, 0,
+ std::min((*it)->contents.width, double_buffer.width - (*it)->x),
+ std::min((*it)->contents.height, double_buffer.height - (*it)->y));
+
+ double_buffer.convert_from(
+ cursor_background, cursor, cursor_x, cursor_y, 0, 0,
+ std::min(cursor.width, framebuffer.width - cursor_x),
+ std::min(cursor.height, framebuffer.height - cursor_y),
+ &overlay_trans);
+
+}
+
+[[noreturn]] void renderer::render_thread_main() {
+ euler::syscall::set_thread_name("render thread");
+ while (true) {
+ uint8_t byte;
+ euler::syscall::read_from_stream(dispatcher_handle_2, 1, &byte);
+ mut.lock();
+ euler::syscall::clear_socket_read_queue(dispatcher_handle_2);
+ do_render();
+ mut.unlock();
+ framebuffer.copy_from(double_buffer, 0, 0);
+ }
+}
+
+void renderer::bump_cursor(int x_offset, int y_offset) {
+
+ cursor_x += x_offset;
+ if (cursor_x < 0)
+ cursor_x = 0;
+ else if (cursor_x >= framebuffer.width)
+ cursor_x = framebuffer.width - 1;
+
+ cursor_y += y_offset;
+ if (cursor_y < 0)
+ cursor_y = 0;
+ else if (cursor_y >= framebuffer.height)
+ cursor_y = framebuffer.height - 1;
+
+}
+
+void renderer::add_window(const window *w) {
+ windows.push_back(w);
+}
+
+void renderer::remove_window(const window *w) {
+ windows.remove(w);
+}
diff --git a/applications/goldman/source/renderer.hpp b/applications/goldman/source/renderer.hpp
new file mode 100644
index 0000000..14a5964
--- /dev/null
+++ b/applications/goldman/source/renderer.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <daguerre/image.hpp>
+#include "window.hpp"
+#include <mutex>
+#include <list>
+
+class renderer {
+
+ daguerre::image<daguerre::hilbert_color> framebuffer;
+ daguerre::image<daguerre::hilbert_color> double_buffer;
+
+ daguerre::image<daguerre::hilbert_color> background;
+ daguerre::image<daguerre::hilbert_color> cursor;
+ daguerre::hilbert_color cursor_background;
+
+ int cursor_x;
+ int cursor_y;
+
+ //bottom to top
+ std::list<const window *> windows;
+
+ std::mutex mut;
+
+ euler::syscall::stream_handle
+ dispatcher_handle_1, dispatcher_handle_2;
+
+ void do_render();
+
+public:
+ renderer(
+ daguerre::image<daguerre::hilbert_color> &&framebuffer,
+ daguerre::image<daguerre::hilbert_color> &&background,
+ daguerre::hilbert_color background_color,
+ daguerre::image<daguerre::hilbert_color> &&cursor,
+ daguerre::hilbert_color cursor_background);
+
+ inline ~renderer() {
+ euler::syscall::close_stream(dispatcher_handle_1);
+ euler::syscall::close_stream(dispatcher_handle_2);
+ }
+
+ renderer(const renderer &) = delete;
+ renderer &operator =(const renderer &) = delete;
+
+ [[noreturn]] void render_thread_main();
+
+ inline void lock() { mut.lock(); }
+ inline void unlock() { mut.unlock(); }
+
+ inline void dispatch_render() {
+ uint8_t byte = 0;
+ euler::syscall::write_to_stream(dispatcher_handle_1, 1, &byte);
+ }
+
+ void bump_cursor(int x_offset, int y_offset);
+
+ void add_window(const window *w);
+ void remove_window(const window *w);
+
+};
diff --git a/applications/goldman/source/socket.cpp b/applications/goldman/source/socket.cpp
new file mode 100644
index 0000000..b175fe9
--- /dev/null
+++ b/applications/goldman/source/socket.cpp
@@ -0,0 +1,162 @@
+#include <daguerre/image.hpp>
+#include "socket.hpp"
+#include "window.hpp"
+#include "main.hpp"
+#include <memory>
+#include <vector>
+
+struct socket_state {
+
+ euler::syscall::stream_handle socket;
+ std::vector<window *> windows;
+ daguerre::hilbert_color window_bg = euler::syscall::encode_color(0, 0, 0);
+
+ bool try_open_window() {
+
+ struct [[gnu::packed]] {
+ uint32_t width;
+ uint32_t height;
+ } body;
+
+ if (euler::syscall::read_from_stream(socket, sizeof(body), &body) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ window *w = new window(body.width, body.height);
+ w->contents.fill(window_bg);
+
+ uint16_t wid = 0;
+
+ while (wid < windows.size())
+ if (windows[wid] != 0)
+ ++wid;
+ else
+ break;
+
+ if (wid == windows.size())
+ windows.push_back(w);
+ else
+ windows[wid] = w;
+
+ r->lock();
+ r->add_window(w);
+ r->unlock();
+
+ struct [[gnu::packed]] {
+ uint8_t type;
+ uint16_t the_window;
+ } response {
+ .type = 0x00,
+ .the_window = wid
+ };
+
+ return
+ euler::syscall::write_to_stream(socket, sizeof(response), &response) ==
+ euler::syscall::stream_result::success;
+
+ }
+
+ bool try_update_window_region() {
+
+ struct [[gnu::packed]] {
+ uint16_t window;
+ uint32_t start_x;
+ uint32_t start_y;
+ uint32_t width;
+ uint32_t height;
+ } body_head;
+
+ if (euler::syscall::read_from_stream(socket, sizeof(body_head), &body_head) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ std::vector<daguerre::hilbert_color> data(body_head.width * body_head.height);
+
+ if (euler::syscall::read_from_stream(socket, data.size() * 4, data.data()) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ daguerre::image<daguerre::hilbert_color>
+ data_as_image(body_head.width, body_head.height, data.data(), body_head.width, false);
+
+ if (body_head.window >= windows.size() || !windows[body_head.window])
+ return false;
+
+ window *w = windows[body_head.window];
+
+ r->lock();
+
+ if ((int)body_head.start_x + data_as_image.width > w->contents.width ||
+ (int)body_head.start_y + data_as_image.height > w->contents.height) {
+ r->unlock();
+ return false;
+ }
+
+ w->contents.copy_from(data_as_image, body_head.start_x, body_head.start_y);
+
+ r->unlock();
+ r->dispatch_render();
+ return true;
+
+ }
+
+ bool try_close_window() {
+
+ uint16_t wid;
+
+ if (euler::syscall::read_from_stream(socket, 2, &wid) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ if (wid >= windows.size() || !windows[wid])
+ return false;
+
+ r->lock();
+
+ r->remove_window(windows[wid]);
+ windows[wid] = 0;
+
+ r->unlock();
+ r->dispatch_render();
+ return true;
+
+ }
+
+ bool try_process_request() {
+
+ uint8_t type;
+ if (euler::syscall::read_from_stream(socket, 1, &type) !=
+ euler::syscall::stream_result::success)
+ return false;
+
+ switch (type) {
+ case 0x00: return try_open_window();
+ case 0x01: return try_update_window_region();
+ case 0x02: return try_close_window();
+ default: return false;
+ }
+
+ }
+
+};
+
+[[noreturn]] void socket_thread_main(euler::syscall::stream_handle socket) {
+
+ euler::syscall::set_thread_name("socket thread");
+
+ socket_state *state = new socket_state {
+ .socket = socket, .windows = {} };
+ while (state->try_process_request()) ;
+
+ r->lock();
+ for (unsigned i = 0; i < state->windows.size(); ++i) {
+ r->remove_window(state->windows[i]);
+ delete state->windows[i];
+ }
+ r->unlock();
+
+ delete state;
+ euler::syscall::close_stream(socket);
+ euler::syscall::end_this_thread(0);
+
+}
diff --git a/applications/goldman/source/socket.hpp b/applications/goldman/source/socket.hpp
new file mode 100644
index 0000000..a9dbeb2
--- /dev/null
+++ b/applications/goldman/source/socket.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <euler/syscall.hpp>
+
+[[noreturn]] void socket_thread_main(euler::syscall::stream_handle socket);
diff --git a/applications/goldman/source/window.hpp b/applications/goldman/source/window.hpp
new file mode 100644
index 0000000..008af2f
--- /dev/null
+++ b/applications/goldman/source/window.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <daguerre/image.hpp>
+
+struct window {
+
+ daguerre::image<daguerre::hilbert_color> contents;
+
+ int x;
+ int y;
+
+ window(int width, int height) : contents(width, height), x(0), y(0) {}
+
+};