mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Backed out changeset 42d3ccf69629 (bug 1583879) for causing reftest failures on sort-startSame-1b.svg CLOSED TREE
This commit is contained in:
parent
bbdd994f71
commit
604018cb2e
@ -333,26 +333,25 @@ struct Reader {
|
||||
layers::BlobFont ReadBlobFont() { return Read<layers::BlobFont>(); }
|
||||
};
|
||||
|
||||
static wr::BlobRenderStatus
|
||||
Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const mozilla::wr::DeviceIntRect* aVisibleRect,
|
||||
const mozilla::wr::LayoutIntRect* aRenderRect,
|
||||
const uint16_t* aTileSize,
|
||||
const mozilla::wr::TileOffset* aTileOffset,
|
||||
const mozilla::wr::LayoutIntRect* aDirtyRect,
|
||||
Range<uint8_t> aOutput) {
|
||||
static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const mozilla::wr::DeviceIntRect* aVisibleRect,
|
||||
const mozilla::wr::LayoutIntRect* aRenderRect,
|
||||
const uint16_t* aTileSize,
|
||||
const mozilla::wr::TileOffset* aTileOffset,
|
||||
const mozilla::wr::LayoutIntRect* aDirtyRect,
|
||||
Range<uint8_t> aOutput) {
|
||||
IntSize size(aRenderRect->size.width, aRenderRect->size.height);
|
||||
AUTO_PROFILER_TRACING("WebRender", "RasterizeSingleBlob", GRAPHICS);
|
||||
MOZ_RELEASE_ASSERT(size.width > 0 && size.height > 0);
|
||||
if (size.width <= 0 || size.height <= 0) {
|
||||
return BlobRenderStatus::Error;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto stride = size.width * gfx::BytesPerPixel(aFormat);
|
||||
|
||||
if (aOutput.length() < static_cast<size_t>(size.height * stride)) {
|
||||
return BlobRenderStatus::Error;
|
||||
return false;
|
||||
}
|
||||
|
||||
// In bindings.rs we allocate a buffer filled with opaque white.
|
||||
@ -363,7 +362,7 @@ Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
||||
uninitialized);
|
||||
|
||||
if (!dt) {
|
||||
return BlobRenderStatus::Error;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We try hard to not have empty blobs but we can end up with
|
||||
@ -393,7 +392,7 @@ Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
||||
aDirtyRect->size.width, aDirtyRect->size.height));
|
||||
}
|
||||
|
||||
wr::BlobRenderStatus status = wr::BlobRenderStatus::Empty;
|
||||
bool ret = true;
|
||||
size_t offset = 0;
|
||||
auto absBounds = IntRectAbsolute::FromRect(bounds);
|
||||
while (reader.pos < reader.len) {
|
||||
@ -408,8 +407,6 @@ Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
||||
continue;
|
||||
}
|
||||
|
||||
status = BlobRenderStatus::Ok;
|
||||
|
||||
layers::WebRenderTranslator translator(dt);
|
||||
Reader fontReader(aBlob.begin().get() + end, extra_end - end);
|
||||
size_t count = fontReader.ReadSize();
|
||||
@ -421,10 +418,9 @@ Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
||||
}
|
||||
|
||||
Range<const uint8_t> blob(aBlob.begin() + offset, aBlob.begin() + end);
|
||||
bool ok =
|
||||
ret =
|
||||
translator.TranslateRecording((char*)blob.begin().get(), blob.length());
|
||||
if (!ok) {
|
||||
status = BlobRenderStatus::Error;
|
||||
if (!ret) {
|
||||
gfxCriticalNote << "Replay failure: " << translator.GetError();
|
||||
MOZ_RELEASE_ASSERT(false);
|
||||
}
|
||||
@ -451,7 +447,7 @@ Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
||||
gfxUtils::WriteAsPNG(dt, filename);
|
||||
#endif
|
||||
|
||||
return status;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
@ -459,15 +455,14 @@ Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
||||
|
||||
extern "C" {
|
||||
|
||||
mozilla::wr::BlobRenderStatus
|
||||
wr_moz2d_render_cb(const mozilla::wr::ByteSlice blob,
|
||||
mozilla::wr::ImageFormat aFormat,
|
||||
const mozilla::wr::LayoutIntRect* aRenderRect,
|
||||
const mozilla::wr::DeviceIntRect* aVisibleRect,
|
||||
const uint16_t* aTileSize,
|
||||
const mozilla::wr::TileOffset* aTileOffset,
|
||||
const mozilla::wr::LayoutIntRect* aDirtyRect,
|
||||
mozilla::wr::MutByteSlice output) {
|
||||
bool wr_moz2d_render_cb(const mozilla::wr::ByteSlice blob,
|
||||
mozilla::wr::ImageFormat aFormat,
|
||||
const mozilla::wr::LayoutIntRect* aRenderRect,
|
||||
const mozilla::wr::DeviceIntRect* aVisibleRect,
|
||||
const uint16_t* aTileSize,
|
||||
const mozilla::wr::TileOffset* aTileOffset,
|
||||
const mozilla::wr::LayoutIntRect* aDirtyRect,
|
||||
mozilla::wr::MutByteSlice output) {
|
||||
return mozilla::wr::Moz2DRenderCallback(
|
||||
mozilla::wr::ByteSliceToRange(blob),
|
||||
mozilla::wr::ImageFormatToSurfaceFormat(aFormat), aVisibleRect,
|
||||
|
@ -3263,24 +3263,20 @@ pub unsafe extern "C" fn wr_dec_ref_arc(arc: *const VecU8) {
|
||||
Arc::from_raw(arc);
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
pub enum BlobRenderStatus {
|
||||
Ok,
|
||||
Empty,
|
||||
Error,
|
||||
}
|
||||
|
||||
// TODO: nical
|
||||
// Update for the new blob image interface changes.
|
||||
//
|
||||
extern "C" {
|
||||
// TODO: figure out the API for tiled blob images.
|
||||
pub fn wr_moz2d_render_cb(blob: ByteSlice,
|
||||
format: ImageFormat,
|
||||
render_rect: &LayoutIntRect,
|
||||
visible_rect: &DeviceIntRect,
|
||||
tile_size: Option<&u16>,
|
||||
tile_offset: Option<&TileOffset>,
|
||||
dirty_rect: Option<&LayoutIntRect>,
|
||||
output: MutByteSlice)
|
||||
-> BlobRenderStatus;
|
||||
// TODO: figure out the API for tiled blob images.
|
||||
pub fn wr_moz2d_render_cb(blob: ByteSlice,
|
||||
format: ImageFormat,
|
||||
render_rect: &LayoutIntRect,
|
||||
visible_rect: &DeviceIntRect,
|
||||
tile_size: Option<&u16>,
|
||||
tile_offset: Option<&TileOffset>,
|
||||
dirty_rect: Option<&LayoutIntRect>,
|
||||
output: MutByteSlice)
|
||||
-> bool;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
use webrender::api::*;
|
||||
use webrender::api::units::{BlobDirtyRect, BlobToDeviceTranslation, DeviceIntRect};
|
||||
use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb, ArcVecU8};
|
||||
use bindings::{BlobRenderStatus, gecko_profiler_start_marker, gecko_profiler_end_marker};
|
||||
use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb, ArcVecU8, gecko_profiler_start_marker, gecko_profiler_end_marker};
|
||||
use rayon::ThreadPool;
|
||||
use rayon::prelude::*;
|
||||
|
||||
@ -580,7 +579,7 @@ fn rasterize_blob(job: Job) -> (BlobImageRequest, BlobImageResult) {
|
||||
assert!(descriptor.rect.size.width > 0 && descriptor.rect.size.height > 0);
|
||||
|
||||
let result = unsafe {
|
||||
match wr_moz2d_render_cb(
|
||||
if wr_moz2d_render_cb(
|
||||
ByteSlice::new(&job.commands[..]),
|
||||
descriptor.format,
|
||||
&descriptor.rect,
|
||||
@ -590,27 +589,18 @@ fn rasterize_blob(job: Job) -> (BlobImageRequest, BlobImageResult) {
|
||||
dirty_rect.as_ref(),
|
||||
MutByteSlice::new(output.as_mut_slice()),
|
||||
) {
|
||||
BlobRenderStatus::Ok => {
|
||||
// We want the dirty rect local to the tile rather than the whole image.
|
||||
// TODO(nical): move that up and avoid recomputing the tile bounds in the callback
|
||||
let local_dirty_rect = job.dirty_rect.to_subrect_of(&descriptor.rect);
|
||||
let tx: BlobToDeviceTranslation = (-descriptor.rect.origin.to_vector()).into();
|
||||
let rasterized_rect = tx.transform_rect(&local_dirty_rect);
|
||||
// We want the dirty rect local to the tile rather than the whole image.
|
||||
// TODO(nical): move that up and avoid recomupting the tile bounds in the callback
|
||||
let dirty_rect = job.dirty_rect.to_subrect_of(&descriptor.rect);
|
||||
let tx: BlobToDeviceTranslation = (-descriptor.rect.origin.to_vector()).into();
|
||||
let rasterized_rect = tx.transform_rect(&dirty_rect);
|
||||
|
||||
Ok(RasterizedBlobImage {
|
||||
rasterized_rect,
|
||||
data: Some(Arc::new(output)),
|
||||
})
|
||||
}
|
||||
BlobRenderStatus::Empty => {
|
||||
Ok(RasterizedBlobImage {
|
||||
rasterized_rect: DeviceIntRect::zero(),
|
||||
data: None,
|
||||
})
|
||||
}
|
||||
BlobRenderStatus::Error => {
|
||||
panic!("Moz2D replay problem");
|
||||
}
|
||||
Ok(RasterizedBlobImage {
|
||||
rasterized_rect,
|
||||
data: Arc::new(output),
|
||||
})
|
||||
} else {
|
||||
panic!("Moz2D replay problem");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ fn render_blob(
|
||||
}
|
||||
|
||||
Ok(api::RasterizedBlobImage {
|
||||
data: Some(Arc::new(texels)),
|
||||
data: Arc::new(texels),
|
||||
rasterized_rect: size2(w, h).into(),
|
||||
})
|
||||
}
|
||||
|
@ -403,26 +403,21 @@ impl ClipNodeInfo {
|
||||
tile_size as i32,
|
||||
);
|
||||
for tile in tiles {
|
||||
let mut render = true;
|
||||
if request_resources {
|
||||
render = resource_cache.request_image(
|
||||
resource_cache.request_image(
|
||||
request.with_tile(tile.offset),
|
||||
gpu_cache,
|
||||
).should_render();
|
||||
}
|
||||
if render {
|
||||
mask_tiles.push(VisibleMaskImageTile {
|
||||
tile_offset: tile.offset,
|
||||
tile_rect: tile.rect,
|
||||
});
|
||||
);
|
||||
}
|
||||
mask_tiles.push(VisibleMaskImageTile {
|
||||
tile_offset: tile.offset,
|
||||
tile_rect: tile.rect,
|
||||
});
|
||||
}
|
||||
}
|
||||
visible_tiles = Some(mask_tiles);
|
||||
} else if request_resources {
|
||||
if resource_cache.request_image(request, gpu_cache).should_skip() {
|
||||
return None;
|
||||
}
|
||||
resource_cache.request_image(request, gpu_cache);
|
||||
}
|
||||
} else {
|
||||
// If the supplied image key doesn't exist in the resource cache,
|
||||
|
@ -17,7 +17,7 @@ use crate::prim_store::{
|
||||
PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData,
|
||||
PrimitiveStore, InternablePrimitive,
|
||||
};
|
||||
use crate::resource_cache::{ImageRequest, ResourceCache, ImageRequestStatus};
|
||||
use crate::resource_cache::{ImageRequest, ResourceCache};
|
||||
use crate::storage;
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
@ -260,11 +260,11 @@ impl ImageBorderData {
|
||||
&mut self,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
) -> ImageRequestStatus {
|
||||
) {
|
||||
resource_cache.request_image(
|
||||
self.request,
|
||||
gpu_cache,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
fn write_prim_gpu_blocks(
|
||||
|
@ -24,7 +24,7 @@ use crate::render_task::{BlitSource, RenderTask};
|
||||
use crate::render_task_cache::{
|
||||
RenderTaskCacheEntryHandle, RenderTaskCacheKey, RenderTaskCacheKeyKind
|
||||
};
|
||||
use crate::resource_cache::{ImageRequest, ResourceCache, ImageRequestStatus};
|
||||
use crate::resource_cache::{ImageRequest, ResourceCache};
|
||||
use crate::util::pack_as_float;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -457,11 +457,11 @@ impl YuvImageData {
|
||||
&mut self,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
) -> ImageRequestStatus {
|
||||
) {
|
||||
let channel_num = self.format.get_plane_num();
|
||||
debug_assert!(channel_num <= 3);
|
||||
for channel in 0 .. channel_num {
|
||||
let status = resource_cache.request_image(
|
||||
resource_cache.request_image(
|
||||
ImageRequest {
|
||||
key: self.yuv_key[channel],
|
||||
rendering: self.image_rendering,
|
||||
@ -469,13 +469,7 @@ impl YuvImageData {
|
||||
},
|
||||
gpu_cache,
|
||||
);
|
||||
|
||||
if status != ImageRequestStatus::Requested {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
ImageRequestStatus::Requested
|
||||
}
|
||||
|
||||
pub fn write_prim_gpu_blocks(&self, request: &mut GpuDataRequest) {
|
||||
|
@ -2364,12 +2364,11 @@ impl PrimitiveStore {
|
||||
|
||||
match image_properties {
|
||||
Some(ImageProperties { tiling: None, .. }) => {
|
||||
if frame_state.resource_cache.request_image(
|
||||
|
||||
frame_state.resource_cache.request_image(
|
||||
request,
|
||||
frame_state.gpu_cache,
|
||||
).should_skip() {
|
||||
prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
|
||||
}
|
||||
);
|
||||
}
|
||||
Some(ImageProperties { tiling: Some(tile_size), visible_rect, .. }) => {
|
||||
image_instance.visible_tiles.clear();
|
||||
@ -2434,17 +2433,17 @@ impl PrimitiveStore {
|
||||
);
|
||||
|
||||
for tile in tiles {
|
||||
if frame_state.resource_cache.request_image(
|
||||
frame_state.resource_cache.request_image(
|
||||
request.with_tile(tile.offset),
|
||||
frame_state.gpu_cache,
|
||||
).should_render() {
|
||||
image_instance.visible_tiles.push(VisibleImageTile {
|
||||
tile_offset: tile.offset,
|
||||
edge_flags: tile.edge_flags & edge_flags,
|
||||
local_rect: tile.rect,
|
||||
local_clip_rect: tight_clip_rect,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
image_instance.visible_tiles.push(VisibleImageTile {
|
||||
tile_offset: tile.offset,
|
||||
edge_flags: tile.edge_flags & edge_flags,
|
||||
local_rect: tile.rect,
|
||||
local_clip_rect: tight_clip_rect,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -2458,21 +2457,17 @@ impl PrimitiveStore {
|
||||
}
|
||||
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
|
||||
let prim_data = &mut frame_state.data_stores.image_border[data_handle];
|
||||
if prim_data.kind.request_resources(
|
||||
prim_data.kind.request_resources(
|
||||
frame_state.resource_cache,
|
||||
frame_state.gpu_cache,
|
||||
).should_skip() {
|
||||
prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
|
||||
}
|
||||
);
|
||||
}
|
||||
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
|
||||
let prim_data = &mut frame_state.data_stores.yuv_image[data_handle];
|
||||
if prim_data.kind.request_resources(
|
||||
prim_data.kind.request_resources(
|
||||
frame_state.resource_cache,
|
||||
frame_state.gpu_cache,
|
||||
).should_skip() {
|
||||
prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
|
||||
}
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -101,8 +101,6 @@ pub enum CachedImageData {
|
||||
/// An image owned by the embedding, and referenced by WebRender. This may
|
||||
/// take the form of a texture or a heap-allocated buffer.
|
||||
External(ExternalImageData),
|
||||
/// The image data is only transparent pixels, we can skip rendering it.
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl From<ImageData> for CachedImageData {
|
||||
@ -133,9 +131,8 @@ impl CachedImageData {
|
||||
ExternalImageType::TextureHandle(_) => false,
|
||||
ExternalImageType::Buffer => true,
|
||||
},
|
||||
CachedImageData::Blob
|
||||
| CachedImageData::Raw(_)
|
||||
| CachedImageData::Empty => true,
|
||||
CachedImageData::Blob => true,
|
||||
CachedImageData::Raw(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -226,7 +223,6 @@ struct CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle,
|
||||
dirty_rect: ImageDirtyRect,
|
||||
manual_eviction: bool,
|
||||
is_fully_transparent: bool
|
||||
}
|
||||
|
||||
impl CachedImageInfo {
|
||||
@ -460,27 +456,6 @@ pub struct AsyncBlobImageInfo {
|
||||
pub clear_requests: Vec<BlobImageClearParams>,
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ImageRequestStatus {
|
||||
Requested,
|
||||
FullyTransparent,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl ImageRequestStatus {
|
||||
pub fn should_render(self) -> bool {
|
||||
match self {
|
||||
Self::Requested => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn should_skip(self) -> bool {
|
||||
!self.should_render()
|
||||
}
|
||||
}
|
||||
|
||||
/// High-level container for resources managed by the `RenderBackend`.
|
||||
///
|
||||
/// This includes a variety of things, including images, fonts, and glyphs,
|
||||
@ -574,9 +549,7 @@ impl ResourceCache {
|
||||
fn should_tile(limit: i32, descriptor: &ImageDescriptor, data: &CachedImageData) -> bool {
|
||||
let size_check = descriptor.size.width > limit || descriptor.size.height > limit;
|
||||
match *data {
|
||||
CachedImageData::Raw(_)
|
||||
| CachedImageData::Blob
|
||||
| CachedImageData::Empty => size_check,
|
||||
CachedImageData::Raw(_) | CachedImageData::Blob => size_check,
|
||||
CachedImageData::External(info) => {
|
||||
// External handles already represent existing textures so it does
|
||||
// not make sense to tile them into smaller ones.
|
||||
@ -810,20 +783,6 @@ impl ResourceCache {
|
||||
|| { RasterizedBlob::Tiled(FastHashMap::default()) }
|
||||
);
|
||||
|
||||
if data.data.is_none() {
|
||||
let entry = ensure_cached_image_entry(
|
||||
&mut self.cached_images,
|
||||
ImageRequest {
|
||||
key: request.key.as_image(),
|
||||
tile: request.tile,
|
||||
rendering: ImageRendering::Auto,
|
||||
},
|
||||
);
|
||||
|
||||
// Mark the cached image as empty to skip rendering it later.
|
||||
entry.is_fully_transparent = true;
|
||||
}
|
||||
|
||||
if let Some(tile) = request.tile {
|
||||
if let RasterizedBlob::NonTiled(..) = *image {
|
||||
*image = RasterizedBlob::Tiled(FastHashMap::default());
|
||||
@ -1151,13 +1110,11 @@ impl ResourceCache {
|
||||
self.active_image_keys.insert(image_key);
|
||||
}
|
||||
|
||||
// Returns false if the image should not be rendered, either due to an error,
|
||||
// or if the image only contains fully transparent pixels.
|
||||
pub fn request_image(
|
||||
&mut self,
|
||||
request: ImageRequest,
|
||||
gpu_cache: &mut GpuCache,
|
||||
) -> ImageRequestStatus {
|
||||
) {
|
||||
debug_assert_eq!(self.state, State::AddResources);
|
||||
|
||||
let template = match self.resources.image_templates.get(request.key) {
|
||||
@ -1165,13 +1122,13 @@ impl ResourceCache {
|
||||
None => {
|
||||
warn!("ERROR: Trying to render deleted / non-existent key");
|
||||
debug!("key={:?}", request.key);
|
||||
return ImageRequestStatus::Error;
|
||||
return
|
||||
}
|
||||
};
|
||||
|
||||
// Images that don't use the texture cache can early out.
|
||||
if !template.data.uses_texture_cache() {
|
||||
return ImageRequestStatus::Requested;
|
||||
return;
|
||||
}
|
||||
|
||||
let side_size =
|
||||
@ -1182,27 +1139,76 @@ impl ResourceCache {
|
||||
warn!("Dropping image, image:(w:{},h:{}, tile:{}) is too big for hardware!",
|
||||
template.descriptor.size.width, template.descriptor.size.height, template.tiling.unwrap_or(0));
|
||||
self.cached_images.insert(request.key, ImageResult::Err(ImageCacheError::OverLimitSize));
|
||||
return ImageRequestStatus::Error;
|
||||
return;
|
||||
}
|
||||
|
||||
let entry = ensure_cached_image_entry(&mut self.cached_images, request);
|
||||
let storage = match self.cached_images.entry(request.key) {
|
||||
Occupied(e) => {
|
||||
// We might have an existing untiled entry, and need to insert
|
||||
// a second entry. In such cases we need to move the old entry
|
||||
// out first, replacing it with a dummy entry, and then creating
|
||||
// the tiled/multi-entry variant.
|
||||
let entry = e.into_mut();
|
||||
if !request.is_untiled_auto() {
|
||||
let untiled_entry = match entry {
|
||||
&mut ImageResult::UntiledAuto(ref mut entry) => {
|
||||
Some(mem::replace(entry, CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
}))
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
|
||||
let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache);
|
||||
|
||||
|
||||
if entry.is_fully_transparent {
|
||||
// Empty tile, skip rendering.
|
||||
return ImageRequestStatus::FullyTransparent;
|
||||
}
|
||||
if let Some(untiled_entry) = untiled_entry {
|
||||
let mut entries = ResourceClassCache::new();
|
||||
let untiled_key = CachedImageKey {
|
||||
rendering: ImageRendering::Auto,
|
||||
tile: None,
|
||||
};
|
||||
entries.insert(untiled_key, untiled_entry);
|
||||
*entry = ImageResult::Multi(entries);
|
||||
}
|
||||
}
|
||||
entry
|
||||
}
|
||||
Vacant(entry) => {
|
||||
entry.insert(if request.is_untiled_auto() {
|
||||
ImageResult::UntiledAuto(CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
})
|
||||
} else {
|
||||
ImageResult::Multi(ResourceClassCache::new())
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
// If this image exists in the texture cache, *and* the dirty rect
|
||||
// in the cache is empty, then it is valid to use as-is.
|
||||
let entry = match *storage {
|
||||
ImageResult::UntiledAuto(ref mut entry) => entry,
|
||||
ImageResult::Multi(ref mut entries) => {
|
||||
entries.entry(request.into())
|
||||
.or_insert(CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
})
|
||||
},
|
||||
ImageResult::Err(_) => panic!("Errors should already have been handled"),
|
||||
};
|
||||
|
||||
let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache);
|
||||
|
||||
if !needs_upload && entry.dirty_rect.is_empty() {
|
||||
return ImageRequestStatus::Requested;
|
||||
return
|
||||
}
|
||||
|
||||
if !self.pending_image_requests.insert(request) {
|
||||
return ImageRequestStatus::Requested;
|
||||
return
|
||||
}
|
||||
|
||||
// By this point, we know that the image request is considered dirty, and will
|
||||
@ -1250,8 +1256,6 @@ impl ResourceCache {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return ImageRequestStatus::Requested;
|
||||
}
|
||||
|
||||
pub fn create_blob_scene_builder_requests(
|
||||
@ -1579,14 +1583,6 @@ impl ResourceCache {
|
||||
pub fn get_cached_image(&self, request: ImageRequest) -> Result<CacheItem, ()> {
|
||||
debug_assert_eq!(self.state, State::QueryResources);
|
||||
let image_info = self.get_image_info(request)?;
|
||||
if image_info.is_fully_transparent {
|
||||
// TODO(nical): Ideally we should have discarded the primitive already.
|
||||
// If a blob image was not rasterized before frame building we end up
|
||||
// knowing whether its content is transparent after the culling phase
|
||||
// so we have to check again here. The plan is to remove the late blob
|
||||
// rasterization code, after which we can simplify this.
|
||||
return Err(())
|
||||
}
|
||||
Ok(self.get_texture_cache_item(&image_info.texture_cache_handle))
|
||||
}
|
||||
|
||||
@ -1624,9 +1620,7 @@ impl ResourceCache {
|
||||
ExternalImageType::Buffer => None,
|
||||
},
|
||||
// raw and blob image are all using resource_cache.
|
||||
CachedImageData::Raw(..)
|
||||
| CachedImageData::Blob
|
||||
| CachedImageData::Empty => None,
|
||||
CachedImageData::Raw(..) | CachedImageData::Blob => None,
|
||||
};
|
||||
|
||||
ImageProperties {
|
||||
@ -1733,9 +1727,7 @@ impl ResourceCache {
|
||||
let mut updates: SmallVec<[(CachedImageData, Option<DeviceIntRect>); 1]> = SmallVec::new();
|
||||
|
||||
match image_template.data {
|
||||
CachedImageData::Raw(..)
|
||||
| CachedImageData::External(..)
|
||||
| CachedImageData::Empty => {
|
||||
CachedImageData::Raw(..) | CachedImageData::External(..) => {
|
||||
// Safe to clone here since the Raw image data is an
|
||||
// Arc, and the external image data is small.
|
||||
updates.push((image_template.data.clone(), None));
|
||||
@ -1746,29 +1738,17 @@ impl ResourceCache {
|
||||
match (blob_image, request.tile) {
|
||||
(RasterizedBlob::Tiled(ref tiles), Some(tile)) => {
|
||||
let img = &tiles[&tile];
|
||||
updates.push(
|
||||
if let Some(ref data) = img.data {
|
||||
(
|
||||
CachedImageData::Raw(Arc::clone(data)),
|
||||
Some(img.rasterized_rect)
|
||||
)
|
||||
} else {
|
||||
(CachedImageData::Empty, None)
|
||||
}
|
||||
);
|
||||
updates.push((
|
||||
CachedImageData::Raw(Arc::clone(&img.data)),
|
||||
Some(img.rasterized_rect)
|
||||
));
|
||||
}
|
||||
(RasterizedBlob::NonTiled(ref mut queue), None) => {
|
||||
for img in queue.drain(..) {
|
||||
updates.push(
|
||||
if let Some(data) = img.data {
|
||||
(
|
||||
CachedImageData::Raw(data),
|
||||
Some(img.rasterized_rect)
|
||||
)
|
||||
} else {
|
||||
(CachedImageData::Empty, None)
|
||||
}
|
||||
);
|
||||
updates.push((
|
||||
CachedImageData::Raw(img.data),
|
||||
Some(img.rasterized_rect)
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -1946,9 +1926,7 @@ impl ResourceCache {
|
||||
for (_, image) in self.resources.image_templates.images.iter() {
|
||||
report.images += match image.data {
|
||||
CachedImageData::Raw(ref v) => unsafe { op(v.as_ptr() as *const c_void) },
|
||||
CachedImageData::Blob
|
||||
| CachedImageData::External(..)
|
||||
| CachedImageData::Empty => 0,
|
||||
CachedImageData::Blob | CachedImageData::External(..) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1993,72 +1971,6 @@ impl Drop for ResourceCache {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn ensure_cached_image_entry(cached_images: &mut ImageCache, request: ImageRequest) -> &mut CachedImageInfo {
|
||||
let storage = match cached_images.entry(request.key) {
|
||||
Occupied(e) => {
|
||||
// We might have an existing untiled entry, and need to insert
|
||||
// a second entry. In such cases we need to move the old entry
|
||||
// out first, replacing it with a dummy entry, and then creating
|
||||
// the tiled/multi-entry variant.
|
||||
let entry = e.into_mut();
|
||||
if !request.is_untiled_auto() {
|
||||
let untiled_entry = match entry {
|
||||
&mut ImageResult::UntiledAuto(ref mut entry) => {
|
||||
Some(mem::replace(entry, CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
is_fully_transparent: false,
|
||||
}))
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
|
||||
if let Some(untiled_entry) = untiled_entry {
|
||||
let mut entries = ResourceClassCache::new();
|
||||
let untiled_key = CachedImageKey {
|
||||
rendering: ImageRendering::Auto,
|
||||
tile: None,
|
||||
};
|
||||
entries.insert(untiled_key, untiled_entry);
|
||||
*entry = ImageResult::Multi(entries);
|
||||
}
|
||||
}
|
||||
entry
|
||||
}
|
||||
Vacant(entry) => {
|
||||
entry.insert(
|
||||
if request.is_untiled_auto() {
|
||||
ImageResult::UntiledAuto(CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
is_fully_transparent: false,
|
||||
})
|
||||
} else {
|
||||
ImageResult::Multi(ResourceClassCache::new())
|
||||
}
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
match *storage {
|
||||
ImageResult::UntiledAuto(ref mut entry) => entry,
|
||||
ImageResult::Multi(ref mut entries) => {
|
||||
entries.entry(request.into())
|
||||
.or_insert(CachedImageInfo {
|
||||
texture_cache_handle: TextureCacheHandle::invalid(),
|
||||
dirty_rect: DirtyRect::All,
|
||||
manual_eviction: false,
|
||||
is_fully_transparent: false,
|
||||
})
|
||||
},
|
||||
ImageResult::Err(_) => panic!("Errors should already have been handled"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_blob_tiling(
|
||||
tiling: Option<TileSize>,
|
||||
size: DeviceIntSize,
|
||||
@ -2241,7 +2153,7 @@ impl ResourceCache {
|
||||
warn!("Tiled blob images aren't supported yet");
|
||||
RasterizedBlobImage {
|
||||
rasterized_rect: desc.size.into(),
|
||||
data: None,
|
||||
data: Arc::new(vec![0; desc.compute_total_size() as usize])
|
||||
}
|
||||
} else {
|
||||
let blob_handler = self.blob_image_handler.as_mut().unwrap();
|
||||
@ -2251,26 +2163,25 @@ impl ResourceCache {
|
||||
result.expect("Blob rasterization failed")
|
||||
};
|
||||
|
||||
num_blobs += 1;
|
||||
assert_eq!(result.rasterized_rect.size, desc.size);
|
||||
if let Some(ref data) = result.data {
|
||||
assert_eq!(data.len(), desc.compute_total_size() as usize);
|
||||
#[cfg(feature = "png")]
|
||||
CaptureConfig::save_png(
|
||||
root.join(format!("blobs/{}.png", num_blobs)),
|
||||
desc.size,
|
||||
desc.format,
|
||||
data,
|
||||
);
|
||||
let file_name = format!("{}.raw", num_blobs);
|
||||
let short_path = format!("blobs/{}", file_name);
|
||||
let full_path = path_blobs.clone().join(&file_name);
|
||||
fs::File::create(full_path)
|
||||
.expect(&format!("Unable to create {}", short_path))
|
||||
.write_all(data)
|
||||
.unwrap();
|
||||
other_paths.insert(key, short_path);
|
||||
}
|
||||
assert_eq!(result.data.len(), desc.compute_total_size() as usize);
|
||||
|
||||
num_blobs += 1;
|
||||
#[cfg(feature = "png")]
|
||||
CaptureConfig::save_png(
|
||||
root.join(format!("blobs/{}.png", num_blobs)),
|
||||
desc.size,
|
||||
desc.format,
|
||||
&result.data,
|
||||
);
|
||||
let file_name = format!("{}.raw", num_blobs);
|
||||
let short_path = format!("blobs/{}", file_name);
|
||||
let full_path = path_blobs.clone().join(&file_name);
|
||||
fs::File::create(full_path)
|
||||
.expect(&format!("Unable to create {}", short_path))
|
||||
.write_all(&result.data)
|
||||
.unwrap();
|
||||
other_paths.insert(key, short_path);
|
||||
}
|
||||
CachedImageData::External(ref ext) => {
|
||||
let short_path = format!("externals/{}", external_images.len() + 1);
|
||||
@ -2281,7 +2192,6 @@ impl ResourceCache {
|
||||
external: ext.clone(),
|
||||
});
|
||||
}
|
||||
CachedImageData::Empty => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,12 +913,6 @@ impl TextureCache {
|
||||
) {
|
||||
debug_assert!(self.now.is_valid());
|
||||
|
||||
if let Some(CachedImageData::Empty) = data {
|
||||
self.mark_unused(handle);
|
||||
*handle = TextureCacheHandle::invalid();
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine if we need to allocate texture cache memory
|
||||
// for this item. We need to reallocate if any of the following
|
||||
// is true:
|
||||
@ -1852,9 +1846,6 @@ impl TextureCacheUpdate {
|
||||
CachedImageData::Blob => {
|
||||
panic!("The vector image should have been rasterized.");
|
||||
}
|
||||
CachedImageData::Empty => {
|
||||
panic!("The entry should have been cleared instead.");
|
||||
}
|
||||
CachedImageData::External(ext_image) => match ext_image.image_type {
|
||||
ExternalImageType::TextureHandle(_) => {
|
||||
panic!("External texture handle should not go through texture_cache.");
|
||||
|
@ -490,10 +490,7 @@ pub struct RasterizedBlobImage {
|
||||
/// image or tile.
|
||||
pub rasterized_rect: DeviceIntRect,
|
||||
/// Backing store. The format is stored out of band in `BlobImageDescriptor`.
|
||||
///
|
||||
/// None means the image only has fully transparent content. We can skip storing
|
||||
/// and rendering it.
|
||||
pub data: Option<Arc<Vec<u8>>>,
|
||||
pub data: Arc<Vec<u8>>,
|
||||
}
|
||||
|
||||
/// Error code for when blob rasterization failed.
|
||||
|
@ -98,7 +98,7 @@ fn render_blob(
|
||||
}
|
||||
|
||||
Ok(RasterizedBlobImage {
|
||||
data: Some(Arc::new(texels)),
|
||||
data: Arc::new(texels),
|
||||
rasterized_rect,
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user