Description
When i update one object’s value in a screen (eg a label’s text), the screen contents sent to the disp_drv.flush_cb do not contain the correct values (i.e, unchanged from before) for all objects in the rest of the screen. Now, i understand that lvgl is only supposed to send the changed part inside the callback, but in my case, i am using two buffers, with sizes equal to the display&screen size. In this case, the contents of the whole screen size are received (i verified this by putting break point in the “flush_cb” and looking at the values of area -> x1, y1, x2, y2 which correspond to 0,0 and height, width of full display). Since the received pixel data (inside the lv_color_t * color_p object in the callback) does not correctly reflect the existing states of the other objects in the screen, i am left with just the updated part being displayed on the screen.
Note that i am using transparency, and using lvgl as a OSD over live video.
What MCU/Processor/Board and compiler are you using?
Xilinx Zynq Arm 9, using Xilinx SDK
What do you experience?
As mentioned above, when i update one object’s value on the screen, i expect that to update, but everything else on the screen to remain the same. However, the flush_cb sends data for the FULL screen, and puts everything else to zero, apart from what was updated recently. This is unexptedted. I have been trying to findo something wrong on my side for several days but i cannot find it. I have read through the relevant documentation few times. I suspect this might have to do with some setting perhaps in lv_conf.h, but i cannot find it. If that is not the case, then it has to be a bug. However, i do not see the same issue on the simulator. I am attaching my flush_cb code below as well…initially i susptected it but i can’t see how that can be wrong.
What do you expect?
Correct values for the full screen inside the callback.
Code to reproduce
Here’s my display driver callback for reference. I am attaching this there as that is usually considered the suspect from other posts i read.
/**** Display Driver Callback *****/
void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
int32_t x, y;
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
uint pxCnt=0;
for(y = area->y1; y <= area->y2; y++)
{
for(x = area->x1; x <= area->x2; x++)
{
//put_px(x, y, *color_p);
memcpy(&(vdmaFrameBuffer[pxCnt]), color_p, sizeof(lv_color_t));
pxCnt += sizeof(lv_color_t);
color_p++;
}
}
/*
* Flush the framebuffer memory range to ensure changes are written to the
* actual memory, and therefore accessible by the VDMA.
*/
Xil_DCacheFlushRange((unsigned int) vdmaFrameBuffer, 1024*768*4);
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(disp_drv);
}
I have verified using breakpoints that everytime, inside the callback, the values of x1 = y1 =0 and x2 and y2 correspond to the full screen width (1024) and height (768) respectively. That is, the data for the full screen is sent, not just the part to be updated.
Following are my settings in lv_conf.h (The ones i changed…rest everything is at default):
/* Maximal horizontal and vertical resolution to support by the library.*/
#define LV_HOR_RES_MAX (1024)
#define LV_VER_RES_MAX (768)
/* Color depth:
#define LV_COLOR_DEPTH 32
/* Swap the 2 bytes of RGB565 color.
* Useful if the display has a 8 bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP 0
#define LV_COLOR_SCREEN_TRANSP 1
Following is how i initialize my display driver in lvgl_hal_init()
/*-----------------------------
* Create a buffer for drawing
*----------------------------*/
// See: https://docs.lvgl.io/v7/en/html/porting/display.html
/*A static or global variable to store the buffers*/
static lv_disp_buf_t disp_buf;
/*Static or global buffer(s). The second buffer is optional*/
static lv_color_t buf_1[LV_HOR_RES_MAX * LV_VER_RES_MAX];
static lv_color_t buf_2[LV_HOR_RES_MAX * LV_VER_RES_MAX];
/*Initialise `disp_buf` with the buffer(s) */
lv_disp_buf_init(&disp_buf, buf_1, buf_2, LV_HOR_RES_MAX * LV_VER_RES_MAX);
/*-----------------------------------
* Register the display in LVGL
*----------------------------------*/
//lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ // Moved to .h file
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
/*Set up the functions to access to your display*/
/*Set the resolution of the display*/
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
/*Used to copy the buffer's content to the display*/
disp_drv.flush_cb = my_flush_cb;
/*Set a display buffer*/
disp_drv.buffer = &disp_buf;
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
Screenshot and/or video
Following is how it is supposed to look (In this case, i am able to show this by manually re-loading the screen every time after changing any value on screen (using lv_disp_load_scr(screen)):
Following is how it actually looks:
Note that as the focus changes from one object in group to next, only those objects remain on screen and rest all disappears.
(p.s Pls ignore the noisy pink background…i do not have live video source connected in the background and it’s just “playing” un-initialized memory buffer in the background.)