From 3f712e3f1c68f2da2e6c221d94d0c97d8f2558cb Mon Sep 17 00:00:00 2001 From: Daniele Cloralio Date: Fri, 16 Oct 2026 14:18:05 +0200 Subject: [PATCH] Improve framebuffer handling Respect portrait dimensions, clear framebuffers during begin(), and add getDrawBuffer() for drawing without exposing LTDC details. --- src/Arduino_Video.cpp | 35 ++++++++++++++++++++++++++++++----- src/Arduino_Video.h | 10 ++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/Arduino_Video.cpp b/src/Arduino_Video.cpp index e1b3e46..2e621e3 100644 --- a/src/Arduino_Video.cpp +++ b/src/Arduino_Video.cpp @@ -56,6 +56,7 @@ static struct display_buffer_descriptor desc = { .frame_incomplete = false }; uint16_t *buffer = nullptr; +static uint8_t *framebuffer_base = nullptr; #endif Arduino_Video::Arduino_Video(int width, int height, DisplayShield &shield) @@ -117,8 +118,8 @@ int Arduino_Video::begin() { #endif display_get_capabilities(display_dev, &display_caps); - _width = display_caps.y_resolution; - _height = display_caps.x_resolution; + _width = _rotated ? display_caps.y_resolution : display_caps.x_resolution; + _height = _rotated ? display_caps.x_resolution : display_caps.y_resolution; printk("- Capabilities:\n"); printk(" x_resolution = %u, y_resolution = %u\n, supported_pixel_formats = %u\n" @@ -127,8 +128,6 @@ int Arduino_Video::begin() { display_caps.supported_pixel_formats, display_caps.current_pixel_format, display_caps.current_orientation); - display_blanking_off(display_dev); - void *ptrFB = display_get_framebuffer(display_dev); if (ptrFB == nullptr) { printk("Memory display allocation failed!"); @@ -136,10 +135,20 @@ int Arduino_Video::begin() { } // Cast the void pointer to an int pointer to use it buffer = static_cast(ptrFB); + if (framebuffer_base == nullptr) { + framebuffer_base = static_cast(ptrFB); + } display_blanking_on(display_dev); + if (display_caps.current_pixel_format == PIXEL_FORMAT_RGB_565) { + memset(framebuffer_base, 0, CONFIG_STM32_LTDC_FB_NUM * display_caps.x_resolution * + display_caps.y_resolution * sizeof(uint16_t)); + } + display_blanking_off(display_dev); - setFrameDesc(width(), height(), width(), (width() * height() * sizeof(uint16_t))); + setFrameDesc(display_caps.x_resolution, display_caps.y_resolution, + display_caps.x_resolution, + display_caps.x_resolution * display_caps.y_resolution * sizeof(uint16_t)); #else /* Video controller/bridge init */ int err_code = _shield->init(_edidMode); @@ -357,6 +366,22 @@ void *Arduino_Video::getFramebuffer() { } #if defined(ARDUINO_GIGA) && defined(__ZEPHYR__) +void *Arduino_Video::getDrawBuffer() { + if (framebuffer_base == nullptr || display_caps.current_pixel_format != PIXEL_FORMAT_RGB_565) { + return nullptr; + } + + uint8_t *front = static_cast(display_get_framebuffer(display_dev)); + size_t bytes = display_caps.x_resolution * display_caps.y_resolution * sizeof(uint16_t); + for (int i = 0; i < CONFIG_STM32_LTDC_FB_NUM; i++) { + uint8_t *candidate = framebuffer_base + i * bytes; + if (candidate != front) { + return candidate; + } + } + return front; +} + void Arduino_Video::setFrameDesc(uint16_t w, uint16_t h, uint16_t pitch, uint32_t buf_size) { desc.buf_size = buf_size; desc.width = w; /** Number of pixels between consecutive rows in the data buffer */ diff --git a/src/Arduino_Video.h b/src/Arduino_Video.h index f621e19..9d8a853 100644 --- a/src/Arduino_Video.h +++ b/src/Arduino_Video.h @@ -105,6 +105,16 @@ class Arduino_Video void *getFramebuffer(); #if defined(__ZEPHYR__) + /** + * @brief Get a native RGB565 buffer for drawing, or nullptr if unavailable. + * + * Uses a non-displayed driver buffer when available, otherwise the displayed + * buffer (which may tear). Present it with drawBuffer(0, 0, buf). + * Buffer coordinates are native panel coordinates, without logical rotation. + * The pointer is owned by the driver and must not be freed. + */ + void *getDrawBuffer(); + /** * @brief Set the frame descriptor for the display. *