Bug 1571974: Simplify orientation handling in line decoration shaders. r=kvark
authorJim Blandy <jimb@mozilla.com>
Fri, 24 Jan 2020 21:46:56 +0000
changeset 512413 71ce2bbd81881f19f797cfc8aec7e7ea2ea8347f
parent 512412 9f54a1daf2f205d25f8d1b12ec09ed29176f9f2d
child 512414 ade9ca7e807b87c5d268ecfafea2a8bb82d580e5
push id37087
push usernbeleuzu@mozilla.com
push dateTue, 04 Feb 2020 04:04:16 +0000
treeherdermozilla-central@c32017c40f19 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskvark
bugs1571974
milestone74.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
Bug 1571974: Simplify orientation handling in line decoration shaders. r=kvark We want to use the same line decoration (dashed, dotted, wavy) shader code for both horizontal and vertical lines, so it makes sense for them to use a coordinate system that has been rotated (transposed, actually) so that .x always runs parallel to the line being decorated, and .y is always perpendicular. Before this patch, we passed the orientation enum as a vertex attribute, used a switch to swap coordinates in the vertex shader, and then swapped them again in the fragment shader. This patch trades the orientation for a f32 'axis select' vertex attribute, and uses `mix` to swap them in the vertex shader. Then no consideration is necessary in the fragment shader: the vLocalPos varying is already in the appropriate form. Since get_line_decoration_sizes is already thinking in terms of line-parallel coordinates, it might seem like a good idea for decoration jobs to simply use line-parallel coordinates throughout. However, this actually results in more swapping and opportunities for confusion: much of the CPU work is concerned with the rectangle the decoration's mask occupies in the texture cache, which is axis-aligned. Differential Revision: https://phabricator.services.mozilla.com/D60926
gfx/wr/webrender/res/cs_line_decoration.glsl
gfx/wr/webrender/src/render_target.rs
gfx/wr/webrender/src/renderer.rs
--- a/gfx/wr/webrender/res/cs_line_decoration.glsl
+++ b/gfx/wr/webrender/res/cs_line_decoration.glsl
@@ -4,51 +4,47 @@
 
 #include shared
 
 #define LINE_STYLE_SOLID        0
 #define LINE_STYLE_DOTTED       1
 #define LINE_STYLE_DASHED       2
 #define LINE_STYLE_WAVY         3
 
-// Local space position
+// Fragment position in the coordinate system used for positioning decorations.
+// To keep the code independent of whether the line is horizontal or vertical,
+// vLocalPos.x is always parallel, and .y always perpendicular, to the line
+// being decorated.
 varying vec2 vLocalPos;
 
-flat varying float vAxisSelect;
 flat varying int vStyle;
 flat varying vec4 vParams;
 
 #ifdef WR_VERTEX_SHADER
 
-#define LINE_ORIENTATION_VERTICAL       0
-#define LINE_ORIENTATION_HORIZONTAL     1
-
+// The size of the mask tile we're rendering, in pixels.
 in vec4 aTaskRect;
+
+// The size of the mask tile. aLocalSize.x is always horizontal and .y vertical,
+// regardless of the line's orientation. The size is chosen by
+// prim_store::get_line_decoration_sizes.
 in vec2 aLocalSize;
+
+// A LINE_STYLE_* value, indicating what sort of line to draw.
 in int aStyle;
-in int aOrientation;
+
+// 0.0 for a horizontal line, 1.0 for a vertical line.
+in float aAxisSelect;
+
+// The thickness of the wavy line itself, not the amplitude of the waves (i.e.,
+// the thickness of the final decorated line).
 in float aWavyLineThickness;
 
 void main(void) {
-    vec2 size;
-
-    switch (aOrientation) {
-        case LINE_ORIENTATION_HORIZONTAL:
-            vAxisSelect = 0.0;
-            size = aLocalSize;
-            break;
-        case LINE_ORIENTATION_VERTICAL:
-            vAxisSelect = 1.0;
-            size = aLocalSize.yx;
-            break;
-        default:
-            vAxisSelect = 0.0;
-            size = vec2(0.0);
-    }
-
+    vec2 size = mix(aLocalSize, aLocalSize.yx, aAxisSelect);
     vStyle = aStyle;
 
     switch (vStyle) {
         case LINE_STYLE_SOLID: {
             break;
         }
         case LINE_STYLE_DASHED: {
             vParams = vec4(size.x,          // period
@@ -81,35 +77,32 @@ void main(void) {
                            flat_length,
                            size.y);
             break;
         }
         default:
             vParams = vec4(0.0);
     }
 
-    vLocalPos = aPosition.xy * aLocalSize;
+    vLocalPos = mix(aPosition.xy, aPosition.yx, aAxisSelect) * size;
 
     gl_Position = uTransform * vec4(aTaskRect.xy + aTaskRect.zw * aPosition.xy, 0.0, 1.0);
 }
 #endif
 
 #ifdef WR_FRAGMENT_SHADER
 
 #define MAGIC_WAVY_LINE_AA_SNAP         0.5
 
 void main(void) {
     // Find the appropriate distance to apply the step over.
-    vec2 local_pos = vLocalPos;
-    float aa_range = compute_aa_range(local_pos);
+    vec2 pos = vLocalPos;
+    float aa_range = compute_aa_range(pos);
     float alpha = 1.0;
 
-    // Select the x/y coord, depending on which axis this edge is.
-    vec2 pos = mix(local_pos.xy, local_pos.yx, vAxisSelect);
-
     switch (vStyle) {
         case LINE_STYLE_SOLID: {
             break;
         }
         case LINE_STYLE_DASHED: {
             // Calculate dash alpha (on/off) based on dash length
             alpha = step(floor(pos.x + 0.5), vParams.y);
             break;
--- a/gfx/wr/webrender/src/render_target.rs
+++ b/gfx/wr/webrender/src/render_target.rs
@@ -768,17 +768,20 @@ impl TextureCacheRenderTarget {
         match task.kind {
             RenderTaskKind::LineDecoration(ref info) => {
                 self.clears.push(target_rect.0);
 
                 self.line_decorations.push(LineDecorationJob {
                     task_rect: target_rect.0.to_f32(),
                     local_size: info.local_size,
                     style: info.style as i32,
-                    orientation: info.orientation as i32,
+                    axis_select: match info.orientation {
+                        LineOrientation::Horizontal => 0.0,
+                        LineOrientation::Vertical => 1.0,
+                    },
                     wavy_line_thickness: info.wavy_line_thickness,
                 });
             }
             RenderTaskKind::HorizontalBlur(..) => {
                 add_blur_instances(
                     &mut self.horizontal_blurs,
                     BlurDirection::Horizontal,
                     task_address,
@@ -1051,17 +1054,17 @@ pub struct BlitJob {
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[derive(Debug)]
 pub struct LineDecorationJob {
     pub task_rect: DeviceRect,
     pub local_size: LayoutSize,
     pub wavy_line_thickness: f32,
     pub style: i32,
-    pub orientation: i32,
+    pub axis_select: f32,
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub struct GradientJob {
     pub task_rect: DeviceRect,
     pub stops: [f32; GRADIENT_FP_STOPS],
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -449,19 +449,19 @@ pub(crate) mod desc {
                 kind: VertexAttributeKind::F32,
             },
             VertexAttribute {
                 name: "aStyle",
                 count: 1,
                 kind: VertexAttributeKind::I32,
             },
             VertexAttribute {
-                name: "aOrientation",
+                name: "aAxisSelect",
                 count: 1,
-                kind: VertexAttributeKind::I32,
+                kind: VertexAttributeKind::F32,
             },
         ],
     };
 
     pub const GRADIENT: VertexDescriptor = VertexDescriptor {
         vertex_attributes: &[
             VertexAttribute {
                 name: "aPosition",