webrender_api/
image.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#![deny(missing_docs)]
6
7use euclid::{size2, Box2D, num::Zero};
8use peek_poke::PeekPoke;
9use std::ops::{Add, Sub};
10use std::sync::Arc;
11// local imports
12use crate::{IdNamespace, TileSize};
13use crate::font::{FontInstanceKey, FontInstanceData, FontKey, FontTemplate};
14use crate::units::*;
15
16/// The default tile size for blob images and regular images larger than
17/// the maximum texture size.
18pub const DEFAULT_TILE_SIZE: TileSize = 512;
19
20/// An opaque identifier describing an image registered with WebRender.
21/// This is used as a handle to reference images, and is used as the
22/// hash map key for the actual image storage in the `ResourceCache`.
23#[repr(C)]
24#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
25pub struct ImageKey(pub IdNamespace, pub u32);
26
27impl Default for ImageKey {
28    fn default() -> Self {
29        ImageKey::DUMMY
30    }
31}
32
33impl ImageKey {
34    /// Placeholder Image key, used to represent None.
35    pub const DUMMY: Self = ImageKey(IdNamespace(0), 0);
36
37    /// Mints a new ImageKey. The given ID must be unique.
38    pub fn new(namespace: IdNamespace, key: u32) -> Self {
39        ImageKey(namespace, key)
40    }
41}
42
43/// An opaque identifier describing a blob image registered with WebRender.
44/// This is used as a handle to reference blob images, and can be used as an
45/// image in display items.
46#[repr(C)]
47#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
48pub struct BlobImageKey(pub ImageKey);
49
50impl BlobImageKey {
51    /// Interpret this blob image as an image for a display item.
52    pub fn as_image(self) -> ImageKey {
53        self.0
54    }
55}
56
57/// An opaque identifier describing a snapshot image registered with WebRender.
58/// This is used as a handle to reference snapshot images, and can be used as an
59/// image in display items.
60#[repr(C)]
61#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
62pub struct SnapshotImageKey(pub ImageKey);
63
64impl SnapshotImageKey {
65    /// Interpret this snapshot image as an image for a display item.
66    pub fn as_image(self) -> ImageKey {
67        self.0
68    }
69}
70
71impl Default for SnapshotImageKey {
72    fn default() -> Self {
73        SnapshotImageKey(ImageKey::DUMMY)
74    }
75}
76
77/// An arbitrary identifier for an external image provided by the
78/// application. It must be a unique identifier for each external
79/// image.
80#[repr(C)]
81#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
82pub struct ExternalImageId(pub u64);
83
84/// The source for an external image.
85pub enum ExternalImageSource<'a> {
86    /// A raw pixel buffer.
87    RawData(&'a [u8]),
88    /// A gl::GLuint texture handle.
89    NativeTexture(u32),
90    /// An invalid source.
91    Invalid,
92}
93
94/// The data that an external client should provide about
95/// an external image. For instance, if providing video frames,
96/// the application could call wr.render() whenever a new
97/// video frame is ready. Note that the UV coords are either normalized or
98/// unnormalized depending on the value of normalized_uvs in the corresponding
99/// ExternalImageData.
100pub struct ExternalImage<'a> {
101    /// UV coordinates for the image.
102    pub uv: TexelRect,
103    /// The source for this image's contents.
104    pub source: ExternalImageSource<'a>,
105}
106
107/// The interfaces that an application can implement to support providing
108/// external image buffers.
109/// When the application passes an external image to WR, it should keep that
110/// external image life time. People could check the epoch id in RenderNotifier
111/// at the client side to make sure that the external image is not used by WR.
112/// Then, do the clean up for that external image.
113pub trait ExternalImageHandler {
114    /// Lock the external image. Then, WR could start to read the image content.
115    /// The WR client should not change the image content until the unlock()
116    /// call.
117    fn lock(&mut self, key: ExternalImageId, channel_index: u8) -> ExternalImage;
118    /// Unlock the external image. WR should not read the image content
119    /// after this call.
120    fn unlock(&mut self, key: ExternalImageId, channel_index: u8);
121}
122
123/// Specifies the type of texture target in driver terms.
124#[repr(u8)]
125#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
126pub enum ImageBufferKind {
127    /// Standard texture. This maps to GL_TEXTURE_2D in OpenGL.
128    Texture2D = 0,
129    /// Rectangle texture. This maps to GL_TEXTURE_RECTANGLE in OpenGL. This
130    /// is similar to a standard texture, with a few subtle differences
131    /// (no mipmaps, non-power-of-two dimensions, different coordinate space)
132    /// that make it useful for representing the kinds of textures we use
133    /// in WebRender. See https://www.khronos.org/opengl/wiki/Rectangle_Texture
134    /// for background on Rectangle textures.
135    TextureRect = 1,
136    /// External texture. This maps to GL_TEXTURE_EXTERNAL_OES in OpenGL, which
137    /// is an extension. This is used for image formats that OpenGL doesn't
138    /// understand, particularly YUV. See
139    /// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
140    TextureExternal = 2,
141    /// External texture which is forced to be converted from YUV to RGB using BT709 colorspace.
142    /// This maps to GL_TEXTURE_EXTERNAL_OES in OpenGL, using the EXT_YUV_TARGET extension.
143    /// https://registry.khronos.org/OpenGL/extensions/EXT/EXT_YUV_target.txt
144    TextureExternalBT709 = 3,
145}
146
147/// Storage format identifier for externally-managed images.
148#[repr(u8)]
149#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
150pub enum ExternalImageType {
151    /// The image is texture-backed.
152    TextureHandle(ImageBufferKind),
153    /// The image is heap-allocated by the embedding.
154    Buffer,
155}
156
157/// Descriptor for external image resources. See `ImageData`.
158#[repr(C)]
159#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
160pub struct ExternalImageData {
161    /// The identifier of this external image, provided by the embedding.
162    pub id: ExternalImageId,
163    /// For multi-plane images (i.e. YUV), indicates the plane of the
164    /// original image that this struct represents. 0 for single-plane images.
165    pub channel_index: u8,
166    /// Storage format identifier.
167    pub image_type: ExternalImageType,
168    /// Whether UV coordinates used with this image are normalized.
169    pub normalized_uvs: bool,
170}
171
172/// Specifies the format of a series of pixels, in driver terms.
173#[repr(u8)]
174#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
175pub enum ImageFormat {
176    /// One-channel, byte storage. The "red" doesn't map to the color
177    /// red per se, and is just the way that OpenGL has historically referred
178    /// to single-channel buffers.
179    R8 = 1,
180    /// One-channel, short storage
181    R16 = 2,
182    /// Four channels, byte storage.
183    BGRA8 = 3,
184    /// Four channels, float storage.
185    RGBAF32 = 4,
186    /// Two-channels, byte storage. Similar to `R8`, this just means
187    /// "two channels" rather than "red and green".
188    RG8 = 5,
189    /// Two-channels, short storage. Similar to `R16`, this just means
190    /// "two channels" rather than "red and green".
191    RG16 = 6,
192
193    /// Four channels, signed integer storage.
194    RGBAI32 = 7,
195    /// Four channels, byte storage.
196    RGBA8 = 8,
197}
198
199impl ImageFormat {
200    /// Returns the number of bytes per pixel for the given format.
201    pub fn bytes_per_pixel(self) -> i32 {
202        match self {
203            ImageFormat::R8 => 1,
204            ImageFormat::R16 => 2,
205            ImageFormat::BGRA8 => 4,
206            ImageFormat::RGBAF32 => 16,
207            ImageFormat::RG8 => 2,
208            ImageFormat::RG16 => 4,
209            ImageFormat::RGBAI32 => 16,
210            ImageFormat::RGBA8 => 4,
211        }
212    }
213}
214
215/// Specifies the color depth of an image. Currently only used for YUV images.
216#[repr(u8)]
217#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
218pub enum ColorDepth {
219    /// 8 bits image (most common)
220    #[default]
221    Color8,
222    /// 10 bits image
223    Color10,
224    /// 12 bits image
225    Color12,
226    /// 16 bits image
227    Color16,
228}
229
230impl ColorDepth {
231    /// Return the numerical bit depth value for the type.
232    pub fn bit_depth(self) -> u32 {
233        match self {
234            ColorDepth::Color8 => 8,
235            ColorDepth::Color10 => 10,
236            ColorDepth::Color12 => 12,
237            ColorDepth::Color16 => 16,
238        }
239    }
240    /// 10 and 12 bits images are encoded using 16 bits integer, we need to
241    /// rescale the 10 or 12 bits value to extend to 16 bits.
242    pub fn rescaling_factor(self) -> f32 {
243        match self {
244            ColorDepth::Color8 => 1.0,
245            ColorDepth::Color10 => 64.0,
246            ColorDepth::Color12 => 16.0,
247            ColorDepth::Color16 => 1.0,
248        }
249    }
250}
251
252bitflags! {
253    /// Various flags that are part of an image descriptor.
254    #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, Serialize)]
255    pub struct ImageDescriptorFlags: u32 {
256        /// Whether this image is opaque, or has an alpha channel. Avoiding blending
257        /// for opaque surfaces is an important optimization.
258        const IS_OPAQUE = 1;
259        /// Whether to allow the driver to automatically generate mipmaps. If images
260        /// are already downscaled appropriately, mipmap generation can be wasted
261        /// work, and cause performance problems on some cards/drivers.
262        ///
263        /// See https://github.com/servo/webrender/pull/2555/
264        const ALLOW_MIPMAPS = 2;
265    }
266}
267
268/// Metadata (but not storage) describing an image In WebRender.
269#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
270pub struct ImageDescriptor {
271    /// Format of the image data.
272    pub format: ImageFormat,
273    /// Width and length of the image data, in pixels.
274    pub size: DeviceIntSize,
275    /// The number of bytes from the start of one row to the next. If non-None,
276    /// `compute_stride` will return this value, otherwise it returns
277    /// `width * bpp`. Different source of images have different alignment
278    /// constraints for rows, so the stride isn't always equal to width * bpp.
279    pub stride: Option<i32>,
280    /// Offset in bytes of the first pixel of this image in its backing buffer.
281    /// This is used for tiling, wherein WebRender extracts chunks of input images
282    /// in order to cache, manipulate, and render them individually. This offset
283    /// tells the texture upload machinery where to find the bytes to upload for
284    /// this tile. Non-tiled images generally set this to zero.
285    pub offset: i32,
286    /// Various bool flags related to this descriptor.
287    pub flags: ImageDescriptorFlags,
288}
289
290impl ImageDescriptor {
291    /// Mints a new ImageDescriptor.
292    pub fn new(
293        width: i32,
294        height: i32,
295        format: ImageFormat,
296        flags: ImageDescriptorFlags,
297    ) -> Self {
298        ImageDescriptor {
299            size: size2(width, height),
300            format,
301            stride: None,
302            offset: 0,
303            flags,
304        }
305    }
306
307    /// Returns the stride, either via an explicit stride stashed on the object
308    /// or by the default computation.
309    pub fn compute_stride(&self) -> i32 {
310        self.stride.unwrap_or(self.size.width * self.format.bytes_per_pixel())
311    }
312
313    /// Computes the total size of the image, in bytes.
314    pub fn compute_total_size(&self) -> i32 {
315        self.compute_stride() * self.size.height
316    }
317
318    /// Computes the bounding rectangle for the image, rooted at (0, 0).
319    pub fn full_rect(&self) -> DeviceIntRect {
320        DeviceIntRect::from_origin_and_size(
321            DeviceIntPoint::zero(),
322            self.size,
323        )
324    }
325
326    /// Returns true if this descriptor is opaque
327    pub fn is_opaque(&self) -> bool {
328        self.flags.contains(ImageDescriptorFlags::IS_OPAQUE)
329    }
330
331    /// Returns true if this descriptor allows mipmaps
332    pub fn allow_mipmaps(&self) -> bool {
333        self.flags.contains(ImageDescriptorFlags::ALLOW_MIPMAPS)
334    }
335}
336
337/// Represents the backing store of an arbitrary series of pixels for display by
338/// WebRender. This storage can take several forms.
339#[derive(Clone, Debug, Serialize, Deserialize)]
340pub enum ImageData {
341    /// A simple series of bytes, provided by the embedding and owned by WebRender.
342    /// The format is stored out-of-band, currently in ImageDescriptor.
343    Raw(#[serde(with = "serde_image_data_raw")] Arc<Vec<u8>>),
344    /// An image owned by the embedding, and referenced by WebRender. This may
345    /// take the form of a texture or a heap-allocated buffer.
346    External(ExternalImageData),
347}
348
349mod serde_image_data_raw {
350    extern crate serde_bytes;
351
352    use std::sync::Arc;
353    use serde::{Deserializer, Serializer};
354
355    pub fn serialize<S: Serializer>(bytes: &Arc<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
356        serde_bytes::serialize(bytes.as_slice(), serializer)
357    }
358
359    pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Arc<Vec<u8>>, D::Error> {
360        serde_bytes::deserialize(deserializer).map(Arc::new)
361    }
362}
363
364impl ImageData {
365    /// Mints a new raw ImageData, taking ownership of the bytes.
366    pub fn new(bytes: Vec<u8>) -> Self {
367        ImageData::Raw(Arc::new(bytes))
368    }
369
370    /// Mints a new raw ImageData from Arc-ed bytes.
371    pub fn new_shared(bytes: Arc<Vec<u8>>) -> Self {
372        ImageData::Raw(bytes)
373    }
374}
375
376/// The resources exposed by the resource cache available for use by the blob rasterizer.
377pub trait BlobImageResources {
378    /// Returns the `FontTemplate` for the given key.
379    fn get_font_data(&self, key: FontKey) -> Option<FontTemplate>;
380    /// Returns the `FontInstanceData` for the given key, if found.
381    fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData>;
382}
383
384/// A handler on the render backend that can create rasterizer objects which will
385/// be sent to the scene builder thread to execute the rasterization.
386///
387/// The handler is responsible for collecting resources, managing/updating blob commands
388/// and creating the rasterizer objects, but isn't expected to do any rasterization itself.
389pub trait BlobImageHandler: Send {
390    /// Creates a snapshot of the current state of blob images in the handler.
391    fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer>;
392
393    /// Creates an empty blob handler of the same type.
394    ///
395    /// This is used to allow creating new API endpoints with blob handlers installed on them.
396    fn create_similar(&self) -> Box<dyn BlobImageHandler>;
397
398    /// A hook to let the blob image handler update any state related to resources that
399    /// are not bundled in the blob recording itself.
400    fn prepare_resources(
401        &mut self,
402        services: &dyn BlobImageResources,
403        requests: &[BlobImageParams],
404    );
405
406    /// Register a blob image.
407    fn add(&mut self, key: BlobImageKey, data: Arc<BlobImageData>, visible_rect: &DeviceIntRect,
408           tile_size: TileSize);
409
410    /// Update an already registered blob image.
411    fn update(&mut self, key: BlobImageKey, data: Arc<BlobImageData>, visible_rect: &DeviceIntRect,
412              dirty_rect: &BlobDirtyRect);
413
414    /// Delete an already registered blob image.
415    fn delete(&mut self, key: BlobImageKey);
416
417    /// A hook to let the handler clean up any state related to a font which the resource
418    /// cache is about to delete.
419    fn delete_font(&mut self, key: FontKey);
420
421    /// A hook to let the handler clean up any state related to a font instance which the
422    /// resource cache is about to delete.
423    fn delete_font_instance(&mut self, key: FontInstanceKey);
424
425    /// A hook to let the handler clean up any state related a given namespace before the
426    /// resource cache deletes them.
427    fn clear_namespace(&mut self, namespace: IdNamespace);
428
429    /// Whether to allow rendering blobs on multiple threads.
430    fn enable_multithreading(&mut self, enable: bool);
431}
432
433/// A group of rasterization requests to execute synchronously on the scene builder thread.
434pub trait AsyncBlobImageRasterizer : Send {
435    /// Rasterize the requests.
436    ///
437    /// Gecko uses te priority hint to schedule work in a way that minimizes the risk
438    /// of high priority work being blocked by (or enqued behind) low priority work.
439    fn rasterize(
440        &mut self,
441        requests: &[BlobImageParams],
442        low_priority: bool,
443        tile_pool: &mut crate::BlobTilePool,
444    ) -> Vec<(BlobImageRequest, BlobImageResult)>;
445}
446
447
448/// Input parameters for the BlobImageRasterizer.
449#[derive(Copy, Clone, Debug)]
450pub struct BlobImageParams {
451    /// A key that identifies the blob image rasterization request.
452    pub request: BlobImageRequest,
453    /// Description of the format of the blob's output image.
454    pub descriptor: BlobImageDescriptor,
455    /// An optional sub-rectangle of the image to avoid re-rasterizing
456    /// the entire image when only a portion is updated.
457    ///
458    /// If set to None the entire image is rasterized.
459    pub dirty_rect: BlobDirtyRect,
460}
461
462/// The possible states of a Dirty rect.
463///
464/// This exists because people kept getting confused with `Option<Box2D>`.
465#[derive(Debug, Serialize, Deserialize)]
466pub enum DirtyRect<T: Copy, U> {
467    /// Everything is Dirty, equivalent to Partial(image_bounds)
468    All,
469    /// Some specific amount is dirty
470    Partial(Box2D<T, U>)
471}
472
473impl<T, U> DirtyRect<T, U>
474where
475    T: Copy + Clone
476        + PartialOrd + PartialEq
477        + Add<T, Output = T>
478        + Sub<T, Output = T>
479        + Zero
480{
481    /// Creates an empty DirtyRect (indicating nothing is invalid)
482    pub fn empty() -> Self {
483        DirtyRect::Partial(Box2D::zero())
484    }
485
486    /// Returns whether the dirty rect is empty
487    pub fn is_empty(&self) -> bool {
488        match self {
489            DirtyRect::All => false,
490            DirtyRect::Partial(rect) => rect.is_empty(),
491        }
492    }
493
494    /// Replaces self with the empty rect and returns the old value.
495    pub fn replace_with_empty(&mut self) -> Self {
496        ::std::mem::replace(self, DirtyRect::empty())
497    }
498
499    /// Maps over the contents of Partial.
500    pub fn map<F>(self, func: F) -> Self
501        where F: FnOnce(Box2D<T, U>) -> Box2D<T, U>,
502    {
503        use crate::DirtyRect::*;
504
505        match self {
506            All        => All,
507            Partial(rect) => Partial(func(rect)),
508        }
509    }
510
511    /// Unions the dirty rects.
512    pub fn union(&self, other: &Self) -> Self {
513        use crate::DirtyRect::*;
514
515        match (*self, *other) {
516            (All, _) | (_, All)        => All,
517            (Partial(rect1), Partial(rect2)) => Partial(rect1.union(&rect2)),
518        }
519    }
520
521    /// Intersects the dirty rects.
522    pub fn intersection(&self, other: &Self) -> Self {
523        use crate::DirtyRect::*;
524
525        match (*self, *other) {
526            (All, rect) | (rect, All)  => rect,
527            (Partial(rect1), Partial(rect2)) => {
528                Partial(rect1.intersection(&rect2).unwrap_or_else(Box2D::zero))
529            }
530        }
531    }
532
533    /// Converts the dirty rect into a subrect of the given one via intersection.
534    pub fn to_subrect_of(&self, rect: &Box2D<T, U>) -> Box2D<T, U> {
535        use crate::DirtyRect::*;
536
537        match *self {
538            All => *rect,
539            Partial(dirty_rect) => {
540                dirty_rect.intersection(rect).unwrap_or_else(Box2D::zero)
541            }
542        }
543    }
544}
545
546impl<T: Copy, U> Copy for DirtyRect<T, U> {}
547impl<T: Copy, U> Clone for DirtyRect<T, U> {
548    fn clone(&self) -> Self { *self }
549}
550
551impl<T: Copy, U> From<Box2D<T, U>> for DirtyRect<T, U> {
552    fn from(rect: Box2D<T, U>) -> Self {
553        DirtyRect::Partial(rect)
554    }
555}
556
557/// Backing store for blob image command streams.
558pub type BlobImageData = Vec<u8>;
559
560/// Result type for blob raserization.
561pub type BlobImageResult = Result<RasterizedBlobImage, BlobImageError>;
562
563/// Metadata (but not storage) for a blob image.
564#[repr(C)]
565#[derive(Copy, Clone, Debug)]
566pub struct BlobImageDescriptor {
567    /// Surface of the image or tile to render in the same coordinate space as
568    /// the drawing commands.
569    pub rect: LayoutIntRect,
570    /// Format for the data in the backing store.
571    pub format: ImageFormat,
572}
573
574/// Representation of a rasterized blob image. This is obtained by passing
575/// `BlobImageData` to the embedding via the rasterization callback.
576pub struct RasterizedBlobImage {
577    /// The rectangle that was rasterized in device pixels, relative to the
578    /// image or tile.
579    pub rasterized_rect: DeviceIntRect,
580    /// Backing store. The format is stored out of band in `BlobImageDescriptor`.
581    pub data: Arc<Vec<u8>>,
582}
583
584/// Error code for when blob rasterization failed.
585#[derive(Clone, Debug)]
586pub enum BlobImageError {
587    /// Out of memory.
588    Oom,
589    /// Other failure, embedding-specified.
590    Other(String),
591}
592
593
594
595/// A key identifying blob image rasterization work requested from the blob
596/// image rasterizer.
597#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
598pub struct BlobImageRequest {
599    /// Unique handle to the image.
600    pub key: BlobImageKey,
601    /// Tiling offset in number of tiles.
602    pub tile: TileOffset,
603}