Skip to content

Commit 9574ba2

Browse files
author
bors-servo
authored
Auto merge of #2630 - kvark:border-edge, r=glennw
Border edge checks This change prevents zero-sized edges from being produced by the frame builder and rendered. <!-- 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/2630) <!-- Reviewable:end -->
2 parents 092ada1 + 9e0e926 commit 9574ba2

File tree

2 files changed

+134
-144
lines changed

2 files changed

+134
-144
lines changed

webrender/src/batch.rs

+27-23
Original file line numberDiff line numberDiff line change
@@ -975,23 +975,17 @@ impl AlphaBatchBuilder {
975975
let border_cpu =
976976
&ctx.prim_store.cpu_borders[prim_metadata.cpu_prim_index.0];
977977
// TODO(gw): Select correct blend mode for edges and corners!!
978-
let corner_kind = BatchKind::Transformable(
979-
transform_kind,
980-
TransformBatchKind::BorderCorner,
981-
);
982-
let corner_key = BatchKey::new(corner_kind, non_segmented_blend_mode, no_textures);
983-
let edge_kind = BatchKind::Transformable(
984-
transform_kind,
985-
TransformBatchKind::BorderEdge,
986-
);
987-
let edge_key = BatchKey::new(edge_kind, non_segmented_blend_mode, no_textures);
988-
989-
// Work around borrow ck on borrowing batch_list twice.
990-
{
991-
let batch =
992-
self.batch_list.get_suitable_batch(corner_key, &task_relative_bounding_rect);
993-
for (i, instance_kind) in border_cpu.corner_instances.iter().enumerate()
994-
{
978+
979+
if border_cpu.corner_instances.iter().any(|&kind| kind != BorderCornerInstance::None) {
980+
let corner_kind = BatchKind::Transformable(
981+
transform_kind,
982+
TransformBatchKind::BorderCorner,
983+
);
984+
let corner_key = BatchKey::new(corner_kind, non_segmented_blend_mode, no_textures);
985+
let batch = self.batch_list
986+
.get_suitable_batch(corner_key, &task_relative_bounding_rect);
987+
988+
for (i, instance_kind) in border_cpu.corner_instances.iter().enumerate() {
995989
let sub_index = i as i32;
996990
match *instance_kind {
997991
BorderCornerInstance::None => {}
@@ -1018,12 +1012,22 @@ impl AlphaBatchBuilder {
10181012
}
10191013
}
10201014

1021-
let batch = self.batch_list.get_suitable_batch(edge_key, &task_relative_bounding_rect);
1022-
for (border_segment, instance_kind) in border_cpu.edges.iter().enumerate() {
1023-
match *instance_kind {
1024-
BorderEdgeKind::None => {},
1025-
_ => {
1026-
batch.push(base_instance.build(border_segment as i32, 0, 0));
1015+
if border_cpu.edges.iter().any(|&kind| kind != BorderEdgeKind::None) {
1016+
let edge_kind = BatchKind::Transformable(
1017+
transform_kind,
1018+
TransformBatchKind::BorderEdge,
1019+
);
1020+
let edge_key = BatchKey::new(edge_kind, non_segmented_blend_mode, no_textures);
1021+
let batch = self.batch_list
1022+
.get_suitable_batch(edge_key, &task_relative_bounding_rect);
1023+
1024+
for (border_segment, instance_kind) in border_cpu.edges.iter().enumerate() {
1025+
match *instance_kind {
1026+
BorderEdgeKind::None => {},
1027+
BorderEdgeKind::Solid |
1028+
BorderEdgeKind::Clip => {
1029+
batch.push(base_instance.build(border_segment as i32, 0, 0));
1030+
}
10271031
}
10281032
}
10291033
}

webrender/src/border.rs

+107-121
Original file line numberDiff line numberDiff line change
@@ -103,134 +103,116 @@ pub enum BorderEdgeKind {
103103
Clip,
104104
}
105105

106-
trait NormalBorderHelpers {
107-
fn get_corner(
108-
&self,
109-
edge0: &BorderSide,
110-
width0: f32,
111-
edge1: &BorderSide,
112-
width1: f32,
113-
radius: &LayerSize,
114-
corner: BorderCorner,
115-
border_rect: &LayerRect,
116-
) -> BorderCornerKind;
106+
fn get_corner(
107+
edge0: &BorderSide,
108+
width0: f32,
109+
edge1: &BorderSide,
110+
width1: f32,
111+
radius: &LayerSize,
112+
corner: BorderCorner,
113+
border_rect: &LayerRect,
114+
) -> BorderCornerKind {
115+
// If both widths are zero, a corner isn't formed.
116+
if width0 == 0.0 && width1 == 0.0 {
117+
return BorderCornerKind::None;
118+
}
117119

118-
fn get_edge(&self, edge: &BorderSide, width: f32) -> (BorderEdgeKind, f32);
119-
}
120+
// If both edges are transparent, no corner is formed.
121+
if edge0.color.a == 0.0 && edge1.color.a == 0.0 {
122+
return BorderCornerKind::None;
123+
}
120124

121-
impl NormalBorderHelpers for NormalBorder {
122-
fn get_corner(
123-
&self,
124-
edge0: &BorderSide,
125-
width0: f32,
126-
edge1: &BorderSide,
127-
width1: f32,
128-
radius: &LayerSize,
129-
corner: BorderCorner,
130-
border_rect: &LayerRect,
131-
) -> BorderCornerKind {
132-
// If both widths are zero, a corner isn't formed.
133-
if width0 == 0.0 && width1 == 0.0 {
134-
return BorderCornerKind::None;
125+
match (edge0.style, edge1.style) {
126+
// If both edges are none or hidden, no corner is needed.
127+
(BorderStyle::None, BorderStyle::None) |
128+
(BorderStyle::None, BorderStyle::Hidden) |
129+
(BorderStyle::Hidden, BorderStyle::None) |
130+
(BorderStyle::Hidden, BorderStyle::Hidden) => {
131+
BorderCornerKind::None
135132
}
136133

137-
// If both edges are transparent, no corner is formed.
138-
if edge0.color.a == 0.0 && edge1.color.a == 0.0 {
139-
return BorderCornerKind::None;
134+
// If one of the edges is none or hidden, we just draw one style.
135+
(BorderStyle::None, _) |
136+
(_, BorderStyle::None) |
137+
(BorderStyle::Hidden, _) |
138+
(_, BorderStyle::Hidden) => {
139+
BorderCornerKind::Clip(BorderCornerInstance::Single)
140140
}
141141

142-
match (edge0.style, edge1.style) {
143-
// If both edges are none or hidden, no corner is needed.
144-
(BorderStyle::None, BorderStyle::None) |
145-
(BorderStyle::None, BorderStyle::Hidden) |
146-
(BorderStyle::Hidden, BorderStyle::None) |
147-
(BorderStyle::Hidden, BorderStyle::Hidden) => {
148-
BorderCornerKind::None
149-
}
150-
151-
// If one of the edges is none or hidden, we just draw one style.
152-
(BorderStyle::None, _) |
153-
(_, BorderStyle::None) |
154-
(BorderStyle::Hidden, _) |
155-
(_, BorderStyle::Hidden) => {
156-
BorderCornerKind::Clip(BorderCornerInstance::Single)
157-
}
158-
159-
// If both borders are solid, we can draw them with a simple rectangle if
160-
// both the colors match and there is no radius.
161-
(BorderStyle::Solid, BorderStyle::Solid) => {
162-
if edge0.color == edge1.color && radius.width == 0.0 && radius.height == 0.0 {
163-
BorderCornerKind::Solid
164-
} else {
165-
BorderCornerKind::Clip(BorderCornerInstance::Single)
166-
}
167-
}
168-
169-
// Inset / outset borders just modify the color of edges, so can be
170-
// drawn with the normal border corner shader.
171-
(BorderStyle::Outset, BorderStyle::Outset) |
172-
(BorderStyle::Inset, BorderStyle::Inset) |
173-
(BorderStyle::Double, BorderStyle::Double) |
174-
(BorderStyle::Groove, BorderStyle::Groove) |
175-
(BorderStyle::Ridge, BorderStyle::Ridge) => {
142+
// If both borders are solid, we can draw them with a simple rectangle if
143+
// both the colors match and there is no radius.
144+
(BorderStyle::Solid, BorderStyle::Solid) => {
145+
if edge0.color == edge1.color && radius.width == 0.0 && radius.height == 0.0 {
146+
BorderCornerKind::Solid
147+
} else {
176148
BorderCornerKind::Clip(BorderCornerInstance::Single)
177149
}
178-
179-
// Dashed and dotted border corners get drawn into a clip mask.
180-
(BorderStyle::Dashed, BorderStyle::Dashed) => BorderCornerKind::new_mask(
181-
BorderCornerClipKind::Dash,
182-
width0,
183-
width1,
184-
corner,
185-
*radius,
186-
*border_rect,
187-
),
188-
(BorderStyle::Dotted, BorderStyle::Dotted) => BorderCornerKind::new_mask(
189-
BorderCornerClipKind::Dot,
190-
width0,
191-
width1,
192-
corner,
193-
*radius,
194-
*border_rect,
195-
),
196-
197-
// Draw border transitions with dots and/or dashes as
198-
// solid segments. The old border path didn't support
199-
// this anyway, so we might as well start using the new
200-
// border path here, since the dashing in the edges is
201-
// much higher quality anyway.
202-
(BorderStyle::Dotted, _) |
203-
(_, BorderStyle::Dotted) |
204-
(BorderStyle::Dashed, _) |
205-
(_, BorderStyle::Dashed) => BorderCornerKind::Clip(BorderCornerInstance::Single),
206-
207-
// Everything else can be handled by drawing the corner twice,
208-
// where the shader outputs zero alpha for the side it's not
209-
// drawing. This is somewhat inefficient in terms of pixels
210-
// written, but it's a fairly rare case, and we can optimize
211-
// this case later.
212-
_ => BorderCornerKind::Clip(BorderCornerInstance::Double),
213150
}
214-
}
215151

216-
fn get_edge(&self, edge: &BorderSide, width: f32) -> (BorderEdgeKind, f32) {
217-
if width == 0.0 {
218-
return (BorderEdgeKind::None, 0.0);
152+
// Inset / outset borders just modify the color of edges, so can be
153+
// drawn with the normal border corner shader.
154+
(BorderStyle::Outset, BorderStyle::Outset) |
155+
(BorderStyle::Inset, BorderStyle::Inset) |
156+
(BorderStyle::Double, BorderStyle::Double) |
157+
(BorderStyle::Groove, BorderStyle::Groove) |
158+
(BorderStyle::Ridge, BorderStyle::Ridge) => {
159+
BorderCornerKind::Clip(BorderCornerInstance::Single)
219160
}
220161

221-
match edge.style {
222-
BorderStyle::None | BorderStyle::Hidden => (BorderEdgeKind::None, 0.0),
162+
// Dashed and dotted border corners get drawn into a clip mask.
163+
(BorderStyle::Dashed, BorderStyle::Dashed) => BorderCornerKind::new_mask(
164+
BorderCornerClipKind::Dash,
165+
width0,
166+
width1,
167+
corner,
168+
*radius,
169+
*border_rect,
170+
),
171+
(BorderStyle::Dotted, BorderStyle::Dotted) => BorderCornerKind::new_mask(
172+
BorderCornerClipKind::Dot,
173+
width0,
174+
width1,
175+
corner,
176+
*radius,
177+
*border_rect,
178+
),
179+
180+
// Draw border transitions with dots and/or dashes as
181+
// solid segments. The old border path didn't support
182+
// this anyway, so we might as well start using the new
183+
// border path here, since the dashing in the edges is
184+
// much higher quality anyway.
185+
(BorderStyle::Dotted, _) |
186+
(_, BorderStyle::Dotted) |
187+
(BorderStyle::Dashed, _) |
188+
(_, BorderStyle::Dashed) => BorderCornerKind::Clip(BorderCornerInstance::Single),
189+
190+
// Everything else can be handled by drawing the corner twice,
191+
// where the shader outputs zero alpha for the side it's not
192+
// drawing. This is somewhat inefficient in terms of pixels
193+
// written, but it's a fairly rare case, and we can optimize
194+
// this case later.
195+
_ => BorderCornerKind::Clip(BorderCornerInstance::Double),
196+
}
197+
}
198+
199+
fn get_edge(edge: &BorderSide, width: f32, height: f32) -> (BorderEdgeKind, f32) {
200+
if width == 0.0 || height <= 0.0 {
201+
return (BorderEdgeKind::None, 0.0);
202+
}
223203

224-
BorderStyle::Solid | BorderStyle::Inset | BorderStyle::Outset => {
225-
(BorderEdgeKind::Solid, width)
226-
}
204+
match edge.style {
205+
BorderStyle::None | BorderStyle::Hidden => (BorderEdgeKind::None, 0.0),
227206

228-
BorderStyle::Double |
229-
BorderStyle::Groove |
230-
BorderStyle::Ridge |
231-
BorderStyle::Dashed |
232-
BorderStyle::Dotted => (BorderEdgeKind::Clip, width),
207+
BorderStyle::Solid | BorderStyle::Inset | BorderStyle::Outset => {
208+
(BorderEdgeKind::Solid, width)
233209
}
210+
211+
BorderStyle::Double |
212+
BorderStyle::Groove |
213+
BorderStyle::Ridge |
214+
BorderStyle::Dashed |
215+
BorderStyle::Dotted => (BorderEdgeKind::Clip, width),
234216
}
235217
}
236218

@@ -431,7 +413,7 @@ impl<'a> DisplayListFlattener<'a> {
431413
}
432414

433415
let corners = [
434-
border.get_corner(
416+
get_corner(
435417
left,
436418
widths.left,
437419
top,
@@ -440,7 +422,7 @@ impl<'a> DisplayListFlattener<'a> {
440422
BorderCorner::TopLeft,
441423
&info.rect,
442424
),
443-
border.get_corner(
425+
get_corner(
444426
right,
445427
widths.right,
446428
top,
@@ -449,7 +431,7 @@ impl<'a> DisplayListFlattener<'a> {
449431
BorderCorner::TopRight,
450432
&info.rect,
451433
),
452-
border.get_corner(
434+
get_corner(
453435
right,
454436
widths.right,
455437
bottom,
@@ -458,7 +440,7 @@ impl<'a> DisplayListFlattener<'a> {
458440
BorderCorner::BottomRight,
459441
&info.rect,
460442
),
461-
border.get_corner(
443+
get_corner(
462444
left,
463445
widths.left,
464446
bottom,
@@ -469,10 +451,14 @@ impl<'a> DisplayListFlattener<'a> {
469451
),
470452
];
471453

472-
let (left_edge, left_len) = border.get_edge(left, widths.left);
473-
let (top_edge, top_len) = border.get_edge(top, widths.top);
474-
let (right_edge, right_len) = border.get_edge(right, widths.right);
475-
let (bottom_edge, bottom_len) = border.get_edge(bottom, widths.bottom);
454+
let (left_edge, left_len) = get_edge(left, widths.left,
455+
info.rect.size.height - radius.top_left.height - radius.bottom_left.height);
456+
let (top_edge, top_len) = get_edge(top, widths.top,
457+
info.rect.size.width - radius.top_left.width - radius.top_right.width);
458+
let (right_edge, right_len) = get_edge(right, widths.right,
459+
info.rect.size.height - radius.top_right.height - radius.bottom_right.height);
460+
let (bottom_edge, bottom_len) = get_edge(bottom, widths.bottom,
461+
info.rect.size.width - radius.bottom_right.width - radius.bottom_left.width);
476462

477463
let edges = [left_edge, top_edge, right_edge, bottom_edge];
478464

0 commit comments

Comments
 (0)