BigW Consortium Gitlab

Commit d9147ae2 by Kiss-Vamosi Gabor

LV_VDB_DOUBLE: Add double virtual display buffer. Needs test on real hardware

parent d1837d26
...@@ -17,18 +17,19 @@ ...@@ -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
/* Buffered rendering: >= LV_DOWNSCALE * LV_HOR_RES or 0 to disable buffering*/
#define LV_VDB_SIZE (LV_HOR_RES * 30)
/* Enable antialaiassing
* If enabled everything will half-sized * If enabled everything will half-sized
* Use LV_DOWNSCALE to compensate * Use LV_DOWNSCALE to compensate he down scaling effect of anti-aliasing*/
* the down scaling effect of antialiassing*/
#define LV_ANTIALIAS 1 #define LV_ANTIALIAS 1
#define LV_DOWNSCALE (1 << LV_ANTIALIAS) /*Set the downscaling value*/
/*Set the downscaling value*/ /* Buffered rendering: >= LV_DOWNSCALE * LV_HOR_RES or 0 to disable buffering*/
#define LV_DOWNSCALE (1 << LV_ANTIALIAS) #define LV_VDB_SIZE (LV_HOR_RES * LV_VER_RES / 20)
#if LV_VDB_SIZE
/* Double virtual buffering
* One for rendering another to transfer former rendered image to frame buffer in the background*/
#define LV_VDB_DOUBLE 1
#endif
#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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 @@ ...@@ -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; ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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); ...@@ -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
**********************/ **********************/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment