rzeldent / esp32-smartdisplay

PlatformIO library LVGL Drivers for Sunton Smart display boards (CYD Cheap Yellow Display). This library supports these boards without any effort. ESP32-2432S024N/R/C, ESP32-2432S028R/C, ESP32-3248S035R/C, ESP32_8048S070N/C
https://github.com/rzeldent/platformio-espressif32-sunton
GNU General Public License v3.0
385 stars 69 forks source link

Parts of the screens aren't redrawn #156

Open olivluca opened 5 months ago

olivluca commented 5 months ago

More than a bug report this is a plea for help: I made a simple display here using an esp32-2432S028R board. It's an mqtt client that changes the text and color of some labels and/or shows/hides elements based on the topics received. It also switches betweeen a normal screen and an error screen. Sometimes parts of the screen aren't refreshed, if I periodically invalidate the screen the issue is "fixed" but it slows everything down considerably. This is the first time I use lvgl, squareline studio and this library, so maybe I'm missing something. In the video the "Reset" button is shown based on a topic, the text of the label "E" depends on the same topic, the "17" and the scrolling label depend on a different topic. When I set the topics to 0 the labels text is empy and the button is hidden, however, as you can see, the texts take a while to disappear while the button stays there (but it's actually hidden since I cannot click on it).

https://github.com/rzeldent/esp32-smartdisplay/assets/8250980/4993d47e-c4ea-4fdc-b229-88dc60c3dc88

other times when I hide a spinner, parts of the spinner are still shown.

olivluca commented 5 months ago

I actually think it's a bug in lvgl. For the time being I just do this:

  //hack to try and fix the missing redraws of the screen
  //without this hacks, parts of the screen won't be redrawn
  //showing elements, or parts of element, that shouldn't be there
  //it works but it slows everything down.
  //I could use a longer delay, but then the scrolling label
  //will become jumpy, this way at least the scrolling is 
  //always slow with no sudden jumps

  if(millis()-refreshdelay>100) {
    refreshdelay=millis();
    lv_obj_invalidate(lv_scr_act());
  } 
rzeldent commented 5 months ago

Yes, looks like something in LVGL but this is rare. What I noticed is that the button at the button is touching the label. Maybe this works better if there is some more space around the button? Have you tried moving it around? Are you setting the button to hidden and not just the internal text?

olivluca commented 5 months ago

No it's not touching the label imatge and, yes, I'm setting the button to hidden https://github.com/olivluca/TrumaDisplay/blob/3f15713f63e3ff83792d82b17cc9bf8bd8dabec3/src/main.cpp#L447 https://github.com/olivluca/TrumaDisplay/blob/3f15713f63e3ff83792d82b17cc9bf8bd8dabec3/src/main.cpp#L91

but it's not just the button, other parts aren't redrawn either (e.g., the spinner when hidden is partially shown, or text in some of the labels, etc.). Anyway, callinglv_obj_invalidate(lv_scr_act()); every 100ms works around the issue, and even if the scrolling text isn't as smooth as without the lv_obj_invalidate, I prefer it this way: if I call it less often (say, every 500ms), there would be noticeable jumps in the scrolling.

rzeldent commented 5 months ago

Why not set the flag always?

void Show(lv_obj_t * obj, boolean show) { show? lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN) : lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); }

olivluca commented 5 months ago

Because internally lvgl changes a lot of state even if it's not necessary. e.g if I set (or clear) the hidden flag it invalidates the object, even if it already had (or hadn't) the flag set

void lv_obj_clear_flag(lv_obj_t * obj, lv_obj_flag_t f)
....
    if(f & LV_OBJ_FLAG_HIDDEN) {
        lv_obj_invalidate(obj);
        if(lv_obj_is_layout_positioned(obj)) {
            lv_obj_mark_layout_as_dirty(lv_obj_get_parent(obj));
            lv_obj_mark_layout_as_dirty(obj);
        }
    }

See, it doesn't check if the flag changed, it only checks the new value. It should do no harm but it's a useless waste of resources (it's also a waste of resources to continually invalidate the screen, but since there is no other way to completely redraw the screen...) In any case, it's not the cause of my lack of redraw problem (it did the same even before these optimizations).