diff --git a/gfx/wr/webrender/res/brush_blend.glsl b/gfx/wr/webrender/res/brush_blend.glsl index f72d41830317..4983efe7650a 100644 --- a/gfx/wr/webrender/res/brush_blend.glsl +++ b/gfx/wr/webrender/res/brush_blend.glsl @@ -6,8 +6,11 @@ #include shared,prim_shared,brush -varying vec3 vUv; +// Interpolated UV coordinates to sample. +varying vec2 vUv; +// X = layer index to sample, Y = flag to allow perspective interpolation of UV. +flat varying vec2 vLayerAndPerspective; flat varying float vAmount; flat varying int vOp; flat varying mat3 vColorMat; @@ -39,8 +42,10 @@ void brush_vs( vec2 y = mix(extra_data.st_bl, extra_data.st_br, f.x); f = mix(x, y, f.y); vec2 uv = mix(uv0, uv1, f); - vUv = vec3(uv / texture_size, res.layer); + float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0; + vUv = uv / texture_size * mix(vi.world_pos.w, 1.0, perspective_interpolate); + vLayerAndPerspective = vec2(res.layer, perspective_interpolate); vUvClipBounds = vec4(uv0, uv1) / texture_size.xyxy; float lumR = 0.2126; @@ -146,7 +151,8 @@ vec3 LinearToSrgb(vec3 color) { } Fragment brush_fs() { - vec4 Cs = texture(sColor0, vUv); + float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y); + vec4 Cs = texture(sColor0, vec3(vUv * perspective_divisor, vLayerAndPerspective.x)); // Un-premultiply the input. float alpha = Cs.a; diff --git a/gfx/wr/webrender/res/brush_image.glsl b/gfx/wr/webrender/res/brush_image.glsl index 9b162368c229..ee4bdffb1207 100644 --- a/gfx/wr/webrender/res/brush_image.glsl +++ b/gfx/wr/webrender/res/brush_image.glsl @@ -10,8 +10,10 @@ varying vec2 vLocalPos; #endif -// Interpolated uv coordinates in xy, and layer in z. -varying vec3 vUv; +// Interpolated UV coordinates to sample. +varying vec2 vUv; +// X = layer index to sample, Y = flag to allow perspective interpolation of UV. +flat varying vec2 vLayerAndPerspective; // Normalized bounds of the source image in the texture. flat varying vec4 vUvBounds; // Normalized bounds of the source image in the texture, adjusted to avoid @@ -97,7 +99,8 @@ void brush_vs( } } - vUv.z = res.layer; + float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0; + vLayerAndPerspective = vec2(res.layer, perspective_interpolate); // Handle case where the UV coords are inverted (e.g. from an // external image). @@ -141,9 +144,12 @@ void brush_vs( // Offset and scale vUv here to avoid doing it in the fragment shader. vec2 repeat = local_rect.size / stretch_size; - vUv.xy = mix(uv0, uv1, f) - min_uv; - vUv.xy /= texture_size; - vUv.xy *= repeat.xy; + vUv = mix(uv0, uv1, f) - min_uv; + vUv /= texture_size; + vUv *= repeat.xy; + if (perspective_interpolate == 0.0) { + vUv *= vi.world_pos.w; + } #ifdef WR_FEATURE_TEXTURE_RECT vUvBounds = vec4(0.0, 0.0, vec2(textureSize(sColor0))); @@ -201,12 +207,13 @@ void brush_vs( Fragment brush_fs() { vec2 uv_size = vUvBounds.zw - vUvBounds.xy; + float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y); #ifdef WR_FEATURE_ALPHA_PASS // This prevents the uv on the top and left parts of the primitive that was inflated // for anti-aliasing purposes from going beyound the range covered by the regular // (non-inflated) primitive. - vec2 local_uv = max(vUv.xy, vec2(0.0)); + vec2 local_uv = max(vUv * perspective_divisor, vec2(0.0)); // Handle horizontal and vertical repetitions. vec2 repeated_uv = mod(local_uv, uv_size) + vUvBounds.xy; @@ -222,13 +229,13 @@ Fragment brush_fs() { } #else // Handle horizontal and vertical repetitions. - vec2 repeated_uv = mod(vUv.xy, uv_size) + vUvBounds.xy; + vec2 repeated_uv = mod(vUv * perspective_divisor, uv_size) + vUvBounds.xy; #endif // Clamp the uvs to avoid sampling artifacts. vec2 uv = clamp(repeated_uv, vUvSampleBounds.xy, vUvSampleBounds.zw); - vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vUv.z)); + vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vLayerAndPerspective.x)); Fragment frag; diff --git a/gfx/wr/webrender/res/ps_split_composite.glsl b/gfx/wr/webrender/res/ps_split_composite.glsl index d3db7e9713a8..6388c023d115 100644 --- a/gfx/wr/webrender/res/ps_split_composite.glsl +++ b/gfx/wr/webrender/res/ps_split_composite.glsl @@ -4,7 +4,10 @@ #include shared,prim_shared -varying vec3 vUv; +// interpolated UV coordinates to sample. +varying vec2 vUv; +// X = layer index to sample, Y = flag to allow perspective interpolation of UV. +flat varying vec2 vLayerAndPerspective; flat varying vec4 vUvSampleBounds; #ifdef WR_VERTEX_SHADER @@ -103,15 +106,18 @@ void main(void) { f.y, f.x ); vec2 uv = mix(uv0, uv1, f); + float perspective_interpolate = float(ph.user_data.y); - vUv = vec3(uv / texture_size, res.layer); + vUv = uv / texture_size * mix(gl_Position.w, 1.0, perspective_interpolate); + vLayerAndPerspective = vec2(res.layer, perspective_interpolate); } #endif #ifdef WR_FRAGMENT_SHADER void main(void) { float alpha = do_clip(); - vec2 uv = clamp(vUv.xy, vUvSampleBounds.xy, vUvSampleBounds.zw); - oFragColor = alpha * textureLod(sPrevPassColor, vec3(uv, vUv.z), 0.0); + float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y); + vec2 uv = clamp(vUv * perspective_divisor, vUvSampleBounds.xy, vUvSampleBounds.zw); + oFragColor = alpha * textureLod(sPrevPassColor, vec3(uv, vLayerAndPerspective.x), 0.0); } #endif diff --git a/gfx/wr/webrender/src/batch.rs b/gfx/wr/webrender/src/batch.rs index 24ad3befbfa6..a3a29837d98f 100644 --- a/gfx/wr/webrender/src/batch.rs +++ b/gfx/wr/webrender/src/batch.rs @@ -597,6 +597,8 @@ impl AlphaBatchBuilder { #[cfg(debug_assertions)] //TODO: why is this needed? debug_assert_eq!(prim_instance.prepared_frame_id, render_tasks.frame_id()); + let is_chased = prim_instance.is_chased(); + let transform_id = transforms .get_id( prim_instance.spatial_node_index, @@ -627,6 +629,12 @@ impl AlphaBatchBuilder { prim_common_data.prim_size, ); + if is_chased { + println!("\tbatch {:?} with clip {:?} and bound {:?}", + prim_rect, clip_task_address, bounding_rect); + } + + match prim_instance.kind { PrimitiveInstanceKind::Clear { data_handle } => { let prim_data = &ctx.data_stores.prim[data_handle]; @@ -972,7 +980,7 @@ impl AlphaBatchBuilder { let prim_instance = &picture.prim_list.prim_instances[child.anchor]; let prim_info = &ctx.scratch.prim_info[prim_instance.visibility_info.0 as usize]; - let pic_index = match prim_instance.kind { + let child_pic_index = match prim_instance.kind { PrimitiveInstanceKind::Picture { pic_index, .. } => pic_index, PrimitiveInstanceKind::LineDecoration { .. } | PrimitiveInstanceKind::TextRun { .. } | @@ -987,7 +995,7 @@ impl AlphaBatchBuilder { unreachable!(); } }; - let pic = &ctx.prim_store.pictures[pic_index.0]; + let pic = &ctx.prim_store.pictures[child_pic_index.0]; // Get clip task, if set, for the picture primitive. @@ -1007,13 +1015,12 @@ impl AlphaBatchBuilder { transform_id: child.transform_id, }; - let surface_index = pic + let raster_config = pic .raster_config .as_ref() - .expect("BUG: 3d primitive was not assigned a surface") - .surface_index; + .expect("BUG: 3d primitive was not assigned a surface"); let (uv_rect_address, _) = ctx - .surfaces[surface_index.0] + .surfaces[raster_config.surface_index.0] .surface .as_ref() .expect("BUG: no surface") @@ -1025,7 +1032,7 @@ impl AlphaBatchBuilder { let prim_header_index = prim_headers.push(&prim_header, z_id, [ uv_rect_address.as_int(), - 0, + if raster_config.establishes_raster_root { 1 } else { 0 }, 0, ]); diff --git a/gfx/wr/wrench/reftests/split/reftest.list b/gfx/wr/wrench/reftests/split/reftest.list index 785a4284d97e..b84b6e6de9a6 100644 --- a/gfx/wr/wrench/reftests/split/reftest.list +++ b/gfx/wr/wrench/reftests/split/reftest.list @@ -16,4 +16,4 @@ platform(linux,mac) fuzzy(1,20) == same-plane.yaml same-plane.png #== cross.yaml cross-ref.yaml == mixed-order.yaml mixed-order-ref.yaml fuzzy(1,40000) == filter.yaml filter-ref.yaml -#fuzzy(1,10000) == gradient.yaml gradient-ref.yaml +fuzzy(1,10000) == gradient.yaml gradient-ref.yaml