This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit d66a44d0dd397764919d8f3332f89a23f1d4bde8
Author: jianglianfang <[email protected]>
AuthorDate: Sat May 9 19:07:22 2026 +0800

    graphics/lvgl: backport virtual framebuffer offset handling
    
    Backport the NuttX fbdev offset adaptation to the LVGL 9.2.2 archive.
    Apply the single-file patch through both Make and CMake, including
    already extracted sources, without modifying independent Git checkouts.
    Release mapped buffers on failure, rebinding and display deletion.
    The patch requires the matching nonconsecutive framebuffer driver.
    
    Signed-off-by: jianglianfang <[email protected]>
    Signed-off-by: rongyichang <[email protected]>
---
 ...uttx-fbdev-use-virtual-framebuffer-offset.patch | 168 +++++++++++++++++++++
 graphics/lvgl/CMakeLists.txt                       |  75 ++++++---
 graphics/lvgl/Makefile                             |  25 ++-
 3 files changed, 237 insertions(+), 31 deletions(-)

diff --git 
a/graphics/lvgl/0001-nuttx-fbdev-use-virtual-framebuffer-offset.patch 
b/graphics/lvgl/0001-nuttx-fbdev-use-virtual-framebuffer-offset.patch
new file mode 100644
index 000000000..7fe10f5b7
--- /dev/null
+++ b/graphics/lvgl/0001-nuttx-fbdev-use-virtual-framebuffer-offset.patch
@@ -0,0 +1,168 @@
+From: jianglianfang <[email protected]>
+Date: Sat, 9 May 2026 19:07:22 +0800
+Subject: [PATCH] nuttx: fbdev: use virtual framebuffer offset
+
+Minimal backport of e2a03f78735104a582a938281dec7d4fd0f3866b
+(Gerrit 7769608, patch set 1) to LVGL v9.2.2.
+
+Map the second frame separately at stride * yres and use yres for
+panning instead of deriving a virtual offset from physical addresses.
+Unlike the original change, v9.2.2 needs the second mapping introduced
+here. Release both mappings on failure, rebinding and display deletion;
+keep the existing off-screen mode. Avoid subtracting unrelated mapped
+pointers for diagnostics.
+
+Signed-off-by: jianglianfang <[email protected]>
+---
+diff --git a/src/drivers/nuttx/lv_nuttx_fbdev.c 
b/src/drivers/nuttx/lv_nuttx_fbdev.c
+--- a/src/drivers/nuttx/lv_nuttx_fbdev.c
++++ b/src/drivers/nuttx/lv_nuttx_fbdev.c
+@@ -54,6 +54,7 @@
+ static lv_color_format_t fb_fmt_to_color_format(int fmt);
+ static int fbdev_get_pinfo(int fd, struct fb_planeinfo_s * pinfo);
+ static int fbdev_init_mem2(lv_nuttx_fb_t * dsc);
++static void fbdev_release(lv_nuttx_fb_t * dsc);
+ static void display_refr_timer_cb(lv_timer_t * tmr);
+ static void display_release_cb(lv_event_t * e);
+ #if defined(CONFIG_FB_UPDATE)
+@@ -96,7 +97,8 @@
+     LV_ASSERT(disp && file);
+     lv_nuttx_fb_t * dsc = lv_display_get_driver_data(disp);
+ 
+-    if(dsc->fd >= 0) close(dsc->fd);
++    lv_display_set_draw_buffers(disp, NULL, NULL);
++    fbdev_release(dsc);
+ 
+     /* Open the file for reading and writing*/
+ 
+@@ -125,14 +127,16 @@
+ 
+     lv_color_format_t color_format = fb_fmt_to_color_format(dsc->vinfo.fmt);
+     if(color_format == LV_COLOR_FORMAT_UNKNOWN) {
++        ret = -EINVAL;
+         goto errout;
+     }
+ 
+     dsc->mem = mmap(NULL, dsc->pinfo.fblen, PROT_READ | PROT_WRITE,
+                     MAP_SHARED | MAP_FILE, dsc->fd, 0);
+     if(dsc->mem == MAP_FAILED) {
+-        LV_LOG_ERROR("ioctl(FBIOGET_PLANEINFO) failed: %d", errno);
++        LV_LOG_ERROR("mmap mem failed: %d", errno);
+         ret = -errno;
++        dsc->mem = NULL;
+         goto errout;
+     }
+ 
+@@ -176,8 +180,7 @@
+     return 0;
+ 
+ errout:
+-    close(dsc->fd);
+-    dsc->fd = -1;
++    fbdev_release(dsc);
+     return ret;
+ }
+ 
+@@ -328,8 +331,9 @@
+ 
+ static int fbdev_init_mem2(lv_nuttx_fb_t * dsc)
+ {
+-    uintptr_t buf_offset;
+     struct fb_planeinfo_s pinfo;
++    void * mem2;
++    size_t framesize;
+     int ret;
+ 
+     lv_memzero(&pinfo, sizeof(pinfo));
+@@ -349,35 +353,46 @@
+         return -EINVAL;
+     }
+ 
+-    /* Check the buffer address offset,
+-     * It needs to be divisible by pinfo.stride
+-     */
+-
+-    buf_offset = pinfo.fbmem - dsc->mem;
+-
+-    if((buf_offset % dsc->pinfo.stride) != 0) {
+-        LV_LOG_WARN("It is detected that buf_offset(%" PRIuPTR ") "
+-                    "and stride(%d) are not divisible, please ensure "
+-                    "that the driver handles the address offset by itself.",
+-                    buf_offset, dsc->pinfo.stride);
+-    }
+-
+-    /* Calculate the address and yoffset of mem2 */
+-
+-    if(buf_offset == 0) {
+-        dsc->mem2_yoffset = dsc->vinfo.yres;
+-        dsc->mem2 = pinfo.fbmem + dsc->mem2_yoffset * pinfo.stride;
+-        LV_LOG_USER("Use consecutive mem2 = %p, yoffset = %" LV_PRIu32,
+-                    dsc->mem2, dsc->mem2_yoffset);
+-    }
+-    else {
+-        dsc->mem2_yoffset = buf_offset / dsc->pinfo.stride;
+-        dsc->mem2 = pinfo.fbmem;
+-        LV_LOG_USER("Use non-consecutive mem2 = %p, yoffset = %" LV_PRIu32,
+-                    dsc->mem2, dsc->mem2_yoffset);
+-    }
++    /* The second frame follows the first in the virtual framebuffer. */
++    framesize = (size_t)dsc->vinfo.yres * dsc->pinfo.stride;
++    mem2 = mmap(NULL, framesize, PROT_READ | PROT_WRITE,
++                MAP_SHARED | MAP_FILE, dsc->fd, framesize);
++    if(mem2 == MAP_FAILED) {
++        int errcode = errno;
++        LV_LOG_ERROR("mmap mem2 failed: %d", errcode);
++        return -errcode;
++    }
++
++    dsc->mem2 = mem2;
++    dsc->mem2_yoffset = dsc->vinfo.yres;
++    LV_LOG_USER("Mapped mem2 = %p, yoffset = %" LV_PRIu32,
++                dsc->mem2, dsc->mem2_yoffset);
+ 
+     return 0;
++}
++
++static void fbdev_release(lv_nuttx_fb_t * dsc)
++{
++    if(dsc->mem2) {
++        munmap(dsc->mem2, (size_t)dsc->vinfo.yres * dsc->pinfo.stride);
++        dsc->mem2 = NULL;
++    }
++    dsc->mem2_yoffset = 0;
++
++    if(dsc->mem) {
++        munmap(dsc->mem, dsc->pinfo.fblen);
++        dsc->mem = NULL;
++    }
++
++    if(dsc->mem_off_screen) {
++        free(dsc->mem_off_screen);
++        dsc->mem_off_screen = NULL;
++    }
++
++    if(dsc->fd >= 0) {
++        close(dsc->fd);
++        dsc->fd = -1;
++    }
+ }
+ 
+ static void display_release_cb(lv_event_t * e)
+@@ -388,16 +403,7 @@
+         lv_display_set_driver_data(disp, NULL);
+         lv_display_set_flush_cb(disp, NULL);
+ 
+-        if(dsc->fd >= 0) {
+-            close(dsc->fd);
+-            dsc->fd = -1;
+-        }
+-
+-        if(dsc->mem_off_screen) {
+-            /* Free the off-screen buffer */
+-            free(dsc->mem_off_screen);
+-            dsc->mem_off_screen = NULL;
+-        }
++        fbdev_release(dsc);
+ 
+         lv_free(dsc);
+     }
diff --git a/graphics/lvgl/CMakeLists.txt b/graphics/lvgl/CMakeLists.txt
index 5551920aa..018b3992a 100644
--- a/graphics/lvgl/CMakeLists.txt
+++ b/graphics/lvgl/CMakeLists.txt
@@ -31,32 +31,59 @@ if(CONFIG_GRAPHICS_LVGL)
       
"${CONFIG_LVGL_VERSION_MAJOR}.${CONFIG_LVGL_VERSION_MINOR}.${CONFIG_LVGL_VERSION_PATCH}"
   )
 
-  if(NOT EXISTS ${LVGL_DIR})
-    set(LVGL_URL
-        "https://github.com/lvgl/lvgl/archive/refs/tags/v${LVGL_VERSION}.zip";)
+  set(LVGL_STAMP ${LVGL_DIR}/.nuttx_patched-${LVGL_VERSION})
+  set(LVGL_FBDEV_PATCH
+      
${CMAKE_CURRENT_LIST_DIR}/0001-nuttx-fbdev-use-virtual-framebuffer-offset.patch
+  )
+
+  if(NOT EXISTS ${LVGL_DIR}/.git)
     if("${LVGL_VERSION}" STREQUAL "9.2.2")
-      set(LVGL_URL_HASH
-          URL_HASH
-          
SHA256=b3d33f7aad1360f588762208d0f563574392debbc28d9187bda86012909f2203
-      )
+      set_property(
+        DIRECTORY
+        APPEND
+        PROPERTY CMAKE_CONFIGURE_DEPENDS ${LVGL_FBDEV_PATCH})
     endif()
-    FetchContent_Declare(
-      lvgl_fetch
-      URL ${LVGL_URL}
-          ${LVGL_URL_HASH}
-          DOWNLOAD_DIR
-          ${CMAKE_CURRENT_LIST_DIR}
-          SOURCE_DIR
-          ${CMAKE_CURRENT_LIST_DIR}/lvgl
-          BINARY_DIR
-          ${NUTTX_BINARY_DIR}/apps/graphics/lvgl/lvgl
-      DOWNLOAD_NO_PROGRESS true
-      TIMEOUT 120)
-
-    FetchContent_GetProperties(lvgl_fetch)
-
-    if(NOT lvgl_fetch_POPULATED)
-      FetchContent_Populate(lvgl_fetch)
+
+    if(NOT EXISTS ${LVGL_STAMP}
+       OR ("${LVGL_VERSION}" STREQUAL "9.2.2" AND ${LVGL_FBDEV_PATCH}
+                                                  IS_NEWER_THAN ${LVGL_STAMP}))
+      # Reset download stamps so a failed patch retries from a fresh archive.
+      set(LVGL_SUBBUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/lvgl-subbuild)
+      file(REMOVE_RECURSE ${LVGL_SUBBUILD_DIR})
+      set(LVGL_URL
+          
"https://github.com/lvgl/lvgl/archive/refs/tags/v${LVGL_VERSION}.zip";)
+      set(LVGL_URL_HASH "")
+      set(LVGL_PATCH_COMMAND "")
+      if("${LVGL_VERSION}" STREQUAL "9.2.2")
+        set(LVGL_URL_HASH
+            URL_HASH
+            
SHA256=b3d33f7aad1360f588762208d0f563574392debbc28d9187bda86012909f2203
+        )
+        set(LVGL_PATCH_COMMAND patch -s -N -p1 -d ${LVGL_DIR} -i
+                               ${LVGL_FBDEV_PATCH})
+      endif()
+      FetchContent_Declare(
+        lvgl_fetch
+        URL ${LVGL_URL}
+            ${LVGL_URL_HASH}
+            DOWNLOAD_DIR
+            ${CMAKE_CURRENT_LIST_DIR}
+            SOURCE_DIR
+            ${LVGL_DIR}
+            BINARY_DIR
+            ${NUTTX_BINARY_DIR}/apps/graphics/lvgl/lvgl
+            SUBBUILD_DIR
+            ${LVGL_SUBBUILD_DIR}
+        PATCH_COMMAND ${LVGL_PATCH_COMMAND}
+        DOWNLOAD_NO_PROGRESS true
+        TIMEOUT 120)
+
+      FetchContent_GetProperties(lvgl_fetch)
+
+      if(NOT lvgl_fetch_POPULATED)
+        FetchContent_Populate(lvgl_fetch)
+      endif()
+      file(TOUCH ${LVGL_STAMP})
     endif()
   endif()
 
