tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

image.rs (21466B)


      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 
      7 use euclid::{size2, Box2D, num::Zero};
      8 use peek_poke::PeekPoke;
      9 use std::ops::{Add, Sub};
     10 use std::sync::Arc;
     11 // local imports
     12 use crate::{IdNamespace, TileSize};
     13 use crate::font::{FontInstanceKey, FontInstanceData, FontKey, FontTemplate};
     14 use crate::units::*;
     15 
     16 /// The default tile size for blob images and regular images larger than
     17 /// the maximum texture size.
     18 pub 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)]
     25 pub struct ImageKey(pub IdNamespace, pub u32);
     26 
     27 impl Default for ImageKey {
     28    fn default() -> Self {
     29        ImageKey::DUMMY
     30    }
     31 }
     32 
     33 impl 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)]
     48 pub struct BlobImageKey(pub ImageKey);
     49 
     50 impl 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)]
     62 pub struct SnapshotImageKey(pub ImageKey);
     63 
     64 impl 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 
     71 impl 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)]
     82 pub struct ExternalImageId(pub u64);
     83 
     84 /// The source for an external image.
     85 pub 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.
    100 pub 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.
    113 pub 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, is_composited: bool) -> 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)]
    126 pub 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)]
    150 pub 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)]
    160 pub 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)]
    175 pub 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 
    199 impl 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)]
    218 pub 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 
    230 impl 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 
    252 bitflags! {
    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)]
    270 pub 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 
    290 impl 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)]
    340 pub 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 
    349 mod 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 
    364 impl 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.
    377 pub 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.
    389 pub 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.
    434 pub 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)]
    450 pub 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)]
    466 pub 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 
    473 impl<T, U> DirtyRect<T, U>
    474 where
    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 
    546 impl<T: Copy, U> Copy for DirtyRect<T, U> {}
    547 impl<T: Copy, U> Clone for DirtyRect<T, U> {
    548    fn clone(&self) -> Self { *self }
    549 }
    550 
    551 impl<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.
    558 pub type BlobImageData = Vec<u8>;
    559 
    560 /// Result type for blob raserization.
    561 pub type BlobImageResult = Result<RasterizedBlobImage, BlobImageError>;
    562 
    563 /// Metadata (but not storage) for a blob image.
    564 #[repr(C)]
    565 #[derive(Copy, Clone, Debug)]
    566 pub 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.
    576 pub 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)]
    586 pub 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)]
    598 pub struct BlobImageRequest {
    599    /// Unique handle to the image.
    600    pub key: BlobImageKey,
    601    /// Tiling offset in number of tiles.
    602    pub tile: TileOffset,
    603 }