fix conflicts

This commit is contained in:
Gabor Kiss-Vamosi
2019-02-25 06:56:49 +01:00
47 changed files with 1318 additions and 1970 deletions

View File

@@ -1,9 +1,9 @@
CSRCS += lv_group.c
CSRCS += lv_indev.c
CSRCS += lv_disp.c
CSRCS += lv_obj.c
CSRCS += lv_refr.c
CSRCS += lv_style.c
CSRCS += lv_vdb.c
CSRCS += lv_lang.c
DEPPATH += --dep-path $(LVGL_DIR)/lvgl/lv_core

117
lv_core/lv_disp.c Normal file
View File

@@ -0,0 +1,117 @@
/**
* @file lv_disp.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_disp.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Return with a pointer to the active screen
* @param disp pointer to display which active screen should be get. (NULL to use the default screen)
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
*/
lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp)
{
if(!disp) disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("lv_scr_act: no display registered to get its top layer");
return NULL;
}
return disp->act_scr;
}
/**
* Make a screen active
* @param scr pointer to a screen
*/
void lv_disp_set_scr_act(lv_obj_t * scr)
{
lv_disp_t * d = lv_obj_get_disp(scr);
d->act_scr = scr;
lv_obj_invalidate(scr);
}
/**
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
* @param disp pointer to display which top layer should be get. (NULL to use the default screen)
* @return pointer to the top layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp)
{
if(!disp) disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("lv_layer_top: no display registered to get its top layer");
return NULL;
}
return disp->top_layer;
}
/**
* Return with the sys. layer. (Same on every screen and it is above the normal screen and the top layer)
* @param disp pointer to display which sys. layer should be get. (NULL to use the default screen)
* @return pointer to the sys layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp)
{
if(!disp) disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("lv_layer_sys: no display registered to get its top layer");
return NULL;
}
return disp->sys_layer;
}
/**
* Assign a screen to a display.
* @param disp pointer to a display where to assign the screen
* @param scr pointer to a screen object to assign
*/
void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr)
{
if(lv_obj_get_parent(scr) != NULL) {
LV_LOG_WARN("lv_disp_assign_screen: try to assign a non-screen object");
return;
}
lv_disp_t * old_disp = lv_obj_get_disp(scr);
if(old_disp == disp) return;
lv_ll_chg_list(&old_disp->scr_ll, &disp->scr_ll, scr);
}
/**********************
* STATIC FUNCTIONS
**********************/

114
lv_core/lv_disp.h Normal file
View File

@@ -0,0 +1,114 @@
/**
* @file lv_disp.h
*
*/
#ifndef LV_DISP_H
#define LV_DISP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_hal/lv_hal.h"
#include "lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Return with a pointer to the active screen
* @param disp pointer to display which active screen should be get. (NULL to use the default screen)
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
*/
lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp);
/**
* Make a screen active
* @param scr pointer to a screen
*/
void lv_disp_set_scr_act(lv_obj_t * scr);
/**
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
* @param disp pointer to display which top layer should be get. (NULL to use the default screen)
* @return pointer to the top layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_disp_get_layer_top(lv_disp_t * disp);
/**
* Return with the sys. layer. (Same on every screen and it is above the normal screen and the top layer)
* @param disp pointer to display which sys. layer should be get. (NULL to use the default screen)
* @return pointer to the sys layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp);
/**
* Assign a screen to a display.
* @param disp pointer to a display where to assign the screen
* @param scr pointer to a screen object to assign
*/
void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr);
/*------------------------------------------------
* To improve backward compatibility
* Recommended only if you have one display
*------------------------------------------------*/
/**
* Get the active screen of the default display
* @return pointer to the active screen
*/
static inline lv_obj_t * lv_scr_act(void)
{
return lv_disp_get_scr_act(lv_disp_get_default());
}
/**
* Get the top layer of the default display
* @return pointer to the top layer
*/
static inline lv_obj_t * lv_top_layer(void)
{
return lv_disp_get_layer_top(lv_disp_get_default());
}
/**
* Get the active screen of the deafult display
* @return pointer to the sys layer
*/
static inline lv_obj_t * lv_sys_layer(void)
{
return lv_disp_get_layer_sys(lv_disp_get_default());
}
/**********************
* MACROS
**********************/
/*------------------------------------------------
* To improve backward compatibility
* Recommended only if you have one display
*------------------------------------------------*/
#define LV_HOR_RES (lv_disp_get_hor_res(lv_disp_get_default());)
#define LV_VER_RES (lv_disp_get_ver_res(lv_disp_get_default());)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_TEMPL_H*/

View File

