osiris_display/display/
gpu.rs

1use std::collections::HashMap;
2use std::time::Instant;
3
4use osiris_data::data::identification::Address;
5
6use crate::display::graphic::{Image, Pixel, Sprite};
7use crate::display::screen::{ScreenMemory};
8
9// [TODO] Think about a way to order drawings from the Cpu and manage them here in the Gpu,
10//        > Maybe it is already done with the methods sprite_* and update().
11// [TODO] Use SDL2 to display sprites on screen,
12// [TODO] Use frequency and next:Instant to manage screen updates.
13
14#[derive(Clone, Debug)]
15struct CachedSprite {
16    displayed: bool,
17    sprite: Sprite,
18}
19
20#[derive(Clone, Debug)]
21pub struct Gpu {
22    flag_swap: bool,
23    _frequency: usize,
24    _next: Instant,
25    memory: ScreenMemory,
26    cache: HashMap<Address, CachedSprite>,
27}
28
29impl Default for Gpu {
30    fn default() -> Self { Self::new() }
31}
32
33impl Gpu {
34    pub fn with_frequency(frequency: usize) -> Self {
35        Self {
36            flag_swap: false,
37            _frequency: frequency,
38            _next: Instant::now(),
39            memory: ScreenMemory::new(Pixel::BLACK),
40            cache: HashMap::new(),
41        }
42    }
43    pub fn new() -> Self { Self::with_frequency(60) }
44
45    pub fn store_sprite(&mut self, reference: &Address, sprite: Sprite, displayed: bool) {
46        self.cache.insert(*reference, CachedSprite { displayed, sprite });
47    }
48
49    pub fn free_sprite(&mut self, reference: &Address) {
50        self.cache.remove(reference);
51    }
52
53    /// Panics if the sprite does not exist.
54    fn unwrap_cached(&mut self, reference: &Address) -> &mut CachedSprite { self.cache.get_mut(reference).unwrap() }
55
56    pub fn sprite_display(&mut self, reference: &Address, displayed: bool) {
57        if !self.cache.contains_key(reference) { return; }
58        self.unwrap_cached(reference).displayed = displayed;
59    }
60
61    pub fn sprite_move(&mut self, reference: &Address, x: usize, y: usize) {
62        if !self.cache.contains_key(reference) { return; }
63        let cached = self.unwrap_cached(reference);
64        cached.sprite.translate(x, y);
65    }
66
67    pub fn sprite_replace(&mut self, reference: &Address, sprite: Sprite, displayed: bool) {
68        if !self.cache.contains_key(reference) { return; }
69        let cached = self.unwrap_cached(reference);
70        cached.displayed = displayed;
71        cached.sprite = sprite;
72    }
73
74    pub fn sprite_show(&mut self, reference: &Address) { self.sprite_display(reference, true); }
75
76    pub fn sprite_hide(&mut self, reference: &Address) { self.sprite_display(reference, false); }
77
78    pub fn draw_all(&mut self) {
79        for sprite in &mut self.cache.values() {
80            if sprite.displayed {
81                self.memory.draw_sprite(&sprite.sprite);
82            }
83        }
84    }
85
86    pub fn clear_all(&mut self) { self.cache.clear(); }
87
88    pub fn swap_on(&mut self) {
89        self.flag_swap = true;
90    }
91
92    pub fn update(&mut self) {
93        if self.flag_swap {
94            self.memory.swap_and_clear();
95            self.flag_swap = false;
96        }
97    }
98
99    pub fn get(&self) -> Image { self.memory.shown_screen().image().clone() }
100
101    pub fn clear(&mut self) { self.memory.clear(); }
102
103    pub fn swap_and_copy(&mut self) -> Image {
104        self.swap_on();
105        self.update();
106        self.memory.copy();
107        self.get()
108    }
109
110    pub fn draw(&mut self) -> Image {
111        self.draw_all();
112        self.swap_on();
113        self.update();
114        self.get()
115    }
116}