diff --git a/servo/components/servo/Cargo.lock b/servo/components/servo/Cargo.lock index 258d8891f743..a7bf8c48ed4a 100644 --- a/servo/components/servo/Cargo.lock +++ b/servo/components/servo/Cargo.lock @@ -2594,7 +2594,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.5.1" -source = "git+https://github.com/servo/webrender#b2cca277407b59c4c3b8122f36b64bd81f83a4dc" +source = "git+https://github.com/servo/webrender#c9ceb97e9f6b919518f3c70cdae85d3213c8290c" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2619,7 +2619,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.5.1" -source = "git+https://github.com/servo/webrender#b2cca277407b59c4c3b8122f36b64bd81f83a4dc" +source = "git+https://github.com/servo/webrender#c9ceb97e9f6b919518f3c70cdae85d3213c8290c" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/servo/ports/cef/Cargo.lock b/servo/ports/cef/Cargo.lock index 8fe77c4de7c4..d02219412a38 100644 --- a/servo/ports/cef/Cargo.lock +++ b/servo/ports/cef/Cargo.lock @@ -2454,7 +2454,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.5.1" -source = "git+https://github.com/servo/webrender#b2cca277407b59c4c3b8122f36b64bd81f83a4dc" +source = "git+https://github.com/servo/webrender#c9ceb97e9f6b919518f3c70cdae85d3213c8290c" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2479,7 +2479,7 @@ dependencies = [ [[package]] name = "webrender_traits" version = "0.5.1" -source = "git+https://github.com/servo/webrender#b2cca277407b59c4c3b8122f36b64bd81f83a4dc" +source = "git+https://github.com/servo/webrender#c9ceb97e9f6b919518f3c70cdae85d3213c8290c" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/servo/resources/shaders/prim_shared.glsl b/servo/resources/shaders/prim_shared.glsl index 21d6c41e382f..e7e0200584ec 100644 --- a/servo/resources/shaders/prim_shared.glsl +++ b/servo/resources/shaders/prim_shared.glsl @@ -30,6 +30,8 @@ #define MAX_STOPS_PER_ANGLE_GRADIENT 8 #ifdef WR_VERTEX_SHADER +uniform sampler2D sLayers; + struct Layer { mat4 transform; mat4 inv_transform; @@ -45,31 +47,32 @@ layout(std140) uniform Tiles { vec4 tiles[WR_MAX_UBO_VECTORS]; }; -layout(std140) uniform Layers { - vec4 layers[WR_MAX_UBO_VECTORS]; -}; - Layer fetch_layer(int index) { Layer layer; - int offset = index * 13; + // Create a UV base coord for each 8 texels. + // This is required because trying to use an offset + // of more than 8 texels doesn't work on some versions + // of OSX. + ivec2 uv0 = ivec2(0, index); + ivec2 uv1 = ivec2(8, index); - layer.transform[0] = layers[offset + 0]; - layer.transform[1] = layers[offset + 1]; - layer.transform[2] = layers[offset + 2]; - layer.transform[3] = layers[offset + 3]; + layer.transform[0] = texelFetchOffset(sLayers, uv0, 0, ivec2(0, 0)); + layer.transform[1] = texelFetchOffset(sLayers, uv0, 0, ivec2(1, 0)); + layer.transform[2] = texelFetchOffset(sLayers, uv0, 0, ivec2(2, 0)); + layer.transform[3] = texelFetchOffset(sLayers, uv0, 0, ivec2(3, 0)); - layer.inv_transform[0] = layers[offset + 4]; - layer.inv_transform[1] = layers[offset + 5]; - layer.inv_transform[2] = layers[offset + 6]; - layer.inv_transform[3] = layers[offset + 7]; + layer.inv_transform[0] = texelFetchOffset(sLayers, uv0, 0, ivec2(4, 0)); + layer.inv_transform[1] = texelFetchOffset(sLayers, uv0, 0, ivec2(5, 0)); + layer.inv_transform[2] = texelFetchOffset(sLayers, uv0, 0, ivec2(6, 0)); + layer.inv_transform[3] = texelFetchOffset(sLayers, uv0, 0, ivec2(7, 0)); - layer.local_clip_rect = layers[offset + 8]; + layer.local_clip_rect = texelFetchOffset(sLayers, uv1, 0, ivec2(0, 0)); - layer.screen_vertices[0] = layers[offset + 9]; - layer.screen_vertices[1] = layers[offset + 10]; - layer.screen_vertices[2] = layers[offset + 11]; - layer.screen_vertices[3] = layers[offset + 12]; + layer.screen_vertices[0] = texelFetchOffset(sLayers, uv1, 0, ivec2(1, 0)); + layer.screen_vertices[1] = texelFetchOffset(sLayers, uv1, 0, ivec2(2, 0)); + layer.screen_vertices[2] = texelFetchOffset(sLayers, uv1, 0, ivec2(2, 0)); + layer.screen_vertices[3] = texelFetchOffset(sLayers, uv1, 0, ivec2(3, 0)); return layer; } @@ -534,7 +537,7 @@ Composite fetch_composite(int index) { #endif #ifdef WR_FRAGMENT_SHADER -void do_clip(vec2 pos, vec4 clip_rect, vec4 radius) { +float do_clip(vec2 pos, vec4 clip_rect, vec4 radius) { vec2 ref_tl = clip_rect.xy + vec2( radius.x, radius.x); vec2 ref_tr = clip_rect.zy + vec2(-radius.y, radius.y); vec2 ref_br = clip_rect.zw + vec2(-radius.z, -radius.z); @@ -545,15 +548,26 @@ void do_clip(vec2 pos, vec4 clip_rect, vec4 radius) { float d_br = distance(pos, ref_br); float d_bl = distance(pos, ref_bl); - bool out0 = pos.x < ref_tl.x && pos.y < ref_tl.y && d_tl > radius.x; - bool out1 = pos.x > ref_tr.x && pos.y < ref_tr.y && d_tr > radius.y; - bool out2 = pos.x > ref_br.x && pos.y > ref_br.y && d_br > radius.z; - bool out3 = pos.x < ref_bl.x && pos.y > ref_bl.y && d_bl > radius.w; + float pixels_per_fragment = length(fwidth(pos.xy)); + float nudge = 0.5 * pixels_per_fragment; - // TODO(gw): Alpha anti-aliasing based on edge distance! - if (out0 || out1 || out2 || out3) { - discard; - } + bool out0 = pos.x < ref_tl.x && pos.y < ref_tl.y && d_tl > radius.x - nudge; + bool out1 = pos.x > ref_tr.x && pos.y < ref_tr.y && d_tr > radius.y - nudge; + bool out2 = pos.x > ref_br.x && pos.y > ref_br.y && d_br > radius.z - nudge; + bool out3 = pos.x < ref_bl.x && pos.y > ref_bl.y && d_bl > radius.w - nudge; + + float distance_from_border = (float(out0) * (d_tl - radius.x + nudge)) + + (float(out1) * (d_tr - radius.y + nudge)) + + (float(out2) * (d_br - radius.z + nudge)) + + (float(out3) * (d_bl - radius.w + nudge)); + + // Move the distance back into pixels. + distance_from_border /= pixels_per_fragment; + + // Apply a more gradual fade out to transparent. + //distance_from_border -= 0.5; + + return smoothstep(1.0, 0, distance_from_border); } float squared_distance_from_rect(vec2 p, vec2 origin, vec2 size) { diff --git a/servo/resources/shaders/ps_border.fs.glsl b/servo/resources/shaders/ps_border.fs.glsl index 9dfeb2d26c2d..252377e3ab51 100644 --- a/servo/resources/shaders/ps_border.fs.glsl +++ b/servo/resources/shaders/ps_border.fs.glsl @@ -52,36 +52,43 @@ float alpha_for_solid_border_corner(vec2 local_pos, return alpha_for_solid_border(distance_from_ref, inner_radius, outer_radius, pixels_per_fragment); } -#ifdef WR_FEATURE_TRANSFORM - -#else -vec4 draw_dotted_edge(vec2 position, vec2 edge_size, float pixels_per_fragment) { - float two_pixels = 2 * pixels_per_fragment; +vec4 draw_dotted_edge(vec2 local_pos, vec4 piece_rect, float pixels_per_fragment) { + // We don't use pixels_per_fragment here, since it can change along the edge + // of a transformed border edge. We want this calculation to be consistent + // across the entire edge so that the positioning of the dots stays the same. + float two_pixels = 2 * length(fwidth(vLocalPos.xy)); // Circle diameter is stroke width, minus a couple pixels to account for anti-aliasing. - float circle_diameter = max(edge_size.x - two_pixels, min(edge_size.x, two_pixels)); + float circle_diameter = max(piece_rect.z - two_pixels, min(piece_rect.z, two_pixels)); - //// Divide the edge into segments which are the size of the circle diameter. - float segments_in_edge = floor(edge_size.y / circle_diameter); + // We want to spread the circles across the edge, but keep one circle diameter at the end + // reserved for two half-circles which connect to the corners. + float edge_available = piece_rect.w - (circle_diameter * 2); + float number_of_circles = floor(edge_available / (circle_diameter * 2)); - // Every other segment has a circle. - float number_of_circles = floor(segments_in_edge / 2); - if (number_of_circles <= 0) - return vec4(0, 0, 0, 0); + // Here we are initializing the distance from the y coordinate of the center of the circle to + // the closest end half-circle. + vec2 relative_pos = local_pos - piece_rect.xy; + float y_distance = min(relative_pos.y, piece_rect.w - relative_pos.y); - // Spread the circles throughout the edge, to distribute the extra space evenly. We want - // to ensure that we have at last two pixels of space for each circle so that they aren't - // touching. - float space_for_each_circle = ceil(max(edge_size.y / number_of_circles, two_pixels)); + if (number_of_circles > 0) { + // Spread the circles throughout the edge, to distribute the extra space evenly. We want + // to ensure that we have at last two pixels of space for each circle so that they aren't + // touching. + float space_for_each_circle = ceil(max(edge_available / number_of_circles, two_pixels)); - // Find the circle index. We adjust the y position here because the first circle is a - // half circle at the edge of this border side. - float circle_index = floor((position.y + (space_for_each_circle / 2)) / space_for_each_circle); + float first_half_circle_space = circle_diameter; - // Find the center of the circle that is closest to our position. We will then calculate - // the distance from the edge of the circle. - vec2 circle_center = vec2(edge_size.x / 2, circle_index * space_for_each_circle); - float distance_from_circle_edge = length(circle_center - position) - (circle_diameter / 2); + float circle_index = (relative_pos.y - first_half_circle_space) / space_for_each_circle; + circle_index = floor(clamp(circle_index, 0, number_of_circles - 1)); + + float circle_y_pos = + circle_index * space_for_each_circle + (space_for_each_circle / 2) + circle_diameter; + y_distance = min(abs(circle_y_pos - relative_pos.y), y_distance); + } + + float distance_from_circle_center = length(vec2(relative_pos.x - (piece_rect.z / 2), y_distance)); + float distance_from_circle_edge = distance_from_circle_center - (circle_diameter / 2); // Don't anti-alias if the circle diameter is small to avoid a blur of color. if (circle_diameter < two_pixels && distance_from_circle_edge > 0) @@ -94,7 +101,24 @@ vec4 draw_dotted_edge(vec2 position, vec2 edge_size, float pixels_per_fragment) return vHorizontalColor * vec4(1, 1, 1, alpha); } -void draw_dotted_border(vec2 local_pos, float distance_from_mix_line) { +vec4 draw_dashed_edge(float position, float border_width, float pixels_per_fragment) { + // TODO: Investigate exactly what FF does. + float size = border_width * 3; + float segment = floor(position / size); + + float alpha = alpha_for_solid_border(position, + segment * size, + (segment + 1) * size, + pixels_per_fragment); + + if (mod(segment + 2, 2) == 0) { + return vHorizontalColor * vec4(1, 1, 1, 1 - alpha); + } else { + return vHorizontalColor * vec4(1, 1, 1, alpha); + } +} + +void draw_dashed_or_dotted_border(vec2 local_pos, float distance_from_mix_line) { // This is the conversion factor for transformations and device pixel scaling. float pixels_per_fragment = length(fwidth(local_pos.xy)); @@ -117,76 +141,30 @@ void draw_dotted_border(vec2 local_pos, float distance_from_mix_line) { } case PST_BOTTOM: case PST_TOP: { - vec2 piece_relative_position = vLocalPos - vPieceRect.xy; - oFragColor = draw_dotted_edge(piece_relative_position.yx, vPieceRect.wz, pixels_per_fragment); - break; - } - case PST_LEFT: - case PST_RIGHT: - { - vec2 piece_relative_position = vLocalPos - vPieceRect.xy; - oFragColor = draw_dotted_edge(piece_relative_position.xy, vPieceRect.zw, pixels_per_fragment); - break; - } - } -} - -#endif - -vec4 draw_dashed_edge(float position, float border_width, float pixels_per_fragment) { - // TODO: Investigate exactly what FF does. - float size = border_width * 3; - float segment = floor(position / size); - - float alpha = alpha_for_solid_border(position, - segment * size, - (segment + 1) * size, - pixels_per_fragment); - - if (mod(segment + 2, 2) == 0) { - return vHorizontalColor * vec4(1, 1, 1, 1 - alpha); - } else { - return vHorizontalColor * vec4(1, 1, 1, alpha); - } -} - -void draw_dashed_border(vec2 local_pos, float distance_from_mix_line) { - // This is the conversion factor for transformations and device pixel scaling. - float pixels_per_fragment = length(fwidth(local_pos.xy)); - - switch (vBorderPart) { - // These are the layer tile part PrimitivePart as uploaded by the tiling.rs - case PST_TOP_LEFT: - case PST_TOP_RIGHT: - case PST_BOTTOM_LEFT: - case PST_BOTTOM_RIGHT: - { - oFragColor = get_fragment_color(distance_from_mix_line, pixels_per_fragment); - if (vRadii.x > 0.0) { - oFragColor *= vec4(1, 1, 1, alpha_for_solid_border_corner(local_pos, - vRadii.z, - vRadii.x, - pixels_per_fragment)); + if (vBorderStyle == BORDER_STYLE_DASHED) { + oFragColor = draw_dashed_edge(vLocalPos.x - vPieceRect.x, + vPieceRect.w, + pixels_per_fragment); + } else { + oFragColor = draw_dotted_edge(local_pos.yx, vPieceRect.yxwz, pixels_per_fragment); } - - break; - } - case PST_BOTTOM: - case PST_TOP: - { - oFragColor = draw_dashed_edge(vLocalPos.x - vPieceRect.x, vPieceRect.w, pixels_per_fragment); break; } case PST_LEFT: case PST_RIGHT: { - oFragColor = draw_dashed_edge(vLocalPos.y - vPieceRect.y, vPieceRect.z, pixels_per_fragment); + if (vBorderStyle == BORDER_STYLE_DASHED) { + oFragColor = draw_dashed_edge(vLocalPos.y - vPieceRect.y, + vPieceRect.z, + pixels_per_fragment); + } else { + oFragColor = draw_dotted_edge(local_pos.xy, vPieceRect.xyzw, pixels_per_fragment); + } break; } } } - vec4 draw_double_edge(float pos, float len, float distance_from_mix_line, @@ -328,46 +306,30 @@ void main(void) { float distance_from_mix_line = (local_pos.x - vPieceRect.x) * vPieceRect.w - (local_pos.y - vPieceRect.y) * vPieceRect.z; distance_from_mix_line /= vPieceRectHypotenuseLength; +#else + float distance_from_mix_line = vDistanceFromMixLine; +#endif switch (vBorderStyle) { case BORDER_STYLE_DASHED: - draw_dashed_border(local_pos, distance_from_mix_line); - break; case BORDER_STYLE_DOTTED: + draw_dashed_or_dotted_border(local_pos, distance_from_mix_line); + break; + case BORDER_STYLE_DOUBLE: + draw_double_border(distance_from_mix_line, local_pos); + break; case BORDER_STYLE_OUTSET: case BORDER_STYLE_INSET: case BORDER_STYLE_SOLID: case BORDER_STYLE_NONE: draw_solid_border(distance_from_mix_line, local_pos); break; - case BORDER_STYLE_DOUBLE: - draw_double_border(distance_from_mix_line, local_pos); - break; default: discard; } +#ifdef WR_FEATURE_TRANSFORM oFragColor *= vec4(1, 1, 1, alpha); -#else - switch (vBorderStyle) { - case BORDER_STYLE_DASHED: - draw_dashed_border(local_pos, vDistanceFromMixLine); - break; - case BORDER_STYLE_DOTTED: - draw_dotted_border(local_pos, vDistanceFromMixLine); - break; - case BORDER_STYLE_OUTSET: - case BORDER_STYLE_INSET: - case BORDER_STYLE_SOLID: - case BORDER_STYLE_NONE: - draw_solid_border(vDistanceFromMixLine, local_pos); - break; - case BORDER_STYLE_DOUBLE: - draw_double_border(vDistanceFromMixLine, local_pos); - break; - default: - discard; - } #endif } diff --git a/servo/resources/shaders/ps_gradient.fs.glsl b/servo/resources/shaders/ps_gradient.fs.glsl index cb99679656d3..bef76b7aafaa 100644 --- a/servo/resources/shaders/ps_gradient.fs.glsl +++ b/servo/resources/shaders/ps_gradient.fs.glsl @@ -7,12 +7,12 @@ void main(void) { float alpha = 0; vec2 local_pos = init_transform_fs(vLocalPos, vLocalRect, alpha); #else + float alpha = 1; vec2 local_pos = vPos; #endif - do_clip(local_pos, vClipRect, vClipRadius); - - oFragColor = mix(vColor0, vColor1, vF); + alpha = min(alpha, do_clip(local_pos, vClipRect, vClipRadius)); + oFragColor = mix(vColor0, vColor1, vF) * vec4(1, 1, 1, alpha); #ifdef WR_FEATURE_TRANSFORM oFragColor.a *= alpha; diff --git a/servo/resources/shaders/ps_image_clip.fs.glsl b/servo/resources/shaders/ps_image_clip.fs.glsl index 2ec824e4414a..bdee07b55e9b 100644 --- a/servo/resources/shaders/ps_image_clip.fs.glsl +++ b/servo/resources/shaders/ps_image_clip.fs.glsl @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ void main(void) { - do_clip(vPos, vClipRect, vClipRadius); + float alpha = do_clip(vPos, vClipRect, vClipRadius); vec2 st = vTextureOffset + vTextureSize * fract(vUv); - oFragColor = texture(sDiffuse, st); + oFragColor = texture(sDiffuse, st) * vec4(1, 1, 1, alpha); } diff --git a/servo/resources/shaders/ps_rectangle_clip.fs.glsl b/servo/resources/shaders/ps_rectangle_clip.fs.glsl index fe3af9162ad5..0d07141b04f0 100644 --- a/servo/resources/shaders/ps_rectangle_clip.fs.glsl +++ b/servo/resources/shaders/ps_rectangle_clip.fs.glsl @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ void main(void) { - do_clip(vPos, vClipRect, vClipRadius); - - oFragColor = vColor; + float alpha = do_clip(vPos, vClipRect, vClipRadius); + oFragColor = vColor * vec4(1, 1, 1, alpha); }