lvgl icon indicating copy to clipboard operation
lvgl copied to clipboard

Animating arc results in black widget

Open tobiasjakobi-compleo opened this issue 1 year ago • 18 comments

LVGL version

v9.1.0-381-g90cfb6c61

What happened?

Hello,

having more trouble here with LVGL Git master.

We have a problem with Git master (also happens with v9.1.0) that results in animations for lv_arc object no longer working. The same code previously worked fine with v8.4.0, so I guess either something broke in LVGL itself, or the API changed and we are now using it incorrectly.

Anyway, let me first show some screenshot: image

So you can see a partial arc here. The animation lets the thing spin, to create a waiting animation. At least that's what happens with v8.4.0.

With Git master the widget immediately turns all black, and looks like that: image

Interestingly we get one good frame. It's only after the animation callback is entered, and lv_arc_set_rotation() is called. This immediately breaks things and the widget becomes all black.

If I just NOP the callback, i.e. disable the calls to lv_arc_set_rotation() and lv_arc_set_bg_angles(), then of course I don't get any animation, but the part of the arc is rendered correctly in its initial position.

In fact, just calling lv_obj_invalidate() in the callback, without any modification of the arc's settings makes things explode. So, I guess something goes wrong during invalidation, either during invalidation itself, or when computing the bounding box.

With best wishes, Tobias

How to reproduce?

LVWaitAnimation::LVWaitAnimation(::lv_obj_t *parent) {
  object = ::lv_arc_create(parent);

  const auto initial_start = ::detail::wait_anim_start(0);

  ::lv_arc_set_rotation(object, initial_start);
  ::lv_arc_set_bg_angles(object, 0, 60 + 0 + initial_start);

  ::lv_obj_remove_style(object, nullptr, ::LV_PART_KNOB);      // Be sure the knob is not displayed
  ::lv_obj_remove_style(object, nullptr, ::LV_PART_INDICATOR); // Be sure the indicator is not displayed
  ::lv_obj_remove_flag(object, ::LV_OBJ_FLAG_CLICKABLE);       // To not allow adjusting by click

  ::lv_anim_t anim;
  ::lv_anim_init(&anim);
  ::lv_anim_set_var(&anim, object);

  ::lv_anim_set_exec_cb(&anim, [](void *data, std::int32_t v) {
    auto obj = reinterpret_cast<::lv_obj_t *>(data);

    const auto start = ::detail::wait_anim_start(v);

    std::cerr << "DBG[in_cb]: " << "start=" << start << std::endl;

    ::lv_arc_set_rotation(obj, (270 + start) % 360); // TODO: this messes up LVGL (black widget)
    ::lv_arc_set_bg_angles(obj, 0, 60 + v - start); // TODO: this creates black dot artifacts
  });

  ::lv_anim_set_duration(&anim, 1000);
  ::lv_anim_set_repeat_count(&anim, LV_ANIM_REPEAT_INFINITE);
  ::lv_anim_set_values(&anim, 0, 360);
  ::lv_anim_start(&anim);
}

tobiasjakobi-compleo avatar Aug 14 '24 11:08 tobiasjakobi-compleo

I turns out that this also affects when lv_image is animated. Same diagnosis here, it suffices to invalidate the object in the callback, and then things break.

ghost avatar Aug 14 '24 12:08 ghost

We need some feedback on this issue.

Now we mark this as "stale" because there was no activity here for 14 days.

Remove the "stale" label or comment else this will be closed in 7 days.

lvgl-bot avatar Aug 29 '24 01:08 lvgl-bot

A few ideas:

  • As a test, please create an lv_spinner.
  • Can it be a display driver issue? Does other small area updates working well? E.g. when you press a button.

kisvegabor avatar Aug 29 '24 07:08 kisvegabor

Hey Gabor,

will try a lv_spinner the next time I work on this.

I doubt it's a display driver issue, since, at the moment, there is no display driver involved. We just copy the framebuffer in the flush callback. But I'm going to check this part again.

ghost avatar Aug 29 '24 13:08 ghost

We need some feedback on this issue.

Now we mark this as "stale" because there was no activity here for 14 days.

Remove the "stale" label or comment else this will be closed in 7 days.

lvgl-bot avatar Sep 16 '24 02:09 lvgl-bot

My plan is to continue working on this issue starting end of this week. Hopefully going to provide some feedback then.

ghost avatar Sep 17 '24 15:09 ghost

I've investigated the flush callback we're using. It looks sane, no obvious errors.

For debugging I've added a check that goes through the incoming pixel data and checks if all pixels are the same. If that's the case, I print a debug message with the pixel color. When the widget goes into its broken state, this check triggers. The incoming pixel data is all 0xff000000 (32-bit, black with full opacity). I.e. the incoming pixel data is already broken/corrupted, so nothing happens in the flush callback here.

I'm going to try a spinner next. Also trying to figure out a way to lift some of our code into a separate repository (since I'm not allowed to share the full project here, for licensing issues and bla bla :grin: ).

ghost avatar Sep 19 '24 13:09 ghost

Okay, I'm curious what the issue can be.

