90° software rotation and LV_COLOR_SCREEN_TRANSP


I am using lvgl 8.3.1 (but tested on 8.3.3 as well) with the software rendering. My application has the following configuration:

  1. fb init
  2. only one buffer
  3. full refresh is off
  4. direct mode is off
  5. software rotation is ON with 90° rotation
  6. LV_COLOR_SCREEN_TRANSP is enabled in lv_conf.h

My UI has 2 screens. Screen#1 has a background color and a bunch of objects (buttons and such). And screen#2 has bg_opa set to 0 (using lv_obj_set_style_bg_opa) and a single button with text.

When the app starts, screen#1 is set as the active screen and I force the refresh. Everything is displayed just fine with the expected rotation and screen contents. Then I set screen#2 as the active screen and force a refresh. I do see my button displayed correctly (correct rotation and button contents/size/position).

But the problem is with what is displayed as the background of screen#2. The upper half of the background (which gets redrawn during the refresh) is actually whatever was on screen#1 but rotated an extra 90°. This part of the screen includes my button (which is rotated correctly). While the bottom half of the background of screen#2 (which did not get redrawn) is fine and matches the contents of screen#1.

how would I go about fixing this behavior ?


Can you show some screen shot to help understand your question?

this is my screen1, in portrait mode with software rotation:

here is screen2 which is transparent and displayed over screen1.
Screen2 only has a single red box which is rendered correctly.

Note that the top half of the background of screen2 (hence, whatever was on screen1) is not rotated as I would expect it.

It seems a bug of SW screen rotation, maybe triggered by 2 screens displayed at the same time. As a workaround, you can try display only one screen. The redbox can also be created to the screen 1.

right, but that takes away the whole point/advantage of having screens. Screen2 is to be populated with more than with a single box. And more screens are to be created.

Also, based on my (relatively short) experience with LVGL, I noticed that, for a given screen, the rendering speed slows down as the number of objects increases, even if those objects are not visible. So one goal behind the usage of screens was to spread objects across screens as much as possible (based on the UI scenario) while keeping all objects in memory.

For your case, I have 2 solutions.

  1. Keep only one screen displayed at a moment, use the msgbox widgets as your popup window. See lv_example_msgbox_1().
  2. Keep only one screen displayed at a moment, move these widgets that you don’t want to show, to the default screen, which is created by lv_disp_drv_register(), by lv_obj_set_parent(). Also move back if you want to show.
lv_obj_t* defaultScreen = lv_disp_get_default()->screens[0];
lv_obj_set_parent(yourWidget, defaultScreen);


I have a similar problem with software rotation and the following configuration

  1. One framebuffer
  2. One (or two) displaybuffer(s)
  3. full refresh is off
  4. direct mode is on
  5. software rotation is ON with 180° rotation

The update of the framebuffer is done in the Disp_drv.flush_cb() callback function with the followoing commands:

  1. Get pointer of actual displaybuffer with _lv_refr_get_disp_refreshing()
  2. Check for refresh with lv_disp_flush_is_last()
  3. If refresh is true, make a loop with disp->inv_p and copy all areas from disp->inv_joined[]

The display is showing several image buttons. If a button is pressed, a different image is shown for this button. Normally this works correct. If buttons are pressed to fast, the new image is shown on the mirrored position (or the position without rotating).

This problem exists regardless of the number of displaybuffers.

Unfortunately, I have no in-depth knowledge of lvgl. Where can I get information on how the update and refresh of the displaybuffer works ?

When I know more about it, I will use my Tracealyzer to make a deeper look inside this mechanism.


It’s definitely not an intended use case as only one screen can loaded at a time. To display two screen-like object at the same time I suggest utilizing the lv_layer_top().