Anything can be be done about the tearing effect?

The tearing effect is a display artifact that is causes by display update the crosses scan frames. here is an example in slow motion

https://vimeo.com/manage/videos/566303015

image

Anybody has any experience how to deal with it or minimize it? For example, in my system, the ILI9488 has a scan sync output (‘Tearing output’) which can potentially be used to sync writing to the display with the frame scanning and I wonder what other people have been or what ideas you may have.

(I am using Pico RP2040 with a PIO that controls the writing to the ILI9488 so potentially could process the Tearing input in another PIO and sync it with the writing PIO somehow).

For LCDs which use a CPU-accessible framebuffer, if you use two fullscreen-sized buffers, you get the standard double-buffering system, where your flush_cb just needs to switch the LCD framebuffer reference back and forth between them. As far as I know, there is then a way to set it up so that you perform the actual switch on a VSYNC interrupt, which would solve your issue. (I can’t recall the exact method of doing this at the moment.)

However, I’m not sure exactly how to do this if you have to send the data to the display through SPI, etc.

@kisvegabor Do you have a suggestion?

With an external display controller (e.g. ILI9488) you need to give LVGL 1 or 2 screen-sized draw buffers, an in flush_cb delay the display refreshing until the TE signal.

It’s required to send the data after to the screen than a VSYNC time.

Having a screen size buffer is a challenge with some MCUs. With the Pico I will have to go back to a single 8bit colors buffer to have the entire screen.

BTW, does a screen size buffer guarantees display update in a single part or is it a flush_cb call per a dirty rectangle?

With two screen size buffers, flush_cb sends fullscreen updates as far as I know.

With just one screen-size buffer, you get the standard behavior, where if a small widget is being redrawn on the screen, only that area gets sent to flush_cb. However, if the whole screen ends up needing to be redrawn, it can be sent in one part, instead of being split into several parts like what happens with a smaller buffer.

Thinking about it more a smaller buffer can work too if there is only 1 area to redraw (e.g. a button).

But if there are more areas (because the buffer was too small or 2 independent areas need to be redrawn) you can’t avoid tearing because probably rendering + display updating will be longer than a VSYNC period.

@zapta I’m using a Teensy MicroMod with an 8 bit parallel bus @30Mhz with DMA transfers for the big chunks of data.
As I only have a 500kB region available for a framebuffer, I can either use two half screen sized frame buffers, or one full screen sized buffer.
I too suffer from Tearing on the 9488, and do have the TE pin connected to a GPIO but I have not utilized it yet.

The way my code run is LVGL will send the pixel data to the DMA engine, and it will be transferred to the display, and only once DMA is finished will it trigger a callback and call lv_disp_flush_ready
While this runs a lot smoother than polling transfers, I do believe that with the TE trigger I can eliminate just a bit more.
Were you ever able to utilize the TE pin to sync the transfers?