Page 1 of 1

Single-pixel vertical lines not rendered correctly with ESP32_Display_Panel RGB framebuffer

Posted: Sat Jul 18, 2026 7:52 pm
by FLYINGSCOT
Hi all,

Problem: Single-pixel vertical lines not rendered correctly with ESP32_Display_Panel RGB framebuffer

Board: Waveshare ESP32-S3 Touch LCD 4.3" (800×480 RGB, ST7262)
MCU: ESP32-S3
Arduino ESP32 Core: 3.3.5
ESP-IDF: 5.5 (bundled with Arduino core)
Library: ESP32_Display_Panel (current version supplied with Waveshare examples)
Problem

Single-pixel-wide vertical lines written directly into the framebuffer are not displayed correctly.

The problem occurs using the official Waveshare example without any application code.

Reproduction

Starting from the standard Waveshare example (08_DrawColorBar), replace:

lcd->colorBarTest();

with:

auto fb = static_cast<uint16_t *>(lcd->getFrameBufferByIndex(0));

const int W = EXAMPLE_LCD_WIDTH;
const int H = EXAMPLE_LCD_HEIGHT;

// Fill background green
for (int i = 0; i < W * H; i++)
{
fb = 0x07E0;
}

// Draw one red vertical line
for (int y = 0; y < H; y++)
{
fb[y * W + 200] = 0xF800;
}
Expected result

A green background with a single red vertical line.

Actual result

A green background with a black vertical stripe where the red line should be.

Additional tests
Full-screen fill
fb = 0x07E0;

✔ Works correctly.

Single horizontal line
for (int x = 0; x < W; x++)
fb[200 * W + x] = 0xF800;

✔ Works correctly.

Single vertical line
for (int y = 0; y < H; y++)
fb[y * W + 200] = 0xF800;

✘ Displays as a black stripe.

Two adjacent vertical lines
for (int y = 0; y < H; y++)
{
fb[y * W + 200] = 0xF800;
fb[y * W + 201] = 0xF800;
}

✔ Both lines display correctly.

Five adjacent coloured columns
for (int y = 0; y < H; y++)
{
fb[y * W + 198] = 0xF800;
fb[y * W + 199] = 0xFFE0;
fb[y * W + 200] = 0xFFFF;
fb[y * W + 201] = 0x001F;
fb[y * W + 202] = 0x0000;
}

✔ All five columns display correctly.

Five isolated single-pixel columns

Columns separated by several pixels:

198 Red
204 Yellow
210 White
216 Blue
222 Black

Results:

Red → black stripe
Yellow → not visible
White → not visible
Blue → black stripe
Black → black stripe
Framebuffer information

Framebuffer pointer obtained using:

auto fb = static_cast<uint16_t *>(lcd->getFrameBufferByIndex(0));

Diagnostics:

Framebuffer located in external PSRAM
64-byte aligned
Not DMA capable
RGB driver configured with a bounce buffer (800 × 10 pixels)
Observation

The problem only affects isolated one-pixel-wide vertical features.

Horizontal features render correctly.
Full-screen fills render correctly.
Adjacent vertical pixels render correctly.
The problem is fully reproducible using the vendor example and does not depend on application code.
Question

Is this a known limitation or bug in:

ESP32_Display_Panel
the ESP-IDF RGB panel driver
bounce-buffer handling
PSRAM framebuffer handling

or is an additional synchronization step required after direct framebuffer writes?

Thanks in advance.

Re: Single-pixel vertical lines not rendered correctly with ESP32_Display_Panel RGB framebuffer

Posted: Tue Jul 28, 2026 12:49 pm
by lichurbagan
This looks like a PSRAM/bounce-buffer coherency or alignment bug, especially because two adjacent RGB565 pixels form one 32-bit write and work correctly.

First, ensure the fill statement is actually:

Code: Select all

fb[i] = 0x07E0;
Then try flushing the modified framebuffer before it is scanned:

Code: Select all

#include "esp_cache.h"

esp_cache_msync(
    fb,
    W * H * sizeof(uint16_t),
    ESP_CACHE_MSYNC_FLAG_DIR_C2M |
    ESP_CACHE_MSYNC_FLAG_UNALIGNED
);
Also test with the bounce buffer disabled or the framebuffer allocated in internal RAM. If either fixes it, the RGB timing and panel are fine and the fault is in the PSRAM/bounce-buffer path.

For production code, use the panel’s drawing API or double buffering with a VSYNC-controlled buffer swap instead of modifying the active framebuffer directly. If cache synchronization does not help, this minimal example is strong enough to report as an ESP-IDF/ESP32_Display_Panel bug. Espressif documents that bounce-buffer mode copies portions of the PSRAM framebuffer into internal DMA buffers during refresh: ESP-IDF RGB LCD documentation.

The ESP32-S3 includes PSRAM support and a dedicated LCD interface, as summarized in this ESP32 versus ESP32-S3 overview. However, the observed behaviour appears to be within the software’s PSRAM-to-bounce-buffer path rather than a limitation of the display hardware.