Issues with lv_obj_invalidate_area()

Description

When displaying some objects with LVGL, LVGL display only a part of the objects. For example, if i draw a rectangle on the screen, LVGL will display only a part of this rectangle.

If I want to display all this rectangle, I have to display the rectangle twice times.

What MCU/Processor/Board and compiler are you using?

NRF52840

What do you experience?

I was working with the version 7.3.0 and there were no problems. Then I update my version of LVGL, and the problem I mentionned appear.

To understand the origin of this bug, I search the last commit where the code was working for me.
This commit is : 71e5618380fecc259bb96d214014768ebbbd895a. (old version)
From the commit : d0cc9283e760a7d7db35ba792009749adf762486 the bug appear (new version). So I checked the modification bewteen the 2 commits.

I saw you changed the method lv_obj_invalide_area() bewteen the 2 commits. I put here the 2 code versions old one and new one (I remove what is useless in my explanation).

The new version code :

void  lv_obj_invalidate_area(const  lv_obj_t * obj, const  lv_area_t * area)
{
	bool  visible = lv_obj_area_is_visible(obj, &area_tmp);
	if(visible) _lv_inv_area(lv_obj_get_disp(obj), &area_tmp);
}
bool  lv_obj_area_is_visible(const  lv_obj_t * obj, lv_area_t * area)
{
	if(lv_obj_get_hidden(obj)) return  false;
	/*Invalidate the object only if it belongs to the curent or previous'*/
	if(toto) 
	{
		//do some stuff and return false if needed
	}
	return  true;
}

The old version code :

void  lv_obj_invalidate_area(const  lv_obj_t * obj, const  lv_area_t * area)
{	/*Invalidate the object only if it belongs to the curent or previous'*/
	if(toto) 
	{
		//do some stuff and return false if needed
		if(is_common) _lv_inv_area(disp, &area_trunc);
	}
}

So basically the 2 code version do the same stuff, but there is one difference. If we look at the moment were LVGL invalidate an area :

  • In the old version : Inside the conditional block
  • In the new version : Outside the conditional block

This mean that in the new version, you will invalidate the area if toto = false, but in the old version, you will not invalidate the area if toto = false.

I try to change the new code version as follow :

void  lv_obj_invalidate_area(const  lv_obj_t * obj, const  lv_area_t * area)
{	/*Invalidate the object only if it belongs to the curent or previous'*/
   if(toto) 
   {
   	//do some stuff and return false if needed
   	return true; 
   }
   return false; 
}

This is working great for me and that match exactly the old LVGL version behavior.

I don’t know if there is a purpose between this 2 different behavior, but this difference cause a bug on my software.

What do you expect?

I except that this issues is fixed in the new realease of LVGL.

Code to reproduce

There is no code to reproduce.

Screenshot and/or video

Hi,

Can you send a minimal code to reproduce the issue? I wonder how could an issue in such a fundamental function remain hidden for months.

Hi,

Thanks for your answer.

This code draw a white or black rectangle.

void  draw_rectangle(bool  isWhite)
{
	//create a new screen
	screen = lv_obj_create(NULL, NULL);
	//create a new object on the screen
	lv_obj_t * rect = lv_obj_create(screen, NULL);
	
	//set style
	if(isWhite)
	{
		lv_obj_set_style_local_border_color(rect,LV_OBJ_PART_MAIN,LV_STATE_DEFAULT,LV_COLOR_WHITE);
		lv_obj_set_style_local_bg_color(rect, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
	}
	else
	{
		lv_obj_set_style_local_border_color(rect, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
		lv_obj_set_style_local_bg_color(rect, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
	}
	lv_obj_set_style_local_radius(rect, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 0);
	lv_obj_set_style_local_bg_opa(rect, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_100);

	//rectangle pos(0,0) cover all the screen
	lv_obj_set_pos(rect, 0, 0);
	lv_obj_set_size(rect, LV_HOR_RES_MAX, LV_VER_RES_MAX);
	 
	//display the new screen
	lv_obj_t *old_screen = lv_scr_act();
	lv_scr_load(screen);
	lv_obj_del(old_screen);
}

This is the configuration of the display. I give a buffer of half-size of the screen to LVGL.

#define  BUFFER_SIZE (LV_HOR_RES_MAX  *  LV_VER_RES_MAX  /  2)
static  lv_color_t  buf[BUFFER_SIZE];

void  display_setup_drv(lv_disp_drv_t *disp_drv)
{
	disp_drv->flush_cb = display_flush;
	/*Initialize the display buffer*/
	lv_disp_buf_init(&disp_buf, buf, NULL, BUFFER_SIZE);	
	disp_drv->buffer = &disp_buf;
}

This is the initialization of LVGL.

lv_disp_drv_t  disp_drv;
void lvgl_init()
{
	lv_init(); 
	lv_disp_drv_init(&disp_drv);
	display_setup_drv(&disp_drv);
	lv_disp_drv_register(&disp_drv);
}

This is for LVGL task. I have a task running for LVGL with a timer of 30ms incrementing time.

void  display_task(void *pvParameters )
{
	for( ;; )
	{
		lv_task_handler();
		vTaskDelay(pdMS_TO_TICKS(15));
	}
}
static  void  timer_callback(TimerHandle_t  pxTimer)
{
	lv_tick_inc(30);
}

The part of the rectangle that isn’t displayed correspond to the size of the buffer.

Best regards

And what are LV_HOR_RES_MAX and LV_VER_RES_MAX? Do you also use those as the display’s actual size? Maybe it only happens with a specific display size.

This is the size of the display. And no, I have this problem with mutliple display size. 240*120 and 390 * 390

What is rect and screen in the example code?

  • screen is a LVGL Screens. It’s the highest level containers which have no parent.
  • rect is an LVGL objects representing a rectangle on the display. This objects has screen as parent.

I have the same problem. Thank’s for the fix Remy.
It should be great if you make a pull request.

@kisvegabor Could you take another look at this?

I’ve checked it again but still can’t reproduce the bug. :slightly_frowning_face:
If others also found it really should be a bug.

Please open an issue on GitHub to investigate it. (I’m more active there)

Hello,

I found the bug. I’m using an RTOS with multiple tasks accessing to LVGL. I had no protection against it. So, i add some mutex and it solve the bug. However, I don’t understand why the fix I send to you solve the bug.

Best regards

My educated guess would be that changing the condition offsets the timing of the code a bit, enough to hide the issue.