summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender_api/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/wr/webrender_api/src/lib.rs656
1 files changed, 656 insertions, 0 deletions
diff --git a/gfx/wr/webrender_api/src/lib.rs b/gfx/wr/webrender_api/src/lib.rs
new file mode 100644
index 0000000000..72016421c8
--- /dev/null
+++ b/gfx/wr/webrender_api/src/lib.rs
@@ -0,0 +1,656 @@
+/* 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/. */
+
+//! The `webrender_api` crate contains an assortment types and functions used
+//! by WebRender consumers as well as, in many cases, WebRender itself.
+//!
+//! This separation allows Servo to parallelize compilation across `webrender`
+//! and other crates that depend on `webrender_api`. So in practice, we put
+//! things in this crate when Servo needs to use them. Firefox depends on the
+//! `webrender` crate directly, and so this distinction is not really relevant
+//! there.
+
+#![cfg_attr(feature = "nightly", feature(nonzero))]
+#![cfg_attr(feature = "cargo-clippy", allow(clippy::float_cmp, clippy::too_many_arguments))]
+#![cfg_attr(feature = "cargo-clippy", allow(clippy::unreadable_literal, clippy::new_without_default))]
+
+pub extern crate crossbeam_channel;
+pub extern crate euclid;
+
+extern crate app_units;
+#[macro_use]
+extern crate bitflags;
+extern crate byteorder;
+#[cfg(feature = "nightly")]
+extern crate core;
+#[cfg(target_os = "macos")]
+extern crate core_foundation;
+#[cfg(target_os = "macos")]
+extern crate core_graphics;
+extern crate derive_more;
+#[macro_use]
+extern crate malloc_size_of_derive;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
+extern crate time;
+
+extern crate malloc_size_of;
+extern crate peek_poke;
+
+pub mod channel;
+mod color;
+mod display_item;
+mod display_item_cache;
+mod display_list;
+mod font;
+mod gradient_builder;
+mod image;
+pub mod units;
+
+pub use crate::color::*;
+pub use crate::display_item::*;
+pub use crate::display_item_cache::DisplayItemCache;
+pub use crate::display_list::*;
+pub use crate::font::*;
+pub use crate::gradient_builder::*;
+pub use crate::image::*;
+
+use crate::units::*;
+use crate::channel::Receiver;
+use std::marker::PhantomData;
+use std::sync::Arc;
+use std::os::raw::c_void;
+use peek_poke::PeekPoke;
+
+/// Width and height in device pixels of image tiles.
+pub type TileSize = u16;
+
+/// Various settings that the caller can select based on desired tradeoffs
+/// between rendering quality and performance / power usage.
+#[derive(Copy, Clone, Deserialize, Serialize)]
+pub struct QualitySettings {
+ /// If true, disable creating separate picture cache slices when the
+ /// scroll root changes. This gives maximum opportunity to find an
+ /// opaque background, which enables subpixel AA. However, it is
+ /// usually significantly more expensive to render when scrolling.
+ pub force_subpixel_aa_where_possible: bool,
+}
+
+impl Default for QualitySettings {
+ fn default() -> Self {
+ QualitySettings {
+ // Prefer performance over maximum subpixel AA quality, since WR
+ // already enables subpixel AA in more situations than other browsers.
+ force_subpixel_aa_where_possible: false,
+ }
+ }
+}
+
+/// An epoch identifies the state of a pipeline in time.
+///
+/// This is mostly used as a synchronization mechanism to observe how/when particular pipeline
+/// updates propagate through WebRender and are applied at various stages.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
+pub struct Epoch(pub u32);
+
+impl Epoch {
+ /// Magic invalid epoch value.
+ pub fn invalid() -> Epoch {
+ Epoch(u32::MAX)
+ }
+}
+
+/// ID namespaces uniquely identify different users of WebRender's API.
+///
+/// For example in Gecko each content process uses a separate id namespace.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Default, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, PeekPoke)]
+#[derive(Deserialize, Serialize)]
+pub struct IdNamespace(pub u32);
+
+/// A key uniquely identifying a WebRender document.
+///
+/// Instances can manage one or several documents (using the same render backend thread).
+/// Each document will internally correspond to a single scene, and scenes are made of
+/// one or several pipelines.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
+pub struct DocumentId {
+ ///
+ pub namespace_id: IdNamespace,
+ ///
+ pub id: u32,
+}
+
+impl DocumentId {
+ ///
+ pub fn new(namespace_id: IdNamespace, id: u32) -> Self {
+ DocumentId {
+ namespace_id,
+ id,
+ }
+ }
+
+ ///
+ pub const INVALID: DocumentId = DocumentId { namespace_id: IdNamespace(0), id: 0 };
+}
+
+/// This type carries no valuable semantics for WR. However, it reflects the fact that
+/// clients (Servo) may generate pipelines by different semi-independent sources.
+/// These pipelines still belong to the same `IdNamespace` and the same `DocumentId`.
+/// Having this extra Id field enables them to generate `PipelineId` without collision.
+pub type PipelineSourceId = u32;
+
+/// From the point of view of WR, `PipelineId` is completely opaque and generic as long as
+/// it's clonable, serializable, comparable, and hashable.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
+pub struct PipelineId(pub PipelineSourceId, pub u32);
+
+impl Default for PipelineId {
+ fn default() -> Self {
+ PipelineId::dummy()
+ }
+}
+
+impl PipelineId {
+ ///
+ pub fn dummy() -> Self {
+ PipelineId(0, 0)
+ }
+}
+
+
+/// An opaque pointer-sized value.
+#[repr(C)]
+#[derive(Clone)]
+pub struct ExternalEvent {
+ raw: usize,
+}
+
+unsafe impl Send for ExternalEvent {}
+
+impl ExternalEvent {
+ /// Creates the event from an opaque pointer-sized value.
+ pub fn from_raw(raw: usize) -> Self {
+ ExternalEvent { raw }
+ }
+ /// Consumes self to make it obvious that the event should be forwarded only once.
+ pub fn unwrap(self) -> usize {
+ self.raw
+ }
+}
+
+/// Describe whether or not scrolling should be clamped by the content bounds.
+#[derive(Clone, Deserialize, Serialize)]
+pub enum ScrollClamping {
+ ///
+ ToContentBounds,
+ ///
+ NoClamping,
+}
+
+/// A handler to integrate WebRender with the thread that contains the `Renderer`.
+pub trait RenderNotifier: Send {
+ ///
+ fn clone(&self) -> Box<dyn RenderNotifier>;
+ /// Wake the thread containing the `Renderer` up (after updates have been put
+ /// in the renderer's queue).
+ fn wake_up(
+ &self,
+ composite_needed: bool,
+ );
+ /// Notify the thread containing the `Renderer` that a new frame is ready.
+ fn new_frame_ready(&self, _: DocumentId, scrolled: bool, composite_needed: bool, render_time_ns: Option<u64>);
+ /// A Gecko-specific notification mechanism to get some code executed on the
+ /// `Renderer`'s thread, mostly replaced by `NotificationHandler`. You should
+ /// probably use the latter instead.
+ fn external_event(&self, _evt: ExternalEvent) {
+ unimplemented!()
+ }
+ /// Notify the thread containing the `Renderer` that the render backend has been
+ /// shut down.
+ fn shut_down(&self) {}
+}
+
+/// A stage of the rendering pipeline.
+#[repr(u32)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Checkpoint {
+ ///
+ SceneBuilt,
+ ///
+ FrameBuilt,
+ ///
+ FrameTexturesUpdated,
+ ///
+ FrameRendered,
+ /// NotificationRequests get notified with this if they get dropped without having been
+ /// notified. This provides the guarantee that if a request is created it will get notified.
+ TransactionDropped,
+}
+
+/// A handler to notify when a transaction reaches certain stages of the rendering
+/// pipeline.
+pub trait NotificationHandler : Send + Sync {
+ /// Entry point of the handler to implement. Invoked by WebRender.
+ fn notify(&self, when: Checkpoint);
+}
+
+/// A request to notify a handler when the transaction reaches certain stages of the
+/// rendering pipeline.
+///
+/// The request is guaranteed to be notified once and only once, even if the transaction
+/// is dropped before the requested check-point.
+pub struct NotificationRequest {
+ handler: Option<Box<dyn NotificationHandler>>,
+ when: Checkpoint,
+}
+
+impl NotificationRequest {
+ /// Constructor.
+ pub fn new(when: Checkpoint, handler: Box<dyn NotificationHandler>) -> Self {
+ NotificationRequest {
+ handler: Some(handler),
+ when,
+ }
+ }
+
+ /// The specified stage at which point the handler should be notified.
+ pub fn when(&self) -> Checkpoint { self.when }
+
+ /// Called by WebRender at specified stages to notify the registered handler.
+ pub fn notify(mut self) {
+ if let Some(handler) = self.handler.take() {
+ handler.notify(self.when);
+ }
+ }
+}
+
+/// An object that can perform hit-testing without doing synchronous queries to
+/// the RenderBackendThread.
+pub trait ApiHitTester: Send + Sync {
+ /// Does a hit test on display items in the specified document, at the given
+ /// point. If a pipeline_id is specified, it is used to further restrict the
+ /// hit results so that only items inside that pipeline are matched. The vector
+ /// of hit results will contain all display items that match, ordered from
+ /// front to back.
+ fn hit_test(&self, pipeline_id: Option<PipelineId>, point: WorldPoint) -> HitTestResult;
+}
+
+/// A hit tester requested to the render backend thread but not necessarily ready yet.
+///
+/// The request should be resolved as late as possible to reduce the likelihood of blocking.
+pub struct HitTesterRequest {
+ #[doc(hidden)]
+ pub rx: Receiver<Arc<dyn ApiHitTester>>,
+}
+
+impl HitTesterRequest {
+ /// Block until the hit tester is available and return it, consuming teh request.
+ pub fn resolve(self) -> Arc<dyn ApiHitTester> {
+ self.rx.recv().unwrap()
+ }
+}
+
+/// Describe an item that matched a hit-test query.
+#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+pub struct HitTestItem {
+ /// The pipeline that the display item that was hit belongs to.
+ pub pipeline: PipelineId,
+
+ /// The tag of the hit display item.
+ pub tag: ItemTag,
+
+ /// The hit point in the coordinate space of the "viewport" of the display item. The
+ /// viewport is the scroll node formed by the root reference frame of the display item's
+ /// pipeline.
+ pub point_in_viewport: LayoutPoint,
+
+ /// The coordinates of the original hit test point relative to the origin of this item.
+ /// This is useful for calculating things like text offsets in the client.
+ pub point_relative_to_item: LayoutPoint,
+}
+
+/// Returned by `RenderApi::hit_test`.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+pub struct HitTestResult {
+ /// List of items that are match the hit-test query.
+ pub items: Vec<HitTestItem>,
+}
+
+impl Drop for NotificationRequest {
+ fn drop(&mut self) {
+ if let Some(ref mut handler) = self.handler {
+ handler.notify(Checkpoint::TransactionDropped);
+ }
+ }
+}
+
+// This Clone impl yields an "empty" request because we don't want the requests
+// to be notified twice so the request is owned by only one of the API messages
+// (the original one) after the clone.
+// This works in practice because the notifications requests are used for
+// synchronization so we don't need to include them in the recording mechanism
+// in wrench that clones the messages.
+impl Clone for NotificationRequest {
+ fn clone(&self) -> Self {
+ NotificationRequest {
+ when: self.when,
+ handler: None,
+ }
+ }
+}
+
+
+/// A key to identify an animated property binding.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
+pub struct PropertyBindingId {
+ pub namespace: IdNamespace,
+ pub uid: u32,
+}
+
+impl PropertyBindingId {
+ /// Constructor.
+ pub fn new(value: u64) -> Self {
+ PropertyBindingId {
+ namespace: IdNamespace((value >> 32) as u32),
+ uid: value as u32,
+ }
+ }
+}
+
+/// A unique key that is used for connecting animated property
+/// values to bindings in the display list.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
+pub struct PropertyBindingKey<T> {
+ ///
+ pub id: PropertyBindingId,
+ #[doc(hidden)]
+ pub _phantom: PhantomData<T>,
+}
+
+/// Construct a property value from a given key and value.
+impl<T: Copy> PropertyBindingKey<T> {
+ ///
+ pub fn with(self, value: T) -> PropertyValue<T> {
+ PropertyValue { key: self, value }
+ }
+}
+
+impl<T> PropertyBindingKey<T> {
+ /// Constructor.
+ pub fn new(value: u64) -> Self {
+ PropertyBindingKey {
+ id: PropertyBindingId::new(value),
+ _phantom: PhantomData,
+ }
+ }
+}
+
+/// A binding property can either be a specific value
+/// (the normal, non-animated case) or point to a binding location
+/// to fetch the current value from.
+/// Note that Binding has also a non-animated value, the value is
+/// used for the case where the animation is still in-delay phase
+/// (i.e. the animation doesn't produce any animation values).
+#[repr(C)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
+pub enum PropertyBinding<T> {
+ /// Non-animated value.
+ Value(T),
+ /// Animated binding.
+ Binding(PropertyBindingKey<T>, T),
+}
+
+impl<T: Default> Default for PropertyBinding<T> {
+ fn default() -> Self {
+ PropertyBinding::Value(Default::default())
+ }
+}
+
+impl<T> From<T> for PropertyBinding<T> {
+ fn from(value: T) -> PropertyBinding<T> {
+ PropertyBinding::Value(value)
+ }
+}
+
+impl From<PropertyBindingKey<ColorF>> for PropertyBindingKey<ColorU> {
+ fn from(key: PropertyBindingKey<ColorF>) -> PropertyBindingKey<ColorU> {
+ PropertyBindingKey {
+ id: key.id.clone(),
+ _phantom: PhantomData,
+ }
+ }
+}
+
+impl From<PropertyBindingKey<ColorU>> for PropertyBindingKey<ColorF> {
+ fn from(key: PropertyBindingKey<ColorU>) -> PropertyBindingKey<ColorF> {
+ PropertyBindingKey {
+ id: key.id.clone(),
+ _phantom: PhantomData,
+ }
+ }
+}
+
+impl From<PropertyBinding<ColorF>> for PropertyBinding<ColorU> {
+ fn from(value: PropertyBinding<ColorF>) -> PropertyBinding<ColorU> {
+ match value {
+ PropertyBinding::Value(value) => PropertyBinding::Value(value.into()),
+ PropertyBinding::Binding(k, v) => {
+ PropertyBinding::Binding(k.into(), v.into())
+ }
+ }
+ }
+}
+
+impl From<PropertyBinding<ColorU>> for PropertyBinding<ColorF> {
+ fn from(value: PropertyBinding<ColorU>) -> PropertyBinding<ColorF> {
+ match value {
+ PropertyBinding::Value(value) => PropertyBinding::Value(value.into()),
+ PropertyBinding::Binding(k, v) => {
+ PropertyBinding::Binding(k.into(), v.into())
+ }
+ }
+ }
+}
+
+/// The current value of an animated property. This is
+/// supplied by the calling code.
+#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
+pub struct PropertyValue<T> {
+ ///
+ pub key: PropertyBindingKey<T>,
+ ///
+ pub value: T,
+}
+
+/// When using `generate_frame()`, a list of `PropertyValue` structures
+/// can optionally be supplied to provide the current value of any
+/// animated properties.
+#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Default)]
+pub struct DynamicProperties {
+ ///
+ pub transforms: Vec<PropertyValue<LayoutTransform>>,
+ /// opacity
+ pub floats: Vec<PropertyValue<f32>>,
+ /// background color
+ pub colors: Vec<PropertyValue<ColorF>>,
+}
+
+/// A C function that takes a pointer to a heap allocation and returns its size.
+///
+/// This is borrowed from the malloc_size_of crate, upon which we want to avoid
+/// a dependency from WebRender.
+pub type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
+
+bitflags! {
+ /// Flags to enable/disable various builtin debugging tools.
+ #[repr(C)]
+ #[derive(Default, Deserialize, MallocSizeOf, Serialize)]
+ pub struct DebugFlags: u32 {
+ /// Display the frame profiler on screen.
+ const PROFILER_DBG = 1 << 0;
+ /// Display intermediate render targets on screen.
+ const RENDER_TARGET_DBG = 1 << 1;
+ /// Display all texture cache pages on screen.
+ const TEXTURE_CACHE_DBG = 1 << 2;
+ /// Display GPU timing results.
+ const GPU_TIME_QUERIES = 1 << 3;
+ /// Query the number of pixels that pass the depth test divided and show it
+ /// in the profiler as a percentage of the number of pixels in the screen
+ /// (window width times height).
+ const GPU_SAMPLE_QUERIES = 1 << 4;
+ /// Render each quad with their own draw call.
+ ///
+ /// Terrible for performance but can help with understanding the drawing
+ /// order when inspecting renderdoc or apitrace recordings.
+ const DISABLE_BATCHING = 1 << 5;
+ /// Display the pipeline epochs.
+ const EPOCHS = 1 << 6;
+ /// Print driver messages to stdout.
+ const ECHO_DRIVER_MESSAGES = 1 << 7;
+ /// Show an overlay displaying overdraw amount.
+ const SHOW_OVERDRAW = 1 << 8;
+ /// Display the contents of GPU cache.
+ const GPU_CACHE_DBG = 1 << 9;
+ /// Clear evicted parts of the texture cache for debugging purposes.
+ const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 10;
+ /// Show picture caching debug overlay
+ const PICTURE_CACHING_DBG = 1 << 11;
+ /// Highlight all primitives with colors based on kind.
+ const PRIMITIVE_DBG = 1 << 12;
+ /// Draw a zoom widget showing part of the framebuffer zoomed in.
+ const ZOOM_DBG = 1 << 13;
+ /// Scale the debug renderer down for a smaller screen. This will disrupt
+ /// any mapping between debug display items and page content, so shouldn't
+ /// be used with overlays like the picture caching or primitive display.
+ const SMALL_SCREEN = 1 << 14;
+ /// Disable various bits of the WebRender pipeline, to help narrow
+ /// down where slowness might be coming from.
+ const DISABLE_OPAQUE_PASS = 1 << 15;
+ ///
+ const DISABLE_ALPHA_PASS = 1 << 16;
+ ///
+ const DISABLE_CLIP_MASKS = 1 << 17;
+ ///
+ const DISABLE_TEXT_PRIMS = 1 << 18;
+ ///
+ const DISABLE_GRADIENT_PRIMS = 1 << 19;
+ ///
+ const OBSCURE_IMAGES = 1 << 20;
+ /// Taint the transparent area of the glyphs with a random opacity to easily
+ /// see when glyphs are re-rasterized.
+ const GLYPH_FLASHING = 1 << 21;
+ /// The profiler only displays information that is out of the ordinary.
+ const SMART_PROFILER = 1 << 22;
+ /// If set, dump picture cache invalidation debug to console.
+ const INVALIDATION_DBG = 1 << 23;
+ /// Log tile cache to memory for later saving as part of wr-capture
+ const TILE_CACHE_LOGGING_DBG = 1 << 24;
+ /// Collect and dump profiler statistics to captures.
+ const PROFILER_CAPTURE = (1 as u32) << 25; // need "as u32" until we have cbindgen#556
+ /// Invalidate picture tiles every frames (useful when inspecting GPU work in external tools).
+ const FORCE_PICTURE_INVALIDATION = (1 as u32) << 26;
+ }
+}
+
+/// Information specific to a primitive type that
+/// uniquely identifies a primitive template by key.
+#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash, Serialize, Deserialize)]
+pub enum PrimitiveKeyKind {
+ /// Clear an existing rect, used for special effects on some platforms.
+ Clear,
+ ///
+ Rectangle {
+ ///
+ color: PropertyBinding<ColorU>,
+ },
+}
+
+///
+#[derive(Clone)]
+pub struct ScrollNodeState {
+ ///
+ pub id: ExternalScrollId,
+ ///
+ pub scroll_offset: LayoutVector2D,
+}
+
+///
+#[derive(Clone, Copy, Debug)]
+pub enum ScrollLocation {
+ /// Scroll by a certain amount.
+ Delta(LayoutVector2D),
+ /// Scroll to very top of element.
+ Start,
+ /// Scroll to very bottom of element.
+ End,
+}
+
+/// Represents a zoom factor.
+#[derive(Clone, Copy, Debug)]
+pub struct ZoomFactor(f32);
+
+impl ZoomFactor {
+ /// Construct a new zoom factor.
+ pub fn new(scale: f32) -> Self {
+ ZoomFactor(scale)
+ }
+
+ /// Get the zoom factor as an untyped float.
+ pub fn get(self) -> f32 {
+ self.0
+ }
+}
+
+/// Crash annotations included in crash reports.
+#[repr(C)]
+#[derive(Clone, Copy)]
+pub enum CrashAnnotation {
+ CompileShader = 0,
+}
+
+/// Handler to expose support for annotating crash reports.
+pub trait CrashAnnotator : Send {
+ fn set(&self, annotation: CrashAnnotation, value: &str);
+ fn clear(&self, annotation: CrashAnnotation);
+ fn box_clone(&self) -> Box<dyn CrashAnnotator>;
+}
+
+impl Clone for Box<dyn CrashAnnotator> {
+ fn clone(&self) -> Box<dyn CrashAnnotator> {
+ self.box_clone()
+ }
+}
+
+/// Guard to add a crash annotation at creation, and clear it at destruction.
+pub struct CrashAnnotatorGuard<'a> {
+ annotator: &'a Option<Box<dyn CrashAnnotator>>,
+ annotation: CrashAnnotation,
+}
+
+impl<'a> CrashAnnotatorGuard<'a> {
+ pub fn new(annotator: &'a Option<Box<dyn CrashAnnotator>>, annotation: CrashAnnotation, value: &str) -> Self {
+ if let Some(ref annotator) = annotator {
+ annotator.set(annotation, value);
+ }
+ Self {
+ annotator,
+ annotation,
+ }
+ }
+}
+
+impl<'a> Drop for CrashAnnotatorGuard<'a> {
+ fn drop(&mut self) {
+ if let Some(ref annotator) = self.annotator {
+ annotator.clear(self.annotation);
+ }
+ }
+}