diff --git a/src/draw/lv_draw.c b/src/draw/lv_draw.c index 356b32d18..0cae941a7 100644 --- a/src/draw/lv_draw.c +++ b/src/draw/lv_draw.c @@ -161,7 +161,7 @@ bool lv_draw_dispatch_layer(struct _lv_disp_t * disp, lv_layer_t * layer) _draw_info.used_memory_for_layers_kb -= layer_size_byte < 1024 ? 1 : layer_size_byte >> 10; LV_LOG_INFO("Layer memory used: %d kB\n", _draw_info.used_memory_for_layers_kb); - lv_draw_buf_free(&layer_drawn->draw_buf); + lv_draw_buf_free(layer_drawn->draw_buf.buf); } /*Remove the layer from the display's*/ @@ -337,8 +337,9 @@ void * lv_draw_layer_alloc_buf(lv_layer_t * layer) if(lv_draw_buf_get_buf(&layer->draw_buf) == NULL) { uint32_t layer_size_byte = layer->draw_buf.height * lv_draw_buf_width_to_stride(layer->draw_buf.width, layer->draw_buf.color_format); + size_t s = lv_draw_buf_get_stride(&layer->draw_buf) * layer->draw_buf.height; + layer->draw_buf.buf = lv_draw_buf_malloc(s); - lv_draw_buf_malloc(&layer->draw_buf); if(lv_draw_buf_get_buf(&layer->draw_buf) == NULL) { LV_LOG_WARN("Allocating %"LV_PRIu32" bytes of layer buffer failed. Try later", layer_size_byte); return NULL; diff --git a/src/draw/lv_draw_buf.c b/src/draw/lv_draw_buf.c index 34b393fba..8f388c17e 100644 --- a/src/draw/lv_draw_buf.c +++ b/src/draw/lv_draw_buf.c @@ -25,18 +25,14 @@ * STATIC PROTOTYPES **********************/ static void buf_init(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, lv_color_format_t color_format); -static void buf_malloc(lv_draw_buf_t * draw_buf); -static void buf_realloc(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, - lv_color_format_t color_format); -static void buf_free(lv_draw_buf_t * draw_buf); -static void * buf_get(lv_draw_buf_t * draw_buf); +static void * buf_malloc(size_t size); +static void buf_free(void * buf); +static void * aligne_buf(void * buf); static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format); -static uint32_t get_stride(const lv_draw_buf_t * draw_buf); static void * go_to_xy(lv_draw_buf_t * draw_buf, lv_coord_t x, lv_coord_t y); static void buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * a); static void buf_copy(void * dest_buf, uint32_t dest_stride, const lv_area_t * dest_area, void * src_buf, uint32_t src_stride, const lv_area_t * src_area, lv_color_format_t color_format); -static uint8_t * buf_alloc_core(void * old_buf, lv_coord_t w, lv_coord_t h); /********************** * STATIC VARIABLES @@ -55,12 +51,10 @@ void _lv_draw_buf_init_handlers(void) lv_memzero(&handlers, sizeof(lv_draw_buf_handlers_t)); handlers.init_cb = buf_init; handlers.buf_malloc_cb = buf_malloc; - handlers.buf_realloc_cb = buf_realloc; handlers.buf_free_cb = buf_free; - handlers.buf_get_cb = buf_get; + handlers.align_pointer_cb = aligne_buf; handlers.invalidate_cache_cb = NULL; handlers.width_to_stride_cb = width_to_stride; - handlers.get_stride_cb = get_stride; handlers.go_to_xy_cb = go_to_xy; handlers.buf_clear_cb = buf_clear; handlers.buf_copy_cb = buf_copy; @@ -73,34 +67,16 @@ lv_draw_buf_handlers_t * lv_draw_buf_get_handlers(void) void lv_draw_buf_init(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, lv_color_format_t color_format) { + lv_memzero(draw_buf, sizeof(lv_draw_buf_t)); if(handlers.init_cb) handlers.init_cb(draw_buf, w, h, color_format); } -void lv_draw_buf_malloc(lv_draw_buf_t * draw_buf) +void lv_draw_buf_init_alloc(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, lv_color_format_t color_format) { - if(handlers.buf_malloc_cb) handlers.buf_malloc_cb(draw_buf); -} + lv_draw_buf_init(draw_buf, w, h, color_format); -void lv_draw_buf_realloc(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, - lv_color_format_t color_format) -{ - if(handlers.buf_realloc_cb) handlers.buf_realloc_cb(draw_buf, w, h, color_format); -} - -void lv_draw_buf_free(lv_draw_buf_t * draw_buf) -{ - if(handlers.buf_free_cb) handlers.buf_free_cb(draw_buf); -} - -void * lv_draw_buf_get_buf(lv_draw_buf_t * draw_buf) -{ - if(handlers.buf_get_cb) return handlers.buf_get_cb(draw_buf); - else return NULL; -} - -void lv_draw_buf_invalidate_cache(lv_draw_buf_t * draw_buf, const char * area) -{ - if(handlers.invalidate_cache_cb) handlers.invalidate_cache_cb(draw_buf, area); + size_t s = lv_draw_buf_get_stride(draw_buf) * h; + draw_buf->buf = lv_draw_buf_malloc(s); } uint32_t lv_draw_buf_width_to_stride(uint32_t w, lv_color_format_t color_format) @@ -109,10 +85,26 @@ uint32_t lv_draw_buf_width_to_stride(uint32_t w, lv_color_format_t color_format) else return 0; } -uint32_t lv_draw_buf_get_stride(const lv_draw_buf_t * draw_buf) +void * lv_draw_buf_malloc(size_t size) { - if(handlers.get_stride_cb) return handlers.get_stride_cb(draw_buf); - else return 0; + if(handlers.buf_malloc_cb) return handlers.buf_malloc_cb(size); + else return NULL; +} + +void lv_draw_buf_free(void * buf) +{ + if(handlers.buf_free_cb) handlers.buf_free_cb(buf); +} + +void * lv_draw_buf_align_buf(void * data) +{ + if(handlers.align_pointer_cb) return handlers.align_pointer_cb(data); + else return NULL; +} + +void lv_draw_buf_invalidate_cache(lv_draw_buf_t * draw_buf, const char * area) +{ + if(handlers.invalidate_cache_cb) handlers.invalidate_cache_cb(draw_buf, area); } void * lv_draw_buf_go_to_xy(lv_draw_buf_t * draw_buf, lv_coord_t x, lv_coord_t y) @@ -133,6 +125,19 @@ void lv_draw_buf_copy(void * dest_buf, uint32_t dest_stride, const lv_area_t * d color_format); } +void * lv_draw_buf_get_buf(lv_draw_buf_t * draw_buf) +{ + if(draw_buf->buf) return lv_draw_buf_align_buf(draw_buf->buf); + else return NULL; +} + + +uint32_t lv_draw_buf_get_stride(const lv_draw_buf_t * draw_buf) +{ + return lv_draw_buf_width_to_stride(draw_buf->width, draw_buf->color_format); +} + + /********************** * STATIC FUNCTIONS **********************/ @@ -146,35 +151,25 @@ static void buf_init(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, lv_co draw_buf->buf = NULL; } -static void buf_malloc(lv_draw_buf_t * draw_buf) +static void * buf_malloc(size_t size) { - if(draw_buf->width != 0 || - draw_buf->height != 0) draw_buf->buf = buf_alloc_core(NULL, lv_draw_buf_get_stride(draw_buf), draw_buf->height); - else draw_buf->buf = NULL; + size += LV_DRAW_BUF_ALIGN - 1; /*Allocate larger memory to be sure it can be aligned as needed*/ + return lv_malloc(size); } -static void buf_realloc(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, - lv_color_format_t color_format) +static void buf_free(void * buf) { - draw_buf->width = w; - draw_buf->height = h; - draw_buf->color_format = color_format; - draw_buf->buf = buf_alloc_core(draw_buf->buf, lv_draw_buf_get_stride(draw_buf), h); + lv_free(buf); } -static void buf_free(lv_draw_buf_t * draw_buf) +static void * aligne_buf(void * buf) { - lv_free(draw_buf->buf); -} - -static void * buf_get(lv_draw_buf_t * draw_buf) -{ - uint8_t * buf = draw_buf->buf; - if(buf) { - buf += LV_DRAW_BUF_ALIGN - 1; - buf = (uint8_t *)((lv_uintptr_t) buf & ~(LV_DRAW_BUF_ALIGN - 1)); + uint8_t * buf_u8 = buf; + if(buf_u8) { + buf_u8 += LV_DRAW_BUF_ALIGN - 1; + buf_u8 = (uint8_t *)((lv_uintptr_t) buf_u8 & ~(LV_DRAW_BUF_ALIGN - 1)); } - return buf; + return buf_u8; } static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format) @@ -183,11 +178,6 @@ static uint32_t width_to_stride(uint32_t w, lv_color_format_t color_format) return (width_byte + LV_DRAW_BUF_STRIDE_ALIGN - 1) & ~(LV_DRAW_BUF_STRIDE_ALIGN - 1); } -static uint32_t get_stride(const lv_draw_buf_t * draw_buf) -{ - return lv_draw_buf_width_to_stride(draw_buf->width, draw_buf->color_format); -} - static void * go_to_xy(lv_draw_buf_t * draw_buf, lv_coord_t x, lv_coord_t y) { uint32_t px_size = lv_color_format_get_size(draw_buf->color_format); @@ -231,15 +221,3 @@ static void buf_copy(void * dest_buf, uint32_t dest_stride, const lv_area_t * de } } - -static uint8_t * buf_alloc_core(void * old_buf, lv_coord_t w, lv_coord_t h) -{ - - uint8_t * buf; - size_t s = w * h + LV_DRAW_BUF_ALIGN - 1; - if(old_buf) buf = lv_realloc(old_buf, s); - else buf = lv_malloc(s); - - return buf; -} - diff --git a/src/draw/lv_draw_buf.h b/src/draw/lv_draw_buf.h index 7854348a2..91b8c0bea 100644 --- a/src/draw/lv_draw_buf.h +++ b/src/draw/lv_draw_buf.h @@ -36,14 +36,11 @@ typedef struct { typedef void (*lv_draw_buf_init_cb)(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, lv_color_format_t color_format); -typedef void (*lv_draw_buf_malloc_cb)(lv_draw_buf_t * draw_buf); +typedef void * (*lv_draw_buf_malloc_cb)(size_t size); -typedef void (*lv_draw_buf_realloc_cb)(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, - lv_color_format_t color_format); +typedef void (*lv_draw_buf_free_cb)(void * draw_buf); -typedef void (*lv_draw_buf_free_cb)(lv_draw_buf_t * draw_buf); - -typedef void * (*lv_draw_buf_get_buf_cb)(lv_draw_buf_t * draw_buf); +typedef void * (*lv_draw_buf_align_buf_cb)(void * buf); typedef void (*lv_draw_buf_invalidate_cache_cb)(lv_draw_buf_t * draw_buf, const char * area); @@ -61,12 +58,10 @@ typedef void (*lv_draw_buf_copy_cb)(void * dest_buf, uint32_t dest_stride, const typedef struct { lv_draw_buf_init_cb init_cb; lv_draw_buf_malloc_cb buf_malloc_cb; - lv_draw_buf_realloc_cb buf_realloc_cb; lv_draw_buf_free_cb buf_free_cb; - lv_draw_buf_get_buf_cb buf_get_cb; + lv_draw_buf_align_buf_cb align_pointer_cb; lv_draw_buf_invalidate_cache_cb invalidate_cache_cb; lv_draw_buf_width_to_stride_cb width_to_stride_cb; - lv_draw_buf_get_stride_cb get_stride_cb; lv_draw_buf_go_to_xy_cb go_to_xy_cb; lv_draw_buf_clear_cb buf_clear_cb; lv_draw_buf_copy_cb buf_copy_cb; @@ -89,7 +84,7 @@ void _lv_draw_buf_init_handlers(void); lv_draw_buf_handlers_t * lv_draw_buf_get_handlers(void); /** - * Initialize a draw buffer object. The buffer won't be allocated + * Initialize a draw buffer object. The buffer won't be allocated. * @param draw_buf pointer to a draw buffer * @param w the width of the buffer in pixel * @param h the height of the buffer in pixel @@ -98,25 +93,35 @@ lv_draw_buf_handlers_t * lv_draw_buf_get_handlers(void); void lv_draw_buf_init(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, lv_color_format_t color_format); /** - * Allocate a buffer in the draw_buf, considering the set width, height and color format + * Initialize a draw buffer object and also allocate the buffer. * @param draw_buf pointer to a draw buffer + * @param w the width of the buffer in pixel + * @param h the height of the buffer in pixel + * @param color_format the color format of the buffer */ -void lv_draw_buf_malloc(lv_draw_buf_t * draw_buf); +void lv_draw_buf_init_alloc(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, lv_color_format_t color_format); /** - * Realloacte the buffer with a new width, height and color format - * @param draw_buf pointer to a draw buffer - * @param w the new width of the buffer in pixel - * @param h the new height of the buffer in pixel - * @param color_format the new color format of the buffer + * Allocate a buffer with the given size. It might allocate slightly larger buffer to fulfill the alignment requirements. + * @param size the size to allocate in bytes + * @param the allocated buffer. + * @note The returned value can be saved in draw_buf->buf + * @note lv_draw_buf_align_buf can be sued the align the returned pointer */ -void lv_draw_buf_realloc(lv_draw_buf_t * draw_buf, lv_coord_t w, lv_coord_t h, lv_color_format_t color_format); +void * lv_draw_buf_malloc(size_t size); /** - * Free the allocated buffer - * @param draw_buf pointer to draw buffer + * Free a buffer allocated by lv_draw_buf_malloc + * @param buf pointer to a buffer */ -void lv_draw_buf_free(lv_draw_buf_t * draw_buf); +void lv_draw_buf_free(void * buf); + +/** + * Align the address of a buffer. The buffer needs to be large enough for the real data after alignement + * @param buf the data to align + * @return the aligned buffer + */ +void * lv_draw_buf_align_buf(void * buf); /** * Get the buffer of the draw_buf. diff --git a/src/draw/lv_draw_label.c b/src/draw/lv_draw_label.c index b307c6183..7ddb71cc6 100644 --- a/src/draw/lv_draw_label.c +++ b/src/draw/lv_draw_label.c @@ -346,7 +346,7 @@ void lv_draw_label_interate_letters(lv_draw_unit_t * draw_unit, const lv_draw_la if(pos.y > draw_unit->clip_area->y2) break; } - lv_free(draw_letter_dsc.bitmap_buf); + lv_draw_buf_free(draw_letter_dsc._bitmap_buf_unaligned); LV_ASSERT_MEM_INTEGRITY(); } @@ -394,9 +394,12 @@ static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc, } uint32_t bitmap_size = lv_draw_buf_width_to_stride(g.box_w, LV_COLOR_FORMAT_A8) * g.box_h; + bitmap_size = (bitmap_size + 63) & (~63); /*Round up*/ if(dsc->_bitmap_buf_size < bitmap_size) { - dsc->bitmap_buf = lv_realloc(dsc->bitmap_buf, bitmap_size); - LV_ASSERT_MALLOC(dsc->bitmap_buf); + lv_draw_buf_free(dsc->_bitmap_buf_unaligned); + dsc->_bitmap_buf_unaligned = lv_draw_buf_malloc(bitmap_size); + LV_ASSERT_MALLOC(dsc->_bitmap_buf_unaligned); + dsc->bitmap_buf = lv_draw_buf_align_buf(dsc->_bitmap_buf_unaligned); dsc->_bitmap_buf_size = bitmap_size; } diff --git a/src/draw/lv_draw_label.h b/src/draw/lv_draw_label.h index 5212a4b1b..ff9009d9a 100644 --- a/src/draw/lv_draw_label.h +++ b/src/draw/lv_draw_label.h @@ -79,6 +79,7 @@ typedef enum { typedef struct { const uint8_t * bitmap; + uint8_t * _bitmap_buf_unaligned; uint8_t * bitmap_buf; uint32_t _bitmap_buf_size; lv_draw_letter_bitmap_format_t format;