summaryrefslogtreecommitdiff
path: root/applications/goldman/source/renderer.cpp
blob: 629c3759e23bd372cfb1d65cadf63f00a6507e40 (plain) (blame)
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
#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);
}