Crates.io | drm-gfx |
lib.rs | drm-gfx |
version | 0.1.0 |
created_at | 2025-09-25 15:03:43.060764+00 |
updated_at | 2025-09-25 15:03:43.060764+00 |
description | 3D graphics rendering for direct rendering manager with optional tokio thread support |
homepage | |
repository | https://gitlab.com/FLimburg/drm-gfx |
max_upload_size | |
id | 1854731 |
size | 121,139 |
A 3D graphics rendering library for the Linux Direct Rendering Manager (DRM). This library provides a lightweight 3D rendering engine that works directly with the DRM interface, without requiring a full graphics stack or window manager.
Or to put it more bluntly: I stitched together https://github.com/Kezii/embedded-gfx/tree/master with https://github.com/Smithay/drm-rs/tree/develop without any care and threw it into https://gitlab.com/FLimburg/drm-gfx .
Add this to your Cargo.toml
:
[dependencies]
drm-gfx = "0.1.0"
use feature tokio-thread to use drm-gfx in a tokio based application
use drm_gfx::mesh::K3dMesh;
use drm_gfx::{
draw::draw,
mesh::Geometry,
perfcounter::PerformanceCounter,
K3dengine,
doublebuffer::DoubleBuffer,
drm_render_target::RenderTarget,
};
use embedded_graphics::Drawable;
use embedded_graphics::{
geometry::Point,
mono_font::{ascii::FONT_6X10, MonoTextStyle},
text::Text,
};
use embedded_graphics_core::pixelcolor::{Bgr888, WebColors};
use nalgebra::Point3;
use std::f32::consts::PI;
use std::ffi::c_void;
mod locs;
// TODO: make this run time
// this needs to fit with the output from display creation
const WIDTH: usize = 1024;
const HEIGHT: usize = 600;
#[tokio::main]
async fn main() {
println!("Hello, world!");
let locs = Vec![[-1,0,0],[1,0,0],[0,1,0]];
// card1 is used for the rasperry pi hdmi port
let display = RenderTarget::new("/dev/dri/card1");
let mut locations = K3dMesh::new(Geometry{
vertices: &locs,
faces: &[],
colors: &[],
lines: &[],
normals: &[],
});
locations.set_color(Bgr888::CSS_GREEN);
let mut raw_framebuffer_0 = Box::new([0u32; WIDTH * HEIGHT]);
let mut raw_framebuffer_1 = Box::new([0u32; WIDTH * HEIGHT]);
let mut buffers = DoubleBuffer::<WIDTH, HEIGHT>::new(
raw_framebuffer_0.as_mut_ptr() as *mut c_void,
raw_framebuffer_1.as_mut_ptr() as *mut c_void,
);
buffers.start_thread(display);
let text_style = MonoTextStyle::new(&FONT_6X10, Bgr888::CSS_WHITE);
let mut engine = K3dengine::new(WIDTH as u16, HEIGHT as u16);
engine.camera.set_position(Point3::new(0.0, 0.0, -4.0));
engine.camera.set_target(Point3::new(0.0, 0.0, 0.0));
engine.camera.set_fovy(PI / 4.0);
let mut perf = PerformanceCounter::new();
// perf.only_fps(true);
// TODO: get Render loop and framebuffer into lib
println!("Starting render loop ... ");
loop {
let fbuf = buffers.swap_framebuffer();
perf.start_of_frame();
engine.render([&locations], |p| draw(p, fbuf));
perf.add_measurement("render");
Text::new(perf.get_text(), Point::new(20, 20), text_style)
.draw(fbuf)
.unwrap();
buffers.send_framebuffer();
perf.add_measurement("draw");
perf.print();
}
println!("all done. Last perf: {}", perf.get_text());
}
embedded-graphics-core
: For pixel color representationnalgebra
: For matrix math and transformationsline_drawing
: For line rasterizationdrm
: For interfacing with the Direct Rendering ManagerThe library includes performance counters that can be used to measure rendering time and optimize your application.
use drm_gfx::perfcounter::PerfCounter;
let mut perf = PerfCounter::new();
perf.start();
// Perform rendering
perf.end();
println!("Rendering took {} ms", perf.elapsed_ms());
For improved performance, the library supports double buffering:
use drm_gfx::doublebuffer::DoubleBuffer;
let mut buffer = DoubleBuffer::new(width, height);
// In your render loop:
buffer.swap();
let framebuffer = buffer.get_front();
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.
All unit tests are autogenerated by some ai.