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 }