feat(draw/sw): allow custom handlers (#7531)
This commit is contained in:
@@ -215,6 +215,7 @@
|
||||
|
||||
/** Enable drawing complex gradients in software: linear at an angle, radial or conical */
|
||||
#define LV_USE_DRAW_SW_COMPLEX_GRADIENTS 0
|
||||
|
||||
#endif
|
||||
|
||||
/*Use TSi's aka (Think Silicon) NemaGFX */
|
||||
|
||||
@@ -126,6 +126,7 @@ typedef struct _lv_global_t {
|
||||
lv_cache_t * img_header_cache;
|
||||
|
||||
lv_draw_global_info_t draw_info;
|
||||
lv_ll_t draw_sw_blend_handler_ll;
|
||||
#if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0
|
||||
lv_draw_sw_shadow_cache_t sw_shadow_cache;
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,14 @@
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static inline void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_sw_blend_color(lv_color_format_t layer_cf,
|
||||
lv_draw_sw_blend_fill_dsc_t * fill_dsc);
|
||||
|
||||
static inline void /* LV_ATTRIBUTE_FAST_MEM */ lv_draw_sw_blend_image(lv_color_format_t layer_cf,
|
||||
lv_draw_sw_blend_image_dsc_t * image_dsc);
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
@@ -66,6 +74,13 @@ void lv_draw_sw_blend(lv_draw_task_t * t, const lv_draw_sw_blend_dsc_t * blend_d
|
||||
lv_layer_t * layer = t->target_layer;
|
||||
uint32_t layer_stride_byte = layer->draw_buf->header.stride;
|
||||
|
||||
lv_draw_sw_blend_handler_t handler = lv_draw_sw_get_blend_handler(layer->color_format);
|
||||
if(handler) {
|
||||
handler(t, blend_dsc);
|
||||
LV_PROFILER_DRAW_END;
|
||||
return;
|
||||
}
|
||||
|
||||
if(blend_dsc->src_buf == NULL) {
|
||||
lv_draw_sw_blend_fill_dsc_t fill_dsc;
|
||||
fill_dsc.dest_w = lv_area_get_width(&blend_area);
|
||||
@@ -90,45 +105,7 @@ void lv_draw_sw_blend(lv_draw_task_t * t, const lv_draw_sw_blend_dsc_t * blend_d
|
||||
(blend_area.x1 - blend_dsc->mask_area->x1);
|
||||
}
|
||||
|
||||
switch(layer->color_format) {
|
||||
#if LV_DRAW_SW_SUPPORT_RGB565
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
lv_draw_sw_blend_color_to_rgb565(&fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_ARGB8888
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
lv_draw_sw_blend_color_to_argb8888(&fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_RGB888
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
lv_draw_sw_blend_color_to_rgb888(&fill_dsc, 3);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_XRGB8888
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
lv_draw_sw_blend_color_to_rgb888(&fill_dsc, 4);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_L8
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
lv_draw_sw_blend_color_to_l8(&fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_AL88
|
||||
case LV_COLOR_FORMAT_AL88:
|
||||
lv_draw_sw_blend_color_to_al88(&fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_I1
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
lv_draw_sw_blend_color_to_i1(&fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
lv_draw_sw_blend_color(layer->color_format, &fill_dsc);
|
||||
}
|
||||
else {
|
||||
if(!lv_area_intersect(&blend_area, &blend_area, blend_dsc->src_area)) {
|
||||
@@ -179,46 +156,7 @@ void lv_draw_sw_blend(lv_draw_task_t * t, const lv_draw_sw_blend_dsc_t * blend_d
|
||||
image_dsc.dest_buf = lv_draw_layer_go_to_xy(layer, blend_area.x1 - layer->buf_area.x1,
|
||||
blend_area.y1 - layer->buf_area.y1);
|
||||
|
||||
switch(layer->color_format) {
|
||||
#if LV_DRAW_SW_SUPPORT_RGB565
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
lv_draw_sw_blend_image_to_rgb565(&image_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_ARGB8888
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
lv_draw_sw_blend_image_to_argb8888(&image_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_RGB888
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
lv_draw_sw_blend_image_to_rgb888(&image_dsc, 3);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_XRGB8888
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
lv_draw_sw_blend_image_to_rgb888(&image_dsc, 4);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_L8
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
lv_draw_sw_blend_image_to_l8(&image_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_AL88
|
||||
case LV_COLOR_FORMAT_AL88:
|
||||
lv_draw_sw_blend_image_to_al88(&image_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_I1
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
lv_draw_sw_blend_image_to_i1(&image_dsc);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
lv_draw_sw_blend_image(layer->color_format, &image_dsc);
|
||||
}
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
@@ -227,4 +165,93 @@ void lv_draw_sw_blend(lv_draw_task_t * t, const lv_draw_sw_blend_dsc_t * blend_d
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static inline void LV_ATTRIBUTE_FAST_MEM lv_draw_sw_blend_color(lv_color_format_t layer_cf,
|
||||
lv_draw_sw_blend_fill_dsc_t * fill_dsc)
|
||||
{
|
||||
switch(layer_cf) {
|
||||
#if LV_DRAW_SW_SUPPORT_RGB565
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
lv_draw_sw_blend_color_to_rgb565(fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_ARGB8888
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
lv_draw_sw_blend_color_to_argb8888(fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_RGB888
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
lv_draw_sw_blend_color_to_rgb888(fill_dsc, 3);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_XRGB8888
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
lv_draw_sw_blend_color_to_rgb888(fill_dsc, 4);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_L8
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
lv_draw_sw_blend_color_to_l8(fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_AL88
|
||||
case LV_COLOR_FORMAT_AL88:
|
||||
lv_draw_sw_blend_color_to_al88(fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_I1
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
lv_draw_sw_blend_color_to_i1(fill_dsc);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void LV_ATTRIBUTE_FAST_MEM lv_draw_sw_blend_image(lv_color_format_t layer_cf,
|
||||
lv_draw_sw_blend_image_dsc_t * image_dsc)
|
||||
{
|
||||
switch(layer_cf) {
|
||||
#if LV_DRAW_SW_SUPPORT_RGB565
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
lv_draw_sw_blend_image_to_rgb565(image_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_ARGB8888
|
||||
case LV_COLOR_FORMAT_ARGB8888:
|
||||
lv_draw_sw_blend_image_to_argb8888(image_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_RGB888
|
||||
case LV_COLOR_FORMAT_RGB888:
|
||||
lv_draw_sw_blend_image_to_rgb888(image_dsc, 3);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_XRGB8888
|
||||
case LV_COLOR_FORMAT_XRGB8888:
|
||||
lv_draw_sw_blend_image_to_rgb888(image_dsc, 4);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_L8
|
||||
case LV_COLOR_FORMAT_L8:
|
||||
lv_draw_sw_blend_image_to_l8(image_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_AL88
|
||||
case LV_COLOR_FORMAT_AL88:
|
||||
lv_draw_sw_blend_image_to_al88(image_dsc);
|
||||
break;
|
||||
#endif
|
||||
#if LV_DRAW_SW_SUPPORT_I1
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
lv_draw_sw_blend_image_to_i1(image_dsc);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,18 @@ extern "C" {
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Custom draw function for SW rendering.
|
||||
* @param t pointer to a draw task
|
||||
* @param dsc pointer to an initialized blend descriptor
|
||||
*/
|
||||
typedef void (*lv_draw_sw_blend_handler_t)(lv_draw_task_t * t, const lv_draw_sw_blend_dsc_t * dsc);
|
||||
|
||||
typedef struct {
|
||||
lv_color_format_t dest_cf;
|
||||
lv_draw_sw_blend_handler_t handler;
|
||||
} lv_draw_sw_custom_blend_handler_t;
|
||||
|
||||
/**
|
||||
* Call the blend function of the `layer`.
|
||||
* @param draw_unit pointer to a draw unit
|
||||
|
||||
@@ -92,6 +92,8 @@ void lv_draw_sw_init(void)
|
||||
#if LV_USE_VECTOR_GRAPHIC && LV_USE_THORVG
|
||||
tvg_engine_init(TVG_ENGINE_SW, 0);
|
||||
#endif
|
||||
|
||||
lv_ll_init(&LV_GLOBAL_DEFAULT()->draw_sw_blend_handler_ll, sizeof(lv_draw_sw_custom_blend_handler_t));
|
||||
}
|
||||
|
||||
void lv_draw_sw_deinit(void)
|
||||
@@ -340,4 +342,57 @@ static void execute_drawing(lv_draw_sw_unit_t * u)
|
||||
LV_PROFILER_DRAW_END;
|
||||
}
|
||||
|
||||
bool lv_draw_sw_register_blend_handler(lv_draw_sw_custom_blend_handler_t * handler)
|
||||
{
|
||||
lv_draw_sw_custom_blend_handler_t * existing_handler = NULL;
|
||||
lv_draw_sw_custom_blend_handler_t * new_handler = NULL;
|
||||
|
||||
// Check if a handler is already registered for the color format
|
||||
LV_LL_READ(&LV_GLOBAL_DEFAULT()->draw_sw_blend_handler_ll, existing_handler) {
|
||||
if(existing_handler->dest_cf == handler->dest_cf) {
|
||||
new_handler = existing_handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(new_handler == NULL) {
|
||||
new_handler = lv_ll_ins_head(&LV_GLOBAL_DEFAULT()->draw_sw_blend_handler_ll);
|
||||
if(new_handler == NULL) {
|
||||
LV_ASSERT_MALLOC(new_handler);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
lv_memcpy(new_handler, handler, sizeof(lv_draw_sw_custom_blend_handler_t));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lv_draw_sw_unregister_blend_handler(lv_color_format_t dest_cf)
|
||||
{
|
||||
lv_draw_sw_custom_blend_handler_t * handler;
|
||||
|
||||
LV_LL_READ(&LV_GLOBAL_DEFAULT()->draw_sw_blend_handler_ll, handler) {
|
||||
if(handler->dest_cf == dest_cf) {
|
||||
lv_ll_remove(&LV_GLOBAL_DEFAULT()->draw_sw_blend_handler_ll, handler);
|
||||
lv_free(handler);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
lv_draw_sw_blend_handler_t lv_draw_sw_get_blend_handler(lv_color_format_t dest_cf)
|
||||
{
|
||||
lv_draw_sw_custom_blend_handler_t * handler;
|
||||
|
||||
LV_LL_READ(&LV_GLOBAL_DEFAULT()->draw_sw_blend_handler_ll, handler) {
|
||||
if(handler->dest_cf == dest_cf) {
|
||||
return handler->handler;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_DRAW_SW*/
|
||||
|
||||
@@ -28,6 +28,7 @@ extern "C" {
|
||||
#include "../lv_draw_line.h"
|
||||
#include "../lv_draw_arc.h"
|
||||
#include "lv_draw_sw_utils.h"
|
||||
#include "blend/lv_draw_sw_blend.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -154,6 +155,32 @@ void lv_draw_sw_transform(const lv_area_t * dest_area, const void * src_buf,
|
||||
void lv_draw_sw_vector(lv_draw_task_t * t, const lv_draw_vector_task_dsc_t * dsc);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Register a custom blend handler for a color format.
|
||||
* Handler will be called when blending a color or an
|
||||
* image to a buffer with the given color format.
|
||||
* At most one handler can be registered for a color format.
|
||||
* Subsequent registrations will overwrite the previous handler.
|
||||
*
|
||||
* @param handler pointer to a blend handler
|
||||
* @return true if the handler was registered, false if the handler could not be registered
|
||||
*/
|
||||
bool lv_draw_sw_register_blend_handler(lv_draw_sw_custom_blend_handler_t * handler);
|
||||
|
||||
/**
|
||||
* Unregister a custom blend handler for a color format.
|
||||
* @param dest_cf color format
|
||||
* @return true if a handler was unregistered, false if no handler was registered
|
||||
*/
|
||||
bool lv_draw_sw_unregister_blend_handler(lv_color_format_t dest_cf);
|
||||
|
||||
/**
|
||||
* Get the blend handler for a color format.
|
||||
* @param dest_cf color format
|
||||
* @return pointer to the blend handler or NULL if no handler is registered
|
||||
*/
|
||||
lv_draw_sw_blend_handler_t lv_draw_sw_get_blend_handler(lv_color_format_t dest_cf);
|
||||
|
||||
/***********************
|
||||
* GLOBAL VARIABLES
|
||||
***********************/
|
||||
@@ -162,8 +189,6 @@ void lv_draw_sw_vector(lv_draw_task_t * t, const lv_draw_vector_task_dsc_t * dsc
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#include "blend/lv_draw_sw_blend.h"
|
||||
|
||||
#endif /*LV_USE_DRAW_SW*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -604,6 +604,7 @@
|
||||
#define LV_USE_DRAW_SW_COMPLEX_GRADIENTS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*Use TSi's aka (Think Silicon) NemaGFX */
|
||||
|
||||
61
tests/src/test_cases/draw/test_draw_custom_handlers.c
Normal file
61
tests/src/test_cases/draw/test_draw_custom_handlers.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#if LV_BUILD_TEST
|
||||
#include "../lvgl.h"
|
||||
#include "../../lvgl_private.h"
|
||||
|
||||
#include "unity/unity.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_register_custom_handlers(void)
|
||||
{
|
||||
lv_draw_sw_custom_blend_handler_t handler = {
|
||||
.dest_cf = LV_COLOR_FORMAT_I2,
|
||||
.handler = NULL,
|
||||
};
|
||||
|
||||
TEST_ASSERT_TRUE(lv_draw_sw_register_blend_handler(&handler));
|
||||
}
|
||||
|
||||
void test_overwrite_custom_handler(void)
|
||||
{
|
||||
lv_draw_sw_custom_blend_handler_t handler = {
|
||||
.dest_cf = LV_COLOR_FORMAT_I2,
|
||||
.handler = (lv_draw_sw_blend_handler_t)0xDEADBEEF,
|
||||
};
|
||||
|
||||
TEST_ASSERT_TRUE(lv_draw_sw_register_blend_handler(&handler));
|
||||
|
||||
lv_draw_sw_custom_blend_handler_t handler2 = {
|
||||
.dest_cf = LV_COLOR_FORMAT_I2,
|
||||
.handler = (lv_draw_sw_blend_handler_t)0xCAFEBABE,
|
||||
};
|
||||
|
||||
TEST_ASSERT_TRUE(lv_draw_sw_register_blend_handler(&handler2));
|
||||
|
||||
lv_draw_sw_blend_handler_t handler3 = lv_draw_sw_get_blend_handler(LV_COLOR_FORMAT_I2);
|
||||
TEST_ASSERT_NOT_NULL(handler3);
|
||||
TEST_ASSERT_EQUAL_PTR(handler3, (lv_draw_sw_blend_handler_t)0xCAFEBABE);
|
||||
}
|
||||
|
||||
void test_unregister_custom_handler(void)
|
||||
{
|
||||
lv_draw_sw_custom_blend_handler_t handler = {
|
||||
.dest_cf = LV_COLOR_FORMAT_I2,
|
||||
.handler = NULL,
|
||||
};
|
||||
|
||||
TEST_ASSERT_TRUE(lv_draw_sw_register_blend_handler(&handler));
|
||||
|
||||
TEST_ASSERT_TRUE(lv_draw_sw_unregister_blend_handler(LV_COLOR_FORMAT_I2));
|
||||
|
||||
lv_draw_sw_blend_handler_t handler2 = lv_draw_sw_get_blend_handler(LV_COLOR_FORMAT_I2);
|
||||
TEST_ASSERT_NULL(handler2);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user