Skip to main content

libdrmtap_sys/
lib.rs

1/*
2 * libdrmtap-sys — Raw FFI bindings for libdrmtap
3 * https://github.com/fxd0h/libdrmtap
4 *
5 * Copyright (c) 2026 Mariano Abad <weimaraner@gmail.com>
6 * SPDX-License-Identifier: MIT
7 *
8 * Hand-written FFI bindings matching include/drmtap.h
9 * These are intentionally minimal — use libdrmtap-rs for safe wrappers.
10 */
11
12#![allow(non_camel_case_types)]
13
14use std::os::raw::{c_char, c_int, c_void};
15
16/// Opaque capture context
17pub enum drmtap_ctx {}
18
19/// Configuration for opening a capture context
20#[repr(C)]
21pub struct drmtap_config {
22    pub device_path: *const c_char,
23    pub crtc_id: u32,
24    pub helper_path: *const c_char,
25    pub debug: c_int,
26}
27
28/// Information about a connected display
29#[repr(C)]
30#[derive(Clone, Copy)]
31pub struct drmtap_display {
32    pub crtc_id: u32,
33    pub connector_id: u32,
34    pub name: [c_char; 32],
35    pub width: u32,
36    pub height: u32,
37    pub refresh_hz: u32,
38    pub active: c_int,
39}
40
41/// Captured frame data
42#[repr(C)]
43pub struct drmtap_frame_info {
44    pub data: *mut c_void,
45    pub dma_buf_fd: c_int,
46    pub width: u32,
47    pub height: u32,
48    pub stride: u32,
49    pub format: u32,
50    pub modifier: u64,
51    pub fb_id: u32,
52    pub _priv: *mut c_void,
53}
54
55/// Cursor state
56#[repr(C)]
57pub struct drmtap_cursor_info {
58    pub x: i32,
59    pub y: i32,
60    pub hot_x: i32,
61    pub hot_y: i32,
62    pub width: u32,
63    pub height: u32,
64    pub pixels: *mut u32,
65    pub visible: c_int,
66    pub _priv: *mut c_void,
67}
68
69/// Dirty rectangle from frame differencing
70#[repr(C)]
71pub struct drmtap_rect {
72    pub x: u32,
73    pub y: u32,
74    pub w: u32,
75    pub h: u32,
76}
77
78extern "C" {
79    // Version
80    pub fn drmtap_version() -> c_int;
81
82    // Context lifecycle
83    pub fn drmtap_open(config: *const drmtap_config) -> *mut drmtap_ctx;
84    pub fn drmtap_close(ctx: *mut drmtap_ctx);
85
86    // Display enumeration
87    pub fn drmtap_list_displays(
88        ctx: *mut drmtap_ctx,
89        displays: *mut drmtap_display,
90        max_count: c_int,
91    ) -> c_int;
92    pub fn drmtap_displays_changed(ctx: *mut drmtap_ctx) -> c_int;
93
94    // Frame capture
95    pub fn drmtap_grab(ctx: *mut drmtap_ctx, frame: *mut drmtap_frame_info) -> c_int;
96    pub fn drmtap_grab_mapped(ctx: *mut drmtap_ctx, frame: *mut drmtap_frame_info) -> c_int;
97    pub fn drmtap_frame_release(ctx: *mut drmtap_ctx, frame: *mut drmtap_frame_info);
98
99    // Cursor
100    pub fn drmtap_get_cursor(ctx: *mut drmtap_ctx, cursor: *mut drmtap_cursor_info) -> c_int;
101    pub fn drmtap_cursor_release(ctx: *mut drmtap_ctx, cursor: *mut drmtap_cursor_info);
102
103    // Info
104    pub fn drmtap_error(ctx: *const drmtap_ctx) -> *const c_char;
105    pub fn drmtap_gpu_driver(ctx: *mut drmtap_ctx) -> *const c_char;
106
107    // Pixel conversion
108    pub fn drmtap_deswizzle(
109        src: *const c_void,
110        dst: *mut c_void,
111        width: u32,
112        height: u32,
113        src_stride: u32,
114        dst_stride: u32,
115        modifier: u64,
116    ) -> c_int;
117    pub fn drmtap_convert_format(
118        src: *const c_void,
119        dst: *mut c_void,
120        width: u32,
121        height: u32,
122        src_stride: u32,
123        dst_stride: u32,
124        src_format: u32,
125        dst_format: u32,
126    ) -> c_int;
127
128    // Frame differencing
129    pub fn drmtap_diff_frames(
130        frame_a: *const c_void,
131        frame_b: *const c_void,
132        width: u32,
133        height: u32,
134        stride: u32,
135        rects_out: *mut drmtap_rect,
136        max_rects: c_int,
137        tile_size: c_int,
138    ) -> c_int;
139}
140
141#[cfg(test)]
142mod tests {
143    use super::*;
144
145    #[test]
146    fn test_version() {
147        let v = unsafe { drmtap_version() };
148        assert_eq!(v, 0x000100); // 0.1.0
149    }
150
151    #[test]
152    fn test_config_size() {
153        // Verify struct sizes are reasonable
154        assert!(std::mem::size_of::<drmtap_config>() > 0);
155        assert!(std::mem::size_of::<drmtap_display>() > 0);
156        assert!(std::mem::size_of::<drmtap_frame_info>() > 0);
157        assert!(std::mem::size_of::<drmtap_cursor_info>() > 0);
158    }
159}