Skip to content

Instantly share code, notes, and snippets.

@Gankra
Created October 3, 2018 04:02
Show Gist options
  • Save Gankra/f42431879ab70656f42f1a6c56a2f666 to your computer and use it in GitHub Desktop.
Save Gankra/f42431879ab70656f42f1a6c56a2f666 to your computer and use it in GitHub Desktop.
diff --git a/gfx/webrender/src/glyph_rasterizer/no_pathfinder.rs b/gfx/webrender/src/glyph_rasterizer/no_pathfinder.rs
index abdc2a7736f8..b75ae10cd293 100644
--- a/gfx/webrender/src/glyph_rasterizer/no_pathfinder.rs
+++ b/gfx/webrender/src/glyph_rasterizer/no_pathfinder.rs
@@ -5,7 +5,7 @@
//! Module only available when pathfinder is deactivated when webrender is
//! compiled regularly (i.e. any configuration without feature = "pathfinder")
-use api::{ImageData, ImageDescriptor, ImageFormat};
+use api::{DirtyRect, ImageData, ImageDescriptor, ImageFormat};
use device::TextureFilter;
use euclid::size2;
use gpu_types::UvRectKind;
@@ -184,7 +184,7 @@ impl GlyphRasterizer {
TextureFilter::Linear,
Some(ImageData::Raw(Arc::new(glyph.bytes))),
[glyph.left, -glyph.top, glyph.scale],
- None,
+ DirtyRect::AllDirty,
gpu_cache,
Some(glyph_key_cache.eviction_notice()),
UvRectKind::Rect,
diff --git a/gfx/webrender/src/render_task.rs b/gfx/webrender/src/render_task.rs
index 1f0fab652da9..88fcc92dc9e1 100644
--- a/gfx/webrender/src/render_task.rs
+++ b/gfx/webrender/src/render_task.rs
@@ -2,7 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize, DeviceIntSideOffsets, ImageDescriptor, ImageFormat};
+use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize};
+use api::{DeviceIntSideOffsets, DirtyRect, ImageDescriptor, ImageFormat};
#[cfg(feature = "pathfinder")]
use api::FontRenderMode;
use border::BorderCacheKey;
@@ -1149,7 +1150,7 @@ impl RenderTaskCache {
TextureFilter::Linear,
None,
entry.user_data.unwrap_or([0.0; 3]),
- None,
+ DirtyRect::AllDirty,
gpu_cache,
None,
render_task.uv_rect_kind(),
diff --git a/gfx/webrender/src/resource_cache.rs b/gfx/webrender/src/resource_cache.rs
index 3ee4f82a5fc0..112317a725ed 100644
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.rs
@@ -5,7 +5,7 @@
use api::{AddFont, BlobImageResources, AsyncBlobImageRasterizer, ResourceUpdate};
use api::{BlobImageDescriptor, BlobImageHandler, BlobImageRequest, RasterizedBlobImage};
use api::{ClearCache, ColorF, DevicePoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
-use api::{FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
+use api::{DirtyRect, FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
use api::{ExternalImageData, ExternalImageType, BlobImageResult, BlobImageParams};
use api::{FontInstanceData, FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
use api::{GlyphDimensions, IdNamespace};
@@ -111,7 +111,7 @@ enum RasterizedBlob {
struct BlobImageTemplate {
descriptor: ImageDescriptor,
tiling: Option<TileSize>,
- dirty_rect: Option<DeviceUintRect>,
+ dirty_rect: DirtyRect,
viewport_tiles: Option<TileRange>,
}
@@ -155,7 +155,7 @@ impl ImageTemplates {
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct CachedImageInfo {
texture_cache_handle: TextureCacheHandle,
- dirty_rect: Option<DeviceUintRect>,
+ dirty_rect: DirtyRect,
}
#[cfg_attr(feature = "capture", derive(Serialize))]
@@ -165,44 +165,36 @@ pub struct ResourceClassCache<K: Hash + Eq, V, U: Default> {
pub user_data: U,
}
+/// Computes the intersection of the dirty rect with the given tile, and then
+/// normalizes it to the tile's local coordinate space.
pub fn intersect_for_tile(
- dirty: DeviceUintRect,
+ dirty: DirtyRect,
clipped_tile_size: DeviceUintSize,
tile_size: TileSize,
tile_offset: TileOffset,
-) -> Option<DeviceUintRect> {
- dirty.intersection(&DeviceUintRect::new(
- DeviceUintPoint::new(
- tile_offset.x as u32 * tile_size as u32,
- tile_offset.y as u32 * tile_size as u32
- ),
+) -> DirtyRect {
+ let tile_position = DeviceUintPoint::new(
+ tile_offset.x as u32 * tile_size as u32,
+ tile_offset.y as u32 * tile_size as u32,
+ );
+
+ let mut rect = dirty.to_subrect_of(&DeviceUintRect::new(
+ tile_position,
clipped_tile_size,
- )).map(|mut r| {
- // we can't translate by a negative size so do it manually
- r.origin.x -= tile_offset.x as u32 * tile_size as u32;
- r.origin.y -= tile_offset.y as u32 * tile_size as u32;
- r
- })
-}
+ ));
-fn merge_dirty_rect(
- prev_dirty_rect: &Option<DeviceUintRect>,
- dirty_rect: &Option<DeviceUintRect>,
- descriptor: &ImageDescriptor,
-) -> Option<DeviceUintRect> {
- // It is important to never assume an empty dirty rect implies a full reupload here,
- // although we are able to do so elsewhere. We store the descriptor's full rect instead
- // There are update sequences which could cause us to forget the correct dirty regions
- // regions if we cleared the dirty rect when we received None, e.g.:
- // 1) Update with no dirty rect. We want to reupload everything.
- // 2) Update with dirty rect B. We still want to reupload everything, not just B.
- // 3) Perform the upload some time later.
- match (dirty_rect, prev_dirty_rect) {
- (&Some(ref rect), &Some(ref prev_rect)) => Some(rect.union(&prev_rect)),
- (&Some(ref rect), &None) => Some(*rect),
- (&None, _) => Some(descriptor.full_rect()),
+ // We can't translate by a negative size so do it manually.
+ //
+ // We check for emptiness here because empty rects may have zeroed out
+ // positions, in which case we will get a benign underflow that nonetheless
+ // causes a panic in debug builds.
+ if !rect.is_empty() {
+ rect.origin.x -= tile_position.x;
+ rect.origin.y -= tile_position.y;
}
+
+ DirtyRect::SomeDirty(rect)
}
impl<K, V, U> ResourceClassCache<K, V, U>
@@ -739,7 +731,7 @@ impl ResourceCache {
image_key: ImageKey,
descriptor: ImageDescriptor,
data: ImageData,
- dirty_rect: Option<DeviceUintRect>,
+ dirty_rect: DirtyRect,
) {
let max_texture_size = self.max_texture_size();
let image = match self.resources.image_templates.get_mut(image_key) {
@@ -756,21 +748,21 @@ impl ResourceCache {
// updated independently.
match self.cached_images.try_get_mut(&image_key) {
Some(&mut ImageResult::UntiledAuto(ref mut entry)) => {
- entry.dirty_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
+ entry.dirty_rect = entry.dirty_rect.union(&dirty_rect);
}
Some(&mut ImageResult::Multi(ref mut entries)) => {
for (key, entry) in entries.iter_mut() {
- let merged_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
+ let merged_rect = entry.dirty_rect.union(&dirty_rect);
- entry.dirty_rect = match (key.tile, merged_rect) {
- (Some(tile), Some(rect)) => {
+ entry.dirty_rect = match key.tile {
+ Some(tile) => {
let tile_size = image.tiling.unwrap();
let clipped_tile_size = compute_tile_size(&descriptor, tile_size, tile);
- rect.intersection(&DeviceUintRect::new(
+ merged_rect.intersection(&DirtyRect::SomeDirty(DeviceUintRect::new(
DeviceUintPoint::new(tile.x as u32, tile.y as u32) * tile_size as u32,
clipped_tile_size,
- ))
+ )))
}
_ => merged_rect,
};
@@ -805,12 +797,7 @@ impl ResourceCache {
BlobImageTemplate {
descriptor: *descriptor,
tiling,
- dirty_rect: Some(
- DeviceUintRect::new(
- DeviceUintPoint::zero(),
- descriptor.size,
- )
- ),
+ dirty_rect: DirtyRect::AllDirty,
viewport_tiles: None,
},
);
@@ -821,10 +808,10 @@ impl ResourceCache {
&mut self,
key: ImageKey,
descriptor: &ImageDescriptor,
- dirty_rect: &Option<DeviceUintRect>,
+ dirty_rect: &DirtyRect,
data: Arc<BlobImageData>,
) {
- self.blob_image_handler.as_mut().unwrap().update(key, data, *dirty_rect);
+ self.blob_image_handler.as_mut().unwrap().update(key, data, dirty_rect);
let max_texture_size = self.max_texture_size();
@@ -837,11 +824,7 @@ impl ResourceCache {
*image = BlobImageTemplate {
descriptor: *descriptor,
tiling,
- dirty_rect: match (*dirty_rect, image.dirty_rect) {
- (Some(rect), Some(prev_rect)) => Some(rect.union(&prev_rect)),
- (Some(rect), None) => Some(rect),
- (None, _) => None,
- },
+ dirty_rect: dirty_rect.union(&image.dirty_rect),
viewport_tiles: image.viewport_tiles,
};
}
@@ -920,7 +903,7 @@ impl ResourceCache {
&mut ImageResult::UntiledAuto(ref mut entry) => {
Some(mem::replace(entry, CachedImageInfo {
texture_cache_handle: TextureCacheHandle::new(),
- dirty_rect: None,
+ dirty_rect: DirtyRect::AllDirty,
}))
}
_ => None
@@ -942,7 +925,7 @@ impl ResourceCache {
entry.insert(if request.is_untiled_auto() {
ImageResult::UntiledAuto(CachedImageInfo {
texture_cache_handle: TextureCacheHandle::new(),
- dirty_rect: Some(template.descriptor.full_rect()),
+ dirty_rect: DirtyRect::AllDirty,
})
} else {
ImageResult::Multi(ResourceClassCache::new())
@@ -958,7 +941,7 @@ impl ResourceCache {
entries.entry(request.into())
.or_insert(CachedImageInfo {
texture_cache_handle: TextureCacheHandle::new(),
- dirty_rect: Some(template.descriptor.full_rect()),
+ dirty_rect: DirtyRect::AllDirty,
})
},
ImageResult::Err(_) => panic!("Errors should already have been handled"),
@@ -966,7 +949,7 @@ impl ResourceCache {
let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache);
- if !needs_upload && entry.dirty_rect.is_none() {
+ if !needs_upload && entry.dirty_rect.is_empty() {
return
}
@@ -1014,7 +997,7 @@ impl ResourceCache {
BlobImageParams {
request,
descriptor,
- dirty_rect: None,
+ dirty_rect: DirtyRect::AllDirty,
}
);
}
@@ -1048,17 +1031,7 @@ impl ResourceCache {
});
// Don't request tiles that weren't invalidated.
- if let Some(dirty_rect) = template.dirty_rect {
- let dirty_rect = DeviceUintRect {
- origin: point2(
- dirty_rect.origin.x,
- dirty_rect.origin.y,
- ),
- size: size2(
- dirty_rect.size.width,
- dirty_rect.size.height,
- ),
- };
+ if let DirtyRect::SomeDirty(dirty_rect) = template.dirty_rect {
let dirty_tiles = compute_tile_range(
&dirty_rect,
tile_size,
@@ -1106,7 +1079,7 @@ impl ResourceCache {
tile: Some(tile),
},
descriptor,
- dirty_rect: None,
+ dirty_rect: DirtyRect::AllDirty,
}
);
});
@@ -1139,7 +1112,7 @@ impl ResourceCache {
let dirty_rect = if needs_upload {
// The texture cache entry has been evicted, treat it as all dirty.
- None
+ DirtyRect::AllDirty
} else {
template.dirty_rect
};
@@ -1159,7 +1132,7 @@ impl ResourceCache {
}
);
}
- template.dirty_rect = None;
+ template.dirty_rect = DirtyRect::empty();
}
let handler = self.blob_image_handler.as_mut().unwrap();
handler.prepare_resources(&self.resources, &blob_request_params);
@@ -1507,15 +1480,16 @@ impl ResourceCache {
let tile_size = image_template.tiling.unwrap();
let clipped_tile_size = compute_tile_size(&descriptor, tile_size, tile);
- local_dirty_rect = if let Some(rect) = entry.dirty_rect.take() {
+ local_dirty_rect = if !entry.dirty_rect.is_empty() {
// We should either have a dirty rect, or we are re-uploading where the dirty
// rect is ignored anyway.
- let intersection = intersect_for_tile(rect, clipped_tile_size, tile_size, tile);
- debug_assert!(intersection.is_some() ||
+ let intersection = intersect_for_tile(entry.dirty_rect.replace_with_empty(),
+ clipped_tile_size, tile_size, tile);
+ debug_assert!(!intersection.is_empty() ||
self.texture_cache.needs_upload(&entry.texture_cache_handle));
intersection
} else {
- None
+ DirtyRect::AllDirty
};
// The tiled image could be stored on the CPU as one large image or be
@@ -1533,14 +1507,14 @@ impl ResourceCache {
descriptor.size = clipped_tile_size;
} else {
- local_dirty_rect = entry.dirty_rect.take();
+ local_dirty_rect = entry.dirty_rect.replace_with_empty();
}
// If we are uploading the dirty region of a blob image we might have several
// rects to upload so we use each of these rasterized rects rather than the
// overall dirty rect of the image.
- if blob_rasterized_rect.is_some() {
- local_dirty_rect = blob_rasterized_rect;
+ if let Some(rect) = blob_rasterized_rect {
+ local_dirty_rect = DirtyRect::SomeDirty(rect);
}
let filter = match request.rendering {
@@ -1873,7 +1847,7 @@ impl ResourceCache {
offset: DevicePoint::zero(),
format: desc.format,
},
- dirty_rect: None,
+ dirty_rect: DirtyRect::AllDirty,
}
];
diff --git a/gfx/webrender/src/texture_cache.rs b/gfx/webrender/src/texture_cache.rs
index 2cc3e79a6006..8d325b36fa78 100644
--- a/gfx/webrender/src/texture_cache.rs
+++ b/gfx/webrender/src/texture_cache.rs
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize};
+use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize, DirtyRect};
use api::{ExternalImageType, ImageData, ImageFormat};
use api::ImageDescriptor;
use device::TextureFilter;
@@ -433,7 +433,7 @@ impl TextureCache {
filter: TextureFilter,
data: Option<ImageData>,
user_data: [f32; 3],
- mut dirty_rect: Option<DeviceUintRect>,
+ mut dirty_rect: DirtyRect,
gpu_cache: &mut GpuCache,
eviction_notice: Option<&EvictionNotice>,
uv_rect_kind: UvRectKind,
@@ -473,7 +473,7 @@ impl TextureCache {
);
// If we reallocated, we need to upload the whole item again.
- dirty_rect = None;
+ dirty_rect = DirtyRect::AllDirty;
}
let entry = self.entries
@@ -1269,7 +1269,7 @@ impl TextureUpdate {
size: DeviceUintSize,
texture_id: CacheTextureId,
layer_index: i32,
- dirty_rect: Option<DeviceUintRect>,
+ dirty_rect: DirtyRect,
) -> TextureUpdate {
let source = match data {
ImageData::Blob(..) => {
@@ -1295,7 +1295,7 @@ impl TextureUpdate {
};
let update_op = match dirty_rect {
- Some(dirty) => {
+ DirtyRect::SomeDirty(dirty) => {
// the dirty rectangle doesn't have to be within the area but has to intersect it, at least
let stride = descriptor.compute_stride();
let offset = descriptor.offset + dirty.origin.y * stride + dirty.origin.x * descriptor.format.bytes_per_pixel();
@@ -1314,7 +1314,7 @@ impl TextureUpdate {
layer_index,
}
}
- None => {
+ DirtyRect::AllDirty => {
TextureUpdateOp::Update {
rect: DeviceUintRect::new(origin, size),
source,
diff --git a/gfx/webrender_api/src/api.rs b/gfx/webrender_api/src/api.rs
index 2c3aa2f460db..85caad8a28c5 100644
--- a/gfx/webrender_api/src/api.rs
+++ b/gfx/webrender_api/src/api.rs
@@ -14,7 +14,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use std::u32;
use {BuiltDisplayList, BuiltDisplayListDescriptor, ColorF, DeviceIntPoint, DeviceUintRect};
-use {DeviceUintSize, ExternalScrollId, FontInstanceKey, FontInstanceOptions};
+use {DeviceUintSize, DirtyRect, ExternalScrollId, FontInstanceKey, FontInstanceOptions};
use {FontInstancePlatformOptions, FontKey, FontVariation, GlyphDimensions, GlyphIndex, ImageData};
use {ImageDescriptor, ImageKey, ItemTag, LayoutPoint, LayoutSize, LayoutTransform, LayoutVector2D};
use {NativeFontHandle, WorldPoint};
@@ -307,7 +307,7 @@ impl Transaction {
key: ImageKey,
descriptor: ImageDescriptor,
data: ImageData,
- dirty_rect: Option<DeviceUintRect>,
+ dirty_rect: DirtyRect,
) {
self.resource_updates.push(ResourceUpdate::UpdateImage(UpdateImage {
key,
@@ -446,7 +446,7 @@ pub struct UpdateImage {
pub key: ImageKey,
pub descriptor: ImageDescriptor,
pub data: ImageData,
- pub dirty_rect: Option<DeviceUintRect>,
+ pub dirty_rect: DirtyRect,
}
#[derive(Clone, Deserialize, Serialize)]
diff --git a/gfx/webrender_api/src/image.rs b/gfx/webrender_api/src/image.rs
index 48ad0c96c7fb..1ace4f4f0b7d 100644
--- a/gfx/webrender_api/src/image.rs
+++ b/gfx/webrender_api/src/image.rs
@@ -318,7 +318,7 @@ pub trait BlobImageHandler: Send {
fn add(&mut self, key: ImageKey, data: Arc<BlobImageData>, tiling: Option<TileSize>);
/// Update an already registered blob image.
- fn update(&mut self, key: ImageKey, data: Arc<BlobImageData>, dirty_rect: Option<DeviceUintRect>);
+ fn update(&mut self, key: ImageKey, data: Arc<BlobImageData>, dirty_rect: &DirtyRect);
/// Delete an already registered blob image.
fn delete(&mut self, key: ImageKey);
@@ -354,7 +354,85 @@ pub struct BlobImageParams {
/// the entire image when only a portion is updated.
///
/// If set to None the entire image is rasterized.
- pub dirty_rect: Option<DeviceUintRect>,
+ pub dirty_rect: DirtyRect,
+}
+
+/// The possible states of a Dirty rect.
+///
+/// This exists because people kept getting confused with `Option<Rect>`.
+#[repr(u8)]
+#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
+pub enum DirtyRect {
+ /// Everything is Dirty, equivalent to SomeDirty(image_bounds)
+ AllDirty,
+ /// Some specific amount is dirty
+ SomeDirty(DeviceUintRect)
+}
+
+impl DirtyRect {
+ /// Creates an empty DirtyRect (indicating nothing is invalid)
+ pub fn empty() -> Self {
+ DirtyRect::SomeDirty(DeviceUintRect::zero())
+ }
+
+ /// Returns whether the dirty rect is empty
+ pub fn is_empty(&self) -> bool {
+ use DirtyRect::*;
+
+ match self {
+ AllDirty => false,
+ SomeDirty(rect) => rect.is_empty(),
+ }
+ }
+
+ /// Replaces self with the empty rect and returns the old value.
+ pub fn replace_with_empty(&mut self) -> Self {
+ ::std::mem::replace(self, DirtyRect::empty())
+ }
+
+ /// Maps over the contents of SomeDirty.
+ pub fn map<F>(self, func: F) -> Self
+ where F: FnOnce(DeviceUintRect) -> DeviceUintRect,
+ {
+ use DirtyRect::*;
+
+ match self {
+ AllDirty => AllDirty,
+ SomeDirty(rect) => SomeDirty(func(rect)),
+ }
+ }
+
+ /// Unions the dirty rects.
+ pub fn union(&self, other: &DirtyRect) -> DirtyRect {
+ use DirtyRect::*;
+
+ match (*self, *other) {
+ (AllDirty, _) | (_, AllDirty) => AllDirty,
+ (SomeDirty(rect1), SomeDirty(rect2)) => SomeDirty(rect1.union(&rect2)),
+ }
+ }
+
+ /// Intersects the dirty rects.
+ pub fn intersection(&self, other: &DirtyRect) -> DirtyRect {
+ use DirtyRect::*;
+
+ match (*self, *other) {
+ (AllDirty, rect) | (rect, AllDirty) => rect,
+ (SomeDirty(rect1), SomeDirty(rect2)) => SomeDirty(rect1.intersection(&rect2)
+ .unwrap_or(DeviceUintRect::zero()))
+ }
+ }
+
+ /// Converts the dirty rect into a subrect of the given one via intersection.
+ pub fn to_subrect_of(&self, rect: &DeviceUintRect) -> DeviceUintRect {
+ use DirtyRect::*;
+
+ match *self {
+ AllDirty => *rect,
+ SomeDirty(dirty_rect) => dirty_rect.intersection(rect)
+ .unwrap_or(DeviceUintRect::zero()),
+ }
+ }
}
/// Backing store for blob image command streams.
diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs
index c005b2741724..920b8af5a55d 100644
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1351,7 +1351,7 @@ pub extern "C" fn wr_resource_updates_update_image(
key,
descriptor.into(),
ImageData::new(bytes.flush_into_vec()),
- None
+ DirtyRect::AllDirty,
);
}
@@ -1383,7 +1383,7 @@ pub extern "C" fn wr_resource_updates_update_external_image(
image_type: image_type.to_wr(),
}
),
- None
+ DirtyRect::AllDirty,
);
}
@@ -1407,7 +1407,7 @@ pub extern "C" fn wr_resource_updates_update_external_image_with_dirty_rect(
image_type: image_type.to_wr(),
}
),
- Some(dirty_rect)
+ DirtyRect::SomeDirty(dirty_rect),
);
}
@@ -1423,7 +1423,7 @@ pub extern "C" fn wr_resource_updates_update_blob_image(
image_key,
descriptor.into(),
ImageData::new_blob_image(bytes.flush_into_vec()),
- Some(dirty_rect)
+ DirtyRect::SomeDirty(dirty_rect),
);
}
diff --git a/gfx/webrender_bindings/src/moz2d_renderer.rs b/gfx/webrender_bindings/src/moz2d_renderer.rs
index 13f5f2afeb3e..ac56ff538a67 100644
--- a/gfx/webrender_bindings/src/moz2d_renderer.rs
+++ b/gfx/webrender_bindings/src/moz2d_renderer.rs
@@ -454,7 +454,7 @@ impl AsyncBlobImageRasterizer for Moz2dBlobRasterizer {
request: BlobImageRequest,
descriptor: BlobImageDescriptor,
commands: Arc<BlobImageData>,
- dirty_rect: Option<DeviceUintRect>,
+ dirty_rect: DirtyRect,
tile_size: Option<TileSize>,
}
@@ -479,6 +479,11 @@ impl AsyncBlobImageRasterizer for Moz2dBlobRasterizer {
let mut output = vec![0u8; buf_size];
+ let dirty_rect = match &item.dirty_rect {
+ DirtyRect::AllDirty => None,
+ DirtyRect::SomeDirty(rect) => Some(rect),
+ };
+
let result = unsafe {
if wr_moz2d_render_cb(
ByteSlice::new(&item.commands[..]),
@@ -487,12 +492,12 @@ impl AsyncBlobImageRasterizer for Moz2dBlobRasterizer {
descriptor.format,
item.tile_size.as_ref(),
item.request.tile.as_ref(),
- item.dirty_rect.as_ref(),
+ dirty_rect,
MutByteSlice::new(output.as_mut_slice()),
) {
Ok(RasterizedBlobImage {
- rasterized_rect: item.dirty_rect.unwrap_or(
- DeviceUintRect {
+ rasterized_rect: item.dirty_rect.to_subrect_of(
+ &DeviceUintRect {
origin: DeviceUintPoint::origin(),
size: descriptor.size,
}
@@ -519,12 +524,17 @@ impl BlobImageHandler for Moz2dBlobImageHandler {
self.blob_commands.insert(key, BlobCommand { data: Arc::clone(&data), tile_size });
}
- fn update(&mut self, key: ImageKey, data: Arc<BlobImageData>, dirty_rect: Option<DeviceUintRect>) {
+ fn update(&mut self, key: ImageKey, data: Arc<BlobImageData>, dirty_rect: &DirtyRect) {
match self.blob_commands.entry(key) {
hash_map::Entry::Occupied(mut e) => {
let command = e.get_mut();
+ let dirty_rect = if let DirtyRect::SomeDirty(rect) = dirty_rect {
+ *rect
+ } else {
+ unreachable!("BlobImage updates require a real dirty rect for merging");
+ };
command.data = Arc::new(merge_blob_images(&command.data, &data,
- dirty_rect.unwrap().into()));
+ dirty_rect.into()));
}
_ => { panic!("missing image key"); }
}
diff --git a/gfx/wrench/src/blob.rs b/gfx/wrench/src/blob.rs
index 7373d5da0c9e..60daa8f83092 100644
--- a/gfx/wrench/src/blob.rs
+++ b/gfx/wrench/src/blob.rs
@@ -139,7 +139,7 @@ impl BlobImageHandler for CheckerboardRenderer {
.insert(key, (deserialize_blob(&cmds[..]).unwrap(), tile_size));
}
- fn update(&mut self, key: ImageKey, cmds: Arc<BlobImageData>, _dirty_rect: Option<DeviceUintRect>) {
+ fn update(&mut self, key: ImageKey, cmds: Arc<BlobImageData>, _dirty_rect: &DirtyRect) {
// Here, updating is just replacing the current version of the commands with
// the new one (no incremental updates).
self.image_cmds.get_mut(&key).unwrap().0 = deserialize_blob(&cmds[..]).unwrap();
@@ -175,7 +175,7 @@ struct Command {
color: ColorU,
descriptor: BlobImageDescriptor,
tile: Option<(TileSize, TileOffset)>,
- dirty_rect: Option<DeviceUintRect>
+ dirty_rect: DirtyRect,
}
struct Rasterizer {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment