echoplayer: add shadow framebuffer to avoid tearing
rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
| Newsgroups | gmane.comp.systems.archos.rockbox.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit ad9471be3b2ef4be5e452a478139778f08878bba Author: Aidan MacDonald <[email protected]> Date: Sat Jan 24 21:26:00 2026 +0000 echoplayer: add shadow framebuffer to avoid tearing Using a simple memcpy to a separate framebuffer prevents objectionable levels of flickering caused by scanning out the main framebuffer while it's modified between updates. With optimized memcpy, copying the whole framebuffer takes about 260us at maximum CPU+bus frequency. Using DMA would likely be a bit faster and more power-efficient, but that can be left as a future optimization. Change-Id: Ia6dc36d797cdb7a5f6663078c0ecce661267bedf diff --git a/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c b/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c index bd7ead842c..bf83ad4937 100644 --- a/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c +++ b/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c @@ -30,6 +30,7 @@ #include "regs/stm32h743/rcc.h" #include "regs/stm32h743/spi.h" #include "regs/stm32h743/ltdc.h" +#include <string.h> #define MS_TO_TICKS(x) \ (((x) + (1000 / HZ - 1)) / (1000 / HZ)) @@ -60,7 +61,8 @@ struct stm_spi_config spi_cfg = { .hw_cs_output = true, }; -struct stm_spi spi; +static struct stm_spi spi; +static fb_data shadowfb[LCD_WIDTH*LCD_HEIGHT] IRAM_LCDFRAMEBUFFER; enum lcd_controller_state { @@ -101,7 +103,7 @@ static void enable_ltdc(void) reg_assignf(LTDC_LAYER_WHPCR(0), WHSPPOS(ahbp + LCD_HAW), WHSTPOS(ahbp + 1)); reg_assignf(LTDC_LAYER_WVPCR(0), WVSPPOS(avbp + LCD_VAH), WVSTPOS(avbp + 1)); reg_assignf(LTDC_LAYER_PFCR(0), PF(BV_LTDC_LAYER_PFCR_PF_RGB565)); - reg_var(LTDC_LAYER_CFBAR(0)) = (uintptr_t)FBADDR(0, 0); + reg_var(LTDC_LAYER_CFBAR(0)) = (uintptr_t)&shadowfb[0]; reg_assignf(LTDC_LAYER_CFBLR(0), CFBP(row_bytes), CFBLL(row_bytes + 7)); reg_assignf(LTDC_LAYER_CFBLNR(0), CFBLNBR(LCD_HEIGHT)); reg_assignf(LTDC_LAYER_CR(0), LEN(1)); @@ -244,6 +246,8 @@ void lcd_update(void) if (!lcd_active()) return; + /* TODO: optimize using DMA2D */ + memcpy(shadowfb, FBADDR(0, 0), sizeof(shadowfb)); commit_dcache(); } @@ -268,8 +272,13 @@ void lcd_update_rect(int x, int y, int width, int height) if (height > LCD_HEIGHT - y) height = LCD_HEIGHT - y; + /* TODO: optimize using DMA2D */ for (int dy = 0; dy < height; ++dy) - commit_dcache_range(FBADDR(x, y+dy), FB_DATA_SZ * width); + { + fb_data *shaddr = &shadowfb[(y+dy)*LCD_WIDTH + x]; + memcpy(shaddr, FBADDR(x, y+dy), FB_DATA_SZ * width); + commit_dcache_range(shaddr, FB_DATA_SZ * width); + } } void spi5_irq_handler(void) -- rockbox-cvs mailing list [email protected] https://lists.haxx.se/mailman/listinfo/rockbox-cvs