1use {
2 crate::{
3 makepad_error_log::*,
4 makepad_math::*,
5 makepad_shader_compiler::{
6 ShaderTy
7 },
8 makepad_live_compiler::{
9 LiveId,
10 },
11 draw_list::DrawListId,
12 makepad_math::{
13 Rect
14 },
15 cx::Cx
16 }
17};
18
19#[derive(Clone, Hash, Ord, PartialOrd, Eq, Debug, PartialEq, Copy)]
20pub struct InstanceArea {
21 pub draw_list_id: DrawListId,
22 pub draw_item_id: usize,
23 pub instance_offset: usize,
24 pub instance_count: usize,
25 pub redraw_id: u64
26}
27#[derive(Clone, Hash, Ord, PartialOrd, Eq, Debug, PartialEq, Copy)]
35pub struct RectArea {
36 pub draw_list_id: DrawListId,
37 pub rect_id: usize,
38 pub redraw_id: u64
39}
40
41#[derive(Clone, Debug, Hash, PartialEq, Ord, PartialOrd, Eq, Copy)]
42pub enum Area {
43 Empty,
44 Instance(InstanceArea),
45 Rect(RectArea)
47}
48
49impl Default for Area {
50 fn default() -> Area {
51 Area::Empty
52 }
53}
54
55pub struct DrawReadRef<'a> {
56 pub repeat: usize,
57 pub stride: usize,
58 pub buffer: &'a [f32]
59}
60
61pub struct DrawWriteRef<'a> {
62 pub repeat: usize,
63 pub stride: usize,
64 pub buffer: &'a mut [f32]
65}
66
67impl Into<Area> for InstanceArea {
68 fn into(self) -> Area {
69 Area::Instance(self)
70 }
71}
72
73impl Area {
74
75 pub fn redraw(&self, cx: &mut Cx) {
76 cx.redraw_area(*self);
77 }
78
79
80 pub fn valid_instance(&self, cx: &Cx) -> Option<&InstanceArea> {
81 if self.is_valid(cx) {
82 if let Self::Instance(inst) = self {
83 return Some(inst)
84 }
85 }
86 None
87 }
88
89 pub fn is_empty(&self) -> bool {
90 if let Area::Empty = self {
91 return true
92 }
93 false
94 }
95
96 pub fn draw_list_id(&self) -> Option<DrawListId> {
97 return match self {
98 Area::Instance(inst) => {
99 Some(inst.draw_list_id)
100 },
101 Area::Rect(list) => {
102 Some(list.draw_list_id)
103 }
104 _ => None
105 }
106 }
107
108 pub fn is_first_instance(&self) -> bool {
109 return match self {
110 Area::Instance(inst) => {
111 inst.instance_offset == 0
112 },
113 _ => false,
114 }
115 }
116
117 pub fn is_valid(&self, cx: &Cx) -> bool {
118 return match self {
119 Area::Instance(inst) => {
120 if inst.instance_count == 0 {
121 return false
122 }
123 let draw_list = &cx.draw_lists[inst.draw_list_id];
124 if draw_list.redraw_id != inst.redraw_id {
125 return false
126 }
127 return true
128 },
129 Area::Rect(list) => {
130 let draw_list = &cx.draw_lists[list.draw_list_id];
131 if draw_list.redraw_id != list.redraw_id {
132 return false
133 }
134 return true
135 },
136 _ => false,
137 }
138 }
139
140 pub fn get_clipped_rect(&self, cx: &Cx) -> Rect {
142
143 return match self {
144 Area::Instance(inst) => {
145 if inst.instance_count == 0 {
146 error!("get_rect called on instance_count ==0 area pointer, use mark/sweep correctly!");
148 return Rect::default()
149 }
150 let draw_list = &cx.draw_lists[inst.draw_list_id];
151 if draw_list.redraw_id != inst.redraw_id {
152 return Rect::default();
153 }
154 let draw_item = &draw_list.draw_items[inst.draw_item_id];
155 let draw_call = draw_item.draw_call().unwrap();
156
157 if draw_item.instances.as_ref().unwrap().len() == 0 {
158 error!("No instances but everything else valid?");
159 return Rect::default()
160 }
161 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
162 error!("Generation invalid get_rect {} {:?} {} {}", draw_list.debug_id, inst, cx.draw_shaders.generation, draw_call.draw_shader.draw_shader_generation);
163 return Rect::default()
164 }
165 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
166 let buf = draw_item.instances.as_ref().unwrap();
168 if let Some(rect_pos) = sh.mapping.rect_pos {
169 let pos = dvec2(buf[inst.instance_offset + rect_pos + 0] as f64, buf[inst.instance_offset + rect_pos + 1] as f64);
170 if let Some(rect_size) = sh.mapping.rect_size {
171 let size = dvec2(buf[inst.instance_offset + rect_size + 0] as f64, buf[inst.instance_offset + rect_size + 1] as f64);
172 if let Some(draw_clip) = sh.mapping.draw_clip {
173 let p1= dvec2(
174 buf[inst.instance_offset + draw_clip + 0] as f64,
175 buf[inst.instance_offset + draw_clip + 1] as f64,
176 );
177 let p2 = dvec2(
178 buf[inst.instance_offset + draw_clip + 2] as f64,
179 buf[inst.instance_offset + draw_clip + 3] as f64
180 );
181 return Rect{pos,size}.clip((p1,p2));
182 }
183 }
184 }
185 Rect::default()
186 },
187 Area::Rect(ra) => {
188 let draw_list = &cx.draw_lists[ra.draw_list_id];
190 let rect_area = &draw_list.rect_areas[ra.rect_id];
191 return rect_area.rect.clip(rect_area.draw_clip);
192 },
193 _ => Rect::default(),
194 }
195 }
196
197 pub fn get_rect(&self, cx: &Cx) -> Rect {
198
199 return match self {
200 Area::Instance(inst) => {
201 if inst.instance_count == 0 {
202 error!("get_rect called on instance_count ==0 area pointer, use mark/sweep correctly!");
204 return Rect::default()
205 }
206 let draw_list = &cx.draw_lists[inst.draw_list_id];
207 if draw_list.redraw_id != inst.redraw_id {
208 return Rect::default();
209 }
210 let draw_item = &draw_list.draw_items[inst.draw_item_id];
211 let draw_call = draw_item.draw_call().unwrap();
212
213 if draw_item.instances.as_ref().unwrap().len() == 0 {
214 error!("No instances but everything else valid?");
215 return Rect::default()
216 }
217 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
218 error!("Generation invalid get_rect {} {:?} {} {}", draw_list.debug_id, inst, cx.draw_shaders.generation, draw_call.draw_shader.draw_shader_generation);
219 return Rect::default()
220 }
221 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
222 let buf = draw_item.instances.as_ref().unwrap();
224 if let Some(rect_pos) = sh.mapping.rect_pos {
225 let pos = dvec2(buf[inst.instance_offset + rect_pos + 0] as f64, buf[inst.instance_offset + rect_pos + 1] as f64);
226 if let Some(rect_size) = sh.mapping.rect_size {
227 let size = dvec2(buf[inst.instance_offset + rect_size + 0] as f64, buf[inst.instance_offset + rect_size + 1] as f64);
228 return Rect{pos,size};
229 }
230 }
231 Rect::default()
232 },
233 Area::Rect(ra) => {
234 let draw_list = &cx.draw_lists[ra.draw_list_id];
235 if draw_list.redraw_id == ra.redraw_id{
236 let rect_area = &draw_list.rect_areas[ra.rect_id];
237 return rect_area.rect;
238 }
239 Rect::default()
240 },
241 _ => Rect::default(),
242 }
243 }
244
245 pub fn abs_to_rel(&self, cx: &Cx, abs: DVec2) -> DVec2 {
246 return match self {
247 Area::Instance(inst) => {
248 if inst.instance_count == 0 {
249 error!("abs_to_rel_scroll called on instance_count ==0 area pointer, use mark/sweep correctly!");
250 return abs
251 }
252 let draw_list = &cx.draw_lists[inst.draw_list_id];
253 if draw_list.redraw_id != inst.redraw_id {
254 return abs;
255 }
256 let draw_item = &draw_list.draw_items[inst.draw_item_id];
257 let draw_call = draw_item.draw_call().unwrap();
258 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
259 error!("Generation invalid abs_to_rel {} {:?} {} {}", draw_list.debug_id, inst, cx.draw_shaders.generation, draw_call.draw_shader.draw_shader_generation);
260 return abs;
261 }
262
263 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
264 if let Some(rect_pos) = sh.mapping.rect_pos {
266 let buf = draw_item.instances.as_ref().unwrap();
267 let x = buf[inst.instance_offset + rect_pos + 0] as f64;
268 let y = buf[inst.instance_offset + rect_pos + 1] as f64;
269 return DVec2 {
270 x: abs.x - x,
271 y: abs.y - y
272 }
273 }
274 abs
275 },
276 Area::Rect(ra) => {
277 let draw_list = &cx.draw_lists[ra.draw_list_id];
278 let rect_area = &draw_list.rect_areas[ra.rect_id];
279 DVec2 {
280 x: abs.x - rect_area.rect.pos.x,
281 y: abs.y - rect_area.rect.pos.y
282 }
283 },
284 _ => abs,
285 }
286 }
287
288 pub fn set_rect(&self, cx: &mut Cx, rect: &Rect) {
289 match self {
290 Area::Instance(inst) => {
291 let cxview = &mut cx.draw_lists[inst.draw_list_id];
292 if cxview.redraw_id != inst.redraw_id {
293 return;
295 }
296 let draw_item = &mut cxview.draw_items[inst.draw_item_id];
297 let draw_call = draw_item.kind.draw_call().unwrap();
299 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
300 return;
301 }
302 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id]; let buf = draw_item.instances.as_mut().unwrap();
304 if let Some(rect_pos) = sh.mapping.rect_pos {
305 buf[inst.instance_offset + rect_pos + 0] = rect.pos.x as f32;
306 buf[inst.instance_offset + rect_pos + 1] = rect.pos.y as f32;
307 }
308 if let Some(rect_size) = sh.mapping.rect_size {
309 buf[inst.instance_offset + rect_size + 0] = rect.size.x as f32;
310 buf[inst.instance_offset + rect_size + 1] = rect.size.y as f32;
311 }
312 },
313 Area::Rect(ra) => {
314 let draw_list = &mut cx.draw_lists[ra.draw_list_id];
315 let rect_area = &mut draw_list.rect_areas[ra.rect_id];
316 rect_area.rect = *rect
317 },
318 _ => ()
319 }
320 }
321
322 pub fn get_read_ref<'a>(&self, cx: &'a Cx, id: LiveId, ty: ShaderTy) -> Option<DrawReadRef<'a >> {
323 match self {
324 Area::Instance(inst) => {
325 let draw_list = &cx.draw_lists[inst.draw_list_id];
326 let draw_item = &draw_list.draw_items[inst.draw_item_id];
327 let draw_call = draw_item.draw_call().unwrap();
328 if draw_list.redraw_id != inst.redraw_id {
329 error!("get_instance_read_ref called on invalid area pointer, use mark/sweep correctly!");
330 return None;
331 }
332 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
333 return None;
334 }
335 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
336 if let Some(input) = sh.mapping.user_uniforms.inputs.iter().find( | input | input.id == id) {
337 if input.ty != ty {
338 panic!("get_read_ref wrong uniform type, expected {:?} got: {:?}!", input.ty, ty);
339 }
340 return Some(
341 DrawReadRef {
342 repeat: 1,
343 stride: 0,
344 buffer: &draw_call.user_uniforms[input.offset..]
345 }
346 )
347 }
348 if let Some(input) = sh.mapping.instances.inputs.iter().find( | input | input.id == id) {
349 if input.ty != ty {
350 panic!("get_read_ref wrong instance type, expected {:?} got: {:?}!", input.ty, ty);
351 }
352 if inst.instance_count == 0 {
353 return None
354 }
355 return Some(
356 DrawReadRef {
357 repeat: inst.instance_count,
358 stride: sh.mapping.instances.total_slots,
359 buffer: &draw_item.instances.as_ref().unwrap()[(inst.instance_offset + input.offset)..],
360 }
361 )
362 }
363 panic!("get_read_ref property not found! {}", id);
364 }
365 _ => (),
366 }
367 None
368 }
369
370 pub fn get_write_ref<'a>(&self, cx: &'a mut Cx, id: LiveId, ty: ShaderTy, name: &str) -> Option<DrawWriteRef<'a >> {
371 match self {
372 Area::Instance(inst) => {
373 let draw_list = &mut cx.draw_lists[inst.draw_list_id];
374 if draw_list.redraw_id != inst.redraw_id {
375 return None;
376 }
377 let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
378 let draw_call = draw_item.kind.draw_call_mut().unwrap();
379 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
380 return None;
381 }
382 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
383
384 if let Some(input) = sh.mapping.user_uniforms.inputs.iter().find( | input | input.id == id) {
385 if input.ty != ty {
386 panic!("get_write_ref {} wrong uniform type, expected {:?} got: {:?}!", name, input.ty, ty);
387 }
388
389 cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
390 draw_call.uniforms_dirty = true;
391
392 return Some(
393 DrawWriteRef {
394 repeat: 1,
395 stride: 0,
396 buffer: &mut draw_call.user_uniforms[input.offset..]
397 }
398 )
399 }
400 if let Some(input) = sh.mapping.instances.inputs.iter().find( | input | input.id == id) {
401 if input.ty != ty {
402 panic!("get_write_ref {} wrong instance type, expected {:?} got: {:?}!", name, input.ty, ty);
403 }
404
405 cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
406 draw_call.instance_dirty = true;
407 if inst.instance_count == 0 {
408 return None
409 }
410 return Some(
411 DrawWriteRef {
412 repeat: inst.instance_count,
413 stride: sh.mapping.instances.total_slots,
414 buffer: &mut draw_item.instances.as_mut().unwrap()[(inst.instance_offset + input.offset)..]
415 }
416 )
417 }
418 panic!("get_write_ref {} property not found!", name);
419 }
420 _ => (),
421 }
422 None
423 }
424}
425