Skip to content

Commit

Permalink
Auto merge of #3233 - kvark:prepare-opacity, r=gw3583
Browse files Browse the repository at this point in the history
Prepare opacity consistently

This is a follow-up to #3232
It makes opacity computation more functional, having us to consider it equally important for all primitive types. It's not supposed to change any logic.
try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=6e4ca6f1b473522e93d5fd11e64c563c2bdf50dd

<!-- 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/3233)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Oct 26, 2018
2 parents 20214bf + 8e75df3 commit 2537e5f
Showing 1 changed file with 51 additions and 44 deletions.
95 changes: 51 additions & 44 deletions webrender/src/prim_store.rs
Expand Up @@ -2583,7 +2583,7 @@ impl PrimitiveInstance {
self.prepared_frame_id = frame_state.render_tasks.frame_id();
}

match *prim_details {
self.opacity = match *prim_details {
PrimitiveDetails::TextRun(ref mut text) => {
// The transform only makes sense for screen space rasterization
let transform = prim_context.spatial_node.world_content_transform.to_transform();
Expand All @@ -2595,6 +2595,7 @@ impl PrimitiveInstance {
display_list,
frame_state,
);
PrimitiveOpacity::translucent()
}
PrimitiveDetails::Brush(ref mut brush) => {
match brush.kind {
Expand Down Expand Up @@ -2624,13 +2625,6 @@ impl PrimitiveInstance {
frame_state.gpu_cache.invalidate(&mut self.gpu_location);
}

// Update opacity for this primitive to ensure the correct
// batching parameters are used.
self.opacity.is_opaque =
image_properties.descriptor.is_opaque &&
opacity_binding.current == 1.0 &&
color.a == 1.0;

if *tile_spacing != LayoutSize::zero() && !is_tiled {
*source = ImageSource::Cache {
// Size in device-pixels we need to allocate in render task cache.
Expand All @@ -2652,6 +2646,7 @@ impl PrimitiveInstance {
}

let mut request_source_image = false;
let mut is_opaque = image_properties.descriptor.is_opaque;

// Every frame, for cached items, we need to request the render
// task cache item. The closure will be invoked on the first
Expand All @@ -2670,9 +2665,7 @@ impl PrimitiveInstance {
size.width += padding.horizontal();
size.height += padding.vertical();

if padding != DeviceIntSideOffsets::zero() {
self.opacity.is_opaque = false;
}
is_opaque &= padding == DeviceIntSideOffsets::zero();

let image_cache_key = ImageCacheKey {
request,
Expand Down Expand Up @@ -2811,18 +2804,17 @@ impl PrimitiveInstance {
frame_state.gpu_cache,
);
}

if is_opaque {
PrimitiveOpacity::from_alpha(opacity_binding.current * color.a)
} else {
PrimitiveOpacity::translucent()
}
} else {
PrimitiveOpacity::opaque()
}
}
BrushKind::LineDecoration { color, ref mut handle, style, orientation, wavy_line_thickness } => {
// Update opacity for this primitive to ensure the correct
// batching parameters are used.
self.opacity.is_opaque = match style {
LineStyle::Solid => color.a == 1.0,
LineStyle::Dotted |
LineStyle::Dashed |
LineStyle::Wavy => false,
};

// Work out the device pixel size to be used to cache this line decoration.
let size = get_line_decoration_sizes(
&prim_local_rect.size,
Expand All @@ -2831,7 +2823,7 @@ impl PrimitiveInstance {
wavy_line_thickness,
);

if is_chased {
if cfg!(debug_assertions) && is_chased {
println!("\tline decoration opaque={}, sizes={:?}", self.opacity.is_opaque, size);
}

Expand Down Expand Up @@ -2903,10 +2895,15 @@ impl PrimitiveInstance {
}
));
}

match style {
LineStyle::Solid => PrimitiveOpacity::from_alpha(color.a),
LineStyle::Dotted |
LineStyle::Dashed |
LineStyle::Wavy => PrimitiveOpacity::translucent(),
}
}
BrushKind::YuvImage { format, yuv_key, image_rendering, .. } => {
self.opacity = PrimitiveOpacity::opaque();

let channel_num = format.get_plane_num();
debug_assert!(channel_num <= 3);
for channel in 0 .. channel_num {
Expand All @@ -2919,6 +2916,8 @@ impl PrimitiveInstance {
frame_state.gpu_cache,
);
}

PrimitiveOpacity::opaque()
}
BrushKind::Border { ref mut source, .. } => {
match *source {
Expand All @@ -2928,15 +2927,15 @@ impl PrimitiveInstance {
.get_image_properties(request.key);

if let Some(image_properties) = image_properties {
// Update opacity for this primitive to ensure the correct
// batching parameters are used.
self.opacity.is_opaque =
image_properties.descriptor.is_opaque;

frame_state.resource_cache.request_image(
request,
frame_state.gpu_cache,
);
PrimitiveOpacity {
is_opaque: image_properties.descriptor.is_opaque,
}
} else {
PrimitiveOpacity::opaque()
}
}
BorderSource::Border { ref border, ref widths, ref mut segments, .. } => {
Expand Down Expand Up @@ -2979,6 +2978,9 @@ impl PrimitiveInstance {
}
));
}

// Shouldn't matter, since the segment opacity is used instead
PrimitiveOpacity::translucent()
}
}
}
Expand Down Expand Up @@ -3031,6 +3033,9 @@ impl PrimitiveInstance {
},
);
}

//TODO: can we make it opaque in some cases?
PrimitiveOpacity::translucent()
}
BrushKind::LinearGradient {
stops_range,
Expand All @@ -3045,19 +3050,6 @@ impl PrimitiveInstance {
ref mut visible_tiles,
..
} => {
// If the coverage of the gradient extends to or beyond
// the primitive rect, then the opacity can be determined
// by the colors of the stops. If we have tiling / spacing
// 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;
self.opacity = if stride.width >= prim_local_rect.size.width &&
stride.height >= prim_local_rect.size.height {
stops_opacity
} else {
PrimitiveOpacity::translucent()
};

build_gradient_stops_request(
stops_handle,
stops_range,
Expand Down Expand Up @@ -3094,6 +3086,19 @@ impl PrimitiveInstance {
}
);
}

// If the coverage of the gradient extends to or beyond
// the primitive rect, then the opacity can be determined
// by the colors of the stops. If we have tiling / spacing
// 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;
if stride.width >= prim_local_rect.size.width &&
stride.height >= prim_local_rect.size.height {
stops_opacity
} else {
PrimitiveOpacity::translucent()
}
}
BrushKind::Picture { pic_index, .. } => {
let pic = &mut pictures[pic_index.0];
Expand All @@ -3117,6 +3122,8 @@ impl PrimitiveInstance {
} else {
self.clipped_world_rect = None;
}

PrimitiveOpacity::translucent()
}
BrushKind::Solid { ref color, ref mut opacity_binding, .. } => {
// If the opacity changed, invalidate the GPU cache so that
Expand All @@ -3126,12 +3133,12 @@ impl PrimitiveInstance {
if opacity_binding.update(frame_context.scene_properties) {
frame_state.gpu_cache.invalidate(&mut self.gpu_location);
}
self.opacity = PrimitiveOpacity::from_alpha(opacity_binding.current * color.a);
PrimitiveOpacity::from_alpha(opacity_binding.current * color.a)
}
BrushKind::Clear => {}
BrushKind::Clear => PrimitiveOpacity::opaque(),
}
}
}
};

if is_tiled {
// we already requested each tile's gpu data.
Expand Down

0 comments on commit 2537e5f

Please sign in to comment.