#![cfg_attr(feature = "nightly", feature(nonzero))]
#![allow(
clippy::float_cmp,
clippy::too_many_arguments,
clippy::unreadable_literal,
clippy::new_without_default,
clippy::empty_docs,
clippy::manual_range_contains,
unknown_lints,
mismatched_lifetime_syntaxes,
)]
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;
#[macro_use]
extern crate malloc_size_of_derive;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate malloc_size_of;
extern crate peek_poke;
pub mod channel;
mod color;
#[cfg(feature = "debugger")]
pub mod debugger;
mod display_item;
mod display_item_cache;
mod display_list;
mod font;
mod gradient_builder;
mod image;
mod tile_pool;
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::*;
pub use crate::tile_pool::*;
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;
pub const MAX_RENDER_TASK_SIZE: i32 = 16384;
pub type TileSize = u16;
#[derive(Copy, Clone, Deserialize, Serialize)]
pub struct QualitySettings {
pub force_subpixel_aa_where_possible: bool,
}
impl Default for QualitySettings {
fn default() -> Self {
QualitySettings {
force_subpixel_aa_where_possible: false,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Epoch(pub u32);
impl Epoch {
pub fn invalid() -> Epoch {
Epoch(u32::MAX)
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, PeekPoke)]
#[derive(Deserialize, Serialize)]
pub struct IdNamespace(pub u32);
impl IdNamespace {
pub const DEBUGGER: IdNamespace = IdNamespace(!0);
}
#[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 };
}
pub type PipelineSourceId = u32;
#[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)
}
pub const INVALID: Self = PipelineId(!0, !0);
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct FramePublishId(pub u64);
impl FramePublishId {
pub fn first() -> Self {
FramePublishId(0)
}
pub fn advance(&mut self) {
self.0 += 1;
}
pub const INVALID: Self = FramePublishId(0);
}
impl Default for FramePublishId {
fn default() -> Self {
FramePublishId::INVALID
}
}
#[repr(C)]
#[derive(Clone)]
pub struct ExternalEvent {
raw: usize,
}
unsafe impl Send for ExternalEvent {}
impl ExternalEvent {
pub fn from_raw(raw: usize) -> Self {
ExternalEvent { raw }
}
pub fn unwrap(self) -> usize {
self.raw
}
}
pub type APZScrollGeneration = u64;
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Default)]
pub struct SampledScrollOffset {
pub offset: LayoutVector2D,
pub generation: APZScrollGeneration,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum HasScrollLinkedEffect {
Yes,
#[default]
No,
}
#[repr(C)]
pub struct MinimapData {
pub is_root_content: bool,
pub visual_viewport: LayoutRect,
pub layout_viewport: LayoutRect,
pub scrollable_rect: LayoutRect,
pub displayport: LayoutRect,
pub zoom_transform: LayoutTransform,
pub root_content_pipeline_id: PipelineId,
pub root_content_scroll_id: u64
}
#[repr(C)]
pub struct FrameReadyParams {
pub present: bool,
pub render: bool,
pub scrolled: bool,
pub tracked: bool,
}
pub trait RenderNotifier: Send {
fn clone(&self) -> Box<dyn RenderNotifier>;
fn wake_up(
&self,
composite_needed: bool,
);
fn new_frame_ready(&self, _: DocumentId, publish_id: FramePublishId, params: &FrameReadyParams);
fn external_event(&self, _evt: ExternalEvent) {
unimplemented!()
}
fn shut_down(&self) {}
}
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Checkpoint {
SceneBuilt,
FrameBuilt,
FrameTexturesUpdated,
FrameRendered,
TransactionDropped,
}
pub trait NotificationHandler : Send + Sync {
fn notify(&self, when: Checkpoint);
}
pub struct NotificationRequest {
handler: Option<Box<dyn NotificationHandler>>,
when: Checkpoint,
}
impl NotificationRequest {
pub fn new(when: Checkpoint, handler: Box<dyn NotificationHandler>) -> Self {
NotificationRequest {
handler: Some(handler),
when,
}
}
pub fn when(&self) -> Checkpoint { self.when }
pub fn notify(mut self) {
if let Some(handler) = self.handler.take() {
handler.notify(self.when);
}
}
}
pub trait ApiHitTester: Send + Sync {
fn hit_test(&self, point: WorldPoint) -> HitTestResult;
}
pub struct HitTesterRequest {
#[doc(hidden)]
pub rx: Receiver<Arc<dyn ApiHitTester>>,
}
impl HitTesterRequest {
pub fn resolve(self) -> Arc<dyn ApiHitTester> {
self.rx.recv().unwrap()
}
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct HitTestResultItem {
pub pipeline: PipelineId,
pub tag: ItemTag,
pub animation_id: u64,
pub point_in_viewport: LayoutPoint,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct HitTestResult {
pub items: Vec<HitTestResultItem>,
}
impl Drop for NotificationRequest {
fn drop(&mut self) {
if let Some(ref mut handler) = self.handler {
handler.notify(Checkpoint::TransactionDropped);
}
}
}
impl Clone for NotificationRequest {
fn clone(&self) -> Self {
NotificationRequest {
when: self.when,
handler: None,
}
}
}
#[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 {
pub fn new(value: u64) -> Self {
PropertyBindingId {
namespace: IdNamespace((value >> 32) as u32),
uid: value as u32,
}
}
pub fn to_u64(&self) -> u64 {
((self.namespace.0 as u64) << 32) | self.uid as u64
}
}
#[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>,
}
impl<T: Copy> PropertyBindingKey<T> {
pub fn with(self, value: T) -> PropertyValue<T> {
PropertyValue { key: self, value }
}
}
impl<T> Into<u64> for PropertyBindingKey<T> {
fn into(self) -> u64 {
self.id.to_u64()
}
}
impl<T> PropertyBindingKey<T> {
pub fn new(value: u64) -> Self {
PropertyBindingKey {
id: PropertyBindingId::new(value),
_phantom: PhantomData,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub enum PropertyBinding<T> {
Value(T),
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,
_phantom: PhantomData,
}
}
}
impl From<PropertyBindingKey<ColorU>> for PropertyBindingKey<ColorF> {
fn from(key: PropertyBindingKey<ColorU>) -> PropertyBindingKey<ColorF> {
PropertyBindingKey {
id: key.id,
_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())
}
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
pub struct PropertyValue<T> {
pub key: PropertyBindingKey<T>,
pub value: T,
}
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Default)]
pub struct DynamicProperties {
pub transforms: Vec<PropertyValue<LayoutTransform>>,
pub floats: Vec<PropertyValue<f32>>,
pub colors: Vec<PropertyValue<ColorF>>,
}
impl DynamicProperties {
pub fn extend(&mut self, other: Self) {
self.transforms.extend(other.transforms);
self.floats.extend(other.floats);
self.colors.extend(other.colors);
}
}
pub type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Parameter {
Bool(BoolParameter, bool),
Int(IntParameter, i32),
Float(FloatParameter, f32),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum BoolParameter {
PboUploads = 0,
Multithreading = 1,
BatchedUploads = 2,
DrawCallsForTextureCopy = 3,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum IntParameter {
BatchedUploadThreshold = 0,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum FloatParameter {
SlowCpuFrameThreshold = 0,
}
#[repr(C)]
#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Default, Deserialize, MallocSizeOf, Serialize)]
pub struct RenderReasons(u32);
bitflags! {
impl RenderReasons: u32 {
const NONE = 0;
const SCENE = 1 << 0;
const ANIMATED_PROPERTY = 1 << 1;
const RESOURCE_UPDATE = 1 << 2;
const ASYNC_IMAGE = 1 << 3;
const CLEAR_RESOURCES = 1 << 4;
const APZ = 1 << 5;
const RESIZE = 1 << 6;
const WIDGET = 1 << 7;
const TEXTURE_CACHE_FLUSH = 1 << 8;
const SNAPSHOT = 1 << 9;
const POST_RESOURCE_UPDATES_HOOK = 1 << 10;
const CONFIG_CHANGE = 1 << 11;
const CONTENT_SYNC = 1 << 12;
const FLUSH = 1 << 13;
const TESTING = 1 << 14;
const OTHER = 1 << 15;
const VSYNC = 1 << 16;
const SKIPPED_COMPOSITE = 1 << 17;
const START_OBSERVING_VSYNC = 1 << 18;
const ASYNC_IMAGE_COMPOSITE_UNTIL = 1 << 19;
}
}
impl core::fmt::Debug for RenderReasons {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
if self.is_empty() {
write!(f, "{:#x}", Self::empty().bits())
} else {
bitflags::parser::to_writer(self, f)
}
}
}
impl RenderReasons {
pub const NUM_BITS: u32 = 17;
}
#[repr(C)]
#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Default, Deserialize, MallocSizeOf, Serialize)]
pub struct DebugFlags(u64);
bitflags! {
impl DebugFlags: u64 {
const PROFILER_DBG = 1 << 0;
const RENDER_TARGET_DBG = 1 << 1;
const TEXTURE_CACHE_DBG = 1 << 2;
const GPU_TIME_QUERIES = 1 << 3;
const GPU_SAMPLE_QUERIES = 1 << 4;
const DISABLE_BATCHING = 1 << 5;
const EPOCHS = 1 << 6;
const ECHO_DRIVER_MESSAGES = 1 << 7;
const SHOW_OVERDRAW = 1 << 8;
const GPU_CACHE_DBG = 1 << 9;
const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 10;
const PICTURE_CACHING_DBG = 1 << 11;
const PRIMITIVE_DBG = 1 << 12;
const ZOOM_DBG = 1 << 13;
const SMALL_SCREEN = 1 << 14;
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;
const GLYPH_FLASHING = 1 << 21;
const SMART_PROFILER = 1 << 22;
const INVALIDATION_DBG = 1 << 23;
const PROFILER_CAPTURE = 1 << 25;
const FORCE_PICTURE_INVALIDATION = 1 << 26;
const WINDOW_VISIBILITY_DBG = 1 << 27;
const RESTRICT_BLOB_SIZE = 1 << 28;
const SURFACE_PROMOTION_LOGGING = 1 << 29;
const PICTURE_BORDERS = 1 << 30;
const MISSING_SNAPSHOT_PANIC = (1 as u64) << 31; const MISSING_SNAPSHOT_PINK = (1 as u64) << 32;
const HIGHLIGHT_BACKDROP_FILTERS = (1 as u64) << 33;
}
}
impl core::fmt::Debug for DebugFlags {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
if self.is_empty() {
write!(f, "{:#x}", Self::empty().bits())
} else {
bitflags::parser::to_writer(self, f)
}
}
}
#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash, Serialize, Deserialize)]
pub enum PrimitiveKeyKind {
Clear,
Rectangle {
color: PropertyBinding<ColorU>,
},
}
#[derive(Clone, Copy, Debug)]
pub enum ScrollLocation {
Delta(LayoutVector2D),
Start,
End,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub enum CrashAnnotation {
CompileShader = 0,
DrawShader = 1,
}
pub trait CrashAnnotator : Send {
fn set(&self, annotation: CrashAnnotation, value: &std::ffi::CStr);
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()
}
}
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: &std::ffi::CStr,
) -> 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);
}
}
}