First commit
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
message(STATUS " Configuring Graphics")
|
||||
|
||||
add_library(Graphics
|
||||
Framebuffer.cpp
|
||||
Renderer.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(Graphics
|
||||
PRIVATE Model Helpers UI
|
||||
)
|
||||
|
||||
target_include_directories(Graphics
|
||||
PUBLIC
|
||||
${INCLUDE_BASE_DIR}
|
||||
)
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace Display::Graphics
|
||||
{
|
||||
struct Color
|
||||
{
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a = 255; // по умолчанию непрозрачный
|
||||
|
||||
Color() = default;
|
||||
Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255)
|
||||
: r(red), g(green), b(blue), a(alpha) {}
|
||||
|
||||
operator uint16_t() const
|
||||
{
|
||||
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
||||
}
|
||||
};
|
||||
|
||||
inline uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
||||
}
|
||||
|
||||
inline uint16_t rgb565(const Color &c)
|
||||
{
|
||||
return rgb565(c.r, c.g, c.b);
|
||||
}
|
||||
|
||||
inline Color Black() { return {0, 0, 0}; }
|
||||
inline Color White() { return {255, 255, 255}; }
|
||||
inline Color Red() { return {255, 0, 0}; }
|
||||
inline Color Green() { return {0, 255, 0}; }
|
||||
inline Color Blue() { return {0, 0, 255}; }
|
||||
} // namespace Display::Graphics
|
||||
@@ -0,0 +1,104 @@
|
||||
#include "Framebuffer.h"
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fb.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Display::Graphics
|
||||
{
|
||||
Framebuffer::Framebuffer(const char *device)
|
||||
{
|
||||
fd_ = open(device, O_RDWR);
|
||||
if (fd_ < 0)
|
||||
throw std::runtime_error("Cannot open framebuffer");
|
||||
|
||||
fb_var_screeninfo vinfo;
|
||||
fb_fix_screeninfo finfo;
|
||||
|
||||
ioctl(fd_, FBIOGET_VSCREENINFO, &vinfo);
|
||||
ioctl(fd_, FBIOGET_FSCREENINFO, &finfo);
|
||||
|
||||
width_ = vinfo.xres;
|
||||
height_ = vinfo.yres;
|
||||
line_len_ = finfo.line_length;
|
||||
size_ = finfo.smem_len;
|
||||
|
||||
fb_ = static_cast<uint8_t *>(mmap(nullptr, size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0));
|
||||
if (fb_ == MAP_FAILED)
|
||||
throw std::runtime_error("mmap failed");
|
||||
}
|
||||
|
||||
Framebuffer::~Framebuffer()
|
||||
{
|
||||
munmap(fb_, size_);
|
||||
close(fd_);
|
||||
}
|
||||
|
||||
void Framebuffer::clear(uint16_t color)
|
||||
{
|
||||
for (int y = 0; y < height_; ++y)
|
||||
{
|
||||
uint16_t *row = reinterpret_cast<uint16_t *>(fb_ + y * line_len_);
|
||||
for (int x = 0; x < width_; ++x)
|
||||
row[x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void Framebuffer::fillRect(int x, int y, int w, int h, uint16_t color)
|
||||
{
|
||||
for (int j = 0; j < h; ++j)
|
||||
{
|
||||
int py = y + j;
|
||||
if (py < 0 || py >= height_)
|
||||
continue;
|
||||
|
||||
uint16_t *row = reinterpret_cast<uint16_t *>(fb_ + py * line_len_);
|
||||
for (int i = 0; i < w; ++i)
|
||||
{
|
||||
int px = x + i;
|
||||
if (px < 0 || px >= width_)
|
||||
continue;
|
||||
|
||||
row[px] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Framebuffer::drawRect(int x, int y, int w, int h, const Color &c)
|
||||
{
|
||||
// верх
|
||||
fillRect(x, y, w, 1, c);
|
||||
// низ
|
||||
fillRect(x, y + h - 1, w, 1, c);
|
||||
// лево
|
||||
fillRect(x, y, 1, h, c);
|
||||
// право
|
||||
fillRect(x + w - 1, y, 1, h, c);
|
||||
}
|
||||
|
||||
void Framebuffer::setPixel(int x, int y, const Color &c)
|
||||
{
|
||||
if (x < 0 || x >= width_ || y < 0 || y >= height_)
|
||||
return;
|
||||
|
||||
uint16_t *p = reinterpret_cast<uint16_t *>(fb_ + y * line_len_) + x;
|
||||
*p = ((c.r & 0xF8) << 8) | ((c.g & 0xFC) << 3) | (c.b >> 3);
|
||||
}
|
||||
|
||||
Color Framebuffer::getPixel(int x, int y) const
|
||||
{
|
||||
if (x < 0 || x >= width_ || y < 0 || y >= height_)
|
||||
return {0, 0, 0, 255};
|
||||
|
||||
uint16_t p = *(reinterpret_cast<uint16_t *>(fb_ + y * line_len_) + x);
|
||||
Color c;
|
||||
c.r = (p >> 8) & 0xF8;
|
||||
c.g = (p >> 3) & 0xFC;
|
||||
c.b = (p << 3) & 0xF8;
|
||||
c.a = 255;
|
||||
return c;
|
||||
}
|
||||
} // namespace Display::Graphics
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "Display/Graphics/Color.h"
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
namespace Display::Graphics
|
||||
{
|
||||
class Framebuffer
|
||||
{
|
||||
public:
|
||||
Framebuffer(const char *device);
|
||||
~Framebuffer();
|
||||
|
||||
void clear(uint16_t color);
|
||||
void fillRect(int x, int y, int w, int h, uint16_t color);
|
||||
void drawRect(int x, int y, int w, int h, const Color &c);
|
||||
void setPixel(int x, int y, const Color &c);
|
||||
Color getPixel(int x, int y) const;
|
||||
|
||||
int width() const { return width_; }
|
||||
int height() const { return height_; }
|
||||
|
||||
private:
|
||||
int fd_;
|
||||
uint8_t *fb_;
|
||||
size_t size_;
|
||||
int width_;
|
||||
int height_;
|
||||
int line_len_;
|
||||
};
|
||||
} // namespace Display::Graphics
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "Renderer.h"
|
||||
|
||||
namespace Display::Graphics
|
||||
{
|
||||
Renderer::Renderer(Framebuffer &framebuffer, Model::HostRegistry ®istry)
|
||||
: framebuffer(framebuffer),
|
||||
registry(registry),
|
||||
barMem(200, 10)
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer::render()
|
||||
{
|
||||
// очистка экрана
|
||||
framebuffer.clear(Color{0, 0, 0});
|
||||
|
||||
int y = 10; // начальная вертикальная позиция
|
||||
int lineHeight = 24; // высота строки (подбираем под шрифт)
|
||||
|
||||
for (auto &[host, m] : registry.snapshot())
|
||||
{
|
||||
// рисуем фон строки
|
||||
framebuffer.fillRect(10, y - 18, 300, lineHeight, Color{0, 64, 0});
|
||||
|
||||
// формируем строку
|
||||
std::string line = host + " " + std::to_string(int(m.cpu.loads.at(0))) +
|
||||
"% " + std::to_string(int(m.memory.used / 1024 / 1024)) +
|
||||
"/" + std::to_string(int(m.memory.total / 1024 / 1024)) +
|
||||
" " + std::to_string(int(m.disks.at(0).used / 1024 / 1024)) +
|
||||
"/" + std::to_string(int(m.disks.at(0).total / 1024 / 1024));
|
||||
|
||||
// выводим текст на экран
|
||||
textRenderer.drawText(framebuffer, 12, y, line, Color{255, 255, 255});
|
||||
|
||||
float mem = (float)m.memory.used / (float)m.memory.total;
|
||||
barMem.draw(framebuffer, 10, y + 35, mem);
|
||||
|
||||
y += lineHeight; // переход на следующую строку
|
||||
}
|
||||
}
|
||||
} // namespace Display::Graphics
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "Display/Graphics/Framebuffer.h"
|
||||
#include "Model/HostRegistry.h"
|
||||
#include "Display/UI/Text/Renderer.h"
|
||||
#include "Display/UI/Bar/Bar.h"
|
||||
#include "Display/Graphics/Color.h"
|
||||
#include <string>
|
||||
|
||||
namespace Display::Graphics
|
||||
{
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
Renderer(Framebuffer &framebuffer, Model::HostRegistry ®istry);
|
||||
|
||||
Renderer(const Renderer &) = delete;
|
||||
Renderer &operator=(const Renderer &) = delete;
|
||||
|
||||
void render();
|
||||
|
||||
private:
|
||||
Framebuffer &framebuffer;
|
||||
Model::HostRegistry ®istry;
|
||||
Display::UI::Text::Renderer textRenderer;
|
||||
Display::UI::Bar::Bar barMem;
|
||||
};
|
||||
} // namespace Display::Graphics
|
||||
Reference in New Issue
Block a user