Bug 1921980 - Retain snapshotted pictures in the resource cache. r=gw

Differential Revision: https://phabricator.services.mozilla.com/D225227
This commit is contained in:
Nicolas Silva 2024-11-07 09:01:56 +00:00
Родитель b58d15506b
Коммит c0c13f6ff1
12 изменённых файлов: 343 добавлений и 148 удалений

Просмотреть файл

@ -94,12 +94,12 @@
//! blend the overlay tile (this is not always optimal right now, but will be
//! improved as a follow up).
use api::{MixBlendMode, PremultipliedColorF, FilterPrimitiveKind, SVGFE_GRAPH_MAX};
use api::{FilterPrimitiveKind, MixBlendMode, PremultipliedColorF, SVGFE_GRAPH_MAX};
use api::{PropertyBinding, PropertyBindingId, FilterPrimitive, FilterOpGraphPictureBufferId, RasterSpace};
use api::{DebugFlags, ImageKey, ColorF, ColorU, PrimitiveFlags};
use api::{DebugFlags, ImageKey, ColorF, ColorU, PrimitiveFlags, SnapshotInfo};
use api::{ImageRendering, ColorDepth, YuvRangedColorSpace, YuvFormat, AlphaType};
use api::units::*;
use crate::command_buffer::PrimitiveCommand;
use crate::{command_buffer::PrimitiveCommand, render_task_graph::RenderTaskGraphBuilder, renderer::GpuBufferBuilderF};
use crate::box_shadow::BLUR_SAMPLE_SCALE;
use crate::clip::{ClipStore, ClipChainInstance, ClipLeafId, ClipNodeId, ClipTreeBuilder};
use crate::profiler::{self, TransactionProfile};
@ -3533,7 +3533,7 @@ impl TileCacheInstance {
PrimitiveInstanceKind::TextRun { .. } => {
// These don't contribute dependencies
}
};
};
self.maybe_report_promotion_failure(promotion_result, pic_coverage_rect, &mut promotion_failure_reported);
@ -4209,6 +4209,8 @@ bitflags! {
const PRESERVE3D = 4;
/// A backdrop that is reused which requires a surface.
const BACKDROP = 8;
/// We may need to render the picture into an image and cache it.
const SNAPSHOT = 16;
}
}
@ -5061,6 +5063,10 @@ pub struct PicturePrimitive {
/// picture, to be ignored when clipping those primitives and applied
/// later when compositing the picture.
pub clip_root: Option<ClipNodeId>,
/// If provided, cache the content of this picture into an image
/// associated with the image key.
pub snapshot: Option<SnapshotInfo>,
}
impl PicturePrimitive {
@ -5132,6 +5138,7 @@ impl PicturePrimitive {
spatial_node_index: SpatialNodeIndex,
raster_space: RasterSpace,
flags: PictureFlags,
snapshot: Option<SnapshotInfo>,
) -> Self {
PicturePrimitive {
prim_list,
@ -5149,6 +5156,7 @@ impl PicturePrimitive {
raster_space,
flags,
clip_root: None,
snapshot,
}
}
@ -5911,15 +5919,23 @@ impl PicturePrimitive {
).with_uv_rect_kind(uv_rect_kind)
);
let blur_render_task_id = RenderTask::new_blur(
blur_std_deviation,
picture_task_id,
frame_state.rg_builder,
RenderTargetKind::Color,
None,
original_size.to_i32(),
);
let blur_render_task_id = request_render_task(
frame_state,
&self.snapshot,
&surface_rects,
false,
&mut|rg_builder, _, _| {
RenderTask::new_blur(
blur_std_deviation,
picture_task_id,
rg_builder,
RenderTargetKind::Color,
None,
original_size.to_i32(),
)
}
);
primary_render_task_id = blur_render_task_id;
surface_descriptor = SurfaceDescriptor::new_chained(
@ -5978,6 +5994,8 @@ impl PicturePrimitive {
);
}
// TODO: Ensure that snapshots bake their shadow.
// Add this content picture as a dependency of the parent surface, to
// ensure it isn't free'd after the shadow uses it as an input.
frame_state.surface_builder.add_picture_render_task(picture_task_id);
@ -6075,23 +6093,32 @@ impl PicturePrimitive {
let cmd_buffer_index = frame_state.cmd_buffers.create_cmd_buffer();
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new_dynamic(
task_size,
RenderTaskKind::new_picture(
task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
let is_opaque = false; // TODO
let render_task_id = request_render_task(
frame_state,
&self.snapshot,
&surface_rects,
is_opaque,
&mut|rg_builder, _, _| {
rg_builder.add().init(
RenderTask::new_dynamic(
task_size,
RenderTaskKind::new_picture(
task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
}
);
primary_render_task_id = render_task_id;
@ -6104,23 +6131,32 @@ impl PicturePrimitive {
PictureCompositeMode::Filter(..) => {
let cmd_buffer_index = frame_state.cmd_buffers.create_cmd_buffer();
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
let is_opaque = false; // TODO
let render_task_id = request_render_task(
frame_state,
&self.snapshot,
&surface_rects,
is_opaque,
&mut|rg_builder, _, _| {
rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
},
);
primary_render_task_id = render_task_id;
@ -6133,23 +6169,32 @@ impl PicturePrimitive {
PictureCompositeMode::ComponentTransferFilter(..) => {
let cmd_buffer_index = frame_state.cmd_buffers.create_cmd_buffer();
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
let is_opaque = false; // TODO
let render_task_id = request_render_task(
frame_state,
&self.snapshot,
&surface_rects,
is_opaque,
&mut|rg_builder, _, _| {
rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
}
);
primary_render_task_id = render_task_id;
@ -6163,23 +6208,32 @@ impl PicturePrimitive {
PictureCompositeMode::Blit(_) => {
let cmd_buffer_index = frame_state.cmd_buffers.create_cmd_buffer();
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
let is_opaque = false; // TODO
let render_task_id = request_render_task(
frame_state,
&self.snapshot,
&surface_rects,
is_opaque,
&mut|rg_builder, _, _| {
rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
}
);
primary_render_task_id = render_task_id;
@ -6198,23 +6252,32 @@ impl PicturePrimitive {
// match cases (they used to be quite different).
let cmd_buffer_index = frame_state.cmd_buffers.create_cmd_buffer();
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
let is_opaque = false; // TODO
let render_task_id = request_render_task(
frame_state,
&self.snapshot,
&surface_rects,
is_opaque,
&mut|rg_builder, _, _| {
rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.needs_scissor_rect,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
cmd_buffer_index,
can_use_shared_surface,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
}
);
primary_render_task_id = render_task_id;
@ -6246,14 +6309,23 @@ impl PicturePrimitive {
).with_uv_rect_kind(surface_rects.uv_rect_kind)
);
let filter_task_id = RenderTask::new_svg_filter(
primitives,
filter_datas,
frame_state.rg_builder,
surface_rects.clipped.size().to_i32(),
surface_rects.uv_rect_kind,
picture_task_id,
device_pixel_scale,
let is_opaque = false; // TODO
let filter_task_id = request_render_task(
frame_state,
&self.snapshot,
&surface_rects,
is_opaque,
&mut|rg_builder, _, _| {
RenderTask::new_svg_filter(
primitives,
filter_datas,
rg_builder,
surface_rects.clipped.size().to_i32(),
surface_rects.uv_rect_kind,
picture_task_id,
device_pixel_scale,
)
}
);
primary_render_task_id = filter_task_id;
@ -6304,18 +6376,26 @@ impl PicturePrimitive {
// Produce the target pixels, this is the result of the
// composite op
let filter_task_id = RenderTask::new_svg_filter_graph(
filters,
&mut frame_state.rg_builder,
&mut frame_state.gpu_cache,
data_stores,
surface_rects.uv_rect_kind,
picture_task_id,
source_subregion.cast_unit(),
target_subregion.cast_unit(),
prim_subregion.cast_unit(),
surface_rects.clipped.cast_unit(),
surface_rects.clipped_local.cast_unit(),
let filter_task_id = request_render_task(
frame_state,
&self.snapshot,
&surface_rects,
false,
&mut|rg_builder, _, gpu_cache| {
RenderTask::new_svg_filter_graph(
filters,
rg_builder,
gpu_cache,
data_stores,
surface_rects.uv_rect_kind,
picture_task_id,
source_subregion.cast_unit(),
target_subregion.cast_unit(),
prim_subregion.cast_unit(),
surface_rects.clipped.cast_unit(),
surface_rects.clipped_local.cast_unit(),
)
}
);
primary_render_task_id = filter_task_id;
@ -7047,7 +7127,7 @@ impl PicturePrimitive {
thickness,
color,
ColorF::TRANSPARENT,
);
);
}
}
@ -7445,7 +7525,7 @@ impl TileNode {
}
}
}
/// Calculate the four child rects for a given node
fn get_child_rects(
rect: &PictureBox2D,
@ -8243,3 +8323,46 @@ fn test_drop_filter_dirty_region_outside_prim() {
).expect("No surface rect");
assert_eq!(info.task_size, DeviceIntSize::new(432, 578));
}
fn request_render_task(
frame_state: &mut FrameBuildingState,
snapshot: &Option<SnapshotInfo>,
surface_rects: &SurfaceAllocInfo,
is_opaque: bool,
f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF, &mut GpuCache) -> RenderTaskId,
) -> RenderTaskId {
let task_id = match snapshot {
Some(info) => {
let task_id = frame_state.resource_cache.render_as_image(
info.key.as_image(),
surface_rects.task_size,
frame_state.rg_builder,
&mut frame_state.frame_gpu_data.f32,
frame_state.gpu_cache,
is_opaque,
f
);
// TODO(bug 1929809): adding the dependency in the other branch causes
// a panic in reftests/blend/backdrop-filter-blend-container.yaml.
// Presumably if we use backdrop filters with snapshotting it will
// trigger the panic as well.
frame_state.surface_builder.add_child_render_task(
task_id,
frame_state.rg_builder,
);
task_id
}
None => {
f(
frame_state.rg_builder,
&mut frame_state.frame_gpu_data.f32,
frame_state.gpu_cache
)
}
};
task_id
}

Просмотреть файл

@ -413,7 +413,7 @@ fn prepare_interned_prim_for_render(
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
&mut frame_state.surface_builder,
&mut |rg_builder, _| {
&mut |rg_builder, _, _| {
rg_builder.add().init(RenderTask::new_dynamic(
task_size,
RenderTaskKind::new_line_decoration(
@ -567,7 +567,7 @@ fn prepare_interned_prim_for_render(
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
&mut frame_state.surface_builder,
&mut |rg_builder, _| {
&mut |rg_builder, _, _| {
rg_builder.add().init(RenderTask::new_dynamic(
cache_size,
RenderTaskKind::new_border_segment(

Просмотреть файл

@ -293,7 +293,7 @@ impl ConicGradientTemplate {
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
&mut frame_state.surface_builder,
&mut |rg_builder, gpu_buffer_builder| {
&mut |rg_builder, gpu_buffer_builder, _| {
let stops = GradientGpuBlockBuilder::build(
false,
gpu_buffer_builder,

Просмотреть файл

@ -525,7 +525,7 @@ impl LinearGradientTemplate {
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
&mut frame_state.surface_builder,
&mut |rg_builder, _| {
&mut |rg_builder, _, _| {
rg_builder.add().init(RenderTask::new_dynamic(
self.task_size,
RenderTaskKind::FastLinearGradient(gradient),
@ -554,7 +554,7 @@ impl LinearGradientTemplate {
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
&mut frame_state.surface_builder,
&mut |rg_builder, gpu_buffer_builder| {
&mut |rg_builder, gpu_buffer_builder, _| {
let stops = Some(GradientGpuBlockBuilder::build(
self.reverse_stops,
gpu_buffer_builder,

Просмотреть файл

@ -259,7 +259,7 @@ impl RadialGradientTemplate {
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
&mut frame_state.surface_builder,
&mut |rg_builder, gpu_buffer_builder| {
&mut |rg_builder, gpu_buffer_builder, _| {
let stops = GradientGpuBlockBuilder::build(
false,
gpu_buffer_builder,

Просмотреть файл

@ -260,7 +260,7 @@ impl ImageData {
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
&mut frame_state.surface_builder,
&mut |rg_builder, _| {
&mut |rg_builder, _, _| {
// Create a task to blit from the texture cache to
// a normal transient render task surface.
// TODO: figure out if/when we can do a blit instead.

Просмотреть файл

@ -677,7 +677,7 @@ impl RenderTaskKind {
gpu_buffer_builder,
rg_builder,
surface_builder,
&mut |rg_builder, _| {
&mut |rg_builder, _, _| {
let clip_data = ClipData::rounded_rect(
source.minimal_shadow_rect.size(),
&source.shadow_radius,

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ImageDescriptor, ImageDescriptorFlags, DirtyRect};
use api::{DirtyRect, ImageDescriptor, ImageDescriptorFlags, SnapshotImageKey};
use api::units::*;
use crate::border::BorderSegmentCacheKey;
use crate::box_shadow::{BoxShadowCacheKey};
@ -52,6 +52,7 @@ pub enum RenderTaskCacheKeyKind {
LinearGradient(LinearGradientCacheKey),
RadialGradient(RadialGradientCacheKey),
ConicGradient(ConicGradientCacheKey),
Snapshot(SnapshotImageKey),
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
@ -232,13 +233,13 @@ impl RenderTaskCache {
gpu_buffer_builder: &mut GpuBufferBuilderF,
rg_builder: &mut RenderTaskGraphBuilder,
surface_builder: &mut SurfaceBuilder,
f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF) -> RenderTaskId,
f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF, &mut GpuCache) -> RenderTaskId,
) -> RenderTaskId {
// If this render task cache is being drawn this frame, ensure we hook up the
// render task for it as a dependency of any render task that uses this as
// an input source.
let (task_id, rendered_this_frame) = match key {
None => (f(rg_builder, gpu_buffer_builder), true),
None => (f(rg_builder, gpu_buffer_builder, gpu_cache), true),
Some(key) => self.request_render_task_impl(
key,
is_opaque,
@ -285,7 +286,7 @@ impl RenderTaskCache {
gpu_cache: &mut GpuCache,
gpu_buffer_builder: &mut GpuBufferBuilderF,
rg_builder: &mut RenderTaskGraphBuilder,
f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF) -> RenderTaskId,
f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF, &mut GpuCache) -> RenderTaskId,
) -> (RenderTaskId, bool) {
let frame_id = self.frame_id;
let size = key.size;
@ -310,7 +311,7 @@ impl RenderTaskCache {
if texture_cache.request(&cache_entry.handle, gpu_cache) {
// Invoke user closure to get render task chain
// to draw this into the texture cache.
let render_task_id = f(rg_builder, gpu_buffer_builder);
let render_task_id = f(rg_builder, gpu_buffer_builder, gpu_cache);
cache_entry.user_data = None;
cache_entry.is_opaque = is_opaque;

Просмотреть файл

@ -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::{BlobImageRequest, RasterizedBlobImage, ImageFormat, ImageDescriptorFlags};
use api::{BlobImageRequest, ImageDescriptorFlags, ImageFormat, RasterizedBlobImage};
use api::{DebugFlags, FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
use api::{ExternalImageData, ExternalImageType, ExternalImageId, BlobImageResult};
use api::{DirtyRect, GlyphDimensions, IdNamespace, DEFAULT_TILE_SIZE};
@ -115,6 +115,11 @@ pub enum CachedImageData {
///
/// The commands are stored elsewhere and this variant is used as a placeholder.
Blob,
/// A stacking context for which a snapshot has been requested.
///
/// The snapshot is grabbed from GPU-side rasterized pixels so there is no
/// CPU-side data to store here.
Snapshot,
/// 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),
@ -139,6 +144,14 @@ impl CachedImageData {
}
}
#[inline]
pub fn is_snapshot(&self) -> bool {
match *self {
CachedImageData::Snapshot => true,
_ => false,
}
}
/// Returns true if this variant of CachedImageData should go through the texture
/// cache.
#[inline]
@ -150,6 +163,7 @@ impl CachedImageData {
},
CachedImageData::Blob => true,
CachedImageData::Raw(_) => true,
CachedImageData::Snapshot => true,
}
}
}
@ -575,6 +589,7 @@ impl ResourceCache {
// not make sense to tile them into smaller ones.
info.image_type == ExternalImageType::Buffer && size_check
}
CachedImageData::Snapshot => false,
}
}
@ -598,10 +613,10 @@ impl ResourceCache {
gpu_buffer_builder: &mut GpuBufferBuilderF,
rg_builder: &mut RenderTaskGraphBuilder,
surface_builder: &mut SurfaceBuilder,
f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF) -> RenderTaskId,
f: &mut dyn FnMut(&mut RenderTaskGraphBuilder, &mut GpuBufferBuilderF, &mut GpuCache) -> RenderTaskId,
) -> RenderTaskId {
self.cached_render_tasks.request_render_task(
key,
key.clone(),
&mut self.texture_cache,
is_opaque,
parent,
@ -748,11 +763,25 @@ impl ResourceCache {
ResourceUpdate::DeleteBlobImage(img) => {
self.delete_image_template(img.as_image());
}
ResourceUpdate::AddSnapshotImage(_img) => {
// TODO
ResourceUpdate::AddSnapshotImage(img) => {
let format = self.texture_cache.shared_color_expected_format();
self.add_image_template(
img.key.as_image(),
ImageDescriptor {
format,
// We'll know about the size when creating the render task.
size: DeviceIntSize::zero(),
stride: None,
offset: 0,
flags: ImageDescriptorFlags::empty(),
},
CachedImageData::Snapshot,
&DeviceIntRect::zero(),
None,
);
}
ResourceUpdate::DeleteSnapshotImage(_img) => {
// TODO
ResourceUpdate::DeleteSnapshotImage(img) => {
self.delete_image_template(img.as_image());
}
ResourceUpdate::DeleteFont(font) => {
if let Some(shared_key) = self.resources.fonts.font_keys.delete_key(&font) {
@ -1333,7 +1362,10 @@ impl ResourceCache {
ExternalImageType::Buffer => None,
},
// raw and blob image are all using resource_cache.
CachedImageData::Raw(..) | CachedImageData::Blob => None,
CachedImageData::Raw(..)
| CachedImageData::Blob
| CachedImageData::Snapshot
=> None,
};
ImageProperties {
@ -1437,7 +1469,11 @@ impl ResourceCache {
let mut updates: SmallVec<[(CachedImageData, Option<DeviceIntRect>); 1]> = SmallVec::new();
match image_template.data {
CachedImageData::Raw(..) | CachedImageData::External(..) => {
CachedImageData::Snapshot => {
// The update is done in ResourceCache::render_as_image.
}
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));
@ -1517,11 +1553,14 @@ impl ResourceCache {
}
};
let eviction = if image_template.data.is_blob() {
entry.manual_eviction = true;
Eviction::Manual
} else {
Eviction::Auto
let eviction = match &image_template.data {
CachedImageData::Blob | CachedImageData::Snapshot => {
entry.manual_eviction = true;
Eviction::Manual
}
_ => {
Eviction::Auto
}
};
//Note: at this point, the dirty rectangle is local to the descriptor space
@ -1788,7 +1827,9 @@ 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(..) => 0,
CachedImageData::Blob
| CachedImageData::External(..)
| CachedImageData::Snapshot => 0,
}
}
@ -2131,6 +2172,9 @@ impl ResourceCache {
.unwrap();
other_paths.insert(key, short_path);
}
CachedImageData::Snapshot => {
unimplemented!();
}
CachedImageData::External(ref ext) => {
let short_path = format!("externals/{}", external_images.len() + 1);
other_paths.insert(key, short_path.clone());

Просмотреть файл

@ -35,7 +35,7 @@
//! - backdrop filters (see add_backdrop_filter)
//!
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter, BuiltDisplayList, PrimitiveFlags};
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayList, BuiltDisplayListIter, PrimitiveFlags, SnapshotInfo};
use api::{ClipId, ColorF, CommonItemProperties, ComplexClipRegion, ComponentTransferFuncType, RasterSpace};
use api::{DebugFlags, DisplayItem, DisplayItemRef, ExtendMode, ExternalScrollId, FilterData};
use api::{FilterOp, FilterPrimitive, FontInstanceKey, FontSize, GlyphInstance, GlyphOptions, GradientStop};
@ -152,6 +152,7 @@ pub struct CompositeOps {
pub filters: Vec<Filter>,
pub filter_datas: Vec<FilterData>,
pub filter_primitives: Vec<FilterPrimitive>,
pub snapshot: Option<SnapshotInfo>,
// Requires two source textures (e.g. mix-blend-mode)
pub mix_blend_mode: Option<MixBlendMode>,
@ -162,20 +163,23 @@ impl CompositeOps {
filters: Vec<Filter>,
filter_datas: Vec<FilterData>,
filter_primitives: Vec<FilterPrimitive>,
mix_blend_mode: Option<MixBlendMode>
mix_blend_mode: Option<MixBlendMode>,
snapshot: Option<SnapshotInfo>,
) -> Self {
CompositeOps {
filters,
filter_datas,
filter_primitives,
mix_blend_mode,
snapshot,
}
}
pub fn is_empty(&self) -> bool {
self.filters.is_empty() &&
self.filter_primitives.is_empty() &&
self.mix_blend_mode.is_none()
self.mix_blend_mode.is_none() &&
self.snapshot.is_none()
}
/// Returns true if this CompositeOps contains any filters that affect
@ -332,6 +336,7 @@ impl PictureChainBuilder {
self.spatial_node_index,
self.raster_space,
flags,
None,
))
);
@ -364,6 +369,7 @@ impl PictureChainBuilder {
interners: &mut Interners,
prim_store: &mut PrimitiveStore,
clip_tree_builder: &mut ClipTreeBuilder,
snapshot: Option<SnapshotInfo>,
) -> PrimitiveInstance {
let mut flags = PictureFlags::empty();
if self.establishes_sub_graph {
@ -373,7 +379,9 @@ impl PictureChainBuilder {
match self.current {
PictureSource::WrappedPicture { instance } => {
let pic_index = instance.kind.as_pic();
prim_store.pictures[pic_index.0].flags |= flags;
let picture = &mut prim_store.pictures[pic_index.0];
picture.flags |= flags;
picture.snapshot = snapshot;
instance
}
@ -395,6 +403,7 @@ impl PictureChainBuilder {
self.spatial_node_index,
self.raster_space,
flags,
snapshot,
))
);
@ -937,6 +946,7 @@ impl<'a> SceneBuilder<'a> {
filter_datas_for_compositing(item.filter_datas()),
filter_primitives_for_compositing(item.filter_primitives()),
info.stacking_context.mix_blend_mode_for_compositing(),
info.snapshot,
);
let sc_info = self.push_stacking_context(
@ -2245,6 +2255,11 @@ impl<'a> SceneBuilder<'a> {
// clip node doesn't affect the stacking context rect.
let mut blit_reason = BlitReason::empty();
// Stacking context snapshots are offscreen syrfaces.
if composite_ops.snapshot.is_some() {
blit_reason = BlitReason::SNAPSHOT;
}
// If this stacking context has any complex clips, we need to draw it
// to an off-screen surface.
if let Some(clip_chain_id) = clip_chain_id {
@ -2393,6 +2408,7 @@ impl<'a> SceneBuilder<'a> {
stacking_context.spatial_node_index,
stacking_context.raster_space,
PictureFlags::empty(),
None,
))
);
@ -2437,6 +2453,7 @@ impl<'a> SceneBuilder<'a> {
stacking_context.spatial_node_index,
stacking_context.raster_space,
PictureFlags::empty(),
None,
))
);
@ -2468,6 +2485,7 @@ impl<'a> SceneBuilder<'a> {
&mut self.interners,
&mut self.prim_store,
&mut self.clip_tree_builder,
None,
);
prims.push(ExtendedPrimitiveInstance {
@ -2541,6 +2559,7 @@ impl<'a> SceneBuilder<'a> {
stacking_context.spatial_node_index,
stacking_context.raster_space,
PictureFlags::empty(),
None,
))
);
@ -2609,6 +2628,7 @@ impl<'a> SceneBuilder<'a> {
&mut self.interners,
&mut self.prim_store,
&mut self.clip_tree_builder,
stacking_context.composite_ops.snapshot,
);
// The primitive instance for the remainder of flat children of this SC
@ -3020,6 +3040,7 @@ impl<'a> SceneBuilder<'a> {
pending_shadow.spatial_node_index,
raster_space,
PictureFlags::empty(),
None,
))
);
@ -3742,6 +3763,7 @@ impl<'a> SceneBuilder<'a> {
&mut self.interners,
&mut self.prim_store,
&mut self.clip_tree_builder,
None,
);
// Extract the pic index for the intermediate surface. We need to
@ -4576,6 +4598,7 @@ impl FlattenedStackingContext {
self.spatial_node_index,
self.raster_space,
PictureFlags::empty(),
None
))
);
@ -4760,7 +4783,7 @@ fn read_gradient_stops(stops: ItemRange<GradientStop>) -> Vec<GradientStopKey> {
/// A helper for reusing the scene builder's memory allocations and dropping
/// scene allocations on the scene builder thread to avoid lock contention in
/// jemalloc.
/// jemalloc.
pub struct SceneRecycler {
pub tx: Sender<BuiltScene>,
rx: Receiver<BuiltScene>,
@ -4829,7 +4852,7 @@ impl SceneRecycler {
self.clip_store = scene.clip_store;
// We currently retain top-level allocations but don't attempt to retain leaf
// allocations in the prim store and clip store. We don't have to reset it here
// but doing so avoids dropping the leaf allocations in the
// but doing so avoids dropping the leaf allocations in the
self.prim_store.reset();
self.clip_store.reset();
self.hit_testing_scene = Arc::try_unwrap(scene.hit_testing_scene).ok();

Просмотреть файл

@ -1574,6 +1574,9 @@ impl TextureCacheUpdate {
dirty_rect: &ImageDirtyRect,
) -> TextureCacheUpdate {
let source = match data {
CachedImageData::Snapshot => {
panic!("Snapshots should not do texture uploads");
}
CachedImageData::Blob => {
panic!("The vector image should have been rasterized.");
}

Просмотреть файл

@ -638,6 +638,7 @@ fn create_tile_cache(
scroll_root,
RasterSpace::Screen,
PictureFlags::empty(),
None,
));
tile_cache_pictures.push(PictureIndex(pic_index));