drm_gfx/
drm_render_target.rs1use drm::control::{Device as ControlDevice, dumbbuffer::DumbBuffer, framebuffer};
3use crate::card::Card;
5use drm::buffer::{Buffer, DrmFourcc};
6use drm::control::{Mode, connector, crtc};
7use log::{debug, error, trace};
8
9pub struct RenderTarget {
10 pub card: Card,
11 pub crtc: crtc::Handle,
12 pub connection: connector::Handle,
13 pub fb: framebuffer::Handle,
14 pub db: DumbBuffer,
15 pub width: usize,
16 pub height: usize,
17 pub format: DrmFourcc,
18 pub mode: Mode,
19}
20
21impl Default for RenderTarget {
22 fn default() -> Self {
23 let device_paths = [
24 "/dev/dri/card0",
25 "/dev/dri/card1",
26 "/dev/dri/card2",
27 "/dev/dri/renderD128",
28 "/dev/dri/renderD129",
29 ];
30 for dev in device_paths {
31 match Self::new(dev) {
32 Ok(render_target) => {
33 trace!("Created render target for device {dev}");
34 return render_target;
35 }
36 Err(e) => {
37 trace!("Could not created render target for device {dev}: {e}");
38 continue;
39 }
40 }
41 }
42
43 error!("Could not create any render target!");
44 panic!("Could not create any render target!");
45 }
46}
47
48impl RenderTarget {
49 pub fn new(device: &str) -> Result<Self, std::io::Error> {
50 let card = Card::open_global(device)
51 .inspect_err(|e| error!("failed to open device {device}: {e}"))?;
52
53 let res = card
55 .resource_handles()
56 .inspect_err(|e| error!("failed to load resource handle ids from {device}: {e}"))?;
57
58 let coninfo: Vec<connector::Info> = res
59 .connectors()
60 .iter()
61 .flat_map(|con| card.get_connector(*con, true))
62 .collect();
63 let crtcinfo: Vec<crtc::Info> = res
64 .crtcs()
65 .iter()
66 .flat_map(|crtc| card.get_crtc(*crtc))
67 .collect();
68
69 let con = coninfo
71 .iter()
72 .find(|&i| i.state() == connector::State::Connected)
73 .expect("No connected connectors");
74
75 let &mode = con.modes().first().expect("No modes found on connector");
77
78 let (width, height) = mode.size();
79
80 let crtc = crtcinfo.first().expect("No crtcs found");
82
83 let format = DrmFourcc::Xrgb8888;
85
86 let mut db = card
90 .create_dumb_buffer((width.into(), height.into()), format, 32)
91 .expect("Could not create dumb buffer");
92
93 {
95 let mut map = card
96 .map_dumb_buffer(&mut db)
97 .expect("Could not map dumbbuffer");
98 let buf = map.as_mut();
102 let line_length = width as u64 * 4;
103 for j in 0..height {
104 if j % 2 == 0 {
105 continue;
106 }
107 let line_offset = j as u64 * line_length;
108 for i in 0..width {
109 if i % 2 == 0 {
110 continue;
111 }
112 let offset = (line_offset + i as u64 * 4) as usize;
113 if offset + 4 > buf.len() {
114 panic!("Buffer overflow at offset {offset}");
115 }
116 buf[offset] = 128; buf[offset + 1] = 0; buf[offset + 2] = 128; buf[offset + 3] = 255; }
121 }
122 }
123
124 let fb = card
126 .add_framebuffer(&db, 24, 32)
127 .expect("Could not create FB");
128
129 debug!("mode: {mode:#?}");
130 trace!("frame buffer handle:{fb:#?}");
131 trace!("dumb buffer{db:#?}");
132
133 card.set_crtc(crtc.handle(), Some(fb), (0, 0), &[con.handle()], Some(mode))
136 .expect("Could not set CRTC");
137
138 Ok(Self {
139 card,
140 crtc: crtc.handle(),
141 connection: con.handle(),
142 fb,
143 db,
144 width: width as usize,
145 height: height as usize,
146 format,
147 mode,
148 })
149 }
150
151 pub fn destroy(&self) {
152 trace!("Destroy the framebuffer");
153 self.card.destroy_framebuffer(self.fb).unwrap();
154 self.card.destroy_dumb_buffer(self.db).unwrap();
155 }
156
157 pub fn get_info(&self) -> String {
158 format!(
159 "RenderTarget details: mode: {:#?} -- buffer: {:#?}",
160 self.mode, self.db,
161 )
162 }
163}
164
165#[derive(Debug)]
166pub enum FbWriteError {
167 Error,
168}
169pub trait FramebufferTarget {
170 fn eat_framebuffer(&mut self, buf: &[u32]) -> Result<(), FbWriteError>;
171}
172impl FramebufferTarget for RenderTarget {
173 fn eat_framebuffer(&mut self, buffer: &[u32]) -> Result<(), FbWriteError> {
174 let pixel_count = self.db.size().0 as usize * self.db.size().1 as usize;
175 if buffer.len() != pixel_count {
176 panic!(
177 "Buffer length mismatch: expected {}, got {}",
178 pixel_count,
179 buffer.len()
180 );
181 }
182 {
184 let mut map = self
185 .card
186 .map_dumb_buffer(&mut self.db)
187 .expect("Could not map dumbbuffer");
188 let buf = map.as_mut();
189 let buf_line_length = self.width as u64 * 4;
190 let buffer_line_length = self.width as u64;
191 for j in 0..self.height {
192 let buf_line_offset = j as u64 * buf_line_length;
193 let buffer_line_offset = j as u64 * buffer_line_length;
194 for i in 0..self.width {
195 let buf_offset = (buf_line_offset + i as u64 * 4) as usize;
196 let buffer_offset = (buffer_line_offset + i as u64) as usize;
197 buf[buf_offset] = ((buffer[buffer_offset] >> 24) & 0xff) as u8; buf[buf_offset + 1] = ((buffer[buffer_offset] >> 16) & 0xff) as u8; buf[buf_offset + 2] = ((buffer[buffer_offset] >> 8) & 0xff) as u8; buf[buf_offset + 3] = 255; }
209 }
210 }
211 let fb = self
213 .card
214 .add_framebuffer(&self.db, 24, 32)
215 .expect("Could not create FB");
216 self.card
217 .set_crtc(
218 self.crtc,
219 Some(fb),
220 (0, 0),
221 &[self.connection],
222 Some(self.mode),
223 )
224 .expect("Could not set CRTC");
225
226 Ok(())
227 }
228}