Bug 1500466 - Update webrender to commit 15656cb497303703b4d541d3e14292259e4c5343. r=kats

Differential Revision: https://phabricator.services.mozilla.com/D9348

--HG--
extra : moz-landing-system : lando
This commit is contained in:
WR Updater Bot 2018-10-20 19:24:12 +00:00
Родитель e96ba0d946
Коммит ec100e51b3
8 изменённых файлов: 318 добавлений и 332 удалений

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

@ -507,7 +507,7 @@ impl AlphaBatchBuilder {
for poly in splitter.sort(vec3(0.0, 0.0, 1.0)) {
let prim_instance = &pic.prim_instances[poly.anchor];
let prim_index = prim_instance.prim_index;
let pic_metadata = &ctx.prim_store.primitives[prim_index.0].metadata;
let prim = &ctx.prim_store.primitives[prim_index.0];
if cfg!(debug_assertions) && ctx.prim_store.chase_id == Some(prim_index) {
println!("\t\tsplit polygon {:?}", poly.points);
}
@ -523,7 +523,7 @@ impl AlphaBatchBuilder {
.map_or(OPAQUE_TASK_ADDRESS, |id| render_tasks.get_task_address(id));
let prim_header = PrimitiveHeader {
local_rect: pic_metadata.local_rect,
local_rect: prim.local_rect,
local_clip_rect: prim_instance.combined_local_clip_rect,
task_address,
specific_prim_address: GpuCacheAddress::invalid(),
@ -531,7 +531,18 @@ impl AlphaBatchBuilder {
transform_id,
};
let pic = ctx.prim_store.get_pic(prim_index);
let pic_index = match prim.details {
PrimitiveDetails::Brush(ref brush) => {
match brush.kind {
BrushKind::Picture { pic_index, .. } => pic_index,
_ => unreachable!(),
}
}
PrimitiveDetails::TextRun(..) => {
unreachable!();
}
};
let pic = &ctx.prim_store.pictures[pic_index.0];
let (uv_rect_address, _) = pic
.raster_config
@ -607,7 +618,6 @@ impl AlphaBatchBuilder {
plane_split_anchor: usize,
) {
let prim = &ctx.prim_store.primitives[prim_instance.prim_index.0];
let prim_metadata = &prim.metadata;
if prim_instance.clipped_world_rect.is_none() {
return;
@ -632,8 +642,7 @@ impl AlphaBatchBuilder {
.expect("bug");
// If the primitive is internally decomposed into multiple sub-primitives we may not
// use some of the per-primitive data typically stored in PrimitiveMetadata and get
// it from each sub-primitive instead.
// use some of the per-primitive data and get it from each sub-primitive instead.
let is_multiple_primitives = match prim.details {
PrimitiveDetails::Brush(ref brush) => {
match brush.kind {
@ -667,7 +676,7 @@ impl AlphaBatchBuilder {
};
let prim_header = PrimitiveHeader {
local_rect: prim_metadata.local_rect,
local_rect: prim.local_rect,
local_clip_rect: prim_instance.combined_local_clip_rect,
task_address,
specific_prim_address: prim_cache_address,
@ -683,7 +692,9 @@ impl AlphaBatchBuilder {
match prim.details {
PrimitiveDetails::Brush(ref brush) => {
match brush.kind {
BrushKind::Picture(ref picture) => {
BrushKind::Picture { pic_index, .. } => {
let picture = &ctx.prim_store.pictures[pic_index.0];
// If this picture is participating in a 3D rendering context,
// then don't add it to any batches here. Instead, create a polygon
// for it and add it to the current plane splitter.
@ -698,8 +709,9 @@ impl AlphaBatchBuilder {
// rather that rectangles. The interpolation still works correctly
// since we determine the UVs by doing a bilerp with a factor
// from the original local rect.
let local_rect = prim_metadata.local_rect
.intersection(&prim_instance.combined_local_clip_rect);
let local_rect = prim
.local_rect
.intersection(&prim_instance.combined_local_clip_rect);
if let Some(local_rect) = local_rect {
match transform.transform_kind() {
@ -828,8 +840,8 @@ impl AlphaBatchBuilder {
0,
]);
let shadow_rect = prim_metadata.local_rect.translate(&offset);
let shadow_clip_rect = prim_metadata.local_clip_rect.translate(&offset);
let shadow_rect = prim.local_rect.translate(&offset);
let shadow_clip_rect = prim.local_clip_rect.translate(&offset);
let shadow_prim_header = PrimitiveHeader {
local_rect: shadow_rect,

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

@ -26,8 +26,8 @@ use internal_types::{FastHashMap, FastHashSet};
use picture::{PictureCompositeMode, PictureIdGenerator, PicturePrimitive};
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, PrimitiveInstance};
use prim_store::{EdgeAaSegmentMask, ImageSource, PrimitiveOpacity, PrimitiveKey};
use prim_store::{BorderSource, BrushSegment, BrushSegmentVec, PrimitiveContainer, PrimitiveIndex, PrimitiveStore};
use prim_store::{OpacityBinding, ScrollNodeAndClipChain, TextRunPrimitive};
use prim_store::{BorderSource, BrushSegment, BrushSegmentVec, PrimitiveContainer, PrimitiveStore};
use prim_store::{OpacityBinding, ScrollNodeAndClipChain, TextRunPrimitive, PictureIndex};
use render_backend::{DocumentView};
use resource_cache::{FontInstanceMap, ImageRequest};
use scene::{Scene, ScenePipeline, StackingContextHelpers};
@ -159,9 +159,9 @@ pub struct DisplayListFlattener<'a> {
/// The estimated count of primtives we expect to encounter during flattening.
prim_count_estimate: usize,
/// The root primitive index for this flattener. This is the primitive
/// The root picture index for this flattener. This is the picture
/// to start the culling phase from.
pub root_prim_index: PrimitiveIndex,
pub root_pic_index: PictureIndex,
}
impl<'a> DisplayListFlattener<'a> {
@ -201,7 +201,7 @@ impl<'a> DisplayListFlattener<'a> {
picture_id_generator,
resources,
prim_count_estimate: 0,
root_prim_index: PrimitiveIndex(0),
root_pic_index: PictureIndex(0),
};
flattener.push_root(
@ -1064,9 +1064,10 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.requested_raster_space,
stacking_context.normal_primitives,
);
let leaf_pic_index = self.prim_store.create_picture(leaf_picture);
// Create a brush primitive that draws this picture.
let leaf_prim = BrushPrimitive::new_picture(leaf_picture);
let leaf_prim = BrushPrimitive::new_picture(leaf_pic_index);
// Add the brush to the parent picture.
let leaf_prim_index = self.prim_store.add_primitive(
@ -1078,6 +1079,7 @@ impl<'a> DisplayListFlattener<'a> {
// Create a chain of pictures based on presence of filters,
// mix-blend-mode and/or 3d rendering context containers.
let mut current_prim_index = leaf_prim_index;
let mut current_pic_index = leaf_pic_index;
// For each filter, create a new image with that composite mode.
for filter in &stacking_context.composite_ops.filters {
@ -1100,8 +1102,10 @@ impl<'a> DisplayListFlattener<'a> {
),
],
);
let filter_pic_index = self.prim_store.create_picture(filter_picture);
current_pic_index = filter_pic_index;
let filter_prim = BrushPrimitive::new_picture(filter_picture);
let filter_prim = BrushPrimitive::new_picture(filter_pic_index);
current_prim_index = self.prim_store.add_primitive(
&LayoutRect::zero(),
@ -1111,7 +1115,7 @@ impl<'a> DisplayListFlattener<'a> {
// Run the optimize pass on this picture, to see if we can
// collapse opacity and avoid drawing to an off-screen surface.
self.prim_store.optimize_picture_if_possible(current_prim_index);
self.prim_store.optimize_picture_if_possible(current_pic_index);
}
// Same for mix-blend-mode.
@ -1133,8 +1137,10 @@ impl<'a> DisplayListFlattener<'a> {
),
],
);
let blend_pic_index = self.prim_store.create_picture(blend_picture);
current_pic_index = blend_pic_index;
let blend_prim = BrushPrimitive::new_picture(blend_picture);
let blend_prim = BrushPrimitive::new_picture(blend_pic_index);
current_prim_index = self.prim_store.add_primitive(
&LayoutRect::zero(),
@ -1167,8 +1173,10 @@ impl<'a> DisplayListFlattener<'a> {
stacking_context.requested_raster_space,
prims,
);
let container_pic_index = self.prim_store.create_picture(container_picture);
current_pic_index = container_pic_index;
let container_prim = BrushPrimitive::new_picture(container_picture);
let container_prim = BrushPrimitive::new_picture(container_pic_index);
current_prim_index = self.prim_store.add_primitive(
&LayoutRect::zero(),
@ -1181,7 +1189,7 @@ impl<'a> DisplayListFlattener<'a> {
if self.sc_stack.is_empty() {
// This must be the root stacking context
self.root_prim_index = current_prim_index;
self.root_pic_index = current_pic_index;
return;
}
@ -1500,7 +1508,8 @@ impl<'a> DisplayListFlattener<'a> {
);
// Create the primitive to draw the shadow picture into the scene.
let shadow_prim = BrushPrimitive::new_picture(shadow_pic);
let shadow_pic_index = self.prim_store.create_picture(shadow_pic);
let shadow_prim = BrushPrimitive::new_picture(shadow_pic_index);
let shadow_prim_index = self.prim_store.add_primitive(
&LayoutRect::zero(),
&max_clip,

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

@ -13,7 +13,7 @@ use gpu_types::{PrimitiveHeaders, TransformPalette, UvRectKind};
use hit_test::{HitTester, HitTestingRun};
use internal_types::{FastHashMap};
use picture::{PictureCompositeMode, PictureSurface, RasterConfig};
use prim_store::{PrimitiveIndex, PrimitiveStore, SpaceMapper};
use prim_store::{PrimitiveIndex, PrimitiveStore, SpaceMapper, PictureIndex};
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
use render_backend::{FrameResources, FrameId};
use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
@ -58,7 +58,7 @@ pub struct FrameBuilder {
background_color: Option<ColorF>,
window_size: DeviceUintSize,
scene_id: u64,
root_prim_index: PrimitiveIndex,
root_pic_index: PictureIndex,
pub prim_store: PrimitiveStore,
pub clip_store: ClipStore,
pub hit_testing_runs: Vec<HitTestingRun>,
@ -88,6 +88,7 @@ pub struct FrameBuildingState<'a> {
}
pub struct PictureContext {
pub pic_index: PictureIndex,
pub pipeline_id: PipelineId,
pub apply_local_clip_rect: bool,
pub inflation_factor: f32,
@ -138,7 +139,7 @@ impl FrameBuilder {
window_size: DeviceUintSize::zero(),
background_color: None,
scene_id: 0,
root_prim_index: PrimitiveIndex(0),
root_pic_index: PictureIndex(0),
config: FrameBuilderConfig {
default_font_render_mode: FontRenderMode::Mono,
dual_source_blending_is_enabled: true,
@ -159,7 +160,7 @@ impl FrameBuilder {
hit_testing_runs: flattener.hit_testing_runs,
prim_store: flattener.prim_store,
clip_store: flattener.clip_store,
root_prim_index: flattener.root_prim_index,
root_pic_index: flattener.root_pic_index,
screen_rect,
background_color,
window_size,
@ -228,8 +229,9 @@ impl FrameBuilder {
let (pic_context, mut pic_state, mut instances) = self
.prim_store
.get_pic_mut(self.root_prim_index)
.pictures[self.root_pic_index.0]
.take_context(
self.root_pic_index,
&prim_context,
root_spatial_node_index,
root_spatial_node_index,
@ -251,9 +253,7 @@ impl FrameBuilder {
&mut pic_rect,
);
let pic = self
.prim_store
.get_pic_mut(self.root_prim_index);
let pic = &mut self.prim_store.pictures[self.root_pic_index.0];
pic.restore_context(
instances,
pic_context,
@ -267,7 +267,7 @@ impl FrameBuilder {
let root_render_task = RenderTask::new_picture(
RenderTaskLocation::Fixed(self.screen_rect.to_i32()),
self.screen_rect.size.to_f32(),
self.root_prim_index,
self.root_pic_index,
DeviceIntPoint::zero(),
pic_state.tasks,
UvRectKind::Rect,

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

@ -14,8 +14,7 @@ use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState};
use frame_builder::{PictureContext, PrimitiveContext};
use gpu_cache::{GpuCacheHandle};
use gpu_types::UvRectKind;
use prim_store::{PrimitiveInstance, SpaceMapper};
use prim_store::{PrimitiveMetadata, get_raster_rects};
use prim_store::{PictureIndex, PrimitiveInstance, SpaceMapper, get_raster_rects};
use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle};
use render_task::{RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
use scene::{FilterOpHelpers, SceneProperties};
@ -242,6 +241,7 @@ impl PicturePrimitive {
pub fn take_context(
&mut self,
pic_index: PictureIndex,
prim_context: &PrimitiveContext,
surface_spatial_node_index: SpatialNodeIndex,
raster_spatial_node_index: SpatialNodeIndex,
@ -366,6 +366,7 @@ impl PicturePrimitive {
};
let context = PictureContext {
pic_index,
pipeline_id: self.pipeline_id,
apply_local_clip_rect: self.apply_local_clip_rect,
inflation_factor,
@ -439,8 +440,9 @@ impl PicturePrimitive {
pub fn prepare_for_render(
&mut self,
pic_index: PictureIndex,
prim_instance: &PrimitiveInstance,
prim_metadata: &PrimitiveMetadata,
prim_local_rect: &LayoutRect,
pic_state: &mut PictureState,
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
@ -455,7 +457,7 @@ impl PicturePrimitive {
frame_context,
);
let pic_rect = PictureRect::from_untyped(&prim_metadata.local_rect.to_untyped());
let pic_rect = PictureRect::from_untyped(&prim_local_rect.to_untyped());
let (clipped, unclipped, transform) = match get_raster_rects(
pic_rect,
@ -511,7 +513,7 @@ impl PicturePrimitive {
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, device_rect.size),
unclipped.size,
prim_instance.prim_index,
pic_index,
device_rect.origin,
pic_state_for_children.tasks,
uv_rect_kind,
@ -569,7 +571,7 @@ impl PicturePrimitive {
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, device_rect.size),
unclipped.size,
prim_instance.prim_index,
pic_index,
device_rect.origin,
child_tasks,
uv_rect_kind,
@ -626,7 +628,7 @@ impl PicturePrimitive {
let mut picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, device_rect.size),
unclipped.size,
prim_instance.prim_index,
pic_index,
device_rect.origin,
pic_state_for_children.tasks,
uv_rect_kind,
@ -669,14 +671,14 @@ impl PicturePrimitive {
// Basic brush primitive header is (see end of prepare_prim_for_render_inner in prim_store.rs)
// [brush specific data]
// [segment_rect, segment data]
let shadow_rect = prim_metadata.local_rect.translate(&offset);
let shadow_rect = prim_local_rect.translate(&offset);
// ImageBrush colors
request.push(color.premultiplied());
request.push(PremultipliedColorF::WHITE);
request.push([
prim_metadata.local_rect.size.width,
prim_metadata.local_rect.size.height,
prim_local_rect.size.width,
prim_local_rect.size.height,
0.0,
0.0,
]);
@ -697,7 +699,7 @@ impl PicturePrimitive {
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
prim_instance.prim_index,
pic_index,
clipped.origin,
pic_state_for_children.tasks,
uv_rect_kind,
@ -734,7 +736,7 @@ impl PicturePrimitive {
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
prim_instance.prim_index,
pic_index,
clipped.origin,
pic_state_for_children.tasks,
uv_rect_kind,
@ -756,7 +758,7 @@ impl PicturePrimitive {
let picture_task = RenderTask::new_picture(
RenderTaskLocation::Dynamic(None, clipped.size),
unclipped.size,
prim_instance.prim_index,
pic_index,
clipped.origin,
pic_state_for_children.tasks,
uv_rect_kind,

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

@ -224,6 +224,11 @@ pub struct DeferredResolve {
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct PrimitiveIndex(pub usize);
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct PictureIndex(pub usize);
impl GpuCacheHandle {
pub fn as_int(&self, gpu_cache: &GpuCache) -> i32 {
gpu_cache.get_address(self).as_int()
@ -281,13 +286,6 @@ pub type PrimitiveDataHandle = intern::Handle<PrimitiveDataMarker>;
pub type PrimitiveDataUpdateList = intern::UpdateList<PrimitiveKey>;
pub type PrimitiveDataInterner = intern::Interner<PrimitiveKey, PrimitiveDataMarker>;
// TODO(gw): Pack the fields here better!
#[derive(Debug)]
pub struct PrimitiveMetadata {
pub local_rect: LayoutRect,
pub local_clip_rect: LayoutRect,
}
// Maintains a list of opacity bindings that have been collapsed into
// the color of a single primitive. This is an important optimization
// that avoids allocating an intermediate surface for most common
@ -372,7 +370,9 @@ pub enum BrushKind {
opacity_binding: OpacityBinding,
},
Clear,
Picture(PicturePrimitive),
Picture {
pic_index: PictureIndex,
},
Image {
request: ImageRequest,
alpha_type: AlphaType,
@ -638,20 +638,11 @@ impl BrushPrimitive {
}
}
pub fn may_need_clip_mask(&self) -> bool {
match self.kind {
BrushKind::Picture(ref pic) => {
pic.raster_config.is_some()
}
_ => {
true
}
}
}
pub fn new_picture(prim: PicturePrimitive) -> Self {
pub fn new_picture(pic_index: PictureIndex) -> Self {
BrushPrimitive {
kind: BrushKind::Picture(prim),
kind: BrushKind::Picture {
pic_index,
},
segment_desc: None,
}
}
@ -1508,30 +1499,11 @@ pub enum PrimitiveDetails {
}
pub struct Primitive {
pub metadata: PrimitiveMetadata,
pub local_rect: LayoutRect,
pub local_clip_rect: LayoutRect,
pub details: PrimitiveDetails,
}
impl Primitive {
pub fn as_pic(&self) -> &PicturePrimitive {
match self.details {
PrimitiveDetails::Brush(BrushPrimitive { kind: BrushKind::Picture(ref pic), .. }) => pic,
_ => {
panic!("bug: not a picture!");
}
}
}
pub fn as_pic_mut(&mut self) -> &mut PicturePrimitive {
match self.details {
PrimitiveDetails::Brush(BrushPrimitive { kind: BrushKind::Picture(ref mut pic), .. }) => pic,
_ => {
panic!("bug: not a picture!");
}
}
}
}
#[derive(Debug)]
pub struct PrimitiveInstance {
/// Index into the prim store containing information about
@ -1602,6 +1574,7 @@ impl PrimitiveInstance {
pub struct PrimitiveStore {
pub primitives: Vec<Primitive>,
pub pictures: Vec<PicturePrimitive>,
/// A primitive index to chase through debugging.
pub chase_id: Option<PrimitiveIndex>,
@ -1611,16 +1584,18 @@ impl PrimitiveStore {
pub fn new() -> PrimitiveStore {
PrimitiveStore {
primitives: Vec::new(),
pictures: Vec::new(),
chase_id: None,
}
}
pub fn get_pic(&self, index: PrimitiveIndex) -> &PicturePrimitive {
self.primitives[index.0].as_pic()
}
pub fn get_pic_mut(&mut self, index: PrimitiveIndex) -> &mut PicturePrimitive {
self.primitives[index.0].as_pic_mut()
pub fn create_picture(
&mut self,
prim: PicturePrimitive,
) -> PictureIndex {
let index = PictureIndex(self.pictures.len());
self.pictures.push(prim);
index
}
pub fn add_primitive(
@ -1631,34 +1606,21 @@ impl PrimitiveStore {
) -> PrimitiveIndex {
let prim_index = self.primitives.len();
let base_metadata = PrimitiveMetadata {
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
let prim = match container {
let details = match container {
PrimitiveContainer::Brush(brush) => {
let metadata = PrimitiveMetadata {
..base_metadata
};
Primitive {
metadata,
details: PrimitiveDetails::Brush(brush),
}
PrimitiveDetails::Brush(brush)
}
PrimitiveContainer::TextRun(text_cpu) => {
let metadata = PrimitiveMetadata {
..base_metadata
};
Primitive {
metadata,
details: PrimitiveDetails::TextRun(text_cpu),
}
PrimitiveDetails::TextRun(text_cpu)
}
};
let prim = Primitive {
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
details,
};
self.primitives.push(prim);
PrimitiveIndex(prim_index)
@ -1668,9 +1630,9 @@ impl PrimitiveStore {
// that can be the target for collapsing parent opacity filters into.
fn get_opacity_collapse_prim(
&self,
pic_prim_index: PrimitiveIndex,
pic_index: PictureIndex,
) -> Option<PrimitiveIndex> {
let pic = self.get_pic(pic_prim_index);
let pic = &self.pictures[pic_index.0];
// We can only collapse opacity if there is a single primitive, otherwise
// the opacity needs to be applied to the primitives as a group.
@ -1688,12 +1650,14 @@ impl PrimitiveStore {
match prim.details {
PrimitiveDetails::Brush(ref brush) => {
match brush.kind {
BrushKind::Picture(ref pic) => {
BrushKind::Picture { pic_index, .. } => {
let pic = &self.pictures[pic_index.0];
// If we encounter a picture that is a pass-through
// (i.e. no composite mode), then we can recurse into
// that to try and find a primitive to collapse to.
if pic.requested_composite_mode.is_none() {
return self.get_opacity_collapse_prim(prim_instance.prim_index);
return self.get_opacity_collapse_prim(pic_index);
}
}
// If we find a single rect or image, we can use that
@ -1721,10 +1685,10 @@ impl PrimitiveStore {
// if that picture contains one compatible primitive.
pub fn optimize_picture_if_possible(
&mut self,
pic_prim_index: PrimitiveIndex,
pic_index: PictureIndex,
) {
// Only handle opacity filters for now.
let binding = match self.get_pic(pic_prim_index).requested_composite_mode {
let binding = match self.pictures[pic_index.0].requested_composite_mode {
Some(PictureCompositeMode::Filter(FilterOp::Opacity(binding, _))) => {
binding
}
@ -1735,7 +1699,7 @@ impl PrimitiveStore {
// See if this picture contains a single primitive that supports
// opacity collapse.
match self.get_opacity_collapse_prim(pic_prim_index) {
match self.get_opacity_collapse_prim(pic_index) {
Some(prim_index) => {
let prim = &mut self.primitives[prim_index.0];
match prim.details {
@ -1773,7 +1737,7 @@ impl PrimitiveStore {
// intermediate surface or incur an extra blend / blit. Instead,
// the collapsed primitive will be drawn directly into the
// parent picture.
self.get_pic_mut(pic_prim_index).requested_composite_mode = None;
self.pictures[pic_index.0].requested_composite_mode = None;
}
pub fn prim_count(&self) -> usize {
@ -1799,8 +1763,11 @@ impl PrimitiveStore {
// picture target, if being composited.
let pic_info = {
match self.primitives[prim_instance.prim_index.0].details {
PrimitiveDetails::Brush(BrushPrimitive { kind: BrushKind::Picture(ref mut pic), .. }) => {
PrimitiveDetails::Brush(BrushPrimitive { kind: BrushKind::Picture { pic_index, .. }, .. }) => {
let pic = &mut self.pictures[pic_index.0];
match pic.take_context(
pic_index,
prim_context,
pic_state.surface_spatial_node_index,
pic_state.raster_spatial_node_index,
@ -1845,13 +1812,12 @@ impl PrimitiveStore {
};
if !pic_state_for_children.is_cacheable {
pic_state.is_cacheable = false;
pic_state.is_cacheable = false;
}
// Restore the dependencies (borrow check dance)
let prim = &mut self.primitives[prim_instance.prim_index.0];
let (new_local_rect, clip_node_collector) = prim
.as_pic_mut()
let (new_local_rect, clip_node_collector) = self
.pictures[pic_context_for_children.pic_index.0]
.restore_context(
prim_instances,
pic_context_for_children,
@ -1860,8 +1826,9 @@ impl PrimitiveStore {
frame_state,
);
if new_local_rect != prim.metadata.local_rect {
prim.metadata.local_rect = new_local_rect;
let prim = &mut self.primitives[prim_instance.prim_index.0];
if new_local_rect != prim.local_rect {
prim.local_rect = new_local_rect;
frame_state.gpu_cache.invalidate(&mut prim_instance.gpu_location);
pic_state.local_rect_changed = true;
}
@ -1882,8 +1849,8 @@ impl PrimitiveStore {
if is_passthrough {
prim_instance.clipped_world_rect = Some(pic_state.map_pic_to_world.bounds);
} else {
if prim.metadata.local_rect.size.width <= 0.0 ||
prim.metadata.local_rect.size.height <= 0.0 {
if prim.local_rect.size.width <= 0.0 ||
prim.local_rect.size.height <= 0.0 {
if cfg!(debug_assertions) && is_chased {
println!("\tculled for zero local rectangle");
}
@ -1895,16 +1862,15 @@ impl PrimitiveStore {
// is not visible, any effects from the blur radius will be correctly
// taken into account.
let local_rect = prim
.metadata
.local_rect
.inflate(pic_context.inflation_factor, pic_context.inflation_factor)
.intersection(&prim.metadata.local_clip_rect);
.intersection(&prim.local_clip_rect);
let local_rect = match local_rect {
Some(local_rect) => local_rect,
None => {
if cfg!(debug_assertions) && is_chased {
println!("\tculled for being out of the local clip rectangle: {:?}",
prim.metadata.local_clip_rect);
prim.local_clip_rect);
}
return false;
}
@ -1915,7 +1881,7 @@ impl PrimitiveStore {
.build_clip_chain_instance(
prim_instance.clip_chain_id,
local_rect,
prim.metadata.local_clip_rect,
prim.local_clip_rect,
prim_context.spatial_node_index,
&pic_state.map_local_to_pic,
&pic_state.map_pic_to_world,
@ -1948,11 +1914,11 @@ impl PrimitiveStore {
prim_instance.combined_local_clip_rect = if pic_context.apply_local_clip_rect {
clip_chain.local_clip_rect
} else {
prim.metadata.local_clip_rect
prim.local_clip_rect
};
let pic_rect = match pic_state.map_local_to_pic
.map(&prim.metadata.local_rect) {
.map(&prim.local_rect) {
Some(pic_rect) => pic_rect,
None => return false,
};
@ -2001,6 +1967,7 @@ impl PrimitiveStore {
prim_context,
pic_context,
pic_state,
&mut self.pictures,
frame_context,
frame_state,
display_list,
@ -2118,7 +2085,7 @@ fn build_gradient_stops_request(
fn decompose_repeated_primitive(
visible_tiles: &mut Vec<VisibleGradientTile>,
instance: &mut PrimitiveInstance,
metadata: &mut PrimitiveMetadata,
prim_local_rect: &LayoutRect,
stretch_size: &LayoutSize,
tile_spacing: &LayoutSize,
prim_context: &PrimitiveContext,
@ -2132,7 +2099,7 @@ fn decompose_repeated_primitive(
// rect and we want to clip these extra parts out.
let tight_clip_rect = instance
.combined_local_clip_rect
.intersection(&metadata.local_rect).unwrap();
.intersection(prim_local_rect).unwrap();
let clipped_world_rect = &instance
.clipped_world_rect
@ -2146,7 +2113,7 @@ fn decompose_repeated_primitive(
let stride = *stretch_size + *tile_spacing;
for_each_repetition(
&metadata.local_rect,
prim_local_rect,
&visible_rect,
&stride,
&mut |origin, _| {
@ -2220,165 +2187,168 @@ impl<'a> GpuDataRequest<'a> {
}
}
fn write_brush_segment_description(
brush: &mut BrushPrimitive,
metadata: &PrimitiveMetadata,
clip_chain: &ClipChainInstance,
frame_state: &mut FrameBuildingState,
) {
match brush.segment_desc {
Some(..) => {
// If we already have a segment descriptor, skip segment build.
return;
}
None => {
// If no segment descriptor built yet, see if it is a brush
// type that wants to be segmented.
if !brush.kind.supports_segments(frame_state.resource_cache) {
impl BrushPrimitive {
fn write_brush_segment_description(
&mut self,
prim_local_rect: LayoutRect,
prim_local_clip_rect: LayoutRect,
clip_chain: &ClipChainInstance,
frame_state: &mut FrameBuildingState,
) {
match self.segment_desc {
Some(..) => {
// If we already have a segment descriptor, skip segment build.
return;
}
}
}
// If the brush is small, we generally want to skip building segments
// and just draw it as a single primitive with clip mask. However,
// if the clips are purely rectangles that have no per-fragment
// clip masks, we will segment anyway. This allows us to completely
// skip allocating a clip mask in these cases.
let is_large = metadata.local_rect.size.area() > MIN_BRUSH_SPLIT_AREA;
// TODO(gw): We should probably detect and store this on each
// ClipSources instance, to avoid having to iterate
// the clip sources here.
let mut rect_clips_only = true;
let segment_builder = &mut frame_state.segment_builder;
segment_builder.initialize(
metadata.local_rect,
None,
metadata.local_clip_rect
);
// Segment the primitive on all the local-space clip sources that we can.
let mut local_clip_count = 0;
for i in 0 .. clip_chain.clips_range.count {
let clip_instance = frame_state
.clip_store
.get_instance_from_range(&clip_chain.clips_range, i);
let clip_node = &frame_state.resources.clip_data_store[clip_instance.handle];
// If this clip item is positioned by another positioning node, its relative position
// could change during scrolling. This means that we would need to resegment. Instead
// of doing that, only segment with clips that have the same positioning node.
// TODO(mrobinson, #2858): It may make sense to include these nodes, resegmenting only
// when necessary while scrolling.
if !clip_instance.flags.contains(ClipNodeFlags::SAME_SPATIAL_NODE) {
continue;
}
local_clip_count += 1;
let (local_clip_rect, radius, mode) = match clip_node.item {
ClipItem::RoundedRectangle(rect, radii, clip_mode) => {
rect_clips_only = false;
(rect, Some(radii), clip_mode)
}
ClipItem::Rectangle(rect, mode) => {
(rect, None, mode)
}
ClipItem::BoxShadow(ref info) => {
rect_clips_only = false;
// For inset box shadows, we can clip out any
// pixels that are inside the shadow region
// and are beyond the inner rect, as they can't
// be affected by the blur radius.
let inner_clip_mode = match info.clip_mode {
BoxShadowClipMode::Outset => None,
BoxShadowClipMode::Inset => Some(ClipMode::ClipOut),
};
// Push a region into the segment builder where the
// box-shadow can have an effect on the result. This
// ensures clip-mask tasks get allocated for these
// pixel regions, even if no other clips affect them.
segment_builder.push_mask_region(
info.prim_shadow_rect,
info.prim_shadow_rect.inflate(
-0.5 * info.shadow_rect_alloc_size.width,
-0.5 * info.shadow_rect_alloc_size.height,
),
inner_clip_mode,
);
continue;
}
ClipItem::Image(..) => {
rect_clips_only = false;
continue;
}
};
segment_builder.push_clip_rect(local_clip_rect, radius, mode);
}
if is_large || rect_clips_only {
// If there were no local clips, then we will subdivide the primitive into
// a uniform grid (up to 8x8 segments). This will typically result in
// a significant number of those segments either being completely clipped,
// or determined to not need a clip mask for that segment.
if local_clip_count == 0 && clip_chain.clips_range.count > 0 {
let x_clip_count = cmp::min(8, (metadata.local_rect.size.width / 128.0).ceil() as i32);
let y_clip_count = cmp::min(8, (metadata.local_rect.size.height / 128.0).ceil() as i32);
for y in 0 .. y_clip_count {
let y0 = metadata.local_rect.size.height * y as f32 / y_clip_count as f32;
let y1 = metadata.local_rect.size.height * (y+1) as f32 / y_clip_count as f32;
for x in 0 .. x_clip_count {
let x0 = metadata.local_rect.size.width * x as f32 / x_clip_count as f32;
let x1 = metadata.local_rect.size.width * (x+1) as f32 / x_clip_count as f32;
let rect = LayoutRect::new(
LayoutPoint::new(
x0 + metadata.local_rect.origin.x,
y0 + metadata.local_rect.origin.y,
),
LayoutSize::new(
x1 - x0,
y1 - y0,
),
);
segment_builder.push_mask_region(rect, LayoutRect::zero(), None);
None => {
// If no segment descriptor built yet, see if it is a brush
// type that wants to be segmented.
if !self.kind.supports_segments(frame_state.resource_cache) {
return;
}
}
}
match brush.segment_desc {
Some(..) => panic!("bug: should not already have descriptor"),
None => {
// TODO(gw): We can probably make the allocation
// patterns of this and the segment
// builder significantly better, by
// retaining it across primitives.
let mut segments = BrushSegmentVec::new();
// If the brush is small, we generally want to skip building segments
// and just draw it as a single primitive with clip mask. However,
// if the clips are purely rectangles that have no per-fragment
// clip masks, we will segment anyway. This allows us to completely
// skip allocating a clip mask in these cases.
let is_large = prim_local_rect.size.area() > MIN_BRUSH_SPLIT_AREA;
segment_builder.build(|segment| {
segments.push(
BrushSegment::new(
segment.rect,
segment.has_mask,
segment.edge_flags,
[0.0; 4],
BrushFlags::empty(),
// TODO(gw): We should probably detect and store this on each
// ClipSources instance, to avoid having to iterate
// the clip sources here.
let mut rect_clips_only = true;
let segment_builder = &mut frame_state.segment_builder;
segment_builder.initialize(
prim_local_rect,
None,
prim_local_clip_rect
);
// Segment the primitive on all the local-space clip sources that we can.
let mut local_clip_count = 0;
for i in 0 .. clip_chain.clips_range.count {
let clip_instance = frame_state
.clip_store
.get_instance_from_range(&clip_chain.clips_range, i);
let clip_node = &frame_state.resources.clip_data_store[clip_instance.handle];
// If this clip item is positioned by another positioning node, its relative position
// could change during scrolling. This means that we would need to resegment. Instead
// of doing that, only segment with clips that have the same positioning node.
// TODO(mrobinson, #2858): It may make sense to include these nodes, resegmenting only
// when necessary while scrolling.
if !clip_instance.flags.contains(ClipNodeFlags::SAME_SPATIAL_NODE) {
continue;
}
local_clip_count += 1;
let (local_clip_rect, radius, mode) = match clip_node.item {
ClipItem::RoundedRectangle(rect, radii, clip_mode) => {
rect_clips_only = false;
(rect, Some(radii), clip_mode)
}
ClipItem::Rectangle(rect, mode) => {
(rect, None, mode)
}
ClipItem::BoxShadow(ref info) => {
rect_clips_only = false;
// For inset box shadows, we can clip out any
// pixels that are inside the shadow region
// and are beyond the inner rect, as they can't
// be affected by the blur radius.
let inner_clip_mode = match info.clip_mode {
BoxShadowClipMode::Outset => None,
BoxShadowClipMode::Inset => Some(ClipMode::ClipOut),
};
// Push a region into the segment builder where the
// box-shadow can have an effect on the result. This
// ensures clip-mask tasks get allocated for these
// pixel regions, even if no other clips affect them.
segment_builder.push_mask_region(
info.prim_shadow_rect,
info.prim_shadow_rect.inflate(
-0.5 * info.shadow_rect_alloc_size.width,
-0.5 * info.shadow_rect_alloc_size.height,
),
inner_clip_mode,
);
});
brush.segment_desc = Some(BrushSegmentDescriptor {
segments,
});
continue;
}
ClipItem::Image(..) => {
rect_clips_only = false;
continue;
}
};
segment_builder.push_clip_rect(local_clip_rect, radius, mode);
}
if is_large || rect_clips_only {
// If there were no local clips, then we will subdivide the primitive into
// a uniform grid (up to 8x8 segments). This will typically result in
// a significant number of those segments either being completely clipped,
// or determined to not need a clip mask for that segment.
if local_clip_count == 0 && clip_chain.clips_range.count > 0 {
let x_clip_count = cmp::min(8, (prim_local_rect.size.width / 128.0).ceil() as i32);
let y_clip_count = cmp::min(8, (prim_local_rect.size.height / 128.0).ceil() as i32);
for y in 0 .. y_clip_count {
let y0 = prim_local_rect.size.height * y as f32 / y_clip_count as f32;
let y1 = prim_local_rect.size.height * (y+1) as f32 / y_clip_count as f32;
for x in 0 .. x_clip_count {
let x0 = prim_local_rect.size.width * x as f32 / x_clip_count as f32;
let x1 = prim_local_rect.size.width * (x+1) as f32 / x_clip_count as f32;
let rect = LayoutRect::new(
LayoutPoint::new(
x0 + prim_local_rect.origin.x,
y0 + prim_local_rect.origin.y,
),
LayoutSize::new(
x1 - x0,
y1 - y0,
),
);
segment_builder.push_mask_region(rect, LayoutRect::zero(), None);
}
}
}
match self.segment_desc {
Some(..) => panic!("bug: should not already have descriptor"),
None => {
// TODO(gw): We can probably make the allocation
// patterns of this and the segment
// builder significantly better, by
// retaining it across primitives.
let mut segments = BrushSegmentVec::new();
segment_builder.build(|segment| {
segments.push(
BrushSegment::new(
segment.rect,
segment.has_mask,
segment.edge_flags,
[0.0; 4],
BrushFlags::empty(),
),
);
});
self.segment_desc = Some(BrushSegmentDescriptor {
segments,
});
}
}
}
}
@ -2402,9 +2372,9 @@ impl Primitive {
PrimitiveDetails::TextRun(..) => return false,
};
write_brush_segment_description(
brush,
&self.metadata,
brush.write_brush_segment_description(
self.local_rect,
self.local_clip_rect,
prim_clip_chain,
frame_state,
);
@ -2437,7 +2407,7 @@ impl Primitive {
.build_clip_chain_instance(
prim_instance.clip_chain_id,
segment.local_rect,
self.metadata.local_clip_rect,
self.local_clip_rect,
prim_context.spatial_node_index,
&pic_state.map_local_to_pic,
&pic_state.map_pic_to_world,
@ -2467,10 +2437,7 @@ impl Primitive {
// Returns true if the primitive *might* need a clip mask. If
// false, there is no need to even check for clip masks for
// this primitive.
fn reset_clip_task(
&mut self,
prim_instance: &mut PrimitiveInstance,
) -> bool {
fn reset_clip_task(&mut self, prim_instance: &mut PrimitiveInstance) {
prim_instance.clip_task_id = None;
match self.details {
PrimitiveDetails::Brush(ref mut brush) => {
@ -2479,11 +2446,8 @@ impl Primitive {
segment.clip_task_id = BrushSegmentTaskId::Opaque;
}
}
brush.may_need_clip_mask()
}
PrimitiveDetails::TextRun(..) => {
true
}
PrimitiveDetails::TextRun(..) => {}
}
}
@ -2493,13 +2457,13 @@ impl Primitive {
prim_context: &PrimitiveContext,
pic_context: &PictureContext,
pic_state: &mut PictureState,
pictures: &mut [PicturePrimitive],
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
display_list: &BuiltDisplayList,
is_chased: bool,
) {
let mut is_tiled = false;
let metadata = &mut self.metadata;
#[cfg(debug_assertions)]
{
prim_instance.prepared_frame_id = frame_state.render_tasks.frame_id();
@ -2660,7 +2624,7 @@ impl Primitive {
// rect and we want to clip these extra parts out.
let tight_clip_rect = prim_instance
.combined_local_clip_rect
.intersection(&metadata.local_rect).unwrap();
.intersection(&self.local_rect).unwrap();
let visible_rect = compute_conservative_visible_rect(
prim_context,
@ -2675,7 +2639,7 @@ impl Primitive {
visible_tiles.clear();
for_each_repetition(
&metadata.local_rect,
&self.local_rect,
&visible_rect,
&stride,
&mut |origin, edge_flags| {
@ -2738,7 +2702,7 @@ impl Primitive {
// Work out the device pixel size to be used to cache this line decoration.
let size = get_line_decoration_sizes(
&metadata.local_rect.size,
&self.local_rect.size,
orientation,
style,
wavy_line_thickness,
@ -2756,19 +2720,19 @@ impl Primitive {
let clip_size = match orientation {
LineOrientation::Horizontal => {
LayoutSize::new(
inline_size * (metadata.local_rect.size.width / inline_size).floor(),
metadata.local_rect.size.height,
inline_size * (self.local_rect.size.width / inline_size).floor(),
self.local_rect.size.height,
)
}
LineOrientation::Vertical => {
LayoutSize::new(
metadata.local_rect.size.width,
inline_size * (metadata.local_rect.size.height / inline_size).floor(),
self.local_rect.size.width,
inline_size * (self.local_rect.size.height / inline_size).floor(),
)
}
};
let clip_rect = LayoutRect::new(
metadata.local_rect.origin,
self.local_rect.origin,
clip_size,
);
prim_instance.combined_local_clip_rect = clip_rect
@ -2918,7 +2882,7 @@ impl Primitive {
decompose_repeated_primitive(
visible_tiles,
prim_instance,
metadata,
&self.local_rect,
&stretch_size,
&tile_spacing,
prim_context,
@ -2960,8 +2924,8 @@ impl Primitive {
// then we just assume the gradient is translucent for now.
// (In the future we could consider segmenting in some cases).
let stride = stretch_size + tile_spacing;
prim_instance.opacity = if stride.width >= metadata.local_rect.size.width &&
stride.height >= metadata.local_rect.size.height {
prim_instance.opacity = if stride.width >= self.local_rect.size.width &&
stride.height >= self.local_rect.size.height {
stops_opacity
} else {
PrimitiveOpacity::translucent()
@ -2981,7 +2945,7 @@ impl Primitive {
decompose_repeated_primitive(
visible_tiles,
prim_instance,
metadata,
&self.local_rect,
&stretch_size,
&tile_spacing,
prim_context,
@ -3004,10 +2968,12 @@ impl Primitive {
);
}
}
BrushKind::Picture(ref mut pic) => {
BrushKind::Picture { pic_index, .. } => {
let pic = &mut pictures[pic_index.0];
if !pic.prepare_for_render(
pic_index,
prim_instance,
metadata,
&self.local_rect,
pic_state,
frame_context,
frame_state,
@ -3042,7 +3008,7 @@ impl Primitive {
text.write_gpu_blocks(&mut request);
}
PrimitiveDetails::Brush(ref mut brush) => {
brush.write_gpu_blocks(&mut request, metadata.local_rect);
brush.write_gpu_blocks(&mut request, self.local_rect);
match brush.segment_desc {
Some(ref segment_desc) => {
@ -3059,7 +3025,7 @@ impl Primitive {
}
None => {
request.write_segment(
metadata.local_rect,
self.local_rect,
[0.0; 4],
);
}
@ -3086,10 +3052,7 @@ impl Primitive {
println!("\tupdating clip task with pic rect {:?}", clip_chain.pic_clip_rect);
}
// Reset clips from previous frames since we may clip differently each frame.
// If this primitive never needs clip masks, just return straight away.
if !self.reset_clip_task(prim_instance) {
return;
}
self.reset_clip_task(prim_instance);
// First try to render this primitive's mask using optimized brush rendering.
if self.update_clip_task_for_brush(

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

@ -22,7 +22,7 @@ use internal_types::{CacheTextureId, FastHashMap, LayerIndex, SavedTargetIndex};
#[cfg(feature = "pathfinder")]
use pathfinder_partitioner::mesh::Mesh;
use picture::PictureCacheKey;
use prim_store::{PrimitiveIndex, ImageCacheKey, LineDecorationCacheKey};
use prim_store::{PictureIndex, ImageCacheKey, LineDecorationCacheKey};
#[cfg(feature = "debugger")]
use print_tree::{PrintTreePrinter};
use render_backend::FrameId;
@ -222,7 +222,7 @@ pub struct ClipRegionTask {
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct PictureTask {
pub prim_index: PrimitiveIndex,
pub pic_index: PictureIndex,
pub can_merge: bool,
pub content_origin: DeviceIntPoint,
pub uv_rect_handle: GpuCacheHandle,
@ -384,7 +384,7 @@ impl RenderTask {
pub fn new_picture(
location: RenderTaskLocation,
unclipped_size: DeviceSize,
prim_index: PrimitiveIndex,
pic_index: PictureIndex,
content_origin: DeviceIntPoint,
children: Vec<RenderTaskId>,
uv_rect_kind: UvRectKind,
@ -405,7 +405,7 @@ impl RenderTask {
location,
children,
kind: RenderTaskKind::Picture(PictureTask {
prim_index,
pic_index,
content_origin,
can_merge,
uv_rect_handle: GpuCacheHandle::new(),
@ -992,7 +992,7 @@ impl RenderTask {
pub fn print_with<T: PrintTreePrinter>(&self, pt: &mut T, tree: &RenderTaskTree) -> bool {
match self.kind {
RenderTaskKind::Picture(ref task) => {
pt.new_level(format!("Picture of {:?}", task.prim_index));
pt.new_level(format!("Picture of {:?}", task.pic_index));
}
RenderTaskKind::CacheMask(ref task) => {
pt.new_level(format!("CacheMask with {} clips", task.clip_node_range.count));

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

@ -407,7 +407,7 @@ impl RenderTarget for ColorRenderTarget {
match task.kind {
RenderTaskKind::Picture(ref pic_task) => {
let pic = ctx.prim_store.get_pic(pic_task.prim_index);
let pic = &ctx.prim_store.pictures[pic_task.pic_index.0];
let (target_rect, _) = task.get_target_rect();
@ -472,7 +472,7 @@ impl RenderTarget for ColorRenderTarget {
);
}
RenderTaskKind::Picture(ref task_info) => {
let pic = ctx.prim_store.get_pic(task_info.prim_index);
let pic = &ctx.prim_store.pictures[task_info.pic_index.0];
self.alpha_tasks.push(task_id);
// If this pipeline is registered as a frame output

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

@ -1 +1 @@
c72754d72ddd0e9e198bb1edefe13f77d9a38f07
15656cb497303703b4d541d3e14292259e4c5343