Code adapted for monochrome 1bpp displays

This commit is contained in:
2026-04-03 18:11:08 -03:00
parent be4abb9289
commit 22a100bee1
2 changed files with 80 additions and 1 deletions

View File

@@ -97,6 +97,14 @@ void LinuxFBDisplay::writePixel(uint8_t* dst, Color color) const {
// ---------------------------------------------------------------------------
void LinuxFBDisplay::drawPixelImpl(int16_t x, int16_t y, Color color) {
if (!buf_) return;
if (bpp_ == 1) {
uint8_t* p = buf_ + static_cast<uint32_t>(y) * line_len_
+ static_cast<uint32_t>(x) / 8;
uint8_t bit = static_cast<uint32_t>(x) & 7u;
if (color) *p |= (1u << bit);
else *p &= ~(1u << bit);
return;
}
uint32_t offset = static_cast<uint32_t>(y) * line_len_
+ static_cast<uint32_t>(x) * (bpp_ / 8);
writePixel(buf_ + offset, color);
@@ -109,6 +117,35 @@ void LinuxFBDisplay::drawHLineImpl(int16_t x, int16_t y,
int16_t w, Color color) {
if (!buf_ || w <= 0) return;
if (bpp_ == 1) {
uint8_t* row = buf_ + static_cast<uint32_t>(y) * line_len_;
uint32_t x0 = static_cast<uint32_t>(x);
uint32_t x1 = x0 + static_cast<uint32_t>(w) - 1;
uint32_t b0 = x0 >> 3;
uint32_t b1 = x1 >> 3;
// LSB-first: bit mask for pixel x within its byte = 0x01 << (x & 7)
// A run from x0 to end-of-byte b0 → 0xFF << (x0 & 7)
// A run from start-of-byte b1 to x1 → 0xFF >> (7 - (x1 & 7))
if (b0 == b1) {
uint8_t mask = (0xFFu << (x0 & 7u)) & (0xFFu >> (7u - (x1 & 7u)));
if (color) row[b0] |= mask;
else row[b0] &= ~mask;
} else {
uint8_t lead = 0xFFu << (x0 & 7u);
uint8_t trail = 0xFFu >> (7u - (x1 & 7u));
if (color) {
row[b0] |= lead;
if (b1 > b0 + 1) std::memset(row + b0 + 1, 0xFF, b1 - b0 - 1);
row[b1] |= trail;
} else {
row[b0] &= ~lead;
if (b1 > b0 + 1) std::memset(row + b0 + 1, 0x00, b1 - b0 - 1);
row[b1] &= ~trail;
}
}
return;
}
uint32_t bytes_pp = bpp_ / 8;
uint8_t* row = buf_ + static_cast<uint32_t>(y) * line_len_
+ static_cast<uint32_t>(x) * bytes_pp;
@@ -143,6 +180,18 @@ void LinuxFBDisplay::drawVLineImpl(int16_t x, int16_t y,
int16_t h, Color color) {
if (!buf_ || h <= 0) return;
if (bpp_ == 1) {
uint8_t bit = static_cast<uint32_t>(x) & 7u;
uint8_t* p = buf_ + static_cast<uint32_t>(y) * line_len_
+ static_cast<uint32_t>(x) / 8;
for (int16_t i = 0; i < h; ++i) {
if (color) *p |= (1u << bit);
else *p &= ~(1u << bit);
p += line_len_;
}
return;
}
uint32_t bytes_pp = bpp_ / 8;
uint8_t* p = buf_ + static_cast<uint32_t>(y) * line_len_
+ static_cast<uint32_t>(x) * bytes_pp;
@@ -164,6 +213,36 @@ void LinuxFBDisplay::fillRectImpl(int16_t x, int16_t y,
int16_t w, int16_t h, Color color) {
if (!buf_ || w <= 0 || h <= 0) return;
if (bpp_ == 1) {
uint32_t x0 = static_cast<uint32_t>(x);
uint32_t x1 = x0 + static_cast<uint32_t>(w) - 1;
uint32_t b0 = x0 >> 3;
uint32_t b1 = x1 >> 3;
// Fill the first row (handles partial edge bytes correctly).
drawHLineImpl(x, y, w, color);
if (h == 1) return;
uint8_t* src = buf_ + static_cast<uint32_t>(y) * line_len_ + b0;
uint32_t span = b1 - b0 + 1;
if ((x0 & 7u) == 0 && (x1 & 7u) == 7u) {
// Byte-aligned: safe to memcpy the full span to every subsequent row.
uint8_t* dst = src + line_len_;
for (int16_t r = 1; r < h; ++r) {
std::memcpy(dst, src, span);
dst += line_len_;
}
} else {
// Unaligned: edge bytes are shared with neighboring pixels,
// so each row must be drawn individually.
for (int16_t r = 1; r < h; ++r)
drawHLineImpl(x, y + r, w, color);
}
return;
}
// For 32-bpp with color == black or white, we can use memset for the
// entire rectangle. Otherwise, fill the first row with drawHLineImpl
// and memcpy it to subsequent rows.

View File

@@ -1,6 +1,6 @@
// linux_fb_display.h — GfxCanvas subclass for Linux framebuffer devices.
//
// Supports XRGB8888 (32 bpp), RGB565 (16 bpp), and 8-bit grayscale.
// Supports XRGB8888 (32 bpp), RGB565 (16 bpp), 8-bit grayscale, and 1 bpp (SSD1306).
// Uses mmap for zero-copy access to the kernel framebuffer.
#ifndef LINUX_FB_DISPLAY_H