Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync changes from mozilla-central gfx/wr #3841

Merged
merged 7 commits into from Jan 23, 2020
@@ -112,7 +112,10 @@ void multi_brush_vs(
#define BRUSH_FLAG_SEGMENT_RELATIVE 2
#define BRUSH_FLAG_SEGMENT_REPEAT_X 4
#define BRUSH_FLAG_SEGMENT_REPEAT_Y 8
#define BRUSH_FLAG_TEXEL_RECT 16
#define BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND 16
#define BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND 32
#define BRUSH_FLAG_SEGMENT_NINEPATCH_MIDDLE 64
#define BRUSH_FLAG_TEXEL_RECT 128

#define INVALID_SEGMENT_INDEX 0xffff

@@ -93,25 +93,71 @@ void image_brush_vs(
local_rect = segment_rect;
stretch_size = local_rect.size;

if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
stretch_size.x = (segment_data.z - segment_data.x);
}
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
stretch_size.y = (segment_data.w - segment_data.y);
}

// If the extra data is a texel rect, modify the UVs.
if ((brush_flags & BRUSH_FLAG_TEXEL_RECT) != 0) {
vec2 uv_size = res.uv_rect.p1 - res.uv_rect.p0;
uv0 = res.uv_rect.p0 + segment_data.xy * uv_size;
uv1 = res.uv_rect.p0 + segment_data.zw * uv_size;

// Size of the uv rect of the segment we are considering when computing
// the repetitions. In most case it is the current segment, but for the
// middle area we look at the border size instead.
vec2 segment_uv_size = uv1 - uv0;

#ifdef WR_FEATURE_REPETITION
// The repetition parameters for the middle area of a nine-patch are based
// on the size of the border segments rather than the middle segment itself,
// taking top and left by default, falling back to bottom and right when a
// size is empty.
// TODO(bug 1609893): Move this logic to the CPU as well as other sources of
// branchiness in this shader.
if ((brush_flags & BRUSH_FLAG_SEGMENT_NINEPATCH_MIDDLE) != 0) {
segment_uv_size = uv0 - res.uv_rect.p0;
stretch_size.x = segment_rect.p0.x - prim_rect.p0.x;
stretch_size.y = segment_rect.p0.y - prim_rect.p0.y;
float epsilon = 0.001;
if (segment_uv_size.x < epsilon || stretch_size.x < epsilon) {
segment_uv_size.x = res.uv_rect.p1.x - uv1.x;
stretch_size.x = prim_rect.p0.x + prim_rect.size.x
- segment_rect.p0.x - segment_rect.size.x;
}
if (segment_uv_size.y < epsilon || stretch_size.y < epsilon) {
segment_uv_size.y = res.uv_rect.p1.y - uv1.y;
stretch_size.y = prim_rect.p0.y + prim_rect.size.y
- segment_rect.p0.y - segment_rect.size.y;
}
}

vec2 original_stretch_size = stretch_size;
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
stretch_size.x = original_stretch_size.y / segment_uv_size.y * segment_uv_size.x;
}
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
stretch_size.y = original_stretch_size.x / segment_uv_size.x * segment_uv_size.y;
}
#endif

} else {
#ifdef WR_FEATURE_REPETITION
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) {
stretch_size.x = stretch_size.x * uv_size.x;
stretch_size.x = segment_data.z - segment_data.x;
}
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
stretch_size.y = stretch_size.y * uv_size.y;
stretch_size.y = segment_data.w - segment_data.y;
}
#endif
}

#ifdef WR_FEATURE_REPETITION
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND) != 0) {
float nx = max(1.0, round(segment_rect.size.x / stretch_size.x));
stretch_size.x = segment_rect.size.x / nx;
}
if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND) != 0) {
float ny = max(1.0, round(segment_rect.size.y / stretch_size.y));
stretch_size.y = segment_rect.size.y / ny;
}
#endif
}

