From 61b8378286782e3b7de5e1876580e21584f2b0e9 Mon Sep 17 00:00:00 2001 From: Benign X <1341398182@qq.com> Date: Tue, 30 Jan 2024 16:52:46 +0800 Subject: [PATCH] feat(nuttx_image_cache): add independent image cache heap support (#5528) --- src/core/lv_global.h | 9 ++ src/drivers/nuttx/lv_nuttx_entry.c | 10 +- src/drivers/nuttx/lv_nuttx_entry.h | 10 ++ src/drivers/nuttx/lv_nuttx_image_cache.c | 129 +++++++++++++++++++++++ src/drivers/nuttx/lv_nuttx_image_cache.h | 45 ++++++++ 5 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 src/drivers/nuttx/lv_nuttx_image_cache.c create mode 100644 src/drivers/nuttx/lv_nuttx_image_cache.h diff --git a/src/core/lv_global.h b/src/core/lv_global.h index 3bb91c6b4..a827459c2 100644 --- a/src/core/lv_global.h +++ b/src/core/lv_global.h @@ -60,6 +60,10 @@ struct _lv_freetype_context_t; struct _lv_profiler_builtin_ctx_t; #endif +#if LV_USE_NUTTX +struct _lv_nuttx_ctx_t; +#endif + typedef struct _lv_global_t { bool inited; bool deinit_in_progress; /**< Can be used e.g. in the LV_EVENT_DELETE to deinit the drivers too */ @@ -196,6 +200,11 @@ typedef struct _lv_global_t { void * objid_array; uint32_t objid_count; #endif + +#if LV_USE_NUTTX + struct _lv_nuttx_ctx_t * nuttx_ctx; +#endif + void * user_data; } lv_global_t; diff --git a/src/drivers/nuttx/lv_nuttx_entry.c b/src/drivers/nuttx/lv_nuttx_entry.c index e484a137d..1754b6205 100644 --- a/src/drivers/nuttx/lv_nuttx_entry.c +++ b/src/drivers/nuttx/lv_nuttx_entry.c @@ -14,6 +14,7 @@ #include #include #include "lv_nuttx_cache.h" +#include "lv_nuttx_image_cache.h" #include "lv_nuttx_profiler.h" #include "../../../lvgl.h" @@ -21,7 +22,7 @@ /********************* * DEFINES *********************/ - +#define nuttx_ctx_p (LV_GLOBAL_DEFAULT()->nuttx_ctx) /********************** * TYPEDEFS **********************/ @@ -92,6 +93,9 @@ void lv_nuttx_dsc_init(lv_nuttx_dsc_t * dsc) void lv_nuttx_init(const lv_nuttx_dsc_t * dsc, lv_nuttx_result_t * result) { + nuttx_ctx_p = lv_malloc_zeroed(sizeof(lv_nuttx_ctx_t)); + LV_ASSERT_MALLOC(nuttx_ctx_p); + #if LV_USE_LOG lv_log_register_print_cb(syslog_print); #endif @@ -99,6 +103,10 @@ void lv_nuttx_init(const lv_nuttx_dsc_t * dsc, lv_nuttx_result_t * result) lv_nuttx_cache_init(); +#if LV_CACHE_DEF_SIZE > 0 + lv_nuttx_image_cache_init(); +#endif + #if LV_USE_PROFILER && LV_USE_PROFILER_BUILTIN lv_nuttx_profiler_init(); #endif diff --git a/src/drivers/nuttx/lv_nuttx_entry.h b/src/drivers/nuttx/lv_nuttx_entry.h index 16c92dbca..e54ec0a4c 100644 --- a/src/drivers/nuttx/lv_nuttx_entry.h +++ b/src/drivers/nuttx/lv_nuttx_entry.h @@ -18,6 +18,7 @@ extern "C" { * INCLUDES *********************/ +#include "../../lv_conf_internal.h" #include "../../display/lv_display.h" #include "../../indev/lv_indev.h" @@ -41,6 +42,15 @@ typedef struct { lv_indev_t * indev; lv_indev_t * utouch_indev; } lv_nuttx_result_t; + +typedef struct _lv_nuttx_ctx_t { + +#if LV_CACHE_DEF_SIZE > 0 + void * image_cache; +#endif + +} lv_nuttx_ctx_t; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/src/drivers/nuttx/lv_nuttx_image_cache.c b/src/drivers/nuttx/lv_nuttx_image_cache.c new file mode 100644 index 000000000..839704c12 --- /dev/null +++ b/src/drivers/nuttx/lv_nuttx_image_cache.c @@ -0,0 +1,129 @@ +/** + * @file lv_nuttx_image_cache.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_nuttx_cache.h" +#include "../../../lvgl.h" + +#if LV_CACHE_DEF_SIZE > 0 + +#if LV_USE_NUTTX + +#include + +/********************* + * DEFINES + *********************/ + +#define HEAP_NAME "GImageCache" + +#define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache) +#define img_header_cache_p (LV_GLOBAL_DEFAULT()->img_header_cache) +#define ctx (*(lv_nuttx_ctx_image_cache_t **)&LV_GLOBAL_DEFAULT()->nuttx_ctx->image_cache) +/********************** + * TYPEDEFS + **********************/ +typedef struct { + uint8_t * mem; + uint32_t mem_size; + + struct mm_heap_s * heap; + uint32_t heap_size; +} lv_nuttx_ctx_image_cache_t; +/********************** + * STATIC PROTOTYPES + **********************/ + +static void * malloc_cb(size_t size_bytes, lv_color_format_t color_format); +static void free_cb(void * draw_buf); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_nuttx_image_cache_init(void) +{ + lv_draw_buf_handlers_t * handlers = lv_draw_buf_get_handlers(); + handlers->buf_malloc_cb = malloc_cb; + handlers->buf_free_cb = free_cb; + + ctx = lv_malloc_zeroed(sizeof(lv_nuttx_ctx_image_cache_t)); + LV_ASSERT_MALLOC(ctx); + + ctx->mem_size = LV_CACHE_DEF_SIZE; + ctx->mem = malloc(ctx->mem_size); + LV_ASSERT_MALLOC(ctx->mem); + + ctx->heap = mm_initialize( + HEAP_NAME, + ctx->mem, + ctx->mem_size + ); + + struct mallinfo info = mm_mallinfo(ctx->heap); + ctx->heap_size = info.arena; + + LV_LOG_USER("heap info:"); + LV_LOG_USER(" heap: %p", ctx->heap); + LV_LOG_USER(" mem: %p", ctx->mem); + LV_LOG_USER(" mem_size: %" LV_PRIu32, ctx->mem_size); + LV_LOG_USER(" arena: %d", info.arena); + LV_LOG_USER(" ordblks: %d", info.ordblks); + LV_LOG_USER(" aordblks: %d", info.aordblks); + LV_LOG_USER(" mxordblk: %d", info.mxordblk); + LV_LOG_USER(" uordblks: %d", info.uordblks); + LV_LOG_USER(" fordblks: %d", info.fordblks); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void * malloc_cb(size_t size_bytes, lv_color_format_t color_format) +{ + LV_UNUSED(color_format); + + /*Allocate larger memory to be sure it can be aligned as needed*/ + size_bytes += LV_DRAW_BUF_ALIGN - 1; + uint32_t cache_max_size = lv_cache_get_max_size(img_cache_p, NULL); + + if(size_bytes > cache_max_size) { + LV_LOG_ERROR("data size (%" LV_PRIu32 ") is larger than max size (%" LV_PRIu32 ")", + (uint32_t)size_bytes, + cache_max_size); + return NULL; + } + + while(1) { + void * mem = mm_malloc(ctx->heap, size_bytes); + if(mem) return mem; + LV_LOG_INFO("appears to be out of memory. attempting to evict one cache entry. with allocated size %" LV_PRIu32, + (uint32_t)size_bytes); + bool evict_res = lv_cache_evict_one(img_cache_p, NULL); + if(evict_res == false) { + LV_LOG_ERROR("failed to evict one cache entry"); + return NULL; + } + } +} + +static void free_cb(void * draw_buf) +{ + mm_free(ctx->heap, draw_buf); +} + +#endif /* LV_USE_NUTTX */ +#endif /* LV_CACHE_DEF_SIZE > 0 */ diff --git a/src/drivers/nuttx/lv_nuttx_image_cache.h b/src/drivers/nuttx/lv_nuttx_image_cache.h new file mode 100644 index 000000000..e2af31f41 --- /dev/null +++ b/src/drivers/nuttx/lv_nuttx_image_cache.h @@ -0,0 +1,45 @@ +/** + * @file lv_nuttx_image_cache.h + * + */ + +#ifndef LV_NUTTX_IMAGE_CACHE_H +#define LV_NUTTX_IMAGE_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../lv_conf_internal.h" + +#if LV_CACHE_DEF_SIZE > 0 + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +void lv_nuttx_image_cache_init(void); + +/********************** + * MACROS + **********************/ + +#endif /*LV_CACHE_DEF_SIZE > 0*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_NUTTX_IMAGE_CACHE_H*/