зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1486405. Update webrender to commit 5fa5c46e167ca834d8fec3bf662bf420418698f4
--HG-- extra : rebase_source : cbd95125423ea2eb4c81dc34012ecd741866bd29
This commit is contained in:
Родитель
42e72ffaa9
Коммит
819c34f560
|
@ -32,7 +32,10 @@ void brush_vs(
|
|||
vec2 uv = snap_device_pos(vi) +
|
||||
src_task.common_data.task_rect.p0 -
|
||||
src_task.content_origin;
|
||||
vUv = vec3(uv / texture_size, src_task.common_data.texture_layer_index);
|
||||
vUv = vec3(
|
||||
uv * gl_Position.w / texture_size, // multiply by W to compensate for perspective interpolation
|
||||
src_task.common_data.texture_layer_index
|
||||
);
|
||||
|
||||
vec2 uv0 = src_task.common_data.task_rect.p0;
|
||||
vec2 uv1 = uv0 + src_task.common_data.task_rect.size;
|
||||
|
@ -124,7 +127,8 @@ vec3 Brightness(vec3 Cs, float amount) {
|
|||
}
|
||||
|
||||
Fragment brush_fs() {
|
||||
vec4 Cs = texture(sColor0, vUv);
|
||||
vec2 base_uv = vUv.xy * gl_FragCoord.w;
|
||||
vec4 Cs = texture(sColor0, vec3(base_uv, vUv.z));
|
||||
|
||||
if (Cs.a == 0.0) {
|
||||
return Fragment(vec4(0.0)); // could also `discard`
|
||||
|
@ -155,7 +159,7 @@ Fragment brush_fs() {
|
|||
|
||||
// Fail-safe to ensure that we don't sample outside the rendered
|
||||
// portion of a blend source.
|
||||
alpha *= point_inside_rect(vUv.xy, vUvClipBounds.xy, vUvClipBounds.zw);
|
||||
alpha *= point_inside_rect(base_uv, vUvClipBounds.xy, vUvClipBounds.zw);
|
||||
|
||||
// Pre-multiply the alpha into the output value.
|
||||
return Fragment(alpha * vec4(color, 1.0));
|
||||
|
|
|
@ -829,6 +829,7 @@ impl AlphaBatchBuilder {
|
|||
);
|
||||
|
||||
let filter_mode = match filter {
|
||||
FilterOp::Identity => 1, // matches `Contrast(1)`
|
||||
FilterOp::Blur(..) => 0,
|
||||
FilterOp::Contrast(..) => 1,
|
||||
FilterOp::Grayscale(..) => 2,
|
||||
|
@ -843,6 +844,7 @@ impl AlphaBatchBuilder {
|
|||
};
|
||||
|
||||
let user_data = match filter {
|
||||
FilterOp::Identity => 0x10000i32, // matches `Contrast(1)`
|
||||
FilterOp::Contrast(amount) |
|
||||
FilterOp::Grayscale(amount) |
|
||||
FilterOp::Invert(amount) |
|
||||
|
|
|
@ -324,6 +324,7 @@ pub struct ClipChainInstance {
|
|||
pub clips_range: ClipNodeRange,
|
||||
pub local_clip_rect: LayoutRect,
|
||||
pub has_non_root_coord_system: bool,
|
||||
pub has_non_local_clips: bool,
|
||||
pub world_clip_rect: WorldRect,
|
||||
}
|
||||
|
||||
|
@ -531,6 +532,7 @@ impl ClipStore {
|
|||
|
||||
let first_clip_node_index = self.clip_node_indices.len() as u32;
|
||||
let mut has_non_root_coord_system = false;
|
||||
let mut has_non_local_clips = false;
|
||||
|
||||
// For each potential clip node
|
||||
for node_info in self.clip_node_info.drain(..) {
|
||||
|
@ -542,9 +544,11 @@ impl ClipStore {
|
|||
node.item.get_clip_result(&local_bounding_rect)
|
||||
}
|
||||
ClipSpaceConversion::Offset(offset) => {
|
||||
has_non_local_clips = true;
|
||||
node.item.get_clip_result(&local_bounding_rect.translate(&-offset))
|
||||
}
|
||||
ClipSpaceConversion::Transform(ref transform) => {
|
||||
has_non_local_clips = true;
|
||||
node.item.get_clip_result_complex(
|
||||
transform,
|
||||
&world_bounding_rect,
|
||||
|
@ -603,6 +607,7 @@ impl ClipStore {
|
|||
Some(ClipChainInstance {
|
||||
clips_range,
|
||||
has_non_root_coord_system,
|
||||
has_non_local_clips,
|
||||
local_clip_rect,
|
||||
world_clip_rect,
|
||||
})
|
||||
|
|
|
@ -2211,7 +2211,8 @@ impl Primitive {
|
|||
|
||||
match segment_clip_chain {
|
||||
Some(segment_clip_chain) => {
|
||||
if segment_clip_chain.clips_range.count == 0 {
|
||||
if segment_clip_chain.clips_range.count == 0 ||
|
||||
(!segment.may_need_clip_mask && !segment_clip_chain.has_non_local_clips) {
|
||||
segment.clip_task_id = BrushSegmentTaskId::Opaque;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -201,6 +201,7 @@ pub trait FilterOpHelpers {
|
|||
impl FilterOpHelpers for FilterOp {
|
||||
fn is_visible(&self) -> bool {
|
||||
match *self {
|
||||
FilterOp::Identity |
|
||||
FilterOp::Blur(..) |
|
||||
FilterOp::Brightness(..) |
|
||||
FilterOp::Contrast(..) |
|
||||
|
@ -219,6 +220,7 @@ impl FilterOpHelpers for FilterOp {
|
|||
|
||||
fn is_noop(&self) -> bool {
|
||||
match *self {
|
||||
FilterOp::Identity => false, // this is intentional
|
||||
FilterOp::Blur(length) => length == 0.0,
|
||||
FilterOp::Brightness(amount) => amount == 1.0,
|
||||
FilterOp::Contrast(amount) => amount == 1.0,
|
||||
|
|
|
@ -543,6 +543,9 @@ pub enum MixBlendMode {
|
|||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
|
||||
pub enum FilterOp {
|
||||
/// Filter that does no transformation of the colors, needed for
|
||||
/// debug purposes only.
|
||||
Identity,
|
||||
Blur(f32),
|
||||
Brightness(f32),
|
||||
Contrast(f32),
|
||||
|
|
|
@ -16,7 +16,7 @@ use time::precise_time_ns;
|
|||
use {AlphaType, BorderDetails, BorderDisplayItem, BorderRadius, BorderWidths, BoxShadowClipMode};
|
||||
use {BoxShadowDisplayItem, ClipAndScrollInfo, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
|
||||
use {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp};
|
||||
use {FontInstanceKey, GlyphInstance, GlyphOptions, GlyphRasterSpace, Gradient};
|
||||
use {FontInstanceKey, GlyphInstance, GlyphOptions, GlyphRasterSpace, Gradient, GradientBuilder};
|
||||
use {GradientDisplayItem, GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask};
|
||||
use {ImageRendering, LayoutPoint, LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform};
|
||||
use {LayoutVector2D, LineDisplayItem, LineOrientation, LineStyle, MixBlendMode, PipelineId};
|
||||
|
@ -947,7 +947,12 @@ impl DisplayListBuilder {
|
|||
index
|
||||
}
|
||||
|
||||
fn push_item(&mut self, item: SpecificDisplayItem, info: &LayoutPrimitiveInfo) {
|
||||
/// Add an item to the display list.
|
||||
///
|
||||
/// NOTE: It is usually preferable to use the specialized methods to push
|
||||
/// display items. Pushing unexpected or invalid items here may
|
||||
/// result in WebRender panicking or behaving in unexpected ways.
|
||||
pub fn push_item(&mut self, item: SpecificDisplayItem, info: &LayoutPrimitiveInfo) {
|
||||
serialize_fast(
|
||||
&mut self.data,
|
||||
&DisplayItem {
|
||||
|
@ -1018,7 +1023,11 @@ impl DisplayListBuilder {
|
|||
debug_assert_eq!(len, count);
|
||||
}
|
||||
|
||||
fn push_iter<I>(&mut self, iter: I)
|
||||
/// Push items from an iterator to the display list.
|
||||
///
|
||||
/// NOTE: Pushing unexpected or invalid items to the display list
|
||||
/// may result in panic and confusion.
|
||||
pub fn push_iter<I>(&mut self, iter: I)
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
|
@ -1112,129 +1121,34 @@ impl DisplayListBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
// Gradients can be defined with stops outside the range of [0, 1]
|
||||
// when this happens the gradient needs to be normalized by adjusting
|
||||
// the gradient stops and gradient line into an equivalent gradient
|
||||
// with stops in the range [0, 1]. this is done by moving the beginning
|
||||
// of the gradient line to where stop[0] and the end of the gradient line
|
||||
// to stop[n-1]. this function adjusts the stops in place, and returns
|
||||
// the amount to adjust the gradient line start and stop
|
||||
fn normalize_stops(stops: &mut Vec<GradientStop>, extend_mode: ExtendMode) -> (f32, f32) {
|
||||
assert!(stops.len() >= 2);
|
||||
|
||||
let first = *stops.first().unwrap();
|
||||
let last = *stops.last().unwrap();
|
||||
|
||||
assert!(first.offset <= last.offset);
|
||||
|
||||
let stops_delta = last.offset - first.offset;
|
||||
|
||||
if stops_delta > 0.000001 {
|
||||
for stop in stops {
|
||||
stop.offset = (stop.offset - first.offset) / stops_delta;
|
||||
}
|
||||
|
||||
(first.offset, last.offset)
|
||||
} else {
|
||||
// We have a degenerate gradient and can't accurately transform the stops
|
||||
// what happens here depends on the repeat behavior, but in any case
|
||||
// we reconstruct the gradient stops to something simpler and equivalent
|
||||
stops.clear();
|
||||
|
||||
match extend_mode {
|
||||
ExtendMode::Clamp => {
|
||||
// This gradient is two colors split at the offset of the stops,
|
||||
// so create a gradient with two colors split at 0.5 and adjust
|
||||
// the gradient line so 0.5 is at the offset of the stops
|
||||
stops.push(GradientStop { color: first.color, offset: 0.0, });
|
||||
stops.push(GradientStop { color: first.color, offset: 0.5, });
|
||||
stops.push(GradientStop { color: last.color, offset: 0.5, });
|
||||
stops.push(GradientStop { color: last.color, offset: 1.0, });
|
||||
|
||||
let offset = last.offset;
|
||||
|
||||
(offset - 0.5, offset + 0.5)
|
||||
}
|
||||
ExtendMode::Repeat => {
|
||||
// A repeating gradient with stops that are all in the same
|
||||
// position should just display the last color. I believe the
|
||||
// spec says that it should be the average color of the gradient,
|
||||
// but this matches what Gecko and Blink does
|
||||
stops.push(GradientStop { color: last.color, offset: 0.0, });
|
||||
stops.push(GradientStop { color: last.color, offset: 1.0, });
|
||||
|
||||
(0.0, 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: gradients must be pushed in the order they're created
|
||||
// because create_gradient stores the stops in anticipation
|
||||
/// NOTE: gradients must be pushed in the order they're created
|
||||
/// because create_gradient stores the stops in anticipation.
|
||||
pub fn create_gradient(
|
||||
&mut self,
|
||||
start_point: LayoutPoint,
|
||||
end_point: LayoutPoint,
|
||||
mut stops: Vec<GradientStop>,
|
||||
stops: Vec<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
) -> Gradient {
|
||||
let (start_offset, end_offset) =
|
||||
DisplayListBuilder::normalize_stops(&mut stops, extend_mode);
|
||||
|
||||
let start_to_end = end_point - start_point;
|
||||
|
||||
self.push_stops(&stops);
|
||||
|
||||
Gradient {
|
||||
start_point: start_point + start_to_end * start_offset,
|
||||
end_point: start_point + start_to_end * end_offset,
|
||||
extend_mode,
|
||||
}
|
||||
let mut builder = GradientBuilder::with_stops(stops);
|
||||
let gradient = builder.gradient(start_point, end_point, extend_mode);
|
||||
self.push_stops(builder.stops());
|
||||
gradient
|
||||
}
|
||||
|
||||
// NOTE: gradients must be pushed in the order they're created
|
||||
// because create_gradient stores the stops in anticipation
|
||||
/// NOTE: gradients must be pushed in the order they're created
|
||||
/// because create_gradient stores the stops in anticipation.
|
||||
pub fn create_radial_gradient(
|
||||
&mut self,
|
||||
center: LayoutPoint,
|
||||
radius: LayoutSize,
|
||||
mut stops: Vec<GradientStop>,
|
||||
stops: Vec<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
) -> RadialGradient {
|
||||
if radius.width <= 0.0 || radius.height <= 0.0 {
|
||||
// The shader cannot handle a non positive radius. So
|
||||
// reuse the stops vector and construct an equivalent
|
||||
// gradient.
|
||||
let last_color = stops.last().unwrap().color;
|
||||
|
||||
let stops = [
|
||||
GradientStop { offset: 0.0, color: last_color, },
|
||||
GradientStop { offset: 1.0, color: last_color, },
|
||||
];
|
||||
|
||||
self.push_stops(&stops);
|
||||
|
||||
return RadialGradient {
|
||||
center,
|
||||
radius: LayoutSize::new(1.0, 1.0),
|
||||
start_offset: 0.0,
|
||||
end_offset: 1.0,
|
||||
extend_mode,
|
||||
};
|
||||
}
|
||||
|
||||
let (start_offset, end_offset) =
|
||||
DisplayListBuilder::normalize_stops(&mut stops, extend_mode);
|
||||
|
||||
self.push_stops(&stops);
|
||||
|
||||
RadialGradient {
|
||||
center,
|
||||
radius,
|
||||
start_offset,
|
||||
end_offset,
|
||||
extend_mode,
|
||||
}
|
||||
let mut builder = GradientBuilder::with_stops(stops);
|
||||
let gradient = builder.radial_gradient(center, radius, extend_mode);
|
||||
self.push_stops(builder.stops());
|
||||
gradient
|
||||
}
|
||||
|
||||
pub fn push_border(
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use {ExtendMode, Gradient, GradientStop, LayoutPoint, LayoutSize, RadialGradient};
|
||||
|
||||
|
||||
/// Construct a gradient to be used in display lists.
|
||||
///
|
||||
/// Each gradient needs at least two stops.
|
||||
pub struct GradientBuilder {
|
||||
stops: Vec<GradientStop>,
|
||||
}
|
||||
|
||||
impl GradientBuilder {
|
||||
/// Create a new gradient builder.
|
||||
pub fn new() -> GradientBuilder {
|
||||
GradientBuilder {
|
||||
stops: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a gradient builder with a list of stops.
|
||||
pub fn with_stops(stops: Vec<GradientStop>) -> GradientBuilder {
|
||||
GradientBuilder { stops }
|
||||
}
|
||||
|
||||
/// Push an additional stop for the gradient.
|
||||
pub fn push(&mut self, stop: GradientStop) {
|
||||
self.stops.push(stop);
|
||||
}
|
||||
|
||||
/// Get a reference to the list of stops.
|
||||
pub fn stops(&self) -> &[GradientStop] {
|
||||
self.stops.as_ref()
|
||||
}
|
||||
|
||||
/// Produce a linear gradient, normalize the stops.
|
||||
pub fn gradient(
|
||||
&mut self,
|
||||
start_point: LayoutPoint,
|
||||
end_point: LayoutPoint,
|
||||
extend_mode: ExtendMode,
|
||||
) -> Gradient {
|
||||
let (start_offset, end_offset) = self.normalize(extend_mode);
|
||||
let start_to_end = end_point - start_point;
|
||||
|
||||
Gradient {
|
||||
start_point: start_point + start_to_end * start_offset,
|
||||
end_point: start_point + start_to_end * end_offset,
|
||||
extend_mode,
|
||||
}
|
||||
}
|
||||
|
||||
/// Produce a radial gradient, normalize the stops.
|
||||
///
|
||||
/// Will replace the gradient with a single color
|
||||
/// if the radius negative.
|
||||
pub fn radial_gradient(
|
||||
&mut self,
|
||||
center: LayoutPoint,
|
||||
radius: LayoutSize,
|
||||
extend_mode: ExtendMode,
|
||||
) -> RadialGradient {
|
||||
if radius.width <= 0.0 || radius.height <= 0.0 {
|
||||
// The shader cannot handle a non positive radius. So
|
||||
// reuse the stops vector and construct an equivalent
|
||||
// gradient.
|
||||
let last_color = self.stops.last().unwrap().color;
|
||||
|
||||
self.stops.clear();
|
||||
self.stops.push(GradientStop { offset: 0.0, color: last_color, });
|
||||
self.stops.push(GradientStop { offset: 1.0, color: last_color, });
|
||||
|
||||
return RadialGradient {
|
||||
center,
|
||||
radius: LayoutSize::new(1.0, 1.0),
|
||||
start_offset: 0.0,
|
||||
end_offset: 1.0,
|
||||
extend_mode,
|
||||
};
|
||||
}
|
||||
|
||||
let (start_offset, end_offset) =
|
||||
self.normalize(extend_mode);
|
||||
|
||||
RadialGradient {
|
||||
center,
|
||||
radius,
|
||||
start_offset,
|
||||
end_offset,
|
||||
extend_mode,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gradients can be defined with stops outside the range of [0, 1]
|
||||
/// when this happens the gradient needs to be normalized by adjusting
|
||||
/// the gradient stops and gradient line into an equivalent gradient
|
||||
/// with stops in the range [0, 1]. this is done by moving the beginning
|
||||
/// of the gradient line to where stop[0] and the end of the gradient line
|
||||
/// to stop[n-1]. this function adjusts the stops in place, and returns
|
||||
/// the amount to adjust the gradient line start and stop.
|
||||
fn normalize(&mut self, extend_mode: ExtendMode) -> (f32, f32) {
|
||||
let stops = &mut self.stops;
|
||||
assert!(stops.len() >= 2);
|
||||
|
||||
let first = *stops.first().unwrap();
|
||||
let last = *stops.last().unwrap();
|
||||
|
||||
assert!(first.offset <= last.offset);
|
||||
|
||||
let stops_delta = last.offset - first.offset;
|
||||
|
||||
if stops_delta > 0.000001 {
|
||||
for stop in stops {
|
||||
stop.offset = (stop.offset - first.offset) / stops_delta;
|
||||
}
|
||||
|
||||
(first.offset, last.offset)
|
||||
} else {
|
||||
// We have a degenerate gradient and can't accurately transform the stops
|
||||
// what happens here depends on the repeat behavior, but in any case
|
||||
// we reconstruct the gradient stops to something simpler and equivalent
|
||||
stops.clear();
|
||||
|
||||
match extend_mode {
|
||||
ExtendMode::Clamp => {
|
||||
// This gradient is two colors split at the offset of the stops,
|
||||
// so create a gradient with two colors split at 0.5 and adjust
|
||||
// the gradient line so 0.5 is at the offset of the stops
|
||||
stops.push(GradientStop { color: first.color, offset: 0.0, });
|
||||
stops.push(GradientStop { color: first.color, offset: 0.5, });
|
||||
stops.push(GradientStop { color: last.color, offset: 0.5, });
|
||||
stops.push(GradientStop { color: last.color, offset: 1.0, });
|
||||
|
||||
let offset = last.offset;
|
||||
|
||||
(offset - 0.5, offset + 0.5)
|
||||
}
|
||||
ExtendMode::Repeat => {
|
||||
// A repeating gradient with stops that are all in the same
|
||||
// position should just display the last color. I believe the
|
||||
// spec says that it should be the average color of the gradient,
|
||||
// but this matches what Gecko and Blink does
|
||||
stops.push(GradientStop { color: last.color, offset: 0.0, });
|
||||
stops.push(GradientStop { color: last.color, offset: 1.0, });
|
||||
|
||||
(0.0, 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ mod color;
|
|||
mod display_item;
|
||||
mod display_list;
|
||||
mod font;
|
||||
mod gradient_builder;
|
||||
mod image;
|
||||
mod units;
|
||||
|
||||
|
@ -41,5 +42,6 @@ pub use color::*;
|
|||
pub use display_item::*;
|
||||
pub use display_list::*;
|
||||
pub use font::*;
|
||||
pub use gradient_builder::*;
|
||||
pub use image::*;
|
||||
pub use units::*;
|
||||
|
|
|
@ -1 +1 @@
|
|||
816ff14c1805c145ccd60d0227d82b1541fc24eb
|
||||
5fa5c46e167ca834d8fec3bf662bf420418698f4
|
||||
|
|
|
@ -228,6 +228,7 @@ fn write_stacking_context(
|
|||
let mut filters = vec![];
|
||||
for filter in filter_iter {
|
||||
match filter {
|
||||
FilterOp::Identity => { filters.push(Yaml::String("identity".into())) }
|
||||
FilterOp::Blur(x) => { filters.push(Yaml::String(format!("blur({})", x))) }
|
||||
FilterOp::Brightness(x) => { filters.push(Yaml::String(format!("brightness({})", x))) }
|
||||
FilterOp::Contrast(x) => { filters.push(Yaml::String(format!("contrast({})", x))) }
|
||||
|
|
|
@ -544,6 +544,9 @@ impl YamlHelper for Yaml {
|
|||
fn as_filter_op(&self) -> Option<FilterOp> {
|
||||
if let Some(s) = self.as_str() {
|
||||
match parse_function(s) {
|
||||
("identity", _, _) => {
|
||||
Some(FilterOp::Identity)
|
||||
}
|
||||
("blur", ref args, _) if args.len() == 1 => {
|
||||
Some(FilterOp::Blur(args[0].parse().unwrap()))
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче