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