1pub mod options;
4pub mod shape_builder;
5
6use crate::graphics::{Vertex2F, Vertex2II, RGB, RGBA};
7use crate::memory::{MainMem, MemoryRegion, Ptr};
8use core::fmt::Debug;
9
10#[derive(Copy, Clone, PartialEq)]
12pub struct DLCmd(u32);
13
14impl DLCmd {
15 pub const LENGTH: u32 = 4;
18
19 pub const DISPLAY: Self = OpCode::DISPLAY.build(0);
20 pub const END: Self = OpCode::END.build(0);
21 pub const CLEAR_ALL: Self = Self::clear(true, true, true);
22 pub const NOP: Self = OpCode::NOP.build(0);
23 pub const RESTORE_CONTEXT: Self = OpCode::RESTORE_CONTEXT.build(0);
24 pub const RETURN: Self = OpCode::RETURN.build(0);
25 pub const SAVE_CONTEXT: Self = OpCode::SAVE_CONTEXT.build(0);
26
27 pub const fn from_raw(raw: u32) -> Self {
31 Self(raw)
32 }
33
34 pub const fn as_raw(&self) -> u32 {
35 self.0
36 }
37
38 pub const fn alpha_test(func: options::TestFunc, ref_val: u8) -> Self {
39 OpCode::ALPHA_FUNC.build((func as u32) << 8 | (ref_val as u32))
40 }
41
42 pub const fn begin(prim: options::GraphicsPrimitive) -> Self {
43 OpCode::BEGIN.build(prim as u32)
44 }
45
46 pub const fn bitmap_cell(idx: u8) -> Self {
47 OpCode::CELL.build((idx & 0b111111) as u32)
48 }
49
50 pub const fn bitmap_ext_format(format: options::BitmapExtFormat) -> Self {
51 OpCode::BITMAP_EXT_FORMAT.build(format as u32)
52 }
53
54 pub const fn bitmap_handle(bmp: options::BitmapHandle) -> Self {
55 OpCode::BITMAP_HANDLE.build(bmp.0 as u32)
56 }
57
58 pub const fn bitmap_layout_l(
59 format: options::BitmapFormat,
60 line_stride: u16,
61 height: u16,
62 ) -> Self {
63 OpCode::BITMAP_LAYOUT.build(
64 (format as u32) << 19
65 | (line_stride as u32 & 0b1111111111) << 9
66 | (height as u32 & 0b111111111),
67 )
68 }
69
70 pub const fn bitmap_layout_h(line_stride: u16, height: u16) -> Self {
71 OpCode::BITMAP_LAYOUT_H.build((line_stride as u32 >> 10) << 2 | (height as u32 >> 10))
72 }
73
74 pub const fn bitmap_layout_pair(
79 format: options::BitmapFormat,
80 line_stride: u16,
81 height: u16,
82 ) -> (Self, Self) {
83 (
84 Self::bitmap_layout_l(format, line_stride, height),
85 Self::bitmap_layout_h(line_stride, height),
86 )
87 }
88
89 const fn physical_bitmap_size(width: u16, height: u16) -> (u16, u16) {
90 (
91 if width < 2048 { width } else { 0 },
92 if height < 2048 { height } else { 0 },
93 )
94 }
95
96 pub const fn bitmap_size_l(
97 width: u16,
98 height: u16,
99 filter: options::BitmapSizeFilter,
100 wrap_x: options::BitmapWrapMode,
101 wrap_y: options::BitmapWrapMode,
102 ) -> Self {
103 let (p_width, p_height) = Self::physical_bitmap_size(width, height);
104 OpCode::BITMAP_SIZE.build(
105 (filter as u32) << 20
106 | (wrap_x as u32) << 19
107 | (wrap_y as u32) << 18
108 | (p_width as u32 & 0b111111111) << 9
109 | (p_height as u32 & 0b111111111),
110 )
111 }
112
113 pub const fn bitmap_size_h(width: u16, height: u16) -> Self {
114 let (p_width, p_height) = Self::physical_bitmap_size(width, height);
115 let p_width = ((p_width as u32) >> 9) & 0b11;
116 let p_height = ((p_height as u32) >> 9) & 0b11;
117 OpCode::BITMAP_SIZE_H.build(p_width << 2 | p_height)
118 }
119
120 pub const fn bitmap_size_pair(
125 width: u16,
126 height: u16,
127 filter: options::BitmapSizeFilter,
128 wrap_x: options::BitmapWrapMode,
129 wrap_y: options::BitmapWrapMode,
130 ) -> (Self, Self) {
131 (
132 Self::bitmap_size_l(width, height, filter, wrap_x, wrap_y),
133 Self::bitmap_size_h(width, height),
134 )
135 }
136
137 pub fn bitmap_source<R: MemoryRegion + MainMem>(ptr: Ptr<R>) -> Self {
140 OpCode::BITMAP_SOURCE.build(ptr.to_raw())
141 }
142
143 pub fn bitmap_swizzle(swizzle: options::BitmapSwizzle) -> Self {
144 OpCode::BITMAP_SWIZZLE.build(swizzle.as_raw())
145 }
146
147 pub fn bitmap_transform_a(coeff: impl Into<options::MatrixCoeff>) -> Self {
148 let coeff: options::MatrixCoeff = coeff.into();
149 OpCode::BITMAP_TRANSFORM_A.build(coeff.to_raw())
150 }
151
152 pub fn bitmap_transform_b(coeff: impl Into<options::MatrixCoeff>) -> Self {
153 let coeff: options::MatrixCoeff = coeff.into();
154 OpCode::BITMAP_TRANSFORM_B.build(coeff.to_raw())
155 }
156
157 pub fn bitmap_transform_c(coeff: impl Into<options::MatrixCoeff>) -> Self {
158 let coeff: options::MatrixCoeff = coeff.into();
159 OpCode::BITMAP_TRANSFORM_C.build(coeff.to_raw())
160 }
161
162 pub fn bitmap_transform_d(coeff: impl Into<options::MatrixCoeff>) -> Self {
163 let coeff: options::MatrixCoeff = coeff.into();
164 OpCode::BITMAP_TRANSFORM_D.build(coeff.to_raw())
165 }
166
167 pub fn bitmap_transform_e(coeff: impl Into<options::MatrixCoeff>) -> Self {
168 let coeff: options::MatrixCoeff = coeff.into();
169 OpCode::BITMAP_TRANSFORM_E.build(coeff.to_raw())
170 }
171
172 pub fn bitmap_transform_f(coeff: impl Into<options::MatrixCoeff>) -> Self {
173 let coeff: options::MatrixCoeff = coeff.into();
174 OpCode::BITMAP_TRANSFORM_F.build(coeff.to_raw())
175 }
176
177 pub const fn blend_func(src: options::BlendFunc, dst: options::BlendFunc) -> Self {
178 OpCode::BLEND_FUNC.build((src as u32) << 3 | dst as u32)
179 }
180
181 pub fn call<R: crate::memory::DisplayListMem>(ptr: Ptr<R>) -> Self {
182 OpCode::CALL.build(ptr.to_raw_offset())
183 }
184
185 pub const fn clear(color: bool, stencil: bool, tag: bool) -> Self {
186 OpCode::CLEAR.build(
187 if color { 0b100 } else { 0b000 }
188 | if stencil { 0b010 } else { 0b000 }
189 | if tag { 0b001 } else { 0b000 },
190 )
191 }
192
193 pub const fn clear_color_rgb(color: RGB) -> Self {
194 OpCode::CLEAR_COLOR_RGB
195 .build((color.r as u32) << 16 | (color.g as u32) << 8 | (color.b as u32) << 0)
196 }
197
198 pub const fn clear_color_alpha(alpha: u8) -> Self {
199 OpCode::CLEAR_COLOR_A.build(alpha as u32)
200 }
201
202 pub const fn clear_color_rgba_pair(color: RGBA) -> (Self, Self) {
203 (
204 Self::clear_color_rgb(color.as_rgb()),
205 Self::clear_color_alpha(color.a),
206 )
207 }
208
209 pub const fn clear_stencil(v: u8) -> Self {
210 OpCode::CLEAR_STENCIL.build(v as u32)
211 }
212
213 pub const fn clear_tag(v: u8) -> Self {
214 OpCode::CLEAR_TAG.build(v as u32)
215 }
216
217 pub const fn color_alpha(alpha: u8) -> Self {
218 OpCode::COLOR_A.build(alpha as u32)
219 }
220
221 pub const fn color_mask(mask: options::ColorMask) -> Self {
222 OpCode::COLOR_MASK.build(mask.to_raw() as u32)
223 }
224
225 pub const fn color_rgb(color: RGB) -> Self {
226 OpCode::COLOR_RGB
227 .build((color.r as u32) << 16 | (color.g as u32) << 8 | (color.b as u32) << 0)
228 }
229
230 pub const fn display() -> Self {
231 Self::DISPLAY
232 }
233
234 pub const fn end() -> Self {
235 Self::END
236 }
237
238 pub fn jump<R: crate::memory::DisplayListMem>(ptr: Ptr<R>) -> Self {
239 OpCode::JUMP.build(ptr.to_raw_offset())
240 }
241
242 pub const fn command_from_macro(num: u8) -> Self {
243 const MASK: u32 = 0b1;
244 OpCode::MACRO.build(num as u32 & MASK)
245 }
246
247 pub const fn line_width(w: u16) -> Self {
248 OpCode::LINE_WIDTH.build((w & 0b111111111111) as u32)
249 }
250
251 pub const fn nop() -> Self {
252 Self::NOP
253 }
254
255 pub fn palette_source<R: MemoryRegion + MainMem>(ptr: Ptr<R>) -> Self {
258 OpCode::PALETTE_SOURCE.build(ptr.to_raw())
259 }
260
261 pub const fn point_size(size: u16) -> Self {
262 const MASK: u32 = 0b0000111111111111;
263 OpCode::POINT_SIZE.build(size as u32 & MASK)
264 }
265
266 pub const fn restore_context() -> Self {
267 Self::RESTORE_CONTEXT
268 }
269
270 pub const fn return_from_call() -> Self {
271 Self::RETURN
272 }
273
274 pub const fn save_context() -> Self {
275 Self::SAVE_CONTEXT
276 }
277
278 pub const fn scissor_size(dims: (u16, u16)) -> Self {
279 const MASK: u32 = 0b111111111111;
280 OpCode::SCISSOR_SIZE.build(((dims.0 as u32 & MASK) << 12) | (dims.1 as u32 & MASK))
281 }
282
283 pub fn scissor_pos(pos: impl Into<crate::graphics::ScissorPos>) -> Self {
284 let pos: crate::graphics::ScissorPos = pos.into();
285 let coords = pos.coords();
286 const MASK: u32 = 0b1111111111;
287 OpCode::SCISSOR_XY.build((coords.0 as u32 & MASK) << 10 | (coords.1 as u32 & MASK))
288 }
289
290 pub fn scissor_rect_pair(rect: impl Into<crate::graphics::ScissorRect>) -> (Self, Self) {
291 let rect: crate::graphics::ScissorRect = rect.into();
292 (
293 Self::scissor_pos(rect.top_left()),
294 Self::scissor_size(rect.size()),
295 )
296 }
297
298 pub const fn stencil_test(func: options::TestFunc, ref_val: u8, mask: u8) -> Self {
299 OpCode::STENCIL_FUNC.build((func as u32) << 16 | (ref_val as u32) << 8 | (mask as u32))
300 }
301
302 pub const fn stencil_mask(mask: u8) -> Self {
303 OpCode::STENCIL_MASK.build(mask as u32)
304 }
305
306 pub const fn stencil_op(fail: options::StencilOp, pass: options::StencilOp) -> Self {
307 OpCode::STENCIL_OP.build(((fail.to_raw() as u32) << 3) | (pass.to_raw() as u32))
308 }
309
310 pub const fn tag(v: u8) -> Self {
311 OpCode::TAG.build(v as u32)
312 }
313
314 pub const fn tag_mask(update: bool) -> Self {
315 OpCode::TAG_MASK.build(if update { 1 } else { 0 })
316 }
317
318 pub fn vertex_2f<Pos: Into<Vertex2F>>(pos: Pos) -> Self {
319 let pos: Vertex2F = pos.into();
320 OpCode::VERTEX2F.build((pos.x as u32) << 15 | (pos.y as u32))
321 }
322
323 pub fn vertex_2ii<Pos: Into<Vertex2II>>(pos: Pos) -> Self {
324 let pos: Vertex2II = pos.into();
325 OpCode::VERTEX2II.build((pos.x as u32) << 21 | (pos.y as u32) << 12)
326 }
327
328 pub const fn vertex_format(fmt: options::VertexFormat) -> Self {
329 OpCode::VERTEX_FORMAT.build(fmt.to_raw() as u32)
330 }
331
332 pub const fn vertex_translate_x(v: i16) -> Self {
333 OpCode::VERTEX_TRANSLATE_X.build(v as u16 as u32)
334 }
335
336 pub const fn vertex_translate_y(v: i16) -> Self {
337 OpCode::VERTEX_TRANSLATE_Y.build(v as u16 as u32)
338 }
339
340 pub const fn vertex_translate_pair(offset: (i16, i16)) -> (Self, Self) {
341 (
342 Self::vertex_translate_x(offset.0),
343 Self::vertex_translate_y(offset.1),
344 )
345 }
346}
347
348pub trait Builder: Sized {
354 type Model: crate::models::Model;
355 type Error;
356
357 fn append_raw_command(&mut self, raw: u32) -> Result<(), Self::Error>;
358
359 fn append_command(&mut self, cmd: DLCmd) -> Result<(), Self::Error> {
360 self.append_raw_command(cmd.as_raw())
361 }
362
363 fn alpha_test(&mut self, func: options::TestFunc, ref_val: u8) -> Result<(), Self::Error> {
364 self.append_command(DLCmd::alpha_test(func, ref_val))
365 }
366
367 fn begin(&mut self, prim: options::GraphicsPrimitive) -> Result<(), Self::Error> {
368 self.append_command(DLCmd::begin(prim))
369 }
370
371 fn bitmap_cell(&mut self, idx: u8) -> Result<(), Self::Error> {
372 self.append_command(DLCmd::bitmap_cell(idx))
373 }
374
375 fn bitmap_ext_format(&mut self, format: options::BitmapExtFormat) -> Result<(), Self::Error> {
376 self.append_command(DLCmd::bitmap_ext_format(format))
377 }
378
379 fn bitmap_handle(&mut self, bmp: options::BitmapHandle) -> Result<(), Self::Error> {
380 self.append_command(DLCmd::bitmap_handle(bmp))
381 }
382
383 fn bitmap_layout_l(
384 &mut self,
385 format: options::BitmapFormat,
386 line_stride: u16,
387 height: u16,
388 ) -> Result<(), Self::Error> {
389 self.append_command(DLCmd::bitmap_layout_l(format, line_stride, height))
390 }
391
392 fn bitmap_layout_h(&mut self, line_stride: u16, height: u16) -> Result<(), Self::Error> {
393 self.append_command(DLCmd::bitmap_layout_h(line_stride, height))
394 }
395
396 fn bitmap_layout(
397 &mut self,
398 format: options::BitmapFormat,
399 line_stride: u16,
400 height: u16,
401 ) -> Result<(), Self::Error> {
402 let pair = DLCmd::bitmap_layout_pair(format, line_stride, height);
403 self.append_command(pair.0)?;
404 self.append_command(pair.1)
405 }
406
407 fn bitmap_size_l(
408 &mut self,
409 width: u16,
410 height: u16,
411 filter: options::BitmapSizeFilter,
412 wrap_x: options::BitmapWrapMode,
413 wrap_y: options::BitmapWrapMode,
414 ) -> Result<(), Self::Error> {
415 self.append_command(DLCmd::bitmap_size_l(width, height, filter, wrap_x, wrap_y))
416 }
417
418 fn bitmap_size_h(&mut self, width: u16, height: u16) -> Result<(), Self::Error> {
419 self.append_command(DLCmd::bitmap_size_h(width, height))
420 }
421
422 fn bitmap_size(
423 &mut self,
424 width: u16,
425 height: u16,
426 filter: options::BitmapSizeFilter,
427 wrap_x: options::BitmapWrapMode,
428 wrap_y: options::BitmapWrapMode,
429 ) -> Result<(), Self::Error> {
430 let pair = DLCmd::bitmap_size_pair(width, height, filter, wrap_x, wrap_y);
431 self.append_command(pair.0)?;
432 self.append_command(pair.1)
433 }
434
435 fn bitmap_swizzle(&mut self, swizzle: options::BitmapSwizzle) -> Result<(), Self::Error> {
436 self.append_command(DLCmd::bitmap_swizzle(swizzle))
437 }
438
439 fn bitmap_source(
440 &mut self,
441 ptr: Ptr<<<Self as Builder>::Model as crate::models::Model>::MainMem>,
442 ) -> Result<(), Self::Error> {
443 self.append_command(DLCmd::bitmap_source(ptr))
444 }
445
446 fn bitmap_source_all(
460 &mut self,
461 bitmap: crate::graphics::Bitmap<
462 <<Self as Builder>::Model as crate::models::Model>::MainMem,
463 >,
464 ) -> Result<(), Self::Error> {
465 self.bitmap_source(bitmap.image_data)?;
466 let base_format: options::BitmapFormat = bitmap.format.into();
467 self.bitmap_layout(base_format, bitmap.stride as u16, bitmap.height as u16)?;
468 if base_format.needs_ext_format() {
469 self.bitmap_ext_format(bitmap.format)?;
470 }
471 if let Some(addr) = bitmap.palette_data {
472 self.palette_source(addr)?;
473 }
474 Ok(())
475 }
476
477 fn bitmap_transform_a(
478 &mut self,
479 coeff: impl Into<options::MatrixCoeff>,
480 ) -> Result<(), Self::Error> {
481 self.append_command(DLCmd::bitmap_transform_a(coeff))
482 }
483
484 fn bitmap_transform_b(
485 &mut self,
486 coeff: impl Into<options::MatrixCoeff>,
487 ) -> Result<(), Self::Error> {
488 self.append_command(DLCmd::bitmap_transform_b(coeff))
489 }
490
491 fn bitmap_transform_c(
492 &mut self,
493 coeff: impl Into<options::MatrixCoeff>,
494 ) -> Result<(), Self::Error> {
495 self.append_command(DLCmd::bitmap_transform_c(coeff))
496 }
497
498 fn bitmap_transform_d(
499 &mut self,
500 coeff: impl Into<options::MatrixCoeff>,
501 ) -> Result<(), Self::Error> {
502 self.append_command(DLCmd::bitmap_transform_d(coeff))
503 }
504
505 fn bitmap_transform_e(
506 &mut self,
507 coeff: impl Into<options::MatrixCoeff>,
508 ) -> Result<(), Self::Error> {
509 self.append_command(DLCmd::bitmap_transform_e(coeff))
510 }
511
512 fn bitmap_transform_f(
513 &mut self,
514 coeff: impl Into<options::MatrixCoeff>,
515 ) -> Result<(), Self::Error> {
516 self.append_command(DLCmd::bitmap_transform_f(coeff))
517 }
518
519 fn bitmap_transform_matrix(
522 &mut self,
523 matrix: impl Into<options::Matrix3x2>,
524 ) -> Result<(), Self::Error> {
525 let matrix: options::Matrix3x2 = matrix.into();
526 self.append_command(DLCmd::bitmap_transform_a(matrix.0 .0))?;
527 self.append_command(DLCmd::bitmap_transform_b(matrix.0 .1))?;
528 self.append_command(DLCmd::bitmap_transform_c(matrix.0 .2))?;
529 self.append_command(DLCmd::bitmap_transform_d(matrix.1 .0))?;
530 self.append_command(DLCmd::bitmap_transform_e(matrix.1 .1))?;
531 self.append_command(DLCmd::bitmap_transform_f(matrix.1 .2))
532 }
533
534 fn blend_func(
535 &mut self,
536 src: options::BlendFunc,
537 dst: options::BlendFunc,
538 ) -> Result<(), Self::Error> {
539 self.append_command(DLCmd::blend_func(src, dst))
540 }
541
542 fn call(
543 &mut self,
544 addr: Ptr<<<Self as Builder>::Model as crate::models::Model>::DisplayListMem>,
545 ) -> Result<(), Self::Error> {
546 self.append_command(DLCmd::call(addr))
547 }
548
549 fn clear(&mut self, color: bool, stencil: bool, tag: bool) -> Result<(), Self::Error> {
550 self.append_command(DLCmd::clear(color, stencil, tag))
551 }
552
553 fn clear_all(&mut self) -> Result<(), Self::Error> {
554 self.append_command(DLCmd::CLEAR_ALL)
555 }
556
557 fn clear_color_rgb(&mut self, color: RGB) -> Result<(), Self::Error> {
558 self.append_command(DLCmd::clear_color_rgb(color))
559 }
560
561 fn clear_color_alpha(&mut self, alpha: u8) -> Result<(), Self::Error> {
562 self.append_command(DLCmd::clear_color_alpha(alpha))
563 }
564
565 fn clear_color_rgba(&mut self, color: RGBA) -> Result<(), Self::Error> {
566 let cmds = DLCmd::clear_color_rgba_pair(color);
567 self.append_command(cmds.0)?;
568 self.append_command(cmds.1)
569 }
570
571 fn clear_stencil(&mut self, v: u8) -> Result<(), Self::Error> {
572 self.append_command(DLCmd::clear_stencil(v))
573 }
574
575 fn clear_tag(&mut self, v: u8) -> Result<(), Self::Error> {
576 self.append_command(DLCmd::clear_tag(v))
577 }
578
579 fn color_rgb(&mut self, color: RGB) -> Result<(), Self::Error> {
580 self.append_command(DLCmd::color_rgb(color))
581 }
582
583 fn color_mask(&mut self, mask: options::ColorMask) -> Result<(), Self::Error> {
584 self.append_command(DLCmd::color_mask(mask))
585 }
586
587 fn color_alpha(&mut self, alpha: u8) -> Result<(), Self::Error> {
588 self.append_command(DLCmd::color_alpha(alpha))
589 }
590
591 fn display(&mut self) -> Result<(), Self::Error> {
592 self.append_command(DLCmd::DISPLAY)
593 }
594
595 fn draw(
601 &mut self,
602 prim: options::GraphicsPrimitive,
603 f: impl FnOnce(shape_builder::VertexBuilder<Self>) -> Result<(), Self::Error>,
604 ) -> Result<(), Self::Error> {
605 self.begin(prim)?;
606 let vb = shape_builder::VertexBuilder::new(self);
607 f(vb)?;
608 self.end()
609 }
610
611 fn draw_iter(
617 &mut self,
618 prim: options::GraphicsPrimitive,
619 iter: impl core::iter::Iterator<Item = crate::graphics::Vertex2F>,
620 ) -> Result<(), Self::Error> {
621 self.begin(prim)?;
622 for v in iter {
623 self.vertex_2f(v)?;
624 }
625 self.end()
626 }
627
628 fn end(&mut self) -> Result<(), Self::Error> {
629 self.append_command(DLCmd::END)
630 }
631
632 fn command_from_macro(&mut self, num: u8) -> Result<(), Self::Error> {
633 self.append_command(DLCmd::command_from_macro(num))
634 }
635
636 fn jump(
637 &mut self,
638 addr: Ptr<<<Self as Builder>::Model as crate::models::Model>::DisplayListMem>,
639 ) -> Result<(), Self::Error> {
640 self.append_command(DLCmd::jump(addr))
641 }
642
643 fn line_width(&mut self, v: u16) -> Result<(), Self::Error> {
644 self.append_command(DLCmd::line_width(v))
645 }
646
647 fn nop(&mut self) -> Result<(), Self::Error> {
648 self.append_command(DLCmd::NOP)
649 }
650
651 fn palette_source(
652 &mut self,
653 ptr: Ptr<<<Self as Builder>::Model as crate::models::Model>::MainMem>,
654 ) -> Result<(), Self::Error> {
655 self.append_command(DLCmd::palette_source(ptr))
656 }
657
658 fn point_size(&mut self, size: u16) -> Result<(), Self::Error> {
659 self.append_command(DLCmd::point_size(size))
660 }
661
662 fn restore_context(&mut self) -> Result<(), Self::Error> {
663 self.append_command(DLCmd::RESTORE_CONTEXT)
664 }
665
666 fn return_from_call(&mut self) -> Result<(), Self::Error> {
667 self.append_command(DLCmd::RETURN)
668 }
669
670 fn save_context(&mut self) -> Result<(), Self::Error> {
671 self.append_command(DLCmd::SAVE_CONTEXT)
672 }
673
674 fn scissor_size(&mut self, dims: (u16, u16)) -> Result<(), Self::Error> {
675 self.append_command(DLCmd::scissor_size(dims))
676 }
677
678 fn scissor_pos(
679 &mut self,
680 pos: impl Into<crate::graphics::ScissorPos>,
681 ) -> Result<(), Self::Error> {
682 self.append_command(DLCmd::scissor_pos(pos))
683 }
684
685 fn scissor_rect(
686 &mut self,
687 rect: impl Into<crate::graphics::ScissorRect>,
688 ) -> Result<(), Self::Error> {
689 let pair = DLCmd::scissor_rect_pair(rect);
690 self.append_command(pair.0)?;
691 self.append_command(pair.1)
692 }
693
694 fn stencil_test(
695 &mut self,
696 func: options::TestFunc,
697 ref_val: u8,
698 mask: u8,
699 ) -> Result<(), Self::Error> {
700 self.append_command(DLCmd::stencil_test(func, ref_val, mask))
701 }
702
703 fn stencil_mask(&mut self, mask: u8) -> Result<(), Self::Error> {
704 self.append_command(DLCmd::stencil_mask(mask))
705 }
706
707 fn stencil_op(
708 &mut self,
709 fail: options::StencilOp,
710 pass: options::StencilOp,
711 ) -> Result<(), Self::Error> {
712 self.append_command(DLCmd::stencil_op(fail, pass))
713 }
714
715 fn tag(&mut self, v: u8) -> Result<(), Self::Error> {
716 self.append_command(DLCmd::tag(v))
717 }
718
719 fn tag_mask(&mut self, update: bool) -> Result<(), Self::Error> {
720 self.append_command(DLCmd::tag_mask(update))
721 }
722
723 fn vertex_2f<Pos: Into<Vertex2F>>(&mut self, pos: Pos) -> Result<(), Self::Error> {
724 self.append_command(DLCmd::vertex_2f(pos))
725 }
726
727 fn vertex_2ii<Pos: Into<Vertex2II>>(&mut self, pos: Pos) -> Result<(), Self::Error> {
728 self.append_command(DLCmd::vertex_2ii(pos))
729 }
730
731 fn vertex_format(&mut self, fmt: options::VertexFormat) -> Result<(), Self::Error> {
732 self.append_command(DLCmd::vertex_format(fmt))
733 }
734
735 fn vertex_translate_x(&mut self, v: i16) -> Result<(), Self::Error> {
736 self.append_command(DLCmd::vertex_translate_x(v))
737 }
738
739 fn vertex_translate_y(&mut self, v: i16) -> Result<(), Self::Error> {
740 self.append_command(DLCmd::vertex_translate_y(v))
741 }
742
743 fn vertex_translate(&mut self, offset: (i16, i16)) -> Result<(), Self::Error> {
744 let pair = DLCmd::vertex_translate_pair(offset);
745 self.append_command(pair.0)?;
746 self.append_command(pair.1)
747 }
748}
749
750pub struct JustBuilder<'a, W: Builder> {
755 w: &'a mut W,
756}
757
758impl<'a, W: Builder> JustBuilder<'a, W> {
759 fn new(w: &'a mut W) -> Self {
760 Self { w: w }
761 }
762}
763
764impl<'a, W: Builder> Builder for JustBuilder<'a, W> {
765 type Error = W::Error;
766 type Model = W::Model;
767
768 fn append_raw_command(&mut self, raw: u32) -> core::result::Result<(), W::Error> {
769 self.w.append_raw_command(raw)
770 }
771}
772
773pub fn just_builder<'a, W: Builder>(wrapped: &'a mut W) -> JustBuilder<'a, W> {
774 JustBuilder::new(wrapped)
775}
776
777impl Into<u32> for DLCmd {
781 fn into(self) -> u32 {
782 self.0
783 }
784}
785
786impl Debug for DLCmd {
787 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
788 write!(f, "DLCmd({:#010x})", self.0)
789 }
790}
791
792#[derive(Clone, Copy, PartialEq, Eq)]
793#[repr(u8)]
794#[allow(non_camel_case_types)]
795enum OpCode {
796 ALPHA_FUNC = 0x09,
797 BEGIN = 0x1F,
798 BITMAP_EXT_FORMAT = 0x2e,
799 BITMAP_HANDLE = 0x05,
800 BITMAP_LAYOUT = 0x07,
801 BITMAP_LAYOUT_H = 0x28,
802 BITMAP_SIZE = 0x08,
803 BITMAP_SIZE_H = 0x29,
804 BITMAP_SOURCE = 0x01,
805 BITMAP_SWIZZLE = 0x2f,
806 BITMAP_TRANSFORM_A = 0x15,
807 BITMAP_TRANSFORM_B = 0x16,
808 BITMAP_TRANSFORM_C = 0x17,
809 BITMAP_TRANSFORM_D = 0x18,
810 BITMAP_TRANSFORM_E = 0x19,
811 BITMAP_TRANSFORM_F = 0x1A,
812 BLEND_FUNC = 0x0b,
813 CALL = 0x1d,
814 CELL = 0x06,
815 CLEAR = 0x26,
816 CLEAR_COLOR_RGB = 0x02,
817 CLEAR_COLOR_A = 0x0F,
818 CLEAR_STENCIL = 0x11,
819 CLEAR_TAG = 0x12,
820 COLOR_A = 0x10,
821 COLOR_MASK = 0x20,
822 COLOR_RGB = 0x04,
823 DISPLAY = 0x00,
824 END = 0x21,
825 JUMP = 0x1e,
826 LINE_WIDTH = 0x0e,
827 MACRO = 0x25,
828 NOP = 0x2d,
829 PALETTE_SOURCE = 0x2a,
830 POINT_SIZE = 0x0d,
831 RESTORE_CONTEXT = 0x23,
832 RETURN = 0x24,
833 SAVE_CONTEXT = 0x22,
834 SCISSOR_SIZE = 0x1c,
835 SCISSOR_XY = 0x1b,
836 STENCIL_FUNC = 0x0a,
837 STENCIL_MASK = 0x13,
838 STENCIL_OP = 0x0c,
839 TAG = 0x03,
840 TAG_MASK = 0x14,
841 VERTEX2F = 0b01000000, VERTEX2II = 0b10000000, VERTEX_FORMAT = 0x27,
844 VERTEX_TRANSLATE_X = 0x2b,
845 VERTEX_TRANSLATE_Y = 0x2c,
846}
847
848impl OpCode {
849 const fn shift(self) -> u32 {
850 (self as u32) << 24
851 }
852
853 const fn build(self, v: u32) -> DLCmd {
854 DLCmd::from_raw(self.shift() | v)
855 }
856}
857
858#[cfg(test)]
859mod tests {
860 use super::*;
861 use crate::models::testing::DisplayListMem as TestDisplayListMem;
862 use crate::models::testing::MainMem as TestMainMem;
863
864 #[test]
865 fn test_dlcmd() {
866 assert_eq!(
867 DLCmd::alpha_test(options::TestFunc::Greater, 254),
868 DLCmd::from_raw(0x090003fe),
869 );
870 assert_eq!(
871 DLCmd::alpha_test(options::TestFunc::Never, 0),
872 DLCmd::from_raw(0x09000000),
873 );
874 assert_eq!(
875 DLCmd::begin(options::GraphicsPrimitive::Bitmaps),
876 DLCmd::from_raw(0x1f000001),
877 );
878 assert_eq!(
879 DLCmd::begin(options::GraphicsPrimitive::Rects),
880 DLCmd::from_raw(0x1f000009),
881 );
882 assert_eq!(DLCmd::bitmap_cell(2), DLCmd::from_raw(0x06000002));
883 assert_eq!(
884 DLCmd::bitmap_ext_format(options::BitmapExtFormat::ARGB1555),
885 DLCmd::from_raw(0x2e000000),
886 );
887 assert_eq!(
888 DLCmd::bitmap_ext_format(options::BitmapExtFormat::ARGB4),
889 DLCmd::from_raw(0x2e000006),
890 );
891 assert_eq!(
892 DLCmd::bitmap_ext_format(options::BitmapExtFormat::TextVGA),
893 DLCmd::from_raw(0x2e00000a),
894 );
895 assert_eq!(
896 DLCmd::bitmap_handle(options::BitmapHandle::force_raw(0)),
897 DLCmd::from_raw(0x05000000),
898 );
899 assert_eq!(
900 DLCmd::bitmap_handle(options::BitmapHandle::force_raw(15)),
901 DLCmd::from_raw(0x0500000f),
902 );
903 assert_eq!(
904 DLCmd::bitmap_handle(options::BitmapHandle::force_raw(31)),
905 DLCmd::from_raw(0x0500001f),
906 );
907 assert_eq!(
908 DLCmd::bitmap_layout_l(options::BitmapFormat::ARGB4, 255, 255),
909 DLCmd::from_raw(0x0731feff),
910 );
911 assert_eq!(
912 DLCmd::bitmap_layout_l(options::BitmapFormat::ARGB4, 1024, 768),
913 DLCmd::from_raw(0x07300100),
914 );
915 assert_eq!(
916 DLCmd::bitmap_layout_h(255, 255),
917 DLCmd::from_raw(0x28000000)
918 );
919 assert_eq!(
920 DLCmd::bitmap_layout_h(1024, 768),
921 DLCmd::from_raw(0x28000004)
922 );
923 assert_eq!(
924 DLCmd::bitmap_layout_pair(options::BitmapFormat::ARGB4, 255, 255),
925 (DLCmd::from_raw(0x0731feff), DLCmd::from_raw(0x28000000)),
926 );
927 assert_eq!(
928 DLCmd::bitmap_layout_pair(options::BitmapFormat::ARGB4, 1024, 768),
929 (DLCmd::from_raw(0x07300100), DLCmd::from_raw(0x28000004)),
930 );
931 assert_eq!(
932 DLCmd::bitmap_swizzle(options::BitmapSwizzle::default()),
933 DLCmd::from_raw(0x2f000000 | 0b010011100101),
934 );
935 assert_eq!(
936 DLCmd::bitmap_size_l(
937 255,
938 255,
939 options::BitmapSizeFilter::Nearest,
940 options::BitmapWrapMode::Border,
941 options::BitmapWrapMode::Border
942 ),
943 DLCmd::from_raw(0x0801feff),
944 );
945 assert_eq!(
946 DLCmd::bitmap_size_l(
947 2048,
948 2048,
949 options::BitmapSizeFilter::Nearest,
950 options::BitmapWrapMode::Border,
951 options::BitmapWrapMode::Border
952 ),
953 DLCmd::from_raw(0x08000000),
954 );
955 assert_eq!(
956 DLCmd::bitmap_size_l(
957 1024,
958 768,
959 options::BitmapSizeFilter::Nearest,
960 options::BitmapWrapMode::Border,
961 options::BitmapWrapMode::Border
962 ),
963 DLCmd::from_raw(0x08000100),
964 );
965 assert_eq!(
966 DLCmd::bitmap_size_l(
967 1,
968 1,
969 options::BitmapSizeFilter::Bilinear,
970 options::BitmapWrapMode::Border,
971 options::BitmapWrapMode::Border
972 ),
973 DLCmd::from_raw(0x08100201),
974 );
975 assert_eq!(
976 DLCmd::bitmap_size_l(
977 1,
978 1,
979 options::BitmapSizeFilter::Nearest,
980 options::BitmapWrapMode::Repeat,
981 options::BitmapWrapMode::Border
982 ),
983 DLCmd::from_raw(0x08080201),
984 );
985 assert_eq!(
986 DLCmd::bitmap_size_l(
987 1,
988 1,
989 options::BitmapSizeFilter::Nearest,
990 options::BitmapWrapMode::Border,
991 options::BitmapWrapMode::Repeat
992 ),
993 DLCmd::from_raw(0x08040201),
994 );
995 assert_eq!(
996 DLCmd::bitmap_size_pair(
997 255,
998 255,
999 options::BitmapSizeFilter::Nearest,
1000 options::BitmapWrapMode::Border,
1001 options::BitmapWrapMode::Border
1002 ),
1003 (DLCmd::from_raw(0x0801feff), DLCmd::from_raw(0x29000000))
1004 );
1005 assert_eq!(
1006 DLCmd::bitmap_size_pair(
1007 2048,
1008 2048,
1009 options::BitmapSizeFilter::Nearest,
1010 options::BitmapWrapMode::Border,
1011 options::BitmapWrapMode::Border
1012 ),
1013 (DLCmd::from_raw(0x08000000), DLCmd::from_raw(0x29000000)),
1014 );
1015 assert_eq!(
1016 DLCmd::bitmap_size_pair(
1017 1024,
1018 768,
1019 options::BitmapSizeFilter::Nearest,
1020 options::BitmapWrapMode::Border,
1021 options::BitmapWrapMode::Border
1022 ),
1023 (DLCmd::from_raw(0x08000100), DLCmd::from_raw(0x29000009)),
1024 );
1025 assert_eq!(
1026 DLCmd::bitmap_size_pair(
1027 3 * 256,
1028 3 * 240,
1029 options::BitmapSizeFilter::Nearest,
1030 options::BitmapWrapMode::Repeat,
1031 options::BitmapWrapMode::Repeat
1032 ),
1033 (
1034 DLCmd::from_raw(0b00001000_000_0_1_1_100000000_011010000),
1035 DLCmd::from_raw(0b00101001_00000000000000000000_01_01)
1036 )
1037 );
1038 assert_eq!(
1039 DLCmd::bitmap_source(Ptr::<TestMainMem>::new(0x20)),
1040 DLCmd::from_raw(0x01000020),
1041 );
1042 assert_eq!(DLCmd::bitmap_transform_a(1), DLCmd::from_raw(0x15000100));
1043 assert_eq!(DLCmd::bitmap_transform_b(0.5), DLCmd::from_raw(0x16014000));
1044 assert_eq!(DLCmd::bitmap_transform_c(1.5), DLCmd::from_raw(0x17000180));
1045 assert_eq!(DLCmd::bitmap_transform_d(-1), DLCmd::from_raw(0x1800ff00));
1046 assert_eq!(DLCmd::bitmap_transform_e(-1.5), DLCmd::from_raw(0x1900fe80));
1047 assert_eq!(
1048 DLCmd::bitmap_transform_f(options::MatrixCoeff::new_8_8(2, 3)),
1049 DLCmd::from_raw(0x1a000203)
1050 );
1051 assert_eq!(
1052 DLCmd::blend_func(
1053 options::BlendFunc::SrcAlpha,
1054 options::BlendFunc::OneMinusDstAlpha
1055 ),
1056 DLCmd::from_raw(0x0b000015)
1057 );
1058 assert_eq!(
1059 DLCmd::call(TestDisplayListMem::ptr(4)),
1060 DLCmd::from_raw(0x1d000004)
1061 );
1062 assert_eq!(DLCmd::clear_stencil(5), DLCmd::from_raw(0x11000005));
1063 assert_eq!(DLCmd::clear_tag(6), DLCmd::from_raw(0x12000006));
1064 assert_eq!(DLCmd::color_alpha(8), DLCmd::from_raw(0x10000008));
1065 assert_eq!(
1066 DLCmd::color_mask(core::default::Default::default()),
1067 DLCmd::from_raw(0x2000000f)
1068 );
1069 assert_eq!(
1070 DLCmd::color_rgb(crate::graphics::RGB { r: 9, g: 8, b: 7 }),
1071 DLCmd::from_raw(0x04090807)
1072 );
1073 assert_eq!(DLCmd::line_width(4094), DLCmd::from_raw(0x0e000ffe));
1074 assert_eq!(DLCmd::scissor_size((10, 8)), DLCmd::from_raw(0x1c00a008));
1075 assert_eq!(DLCmd::scissor_pos((10, 8)), DLCmd::from_raw(0x1b002808));
1076 assert_eq!(
1077 DLCmd::stencil_test(options::TestFunc::Greater, 254, 2),
1078 DLCmd::from_raw(0x0a03fe02),
1079 );
1080 assert_eq!(
1081 DLCmd::stencil_test(options::TestFunc::Never, 0, 4),
1082 DLCmd::from_raw(0x0a000004),
1083 );
1084 assert_eq!(DLCmd::stencil_mask(4), DLCmd::from_raw(0x13000004));
1085 assert_eq!(
1086 DLCmd::stencil_op(options::StencilOp::Keep, options::StencilOp::Replace),
1087 DLCmd::from_raw(0x0c00000a),
1088 );
1089 assert_eq!(DLCmd::tag(4), DLCmd::from_raw(0x03000004));
1090 assert_eq!(DLCmd::tag_mask(true), DLCmd::from_raw(0x14000001));
1091 assert_eq!(DLCmd::tag_mask(false), DLCmd::from_raw(0x14000000));
1092 assert_eq!(
1093 DLCmd::vertex_format(options::VertexFormat::Sixteenth),
1094 DLCmd::from_raw(0x27000004)
1095 );
1096 assert_eq!(DLCmd::vertex_translate_x(2), DLCmd::from_raw(0x2b000002));
1097 assert_eq!(DLCmd::vertex_translate_y(4), DLCmd::from_raw(0x2c000004));
1098 }
1099}