embedded_3dgfx/
command_buffer.rs1use heapless::Vec;
2
3use crate::{
4 DrawPrimitive,
5 error::{BudgetKind, RenderError},
6};
7
8#[derive(Debug, Clone)]
9pub enum RenderCommand {
10 ClearColor(embedded_graphics_core::pixelcolor::Rgb565),
11 ClearDepth(u32),
12 Draw(DrawPrimitive),
13}
14
15pub struct CommandBuffer<const MAX: usize> {
16 commands: Vec<RenderCommand, MAX>,
17}
18
19impl<const MAX: usize> CommandBuffer<MAX> {
20 pub const fn new() -> Self {
21 Self {
22 commands: Vec::new(),
23 }
24 }
25
26 pub fn clear(&mut self) {
27 self.commands.clear();
28 }
29
30 pub fn len(&self) -> usize {
31 self.commands.len()
32 }
33
34 pub fn is_empty(&self) -> bool {
35 self.commands.is_empty()
36 }
37
38 pub fn push(&mut self, cmd: RenderCommand) -> Result<(), RenderError> {
39 self.commands.push(cmd).map_err(|_| {
40 RenderError::OutOfBudget(BudgetKind::DrawPrimitives {
41 attempted: self.commands.len() + 1,
42 max: MAX,
43 })
44 })
45 }
46
47 pub fn iter(&self) -> core::slice::Iter<'_, RenderCommand> {
48 self.commands.iter()
49 }
50
51 pub fn get(&self, index: usize) -> Option<&RenderCommand> {
52 self.commands.get(index)
53 }
54}
55
56impl<const MAX: usize> Default for CommandBuffer<MAX> {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 use embedded_graphics_core::pixelcolor::Rgb565;
66 use nalgebra::Point2;
67
68 #[test]
69 fn new_buffer_starts_empty() {
70 let buf: CommandBuffer<4> = CommandBuffer::new();
71 assert_eq!(buf.len(), 0);
72 assert!(buf.is_empty());
73 }
74
75 #[test]
76 fn push_and_get_roundtrip() {
77 let mut buf: CommandBuffer<4> = CommandBuffer::new();
78 buf.push(RenderCommand::Draw(DrawPrimitive::ColoredPoint(
79 Point2::new(3, 7),
80 Rgb565::new(31, 0, 0),
81 )))
82 .unwrap();
83 assert_eq!(buf.len(), 1);
84 assert!(matches!(
85 buf.get(0),
86 Some(RenderCommand::Draw(DrawPrimitive::ColoredPoint(_, _)))
87 ));
88 }
89
90 #[test]
91 fn push_over_capacity_returns_budget_error() {
92 let mut buf: CommandBuffer<1> = CommandBuffer::new();
93 buf.push(RenderCommand::ClearDepth(0)).unwrap();
94 let err = buf
95 .push(RenderCommand::ClearDepth(1))
96 .expect_err("overflow must fail");
97 assert_eq!(
98 err,
99 RenderError::OutOfBudget(BudgetKind::DrawPrimitives {
100 attempted: 2,
101 max: 1
102 })
103 );
104 }
105}