Unexpected results with two screen-sized buffer

Description

Hi, I met a problem only with “two screen-sized” buffers. (All the other settings are the same)

When I want to delete objects or add objects, I need to call lv_obj_invalidate(lv_scr_act()) to make the result correct.
If I do not call that, it would be empty after the second lv_refr_now.

Can someone kindly give me some suggestion?
Does it cause by flush_cb?
Can some kindly tell me how can I write flush_cb to operate successfully?

I’ve tried another test to add an obj. (un-comment the code for button3)
If I do not call lv_obj_invalidate(lv_scr_act()), the result only draws the area which needs to be re-drawn.
But the areas that do not have to be re-drawn (button1,button2) do not contain in the buffer(show on the screen).

Do I need to invalidate whole screen every time to make all objects re-draw to the buffer?
I want to directly use the given-buffer as my display buffer.

void Demo(){

    lv_obj_t * button = lv_obj_create(lv_scr_act(), NULL);
    lv_obj_set_size(button, 300,300);
    lv_obj_set_pos(button, 250,250);
    lv_obj_add_style(button,LV_OBJ_PART_MAIN,&style1);

    lv_obj_t * button2 = lv_obj_create(lv_scr_act(), NULL);
    lv_obj_set_size(button2, 100,100);
    lv_obj_set_pos(button2,100,100);
    lv_obj_add_style(button2, LV_OBJ_PART_MAIN,&style1);

    lv_refr_now(NULL);

    usleep(1000*1000*2);
    lv_obj_del(button2);
    // lv_obj_t * button3 = lv_obj_create(lv_scr_act(), NULL);
    // lv_obj_set_size(button3, 100,100);
    // lv_obj_set_pos(button3,500,500);
    // lv_obj_add_style(button3, LV_OBJ_PART_MAIN,&style1);
    lv_obj_invalidate(lv_scr_act());
    lv_refr_now(NULL);
}


void my_disp_flush_ex(struct _disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p){




    
    int32_t x1 = area->x1;
    int32_t x2 = area->x2;
    int32_t y1 = area->y1;
    int32_t y2 = area->y2;

    uint32_t w = x2 - x1 + 1;
    for(int32_t y = y1; y <= y2; y++) {
        memcpy(&tft_buf[y * LV_HOR_RES_MAX + x1], color_p, w * sizeof(lv_color_t));
        color_p += w;
    }

   //SDL_UpdateTexture(gTexture, NULL, disp->buffer->buf_act, LV_HOR_RES_MAX * sizeof(uint32_t));
    SDL_UpdateTexture(gTexture, NULL, tft_buf, LV_HOR_RES_MAX * sizeof(uint32_t));
    SDL_RenderClear(gRenderer);
    SDL_RenderCopy(gRenderer, gTexture, NULL, NULL);
    SDL_RenderPresent(gRenderer);
    

    lv_disp_flush_ready(disp);         //Indicate you are ready with the flushing
}

When object is created, it’s added to the list of the parent’s children and parent is invalidated. So within next refresh cycle, parent will be refreshed correctly without the need to call lv_obj_invalidate() in your code. Where do you call lv_task_handler ? This one should take care of it automatically.

1 Like

With 2 screen sized buffer you will always get a fully rendered image and all you need to do is changing the framebuffer to color_p.

So this works for me:

void monitor_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
       SDL_UpdateTexture(monitor.texture, NULL, color_p, LV_HOR_RES_MAX * sizeof(uint32_t));
       SDL_RenderClear(monitor.renderer);
       SDL_RenderCopy(monitor.renderer, monitor.texture, NULL, NULL);
       SDL_RenderPresent(monitor.renderer);
       lv_disp_flush_ready(disp_drv);
       return;
}