1use api::{DocumentLayer, PremultipliedColorF};
6use api::units::*;
7use crate::clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex};
8use crate::gpu_cache::{GpuCacheAddress, GpuDataRequest};
9use crate::internal_types::FastHashMap;
10use crate::prim_store::EdgeAaSegmentMask;
11use crate::render_task::RenderTaskAddress;
12use std::i32;
13use crate::util::{TransformedRectKind, MatrixHelpers};
14
15pub const VECS_PER_TRANSFORM: usize = 8;
18
19#[derive(Copy, Clone, Debug, PartialEq)]
20#[repr(C)]
21#[cfg_attr(feature = "capture", derive(Serialize))]
22#[cfg_attr(feature = "replay", derive(Deserialize))]
23pub struct ZBufferId(i32);
24
25const MAX_DOCUMENT_LAYERS : i8 = 1 << 3;
30const MAX_ITEMS_PER_DOCUMENT_LAYER : i32 = 1 << 19;
31const MAX_DOCUMENT_LAYER_VALUE : i8 = MAX_DOCUMENT_LAYERS / 2 - 1;
32const MIN_DOCUMENT_LAYER_VALUE : i8 = -MAX_DOCUMENT_LAYERS / 2;
33
34impl ZBufferId {
35 pub fn invalid() -> Self {
36 ZBufferId(i32::MAX)
37 }
38}
39
40#[derive(Debug)]
41#[cfg_attr(feature = "capture", derive(Serialize))]
42#[cfg_attr(feature = "replay", derive(Deserialize))]
43pub struct ZBufferIdGenerator {
44 base: i32,
45 next: i32,
46}
47
48impl ZBufferIdGenerator {
49 pub fn new(layer: DocumentLayer) -> Self {
50 debug_assert!(layer >= MIN_DOCUMENT_LAYER_VALUE);
51 debug_assert!(layer <= MAX_DOCUMENT_LAYER_VALUE);
52 ZBufferIdGenerator {
53 base: layer as i32 * MAX_ITEMS_PER_DOCUMENT_LAYER,
54 next: 0
55 }
56 }
57
58 pub fn next(&mut self) -> ZBufferId {
59 debug_assert!(self.next < MAX_ITEMS_PER_DOCUMENT_LAYER);
60 let id = ZBufferId(self.next + self.base);
61 self.next += 1;
62 id
63 }
64}
65
66#[repr(i32)]
73#[derive(Copy, Clone, Debug, PartialEq)]
74pub enum BrushShaderKind {
75 None = 0,
76 Solid = 1,
77 Image = 2,
78 Text = 3,
79 LinearGradient = 4,
80 RadialGradient = 5,
81 Blend = 6,
82 MixBlend = 7,
83 Yuv = 8,
84 Opacity = 9,
85}
86
87#[derive(Debug, Copy, Clone)]
88#[cfg_attr(feature = "capture", derive(Serialize))]
89#[cfg_attr(feature = "replay", derive(Deserialize))]
90#[repr(C)]
91pub enum RasterizationSpace {
92 Local = 0,
93 Screen = 1,
94}
95
96#[derive(Debug, Copy, Clone, MallocSizeOf)]
97#[cfg_attr(feature = "capture", derive(Serialize))]
98#[cfg_attr(feature = "replay", derive(Deserialize))]
99#[repr(C)]
100pub enum BoxShadowStretchMode {
101 Stretch = 0,
102 Simple = 1,
103}
104
105#[repr(i32)]
106#[derive(Debug, Copy, Clone)]
107#[cfg_attr(feature = "capture", derive(Serialize))]
108#[cfg_attr(feature = "replay", derive(Deserialize))]
109pub enum BlurDirection {
110 Horizontal = 0,
111 Vertical,
112}
113
114#[derive(Debug)]
115#[repr(C)]
116#[cfg_attr(feature = "capture", derive(Serialize))]
117#[cfg_attr(feature = "replay", derive(Deserialize))]
118pub struct BlurInstance {
119 pub task_address: RenderTaskAddress,
120 pub src_task_address: RenderTaskAddress,
121 pub blur_direction: BlurDirection,
122}
123
124#[derive(Debug)]
125#[repr(C)]
126#[cfg_attr(feature = "capture", derive(Serialize))]
127#[cfg_attr(feature = "replay", derive(Deserialize))]
128pub struct ScalingInstance {
129 pub target_rect: DeviceRect,
130 pub source_rect: DeviceIntRect,
131 pub source_layer: i32,
132}
133
134#[derive(Debug)]
135#[repr(C)]
136#[cfg_attr(feature = "capture", derive(Serialize))]
137#[cfg_attr(feature = "replay", derive(Deserialize))]
138pub struct SvgFilterInstance {
139 pub task_address: RenderTaskAddress,
140 pub input_1_task_address: RenderTaskAddress,
141 pub input_2_task_address: RenderTaskAddress,
142 pub kind: u16,
143 pub input_count: u16,
144 pub generic_int: u16,
145 pub extra_data_address: GpuCacheAddress,
146}
147
148#[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
149#[repr(C)]
150#[cfg_attr(feature = "capture", derive(Serialize))]
151#[cfg_attr(feature = "replay", derive(Deserialize))]
152pub enum BorderSegment {
153 TopLeft,
154 TopRight,
155 BottomRight,
156 BottomLeft,
157 Left,
158 Top,
159 Right,
160 Bottom,
161}
162
163#[derive(Debug, Clone)]
164#[repr(C)]
165#[cfg_attr(feature = "capture", derive(Serialize))]
166#[cfg_attr(feature = "replay", derive(Deserialize))]
167pub struct BorderInstance {
168 pub task_origin: DevicePoint,
169 pub local_rect: DeviceRect,
170 pub color0: PremultipliedColorF,
171 pub color1: PremultipliedColorF,
172 pub flags: i32,
173 pub widths: DeviceSize,
174 pub radius: DeviceSize,
175 pub clip_params: [f32; 8],
176}
177
178#[derive(Debug, Copy, Clone)]
182#[cfg_attr(feature = "capture", derive(Serialize))]
183#[cfg_attr(feature = "replay", derive(Deserialize))]
184#[repr(C)]
185pub struct ClipMaskInstance {
186 pub clip_transform_id: TransformPaletteId,
187 pub prim_transform_id: TransformPaletteId,
188 pub clip_data_address: GpuCacheAddress,
189 pub resource_address: GpuCacheAddress,
190 pub local_pos: LayoutPoint,
191 pub tile_rect: LayoutRect,
192 pub sub_rect: DeviceRect,
193 pub task_origin: DevicePoint,
194 pub screen_origin: DevicePoint,
195 pub device_pixel_scale: f32,
196}
197
198#[derive(Debug, Copy, Clone)]
200#[cfg_attr(feature = "capture", derive(Serialize))]
201#[cfg_attr(feature = "replay", derive(Deserialize))]
202#[repr(C)]
203pub struct ClipMaskBorderCornerDotDash {
204 pub clip_mask_instance: ClipMaskInstance,
205 pub dot_dash_data: [f32; 8],
206}
207
208#[derive(Debug, Clone)]
210#[cfg_attr(feature = "capture", derive(Serialize))]
211#[cfg_attr(feature = "replay", derive(Deserialize))]
212pub struct PrimitiveInstanceData {
213 data: [i32; 4],
214}
215
216#[derive(Debug, Clone)]
218#[repr(C)]
219pub struct ResolveInstanceData {
220 rect: [f32; 4],
221}
222
223impl ResolveInstanceData {
224 pub fn new(rect: DeviceIntRect) -> Self {
225 ResolveInstanceData {
226 rect: [
227 rect.origin.x as f32,
228 rect.origin.y as f32,
229 rect.size.width as f32,
230 rect.size.height as f32,
231 ],
232 }
233 }
234}
235
236#[derive(Debug, Clone)]
238#[repr(C)]
239pub struct CompositeInstance {
240 rect: DeviceRect,
241 clip_rect: DeviceRect,
242 color: PremultipliedColorF,
243 layer: f32,
244 z_id: f32,
245}
246
247impl CompositeInstance {
248 pub fn new(
249 rect: DeviceRect,
250 clip_rect: DeviceRect,
251 color: PremultipliedColorF,
252 layer: f32,
253 z_id: ZBufferId,
254 ) -> Self {
255 CompositeInstance {
256 rect,
257 clip_rect,
258 color,
259 layer,
260 z_id: z_id.0 as f32,
261 }
262 }
263}
264
265#[derive(Debug, Copy, Clone)]
266#[cfg_attr(feature = "capture", derive(Serialize))]
267#[cfg_attr(feature = "replay", derive(Deserialize))]
268pub struct PrimitiveHeaderIndex(pub i32);
269
270#[derive(Debug)]
271#[repr(C)]
272#[cfg_attr(feature = "capture", derive(Serialize))]
273#[cfg_attr(feature = "replay", derive(Deserialize))]
274pub struct PrimitiveHeaders {
275 pub headers_int: Vec<PrimitiveHeaderI>,
277 pub headers_float: Vec<PrimitiveHeaderF>,
279}
280
281impl PrimitiveHeaders {
282 pub fn new() -> PrimitiveHeaders {
283 PrimitiveHeaders {
284 headers_int: Vec::new(),
285 headers_float: Vec::new(),
286 }
287 }
288
289 pub fn push(
291 &mut self,
292 prim_header: &PrimitiveHeader,
293 z: ZBufferId,
294 user_data: [i32; 4],
295 ) -> PrimitiveHeaderIndex {
296 debug_assert_eq!(self.headers_int.len(), self.headers_float.len());
297 let id = self.headers_float.len();
298
299 self.headers_float.push(PrimitiveHeaderF {
300 local_rect: prim_header.local_rect,
301 local_clip_rect: prim_header.local_clip_rect,
302 });
303
304 self.headers_int.push(PrimitiveHeaderI {
305 z,
306 unused: 0,
307 specific_prim_address: prim_header.specific_prim_address.as_int(),
308 transform_id: prim_header.transform_id,
309 user_data,
310 });
311
312 PrimitiveHeaderIndex(id as i32)
313 }
314}
315
316#[derive(Debug)]
319pub struct PrimitiveHeader {
320 pub local_rect: LayoutRect,
321 pub local_clip_rect: LayoutRect,
322 pub specific_prim_address: GpuCacheAddress,
323 pub transform_id: TransformPaletteId,
324}
325
326#[derive(Debug)]
328#[repr(C)]
329#[cfg_attr(feature = "capture", derive(Serialize))]
330#[cfg_attr(feature = "replay", derive(Deserialize))]
331pub struct PrimitiveHeaderF {
332 pub local_rect: LayoutRect,
333 pub local_clip_rect: LayoutRect,
334}
335
336#[derive(Debug)]
339#[repr(C)]
340#[cfg_attr(feature = "capture", derive(Serialize))]
341#[cfg_attr(feature = "replay", derive(Deserialize))]
342pub struct PrimitiveHeaderI {
343 pub z: ZBufferId,
344 pub specific_prim_address: i32,
345 pub transform_id: TransformPaletteId,
346 pub unused: i32, pub user_data: [i32; 4],
348}
349
350pub struct GlyphInstance {
351 pub prim_header_index: PrimitiveHeaderIndex,
352}
353
354impl GlyphInstance {
355 pub fn new(
356 prim_header_index: PrimitiveHeaderIndex,
357 ) -> Self {
358 GlyphInstance {
359 prim_header_index,
360 }
361 }
362
363 pub fn build(&self, data0: i32, data1: i32, resource_address: i32) -> PrimitiveInstanceData {
367 PrimitiveInstanceData {
368 data: [
369 self.prim_header_index.0 as i32,
370 data0,
371 data1,
372 resource_address | ((BrushShaderKind::Text as i32) << 24),
373 ],
374 }
375 }
376}
377
378pub struct SplitCompositeInstance {
379 pub prim_header_index: PrimitiveHeaderIndex,
380 pub polygons_address: GpuCacheAddress,
381 pub z: ZBufferId,
382 pub render_task_address: RenderTaskAddress,
383}
384
385impl From<SplitCompositeInstance> for PrimitiveInstanceData {
386 fn from(instance: SplitCompositeInstance) -> Self {
387 PrimitiveInstanceData {
388 data: [
389 instance.prim_header_index.0,
390 instance.polygons_address.as_int(),
391 instance.z.0,
392 instance.render_task_address.0 as i32,
393 ],
394 }
395 }
396}
397
398bitflags! {
399 #[cfg_attr(feature = "capture", derive(Serialize))]
402 #[cfg_attr(feature = "replay", derive(Deserialize))]
403 #[derive(MallocSizeOf)]
404 pub struct BrushFlags: u8 {
405 const PERSPECTIVE_INTERPOLATION = 0x1;
407 const SEGMENT_RELATIVE = 0x2;
410 const SEGMENT_REPEAT_X = 0x4;
412 const SEGMENT_REPEAT_Y = 0x8;
414 const SEGMENT_TEXEL_RECT = 0x10;
416 }
417}
418
419pub struct BrushInstance {
421 pub prim_header_index: PrimitiveHeaderIndex,
422 pub render_task_address: RenderTaskAddress,
423 pub clip_task_address: RenderTaskAddress,
424 pub segment_index: i32,
425 pub edge_flags: EdgeAaSegmentMask,
426 pub brush_flags: BrushFlags,
427 pub resource_address: i32,
428 pub brush_kind: BrushShaderKind,
429}
430
431impl From<BrushInstance> for PrimitiveInstanceData {
432 fn from(instance: BrushInstance) -> Self {
433 PrimitiveInstanceData {
434 data: [
435 instance.prim_header_index.0,
436 ((instance.render_task_address.0 as i32) << 16)
437 | instance.clip_task_address.0 as i32,
438 instance.segment_index
439 | ((instance.edge_flags.bits() as i32) << 16)
440 | ((instance.brush_flags.bits() as i32) << 24),
441 instance.resource_address
442 | ((instance.brush_kind as i32) << 24),
443 ]
444 }
445 }
446}
447
448#[derive(Copy, Debug, Clone, PartialEq)]
455#[cfg_attr(feature = "capture", derive(Serialize))]
456#[cfg_attr(feature = "replay", derive(Deserialize))]
457#[repr(C)]
458pub struct TransformPaletteId(pub u32);
459
460impl TransformPaletteId {
461 pub const IDENTITY: Self = TransformPaletteId(0);
463
464 pub fn transform_kind(&self) -> TransformedRectKind {
466 if (self.0 >> 24) == 0 {
467 TransformedRectKind::AxisAligned
468 } else {
469 TransformedRectKind::Complex
470 }
471 }
472}
473
474#[derive(Debug, Clone)]
476#[cfg_attr(feature = "capture", derive(Serialize))]
477#[cfg_attr(feature = "replay", derive(Deserialize))]
478#[repr(C)]
479pub struct TransformData {
480 transform: LayoutToPictureTransform,
481 inv_transform: PictureToLayoutTransform,
482}
483
484impl TransformData {
485 fn invalid() -> Self {
486 TransformData {
487 transform: LayoutToPictureTransform::identity(),
488 inv_transform: PictureToLayoutTransform::identity(),
489 }
490 }
491}
492
493#[derive(Clone)]
495pub struct TransformMetadata {
496 transform_kind: TransformedRectKind,
497}
498
499impl TransformMetadata {
500 pub fn invalid() -> Self {
501 TransformMetadata {
502 transform_kind: TransformedRectKind::AxisAligned,
503 }
504 }
505}
506
507#[derive(Debug, Hash, Eq, PartialEq)]
508struct RelativeTransformKey {
509 from_index: SpatialNodeIndex,
510 to_index: SpatialNodeIndex,
511}
512
513pub struct TransformPalette {
521 transforms: Vec<TransformData>,
522 metadata: Vec<TransformMetadata>,
523 map: FastHashMap<RelativeTransformKey, usize>,
524}
525
526impl TransformPalette {
527 pub fn new(count: usize) -> Self {
528 let _ = VECS_PER_TRANSFORM;
529 TransformPalette {
530 transforms: vec![TransformData::invalid(); count],
531 metadata: vec![TransformMetadata::invalid(); count],
532 map: FastHashMap::default(),
533 }
534 }
535
536 pub fn finish(self) -> Vec<TransformData> {
537 self.transforms
538 }
539
540 pub fn set_world_transform(
541 &mut self,
542 index: SpatialNodeIndex,
543 transform: LayoutToWorldTransform,
544 ) {
545 register_transform(
546 &mut self.metadata,
547 &mut self.transforms,
548 index,
549 ROOT_SPATIAL_NODE_INDEX,
550 transform.with_destination::<PicturePixel>(),
552 );
553 }
554
555 fn get_index(
556 &mut self,
557 child_index: SpatialNodeIndex,
558 parent_index: SpatialNodeIndex,
559 clip_scroll_tree: &ClipScrollTree,
560 ) -> usize {
561 if parent_index == ROOT_SPATIAL_NODE_INDEX {
562 child_index.0 as usize
563 } else if child_index == parent_index {
564 0
565 } else {
566 let key = RelativeTransformKey {
567 from_index: child_index,
568 to_index: parent_index,
569 };
570
571 let metadata = &mut self.metadata;
572 let transforms = &mut self.transforms;
573
574 *self.map
575 .entry(key)
576 .or_insert_with(|| {
577 let transform = clip_scroll_tree.get_relative_transform(
578 child_index,
579 parent_index,
580 )
581 .into_transform()
582 .with_destination::<PicturePixel>();
583
584 register_transform(
585 metadata,
586 transforms,
587 child_index,
588 parent_index,
589 transform,
590 )
591 })
592 }
593 }
594
595 pub fn get_id(
600 &mut self,
601 from_index: SpatialNodeIndex,
602 to_index: SpatialNodeIndex,
603 clip_scroll_tree: &ClipScrollTree,
604 ) -> TransformPaletteId {
605 let index = self.get_index(
606 from_index,
607 to_index,
608 clip_scroll_tree,
609 );
610 let transform_kind = self.metadata[index].transform_kind as u32;
611 TransformPaletteId(
612 (index as u32) |
613 (transform_kind << 24)
614 )
615 }
616}
617
618#[derive(Debug, Copy, Clone)]
623#[cfg_attr(feature = "capture", derive(Serialize))]
624#[cfg_attr(feature = "replay", derive(Deserialize))]
625pub enum UvRectKind {
626 Rect,
629 Quad {
634 top_left: DeviceHomogeneousVector,
635 top_right: DeviceHomogeneousVector,
636 bottom_left: DeviceHomogeneousVector,
637 bottom_right: DeviceHomogeneousVector,
638 },
639}
640
641#[derive(Debug, Copy, Clone)]
642#[cfg_attr(feature = "capture", derive(Serialize))]
643#[cfg_attr(feature = "replay", derive(Deserialize))]
644pub struct ImageSource {
645 pub p0: DevicePoint,
646 pub p1: DevicePoint,
647 pub texture_layer: f32,
648 pub user_data: [f32; 3],
649 pub uv_rect_kind: UvRectKind,
650}
651
652impl ImageSource {
653 pub fn write_gpu_blocks(&self, request: &mut GpuDataRequest) {
654 request.push([
657 self.p0.x,
658 self.p0.y,
659 self.p1.x,
660 self.p1.y,
661 ]);
662 request.push([
663 self.texture_layer,
664 self.user_data[0],
665 self.user_data[1],
666 self.user_data[2],
667 ]);
668
669 if let UvRectKind::Quad { top_left, top_right, bottom_left, bottom_right } = self.uv_rect_kind {
671 request.push(top_left);
674 request.push(top_right);
675 request.push(bottom_left);
676 request.push(bottom_right);
677 }
678 }
679}
680
681fn register_transform(
684 metadatas: &mut Vec<TransformMetadata>,
685 transforms: &mut Vec<TransformData>,
686 from_index: SpatialNodeIndex,
687 to_index: SpatialNodeIndex,
688 transform: LayoutToPictureTransform,
689) -> usize {
690 let inv_transform = transform
693 .inverse()
694 .unwrap_or_else(PictureToLayoutTransform::identity);
695
696 let metadata = TransformMetadata {
697 transform_kind: transform.transform_kind()
698 };
699 let data = TransformData {
700 transform,
701 inv_transform,
702 };
703
704 if to_index == ROOT_SPATIAL_NODE_INDEX {
705 let index = from_index.0 as usize;
706 metadatas[index] = metadata;
707 transforms[index] = data;
708 index
709 } else {
710 let index = transforms.len();
711 metadatas.push(metadata);
712 transforms.push(data);
713 index
714 }
715}