Force redraw screen

Hi here,
I’m experimenting a weird bug with my Lvl_pc_simulator. If my app his launched as a debug session, all the screen are displayed correctly. If it’s not then only the 1st screen his displayed but never updated.
So here my question.

  • How do you force refresh / redraw the screen ?
    I tryed a combinaison of lv_obj_invalidate + lv_refr_now. but this doesn’t seem to do the trick.

Here is my code sample

    struct View {
        bool _quit;
        unsigned int _timeout;

        lv_obj_t* _lvglBaseView;
        lv_group_t* _group;
};

void mainLoop(View* view) {
            if (view) {
                _currentView = view;
                _currentView->_quit = false;
                unsigned long prevTick = getSystemTick();
                unsigned long timeoutTick = prevTick + (static_cast<unsigned long>(_currentView->_timeout)/10);

                // try to force refresh here
                //lv_obj_refresh_ext_draw_pad()
                lv_obj_invalidate(_currentView->_lvglBaseView);
                lv_refr_now(lv_obj_get_disp(_currentView->_lvglBaseView));

                while (timeoutTick >= prevTick && _currentView->_quit == false) {
                    delay_ms(10); //yield
                    lv_task_handler();
                    unsigned long newTick = getSystemTick();
                    lv_tick_inc((prevTick - newTick)*10);
                    prevTick = newTick;
                }

                _currentView = 0;
            }
        }

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

It’s very rare that you should need to manually invalidate the screen. Usually, it’s only needed in special cases to remove tearing artifacts from slow display.

I suspect the issue is with the way you are calling lv_tick_inc. It should not be called in the same loop as lv_task_handler (it needs to be called in parallel).

I suggest creating a separate thread to run lv_tick_inc or configuring LV_TICK_CUSTOM so you don’t need to call it at all.

I tryed with

lvgl_drivers_int(){
    _tickThread = SDL_CreateThread(tick_thread, "tick", NULL);
}

int tick_thread(void *data) {
    (void)data;

    while (_tickThreadContinue) {
        SDL_Delay(10);   /*Sleep for 10 millisecond*/
        lv_tick_inc(10); /*Tell LittelvGL that 10 milliseconds were elapsed*/
    }

    return 0;
}

And the same mainLoop without the lv_tick_inc but no changes.
Even tough it is rare, isn’t invalidate_obj the way to ask to redraw an object ?

lv_obj_invalidate is the only way to get an object to be redrawn. You shouldn’t need to call lv_refr_now as lv_task_handler will call that automatically.

The most common reason why refreshing doesn’t work is that lv_tick_inc doesn’t get called. I assume _tickThreadContinue is true?

Yes is true.
So I did more test and the display is OK when I’m using a small project but doesn’t with the real one except on a “debug session”.
Now I did add some printf in the “disp_drv.flush_cb”
I get called so I assume LVGL do his part OK. but SDL2 doesn’t refresh anything.
Or is it possible that the video_buffer that LVGL has sent me was the previous image again and again ? thus the no change ?

Perhaps it’s an issue with your project then; the SDL drivers are used for testing quite frequently so I doubt they have an issue.

I manage to fix it, via letting the SDL driver more time to initialize.
It’s a bit overcustom use, but since we have no animation we don’t call lv_task_handler this frequently.

It’s basically a
while(displayView) lv_task_handler();
Where displayView is altered by event or timeout…

Anyway in case someone have this issue, the fix is to let SDL do some lv_task_handler() for some little time before continuing.
Ofc if you have the regular case it’s all fine.