From d9147ae21b6510749a1759d976ca7b3bb4319b92 Mon Sep 17 00:00:00 2001 From: Kiss-Vamosi Gabor Date: Fri, 4 Aug 2017 19:09:29 +0200 Subject: [PATCH 1/2] LV_VDB_DOUBLE: Add double virtual display buffer. Needs test on real hardware --- lv_conf_templ.h | 21 +++++++------ lv_obj/lv_refr.c | 30 +++++++++--------- lv_obj/lv_vdb.c | 79 ++++++++++++++++++++++++++++++++++++++++-------- lv_obj/lv_vdb.h | 13 +++++--- 4 files changed, 102 insertions(+), 41 deletions(-) diff --git a/lv_conf_templ.h b/lv_conf_templ.h index fc87d5a21..3ddc20494 100644 --- a/lv_conf_templ.h +++ b/lv_conf_templ.h @@ -17,18 +17,19 @@ #define LV_HOR_RES (320 * LV_DOWNSCALE) #define LV_VER_RES (240 * 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*/ -#define LV_VDB_SIZE (LV_HOR_RES * 30) - -/* Enable antialaiassing - * If enabled everything will half-sized - * Use LV_DOWNSCALE to compensate - * the down scaling effect of antialiassing*/ -#define LV_ANTIALIAS 1 - -/*Set the downscaling value*/ -#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_INV_FIFO_SIZE 32 /*The average number of objects on a screen */ diff --git a/lv_obj/lv_refr.c b/lv_obj/lv_refr.c index a8fac13ee..9216700be 100644 --- a/lv_obj/lv_refr.c +++ b/lv_obj/lv_refr.c @@ -70,7 +70,6 @@ void lv_refr_init(void) ptask_t* task; task = ptask_create(lv_refr_task, LV_REFR_PERIOD, PTASK_PRIO_MID, NULL); 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)) * 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 with opacity areas) + * (more pixels are drawn because of overlapping objects) */ 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) { - 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*/ - 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); /*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); #endif - /*Refresh all rows*/ - cord_t row = area_p->y1; - + /*Always use the full row*/ + cord_t row; + cord_t row_last = 0; 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*/ + 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; - + row_last = row + max_row - 1; lv_refr_area_part_vdb(area_p); } /*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*/ + vdb_p->area.x1 = area_p->x1; + vdb_p->area.x2 = area_p->x2; vdb_p->area.y1 = row; vdb_p->area.y2 = area_p->y2; diff --git a/lv_obj/lv_vdb.c b/lv_obj/lv_vdb.c index e2679b0c4..7fd4ac760 100644 --- a/lv_obj/lv_vdb.c +++ b/lv_obj/lv_vdb.c @@ -20,7 +20,13 @@ /********************** * 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 **********************/ @@ -28,7 +34,12 @@ /********************** * STATIC VARIABLES **********************/ +#if LV_VDB_DOUBLE == 0 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 @@ -39,21 +50,53 @@ static lv_vdb_t vdb; **********************/ /** - * Get the vdb variable - * @return pointer to the vdb variable + * Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode + * @return pointer to the 'vdb' variable */ lv_vdb_t * lv_vdb_get(void) { +#if LV_VDB_DOUBLE == 0 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) { + 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 - 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 /* Get the average of 2x2 pixels and put the result back to the VDB * The reading goes much faster then the write back @@ -68,12 +111,12 @@ void lv_vdb_flush(void) * */ cord_t x; cord_t y; - cord_t w = area_get_width(&vdb.area); - color_t * in1_buf = vdb.buf; /*Pointer to the first row*/ - color_t * in2_buf = vdb.buf + w; /*Pointer to the second row*/ - color_t * out_buf = vdb.buf; /*Store the result here*/ - for(y = vdb.area.y1; y < vdb.area.y2; y += 2) { - for(x = vdb.area.x1; x < vdb.area.x2; x += 2) { + cord_t w = area_get_width(&vdb_act->area); + color_t * in1_buf = vdb_act->buf; /*Pointer to the first row*/ + color_t * in2_buf = vdb_act->buf + w; /*Pointer to the second row*/ + color_t * out_buf = vdb_act->buf; /*Store the result here*/ + for(y = vdb_act->area.y1; y < vdb_act->area.y2; y += 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(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 * 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 } diff --git a/lv_obj/lv_vdb.h b/lv_obj/lv_vdb.h index 181cca71c..54a0facf6 100644 --- a/lv_obj/lv_vdb.h +++ b/lv_obj/lv_vdb.h @@ -34,15 +34,13 @@ typedef struct color_t buf[LV_VDB_SIZE]; }lv_vdb_t; - - /********************** * GLOBAL PROTOTYPES **********************/ /** - * Get the vdb variable - * @return pointer to the vdb variable + * Get the 'vdb' variable or allocate one in LV_VDB_DOUBLE mode + * @return pointer to the 'vdb' variable */ lv_vdb_t * lv_vdb_get(void); @@ -51,6 +49,13 @@ lv_vdb_t * lv_vdb_get(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 **********************/ From 09f8e25fdd49b7c9a970cf3298469c462a1c5e42 Mon Sep 17 00:00:00 2001 From: Gabor Date: Tue, 8 Aug 2017 09:47:17 +0200 Subject: [PATCH 2/2] LV_VDB_DOUBLE: tested on STM32F429 Discovery --- lv_appx/lv_app_benchmark.c | 8 ++++++++ lv_conf_templ.h | 2 +- lv_draw/lv_draw_vbasic.c | 4 +--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lv_appx/lv_app_benchmark.c b/lv_appx/lv_app_benchmark.c index 242c8ebb0..6873fa949 100644 --- a/lv_appx/lv_app_benchmark.c +++ b/lv_appx/lv_app_benchmark.c @@ -146,6 +146,14 @@ const lv_app_dsc_t * lv_app_benchmark_init(void) static void my_app_run(lv_app_inst_t * app, void * conf) { /*Initialize the application*/ + my_app_data_t * ad = app->app_data; + ad->opa = 0; + ad->recolor = 0; + ad->shdw = 0; + ad->upscalse = 0; + ad->wp = 0; + + } /** diff --git a/lv_conf_templ.h b/lv_conf_templ.h index 3ddc20494..86d23f61d 100644 --- a/lv_conf_templ.h +++ b/lv_conf_templ.h @@ -28,7 +28,7 @@ #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 +#define LV_VDB_DOUBLE 0 #endif #define LV_REFR_PERIOD 40 /*Screen refresh period in milliseconds*/ diff --git a/lv_draw/lv_draw_vbasic.c b/lv_draw/lv_draw_vbasic.c index 920003441..51760f75a 100644 --- a/lv_draw/lv_draw_vbasic.c +++ b/lv_draw/lv_draw_vbasic.c @@ -123,8 +123,7 @@ void lv_vfill(const area_t * cords_p, const area_t * mask_p, cord_t map_width = area_get_width(&vdb_rel_a); if(color_map[0].full != color.full || last_width != map_width) { uint16_t i; - - for(i =0; i < map_width; i++) { + for(i = 0; i < map_width; i++) { color_map[i].full = color.full; } @@ -133,7 +132,6 @@ void lv_vfill(const area_t * cords_p, const area_t * mask_p, cord_t row; for(row = vdb_rel_a.y1;row <= vdb_rel_a.y2; row++) { disp_color_cpy(&vdb_buf_tmp[vdb_rel_a.x1], color_map, map_width, opa); - vdb_buf_tmp += vdb_width; } #endif