ESP3D-TFT icon indicating copy to clipboard operation
ESP3D-TFT copied to clipboard

[FEATURE REQUEST]Do better snapshot code with no memory need

Open luc-github opened this issue 1 year ago • 0 comments

Currently the lvgl snapshot API use a lot of memory because it allocate all screen in one buffer then push data to it, it crash if any animation or scrolling text is active which is really not convenient

I am thinking to use my previous method for snapshot (in first 3.0 version ) that actually hook the void esp_lv_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) function. It did not need any buffer screen unlike the lvgl API and may just freeze the screen the time the data are saved here the old code :

/* Display flushing */
void esp_lv_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
    //TODO: need to write version for oled with big resolution
    uint16_t c;
    esp3d_screen.startWrite(); /* Start new TFT transaction */
    esp3d_screen.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */
    for (int y = area->y1; y <= area->y2; y++) {
        for (int x = area->x1; x <= area->x2; x++) {
            c = color_p->full;
            esp3d_screen.writeColor(c, 1);
#if defined(DISPLAY_SNAPSHOT_FEATURE)
            if(bSnapshot) {
                uint32_t data = lv_color_to32(*color_p);
                //to handle any write issue
                if (fsSnapFile.write((const uint8_t *)(&data), sizeof(uint32_t)) !=  sizeof(uint32_t)) {
                    //if error we stop to dump
                    bSnapshot = false;
                    //raise error
                    error_snapshot = 1;
                }
            }
#endif //DISPLAY_SNAPSHOT_FEATURE
            color_p++;
        }
    }
    esp3d_screen.endWrite(); /* terminate TFT transaction */
    lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
}


bool Display::snapshot(char * filename)
{
    bool res = false;
#if defined(DISPLAY_SNAPSHOT_FEATURE)
    //sanity check to avoid to corrupt FS with capacity overload
    error_snapshot = 0;
    if (ESP_FileSystem::freeBytes() < SNAP_SIZE) {
        return false;
    }
    if(filename) {
        fsSnapFile = ESP_FileSystem::open(filename, ESP_FILE_WRITE);
    } else {
        fsSnapFile = ESP_FileSystem::open(SNAPFILENAME, ESP_FILE_WRITE);
    }
    if (!fsSnapFile) {
        return false;
    }

    bSnapshot = true;
    lv_obj_invalidate(lv_scr_act());
    lv_refr_now(lv_disp_get_default());                    /* Will call our disp_drv.disp_flush function */
    bSnapshot = false;
    fsSnapFile.close();
    //if any snapshot error
    if (error_snapshot == 0) {
        res = true;
    }
#endif //DISPLAY_SNAPSHOT_FEATURE
    return res;
}

the new lvgl API use one function only:

static void lv_disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) {
  esp_lcd_panel_draw_bitmap(disp_panel, area->x1, area->y1, area->x2 + 1, area->y2 + 1, color_p);  
}

so it may be possible to redo same for snapshot - this method do a real snap what ever is displayed and even there is an animation.=> TBC

luc-github avatar Jan 07 '24 04:01 luc-github