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