Skip to content

Commit

Permalink
Auto merge of servo#3336 - gw3583:opacity-binding-store, r=nical
Browse files Browse the repository at this point in the history
Switch opacity bindings to array, and optimize size of BrushPrimitive.

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/3336)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo authored Nov 22, 2018
2 parents 3d7a8fa + 4f198c6 commit 29dab25
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 30 deletions.
20 changes: 13 additions & 7 deletions webrender/src/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, Trans
use internal_types::{FastHashMap, SavedTargetIndex, TextureSource};
use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureSurface};
use prim_store::{BrushKind, BrushPrimitive, DeferredResolve};
use prim_store::{EdgeAaSegmentMask, ImageSource, PrimitiveInstanceKind};
use prim_store::{EdgeAaSegmentMask, ImageSource, PrimitiveInstanceKind, PrimitiveStore};
use prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity};
use prim_store::{BrushSegment, BorderSource, ClipMaskKind, ClipTaskIndex, PrimitiveDetails};
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskTree};
Expand Down Expand Up @@ -1261,15 +1261,17 @@ impl AlphaBatchBuilder {
}

match brush.kind {
BrushKind::Image { alpha_type, request, ref opacity_binding, ref visible_tiles, .. } if !visible_tiles.is_empty() => {
BrushKind::Image { alpha_type, request, opacity_binding_index, ref visible_tiles, .. } if !visible_tiles.is_empty() => {
let opacity_binding = ctx.prim_store.get_opacity_binding(opacity_binding_index);

for tile in visible_tiles {
if let Some((batch_kind, textures, user_data, uv_rect_address)) = get_image_tile_params(
ctx.resource_cache,
gpu_cache,
deferred_resolves,
request.with_tile(tile.tile_offset),
alpha_type,
get_shader_opacity(opacity_binding.current),
get_shader_opacity(opacity_binding),
) {
let prim_cache_address = gpu_cache.get_address(&tile.handle);
let prim_header = PrimitiveHeader {
Expand Down Expand Up @@ -1330,6 +1332,7 @@ impl AlphaBatchBuilder {
gpu_cache,
deferred_resolves,
prim_instance,
ctx.prim_store,
) {
let prim_header_index = prim_headers.push(&prim_header, z_id, params.prim_user_data);
if prim_instance.is_chased() {
Expand Down Expand Up @@ -1691,9 +1694,10 @@ impl BrushPrimitive {
gpu_cache: &mut GpuCache,
deferred_resolves: &mut Vec<DeferredResolve>,
prim_instance: &PrimitiveInstance,
prim_store: &PrimitiveStore,
) -> Option<BrushBatchParameters> {
match self.kind {
BrushKind::Image { alpha_type, request, ref source, ref opacity_binding, .. } => {
BrushKind::Image { alpha_type, request, ref source, opacity_binding_index, .. } => {
let cache_item = match *source {
ImageSource::Default => {
resolve_image(
Expand All @@ -1720,14 +1724,15 @@ impl BrushPrimitive {
None
} else {
let textures = BatchTextures::color(cache_item.texture_id);
let opacity_binding = prim_store.get_opacity_binding(opacity_binding_index);

Some(BrushBatchParameters::shared(
BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)),
textures,
[
ShaderColorMode::Image as i32 | ((alpha_type as i32) << 16),
RasterizationSpace::Local as i32,
get_shader_opacity(opacity_binding.current),
get_shader_opacity(opacity_binding),
],
cache_item.uv_rect_handle.as_int(gpu_cache),
))
Expand Down Expand Up @@ -1791,11 +1796,12 @@ impl BrushPrimitive {
}
}
}
BrushKind::Solid { ref opacity_binding, .. } => {
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.current), 0, 0],
[get_shader_opacity(opacity_binding), 0, 0],
0,
))
}
Expand Down
9 changes: 4 additions & 5 deletions webrender/src/border.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use gpu_types::{BorderInstance, BorderSegment, BrushFlags};
use prim_store::{BorderSegmentInfo, BrushKind, BrushPrimitive, BrushSegment, BrushSegmentVec};
use prim_store::{EdgeAaSegmentMask, PrimitiveContainer, ScrollNodeAndClipChain, BrushSegmentDescriptor};
use render_task::{RenderTaskCacheKey, RenderTaskCacheKeyKind};
use smallvec::SmallVec;
use util::{lerp, RectHelpers};

// Using 2048 as the maximum radius in device space before which we
Expand Down Expand Up @@ -606,7 +605,7 @@ fn create_border_segments(
rect: &LayoutRect,
border: &NormalBorder,
widths: &LayoutSideOffsets,
border_segments: &mut SmallVec<[BorderSegmentInfo; 8]>,
border_segments: &mut Vec<BorderSegmentInfo>,
brush_segments: &mut BrushSegmentVec,
) {
let local_size_tl = LayoutSize::new(
Expand Down Expand Up @@ -938,7 +937,7 @@ fn add_corner_segment(
segment: BorderSegment,
edge_flags: EdgeAaSegmentMask,
brush_segments: &mut BrushSegmentVec,
border_segments: &mut SmallVec<[BorderSegmentInfo; 8]>,
border_segments: &mut Vec<BorderSegmentInfo>,
do_aa: bool,
) {
if side0.color.a <= 0.0 && side1.color.a <= 0.0 {
Expand Down Expand Up @@ -996,7 +995,7 @@ fn add_edge_segment(
segment: BorderSegment,
edge_flags: EdgeAaSegmentMask,
brush_segments: &mut BrushSegmentVec,
border_segments: &mut SmallVec<[BorderSegmentInfo; 8]>,
border_segments: &mut Vec<BorderSegmentInfo>,
do_aa: bool,
) {
if side.color.a <= 0.0 {
Expand Down Expand Up @@ -1121,7 +1120,7 @@ pub fn create_normal_border_prim(
widths: LayoutSideOffsets,
) -> BrushPrimitive {
let mut brush_segments = BrushSegmentVec::new();
let mut border_segments = SmallVec::new();
let mut border_segments = Vec::new();

create_border_segments(
local_rect,
Expand Down
4 changes: 2 additions & 2 deletions webrender/src/display_list_flattener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, Primitiv
use prim_store::{BrushKind, BrushPrimitive, PrimitiveInstance, PrimitiveDataInterner, PrimitiveKeyKind};
use prim_store::{ImageSource, PrimitiveOpacity, PrimitiveKey, PrimitiveSceneData, PrimitiveInstanceKind};
use prim_store::{BorderSource, PrimitiveContainer, PrimitiveDataHandle, PrimitiveStore, PrimitiveStoreStats};
use prim_store::{OpacityBinding, ScrollNodeAndClipChain, PictureIndex, register_prim_chase_id};
use prim_store::{ScrollNodeAndClipChain, PictureIndex, register_prim_chase_id, OpacityBindingIndex};
use render_backend::{DocumentView};
use resource_cache::{FontInstanceMap, ImageRequest};
use scene::{Scene, ScenePipeline, StackingContextHelpers};
Expand Down Expand Up @@ -2015,7 +2015,7 @@ impl<'a> DisplayListFlattener<'a> {
source: ImageSource::Default,
sub_rect,
visible_tiles: Vec::new(),
opacity_binding: OpacityBinding::new(),
opacity_binding_index: OpacityBindingIndex::INVALID,
},
None,
);
Expand Down
79 changes: 64 additions & 15 deletions webrender/src/prim_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ pub struct BorderSegmentInfo {
pub enum BorderSource {
Image(ImageRequest),
Border {
segments: SmallVec<[BorderSegmentInfo; 8]>,
segments: Vec<BorderSegmentInfo>,
border: NormalBorder,
widths: LayoutSideOffsets,
},
Expand All @@ -690,7 +690,7 @@ pub enum BorderSource {
pub enum BrushKind {
Solid {
color: ColorF,
opacity_binding: OpacityBinding,
opacity_binding_index: OpacityBindingIndex,
},
Image {
request: ImageRequest,
Expand All @@ -700,7 +700,7 @@ pub enum BrushKind {
color: ColorF,
source: ImageSource,
sub_rect: Option<DeviceIntRect>,
opacity_binding: OpacityBinding,
opacity_binding_index: OpacityBindingIndex,
visible_tiles: Vec<VisibleImageTile>,
},
YuvImage {
Expand Down Expand Up @@ -762,7 +762,7 @@ impl BrushKind {
pub fn new_solid(color: ColorF) -> BrushKind {
BrushKind::Solid {
color,
opacity_binding: OpacityBinding::new(),
opacity_binding_index: OpacityBindingIndex::INVALID,
}
}

Expand All @@ -771,7 +771,7 @@ impl BrushKind {
pub fn new_border(
mut border: NormalBorder,
widths: LayoutSideOffsets,
segments: SmallVec<[BorderSegmentInfo; 8]>,
segments: Vec<BorderSegmentInfo>,
) -> BrushKind {
// FIXME(emilio): Is this the best place to do this?
border.normalize(&widths);
Expand Down Expand Up @@ -800,7 +800,7 @@ impl BrushKind {
color,
source: ImageSource::Default,
sub_rect: None,
opacity_binding: OpacityBinding::new(),
opacity_binding_index: OpacityBindingIndex::INVALID,
visible_tiles: Vec::new(),
}
}
Expand Down Expand Up @@ -1911,6 +1911,8 @@ impl PrimitiveInstance {
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>;

/// 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
Expand Down Expand Up @@ -1955,6 +1957,7 @@ pub struct PrimitiveStoreStats {
primitive_count: usize,
picture_count: usize,
text_run_count: usize,
opacity_binding_count: usize,
}

impl PrimitiveStoreStats {
Expand All @@ -1963,6 +1966,7 @@ impl PrimitiveStoreStats {
primitive_count: 0,
picture_count: 0,
text_run_count: 0,
opacity_binding_count: 0,
}
}
}
Expand All @@ -1971,6 +1975,9 @@ pub struct PrimitiveStore {
pub primitives: Vec<Primitive>,
pub pictures: Vec<PicturePrimitive>,
pub text_runs: TextRunStorage,

/// List of animated opacity bindings for a primitive.
pub opacity_bindings: OpacityBindingStorage,
}

impl PrimitiveStore {
Expand All @@ -1979,6 +1986,7 @@ impl PrimitiveStore {
primitives: Vec::with_capacity(stats.primitive_count),
pictures: Vec::with_capacity(stats.picture_count),
text_runs: TextRunStorage::new(stats.text_run_count),
opacity_bindings: OpacityBindingStorage::new(stats.opacity_binding_count),
}
}

Expand All @@ -1987,6 +1995,7 @@ impl PrimitiveStore {
primitive_count: self.primitives.len(),
picture_count: self.pictures.len(),
text_run_count: self.text_runs.len(),
opacity_binding_count: self.opacity_bindings.len(),
}
}

Expand Down Expand Up @@ -2047,6 +2056,17 @@ impl PrimitiveStore {
PrimitiveIndex(prim_index)
}

pub fn get_opacity_binding(
&self,
opacity_binding_index: OpacityBindingIndex,
) -> f32 {
if opacity_binding_index == OpacityBindingIndex::INVALID {
1.0
} else {
self.opacity_bindings[opacity_binding_index].current
}
}

// Internal method that retrieves the primitive index of a primitive
// that can be the target for collapsing parent opacity filters into.
fn get_opacity_collapse_prim(
Expand Down Expand Up @@ -2092,7 +2112,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 { .. } => {
BrushKind::Solid { .. } |
BrushKind::Image { .. } => {
return Some(prim_index)
}
BrushKind::Border { .. } |
Expand Down Expand Up @@ -2136,8 +2157,12 @@ impl PrimitiveStore {
// 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, .. } |
BrushKind::Image { ref mut opacity_binding, .. } => {
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());
}
let opacity_binding = &mut self.opacity_bindings[*opacity_binding_index];
opacity_binding.push(binding);
}
BrushKind::YuvImage { .. } |
Expand Down Expand Up @@ -2459,6 +2484,7 @@ impl PrimitiveStore {
frame_context,
frame_state,
display_list,
&mut self.opacity_bindings,
);
}
}
Expand Down Expand Up @@ -3070,6 +3096,7 @@ impl PrimitiveInstance {
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
display_list: &BuiltDisplayList,
opacity_bindings: &mut OpacityBindingStorage,
) {
let mut is_tiled = false;

Expand All @@ -3088,7 +3115,7 @@ impl PrimitiveInstance {
color,
ref mut tile_spacing,
ref mut source,
ref mut opacity_binding,
opacity_binding_index,
ref mut visible_tiles,
..
} => {
Expand All @@ -3100,7 +3127,11 @@ impl PrimitiveInstance {
// Set if we need to request the source image from the cache this frame.
if let Some(image_properties) = image_properties {
is_tiled = image_properties.tiling.is_some();
opacity_binding.update(frame_context.scene_properties);
let current_opacity = update_opacity_binding(
opacity_bindings,
opacity_binding_index,
frame_context.scene_properties,
);

if *tile_spacing != LayoutSize::zero() && !is_tiled {
*source = ImageSource::Cache {
Expand Down Expand Up @@ -3284,7 +3315,7 @@ impl PrimitiveInstance {
}

if is_opaque {
PrimitiveOpacity::from_alpha(opacity_binding.current * color.a)
PrimitiveOpacity::from_alpha(current_opacity * color.a)
} else {
PrimitiveOpacity::translucent()
}
Expand Down Expand Up @@ -3493,9 +3524,13 @@ impl PrimitiveInstance {
PrimitiveOpacity::translucent()
}
}
BrushKind::Solid { ref color, ref mut opacity_binding, .. } => {
opacity_binding.update(frame_context.scene_properties);
PrimitiveOpacity::from_alpha(opacity_binding.current * color.a)
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)
}
};
}
Expand Down Expand Up @@ -3668,3 +3703,17 @@ fn get_line_decoration_sizes(
}
}
}

fn update_opacity_binding(
opacity_bindings: &mut OpacityBindingStorage,
opacity_binding_index: OpacityBindingIndex,
scene_properties: &SceneProperties,
) -> f32 {
if opacity_binding_index == OpacityBindingIndex::INVALID {
1.0
} else {
let binding = &mut opacity_bindings[opacity_binding_index];
binding.update(scene_properties);
binding.current
}
}
Loading

0 comments on commit 29dab25

Please sign in to comment.