1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

feat(vg_lite): add radial gradient support (#5836)

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
VIFEXT 2024-03-20 19:03:45 +08:00 committed by GitHub
parent 3c2a1935c8
commit 4d4bb340c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 458 additions and 92 deletions

14
Kconfig
View File

@ -335,6 +335,20 @@ menu "LVGL configuration"
which usually improves performance, which usually improves performance,
but does not guarantee the same rendering quality as the software. but does not guarantee the same rendering quality as the software.
config LV_VG_LITE_LINEAER_GRAD_CACHE_CNT
int "VG-Lite linear gradient image maximum cache number."
default 32
depends on LV_USE_DRAW_VG_LITE
help
The memory usage of a single gradient image is 4K bytes.
config LV_VG_LITE_RADIAL_GRAD_CACHE_CNT
int "VG-Lite radial gradient image maximum cache number."
default 32
depends on LV_USE_DRAW_VG_LITE
help
The memory usage of a single gradient image is radial grad radius * 4 bytes.
config LV_USE_VECTOR_GRAPHIC config LV_USE_VECTOR_GRAPHIC
bool "Use Vector Graphic APIs" bool "Use Vector Graphic APIs"
default n default n

View File

@ -184,10 +184,15 @@
* but does not guarantee the same rendering quality as the software. */ * but does not guarantee the same rendering quality as the software. */
#define LV_VG_LITE_USE_BOX_SHADOW 0 #define LV_VG_LITE_USE_BOX_SHADOW 0
/* VG-Lite gradient image maximum cache number. /* VG-Lite linear gradient image maximum cache number.
* NOTE: The memory usage of a single gradient image is 4K bytes. * NOTE: The memory usage of a single gradient image is 4K bytes.
*/ */
#define LV_VG_LITE_GRAD_CACHE_SIZE 32 #define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT 32
/* VG-Lite radial gradient image maximum cache size.
* NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes.
*/
#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32
#endif #endif

View File

@ -198,10 +198,15 @@
* but does not guarantee the same rendering quality as the software. */ * but does not guarantee the same rendering quality as the software. */
#define LV_VG_LITE_USE_BOX_SHADOW 0 #define LV_VG_LITE_USE_BOX_SHADOW 0
/* VG-Lite gradient image maximum cache number. /* VG-Lite linear gradient image maximum cache number.
* NOTE: The memory usage of a single gradient image is 4K bytes. * NOTE: The memory usage of a single gradient image is 4K bytes.
*/ */
#define LV_VG_LITE_GRAD_CACHE_SIZE 32 #define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT 32
/* VG-Lite radial gradient image maximum cache size.
* NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes.
*/
#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32
#endif #endif

View File

@ -72,7 +72,7 @@ void lv_draw_vg_lite_init(void)
unit->base_unit.delete_cb = draw_delete; unit->base_unit.delete_cb = draw_delete;
lv_vg_lite_image_dsc_init(unit); lv_vg_lite_image_dsc_init(unit);
lv_vg_lite_grad_init(unit); lv_vg_lite_grad_init(unit, LV_VG_LITE_LINEAER_GRAD_CACHE_CNT, LV_VG_LITE_RADIAL_GRAD_CACHE_CNT);
lv_vg_lite_path_init(unit); lv_vg_lite_path_init(unit);
lv_vg_lite_decoder_init(); lv_vg_lite_decoder_init();
} }

View File

