mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
LV_VDB_DOUBLE: Add double virtual display buffer. Needs test on real hardware
This commit is contained in:
parent
d1837d2684
commit
d9147ae21b
@ -17,18 +17,19 @@
|
|||||||
#define LV_HOR_RES (320 * LV_DOWNSCALE)
|
#define LV_HOR_RES (320 * LV_DOWNSCALE)
|
||||||
#define LV_VER_RES (240 * LV_DOWNSCALE)
|
#define LV_VER_RES (240 * LV_DOWNSCALE)
|
||||||
#define LV_DPI (80 * LV_DOWNSCALE)
|
#define LV_DPI (80 * LV_DOWNSCALE)
|
||||||
|
/* Enable anti-aliasing
|
||||||
|
* If enabled everything will half-sized
|
||||||
|
* Use LV_DOWNSCALE to compensate he down scaling effect of anti-aliasing*/
|
||||||
|
#define LV_ANTIALIAS 1
|
||||||
|
#define LV_DOWNSCALE (1 << LV_ANTIALIAS) /*Set the downscaling value*/
|
||||||
|
|
||||||
/* Buffered rendering: >= LV_DOWNSCALE * LV_HOR_RES or 0 to disable buffering*/
|
/* Buffered rendering: >= LV_DOWNSCALE * LV_HOR_RES or 0 to disable buffering*/
|
||||||
#define LV_VDB_SIZE (LV_HOR_RES * 30)
|
#define LV_VDB_SIZE (LV_HOR_RES * LV_VER_RES / 20)
|
||||||
|
#if LV_VDB_SIZE
|
||||||
/* Enable antialaiassing
|
/* Double virtual buffering
|
||||||
* If enabled everything will half-sized
|
* One for rendering another to transfer former rendered image to frame buffer in the background*/
|
||||||
* Use LV_DOWNSCALE to compensate
|
#define LV_VDB_DOUBLE 1
|
||||||
* the down scaling effect of antialiassing*/
|
#endif
|
||||||
#define LV_ANTIALIAS 1
|
|
||||||
|
|
||||||
/*Set the downscaling value*/
|
|
||||||
#define LV_DOWNSCALE (1 << LV_ANTIALIAS)
|
|
||||||
|
|
||||||
#define LV_REFR_PERIOD 40 /*Screen refresh period in milliseconds*/
|
#define LV_REFR_PERIOD 40 /*Screen refresh period in milliseconds*/
|
||||||
#define LV_INV_FIFO_SIZE 32 /*The average number of objects on a screen */
|
#define LV_INV_FIFO_SIZE 32 /*The average number of objects on a screen */
|
||||||
|
@ -70,7 +70,6 @@ void lv_refr_init(void)
|
|||||||
ptask_t* task;
|
ptask_t* task;
|
||||||
task = ptask_create(lv_refr_task, LV_REFR_PERIOD, PTASK_PRIO_MID, NULL);
|
task = ptask_create(lv_refr_task, LV_REFR_PERIOD, PTASK_PRIO_MID, NULL);
|
||||||
dm_assert(task);
|
dm_assert(task);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,7 +129,7 @@ void lv_inv_area(const area_t * area_p)
|
|||||||
* @param cb pointer to a callback function (void my_refr_cb(uint32_t time_ms, uint32_t px_num))
|
* @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]
|
* time_ms: refresh time in [ms]
|
||||||
* px_num: not the drawn pixels but the number of affected pixels of the screen
|
* px_num: not the drawn pixels but the number of affected pixels of the screen
|
||||||
* (more pixels are drawn with opacity areas)
|
* (more pixels are drawn because of overlapping objects)
|
||||||
*/
|
*/
|
||||||
void lv_refr_set_monitor_cb(void (*cb)(uint32_t, uint32_t))
|
void lv_refr_set_monitor_cb(void (*cb)(uint32_t, uint32_t))
|
||||||
{
|
{
|
||||||
@ -257,15 +256,8 @@ static void lv_refr_area_no_vdb(const area_t * area_p)
|
|||||||
*/
|
*/
|
||||||
static void lv_refr_area_with_vdb(const area_t * area_p)
|
static void lv_refr_area_with_vdb(const area_t * area_p)
|
||||||
{
|
{
|
||||||
lv_vdb_t * vdb_p = lv_vdb_get();
|
|
||||||
|
|
||||||
/*Always use the full row*/
|
|
||||||
vdb_p->area.x1 = area_p->x1;
|
|
||||||
vdb_p->area.y1 = area_p->y1;
|
|
||||||
vdb_p->area.x2 = area_p->x2;
|
|
||||||
|
|
||||||
/*Calculate the max row num*/
|
/*Calculate the max row num*/
|
||||||
uint32_t max_row = (uint32_t) LV_VDB_SIZE / (vdb_p->area.x2 - vdb_p->area.x1 + 1);
|
uint32_t max_row = (uint32_t) LV_VDB_SIZE / (area_get_width(area_p));
|
||||||
if(max_row > area_get_height(area_p)) max_row = area_get_height(area_p);
|
if(max_row > area_get_height(area_p)) max_row = area_get_height(area_p);
|
||||||
|
|
||||||
/*Round the row number with downscale*/
|
/*Round the row number with downscale*/
|
||||||
@ -273,20 +265,28 @@ static void lv_refr_area_with_vdb(const area_t * area_p)
|
|||||||
max_row &= (~0x1);
|
max_row &= (~0x1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*Refresh all rows*/
|
/*Always use the full row*/
|
||||||
cord_t row = area_p->y1;
|
cord_t row;
|
||||||
|
cord_t row_last = 0;
|
||||||
for(row = area_p->y1; row + max_row - 1 <= area_p->y2; row += max_row) {
|
for(row = area_p->y1; row + max_row - 1 <= area_p->y2; row += max_row) {
|
||||||
|
lv_vdb_t * vdb_p = lv_vdb_get();
|
||||||
|
|
||||||
/*Calc. the next y coordinates of VDB*/
|
/*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.y1 = row;
|
||||||
vdb_p->area.y2 = row + max_row - 1;
|
vdb_p->area.y2 = row + max_row - 1;
|
||||||
|
row_last = row + max_row - 1;
|
||||||
lv_refr_area_part_vdb(area_p);
|
lv_refr_area_part_vdb(area_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*If the last y coordinates are not handled yet ...*/
|
/*If the last y coordinates are not handled yet ...*/
|
||||||
if(area_p->y2 != vdb_p->area.y2) {
|
if(area_p->y2 != row_last) {
|
||||||
|
lv_vdb_t * vdb_p = lv_vdb_get();
|
||||||
|
|
||||||
/*Calc. the next y coordinates of VDB*/
|
/*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.y1 = row;
|
||||||
vdb_p->area.y2 = area_p->y2;
|
vdb_p->area.y2 = area_p->y2;
|
||||||
|
|
||||||
|
@ -20,7 +20,13 @@
|
|||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
|
#if LV_VDB_DOUBLE != 0
|
||||||
|
typedef enum {
|
||||||
|
LV_VDB_STATE_FREE = 0,
|
||||||
|
LV_VDB_STATE_ACTIVE,
|
||||||
|
LV_VDB_STATE_FLUSH,
|
||||||
|
} lv_vdb_state_t;
|
||||||
|
#endif
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC PROTOTYPES
|
* STATIC PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
@ -28,7 +34,12 @@
|
|||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
**********************/
|
**********************/
|
||||||
|
#if LV_VDB_DOUBLE == 0
|
||||||
static lv_vdb_t vdb;
|
static lv_vdb_t vdb;
|
||||||
|
#else
|
||||||
|
static lv_vdb_t vdb[2];
|
||||||
|
static volatile lv_vdb_state_t vdb_state[2] = {LV_VDB_STATE_FREE, LV_VDB_STATE_FREE};
|
||||||
|
#endif
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
@ -39,21 +50,53 @@ static lv_vdb_t vdb;
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the vdb variable
|
* Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode
|
||||||
* @return pointer to the vdb variable
|
* @return pointer to the 'vdb' variable
|
||||||
*/
|
*/
|
||||||
lv_vdb_t * lv_vdb_get(void)
|
lv_vdb_t * lv_vdb_get(void)
|
||||||
{
|
{
|
||||||
|
#if LV_VDB_DOUBLE == 0
|
||||||
return &vdb;
|
return &vdb;
|
||||||
|
#else
|
||||||
|
/*If already there is an active do nothing*/
|
||||||
|
if(vdb_state[0] == LV_VDB_STATE_ACTIVE) return &vdb[0];
|
||||||
|
if(vdb_state[1] == LV_VDB_STATE_ACTIVE) return &vdb[1];
|
||||||
|
|
||||||
|
/*Try to allocate a free VDB*/
|
||||||
|
if(vdb_state[0] == LV_VDB_STATE_FREE) {
|
||||||
|
vdb_state[0] = LV_VDB_STATE_ACTIVE;
|
||||||
|
return &vdb[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(vdb_state[1] == LV_VDB_STATE_FREE) {
|
||||||
|
vdb_state[1] = LV_VDB_STATE_ACTIVE;
|
||||||
|
return &vdb[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; /*There wasn't free VDB (never happen)*/
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush the content of the vdb
|
* Flush the content of the VDB
|
||||||
*/
|
*/
|
||||||
void lv_vdb_flush(void)
|
void lv_vdb_flush(void)
|
||||||
{
|
{
|
||||||
|
lv_vdb_t * vdb_act = lv_vdb_get();
|
||||||
|
if(vdb_act == NULL) return;
|
||||||
|
|
||||||
|
#if LV_VDB_DOUBLE != 0
|
||||||
|
/* Wait the pending flush before starting this one
|
||||||
|
* (Don't forget: 'lv_vdb_flush_ready' has to be called when flushing is ready)*/
|
||||||
|
while(vdb_state[0] == LV_VDB_STATE_FLUSH || vdb_state[1] == LV_VDB_STATE_FLUSH);
|
||||||
|
|
||||||
|
/*Turn the active VDB to flushing*/
|
||||||
|
if(vdb_state[0] == LV_VDB_STATE_ACTIVE) vdb_state[0] = LV_VDB_STATE_FLUSH;
|
||||||
|
if(vdb_state[1] == LV_VDB_STATE_ACTIVE) vdb_state[1] = LV_VDB_STATE_FLUSH;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LV_ANTIALIAS == 0
|
#if LV_ANTIALIAS == 0
|
||||||
disp_map(vdb.area.x1, vdb.area.y1, vdb.area.x2, vdb.area.y2, vdb.buf);
|
disp_map(vdb_act->area.x1, vdb_act->area.y1, vdb_act->area.x2, vdb_act->area.y2, vdb_act->buf);
|
||||||
#else
|
#else
|
||||||
/* Get the average of 2x2 pixels and put the result back to the VDB
|
/* Get the average of 2x2 pixels and put the result back to the VDB
|
||||||
* The reading goes much faster then the write back
|
* The reading goes much faster then the write back
|
||||||
@ -68,12 +111,12 @@ void lv_vdb_flush(void)
|
|||||||
* */
|
* */
|
||||||
cord_t x;
|
cord_t x;
|
||||||
cord_t y;
|
cord_t y;
|
||||||
cord_t w = area_get_width(&vdb.area);
|
cord_t w = area_get_width(&vdb_act->area);
|
||||||
color_t * in1_buf = vdb.buf; /*Pointer to the first row*/
|
color_t * in1_buf = vdb_act->buf; /*Pointer to the first row*/
|
||||||
color_t * in2_buf = vdb.buf + w; /*Pointer to the second row*/
|
color_t * in2_buf = vdb_act->buf + w; /*Pointer to the second row*/
|
||||||
color_t * out_buf = vdb.buf; /*Store the result here*/
|
color_t * out_buf = vdb_act->buf; /*Store the result here*/
|
||||||
for(y = vdb.area.y1; y < vdb.area.y2; y += 2) {
|
for(y = vdb_act->area.y1; y < vdb_act->area.y2; y += 2) {
|
||||||
for(x = vdb.area.x1; x < vdb.area.x2; x += 2) {
|
for(x = vdb_act->area.x1; x < vdb_act->area.x2; x += 2) {
|
||||||
|
|
||||||
/*If the pixels are the same do not calculate the average */
|
/*If the pixels are the same do not calculate the average */
|
||||||
if(in1_buf->full == (in1_buf + 1)->full &&
|
if(in1_buf->full == (in1_buf + 1)->full &&
|
||||||
@ -103,7 +146,19 @@ void lv_vdb_flush(void)
|
|||||||
|
|
||||||
/* Now the full the VDB is filtered and the result is stored in the first quarter of it
|
/* Now the full the VDB is filtered and the result is stored in the first quarter of it
|
||||||
* Write out the filtered map to the display*/
|
* Write out the filtered map to the display*/
|
||||||
disp_map(vdb.area.x1 >> 1, vdb.area.y1 >> 1, vdb.area.x2 >> 1, vdb.area.y2 >> 1, vdb.buf);
|
disp_map(vdb_act->area.x1 >> 1, vdb_act->area.y1 >> 1, vdb_act->area.x2 >> 1, vdb_act->area.y2 >> 1, vdb_act->buf);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In 'LV_VDB_DOUBLE' mode has to be called when the 'disp_map'
|
||||||
|
* is ready with copying the map to a frame buffer.
|
||||||
|
*/
|
||||||
|
void lv_vdb_flush_ready(void)
|
||||||
|
{
|
||||||
|
#if LV_VDB_DOUBLE != 0
|
||||||
|
if(vdb_state[0] == LV_VDB_STATE_FLUSH) vdb_state[0] = LV_VDB_STATE_FREE;
|
||||||
|
if(vdb_state[1] == LV_VDB_STATE_FLUSH) vdb_state[1] = LV_VDB_STATE_FREE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,15 +34,13 @@ typedef struct
|
|||||||
color_t buf[LV_VDB_SIZE];
|
color_t buf[LV_VDB_SIZE];
|
||||||
}lv_vdb_t;
|
}lv_vdb_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* GLOBAL PROTOTYPES
|
* GLOBAL PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the vdb variable
|
* Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode
|
||||||
* @return pointer to the vdb variable
|
* @return pointer to the 'vdb' variable
|
||||||
*/
|
*/
|
||||||
lv_vdb_t * lv_vdb_get(void);
|
lv_vdb_t * lv_vdb_get(void);
|
||||||
|
|
||||||
@ -51,6 +49,13 @@ lv_vdb_t * lv_vdb_get(void);
|
|||||||
*/
|
*/
|
||||||
void lv_vdb_flush(void);
|
void lv_vdb_flush(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In 'LV_VDB_DOUBLE' mode has to be called when 'disp_map()'
|
||||||
|
* is ready with copying the map to a frame buffer.
|
||||||
|
*/
|
||||||
|
void lv_vdb_flush_ready(void);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user