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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.