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, .. } | Self::Gradient { transformation, .. } => {
51 *transformation
52 }
53 }
54 }
55
56 pub fn clip_bounds(&self) -> Rectangle {
58 match self {
59 Self::Solid {
60 clip_bounds,
61 transformation,
62 ..
63 }
64 | Self::Gradient {
65 clip_bounds,
66 transformation,
67 ..
68 } => *clip_bounds * *transformation,
69 }
70 }
71}
72
73#[derive(Clone, Debug, PartialEq, Eq)]
75pub struct Indexed<T> {
76 pub vertices: Vec<T>,
78
79 pub indices: Vec<u32>,
83}
84
85#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
87#[repr(C)]
88pub struct SolidVertex2D {
89 pub position: [f32; 2],
91
92 pub color: color::Packed,
94}
95
96#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
98#[repr(C)]
99pub struct GradientVertex2D {
100 pub position: [f32; 2],
102
103 pub gradient: gradient::Packed,
105}
106
107#[derive(Debug, Clone, Copy, Default)]
109pub struct AttributeCount {
110 pub solid_vertices: usize,
112
113 pub solids: usize,
115
116 pub gradient_vertices: usize,
118
119 pub gradients: usize,
121
122 pub indices: usize,
124}
125
126pub fn attribute_count_of(meshes: &[Mesh]) -> AttributeCount {
128 meshes
129 .iter()
130 .fold(AttributeCount::default(), |mut count, mesh| {
131 match mesh {
132 Mesh::Solid { buffers, .. } => {
133 count.solids += 1;
134 count.solid_vertices += buffers.vertices.len();
135 count.indices += buffers.indices.len();
136 }
137 Mesh::Gradient { buffers, .. } => {
138 count.gradients += 1;
139 count.gradient_vertices += buffers.vertices.len();
140 count.indices += buffers.indices.len();
141 }
142 }
143
144 count
145 })
146}
147
148#[derive(Debug, Clone)]
150pub struct Cache {
151 id: Id,
152 batch: Arc<[Mesh]>,
153 version: usize,
154}
155
156#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
158pub struct Id(u64);
159
160impl Cache {
161 pub fn new(meshes: Arc<[Mesh]>) -> Self {
163 static NEXT_ID: AtomicU64 = AtomicU64::new(0);
164
165 Self {
166 id: Id(NEXT_ID.fetch_add(1, atomic::Ordering::Relaxed)),
167 batch: meshes,
168 version: 0,
169 }
170 }
171
172 pub fn id(&self) -> Id {
174 self.id
175 }
176
177 pub fn version(&self) -> usize {
179 self.version
180 }
181
182 pub fn batch(&self) -> &[Mesh] {
184 &self.batch
185 }
186
187 pub fn downgrade(&self) -> Weak<[Mesh]> {
189 Arc::downgrade(&self.batch)
190 }
191
192 pub fn is_empty(&self) -> bool {
194 self.batch.is_empty()
195 }
196
197 pub fn update(&mut self, meshes: Arc<[Mesh]>) {
199 self.batch = meshes;
200 self.version += 1;
201 }
202}
203
204pub trait Renderer {
206 fn draw_mesh(&mut self, mesh: Mesh);
208
209 fn draw_mesh_cache(&mut self, cache: Cache);
211}