/* 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::{BorderRadius, ClipMode, ColorF}; use api::{ImageRendering, RepeatMode, PrimitiveFlags}; use api::{FillRule, POLYGON_CLIP_VERTEX_MAX}; use api::units::*; use euclid::{SideOffsets2D, Size2D}; use malloc_size_of::MallocSizeOf; usecrate::clip::ClipLeafId; usecrate::quad::QuadTileClassifier; usecrate::renderer::{GpuBufferAddress, GpuBufferHandle, GpuBufferWriterF}; usecrate::segment::EdgeMask; usecrate::border::BorderSegmentCacheKey; usecrate::debug_item::{DebugItem, DebugMessage}; usecrate::debug_colors; use glyph_rasterizer::GlyphKey; usecrate::gpu_types::{BrushFlags, BrushSegmentGpuData, QuadSegment}; usecrate::intern; usecrate::picture::{PictureInstance, PictureScratch}; usecrate::render_task_graph::RenderTaskId; usecrate::resource_cache::ImageProperties; use std::{hash, u32, usize}; usecrate::util::Recycler; usecrate::internal_types::{FastHashSet, LayoutPrimitiveInfo}; usecrate::visibility::PrimitiveDrawHeader;
use backdrop::{BackdropCaptureDataHandle, BackdropRenderDataHandle, BackdropRenderScratch}; use borders::{ImageBorderDataHandle, ImageBorderScratch, NormalBorderDataHandle, NormalBorderScratch}; use gradient::{LinearGradientDataHandle, RadialGradientDataHandle, ConicGradientDataHandle}; use image::{ImageDataHandle, ImageScratch, VisibleImageTile, YuvImageDataHandle}; use line_dec::LineDecorationDataHandle; use picture::PictureDataHandle; use rectangle::RectangleDataHandle; use text_run::{TextRunDataHandle, TextRunScratch}; usecrate::box_shadow::BoxShadowDataHandle;
/// For external images, it's not possible to know the /// UV coords of the image (or the image data itself) /// until the render thread receives the frame and issues /// callbacks to the client application. For external /// images that are visible, a DeferredResolve is created /// that is stored in the frame. This allows the render /// thread to iterate this list and update any changed /// texture data and update the UV rect. Any filtering /// is handled externally for NativeTexture external /// images. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pubstruct DeferredResolve { pub handle: GpuBufferHandle, pub image_properties: ImageProperties, pub rendering: ImageRendering, pub is_composited: bool,
}
/// To create a fixed-size representation of a polygon, we use a fixed /// number of points. Our initialization method restricts us to values /// <= 32. If our constant POLYGON_CLIP_VERTEX_MAX is > 32, the Rust /// compiler will complain. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[derive(Copy, Debug, Clone, Hash, MallocSizeOf, PartialEq)] pubstruct PolygonKey { pub point_count: u8, pub points: [PointKey; POLYGON_CLIP_VERTEX_MAX], pub fill_rule: FillRule,
}
impl PolygonKey { pubfn new(
points_layout: &Vec<LayoutPoint>,
fill_rule: FillRule,
) -> Self { // We have to fill fixed-size arrays with data from a Vec. // We'll do this by initializing the arrays to known-good // values then overwriting those values as long as our // iterator provides values. letmut points: [PointKey; POLYGON_CLIP_VERTEX_MAX] = [PointKey { x: 0.0, y: 0.0}; POLYGON_CLIP_VERTEX_MAX];
letmut point_count: u8 = 0; for (src, dest) in points_layout.iter().zip(points.iter_mut()) {
*dest = (*src as LayoutPoint).into();
point_count = point_count + 1;
}
/// A hashable point for using as a key during primitive interning. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)] pubstruct PointKey { pub x: f32, pub y: f32,
}
#[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[derive(MallocSizeOf)] #[derive(Debug)] pubstruct PrimTemplateCommonData { pub flags: PrimitiveFlags, pub opacity: PrimitiveOpacity, /// Address of the per-primitive data in the GPU cache. /// /// TODO: This is only valid during the current frame and must /// be overwritten each frame. We should move this out of the /// common data to avoid accidental reuse. pub gpu_buffer_address: GpuBufferAddress, pub aligned_aa_edges: EdgeMask, pub transformed_aa_edges: EdgeMask,
}
/// Information about how to cache a border segment, /// along with the current render task cache entry. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[derive(Debug, MallocSizeOf)] pubstruct BorderSegmentInfo { pub local_task_size: LayoutSize, pub cache_key: BorderSegmentCacheKey,
}
/// Represents the visibility state of a segment (wrt clip masks). #[cfg_attr(feature = "capture", derive(Serialize))] #[derive(Debug, Clone)] pubenum ClipMaskKind { /// The segment has a clip mask, specified by the render task.
Mask(RenderTaskId), /// The segment has no clip mask.
None, /// The segment is made invisible / clipped completely.
Clipped,
}
impl ClipData { pubfn rounded_rect(size: LayoutSize, radii: &BorderRadius, mode: ClipMode) -> ClipData { // TODO(gw): For simplicity, keep most of the clip GPU structs the // same as they were, even though the origin is now always // zero, since they are in the clip's local space. In future, // we could reduce the GPU cache size of ClipData. let rect = LayoutRect::from_size(size);
pubfn uniform(size: LayoutSize, radius: f32, mode: ClipMode) -> ClipData { // TODO(gw): For simplicity, keep most of the clip GPU structs the // same as they were, even though the origin is now always // zero, since they are in the clip's local space. In future, // we could reduce the GPU cache size of ClipData. let rect = LayoutRect::from_size(size);
#[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] pubenum PrimitiveKind { /// Direct reference to a Picture
Picture { /// Handle to the common interned data for this primitive.
data_handle: PictureDataHandle,
pic_index: PictureIndex,
}, /// A run of glyphs, with associated font parameters.
TextRun { /// Handle to the common interned data for this primitive.
data_handle: TextRunDataHandle,
}, /// A line decoration. cache_handle refers to a cached render /// task handle, if this line decoration is not a simple solid.
LineDecoration { /// Handle to the common interned data for this primitive.
data_handle: LineDecorationDataHandle,
},
NormalBorder { /// Handle to the common interned data for this primitive.
data_handle: NormalBorderDataHandle,
},
ImageBorder { /// Handle to the common interned data for this primitive.
data_handle: ImageBorderDataHandle,
},
Rectangle { /// Handle to the common interned data for this primitive.
data_handle: RectangleDataHandle,
},
YuvImage { /// Handle to the common interned data for this primitive.
data_handle: YuvImageDataHandle,
},
Image { /// Handle to the common interned data for this primitive.
data_handle: ImageDataHandle,
},
LinearGradient { /// Handle to the common interned data for this primitive.
data_handle: LinearGradientDataHandle,
},
RadialGradient { /// Handle to the common interned data for this primitive.
data_handle: RadialGradientDataHandle,
},
ConicGradient { /// Handle to the common interned data for this primitive.
data_handle: ConicGradientDataHandle,
}, /// Render a portion of a specified backdrop.
BackdropCapture {
data_handle: BackdropCaptureDataHandle,
},
BackdropRender {
data_handle: BackdropRenderDataHandle,
pic_index: PictureIndex,
},
BoxShadow {
data_handle: BoxShadowDataHandle,
},
}
impl PrimitiveKind { pubfn as_pic(&self) -> PictureIndex { matchself {
PrimitiveKind::Picture { pic_index, .. } => *pic_index,
_ => panic!("bug: as_pic called on a prim that is not a picture"),
}
}
}
#[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] pubstruct PrimitiveInstance { /// Identifies the kind of primitive this /// instance is, and references to where /// the relevant information for the primitive /// can be found. pub kind: PrimitiveKind,
/// All information and state related to clip(s) for this primitive pub clip_leaf_id: ClipLeafId,
/// Local-space rect of the primitive (origin + size), as authored by the /// display list (not snapped to the device pixel grid). Carries both the /// position and the per-instance size; the latter used to live on /// `PrimTemplateCommonData.prim_size` but is per-instance now so that the /// intern key can deduplicate across differently-sized instances of the /// same prim shape. pub unsnapped_prim_rect: LayoutRect,
}
pubtype GlyphKeyStorage = storage::Storage<GlyphKey>; pubtype SegmentStorage = storage::Storage<BrushSegment>; pubtype SegmentsRange = storage::Range<BrushSegment>; pubtype SegmentInstanceStorage = storage::Storage<BrushSegmentation>; pubtype SegmentInstanceIndex = storage::Index<BrushSegmentation>; /// Per-frame scratch storage. All fields are cleared every frame in /// `begin_frame`. Anything written here lives only for the current frame. #[cfg_attr(feature = "capture", derive(Serialize))] pubstruct PrimitiveFrameScratch { /// Per-frame draw headers, one entry per `PrimitiveInstance`. /// Resized to `prim_instances.len()` at frame start and identity- /// indexed by `PrimitiveInstanceIndex.0` (a follow-up will switch /// this to push-per-draw with `Index<PrimitiveDrawHeader>`). Holds /// visibility state, clip chain and clip-task index for each /// visible primitive. pub draws: Vec<PrimitiveDrawHeader>,
/// Per-frame scratch for NormalBorder primitives. pub normal_border: storage::Storage<NormalBorderScratch>,
/// Per-frame scratch for BackdropRender primitives. Captures the /// source sub-graph render task id at prepare time so batch reads /// don't reach into the source Picture's per-frame state. pub backdrop_render: storage::Storage<BackdropRenderScratch>,
/// Per-frame scratch for Picture primitives. Holds the picture's /// primary/secondary render task ids and any per-composite-mode /// extra GPU buffer addresses. Indexed by `scratch_handle` on /// `PrimitiveKind::Picture`. pub pictures: storage::Storage<PictureScratch>,
/// Per-frame scratch for Image primitives. Holds the source render /// task (or a Range of per-tile tasks for tiled images), normalized- /// uvs flag, and image adjustment. pub images: storage::Storage<ImageScratch>,
/// Per-tile entries for tiled Image primitives. Each `ImageScratch` /// holds a `Range` into this storage. pub visible_image_tiles: storage::Storage<VisibleImageTile>,
/// Per-frame scratch for TextRun primitives. Holds the per-frame /// font snapshot, glyph-key range, snapping offset, and raster /// scale for each visible text run. pub text_runs: storage::Storage<TextRunScratch>,
/// Per-frame storage for glyph keys allocated by visible text /// runs. Each `TextRunScratch` holds a `Range` into this storage. /// Used to be on `PrimitiveSceneCache` (memoized across frames); /// graduated to per-frame here so the scene buffer cannot grow /// unbounded between scene rebuilds. pub glyph_keys: GlyphKeyStorage,
/// A list of brush segments built each frame for the segmented /// brush primitives (Rectangle, YuvImage, non-tiled Image). The /// segment builder runs every frame for every visible segmented /// prim. pub segments: SegmentStorage,
/// A list of per-prim brush segmentation records (segments range /// + GPU buffer address). Each PrimitiveDrawHeader.segment_instance_index /// holds an index into this storage, or UNUSED for non-segmented /// prims. pub segment_instances: SegmentInstanceStorage,
/// Trailing-array store for per-segment cached render-task ids /// referenced by NormalBorderScratch entries. pub border_task_ids: storage::Storage<RenderTaskId>,
/// Per-frame BorderSegmentInfo arena. NormalBorder builds its /// edge/corner segment list each frame against the prim's size and /// stores the resulting range on `NormalBorderScratch`. pub border_segments: storage::Storage<BorderSegmentInfo>,
/// Per-frame scratch for ImageBorder primitives. Holds the range /// into `segments` for the nine-patch brush segments built each /// frame against the prim's size. pub image_border: storage::Storage<ImageBorderScratch>,
/// Contains a list of clip mask instance parameters /// per segment generated. pub clip_mask_instances: Vec<ClipMaskKind>,
/// List of debug display items for rendering. Cleared in `begin_frame` /// and refilled in `end_frame` (where retained `messages` are flushed /// into it for on-screen display). pub debug_items: Vec<DebugItem>,
/// Set of sub-graphs that are required, determined during visibility pass pub required_sub_graphs: FastHashSet<PictureIndex>,
/// Temporary buffers for building segments in to during prepare pass pub quad_direct_segments: Vec<QuadSegment>, pub quad_indirect_segments: Vec<QuadSegment>,
}
// Clear the clip mask tasks for the beginning of the frame. Append // a single kind representing no clip mask, at the ClipTaskIndex::INVALID // location. self.clip_mask_instances.clear(); self.clip_mask_instances.push(ClipMaskKind::None); self.quad_direct_segments.clear(); self.quad_indirect_segments.clear();
self.required_sub_graphs.clear();
self.debug_items.clear();
}
}
/// Per-scene cache. Now empty — the originally memoized fields have /// migrated to per-frame storage. Kept as a placeholder for any future /// scene-stable state and so the lifetime invariant on /// PrimitiveScratchBuffer (frame / scene / retained) remains visible /// at the type level; a follow-up may drop it entirely. #[cfg_attr(feature = "capture", derive(Serialize))] #[derive(Default)] pubstruct PrimitiveSceneCache {}
/// State that lives strictly longer than a single frame *and* is not tied /// to scene lifetime. These fields manage their own trim/eviction policy /// rather than being cleared by `begin_frame` or `recycle`. #[cfg_attr(feature = "capture", derive(Serialize))] pubstruct PrimitiveRetained { /// Debug log of recent messages. Trimmed by time/count in /// `PrimitiveScratchBuffer::end_frame` and flushed into /// `PrimitiveFrameScratch::debug_items` for display.
messages: Vec<DebugMessage>,
/// A retained classifier for checking which segments of a tiled /// primitive need a mask / are clipped / can be rendered directly. pub quad_tile_classifier: QuadTileClassifier,
}
/// Contains various vecs of data that is used only during frame building, /// where we want to recycle the memory each new display list, to avoid /// constantly re-allocating and moving memory around. Written during /// primitive preparation, and read during batching. /// /// Storage is partitioned by lifetime: `frame` is per-frame (cleared in /// `begin_frame`), `scene` is per-scene (recycled on scene rebuild), and /// `retained` lives across both with its own trim policy. #[cfg_attr(feature = "capture", derive(Serialize))] #[derive(Default)] pubstruct PrimitiveScratchBuffer { pub frame: PrimitiveFrameScratch, pub scene: PrimitiveSceneCache, pub retained: PrimitiveRetained,
}
/// Trait for primitives that are directly internable. /// see SceneBuilder::add_primitive<P> pubtrait InternablePrimitive: intern::Internable<InternData = ()> + Sized { /// Build a new key from self with `info`. fn into_key( self,
info: &LayoutPrimitiveInfo,
) -> Self::Key;
#[test] #[cfg(target_pointer_width = "64")] fn test_struct_sizes() { use std::mem; // The sizes of these structures are critical for performance on a number of // talos stress tests. If you get a failure here on CI, there's two possibilities: // (a) You made a structure smaller than it currently is. Great work! Update the // test expectations and move on. // (b) You made a structure larger. This is not necessarily a problem, but should only // be done with care, and after checking if talos performance regresses badly.
assert_eq!(mem::size_of::<PrimitiveInstance>(), 48, "PrimitiveInstance size changed");
assert_eq!(mem::size_of::<PrimitiveKind>(), 24, "PrimitiveKind size changed");
}
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.