1use api::{BorderRadius, ColorF, ExternalImageId, ImageBufferKind, ImageKey, ImageRendering, YuvFormat, YuvRangedColorSpace};
6use api::units::*;
7use api::ColorDepth;
8use crate::image_source::resolve_image;
9use euclid::Box2D;
10use crate::gpu_cache::GpuCache;
11use crate::gpu_types::{ZBufferId, ZBufferIdGenerator};
12use crate::internal_types::{FrameAllocator, FrameMemory, FrameVec, TextureSource};
13use crate::picture::{ImageDependency, ResolvedSurfaceTexture, TileCacheInstance, TileId, TileSurface};
14use crate::prim_store::DeferredResolve;
15use crate::resource_cache::{ImageRequest, ResourceCache};
16use crate::util::{extract_inner_rect_safe, Preallocator, ScaleOffset};
17use crate::tile_cache::PictureCacheDebugInfo;
18use crate::device::Device;
19use crate::space::SpaceMapper;
20use std::{ops, u64, os::raw::c_void};
21use std::num::NonZeroUsize;
22
23#[cfg_attr(feature = "capture", derive(Serialize))]
30#[cfg_attr(feature = "replay", derive(Deserialize))]
31#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
32pub enum CompositorSurfaceKind {
33    Blit,
35    Underlay,
37    Overlay,
39}
40
41impl CompositorSurfaceKind {
42    pub fn is_composited(&self) -> bool {
43        match *self {
44            CompositorSurfaceKind::Blit => false,
45            CompositorSurfaceKind::Underlay | CompositorSurfaceKind::Overlay => true,
46        }
47    }
48}
49
50#[derive(Debug, Clone)]
52#[cfg_attr(feature = "capture", derive(Serialize))]
53#[cfg_attr(feature = "replay", derive(Deserialize))]
54pub enum NativeSurfaceOperationDetails {
55    CreateSurface {
56        id: NativeSurfaceId,
57        virtual_offset: DeviceIntPoint,
58        tile_size: DeviceIntSize,
59        is_opaque: bool,
60    },
61    CreateExternalSurface {
62        id: NativeSurfaceId,
63        is_opaque: bool,
64    },
65    CreateBackdropSurface {
66        id: NativeSurfaceId,
67        color: ColorF,
68    },
69    DestroySurface {
70        id: NativeSurfaceId,
71    },
72    CreateTile {
73        id: NativeTileId,
74    },
75    DestroyTile {
76        id: NativeTileId,
77    },
78    AttachExternalImage {
79        id: NativeSurfaceId,
80        external_image: ExternalImageId,
81    }
82}
83
84#[derive(Debug, Clone)]
86#[cfg_attr(feature = "capture", derive(Serialize))]
87#[cfg_attr(feature = "replay", derive(Deserialize))]
88pub struct NativeSurfaceOperation {
89    pub details: NativeSurfaceOperationDetails,
90}
91
92#[cfg_attr(feature = "capture", derive(Serialize))]
96#[cfg_attr(feature = "replay", derive(Deserialize))]
97#[derive(Clone)]
98pub enum CompositeTileSurface {
99    Texture {
100        surface: ResolvedSurfaceTexture,
101    },
102    Color {
103        color: ColorF,
104    },
105    Clear,
106    ExternalSurface {
107        external_surface_index: ResolvedExternalSurfaceIndex,
108    },
109}
110
111#[derive(Debug, Copy, Clone, PartialEq)]
113pub enum CompositeSurfaceFormat {
114    Rgba,
115    Yuv,
116}
117
118bitflags! {
119    #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
122    pub struct CompositeFeatures: u8 {
123        const NO_UV_CLAMP = 1 << 0;
126        const NO_COLOR_MODULATION = 1 << 1;
128        const NO_CLIP_MASK = 1 << 2;
130    }
131}
132
133#[derive(Copy, Clone, Debug, PartialEq)]
134#[cfg_attr(feature = "capture", derive(Serialize))]
135#[cfg_attr(feature = "replay", derive(Deserialize))]
136pub enum TileKind {
137    Opaque,
138    Alpha,
139    Clear,
140}
141
142#[cfg_attr(feature = "capture", derive(Serialize))]
144#[cfg_attr(feature = "replay", derive(Deserialize))]
145#[derive(Debug, Copy, Clone)]
146pub struct CompositorTransformIndex(usize);
147
148impl CompositorTransformIndex {
149    pub const INVALID: CompositorTransformIndex = CompositorTransformIndex(!0);
150}
151
152#[cfg_attr(feature = "capture", derive(Serialize))]
154#[cfg_attr(feature = "replay", derive(Deserialize))]
155#[derive(Debug, Copy, Clone)]
156pub struct CompositorClipIndex(NonZeroUsize);
157
158#[cfg_attr(feature = "capture", derive(Serialize))]
160#[cfg_attr(feature = "replay", derive(Deserialize))]
161#[derive(Clone)]
162pub struct CompositeTile {
163    pub surface: CompositeTileSurface,
164    pub local_rect: PictureRect,
165    pub local_valid_rect: PictureRect,
166    pub local_dirty_rect: PictureRect,
167    pub device_clip_rect: DeviceRect,
168    pub z_id: ZBufferId,
169    pub kind: TileKind,
170    pub transform_index: CompositorTransformIndex,
171    pub clip_index: Option<CompositorClipIndex>,
172    pub tile_id: Option<TileId>,
173}
174
175pub fn tile_kind(surface: &CompositeTileSurface, is_opaque: bool) -> TileKind {
176    match surface {
177        CompositeTileSurface::Color { .. } => TileKind::Opaque,
180        CompositeTileSurface::Clear => TileKind::Clear,
182        CompositeTileSurface::Texture { .. }
183        | CompositeTileSurface::ExternalSurface { .. } => {
184            if is_opaque {
187                TileKind::Opaque
188            } else {
189                TileKind::Alpha
190            }
191        }
192    }
193}
194
195pub enum ExternalSurfaceDependency {
196    Yuv {
197        image_dependencies: [ImageDependency; 3],
198        color_space: YuvRangedColorSpace,
199        format: YuvFormat,
200        channel_bit_depth: u32,
201    },
202    Rgb {
203        image_dependency: ImageDependency,
204    },
205}
206
207pub struct ExternalSurfaceDescriptor {
211    pub local_surface_size: LayoutSize,
214    pub local_rect: PictureRect,
215    pub local_clip_rect: PictureRect,
216    pub clip_rect: DeviceRect,
217    pub transform_index: CompositorTransformIndex,
218    pub image_rendering: ImageRendering,
219    pub z_id: ZBufferId,
220    pub dependency: ExternalSurfaceDependency,
221    pub native_surface_id: Option<NativeSurfaceId>,
224    pub update_params: Option<DeviceIntSize>,
227    pub external_image_id: Option<ExternalImageId>,
229}
230
231impl ExternalSurfaceDescriptor {
232    pub fn get_occluder_rect(
234        &self,
235        local_clip_rect: &PictureRect,
236        map_pic_to_world: &SpaceMapper<PicturePixel, WorldPixel>,
237    ) -> Option<WorldRect> {
238        let local_surface_rect = self
239            .local_rect
240            .intersection(&self.local_clip_rect)
241            .and_then(|r| {
242                r.intersection(local_clip_rect)
243            });
244
245        local_surface_rect.map(|local_surface_rect| {
246            map_pic_to_world
247                .map(&local_surface_rect)
248                .expect("bug: unable to map external surface to world space")
249        })
250    }
251}
252
253#[cfg_attr(feature = "capture", derive(Serialize))]
255#[cfg_attr(feature = "replay", derive(Deserialize))]
256#[derive(Debug, Copy, Clone)]
257pub struct ExternalPlaneDescriptor {
258    pub texture: TextureSource,
259    pub uv_rect: TexelRect,
260}
261
262impl ExternalPlaneDescriptor {
263    fn invalid() -> Self {
264        ExternalPlaneDescriptor {
265            texture: TextureSource::Invalid,
266            uv_rect: TexelRect::invalid(),
267        }
268    }
269}
270
271#[cfg_attr(feature = "capture", derive(Serialize))]
272#[cfg_attr(feature = "replay", derive(Deserialize))]
273#[derive(Debug, Copy, Clone, PartialEq)]
274pub struct ResolvedExternalSurfaceIndex(pub usize);
275
276impl ResolvedExternalSurfaceIndex {
277    pub const INVALID: ResolvedExternalSurfaceIndex = ResolvedExternalSurfaceIndex(usize::MAX);
278}
279
280#[cfg_attr(feature = "capture", derive(Serialize))]
281#[cfg_attr(feature = "replay", derive(Deserialize))]
282pub enum ResolvedExternalSurfaceColorData {
283    Yuv {
284        image_dependencies: [ImageDependency; 3],
286        planes: [ExternalPlaneDescriptor; 3],
287        color_space: YuvRangedColorSpace,
288        format: YuvFormat,
289        channel_bit_depth: u32,
290    },
291    Rgb {
292        image_dependency: ImageDependency,
293        plane: ExternalPlaneDescriptor,
294    },
295}
296
297#[cfg_attr(feature = "capture", derive(Serialize))]
302#[cfg_attr(feature = "replay", derive(Deserialize))]
303pub struct ResolvedExternalSurface {
304    pub color_data: ResolvedExternalSurfaceColorData,
305    pub image_buffer_kind: ImageBufferKind,
306    pub update_params: Option<(NativeSurfaceId, DeviceIntSize)>,
308    pub external_image_id: Option<ExternalImageId>,
310}
311
312pub enum CompositorConfig {
315    Draw {
317        max_partial_present_rects: usize,
322        draw_previous_partial_present_regions: bool,
326        partial_present: Option<Box<dyn PartialPresentCompositor>>,
329    },
330    Layer {
331        compositor: Box<dyn LayerCompositor>,
335    },
336    Native {
340        compositor: Box<dyn Compositor>,
342    }
343}
344
345impl CompositorConfig {
346    pub fn compositor(&mut self) -> Option<&mut Box<dyn Compositor>> {
347        match self {
348            CompositorConfig::Native { ref mut compositor, .. } => {
349                Some(compositor)
350            }
351            CompositorConfig::Draw { .. } | CompositorConfig::Layer { .. } => {
352                None
353            }
354        }
355    }
356
357    pub fn partial_present(&mut self) -> Option<&mut Box<dyn PartialPresentCompositor>> {
358        match self {
359            CompositorConfig::Native { .. } => {
360                None
361            }
362            CompositorConfig::Draw { ref mut partial_present, .. } => {
363                partial_present.as_mut()
364            }
365            CompositorConfig::Layer { .. } => {
366                None
367            }
368        }
369    }
370
371    pub fn layer_compositor(&mut self) -> Option<&mut Box<dyn LayerCompositor>> {
372        match self {
373            CompositorConfig::Native { .. } => {
374                None
375            }
376            CompositorConfig::Draw { .. } => {
377                None
378            }
379            CompositorConfig::Layer { ref mut compositor } => {
380                Some(compositor)
381            }
382        }
383    }
384}
385
386impl Default for CompositorConfig {
387    fn default() -> Self {
389        CompositorConfig::Draw {
390            max_partial_present_rects: 0,
391            draw_previous_partial_present_regions: false,
392            partial_present: None,
393        }
394    }
395}
396
397#[cfg_attr(feature = "capture", derive(Serialize))]
401#[cfg_attr(feature = "replay", derive(Deserialize))]
402#[derive(Debug, Copy, Clone, PartialEq)]
403pub enum CompositorKind {
404    Draw {
406        max_partial_present_rects: usize,
408        draw_previous_partial_present_regions: bool,
410    },
411    Layer {
412
413    },
414    Native {
416        capabilities: CompositorCapabilities,
418    },
419}
420
421impl Default for CompositorKind {
422    fn default() -> Self {
424        CompositorKind::Draw {
425            max_partial_present_rects: 0,
426            draw_previous_partial_present_regions: false,
427        }
428    }
429}
430
431impl CompositorKind {
432    pub fn get_virtual_surface_size(&self) -> i32 {
433        match self {
434            CompositorKind::Draw { .. } | CompositorKind::Layer {  .. }=> 0,
435            CompositorKind::Native { capabilities, .. } => capabilities.virtual_surface_size,
436        }
437    }
438
439    pub fn should_redraw_on_invalidation(&self) -> bool {
440        match self {
441            CompositorKind::Draw { max_partial_present_rects, .. } => {
442                *max_partial_present_rects > 0
444            }
445            CompositorKind::Layer {  } => false,    CompositorKind::Native { capabilities, .. } => capabilities.redraw_on_invalidation,
447        }
448    }
449}
450
451#[cfg_attr(feature = "capture", derive(Serialize))]
454#[cfg_attr(feature = "replay", derive(Deserialize))]
455#[derive(PartialEq, Clone)]
456pub enum TileSurfaceKind {
457    Texture,
458    Color {
459        color: ColorF,
460    },
461    Clear,
462}
463
464impl From<&TileSurface> for TileSurfaceKind {
465    fn from(surface: &TileSurface) -> Self {
466        match surface {
467            TileSurface::Texture { .. } => TileSurfaceKind::Texture,
468            TileSurface::Color { color } => TileSurfaceKind::Color { color: *color },
469            TileSurface::Clear => TileSurfaceKind::Clear,
470        }
471    }
472}
473
474#[cfg_attr(feature = "capture", derive(Serialize))]
477#[cfg_attr(feature = "replay", derive(Deserialize))]
478#[derive(PartialEq, Clone)]
479pub struct CompositeTileDescriptor {
480    pub tile_id: TileId,
481    pub surface_kind: TileSurfaceKind,
482}
483
484#[cfg_attr(feature = "capture", derive(Serialize))]
487#[cfg_attr(feature = "replay", derive(Deserialize))]
488#[derive(Debug, Copy, Clone)]
489pub enum CompositorSurfaceUsage {
490    Content,
491    External {
492        image_key: ImageKey,
493        external_image_id: ExternalImageId,
494        transform_index: CompositorTransformIndex,
495    },
496    DebugOverlay,
497}
498
499impl CompositorSurfaceUsage {
500    pub fn matches(&self, other: &CompositorSurfaceUsage) -> bool {
502        match (self, other) {
503            (CompositorSurfaceUsage::Content, CompositorSurfaceUsage::Content) => true,
505
506            (CompositorSurfaceUsage::Content, CompositorSurfaceUsage::External { .. }) |
507            (CompositorSurfaceUsage::External { .. }, CompositorSurfaceUsage::Content) => false,
508
509            (CompositorSurfaceUsage::External { image_key: key1, .. }, CompositorSurfaceUsage::External { image_key: key2, .. }) => {
511                key1 == key2
512            }
513
514            (CompositorSurfaceUsage::DebugOverlay, CompositorSurfaceUsage::DebugOverlay) => true,
515
516            (CompositorSurfaceUsage::DebugOverlay, _) | (_, CompositorSurfaceUsage::DebugOverlay) => false,
517        }
518    }
519}
520
521#[cfg_attr(feature = "capture", derive(Serialize))]
523#[cfg_attr(feature = "replay", derive(Deserialize))]
524#[derive(PartialEq, Clone)]
525pub struct CompositeSurfaceDescriptor {
526    pub surface_id: Option<NativeSurfaceId>,
527    pub clip_rect: DeviceRect,
528    pub transform: CompositorSurfaceTransform,
529    pub image_dependencies: [ImageDependency; 3],
534    pub image_rendering: ImageRendering,
535    pub tile_descriptors: Vec<CompositeTileDescriptor>,
537    pub rounded_clip_rect: DeviceRect,
538    pub rounded_clip_radii: ClipRadius,
539}
540
541#[cfg_attr(feature = "capture", derive(Serialize))]
544#[cfg_attr(feature = "replay", derive(Deserialize))]
545#[derive(PartialEq, Clone)]
546pub struct CompositeDescriptor {
547    pub surfaces: Vec<CompositeSurfaceDescriptor>,
548    pub external_surfaces_rect: DeviceRect,
549}
550
551impl CompositeDescriptor {
552    pub fn empty() -> Self {
554        CompositeDescriptor {
555            surfaces: Vec::new(),
556            external_surfaces_rect: DeviceRect::zero(),
557        }
558    }
559}
560
561pub struct CompositeStatePreallocator {
562    tiles: Preallocator,
563    external_surfaces: Preallocator,
564    occluders: Preallocator,
565    occluders_events: Preallocator,
566    occluders_active: Preallocator,
567    descriptor_surfaces: Preallocator,
568}
569
570impl CompositeStatePreallocator {
571    pub fn record(&mut self, state: &CompositeState) {
572        self.tiles.record_vec(&state.tiles);
573        self.external_surfaces.record_vec(&state.external_surfaces);
574        self.occluders.record_vec(&state.occluders.occluders);
575        self.occluders_events.record_vec(&state.occluders.scratch.events);
576        self.occluders_active.record_vec(&state.occluders.scratch.active);
577        self.descriptor_surfaces.record_vec(&state.descriptor.surfaces);
578    }
579
580    pub fn preallocate(&self, state: &mut CompositeState) {
581        self.tiles.preallocate_framevec(&mut state.tiles);
582        self.external_surfaces.preallocate_framevec(&mut state.external_surfaces);
583        self.occluders.preallocate_framevec(&mut state.occluders.occluders);
584        self.occluders_events.preallocate_framevec(&mut state.occluders.scratch.events);
585        self.occluders_active.preallocate_framevec(&mut state.occluders.scratch.active);
586        self.descriptor_surfaces.preallocate_vec(&mut state.descriptor.surfaces);
587    }
588}
589
590impl Default for CompositeStatePreallocator {
591    fn default() -> Self {
592        CompositeStatePreallocator {
593            tiles: Preallocator::new(56),
594            external_surfaces: Preallocator::new(0),
595            occluders: Preallocator::new(16),
596            occluders_events: Preallocator::new(32),
597            occluders_active: Preallocator::new(16),
598            descriptor_surfaces: Preallocator::new(8),
599        }
600    }
601}
602
603#[cfg_attr(feature = "capture", derive(Serialize))]
610#[cfg_attr(feature = "replay", derive(Deserialize))]
611pub struct CompositorTransform {
612    local_to_raster: ScaleOffset,
614    raster_to_device: ScaleOffset,
616    local_to_device: ScaleOffset,
618}
619
620#[cfg_attr(feature = "capture", derive(Serialize))]
621#[cfg_attr(feature = "replay", derive(Deserialize))]
622pub struct CompositorClip {
623    pub rect: DeviceRect,
624    pub radius: BorderRadius,
625}
626
627#[cfg_attr(feature = "capture", derive(Serialize))]
629#[cfg_attr(feature = "replay", derive(Deserialize))]
630pub struct CompositeState {
631    pub tiles: FrameVec<CompositeTile>,
638    pub external_surfaces: FrameVec<ResolvedExternalSurface>,
640    pub z_generator: ZBufferIdGenerator,
642    pub dirty_rects_are_valid: bool,
649    pub compositor_kind: CompositorKind,
651    pub occluders: Occluders,
653    pub descriptor: CompositeDescriptor,
655    pub picture_cache_debug: PictureCacheDebugInfo,
657    pub transforms: FrameVec<CompositorTransform>,
659    low_quality_pinch_zoom: bool,
661    pub clips: FrameVec<CompositorClip>,
663}
664
665impl CompositeState {
666    pub fn new(
669        compositor_kind: CompositorKind,
670        max_depth_ids: i32,
671        dirty_rects_are_valid: bool,
672        low_quality_pinch_zoom: bool,
673        memory: &FrameMemory,
674    ) -> Self {
675        let mut clips = memory.new_vec();
678        clips.push(CompositorClip {
679            rect: DeviceRect::zero(),
680            radius: BorderRadius::zero(),
681        });
682
683        CompositeState {
684            tiles: memory.new_vec(),
685            z_generator: ZBufferIdGenerator::new(max_depth_ids),
686            dirty_rects_are_valid,
687            compositor_kind,
688            occluders: Occluders::new(memory),
689            descriptor: CompositeDescriptor::empty(),
690            external_surfaces: memory.new_vec(),
691            picture_cache_debug: PictureCacheDebugInfo::new(),
692            transforms: memory.new_vec(),
693            low_quality_pinch_zoom,
694            clips,
695        }
696    }
697
698    fn compositor_clip_params(
699        &self,
700        clip_index: Option<CompositorClipIndex>,
701        default_rect: DeviceRect,
702    ) -> (DeviceRect, ClipRadius) {
703        match clip_index {
704            Some(clip_index) => {
705                let clip = self.get_compositor_clip(clip_index);
706
707                (
708                    clip.rect.cast_unit(),
709                    ClipRadius {
710                        top_left: clip.radius.top_left.width.round() as i32,
711                        top_right: clip.radius.top_right.width.round() as i32,
712                        bottom_left: clip.radius.bottom_left.width.round() as i32,
713                        bottom_right: clip.radius.bottom_right.width.round() as i32,
714                    }
715                )
716            }
717            None => {
718                (default_rect, ClipRadius::EMPTY)
719            }
720        }
721    }
722
723    pub fn register_transform(
725        &mut self,
726        local_to_raster: ScaleOffset,
727        raster_to_device: ScaleOffset,
728    ) -> CompositorTransformIndex {
729        let index = CompositorTransformIndex(self.transforms.len());
730
731        let local_to_device = local_to_raster.then(&raster_to_device);
732
733        self.transforms.push(CompositorTransform {
734            local_to_raster,
735            raster_to_device,
736            local_to_device,
737        });
738
739        index
740    }
741
742    pub fn register_clip(
744        &mut self,
745        rect: DeviceRect,
746        radius: BorderRadius,
747    ) -> CompositorClipIndex {
748        let index = CompositorClipIndex(NonZeroUsize::new(self.clips.len()).expect("bug"));
749
750        self.clips.push(CompositorClip {
751            rect,
752            radius,
753        });
754
755        index
756    }
757
758    pub fn get_device_rect(
760        &self,
761        local_rect: &PictureRect,
762        transform_index: CompositorTransformIndex,
763    ) -> DeviceRect {
764        let transform = &self.transforms[transform_index.0];
765        transform.local_to_device.map_rect(&local_rect).round()
766    }
767
768    pub fn get_surface_rect<T>(
771        &self,
772        local_sub_rect: &Box2D<f32, T>,
773        local_bounds: &Box2D<f32, T>,
774        transform_index: CompositorTransformIndex,
775    ) -> DeviceRect {
776        let transform = &self.transforms[transform_index.0];
777
778        let surface_bounds = transform.local_to_raster.map_rect(&local_bounds);
779        let surface_rect = transform.local_to_raster.map_rect(&local_sub_rect);
780
781        surface_rect
782            .round_out()
783            .translate(-surface_bounds.min.to_vector())
784            .round_out()
785            .intersection(&surface_bounds.size().round().into())
786            .unwrap_or_else(DeviceRect::zero)
787    }
788
789    pub fn get_device_transform(
791        &self,
792        transform_index: CompositorTransformIndex,
793    ) -> ScaleOffset {
794        let transform = &self.transforms[transform_index.0];
795        transform.local_to_device
796    }
797
798    pub fn get_compositor_transform(
800        &self,
801        transform_index: CompositorTransformIndex,
802    ) -> ScaleOffset {
803        let transform = &self.transforms[transform_index.0];
804        transform.raster_to_device
805    }
806
807    pub fn get_compositor_clip(
809        &self,
810        clip_index: CompositorClipIndex,
811    ) -> &CompositorClip {
812        &self.clips[clip_index.0.get()]
813    }
814
815    pub fn register_occluder(
818        &mut self,
819        z_id: ZBufferId,
820        rect: WorldRect,
821        compositor_clip: Option<CompositorClipIndex>,
822    ) {
823        let rect = match compositor_clip {
824            Some(clip_index) => {
825                let clip = self.get_compositor_clip(clip_index);
826
827                let inner_rect = match extract_inner_rect_safe(
828                    &clip.rect,
829                    &clip.radius,
830                ) {
831                    Some(rect) => rect,
832                    None => return,
833                };
834
835                match inner_rect.cast_unit().intersection(&rect) {
836                    Some(rect) => rect,
837                    None => return,
838                }
839            }
840            None => {
841                rect
842            }
843        };
844
845        let world_rect = rect.round().to_i32();
846
847        self.occluders.push(world_rect, z_id);
848    }
849
850    fn push_compositor_surface(
852        &mut self,
853        external_surface: &ExternalSurfaceDescriptor,
854        is_opaque: bool,
855        device_clip_rect: DeviceRect,
856        resource_cache: &ResourceCache,
857        gpu_cache: &mut GpuCache,
858        deferred_resolves: &mut FrameVec<DeferredResolve>,
859        clip_index: Option<CompositorClipIndex>,
860    ) {
861        let clip_rect = external_surface
862            .clip_rect
863            .intersection(&device_clip_rect)
864            .unwrap_or_else(DeviceRect::zero);
865
866        if clip_rect.is_empty() {
868            return;
869        }
870
871        let required_plane_count =
872            match external_surface.dependency {
873                ExternalSurfaceDependency::Yuv { format, .. } => {
874                    format.get_plane_num()
875                },
876                ExternalSurfaceDependency::Rgb { .. } => {
877                    1
878                }
879            };
880
881        let mut image_dependencies = [ImageDependency::INVALID; 3];
882
883        for i in 0 .. required_plane_count {
884            let dependency = match external_surface.dependency {
885                ExternalSurfaceDependency::Yuv { image_dependencies, .. } => {
886                    image_dependencies[i]
887                },
888                ExternalSurfaceDependency::Rgb { image_dependency, .. } => {
889                    image_dependency
890                }
891            };
892            image_dependencies[i] = dependency;
893        }
894
895        let needs_external_surface_update = match self.compositor_kind {
899            CompositorKind::Draw { .. } | CompositorKind::Layer { .. } => true,
900            _ => external_surface.update_params.is_some(),
901        };
902        let external_surface_index = if needs_external_surface_update {
903            let external_surface_index = self.compute_external_surface_dependencies(
904                &external_surface,
905                &image_dependencies,
906                required_plane_count,
907                resource_cache,
908                gpu_cache,
909                deferred_resolves,
910            );
911            if external_surface_index == ResolvedExternalSurfaceIndex::INVALID {
912                return;
913            }
914            external_surface_index
915        } else {
916            ResolvedExternalSurfaceIndex::INVALID
917        };
918
919        let surface = CompositeTileSurface::ExternalSurface { external_surface_index };
920        let local_rect = external_surface.local_surface_size.cast_unit().into();
921
922        let tile = CompositeTile {
923            kind: tile_kind(&surface, is_opaque),
924            surface,
925            local_rect,
926            local_valid_rect: local_rect,
927            local_dirty_rect: local_rect,
928            device_clip_rect: clip_rect,
929            z_id: external_surface.z_id,
930            transform_index: external_surface.transform_index,
931            clip_index,
932            tile_id: None,
933        };
934
935        let (rounded_clip_rect, rounded_clip_radii) = self.compositor_clip_params(
936            clip_index,
937            clip_rect,
938        );
939
940        self.descriptor.surfaces.push(
944            CompositeSurfaceDescriptor {
945                surface_id: external_surface.native_surface_id,
946                clip_rect,
947                transform: self.get_compositor_transform(external_surface.transform_index),
948                image_dependencies: image_dependencies,
949                image_rendering: external_surface.image_rendering,
950                tile_descriptors: Vec::new(),
951                rounded_clip_rect,
952                rounded_clip_radii,
953            }
954        );
955
956        let device_rect =
957            self.get_device_rect(&local_rect, external_surface.transform_index);
958        self.descriptor.external_surfaces_rect =
959            self.descriptor.external_surfaces_rect.union(&device_rect);
960
961        self.tiles.push(tile);
962    }
963
964    pub fn push_surface(
966        &mut self,
967        tile_cache: &TileCacheInstance,
968        device_clip_rect: DeviceRect,
969        resource_cache: &ResourceCache,
970        gpu_cache: &mut GpuCache,
971        deferred_resolves: &mut FrameVec<DeferredResolve>,
972    ) {
973        let slice_transform = self.get_compositor_transform(tile_cache.transform_index);
974
975        let image_rendering = if self.low_quality_pinch_zoom {
976            ImageRendering::Auto
977        } else {
978            ImageRendering::CrispEdges
979        };
980
981        if let Some(backdrop_surface) = &tile_cache.backdrop_surface {
982            let (rounded_clip_rect, rounded_clip_radii) = self.compositor_clip_params(
983                tile_cache.compositor_clip,
984                backdrop_surface.device_rect,
985            );
986    
987            self.descriptor.surfaces.push(
989                CompositeSurfaceDescriptor {
990                    surface_id: Some(backdrop_surface.id),
991                    clip_rect: backdrop_surface.device_rect,
992                    transform: slice_transform,
993                    image_dependencies: [ImageDependency::INVALID; 3],
994                    image_rendering,
995                    tile_descriptors: Vec::new(),
996                    rounded_clip_rect,
997                    rounded_clip_radii,
998                }
999            );
1000        }
1001
1002        for underlay in &tile_cache.underlays {
1004            self.push_compositor_surface(
1005                underlay,
1006                true,
1007                device_clip_rect,
1008                resource_cache,
1009                gpu_cache,
1010                deferred_resolves,
1011                tile_cache.compositor_clip,
1012            );
1013        }
1014
1015        for sub_slice in &tile_cache.sub_slices {
1016            let mut surface_device_rect = DeviceRect::zero();
1017
1018            for tile in sub_slice.tiles.values() {
1019                if !tile.is_visible {
1020                    continue;
1022                }
1023
1024                surface_device_rect = surface_device_rect.union(&tile.device_valid_rect);
1034            }
1035
1036            self.tiles.extend_from_slice(&sub_slice.composite_tiles);
1038
1039            let surface_clip_rect = device_clip_rect
1044                .intersection(&surface_device_rect)
1045                .unwrap_or(DeviceRect::zero());
1046
1047            if !surface_clip_rect.is_empty() {
1049                let (rounded_clip_rect, rounded_clip_radii) = self.compositor_clip_params(
1050                    tile_cache.compositor_clip,
1051                    surface_clip_rect,
1052                );
1053
1054                if !sub_slice.opaque_tile_descriptors.is_empty() {
1056                    self.descriptor.surfaces.push(
1057                        CompositeSurfaceDescriptor {
1058                            surface_id: sub_slice.native_surface.as_ref().map(|s| s.opaque),
1059                            clip_rect: surface_clip_rect,
1060                            transform: slice_transform,
1061                            image_dependencies: [ImageDependency::INVALID; 3],
1062                            image_rendering,
1063                            tile_descriptors: sub_slice.opaque_tile_descriptors.clone(),
1064                            rounded_clip_rect,
1065                            rounded_clip_radii,
1066                        }
1067                    );
1068                }
1069
1070                if !sub_slice.alpha_tile_descriptors.is_empty() {
1072                    self.descriptor.surfaces.push(
1073                        CompositeSurfaceDescriptor {
1074                            surface_id: sub_slice.native_surface.as_ref().map(|s| s.alpha),
1075                            clip_rect: surface_clip_rect,
1076                            transform: slice_transform,
1077                            image_dependencies: [ImageDependency::INVALID; 3],
1078                            image_rendering,
1079                            tile_descriptors: sub_slice.alpha_tile_descriptors.clone(),
1080                            rounded_clip_rect,
1081                            rounded_clip_radii,
1082                        }
1083                    );
1084                }
1085            }
1086
1087            for compositor_surface in &sub_slice.compositor_surfaces {
1090                self.push_compositor_surface(
1091                    &compositor_surface.descriptor,
1092                    compositor_surface.is_opaque,
1093                    device_clip_rect,
1094                    resource_cache,
1095                    gpu_cache,
1096                    deferred_resolves,
1097                    tile_cache.compositor_clip,
1098                );
1099            }
1100        }
1101    }
1102
1103    pub fn update_dirty_rect_validity(
1106        &mut self,
1107        old_descriptor: &CompositeDescriptor,
1108    ) {
1109        if old_descriptor.surfaces.len() != self.descriptor.surfaces.len() {
1115            self.dirty_rects_are_valid = false;
1116            return;
1117        }
1118
1119        if !self
1124            .descriptor
1125            .external_surfaces_rect
1126            .contains_box(&old_descriptor.external_surfaces_rect)
1127        {
1128            self.dirty_rects_are_valid = false;
1129            return;
1130        }
1131    }
1132
1133    fn compute_external_surface_dependencies(
1134        &mut self,
1135        external_surface: &ExternalSurfaceDescriptor,
1136        image_dependencies: &[ImageDependency; 3],
1137        required_plane_count: usize,
1138        resource_cache: &ResourceCache,
1139        gpu_cache: &mut GpuCache,
1140        deferred_resolves: &mut FrameVec<DeferredResolve>,
1141    ) -> ResolvedExternalSurfaceIndex {
1142        let mut planes = [
1143            ExternalPlaneDescriptor::invalid(),
1144            ExternalPlaneDescriptor::invalid(),
1145            ExternalPlaneDescriptor::invalid(),
1146        ];
1147
1148        let mut valid_plane_count = 0;
1149        for i in 0 .. required_plane_count {
1150            let request = ImageRequest {
1151                key: image_dependencies[i].key,
1152                rendering: external_surface.image_rendering,
1153                tile: None,
1154            };
1155
1156            let cache_item = resolve_image(
1157                request,
1158                resource_cache,
1159                gpu_cache,
1160                deferred_resolves,
1161                true,
1162            );
1163
1164            if cache_item.texture_id != TextureSource::Invalid {
1165                valid_plane_count += 1;
1166                let plane = &mut planes[i];
1167                *plane = ExternalPlaneDescriptor {
1168                    texture: cache_item.texture_id,
1169                    uv_rect: cache_item.uv_rect.into(),
1170                };
1171            }
1172        }
1173
1174        if valid_plane_count < required_plane_count {
1176            warn!("Warnings: skip a YUV/RGB compositor surface, found {}/{} valid images",
1177                valid_plane_count,
1178                required_plane_count,
1179            );
1180            return ResolvedExternalSurfaceIndex::INVALID;
1181        }
1182
1183        let external_surface_index = ResolvedExternalSurfaceIndex(self.external_surfaces.len());
1184
1185        let update_params = external_surface.update_params.map(|surface_size| {
1189            (
1190                external_surface.native_surface_id.expect("bug: no native surface!"),
1191                surface_size
1192            )
1193        });
1194
1195        match external_surface.dependency {
1196            ExternalSurfaceDependency::Yuv{ color_space, format, channel_bit_depth, .. } => {
1197
1198                let image_buffer_kind = planes[0].texture.image_buffer_kind();
1199
1200                self.external_surfaces.push(ResolvedExternalSurface {
1201                    color_data: ResolvedExternalSurfaceColorData::Yuv {
1202                        image_dependencies: *image_dependencies,
1203                        planes,
1204                        color_space,
1205                        format,
1206                        channel_bit_depth,
1207                        },
1208                    image_buffer_kind,
1209                    update_params,
1210                    external_image_id: external_surface.external_image_id,
1211                });
1212            },
1213            ExternalSurfaceDependency::Rgb { .. } => {
1214                let image_buffer_kind = planes[0].texture.image_buffer_kind();
1215
1216                self.external_surfaces.push(ResolvedExternalSurface {
1217                    color_data: ResolvedExternalSurfaceColorData::Rgb {
1218                        image_dependency: image_dependencies[0],
1219                        plane: planes[0],
1220                    },
1221                    image_buffer_kind,
1222                    update_params,
1223                    external_image_id: external_surface.external_image_id,
1224                });
1225            },
1226        }
1227        external_surface_index
1228    }
1229
1230    pub fn end_frame(&mut self) {
1231        self.tiles.sort_by_key(|tile| tile.z_id.0);
1233    }
1234
1235    #[cfg(feature = "debugger")]
1236    pub fn print_to_string(&self) -> String {
1237        use crate::print_tree::PrintTree;
1238        use crate::print_tree::PrintTreePrinter;
1239
1240        let mut buf = Vec::<u8>::new();
1241        {
1242            let mut pt = PrintTree::new_with_sink("composite config", &mut buf);
1243
1244            pt.new_level("tiles".into());
1245            for (i, tile) in self.tiles.iter().enumerate() {
1246                pt.new_level(format!("tile {}", i));
1247                pt.add_item(format!("local_rect = {:?}", tile.local_rect.to_rect()));
1248                pt.add_item(format!("local_valid_rect = {:?}", tile.local_valid_rect.to_rect()));
1249                pt.add_item(format!("local_dirty_rect = {:?}", tile.local_dirty_rect.to_rect()));
1250                pt.add_item(format!("device_clip_rect = {:?}", tile.device_clip_rect.to_rect()));
1251                pt.add_item(format!("z_id = {:?}", tile.z_id));
1252                pt.add_item(format!("kind = {:?}", tile.kind));
1253                pt.add_item(format!("tile_id = {:?}", tile.tile_id));
1254                pt.add_item(format!("clip = {:?}", tile.clip_index));
1255                pt.add_item(format!("transform = {:?}", tile.transform_index));
1256                pt.end_level();
1257            }
1258            pt.end_level();
1259
1260            pt.new_level("external_surfaces".into());
1261            for (i, surface) in self.external_surfaces.iter().enumerate() {
1262                pt.new_level(format!("surface {}", i));
1263                pt.add_item(format!("{:?}", surface.image_buffer_kind));
1264                pt.end_level();
1265            }
1266            pt.end_level();
1267
1268            pt.new_level("occluders".into());
1269            for (i, occluder) in self.occluders.occluders.iter().enumerate() {
1270                pt.new_level(format!("occluder {}", i));
1271                pt.add_item(format!("{:?}", occluder.z_id));
1272                pt.add_item(format!("{:?}", occluder.world_rect.to_rect()));
1273                pt.end_level();
1274            }
1275            pt.end_level();
1276
1277            pt.new_level("transforms".into());
1278            for (i, transform) in self.transforms.iter().enumerate() {
1279                pt.new_level(format!("transform {}", i));
1280                pt.add_item(format!("local_to_raster {:?}", transform.local_to_raster));
1281                pt.add_item(format!("raster_to_device {:?}", transform.raster_to_device));
1282                pt.add_item(format!("local_to_device {:?}", transform.local_to_device));
1283                pt.end_level();
1284            }
1285            pt.end_level();
1286
1287            pt.new_level("clips".into());
1288            for (i, clip) in self.clips.iter().enumerate() {
1289                pt.new_level(format!("clip {}", i));
1290                pt.add_item(format!("{:?}", clip.rect.to_rect()));
1291                pt.add_item(format!("{:?}", clip.radius));
1292                pt.end_level();
1293            }
1294            pt.end_level();
1295        }
1296
1297        std::str::from_utf8(&buf).unwrap_or("(Tree printer emitted non-utf8)").to_string()
1298    }
1299}
1300
1301#[repr(C)]
1303#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
1304#[cfg_attr(feature = "capture", derive(Serialize))]
1305#[cfg_attr(feature = "replay", derive(Deserialize))]
1306pub struct NativeSurfaceId(pub u64);
1307
1308impl NativeSurfaceId {
1309    pub const DEBUG_OVERLAY: NativeSurfaceId = NativeSurfaceId(u64::MAX);
1311}
1312
1313#[repr(C)]
1314#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
1315#[cfg_attr(feature = "capture", derive(Serialize))]
1316#[cfg_attr(feature = "replay", derive(Deserialize))]
1317pub struct NativeTileId {
1318    pub surface_id: NativeSurfaceId,
1319    pub x: i32,
1320    pub y: i32,
1321}
1322
1323impl NativeTileId {
1324    pub const DEBUG_OVERLAY: NativeTileId = NativeTileId {
1326        surface_id: NativeSurfaceId::DEBUG_OVERLAY,
1327        x: 0,
1328        y: 0,
1329    };
1330}
1331
1332#[repr(C)]
1335#[derive(Copy, Clone)]
1336pub struct NativeSurfaceInfo {
1337    pub origin: DeviceIntPoint,
1343    pub fbo_id: u32,
1351}
1352
1353#[repr(C)]
1354#[derive(Debug, Copy, Clone)]
1355pub struct WindowProperties {
1356    pub is_opaque: bool,
1357    pub enable_screenshot: bool,
1358}
1359
1360impl Default for WindowProperties {
1361    fn default() -> Self {
1362        WindowProperties {
1363            is_opaque: true,
1364            enable_screenshot: true,
1365        }
1366    }
1367}
1368
1369#[repr(C)]
1370#[derive(Debug, Copy, Clone, PartialEq)]
1371#[cfg_attr(feature = "capture", derive(Serialize))]
1372#[cfg_attr(feature = "replay", derive(Deserialize))]
1373pub struct CompositorCapabilities {
1374    pub virtual_surface_size: i32,
1376    pub redraw_on_invalidation: bool,
1378    pub max_update_rects: usize,
1382    pub supports_surface_for_backdrop: bool,
1384    pub supports_external_compositor_surface_negative_scaling: bool,
1386}
1387
1388impl Default for CompositorCapabilities {
1389    fn default() -> Self {
1390        CompositorCapabilities {
1395            virtual_surface_size: 0,
1396            redraw_on_invalidation: false,
1397            max_update_rects: 1,
1400            supports_surface_for_backdrop: false,
1401            supports_external_compositor_surface_negative_scaling: true,
1402        }
1403    }
1404}
1405
1406#[repr(C)]
1407#[derive(Copy, Clone, Debug)]
1408pub struct WindowVisibility {
1409    pub is_fully_occluded: bool,
1410}
1411
1412impl Default for WindowVisibility {
1413    fn default() -> Self {
1414        WindowVisibility {
1415            is_fully_occluded: false,
1416        }
1417    }
1418}
1419
1420pub type CompositorSurfaceTransform = ScaleOffset;
1427
1428#[repr(C)]
1429#[cfg_attr(feature = "capture", derive(Serialize))]
1430#[cfg_attr(feature = "replay", derive(Deserialize))]
1431#[derive(PartialEq, Copy, Clone, Debug)]
1432pub struct ClipRadius {
1433    pub top_left: i32,
1434    pub top_right: i32,
1435    pub bottom_left: i32,
1436    pub bottom_right: i32,
1437}
1438
1439impl ClipRadius {
1440    pub const EMPTY: ClipRadius = ClipRadius { top_left: 0, top_right: 0, bottom_left: 0, bottom_right: 0 };
1441}
1442
1443pub trait Compositor {
1447    fn create_surface(
1449        &mut self,
1450        device: &mut Device,
1451        id: NativeSurfaceId,
1452        virtual_offset: DeviceIntPoint,
1453        tile_size: DeviceIntSize,
1454        is_opaque: bool,
1455    );
1456
1457    fn create_external_surface(
1462        &mut self,
1463        device: &mut Device,
1464        id: NativeSurfaceId,
1465        is_opaque: bool,
1466    );
1467
1468    fn create_backdrop_surface(
1470        &mut self,
1471        device: &mut Device,
1472        id: NativeSurfaceId,
1473        color: ColorF,
1474    );
1475
1476    fn destroy_surface(
1483        &mut self,
1484        device: &mut Device,
1485        id: NativeSurfaceId,
1486    );
1487
1488    fn create_tile(
1490        &mut self,
1491        device: &mut Device,
1492        id: NativeTileId,
1493    );
1494
1495    fn destroy_tile(
1497        &mut self,
1498        device: &mut Device,
1499        id: NativeTileId,
1500    );
1501
1502    fn attach_external_image(
1507        &mut self,
1508        device: &mut Device,
1509        id: NativeSurfaceId,
1510        external_image: ExternalImageId
1511    );
1512
1513    fn invalidate_tile(
1518        &mut self,
1519        _device: &mut Device,
1520        _id: NativeTileId,
1521        _valid_rect: DeviceIntRect
1522    ) {}
1523
1524    fn bind(
1536        &mut self,
1537        device: &mut Device,
1538        id: NativeTileId,
1539        dirty_rect: DeviceIntRect,
1540        valid_rect: DeviceIntRect,
1541    ) -> NativeSurfaceInfo;
1542
1543    fn unbind(
1546        &mut self,
1547        device: &mut Device,
1548    );
1549
1550    fn begin_frame(&mut self, device: &mut Device);
1552
1553    fn add_surface(
1563        &mut self,
1564        device: &mut Device,
1565        id: NativeSurfaceId,
1566        transform: CompositorSurfaceTransform,
1567        clip_rect: DeviceIntRect,
1568        image_rendering: ImageRendering,
1569        rounded_clip_rect: DeviceIntRect,
1570        rounded_clip_radii: ClipRadius,
1571    );
1572
1573    fn start_compositing(
1580        &mut self,
1581        _device: &mut Device,
1582        _clear_color: ColorF,
1583        _dirty_rects: &[DeviceIntRect],
1584        _opaque_rects: &[DeviceIntRect],
1585    ) {}
1586
1587    fn end_frame(&mut self, device: &mut Device);
1591
1592    fn enable_native_compositor(&mut self, device: &mut Device, enable: bool);
1594
1595    fn deinit(&mut self, device: &mut Device);
1597
1598    fn get_capabilities(&self, device: &mut Device) -> CompositorCapabilities;
1602
1603    fn get_window_visibility(&self, device: &mut Device) -> WindowVisibility;
1604}
1605
1606#[derive(Debug)]
1609pub struct CompositorInputLayer {
1610    pub offset: DeviceIntPoint,
1612    pub clip_rect: DeviceIntRect,
1614    pub usage: CompositorSurfaceUsage,
1616    pub is_opaque: bool,
1618}
1619
1620#[derive(Debug)]
1623pub struct CompositorInputConfig<'a> {
1624    pub enable_screenshot: bool,
1625    pub layers: &'a [CompositorInputLayer],
1626}
1627
1628pub trait LayerCompositor {
1631    fn begin_frame(
1634        &mut self,
1635        input: &CompositorInputConfig,
1636    ) -> bool;
1637
1638    fn bind_layer(
1641        &mut self,
1642        index: usize,
1643        dirty_rects: &[DeviceIntRect],
1644    );
1645
1646    fn present_layer(
1648        &mut self,
1649        index: usize,
1650        dirty_rects: &[DeviceIntRect],
1651    );
1652
1653    fn add_surface(
1654        &mut self,
1655        index: usize,
1656        transform: CompositorSurfaceTransform,
1657        clip_rect: DeviceIntRect,
1658        image_rendering: ImageRendering,
1659    );
1660
1661    fn end_frame(&mut self);
1663
1664    fn get_window_properties(&self) -> WindowProperties;
1666}
1667
1668#[repr(C)]
1670#[derive(Copy, Clone)]
1671pub struct MappedTileInfo {
1672    pub data: *mut c_void,
1673    pub stride: i32,
1674}
1675
1676#[repr(C)]
1678pub struct SWGLCompositeSurfaceInfo {
1679    pub yuv_planes: u32,
1682    pub textures: [u32; 3],
1684    pub color_space: YuvRangedColorSpace,
1686    pub color_depth: ColorDepth,
1688    pub size: DeviceIntSize,
1690}
1691
1692pub trait MappableCompositor: Compositor {
1694    fn map_tile(
1699        &mut self,
1700        device: &mut Device,
1701        id: NativeTileId,
1702        dirty_rect: DeviceIntRect,
1703        valid_rect: DeviceIntRect,
1704    ) -> Option<MappedTileInfo>;
1705
1706    fn unmap_tile(&mut self, device: &mut Device);
1709
1710    fn lock_composite_surface(
1711        &mut self,
1712        device: &mut Device,
1713        ctx: *mut c_void,
1714        external_image_id: ExternalImageId,
1715        composite_info: *mut SWGLCompositeSurfaceInfo,
1716    ) -> bool;
1717    fn unlock_composite_surface(&mut self, device: &mut Device, ctx: *mut c_void, external_image_id: ExternalImageId);
1718}
1719
1720pub trait PartialPresentCompositor {
1725    fn set_buffer_damage_region(&mut self, rects: &[DeviceIntRect]);
1730}
1731
1732#[cfg_attr(feature = "capture", derive(Serialize))]
1734#[cfg_attr(feature = "replay", derive(Deserialize))]
1735struct Occluder {
1736    z_id: ZBufferId,
1737    world_rect: WorldIntRect,
1738}
1739
1740#[derive(Debug)]
1742enum OcclusionEventKind {
1743    Begin,
1744    End,
1745}
1746
1747#[derive(Debug)]
1749struct OcclusionEvent {
1750    y: i32,
1751    x_range: ops::Range<i32>,
1752    kind: OcclusionEventKind,
1753}
1754
1755impl OcclusionEvent {
1756    fn new(y: i32, kind: OcclusionEventKind, x0: i32, x1: i32) -> Self {
1757        OcclusionEvent {
1758            y,
1759            x_range: ops::Range {
1760                start: x0,
1761                end: x1,
1762            },
1763            kind,
1764        }
1765    }
1766}
1767
1768pub struct OccludersScratchBuffers {
1772    events: FrameVec<OcclusionEvent>,
1773    active: FrameVec<ops::Range<i32>>,
1774}
1775
1776impl Default for OccludersScratchBuffers {
1777    fn default() -> Self {
1778        OccludersScratchBuffers {
1779            events: FrameVec::new_in(FrameAllocator::fallback()),
1780            active: FrameVec::new_in(FrameAllocator::fallback()),
1781        }
1782    }
1783}
1784
1785#[cfg_attr(feature = "capture", derive(Serialize))]
1789#[cfg_attr(feature = "replay", derive(Deserialize))]
1790pub struct Occluders {
1791    occluders: FrameVec<Occluder>,
1792
1793    #[cfg_attr(any(feature = "capture", feature = "replay"), serde(skip))]
1795    scratch: OccludersScratchBuffers,
1796}
1797
1798impl Occluders {
1799    fn new(memory: &FrameMemory) -> Self {
1800        Occluders {
1801            occluders: memory.new_vec(),
1802            scratch: OccludersScratchBuffers {
1803                events: memory.new_vec(),
1804                active: memory.new_vec(),    
1805            }
1806        }
1807    }
1808
1809    fn push(&mut self, world_rect: WorldIntRect, z_id: ZBufferId) {
1810        self.occluders.push(Occluder { world_rect, z_id });
1811    }
1812
1813    pub fn is_tile_occluded(
1816        &mut self,
1817        z_id: ZBufferId,
1818        world_rect: WorldRect,
1819    ) -> bool {
1820        let world_rect = world_rect.round().to_i32();
1834        let ref_area = world_rect.area();
1835
1836        let cover_area = self.area(z_id, &world_rect);
1838        debug_assert!(cover_area <= ref_area);
1839
1840        ref_area == cover_area
1842    }
1843
1844    fn area(
1847        &mut self,
1848        z_id: ZBufferId,
1849        clip_rect: &WorldIntRect,
1850    ) -> i32 {
1851        self.scratch.events.clear();
1856        self.scratch.active.clear();
1857
1858        let mut area = 0;
1859
1860        for occluder in &self.occluders {
1862            if occluder.z_id.0 < z_id.0 {
1864                if let Some(rect) = occluder.world_rect.intersection(clip_rect) {
1867                    let x0 = rect.min.x;
1868                    let x1 = x0 + rect.width();
1869                    self.scratch.events.push(OcclusionEvent::new(rect.min.y, OcclusionEventKind::Begin, x0, x1));
1870                    self.scratch.events.push(OcclusionEvent::new(rect.min.y + rect.height(), OcclusionEventKind::End, x0, x1));
1871                }
1872            }
1873        }
1874
1875        if self.scratch.events.is_empty() {
1877            return 0;
1878        }
1879
1880        self.scratch.events.sort_by_key(|e| e.y);
1882        let mut cur_y = self.scratch.events[0].y;
1883
1884        for event in &self.scratch.events {
1886            let dy = event.y - cur_y;
1888
1889            if dy != 0 && !self.scratch.active.is_empty() {
1891                assert!(dy > 0);
1892
1893                self.scratch.active.sort_by_key(|i| i.start);
1895                let mut query = 0;
1896                let mut cur = self.scratch.active[0].start;
1897
1898                for interval in &self.scratch.active {
1900                    cur = interval.start.max(cur);
1901                    query += (interval.end - cur).max(0);
1902                    cur = cur.max(interval.end);
1903                }
1904
1905                area += query * dy;
1907            }
1908
1909            match event.kind {
1911                OcclusionEventKind::Begin => {
1912                    self.scratch.active.push(event.x_range.clone());
1913                }
1914                OcclusionEventKind::End => {
1915                    let index = self.scratch.active.iter().position(|i| *i == event.x_range).unwrap();
1916                    self.scratch.active.remove(index);
1917                }
1918            }
1919
1920            cur_y = event.y;
1921        }
1922
1923        area
1924    }
1925}