float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;
@@ -1349,40 +1349,47 @@ impl NinePatchDescriptor {
rect: LayoutRect,
uv_rect: TexelRect,
repeat_horizontal: RepeatMode,
repeat_vertical: RepeatMode
repeat_vertical: RepeatMode,
extra_flags: BrushFlags,
) {
if uv_rect.uv1.x > uv_rect.uv0.x &&
uv_rect.uv1.y > uv_rect.uv0.y {

// Use segment relative interpolation for all
// instances in this primitive.
let mut brush_flags =
BrushFlags::SEGMENT_RELATIVE |
BrushFlags::SEGMENT_TEXEL_RECT;

// Enable repeat modes on the segment.
if repeat_horizontal == RepeatMode::Repeat {
brush_flags |= BrushFlags::SEGMENT_REPEAT_X;
}
if repeat_vertical == RepeatMode::Repeat {
brush_flags |= BrushFlags::SEGMENT_REPEAT_Y;
}
if uv_rect.uv1.x < uv_rect.uv0.x || uv_rect.uv1.y < uv_rect.uv0.y {
return;
}

let segment = BrushSegment::new(
rect,
true,
EdgeAaSegmentMask::empty(),
[
uv_rect.uv0.x,
uv_rect.uv0.y,
uv_rect.uv1.x,
uv_rect.uv1.y,
],
brush_flags,
);

segments.push(segment);
// Use segment relative interpolation for all
// instances in this primitive.
let mut brush_flags =
BrushFlags::SEGMENT_RELATIVE |
BrushFlags::SEGMENT_TEXEL_RECT |
extra_flags;

// Enable repeat modes on the segment.
if repeat_horizontal == RepeatMode::Repeat {
brush_flags |= BrushFlags::SEGMENT_REPEAT_X;
} else if repeat_horizontal == RepeatMode::Round {
brush_flags |= BrushFlags::SEGMENT_REPEAT_X | BrushFlags::SEGMENT_REPEAT_X_ROUND;
}

if repeat_vertical == RepeatMode::Repeat {
brush_flags |= BrushFlags::SEGMENT_REPEAT_Y;
} else if repeat_vertical == RepeatMode::Round {
brush_flags |= BrushFlags::SEGMENT_REPEAT_Y | BrushFlags::SEGMENT_REPEAT_Y_ROUND;
}

let segment = BrushSegment::new(
rect,
true,
EdgeAaSegmentMask::empty(),
[
uv_rect.uv0.x,
uv_rect.uv0.y,
uv_rect.uv1.x,
uv_rect.uv1.y,
],
brush_flags,
);

segments.push(segment);
}

// Build the list of image segments
@@ -1394,31 +1401,35 @@ impl NinePatchDescriptor {
LayoutRect::from_floats(tl_outer.x, tl_outer.y, tl_inner.x, tl_inner.y),
TexelRect::new(px0, py0, px1, py1),
RepeatMode::Stretch,
RepeatMode::Stretch
RepeatMode::Stretch,
BrushFlags::empty(),
);
// Top right
add_segment(
&mut segments,
LayoutRect::from_floats(tr_inner.x, tr_outer.y, tr_outer.x, tr_inner.y),
TexelRect::new(px2, py0, px3, py1),
RepeatMode::Stretch,
RepeatMode::Stretch
RepeatMode::Stretch,
BrushFlags::empty(),
);
// Bottom right
add_segment(
&mut segments,
LayoutRect::from_floats(br_inner.x, br_inner.y, br_outer.x, br_outer.y),
TexelRect::new(px2, py2, px3, py3),
RepeatMode::Stretch,
RepeatMode::Stretch
RepeatMode::Stretch,
BrushFlags::empty(),
);
// Bottom left
add_segment(
&mut segments,
LayoutRect::from_floats(bl_outer.x, bl_inner.y, bl_inner.x, bl_outer.y),
TexelRect::new(px0, py2, px1, py3),
RepeatMode::Stretch,
RepeatMode::Stretch
RepeatMode::Stretch,
BrushFlags::empty(),
);

// Center
@@ -1428,7 +1439,8 @@ impl NinePatchDescriptor {
LayoutRect::from_floats(tl_inner.x, tl_inner.y, tr_inner.x, bl_inner.y),
TexelRect::new(px1, py1, px2, py2),
self.repeat_horizontal,
self.repeat_vertical
self.repeat_vertical,
BrushFlags::SEGMENT_NINEPATCH_MIDDLE,
);
}

