fix conflicts
This commit is contained in:
@@ -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
117
lv_core/lv_disp.c
Normal 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
114
lv_core/lv_disp.h
Normal 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*/
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
142
lv_core/lv_obj.c
142
lv_core/lv_obj.c
@@ -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
|
||||
*--------------------*/
|
||||
|
||||
@@ -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
|
||||
*--------------------*/
|
||||
|
||||
@@ -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*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
**********************/
|
||||
|
||||
207
lv_core/lv_vdb.c
207
lv_core/lv_vdb.c
@@ -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
|
||||
119
lv_core/lv_vdb.h
119
lv_core/lv_vdb.h
@@ -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*/
|
||||
Reference in New Issue
Block a user