drm-gfx 0.1.2

3D graphics rendering for direct rendering manager with optional tokio thread support
Documentation
# drm-gfx
<a href="https://crates.io/crates/drm-gfx"><img alt="crates.io" src="https://img.shields.io/crates/v/drm-gfx"></a>
<a href="https://github.com/FLimburg/drm-gfx/actions"><img alt="actions" src="https://github.com/FLimburg/drm-gfx/actions/workflows/rust.yml/badge.svg"></a>

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://github.com/FLimburg/drm-gfx .

## Features

- 3D mesh rendering with multiple render modes (Points, Lines, Solid, Directional Lighting)
- Camera with configurable position, target, and field of view
- Support for transformations and model matrices
- Backface culling
- Simple lighting model
- Direct rendering to DRM framebuffers
- Double buffering support
- Performance counters for optimization

## Usage

Add this to your `Cargo.toml`:

```toml
[dependencies]
drm-gfx = "0.1.1"
```

### features

use feature tokio-thread to use drm-gfx in a tokio based application

### Basic Example

```rust
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());
}
```

## Supported Render Modes

- **Points**: Renders just the vertices as points
- **Lines**: Renders edges of the mesh as lines
- **Solid**: Renders filled triangles with backface culling
- **SolidLightDir**: Adds directional lighting to solid rendering

## Dependencies

- `embedded-graphics-core`: For pixel color representation
- `nalgebra`: For matrix math and transformations
- `line_drawing`: For line rasterization
- `drm`: For interfacing with the Direct Rendering Manager

## Performance

The library includes performance counters that can be used to measure rendering time and optimize your application.

```rust
use drm_gfx::perfcounter::PerfCounter;

let mut perf = PerfCounter::new();
perf.start();
// Perform rendering
perf.end();
println!("Rendering took {} ms", perf.elapsed_ms());
```

## Framebuffer Optimization

For improved performance, the library supports double buffering:

```rust
use drm_gfx::doublebuffer::DoubleBuffer;

let mut buffer = DoubleBuffer::new(width, height);

// In your render loop:
buffer.swap();
let framebuffer = buffer.get_front();
```

## License

Licensed under either of

 * Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

## Contribution

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.

## unit test disclaimer

All unit tests are autogenerated by some ai.