| author | Nicolas Silva <nsilva@mozilla.com> |
| Thu, 23 Jan 2020 14:26:32 +0000 | |
| changeset 511475 | 834d49acd3c02a7e5ae75d0a4d01a55e69c8fdba |
| parent 511474 | 6b61867f80b123f11aa3e9252f0ac005a12787c0 |
| child 511476 | fcea11e2d25a45bb7cfe6c2187c30a17ca5e4c4e |
| push id | 37048 |
| push user | rmaries@mozilla.com |
| push date | Thu, 23 Jan 2020 21:42:24 +0000 |
| treeherder | mozilla-central@fb6b61e49217 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | gw |
| bugs | 1606771 |
| milestone | 74.0a1 |
| first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
| last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/wr/webrender/res/brush.glsl +++ b/gfx/wr/webrender/res/brush.glsl @@ -109,17 +109,18 @@ void multi_brush_vs( #define VECS_PER_SEGMENT 2 #define BRUSH_FLAG_PERSPECTIVE_INTERPOLATION 1 #define BRUSH_FLAG_SEGMENT_RELATIVE 2 #define BRUSH_FLAG_SEGMENT_REPEAT_X 4 #define BRUSH_FLAG_SEGMENT_REPEAT_Y 8 #define BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND 16 #define BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND 32 -#define BRUSH_FLAG_TEXEL_RECT 64 +#define BRUSH_FLAG_SEGMENT_NINEPATCH_MIDDLE 64 +#define BRUSH_FLAG_TEXEL_RECT 128 #define INVALID_SEGMENT_INDEX 0xffff void main(void) { // Load the brush instance from vertex attributes. Instance instance = decode_instance_attributes(); int edge_flags = instance.flags & 0xff; int brush_flags = (instance.flags >> 8) & 0xff;
--- a/gfx/wr/webrender/res/brush_image.glsl +++ b/gfx/wr/webrender/res/brush_image.glsl @@ -99,23 +99,49 @@ void image_brush_vs( // 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; #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 of the CPU as well as other sources of + // branchiness in this shader. + if ((brush_flags & BRUSH_FLAG_SEGMENT_NINEPATCH_MIDDLE) != 0) { + dx = segment_data.x; + dy = segment_data.y; + 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 (dx < epsilon || stretch_size.x < epsilon) { + dx = 1.0 - segment_data.z; + stretch_size.x = prim_rect.p0.x + prim_rect.size.x + - segment_rect.p0.x - segment_rect.size.x; + } + if (dy < epsilon || stretch_size.y < epsilon) { + dy = 1.0 - segment_data.w; + 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 = local_rect.size.y / dy * dx; + stretch_size.x = original_stretch_size.y / dy * dx; } if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) { - stretch_size.y = local_rect.size.x / dx * dy; + stretch_size.y = original_stretch_size.x / dx * dy; } #endif + } else { #ifdef WR_FEATURE_REPETITION if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_X) != 0) { stretch_size.x = dx; } if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) { stretch_size.y = dy; }
--- a/gfx/wr/webrender/src/border.rs +++ b/gfx/wr/webrender/src/border.rs @@ -1344,27 +1344,29 @@ impl NinePatchDescriptor { ); let br_inner = br_outer - vec2(self.widths.right, self.widths.bottom); fn add_segment( segments: &mut Vec<BrushSegment>, 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 { return; } // Use segment relative interpolation for all // instances in this primitive. let mut brush_flags = BrushFlags::SEGMENT_RELATIVE | - BrushFlags::SEGMENT_TEXEL_RECT; + 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; } @@ -1394,84 +1396,93 @@ impl NinePatchDescriptor { let mut segments = Vec::new(); // Top left add_segment( &mut segments, 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 if self.fill { add_segment( &mut segments, 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, ); } // Add edge segments. // Top add_segment( &mut segments, LayoutRect::from_floats(tl_inner.x, tl_outer.y, tr_inner.x, tl_inner.y), TexelRect::new(px1, py0, px2, py1), self.repeat_horizontal, RepeatMode::Stretch, + BrushFlags::empty(), ); // Bottom add_segment( &mut segments, LayoutRect::from_floats(bl_inner.x, bl_inner.y, br_inner.x, bl_outer.y), TexelRect::new(px1, py2, px2, py3), self.repeat_horizontal, RepeatMode::Stretch, + BrushFlags::empty(), ); // Left add_segment( &mut segments, LayoutRect::from_floats(tl_outer.x, tl_inner.y, tl_inner.x, bl_inner.y), TexelRect::new(px0, py1, px1, py2), RepeatMode::Stretch, self.repeat_vertical, + BrushFlags::empty(), ); // Right add_segment( &mut segments, LayoutRect::from_floats(tr_inner.x, tr_inner.y, br_outer.x, br_inner.y), TexelRect::new(px2, py1, px3, py2), RepeatMode::Stretch, self.repeat_vertical, + BrushFlags::empty(), ); segments } }
--- a/gfx/wr/webrender/src/gpu_types.rs +++ b/gfx/wr/webrender/src/gpu_types.rs @@ -406,22 +406,24 @@ bitflags! { const PERSPECTIVE_INTERPOLATION = 1; /// Do interpolation relative to segment rect, /// rather than primitive rect. const SEGMENT_RELATIVE = 2; /// Repeat UVs horizontally. const SEGMENT_REPEAT_X = 4; /// Repeat UVs vertically. const SEGMENT_REPEAT_Y = 8; - /// Horizontally follow border-image-repeat: round + /// Horizontally follow border-image-repeat: round. const SEGMENT_REPEAT_X_ROUND = 16; - /// Vorizontally follow border-image-repeat: round + /// 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 = 64; + const SEGMENT_TEXEL_RECT = 128; } } /// Convenience structure to encode into PrimitiveInstanceData. pub struct BrushInstance { pub prim_header_index: PrimitiveHeaderIndex, pub render_task_address: RenderTaskAddress, pub clip_task_address: RenderTaskAddress,