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 fn waveform_for(scenario: RenderScenario) -> u32 {
80 match scenario {
81 RenderScenario::Transition => WAVE_GL16,
82 RenderScenario::Content => WAVE_GL16,
83 RenderScenario::Animation => WAVE_A2,
84 }
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum RenderScenario {
89 Transition,
90 Content,
91 Animation,
92}
93
94pub fn diff_rows(prev: &[u8], cur: &[u8], w: usize, h: usize) -> Option<(usize, usize)> {
102 let mut min_y = h;
103 let mut max_y = 0;
104 let mut dirty = false;
105 for y in 0..h {
106 let base = y * w * 2;
107 if prev[base..base + w * 2] != cur[base..base + w * 2] {
108 dirty = true;
109 if y < min_y {
110 min_y = y;
111 }
112 if y > max_y {
113 max_y = y;
114 }
115 }
116 }
117 if !dirty {
118 return None;
119 }
120 const A: usize = 8;
121 let top = (min_y / A) * A;
122 let bottom = ((max_y + A) / A) * A;
123 let rh = bottom.min(h) - top;
124 Some((top, rh))
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 fn make_buf(w: usize, h: usize, fill: u8) -> Vec<u8> {
132 vec![fill; w * h * 2]
133 }
134
135 #[test]
136 fn diff_rows_detects_change() {
137 let w = 10;
138 let h = 16;
139 let prev = make_buf(w, h, 0);
140 let mut cur = prev.clone();
141 let px = (5 * w + 3) * 2;
142 cur[px] = 1;
143 cur[px + 1] = 1;
144 let (top, rh) = diff_rows(&prev, &cur, w, h).unwrap();
145 assert_eq!(top, 0);
146 assert!(rh > 0);
147 }
148
149 #[test]
150 fn diff_rows_returns_none_when_identical() {
151 let w = 10;
152 let h = 10;
153 let buf = make_buf(w, h, 0);
154 assert!(diff_rows(&buf, &buf, w, h).is_none());
155 }
156
157 #[test]
158 fn diff_rows_aligns_to_8px_boundary() {
159 let w = 10;
160 let h = 32;
161 let prev = make_buf(w, h, 0);
162 let mut cur = prev.clone();
163 let px = (13 * w) * 2;
164 cur[px] = 1;
165 let (top, rh) = diff_rows(&prev, &cur, w, h).unwrap();
166 assert_eq!(top, 8);
167 assert_eq!(rh, 8);
168 }
169}