void WDisplay::updateLoop()

in libs/screen---linux/screen.cpp [50:181]


void WDisplay::updateLoop() {
    int cur_page = 1;
    int frameNo = 0;
    int numPages = vinfo.yres_virtual / vinfo.yres;
    int ledScreen = getConfigInt("LED_SCREEN", 0);

    int sx = vinfo.xres / width;
    int sy = vinfo.yres / height;

    if (ledScreen)
        sx = ledScreen;

    if (sx > sy)
        sx = sy;
    else
        sy = sx;

    if (sx > 1)
        sx &= ~1;

    int offx = (vinfo.xres - width * sx) / 2;
    int offy = (vinfo.yres - height * sy) / 2;

    if (ledScreen) {
        offx = getConfigInt("LED_SCREEN_X", 0);
        offy = getConfigInt("LED_SCREEN_Y", 0);
    }

    int screensize = finfo.line_length * vinfo.yres;
    uint32_t skip = offx;

    if (sx > 1)
        offx &= ~1;

    DMESG("sx=%d sy=%d ox=%d oy=%d 32=%d", sx, sy, offx, offy, is32Bit);
    DMESG("fbuf=%p sz:%d", fbuf, screensize);
    memset(fbuf, 0x00, screensize * numPages);

    if (numPages == 1)
        cur_page = 0;

    dirty = true;

    DMESG("loop");

    for (;;) {
        auto start0 = current_time_us();

        while (!dirty)
            sleep_core_us(2000);

        // auto start = current_time_us();
        // DMESG("update");

        pthread_mutex_lock(&mutex);
        dirty = false;

        if (!is32Bit) {
            uint16_t *dst =
                (uint16_t *)fbuf + cur_page * screensize / 2 + offx + offy * finfo.line_length / 2;
            if (sx == 1 && sy == 1) {
                skip = vinfo.xres - width * sx;
                for (int yy = 0; yy < height; yy++) {
                    auto shift = yy & 1 ? 4 : 0;
                    auto src = screenBuf + yy / 2;
                    for (int xx = 0; xx < width; ++xx) {
                        int c = this->currPalette[(*src >> shift) & 0xf];
                        src += height / 2;
                        *dst++ = c;
                    }
                    dst += skip;
                }
            } else {
                uint32_t *d2 = (uint32_t *)dst;
                for (int yy = 0; yy < height; yy++) {
                    auto shift = yy & 1 ? 4 : 0;
                    for (int i = 0; i < sy; ++i) {
                        auto src = screenBuf + yy / 2;
                        for (int xx = 0; xx < width; ++xx) {
                            int c = this->currPalette[(*src >> shift) & 0xf];
                            src += height / 2;
                            for (int j = 0; j < sx / 2; ++j)
                                *d2++ = c;
                        }
                        d2 += skip;
                    }
                }
            }
        } else {
            uint32_t *d2 =
                (uint32_t *)fbuf + cur_page * screensize / 4 + offx + offy * finfo.line_length / 4;
            skip = vinfo.xres - width * sx;
            for (int yy = 0; yy < height; yy++) {
                auto shift = yy & 1 ? 4 : 0;
                for (int i = 0; i < sy; ++i) {
                    auto src = screenBuf + yy / 2;
                    for (int xx = 0; xx < width; ++xx) {
                        int c = this->currPalette[(*src >> shift) & 0xf];
                        src += height / 2;
                        for (int j = 0; j < sx; ++j)
                            *d2++ = c;
                    }
                    d2 += skip;
                }
            }
        }

        pthread_mutex_unlock(&mutex);

        // auto len = current_time_us() - start;

        painted = true;
        raiseEvent(DEVICE_ID_NOTIFY_ONE, eventId);

        vinfo.yoffset = cur_page * vinfo.yres;
        ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo);
        ioctl(fb_fd, FBIO_WAITFORVSYNC, 0);
        if (numPages > 1)
            cur_page = !cur_page;
        frameNo++;

        auto fulllen = current_time_us() - start0;
        // throttle it to 40fps (really 30fps)
        if (fulllen < 25000) {
            ioctl(fb_fd, FBIO_WAITFORVSYNC, 0);
        }

        // auto tot = current_time_us() - start;
        // if (frameNo % 37 == 0)
        //    DMESG("copy %d us, tot %d us delay %d us",  (int)len, (int)tot, (int)(start-start0));
    }
}