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}