1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#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 ¶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<window *>::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);
}
|