/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::ColorF; use api::PropertyBindingId; use api::units::*; use smallvec::SmallVec; usecrate::composite::CompositeState; usecrate::internal_types::{FastHashMap, FrameId}; usecrate::invalidation::compare::ImageDependency; usecrate::invalidation::compare::{ColorBinding, OpacityBinding, OpacityBindingInfo, PrimitiveComparisonKey}; usecrate::invalidation::compare::{PrimitiveComparer, PrimitiveDependency, ColorBindingInfo}; usecrate::invalidation::{InvalidationReason, PrimitiveCompareResult, quadtree::TileNode}; usecrate::invalidation::vert_buffer::{CornersCache, VertRange}; usecrate::intern::ItemUid; usecrate::picture::{PictureCompositeMode, SurfaceIndex, clampf}; usecrate::print_tree::PrintTreePrinter; usecrate::resource_cache::ResourceCache; usecrate::space::SpaceMapper; usecrate::visibility::FrameVisibilityContext; use peek_poke::poke_into_vec; use std::mem;
/// Setup state before primitive dependency calculation. pubfn pre_update(
&mutself,
background_color: Option<ColorF>,
local_tile_rect: PictureRect,
frame_id: FrameId,
is_visible: bool,
) { // TODO(gw): This is a hack / fix for Box2D::union in euclid not working with // zero sized rect accumulation. Once that lands, we'll revert this // to be zero. self.local_valid_rect = PictureBox2D::new(
PicturePoint::new( 1.0e32, 1.0e32),
PicturePoint::new(-1.0e32, -1.0e32),
); self.invalidation_reason = None; self.sub_graphs.clear();
// If the tile isn't visible, early exit, skipping the normal set up to // validate dependencies. Instead, we will only compare the current tile // dependencies the next time it comes into view. if !is_visible { return;
}
// Clear any dependencies so that when we rebuild them we // can compare if the tile has the same content.
mem::swap(
&mutself.current_descriptor,
&mutself.prev_descriptor,
); self.current_descriptor.clear(); self.root.clear(local_tile_rect);
pubfn add_prim_dependency(
&mutself,
info: &PrimitiveDependencyInfo,
corners_cache: &CornersCache,
prim_clamp_to_tile: bool,
local_raster_rect: &RasterRect,
local_tile_rect: PictureRect,
) { // Incorporate the bounding rect of the primitive in the local valid rect // for this tile. This is used to minimize the size of the scissor rect // during rasterization and the draw rect during composition of partial tiles. self.local_valid_rect = self.local_valid_rect.union(&info.prim_clip_box);
// TODO(gw): The prim_clip_rect can be impacted by the clip rect of the display port, // which can cause invalidations when a new display list with changed // display port is received. To work around this, clamp the prim clip rect // to the tile boundaries - if the clip hasn't affected the tile, then the // changed clip can't affect the content of the primitive on this tile. // In future, we could consider supplying the display port clip from Gecko // in a different way (e.g. as a scroll frame clip) which still provides // the desired clip for checkerboarding, but doesn't require this extra // work below.
// TODO(gw): This is a hot part of the code - we could probably optimize further by: // - Using min/max instead of clamps below (if we guarantee the rects are well formed)
let pmin = local_tile_rect.min; let pmax = local_tile_rect.max;
// Push raster-space corners into this tile's vert_data, clamping if requested. let vert_data = &mutself.current_descriptor.vert_data; let (prim_corners, coverage_corners) = if prim_clamp_to_tile {
(
corners_cache.push_verts_clamped(info.prim_scratch, local_raster_rect, vert_data),
corners_cache.push_verts_clamped(info.cov_scratch, local_raster_rect, vert_data),
)
} else {
(
corners_cache.push_verts(info.prim_scratch, vert_data),
corners_cache.push_verts(info.cov_scratch, vert_data),
)
};
// Update the tile descriptor, used for tile comparison during scene swaps. let prim_index = PrimitiveDependencyIndex(self.current_descriptor.prims.len() as u32);
// Encode the deps for this primitive in the `dep_data` byte buffer. let dep_offset = self.current_descriptor.dep_data.len() as u32; letmut dep_count = 0;
/// Invalidate a tile based on change in content. This /// must be called even if the tile is not currently /// visible on screen. We might be able to improve this /// later by changing how ComparableVec is used. pubfn update_content_validity(
&mutself,
ctx: &TileUpdateDirtyContext,
state: &mut TileUpdateDirtyState,
frame_context: &FrameVisibilityContext,
) { // Check if the contents of the primitives, clips, and // other dependencies are the same.
state.compare_cache.clear(); letmut invalidation_reason = None; let dirty_rect = self.update_dirty_rects(
ctx,
state,
&mut invalidation_reason,
frame_context,
);
if !dirty_rect.is_empty() { self.invalidate(
Some(dirty_rect),
invalidation_reason.expect("bug: no invalidation_reason")
);
} if ctx.invalidate_all { self.invalidate(None, InvalidationReason::ScaleChanged);
} // TODO(gw): We can avoid invalidating the whole tile in some cases here, // but it should be a fairly rare invalidation case. ifself.current_descriptor.local_valid_rect != self.prev_descriptor.local_valid_rect { self.invalidate(None, InvalidationReason::ValidRectChanged);
state.composite_state.dirty_rects_are_valid = false;
}
}
/// Invalidate this tile. If `invalidation_rect` is None, the entire /// tile is invalidated. pubfn invalidate(
&mutself,
invalidation_rect: Option<PictureRect>,
reason: InvalidationReason,
) { self.is_valid = false;
// Immutable context passed to picture cache tiles during update_dirty_and_valid_rects pubstruct TileUpdateDirtyContext<'a> { /// Maps from picture cache coords -> world space coords. pub pic_to_world_mapper: SpaceMapper<PicturePixel, WorldPixel>,
/// Global scale factor from world -> device pixels. pub global_device_pixel_scale: DevicePixelScale,
/// Information about opacity bindings from the picture cache. pub opacity_bindings: &'a FastHashMap<PropertyBindingId, OpacityBindingInfo>,
/// Information about color bindings from the picture cache. pub color_bindings: &'a FastHashMap<PropertyBindingId, ColorBindingInfo>,
/// The local rect of the overall picture cache pub local_rect: PictureRect,
/// If true, the scale factor of the root transform for this picture /// cache changed, so we need to invalidate the tile and re-render. pub invalidate_all: bool,
}
// Mutable state passed to picture cache tiles during update_dirty_and_valid_rects pubstruct TileUpdateDirtyState<'a> { /// Allow access to the texture cache for requesting tiles pub resource_cache: &'a mut ResourceCache,
/// Current configuration and setup for compositing all the picture cache tiles in renderer. pub composite_state: &'a mut CompositeState,
/// A cache of comparison results to avoid re-computation during invalidation. pub compare_cache: &'a mut FastHashMap<PrimitiveComparisonKey, PrimitiveCompareResult>,
}
/// Information about the dependencies of a single primitive instance. /// Built once per primitive (outside the tile loop); passed to each tile's /// add_prim_dependency, which does the per-tile clamping and vert-data push. pubstruct PrimitiveDependencyInfo { /// The (conservative) clipped area in picture space this primitive occupies. /// Used for local_valid_rect accumulation and quadtree binning. pub prim_clip_box: PictureBox2D, /// Image keys this primitive depends on. pub images: SmallVec<[ImageDependency; 8]>, /// Opacity bindings this primitive depends on. pub opacity_bindings: SmallVec<[OpacityBinding; 4]>, /// Color binding this primitive depends on. pub color_binding: Option<ColorBinding>, /// Intern uid for this primitive instance. Stable across frames and across /// content-side scroll events: scene building normalises each primitive's /// prim_rect by the accumulated external_scroll_offset before interning, /// so the key (and therefore this uid) does not change when the scroll /// position changes. If external_scroll_offset is ever removed, this /// stability guarantee would need to be preserved by another mechanism. pub prim_uid: ItemUid, /// Scratch range for the primitive's rect corners in raster space (unquantized). /// Quantized into per-tile vert_data inside add_prim_dependency. pub prim_scratch: VertRange, /// Scratch range for the coverage rect corners (prim ∩ clip) in raster space. /// Tracked separately from prim_scratch because merging them into a single /// intersection loses prim-rect information: a UV-mapped primitive whose /// rect changes size while the clip keeps the visible region constant would /// produce an unchanged intersection yet sample different source pixels. /// Using coverage_rect (rather than the raw local_clip_rect) avoids /// spurious invalidations when the clip changes outside the prim extent. pub cov_scratch: VertRange, /// Per-clip data: (clip intern uid, scratch range for clip corners). /// The uid covers the clip's shape/mode; position is captured in the scratch range. pub clips: SmallVec<[(ItemUid, VertRange); 4]>,
}
/// Information about a primitive that is a dependency for a cached surface. #[derive(Debug, Clone)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pubstruct PrimitiveDescriptor { /// Picture-space bounds, clamped to tile boundary. Used for quadtree /// binning and local_valid_rect; not used for comparison. pub prim_clip_box: PictureBox2D, // TODO(gw): These two fields could be packed as a u24/u8 pub dep_offset: u32, pub dep_count: u32, /// Intern uid for this primitive. See PrimitiveDependencyInfo::prim_uid for the /// scroll-stability guarantee. pub prim_uid: ItemUid, /// Range into vert_data for this primitive's corners (local_prim_rect). pub prim_corners: VertRange, /// Range into vert_data for the coverage rect corners (prim ∩ clip). pub coverage_corners: VertRange,
}
/// An index into the prims array in a TileDescriptor. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pubstruct PrimitiveDependencyIndex(pub u32);
/// Uniquely describes the content of this cached surface, in a way that can be /// (reasonably) efficiently hashed and compared. #[cfg_attr(any(feature="capture",feature="replay"), derive(Clone))] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pubstruct CachedSurfaceDescriptor { /// List of primitive instance unique identifiers. The uid is guaranteed /// to uniquely describe the content of the primitive template, while /// the other parameters describe the clip chain and instance params. pub prims: Vec<PrimitiveDescriptor>,
/// Picture space rect that contains valid pixels region of this tile. pub local_valid_rect: PictureRect,
/// The last frame this tile had its dependencies updated (dependency updating is /// skipped if a tile is off-screen). pub last_updated_frame_id: FrameId,
/// Packed per-prim dependency information pub dep_data: Vec<u8>,
/// Per-tile quantized raster-space vert data. VertRanges stored in /// PrimitiveDescriptor and PrimitiveDependency::Clip index into this buffer. pub vert_data: Vec<i32>,
}
/// Print debug information about this tile descriptor to a tree printer. pubfn print(&self, pt: &mutdyncrate::print_tree::PrintTreePrinter) {
pt.new_level("current_descriptor".to_string());
pt.new_level("prims".to_string()); for prim in &self.prims {
pt.new_level(format!("prim uid={}", prim.prim_uid.get_uid()));
pt.add_item(format!("clip: p0={},{} p1={},{}",
prim.prim_clip_box.min.x,
prim.prim_clip_box.min.y,
prim.prim_clip_box.max.x,
prim.prim_clip_box.max.y,
));
pt.end_level();
}
pt.end_level();
pt.end_level();
}
/// Clear the dependency information for a tile, when the dependencies /// are being rebuilt. pubfn clear(&mutself) { self.local_valid_rect = PictureRect::zero(); self.prims.clear(); self.dep_data.clear(); self.vert_data.clear();
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.