1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use libc;
use std::os::unix::io::AsRawFd;
use std::sync::atomic::Ordering;
use fb;
use mxc_types;
use mxc_types::{mxcfb_update_marker_data, mxcfb_update_data};
macro_rules! max {
($x: expr) => ($x);
($x: expr, $($z: expr),+) => (::std::cmp::max($x, max!($($z),*)));
}
pub trait FramebufferRefresh {
fn refresh(
&mut self,
region: &mxc_types::mxcfb_rect,
update_mode: mxc_types::update_mode,
waveform_mode: mxc_types::waveform_mode,
temperature: mxc_types::display_temp,
dither_mode: mxc_types::dither_mode,
quant_bit: i32,
flags: u32,
) -> u32;
fn wait_refresh_complete(&mut self, marker: u32);
}
impl<'a> FramebufferRefresh for fb::Framebuffer<'a> {
fn refresh(
&mut self,
region: &mxc_types::mxcfb_rect,
update_mode: mxc_types::update_mode,
waveform_mode: mxc_types::waveform_mode,
temperature: mxc_types::display_temp,
dither_mode: mxc_types::dither_mode,
quant_bit: i32,
flags: u32,
) -> u32 {
let mut update_region = region.clone();
if update_region.left >= mxc_types::DISPLAYWIDTH as u32 ||
update_region.top >= mxc_types::DISPLAYHEIGHT as u32 {
return 0;
}
update_region.width = max!(update_region.width, 8);
update_region.height = max!(update_region.height, 8);
let max_x = update_region.left + update_region.width;
if max_x > mxc_types::DISPLAYWIDTH as u32 {
update_region.width -= max_x - (mxc_types::DISPLAYWIDTH as u32);
}
let max_y = update_region.top + update_region.height;
if max_y > mxc_types::DISPLAYHEIGHT as u32 {
update_region.height -= max_y - (mxc_types::DISPLAYHEIGHT as u32);
}
let whole = mxcfb_update_data {
update_mode: update_mode as u32,
update_marker: *self.marker.get_mut() as u32,
waveform_mode: waveform_mode as u32,
temp: temperature as i32,
flags,
quant_bit,
dither_mode: dither_mode as i32,
update_region,
..Default::default()
};
let pt: *const mxcfb_update_data = &whole;
unsafe {
libc::ioctl(self.device.as_raw_fd(), mxc_types::MXCFB_SEND_UPDATE, pt);
}
self.marker.swap(whole.update_marker + 1, Ordering::Relaxed);
return whole.update_marker;
}
fn wait_refresh_complete(&mut self, marker: u32) {
let mut markerdata = mxcfb_update_marker_data {
update_marker: marker,
collision_test: 0,
};
unsafe {
libc::ioctl(
self.device.as_raw_fd(),
mxc_types::MXCFB_WAIT_FOR_UPDATE_COMPLETE,
&mut markerdata,
);
};
}
}