Skip to main content

webrender_api/
units.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5//! A collection of coordinate spaces and their corresponding Point, Size and Rect types.
6//!
7//! Physical pixels take into account the device pixel ratio and their dimensions tend
8//! to correspond to the allocated size of resources in memory, while logical pixels
9//! don't have the device pixel ratio applied which means they are agnostic to the usage
10//! of hidpi screens and the like.
11//!
12//! The terms "layer" and "stacking context" can be used interchangeably
13//! in the context of coordinate systems.
14//!
15//! See also webrender/doc/coordinate-spaces.md
16
17pub use app_units::Au;
18use euclid::{Length, Rect, Scale, Size2D, Transform3D, Translation2D};
19use euclid::{Point2D, Point3D, Vector2D, Vector3D, SideOffsets2D, Box2D};
20use euclid::HomogeneousVector;
21use peek_poke::PeekPoke;
22// local imports
23use crate::image::DirtyRect;
24
25/// Geometry in the coordinate system of the render target (screen or intermediate
26/// surface) in physical pixels.
27#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
28pub struct DevicePixel;
29
30pub type DeviceIntRect = Box2D<i32, DevicePixel>;
31pub type DeviceIntPoint = Point2D<i32, DevicePixel>;
32pub type DeviceIntSize = Size2D<i32, DevicePixel>;
33pub type DeviceIntLength = Length<i32, DevicePixel>;
34pub type DeviceIntSideOffsets = SideOffsets2D<i32, DevicePixel>;
35pub type DeviceIntVector2D = Vector2D<i32, DevicePixel>;
36
37pub type DeviceRect = Box2D<f32, DevicePixel>;
38pub type DeviceBox2D = Box2D<f32, DevicePixel>;
39pub type DevicePoint = Point2D<f32, DevicePixel>;
40pub type DeviceVector2D = Vector2D<f32, DevicePixel>;
41pub type DeviceSize = Size2D<f32, DevicePixel>;
42pub type DeviceHomogeneousVector = HomogeneousVector<f32, DevicePixel>;
43
44/// Geometry in the coordinate system of the framebuffer in physical pixels.
45/// It's Y-flipped comparing to DevicePixel.
46#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
47pub struct FramebufferPixel;
48
49pub type FramebufferIntPoint = Point2D<i32, FramebufferPixel>;
50pub type FramebufferIntSize = Size2D<i32, FramebufferPixel>;
51pub type FramebufferIntRect = Box2D<i32, FramebufferPixel>;
52
53/// Geometry in the coordinate system of a Picture.
54#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
55pub struct PicturePixel;
56
57pub type PictureIntRect = Box2D<i32, PicturePixel>;
58pub type PictureIntPoint = Point2D<i32, PicturePixel>;
59pub type PictureIntSize = Size2D<i32, PicturePixel>;
60pub type PictureRect = Box2D<f32, PicturePixel>;
61pub type PicturePoint = Point2D<f32, PicturePixel>;
62pub type PictureSize = Size2D<f32, PicturePixel>;
63pub type PicturePoint3D = Point3D<f32, PicturePixel>;
64pub type PictureVector2D = Vector2D<f32, PicturePixel>;
65pub type PictureVector3D = Vector3D<f32, PicturePixel>;
66pub type PictureBox2D = Box2D<f32, PicturePixel>;
67
68/// Geometry gets rasterized in a given root coordinate space. This
69/// is often the root spatial node (world space), but may be a local
70/// space for a variety of reasons (e.g. perspective).
71#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
72pub struct RasterPixel;
73
74pub type RasterIntRect = Box2D<i32, RasterPixel>;
75pub type RasterIntPoint = Point2D<i32, RasterPixel>;
76pub type RasterIntSize = Size2D<i32, RasterPixel>;
77pub type RasterRect = Box2D<f32, RasterPixel>;
78pub type RasterPoint = Point2D<f32, RasterPixel>;
79pub type RasterSize = Size2D<f32, RasterPixel>;
80pub type RasterPoint3D = Point3D<f32, RasterPixel>;
81pub type RasterVector2D = Vector2D<f32, RasterPixel>;
82pub type RasterVector3D = Vector3D<f32, RasterPixel>;
83
84/// Geometry in a stacking context's local coordinate space (logical pixels).
85#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
86pub struct LayoutPixel;
87
88pub type LayoutRect = Box2D<f32, LayoutPixel>;
89pub type LayoutPoint = Point2D<f32, LayoutPixel>;
90pub type LayoutPoint3D = Point3D<f32, LayoutPixel>;
91pub type LayoutVector2D = Vector2D<f32, LayoutPixel>;
92pub type LayoutVector3D = Vector3D<f32, LayoutPixel>;
93pub type LayoutSize = Size2D<f32, LayoutPixel>;
94pub type LayoutSideOffsets = SideOffsets2D<f32, LayoutPixel>;
95
96pub type LayoutIntRect = Box2D<i32, LayoutPixel>;
97pub type LayoutIntPoint = Point2D<i32, LayoutPixel>;
98pub type LayoutIntSize = Size2D<i32, LayoutPixel>;
99
100/// Geometry in the document's coordinate space (logical pixels).
101#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
102pub struct WorldPixel;
103
104pub type WorldRect = Box2D<f32, WorldPixel>;
105pub type WorldIntRect = Box2D<i32, WorldPixel>;
106pub type WorldPoint = Point2D<f32, WorldPixel>;
107pub type WorldSize = Size2D<f32, WorldPixel>;
108pub type WorldPoint3D = Point3D<f32, WorldPixel>;
109pub type WorldVector2D = Vector2D<f32, WorldPixel>;
110pub type WorldVector3D = Vector3D<f32, WorldPixel>;
111
112/// Geometry in the space in which we decided to perform visibility/clipping/invalidation
113/// calculations.
114/// This is intended to be a temporary type while transitioning some calculation from world
115/// to raster space.
116#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
117pub struct VisPixel;
118
119pub type VisRect = Box2D<f32, VisPixel>;
120
121/// TODO: Remove this once visibility rects have moved to raster space.
122pub fn vis_rect_as_world(r: VisRect) -> WorldRect {
123    r.cast_unit()
124}
125
126
127/// Offset in number of tiles.
128#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
129pub struct Tiles;
130pub type TileOffset = Point2D<i32, Tiles>;
131pub type TileRange = Box2D<i32, Tiles>;
132
133/// Scaling ratio from world pixels to device pixels.
134pub type DevicePixelScale = Scale<f32, WorldPixel, DevicePixel>;
135/// Scaling ratio from layout to world. Used for cases where we know the layout
136/// is in world space, or specifically want to treat it this way.
137pub type LayoutToWorldScale = Scale<f32, LayoutPixel, WorldPixel>;
138/// A complete scaling ratio from layout space to device pixel space.
139pub type LayoutToDeviceScale = Scale<f32, LayoutPixel, DevicePixel>;
140
141pub type LayoutTransform = Transform3D<f32, LayoutPixel, LayoutPixel>;
142pub type LayoutToWorldTransform = Transform3D<f32, LayoutPixel, WorldPixel>;
143pub type WorldToLayoutTransform = Transform3D<f32, WorldPixel, LayoutPixel>;
144pub type LayoutToVisTransform = Transform3D<f32, LayoutPixel, VisPixel>;
145
146pub type LayoutToPictureTransform = Transform3D<f32, LayoutPixel, PicturePixel>;
147pub type PictureToLayoutTransform = Transform3D<f32, PicturePixel, LayoutPixel>;
148
149pub type LayoutToRasterTransform = Transform3D<f32, LayoutPixel, RasterPixel>;
150pub type RasterToLayoutTransform = Transform3D<f32, RasterPixel, LayoutPixel>;
151
152pub type PictureToRasterTransform = Transform3D<f32, PicturePixel, RasterPixel>;
153pub type RasterToPictureTransform = Transform3D<f32, RasterPixel, PicturePixel>;
154
155/// Scaling ratio from picture pixels to raster pixels (e.g. if scaling a picture surface up/down).
156pub type RasterPixelScale = Scale<f32, PicturePixel, RasterPixel>;
157
158// Fixed position coordinates, to avoid float precision errors.
159pub type LayoutPointAu = Point2D<Au, LayoutPixel>;
160pub type LayoutRectAu = Box2D<Au, LayoutPixel>;
161pub type LayoutSizeAu = Size2D<Au, LayoutPixel>;
162pub type LayoutVector2DAu = Vector2D<Au, LayoutPixel>;
163pub type LayoutSideOffsetsAu = SideOffsets2D<Au, LayoutPixel>;
164
165pub type ImageDirtyRect = DirtyRect<i32, DevicePixel>;
166pub type BlobDirtyRect = DirtyRect<i32, LayoutPixel>;
167
168pub type BlobToDeviceTranslation = Translation2D<i32, LayoutPixel, DevicePixel>;
169
170/// Stores two coordinates in texel space. The coordinates
171/// are stored in texel coordinates because the texture atlas
172/// may grow. Storing them as texel coords and normalizing
173/// the UVs in the vertex shader means nothing needs to be
174/// updated on the CPU when the texture size changes.
175#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
176#[repr(C)]
177pub struct TexelRect {
178    pub uv0: DevicePoint,
179    pub uv1: DevicePoint,
180}
181
182impl TexelRect {
183    pub fn new(u0: f32, v0: f32, u1: f32, v1: f32) -> Self {
184        TexelRect {
185            uv0: DevicePoint::new(u0, v0),
186            uv1: DevicePoint::new(u1, v1),
187        }
188    }
189
190    pub fn invalid() -> Self {
191        TexelRect {
192            uv0: DevicePoint::new(-1.0, -1.0),
193            uv1: DevicePoint::new(-1.0, -1.0),
194        }
195    }
196
197    pub fn to_array(&self) -> [f32; 4] {
198        [
199            self.uv0.x,
200            self.uv0.y,
201            self.uv1.x,
202            self.uv1.y,
203        ]
204    }
205
206    pub fn is_empty(&self) -> bool {
207        self.uv1.x <= self.uv0.x || self.uv1.y <= self.uv0.y
208    }
209}
210
211impl Into<TexelRect> for DeviceIntRect {
212    fn into(self) -> TexelRect {
213        TexelRect {
214            uv0: self.min.to_f32(),
215            uv1: self.max.to_f32(),
216        }
217    }
218}
219
220const MAX_AU_FLOAT: f32 = 1.0e6;
221
222pub trait AuHelpers<T> {
223    fn from_au(data: T) -> Self;
224    fn to_au(&self) -> T;
225}
226
227impl AuHelpers<LayoutSizeAu> for LayoutSize {
228    fn from_au(size: LayoutSizeAu) -> Self {
229        LayoutSize::new(
230            size.width.to_f32_px(),
231            size.height.to_f32_px(),
232        )
233    }
234
235    fn to_au(&self) -> LayoutSizeAu {
236        let width = self.width.min(2.0 * MAX_AU_FLOAT);
237        let height = self.height.min(2.0 * MAX_AU_FLOAT);
238
239        LayoutSizeAu::new(
240            Au::from_f32_px(width),
241            Au::from_f32_px(height),
242        )
243    }
244}
245
246impl AuHelpers<LayoutVector2DAu> for LayoutVector2D {
247    fn from_au(size: LayoutVector2DAu) -> Self {
248        LayoutVector2D::new(
249            size.x.to_f32_px(),
250            size.y.to_f32_px(),
251        )
252    }
253
254    fn to_au(&self) -> LayoutVector2DAu {
255        LayoutVector2DAu::new(
256            Au::from_f32_px(self.x),
257            Au::from_f32_px(self.y),
258        )
259    }
260}
261
262impl AuHelpers<LayoutPointAu> for LayoutPoint {
263    fn from_au(point: LayoutPointAu) -> Self {
264        LayoutPoint::new(
265            point.x.to_f32_px(),
266            point.y.to_f32_px(),
267        )
268    }
269
270    fn to_au(&self) -> LayoutPointAu {
271        let x = self.x.clamp(-MAX_AU_FLOAT, MAX_AU_FLOAT);
272        let y = self.y.clamp(-MAX_AU_FLOAT, MAX_AU_FLOAT);
273
274        LayoutPointAu::new(
275            Au::from_f32_px(x),
276            Au::from_f32_px(y),
277        )
278    }
279}
280
281impl AuHelpers<LayoutRectAu> for LayoutRect {
282    fn from_au(rect: LayoutRectAu) -> Self {
283        LayoutRect {
284            min: LayoutPoint::from_au(rect.min),
285            max: LayoutPoint::from_au(rect.max),
286        }
287    }
288
289    fn to_au(&self) -> LayoutRectAu {
290        LayoutRectAu {
291            min: self.min.to_au(),
292            max: self.max.to_au(),
293        }
294    }
295}
296
297impl AuHelpers<LayoutSideOffsetsAu> for LayoutSideOffsets {
298    fn from_au(offsets: LayoutSideOffsetsAu) -> Self {
299        LayoutSideOffsets::new(
300            offsets.top.to_f32_px(),
301            offsets.right.to_f32_px(),
302            offsets.bottom.to_f32_px(),
303            offsets.left.to_f32_px(),
304        )
305    }
306
307    fn to_au(&self) -> LayoutSideOffsetsAu {
308        LayoutSideOffsetsAu::new(
309            Au::from_f32_px(self.top),
310            Au::from_f32_px(self.right),
311            Au::from_f32_px(self.bottom),
312            Au::from_f32_px(self.left),
313        )
314    }
315}
316
317pub trait RectExt {
318    type Point;
319    fn top_left(&self) -> Self::Point;
320    fn top_right(&self) -> Self::Point;
321    fn bottom_left(&self) -> Self::Point;
322    fn bottom_right(&self) -> Self::Point;
323}
324
325impl<U> RectExt for Rect<f32, U> {
326    type Point = Point2D<f32, U>;
327    fn top_left(&self) -> Self::Point {
328        self.min()
329    }
330    fn top_right(&self) -> Self::Point {
331        Point2D::new(self.max_x(), self.min_y())
332    }
333    fn bottom_left(&self) -> Self::Point {
334        Point2D::new(self.min_x(), self.max_y())
335    }
336    fn bottom_right(&self) -> Self::Point {
337        self.max()
338    }
339}
340
341impl<U> RectExt for Box2D<f32, U> {
342    type Point = Point2D<f32, U>;
343    fn top_left(&self) -> Self::Point {
344        self.min
345    }
346    fn top_right(&self) -> Self::Point {
347        Point2D::new(self.max.x, self.min.y)
348    }
349    fn bottom_left(&self) -> Self::Point {
350        Point2D::new(self.min.x, self.max.y)
351    }
352    fn bottom_right(&self) -> Self::Point {
353        self.max
354    }
355}
356
357// A few helpers to convert to cast between coordinate spaces that are often equivalent.
358
359#[inline]
360pub fn layout_rect_as_picture_rect(layout_rect: &LayoutRect) -> PictureRect {
361    layout_rect.cast_unit()
362}
363
364#[inline]
365pub fn layout_vector_as_picture_vector(layout_vector: LayoutVector2D) -> PictureVector2D {
366    layout_vector.cast_unit()
367}
368
369#[inline]
370pub fn device_size_as_framebuffer_size(framebuffer_size: DeviceIntSize) -> FramebufferIntSize {
371    framebuffer_size.cast_unit()
372}
373
374#[inline]
375pub fn device_rect_as_framebuffer_rect(framebuffer_rect: &DeviceIntRect) -> FramebufferIntRect {
376    framebuffer_rect.cast_unit()
377}