掌機 - Miyoo Flip - C/C++ - DRM/KMS - Double Framebuffer



參考資訊:
https://gist.github.com/dvdhrm/5083553
https://www.kernel.org/doc/html/v4.15/gpu/drm-kms.html
https://github.com/grate-driver/libdrm/blob/master/xf86drmMode.h

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
 
int main(int argc, char *argv[])
{
    const int w = 640;
    const int h = 480;
    const int bpp = 32;
    const int depth = 24;

    int i = 0;
    int j = 0;
    int r = 0;
    int fd = -1;
    uint32_t fb[2] = { 0 };
    drmModeRes *res = NULL;
    drmModeCrtc *crtc = NULL;
    drmModeEncoder *enc = NULL;
    drmModeConnector *conn = NULL;
    struct drm_mode_map_dumb mreq = { 0 };
    struct drm_mode_create_dumb creq = { 0 };
    struct drm_mode_destroy_dumb dreq = { 0 };

    fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
    res = drmModeGetResources(fd);
    conn = drmModeGetConnector(fd, res->connectors[1]);
    enc = drmModeGetEncoder(fd, res->encoders[2]);
    crtc = drmModeGetCrtc(fd, res->crtcs[1]);

    creq.bpp = bpp;
    creq.width = w;
    creq.height = h;
    drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
    drmModeAddFB(fd, creq.width, creq.height, depth, creq.bpp, creq.pitch, creq.handle, &fb[0]);
    drmModeAddFB(fd, creq.width, creq.height, depth, creq.bpp, creq.pitch, creq.handle, &fb[1]);
    mreq.handle = creq.handle;
    drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);

    uint8_t *map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
    uint32_t color[] = { 0xff0000, 0x00ff00, 0x0000ff };
    uint32_t cc = 0;
    while (1) {
        uint32_t *p = (uint32_t *)map;

        drmModeSetCrtc(fd, crtc->crtc_id, fb[cc % 2], 0, 0, (uint32_t *)conn, 1, &crtc->mode);
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                *p++ = color[cc % 3];
            }
        }
        cc += 1;
    }

    munmap(map, creq.size);
    drmModeRmFB(fd, fb[0]);
    drmModeRmFB(fd, fb[1]);
    dreq.handle = creq.handle;
    drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);

    drmModeFreeCrtc(crtc);
    drmModeFreeEncoder(enc);
    drmModeFreeConnector(conn);
    drmModeFreeResources(res);
    close(fd);
    return 0;
}

編譯、執行

$ /opt/flip/bin/aarch64-linux-gcc main.c -O3 -o main -I/opt/flip/aarch64-flip-linux-gnu/sysroot/usr/include/libdrm -ldrm

root@rk3566-buildroot:/mnt/SDCARD# ./main