Bug 1510082 - Update webrender to commit e2e52b1145ad959191c0612edd41b0b189cf6b59 (WR PR #3346). r=kats

https://github.com/servo/webrender/pull/3346

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
WR Updater Bot 2018-11-27 02:52:50 +00:00
Родитель 1669ae2beb
Коммит 0d52f7e529
10 изменённых файлов: 364 добавлений и 155 удалений

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

@ -1 +1 @@
f450af9277e2474e2a2a2c1358689ca9486e2a09
e2e52b1145ad959191c0612edd41b0b189cf6b59

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

@ -17,7 +17,7 @@ use internal_types::{FastHashMap, SavedTargetIndex, TextureSource};
use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureSurface};
use prim_store::{BrushKind, BrushPrimitive, DeferredResolve, PrimitiveTemplateKind};
use prim_store::{EdgeAaSegmentMask, ImageSource, PrimitiveInstanceKind, PrimitiveStore};
use prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity};
use prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity, SegmentInstanceIndex};
use prim_store::{BrushSegment, ClipMaskKind, ClipTaskIndex, PrimitiveDetails};
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskTree};
use renderer::{BlendMode, ImageBufferKind, ShaderColorMode};
@ -905,6 +905,7 @@ impl AlphaBatchBuilder {
PrimitiveInstanceKind::LegacyPrimitive { .. } |
PrimitiveInstanceKind::NormalBorder { .. } |
PrimitiveInstanceKind::ImageBorder { .. } |
PrimitiveInstanceKind::Rectangle { .. } |
PrimitiveInstanceKind::Clear => {
unreachable!();
}
@ -1617,6 +1618,71 @@ impl AlphaBatchBuilder {
ctx,
);
}
(
PrimitiveInstanceKind::Rectangle { segment_instance_index, opacity_binding_index, .. },
PrimitiveTemplateKind::Rectangle { .. }
) => {
let specified_blend_mode = BlendMode::PremultipliedAlpha;
let opacity_binding = ctx.prim_store.get_opacity_binding(*opacity_binding_index);
let opacity = PrimitiveOpacity::from_alpha(opacity_binding);
let opacity = opacity.combine(prim_data.opacity);
let non_segmented_blend_mode = if !opacity.is_opaque ||
prim_instance.clip_task_index != ClipTaskIndex::INVALID ||
transform_kind == TransformedRectKind::Complex
{
specified_blend_mode
} else {
BlendMode::None
};
let batch_params = BrushBatchParameters::shared(
BrushBatchKind::Solid,
BatchTextures::no_texture(),
[get_shader_opacity(opacity_binding), 0, 0],
0,
);
let (prim_cache_address, segments) = if *segment_instance_index == SegmentInstanceIndex::UNUSED {
(gpu_cache.get_address(&prim_data.gpu_cache_handle), None)
} else {
let segment_instance = &ctx.scratch.segment_instances[*segment_instance_index];
let segments = Some(&ctx.scratch.segments[segment_instance.segments_range]);
(gpu_cache.get_address(&segment_instance.gpu_cache_handle), segments)
};
let prim_header = PrimitiveHeader {
local_rect: prim_data.prim_rect,
local_clip_rect: prim_instance.combined_local_clip_rect,
task_address,
specific_prim_address: prim_cache_address,
clip_task_address,
transform_id,
};
let prim_header_index = prim_headers.push(
&prim_header,
z_id,
batch_params.prim_user_data,
);
self.add_segmented_prim_to_batch(
segments,
opacity,
&batch_params,
specified_blend_mode,
non_segmented_blend_mode,
prim_header_index,
clip_task_address,
bounding_rect,
transform_kind,
render_tasks,
z_id,
prim_instance.clip_task_index,
ctx,
);
}
_ => {
unreachable!();
}
@ -1794,7 +1860,7 @@ impl AlphaBatchBuilder {
textures: segment_data.textures,
};
let instance = PrimitiveInstanceData::from(BrushInstance {
segment_index: 0,
segment_index: INVALID_SEGMENT_INDEX,
edge_flags: EdgeAaSegmentMask::all(),
clip_task_address,
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
@ -1999,15 +2065,6 @@ impl BrushPrimitive {
))
}
}
BrushKind::Solid { opacity_binding_index, .. } => {
let opacity_binding = prim_store.get_opacity_binding(opacity_binding_index);
Some(BrushBatchParameters::shared(
BrushBatchKind::Solid,
BatchTextures::no_texture(),
[get_shader_opacity(opacity_binding), 0, 0],
0,
))
}
BrushKind::RadialGradient { ref stops_handle, .. } => {
Some(BrushBatchParameters::shared(
BrushBatchKind::RadialGradient,
@ -2106,7 +2163,6 @@ impl PrimitiveInstance {
AlphaType::Alpha => BlendMode::Alpha,
}
}
BrushKind::Solid { .. } |
BrushKind::YuvImage { .. } |
BrushKind::RadialGradient { .. } |
BrushKind::LinearGradient { .. } => {

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

@ -8,7 +8,7 @@ use clip::ClipItemKey;
use display_list_flattener::DisplayListFlattener;
use gpu_cache::GpuCacheHandle;
use gpu_types::BoxShadowStretchMode;
use prim_store::{BrushKind, BrushPrimitive, PrimitiveContainer};
use prim_store::PrimitiveContainer;
use prim_store::ScrollNodeAndClipChain;
use render_task::RenderTaskCacheEntryHandle;
use util::RectHelpers;
@ -149,7 +149,9 @@ impl<'a> DisplayListFlattener<'a> {
clip_and_scroll,
&LayoutPrimitiveInfo::with_clip_rect(final_prim_rect, prim_info.clip_rect),
clips,
PrimitiveContainer::Brush(BrushPrimitive::new(BrushKind::new_solid(*color), None)),
PrimitiveContainer::Rectangle {
color: *color,
},
);
} else {
// Normal path for box-shadows with a valid blur radius.
@ -170,7 +172,9 @@ impl<'a> DisplayListFlattener<'a> {
// Draw the box-shadow as a solid rect, using a box-shadow
// clip mask item.
let prim = BrushPrimitive::new(BrushKind::new_solid(*color), None);
let prim = PrimitiveContainer::Rectangle {
color: *color,
};
// Create the box-shadow clip item.
let shadow_clip_source = ClipItemKey::box_shadow(
@ -221,7 +225,7 @@ impl<'a> DisplayListFlattener<'a> {
clip_and_scroll,
&prim_info,
extra_clips,
PrimitiveContainer::Brush(prim),
prim,
);
}
}

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

@ -840,7 +840,9 @@ impl<'a> DisplayListFlattener<'a> {
// style PrimitiveDetails structure from the
// source primitive container.
let mut info = info.clone();
let (prim_key_kind, prim_details) = container.build(&mut info);
let (prim_key_kind, prim_details) = container.build(
&mut info,
);
let prim_key = PrimitiveKey::new(
info.is_backface_visible,
@ -1679,16 +1681,13 @@ impl<'a> DisplayListFlattener<'a> {
return;
}
let prim = BrushPrimitive::new(
BrushKind::new_solid(color),
None,
);
self.add_primitive(
clip_and_scroll,
info,
Vec::new(),
PrimitiveContainer::Brush(prim),
PrimitiveContainer::Rectangle {
color,
},
);
}

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

@ -85,7 +85,6 @@ pub struct FrameBuildingState<'a> {
pub transforms: &'a mut TransformPalette,
pub segment_builder: SegmentBuilder,
pub surfaces: &'a mut Vec<SurfaceInfo>,
pub scratch: &'a mut PrimitiveScratchBuffer,
}
/// Immutable context of a picture when processing children.
@ -255,7 +254,6 @@ impl FrameBuilder {
transforms: transform_palette,
segment_builder: SegmentBuilder::new(),
surfaces: pic_update_state.surfaces,
scratch,
};
let (pic_context, mut pic_state, mut prim_list) = self
@ -279,6 +277,7 @@ impl FrameBuilder {
&frame_context,
&mut frame_state,
resources,
scratch,
);
let pic = &mut self.prim_store.pictures[self.root_pic_index.0];

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

@ -414,14 +414,6 @@ impl TileCache {
// TODO(gw): In future, we might be able to completely remove
// opacity collapsing support. It's of limited use
// once we have full picture caching.
BrushKind::Solid { opacity_binding_index, .. } => {
let opacity_binding = &opacity_binding_store[opacity_binding_index];
for binding in &opacity_binding.bindings {
if let PropertyBinding::Binding(key, default) = binding {
opacity_bindings.push((key.id, *default));
}
}
}
BrushKind::Image { opacity_binding_index, ref request, .. } => {
let opacity_binding = &opacity_binding_store[opacity_binding_index];
for binding in &opacity_binding.bindings {
@ -442,6 +434,14 @@ impl TileCache {
}
}
}
PrimitiveInstanceKind::Rectangle { opacity_binding_index, .. } => {
let opacity_binding = &opacity_binding_store[opacity_binding_index];
for binding in &opacity_binding.bindings {
if let PropertyBinding::Binding(key, default) = binding {
opacity_bindings.push((key.id, *default));
}
}
}
PrimitiveInstanceKind::TextRun { .. } |
PrimitiveInstanceKind::LineDecoration { .. } |
PrimitiveInstanceKind::Clear |

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

@ -12,7 +12,7 @@ use api::{PicturePixel, RasterPixel, ColorDepth, LineStyle, LineOrientation, Lay
use app_units::Au;
use border::{get_max_scale_for_border, build_border_instances, create_border_segments};
use border::{create_nine_patch_segments, BorderSegmentCacheKey, NormalBorderAu};
use clip::ClipStore;
use clip::{ClipStore};
use clip_scroll_tree::{ClipScrollTree, SpatialNodeIndex};
use clip::{ClipDataStore, ClipNodeFlags, ClipChainId, ClipChainInstance, ClipItem, ClipNodeCollector};
use euclid::{SideOffsets2D, TypedTransform3D, TypedRect, TypedScale};
@ -33,6 +33,7 @@ use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskCacheEntryHand
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
use resource_cache::{ImageProperties, ImageRequest, ResourceCache};
use scene::SceneProperties;
use segment::SegmentBuilder;
use std::{cmp, fmt, mem, ops, u32, usize};
#[cfg(debug_assertions)]
use std::sync::atomic::{AtomicUsize, Ordering};
@ -100,6 +101,12 @@ impl PrimitiveOpacity {
is_opaque: alpha >= 1.0,
}
}
pub fn combine(&self, other: PrimitiveOpacity) -> PrimitiveOpacity {
PrimitiveOpacity{
is_opaque: self.is_opaque && other.is_opaque
}
}
}
#[derive(Debug, Copy, Clone)]
@ -377,6 +384,9 @@ pub enum PrimitiveKeyKind {
repeat_vertical: RepeatMode,
outset: SideOffsets2D<Au>,
},
Rectangle {
color: ColorU,
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
@ -439,6 +449,12 @@ impl PrimitiveKey {
PrimitiveInstanceKind::ImageBorder {
}
}
PrimitiveKeyKind::Rectangle { .. } => {
PrimitiveInstanceKind::Rectangle {
opacity_binding_index: OpacityBindingIndex::INVALID,
segment_instance_index: SegmentInstanceIndex::INVALID,
}
}
PrimitiveKeyKind::Unused => {
// Should never be hit as this method should not be
// called for old style primitives.
@ -478,6 +494,9 @@ pub enum PrimitiveTemplateKind {
request: ImageRequest,
brush_segments: Vec<BrushSegment>,
},
Rectangle {
color: ColorF,
},
Clear,
Unused,
}
@ -486,7 +505,10 @@ pub enum PrimitiveTemplateKind {
/// is invoked when a primitive key is created and the interner
/// doesn't currently contain a primitive with this key.
impl PrimitiveKeyKind {
fn into_template(self, rect: &LayoutRect) -> PrimitiveTemplateKind {
fn into_template(
self,
rect: &LayoutRect,
) -> PrimitiveTemplateKind {
match self {
PrimitiveKeyKind::Unused => PrimitiveTemplateKind::Unused,
PrimitiveKeyKind::TextRun { glyphs, font, offset, .. } => {
@ -562,6 +584,11 @@ impl PrimitiveKeyKind {
brush_segments,
}
}
PrimitiveKeyKind::Rectangle { color, .. } => {
PrimitiveTemplateKind::Rectangle {
color: color.into(),
}
}
PrimitiveKeyKind::LineDecoration { cache_key, color } => {
PrimitiveTemplateKind::LineDecoration {
cache_key,
@ -627,6 +654,13 @@ impl PrimitiveTemplate {
PrimitiveOpacity::translucent()
}
PrimitiveTemplateKind::Rectangle { ref color, .. } => {
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.gpu_cache_handle) {
request.push(color.premultiplied());
}
PrimitiveOpacity::from_alpha(color.a)
}
PrimitiveTemplateKind::NormalBorder { ref template, .. } => {
if let Some(mut request) = frame_state.gpu_cache.request(&mut self.gpu_cache_handle) {
// Border primitives currently used for
@ -856,10 +890,6 @@ pub struct BorderSegmentInfo {
}
pub enum BrushKind {
Solid {
color: ColorF,
opacity_binding_index: OpacityBindingIndex,
},
Image {
request: ImageRequest,
alpha_type: AlphaType,
@ -915,21 +945,12 @@ impl BrushKind {
.is_none()
}
BrushKind::Solid { .. } |
BrushKind::YuvImage { .. } |
BrushKind::RadialGradient { .. } |
BrushKind::LinearGradient { .. } => true,
}
}
// Construct a brush that is a solid color rectangle.
pub fn new_solid(color: ColorF) -> BrushKind {
BrushKind::Solid {
color,
opacity_binding_index: OpacityBindingIndex::INVALID,
}
}
// Construct a brush that is an image wisth `stretch_size` dimensions and
// `color`.
pub fn new_image(
@ -1117,10 +1138,6 @@ impl BrushPrimitive {
0.0,
]);
}
// Solid rects also support opacity collapsing.
BrushKind::Solid { ref color, .. } => {
request.push(color.premultiplied());
}
BrushKind::LinearGradient { stretch_size, start_point, end_point, extend_mode, .. } => {
request.push([
start_point.x,
@ -1725,6 +1742,9 @@ pub enum PrimitiveContainer {
repeat_vertical: RepeatMode,
outset: SideOffsets2D<f32>,
},
Rectangle {
color: ColorF,
},
}
impl PrimitiveContainer {
@ -1742,9 +1762,6 @@ impl PrimitiveContainer {
}
PrimitiveContainer::Brush(ref brush) => {
match brush.kind {
BrushKind::Solid { ref color, .. } => {
color.a > 0.0
}
BrushKind::Image { .. } |
BrushKind::YuvImage { .. } |
BrushKind::RadialGradient { .. } |
@ -1758,6 +1775,7 @@ impl PrimitiveContainer {
PrimitiveContainer::Clear => {
true
}
PrimitiveContainer::Rectangle { ref color, .. } |
PrimitiveContainer::LineDecoration { ref color, .. } => {
color.a > 0.0
}
@ -1784,6 +1802,13 @@ impl PrimitiveContainer {
PrimitiveContainer::Clear => {
(PrimitiveKeyKind::Clear, None)
}
PrimitiveContainer::Rectangle { color, .. } => {
let key = PrimitiveKeyKind::Rectangle {
color: color.into(),
};
(key, None)
}
PrimitiveContainer::ImageBorder {
request,
widths,
@ -1920,6 +1945,11 @@ impl PrimitiveContainer {
wavy_line_thickness,
}
}
PrimitiveContainer::Rectangle { .. } => {
PrimitiveContainer::Rectangle {
color: shadow.color,
}
}
PrimitiveContainer::NormalBorder { border, widths, .. } => {
let border = border.with_color(shadow.color);
PrimitiveContainer::NormalBorder {
@ -1929,12 +1959,6 @@ impl PrimitiveContainer {
}
PrimitiveContainer::Brush(ref brush) => {
match brush.kind {
BrushKind::Solid { .. } => {
PrimitiveContainer::Brush(BrushPrimitive::new(
BrushKind::new_solid(shadow.color),
None,
))
}
BrushKind::Image { request, stretch_size, .. } => {
PrimitiveContainer::Brush(BrushPrimitive::new(
BrushKind::new_image(request.clone(),
@ -2008,6 +2032,10 @@ pub enum PrimitiveInstanceKind {
},
ImageBorder {
},
Rectangle {
opacity_binding_index: OpacityBindingIndex,
segment_instance_index: SegmentInstanceIndex,
},
/// Clear out a rect, used for special effects.
Clear,
}
@ -2091,12 +2119,22 @@ impl PrimitiveInstance {
}
}
#[derive(Debug)]
pub struct SegmentedInstance {
pub gpu_cache_handle: GpuCacheHandle,
pub segments_range: SegmentsRange,
}
pub type GlyphKeyStorage = storage::Storage<GlyphKey>;
pub type TextRunIndex = storage::Index<TextRunPrimitive>;
pub type TextRunStorage = storage::Storage<TextRunPrimitive>;
pub type OpacityBindingIndex = storage::Index<OpacityBinding>;
pub type OpacityBindingStorage = storage::Storage<OpacityBinding>;
pub type BorderHandleStorage = storage::Storage<RenderTaskCacheEntryHandle>;
pub type SegmentStorage = storage::Storage<BrushSegment>;
pub type SegmentsRange = storage::Range<BrushSegment>;
pub type SegmentInstanceStorage = storage::Storage<SegmentedInstance>;
pub type SegmentInstanceIndex = storage::Index<SegmentedInstance>;
/// Contains various vecs of data that is used only during frame building,
/// where we want to recycle the memory each new display list, to avoid constantly
@ -2114,6 +2152,14 @@ pub struct PrimitiveScratchBuffer {
/// List of render task handles for border segment instances
/// that have been added this frame.
pub border_cache_handles: BorderHandleStorage,
/// A list of brush segments that have been built for this scene.
pub segments: SegmentStorage,
/// A list of segment ranges and GPU cache handles for prim instances
/// that have opted into segment building. In future, this should be
/// removed in favor of segment building during primitive interning.
pub segment_instances: SegmentInstanceStorage,
}
impl PrimitiveScratchBuffer {
@ -2122,6 +2168,8 @@ impl PrimitiveScratchBuffer {
clip_mask_instances: Vec::new(),
glyph_keys: GlyphKeyStorage::new(0),
border_cache_handles: BorderHandleStorage::new(0),
segments: SegmentStorage::new(0),
segment_instances: SegmentInstanceStorage::new(0),
}
}
@ -2129,6 +2177,8 @@ impl PrimitiveScratchBuffer {
recycle_vec(&mut self.clip_mask_instances);
self.glyph_keys.recycle();
self.border_cache_handles.recycle();
self.segments.recycle();
self.segment_instances.recycle();
}
pub fn begin_frame(&mut self) {
@ -2282,7 +2332,7 @@ impl PrimitiveStore {
fn get_opacity_collapse_prim(
&self,
pic_index: PictureIndex,
) -> Option<PrimitiveIndex> {
) -> Option<PictureIndex> {
let pic = &self.pictures[pic_index.0];
// We can only collapse opacity if there is a single primitive, otherwise
@ -2298,6 +2348,9 @@ impl PrimitiveStore {
// handled by this optimization. In the future, we can easily extend
// this to other primitives, such as text runs and gradients.
match prim_instance.kind {
PrimitiveInstanceKind::Rectangle { .. } => {
return Some(pic_index);
}
PrimitiveInstanceKind::Clear |
PrimitiveInstanceKind::TextRun { .. } |
PrimitiveInstanceKind::NormalBorder { .. } |
@ -2324,9 +2377,8 @@ impl PrimitiveStore {
match brush.kind {
// If we find a single rect or image, we can use that
// as the primitive to collapse the opacity into.
BrushKind::Solid { .. } |
BrushKind::Image { .. } => {
return Some(prim_index)
return Some(pic_index)
}
BrushKind::YuvImage { .. } |
BrushKind::LinearGradient { .. } |
@ -2361,28 +2413,43 @@ impl PrimitiveStore {
// See if this picture contains a single primitive that supports
// opacity collapse.
match self.get_opacity_collapse_prim(pic_index) {
Some(prim_index) => {
let prim = &mut self.primitives[prim_index.0];
match prim.details {
PrimitiveDetails::Brush(ref mut brush) => {
// By this point, we know we should only have found a primitive
// that supports opacity collapse.
match brush.kind {
BrushKind::Solid { ref mut opacity_binding_index, .. } |
BrushKind::Image { ref mut opacity_binding_index, .. } => {
if *opacity_binding_index == OpacityBindingIndex::INVALID {
*opacity_binding_index = self.opacity_bindings.push(OpacityBinding::new());
Some(pic_index) => {
let pic = &mut self.pictures[pic_index.0];
let prim_instance = &mut pic.prim_list.prim_instances[0];
match prim_instance.kind {
PrimitiveInstanceKind::Rectangle { ref mut opacity_binding_index, .. } => {
if *opacity_binding_index == OpacityBindingIndex::INVALID {
*opacity_binding_index = self.opacity_bindings.push(OpacityBinding::new());
}
let opacity_binding = &mut self.opacity_bindings[*opacity_binding_index];
opacity_binding.push(binding);
}
PrimitiveInstanceKind::LegacyPrimitive { prim_index } => {
let prim = &mut self.primitives[prim_index.0];
match prim.details {
PrimitiveDetails::Brush(ref mut brush) => {
// By this point, we know we should only have found a primitive
// that supports opacity collapse.
match brush.kind {
BrushKind::Image { ref mut opacity_binding_index, .. } => {
if *opacity_binding_index == OpacityBindingIndex::INVALID {
*opacity_binding_index = self.opacity_bindings.push(OpacityBinding::new());
}
let opacity_binding = &mut self.opacity_bindings[*opacity_binding_index];
opacity_binding.push(binding);
}
BrushKind::YuvImage { .. } |
BrushKind::LinearGradient { .. } |
BrushKind::RadialGradient { .. } => {
unreachable!("bug: invalid prim type for opacity collapse");
}
}
let opacity_binding = &mut self.opacity_bindings[*opacity_binding_index];
opacity_binding.push(binding);
}
BrushKind::YuvImage { .. } |
BrushKind::LinearGradient { .. } |
BrushKind::RadialGradient { .. } => {
unreachable!("bug: invalid prim type for opacity collapse");
}
}
}
_ => {
unreachable!();
}
}
}
None => {
@ -2413,6 +2480,7 @@ impl PrimitiveStore {
display_list: &BuiltDisplayList,
plane_split_anchor: usize,
resources: &mut FrameResources,
scratch: &mut PrimitiveScratchBuffer,
) -> bool {
// If we have dependencies, we need to prepare them first, in order
// to know the actual rect of this primitive.
@ -2444,6 +2512,7 @@ impl PrimitiveStore {
}
}
PrimitiveInstanceKind::TextRun { .. } |
PrimitiveInstanceKind::Rectangle { .. } |
PrimitiveInstanceKind::LineDecoration { .. } |
PrimitiveInstanceKind::LegacyPrimitive { .. } |
PrimitiveInstanceKind::NormalBorder { .. } |
@ -2466,6 +2535,7 @@ impl PrimitiveStore {
frame_context,
frame_state,
resources,
scratch,
);
if !pic_state_for_children.is_cacheable {
@ -2498,6 +2568,7 @@ impl PrimitiveStore {
PrimitiveInstanceKind::Clear |
PrimitiveInstanceKind::NormalBorder { .. } |
PrimitiveInstanceKind::ImageBorder { .. } |
PrimitiveInstanceKind::Rectangle { .. } |
PrimitiveInstanceKind::LineDecoration { .. } => {
let prim_data = &resources
.prim_data_store[prim_instance.prim_data_handle];
@ -2633,6 +2704,7 @@ impl PrimitiveStore {
&clip_node_collector,
&mut self.primitives,
resources,
scratch,
);
if prim_instance.is_chased() {
@ -2688,6 +2760,7 @@ impl PrimitiveStore {
}
PrimitiveInstanceKind::TextRun { .. } |
PrimitiveInstanceKind::Clear |
PrimitiveInstanceKind::Rectangle { .. } |
PrimitiveInstanceKind::NormalBorder { .. } |
PrimitiveInstanceKind::ImageBorder { .. } |
PrimitiveInstanceKind::LineDecoration { .. } => {
@ -2698,6 +2771,7 @@ impl PrimitiveStore {
frame_context,
frame_state,
resources,
scratch,
);
}
PrimitiveInstanceKind::LegacyPrimitive { prim_index } => {
@ -2728,6 +2802,7 @@ impl PrimitiveStore {
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
resources: &mut FrameResources,
scratch: &mut PrimitiveScratchBuffer,
) {
let display_list = &frame_context
.pipelines
@ -2808,6 +2883,7 @@ impl PrimitiveStore {
display_list,
plane_split_anchor,
resources,
scratch,
) {
frame_state.profile_counters.visible_primitives.inc();
}
@ -2825,6 +2901,7 @@ impl PrimitiveStore {
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
resources: &mut FrameResources,
scratch: &mut PrimitiveScratchBuffer,
) {
let prim_data = &mut resources
.prim_data_store[prim_instance.prim_data_handle];
@ -2907,7 +2984,7 @@ impl PrimitiveStore {
frame_state.gpu_cache,
frame_state.render_tasks,
frame_state.special_render_passes,
frame_state.scratch,
scratch,
);
}
(
@ -2969,8 +3046,7 @@ impl PrimitiveStore {
));
}
*cache_handles = frame_state
.scratch
*cache_handles = scratch
.border_cache_handles
.extend(handles);
}
@ -2979,6 +3055,33 @@ impl PrimitiveStore {
PrimitiveTemplateKind::ImageBorder { .. }
) => {
}
(
PrimitiveInstanceKind::Rectangle { segment_instance_index, opacity_binding_index, .. },
PrimitiveTemplateKind::Rectangle { ref color, .. }
) => {
if *segment_instance_index != SegmentInstanceIndex::UNUSED {
let segment_instance = &mut scratch.segment_instances[*segment_instance_index];
if let Some(mut request) = frame_state.gpu_cache.request(&mut segment_instance.gpu_cache_handle) {
let segments = &scratch.segments[segment_instance.segments_range];
request.push(color.premultiplied());
for segment in segments {
request.write_segment(
segment.local_rect,
[0.0; 4],
);
}
}
}
update_opacity_binding(
&mut self.opacity_bindings,
*opacity_binding_index,
frame_context.scene_properties,
);
}
_ => {
unreachable!();
}
@ -3103,29 +3206,14 @@ impl<'a> GpuDataRequest<'a> {
}
}
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,
segment_builder: &mut SegmentBuilder,
clip_store: &ClipStore,
resources: &FrameResources,
) {
match self.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 !self.kind.supports_segments(frame_state.resource_cache) {
return;
}
}
}
) -> bool {
// 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
@ -3138,7 +3226,6 @@ impl BrushPrimitive {
// 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,
@ -3148,8 +3235,7 @@ impl BrushPrimitive {
// 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
let clip_instance = clip_store
.get_instance_from_range(&clip_chain.clips_range, i);
let clip_node = &resources.clip_data_store[clip_instance.handle];
@ -3241,35 +3327,11 @@ impl BrushPrimitive {
}
}
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,
});
}
}
return true
}
false
}
}
impl PrimitiveInstance {
fn build_segments_if_needed(
@ -3280,20 +3342,100 @@ impl PrimitiveInstance {
frame_state: &mut FrameBuildingState,
primitives: &mut [Primitive],
resources: &FrameResources,
scratch: &mut PrimitiveScratchBuffer,
) {
if let PrimitiveInstanceKind::LegacyPrimitive { prim_index } = self.kind {
let prim = &mut primitives[prim_index.0];
match prim.details {
PrimitiveDetails::Brush(ref mut brush) => {
brush.write_brush_segment_description(
match self.kind {
PrimitiveInstanceKind::Rectangle { ref mut segment_instance_index, .. } => {
if *segment_instance_index == SegmentInstanceIndex::INVALID {
let mut segments: SmallVec<[BrushSegment; 8]> = SmallVec::new();
if write_brush_segment_description(
prim_local_rect,
prim_local_clip_rect,
prim_clip_chain,
frame_state,
&mut frame_state.segment_builder,
frame_state.clip_store,
resources,
);
) {
frame_state.segment_builder.build(|segment| {
segments.push(
BrushSegment::new(
segment.rect,
segment.has_mask,
segment.edge_flags,
[0.0; 4],
BrushFlags::empty(),
),
);
});
}
if segments.is_empty() {
*segment_instance_index = SegmentInstanceIndex::UNUSED;
} else {
let segments_range = scratch
.segments
.extend(segments);
let instance = SegmentedInstance {
segments_range,
gpu_cache_handle: GpuCacheHandle::new(),
};
*segment_instance_index = scratch
.segment_instances
.push(instance);
};
}
}
PrimitiveInstanceKind::LegacyPrimitive { prim_index } => {
let prim = &mut primitives[prim_index.0];
match prim.details {
PrimitiveDetails::Brush(ref mut brush) => {
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) {
let mut segments = BrushSegmentVec::new();
if write_brush_segment_description(
prim_local_rect,
prim_local_clip_rect,
prim_clip_chain,
&mut frame_state.segment_builder,
frame_state.clip_store,
resources,
) {
frame_state.segment_builder.build(|segment| {
segments.push(
BrushSegment::new(
segment.rect,
segment.has_mask,
segment.edge_flags,
[0.0; 4],
BrushFlags::empty(),
),
);
});
}
if !segments.is_empty() {
brush.segment_desc = Some(BrushSegmentDescriptor {
segments,
});
}
}
}
}
}
}
}
_ => {}
}
}
@ -3311,6 +3453,7 @@ impl PrimitiveInstance {
clip_node_collector: &Option<ClipNodeCollector>,
primitives: &[Primitive],
resources: &mut FrameResources,
scratch: &mut PrimitiveScratchBuffer,
) -> bool {
let segments = match self.kind {
PrimitiveInstanceKind::Picture { .. } |
@ -3319,6 +3462,17 @@ impl PrimitiveInstance {
PrimitiveInstanceKind::LineDecoration { .. } => {
return false;
}
PrimitiveInstanceKind::Rectangle { segment_instance_index, .. } => {
debug_assert!(segment_instance_index != SegmentInstanceIndex::INVALID);
if segment_instance_index == SegmentInstanceIndex::UNUSED {
return false;
}
let segment_instance = &scratch.segment_instances[segment_instance_index];
&mut scratch.segments[segment_instance.segments_range]
}
PrimitiveInstanceKind::ImageBorder { .. } => {
let prim_data = &resources.prim_data_store[self.prim_data_handle];
@ -3326,7 +3480,7 @@ impl PrimitiveInstance {
// can change this to be a tuple match on (instance, template)
match prim_data.kind {
PrimitiveTemplateKind::ImageBorder { ref brush_segments, .. } => {
brush_segments
brush_segments.as_slice()
}
_ => {
unreachable!();
@ -3373,7 +3527,7 @@ impl PrimitiveInstance {
// Set where in the clip mask instances array the clip mask info
// can be found for this primitive. Each segment will push the
// clip mask information for itself in update_clip_task below.
self.clip_task_index = ClipTaskIndex(frame_state.scratch.clip_mask_instances.len() as _);
self.clip_task_index = ClipTaskIndex(scratch.clip_mask_instances.len() as _);
// If we only built 1 segment, there is no point in re-running
// the clip chain builder. Instead, just use the clip chain
@ -3390,7 +3544,7 @@ impl PrimitiveInstance {
frame_state,
&mut resources.clip_data_store,
);
frame_state.scratch.clip_mask_instances.push(clip_mask_kind);
scratch.clip_mask_instances.push(clip_mask_kind);
} else {
for segment in segments {
// Build a clip chain for the smaller segment rect. This will
@ -3424,7 +3578,7 @@ impl PrimitiveInstance {
frame_state,
&mut resources.clip_data_store,
);
frame_state.scratch.clip_mask_instances.push(clip_mask_kind);
scratch.clip_mask_instances.push(clip_mask_kind);
}
}
@ -3802,14 +3956,6 @@ impl PrimitiveInstance {
PrimitiveOpacity::translucent()
}
}
BrushKind::Solid { ref color, opacity_binding_index, .. } => {
let current_opacity = update_opacity_binding(
opacity_bindings,
opacity_binding_index,
frame_context.scene_properties,
);
PrimitiveOpacity::from_alpha(current_opacity * color.a)
}
};
}
}
@ -3845,6 +3991,7 @@ impl PrimitiveInstance {
clip_node_collector: &Option<ClipNodeCollector>,
primitives: &mut [Primitive],
resources: &mut FrameResources,
scratch: &mut PrimitiveScratchBuffer,
) {
if self.is_chased() {
println!("\tupdating clip task with pic rect {:?}", clip_chain.pic_clip_rect);
@ -3860,6 +4007,7 @@ impl PrimitiveInstance {
frame_state,
primitives,
resources,
scratch,
);
// First try to render this primitive's mask using optimized brush rendering.
@ -3876,6 +4024,7 @@ impl PrimitiveInstance {
clip_node_collector,
primitives,
resources,
scratch,
) {
if self.is_chased() {
println!("\tsegment tasks have been created for clipping");
@ -3908,8 +4057,8 @@ impl PrimitiveInstance {
clip_task_id, device_rect);
}
// Set the global clip mask instance for this primitive.
let clip_task_index = ClipTaskIndex(frame_state.scratch.clip_mask_instances.len() as _);
frame_state.scratch.clip_mask_instances.push(ClipMaskKind::Mask(clip_task_id));
let clip_task_index = ClipTaskIndex(scratch.clip_mask_instances.len() as _);
scratch.clip_mask_instances.push(ClipMaskKind::Mask(clip_task_id));
self.clip_task_index = clip_task_index;
frame_state.surfaces[pic_context.surface_index.0].tasks.push(clip_task_id);
}

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

@ -31,6 +31,7 @@ impl<T> Index<T> {
}
pub const INVALID: Index<T> = Index(u32::MAX, PhantomData);
pub const UNUSED: Index<T> = Index(u32::MAX-1, PhantomData);
}
#[derive(Debug)]

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

@ -243,6 +243,7 @@ impl SurfaceDescriptor {
PrimitiveInstanceKind::LineDecoration { .. } |
PrimitiveInstanceKind::TextRun { .. } |
PrimitiveInstanceKind::NormalBorder { .. } |
PrimitiveInstanceKind::Rectangle { .. } |
PrimitiveInstanceKind::ImageBorder { .. } |
PrimitiveInstanceKind::Clear => {}
}

Двоичные данные
gfx/wr/wrench/reftests/boxshadow/inset-alpha.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.6 KiB

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB