adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.09k stars 1.21k forks source link

OnDiskBitmap: performs very poorly with rotated screens + bitmap on SD card #2386

Open jepler opened 4 years ago

jepler commented 4 years ago

On pygamer, which has a screen with rotation 270, displaying a fullscreen bitmap from SD takes about 20 seconds.

How to reproduce:

import busio, board, digitalio, storage, adafruit_sdcard

def mount_sd():
    spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
    cs = digitalio.DigitalInOut(board.SD_CS)
    sdcard = adafruit_sdcard.SDCard(spi, cs)
    vfs = storage.VfsFat(sdcard)
    storage.mount(vfs, "/sd")

mount_sd()

import board
import displayio

display = board.DISPLAY

filename = "/sd/001.bmp"
# Open the file
with open(filename, "rb") as bitmap_file:

    # Setup the file as the bitmap data source
    bitmap = displayio.OnDiskBitmap(bitmap_file)

    # Create a TileGrid to hold the bitmap
    tile_grid = displayio.TileGrid(bitmap, pixel_shader=displayio.ColorConverter())
#    tile_grid.transpose_xy = True
#    tile_grid.flip_y = True

    # Create a Group to hold the TileGrid
    group = displayio.Group()

    # Add the TileGrid to the Group
    group.append(tile_grid)

    # Add the Group to the Display
    display.show(group)

    # Loop forever so you can enjoy your image
    while True:
        pass

If the "transpose" property of the tilegrid is set to True, it is quite a bit faster.

Reportedly, the pyportal is much better.

Notably, pygamer has a rotation of 270, while pyportal has a rotation of 0.

hypothesis: when the bitmap is loaded OTHER THAN its on-disk order, the overhead of all the disk seeks becomes enormous, particularly when going through adafruit_sdcard.

tannewt commented 4 years ago

I've seen this with internal flash as well. If the load isn't in on-disk order then it is super slow.

With the pixel loading code I tried to ensure it always loads from the source bitmap by row. The code to do it is here: https://github.com/adafruit/circuitpython/blob/master/shared-module/displayio/TileGrid.c#L429