@@ -7,14 +7,14 @@
* INCLUDES
********************/
#include "lv_indev.h"
#include "lv_disp.h"
#include "lv_obj.h"
#include "../lv_hal/lv_hal_tick.h"
#include "../lv_core/lv_group.h"
#include "../lv_core/lv_refr.h"
#include "../lv_misc/lv_task.h"
#include "../lv_misc/lv_math.h"
#include "../lv_draw/lv_draw_rbasic.h"
#include "lv_obj.h"
/*********************
* DEFINES
@@ -125,6 +125,7 @@ void lv_indev_reset_lpr(lv_indev_t * indev)
*/
void lv_indev_enable(lv_hal_indev_type_t type, bool enable)
{
lv_indev_t * i = lv_indev_next(NULL);
while(i) {
@@ -143,7 +144,7 @@ void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj)
if(indev->driver.type != LV_INDEV_TYPE_POINTER) return;
indev->cursor = cur_obj;
lv_obj_set_parent(indev->cursor, lv_layer_sys());
lv_obj_set_parent(indev->cursor, lv_disp_get_layer_sys(indev->driver.disp));
lv_obj_set_pos(indev->cursor, indev->proc.act_point.x, indev->proc.act_point.y);
}
@@ -248,6 +249,7 @@ void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point)
*/
uint32_t lv_indev_get_inactive_time(const lv_indev_t * indev)
{
uint32_t t;
if(indev) return t = lv_tick_elaps(indev->last_activity_time);
@@ -361,14 +363,6 @@ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data)
i->proc.act_point.y = data->point.y;
if(i->proc.state == LV_INDEV_STATE_PR) {
#if LV_INDEV_POINT_MARKER != 0
lv_area_t area;
area.x1 = i->proc.act_point.x - (LV_INDEV_POINT_MARKER >> 1);
area.y1 = i->proc.act_point.y - (LV_INDEV_POINT_MARKER >> 1);
area.x2 = i->proc.act_point.x + ((LV_INDEV_POINT_MARKER >> 1) | 0x1);
area.y2 = i->proc.act_point.y + ((LV_INDEV_POINT_MARKER >> 1) | 0x1);
lv_rfill(&area, NULL, LV_COLOR_MAKE(0xFF, 0, 0), LV_OPA_COVER);
#endif
indev_proc_press(&i->proc);
} else {
indev_proc_release(&i->proc);
@@ -550,21 +544,14 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data)
*/
static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data)
{
i->proc.act_point.x = i->btn_points[data->btn].x;
i->proc.act_point.y = i->btn_points[data->btn].y;
i->proc.act_point.x = i->btn_points[data->btn_id].x;
i->proc.act_point.y = i->btn_points[data->btn_id].y;
/*Still the same point is pressed*/
if(i->proc.last_point.x == i->proc.act_point.x &&
i->proc.last_point.y == i->proc.act_point.y &&
data->state == LV_INDEV_STATE_PR) {
#if LV_INDEV_POINT_MARKER != 0
lv_area_t area;
area.x1 = i->proc.act_point.x - (LV_INDEV_POINT_MARKER >> 1);
area.y1 = i->proc.act_point.y - (LV_INDEV_POINT_MARKER >> 1);
area.x2 = i->proc.act_point.x + ((LV_INDEV_POINT_MARKER >> 1) | 0x1);
area.y2 = i->proc.act_point.y + ((LV_INDEV_POINT_MARKER >> 1) | 0x1);
lv_rfill(&area, NULL, LV_COLOR_MAKE(0xFF, 0, 0), LV_OPA_COVER);
#endif
data->state == LV_INDEV_STATE_PR)
{
indev_proc_press(&i->proc);
} else {
/*If a new point comes always make a release*/
@@ -585,16 +572,20 @@ static void indev_proc_press(lv_indev_proc_t * proc)
if(proc->wait_unil_release != 0) return;
lv_disp_t * disp = indev_act->driver.disp;
/*If there is no last object then search*/
if(proc->act_obj == NULL) {
pr_obj = indev_search_obj(proc, lv_layer_top());
if(pr_obj == NULL) pr_obj = indev_search_obj(proc, lv_scr_act());
pr_obj = indev_search_obj(proc, lv_disp_get_layer_sys(disp));
if(pr_obj == NULL) pr_obj = indev_search_obj(proc, lv_disp_get_layer_top(disp));
if(pr_obj == NULL) pr_obj = indev_search_obj(proc, lv_disp_get_scr_act(disp));
}
/*If there is last object but it is not dragged and not protected also search*/
else if(proc->drag_in_prog == 0 &&
lv_obj_is_protected(proc->act_obj, LV_PROTECT_PRESS_LOST) == false) {/*Now act_obj != NULL*/
pr_obj = indev_search_obj(proc, lv_layer_top());
if(pr_obj == NULL) pr_obj = indev_search_obj(proc, lv_scr_act());
pr_obj = indev_search_obj(proc, lv_disp_get_layer_sys(disp));
if(pr_obj == NULL) pr_obj = indev_search_obj(proc, lv_disp_get_layer_top(disp));
if(pr_obj == NULL) pr_obj = indev_search_obj(proc, lv_disp_get_scr_act(disp));
}
/*If a dragable or a protected object was the last then keep it*/
else {
@@ -870,7 +861,7 @@ static void indev_drag(lv_indev_proc_t * state)
/*Get the coordinates of the object and modify them*/
lv_coord_t act_x = lv_obj_get_x(drag_obj);
lv_coord_t act_y = lv_obj_get_y(drag_obj);
uint16_t inv_buf_size = lv_refr_get_buf_size(); /*Get the number of currently invalidated areas*/
uint16_t inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp); /*Get the number of currently invalidated areas*/
lv_coord_t prev_x = drag_obj->coords.x1;
lv_coord_t prev_y = drag_obj->coords.y1;
@@ -896,8 +887,8 @@ static void indev_drag(lv_indev_proc_t * state)
lv_coord_t act_par_w = lv_obj_get_width(lv_obj_get_parent(drag_obj));
lv_coord_t act_par_h = lv_obj_get_height(lv_obj_get_parent(drag_obj));
if(act_par_w == prev_par_w && act_par_h == prev_par_h) {
uint16_t new_inv_buf_size = lv_refr_get_buf_size();
lv_refr_pop_from_buf(new_inv_buf_size - inv_buf_size);
uint16_t new_inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp);
lv_disp_pop_from_inv_buf(indev_act->driver.disp, new_inv_buf_size - inv_buf_size);
}
}
}

View File

