1use {
2 crate::{
3 makepad_live_compiler::{
4 LiveId,
5 },
6 makepad_math::*,
7 cx::Cx,
8 os::{
9 CxOsDrawCall,
10 CxOsDrawList,
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::Texture,
26 geometry::{GeometryId}
27 }
28};
29
30
31#[derive(Debug)]
32pub struct DrawList(PoolId);
33
34impl DrawList{
35 pub fn new(cx:&mut Cx)->Self{
36 cx.draw_lists.alloc()
37 }
38}
39
40#[derive(Clone, Debug, PartialEq, Copy, Hash, Ord, PartialOrd, Eq)]
41pub struct DrawListId(usize, u64);
42
43impl DrawListId{
44 pub fn index(&self)->usize{self.0}
45 pub fn generation(&self)->u64{self.1}
46}
47
48impl DrawList {
49 pub fn id(&self) -> DrawListId {DrawListId(self.0.id, self.0.generation)}
50}
51
52#[derive(Default)]
53pub struct CxDrawListPool(pub (crate) IdPool<CxDrawList>);
54impl CxDrawListPool {
55 pub fn alloc(&mut self) -> DrawList {
56 DrawList(self.0.alloc())
57 }
58
59 pub fn checked_index(&self, index: DrawListId)->Option<&CxDrawList>{
60 let d = &self.0.pool[index.0];
61 if d.generation != index.1 {
62 return None
63 }
64 return Some(&d.item)
65 }
66}
67
68impl std::ops::Index<DrawListId> for CxDrawListPool {
69
70 type Output = CxDrawList;
71 fn index(&self, index: DrawListId) -> &Self::Output {
72 let d = &self.0.pool[index.0];
73 if d.generation != index.1 {
74 error!("Drawlist id generation wrong index: {} current gen:{} in pointer:{}", index.0, d.generation, index.1)
75 }
76 &d.item
77 }
78}
79
80impl std::ops::IndexMut<DrawListId> for CxDrawListPool {
81 fn index_mut(&mut self, index: DrawListId) -> &mut Self::Output {
82 let d = &mut self.0.pool[index.0];
83 if d.generation != index.1 {
84 error!("Drawlist id generation wrong {} {} {}", index.0, d.generation, index.1)
85 }
86 &mut d.item
87
88 }
89}
90
91
92#[derive(Default, Clone)]
93#[repr(C)]
94pub struct CxDrawCallUniforms {
95 pub draw_zbias: f32,
96 pub pad1: f32,
97 pub pad2: f32,
98 pub pad3: f32,
99}
100
101
102impl CxDrawCallUniforms {
103 pub fn as_slice(&self) -> &[f32; std::mem::size_of::<CxDrawCallUniforms>()] {
104 unsafe {std::mem::transmute(self)}
105 }
106 pub fn set_zbias(&mut self, zbias: f32) {
112 self.draw_zbias = zbias;
113 }
114 }
135
136pub enum CxDrawKind{
137 SubList(DrawListId),
138 DrawCall(CxDrawCall),
139 Empty
140}
141
142pub struct CxDrawItem {
143 pub redraw_id: u64,
144 pub kind: CxDrawKind,
145 pub draw_item_id: usize,
147 pub instances: Option<Vec<f32 >>,
148 pub os: CxOsDrawCall
149}
150
151impl std::ops::Deref for CxDrawItem {
152 type Target = CxDrawKind;
153 fn deref(&self) -> &Self::Target {&self.kind}
154}
155
156impl CxDrawKind{
157 pub fn is_empty(&self)->bool{
158 match self{
159 CxDrawKind::Empty=>true,
160 _=>false
161 }
162 }
163
164 pub fn sub_list(&self)->Option<DrawListId>{
165 match self{
166 CxDrawKind::SubList(id)=>Some(*id),
167 _=>None
168 }
169 }
170 pub fn draw_call(&self)->Option<&CxDrawCall>{
171 match self{
172 CxDrawKind::DrawCall(call)=>Some(call),
173 _=>None
174 }
175 }
176 pub fn draw_call_mut(&mut self)->Option<&mut CxDrawCall>{
177 match self{
178 CxDrawKind::DrawCall(call)=>Some(call),
179 _=>None
180 }
181 }
182}
183
184pub struct CxDrawCall {
185 pub draw_shader: DrawShader, pub options: CxDrawShaderOptions,
187 pub total_instance_slots: usize,
188 pub draw_call_uniforms: CxDrawCallUniforms, pub geometry_id: Option<GeometryId>,
190 pub user_uniforms: [f32; DRAW_CALL_USER_UNIFORMS], pub texture_slots: [Option<Texture>; DRAW_CALL_TEXTURE_SLOTS],
192 pub instance_dirty: bool,
193 pub uniforms_dirty: bool,
194}
195
196impl CxDrawCall {
197 pub fn new(mapping: &CxDrawShaderMapping, draw_vars: &DrawVars) -> Self {
198 CxDrawCall {
199 geometry_id: draw_vars.geometry_id,
200 options: draw_vars.options.clone(),
201 draw_shader: draw_vars.draw_shader.unwrap(),
202 total_instance_slots: mapping.instances.total_slots,
203 draw_call_uniforms: CxDrawCallUniforms::default(),
204 user_uniforms: draw_vars.user_uniforms,
205 texture_slots: draw_vars.texture_slots.clone(),
206 instance_dirty: true,
207 uniforms_dirty: true,
208 }
209 }
210}
211
212#[derive(Clone)]
213#[repr(C)]
214pub struct CxDrawListUniforms {
215 pub view_transform: Mat4,
216 pub view_clip: Vec4,
217 pub view_shift: Vec2,
218 pub pad1: f32,
219 pub pad2: f32
220}
221
222impl Default for CxDrawListUniforms{
223 fn default()->Self{
224 Self{
225 view_transform: Mat4::identity(),
226 view_clip: vec4(-100000.0, -100000.0, 100000.0, 100000.0),
227 view_shift: vec2(0.0,0.0),
228 pad1: 0.0,
229 pad2: 0.0,
230 }
231 }
232}
233
234impl CxDrawListUniforms {
235 pub fn as_slice(&self) -> &[f32; std::mem::size_of::<CxDrawListUniforms>()] {
236 unsafe {std::mem::transmute(self)}
237 }
238}
239
240#[derive(Default)]
241pub struct CxDrawItems {
242 pub(crate) buffer: Vec<CxDrawItem>,
243 used: usize
244}
245
246impl std::ops::Index<usize> for CxDrawItems {
247 type Output = CxDrawItem;
248 fn index(&self, index: usize) -> &Self::Output {
249 &self.buffer[index]
250 }
251}
252
253impl std::ops::IndexMut<usize> for CxDrawItems {
254 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
255 &mut self.buffer[index]
256 }
257}
258
259impl CxDrawItems{
260 pub fn len(&self)->usize{self.used}
261 pub fn clear(&mut self){self.used = 0}
262 pub fn push_item(&mut self, redraw_id: u64, kind:CxDrawKind)->&mut CxDrawItem{
263 let draw_item_id = self.used;
264 if self.used >= self.buffer.len() {
265 self.buffer.push(CxDrawItem {
266 draw_item_id,
267 redraw_id,
268 instances: Some(Vec::new()),
269 os: CxOsDrawCall::default(),
270 kind: kind,
271 });
272 }
273 else{
274 let draw_item = &mut self.buffer[draw_item_id];
276 draw_item.instances.as_mut().unwrap().clear();
277 draw_item.kind = kind;
278 draw_item.redraw_id = redraw_id;
279 }
280 self.used += 1;
281 &mut self.buffer[draw_item_id]
282 }
283}
284
285#[derive(Default)]
286pub struct CxDrawList {
287 pub debug_id: LiveId,
288
289 pub codeflow_parent_id: Option<DrawListId>, pub redraw_id: u64,
292 pub pass_id: Option<PassId>,
293
294 pub draw_items: CxDrawItems,
295
296 pub draw_list_uniforms: CxDrawListUniforms,
297 pub draw_list_has_clip: bool,
298
299 pub os: CxOsDrawList,
300 pub rect_areas: Vec<CxRectArea>,
301 pub find_appendable_draw_shader_id: Vec<u64>
302}
303
304pub struct CxRectArea{
305 pub rect: Rect,
306 pub draw_clip: (DVec2,DVec2)
307}
308
309impl CxDrawList {
310pub fn find_appendable_drawcall(&mut self, sh: &CxDrawShader, draw_vars: &DrawVars) -> Option<usize> {
335 if draw_vars.draw_shader.is_none(){
337 return None
338 }
339 let draw_shader_id = draw_vars.draw_shader.as_ref().unwrap().false_compare_id();
340
341 for i in (0..self.draw_items.len()).rev() {
343 if self.find_appendable_draw_shader_id[i] == draw_shader_id{
344 let draw_item = &mut self.draw_items[i];
345 if let Some(draw_call) = &draw_item.draw_call() {
346 if draw_call.draw_shader != draw_vars.draw_shader.unwrap(){
348 continue
349 }
350 if !sh.mapping.flags.draw_call_nocompare {
352 if draw_call.geometry_id != draw_vars.geometry_id {
353 continue
354 }
355 let mut diff = false;
356 for i in 0..sh.mapping.user_uniforms.total_slots {
357 if draw_call.user_uniforms[i] != draw_vars.user_uniforms[i] {
358 diff = true;
359 break;
360 }
361 }
362 if diff {continue}
363
364 for i in 0..sh.mapping.textures.len() {
365 fn neq(a:&Option<Texture>, b:&Option<Texture>)->bool{
366 if let Some(a) = a{
367 if let Some(b) = b{
368 return a.texture_id() != b.texture_id()
369 }
370 return true
371 }
372 return false
373 }
374 if neq(&draw_call.texture_slots[i], &draw_vars.texture_slots[i]) {
375 diff = true;
376 break;
377 }
378 }
379 if diff {continue}
380 }
381 if !draw_call.options._appendable_drawcall(&draw_vars.options) {
382 continue
383 }
384 return Some(i)
385 }
386 else{
387 break;
388 }
389 }
390 }
391 None
392 }
393
394 pub fn append_draw_call(&mut self, redraw_id: u64, sh: &CxDrawShader, draw_vars: &DrawVars) -> &mut CxDrawItem {
395
396 if let Some(ds) = &draw_vars.draw_shader{
397 self.find_appendable_draw_shader_id.push(ds.false_compare_id());
398 }
399 else{
400 self.find_appendable_draw_shader_id.push(0);
401 }
402 self.draw_items.push_item(
403 redraw_id,
404 CxDrawKind::DrawCall(CxDrawCall::new(&sh.mapping, draw_vars))
405 )
406 }
407
408 pub fn clear_draw_items(&mut self, redraw_id: u64) {
409 self.redraw_id = redraw_id;
410 self.draw_items.clear();
411 self.rect_areas.clear();
412 self.find_appendable_draw_shader_id.clear();
413 }
414
415 pub fn append_sub_list(&mut self, redraw_id: u64, sub_list_id: DrawListId) {
416 self.draw_items.push_item(redraw_id, CxDrawKind::SubList(sub_list_id));
418 self.find_appendable_draw_shader_id.push(0);
419 }
420
421 pub fn store_sub_list_last(&mut self, redraw_id: u64, sub_list_id: DrawListId) {
422 let len = self.draw_items.len();
424 for i in 0..len{
425 let item = &mut self.draw_items[i];
426 if let Some(id) = item.kind.sub_list(){
427 if id == sub_list_id{
428 item.kind = CxDrawKind::Empty;
429 break
430 }
431 }
432 }
433 if len > 0{
434 let item = &mut self.draw_items[len - 1];
435 if item.kind.is_empty(){
436 item.redraw_id = redraw_id;
437 item.kind = CxDrawKind::SubList(sub_list_id);
438 return
439 }
440 if let CxDrawKind::SubList(id) = item.kind{
441 if id == sub_list_id{
442 item.redraw_id = redraw_id;
443 return
444 }
445 }
446 }
447 self.append_sub_list(redraw_id, sub_list_id);
448 }
449
450 pub fn store_sub_list(&mut self, redraw_id: u64, sub_list_id: DrawListId) {
451 for i in 0..self.draw_items.len(){
453 let item = &mut self.draw_items[i];
454 if let Some(id) = item.kind.sub_list(){
455 if id == sub_list_id{
456 return
457 }
458 }
459 }
460 for i in 0..self.draw_items.len(){
461 let item = &mut self.draw_items[i];
462 if item.kind.is_empty(){
463 item.redraw_id = redraw_id;
464 item.kind = CxDrawKind::SubList(sub_list_id);
465 return
466 }
467 }
468 self.append_sub_list(redraw_id, sub_list_id);
469 }
470
471 pub fn clear_sub_list(&mut self, sub_list_id: DrawListId) {
472 for i in 0..self.draw_items.len(){
474 let item = &mut self.draw_items[i];
475 if let Some(check_id) = item.kind.sub_list(){
476 if check_id == sub_list_id{
477 item.kind = CxDrawKind::Empty;
478 }
479 }
480 }
481 }
482 }