@@ -1441,6 +1453,7 @@ impl NinePatchDescriptor {
TexelRect::new(px1, py0, px2, py1),
self.repeat_horizontal,
RepeatMode::Stretch,
BrushFlags::empty(),
);
// Bottom
add_segment(
@@ -1449,6 +1462,7 @@ impl NinePatchDescriptor {
TexelRect::new(px1, py2, px2, py3),
self.repeat_horizontal,
RepeatMode::Stretch,
BrushFlags::empty(),
);
// Left
add_segment(
@@ -1457,6 +1471,7 @@ impl NinePatchDescriptor {
TexelRect::new(px0, py1, px1, py2),
RepeatMode::Stretch,
self.repeat_vertical,
BrushFlags::empty(),
);
// Right
add_segment(
@@ -1465,6 +1480,7 @@ impl NinePatchDescriptor {
TexelRect::new(px2, py1, px3, py2),
RepeatMode::Stretch,
self.repeat_vertical,
BrushFlags::empty(),
);

segments
@@ -403,16 +403,22 @@ bitflags! {
#[derive(MallocSizeOf)]
pub struct BrushFlags: u8 {
/// Apply perspective interpolation to UVs
const PERSPECTIVE_INTERPOLATION = 0x1;
const PERSPECTIVE_INTERPOLATION = 1;
/// Do interpolation relative to segment rect,
/// rather than primitive rect.
const SEGMENT_RELATIVE = 0x2;
const SEGMENT_RELATIVE = 2;
/// Repeat UVs horizontally.
const SEGMENT_REPEAT_X = 0x4;
const SEGMENT_REPEAT_X = 4;
/// Repeat UVs vertically.
const SEGMENT_REPEAT_Y = 0x8;
const SEGMENT_REPEAT_Y = 8;
/// Horizontally follow border-image-repeat: round.
const SEGMENT_REPEAT_X_ROUND = 16;
/// Vertically follow border-image-repeat: round.
const SEGMENT_REPEAT_Y_ROUND = 32;
/// Middle (fill) area of a border-image-repeat.
const SEGMENT_NINEPATCH_MIDDLE = 64;
/// The extra segment data is a texel rect.
const SEGMENT_TEXEL_RECT = 0x10;
const SEGMENT_TEXEL_RECT = 128;
}
}

Binary file not shown.
@@ -0,0 +1,42 @@
---
root:
items:
- type: stacking-context
bounds: [0, 0, 500, 500]
items:
# The pattern fits exactly a whole number of times in the border.
- type: border
bounds: [ 50, 50, 192, 192 ]
width: 32
border-type: image
image-source: "border-image-src.png"
image-width: 96
image-height: 96
slice: [ 32 ]
outset: 0
repeat-vertical: round
repeat-horizontal: round
# The pattern has to be stretched to fit.
- type: border
bounds: [ 300, 50, 200, 200 ]
width: 32
border-type: image
image-source: "border-image-src.png"
image-width: 96
image-height: 96
slice: [ 32 ]
outset: 0
repeat-vertical: round
repeat-horizontal: round
# The pattern has to be shrunk to fit.
- type: border
bounds: [ 550, 50, 180, 180 ]
width: 32
border-type: image
image-source: "border-image-src.png"
image-width: 96
image-height: 96
slice: [ 32 ]
outset: 0
repeat-vertical: round
repeat-horizontal: round
@@ -17,6 +17,7 @@ skip_on(android,device) fuzzy(64,24) == border-groove-simple.yaml border-groove-
skip_on(android,device) fuzzy(64,24) == border-ridge-simple.yaml border-ridge-simple-ref.yaml # Fails on Pixel2
platform(linux,mac) fuzzy(1,3) == degenerate-curve.yaml degenerate-curve.png
platform(linux,mac) == border-image.yaml border-image-ref.png
platform(linux,mac) == border-image-round.yaml border-image-round-ref.png
== border-image-crash.yaml border-image-crash-ref.yaml
== border-image-fill.yaml border-image-fill-ref.png
== border-no-bogus-line.yaml border-no-bogus-line-ref.png
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.