This commit is contained in:
2025-12-25 13:00:42 +00:00
parent f5dc0ccbc9
commit 86947912dc
58 changed files with 959 additions and 328 deletions
+11 -5
View File
@@ -1,15 +1,21 @@
message(STATUS " Configuring Graphics")
message(STATUS "··Configuring Graphics")
add_library(Graphics
add_library(DisplayGraphics
Framebuffer.cpp
Renderer.cpp
)
target_link_libraries(Graphics
PRIVATE Model Helpers UI
add_library(Display::Graphics ALIAS DisplayGraphics)
target_link_libraries(DisplayGraphics
PRIVATE
Model::All
Helpers::All
Display::UI::Text
Display::UI::HostBlock
)
target_include_directories(Graphics
target_include_directories(DisplayGraphics
PUBLIC
${INCLUDE_BASE_DIR}
)
+86 -52
View File
@@ -9,95 +9,129 @@
namespace Display::Graphics
{
Framebuffer::Framebuffer(const char *device)
Framebuffer::Framebuffer(const char *device, FramebufferRotation rotation) : rotation(rotation)
{
fd_ = open(device, O_RDWR);
if (fd_ < 0)
throw std::runtime_error("Cannot open framebuffer");
fd = open(device, O_RDWR);
if (fd < 0)
throw std::runtime_error("Failed to open framebuffer");
fb_var_screeninfo vinfo;
fb_fix_screeninfo finfo;
fb_var_screeninfo vinfo{};
fb_fix_screeninfo finfo{};
ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
physical.width = vinfo.xres;
physical.height = vinfo.yres;
line_length = finfo.line_length;
size = finfo.smem_len;
ioctl(fd_, FBIOGET_VSCREENINFO, &vinfo);
ioctl(fd_, FBIOGET_FSCREENINFO, &finfo);
if (rotation == FramebufferRotation::R90 || rotation == FramebufferRotation::R270)
{
logical.width = physical.height;
logical.height = physical.width;
}
else
{
logical.width = physical.width;
logical.height = physical.height;
}
width_ = vinfo.xres;
height_ = vinfo.yres;
line_len_ = finfo.line_length;
size_ = finfo.smem_len;
buffer.resize(physical.width * physical.height, 0);
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");
fb = static_cast<uint8_t *>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
if (fb == MAP_FAILED)
throw std::runtime_error("Failed to mmap framebuffer");
}
Framebuffer::~Framebuffer()
{
munmap(fb_, size_);
close(fd_);
munmap(fb, size);
close(fd);
}
void Framebuffer::clear(uint16_t color)
{
for (int y = 0; y < height_; ++y)
for (int y = 0; y < logical.height; ++y)
{
uint16_t *row = reinterpret_cast<uint16_t *>(fb_ + y * line_len_);
for (int x = 0; x < width_; ++x)
uint16_t *row = reinterpret_cast<uint16_t *>(fb + y * line_length);
for (int x = 0; x < logical.width; ++x)
row[x] = color;
}
}
void Framebuffer::fillRect(int x, int y, int w, int h, uint16_t color)
void Framebuffer::present()
{
for (int j = 0; j < h; ++j)
for (int y = 0; y < logical.height; ++y)
{
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)
for (int x = 0; x < logical.width; ++x)
{
int px = x + i;
if (px < 0 || px >= width_)
continue;
int fx = 0;
int fy = 0;
row[px] = color;
switch (rotation)
{
case FramebufferRotation::R0:
fx = x;
fy = y;
break;
case FramebufferRotation::R90:
fx = physical.width - 1 - y;
fy = x;
break;
case FramebufferRotation::R180:
fx = physical.width - 1 - x;
fy = physical.height - 1 - y;
break;
case FramebufferRotation::R270:
fx = y;
fy = physical.height - 1 - x;
break;
}
uint16_t *row =
reinterpret_cast<uint16_t *>(fb + fy * line_length);
row[fx] = buffer[y * logical.width + x];
}
}
}
void Framebuffer::drawRect(int x, int y, int w, int h, const Color &c)
void Framebuffer::fillRect(int x, int y, int w, int h, const Color &color)
{
// верх
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);
for (int j = 0; j < h; ++j)
for (int i = 0; i < w; ++i)
setPixel(x + i, y + j, color);
}
void Framebuffer::setPixel(int x, int y, const Color &c)
void Framebuffer::drawRect(int x, int y, int w, int h, const Color &color)
{
if (x < 0 || x >= width_ || y < 0 || y >= height_)
return;
// верх
fillRect(x, y, w, 1, color);
// низ
fillRect(x, y + h - 1, w, 1, color);
// лево
fillRect(x, y, 1, h, color);
// право
fillRect(x + w - 1, y, 1, h, color);
}
uint16_t *p = reinterpret_cast<uint16_t *>(fb_ + y * line_len_) + x;
*p = ((c.r & 0xF8) << 8) | ((c.g & 0xFC) << 3) | (c.b >> 3);
void Framebuffer::setPixel(int x, int y, const Color &color)
{
if (x < 0 || x >= logical.width || y < 0 || y >= logical.height)
return;
buffer[y * logical.width + x] = rgb565(color);
}
Color Framebuffer::getPixel(int x, int y) const
{
if (x < 0 || x >= width_ || y < 0 || y >= height_)
if (x < 0 || x >= logical.width || y < 0 || y >= logical.height)
return {0, 0, 0, 255};
uint16_t p = *(reinterpret_cast<uint16_t *>(fb_ + y * line_len_) + x);
uint16_t p = buffer[y * logical.width + x];
Color c;
c.r = (p >> 8) & 0xF8;
c.g = (p >> 3) & 0xFC;
c.b = (p << 3) & 0xF8;
c.r = ((p >> 11) & 0x1F) << 3;
c.g = ((p >> 5) & 0x3F) << 2;
c.b = (p & 0x1F) << 3;
c.a = 255;
return c;
}
+26 -14
View File
@@ -1,31 +1,43 @@
#pragma once
#include "Display/Graphics/Color.h"
#include <vector>
#include <cstdint>
#include <cstddef>
#include "Display/Graphics/Color.h"
#include "Display/Graphics/FramebufferRotation.h"
namespace Display::Graphics
{
class Framebuffer
{
public:
Framebuffer(const char *device);
Framebuffer(const char *device, FramebufferRotation rotation);
~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);
void present();
void fillRect(int x, int y, int w, int h, const Color &color);
void drawRect(int x, int y, int w, int h, const Color &color);
void setPixel(int x, int y, const Color &color);
Color getPixel(int x, int y) const;
int width() const { return width_; }
int height() const { return height_; }
int getWidth() const { return logical.width; }
int getHeight() const { return logical.height; }
FramebufferRotation getRotation() const { return rotation; }
private:
int fd_;
uint8_t *fb_;
size_t size_;
int width_;
int height_;
int line_len_;
struct Dimensions
{
int width;
int height;
};
FramebufferRotation rotation = FramebufferRotation::R0;
std::vector<uint16_t> buffer;
Dimensions physical;
Dimensions logical;
int fd;
uint8_t *fb;
size_t size;
int line_length;
};
} // namespace Display::Graphics
@@ -0,0 +1,12 @@
#pragma once
namespace Display::Graphics
{
enum class FramebufferRotation
{
R0,
R90,
R180,
R270
};
} // namespace Display::Graphics
+21 -19
View File
@@ -4,38 +4,40 @@ namespace Display::Graphics
{
Renderer::Renderer(Framebuffer &framebuffer, Model::HostRegistry &registry)
: framebuffer(framebuffer),
registry(registry),
barMem(200, 10)
registry(registry)
{
}
void Renderer::render()
{
// очистка экрана
framebuffer.clear(Color{0, 0, 0});
int y = 10; // начальная вертикальная позиция
int lineHeight = 24; // высота строки (подбираем под шрифт)
int blocksPerRow =
(SCREEN_WIDTH + BLOCK_GAP) / (Display::UI::HostBlock::BLOCK_WIDTH + BLOCK_GAP);
if (blocksPerRow < 1)
blocksPerRow = 1;
int index = 0;
for (auto &[host, m] : registry.snapshot())
{
// рисуем фон строки
framebuffer.fillRect(10, y - 18, 300, lineHeight, Color{0, 64, 0});
int col = index % blocksPerRow;
int row = index / blocksPerRow;
// формируем строку
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));
int x = START_X + col * (Display::UI::HostBlock::BLOCK_WIDTH + BLOCK_GAP);
int y = START_Y + row * (Display::UI::HostBlock::BLOCK_HEIGHT + BLOCK_GAP);
// выводим текст на экран
textRenderer.drawText(framebuffer, 12, y, line, Color{255, 255, 255});
hostblock.draw(
framebuffer,
textRenderer,
x,
y,
host,
m);
float mem = (float)m.memory.used / (float)m.memory.total;
barMem.draw(framebuffer, 10, y + 35, mem);
y += lineHeight; // переход на следующую строку
++index;
}
framebuffer.present();
}
} // namespace Display::Graphics
+8 -2
View File
@@ -2,12 +2,18 @@
#include "Display/Graphics/Framebuffer.h"
#include "Model/HostRegistry.h"
#include "Display/UI/Text/Renderer.h"
#include "Display/UI/Bar/Bar.h"
#include "Display/UI/HostBlock/HostBlock.h"
#include "Display/Graphics/Color.h"
#include <string>
namespace Display::Graphics
{
static constexpr int START_X = 0;
static constexpr int START_Y = 10;
static constexpr int BLOCK_GAP = 4;
static constexpr int SCREEN_WIDTH = 240;
class Renderer
{
public:
@@ -22,6 +28,6 @@ namespace Display::Graphics
Framebuffer &framebuffer;
Model::HostRegistry &registry;
Display::UI::Text::Renderer textRenderer;
Display::UI::Bar::Bar barMem;
Display::UI::HostBlock::HostBlock hostblock;
};
} // namespace Display::Graphics