102 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#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)
 | 
						|
 | 
						|
    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);
 | 
						|
}
 |