kobo_core/rendering/
eink.rs1pub const FBIOGET_VSCREENINFO: libc::c_ulong = 0x4600;
10pub const FBIOGET_FSCREENINFO: libc::c_ulong = 0x4602;
11pub const MXCFB_SEND_UPDATE: libc::c_ulong = 0x4024462E;
12pub const MXCFB_WAIT_FOR_UPDATE_COMPLETE: libc::c_ulong = 0x4004462F;
13
14#[repr(C)]
15#[derive(Default)]
16pub struct FbVarScreeninfo {
17 pub xres: u32,
18 pub yres: u32,
19 pub xres_virtual: u32,
20 pub yres_virtual: u32,
21 pub xoffset: u32,
22 pub yoffset: u32,
23 pub bits_per_pixel: u32,
24 pub grayscale: u32,
25 pub rest: [u32; 32],
26}
27
28#[repr(C)]
29#[derive(Default)]
30pub struct FbFixScreeninfo {
31 id: [u8; 16],
32 pub smem_start: usize,
33 pub smem_len: u32,
34 typ: u32,
35 type_aux: u32,
36 visual: u32,
37 xpanstep: u16,
38 ypanstep: u16,
39 ywrapstep: u16,
40 pub line_length: u32,
41 rest: [u32; 16],
42}
43
44#[repr(C)]
45pub struct MxcfbRect {
46 pub top: u32,
47 pub left: u32,
48 pub width: u32,
49 pub height: u32,
50}
51
52#[repr(C)]
53pub struct MxcfbUpdateData {
54 pub update_region: MxcfbRect,
55 pub waveform_mode: u32,
56 pub update_mode: u32,
57 pub update_marker: u32,
58 pub temp: u32,
59 pub flags: u32,
60}
61
62pub const WAVE_INIT: u32 = 0;
63pub const WAVE_DU: u32 = 1;
64pub const WAVE_GC16: u32 = 2;
65pub const WAVE_GL16: u32 = 3;
66pub const WAVE_A2: u32 = 4;
67pub const WAVE_GLR16: u32 = 5;
68pub const WAVE_GLD16: u32 = 6;
69
70pub const WAVE_REAGL_MTK: u32 = 4;
80
81pub fn waveform_for(scenario: RenderScenario) -> u32 {
92 match scenario {
93 RenderScenario::Transition => WAVE_GL16,
94 RenderScenario::Content => WAVE_GL16,
95 RenderScenario::Animation => WAVE_A2,
96 }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub enum RenderScenario {
101 Transition,
102 Content,
103 Animation,
104}
105
106pub fn diff_rows(prev: &[u8], cur: &[u8], w: usize, h: usize) -> Option<(usize, usize)> {
114 let mut min_y = h;
115 let mut max_y = 0;
116 let mut dirty = false;
117 for y in 0..h {
118 let base = y * w * 2;
119 if prev[base..base + w * 2] != cur[base..base + w * 2] {
120 dirty = true;
121 if y < min_y {
122 min_y = y;
123 }
124 if y > max_y {
125 max_y = y;
126 }
127 }
128 }
129 if !dirty {
130 return None;
131 }
132 const A: usize = 8;
133 let top = (min_y / A) * A;
134 let bottom = ((max_y + A) / A) * A;
135 let rh = bottom.min(h) - top;
136 Some((top, rh))
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 fn make_buf(w: usize, h: usize, fill: u8) -> Vec<u8> {
144 vec![fill; w * h * 2]
145 }
146
147 #[test]
148 fn diff_rows_detects_change() {
149 let w = 10;
150 let h = 16;
151 let prev = make_buf(w, h, 0);
152 let mut cur = prev.clone();
153 let px = (5 * w + 3) * 2;
154 cur[px] = 1;
155 cur[px + 1] = 1;
156 let (top, rh) = diff_rows(&prev, &cur, w, h).unwrap();
157 assert_eq!(top, 0);
158 assert!(rh > 0);
159 }
160
161 #[test]
162 fn diff_rows_returns_none_when_identical() {
163 let w = 10;
164 let h = 10;
165 let buf = make_buf(w, h, 0);
166 assert!(diff_rows(&buf, &buf, w, h).is_none());
167 }
168
169 #[test]
170 fn diff_rows_aligns_to_8px_boundary() {
171 let w = 10;
172 let h = 32;
173 let prev = make_buf(w, h, 0);
174 let mut cur = prev.clone();
175 let px = (13 * w) * 2;
176 cur[px] = 1;
177 let (top, rh) = diff_rows(&prev, &cur, w, h).unwrap();
178 assert_eq!(top, 8);
179 assert_eq!(rh, 8);
180 }
181}