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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
pub mod common;
pub mod mxcfb;
pub mod screeninfo;
#[cfg(feature = "framebuffer-storage")]
pub mod storage;
#[cfg(feature = "framebuffer")]
pub mod io;
#[cfg(feature = "framebuffer")]
pub mod swtfb_client;
pub use cgmath;
pub trait FramebufferIO {
/// Writes an arbitrary length frame into the framebuffer
fn write_frame(&mut self, frame: &[u8]);
/// Writes a single pixel at `pos` with value `v`
fn write_pixel(&mut self, pos: cgmath::Point2<i32>, v: common::color);
/// Reads the value of the pixel at `pos`
fn read_pixel(&self, pos: cgmath::Point2<u32>) -> common::color;
/// Reads the value at offset `ofst` from the mmapp'ed framebuffer region
fn read_offset(&self, ofst: isize) -> u8;
/// Dumps the contents of the specified rectangle into a `Vec<u8>` from which
/// you can later create a CompressedCanvasState or pass to restore_region().
/// The pixel format is rgb565_le.
fn dump_region(&self, rect: common::mxcfb_rect) -> Result<Vec<u8>, &'static str>;
/// Restores into the framebuffer the contents of the specified rectangle from a u8 slice
fn restore_region(
&mut self,
rect: common::mxcfb_rect,
data: &[u8],
) -> Result<u32, &'static str>;
}
#[cfg(feature = "framebuffer-drawing")]
mod graphics;
#[cfg(feature = "framebuffer-drawing")]
pub mod draw;
#[cfg(feature = "framebuffer-drawing")]
pub trait FramebufferDraw {
#[cfg(feature = "image")]
/// Draws `img` at `pos` with 1:1 scaling
fn draw_image(&mut self, img: &image::RgbImage, pos: cgmath::Point2<i32>)
-> common::mxcfb_rect;
/// Draws a straight line
fn draw_line(
&mut self,
start: cgmath::Point2<i32>,
end: cgmath::Point2<i32>,
width: u32,
v: common::color,
) -> common::mxcfb_rect;
/// Draws a circle using Bresenham circle algorithm
fn draw_circle(
&mut self,
pos: cgmath::Point2<i32>,
rad: u32,
c: common::color,
) -> common::mxcfb_rect;
/// Fills a circle
fn fill_circle(
&mut self,
pos: cgmath::Point2<i32>,
rad: u32,
c: common::color,
) -> common::mxcfb_rect;
/// Draws a polygon
fn draw_polygon(
&mut self,
_: &[cgmath::Point2<i32>],
fill: bool,
c: common::color,
) -> common::mxcfb_rect;
/// Draws a bezier curve begining at `startpt`, with control point `ctrlpt`, ending at `endpt` with `color`
fn draw_bezier(
&mut self,
startpt: cgmath::Point2<f32>,
ctrlpt: cgmath::Point2<f32>,
endpt: cgmath::Point2<f32>,
width: f32,
samples: i32,
v: common::color,
) -> common::mxcfb_rect;
/// Draws a bezier curve begining at `startpt`, with control point `ctrlpt`, ending at `endpt`
/// with a width at each point and color `color`
fn draw_dynamic_bezier(
&mut self,
startpt: (cgmath::Point2<f32>, f32),
ctrlpt: (cgmath::Point2<f32>, f32),
endpt: (cgmath::Point2<f32>, f32),
samples: i32,
v: common::color,
) -> common::mxcfb_rect;
/// Draws `text` at `pos` with `color` using scale `size`
#[cfg(feature = "framebuffer-text-drawing")]
fn draw_text(
&mut self,
pos: cgmath::Point2<f32>,
text: &str,
size: f32,
col: common::color,
dryrun: bool,
) -> common::mxcfb_rect;
/// Draws a 1px border rectangle of size `size` at `pos` with `border_px` border thickness
fn draw_rect(
&mut self,
pos: cgmath::Point2<i32>,
size: cgmath::Vector2<u32>,
border_px: u32,
c: common::color,
);
/// Fills rectangle of size `size` at `pos`
fn fill_rect(&mut self, pos: cgmath::Point2<i32>, size: cgmath::Vector2<u32>, c: common::color);
/// Clears the framebuffer however does not perform a refresh
fn clear(&mut self);
}
#[cfg(feature = "framebuffer")]
pub mod core;
pub trait FramebufferBase {
/// Toggles the EPD Controller (see https://wiki.mobileread.com/wiki/EPD_controller)
fn set_epdc_access(&mut self, state: bool);
/// Toggles autoupdate mode
fn set_autoupdate_mode(&mut self, mode: u32);
/// Toggles update scheme
fn set_update_scheme(&mut self, scheme: u32);
/// Creates a FixScreeninfo struct and fills it using ioctl
fn get_fix_screeninfo(device: &std::fs::File) -> screeninfo::FixScreeninfo;
/// Creates a VarScreeninfo struct and fills it using ioctl
fn get_var_screeninfo(device: &std::fs::File) -> screeninfo::VarScreeninfo;
/// Makes the proper ioctl call to set the VarScreenInfo.
/// You must first update the contents of self.var_screen_info
/// and then call this function.
fn put_var_screeninfo(
device: &std::fs::File,
var_screen_info: &mut screeninfo::VarScreeninfo,
) -> bool;
fn update_var_screeninfo(&mut self) -> bool;
}
pub enum PartialRefreshMode {
DryRun,
Async,
Wait,
}
#[cfg(feature = "framebuffer")]
pub mod refresh;
pub trait FramebufferRefresh {
/// Refreshes the entire screen with the provided parameters. If `wait_completion` is
/// set to true, doesn't return before the refresh has been completed. Returns the marker.
fn full_refresh(
&self,
waveform_mode: common::waveform_mode,
temperature: common::display_temp,
dither_mode: common::dither_mode,
quant_bit: i32,
wait_completion: bool,
) -> u32;
/// Refreshes the given `region` with the provided parameters. If `mode` is `DryRun` or
/// `Wait`, this function won't return before the `DryRun`'s collision_test or
/// refresh has been completed. In `Async` mode, this function will return immediately
/// and return a `marker` which can then later be fed to `wait_refresh_complete` to wait
/// for its completion. In `DryRun`, it will return the `collision_test` result.
///
/// `force_full_refresh` allows rare cases where you may want to do a full refresh on a
/// partial region. 99.9% of of the time, you want this set to `false`.
///
/// Some additional points to note:
///
/// 1) PxP must process 8x8 pixel blocks, and all pixels in each block
/// are considered for auto-waveform mode selection. If the
/// update region is not 8x8 aligned, additional unwanted pixels
/// will be considered in auto-waveform mode selection.
///
/// 2) PxP input must be 32-bit aligned, so any update
/// address not 32-bit aligned must be shifted to meet the
/// 32-bit alignment. The PxP will thus end up processing pixels
/// outside of the update region to satisfy this alignment restriction,
/// which can affect auto-waveform mode selection.
///
/// 3) If input fails 32-bit alignment, and the resulting expansion
/// of the processed region would add at least 8 pixels more per
/// line than the original update line width, the EPDC would
/// cause screen artifacts by incorrectly handling the 8+ pixels
/// at the end of each line.
#[allow(clippy::too_many_arguments)]
fn partial_refresh(
&self,
region: &common::mxcfb_rect,
mode: PartialRefreshMode,
waveform_mode: common::waveform_mode,
temperature: common::display_temp,
dither_mode: common::dither_mode,
quant_bit: i32,
force_full_refresh: bool,
) -> u32;
/// Takes a marker returned by `partial_refresh` and blocks until that
/// refresh has been reflected on the display.
/// Returns the collusion_test result which is supposed to be
/// related to the collusion information.
fn wait_refresh_complete(&self, marker: u32) -> u32;
}