@@ -54,7 +54,7 @@ void lv_lang_set(uint8_t lang_id)
lang_set_core(i);
}
lang_set_core(lv_scr_act());
lang_set_core(lv_scr_act(NULL));
}
/**

View File

@@ -10,13 +10,14 @@
#include "lv_indev.h"
#include "lv_refr.h"
#include "lv_group.h"
#include "lv_disp.h"
#include "../lv_themes/lv_theme.h"
#include "../lv_draw/lv_draw.h"
#include "../lv_draw/lv_draw_rbasic.h"
#include "../lv_misc/lv_anim.h"
#include "../lv_misc/lv_task.h"
#include "../lv_misc/lv_fs.h"
#include "../lv_misc/lv_ufs.h"
#include "../lv_hal/lv_hal.h"
#include <stdint.h>
#include <string.h>
#include "../lv_misc/lv_gc.h"
@@ -65,15 +66,10 @@ static bool _lv_initialized = false;
void lv_init(void)
{
/* Do nothing if already initialized */
if (_lv_initialized)
return;
LV_GC_ROOT(_lv_def_scr) = NULL;
LV_GC_ROOT(_lv_act_scr) = NULL;
LV_GC_ROOT(_lv_top_layer) = NULL;
LV_GC_ROOT(_lv_sys_layer) = NULL;
LV_GC_ROOT(_lv_disp_list) = NULL;
LV_GC_ROOT(_lv_indev_list) = NULL;
if (_lv_initialized) {
LV_LOG_WARN("lv_init: already inited");
return;
}
LV_LOG_TRACE("lv_init started");
@@ -101,20 +97,9 @@ void lv_init(void)
/*Initialize the screen refresh system*/
lv_refr_init();
/*Create the default screen*/
lv_ll_init(&LV_GC_ROOT(_lv_scr_ll), sizeof(lv_obj_t));
LV_GC_ROOT(_lv_def_scr) = lv_obj_create(NULL, NULL);
lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t));
lv_ll_init(&LV_GC_ROOT(_lv_indev_ll), sizeof(lv_indev_t));
LV_GC_ROOT(_lv_act_scr) = LV_GC_ROOT(_lv_def_scr);
LV_GC_ROOT(_lv_top_layer) = lv_obj_create(NULL, NULL);
lv_obj_set_style(LV_GC_ROOT(_lv_top_layer), &lv_style_transp_fit);
LV_GC_ROOT(_lv_sys_layer) = lv_obj_create(NULL, NULL);
lv_obj_set_style(LV_GC_ROOT(_lv_sys_layer), &lv_style_transp_fit);
/*Refresh the screen*/
lv_obj_invalidate(LV_GC_ROOT(_lv_act_scr));
#if LV_INDEV_READ_PERIOD != 0
/*Init the input device handling*/
@@ -143,8 +128,13 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
/*Create a screen if the parent is NULL*/
if(parent == NULL) {
LV_LOG_TRACE("Screen create started");
lv_disp_t * disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("lv_obj_create: not display created to so far. No place to assign the new screen");
return NULL;
}
new_obj = lv_ll_ins_head(&LV_GC_ROOT(_lv_scr_ll));
new_obj = lv_ll_ins_head(&disp->scr_ll);
lv_mem_assert(new_obj);
if(new_obj == NULL) return NULL;
@@ -154,8 +144,8 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
/*Set coordinates to full screen size*/
new_obj->coords.x1 = 0;
new_obj->coords.y1 = 0;
new_obj->coords.x2 = LV_HOR_RES - 1;
new_obj->coords.y2 = LV_VER_RES - 1;
new_obj->coords.x2 = lv_disp_get_hor_res(NULL) - 1;
new_obj->coords.y2 = lv_disp_get_ver_res(NULL) - 1;
new_obj->ext_size = 0;
/*Init realign*/
@@ -367,7 +357,8 @@ lv_res_t lv_obj_del(lv_obj_t * obj)
/*Remove the object from parent's children list*/
lv_obj_t * par = lv_obj_get_parent(obj);
if(par == NULL) { /*It is a screen*/
lv_ll_rem(&LV_GC_ROOT(_lv_scr_ll), obj);
lv_disp_t * d = lv_obj_get_disp(obj);
lv_ll_rem(&d->scr_ll, obj);
} else {
lv_ll_rem(&(par->child_ll), obj);
}
@@ -425,9 +416,10 @@ void lv_obj_invalidate(const lv_obj_t * obj)
/*Invalidate the object only if it belongs to the 'LV_GC_ROOT(_lv_act_scr)'*/
lv_obj_t * obj_scr = lv_obj_get_screen(obj);
if(obj_scr == lv_scr_act() ||
obj_scr == lv_layer_top() ||
obj_scr == lv_layer_sys()) {
lv_disp_t * disp = lv_obj_get_disp(obj_scr);
if(obj_scr == lv_disp_get_scr_act(disp) ||
obj_scr == lv_disp_get_layer_top(disp)||
obj_scr == lv_disp_get_layer_sys(disp)) {
/*Truncate recursively to the parents*/
lv_area_t area_trunc;
lv_obj_t * par = lv_obj_get_parent(obj);
@@ -449,7 +441,7 @@ void lv_obj_invalidate(const lv_obj_t * obj)
par = lv_obj_get_parent(par);
}
if(union_ok != false) lv_inv_area(&area_trunc);
if(union_ok) lv_inv_area(disp, &area_trunc);
}
}
@@ -458,21 +450,6 @@ void lv_obj_invalidate(const lv_obj_t * obj)
* Setter functions
*====================*/
/*--------------
* Screen set
*--------------*/
/**
* Load a new screen
* @param scr pointer to a screen
*/
void lv_scr_load(lv_obj_t * scr)
{
LV_GC_ROOT(_lv_act_scr) = scr;
lv_obj_invalidate(LV_GC_ROOT(_lv_act_scr));
}
/*--------------------
* Parent/children set
*--------------------*/
@@ -1022,13 +999,18 @@ void lv_obj_refresh_style(lv_obj_t * obj)
*/
void lv_obj_report_style_mod(lv_style_t * style)
{
lv_obj_t * i;
LL_READ(LV_GC_ROOT(_lv_scr_ll), i) {
if(i->style_p == style || style == NULL) {
lv_obj_refresh_style(i);
}
lv_disp_t * d = lv_disp_get_next(NULL);
report_style_mod_core(style, i);
while(d) {
lv_obj_t * i;
LL_READ(d->scr_ll, i) {
if(i->style_p == style || style == NULL) {
lv_obj_refresh_style(i);
}
report_style_mod_core(style, i);
}
d = lv_disp_get_next(d);
}
}
@@ -1310,38 +1292,6 @@ void lv_obj_animate(lv_obj_t * obj, lv_anim_builtin_t type, uint16_t time, uint1
* Getter functions
*======================*/
/*------------------
* Screen get
*-----------------*/
/**
* Return with a pointer to the active screen
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
*/
lv_obj_t * lv_scr_act(void)
{
return LV_GC_ROOT(_lv_act_scr);
}
/**
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
* @return pointer to the top layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_layer_top(void)
{
return LV_GC_ROOT(_lv_top_layer);
}
/**
* Return with the system layer. (Same on every screen and it is above the all other layers)
* It is used for example by the cursor
* @return pointer to the system layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_layer_sys(void)
{
return LV_GC_ROOT(_lv_sys_layer);
}
/**
* Return with the screen of an object
* @param obj pointer to an object
@@ -1360,6 +1310,30 @@ lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj)
return (lv_obj_t *)act_p;
}
/**
* Get the display of an object
* @param scr pointer to an object
* @return pointer the object's display
*/
lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj)
{
const lv_obj_t * scr;
if(obj->par == NULL) scr = obj; /*`obj` is a screen*/
else scr = lv_obj_get_screen(obj); /*get the screen of `obj`*/
lv_disp_t * d;
LL_READ(LV_GC_ROOT(_lv_disp_ll), d) {
lv_obj_t * s;
LL_READ(d->scr_ll, s) {
if(s == scr) return d;
}
}
LV_LOG_WARN("lv_scr_get_disp: screen not found")
return NULL;
}
/*---------------------
* Parent/children get
*--------------------*/

View File

@@ -27,13 +27,14 @@ extern "C" {
#include "../lv_misc/lv_ll.h"
#include "../lv_misc/lv_color.h"
#include "../lv_misc/lv_log.h"
#include "../lv_hal/lv_hal.h"
/*********************
* DEFINES
*********************/
/*Error check of lv_conf.h*/
#if LV_HOR_RES == 0 || LV_VER_RES == 0
#if LV_HOR_RES_MAX == 0 || LV_VER_RES_MAX == 0
#error "LittlevGL: LV_HOR_RES and LV_VER_RES must be greater than 0"
#endif
@@ -41,19 +42,6 @@ extern "C" {
#error "LittlevGL: LV_ANTIALIAS can be only 0 or 1"
#endif
#if LV_VDB_SIZE == 0 && LV_ANTIALIAS != 0
#error "LittlevGL: If LV_VDB_SIZE == 0 the anti-aliasing must be disabled"
#endif
#if LV_VDB_SIZE > 0 && LV_VDB_SIZE < LV_HOR_RES
#error "LittlevGL: Small Virtual Display Buffer (lv_conf.h: LV_VDB_SIZE >= LV_HOR_RES)"
#endif
#if LV_VDB_SIZE == 0 && USE_LV_REAL_DRAW == 0
#error "LittlevGL: If LV_VDB_SIZE = 0 Real drawing function are required (lv_conf.h: USE_LV_REAL_DRAW 1)"
#endif
#define LV_ANIM_IN 0x00 /*Animation to show an object. 'OR' it with lv_anim_builtin_t*/
#define LV_ANIM_OUT 0x80 /*Animation to hide an object. 'OR' it with lv_anim_builtin_t*/
#define LV_ANIM_DIR_MASK 0x80 /*ANIM_IN/ANIM_OUT mask*/
@@ -274,16 +262,6 @@ void lv_obj_invalidate(const lv_obj_t * obj);
* Setter functions
*====================*/
/*--------------
* Screen set
*--------------*/
/**
* Load a new screen
* @param scr pointer to a screen
*/
void lv_scr_load(lv_obj_t * scr);
/*--------------------
* Parent/children set
*--------------------*/
@@ -553,29 +531,6 @@ void lv_obj_animate(lv_obj_t * obj, lv_anim_builtin_t type, uint16_t time, uint1
* Getter functions
*======================*/
/*------------------
* Screen get
*-----------------*/
/**
* Return with a pointer to the active screen
* @return pointer to the active screen object (loaded by 'lv_scr_load()')
*/
lv_obj_t * lv_scr_act(void);
/**
* Return with the top layer. (Same on every screen and it is above the normal screen layer)
* @return pointer to the top layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_layer_top(void);
/**
* Return with the system layer. (Same on every screen and it is above the all other layers)
* It is used for example by the cursor
* @return pointer to the system layer object (transparent screen sized lv_obj)
*/
lv_obj_t * lv_layer_sys(void);
/**
* Return with the screen of an object
* @param obj pointer to an object
@@ -583,6 +538,13 @@ lv_obj_t * lv_layer_sys(void);
*/
lv_obj_t * lv_obj_get_screen(const lv_obj_t * obj);
/**
* Get the display of an object
* @param scr pointer to an object
* @return pointer the object's display
*/
lv_disp_t * lv_obj_get_disp(const lv_obj_t * obj);
/*---------------------
* Parent/children get
*--------------------*/

View File

@@ -8,26 +8,20 @@
*********************/
#include <stddef.h>
#include "lv_refr.h"
#include "lv_vdb.h"
#include "lv_disp.h"
#include "../lv_hal/lv_hal_tick.h"
#include "../lv_hal/lv_hal_disp.h"
#include "../lv_misc/lv_task.h"
#include "../lv_misc/lv_mem.h"
#include "../lv_misc/lv_gc.h"
/*********************
* DEFINES
*********************/
#ifndef LV_INV_FIFO_SIZE
#define LV_INV_FIFO_SIZE 32 /*The average count of objects on a screen */
#endif
/**********************
* TYPEDEFS
**********************/
typedef struct {
lv_area_t area;
uint8_t joined;
} lv_join_t;
/**********************
* STATIC PROTOTYPES
@@ -35,24 +29,18 @@ typedef struct {
static void lv_refr_task(void * param);
static void lv_refr_join_area(void);
static void lv_refr_areas(void);
#if LV_VDB_SIZE == 0
static void lv_refr_area_no_vdb(const lv_area_t * area_p);
#else
static void lv_refr_area_with_vdb(const lv_area_t * area_p);
static void lv_refr_area_part_vdb(const lv_area_t * area_p);
#endif
static void lv_refr_area(const lv_area_t * area_p);
static void lv_refr_area_part(const lv_area_t * area_p);
static lv_obj_t * lv_refr_get_top_obj(const lv_area_t * area_p, lv_obj_t * obj);
static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p);
static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p);
static void lv_refr_vdb_flush(void);
/**********************
* STATIC VARIABLES
**********************/
static lv_join_t inv_buf[LV_INV_FIFO_SIZE];
static uint16_t inv_buf_p;
static void (*monitor_cb)(uint32_t, uint32_t); /*Monitor the rendering time*/
static void (*round_cb)(lv_area_t *); /*If set then called to modify invalidated areas for special display controllers*/
static uint32_t px_num;
static lv_disp_t * disp_refr; /*Display being refreshed*/
/**********************
* MACROS
@@ -67,9 +55,6 @@ static uint32_t px_num;
*/
void lv_refr_init(void)
{
inv_buf_p = 0;
memset(inv_buf, 0, sizeof(inv_buf));
lv_task_t * task;
task = lv_task_create(lv_refr_task, LV_REFR_PERIOD, LV_TASK_PRIO_MID, NULL);
lv_task_ready(task); /*Be sure the screen will be refreshed immediately on start up*/
@@ -88,22 +73,26 @@ void lv_refr_now(void)
/**
* Invalidate an area
* @param area_p pointer to area which should be invalidated
* Invalidate an area on display to redraw it
* @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas)
* @param disp pointer to display where the area should be invalidated (NULL can be used if there is only one display)
*/
void lv_inv_area(const lv_area_t * area_p)
void lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p)
{
if(!disp) disp = lv_disp_get_default();
if(!disp) return;
/*Clear the invalidate buffer if the parameter is NULL*/
if(area_p == NULL) {
inv_buf_p = 0;
disp->inv_p = 0;
return;
}
lv_area_t scr_area;
scr_area.x1 = 0;
scr_area.y1 = 0;
scr_area.x2 = LV_HOR_RES - 1;
scr_area.y2 = LV_VER_RES - 1;
scr_area.x2 = disp->driver.hor_res - 1;
scr_area.y2 = disp->driver.ver_res - 1;
lv_area_t com_area;
bool suc;
@@ -112,64 +101,32 @@ void lv_inv_area(const lv_area_t * area_p)
/*The area is truncated to the screen*/
if(suc != false) {
if(round_cb) round_cb(&com_area);
if(disp->driver.rounder_cb) disp->driver.rounder_cb(&disp_refr->driver, &com_area);
/*Save only if this area is not in one of the saved areas*/
uint16_t i;
for(i = 0; i < inv_buf_p; i++) {
if(lv_area_is_in(&com_area, &inv_buf[i].area) != false) return;
for(i = 0; i < disp->inv_p; i++) {
if(lv_area_is_in(&com_area, &disp->inv_areas[i]) != false) return;
}
/*Save the area*/
if(inv_buf_p < LV_INV_FIFO_SIZE) {
lv_area_copy(&inv_buf[inv_buf_p].area, &com_area);
if(disp->inv_p < LV_INV_BUF_SIZE) {
lv_area_copy(&disp->inv_areas[disp->inv_p], &com_area);
} else {/*If no place for the area add the screen*/
inv_buf_p = 0;
lv_area_copy(&inv_buf[inv_buf_p].area, &scr_area);
disp->inv_p = 0;
lv_area_copy(&disp->inv_areas[disp->inv_p], &scr_area);
}
inv_buf_p ++;
disp->inv_p ++;
}
}
/**
* Set a function to call after every refresh to announce the refresh time and the number of refreshed pixels
* @param cb pointer to a callback function (void my_refr_cb(uint32_t time_ms, uint32_t px_num))
* time_ms: refresh time in [ms]
* px_num: not the drawn pixels but the number of affected pixels of the screen
* (more pixels are drawn because of overlapping objects)
* Get the display which is being refreshed
* @return the display being refreshed
*/
void lv_refr_set_monitor_cb(void (*cb)(uint32_t, uint32_t))
lv_disp_t * lv_refr_get_disp_refreshing(void)
{
monitor_cb = cb;
}
/**
* Called when an area is invalidated to modify the coordinates of the area.
* Special display controllers may require special coordinate rounding
* @param cb pointer to the a function which will modify the area
*/
void lv_refr_set_round_cb(void(*cb)(lv_area_t *))
{
round_cb = cb;
}
/**
* Get the number of areas in the buffer
* @return number of invalid areas
*/
uint16_t lv_refr_get_buf_size(void)
{
return inv_buf_p;
}
/**
* Pop (delete) the last 'num' invalidated areas from the buffer
* @param num number of areas to delete
*/
void lv_refr_pop_from_buf(uint16_t num)
{
if(inv_buf_p < num) inv_buf_p = 0;
else inv_buf_p -= num;
return disp_refr;
}
/**********************
@@ -184,69 +141,63 @@ static void lv_refr_task(void * param)
{
(void)param;
LV_LOG_TRACE("display refresh task started");
LV_LOG_TRACE("lv_refr_task: started");
uint32_t start = lv_tick_get();
if(lv_disp_get_active() == NULL) {
LV_LOG_TRACE("No display is registered");
return;
}
LL_READ(LV_GC_ROOT(_lv_disp_ll), disp_refr) {
LV_LOG_TRACE("lv_refr_task: refreshing a display");
lv_refr_join_area();
lv_refr_join_area();
lv_refr_areas();
lv_refr_areas();
/*If refresh happened ...*/
if(inv_buf_p != 0) {
/*If refresh happened ...*/
if(disp_refr->inv_p != 0) {
/*In true double buffered mode copy the refreshed areas to the new VDB to keep it up to date*/
if(lv_disp_is_true_double_buf(disp_refr)) {
lv_disp_buf_t * vdb = lv_disp_get_buf(disp_refr);
/*In true double buffered mode copy the refreshed areas to the new VDB to keep it up to date*/
#if LV_VDB_TRUE_DOUBLE_BUFFERED
lv_vdb_t * vdb_p = lv_vdb_get();
vdb_p->area.x1 = 0;
vdb_p->area.x2 = LV_HOR_RES-1;
vdb_p->area.y1 = 0;
vdb_p->area.y2 = LV_VER_RES - 1;
/*Flush the content of the VDB*/
lv_refr_vdb_flush();
/*Flush the content of the VDB*/
lv_vdb_flush();
/* With true double buffering the flushing should be only the address change of the current frame buffer.
* Wait until the address change is ready and copy the changed content to the other frame buffer (new active VDB)
* to keep the buffers synchronized*/
while(vdb->flushing);
/* With true double buffering the flushing should be only the address change of the current frame buffer
* Wait until the address change is ready and copy the active content to the other frame buffer (new active VDB)
* The changes will be written to the new VDB.*/
lv_vdb_t * vdb_act = lv_vdb_get_active();
lv_vdb_t * vdb_ina = lv_vdb_get_inactive();
uint8_t * buf_act = (uint8_t *) vdb->buf_act;
uint8_t * buf_ina = (uint8_t *) vdb->buf_act == vdb->buf1 ? vdb->buf2 : vdb->buf1;
uint8_t * buf_act = (uint8_t *) vdb_act->buf;
uint8_t * buf_ina = (uint8_t *) vdb_ina->buf;
lv_coord_t hres = lv_disp_get_hor_res(disp_refr);
uint16_t a;
for(a = 0; a < disp_refr->inv_p; a++) {
if(disp_refr->inv_area_joined[a] == 0) {
lv_coord_t y;
uint32_t start_offs = (hres * disp_refr->inv_areas[a].y1 + disp_refr->inv_areas[a].x1) * sizeof(lv_color_t);
uint32_t line_length = lv_area_get_width(&disp_refr->inv_areas[a]) * sizeof(lv_color_t);
uint16_t a;
for(a = 0; a < inv_buf_p; a++) {
if(inv_buf[a].joined == 0) {
lv_coord_t y;
uint32_t start_offs = ((LV_HOR_RES * inv_buf[a].area.y1 + inv_buf[a].area.x1) * LV_VDB_PX_BPP) >> 3;
uint32_t line_length = (lv_area_get_width(&inv_buf[a].area) * LV_VDB_PX_BPP) >> 3;
for(y = inv_buf[a].area.y1; y <= inv_buf[a].area.y2; y++) {
memcpy(buf_act + start_offs, buf_ina + start_offs, line_length);
start_offs += (LV_HOR_RES * LV_VDB_PX_BPP) >> 3;
for(y = disp_refr->inv_areas[a].y1; y <= disp_refr->inv_areas[a].y2; y++) {
memcpy(buf_act + start_offs, buf_ina + start_offs, line_length);
start_offs += hres * sizeof(lv_color_t);
}
}
}
} /*End of true double buffer handling*/
/*Clean up*/
memset(disp_refr->inv_areas, 0, sizeof(disp_refr->inv_areas));
memset(disp_refr->inv_area_joined, 0, sizeof(disp_refr->inv_area_joined));
disp_refr->inv_p = 0;
/*Call monitor cb if present*/
if(disp_refr->driver.monitor_cb) {
disp_refr->driver.monitor_cb(&disp_refr->driver, lv_tick_elaps(start), px_num);
}
}
#endif
/*Clean up*/
memset(inv_buf, 0, sizeof(inv_buf));
inv_buf_p = 0;
/*Call monitor cb if present*/
if(monitor_cb != NULL) {
monitor_cb(lv_tick_elaps(start), px_num);
}
}
LV_LOG_TRACE("display refresh task finished");
LV_LOG_TRACE("lv_refr_task: ready");
}
@@ -258,32 +209,32 @@ static void lv_refr_join_area(void)
uint32_t join_from;
uint32_t join_in;
lv_area_t joined_area;
for(join_in = 0; join_in < inv_buf_p; join_in++) {
if(inv_buf[join_in].joined != 0) continue;
for(join_in = 0; join_in < disp_refr->inv_p; join_in++) {
if(disp_refr->inv_area_joined[join_in] != 0) continue;
/*Check all areas to join them in 'join_in'*/
for(join_from = 0; join_from < inv_buf_p; join_from++) {
for(join_from = 0; join_from < disp_refr->inv_p; join_from++) {
/*Handle only unjoined areas and ignore itself*/
if(inv_buf[join_from].joined != 0 || join_in == join_from) {
if(disp_refr->inv_area_joined[join_from] != 0 || join_in == join_from) {
continue;
}
/*Check if the areas are on each other*/
if(lv_area_is_on(&inv_buf[join_in].area,
&inv_buf[join_from].area) == false) {
if(lv_area_is_on(&disp_refr->inv_areas[join_in],
&disp_refr->inv_areas[join_from]) == false) {
continue;
}
lv_area_join(&joined_area, &inv_buf[join_in].area,
&inv_buf[join_from].area);
lv_area_join(&joined_area, &disp_refr->inv_areas[join_in],
&disp_refr->inv_areas[join_from]);
/*Join two area only if the joined area size is smaller*/
if(lv_area_get_size(&joined_area) <
(lv_area_get_size(&inv_buf[join_in].area) + lv_area_get_size(&inv_buf[join_from].area))) {
lv_area_copy(&inv_buf[join_in].area, &joined_area);
(lv_area_get_size(&disp_refr->inv_areas[join_in]) + lv_area_get_size(&disp_refr->inv_areas[join_from]))) {
lv_area_copy(&disp_refr->inv_areas[join_in], &joined_area);
/*Mark 'join_form' is joined into 'join_in'*/
inv_buf[join_from].joined = 1;
disp_refr->inv_area_joined[join_from] = 1;
}
}
}
@@ -297,170 +248,133 @@ static void lv_refr_areas(void)
px_num = 0;
uint32_t i;
for(i = 0; i < inv_buf_p; i++) {
for(i = 0; i < disp_refr->inv_p; i++) {
/*Refresh the unjoined areas*/
if(inv_buf[i].joined == 0) {
/*If there is no VDB do simple drawing*/
#if LV_VDB_SIZE == 0
lv_refr_area_no_vdb(&inv_buf[i].area);
#else
/*If VDB is used...*/
lv_refr_area_with_vdb(&inv_buf[i].area);
#endif
if(monitor_cb != NULL) px_num += lv_area_get_size(&inv_buf[i].area);
if(disp_refr->inv_area_joined[i] == 0) {
lv_refr_area(&disp_refr->inv_areas[i]);
if(disp_refr->driver.monitor_cb) px_num += lv_area_get_size(&disp_refr->inv_areas[i]);
}
}
}
#if LV_VDB_SIZE == 0
/**
* Refresh an area if there is no Virtual Display Buffer
* @param area_p pointer to an area to refresh
*/
static void lv_refr_area_no_vdb(const lv_area_t * area_p)
{
lv_obj_t * top_p;
/*Get top object which is not covered by others*/
top_p = lv_refr_get_top_obj(area_p, lv_scr_act());
/*Do the refreshing*/
lv_refr_obj_and_children(top_p, area_p);
/*Also refresh top and sys layer unconditionally*/
lv_refr_obj_and_children(lv_layer_top(), area_p);
lv_refr_obj_and_children(lv_layer_sys(), area_p);
}
#else
/**
* Refresh an area if there is Virtual Display Buffer
* @param area_p pointer to an area to refresh
*/
static void lv_refr_area_with_vdb(const lv_area_t * area_p)
static void lv_refr_area(const lv_area_t * area_p)
{
#if LV_VDB_TRUE_DOUBLE_BUFFERED == 0
/*Calculate the max row num*/
lv_coord_t w = lv_area_get_width(area_p);
lv_coord_t h = lv_area_get_height(area_p);
lv_coord_t y2 = area_p->y2 >= LV_VER_RES ? y2 = LV_VER_RES - 1 : area_p->y2;
int32_t max_row = (uint32_t) LV_VDB_SIZE / w;
if(max_row > h) max_row = h;
/*Round down the lines of VDB if rounding is added*/
if(round_cb) {
lv_area_t tmp;
tmp.x1 = 0;
tmp.x2 = 0;
tmp.y1 = 0;
tmp.y2 = max_row;
lv_coord_t y_tmp = max_row;
do {
tmp.y2 = y_tmp;
round_cb(&tmp);
y_tmp --; /*Decrement the number of line until it is rounded to a smaller (or equal) value then the original. */
} while(lv_area_get_height(&tmp) > max_row && y_tmp != 0);
if(y_tmp == 0) {
LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to small VDB)");
return;
} else {
max_row = tmp.y2 + 1;
}
/*True double buffering: there are two screen sized buffers. Just redraw directly into a buffer*/
if(lv_disp_is_true_double_buf(disp_refr)) {
lv_disp_buf_t * vdb = lv_disp_get_buf(disp_refr);
vdb->area.x1 = 0;
vdb->area.x2 = lv_disp_get_hor_res(disp_refr) - 1;
vdb->area.y1 = 0;
vdb->area.y2 = lv_disp_get_ver_res(disp_refr) - 1;
lv_refr_area_part(area_p);
}
/*The buffer is smaller: refresh the area in parts*/
else {
lv_disp_buf_t * vdb = lv_disp_get_buf(disp_refr);
/*Calculate the max row num*/
lv_coord_t w = lv_area_get_width(area_p);
lv_coord_t h = lv_area_get_height(area_p);
lv_coord_t y2 = area_p->y2 >= lv_disp_get_ver_res(NULL) ? y2 = lv_disp_get_ver_res(NULL) - 1 : area_p->y2;
/*Always use the full row*/
lv_coord_t row;
lv_coord_t row_last = 0;
for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) {
lv_vdb_t * vdb_p = lv_vdb_get();
if(!vdb_p) {
LV_LOG_WARN("Invalid VDB pointer");
return;
int32_t max_row = (uint32_t) vdb->size / w;
if(max_row > h) max_row = h;
/*Round down the lines of VDB if rounding is added*/
if(disp_refr->driver.rounder_cb) {
lv_area_t tmp;
tmp.x1 = 0;
tmp.x2 = 0;
tmp.y1 = 0;
tmp.y2 = max_row;
lv_coord_t y_tmp = max_row;
do {
tmp.y2 = y_tmp;
disp_refr->driver.rounder_cb(&disp_refr->driver, &tmp);
y_tmp --; /*Decrement the number of line until it is rounded to a smaller (or equal) value then the original. */
} while(lv_area_get_height(&tmp) > max_row && y_tmp != 0);
if(y_tmp == 0) {
LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to small VDB)");
return;
} else {
max_row = tmp.y2 + 1;
}
}
/*Calc. the next y coordinates of VDB*/
vdb_p->area.x1 = area_p->x1;
vdb_p->area.x2 = area_p->x2;
vdb_p->area.y1 = row;
vdb_p->area.y2 = row + max_row - 1;
if(vdb_p->area.y2 > y2) vdb_p->area.y2 = y2;
row_last = vdb_p->area.y2;
lv_refr_area_part_vdb(area_p);
}
/*If the last y coordinates are not handled yet ...*/
if(y2 != row_last) {
lv_vdb_t * vdb_p = lv_vdb_get();
if(!vdb_p) {
LV_LOG_WARN("Invalid VDB pointer");
return;
/*Always use the full row*/
lv_coord_t row;
lv_coord_t row_last = 0;
for(row = area_p->y1; row + max_row - 1 <= y2; row += max_row) {
/*Calc. the next y coordinates of VDB*/
vdb->area.x1 = area_p->x1;
vdb->area.x2 = area_p->x2;
vdb->area.y1 = row;
vdb->area.y2 = row + max_row - 1;
if(vdb->area.y2 > y2) vdb->area.y2 = y2;
row_last = vdb->area.y2;
lv_refr_area_part(area_p);
}
/*Calc. the next y coordinates of VDB*/
vdb_p->area.x1 = area_p->x1;
vdb_p->area.x2 = area_p->x2;
vdb_p->area.y1 = row;
vdb_p->area.y2 = y2;
/*If the last y coordinates are not handled yet ...*/
if(y2 != row_last) {
/*Calc. the next y coordinates of VDB*/
vdb->area.x1 = area_p->x1;
vdb->area.x2 = area_p->x2;
vdb->area.y1 = row;
vdb->area.y2 = y2;
/*Refresh this part too*/
lv_refr_area_part_vdb(area_p);
/*Refresh this part too*/
lv_refr_area_part(area_p);
}
}
#else
lv_vdb_t * vdb_p = lv_vdb_get();
vdb_p->area.x1 = 0;
vdb_p->area.x2 = LV_HOR_RES-1;
vdb_p->area.y1 = 0;
vdb_p->area.y2 = LV_VER_RES - 1;
lv_refr_area_part_vdb(area_p);
#endif
}
/**
* Refresh a part of an area which is on the actual Virtual Display Buffer
* @param area_p pointer to an area to refresh
*/
static void lv_refr_area_part_vdb(const lv_area_t * area_p)
static void lv_refr_area_part(const lv_area_t * area_p)
{
lv_vdb_t * vdb_p = lv_vdb_get();
if(!vdb_p) {
LV_LOG_WARN("Invalid VDB pointer");
return;
lv_disp_buf_t * vdb = lv_disp_get_buf(disp_refr);
/*In non double buffered mode, before rendering the next part wait until the previous image is flushed*/
if(lv_disp_is_double_buf(disp_refr) == false) {
while(vdb->flushing);
}
lv_obj_t * top_p;
/*Get the new mask from the original area and the act. VDB
It will be a part of 'area_p'*/
lv_area_t start_mask;
lv_area_intersect(&start_mask, area_p, &vdb_p->area);
lv_area_intersect(&start_mask, area_p, &vdb->area);
/*Get the most top object which is not covered by others*/
top_p = lv_refr_get_top_obj(&start_mask, lv_scr_act());
top_p = lv_refr_get_top_obj(&start_mask, lv_disp_get_scr_act(disp_refr));
/*Do the refreshing from the top object*/
lv_refr_obj_and_children(top_p, &start_mask);
/*Also refresh top and sys layer unconditionally*/
lv_refr_obj_and_children(lv_layer_top(), &start_mask);
lv_refr_obj_and_children(lv_layer_sys(), &start_mask);
lv_refr_obj_and_children(lv_disp_get_layer_top(disp_refr), &start_mask);
lv_refr_obj_and_children(lv_disp_get_layer_sys(disp_refr), &start_mask);
/* In true double buffered mode flush only once when all areas were rendered.
* In normal mode flush after every area */
#if LV_VDB_TRUE_DOUBLE_BUFFERED == 0
/*Flush the content of the VDB*/
lv_vdb_flush();
#endif
if(lv_disp_is_true_double_buf(disp_refr) == false) {
lv_refr_vdb_flush();
}
}
#endif /*LV_VDB_SIZE == 0*/
/**
* Search the most top object which fully covers an area
* @param area_p pointer to an area
@@ -507,7 +421,7 @@ static void lv_refr_obj_and_children(lv_obj_t * top_p, const lv_area_t * mask_p)
/* Normally always will be a top_obj (at least the screen)
* but in special cases (e.g. if the screen has alpha) it won't.
* In this case use the screen directly */
if(top_p == NULL) top_p = lv_scr_act();
if(top_p == NULL) top_p = lv_disp_get_scr_act(disp_refr);
/*Refresh the top object and its children*/
lv_refr_obj(top_p, mask_p);
@@ -608,3 +522,33 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p)
}
}
/**
* Flush the content of the VDB
*/
static void lv_refr_vdb_flush(void)
{
lv_disp_buf_t * vdb = lv_disp_get_buf(lv_refr_get_disp_refreshing());
/*In double buffered mode wait until the other buffer is flushed before flushing the current one*/
if(vdb->buf1 && vdb->buf2) {
while(vdb->flushing);
}
vdb->flushing = 1;
/*Flush the rendered content to the display*/
lv_disp_t * disp = lv_refr_get_disp_refreshing();
if(disp->driver.flush_cb) disp->driver.flush_cb(&disp->driver, &vdb->area, vdb->buf_act);
if(vdb->buf1 && vdb->buf2) {
if(vdb->buf_act == vdb->buf1) vdb->buf_act = vdb->buf2;
else vdb->buf_act = vdb->buf1;
/*If the screen is transparent initialize it when the new VDB is selected*/
# if LV_COLOR_SCREEN_TRANSP
memset(vdb[vdb_active].buf, 0x00, LV_VDB_SIZE_IN_BYTES);
# endif /*LV_COLOR_SCREEN_TRANSP*/
}
}

View File

@@ -54,23 +54,11 @@ void lv_refr_init(void);
void lv_refr_now(void);
/**
* Invalidate an area
* @param area_p pointer to area which should be invalidated
* Invalidate an area on display to redraw it
* @param area_p pointer to area which should be invalidated (NULL: delete the invalidated areas)
* @param disp pointer to display where the area should be invalidated (NULL can be used if there is only one display)
*/
void lv_inv_area(const lv_area_t * area_p);
/**
* Set a function to call after every refresh to announce the refresh time and the number of refreshed pixels
* @param cb pointer to a callback function (void my_refr_cb(uint32_t time_ms, uint32_t px_num))
*/
void lv_refr_set_monitor_cb(void (*cb)(uint32_t, uint32_t));
/**
* Called when an area is invalidated to modify the coordinates of the area.
* Special display controllers may require special coordinate rounding
* @param cb pointer to the a function which will modify the area
*/
void lv_refr_set_round_cb(void(*cb)(lv_area_t*));
void lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p);
/**
* Get the number of areas in the buffer
@@ -83,6 +71,13 @@ uint16_t lv_refr_get_buf_size(void);
* @param num number of areas to delete
*/
void lv_refr_pop_from_buf(uint16_t num);
/**
* Get the display which is being refreshed
* @return the display being refreshed
*/
lv_disp_t * lv_refr_get_disp_refreshing(void);
/**********************
* STATIC FUNCTIONS
**********************/

View File

@@ -1,207 +0,0 @@
/**
* @file lv_vdb.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_vdb.h"
#if LV_VDB_SIZE != 0
#include "../lv_hal/lv_hal_disp.h"
#include "../lv_misc/lv_log.h"
#include <stddef.h>
/*********************
* DEFINES
*********************/
#ifndef LV_ATTRIBUTE_FLUSH_READY
#define LV_ATTRIBUTE_FLUSH_READY
#endif
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/*Simple VDB*/
#if LV_VDB_DOUBLE == 0
# if LV_VDB_ADR == 0
/*If the buffer address is not specified simply allocate it*/
static LV_ATTRIBUTE_MEM_ALIGN uint8_t vdb_buf[LV_VDB_SIZE_IN_BYTES];
static lv_vdb_t vdb = {.buf = (lv_color_t *)vdb_buf};
# else /*LV_VDB_ADR != 0*/
/*If the buffer address is specified use that address*/
static lv_vdb_t vdb = {.buf = (lv_color_t *)LV_VDB_ADR};
# endif
/*LV_VDB_DOUBLE != 0*/
#else
/*Double VDB*/
static uint8_t vdb_active = 0;
# if LV_VDB_ADR == 0
/*If the buffer address is not specified simply allocate it*/
static LV_ATTRIBUTE_MEM_ALIGN uint8_t vdb_buf1[LV_VDB_SIZE_IN_BYTES];
static LV_ATTRIBUTE_MEM_ALIGN uint8_t vdb_buf2[LV_VDB_SIZE_IN_BYTES];
static lv_vdb_t vdb[2] = {{.buf = (lv_color_t *) vdb_buf1}, {.buf = (lv_color_t *) vdb_buf2}};
# else /*LV_VDB_ADR != 0*/
/*If the buffer address is specified use that address*/
static lv_vdb_t vdb[2] = {{.buf = (lv_color_t *)LV_VDB_ADR}, {.buf = (lv_color_t *)LV_VDB2_ADR}};
# endif
#endif
static volatile bool vdb_flushing = false;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode
* @return pointer to a 'vdb' variable
*/
lv_vdb_t * lv_vdb_get(void)
{
#if LV_VDB_DOUBLE == 0
/* Wait until VDB is flushing.
* (Until this user calls of 'lv_flush_ready()' in the display drivers's flush function*/
while(vdb_flushing);
return &vdb;
#else
/*If already there is an active do nothing*/
return &vdb[vdb_active];
#endif
}
/**
* Flush the content of the VDB
*/
void lv_vdb_flush(void)
{
lv_vdb_t * vdb_act = lv_vdb_get();
if(!vdb_act) {
LV_LOG_WARN("Invalid VDB pointer");
return;
}
/*Don't start a new flush while the previous is not finished*/
#if LV_VDB_DOUBLE
while(vdb_flushing);
#endif /*LV_VDB_DOUBLE*/
vdb_flushing = true;
/*Flush the rendered content to the display*/
lv_disp_flush(vdb_act->area.x1, vdb_act->area.y1, vdb_act->area.x2, vdb_act->area.y2, vdb_act->buf);
#if LV_VDB_DOUBLE
/*Make the other VDB active. The content of the current will be kept until the next flush*/
vdb_active++;
vdb_active &= 0x1;
/*If the screen is transparent initialize it when the new VDB is selected*/
# if LV_COLOR_SCREEN_TRANSP
memset(vdb[vdb_active].buf, 0x00, LV_VDB_SIZE_IN_BYTES);
# endif /*LV_COLOR_SCREEN_TRANSP*/
#endif /*#if LV_VDB_DOUBLE*/
}
/**
* Set the address of VDB buffer(s) manually. To use this set `LV_VDB_ADR` (and `LV_VDB2_ADR`) to `LV_VDB_ADR_INV` in `lv_conf.h`.
* It should be called before `lv_init()`. The size of the buffer should be: `LV_VDB_SIZE_IN_BYTES`
* @param buf1 address of the VDB.
* @param buf2 address of the second buffer. `NULL` if `LV_VDB_DOUBLE 0`
*/
void lv_vdb_set_adr(void * buf1, void * buf2)
{
#if LV_VDB_DOUBLE == 0
(void) buf2; /*unused*/
vdb.buf = buf1;
#else
vdb[0].buf = buf1;
vdb[1].buf = buf2;
#endif
}
/**
* Call in the display driver's 'disp_flush' function when the flushing is finished
*/
LV_ATTRIBUTE_FLUSH_READY void lv_flush_ready(void)
{
vdb_flushing = false;
/*If the screen is transparent initialize it when the flushing is ready*/
#if LV_VDB_DOUBLE == 0 && LV_COLOR_SCREEN_TRANSP
memset(vdb_buf, 0x00, LV_VDB_SIZE_IN_BYTES);
#endif
}
/**
* Get currently active VDB, where the drawing happens. Used with `LV_VDB_DOUBLE 1`
* @return pointer to the active VDB. If `LV_VDB_DOUBLE 0` give the single VDB
*/
lv_vdb_t * lv_vdb_get_active(void)
{
#if LV_VDB_DOUBLE == 0
return &vdb;
#else
return &vdb[vdb_active];
#endif
}
/**
* Get currently inactive VDB, which is being displayed or being flushed. Used with `LV_VDB_DOUBLE 1`
* @return pointer to the inactive VDB. If `LV_VDB_DOUBLE 0` give the single VDB
*/
lv_vdb_t * lv_vdb_get_inactive(void)
{
#if LV_VDB_DOUBLE == 0
return &vdb;
#else
return &vdb[(vdb_active + 1) & 0x1];
#endif
}
/**
* Whether the flushing is in progress or not
* @return true: flushing is in progress; false: flushing ready
*/
bool lv_vdb_is_flushing(void)
{
return vdb_flushing;
}
/**********************
* STATIC FUNCTIONS
**********************/
#else
/**
* Just for compatibility
*/
void lv_flush_ready(void)
{
/*Do nothing. It is used only for VDB*/
}
#endif

View File

@@ -1,119 +0,0 @@
/**
* @file lv_vdb.h
*
*/
#ifndef LV_VDB_H
#define LV_VDB_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#ifdef LV_CONF_INCLUDE_SIMPLE
#include "lv_conf.h"
#else
#include "../../lv_conf.h"
#endif
#if LV_VDB_SIZE != 0
#include "../lv_misc/lv_color.h"
#include "../lv_misc/lv_area.h"
/*********************
* DEFINES
*********************/
/*Can be used in `lv_conf.h` the set an invalid address for the VDB. It should be replaced later by a valid address using `lv_vdb_set_adr()`*/
#define LV_VDB_ADR_INV 8 /*8 is still too small to be valid but it's aligned on 64 bit machines as well*/
#ifndef LV_VDB_PX_BPP
#define LV_VDB_PX_BPP LV_COLOR_SIZE /* Default is LV_COLOR_SIZE */
#endif
#if LV_VDB_TRUE_DOUBLE_BUFFERED && (LV_VDB_SIZE != LV_HOR_RES * LV_VER_RES || LV_VDB_DOUBLE == 0)
#error "With LV_VDB_TRUE_DOUBLE_BUFFERED: (LV_VDB_SIZE = LV_HOR_RES * LV_VER_RES and LV_VDB_DOUBLE = 1 is required"
#endif
/* The size of VDB in bytes.
* (LV_VDB_SIZE * LV_VDB_PX_BPP) >> 3): just divide by 8 to convert bits to bytes
* (((LV_VDB_SIZE * LV_VDB_PX_BPP) & 0x7) ? 1 : 0): add an extra byte to round up.
* E.g. if LV_VDB_SIZE = 10 and LV_VDB_PX_BPP = 1 -> 10 bits -> 2 bytes*/
#define LV_VDB_SIZE_IN_BYTES ((LV_VDB_SIZE * LV_VDB_PX_BPP) >> 3) + (((LV_VDB_SIZE * LV_VDB_PX_BPP) & 0x7) ? 1 : 0)
/**********************
* TYPEDEFS
**********************/
typedef struct
{
lv_area_t area;
lv_color_t *buf;
} lv_vdb_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode
* @return pointer to a 'vdb' variable
*/
lv_vdb_t * lv_vdb_get(void);
/**
* Flush the content of the vdb
*/
void lv_vdb_flush(void);
/**
* Set the address of VDB buffer(s) manually. To use this set `LV_VDB_ADR` (and `LV_VDB2_ADR`) to `LV_VDB_ADR_INV` in `lv_conf.h`.
* It should be called before `lv_init()`. The size of the buffer should be: `LV_VDB_SIZE_IN_BYTES`
* @param buf1 address of the VDB.
* @param buf2 address of the second buffer. `NULL` if `LV_VDB_DOUBLE 0`
*/
void lv_vdb_set_adr(void * buf1, void * buf2);
/**
* Call in the display driver's 'disp_flush' function when the flushing is finished
*/
void lv_flush_ready(void);
/**
* Get currently active VDB, where the drawing happens. Used with `LV_VDB_DOUBLE 1`
* @return pointer to the active VDB. If `LV_VDB_DOUBLE 0` give the single VDB
*/
lv_vdb_t * lv_vdb_get_active(void);
/**
* Get currently inactive VDB, which is being displayed or being flushed. Used with `LV_VDB_DOUBLE 1`
* @return pointer to the inactive VDB. If `LV_VDB_DOUBLE 0` give the single VDB
*/
lv_vdb_t * lv_vdb_get_inactive(void);
/**
* Whether the flushing is in progress or not
* @return true: flushing is in progress; false: flushing ready
*/
bool lv_vdb_is_flushing(void);
/**********************
* MACROS
**********************/
#else /*LV_VDB_SIZE != 0*/
/*Just for compatibility*/
void lv_flush_ready(void);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_VDB_H*/