Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
//! Invalidation tracking and dirty region management
//!
//! This module contains types and logic for tracking dirty regions and
//! dependencies used to determine what needs to be redrawn each frame.
pub mod compare;
pub mod quadtree;
pub mod cached_surface;
use api::units::*;
use crate::spatial_tree::{SpatialTree, SpatialNodeIndex};
use crate::space::SpaceMapper;
use crate::util::MaxRect;
/// Represents the dirty region of a tile cache picture, relative to a
/// "visibility" spatial node. At the moment the visibility node is
/// world space, but the plan is to switch to raster space.
///
/// The plan is to move away from these world space representation and
/// compute dirty regions in raster space instead.
#[derive(Clone)]
pub struct DirtyRegion {
/// The overall dirty rect, a combination of dirty_rects
pub combined: VisRect,
/// The corrdinate space used to do clipping, visibility, and
/// dirty rect calculations.
pub visibility_spatial_node: SpatialNodeIndex,
/// Spatial node of the picture this region represents.
local_spatial_node: SpatialNodeIndex,
}
impl DirtyRegion {
/// Construct a new dirty region tracker.
pub fn new(
visibility_spatial_node: SpatialNodeIndex,
local_spatial_node: SpatialNodeIndex,
) -> Self {
DirtyRegion {
combined: VisRect::zero(),
visibility_spatial_node,
local_spatial_node,
}
}
/// Reset the dirty regions back to empty
pub fn reset(
&mut self,
visibility_spatial_node: SpatialNodeIndex,
local_spatial_node: SpatialNodeIndex,
) {
self.combined = VisRect::zero();
self.visibility_spatial_node = visibility_spatial_node;
self.local_spatial_node = local_spatial_node;
}
/// Add a dirty region to the tracker. Returns the visibility mask that corresponds to
/// this region in the tracker.
pub fn add_dirty_region(
&mut self,
rect_in_pic_space: PictureRect,
spatial_tree: &SpatialTree,
) {
let map_pic_to_raster = SpaceMapper::new_with_target(
self.visibility_spatial_node,
self.local_spatial_node,
VisRect::max_rect(),
spatial_tree,
);
let raster_rect = map_pic_to_raster
.map(&rect_in_pic_space)
.expect("bug");
// Include this in the overall dirty rect
self.combined = self.combined.union(&raster_rect);
}
}
/// Debugging information about why a tile was invalidated
#[derive(Debug,Clone)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum InvalidationReason {
/// The background color changed
BackgroundColor,
/// The opaque state of the backing native surface changed
SurfaceOpacityChanged,
/// There was no backing texture (evicted or never rendered)
NoTexture,
/// There was no backing native surface (never rendered, or recreated)
NoSurface,
/// The primitive count in the dependency list was different
PrimCount,
/// The content of one of the primitives was different
Content,
// The compositor type changed
CompositorKindChanged,
// The valid region of the tile changed
ValidRectChanged,
// The overall scale of the picture cache changed
ScaleChanged,
// The content of the sampling surface changed
SurfaceContentChanged,
}
/// The result of a primitive dependency comparison. Size is a u8
/// since this is a hot path in the code, and keeping the data small
/// is a performance win.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[repr(u8)]
pub enum PrimitiveCompareResult {
/// Primitives match
Equal,
/// Something in the PrimitiveDescriptor was different
Descriptor,
/// The clip node content or spatial node changed
Clip,
/// The value of the transform changed
Transform,
/// An image dependency was dirty
Image,
/// The value of an opacity binding changed
OpacityBinding,
/// The value of a color binding changed
ColorBinding,
}