summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/src/internal_types.rs
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/wr/webrender/src/internal_types.rs')
-rw-r--r--gfx/wr/webrender/src/internal_types.rs761
1 files changed, 761 insertions, 0 deletions
diff --git a/gfx/wr/webrender/src/internal_types.rs b/gfx/wr/webrender/src/internal_types.rs
new file mode 100644
index 0000000000..c76b7d362d
--- /dev/null
+++ b/gfx/wr/webrender/src/internal_types.rs
@@ -0,0 +1,761 @@
+/* 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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use api::{ColorF, DocumentId, ExternalImageId, PrimitiveFlags, Parameter, RenderReasons};
+use api::{ImageFormat, NotificationRequest, Shadow, FilterOp, ImageBufferKind};
+use api::FramePublishId;
+use api::units::*;
+use api;
+use crate::render_api::DebugCommand;
+use crate::composite::NativeSurfaceOperation;
+use crate::device::TextureFilter;
+use crate::renderer::{FullFrameStats, PipelineInfo};
+use crate::gpu_cache::GpuCacheUpdateList;
+use crate::frame_builder::Frame;
+use crate::profiler::TransactionProfile;
+use crate::spatial_tree::SpatialNodeIndex;
+use crate::prim_store::PrimitiveInstanceIndex;
+use fxhash::FxHasher;
+use plane_split::BspSplitter;
+use smallvec::SmallVec;
+use std::{usize, i32};
+use std::collections::{HashMap, HashSet};
+use std::f32;
+use std::hash::BuildHasherDefault;
+use std::path::PathBuf;
+use std::sync::Arc;
+use std::time::{UNIX_EPOCH, SystemTime};
+use peek_poke::PeekPoke;
+
+#[cfg(any(feature = "capture", feature = "replay"))]
+use crate::capture::CaptureConfig;
+#[cfg(feature = "capture")]
+use crate::capture::ExternalCaptureImage;
+#[cfg(feature = "replay")]
+use crate::capture::PlainExternalImage;
+
+pub type FastHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
+pub type FastHashSet<K> = HashSet<K, BuildHasherDefault<FxHasher>>;
+
+#[derive(Copy, Clone, Hash, MallocSizeOf, PartialEq, PartialOrd, Debug, Eq, Ord, PeekPoke)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub struct FrameId(u64);
+
+impl FrameId {
+ /// Returns a FrameId corresponding to the first frame.
+ ///
+ /// Note that we use 0 as the internal id here because the current code
+ /// increments the frame id at the beginning of the frame, rather than
+ /// at the end, and we want the first frame to be 1. It would probably
+ /// be sensible to move the advance() call to after frame-building, and
+ /// then make this method return FrameId(1).
+ pub fn first() -> Self {
+ FrameId(0)
+ }
+
+ /// Returns the backing u64 for this FrameId.
+ pub fn as_u64(&self) -> u64 {
+ self.0
+ }
+
+ /// Advances this FrameId to the next frame.
+ pub fn advance(&mut self) {
+ self.0 += 1;
+ }
+
+ /// An invalid sentinel FrameId, which will always compare less than
+ /// any valid FrameId.
+ pub const INVALID: FrameId = FrameId(0);
+}
+
+impl Default for FrameId {
+ fn default() -> Self {
+ FrameId::INVALID
+ }
+}
+
+impl ::std::ops::Add<u64> for FrameId {
+ type Output = Self;
+ fn add(self, other: u64) -> FrameId {
+ FrameId(self.0 + other)
+ }
+}
+
+impl ::std::ops::Sub<u64> for FrameId {
+ type Output = Self;
+ fn sub(self, other: u64) -> FrameId {
+ assert!(self.0 >= other, "Underflow subtracting FrameIds");
+ FrameId(self.0 - other)
+ }
+}
+
+/// Identifier to track a sequence of frames.
+///
+/// This is effectively a `FrameId` with a ridealong timestamp corresponding
+/// to when advance() was called, which allows for more nuanced cache eviction
+/// decisions. As such, we use the `FrameId` for equality and comparison, since
+/// we should never have two `FrameStamps` with the same id but different
+/// timestamps.
+#[derive(Copy, Clone, Debug, MallocSizeOf)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub struct FrameStamp {
+ id: FrameId,
+ time: SystemTime,
+ document_id: DocumentId,
+}
+
+impl Eq for FrameStamp {}
+
+impl PartialEq for FrameStamp {
+ fn eq(&self, other: &Self) -> bool {
+ // We should not be checking equality unless the documents are the same
+ debug_assert!(self.document_id == other.document_id);
+ self.id == other.id
+ }
+}
+
+impl PartialOrd for FrameStamp {
+ fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
+ self.id.partial_cmp(&other.id)
+ }
+}
+
+impl FrameStamp {
+ /// Gets the FrameId in this stamp.
+ pub fn frame_id(&self) -> FrameId {
+ self.id
+ }
+
+ /// Gets the time associated with this FrameStamp.
+ pub fn time(&self) -> SystemTime {
+ self.time
+ }
+
+ /// Gets the DocumentId in this stamp.
+ pub fn document_id(&self) -> DocumentId {
+ self.document_id
+ }
+
+ pub fn is_valid(&self) -> bool {
+ // If any fields are their default values, the whole struct should equal INVALID
+ debug_assert!((self.time != UNIX_EPOCH && self.id != FrameId(0) && self.document_id != DocumentId::INVALID) ||
+ *self == Self::INVALID);
+ self.document_id != DocumentId::INVALID
+ }
+
+ /// Returns a FrameStamp corresponding to the first frame.
+ pub fn first(document_id: DocumentId) -> Self {
+ FrameStamp {
+ id: FrameId::first(),
+ time: SystemTime::now(),
+ document_id,
+ }
+ }
+
+ /// Advances to a new frame.
+ pub fn advance(&mut self) {
+ self.id.advance();
+ self.time = SystemTime::now();
+ }
+
+ /// An invalid sentinel FrameStamp.
+ pub const INVALID: FrameStamp = FrameStamp {
+ id: FrameId(0),
+ time: UNIX_EPOCH,
+ document_id: DocumentId::INVALID,
+ };
+}
+
+/// Custom field embedded inside the Polygon struct of the plane-split crate.
+#[derive(Copy, Clone, Debug)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+pub struct PlaneSplitAnchor {
+ pub spatial_node_index: SpatialNodeIndex,
+ pub instance_index: PrimitiveInstanceIndex,
+}
+
+impl PlaneSplitAnchor {
+ pub fn new(
+ spatial_node_index: SpatialNodeIndex,
+ instance_index: PrimitiveInstanceIndex,
+ ) -> Self {
+ PlaneSplitAnchor {
+ spatial_node_index,
+ instance_index,
+ }
+ }
+}
+
+impl Default for PlaneSplitAnchor {
+ fn default() -> Self {
+ PlaneSplitAnchor {
+ spatial_node_index: SpatialNodeIndex::INVALID,
+ instance_index: PrimitiveInstanceIndex(!0),
+ }
+ }
+}
+
+/// A concrete plane splitter type used in WebRender.
+pub type PlaneSplitter = BspSplitter<PlaneSplitAnchor>;
+
+/// An index into the scene's list of plane splitters
+#[derive(Debug, Copy, Clone)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+pub struct PlaneSplitterIndex(pub usize);
+
+/// An arbitrary number which we assume opacity is invisible below.
+const OPACITY_EPSILON: f32 = 0.001;
+
+/// Equivalent to api::FilterOp with added internal information
+#[derive(Clone, Debug, PartialEq)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub enum Filter {
+ Identity,
+ Blur {
+ width: f32,
+ height: f32,
+ should_inflate: bool,
+ },
+ Brightness(f32),
+ Contrast(f32),
+ Grayscale(f32),
+ HueRotate(f32),
+ Invert(f32),
+ Opacity(api::PropertyBinding<f32>, f32),
+ Saturate(f32),
+ Sepia(f32),
+ DropShadows(SmallVec<[Shadow; 1]>),
+ ColorMatrix(Box<[f32; 20]>),
+ SrgbToLinear,
+ LinearToSrgb,
+ ComponentTransfer,
+ Flood(ColorF),
+}
+
+impl Filter {
+ pub fn is_visible(&self) -> bool {
+ match *self {
+ Filter::Identity |
+ Filter::Blur { .. } |
+ Filter::Brightness(..) |
+ Filter::Contrast(..) |
+ Filter::Grayscale(..) |
+ Filter::HueRotate(..) |
+ Filter::Invert(..) |
+ Filter::Saturate(..) |
+ Filter::Sepia(..) |
+ Filter::DropShadows(..) |
+ Filter::ColorMatrix(..) |
+ Filter::SrgbToLinear |
+ Filter::LinearToSrgb |
+ Filter::ComponentTransfer => true,
+ Filter::Opacity(_, amount) => {
+ amount > OPACITY_EPSILON
+ },
+ Filter::Flood(color) => {
+ color.a > OPACITY_EPSILON
+ }
+ }
+ }
+
+ pub fn is_noop(&self) -> bool {
+ match *self {
+ Filter::Identity => false, // this is intentional
+ Filter::Blur { width, height, .. } => width == 0.0 && height == 0.0,
+ Filter::Brightness(amount) => amount == 1.0,
+ Filter::Contrast(amount) => amount == 1.0,
+ Filter::Grayscale(amount) => amount == 0.0,
+ Filter::HueRotate(amount) => amount == 0.0,
+ Filter::Invert(amount) => amount == 0.0,
+ Filter::Opacity(api::PropertyBinding::Value(amount), _) => amount >= 1.0,
+ Filter::Saturate(amount) => amount == 1.0,
+ Filter::Sepia(amount) => amount == 0.0,
+ Filter::DropShadows(ref shadows) => {
+ for shadow in shadows {
+ if shadow.offset.x != 0.0 || shadow.offset.y != 0.0 || shadow.blur_radius != 0.0 {
+ return false;
+ }
+ }
+
+ true
+ }
+ Filter::ColorMatrix(ref matrix) => {
+ **matrix == [
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ 0.0, 0.0, 0.0, 0.0
+ ]
+ }
+ Filter::Opacity(api::PropertyBinding::Binding(..), _) |
+ Filter::SrgbToLinear |
+ Filter::LinearToSrgb |
+ Filter::ComponentTransfer |
+ Filter::Flood(..) => false,
+ }
+ }
+
+
+ pub fn as_int(&self) -> i32 {
+ // Must be kept in sync with brush_blend.glsl
+ match *self {
+ Filter::Identity => 0, // matches `Contrast(1)`
+ Filter::Contrast(..) => 0,
+ Filter::Grayscale(..) => 1,
+ Filter::HueRotate(..) => 2,
+ Filter::Invert(..) => 3,
+ Filter::Saturate(..) => 4,
+ Filter::Sepia(..) => 5,
+ Filter::Brightness(..) => 6,
+ Filter::ColorMatrix(..) => 7,
+ Filter::SrgbToLinear => 8,
+ Filter::LinearToSrgb => 9,
+ Filter::Flood(..) => 10,
+ Filter::ComponentTransfer => 11,
+ Filter::Blur { .. } => 12,
+ Filter::DropShadows(..) => 13,
+ Filter::Opacity(..) => 14,
+ }
+ }
+}
+
+impl From<FilterOp> for Filter {
+ fn from(op: FilterOp) -> Self {
+ match op {
+ FilterOp::Identity => Filter::Identity,
+ FilterOp::Blur(width, height) => Filter::Blur { width, height, should_inflate: true },
+ FilterOp::Brightness(b) => Filter::Brightness(b),
+ FilterOp::Contrast(c) => Filter::Contrast(c),
+ FilterOp::Grayscale(g) => Filter::Grayscale(g),
+ FilterOp::HueRotate(h) => Filter::HueRotate(h),
+ FilterOp::Invert(i) => Filter::Invert(i),
+ FilterOp::Opacity(binding, opacity) => Filter::Opacity(binding, opacity),
+ FilterOp::Saturate(s) => Filter::Saturate(s),
+ FilterOp::Sepia(s) => Filter::Sepia(s),
+ FilterOp::ColorMatrix(mat) => Filter::ColorMatrix(Box::new(mat)),
+ FilterOp::SrgbToLinear => Filter::SrgbToLinear,
+ FilterOp::LinearToSrgb => Filter::LinearToSrgb,
+ FilterOp::ComponentTransfer => Filter::ComponentTransfer,
+ FilterOp::DropShadow(shadow) => Filter::DropShadows(smallvec![shadow]),
+ FilterOp::Flood(color) => Filter::Flood(color),
+ }
+ }
+}
+
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+pub enum Swizzle {
+ Rgba,
+ Bgra,
+}
+
+impl Default for Swizzle {
+ fn default() -> Self {
+ Swizzle::Rgba
+ }
+}
+
+/// Swizzle settings of the texture cache.
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+pub struct SwizzleSettings {
+ /// Swizzle required on sampling a texture with BGRA8 format.
+ pub bgra8_sampling_swizzle: Swizzle,
+}
+
+/// An ID for a texture that is owned by the `texture_cache` module.
+///
+/// This can include atlases or standalone textures allocated via the texture
+/// cache (e.g. if an image is too large to be added to an atlas). The texture
+/// cache manages the allocation and freeing of these IDs, and the rendering
+/// thread maintains a map from cache texture ID to native texture.
+///
+/// We never reuse IDs, so we use a u64 here to be safe.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub struct CacheTextureId(pub u32);
+
+impl CacheTextureId {
+ pub const INVALID: CacheTextureId = CacheTextureId(!0);
+}
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub struct DeferredResolveIndex(pub u32);
+
+/// Identifies the source of an input texture to a shader.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub enum TextureSource {
+ /// Equivalent to `None`, allowing us to avoid using `Option`s everywhere.
+ Invalid,
+ /// An entry in the texture cache.
+ TextureCache(CacheTextureId, Swizzle),
+ /// An external image texture, mananged by the embedding.
+ External(DeferredResolveIndex, ImageBufferKind),
+ /// Select a dummy 1x1 white texture. This can be used by image
+ /// shaders that want to draw a solid color.
+ Dummy,
+}
+
+impl TextureSource {
+ pub fn image_buffer_kind(&self) -> ImageBufferKind {
+ match *self {
+ TextureSource::TextureCache(..) => ImageBufferKind::Texture2D,
+
+ TextureSource::External(_, image_buffer_kind) => image_buffer_kind,
+
+ // Render tasks use texture arrays for now.
+ TextureSource::Dummy => ImageBufferKind::Texture2D,
+
+ TextureSource::Invalid => ImageBufferKind::Texture2D,
+ }
+ }
+
+ #[inline]
+ pub fn is_compatible(
+ &self,
+ other: &TextureSource,
+ ) -> bool {
+ *self == TextureSource::Invalid ||
+ *other == TextureSource::Invalid ||
+ self == other
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub struct RenderTargetInfo {
+ pub has_depth: bool,
+}
+
+#[derive(Debug)]
+pub enum TextureUpdateSource {
+ External {
+ id: ExternalImageId,
+ channel_index: u8,
+ },
+ Bytes { data: Arc<Vec<u8>> },
+ /// Clears the target area, rather than uploading any pixels. Used when the
+ /// texture cache debug display is active.
+ DebugClear,
+}
+
+/// Command to allocate, reallocate, or free a texture for the texture cache.
+#[derive(Debug)]
+pub struct TextureCacheAllocation {
+ /// The virtual ID (i.e. distinct from device ID) of the texture.
+ pub id: CacheTextureId,
+ /// Details corresponding to the operation in question.
+ pub kind: TextureCacheAllocationKind,
+}
+
+/// A little bit of extra information to make memory reports more useful
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+pub enum TextureCacheCategory {
+ Atlas,
+ Standalone,
+ PictureTile,
+ RenderTarget,
+}
+
+/// Information used when allocating / reallocating.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct TextureCacheAllocInfo {
+ pub width: i32,
+ pub height: i32,
+ pub format: ImageFormat,
+ pub filter: TextureFilter,
+ pub target: ImageBufferKind,
+ /// Indicates whether this corresponds to one of the shared texture caches.
+ pub is_shared_cache: bool,
+ /// If true, this texture requires a depth target.
+ pub has_depth: bool,
+ pub category: TextureCacheCategory
+}
+
+/// Sub-operation-specific information for allocation operations.
+#[derive(Debug)]
+pub enum TextureCacheAllocationKind {
+ /// Performs an initial texture allocation.
+ Alloc(TextureCacheAllocInfo),
+ /// Reallocates the texture without preserving its contents.
+ Reset(TextureCacheAllocInfo),
+ /// Frees the texture and the corresponding cache ID.
+ Free,
+}
+
+/// Command to update the contents of the texture cache.
+#[derive(Debug)]
+pub struct TextureCacheUpdate {
+ pub rect: DeviceIntRect,
+ pub stride: Option<i32>,
+ pub offset: i32,
+ pub format_override: Option<ImageFormat>,
+ pub source: TextureUpdateSource,
+}
+
+/// Command to update the contents of the texture cache.
+#[derive(Debug)]
+pub struct TextureCacheCopy {
+ pub src_rect: DeviceIntRect,
+ pub dst_rect: DeviceIntRect,
+}
+
+/// Atomic set of commands to manipulate the texture cache, generated on the
+/// RenderBackend thread and executed on the Renderer thread.
+///
+/// The list of allocation operations is processed before the updates. This is
+/// important to allow coalescing of certain allocation operations.
+#[derive(Default)]
+pub struct TextureUpdateList {
+ /// Indicates that there was some kind of cleanup clear operation. Used for
+ /// sanity checks.
+ pub clears_shared_cache: bool,
+ /// Commands to alloc/realloc/free the textures. Processed first.
+ pub allocations: Vec<TextureCacheAllocation>,
+ /// Commands to update the contents of the textures. Processed second.
+ pub updates: FastHashMap<CacheTextureId, Vec<TextureCacheUpdate>>,
+ /// Commands to move items within the cache, these are applied before everything
+ /// else in the update list.
+ pub copies: FastHashMap<(CacheTextureId, CacheTextureId), Vec<TextureCacheCopy>>,
+}
+
+impl TextureUpdateList {
+ /// Mints a new `TextureUpdateList`.
+ pub fn new() -> Self {
+ TextureUpdateList {
+ clears_shared_cache: false,
+ allocations: Vec::new(),
+ updates: FastHashMap::default(),
+ copies: FastHashMap::default(),
+ }
+ }
+
+ /// Returns true if this is a no-op (no updates to be applied).
+ pub fn is_nop(&self) -> bool {
+ self.allocations.is_empty() && self.updates.is_empty()
+ }
+
+ /// Sets the clears_shared_cache flag for renderer-side sanity checks.
+ #[inline]
+ pub fn note_clear(&mut self) {
+ self.clears_shared_cache = true;
+ }
+
+ /// Pushes an update operation onto the list.
+ #[inline]
+ pub fn push_update(&mut self, id: CacheTextureId, update: TextureCacheUpdate) {
+ self.updates
+ .entry(id)
+ .or_default()
+ .push(update);
+ }
+
+ /// Sends a command to the Renderer to clear the portion of the shared region
+ /// we just freed. Used when the texture cache debugger is enabled.
+ #[cold]
+ pub fn push_debug_clear(
+ &mut self,
+ id: CacheTextureId,
+ origin: DeviceIntPoint,
+ width: i32,
+ height: i32,
+ ) {
+ let size = DeviceIntSize::new(width, height);
+ let rect = DeviceIntRect::from_origin_and_size(origin, size);
+ self.push_update(id, TextureCacheUpdate {
+ rect,
+ stride: None,
+ offset: 0,
+ format_override: None,
+ source: TextureUpdateSource::DebugClear,
+ });
+ }
+
+
+ /// Pushes an allocation operation onto the list.
+ pub fn push_alloc(&mut self, id: CacheTextureId, info: TextureCacheAllocInfo) {
+ debug_assert!(!self.allocations.iter().any(|x| x.id == id));
+ self.allocations.push(TextureCacheAllocation {
+ id,
+ kind: TextureCacheAllocationKind::Alloc(info),
+ });
+ }
+
+ /// Pushes a reallocation operation onto the list, potentially coalescing
+ /// with previous operations.
+ pub fn push_reset(&mut self, id: CacheTextureId, info: TextureCacheAllocInfo) {
+ self.debug_assert_coalesced(id);
+
+ // Drop any unapplied updates to the to-be-freed texture.
+ self.updates.remove(&id);
+
+ // Coallesce this realloc into a previous alloc or realloc, if available.
+ if let Some(cur) = self.allocations.iter_mut().find(|x| x.id == id) {
+ match cur.kind {
+ TextureCacheAllocationKind::Alloc(ref mut i) => *i = info,
+ TextureCacheAllocationKind::Reset(ref mut i) => *i = info,
+ TextureCacheAllocationKind::Free => panic!("Resetting freed texture"),
+ }
+ return
+ }
+
+ self.allocations.push(TextureCacheAllocation {
+ id,
+ kind: TextureCacheAllocationKind::Reset(info),
+ });
+ }
+
+ /// Pushes a free operation onto the list, potentially coalescing with
+ /// previous operations.
+ pub fn push_free(&mut self, id: CacheTextureId) {
+ self.debug_assert_coalesced(id);
+
+ // Drop any unapplied updates to the to-be-freed texture.
+ self.updates.remove(&id);
+
+ // Drop any allocations for it as well. If we happen to be allocating and
+ // freeing in the same batch, we can collapse them to a no-op.
+ let idx = self.allocations.iter().position(|x| x.id == id);
+ let removed_kind = idx.map(|i| self.allocations.remove(i).kind);
+ match removed_kind {
+ Some(TextureCacheAllocationKind::Alloc(..)) => { /* no-op! */ },
+ Some(TextureCacheAllocationKind::Free) => panic!("Double free"),
+ Some(TextureCacheAllocationKind::Reset(..)) |
+ None => {
+ self.allocations.push(TextureCacheAllocation {
+ id,
+ kind: TextureCacheAllocationKind::Free,
+ });
+ }
+ };
+ }
+
+ /// Push a copy operation from a texture to another.
+ ///
+ /// The source and destination rectangles must have the same size.
+ /// The copies are applied before every other operations in the
+ /// texture update list.
+ pub fn push_copy(
+ &mut self,
+ src_id: CacheTextureId, src_rect: &DeviceIntRect,
+ dst_id: CacheTextureId, dst_rect: &DeviceIntRect,
+ ) {
+ debug_assert_eq!(src_rect.size(), dst_rect.size());
+ self.copies.entry((src_id, dst_id))
+ .or_insert_with(Vec::new)
+ .push(TextureCacheCopy {
+ src_rect: *src_rect,
+ dst_rect: *dst_rect,
+ });
+ }
+
+ fn debug_assert_coalesced(&self, id: CacheTextureId) {
+ debug_assert!(
+ self.allocations.iter().filter(|x| x.id == id).count() <= 1,
+ "Allocations should have been coalesced",
+ );
+ }
+}
+
+/// A list of updates built by the render backend that should be applied
+/// by the renderer thread.
+pub struct ResourceUpdateList {
+ /// List of OS native surface create / destroy operations to apply.
+ pub native_surface_updates: Vec<NativeSurfaceOperation>,
+
+ /// Atomic set of texture cache updates to apply.
+ pub texture_updates: TextureUpdateList,
+}
+
+impl ResourceUpdateList {
+ /// Returns true if this update list has no effect.
+ pub fn is_nop(&self) -> bool {
+ self.texture_updates.is_nop() && self.native_surface_updates.is_empty()
+ }
+}
+
+/// Wraps a frame_builder::Frame, but conceptually could hold more information
+pub struct RenderedDocument {
+ pub frame: Frame,
+ pub is_new_scene: bool,
+ pub profile: TransactionProfile,
+ pub render_reasons: RenderReasons,
+ pub frame_stats: Option<FullFrameStats>
+}
+
+pub enum DebugOutput {
+ #[cfg(feature = "capture")]
+ SaveCapture(CaptureConfig, Vec<ExternalCaptureImage>),
+ #[cfg(feature = "replay")]
+ LoadCapture(CaptureConfig, Vec<PlainExternalImage>),
+}
+
+#[allow(dead_code)]
+pub enum ResultMsg {
+ DebugCommand(DebugCommand),
+ DebugOutput(DebugOutput),
+ RefreshShader(PathBuf),
+ UpdateGpuCache(GpuCacheUpdateList),
+ UpdateResources {
+ resource_updates: ResourceUpdateList,
+ memory_pressure: bool,
+ },
+ PublishPipelineInfo(PipelineInfo),
+ PublishDocument(
+ FramePublishId,
+ DocumentId,
+ RenderedDocument,
+ ResourceUpdateList,
+ ),
+ AppendNotificationRequests(Vec<NotificationRequest>),
+ SetParameter(Parameter),
+ ForceRedraw,
+}
+
+/// Primitive metadata we pass around in a bunch of places
+#[derive(Copy, Clone, Debug)]
+pub struct LayoutPrimitiveInfo {
+ /// NOTE: this is *ideally* redundant with the clip_rect
+ /// but that's an ongoing project, so for now it exists and is used :(
+ pub rect: LayoutRect,
+ pub clip_rect: LayoutRect,
+ pub flags: PrimitiveFlags,
+}
+
+impl LayoutPrimitiveInfo {
+ pub fn with_clip_rect(rect: LayoutRect, clip_rect: LayoutRect) -> Self {
+ Self {
+ rect,
+ clip_rect,
+ flags: PrimitiveFlags::default(),
+ }
+ }
+}
+
+// In some cases (e.g. printing) a pipeline is referenced multiple times by
+// a parent display list. This allows us to distinguish between them.
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Copy, Clone, PartialEq, Debug, Eq, Hash)]
+pub struct PipelineInstanceId(u32);
+
+impl PipelineInstanceId {
+ pub fn new(id: u32) -> Self {
+ PipelineInstanceId(id)
+ }
+}