go-play icon indicating copy to clipboard operation
go-play copied to clipboard

[Discussion] Reduce Tearing in NES

Open rickyzhang82 opened this issue 6 years ago • 51 comments

I want to reduce tearing problem in NES. I copied our discussion from odroid forum to here

How it works now

The way the display system currently works:

  1. emulator finishes a frame on core 0
  2. frame is copied and the copy is sent to core 1
  3. emulator works on next frame on core 0

meanwhile on core 1:

  1. a frame is received from core 0
  2. a group of scanlines is processed (palette and scaling).
  3. the group is sent to DMA.
  4. the next group of scanlines is processed while DMA is in progress.

meanwhile on DMA:

  1. data is received by the DMA engine and is fed to the SPI hardware
  2. DMA notifies completion.

There are two frame buffers, two scanline buffers of 3 lines, and multiple DMA buffers.

At 40Mhz SPI, there is 40,000Kbps / 8 bits = 5KBps. A frame is 320 * 240 * 2 bytes / 1024 = 150KB. 5KBps / 150KB = 33.3 fps. However, because there is protocol overhead, the achieved frame rate is less (closer to 30fps). The LCD updates at 70fps (61 is the slowest but looked worse). 70fps / 30fps = 2.3 refreshes for every frame displayed.

LCD controller specs

IL9341 specs

Other's improvement on IL9341 over SPI

fbcp-ili9341 repo

My proposal

  1. Use two frame buffers to do swap instead of memcpy
  2. Find minimal different rectangle between two frame buffer and send the delta over SPI
  3. Use Good old interlacing is added into the mix: if the amount of pixels that needs updating is detected to be too much that the SPI bus cannot handle it, the driver adaptively resorts to doing an interlaced update, uploading even and odd scanlines at subsequent frames. Once the number of pending pixels to write returns to manageable amounts, progressive updating is resumed. This effectively doubles the maximum display update rate.

rickyzhang82 avatar Jun 30 '18 11:06 rickyzhang82