#include "renderer.hpp" renderer::renderer( daguerre::image &&fb, daguerre::image &&bg, daguerre::hilbert_color bgc, daguerre::image &&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 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 void overlay_trans(color_t &to, const color_t &from, const color_t ¶m) { 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) { int tx = (*it)->x, ty = (*it)->y, fx = 0, fy = 0; int w = (*it)->contents_with_decorations.width; int h = (*it)->contents_with_decorations.height; daguerre::make_safe(tx, fx, w, 0, double_buffer.width); daguerre::make_safe(ty, fy, h, 0, double_buffer.height); double_buffer.copy_from( (*it)->contents_with_decorations, tx, ty, fx, fy, w, h); } 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::get_cursor(int &x_out, int &y_out) { x_out = cursor_x; y_out = cursor_y; } 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::move_window_to_front(std::list::iterator w) { window *wp = *w; windows.erase(w); if (windows.size() != 0) windows.back()->draw_decorations(false); windows.push_back(wp); wp->draw_decorations(true); } void renderer::add_window(window *w) { if (windows.size() != 0) windows.back()->draw_decorations(false); w->draw_decorations(true); windows.push_back(w); } void renderer::remove_window(window *w) { windows.remove(w); if (windows.size() != 0) windows.back()->draw_decorations(true); }