Bug 1606771 - Fix border image repetition computation. r=gw
authorNicolas Silva <nsilva@mozilla.com>
Thu, 23 Jan 2020 14:24:57 +0000
changeset 511477 b77165c764503ccf3b0f52b60fff265d4048ba6e
parent 511476 fcea11e2d25a45bb7cfe6c2187c30a17ca5e4c4e
child 511478 47c89996827d2abfb923ba769e676581b181f04b
push id37048
push userrmaries@mozilla.com
push dateThu, 23 Jan 2020 21:42:24 +0000
treeherdermozilla-central@fb6b61e49217 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1606771
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 1606771 - Fix border image repetition computation. r=gw The computation of the repetition depends on the aspect ratio of the segment's uv rectangle, which was previously represented by the dx/dy variables in the shader. These were mistakenly computing the ratio of the normalized uvs within the primitive's total uv rect, which was incorrect since the normalization introduces a non-uniform scale. This patch fixes it by taking the uv size in device pixels instead of the the normalized textel rect. dx and dy are also renamed into segment_uv_size which is a more informative name. Differential Revision: https://phabricator.services.mozilla.com/D60768
gfx/wr/webrender/res/brush_image.glsl
--- a/gfx/wr/webrender/res/brush_image.glsl
+++ b/gfx/wr/webrender/res/brush_image.glsl
@@ -88,67 +88,67 @@ void image_brush_vs(
     }
 
     // If this segment should interpolate relative to the
     // segment, modify the parameters for that.
     if ((brush_flags & BRUSH_FLAG_SEGMENT_RELATIVE) != 0) {
         local_rect = segment_rect;
         stretch_size = local_rect.size;
 
-        float dx = segment_data.z - segment_data.x;
-        float dy = 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 of the CPU as well as other sources of
+            // 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) {
-                dx = segment_data.x;
-                dy = segment_data.y;
+                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 (dx < epsilon || stretch_size.x < epsilon) {
-                    dx = 1.0 - segment_data.z;
+                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 (dy < epsilon || stretch_size.y < epsilon) {
-                    dy = 1.0 - segment_data.w;
+                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 / dy * dx;
+              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 / dx * dy;
+              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 = dx;
+                stretch_size.x = segment_data.z - segment_data.x;
             }
             if ((brush_flags & BRUSH_FLAG_SEGMENT_REPEAT_Y) != 0) {
-                stretch_size.y = dy;
+                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;