From: Austin Hu <austin.hu@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: chris@chris-wilson.co.uk
Subject: [PATCH i-g-t] tools/intel_framebuffer_dump: dump frame buffers with igt_fb API.
Date: Mon, 16 Mar 2026 11:36:58 -0700 [thread overview]
Message-ID: <20260316183658.384575-1-austin.hu@intel.com> (raw)
This app is out of date as it opens i915 DRM device to just dump
the "main" frame buffer connected to a CRTC.
So improve it to support Xe driver as well, and dump all the frame
buffers attached to active Planes (including Cursor) of each CRTC
with igt_fb API.
Signed-off-by: Austin Hu <austin.hu@intel.com>
---
tools/intel_framebuffer_dump.c | 137 +++++++++++++++++++--------------
1 file changed, 81 insertions(+), 56 deletions(-)
diff --git a/tools/intel_framebuffer_dump.c b/tools/intel_framebuffer_dump.c
index 79c0688b1..907c65a14 100644
--- a/tools/intel_framebuffer_dump.c
+++ b/tools/intel_framebuffer_dump.c
@@ -36,75 +36,100 @@
#include "intel_io.h"
#include "drmtest.h"
+#include "igt_fb.h"
-int main(int argc, char **argv)
+static void dump_frame_buffer(int fd, uint32_t crtc_id, uint32_t fb_id)
{
- drmModeResPtr res;
- int fd, n;
+ drmModeFB2Ptr fb = drmModeGetFB2(fd, fb_id);
+
+ if (fb == NULL)
+ return;
+
+ /* Wrap drmModeFB2Ptr object into the igt_fb one. */
+ struct igt_fb igt_fb;
+
+ igt_init_fb(&igt_fb, fd, fb->width, fb->height,
+ fb->pixel_format, fb->modifier,
+ IGT_COLOR_YCBCR_BT709, IGT_COLOR_YCBCR_LIMITED_RANGE);
+
+ /* Update more attributes of the igt_fb object. */
+ igt_calc_fb_size(&igt_fb);
+
+ /* Import the GEM handle from drmModeFB2Ptr object into igt_fb object. */
+ igt_fb.gem_handle = fb->handles[0];
+
+ /* Dump the framebuffer contents with igt_fb and Cairo APIs. */
+ /* Note: the FB memory layout may be non-linear (like X/Y-Major Tile). */
+ cairo_surface_t *surface = igt_get_cairo_surface(fd, &igt_fb);
+
+ if (surface != NULL) {
+ char name[80];
- fd = drmOpen("i915", NULL);
+ snprintf(name, sizeof(name), "crtc-%d-fb-%d.png", crtc_id, fb->fb_id);
+ cairo_surface_write_to_png(surface, name);
+ fprintf(stdout, "Framebuffer dumped to %s\n", name);
+
+ cairo_surface_destroy(surface);
+ }
+
+ drmModeFreeFB2(fb);
+}
+
+int main(int argc, char **argv)
+{
+ int fd = drm_open_driver(DRIVER_INTEL | DRIVER_XE);
if (fd < 0)
- return ENOENT;
+ return -ENOENT;
- res = drmModeGetResources(fd);
- if (res == NULL)
- return ENOMEM;
+ /* To enumerate DRM Plane attached to cursor frame buffer. */
+ drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
- for (n = 0; n < res->count_crtcs; n++) {
- struct drm_gem_open open_arg;
- struct drm_gem_flink flink;
- drmModeCrtcPtr crtc;
- drmModeFBPtr fb;
+ drmModeResPtr res = drmModeGetResources(fd);
- crtc = drmModeGetCrtc(fd, res->crtcs[n]);
- if (crtc == NULL)
- continue;
+ if (res == NULL) {
+ close(fd);
+ return -ENOMEM;
+ }
- fb = drmModeGetFB(fd, crtc->buffer_id);
- drmModeFreeCrtc(crtc);
- if (fb == NULL)
- continue;
+ drmModePlaneResPtr pres = drmModeGetPlaneResources(fd);
- flink.handle = fb->handle;
- if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &flink)) {
- drmModeFreeFB(fb);
+ if (pres == NULL) {
+ drmModeFreeResources(res);
+ close(fd);
+ return -ENOMEM;
+ }
+
+ /* Iterate CRTCs. */
+ for (int c = 0; c < res->count_crtcs; c++) {
+ uint32_t cid = res->crtcs[c];
+ drmModeCrtcPtr crtc = drmModeGetCrtc(fd, cid);
+
+ if ((crtc == NULL) || (crtc->buffer_id == 0))
continue;
- }
- open_arg.name = flink.name;
- if (drmIoctl(fd, DRM_IOCTL_GEM_OPEN, &open_arg) == 0) {
- struct drm_i915_gem_mmap_gtt mmap_arg;
- void *ptr;
-
- mmap_arg.handle = open_arg.handle;
- if (drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg) == 0 &&
- (ptr = mmap(0, open_arg.size, PROT_READ, MAP_SHARED, fd, mmap_arg.offset)) != (void *)-1) {
- cairo_surface_t *surface;
- cairo_format_t format;
- char name[80];
-
- snprintf(name, sizeof(name), "fb-%d.png", fb->fb_id);
-
- switch (fb->depth) {
- case 16: format = CAIRO_FORMAT_RGB16_565; break;
- case 24: format = CAIRO_FORMAT_RGB24; break;
- case 30: format = CAIRO_FORMAT_RGB30; break;
- case 32: format = CAIRO_FORMAT_ARGB32; break;
- default: format = CAIRO_FORMAT_INVALID; break;
- }
-
- surface = cairo_image_surface_create_for_data(ptr, format,
- fb->width, fb->height, fb->pitch);
- cairo_surface_write_to_png(surface, name);
- cairo_surface_destroy(surface);
-
- munmap(ptr, open_arg.size);
- }
- drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &open_arg.handle);
- }
+ /* Dump the 'main' frame buffer attached to this CRTC. */
+ dump_frame_buffer(fd, cid, crtc->buffer_id);
+
+ /* Iterate and dump other FBs of Planes attached to this CRTC. */
+ for (int p = 0; p < pres->count_planes; p++) {
+ uint32_t pid = pres->planes[p];
+ drmModePlanePtr pl = drmModeGetPlane(fd, pid);
+
+ if (!pl)
+ continue;
+
+ if ((pl->crtc_id == cid) && (pl->fb_id != 0) &&
+ (pl->fb_id != crtc->buffer_id))
+ dump_frame_buffer(fd, cid, pl->fb_id);
- drmModeFreeFB(fb);
+ drmModeFreePlane(pl);
+ }
+ drmModeFreeCrtc(crtc);
}
+ drmModeFreePlaneResources(pres);
+ drmModeFreeResources(res);
+ close(fd);
+
return 0;
}
--
2.34.1
next reply other threads:[~2026-03-16 18:39 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-16 18:36 Austin Hu [this message]
2026-03-17 12:52 ` ✓ Xe.CI.BAT: success for tools/intel_framebuffer_dump: dump frame buffers with igt_fb API Patchwork
2026-03-17 14:05 ` ✓ i915.CI.BAT: " Patchwork
2026-03-18 15:20 ` ✓ i915.CI.Full: " Patchwork
2026-03-18 20:50 ` ✓ Xe.CI.FULL: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260316183658.384575-1-austin.hu@intel.com \
--to=austin.hu@intel.com \
--cc=chris@chris-wilson.co.uk \
--cc=igt-dev@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox