1use crate::color;
3use crate::core::{Rectangle, Transformation};
4use crate::gradient;
5
6use bytemuck::{Pod, Zeroable};
7
8use std::sync::atomic::{self, AtomicU64};
9use std::sync::{Arc, Weak};
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum Mesh {
14 Solid {
16 buffers: Indexed<SolidVertex2D>,
18
19 transformation: Transformation,
21
22 clip_bounds: Rectangle,
24 },
25 Gradient {
27 buffers: Indexed<GradientVertex2D>,
29
30 transformation: Transformation,
32
33 clip_bounds: Rectangle,
35 },
36}
37
38impl Mesh {
39 pub fn indices(&self) -> &[u32] {
41 match self {
42 Self::Solid { buffers, .. } => &buffers.indices,
43 Self::Gradient { buffers, .. } => &buffers.indices,
44 }
45 }
46
47 pub fn transformation(&self) -> Transformation {
49 match self {
50 Self::Solid { transformation, .. }
51 | Self::Gradient { transformation, .. } => *transformation,
52 }
53 }
54
55 pub fn clip_bounds(&self) -> Rectangle {
57 match self {
58 Self::Solid {
59 clip_bounds,
60 transformation,
61 ..
62 }
63 | Self::Gradient {
64 clip_bounds,
65 transformation,
66 ..
67 } => *clip_bounds * *transformation,
68 }
69 }
70}
71
72#[derive(Clone, Debug, PartialEq, Eq)]
74pub struct Indexed<T> {
75 pub vertices: Vec<T>,
77
78 pub indices: Vec<u32>,
82}
83
84#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
86#[repr(C)]
87pub struct SolidVertex2D {
88 pub position: [f32; 2],
90
91 pub color: color::Packed,
93}
94
95#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
97#[repr(C)]
98pub struct GradientVertex2D {
99 pub position: [f32; 2],
101
102 pub gradient: gradient::Packed,
104}
105
106#[derive(Debug, Clone, Copy, Default)]
108pub struct AttributeCount {
109 pub solid_vertices: usize,
111
112 pub solids: usize,
114
115 pub gradient_vertices: usize,
117
118 pub gradients: usize,
120
121 pub indices: usize,
123}
124
125pub fn attribute_count_of(meshes: &[Mesh]) -> AttributeCount {
127 meshes
128 .iter()
129 .fold(AttributeCount::default(), |mut count, mesh| {
130 match mesh {
131 Mesh::Solid { buffers, .. } => {
132 count.solids += 1;
133 count.solid_vertices += buffers.vertices.len();
134 count.indices += buffers.indices.len();
135 }
136 Mesh::Gradient { buffers, .. } => {
137 count.gradients += 1;
138 count.gradient_vertices += buffers.vertices.len();
139 count.indices += buffers.indices.len();
140 }
141 }
142
143 count
144 })
145}
146
147#[derive(Debug, Clone)]
149pub struct Cache {
150 id: Id,
151 batch: Arc<[Mesh]>,
152 version: usize,
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
157pub struct Id(u64);
158
159impl Cache {
160 pub fn new(meshes: Arc<[Mesh]>) -> Self {
162 static NEXT_ID: AtomicU64 = AtomicU64::new(0);
163
164 Self {
165 id: Id(NEXT_ID.fetch_add(1, atomic::Ordering::Relaxed)),
166 batch: meshes,
167 version: 0,
168 }
169 }
170
171 pub fn id(&self) -> Id {
173 self.id
174 }
175
176 pub fn version(&self) -> usize {
178 self.version
179 }
180
181 pub fn batch(&self) -> &[Mesh] {
183 &self.batch
184 }
185
186 pub fn downgrade(&self) -> Weak<[Mesh]> {
188 Arc::downgrade(&self.batch)
189 }
190
191 pub fn is_empty(&self) -> bool {
193 self.batch.is_empty()
194 }
195
196 pub fn update(&mut self, meshes: Arc<[Mesh]>) {
198 self.batch = meshes;
199 self.version += 1;
200 }
201}
202
203pub trait Renderer {
205 fn draw_mesh(&mut self, mesh: Mesh);
207
208 fn draw_mesh_cache(&mut self, cache: Cache);
210}