idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
rgb565_framebuffer.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
13#include <idfxx/error>
14#include <idfxx/lcd/color>
15#include <idfxx/lcd/panel>
16
17#include <algorithm>
18#include <cstddef>
19#include <span>
20#include <vector>
21
26namespace idfxx::lcd {
27
54public:
57
58#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
68 [[nodiscard]] rgb565_framebuffer(size_t width, size_t height)
70#endif
71
81 [[nodiscard]] static result<rgb565_framebuffer> make(size_t width, size_t height) {
82 if (width == 0 || height == 0) {
84 }
85 return rgb565_framebuffer{width, height, std::vector<rgb565>(width * height)};
86 }
87
89 [[nodiscard]] size_t width() const noexcept { return _width; }
90
92 [[nodiscard]] size_t height() const noexcept { return _height; }
93
103 void set_pixel(size_t x, size_t y, rgb565 color) noexcept {
104 if (x >= _width || y >= _height) {
105 return;
106 }
107 _data[y * _width + x] = color;
108 }
109
117 [[nodiscard]] rgb565 get_pixel(size_t x, size_t y) const noexcept {
118 if (x >= _width || y >= _height) {
119 return {};
120 }
121 return _data[y * _width + x];
122 }
123
128 void fill(rgb565 color) noexcept { std::ranges::fill(_data, color); }
129
131 void clear() noexcept { fill({}); }
132
142 [[nodiscard]] std::span<const rgb565> data() const noexcept { return _data; }
143
144#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
158 void flush(panel& panel, size_t x = 0, size_t y = 0) const { unwrap(try_flush(panel, x, y)); }
159
173 void flush_rows(panel& panel, size_t y_start, size_t y_end) const { unwrap(try_flush_rows(panel, y_start, y_end)); }
174
192 void flush_region(panel& panel, size_t x_start, size_t y_start, size_t x_end, size_t y_end) const {
193 unwrap(try_flush_region(panel, x_start, y_start, x_end, y_end));
194 }
195#endif
196
209 [[nodiscard]] result<void> try_flush(panel& panel, size_t x = 0, size_t y = 0) const {
210 return panel.try_draw_bitmap(
211 static_cast<int>(x),
212 static_cast<int>(y),
213 static_cast<int>(x + _width),
214 static_cast<int>(y + _height),
215 _data.data()
216 );
217 }
218
232 [[nodiscard]] result<void> try_flush_rows(panel& panel, size_t y_start, size_t y_end) const {
233 return try_flush_region(panel, 0, y_start, _width, y_end);
234 }
235
253 [[nodiscard]] result<void>
254 try_flush_region(panel& panel, size_t x_start, size_t y_start, size_t x_end, size_t y_end) const {
255 if (x_start >= x_end || x_end > _width || y_start >= y_end || y_end > _height) {
256 return error(errc::invalid_arg);
257 }
258 if (x_start == 0 && x_end == _width) {
259 // In the row-major layout a full-width band is contiguous, so a
260 // single transfer covers all its rows.
261 return panel.try_draw_bitmap(
262 0,
263 static_cast<int>(y_start),
264 static_cast<int>(_width),
265 static_cast<int>(y_end),
266 _data.data() + y_start * _width
267 );
268 }
269 for (size_t row = y_start; row < y_end; ++row) {
270 auto drawn = panel.try_draw_bitmap(
271 static_cast<int>(x_start),
272 static_cast<int>(row),
273 static_cast<int>(x_end),
274 static_cast<int>(row + 1),
275 _data.data() + row * _width + x_start
276 );
277 if (!drawn) {
278 return drawn;
279 }
280 }
281 return {};
282 }
283
284private:
285 rgb565_framebuffer(size_t width, size_t height, std::vector<rgb565> data)
286 : _width(width)
287 , _height(height)
288 , _data(std::move(data)) {}
289
290 size_t _width;
291 size_t _height;
292 std::vector<rgb565> _data;
293};
294
295} // namespace idfxx::lcd
Abstract base class for LCD panels.
Definition panel.hpp:47
result< void > try_draw_bitmap(int x_start, int y_start, int x_end, int y_end, const void *color_data)
Draws bitmap data to a region of the display.
Definition panel.hpp:163
In-memory framebuffer for RGB565 (16 bits per pixel) color displays.
void flush(panel &panel, size_t x=0, size_t y=0) const
Draws the full framebuffer to a panel.
rgb565_framebuffer(size_t width, size_t height)
Creates a framebuffer of the given dimensions, with all pixels black.
result< void > try_flush(panel &panel, size_t x=0, size_t y=0) const
Draws the full framebuffer to a panel.
size_t height() const noexcept
Returns the height in pixels.
void fill(rgb565 color) noexcept
Sets every pixel to the given color.
rgb565 get_pixel(size_t x, size_t y) const noexcept
Returns the color of a single pixel.
void set_pixel(size_t x, size_t y, rgb565 color) noexcept
Sets a single pixel to the given color.
void flush_rows(panel &panel, size_t y_start, size_t y_end) const
Draws a horizontal band of the framebuffer to a panel.
static result< rgb565_framebuffer > make(size_t width, size_t height)
Creates a framebuffer of the given dimensions, with all pixels black.
void flush_region(panel &panel, size_t x_start, size_t y_start, size_t x_end, size_t y_end) const
Draws a rectangular region of the framebuffer to a panel.
result< void > try_flush_region(panel &panel, size_t x_start, size_t y_start, size_t x_end, size_t y_end) const
Draws a rectangular region of the framebuffer to a panel.
result< void > try_flush_rows(panel &panel, size_t y_start, size_t y_end) const
Draws a horizontal band of the framebuffer to a panel.
size_t width() const noexcept
Returns the width in pixels.
std::span< const rgb565 > data() const noexcept
Returns the raw pixel data.
void clear() noexcept
Sets every pixel to black (equivalent to fill({})).
A 16-bit RGB565 color, stored in panel byte order.
Definition color.hpp:55
LCD driver classes.
Definition color.hpp:21
constexpr std::unexpected< std::error_code > error(E e) noexcept
Creates an unexpected error from an error code enum.
Definition error.hpp:187
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
@ invalid_arg
Invalid argument.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120