1 /**
2  * @file lv_draw_buf.h
3  *
4  */
5 
6 #ifndef LV_DRAW_BUF_H
7 #define LV_DRAW_BUF_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /*********************
14  *      INCLUDES
15  *********************/
16 #include "../misc/lv_types.h"
17 #include "../misc/lv_area.h"
18 #include "../misc/lv_color.h"
19 #include "../stdlib/lv_string.h"
20 #include "lv_image_dsc.h"
21 
22 /*********************
23  *      DEFINES
24  *********************/
25 
26 /** Use this value to let LVGL calculate stride automatically */
27 #define LV_STRIDE_AUTO 0
28 LV_EXPORT_CONST_INT(LV_STRIDE_AUTO);
29 
30 /**
31  * Stride alignment for draw buffers.
32  * It may vary between different color formats and hardware.
33  * Refine it to suit your needs.
34  */
35 
36 #define LV_DRAW_BUF_STRIDE(w, cf) \
37     LV_ROUND_UP(((w) * LV_COLOR_FORMAT_GET_BPP(cf) + 7) / 8, LV_DRAW_BUF_STRIDE_ALIGN)
38 
39 /** Allocate a slightly larger buffer, so we can adjust the start address to meet alignment */
40 #define LV_DRAW_BUF_SIZE(w, h, cf) \
41     (LV_DRAW_BUF_STRIDE(w, cf) * (h) + LV_DRAW_BUF_ALIGN + \
42      LV_COLOR_INDEXED_PALETTE_SIZE(cf) * sizeof(lv_color32_t))
43 
44 /**
45  * Define a static draw buffer with the given width, height, and color format.
46  * Stride alignment is set to LV_DRAW_BUF_STRIDE_ALIGN.
47  *
48  * For platform that needs special buffer alignment, call LV_DRAW_BUF_INIT_STATIC.
49  */
50 #define LV_DRAW_BUF_DEFINE_STATIC(name, _w, _h, _cf) \
51     static LV_ATTRIBUTE_MEM_ALIGN uint8_t buf_##name[LV_DRAW_BUF_SIZE(_w, _h, _cf)]; \
52     static lv_draw_buf_t name = { \
53                                   .header = { \
54                                               .magic = LV_IMAGE_HEADER_MAGIC, \
55                                               .cf = (_cf), \
56                                               .flags = LV_IMAGE_FLAGS_MODIFIABLE, \
57                                               .w = (_w), \
58                                               .h = (_h), \
59                                               .stride = LV_DRAW_BUF_STRIDE(_w, _cf), \
60                                               .reserved_2 = 0, \
61                                             }, \
62                                   .data_size = sizeof(buf_##name), \
63                                   .data = buf_##name, \
64                                   .unaligned_data = buf_##name, \
65                                 }
66 
67 #define LV_DRAW_BUF_INIT_STATIC(name) \
68     do { \
69         lv_image_header_t * header = &name.header; \
70         lv_draw_buf_init(&name, header->w, header->h, (lv_color_format_t)header->cf, header->stride, buf_##name, sizeof(buf_##name)); \
71         lv_draw_buf_set_flag(&name, LV_IMAGE_FLAGS_MODIFIABLE); \
72     } while(0)
73 
74 /**********************
75  *      TYPEDEFS
76  **********************/
77 
78 typedef void * (*lv_draw_buf_malloc_cb)(size_t size, lv_color_format_t color_format);
79 
80 typedef void (*lv_draw_buf_free_cb)(void * draw_buf);
81 
82 typedef void * (*lv_draw_buf_align_cb)(void * buf, lv_color_format_t color_format);
83 
84 typedef void (*lv_draw_buf_cache_operation_cb)(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
85 
86 typedef uint32_t (*lv_draw_buf_width_to_stride_cb)(uint32_t w, lv_color_format_t color_format);
87 
88 struct _lv_draw_buf_t {
89     lv_image_header_t header;
90     uint32_t data_size;       /**< Total buf size in bytes */
91     uint8_t * data;
92     void * unaligned_data;    /**< Unaligned address of `data`, used internally by lvgl */
93     const lv_draw_buf_handlers_t * handlers; /**< draw buffer alloc/free ops. */
94 };
95 
96 /**********************
97  * GLOBAL PROTOTYPES
98  **********************/
99 
100 /**
101  * Initialize the draw buffer with the default handlers.
102  *
103  * @param handlers  the draw buffer handlers to set
104  */
105 void lv_draw_buf_init_with_default_handlers(lv_draw_buf_handlers_t * handlers);
106 
107 /**
108  * Initialize the draw buffer with given handlers.
109  *
110  * @param handlers             the draw buffer handlers to set
111  * @param buf_malloc_cb        the callback to allocate memory for the buffer
112  * @param buf_free_cb          the callback to free memory of the buffer
113  * @param align_pointer_cb     the callback to align the buffer
114  * @param invalidate_cache_cb  the callback to invalidate the cache of the buffer
115  * @param flush_cache_cb       the callback to flush buffer
116  * @param width_to_stride_cb   the callback to calculate the stride based on the width and color format
117  */
118 void lv_draw_buf_handlers_init(lv_draw_buf_handlers_t * handlers,
119                                lv_draw_buf_malloc_cb buf_malloc_cb,
120                                lv_draw_buf_free_cb buf_free_cb,
121                                lv_draw_buf_align_cb align_pointer_cb,
122                                lv_draw_buf_cache_operation_cb invalidate_cache_cb,
123                                lv_draw_buf_cache_operation_cb flush_cache_cb,
124                                lv_draw_buf_width_to_stride_cb width_to_stride_cb);
125 
126 /**
127  * Get the struct which holds the callbacks for draw buf management.
128  * Custom callback can be set on the returned value
129  * @return                  pointer to the struct of handlers
130  */
131 lv_draw_buf_handlers_t * lv_draw_buf_get_handlers(void);
132 lv_draw_buf_handlers_t * lv_draw_buf_get_font_handlers(void);
133 lv_draw_buf_handlers_t * lv_draw_buf_get_image_handlers(void);
134 
135 
136 /**
137  * Align the address of a buffer. The buffer needs to be large enough for the real data after alignment
138  * @param buf           the data to align
139  * @param color_format  the color format of the buffer
140  * @return              the aligned buffer
141  */
142 void * lv_draw_buf_align(void * buf, lv_color_format_t color_format);
143 
144 /**
145  * Align the address of a buffer with custom draw buffer handlers.
146  * The buffer needs to be large enough for the real data after alignment
147  * @param handlers      the draw buffer handlers
148  * @param buf           the data to align
149  * @param color_format  the color format of the buffer
150  * @return              the aligned buffer
151  */
152 void * lv_draw_buf_align_ex(const lv_draw_buf_handlers_t * handlers, void * buf, lv_color_format_t color_format);
153 
154 /**
155  * Invalidate the cache of the buffer
156  * @param draw_buf     the draw buffer needs to be invalidated
157  * @param area         the area to invalidate in the buffer,
158  *                     use NULL to invalidate the whole draw buffer address range
159  */
160 void lv_draw_buf_invalidate_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
161 
162 /**
163  * Flush the cache of the buffer
164  * @param draw_buf     the draw buffer needs to be flushed
165  * @param area         the area to flush in the buffer,
166  *                     use NULL to flush the whole draw buffer address range
167  */
168 void lv_draw_buf_flush_cache(const lv_draw_buf_t * draw_buf, const lv_area_t * area);
169 
170 /**
171  * Calculate the stride in bytes based on a width and color format
172  * @param w                 the width in pixels
173  * @param color_format      the color format
174  * @return                  the stride in bytes
175  */
176 uint32_t lv_draw_buf_width_to_stride(uint32_t w, lv_color_format_t color_format);
177 
178 /**
179  * Calculate the stride in bytes based on a width and color format
180  * @param handlers          the draw buffer handlers
181  * @param w                 the width in pixels
182  * @param color_format      the color format
183  * @return                  the stride in bytes
184  */
185 uint32_t lv_draw_buf_width_to_stride_ex(const lv_draw_buf_handlers_t * handlers, uint32_t w,
186                                         lv_color_format_t color_format);
187 
188 /**
189  * Clear an area on the buffer
190  * @param draw_buf          pointer to draw buffer
191  * @param a                 the area to clear, or NULL to clear the whole buffer
192  */
193 void lv_draw_buf_clear(lv_draw_buf_t * draw_buf, const lv_area_t * a);
194 
195 /**
196  * Copy an area from a buffer to another
197  * @param dest      pointer to the destination draw buffer
198  * @param dest_area the area to copy from the destination buffer, if NULL, use the whole buffer
199  * @param src       pointer to the source draw buffer
200  * @param src_area  the area to copy from the destination buffer, if NULL, use the whole buffer
201  * @note `dest_area` and `src_area` should have the same width and height
202  * @note  `dest` and `src` should have same color format. Color converting is not supported fow now.
203  */
204 void lv_draw_buf_copy(lv_draw_buf_t * dest, const lv_area_t * dest_area,
205                       const lv_draw_buf_t * src, const lv_area_t * src_area);
206 
207 /**
208  * Note: Eventually, lv_draw_buf_malloc/free will be kept as private.
209  *       For now, we use `create` to distinguish with malloc.
210  *
211  * Create an draw buf by allocating struct for `lv_draw_buf_t` and allocating a buffer for it
212  * that meets specified requirements.
213  *
214  * @param w         the buffer width in pixels
215  * @param h         the buffer height in pixels
216  * @param cf        the color format for image
217  * @param stride    the stride in bytes for image. Use 0 for automatic calculation based on
218  *                  w, cf, and global stride alignment configuration.
219  */
220 lv_draw_buf_t * lv_draw_buf_create(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride);
221 
222 /**
223  * Note: Eventually, lv_draw_buf_malloc/free will be kept as private.
224  *       For now, we use `create` to distinguish with malloc.
225  *
226  * Create an draw buf by allocating struct for `lv_draw_buf_t` and allocating a buffer for it
227  * that meets specified requirements.
228  *
229  * @param handlers  the draw buffer handlers
230  * @param w         the buffer width in pixels
231  * @param h         the buffer height in pixels
232  * @param cf        the color format for image
233  * @param stride    the stride in bytes for image. Use 0 for automatic calculation based on
234  *                  w, cf, and global stride alignment configuration.
235  */
236 lv_draw_buf_t * lv_draw_buf_create_ex(const lv_draw_buf_handlers_t * handlers, uint32_t w, uint32_t h,
237                                       lv_color_format_t cf, uint32_t stride);
238 
239 /**
240  * Duplicate a draw buf with same image size, stride and color format. Copy the image data too.
241  * @param draw_buf  the draw buf to duplicate
242  * @return          the duplicated draw buf on success, NULL if failed
243  */
244 lv_draw_buf_t * lv_draw_buf_dup(const lv_draw_buf_t * draw_buf);
245 
246 /**
247  * Duplicate a draw buf with same image size, stride and color format. Copy the image data too.
248  * @param handlers  the draw buffer handlers
249  * @param draw_buf  the draw buf to duplicate
250  * @return          the duplicated draw buf on success, NULL if failed
251  */
252 lv_draw_buf_t * lv_draw_buf_dup_ex(const lv_draw_buf_handlers_t * handlers, const lv_draw_buf_t * draw_buf);
253 
254 /**
255  * Initialize a draw buf with the given buffer and parameters. Clear draw buffer flag to zero.
256  * @param draw_buf  the draw buf to initialize
257  * @param w         the buffer width in pixels
258  * @param h         the buffer height in pixels
259  * @param cf        the color format
260  * @param stride    the stride in bytes. Use 0 for automatic calculation
261  * @param data      the buffer used for drawing. Unaligned `data` will be aligned internally
262  * @param data_size the size of the buffer in bytes
263  * @return          return LV_RESULT_OK on success, LV_RESULT_INVALID otherwise
264  */
265 lv_result_t lv_draw_buf_init(lv_draw_buf_t * draw_buf, uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride,
266                              void * data, uint32_t data_size);
267 
268 /**
269  * Keep using the existing memory, reshape the draw buffer to the given width and height.
270  * Return NULL if data_size is smaller than the required size.
271  * @param draw_buf  pointer to a draw buffer
272  * @param cf        the new color format, use 0 or LV_COLOR_FORMAT_UNKNOWN to keep using the original color format.
273  * @param w         the new width in pixels
274  * @param h         the new height in pixels
275  * @param stride    the stride in bytes for image. Use 0 for automatic calculation.
276  */
277 lv_draw_buf_t * lv_draw_buf_reshape(lv_draw_buf_t * draw_buf, lv_color_format_t cf, uint32_t w, uint32_t h,
278                                     uint32_t stride);
279 
280 /**
281  * Destroy a draw buf by freeing the actual buffer if it's marked as LV_IMAGE_FLAGS_ALLOCATED in header.
282  * Then free the lv_draw_buf_t struct.
283  *
284  * @param draw_buf  the draw buffer to destroy
285  */
286 void lv_draw_buf_destroy(lv_draw_buf_t * draw_buf);
287 
288 /**
289  * Return pointer to the buffer at the given coordinates
290  */
291 void * lv_draw_buf_goto_xy(const lv_draw_buf_t * buf, uint32_t x, uint32_t y);
292 
293 /**
294  * Adjust the stride of a draw buf in place.
295  * @param src       pointer to a draw buffer
296  * @param stride    the new stride in bytes for image. Use LV_STRIDE_AUTO for automatic calculation.
297  * @return          LV_RESULT_OK: success or LV_RESULT_INVALID: failed
298  */
299 lv_result_t lv_draw_buf_adjust_stride(lv_draw_buf_t * src, uint32_t stride);
300 
301 /**
302  * Premultiply draw buffer color with alpha channel.
303  * If it's already premultiplied, return directly.
304  * Only color formats with alpha channel will be processed.
305  *
306  * @return LV_RESULT_OK: premultiply success
307  */
308 lv_result_t lv_draw_buf_premultiply(lv_draw_buf_t * draw_buf);
309 
310 bool lv_draw_buf_has_flag(const lv_draw_buf_t * draw_buf, lv_image_flags_t flag);
311 
312 void lv_draw_buf_set_flag(lv_draw_buf_t * draw_buf, lv_image_flags_t flag);
313 
314 void lv_draw_buf_clear_flag(lv_draw_buf_t * draw_buf, lv_image_flags_t flag);
315 
316 /**
317  * As of now, draw buf share same definition as `lv_image_dsc_t`.
318  * And is interchangeable with `lv_image_dsc_t`.
319  */
320 
321 void lv_draw_buf_from_image(lv_draw_buf_t * buf, const lv_image_dsc_t * img);
322 
323 void lv_draw_buf_to_image(const lv_draw_buf_t * buf, lv_image_dsc_t * img);
324 
325 /**
326  * Set the palette color of an indexed image. Valid only for `LV_COLOR_FORMAT_I1/2/4/8`
327  * @param draw_buf pointer to an image descriptor
328  * @param index the palette color to set:
329  *   - for `LV_COLOR_FORMAT_I1`: 0..1
330  *   - for `LV_COLOR_FORMAT_I2`: 0..3
331  *   - for `LV_COLOR_FORMAT_I4`: 0..15
332  *   - for `LV_COLOR_FORMAT_I8`: 0..255
333  * @param color the color to set in lv_color32_t format
334  */
335 void lv_draw_buf_set_palette(lv_draw_buf_t * draw_buf, uint8_t index, lv_color32_t color);
336 
337 /**
338  * @deprecated Use lv_draw_buf_set_palette instead.
339  */
340 void lv_image_buf_set_palette(lv_image_dsc_t * dsc, uint8_t id, lv_color32_t c);
341 
342 /**
343  * @deprecated Use lv_draw_buffer_create/destroy instead.
344  * Free the data pointer and dsc struct of an image.
345  */
346 void lv_image_buf_free(lv_image_dsc_t * dsc);
347 
348 /**********************
349  *      MACROS
350  **********************/
351 
352 #ifdef __cplusplus
353 } /*extern "C"*/
354 #endif
355 
356 #endif /*LV_DRAW_BUF_H*/
357