#![allow(unused_imports)] #![allow(unused_variables)] use clap::{App, Arg}; use himpp::{ hifb, hitde::{ TdeCanvas, TdeColor, TdeColorFmt, TdeDev, TdeJob, TdeLine, TdeMemory, TdeOptBuilder, TdeOutAlphaFrom, TdePatternFillOpt, TdeSurfaceLoader, }, mpi::hdmi::{HdmiCore, HdmiId, HdmiPortBuilder}, mpi::sys::{SysBinder, SysManager, ViVpssMode}, mpi::types::{DynamicRange, PixelFormat, Rect, Size, VideoInterface, VideoStandard, WdrMode}, mpi::vb::{VbConfigBuilder, VbManager, VbRemapMode}, mpi::vo::{VoChn, VoChnAttrBuilder, VoDev, VoLayer, VoPubAttrBuilder, VoVideoLayerAttrBuilder}, mpi::{sys, vb}, }; use pavo_traits::AlignUpwards; use poller::{EventContext, Events, Poller}; use std::fs::File; use std::io::prelude::*; use std::sync::{Arc, Mutex}; enum MoveDirection { Left, Right, Up, Down, } fn move_direction(rect: &Rect, clip: &Rect) -> MoveDirection { let tl1 = rect.top_left(); let tl2 = clip.top_left(); let tr1 = rect.top_right(); let tr2 = clip.top_right(); let bl1 = rect.bottom_left(); let bl2 = clip.bottom_left(); let br1 = rect.bottom_right(); let br2 = clip.bottom_right(); if tl1 == tl2 || (tr1.x < tr2.x && tr1.y == tr2.y) { MoveDirection::Right } else if tr1 == tr2 || (br1.y < br2.y && br1.x == br2.x) { MoveDirection::Down } else if br1 == br2 || (bl1.x > bl2.x && bl1.y == bl2.y) { MoveDirection::Left } else if bl1 == bl2 || (tl1.y > tl2.y && tl1.x == tl2.x) { MoveDirection::Up } else { MoveDirection::Right } } fn move_rect(rect: &Rect, clip: &Rect, speed: isize) -> Rect { match move_direction(rect, clip) { MoveDirection::Left => rect.translated(-speed, 0), MoveDirection::Right => rect.translated(speed, 0), MoveDirection::Up => rect.translated(0, -speed), MoveDirection::Down => rect.translated(0, speed), } } fn main() -> Result<(), Box> { let matches = App::new("tde-fb") .version("1.0") .author("Varphone Wong ") .about("The example of pipeline: HiTDE -> HiFB") .arg( Arg::with_name("framerate") .short("f") .long("framerate") .help("Set the Video Framerate") .takes_value(true), ) .arg( Arg::with_name("vo-size") .short("o") .long("vo-size") .help("Set the Video Ouput Size") .takes_value(true), ) .get_matches(); let fps: u32 = matches .value_of("framerate") .unwrap_or("60") .parse() .unwrap(); let vo_size = Size::from(matches.value_of("vo-size").unwrap_or("1920x1080")); let vb_pool1 = (vo_size.width * vo_size.height * 4).align_upwards(64); let vb_pool2 = (vo_size.width * vo_size.height * 3).align_upwards(64); let vb_pool3 = (vo_size.width * vo_size.height * 2).align_upwards(64); let vb_pool4 = (vo_size.width * vo_size.height * 3 / 2).align_upwards(64); let vb_conf = VbConfigBuilder::new() .pool(vb_pool1.into(), 4, VbRemapMode::None, "") .pool(vb_pool2.into(), 4, VbRemapMode::None, "") .pool(vb_pool3.into(), 4, VbRemapMode::None, "") .pool(vb_pool3.into(), 4, VbRemapMode::None, "") .build(); let _vb_mgr = VbManager::new(&vb_conf, &[]); let _sys_mgr = SysManager::with_align(64, Some(_vb_mgr)); let vo_attr = VoPubAttrBuilder::new() .with_bg_color(0xff00_0000) .with_video_interface(VideoInterface::Hdmi) .with_video_standard(VideoStandard::Hd1080p60) .build(); let vo_dev0 = Arc::new(VoDev::new(0, &vo_attr)); let hdmi_core = Arc::new(HdmiCore::new()); let hdmi_port = HdmiPortBuilder::with_dvi_1080p60(HdmiId::Hdmi0, Arc::clone(&hdmi_core)).build(); hdmi_port.start()?; let mut fb = hifb::FrameBuffer::new_ext("/dev/fb0").unwrap(); fb.set_pixel_format(hifb::PixelFormat::Argb8888).unwrap(); fb.set_resolution(vo_size.width, vo_size.height).unwrap(); fb.set_num_buffers(2).unwrap(); fb.set_compression(false).unwrap(); fb.enable_alpha().unwrap(); fb.enable_alpha_channel(0xff).unwrap(); fb.show().unwrap(); let tde = Arc::new(TdeDev::new()); let pic = TdeSurfaceLoader::from_bytes( include_bytes!("data/images/dog_bike_car.jpg"), Some(TdeColorFmt::Argb8888), )?; let pic_rect = Rect::with_size(pic.size()); let fixed_rect = pic_rect.translated(10, 10); let mut moved_rect = pic_rect; let mut time: u32 = 0; let mut poller = Poller::new()?; poller.add(0, Events::new().read(), None).unwrap(); println!("Press enter to exit ..."); 'outer: loop { let events = poller.pull_events(8).unwrap(); for (_fd, _events, ctx) in events.iter() { match ctx { Some(x) => {} None => { if _fd == &0 { break 'outer; } } } } // Create the surface from hifb for drawing. let dst = TdeSurfaceLoader::from_hifb(&fb)?; let dst_rect = Rect::with_size(dst.size()); // Move the dynamic picture display rect. let speed = ((time as f32).to_radians().sin() * 10.0f32).abs() as isize; moved_rect = move_rect(&moved_rect, &dst_rect, speed + 1).clipped(&dst_rect); // Wait for vblank ready. fb.vblank()?; // Create a new canvas to drawing. let mut canvas = TdeCanvas::new(&tde, &dst, &dst_rect); // Clear the canvas with blue color. canvas.clear(None, TdeColor::rgba(0, 0, 255, 128))?; // Drw fixed picture with box-shadow. canvas.draw_pixmap(&pic, &fixed_rect, 0xff)?; canvas.box_shadow(&fixed_rect, 0xf0)?; // Drw moved picture with box-shadow. canvas.draw_pixmap(&pic, &moved_rect, 0xf0)?; canvas.box_shadow(&moved_rect, 0xd0)?; // Draw cross lines. let color = TdeColor::packed(0xb0ff_ff00); let x = (dst_rect.width() / 4) as i32; let y = (dst_rect.height() / 2) as i32; let w = (dst_rect.width() / 2) as i32; canvas.draw_straight_line(&TdeLine::new_hline(x, y, w, color, 3))?; let x = (dst_rect.width() / 2) as i32; let y = (dst_rect.height() / 4) as i32; let h = (dst_rect.height() / 2) as i32; canvas.draw_straight_line(&TdeLine::new_vline(x, y, h, color, 3))?; // Refresh display buffers. fb.refresh()?; time += 1; } Ok(()) }