fix(fbcond): buffer TextScreen writes while display map is unavailable
fbcond can start before vesad has registered the display, leaving TextScreen.display.map as None. The old write() silently dropped all output in that state, so getty/login prompts written during the race window never appeared. - Add pending_writes buffer to TextScreen. - Buffer writes when display.map is None and log a warning. - Flush buffered writes after a successful display handoff. - Upgrade handoff success logs from debug to info so they appear in the default boot log.
This commit is contained in:
@@ -33,11 +33,11 @@ impl Display {
|
||||
};
|
||||
let new_display_handle = V2GraphicsHandle::from_file(display_file).unwrap();
|
||||
|
||||
log::debug!("fbcond: Opened new display");
|
||||
log::info!("fbcond: Opened new display");
|
||||
|
||||
match V2DisplayMap::new(new_display_handle) {
|
||||
Ok(map) => {
|
||||
log::debug!(
|
||||
log::info!(
|
||||
"fbcond: Mapped new display with size {}x{}",
|
||||
map.buffer.buffer().size().0,
|
||||
map.buffer.buffer().size().1,
|
||||
|
||||
@@ -10,6 +10,7 @@ pub struct TextScreen {
|
||||
inner: console_draw::TextScreen,
|
||||
ctrl: bool,
|
||||
input: VecDeque<u8>,
|
||||
pending_writes: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl TextScreen {
|
||||
@@ -19,12 +20,16 @@ impl TextScreen {
|
||||
inner: console_draw::TextScreen::new(),
|
||||
ctrl: false,
|
||||
input: VecDeque::new(),
|
||||
pending_writes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_handoff(&mut self) {
|
||||
log::info!("fbcond: Performing handoff");
|
||||
self.display.reopen_for_handoff();
|
||||
if self.display.map.is_some() {
|
||||
self.flush_pending_writes();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input(&mut self, event: &Event) {
|
||||
@@ -127,8 +132,42 @@ impl TextScreen {
|
||||
let damage = self.inner.write(map, buf, &mut self.input);
|
||||
|
||||
self.display.sync_rect(damage);
|
||||
} else {
|
||||
log::warn!(
|
||||
"fbcond: TextScreen::write() called while display map is None; \
|
||||
buffering {} bytes ({} pending chunks). Will flush after handoff.",
|
||||
buf.len(),
|
||||
self.pending_writes.len() + 1,
|
||||
);
|
||||
self.pending_writes.push(buf.to_vec());
|
||||
}
|
||||
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
pub fn flush_pending_writes(&mut self) {
|
||||
if self.pending_writes.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let count = self.pending_writes.len();
|
||||
log::info!(
|
||||
"fbcond: Flushing {} pending write chunks after display handoff",
|
||||
count,
|
||||
);
|
||||
|
||||
if let Some(map) = &mut self.display.map {
|
||||
for pending in self.pending_writes.drain(..) {
|
||||
Display::handle_resize(map, &mut self.inner);
|
||||
let damage = self.inner.write(map, &pending, &mut self.input);
|
||||
map.dirty_fb(damage).unwrap();
|
||||
}
|
||||
} else {
|
||||
log::error!(
|
||||
"fbcond: flush_pending_writes called but display map is still None; \
|
||||
keeping {} buffered chunks",
|
||||
self.pending_writes.len(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user