參考資訊:
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
https://gist.github.com/Miouyouyou/89e9fe56a2c59bce7d4a18a858f389ef
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>
static int waiting_for_flip = 0;
static void flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
{
*((int *)data) = 0;
}
drmEventContext evctx = {
.version = DRM_EVENT_CONTEXT_VERSION,
.page_flip_handler = flip_handler,
};
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 = 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);
mreq.handle = creq.handle;
drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
drmModeSetCrtc(fd, crtc->crtc_id, fb, 0, 0, (uint32_t *)conn, 1, &crtc->mode);
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;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
*p++ = color[cc % 3];
}
}
cc += 1;
waiting_for_flip = 1;
drmModePageFlip(fd, crtc->crtc_id, fb, DRM_MODE_PAGE_FLIP_EVENT, (void *)&waiting_for_flip);
while (waiting_for_flip) {
drmHandleEvent(fd, &evctx);
}
}
munmap(map, creq.size);
drmModeRmFB(fd, fb);
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