#include #include #include #include #include #include #include #include #include #include int main(void) { int fd = open("/dev/dri/card0", O_RDWR); if (fd < 0) { perror("open"); return 1; } drmModeRes *res = drmModeGetResources(fd); if (!res) { perror("getResources"); return 1; } drmModeCrtc *crtc = NULL; uint32_t crtc_id = 0; for (int i = 0; i < res->count_crtcs; i++) { crtc = drmModeGetCrtc(fd, res->crtcs[i]); if (crtc && crtc->buffer_id) { crtc_id = crtc->crtc_id; break; } if (crtc) { drmModeFreeCrtc(crtc); crtc = NULL; } } if (!crtc || !crtc->buffer_id) { fprintf(stderr, "No active CRTC\n"); drmModeFreeResources(res); return 1; } fprintf(stderr, "CRTC %u -> FB %u, %ux%u\n", crtc_id, crtc->buffer_id, crtc->width, crtc->height); drmModeFB2 *fb = drmModeGetFB2(fd, crtc->buffer_id); if (!fb) { fprintf(stderr, "drmModeGetFB2 failed, trying FB...\n"); drmModeFB *fb1 = drmModeGetFB(fd, crtc->buffer_id); if (!fb1) { perror("getFB"); return 1; } fprintf(stderr, "FB: %ux%u pitch=%u handle=%u\n", fb1->width, fb1->height, fb1->pitch, fb1->handle); uint32_t size = fb1->pitch * fb1->height; void *map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { struct drm_mode_map_dumb mreq = { .handle = fb1->handle }; if (ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)) { perror("map"); return 1; } map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, mreq.offset); if (map == MAP_FAILED) { perror("mmap2"); return 1; } } FILE *fp = fopen("/tmp/frame.bin", "wb"); fwrite(map, 1, size, fp); fclose(fp); fprintf(stderr, "Dumped %u bytes to /tmp/frame.bin\n", size); munmap(map, size); drmModeFreeFB(fb1); drmModeFreeCrtc(crtc); drmModeFreeResources(res); return 0; } fprintf(stderr, "FB2: %ux%u format=0x%x\n", fb->width, fb->height, fb->pixel_format); for (int i = 0; i < 4; i++) fprintf(stderr, " plane[%d]: handle=%u pitch=%u offset=%u\n", i, fb->handles[i], fb->pitches[i], fb->offsets[i]); if (fb->handles[0] == 0) { fprintf(stderr, "No handle on plane 0\n"); drmModeFreeFB2(fb); drmModeFreeCrtc(crtc); drmModeFreeResources(res); return 1; } uint32_t w = fb->width, h = fb->height; uint32_t pitch = fb->pitches[0]; uint32_t size = pitch * h; struct drm_mode_map_dumb mreq = { .handle = fb->handles[0] }; if (ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)) { perror("map_dumb"); return 1; } void *map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, mreq.offset); if (map == MAP_FAILED) { perror("mmap"); return 1; } FILE *fp = fopen("/tmp/frame.bin", "wb"); fwrite(map, 1, size, fp); fclose(fp); fprintf(stderr, "Dumped %ux%u (pitch=%u, %u bytes) to /tmp/frame.bin\n", w, h, pitch, size); munmap(map, size); drmModeFreeFB2(fb); drmModeFreeCrtc(crtc); drmModeFreeResources(res); return 0; }