1use api::{BorderRadius, ColorF, ExternalImageId, ImageBufferKind, ImageKey, ImageRendering, YuvFormat, YuvRangedColorSpace};
6use api::units::*;
7use api::ColorDepth;
8use crate::image_source::resolve_image;
9use crate::picture::ResolvedSurfaceTexture;
10use crate::renderer::GpuBufferBuilderF;
11use euclid::Box2D;
12use crate::gpu_types::{ZBufferId, ZBufferIdGenerator};
13use crate::internal_types::{FrameAllocator, FrameMemory, FrameVec, TextureSource};
14use crate::invalidation::compare::ImageDependency;
15use crate::tile_cache::{TileCacheInstance, TileSurface};
16use crate::tile_cache::TileId;
17use crate::prim_store::{DeferredResolve, PrimitiveInstanceIndex};
18use crate::resource_cache::{ImageRequest, ResourceCache};
19use crate::segment::EdgeMask;
20use crate::util::{extract_inner_rect_safe, Preallocator, ScaleOffset};
21use crate::tile_cache::PictureCacheDebugInfo;
22use crate::device::Device;
23use crate::space::SpaceMapper;
24use std::{ops, u64, os::raw::c_void, hash};
25use std::num::NonZeroUsize;
26
27#[cfg_attr(feature = "capture", derive(Serialize))]
34#[cfg_attr(feature = "replay", derive(Deserialize))]
35#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
36pub enum CompositorSurfaceKind {
37 Blit,
39 Underlay,
41 Overlay,
43}
44
45impl CompositorSurfaceKind {
46 pub fn is_composited(&self) -> bool {
47 match *self {
48 CompositorSurfaceKind::Blit => false,
49 CompositorSurfaceKind::Underlay | CompositorSurfaceKind::Overlay => true,
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
56#[cfg_attr(feature = "capture", derive(Serialize))]
57#[cfg_attr(feature = "replay", derive(Deserialize))]
58pub enum NativeSurfaceOperationDetails {
59 CreateSurface {
60 id: NativeSurfaceId,
61 virtual_offset: DeviceIntPoint,
62 tile_size: DeviceIntSize,
63 is_opaque: bool,
64 },
65 CreateExternalSurface {
66 id: NativeSurfaceId,
67 is_opaque: bool,
68 },
69 CreateBackdropSurface {
70 id: NativeSurfaceId,
71 color: ColorF,
72 },
73 DestroySurface {
74 id: NativeSurfaceId,
75 },
76 CreateTile {
77 id: NativeTileId,
78 },
79 DestroyTile {
80 id: NativeTileId,
81 },
82 AttachExternalImage {
83 id: NativeSurfaceId,
84 external_image: ExternalImageId,
85 }
86}
87
88#[derive(Debug, Clone)]
90#[cfg_attr(feature = "capture", derive(Serialize))]
91#[cfg_attr(feature = "replay", derive(Deserialize))]
92pub struct NativeSurfaceOperation {
93 pub details: NativeSurfaceOperationDetails,
94}
95
96#[cfg_attr(feature = "capture", derive(Serialize))]
100#[cfg_attr(feature = "replay", derive(Deserialize))]
101#[derive(Clone)]
102pub enum CompositeTileSurface {
103 Texture {
104 surface: ResolvedSurfaceTexture,
105 },
106 Color {
107 color: ColorF,
108 },
109 ExternalSurface {
110 external_surface_index: ResolvedExternalSurfaceIndex,
111 },
112}
113
114#[derive(Debug, Copy, Clone, PartialEq)]
116pub enum CompositeSurfaceFormat {
117 Rgba,
118 Yuv,
119}
120
121bitflags! {
122 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
125 pub struct CompositeFeatures: u8 {
126 const NO_UV_CLAMP = 1 << 0;
129 const NO_COLOR_MODULATION = 1 << 1;
131 const NO_CLIP_MASK = 1 << 2;
133 }
134}
135
136#[derive(Copy, Clone, Debug, PartialEq)]
137#[cfg_attr(feature = "capture", derive(Serialize))]
138#[cfg_attr(feature = "replay", derive(Deserialize))]
139pub enum TileKind {
140 Opaque,
141 Alpha,
142}
143
144#[cfg_attr(feature = "capture", derive(Serialize))]
146#[cfg_attr(feature = "replay", derive(Deserialize))]
147#[derive(Debug, Copy, Clone)]
148pub struct CompositorTransformIndex(usize);
149
150impl CompositorTransformIndex {
151 pub const INVALID: CompositorTransformIndex = CompositorTransformIndex(!0);
152}
153
154#[cfg_attr(feature = "capture", derive(Serialize))]
156#[cfg_attr(feature = "replay", derive(Deserialize))]
157#[derive(Debug, Copy, Clone)]
158pub struct CompositorClipIndex(NonZeroUsize);
159
160#[cfg_attr(feature = "capture", derive(Serialize))]
162#[cfg_attr(feature = "replay", derive(Deserialize))]
163#[derive(Clone)]
164pub struct CompositeTile {
165 pub surface: CompositeTileSurface,
166 pub local_rect: PictureRect,
167 pub local_valid_rect: PictureRect,
168 pub local_dirty_rect: PictureRect,
169 pub device_clip_rect: DeviceRect,
170 pub z_id: ZBufferId,
171 pub kind: TileKind,
172 pub transform_index: CompositorTransformIndex,
173 pub clip_index: Option<CompositorClipIndex>,
174 pub tile_id: Option<TileId>,
175}
176
177pub fn tile_kind(surface: &CompositeTileSurface, is_opaque: bool) -> TileKind {
178 match surface {
179 CompositeTileSurface::Color { .. } => TileKind::Opaque,
182 CompositeTileSurface::Texture { .. }
183 | CompositeTileSurface::ExternalSurface { .. } => {
184 if is_opaque {
187 TileKind::Opaque
188 } else {
189 TileKind::Alpha
190 }
191 }
192 }
193}
194
195#[derive(Clone)]
196pub enum ExternalSurfaceDependency {
197 Yuv {
198 image_dependencies: [ImageDependency; 3],
199 color_space: YuvRangedColorSpace,
200 format: YuvFormat,
201 channel_bit_depth: u32,
202 },
203 Rgb {
204 image_dependency: ImageDependency,
205 },
206}
207
208#[derive(Clone)]
212pub struct ExternalSurfaceDescriptor {
213 pub local_surface_size: LayoutSize,
216 pub local_rect: PictureRect,
217 pub local_clip_rect: PictureRect,
218 pub clip_rect: DeviceRect,
219 pub transform_index: CompositorTransformIndex,
220 pub compositor_clip_index: Option<CompositorClipIndex>,
221 pub image_rendering: ImageRendering,
222 pub z_id: ZBufferId,
223 pub dependency: ExternalSurfaceDependency,
224 pub native_surface_id: Option<NativeSurfaceId>,
227 pub update_params: Option<DeviceIntSize>,
230 pub external_image_id: Option<ExternalImageId>,
232 pub prim_instance_index: PrimitiveInstanceIndex,
233}
234
235impl ExternalSurfaceDescriptor {
236 pub fn get_occluder_rect(
238 &self,
239 local_clip_rect: &PictureRect,
240 map_pic_to_world: &SpaceMapper<PicturePixel, WorldPixel>,
241 ) -> Option<WorldRect> {
242 let local_surface_rect = self
243 .local_rect
244 .intersection(&self.local_clip_rect)
245 .and_then(|r| {
246 r.intersection(local_clip_rect)
247 });
248
249 local_surface_rect.map(|local_surface_rect| {
250 map_pic_to_world
251 .map(&local_surface_rect)
252 .expect("bug: unable to map external surface to world space")
253 })
254 }
255}
256
257#[cfg_attr(feature = "capture", derive(Serialize))]
259#[cfg_attr(feature = "replay", derive(Deserialize))]
260#[derive(Debug, Copy, Clone)]
261pub struct ExternalPlaneDescriptor {
262 pub texture: TextureSource,
263 pub uv_rect: TexelRect,
264}
265
266impl ExternalPlaneDescriptor {
267 fn invalid() -> Self {
268 ExternalPlaneDescriptor {
269 texture: TextureSource::Invalid,
270 uv_rect: TexelRect::invalid(),
271 }
272 }
273}
274
275#[cfg_attr(feature = "capture", derive(Serialize))]
276#[cfg_attr(feature = "replay", derive(Deserialize))]
277#[derive(Debug, Copy, Clone, PartialEq)]
278pub struct ResolvedExternalSurfaceIndex(pub usize);
279
280impl ResolvedExternalSurfaceIndex {
281 pub const INVALID: ResolvedExternalSurfaceIndex = ResolvedExternalSurfaceIndex(usize::MAX);
282}
283
284#[cfg_attr(feature = "capture", derive(Serialize))]
285#[cfg_attr(feature = "replay", derive(Deserialize))]
286pub enum ResolvedExternalSurfaceColorData {
287 Yuv {
288 image_dependencies: [ImageDependency; 3],
290 planes: [ExternalPlaneDescriptor; 3],
291 color_space: YuvRangedColorSpace,
292 format: YuvFormat,
293 channel_bit_depth: u32,
294 },
295 Rgb {
296 image_dependency: ImageDependency,
297 plane: ExternalPlaneDescriptor,
298 },
299}
300
301#[cfg_attr(feature = "capture", derive(Serialize))]
306#[cfg_attr(feature = "replay", derive(Deserialize))]
307pub struct ResolvedExternalSurface {
308 pub color_data: ResolvedExternalSurfaceColorData,
309 pub image_buffer_kind: ImageBufferKind,
310 pub update_params: Option<(NativeSurfaceId, DeviceIntSize)>,
312 pub external_image_id: Option<ExternalImageId>,
314}
315
316pub enum CompositorConfig {
319 Draw {
321 max_partial_present_rects: usize,
326 draw_previous_partial_present_regions: bool,
330 partial_present: Option<Box<dyn PartialPresentCompositor>>,
333 },
334 Layer {
335 compositor: Box<dyn LayerCompositor>,
339 },
340 Native {
344 compositor: Box<dyn Compositor>,
346 }
347}
348
349impl CompositorConfig {
350 pub fn compositor(&mut self) -> Option<&mut Box<dyn Compositor>> {
351 match self {
352 CompositorConfig::Native { ref mut compositor, .. } => {
353 Some(compositor)
354 }
355 CompositorConfig::Draw { .. } | CompositorConfig::Layer { .. } => {
356 None
357 }
358 }
359 }
360
361 pub fn partial_present(&mut self) -> Option<&mut Box<dyn PartialPresentCompositor>> {
362 match self {
363 CompositorConfig::Native { .. } => {
364 None
365 }
366 CompositorConfig::Draw { ref mut partial_present, .. } => {
367 partial_present.as_mut()
368 }
369 CompositorConfig::Layer { .. } => {
370 None
371 }
372 }
373 }
374
375 pub fn layer_compositor(&mut self) -> Option<&mut Box<dyn LayerCompositor>> {
376 match self {
377 CompositorConfig::Native { .. } => {
378 None
379 }
380 CompositorConfig::Draw { .. } => {
381 None
382 }
383 CompositorConfig::Layer { ref mut compositor } => {
384 Some(compositor)
385 }
386 }
387 }
388}
389
390impl Default for CompositorConfig {
391 fn default() -> Self {
393 CompositorConfig::Draw {
394 max_partial_present_rects: 0,
395 draw_previous_partial_present_regions: false,
396 partial_present: None,
397 }
398 }
399}
400
401#[cfg_attr(feature = "capture", derive(Serialize))]
405#[cfg_attr(feature = "replay", derive(Deserialize))]
406#[derive(Debug, Copy, Clone, PartialEq)]
407pub enum CompositorKind {
408 Draw {
410 max_partial_present_rects: usize,
412 draw_previous_partial_present_regions: bool,
414 },
415 Layer {
416
417 },
418 Native {
420 capabilities: CompositorCapabilities,
422 },
423}
424
425impl Default for CompositorKind {
426 fn default() -> Self {
428 CompositorKind::Draw {
429 max_partial_present_rects: 0,
430 draw_previous_partial_present_regions: false,
431 }
432 }
433}
434
435impl CompositorKind {
436 pub fn get_virtual_surface_size(&self) -> i32 {
437 match self {
438 CompositorKind::Draw { .. } | CompositorKind::Layer { .. }=> 0,
439 CompositorKind::Native { capabilities, .. } => capabilities.virtual_surface_size,
440 }
441 }
442
443 pub fn should_redraw_on_invalidation(&self) -> bool {
444 match self {
445 CompositorKind::Draw { max_partial_present_rects, .. } => {
446 *max_partial_present_rects > 0
448 }
449 CompositorKind::Layer { } => false, CompositorKind::Native { capabilities, .. } => capabilities.redraw_on_invalidation,
451 }
452 }
453}
454
455#[cfg_attr(feature = "capture", derive(Serialize))]
458#[cfg_attr(feature = "replay", derive(Deserialize))]
459#[derive(PartialEq, Clone)]
460pub enum TileSurfaceKind {
461 Texture,
462 Color {
463 color: ColorF,
464 },
465}
466
467impl From<&TileSurface> for TileSurfaceKind {
468 fn from(surface: &TileSurface) -> Self {
469 match surface {
470 TileSurface::Texture { .. } => TileSurfaceKind::Texture,
471 TileSurface::Color { color } => TileSurfaceKind::Color { color: *color },
472 }
473 }
474}
475
476#[cfg_attr(feature = "capture", derive(Serialize))]
479#[cfg_attr(feature = "replay", derive(Deserialize))]
480#[derive(PartialEq, Clone)]
481pub struct CompositeTileDescriptor {
482 pub tile_id: TileId,
483 pub surface_kind: TileSurfaceKind,
484}
485
486#[cfg_attr(feature = "capture", derive(Serialize))]
489#[cfg_attr(feature = "replay", derive(Deserialize))]
490#[derive(Debug, Copy, Clone)]
491pub enum CompositorSurfaceUsage {
492 Content,
493 External {
494 image_key: ImageKey,
495 external_image_id: ExternalImageId,
496 transform_index: CompositorTransformIndex,
497 },
498 DebugOverlay,
499}
500
501impl CompositorSurfaceUsage {
502 pub fn matches(&self, other: &CompositorSurfaceUsage) -> bool {
504 match (self, other) {
505 (CompositorSurfaceUsage::Content, CompositorSurfaceUsage::Content) => true,
507
508 (CompositorSurfaceUsage::Content, CompositorSurfaceUsage::External { .. }) |
509 (CompositorSurfaceUsage::External { .. }, CompositorSurfaceUsage::Content) => false,
510
511 (CompositorSurfaceUsage::External { image_key: key1, .. }, CompositorSurfaceUsage::External { image_key: key2, .. }) => {
513 key1 == key2
514 }
515
516 (CompositorSurfaceUsage::DebugOverlay, CompositorSurfaceUsage::DebugOverlay) => true,
517
518 (CompositorSurfaceUsage::DebugOverlay, _) | (_, CompositorSurfaceUsage::DebugOverlay) => false,
519 }
520 }
521}
522
523#[cfg_attr(feature = "capture", derive(Serialize))]
525#[cfg_attr(feature = "replay", derive(Deserialize))]
526#[derive(PartialEq, Clone)]
527pub struct CompositeSurfaceDescriptor {
528 pub surface_id: Option<NativeSurfaceId>,
529 pub clip_rect: DeviceRect,
530 pub transform: CompositorSurfaceTransform,
531 pub image_dependencies: [ImageDependency; 3],
536 pub image_rendering: ImageRendering,
537 pub tile_descriptors: Vec<CompositeTileDescriptor>,
539 pub rounded_clip_rect: DeviceRect,
540 pub rounded_clip_radii: ClipRadius,
541}
542
543#[cfg_attr(feature = "capture", derive(Serialize))]
546#[cfg_attr(feature = "replay", derive(Deserialize))]
547#[derive(PartialEq, Clone)]
548pub struct CompositeDescriptor {
549 pub surfaces: Vec<CompositeSurfaceDescriptor>,
550 pub external_surfaces_rect: DeviceRect,
551}
552
553impl CompositeDescriptor {
554 pub fn empty() -> Self {
556 CompositeDescriptor {
557 surfaces: Vec::new(),
558 external_surfaces_rect: DeviceRect::zero(),
559 }
560 }
561}
562
563pub struct CompositeStatePreallocator {
564 tiles: Preallocator,
565 external_surfaces: Preallocator,
566 occluders: Preallocator,
567 occluders_events: Preallocator,
568 occluders_active: Preallocator,
569 descriptor_surfaces: Preallocator,
570}
571
572impl CompositeStatePreallocator {
573 pub fn record(&mut self, state: &CompositeState) {
574 self.tiles.record_vec(&state.tiles);
575 self.external_surfaces.record_vec(&state.external_surfaces);
576 self.occluders.record_vec(&state.occluders.occluders);
577 self.occluders_events.record_vec(&state.occluders.scratch.events);
578 self.occluders_active.record_vec(&state.occluders.scratch.active);
579 self.descriptor_surfaces.record_vec(&state.descriptor.surfaces);
580 }
581
582 pub fn preallocate(&self, state: &mut CompositeState) {
583 self.tiles.preallocate_framevec(&mut state.tiles);
584 self.external_surfaces.preallocate_framevec(&mut state.external_surfaces);
585 self.occluders.preallocate_framevec(&mut state.occluders.occluders);
586 self.occluders_events.preallocate_framevec(&mut state.occluders.scratch.events);
587 self.occluders_active.preallocate_framevec(&mut state.occluders.scratch.active);
588 self.descriptor_surfaces.preallocate_vec(&mut state.descriptor.surfaces);
589 }
590}
591
592impl Default for CompositeStatePreallocator {
593 fn default() -> Self {
594 CompositeStatePreallocator {
595 tiles: Preallocator::new(56),
596 external_surfaces: Preallocator::new(0),
597 occluders: Preallocator::new(16),
598 occluders_events: Preallocator::new(32),
599 occluders_active: Preallocator::new(16),
600 descriptor_surfaces: Preallocator::new(8),
601 }
602 }
603}
604
605#[cfg_attr(feature = "capture", derive(Serialize))]
612#[cfg_attr(feature = "replay", derive(Deserialize))]
613pub struct CompositorTransform {
614 local_to_raster: ScaleOffset,
616 raster_to_device: ScaleOffset,
618 local_to_device: ScaleOffset,
620}
621
622#[cfg_attr(feature = "capture", derive(Serialize))]
623#[cfg_attr(feature = "replay", derive(Deserialize))]
624#[derive(Clone, Copy, Debug)]
625pub struct CompositorClip {
626 pub rect: DeviceRect,
627 pub radius: BorderRadius,
628}
629
630#[derive(PartialEq, Debug)]
631pub struct CompositeRoundedCorner {
632 pub rect: LayoutRect,
633 pub radius: LayoutSize,
634 pub edge_flags: EdgeMask,
635}
636
637impl Eq for CompositeRoundedCorner {}
638
639impl hash::Hash for CompositeRoundedCorner {
640 fn hash<H: hash::Hasher>(&self, state: &mut H) {
641 self.rect.min.x.to_bits().hash(state);
642 self.rect.min.y.to_bits().hash(state);
643 self.rect.max.x.to_bits().hash(state);
644 self.rect.max.y.to_bits().hash(state);
645 self.radius.width.to_bits().hash(state);
646 self.radius.height.to_bits().hash(state);
647 self.edge_flags.bits().hash(state);
648 }
649}
650
651#[cfg_attr(feature = "capture", derive(Serialize))]
653#[cfg_attr(feature = "replay", derive(Deserialize))]
654pub struct CompositeState {
655 pub tiles: FrameVec<CompositeTile>,
662 pub external_surfaces: FrameVec<ResolvedExternalSurface>,
664 pub z_generator: ZBufferIdGenerator,
666 pub dirty_rects_are_valid: bool,
673 pub compositor_kind: CompositorKind,
675 pub occluders: Occluders,
677 pub descriptor: CompositeDescriptor,
679 pub picture_cache_debug: PictureCacheDebugInfo,
681 pub transforms: FrameVec<CompositorTransform>,
683 low_quality_pinch_zoom: bool,
685 pub clips: FrameVec<CompositorClip>,
687 pub did_rasterize_any_tile: bool,
689}
690
691impl CompositeState {
692 pub fn new(
695 compositor_kind: CompositorKind,
696 max_depth_ids: i32,
697 dirty_rects_are_valid: bool,
698 low_quality_pinch_zoom: bool,
699 memory: &FrameMemory,
700 ) -> Self {
701 let mut clips = memory.new_vec();
704 clips.push(CompositorClip {
705 rect: DeviceRect::zero(),
706 radius: BorderRadius::zero(),
707 });
708
709 CompositeState {
710 tiles: memory.new_vec(),
711 z_generator: ZBufferIdGenerator::new(max_depth_ids),
712 dirty_rects_are_valid,
713 compositor_kind,
714 occluders: Occluders::new(memory),
715 descriptor: CompositeDescriptor::empty(),
716 external_surfaces: memory.new_vec(),
717 picture_cache_debug: PictureCacheDebugInfo::new(),
718 transforms: memory.new_vec(),
719 low_quality_pinch_zoom,
720 clips,
721 did_rasterize_any_tile: false,
722 }
723 }
724
725 pub fn compositor_clip_params(
726 &self,
727 clip_index: Option<CompositorClipIndex>,
728 default_rect: DeviceRect,
729 ) -> (DeviceRect, ClipRadius) {
730 match clip_index {
731 Some(clip_index) => {
732 let clip = self.get_compositor_clip(clip_index);
733
734 (
735 clip.rect.cast_unit(),
736 ClipRadius {
737 top_left: clip.radius.top_left.width.round() as i32,
738 top_right: clip.radius.top_right.width.round() as i32,
739 bottom_left: clip.radius.bottom_left.width.round() as i32,
740 bottom_right: clip.radius.bottom_right.width.round() as i32,
741 }
742 )
743 }
744 None => {
745 (default_rect, ClipRadius::EMPTY)
746 }
747 }
748 }
749
750 pub fn register_transform(
752 &mut self,
753 local_to_raster: ScaleOffset,
754 raster_to_device: ScaleOffset,
755 ) -> CompositorTransformIndex {
756 let index = CompositorTransformIndex(self.transforms.len());
757
758 let local_to_device = local_to_raster.then(&raster_to_device);
759
760 self.transforms.push(CompositorTransform {
761 local_to_raster,
762 raster_to_device,
763 local_to_device,
764 });
765
766 index
767 }
768
769 pub fn register_clip(
771 &mut self,
772 rect: DeviceRect,
773 radius: BorderRadius,
774 ) -> CompositorClipIndex {
775 let index = CompositorClipIndex(NonZeroUsize::new(self.clips.len()).expect("bug"));
776
777 self.clips.push(CompositorClip {
778 rect,
779 radius,
780 });
781
782 index
783 }
784
785 pub fn get_device_rect(
787 &self,
788 local_rect: &PictureRect,
789 transform_index: CompositorTransformIndex,
790 ) -> DeviceRect {
791 let transform = &self.transforms[transform_index.0];
792 transform.local_to_device.map_rect(&local_rect).round()
793 }
794
795 pub fn get_surface_rect<T>(
798 &self,
799 local_sub_rect: &Box2D<f32, T>,
800 local_bounds: &Box2D<f32, T>,
801 transform_index: CompositorTransformIndex,
802 ) -> DeviceRect {
803 let transform = &self.transforms[transform_index.0];
804
805 let surface_bounds = transform.local_to_raster.map_rect(&local_bounds);
806 let surface_rect = transform.local_to_raster.map_rect(&local_sub_rect);
807
808 surface_rect
809 .round_out()
810 .translate(-surface_bounds.min.to_vector())
811 .round_out()
812 .intersection(&surface_bounds.size().round().into())
813 .unwrap_or_else(DeviceRect::zero)
814 }
815
816 pub fn get_device_transform(
818 &self,
819 transform_index: CompositorTransformIndex,
820 ) -> ScaleOffset {
821 let transform = &self.transforms[transform_index.0];
822 transform.local_to_device
823 }
824
825 pub fn get_compositor_transform(
827 &self,
828 transform_index: CompositorTransformIndex,
829 ) -> ScaleOffset {
830 let transform = &self.transforms[transform_index.0];
831 transform.raster_to_device
832 }
833
834 pub fn get_compositor_clip(
836 &self,
837 clip_index: CompositorClipIndex,
838 ) -> &CompositorClip {
839 &self.clips[clip_index.0.get()]
840 }
841
842 pub fn register_occluder(
845 &mut self,
846 z_id: ZBufferId,
847 rect: WorldRect,
848 compositor_clip: Option<CompositorClipIndex>,
849 ) {
850 let rect = match compositor_clip {
851 Some(clip_index) => {
852 let clip = self.get_compositor_clip(clip_index);
853
854 let inner_rect = match extract_inner_rect_safe(
855 &clip.rect,
856 &clip.radius,
857 ) {
858 Some(rect) => rect,
859 None => return,
860 };
861
862 match inner_rect.cast_unit().intersection(&rect) {
863 Some(rect) => rect,
864 None => return,
865 }
866 }
867 None => {
868 rect
869 }
870 };
871
872 let world_rect = rect.round().to_i32();
873
874 self.occluders.push(world_rect, z_id);
875 }
876
877 fn push_compositor_surface(
879 &mut self,
880 external_surface: &ExternalSurfaceDescriptor,
881 is_opaque: bool,
882 device_clip_rect: DeviceRect,
883 resource_cache: &ResourceCache,
884 gpu_buffer: &mut GpuBufferBuilderF,
885 deferred_resolves: &mut FrameVec<DeferredResolve>,
886 clip_index: Option<CompositorClipIndex>,
887 ) {
888 let clip_rect = external_surface
889 .clip_rect
890 .intersection(&device_clip_rect)
891 .unwrap_or_else(DeviceRect::zero);
892
893 if clip_rect.is_empty() {
895 return;
896 }
897
898 let required_plane_count =
899 match external_surface.dependency {
900 ExternalSurfaceDependency::Yuv { format, .. } => {
901 format.get_plane_num()
902 },
903 ExternalSurfaceDependency::Rgb { .. } => {
904 1
905 }
906 };
907
908 let mut image_dependencies = [ImageDependency::INVALID; 3];
909
910 for i in 0 .. required_plane_count {
911 let dependency = match external_surface.dependency {
912 ExternalSurfaceDependency::Yuv { image_dependencies, .. } => {
913 image_dependencies[i]
914 },
915 ExternalSurfaceDependency::Rgb { image_dependency, .. } => {
916 image_dependency
917 }
918 };
919 image_dependencies[i] = dependency;
920 }
921
922 let needs_external_surface_update = match self.compositor_kind {
926 CompositorKind::Draw { .. } | CompositorKind::Layer { .. } => true,
927 _ => external_surface.update_params.is_some(),
928 };
929 let external_surface_index = if needs_external_surface_update {
930 let external_surface_index = self.compute_external_surface_dependencies(
931 &external_surface,
932 &image_dependencies,
933 required_plane_count,
934 resource_cache,
935 gpu_buffer,
936 deferred_resolves,
937 );
938 if external_surface_index == ResolvedExternalSurfaceIndex::INVALID {
939 return;
940 }
941 external_surface_index
942 } else {
943 ResolvedExternalSurfaceIndex::INVALID
944 };
945
946 let surface = CompositeTileSurface::ExternalSurface { external_surface_index };
947 let local_rect = external_surface.local_surface_size.cast_unit().into();
948
949 let tile = CompositeTile {
950 kind: tile_kind(&surface, is_opaque),
951 surface,
952 local_rect,
953 local_valid_rect: local_rect,
954 local_dirty_rect: local_rect,
955 device_clip_rect: clip_rect,
956 z_id: external_surface.z_id,
957 transform_index: external_surface.transform_index,
958 clip_index,
959 tile_id: None,
960 };
961
962 let (rounded_clip_rect, rounded_clip_radii) = self.compositor_clip_params(
963 clip_index,
964 clip_rect,
965 );
966
967 self.descriptor.surfaces.push(
971 CompositeSurfaceDescriptor {
972 surface_id: external_surface.native_surface_id,
973 clip_rect,
974 transform: self.get_compositor_transform(external_surface.transform_index),
975 image_dependencies: image_dependencies,
976 image_rendering: external_surface.image_rendering,
977 tile_descriptors: Vec::new(),
978 rounded_clip_rect,
979 rounded_clip_radii,
980 }
981 );
982
983 let device_rect =
984 self.get_device_rect(&local_rect, external_surface.transform_index);
985 self.descriptor.external_surfaces_rect =
986 self.descriptor.external_surfaces_rect.union(&device_rect);
987
988 self.tiles.push(tile);
989 }
990
991 pub fn push_surface(
993 &mut self,
994 tile_cache: &TileCacheInstance,
995 device_clip_rect: DeviceRect,
996 resource_cache: &ResourceCache,
997 gpu_buffer: &mut GpuBufferBuilderF,
998 deferred_resolves: &mut FrameVec<DeferredResolve>,
999 ) {
1000 let slice_transform = self.get_compositor_transform(tile_cache.transform_index);
1001
1002 let image_rendering = if self.low_quality_pinch_zoom {
1003 ImageRendering::Auto
1004 } else {
1005 ImageRendering::CrispEdges
1006 };
1007
1008 if let Some(backdrop_surface) = &tile_cache.backdrop_surface {
1009 let (rounded_clip_rect, rounded_clip_radii) = self.compositor_clip_params(
1010 tile_cache.compositor_clip,
1011 backdrop_surface.device_rect,
1012 );
1013
1014 self.descriptor.surfaces.push(
1016 CompositeSurfaceDescriptor {
1017 surface_id: Some(backdrop_surface.id),
1018 clip_rect: backdrop_surface.device_rect,
1019 transform: slice_transform,
1020 image_dependencies: [ImageDependency::INVALID; 3],
1021 image_rendering,
1022 tile_descriptors: Vec::new(),
1023 rounded_clip_rect,
1024 rounded_clip_radii,
1025 }
1026 );
1027 }
1028
1029 for underlay in &tile_cache.underlays {
1031 self.push_compositor_surface(
1032 underlay,
1033 true,
1034 device_clip_rect,
1035 resource_cache,
1036 gpu_buffer,
1037 deferred_resolves,
1038 tile_cache.compositor_clip,
1039 );
1040 }
1041
1042 for sub_slice in &tile_cache.sub_slices {
1043 let mut surface_device_rect = DeviceRect::zero();
1044
1045 for tile in sub_slice.tiles.values() {
1046 if !tile.is_visible {
1047 continue;
1049 }
1050
1051 surface_device_rect = surface_device_rect.union(&tile.device_valid_rect);
1061 }
1062
1063 self.tiles.extend_from_slice(&sub_slice.composite_tiles);
1065
1066 let surface_clip_rect = device_clip_rect
1071 .intersection(&surface_device_rect)
1072 .unwrap_or(DeviceRect::zero());
1073
1074 if !surface_clip_rect.is_empty() {
1076 let (rounded_clip_rect, rounded_clip_radii) = self.compositor_clip_params(
1077 tile_cache.compositor_clip,
1078 surface_clip_rect,
1079 );
1080
1081 if !sub_slice.opaque_tile_descriptors.is_empty() {
1083 self.descriptor.surfaces.push(
1084 CompositeSurfaceDescriptor {
1085 surface_id: sub_slice.native_surface.as_ref().map(|s| s.opaque),
1086 clip_rect: surface_clip_rect,
1087 transform: slice_transform,
1088 image_dependencies: [ImageDependency::INVALID; 3],
1089 image_rendering,
1090 tile_descriptors: sub_slice.opaque_tile_descriptors.clone(),
1091 rounded_clip_rect,
1092 rounded_clip_radii,
1093 }
1094 );
1095 }
1096
1097 if !sub_slice.alpha_tile_descriptors.is_empty() {
1099 self.descriptor.surfaces.push(
1100 CompositeSurfaceDescriptor {
1101 surface_id: sub_slice.native_surface.as_ref().map(|s| s.alpha),
1102 clip_rect: surface_clip_rect,
1103 transform: slice_transform,
1104 image_dependencies: [ImageDependency::INVALID; 3],
1105 image_rendering,
1106 tile_descriptors: sub_slice.alpha_tile_descriptors.clone(),
1107 rounded_clip_rect,
1108 rounded_clip_radii,
1109 }
1110 );
1111 }
1112 }
1113
1114 for compositor_surface in &sub_slice.compositor_surfaces {
1117 let compositor_clip_index = if compositor_surface.descriptor.compositor_clip_index.is_some() {
1118 assert!(tile_cache.compositor_clip.is_none());
1119 compositor_surface.descriptor.compositor_clip_index
1120 } else {
1121 tile_cache.compositor_clip
1122 };
1123
1124 self.push_compositor_surface(
1125 &compositor_surface.descriptor,
1126 compositor_surface.is_opaque,
1127 device_clip_rect,
1128 resource_cache,
1129 gpu_buffer,
1130 deferred_resolves,
1131 compositor_clip_index,
1132 );
1133 }
1134 }
1135 }
1136
1137 pub fn update_dirty_rect_validity(
1140 &mut self,
1141 old_descriptor: &CompositeDescriptor,
1142 ) {
1143 if old_descriptor.surfaces.len() != self.descriptor.surfaces.len() {
1149 self.dirty_rects_are_valid = false;
1150 return;
1151 }
1152
1153 if !self
1158 .descriptor
1159 .external_surfaces_rect
1160 .contains_box(&old_descriptor.external_surfaces_rect)
1161 {
1162 self.dirty_rects_are_valid = false;
1163 return;
1164 }
1165 }
1166
1167 fn compute_external_surface_dependencies(
1168 &mut self,
1169 external_surface: &ExternalSurfaceDescriptor,
1170 image_dependencies: &[ImageDependency; 3],
1171 required_plane_count: usize,
1172 resource_cache: &ResourceCache,
1173 gpu_buffer: &mut GpuBufferBuilderF,
1174 deferred_resolves: &mut FrameVec<DeferredResolve>,
1175 ) -> ResolvedExternalSurfaceIndex {
1176 let mut planes = [
1177 ExternalPlaneDescriptor::invalid(),
1178 ExternalPlaneDescriptor::invalid(),
1179 ExternalPlaneDescriptor::invalid(),
1180 ];
1181
1182 let mut valid_plane_count = 0;
1183 for i in 0 .. required_plane_count {
1184 let request = ImageRequest {
1185 key: image_dependencies[i].key,
1186 rendering: external_surface.image_rendering,
1187 tile: None,
1188 };
1189
1190 let cache_item = resolve_image(
1191 request,
1192 resource_cache,
1193 gpu_buffer,
1194 deferred_resolves,
1195 true,
1196 );
1197
1198 if cache_item.texture_id != TextureSource::Invalid {
1199 valid_plane_count += 1;
1200 let plane = &mut planes[i];
1201 *plane = ExternalPlaneDescriptor {
1202 texture: cache_item.texture_id,
1203 uv_rect: cache_item.uv_rect.into(),
1204 };
1205 }
1206 }
1207
1208 if valid_plane_count < required_plane_count {
1210 warn!("Warnings: skip a YUV/RGB compositor surface, found {}/{} valid images",
1211 valid_plane_count,
1212 required_plane_count,
1213 );
1214 return ResolvedExternalSurfaceIndex::INVALID;
1215 }
1216
1217 let external_surface_index = ResolvedExternalSurfaceIndex(self.external_surfaces.len());
1218
1219 let update_params = external_surface.update_params.map(|surface_size| {
1223 (
1224 external_surface.native_surface_id.expect("bug: no native surface!"),
1225 surface_size
1226 )
1227 });
1228
1229 match external_surface.dependency {
1230 ExternalSurfaceDependency::Yuv{ color_space, format, channel_bit_depth, .. } => {
1231
1232 let image_buffer_kind = planes[0].texture.image_buffer_kind();
1233
1234 self.external_surfaces.push(ResolvedExternalSurface {
1235 color_data: ResolvedExternalSurfaceColorData::Yuv {
1236 image_dependencies: *image_dependencies,
1237 planes,
1238 color_space,
1239 format,
1240 channel_bit_depth,
1241 },
1242 image_buffer_kind,
1243 update_params,
1244 external_image_id: external_surface.external_image_id,
1245 });
1246 },
1247 ExternalSurfaceDependency::Rgb { .. } => {
1248 let image_buffer_kind = planes[0].texture.image_buffer_kind();
1249
1250 self.external_surfaces.push(ResolvedExternalSurface {
1251 color_data: ResolvedExternalSurfaceColorData::Rgb {
1252 image_dependency: image_dependencies[0],
1253 plane: planes[0],
1254 },
1255 image_buffer_kind,
1256 update_params,
1257 external_image_id: external_surface.external_image_id,
1258 });
1259 },
1260 }
1261 external_surface_index
1262 }
1263
1264 pub fn end_frame(&mut self) {
1265 self.tiles.sort_by_key(|tile| tile.z_id.0);
1267 }
1268
1269 #[cfg(feature = "debugger")]
1270 pub fn print_to_string(&self) -> String {
1271 use crate::print_tree::PrintTree;
1272 use crate::print_tree::PrintTreePrinter;
1273
1274 let mut buf = Vec::<u8>::new();
1275 {
1276 let mut pt = PrintTree::new_with_sink("composite config", &mut buf);
1277
1278 pt.new_level("tiles".into());
1279 for (i, tile) in self.tiles.iter().enumerate() {
1280 pt.new_level(format!("tile {}", i));
1281 pt.add_item(format!("local_rect = {:?}", tile.local_rect.to_rect()));
1282 pt.add_item(format!("local_valid_rect = {:?}", tile.local_valid_rect.to_rect()));
1283 pt.add_item(format!("local_dirty_rect = {:?}", tile.local_dirty_rect.to_rect()));
1284 pt.add_item(format!("device_clip_rect = {:?}", tile.device_clip_rect.to_rect()));
1285 pt.add_item(format!("z_id = {:?}", tile.z_id));
1286 pt.add_item(format!("kind = {:?}", tile.kind));
1287 pt.add_item(format!("tile_id = {:?}", tile.tile_id));
1288 pt.add_item(format!("clip = {:?}", tile.clip_index));
1289 pt.add_item(format!("transform = {:?}", tile.transform_index));
1290 pt.end_level();
1291 }
1292 pt.end_level();
1293
1294 pt.new_level("external_surfaces".into());
1295 for (i, surface) in self.external_surfaces.iter().enumerate() {
1296 pt.new_level(format!("surface {}", i));
1297 pt.add_item(format!("{:?}", surface.image_buffer_kind));
1298 pt.end_level();
1299 }
1300 pt.end_level();
1301
1302 pt.new_level("occluders".into());
1303 for (i, occluder) in self.occluders.occluders.iter().enumerate() {
1304 pt.new_level(format!("occluder {}", i));
1305 pt.add_item(format!("{:?}", occluder.z_id));
1306 pt.add_item(format!("{:?}", occluder.world_rect.to_rect()));
1307 pt.end_level();
1308 }
1309 pt.end_level();
1310
1311 pt.new_level("transforms".into());
1312 for (i, transform) in self.transforms.iter().enumerate() {
1313 pt.new_level(format!("transform {}", i));
1314 pt.add_item(format!("local_to_raster {:?}", transform.local_to_raster));
1315 pt.add_item(format!("raster_to_device {:?}", transform.raster_to_device));
1316 pt.add_item(format!("local_to_device {:?}", transform.local_to_device));
1317 pt.end_level();
1318 }
1319 pt.end_level();
1320
1321 pt.new_level("clips".into());
1322 for (i, clip) in self.clips.iter().enumerate() {
1323 pt.new_level(format!("clip {}", i));
1324 pt.add_item(format!("{:?}", clip.rect.to_rect()));
1325 pt.add_item(format!("{:?}", clip.radius));
1326 pt.end_level();
1327 }
1328 pt.end_level();
1329 }
1330
1331 std::str::from_utf8(&buf).unwrap_or("(Tree printer emitted non-utf8)").to_string()
1332 }
1333}
1334
1335#[repr(C)]
1337#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
1338#[cfg_attr(feature = "capture", derive(Serialize))]
1339#[cfg_attr(feature = "replay", derive(Deserialize))]
1340pub struct NativeSurfaceId(pub u64);
1341
1342impl NativeSurfaceId {
1343 pub const DEBUG_OVERLAY: NativeSurfaceId = NativeSurfaceId(u64::MAX);
1345}
1346
1347#[repr(C)]
1348#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
1349#[cfg_attr(feature = "capture", derive(Serialize))]
1350#[cfg_attr(feature = "replay", derive(Deserialize))]
1351pub struct NativeTileId {
1352 pub surface_id: NativeSurfaceId,
1353 pub x: i32,
1354 pub y: i32,
1355}
1356
1357impl NativeTileId {
1358 pub const DEBUG_OVERLAY: NativeTileId = NativeTileId {
1360 surface_id: NativeSurfaceId::DEBUG_OVERLAY,
1361 x: 0,
1362 y: 0,
1363 };
1364}
1365
1366#[repr(C)]
1369#[derive(Copy, Clone)]
1370pub struct NativeSurfaceInfo {
1371 pub origin: DeviceIntPoint,
1377 pub fbo_id: u32,
1385}
1386
1387#[repr(C)]
1388#[derive(Debug, Copy, Clone)]
1389pub struct WindowProperties {
1390 pub is_opaque: bool,
1391 pub enable_screenshot: bool,
1392}
1393
1394impl Default for WindowProperties {
1395 fn default() -> Self {
1396 WindowProperties {
1397 is_opaque: true,
1398 enable_screenshot: true,
1399 }
1400 }
1401}
1402
1403#[repr(C)]
1404#[derive(Debug, Copy, Clone, PartialEq)]
1405#[cfg_attr(feature = "capture", derive(Serialize))]
1406#[cfg_attr(feature = "replay", derive(Deserialize))]
1407pub struct CompositorCapabilities {
1408 pub virtual_surface_size: i32,
1410 pub redraw_on_invalidation: bool,
1412 pub max_update_rects: usize,
1416 pub supports_surface_for_backdrop: bool,
1418 pub supports_external_compositor_surface_negative_scaling: bool,
1420}
1421
1422impl Default for CompositorCapabilities {
1423 fn default() -> Self {
1424 CompositorCapabilities {
1429 virtual_surface_size: 0,
1430 redraw_on_invalidation: false,
1431 max_update_rects: 1,
1434 supports_surface_for_backdrop: false,
1435 supports_external_compositor_surface_negative_scaling: true,
1436 }
1437 }
1438}
1439
1440#[repr(C)]
1441#[derive(Copy, Clone, Debug)]
1442pub struct WindowVisibility {
1443 pub is_fully_occluded: bool,
1444}
1445
1446impl Default for WindowVisibility {
1447 fn default() -> Self {
1448 WindowVisibility {
1449 is_fully_occluded: false,
1450 }
1451 }
1452}
1453
1454pub type CompositorSurfaceTransform = ScaleOffset;
1461
1462#[repr(C)]
1463#[cfg_attr(feature = "capture", derive(Serialize))]
1464#[cfg_attr(feature = "replay", derive(Deserialize))]
1465#[derive(PartialEq, Copy, Clone, Debug)]
1466pub struct ClipRadius {
1467 pub top_left: i32,
1468 pub top_right: i32,
1469 pub bottom_left: i32,
1470 pub bottom_right: i32,
1471}
1472
1473impl ClipRadius {
1474 pub const EMPTY: ClipRadius = ClipRadius { top_left: 0, top_right: 0, bottom_left: 0, bottom_right: 0 };
1475}
1476
1477pub trait Compositor {
1481 fn create_surface(
1483 &mut self,
1484 device: &mut Device,
1485 id: NativeSurfaceId,
1486 virtual_offset: DeviceIntPoint,
1487 tile_size: DeviceIntSize,
1488 is_opaque: bool,
1489 );
1490
1491 fn create_external_surface(
1496 &mut self,
1497 device: &mut Device,
1498 id: NativeSurfaceId,
1499 is_opaque: bool,
1500 );
1501
1502 fn create_backdrop_surface(
1504 &mut self,
1505 device: &mut Device,
1506 id: NativeSurfaceId,
1507 color: ColorF,
1508 );
1509
1510 fn destroy_surface(
1517 &mut self,
1518 device: &mut Device,
1519 id: NativeSurfaceId,
1520 );
1521
1522 fn create_tile(
1524 &mut self,
1525 device: &mut Device,
1526 id: NativeTileId,
1527 );
1528
1529 fn destroy_tile(
1531 &mut self,
1532 device: &mut Device,
1533 id: NativeTileId,
1534 );
1535
1536 fn attach_external_image(
1541 &mut self,
1542 device: &mut Device,
1543 id: NativeSurfaceId,
1544 external_image: ExternalImageId
1545 );
1546
1547 fn invalidate_tile(
1552 &mut self,
1553 _device: &mut Device,
1554 _id: NativeTileId,
1555 _valid_rect: DeviceIntRect
1556 ) {}
1557
1558 fn bind(
1570 &mut self,
1571 device: &mut Device,
1572 id: NativeTileId,
1573 dirty_rect: DeviceIntRect,
1574 valid_rect: DeviceIntRect,
1575 ) -> NativeSurfaceInfo;
1576
1577 fn unbind(
1580 &mut self,
1581 device: &mut Device,
1582 );
1583
1584 fn begin_frame(&mut self, device: &mut Device);
1586
1587 fn add_surface(
1597 &mut self,
1598 device: &mut Device,
1599 id: NativeSurfaceId,
1600 transform: CompositorSurfaceTransform,
1601 clip_rect: DeviceIntRect,
1602 image_rendering: ImageRendering,
1603 rounded_clip_rect: DeviceIntRect,
1604 rounded_clip_radii: ClipRadius,
1605 );
1606
1607 fn start_compositing(
1614 &mut self,
1615 _device: &mut Device,
1616 _clear_color: ColorF,
1617 _dirty_rects: &[DeviceIntRect],
1618 _opaque_rects: &[DeviceIntRect],
1619 ) {}
1620
1621 fn end_frame(&mut self, device: &mut Device);
1625
1626 fn enable_native_compositor(&mut self, device: &mut Device, enable: bool);
1628
1629 fn deinit(&mut self, device: &mut Device);
1631
1632 fn get_capabilities(&self, device: &mut Device) -> CompositorCapabilities;
1636
1637 fn get_window_visibility(&self, device: &mut Device) -> WindowVisibility;
1638}
1639
1640#[derive(Debug)]
1643pub struct CompositorInputLayer {
1644 pub offset: DeviceIntPoint,
1646 pub clip_rect: DeviceIntRect,
1648 pub usage: CompositorSurfaceUsage,
1650 pub is_opaque: bool,
1652 pub rounded_clip_rect: DeviceIntRect,
1653 pub rounded_clip_radii: ClipRadius,
1654}
1655
1656#[derive(Debug)]
1659pub struct CompositorInputConfig<'a> {
1660 pub enable_screenshot: bool,
1661 pub layers: &'a [CompositorInputLayer],
1662}
1663
1664pub trait LayerCompositor {
1667 fn begin_frame(
1670 &mut self,
1671 input: &CompositorInputConfig,
1672 ) -> bool;
1673
1674 fn bind_layer(
1677 &mut self,
1678 index: usize,
1679 dirty_rects: &[DeviceIntRect],
1680 );
1681
1682 fn present_layer(
1684 &mut self,
1685 index: usize,
1686 dirty_rects: &[DeviceIntRect],
1687 );
1688
1689 fn add_surface(
1690 &mut self,
1691 index: usize,
1692 transform: CompositorSurfaceTransform,
1693 clip_rect: DeviceIntRect,
1694 image_rendering: ImageRendering,
1695 rounded_clip_rect: DeviceIntRect,
1696 rounded_clip_radii: ClipRadius,
1697 );
1698
1699 fn end_frame(&mut self);
1701
1702 fn get_window_properties(&self) -> WindowProperties;
1704}
1705
1706#[repr(C)]
1708#[derive(Copy, Clone)]
1709pub struct MappedTileInfo {
1710 pub data: *mut c_void,
1711 pub stride: i32,
1712}
1713
1714#[repr(C)]
1716pub struct SWGLCompositeSurfaceInfo {
1717 pub yuv_planes: u32,
1720 pub textures: [u32; 3],
1722 pub color_space: YuvRangedColorSpace,
1724 pub color_depth: ColorDepth,
1726 pub size: DeviceIntSize,
1728}
1729
1730pub trait MappableCompositor: Compositor {
1732 fn map_tile(
1737 &mut self,
1738 device: &mut Device,
1739 id: NativeTileId,
1740 dirty_rect: DeviceIntRect,
1741 valid_rect: DeviceIntRect,
1742 ) -> Option<MappedTileInfo>;
1743
1744 fn unmap_tile(&mut self, device: &mut Device);
1747
1748 fn lock_composite_surface(
1749 &mut self,
1750 device: &mut Device,
1751 ctx: *mut c_void,
1752 external_image_id: ExternalImageId,
1753 composite_info: *mut SWGLCompositeSurfaceInfo,
1754 ) -> bool;
1755 fn unlock_composite_surface(&mut self, device: &mut Device, ctx: *mut c_void, external_image_id: ExternalImageId);
1756}
1757
1758pub trait PartialPresentCompositor {
1763 fn set_buffer_damage_region(&mut self, rects: &[DeviceIntRect]);
1768}
1769
1770#[cfg_attr(feature = "capture", derive(Serialize))]
1772#[cfg_attr(feature = "replay", derive(Deserialize))]
1773struct Occluder {
1774 z_id: ZBufferId,
1775 world_rect: WorldIntRect,
1776}
1777
1778#[derive(Debug)]
1780enum OcclusionEventKind {
1781 Begin,
1782 End,
1783}
1784
1785#[derive(Debug)]
1787struct OcclusionEvent {
1788 y: i32,
1789 x_range: ops::Range<i32>,
1790 kind: OcclusionEventKind,
1791}
1792
1793impl OcclusionEvent {
1794 fn new(y: i32, kind: OcclusionEventKind, x0: i32, x1: i32) -> Self {
1795 OcclusionEvent {
1796 y,
1797 x_range: ops::Range {
1798 start: x0,
1799 end: x1,
1800 },
1801 kind,
1802 }
1803 }
1804}
1805
1806pub struct OccludersScratchBuffers {
1810 events: FrameVec<OcclusionEvent>,
1811 active: FrameVec<ops::Range<i32>>,
1812}
1813
1814impl Default for OccludersScratchBuffers {
1815 fn default() -> Self {
1816 OccludersScratchBuffers {
1817 events: FrameVec::new_in(FrameAllocator::fallback()),
1818 active: FrameVec::new_in(FrameAllocator::fallback()),
1819 }
1820 }
1821}
1822
1823#[cfg_attr(feature = "capture", derive(Serialize))]
1827#[cfg_attr(feature = "replay", derive(Deserialize))]
1828pub struct Occluders {
1829 occluders: FrameVec<Occluder>,
1830
1831 #[cfg_attr(any(feature = "capture", feature = "replay"), serde(skip))]
1833 scratch: OccludersScratchBuffers,
1834}
1835
1836impl Occluders {
1837 fn new(memory: &FrameMemory) -> Self {
1838 Occluders {
1839 occluders: memory.new_vec(),
1840 scratch: OccludersScratchBuffers {
1841 events: memory.new_vec(),
1842 active: memory.new_vec(),
1843 }
1844 }
1845 }
1846
1847 fn push(&mut self, world_rect: WorldIntRect, z_id: ZBufferId) {
1848 self.occluders.push(Occluder { world_rect, z_id });
1849 }
1850
1851 pub fn is_tile_occluded(
1854 &mut self,
1855 z_id: ZBufferId,
1856 world_rect: WorldRect,
1857 ) -> bool {
1858 let world_rect = world_rect.round().to_i32();
1872 let ref_area = world_rect.area();
1873
1874 let cover_area = self.area(z_id, &world_rect);
1876 debug_assert!(cover_area <= ref_area);
1877
1878 ref_area == cover_area
1880 }
1881
1882 fn area(
1885 &mut self,
1886 z_id: ZBufferId,
1887 clip_rect: &WorldIntRect,
1888 ) -> i32 {
1889 self.scratch.events.clear();
1894 self.scratch.active.clear();
1895
1896 let mut area = 0;
1897
1898 for occluder in &self.occluders {
1900 if occluder.z_id.0 < z_id.0 {
1902 if let Some(rect) = occluder.world_rect.intersection(clip_rect) {
1905 let x0 = rect.min.x;
1906 let x1 = x0 + rect.width();
1907 self.scratch.events.push(OcclusionEvent::new(rect.min.y, OcclusionEventKind::Begin, x0, x1));
1908 self.scratch.events.push(OcclusionEvent::new(rect.min.y + rect.height(), OcclusionEventKind::End, x0, x1));
1909 }
1910 }
1911 }
1912
1913 if self.scratch.events.is_empty() {
1915 return 0;
1916 }
1917
1918 self.scratch.events.sort_by_key(|e| e.y);
1920 let mut cur_y = self.scratch.events[0].y;
1921
1922 for event in &self.scratch.events {
1924 let dy = event.y - cur_y;
1926
1927 if dy != 0 && !self.scratch.active.is_empty() {
1929 assert!(dy > 0);
1930
1931 self.scratch.active.sort_by_key(|i| i.start);
1933 let mut query = 0;
1934 let mut cur = self.scratch.active[0].start;
1935
1936 for interval in &self.scratch.active {
1938 cur = interval.start.max(cur);
1939 query += (interval.end - cur).max(0);
1940 cur = cur.max(interval.end);
1941 }
1942
1943 area += query * dy;
1945 }
1946
1947 match event.kind {
1949 OcclusionEventKind::Begin => {
1950 self.scratch.active.push(event.x_range.clone());
1951 }
1952 OcclusionEventKind::End => {
1953 let index = self.scratch.active.iter().position(|i| *i == event.x_range).unwrap();
1954 self.scratch.active.remove(index);
1955 }
1956 }
1957
1958 cur_y = event.y;
1959 }
1960
1961 area
1962 }
1963}