diff --git a/graphics/lvgl/Makefile b/graphics/lvgl/Makefile
index 6bd8e2d1a..610e8e439 100644
--- a/graphics/lvgl/Makefile
+++ b/graphics/lvgl/Makefile
@@ -72,8 +72,6 @@ LVGL_UNPACKNAME = lvgl
 UNPACK ?= unzip -o $(if $(V),,-q)
 CURL ?= curl -L -O $(if $(V),,-Ss)
 
-LVGL_UNPACKDIR =  $(WD)/$(LVGL_UNPACKNAME)
-
 $(LVGL_TARBALL):
        $(ECHO_BEGIN)"Downloading: $(LVGL_TARBALL)"
        $(Q) $(CURL) $(CONFIG_GRAPH_LVGL_URL)/$(LVGL_TARBALL)
@@ -82,19 +80,32 @@ ifneq ($(LVGL_TARBALL_SHA256),)
 endif
        $(ECHO_END)
 
-$(LVGL_UNPACKNAME): $(LVGL_TARBALL)
+# This minimal backport targets the default LVGL 9.2.2 archive.
+
+ifeq ($(LVGL_VERSION),9.2.2)
+LVGL_PATCHES = $(WD)/0001-nuttx-fbdev-use-virtual-framebuffer-offset.patch
+endif
+
+LVGL_STAMP = $(LVGL_UNPACKNAME)/.nuttx_patched-$(LVGL_VERSION)
+
+# Recreate incomplete or outdated archive trees; never modify a git checkout.
+
+ifeq ($(wildcard $(LVGL_UNPACKNAME)/.git),)
+$(LVGL_STAMP): $(LVGL_TARBALL) $(LVGL_PATCHES)
        $(ECHO_BEGIN)"Unpacking: $(LVGL_TARBALL) -> $(LVGL_UNPACKNAME)"
 ifneq ($(LVGL_TARBALL_SHA256),)
        $(Q) $(CHECKHASH) sha256 $(LVGL_TARBALL_SHA256) $(LVGL_TARBALL)
 endif
+       $(Q) rm -rf $(LVGL_UNPACKNAME) lvgl-$(LVGL_VERSION)
        $(Q) $(UNPACK) $(LVGL_TARBALL)
        $(Q) mv lvgl-$(LVGL_VERSION) $(LVGL_UNPACKNAME)
-       $(Q) touch $(LVGL_UNPACKNAME)
+       $(Q) for p in $(LVGL_PATCHES); do \
+               patch -s -N -p1 -d $(LVGL_UNPACKNAME) < $$p || exit 1; \
+       done
+       $(Q) touch $@
        $(ECHO_END)
 
-# Download and unpack tarball if no git repo found
-ifeq ($(wildcard $(LVGL_UNPACKNAME)/.git),)
-context:: $(LVGL_UNPACKNAME)
+context:: $(LVGL_STAMP)
 endif
 
 include $(APPDIR)/Application.mk

Reply via email to