1use api::{BorderRadius, ClipMode, ColorF};
6use api::{ImageRendering, RepeatMode, PrimitiveFlags};
7use api::{FillRule, POLYGON_CLIP_VERTEX_MAX};
8use api::units::*;
9use euclid::{SideOffsets2D, Size2D};
10use malloc_size_of::MallocSizeOf;
11use crate::clip::ClipLeafId;
12use crate::quad::QuadTileClassifier;
13use crate::renderer::{GpuBufferAddress, GpuBufferHandle, GpuBufferWriterF};
14use crate::segment::EdgeMask;
15use crate::border::BorderSegmentCacheKey;
16use crate::debug_item::{DebugItem, DebugMessage};
17use crate::debug_colors;
18use glyph_rasterizer::GlyphKey;
19use crate::gpu_types::{BrushFlags, BrushSegmentGpuData, QuadSegment};
20use crate::intern;
21use crate::picture::{PictureInstance, PictureScratch};
22use crate::render_task_graph::RenderTaskId;
23use crate::resource_cache::ImageProperties;
24use std::{hash, u32, usize};
25use crate::util::Recycler;
26use crate::internal_types::{FastHashSet, LayoutPrimitiveInfo};
27use crate::visibility::PrimitiveDrawHeader;
28
29pub mod backdrop;
30pub mod borders;
31pub mod gradient;
32pub mod image;
33pub mod line_dec;
34pub mod picture;
35pub mod rectangle;
36pub mod text_run;
37pub mod interned;
38
39pub mod storage;
40
41use backdrop::{BackdropCaptureDataHandle, BackdropRenderDataHandle, BackdropRenderScratch};
42use borders::{ImageBorderDataHandle, ImageBorderScratch, NormalBorderDataHandle, NormalBorderScratch};
43use gradient::{LinearGradientDataHandle, RadialGradientDataHandle, ConicGradientDataHandle};
44use image::{ImageDataHandle, ImageScratch, VisibleImageTile, YuvImageDataHandle};
45use line_dec::{LineDecorationDataHandle, LineDecorationScratch};
46use picture::PictureDataHandle;
47use rectangle::RectangleDataHandle;
48use text_run::{TextRunDataHandle, TextRunScratch};
49use crate::box_shadow::BoxShadowDataHandle;
50
51pub const VECS_PER_SEGMENT: usize = 2;
52
53#[cfg_attr(feature = "capture", derive(Serialize))]
54#[cfg_attr(feature = "replay", derive(Deserialize))]
55#[derive(Debug, Copy, Clone, MallocSizeOf)]
56pub struct PrimitiveOpacity {
57 pub is_opaque: bool,
58}
59
60impl PrimitiveOpacity {
61 pub fn opaque() -> PrimitiveOpacity {
62 PrimitiveOpacity { is_opaque: true }
63 }
64
65 pub fn translucent() -> PrimitiveOpacity {
66 PrimitiveOpacity { is_opaque: false }
67 }
68
69 pub fn from_alpha(alpha: f32) -> PrimitiveOpacity {
70 PrimitiveOpacity {
71 is_opaque: alpha >= 1.0,
72 }
73 }
74}
75
76#[cfg_attr(feature = "capture", derive(Serialize))]
87#[cfg_attr(feature = "replay", derive(Deserialize))]
88pub struct DeferredResolve {
89 pub handle: GpuBufferHandle,
90 pub image_properties: ImageProperties,
91 pub rendering: ImageRendering,
92 pub is_composited: bool,
93}
94
95#[derive(Debug, Copy, Clone, PartialEq)]
96#[cfg_attr(feature = "capture", derive(Serialize))]
97pub struct ClipTaskIndex(pub u32);
98
99impl ClipTaskIndex {
100 pub const INVALID: ClipTaskIndex = ClipTaskIndex(0);
101}
102
103#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, MallocSizeOf, Ord, PartialOrd)]
104#[cfg_attr(feature = "capture", derive(Serialize))]
105#[cfg_attr(feature = "replay", derive(Deserialize))]
106pub struct PictureIndex(pub usize);
107
108impl PictureIndex {
109 pub const INVALID: PictureIndex = PictureIndex(!0);
110}
111
112#[cfg_attr(feature = "capture", derive(Serialize))]
113#[cfg_attr(feature = "replay", derive(Deserialize))]
114#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)]
115pub struct RectKey {
116 pub x0: f32,
117 pub y0: f32,
118 pub x1: f32,
119 pub y1: f32,
120}
121
122impl RectKey {
123 pub fn intersects(&self, other: &Self) -> bool {
124 self.x0 < other.x1
125 && other.x0 < self.x1
126 && self.y0 < other.y1
127 && other.y0 < self.y1
128 }
129}
130
131impl Eq for RectKey {}
132
133impl hash::Hash for RectKey {
134 fn hash<H: hash::Hasher>(&self, state: &mut H) {
135 self.x0.to_bits().hash(state);
136 self.y0.to_bits().hash(state);
137 self.x1.to_bits().hash(state);
138 self.y1.to_bits().hash(state);
139 }
140}
141
142impl From<RectKey> for LayoutRect {
143 fn from(key: RectKey) -> LayoutRect {
144 LayoutRect {
145 min: LayoutPoint::new(key.x0, key.y0),
146 max: LayoutPoint::new(key.x1, key.y1),
147 }
148 }
149}
150
151impl From<RectKey> for WorldRect {
152 fn from(key: RectKey) -> WorldRect {
153 WorldRect {
154 min: WorldPoint::new(key.x0, key.y0),
155 max: WorldPoint::new(key.x1, key.y1),
156 }
157 }
158}
159
160impl From<LayoutRect> for RectKey {
161 fn from(rect: LayoutRect) -> RectKey {
162 RectKey {
163 x0: rect.min.x,
164 y0: rect.min.y,
165 x1: rect.max.x,
166 y1: rect.max.y,
167 }
168 }
169}
170
171impl From<PictureRect> for RectKey {
172 fn from(rect: PictureRect) -> RectKey {
173 RectKey {
174 x0: rect.min.x,
175 y0: rect.min.y,
176 x1: rect.max.x,
177 y1: rect.max.y,
178 }
179 }
180}
181
182impl From<WorldRect> for RectKey {
183 fn from(rect: WorldRect) -> RectKey {
184 RectKey {
185 x0: rect.min.x,
186 y0: rect.min.y,
187 x1: rect.max.x,
188 y1: rect.max.y,
189 }
190 }
191}
192
193#[cfg_attr(feature = "capture", derive(Serialize))]
198#[cfg_attr(feature = "replay", derive(Deserialize))]
199#[derive(Copy, Debug, Clone, Hash, MallocSizeOf, PartialEq)]
200pub struct PolygonKey {
201 pub point_count: u8,
202 pub points: [PointKey; POLYGON_CLIP_VERTEX_MAX],
203 pub fill_rule: FillRule,
204}
205
206impl PolygonKey {
207 pub fn new(
208 points_layout: &Vec<LayoutPoint>,
209 fill_rule: FillRule,
210 ) -> Self {
211 let mut points: [PointKey; POLYGON_CLIP_VERTEX_MAX] = [PointKey { x: 0.0, y: 0.0}; POLYGON_CLIP_VERTEX_MAX];
216
217 let mut point_count: u8 = 0;
218 for (src, dest) in points_layout.iter().zip(points.iter_mut()) {
219 *dest = (*src as LayoutPoint).into();
220 point_count = point_count + 1;
221 }
222
223 PolygonKey {
224 point_count,
225 points,
226 fill_rule,
227 }
228 }
229}
230
231impl Eq for PolygonKey {}
232
233#[cfg_attr(feature = "capture", derive(Serialize))]
235#[cfg_attr(feature = "replay", derive(Deserialize))]
236#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
237pub struct SideOffsetsKey {
238 pub top: f32,
239 pub right: f32,
240 pub bottom: f32,
241 pub left: f32,
242}
243
244impl Eq for SideOffsetsKey {}
245
246impl hash::Hash for SideOffsetsKey {
247 fn hash<H: hash::Hasher>(&self, state: &mut H) {
248 self.top.to_bits().hash(state);
249 self.right.to_bits().hash(state);
250 self.bottom.to_bits().hash(state);
251 self.left.to_bits().hash(state);
252 }
253}
254
255impl From<SideOffsetsKey> for LayoutSideOffsets {
256 fn from(key: SideOffsetsKey) -> LayoutSideOffsets {
257 LayoutSideOffsets::new(
258 key.top,
259 key.right,
260 key.bottom,
261 key.left,
262 )
263 }
264}
265
266impl<U> From<SideOffsets2D<f32, U>> for SideOffsetsKey {
267 fn from(offsets: SideOffsets2D<f32, U>) -> SideOffsetsKey {
268 SideOffsetsKey {
269 top: offsets.top,
270 right: offsets.right,
271 bottom: offsets.bottom,
272 left: offsets.left,
273 }
274 }
275}
276
277#[cfg_attr(feature = "capture", derive(Serialize))]
279#[cfg_attr(feature = "replay", derive(Deserialize))]
280#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)]
281pub struct SizeKey {
282 w: f32,
283 h: f32,
284}
285
286impl Eq for SizeKey {}
287
288impl hash::Hash for SizeKey {
289 fn hash<H: hash::Hasher>(&self, state: &mut H) {
290 self.w.to_bits().hash(state);
291 self.h.to_bits().hash(state);
292 }
293}
294
295impl From<SizeKey> for LayoutSize {
296 fn from(key: SizeKey) -> LayoutSize {
297 LayoutSize::new(key.w, key.h)
298 }
299}
300
301impl<U> From<Size2D<f32, U>> for SizeKey {
302 fn from(size: Size2D<f32, U>) -> SizeKey {
303 SizeKey {
304 w: size.width,
305 h: size.height,
306 }
307 }
308}
309
310#[cfg_attr(feature = "capture", derive(Serialize))]
312#[cfg_attr(feature = "replay", derive(Deserialize))]
313#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)]
314pub struct VectorKey {
315 pub x: f32,
316 pub y: f32,
317}
318
319impl Eq for VectorKey {}
320
321impl hash::Hash for VectorKey {
322 fn hash<H: hash::Hasher>(&self, state: &mut H) {
323 self.x.to_bits().hash(state);
324 self.y.to_bits().hash(state);
325 }
326}
327
328impl From<VectorKey> for LayoutVector2D {
329 fn from(key: VectorKey) -> LayoutVector2D {
330 LayoutVector2D::new(key.x, key.y)
331 }
332}
333
334impl From<VectorKey> for WorldVector2D {
335 fn from(key: VectorKey) -> WorldVector2D {
336 WorldVector2D::new(key.x, key.y)
337 }
338}
339
340impl From<LayoutVector2D> for VectorKey {
341 fn from(vec: LayoutVector2D) -> VectorKey {
342 VectorKey {
343 x: vec.x,
344 y: vec.y,
345 }
346 }
347}
348
349impl From<WorldVector2D> for VectorKey {
350 fn from(vec: WorldVector2D) -> VectorKey {
351 VectorKey {
352 x: vec.x,
353 y: vec.y,
354 }
355 }
356}
357
358#[cfg_attr(feature = "capture", derive(Serialize))]
360#[cfg_attr(feature = "replay", derive(Deserialize))]
361#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
362pub struct PointKey {
363 pub x: f32,
364 pub y: f32,
365}
366
367impl Eq for PointKey {}
368
369impl hash::Hash for PointKey {
370 fn hash<H: hash::Hasher>(&self, state: &mut H) {
371 self.x.to_bits().hash(state);
372 self.y.to_bits().hash(state);
373 }
374}
375
376impl From<PointKey> for LayoutPoint {
377 fn from(key: PointKey) -> LayoutPoint {
378 LayoutPoint::new(key.x, key.y)
379 }
380}
381
382impl From<LayoutPoint> for PointKey {
383 fn from(p: LayoutPoint) -> PointKey {
384 PointKey {
385 x: p.x,
386 y: p.y,
387 }
388 }
389}
390
391impl From<PicturePoint> for PointKey {
392 fn from(p: PicturePoint) -> PointKey {
393 PointKey {
394 x: p.x,
395 y: p.y,
396 }
397 }
398}
399
400impl From<WorldPoint> for PointKey {
401 fn from(p: WorldPoint) -> PointKey {
402 PointKey {
403 x: p.x,
404 y: p.y,
405 }
406 }
407}
408
409#[cfg_attr(feature = "capture", derive(Serialize))]
412#[cfg_attr(feature = "replay", derive(Deserialize))]
413#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
414pub struct PrimKeyCommonData {
415 pub flags: PrimitiveFlags,
416 pub aligned_aa_edges: EdgeMask,
417 pub transformed_aa_edges: EdgeMask,
418}
419
420impl From<&LayoutPrimitiveInfo> for PrimKeyCommonData {
421 fn from(info: &LayoutPrimitiveInfo) -> Self {
422 PrimKeyCommonData {
423 flags: info.flags,
424 aligned_aa_edges: info.aligned_aa_edges,
425 transformed_aa_edges: info.transformed_aa_edges,
426 }
427 }
428}
429
430#[cfg_attr(feature = "capture", derive(Serialize))]
431#[cfg_attr(feature = "replay", derive(Deserialize))]
432#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
433pub struct PrimKey<T: MallocSizeOf> {
434 pub common: PrimKeyCommonData,
435 pub kind: T,
436}
437
438#[cfg_attr(feature = "capture", derive(Serialize))]
439#[cfg_attr(feature = "replay", derive(Deserialize))]
440#[derive(MallocSizeOf)]
441#[derive(Debug)]
442pub struct PrimTemplateCommonData {
443 pub flags: PrimitiveFlags,
444 pub opacity: PrimitiveOpacity,
445 pub gpu_buffer_address: GpuBufferAddress,
451 pub aligned_aa_edges: EdgeMask,
452 pub transformed_aa_edges: EdgeMask,
453}
454
455impl PrimTemplateCommonData {
456 pub fn with_key_common(common: PrimKeyCommonData) -> Self {
457 PrimTemplateCommonData {
458 flags: common.flags,
459 gpu_buffer_address: GpuBufferAddress::INVALID,
460 opacity: PrimitiveOpacity::translucent(),
461 aligned_aa_edges: common.aligned_aa_edges,
462 transformed_aa_edges: common.transformed_aa_edges,
463 }
464 }
465}
466
467#[cfg_attr(feature = "capture", derive(Serialize))]
468#[cfg_attr(feature = "replay", derive(Deserialize))]
469#[derive(MallocSizeOf)]
470pub struct PrimTemplate<T> {
471 pub common: PrimTemplateCommonData,
472 pub kind: T,
473}
474
475#[derive(Debug, MallocSizeOf)]
476#[cfg_attr(feature = "capture", derive(Serialize))]
477#[cfg_attr(feature = "replay", derive(Deserialize))]
478pub struct VisibleMaskImageTile {
479 pub tile_offset: TileOffset,
480 pub tile_rect: LayoutRect,
481 pub task_id: RenderTaskId,
482}
483
484#[cfg_attr(feature = "capture", derive(Serialize))]
487#[cfg_attr(feature = "replay", derive(Deserialize))]
488#[derive(Debug, MallocSizeOf)]
489pub struct BorderSegmentInfo {
490 pub local_task_size: LayoutSize,
491 pub cache_key: BorderSegmentCacheKey,
492}
493
494#[cfg_attr(feature = "capture", derive(Serialize))]
496#[derive(Debug, Clone)]
497pub enum ClipMaskKind {
498 Mask(RenderTaskId),
500 None,
502 Clipped,
504}
505
506#[cfg_attr(feature = "capture", derive(Serialize))]
507#[cfg_attr(feature = "replay", derive(Deserialize))]
508#[derive(Debug, Clone, MallocSizeOf)]
509pub struct BrushSegment {
510 pub local_rect: LayoutRect,
511 pub may_need_clip_mask: bool,
512 pub edge_flags: EdgeMask,
513 pub extra_data: [f32; 4],
514 pub brush_flags: BrushFlags,
515}
516
517impl BrushSegment {
518 pub fn new(
519 local_rect: LayoutRect,
520 may_need_clip_mask: bool,
521 edge_flags: EdgeMask,
522 extra_data: [f32; 4],
523 brush_flags: BrushFlags,
524 ) -> Self {
525 Self {
526 local_rect,
527 may_need_clip_mask,
528 edge_flags,
529 extra_data,
530 brush_flags,
531 }
532 }
533
534 pub fn gpu_data(&self) -> BrushSegmentGpuData {
535 BrushSegmentGpuData {
536 local_rect: self.local_rect,
537 extra_data: self.extra_data,
538 }
539 }
540
541 pub fn write_gpu_blocks(&self, writer: &mut GpuBufferWriterF) {
542 writer.push(&self.gpu_data());
543 }
544}
545
546#[derive(Debug, Clone)]
547#[repr(C)]
548#[cfg_attr(feature = "capture", derive(Serialize))]
549#[cfg_attr(feature = "replay", derive(Deserialize))]
550struct ClipRect {
551 rect: LayoutRect,
552 mode: f32,
553}
554
555#[derive(Debug, Clone)]
556#[repr(C)]
557#[cfg_attr(feature = "capture", derive(Serialize))]
558#[cfg_attr(feature = "replay", derive(Deserialize))]
559struct ClipCorner {
560 rect: LayoutRect,
561 outer_radius_x: f32,
562 outer_radius_y: f32,
563 inner_radius_x: f32,
564 inner_radius_y: f32,
565}
566
567impl ClipCorner {
568 fn uniform(rect: LayoutRect, outer_radius: f32, inner_radius: f32) -> ClipCorner {
569 ClipCorner {
570 rect,
571 outer_radius_x: outer_radius,
572 outer_radius_y: outer_radius,
573 inner_radius_x: inner_radius,
574 inner_radius_y: inner_radius,
575 }
576 }
577}
578
579#[derive(Debug, Clone)]
580#[repr(C)]
581#[cfg_attr(feature = "capture", derive(Serialize))]
582#[cfg_attr(feature = "replay", derive(Deserialize))]
583pub struct ClipData {
584 rect: ClipRect,
585 top_left: ClipCorner,
586 top_right: ClipCorner,
587 bottom_left: ClipCorner,
588 bottom_right: ClipCorner,
589}
590
591impl ClipData {
592 pub fn rounded_rect(size: LayoutSize, radii: &BorderRadius, mode: ClipMode) -> ClipData {
593 let rect = LayoutRect::from_size(size);
598
599 ClipData {
600 rect: ClipRect {
601 rect,
602 mode: mode as u32 as f32,
603 },
604 top_left: ClipCorner {
605 rect: LayoutRect::from_origin_and_size(
606 LayoutPoint::new(rect.min.x, rect.min.y),
607 LayoutSize::new(radii.top_left.width, radii.top_left.height),
608 ),
609 outer_radius_x: radii.top_left.width,
610 outer_radius_y: radii.top_left.height,
611 inner_radius_x: 0.0,
612 inner_radius_y: 0.0,
613 },
614 top_right: ClipCorner {
615 rect: LayoutRect::from_origin_and_size(
616 LayoutPoint::new(
617 rect.max.x - radii.top_right.width,
618 rect.min.y,
619 ),
620 LayoutSize::new(radii.top_right.width, radii.top_right.height),
621 ),
622 outer_radius_x: radii.top_right.width,
623 outer_radius_y: radii.top_right.height,
624 inner_radius_x: 0.0,
625 inner_radius_y: 0.0,
626 },
627 bottom_left: ClipCorner {
628 rect: LayoutRect::from_origin_and_size(
629 LayoutPoint::new(
630 rect.min.x,
631 rect.max.y - radii.bottom_left.height,
632 ),
633 LayoutSize::new(radii.bottom_left.width, radii.bottom_left.height),
634 ),
635 outer_radius_x: radii.bottom_left.width,
636 outer_radius_y: radii.bottom_left.height,
637 inner_radius_x: 0.0,
638 inner_radius_y: 0.0,
639 },
640 bottom_right: ClipCorner {
641 rect: LayoutRect::from_origin_and_size(
642 LayoutPoint::new(
643 rect.max.x - radii.bottom_right.width,
644 rect.max.y - radii.bottom_right.height,
645 ),
646 LayoutSize::new(radii.bottom_right.width, radii.bottom_right.height),
647 ),
648 outer_radius_x: radii.bottom_right.width,
649 outer_radius_y: radii.bottom_right.height,
650 inner_radius_x: 0.0,
651 inner_radius_y: 0.0,
652 },
653 }
654 }
655
656 pub fn uniform(size: LayoutSize, radius: f32, mode: ClipMode) -> ClipData {
657 let rect = LayoutRect::from_size(size);
662
663 ClipData {
664 rect: ClipRect {
665 rect,
666 mode: mode as u32 as f32,
667 },
668 top_left: ClipCorner::uniform(
669 LayoutRect::from_origin_and_size(
670 LayoutPoint::new(rect.min.x, rect.min.y),
671 LayoutSize::new(radius, radius),
672 ),
673 radius,
674 0.0,
675 ),
676 top_right: ClipCorner::uniform(
677 LayoutRect::from_origin_and_size(
678 LayoutPoint::new(rect.max.x - radius, rect.min.y),
679 LayoutSize::new(radius, radius),
680 ),
681 radius,
682 0.0,
683 ),
684 bottom_left: ClipCorner::uniform(
685 LayoutRect::from_origin_and_size(
686 LayoutPoint::new(rect.min.x, rect.max.y - radius),
687 LayoutSize::new(radius, radius),
688 ),
689 radius,
690 0.0,
691 ),
692 bottom_right: ClipCorner::uniform(
693 LayoutRect::from_origin_and_size(
694 LayoutPoint::new(
695 rect.max.x - radius,
696 rect.max.y - radius,
697 ),
698 LayoutSize::new(radius, radius),
699 ),
700 radius,
701 0.0,
702 ),
703 }
704 }
705}
706
707#[derive(Debug, Clone, PartialEq, Eq, Hash, MallocSizeOf)]
710#[cfg_attr(feature = "capture", derive(Serialize))]
711#[cfg_attr(feature = "replay", derive(Deserialize))]
712pub struct NinePatchDescriptor {
713 pub width: i32,
714 pub height: i32,
715 pub slice: DeviceIntSideOffsets,
716 pub fill: bool,
717 pub repeat_horizontal: RepeatMode,
718 pub repeat_vertical: RepeatMode,
719 pub widths: SideOffsetsKey,
720}
721
722#[derive(Debug)]
723#[cfg_attr(feature = "capture", derive(Serialize))]
724pub enum PrimitiveKind {
725 Picture {
727 data_handle: PictureDataHandle,
729 pic_index: PictureIndex,
730 },
731 TextRun {
733 data_handle: TextRunDataHandle,
735 },
736 LineDecoration {
739 data_handle: LineDecorationDataHandle,
741 },
742 NormalBorder {
743 data_handle: NormalBorderDataHandle,
745 },
746 ImageBorder {
747 data_handle: ImageBorderDataHandle,
749 },
750 Rectangle {
751 data_handle: RectangleDataHandle,
753 },
754 YuvImage {
755 data_handle: YuvImageDataHandle,
757 },
758 Image {
759 data_handle: ImageDataHandle,
761 },
762 LinearGradient {
763 data_handle: LinearGradientDataHandle,
765 },
766 RadialGradient {
767 data_handle: RadialGradientDataHandle,
769 },
770 ConicGradient {
771 data_handle: ConicGradientDataHandle,
773 },
774 BackdropCapture {
776 data_handle: BackdropCaptureDataHandle,
777 },
778 BackdropRender {
779 data_handle: BackdropRenderDataHandle,
780 pic_index: PictureIndex,
781 },
782 BoxShadow {
783 data_handle: BoxShadowDataHandle,
784 },
785}
786
787impl PrimitiveKind {
788 pub fn as_pic(&self) -> PictureIndex {
789 match self {
790 PrimitiveKind::Picture { pic_index, .. } => *pic_index,
791 _ => panic!("bug: as_pic called on a prim that is not a picture"),
792 }
793 }
794}
795
796#[derive(Debug, Copy, Clone)]
797#[cfg_attr(feature = "capture", derive(Serialize))]
798#[cfg_attr(feature = "replay", derive(Deserialize))]
799pub struct PrimitiveInstanceIndex(pub u32);
800
801impl PrimitiveInstanceIndex {
802 pub const INVALID: PrimitiveInstanceIndex = PrimitiveInstanceIndex(!0);
803}
804
805#[derive(Debug)]
806#[cfg_attr(feature = "capture", derive(Serialize))]
807pub struct PrimitiveInstance {
808 pub kind: PrimitiveKind,
813
814 pub clip_leaf_id: ClipLeafId,
816
817 pub unsnapped_prim_rect: LayoutRect,
824}
825
826impl PrimitiveInstance {
827 pub fn new(
828 kind: PrimitiveKind,
829 clip_leaf_id: ClipLeafId,
830 unsnapped_prim_rect: LayoutRect,
831 ) -> Self {
832 PrimitiveInstance {
833 kind,
834 clip_leaf_id,
835 unsnapped_prim_rect,
836 }
837 }
838
839 pub fn uid(&self) -> intern::ItemUid {
840 match &self.kind {
841 PrimitiveKind::Rectangle { data_handle, .. } => {
842 data_handle.uid()
843 }
844 PrimitiveKind::Image { data_handle, .. } => {
845 data_handle.uid()
846 }
847 PrimitiveKind::ImageBorder { data_handle, .. } => {
848 data_handle.uid()
849 }
850 PrimitiveKind::LineDecoration { data_handle, .. } => {
851 data_handle.uid()
852 }
853 PrimitiveKind::LinearGradient { data_handle, .. } => {
854 data_handle.uid()
855 }
856 PrimitiveKind::NormalBorder { data_handle, .. } => {
857 data_handle.uid()
858 }
859 PrimitiveKind::Picture { data_handle, .. } => {
860 data_handle.uid()
861 }
862 PrimitiveKind::RadialGradient { data_handle, .. } => {
863 data_handle.uid()
864 }
865 PrimitiveKind::ConicGradient { data_handle, .. } => {
866 data_handle.uid()
867 }
868 PrimitiveKind::TextRun { data_handle, .. } => {
869 data_handle.uid()
870 }
871 PrimitiveKind::YuvImage { data_handle, .. } => {
872 data_handle.uid()
873 }
874 PrimitiveKind::BackdropCapture { data_handle, .. } => {
875 data_handle.uid()
876 }
877 PrimitiveKind::BackdropRender { data_handle, .. } => {
878 data_handle.uid()
879 }
880 PrimitiveKind::BoxShadow { data_handle, .. } => {
881 data_handle.uid()
882 }
883
884 }
885 }
886}
887
888#[cfg_attr(feature = "capture", derive(Serialize))]
889#[derive(Debug)]
890pub struct BrushSegmentation {
891 pub gpu_data: GpuBufferAddress,
892 pub segments_range: SegmentsRange,
893}
894
895pub type GlyphKeyStorage = storage::Storage<GlyphKey>;
896pub type SegmentStorage = storage::Storage<BrushSegment>;
897pub type SegmentsRange = storage::Range<BrushSegment>;
898pub type SegmentInstanceStorage = storage::Storage<BrushSegmentation>;
899pub type SegmentInstanceIndex = storage::Index<BrushSegmentation>;
900#[cfg_attr(feature = "capture", derive(Serialize))]
903pub struct PrimitiveFrameScratch {
904 pub draws: Vec<PrimitiveDrawHeader>,
911
912 pub line_decoration: storage::Storage<LineDecorationScratch>,
914
915 pub normal_border: storage::Storage<NormalBorderScratch>,
917
918 pub backdrop_render: storage::Storage<BackdropRenderScratch>,
922
923 pub pictures: storage::Storage<PictureScratch>,
928
929 pub images: storage::Storage<ImageScratch>,
933
934 pub visible_image_tiles: storage::Storage<VisibleImageTile>,
937
938 pub text_runs: storage::Storage<TextRunScratch>,
942
943 pub glyph_keys: GlyphKeyStorage,
949
950 pub segments: SegmentStorage,
955
956 pub segment_instances: SegmentInstanceStorage,
961
962 pub border_task_ids: storage::Storage<RenderTaskId>,
965
966 pub border_segments: storage::Storage<BorderSegmentInfo>,
970
971 pub image_border: storage::Storage<ImageBorderScratch>,
975
976 pub clip_mask_instances: Vec<ClipMaskKind>,
979
980 pub debug_items: Vec<DebugItem>,
984
985 pub required_sub_graphs: FastHashSet<PictureIndex>,
987
988 pub quad_direct_segments: Vec<QuadSegment>,
990 pub quad_indirect_segments: Vec<QuadSegment>,
991}
992
993impl Default for PrimitiveFrameScratch {
994 fn default() -> Self {
995 PrimitiveFrameScratch {
996 draws: Vec::new(),
997 line_decoration: storage::Storage::new(0),
998 normal_border: storage::Storage::new(0),
999 backdrop_render: storage::Storage::new(0),
1000 pictures: storage::Storage::new(0),
1001 images: storage::Storage::new(0),
1002 visible_image_tiles: storage::Storage::new(0),
1003 text_runs: storage::Storage::new(0),
1004 glyph_keys: GlyphKeyStorage::new(0),
1005 segments: SegmentStorage::new(0),
1006 segment_instances: SegmentInstanceStorage::new(0),
1007 border_task_ids: storage::Storage::new(0),
1008 border_segments: storage::Storage::new(0),
1009 image_border: storage::Storage::new(0),
1010 clip_mask_instances: Vec::new(),
1011 debug_items: Vec::new(),
1012 required_sub_graphs: FastHashSet::default(),
1013 quad_direct_segments: Vec::new(),
1014 quad_indirect_segments: Vec::new(),
1015 }
1016 }
1017}
1018
1019impl PrimitiveFrameScratch {
1020 pub fn recycle(&mut self, recycler: &mut Recycler) {
1021 recycler.recycle_vec(&mut self.draws);
1022 self.line_decoration.recycle(recycler);
1023 self.normal_border.recycle(recycler);
1024 self.backdrop_render.recycle(recycler);
1025 self.pictures.recycle(recycler);
1026 self.images.recycle(recycler);
1027 self.visible_image_tiles.recycle(recycler);
1028 self.text_runs.recycle(recycler);
1029 self.glyph_keys.recycle(recycler);
1030 self.segments.recycle(recycler);
1031 self.segment_instances.recycle(recycler);
1032 self.border_task_ids.recycle(recycler);
1033 self.border_segments.recycle(recycler);
1034 self.image_border.recycle(recycler);
1035 recycler.recycle_vec(&mut self.clip_mask_instances);
1036 recycler.recycle_vec(&mut self.debug_items);
1037 recycler.recycle_vec(&mut self.quad_direct_segments);
1038 recycler.recycle_vec(&mut self.quad_indirect_segments);
1039 }
1040
1041 pub fn begin_frame(&mut self) {
1042 self.line_decoration.clear();
1043 self.normal_border.clear();
1044 self.backdrop_render.clear();
1045 self.pictures.clear();
1046 self.images.clear();
1047 self.visible_image_tiles.clear();
1048 self.text_runs.clear();
1049 self.glyph_keys.clear();
1050 self.segments.clear();
1051 self.segment_instances.clear();
1052 self.border_task_ids.clear();
1053 self.border_segments.clear();
1054 self.image_border.clear();
1055
1056 self.clip_mask_instances.clear();
1060 self.clip_mask_instances.push(ClipMaskKind::None);
1061 self.quad_direct_segments.clear();
1062 self.quad_indirect_segments.clear();
1063
1064 self.required_sub_graphs.clear();
1065
1066 self.debug_items.clear();
1067 }
1068}
1069
1070#[cfg_attr(feature = "capture", derive(Serialize))]
1076#[derive(Default)]
1077pub struct PrimitiveSceneCache {}
1078
1079impl PrimitiveSceneCache {
1080 pub fn recycle(&mut self, _recycler: &mut Recycler) {}
1081}
1082
1083#[cfg_attr(feature = "capture", derive(Serialize))]
1087pub struct PrimitiveRetained {
1088 messages: Vec<DebugMessage>,
1092
1093 pub quad_tile_classifier: QuadTileClassifier,
1096}
1097
1098impl Default for PrimitiveRetained {
1099 fn default() -> Self {
1100 PrimitiveRetained {
1101 messages: Vec::new(),
1102 quad_tile_classifier: QuadTileClassifier::new(),
1103 }
1104 }
1105}
1106
1107#[cfg_attr(feature = "capture", derive(Serialize))]
1116#[derive(Default)]
1117pub struct PrimitiveScratchBuffer {
1118 pub frame: PrimitiveFrameScratch,
1119 pub scene: PrimitiveSceneCache,
1120 pub retained: PrimitiveRetained,
1121}
1122
1123impl PrimitiveScratchBuffer {
1124 pub fn recycle(&mut self, recycler: &mut Recycler) {
1125 self.frame.recycle(recycler);
1126 self.scene.recycle(recycler);
1127 }
1128
1129 pub fn begin_frame(&mut self) {
1130 self.frame.begin_frame();
1131 }
1132
1133 pub fn end_frame(&mut self) {
1134 const MSGS_TO_RETAIN: usize = 32;
1135 const TIME_TO_RETAIN: u64 = 2000000000;
1136 const LINE_HEIGHT: f32 = 20.0;
1137 const X0: f32 = 32.0;
1138 const Y0: f32 = 32.0;
1139 let now = zeitstempel::now();
1140
1141 let messages = &mut self.retained.messages;
1142 let msgs_to_remove = messages.len().max(MSGS_TO_RETAIN) - MSGS_TO_RETAIN;
1143 let mut msgs_removed = 0;
1144
1145 messages.retain(|msg| {
1146 if msgs_removed < msgs_to_remove {
1147 msgs_removed += 1;
1148 return false;
1149 }
1150
1151 if msg.timestamp + TIME_TO_RETAIN < now {
1152 return false;
1153 }
1154
1155 true
1156 });
1157
1158 let mut y = Y0 + messages.len() as f32 * LINE_HEIGHT;
1159 let shadow_offset = 1.0;
1160 let debug_items = &mut self.frame.debug_items;
1161
1162 for msg in messages.iter() {
1163 debug_items.push(DebugItem::Text {
1164 position: DevicePoint::new(X0 + shadow_offset, y + shadow_offset),
1165 color: debug_colors::BLACK,
1166 msg: msg.msg.clone(),
1167 });
1168
1169 debug_items.push(DebugItem::Text {
1170 position: DevicePoint::new(X0, y),
1171 color: debug_colors::RED,
1172 msg: msg.msg.clone(),
1173 });
1174
1175 y -= LINE_HEIGHT;
1176 }
1177 }
1178
1179 pub fn push_debug_rect_with_stroke_width(
1180 &mut self,
1181 rect: WorldRect,
1182 border: ColorF,
1183 stroke_width: f32
1184 ) {
1185 let top_edge = WorldRect::new(
1186 WorldPoint::new(rect.min.x + stroke_width, rect.min.y),
1187 WorldPoint::new(rect.max.x - stroke_width, rect.min.y + stroke_width)
1188 );
1189 self.push_debug_rect(top_edge * DevicePixelScale::new(1.0), 1, border, border);
1190
1191 let bottom_edge = WorldRect::new(
1192 WorldPoint::new(rect.min.x + stroke_width, rect.max.y - stroke_width),
1193 WorldPoint::new(rect.max.x - stroke_width, rect.max.y)
1194 );
1195 self.push_debug_rect(bottom_edge * DevicePixelScale::new(1.0), 1, border, border);
1196
1197 let right_edge = WorldRect::new(
1198 WorldPoint::new(rect.max.x - stroke_width, rect.min.y),
1199 rect.max
1200 );
1201 self.push_debug_rect(right_edge * DevicePixelScale::new(1.0), 1, border, border);
1202
1203 let left_edge = WorldRect::new(
1204 rect.min,
1205 WorldPoint::new(rect.min.x + stroke_width, rect.max.y)
1206 );
1207 self.push_debug_rect(left_edge * DevicePixelScale::new(1.0), 1, border, border);
1208 }
1209
1210 #[allow(dead_code)]
1211 pub fn push_debug_rect(
1212 &mut self,
1213 rect: DeviceRect,
1214 thickness: i32,
1215 outer_color: ColorF,
1216 inner_color: ColorF,
1217 ) {
1218 self.frame.debug_items.push(DebugItem::Rect {
1219 rect,
1220 outer_color,
1221 inner_color,
1222 thickness,
1223 });
1224 }
1225
1226 #[allow(dead_code)]
1227 pub fn push_debug_string(
1228 &mut self,
1229 position: DevicePoint,
1230 color: ColorF,
1231 msg: String,
1232 ) {
1233 self.frame.debug_items.push(DebugItem::Text {
1234 position,
1235 color,
1236 msg,
1237 });
1238 }
1239
1240 #[allow(dead_code)]
1241 pub fn log(
1242 &mut self,
1243 msg: String,
1244 ) {
1245 self.retained.messages.push(DebugMessage {
1246 msg,
1247 timestamp: zeitstempel::now(),
1248 })
1249 }
1250}
1251
1252#[cfg_attr(feature = "capture", derive(Serialize))]
1253#[cfg_attr(feature = "replay", derive(Deserialize))]
1254#[derive(Clone, Debug)]
1255pub struct PrimitiveStoreStats {
1256 picture_count: usize,
1257}
1258
1259impl PrimitiveStoreStats {
1260 pub fn empty() -> Self {
1261 PrimitiveStoreStats {
1262 picture_count: 0,
1263 }
1264 }
1265}
1266
1267#[cfg_attr(feature = "capture", derive(Serialize))]
1268pub struct PrimitiveStore {
1269 pub pictures: Vec<PictureInstance>,
1270}
1271
1272impl PrimitiveStore {
1273 pub fn new(stats: &PrimitiveStoreStats) -> PrimitiveStore {
1274 PrimitiveStore {
1275 pictures: Vec::with_capacity(stats.picture_count),
1276 }
1277 }
1278
1279 pub fn reset(&mut self) {
1280 self.pictures.clear();
1281 }
1282
1283 pub fn get_stats(&self) -> PrimitiveStoreStats {
1284 PrimitiveStoreStats {
1285 picture_count: self.pictures.len(),
1286 }
1287 }
1288
1289 #[allow(unused)]
1290 pub fn print_picture_tree(&self, root: PictureIndex) {
1291 use crate::print_tree::PrintTree;
1292 let mut pt = PrintTree::new("picture tree");
1293 self.pictures[root.0].print(&self.pictures, root, &mut pt);
1294 }
1295}
1296
1297impl Default for PrimitiveStore {
1298 fn default() -> Self {
1299 PrimitiveStore::new(&PrimitiveStoreStats::empty())
1300 }
1301}
1302
1303pub trait InternablePrimitive: intern::Internable<InternData = ()> + Sized {
1306 fn into_key(
1308 self,
1309 info: &LayoutPrimitiveInfo,
1310 ) -> Self::Key;
1311
1312 fn make_instance_kind(
1313 key: Self::Key,
1314 data_handle: intern::Handle<Self>,
1315 prim_store: &mut PrimitiveStore,
1316 ) -> PrimitiveKind;
1317}
1318
1319
1320#[test]
1321#[cfg(target_pointer_width = "64")]
1322fn test_struct_sizes() {
1323 use std::mem;
1324 assert_eq!(mem::size_of::<PrimitiveInstance>(), 48, "PrimitiveInstance size changed");
1331 assert_eq!(mem::size_of::<PrimitiveKind>(), 24, "PrimitiveKind size changed");
1332}