1use {
2 crate::{
3 makepad_live_compiler::{
4 LiveId,
5 },
6 makepad_math::*,
7 makepad_error_log::*,
8 os::{
9 CxOsDrawCall,
10 CxOsView,
11 },
12 pass::PassId,
13 id_pool::*,
14 draw_shader::{
15 CxDrawShaderOptions,
16 CxDrawShaderMapping,
17 CxDrawShader,
18 DrawShader,
19 },
20 draw_vars::{
21 DrawVars,
22 DRAW_CALL_USER_UNIFORMS,
23 DRAW_CALL_TEXTURE_SLOTS
24 },
25 texture::TextureId,
26 geometry::{GeometryId}
27 }
28};
29
30
31#[derive(Debug)]
32pub struct DrawList(PoolId);
33
34#[derive(Clone, Debug, PartialEq, Copy, Hash, Ord, PartialOrd, Eq)]
35pub struct DrawListId(usize, u64);
36
37impl DrawListId{
38 pub fn index(&self)->usize{self.0}
39 pub fn generation(&self)->u64{self.1}
40}
41
42impl DrawList {
43 pub fn id(&self) -> DrawListId {DrawListId(self.0.id, self.0.generation)}
44}
45
46#[derive(Default)]
47pub struct CxDrawListPool(pub (crate) IdPool<CxDrawList>);
48impl CxDrawListPool {
49 pub fn alloc(&mut self) -> DrawList {
50 DrawList(self.0.alloc())
51 }
52}
53
54impl std::ops::Index<DrawListId> for CxDrawListPool {
55
56 type Output = CxDrawList;
57 fn index(&self, index: DrawListId) -> &Self::Output {
58 let d = &self.0.pool[index.0];
59 if d.generation != index.1 {
60 error!("Drawlist id generation wrong {} {} {}", index.0, d.generation, index.1)
61 }
62 &d.item
63 }
64}
65
66impl std::ops::IndexMut<DrawListId> for CxDrawListPool {
67 fn index_mut(&mut self, index: DrawListId) -> &mut Self::Output {
68 let d = &mut self.0.pool[index.0];
69 if d.generation != index.1 {
70 error!("Drawlist id generation wrong {} {} {}", index.0, d.generation, index.1)
71 }
72 &mut d.item
73
74 }
75}
76
77
78#[derive(Default, Clone)]
79#[repr(C)]
80pub struct DrawUniforms {
81 pub draw_zbias: f32,
87 pub pad1: f32,
88 pub pad2: f32,
89 pub pad3: f32
90}
91
92impl DrawUniforms {
93 pub fn as_slice(&self) -> &[f32; std::mem::size_of::<DrawUniforms>()] {
94 unsafe {std::mem::transmute(self)}
95 }
96 pub fn set_zbias(&mut self, zbias: f32) {
102 self.draw_zbias = zbias;
103 }
104 }
125
126pub enum CxDrawKind{
127 SubList(DrawListId),
128 DrawCall(CxDrawCall),
129 Empty
130}
131
132pub struct CxDrawItem {
133 pub redraw_id: u64,
134 pub kind: CxDrawKind,
135 pub draw_item_id: usize,
137 pub instances: Option<Vec<f32 >>,
138 pub os: CxOsDrawCall
139}
140
141impl std::ops::Deref for CxDrawItem {
142 type Target = CxDrawKind;
143 fn deref(&self) -> &Self::Target {&self.kind}
144}
145
146impl CxDrawKind{
147 pub fn is_empty(&self)->bool{
148 match self{
149 CxDrawKind::Empty=>true,
150 _=>false
151 }
152 }
153
154 pub fn sub_list(&self)->Option<DrawListId>{
155 match self{
156 CxDrawKind::SubList(id)=>Some(*id),
157 _=>None
158 }
159 }
160 pub fn draw_call(&self)->Option<&CxDrawCall>{
161 match self{
162 CxDrawKind::DrawCall(call)=>Some(call),
163 _=>None
164 }
165 }
166 pub fn draw_call_mut(&mut self)->Option<&mut CxDrawCall>{
167 match self{
168 CxDrawKind::DrawCall(call)=>Some(call),
169 _=>None
170 }
171 }
172}
173
174pub struct CxDrawCall {
175 pub draw_shader: DrawShader, pub options: CxDrawShaderOptions,
177 pub total_instance_slots: usize,
178 pub draw_uniforms: DrawUniforms, pub geometry_id: Option<GeometryId>,
180 pub user_uniforms: [f32; DRAW_CALL_USER_UNIFORMS], pub texture_slots: [Option<TextureId>; DRAW_CALL_TEXTURE_SLOTS],
182 pub instance_dirty: bool,
183 pub uniforms_dirty: bool,
184}
185
186impl CxDrawCall {
187 pub fn new(mapping: &CxDrawShaderMapping, draw_vars: &DrawVars) -> Self {
188 CxDrawCall {
189 geometry_id: draw_vars.geometry_id,
190 options: draw_vars.options.clone(),
191 draw_shader: draw_vars.draw_shader.unwrap(),
192 total_instance_slots: mapping.instances.total_slots,
193 draw_uniforms: DrawUniforms::default(),
194 user_uniforms: draw_vars.user_uniforms,
195 texture_slots: draw_vars.texture_slots,
196 instance_dirty: true,
197 uniforms_dirty: true,
198 }
199 }
200}
201
202#[derive(Default, Clone)]
203#[repr(C)]
204pub struct CxDrawListUniforms {
205 pub view_transform: [f32; 16],
206}
207
208impl CxDrawListUniforms {
209 pub fn as_slice(&self) -> &[f32; std::mem::size_of::<CxDrawListUniforms>()] {
210 unsafe {std::mem::transmute(self)}
211 }
212}
213
214#[derive(Default)]
215pub struct CxDrawItems {
216 pub(crate) buffer: Vec<CxDrawItem>,
217 used: usize
218}
219
220impl std::ops::Index<usize> for CxDrawItems {
221 type Output = CxDrawItem;
222 fn index(&self, index: usize) -> &Self::Output {
223 &self.buffer[index]
224 }
225}
226
227impl std::ops::IndexMut<usize> for CxDrawItems {
228 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
229 &mut self.buffer[index]
230 }
231}
232
233impl CxDrawItems{
234 pub fn len(&self)->usize{self.used}
235 pub fn clear(&mut self){self.used = 0}
236 pub fn push_item(&mut self, redraw_id: u64, kind:CxDrawKind)->&mut CxDrawItem{
237 let draw_item_id = self.used;
238 if self.used >= self.buffer.len() {
239 self.buffer.push(CxDrawItem {
240 draw_item_id,
241 redraw_id,
242 instances: Some(Vec::new()),
243 os: CxOsDrawCall::default(),
244 kind: kind,
245 });
246 }
247 else{
248 let draw_item = &mut self.buffer[draw_item_id];
250 draw_item.instances.as_mut().unwrap().clear();
251 draw_item.kind = kind;
252 draw_item.redraw_id = redraw_id;
253 }
254 self.used += 1;
255 &mut self.buffer[draw_item_id]
256 }
257}
258
259#[derive(Default)]
260pub struct CxDrawList {
261 pub debug_id: LiveId,
262
263 pub codeflow_parent_id: Option<DrawListId>, pub redraw_id: u64,
266 pub pass_id: Option<PassId>,
267
268 pub draw_items: CxDrawItems,
269
270 pub draw_list_uniforms: CxDrawListUniforms,
271 pub os: CxOsView,
272 pub rect_areas: Vec<CxRectArea>,
273}
274
275pub struct CxRectArea{
276 pub rect: Rect,
277 pub draw_clip: (DVec2,DVec2)
278}
279
280impl CxDrawList {
281pub fn find_appendable_drawcall(&mut self, sh: &CxDrawShader, draw_vars: &DrawVars) -> Option<usize> {
306 if self.draw_items.len() > 0 {
308 for i in (0..self.draw_items.len()).rev() {
309 let draw_item = &mut self.draw_items[i];
310 if let Some(draw_call) = &draw_item.draw_call() {
311 if draw_call.draw_shader == draw_vars.draw_shader.unwrap() {
312 if !sh.mapping.flags.draw_call_nocompare {
314 if draw_call.geometry_id != draw_vars.geometry_id {
315 continue
316 }
317 let mut diff = false;
318 for i in 0..sh.mapping.user_uniforms.total_slots {
319 if draw_call.user_uniforms[i] != draw_vars.user_uniforms[i] {
320 diff = true;
321 break;
322 }
323 }
324 if diff {continue}
325 for i in 0..sh.mapping.textures.len() {
326 if draw_call.texture_slots[i] != draw_vars.texture_slots[i] {
327 diff = true;
328 break;
329 }
330 }
331 if diff {continue}
332 }
333 if !draw_call.options._appendable_drawcall(&draw_vars.options) {
334 continue
335 }
336 return Some(i)
337 }
338 }
339 }
340 }
341 None
342 }
343
344 pub fn append_draw_call(&mut self, redraw_id: u64, sh: &CxDrawShader, draw_vars: &DrawVars) -> &mut CxDrawItem {
345 self.draw_items.push_item(
346 redraw_id,
347 CxDrawKind::DrawCall(CxDrawCall::new(&sh.mapping, draw_vars))
348 )
349 }
350
351 pub fn clear_draw_items(&mut self, redraw_id: u64) {
352 self.redraw_id = redraw_id;
353 self.draw_items.clear();
354 self.rect_areas.clear();
355 }
356
357 pub fn append_sub_list(&mut self, redraw_id: u64, sub_list_id: DrawListId) {
358 self.draw_items.push_item(redraw_id, CxDrawKind::SubList(sub_list_id));
360 }
361
362 pub fn store_sub_list_last(&mut self, redraw_id: u64, sub_list_id: DrawListId) {
363 let len = self.draw_items.len();
365 for i in 0..len{
366 let item = &mut self.draw_items[i];
367 if let Some(id) = item.kind.sub_list(){
368 if id == sub_list_id{
369 item.kind = CxDrawKind::Empty;
370 break
371 }
372 }
373 }
374 if len > 0{
375 let item = &mut self.draw_items[len - 1];
376 if item.kind.is_empty(){
377 item.redraw_id = redraw_id;
378 item.kind = CxDrawKind::SubList(sub_list_id);
379 return
380 }
381 if let CxDrawKind::SubList(id) = item.kind{
382 if id == sub_list_id{
383 item.redraw_id = redraw_id;
384 return
385 }
386 }
387 }
388 self.append_sub_list(redraw_id, sub_list_id);
389 }
390
391 pub fn store_sub_list(&mut self, redraw_id: u64, sub_list_id: DrawListId) {
392 for i in 0..self.draw_items.len(){
394 let item = &mut self.draw_items[i];
395 if let Some(id) = item.kind.sub_list(){
396 if id == sub_list_id{
397 return
398 }
399 }
400 }
401 for i in 0..self.draw_items.len(){
402 let item = &mut self.draw_items[i];
403 if item.kind.is_empty(){
404 item.redraw_id = redraw_id;
405 item.kind = CxDrawKind::SubList(sub_list_id);
406 return
407 }
408 }
409 self.append_sub_list(redraw_id, sub_list_id);
410 }
411
412 pub fn clear_sub_list(&mut self, sub_list_id: DrawListId) {
413 for i in 0..self.draw_items.len(){
415 let item = &mut self.draw_items[i];
416 if let Some(check_id) = item.kind.sub_list(){
417 if check_id == sub_list_id{
418 item.kind = CxDrawKind::Empty;
419 }
420 }
421 }
422 }
423 pub fn uniform_view_transform(&mut self, v: &Mat4) {
431 for i in 0..16 {
433 self.draw_list_uniforms.view_transform[i] = v.v[i];
434 }
435 }
436
437 pub fn get_view_transform(&self) -> Mat4 {
438 let mut m = Mat4::default();
440 for i in 0..16 {
441 m.v[i] = self.draw_list_uniforms.view_transform[i];
442 }
443 m
444 }
445}