kisvegabor avatar Sep 25 '24 13:09 kisvegabor

I can give a small update: So in addition to this issue here I was seeing some other problems that manifest in parts of the screen not updating. I can maybe upload a small video later. Turns out that the problem is related to the render mode. I had selected direct mode with a single buffer. For testing purpose I just changed direct to full. Still just one buffer though. And voila, all the issues gone! The widget animation renders correctly and the update problems are also gone.

Going to investigate this further. Planning on testing the direct + double buffering scenario next. I really want to avoid full mode because of memory bandwidth.

So as of now, this looks like a genuine bug in LVGL itself...

ghost avatar Sep 25 '24 13:09 ghost

Enabling double buffering has no effect. I.e. this means in detail:

  • direct + single -> broken
  • direct + double -> broken
  • full + single -> working
  • full + double -> working

I can only conclude that the issue somehow stems from how direct mode optimizes redrawing of the display.

EDIT: It seems like the px_map and area arguments in the flush callback are sometimes bogus. So far our flush callback has copied any incoming pixel to a user provided buffer. This buffer was then displayed via IMGui. I have changed stuff like in the DRM driver, i.e. both px_map and area are ignored, we have two buffers and the flush callback merely swaps the two. IMGui now fetches the front buffer whenever it needs to display.

My guess is that nobody noticed that because you need to have direct mode enabled, double buffering and ignore the px_map and area arguments. Not sure how many HW drivers do this.

Anyway, enough debugging for the day...

ghost avatar Sep 25 '24 14:09 ghost

I'm not sure it's related, but I hope it helps: With DIRECT mode the flush_cb is called multiple times for each changed small area. You don't really have to do anything in the flush_cb as LVGL renders directly to the frame buffer, however on the last area you you should tell the driver that now the rendered image is ready, display it. You can check if it's the last area with lv_display_flush_is_last(disp). If it's not the last you just need to call lv_display_flush_ready() and return.

kisvegabor avatar Sep 26 '24 07:09 kisvegabor

Yeah, but then it's not clear to me what I'm supposed to do with px_map and area. If I understand things correctly, then these two define a "damage area". Which the user can use to optimize pixel upload to the display hardware.

I mean, the code in examples/porting/lv_port_disp_template.h explicitly tells us how to use these two arguments.

So, in any case, this damage area should contain valid data. But like I said above (https://github.com/lvgl/lvgl/issues/6685#issuecomment-2360964118) in these situations the damage area is all black. This doesn't look correct to me. Because that's the pixels the user is supposed to upload to his HW.

If the damage area is only valid under certain conditions, then this should be reflected in the API. Maybe by passing a NULL area pointer to the callback.

Anyway, I'm trying to come up with a minimum example to demonstrate this behaviour.

ghost avatar Sep 26 '24 07:09 ghost

Yeah, but then it's not clear to me what I'm supposed to do with px_map and area.

You don't really have to do anything with these as in case of DIRECT mode the UI is already rendered into the frame buffer.

Can you share your current flush_cb?

kisvegabor avatar Oct 03 '24 13:10 kisvegabor

I'm still working on this one. Currently swamped with other stuff, so sorry already for the delay...

ghost avatar Oct 09 '24 13:10 ghost

We need some feedback on this issue.

Now we mark this as "Abandoned" because there was no activity here for 14 days.

Remove the "Stale" label or comment else this will be closed in 7 days.

lvgl-bot avatar Oct 24 '24 02:10 lvgl-bot

Not stale, but not finding the time to work on a testcase for this at the moment.

ghost avatar Oct 24 '24 07:10 ghost

We need some feedback on this issue.

Now we mark this as "Abandoned" because there was no activity here for 14 days.

Remove the "Stale" label or comment else this will be closed in 7 days.

lvgl-bot avatar Nov 15 '24 02:11 lvgl-bot

Not stale, but status unchanged. Still plan to get to the bottom of this.

ghost avatar Nov 15 '24 10:11 ghost

We need some feedback on this issue.

Now we mark this as "Abandoned" because there was no activity here for 14 days.

Remove the "Stale" label or comment else this will be closed in 7 days.

lvgl-bot avatar Dec 06 '24 02:12 lvgl-bot

Another "not stale"! :grin:

ghost avatar Dec 09 '24 10:12 ghost

We need some feedback on this issue.

Now we mark this as "Abandoned" because there was no activity here for 14 days.

Remove the "Stale" label or comment else this will be closed in 7 days.

lvgl-bot avatar Dec 26 '24 02:12 lvgl-bot

We can close it for now, and we can reopen it when you have some news. :slightly_smiling_face:

kisvegabor avatar Jan 03 '25 15:01 kisvegabor

Yes, seems like the best solution for now. Also I'm leaving Compleo (the company for which I'm doing the LVGL integration) in March. So I won't be working on this anyway. Someone new might pick up the project, but that's something I don't have any say in.

ghost avatar Jan 13 '25 09:01 ghost

Okay, I see. I hope you will find a good new workplace.

kisvegabor avatar Jan 13 '25 11:01 kisvegabor