Created
October 3, 2018 04:02
-
-
Save Gankra/f42431879ab70656f42f1a6c56a2f666 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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