@ -40,9 +40,15 @@ struct _lv_vg_lite_pending_t;
struct _lv_draw_vg_lite_unit_t { struct _lv_draw_vg_lite_unit_t {
lv_draw_unit_t base_unit; lv_draw_unit_t base_unit;
lv_draw_task_t * task_act; lv_draw_task_t * task_act;
struct _lv_vg_lite_pending_t * image_dsc_pending; struct _lv_vg_lite_pending_t * image_dsc_pending;
lv_cache_t * grad_cache;
struct _lv_vg_lite_pending_t * grad_pending; lv_cache_t * linear_grad_cache;
struct _lv_vg_lite_pending_t * linear_grad_pending;
lv_cache_t * radial_grad_cache;
struct _lv_vg_lite_pending_t * radial_grad_pending;
uint16_t flush_count; uint16_t flush_count;
vg_lite_buffer_t target_buffer; vg_lite_buffer_t target_buffer;
vg_lite_matrix_t global_matrix; vg_lite_matrix_t global_matrix;

View File

@ -36,7 +36,6 @@ static void lv_path_opa_to_vg(lv_vg_lite_path_t * dest, const lv_vector_draw_dsc
static void lv_stroke_to_vg(lv_vg_lite_path_t * dest, const lv_vector_stroke_dsc_t * dsc); static void lv_stroke_to_vg(lv_vg_lite_path_t * dest, const lv_vector_stroke_dsc_t * dsc);
static vg_lite_blend_t lv_blend_to_vg(lv_vector_blend_t blend); static vg_lite_blend_t lv_blend_to_vg(lv_vector_blend_t blend);
static vg_lite_fill_t lv_fill_to_vg(lv_vector_fill_t fill_rule); static vg_lite_fill_t lv_fill_to_vg(lv_vector_fill_t fill_rule);
static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread);
static vg_lite_cap_style_t lv_stroke_cap_to_vg(lv_vector_stroke_cap_t cap); static vg_lite_cap_style_t lv_stroke_cap_to_vg(lv_vector_stroke_cap_t cap);
static vg_lite_join_style_t lv_stroke_join_to_vg(lv_vector_stroke_join_t join); static vg_lite_join_style_t lv_stroke_join_to_vg(lv_vector_stroke_join_t join);
@ -205,8 +204,6 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec
case LV_VECTOR_DRAW_STYLE_GRADIENT: { case LV_VECTOR_DRAW_STYLE_GRADIENT: {
/* draw gradient */ /* draw gradient */
lv_vector_gradient_style_t style = dsc->fill_dsc.gradient.style; lv_vector_gradient_style_t style = dsc->fill_dsc.gradient.style;
vg_lite_gradient_spreadmode_t spreadmode = lv_spread_to_vg(dsc->fill_dsc.gradient.spread);
LV_UNUSED(spreadmode);
if(style == LV_VECTOR_GRADIENT_STYLE_LINEAR) { if(style == LV_VECTOR_GRADIENT_STYLE_LINEAR) {
vg_lite_matrix_t grad_matrix, fill_matrix; vg_lite_matrix_t grad_matrix, fill_matrix;
@ -229,12 +226,23 @@ static void task_draw_cb(void * ctx, const lv_vector_path_t * path, const lv_vec
blend); blend);
} }
else if(style == LV_VECTOR_GRADIENT_STYLE_RADIAL) { else if(style == LV_VECTOR_GRADIENT_STYLE_RADIAL) {
if(vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) { vg_lite_matrix_t grad_matrix;
/* TODO: radial gradient */ lv_matrix_to_vg(&grad_matrix, &dsc->fill_dsc.matrix);
}
else { /* add min_x, min_y to gradient center */
LV_LOG_WARN("radial gradient is not supported"); lv_vector_gradient_t new_grad = dsc->fill_dsc.gradient;
} new_grad.cx += min_x;
new_grad.cy += min_y;
lv_vg_lite_draw_radial_grad(
u,
&u->target_buffer,
vg_path,
&new_grad,
&grad_matrix,
&matrix,
fill,
blend);
} }
} }
break; break;
@ -431,20 +439,6 @@ static vg_lite_fill_t lv_fill_to_vg(lv_vector_fill_t fill_rule)
} }
} }
static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread)
{
switch(spread) {
case LV_VECTOR_GRADIENT_SPREAD_PAD:
return VG_LITE_GRADIENT_SPREAD_PAD;
case LV_VECTOR_GRADIENT_SPREAD_REPEAT:
return VG_LITE_GRADIENT_SPREAD_REPEAT;
case LV_VECTOR_GRADIENT_SPREAD_REFLECT:
return VG_LITE_GRADIENT_SPREAD_REFLECT;
default:
return VG_LITE_GRADIENT_SPREAD_FILL;
}
}
static vg_lite_cap_style_t lv_stroke_cap_to_vg(lv_vector_stroke_cap_t cap) static vg_lite_cap_style_t lv_stroke_cap_to_vg(lv_vector_stroke_cap_t cap)
{ {
switch(cap) { switch(cap) {

View File

@ -13,6 +13,7 @@
#include "lv_draw_vg_lite_type.h" #include "lv_draw_vg_lite_type.h"
#include "lv_vg_lite_pending.h" #include "lv_vg_lite_pending.h"
#include "lv_vg_lite_math.h"
#include "../../misc/lv_types.h" #include "../../misc/lv_types.h"
#include "../../stdlib/lv_string.h" #include "../../stdlib/lv_string.h"
@ -25,22 +26,47 @@
**********************/ **********************/
typedef struct { typedef struct {
vg_lite_linear_gradient_t vg_grad;
lv_grad_dsc_t lv_grad; lv_grad_dsc_t lv_grad;
} grad_item_t; vg_lite_linear_gradient_t vg_grad;
} linear_grad_item_t;
#if LV_USE_VECTOR_GRAPHIC
typedef struct {
lv_vector_gradient_t lv_grad;
vg_lite_radial_gradient_t vg_grad;
} radial_grad_item_t;
#endif /* LV_USE_VECTOR_GRAPHIC */
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static vg_lite_linear_gradient_t * lv_vg_lite_linear_grad_get(struct _lv_draw_vg_lite_unit_t * u,
const lv_grad_dsc_t * grad);
static bool grad_create_cb(grad_item_t * item, void * user_data);
static void grad_free_cb(grad_item_t * item, void * user_data);
static lv_cache_compare_res_t grad_compare_cb(const grad_item_t * lhs, const grad_item_t * rhs);
static void grad_cache_release_cb(void * entry, void * user_data); static void grad_cache_release_cb(void * entry, void * user_data);
/* Linear gradient */
static vg_lite_linear_gradient_t * linear_grad_get(struct _lv_draw_vg_lite_unit_t * u,
const lv_grad_dsc_t * grad);
static bool linear_grad_create_cb(linear_grad_item_t * item, void * user_data);
static void linear_grad_free_cb(linear_grad_item_t * item, void * user_data);
static lv_cache_compare_res_t linear_grad_compare_cb(const linear_grad_item_t * lhs, const linear_grad_item_t * rhs);
#if LV_USE_VECTOR_GRAPHIC
/* Radial gradient */
static vg_lite_radial_gradient_t * radial_grad_get(struct _lv_draw_vg_lite_unit_t * u,
const lv_vector_gradient_t * grad);
static bool radial_grad_create_cb(radial_grad_item_t * item, void * user_data);
static void radial_grad_free_cb(radial_grad_item_t * item, void * user_data);
static lv_cache_compare_res_t radial_grad_compare_cb(const radial_grad_item_t * lhs, const radial_grad_item_t * rhs);
static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread);
#endif /* LV_USE_VECTOR_GRAPHIC */
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
@ -53,28 +79,63 @@ static void grad_cache_release_cb(void * entry, void * user_data);
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
void lv_vg_lite_grad_init(struct _lv_draw_vg_lite_unit_t * u) void lv_vg_lite_grad_init(
struct _lv_draw_vg_lite_unit_t * u,
uint32_t linear_grad_cache_cnt,
uint32_t radial_grad_cache_cnt)
{ {
LV_ASSERT_NULL(u); LV_ASSERT_NULL(u);
LV_UNUSED(radial_grad_cache_cnt);
lv_cache_ops_t ops = { /* Create the cache for linear gradients */
.compare_cb = (lv_cache_compare_cb_t)grad_compare_cb, {
.create_cb = (lv_cache_create_cb_t)grad_create_cb, lv_cache_ops_t ops = {
.free_cb = (lv_cache_free_cb_t)grad_free_cb, .compare_cb = (lv_cache_compare_cb_t)linear_grad_compare_cb,
}; .create_cb = (lv_cache_create_cb_t)linear_grad_create_cb,
.free_cb = (lv_cache_free_cb_t)linear_grad_free_cb,
};
u->grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(grad_item_t), LV_VG_LITE_GRAD_CACHE_SIZE, ops); u->linear_grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(linear_grad_item_t),
LV_ASSERT_NULL(u->grad_cache); linear_grad_cache_cnt,
ops);
u->linear_grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4);
lv_vg_lite_pending_set_free_cb(u->linear_grad_pending, grad_cache_release_cb, u->linear_grad_cache);
}
u->grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4); #if LV_USE_VECTOR_GRAPHIC
lv_vg_lite_pending_set_free_cb(u->grad_pending, grad_cache_release_cb, u->grad_cache);
/* Create the cache for radial gradients */
if(vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) {
lv_cache_ops_t ops = {
.compare_cb = (lv_cache_compare_cb_t)radial_grad_compare_cb,
.create_cb = (lv_cache_create_cb_t)radial_grad_create_cb,
.free_cb = (lv_cache_free_cb_t)radial_grad_free_cb,
};
u->radial_grad_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(radial_grad_item_t),
radial_grad_cache_cnt,
ops);
u->radial_grad_pending = lv_vg_lite_pending_create(sizeof(lv_cache_entry_t *), 4);
lv_vg_lite_pending_set_free_cb(u->radial_grad_pending, grad_cache_release_cb, u->radial_grad_cache);
}
#endif /* LV_USE_VECTOR_GRAPHIC */
} }
void lv_vg_lite_grad_deinit(struct _lv_draw_vg_lite_unit_t * u) void lv_vg_lite_grad_deinit(struct _lv_draw_vg_lite_unit_t * u)
{ {
LV_ASSERT_NULL(u); LV_ASSERT_NULL(u);
lv_vg_lite_pending_destroy(u->grad_pending); lv_vg_lite_pending_destroy(u->linear_grad_pending);
lv_cache_destroy(u->grad_cache, NULL); u->linear_grad_pending = NULL;
lv_cache_destroy(u->linear_grad_cache, NULL);
u->linear_grad_cache = NULL;
if(u->radial_grad_pending) {
lv_vg_lite_pending_destroy(u->radial_grad_pending);
u->radial_grad_pending = NULL;
lv_cache_destroy(u->radial_grad_cache, NULL);
u->radial_grad_cache = NULL;
}
} }
void lv_vg_lite_grad_area_to_matrix(vg_lite_matrix_t * grad_matrix, const lv_area_t * area, lv_grad_dir_t dir) void lv_vg_lite_grad_area_to_matrix(vg_lite_matrix_t * grad_matrix, const lv_area_t * area, lv_grad_dir_t dir)
@ -119,20 +180,20 @@ void lv_vg_lite_draw_linear_grad(
LV_PROFILER_BEGIN; LV_PROFILER_BEGIN;
vg_lite_linear_gradient_t * gradient = lv_vg_lite_linear_grad_get(u, grad); vg_lite_linear_gradient_t * linear_grad = linear_grad_get(u, grad);
LV_ASSERT_NULL(gradient); LV_ASSERT_NULL(linear_grad);
if(!gradient) { if(!linear_grad) {
LV_LOG_ERROR("Failed to get linear gradient"); LV_LOG_ERROR("Failed to get linear gradient");
LV_PROFILER_END; LV_PROFILER_END;
return; return;
} }
vg_lite_matrix_t * grad_mat_p = vg_lite_get_grad_matrix(gradient); vg_lite_matrix_t * grad_mat_p = vg_lite_get_grad_matrix(linear_grad);
LV_ASSERT_NULL(grad_mat_p); LV_ASSERT_NULL(grad_mat_p);
*grad_mat_p = *grad_matrix; *grad_mat_p = *grad_matrix;
LV_VG_LITE_ASSERT_DEST_BUFFER(buffer); LV_VG_LITE_ASSERT_DEST_BUFFER(buffer);
LV_VG_LITE_ASSERT_SRC_BUFFER(&gradient->image); LV_VG_LITE_ASSERT_SRC_BUFFER(&linear_grad->image);
LV_VG_LITE_ASSERT_PATH(path); LV_VG_LITE_ASSERT_PATH(path);
LV_VG_LITE_ASSERT_MATRIX(grad_mat_p); LV_VG_LITE_ASSERT_MATRIX(grad_mat_p);
LV_VG_LITE_ASSERT_MATRIX(matrix); LV_VG_LITE_ASSERT_MATRIX(matrix);
@ -143,37 +204,101 @@ void lv_vg_lite_draw_linear_grad(
path, path,
fill, fill,
(vg_lite_matrix_t *)matrix, (vg_lite_matrix_t *)matrix,
gradient, linear_grad,
blend)); blend));
LV_PROFILER_END_TAG("vg_lite_draw_grad"); LV_PROFILER_END_TAG("vg_lite_draw_grad");
LV_PROFILER_END; LV_PROFILER_END;
} }
#if LV_USE_VECTOR_GRAPHIC
void lv_vg_lite_draw_radial_grad(
struct _lv_draw_vg_lite_unit_t * u,
vg_lite_buffer_t * buffer,
vg_lite_path_t * path,
const lv_vector_gradient_t * grad,
const vg_lite_matrix_t * grad_matrix,
const vg_lite_matrix_t * matrix,
vg_lite_fill_t fill,
vg_lite_blend_t blend)
{
LV_ASSERT_NULL(u);
LV_ASSERT_NULL(buffer);
LV_ASSERT_NULL(path);
LV_ASSERT_NULL(grad);
LV_ASSERT_NULL(grad_matrix);
LV_ASSERT_NULL(matrix);
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_RADIAL_GRADIENT)) {
LV_LOG_INFO("radial gradient is not supported");
return;
}
if(grad->spread == LV_VECTOR_GRADIENT_SPREAD_REPEAT || grad->spread == LV_VECTOR_GRADIENT_SPREAD_REFLECT) {
if(!vg_lite_query_feature(gcFEATURE_BIT_VG_IM_REPEAT_REFLECT)) {
LV_LOG_INFO("repeat/reflect spread(%d) is not supported", (int)grad->spread);
return;
}
}
LV_PROFILER_BEGIN;
vg_lite_radial_gradient_t * radial_grad = radial_grad_get(u, grad);
vg_lite_matrix_t * grad_mat_p = vg_lite_get_radial_grad_matrix(radial_grad);
LV_ASSERT_NULL(grad_mat_p);
*grad_mat_p = *grad_matrix;
LV_VG_LITE_ASSERT_DEST_BUFFER(buffer);
LV_VG_LITE_ASSERT_SRC_BUFFER(&radial_grad->image);
LV_VG_LITE_ASSERT_PATH(path);
LV_VG_LITE_ASSERT_MATRIX(grad_mat_p);
LV_VG_LITE_ASSERT_MATRIX(matrix);
LV_PROFILER_BEGIN_TAG("vg_lite_draw_radial_grad");
LV_VG_LITE_CHECK_ERROR(
vg_lite_draw_radial_grad(
buffer,
path,
fill,
(vg_lite_matrix_t *)matrix,
radial_grad,
0,
blend,
VG_LITE_FILTER_LINEAR));
LV_PROFILER_END_TAG("vg_lite_draw_radial_grad");
LV_PROFILER_END;
}
#endif /* LV_USE_VECTOR_GRAPHIC */
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static vg_lite_linear_gradient_t * lv_vg_lite_linear_grad_get(struct _lv_draw_vg_lite_unit_t * u, static void * grad_get(
const lv_grad_dsc_t * grad) struct _lv_draw_vg_lite_unit_t * u,
lv_cache_t * cache,
lv_vg_lite_pending_t * pending,
const void * key)
{ {
LV_ASSERT_NULL(u); LV_ASSERT_NULL(u);
LV_ASSERT_NULL(grad); LV_ASSERT_NULL(cache);
LV_ASSERT_NULL(pending);
LV_ASSERT_NULL(key);
grad_item_t search_key; lv_cache_entry_t * cache_node_entry = lv_cache_acquire(cache, key, NULL);
lv_memzero(&search_key, sizeof(grad_item_t));
search_key.lv_grad = *grad;
lv_cache_entry_t * cache_node_entry = lv_cache_acquire(u->grad_cache, &search_key, NULL);
if(cache_node_entry == NULL) { if(cache_node_entry == NULL) {
/* check if the cache is full */ /* check if the cache is full */
size_t free_size = lv_cache_get_free_size(u->grad_cache, NULL); size_t free_size = lv_cache_get_free_size(cache, NULL);
if(free_size == 0) { if(free_size == 0) {
LV_LOG_INFO("grad cache is full, release all pending cache entries"); LV_LOG_INFO("grad cache is full, release all pending cache entries");
lv_vg_lite_finish(u); lv_vg_lite_finish(u);
} }
cache_node_entry = lv_cache_acquire_or_create(u->grad_cache, &search_key, NULL); cache_node_entry = lv_cache_acquire_or_create(cache, key, NULL);
if(cache_node_entry == NULL) { if(cache_node_entry == NULL) {
LV_LOG_ERROR("grad cache creating failed"); LV_LOG_ERROR("grad cache creating failed");
return NULL; return NULL;
@ -181,13 +306,36 @@ static vg_lite_linear_gradient_t * lv_vg_lite_linear_grad_get(struct _lv_draw_vg
} }
/* Add the new entry to the pending list */ /* Add the new entry to the pending list */
lv_vg_lite_pending_add(u->grad_pending, &cache_node_entry); lv_vg_lite_pending_add(pending, &cache_node_entry);
return lv_cache_entry_get_data(cache_node_entry);
}
static void grad_cache_release_cb(void * entry, void * user_data)
{
lv_cache_entry_t ** entry_p = entry;
lv_cache_t * cache = user_data;
lv_cache_release(cache, *entry_p, NULL);
}
/* Linear gradient */
static vg_lite_linear_gradient_t * linear_grad_get(struct _lv_draw_vg_lite_unit_t * u,
const lv_grad_dsc_t * grad)
{
linear_grad_item_t search_key;
lv_memzero(&search_key, sizeof(search_key));
search_key.lv_grad = *grad;
linear_grad_item_t * item = grad_get(u, u->linear_grad_cache, u->linear_grad_pending, &search_key);
if(!item) {
return NULL;
}
grad_item_t * item = lv_cache_entry_get_data(cache_node_entry);
return &item->vg_grad; return &item->vg_grad;
} }
static bool grad_create_cb(grad_item_t * item, void * user_data) static bool linear_grad_create_cb(linear_grad_item_t * item, void * user_data)
{ {
LV_UNUSED(user_data); LV_UNUSED(user_data);
@ -226,13 +374,13 @@ static bool grad_create_cb(grad_item_t * item, void * user_data)
return true; return true;
} }
static void grad_free_cb(grad_item_t * item, void * user_data) static void linear_grad_free_cb(linear_grad_item_t * item, void * user_data)
{ {
LV_UNUSED(user_data); LV_UNUSED(user_data);
LV_VG_LITE_CHECK_ERROR(vg_lite_clear_grad(&item->vg_grad)); LV_VG_LITE_CHECK_ERROR(vg_lite_clear_grad(&item->vg_grad));
} }
static lv_cache_compare_res_t grad_compare_cb(const grad_item_t * lhs, const grad_item_t * rhs) static lv_cache_compare_res_t linear_grad_compare_cb(const linear_grad_item_t * lhs, const linear_grad_item_t * rhs)
{ {
if(lhs->lv_grad.stops_count != rhs->lv_grad.stops_count) { if(lhs->lv_grad.stops_count != rhs->lv_grad.stops_count) {
return lhs->lv_grad.stops_count > rhs->lv_grad.stops_count ? 1 : -1; return lhs->lv_grad.stops_count > rhs->lv_grad.stops_count ? 1 : -1;
@ -247,11 +395,139 @@ static lv_cache_compare_res_t grad_compare_cb(const grad_item_t * lhs, const gra
return 0; return 0;
} }
static void grad_cache_release_cb(void * entry, void * user_data) #if LV_USE_VECTOR_GRAPHIC
/* Radial gradient */
static vg_lite_radial_gradient_t * radial_grad_get(struct _lv_draw_vg_lite_unit_t * u,
const lv_vector_gradient_t * grad)
{ {
lv_cache_entry_t ** entry_p = entry; radial_grad_item_t search_key;
lv_cache_t * cache = user_data; lv_memzero(&search_key, sizeof(search_key));
lv_cache_release(cache, *entry_p, NULL); search_key.lv_grad = *grad;
radial_grad_item_t * item = grad_get(u, u->radial_grad_cache, u->radial_grad_pending, &search_key);
if(!item) {
return NULL;
}
return &item->vg_grad;
} }
static bool radial_grad_create_cb(radial_grad_item_t * item, void * user_data)
{
LV_UNUSED(user_data);
LV_PROFILER_BEGIN;
lv_vector_gradient_t * grad = &item->lv_grad;
uint8_t stops_count = grad->grad.stops_count;
vg_lite_color_ramp_t * color_ramp = lv_malloc(sizeof(vg_lite_color_ramp_t) * stops_count);
LV_ASSERT_MALLOC(color_ramp);
if(!color_ramp) {
LV_LOG_ERROR("malloc failed for color_ramp");
return false;
}
for(uint8_t i = 0; i < stops_count; i++) {
color_ramp[i].stop = grad->grad.stops[i].frac / 255.0f;
lv_color_t c = grad->grad.stops[i].color;
color_ramp[i].red = c.red / 255.0f;
color_ramp[i].green = c.green / 255.0f;
color_ramp[i].blue = c.blue / 255.0f;
color_ramp[i].alpha = grad->grad.stops[i].opa / 255.0f;
}
const vg_lite_radial_gradient_parameter_t grad_param = {
.cx = grad->cx,
.cy = grad->cy,
.r = grad->cr,
.fx = grad->cx,
.fy = grad->cy,
};
vg_lite_radial_gradient_t radial_grad;
lv_memzero(&radial_grad, sizeof(radial_grad));
LV_PROFILER_BEGIN_TAG("vg_lite_set_radial_grad");
LV_VG_LITE_CHECK_ERROR(
vg_lite_set_radial_grad(
&radial_grad,
stops_count,
color_ramp,
grad_param,
lv_spread_to_vg(grad->spread),
1));
LV_PROFILER_END_TAG("vg_lite_set_radial_grad");
LV_PROFILER_BEGIN_TAG("vg_lite_update_radial_grad");
vg_lite_error_t err = vg_lite_update_radial_grad(&radial_grad);
LV_PROFILER_END_TAG("vg_lite_update_radial_grad");
if(!err) {
item->vg_grad = radial_grad;
}
else {
LV_LOG_ERROR("update radial grad error(%d): %s", (int)err, lv_vg_lite_error_string(err));
}
lv_free(color_ramp);
LV_PROFILER_END;
return err == VG_LITE_SUCCESS;
}
static void radial_grad_free_cb(radial_grad_item_t * item, void * user_data)
{
LV_UNUSED(user_data);
LV_VG_LITE_CHECK_ERROR(vg_lite_clear_radial_grad(&item->vg_grad));
}
static lv_cache_compare_res_t radial_grad_compare_cb(const radial_grad_item_t * lhs, const radial_grad_item_t * rhs)
{
if(!math_equal(lhs->lv_grad.cx, rhs->lv_grad.cx)) {
return lhs->lv_grad.cx > rhs->lv_grad.cx ? 1 : -1;
}
if(!math_equal(lhs->lv_grad.cy, rhs->lv_grad.cy)) {
return lhs->lv_grad.cy > rhs->lv_grad.cy ? 1 : -1;
}
if(!math_equal(lhs->lv_grad.cr, rhs->lv_grad.cr)) {
return lhs->lv_grad.cr > rhs->lv_grad.cr ? 1 : -1;
}
if(lhs->lv_grad.spread != rhs->lv_grad.spread) {
return lhs->lv_grad.spread > rhs->lv_grad.spread ? 1 : -1;
}
if(lhs->lv_grad.grad.stops_count != rhs->lv_grad.grad.stops_count) {
return lhs->lv_grad.grad.stops_count > rhs->lv_grad.grad.stops_count ? 1 : -1;
}
int cmp_res = lv_memcmp(lhs->lv_grad.grad.stops, rhs->lv_grad.grad.stops,
sizeof(lv_gradient_stop_t) * lhs->lv_grad.grad.stops_count);
if(cmp_res != 0) {
return cmp_res > 0 ? 1 : -1;
}
return 0;
}
static vg_lite_gradient_spreadmode_t lv_spread_to_vg(lv_vector_gradient_spread_t spread)
{
switch(spread) {
case LV_VECTOR_GRADIENT_SPREAD_PAD:
return VG_LITE_GRADIENT_SPREAD_PAD;
case LV_VECTOR_GRADIENT_SPREAD_REPEAT:
return VG_LITE_GRADIENT_SPREAD_REPEAT;
case LV_VECTOR_GRADIENT_SPREAD_REFLECT:
return VG_LITE_GRADIENT_SPREAD_REFLECT;
default:
return VG_LITE_GRADIENT_SPREAD_FILL;
}
}
#endif /* LV_USE_VECTOR_GRAPHIC */
#endif /*LV_USE_DRAW_VG_LITE*/ #endif /*LV_USE_DRAW_VG_LITE*/

View File

@ -32,7 +32,10 @@ extern "C" {
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
void lv_vg_lite_grad_init(struct _lv_draw_vg_lite_unit_t * u); void lv_vg_lite_grad_init(
struct _lv_draw_vg_lite_unit_t * u,
uint32_t linear_grad_cache_cnt,
uint32_t radial_grad_cache_cnt);
void lv_vg_lite_grad_deinit(struct _lv_draw_vg_lite_unit_t * u); void lv_vg_lite_grad_deinit(struct _lv_draw_vg_lite_unit_t * u);
@ -48,7 +51,19 @@ void lv_vg_lite_draw_linear_grad(
vg_lite_fill_t fill, vg_lite_fill_t fill,
vg_lite_blend_t blend); vg_lite_blend_t blend);
void lv_vg_lite_linear_grad_release_all(struct _lv_draw_vg_lite_unit_t * u); #if LV_USE_VECTOR_GRAPHIC
void lv_vg_lite_draw_radial_grad(
struct _lv_draw_vg_lite_unit_t * u,
vg_lite_buffer_t * buffer,
vg_lite_path_t * path,
const lv_vector_gradient_t * grad,
const vg_lite_matrix_t * grad_matrix,
const vg_lite_matrix_t * matrix,
vg_lite_fill_t fill,
vg_lite_blend_t blend);
#endif /* LV_USE_VECTOR_GRAPHIC */
/********************** /**********************
* MACROS * MACROS

View File

@ -1064,7 +1064,11 @@ void lv_vg_lite_finish(struct _lv_draw_vg_lite_unit_t * u)
LV_VG_LITE_CHECK_ERROR(vg_lite_finish()); LV_VG_LITE_CHECK_ERROR(vg_lite_finish());
/* Clear all gradient caches reference */ /* Clear all gradient caches reference */
lv_vg_lite_pending_remove_all(u->grad_pending); lv_vg_lite_pending_remove_all(u->linear_grad_pending);
if(u->radial_grad_pending) {
lv_vg_lite_pending_remove_all(u->radial_grad_pending);
}
/* Clear image decoder dsc reference */ /* Clear image decoder dsc reference */
lv_vg_lite_pending_remove_all(u->image_dsc_pending); lv_vg_lite_pending_remove_all(u->image_dsc_pending);

View File

@ -538,14 +538,25 @@
#endif #endif
#endif #endif
/* VG-Lite gradient image maximum cache number. /* VG-Lite linear gradient image maximum cache number.
* NOTE: The memory usage of a single gradient image is 4K bytes. * NOTE: The memory usage of a single gradient image is 4K bytes.
*/ */
#ifndef LV_VG_LITE_GRAD_CACHE_SIZE #ifndef LV_VG_LITE_LINEAER_GRAD_CACHE_CNT
#ifdef CONFIG_LV_VG_LITE_GRAD_CACHE_SIZE #ifdef CONFIG_LV_VG_LITE_LINEAER_GRAD_CACHE_CNT
#define LV_VG_LITE_GRAD_CACHE_SIZE CONFIG_LV_VG_LITE_GRAD_CACHE_SIZE #define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT CONFIG_LV_VG_LITE_LINEAER_GRAD_CACHE_CNT
#else #else
#define LV_VG_LITE_GRAD_CACHE_SIZE 32 #define LV_VG_LITE_LINEAER_GRAD_CACHE_CNT 32
#endif
#endif
/* VG-Lite radial gradient image maximum cache size.
* NOTE: The memory usage of a single gradient image is radial grad radius * 4 bytes.
*/
#ifndef LV_VG_LITE_RADIAL_GRAD_CACHE_CNT
#ifdef CONFIG_LV_VG_LITE_RADIAL_GRAD_CACHE_CNT
#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT CONFIG_LV_VG_LITE_RADIAL_GRAD_CACHE_CNT
#else
#define LV_VG_LITE_RADIAL_GRAD_CACHE_CNT 32
#endif #endif
#endif #endif

View File

@ -271,6 +271,7 @@ static FillRule fill_rule_conv(vg_lite_fill_t fill);
static BlendMethod blend_method_conv(vg_lite_blend_t blend); static BlendMethod blend_method_conv(vg_lite_blend_t blend);
static StrokeCap stroke_cap_conv(vg_lite_cap_style_t cap); static StrokeCap stroke_cap_conv(vg_lite_cap_style_t cap);
static StrokeJoin stroke_join_conv(vg_lite_join_style_t join); static StrokeJoin stroke_join_conv(vg_lite_join_style_t join);
static FillSpread fill_spread_conv(vg_lite_gradient_spreadmode_t spread);
static Result shape_append_path(std::unique_ptr<Shape> & shape, vg_lite_path_t * path, vg_lite_matrix_t * matrix); static Result shape_append_path(std::unique_ptr<Shape> & shape, vg_lite_path_t * path, vg_lite_matrix_t * matrix);
static Result shape_append_rect(std::unique_ptr<Shape> & shape, const vg_lite_buffer_t * target, static Result shape_append_rect(std::unique_ptr<Shape> & shape, const vg_lite_buffer_t * target,
const vg_lite_rectangle_t * rect); const vg_lite_rectangle_t * rect);
@ -808,6 +809,8 @@ extern "C" {
case gcFEATURE_BIT_VG_24BIT: case gcFEATURE_BIT_VG_24BIT:
case gcFEATURE_BIT_VG_DITHER: case gcFEATURE_BIT_VG_DITHER:
case gcFEATURE_BIT_VG_USE_DST: case gcFEATURE_BIT_VG_USE_DST:
case gcFEATURE_BIT_VG_RADIAL_GRADIENT:
case gcFEATURE_BIT_VG_IM_REPEAT_REFLECT:
#if LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT #if LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT
case gcFEATURE_BIT_VG_LVGL_SUPPORT: case gcFEATURE_BIT_VG_LVGL_SUPPORT:
@ -1736,15 +1739,34 @@ Empty_sequence_handler:
vg_lite_blend_t blend, vg_lite_blend_t blend,
vg_lite_filter_t filter) vg_lite_filter_t filter)
{ {
LV_UNUSED(target); auto ctx = vg_lite_ctx::get_instance();
LV_UNUSED(path); TVG_CHECK_RETURN_VG_ERROR(canvas_set_target(ctx, target));
LV_UNUSED(fill_rule);
LV_UNUSED(path_matrix); auto shape = Shape::gen();
LV_UNUSED(grad); TVG_CHECK_RETURN_VG_ERROR(shape_append_path(shape, path, path_matrix));
LV_UNUSED(paint_color); TVG_CHECK_RETURN_VG_ERROR(shape->transform(matrix_conv(path_matrix)));
LV_UNUSED(blend); TVG_CHECK_RETURN_VG_ERROR(shape->fill(fill_rule_conv(fill_rule)););
LV_UNUSED(filter); TVG_CHECK_RETURN_VG_ERROR(shape->blend(blend_method_conv(blend)));
return VG_LITE_NOT_SUPPORT;
auto radialGrad = RadialGradient::gen();
TVG_CHECK_RETURN_VG_ERROR(radialGrad->transform(matrix_conv(&grad->matrix)));
TVG_CHECK_RETURN_VG_ERROR(radialGrad->radial(grad->radial_grad.cx, grad->radial_grad.cy, grad->radial_grad.r));
TVG_CHECK_RETURN_VG_ERROR(radialGrad->spread(fill_spread_conv(grad->spread_mode)));
tvg::Fill::ColorStop colorStops[VLC_MAX_COLOR_RAMP_STOPS];
for(vg_lite_uint32_t i = 0; i < grad->ramp_length; i++) {
colorStops[i].offset = grad->color_ramp[i].stop;
colorStops[i].r = grad->color_ramp[i].red * 255.0f;
colorStops[i].g = grad->color_ramp[i].green * 255.0f;
colorStops[i].b = grad->color_ramp[i].blue * 255.0f;
colorStops[i].a = grad->color_ramp[i].alpha * 255.0f;
}
TVG_CHECK_RETURN_VG_ERROR(radialGrad->colorStops(colorStops, grad->ramp_length));
TVG_CHECK_RETURN_VG_ERROR(shape->fill(std::move(radialGrad)));
TVG_CHECK_RETURN_VG_ERROR(ctx->canvas->push(std::move(shape)));
return VG_LITE_SUCCESS;
} }
vg_lite_error_t vg_lite_set_command_buffer_size(vg_lite_uint32_t size) vg_lite_error_t vg_lite_set_command_buffer_size(vg_lite_uint32_t size)
@ -1979,6 +2001,20 @@ static StrokeJoin stroke_join_conv(vg_lite_join_style_t join)
return StrokeJoin::Bevel; return StrokeJoin::Bevel;
} }
static FillSpread fill_spread_conv(vg_lite_gradient_spreadmode_t spread)
{
switch(spread) {
case VG_LITE_GRADIENT_SPREAD_PAD:
return FillSpread::Pad;
case VG_LITE_GRADIENT_SPREAD_REPEAT:
return FillSpread::Repeat;
case VG_LITE_GRADIENT_SPREAD_REFLECT:
return FillSpread::Reflect;
default:
return FillSpread::Pad;
}
}
static float vlc_get_arg(const void * data, vg_lite_format_t format) static float vlc_get_arg(const void * data, vg_lite_format_t format)
{ {
switch(format) { switch(format) {