diff --git a/gfx/wr/webrender/res/brush.glsl b/gfx/wr/webrender/res/brush.glsl index 9f21741be27f..6ed53c519732 100644 --- a/gfx/wr/webrender/res/brush.glsl +++ b/gfx/wr/webrender/res/brush.glsl @@ -156,7 +156,11 @@ void brush_shader_main_vs( // shaders that don't clip in the future, // but it's reasonable to assume that one // implies the other, for now. -#ifdef WR_FEATURE_ALPHA_PASS + // SW-WR may decay some requests for alpha-pass shaders to + // the opaque version if only the clip-mask is required. In + // that case the opaque vertex shader must still write out + // the clip information, which is cheap to do for SWGL. +#if defined(WR_FEATURE_ALPHA_PASS) || defined(SWGL) write_clip( vi.world_pos, clip_area, diff --git a/gfx/wr/webrender/src/device/gl.rs b/gfx/wr/webrender/src/device/gl.rs index 297f2732a3f9..776178ee8ea4 100644 --- a/gfx/wr/webrender/src/device/gl.rs +++ b/gfx/wr/webrender/src/device/gl.rs @@ -981,6 +981,9 @@ pub struct Capabilities { /// Whether the driver prefers fewer and larger texture uploads /// over many smaller updates. pub prefers_batched_texture_uploads: bool, + /// Whether clip-masking is supported natively by the GL implementation + /// rather than emulated in shaders. + pub uses_native_clip_mask: bool, /// The name of the renderer, as reported by GL pub renderer_name: String, } @@ -1627,6 +1630,12 @@ impl Device { gl::GlType::Gles => gl_version >= [3, 1], }; + // SWGL uses swgl_clipMask() instead of implementing clip-masking in shaders. + // This allows certain shaders to potentially bypass the more expensive alpha- + // pass variants if they know the alpha-pass was only required to deal with + // clip-masking. + let uses_native_clip_mask = is_software_webrender; + // On Mali-Gxx the driver really struggles with many small texture uploads, // and handles fewer, larger uploads better. let prefers_batched_texture_uploads = is_mali_g; @@ -1654,6 +1663,7 @@ impl Device { supports_render_target_partial_update, supports_shader_storage_object, prefers_batched_texture_uploads, + uses_native_clip_mask, renderer_name, }, diff --git a/gfx/wr/webrender/src/renderer/mod.rs b/gfx/wr/webrender/src/renderer/mod.rs index c73f34327ed8..da30166b2af3 100644 --- a/gfx/wr/webrender/src/renderer/mod.rs +++ b/gfx/wr/webrender/src/renderer/mod.rs @@ -3038,7 +3038,7 @@ impl Renderer { } self.shaders.borrow_mut() - .get(&batch.key, batch.features, self.debug_flags) + .get(&batch.key, batch.features, self.debug_flags, &self.device) .bind( &mut self.device, projection, &mut self.renderer_errors, @@ -3078,6 +3078,7 @@ impl Renderer { &batch.key, batch.features | BatchFeatures::ALPHA_PASS, self.debug_flags, + &self.device, ); if batch.key.blend_mode != prev_blend_mode { diff --git a/gfx/wr/webrender/src/renderer/shade.rs b/gfx/wr/webrender/src/renderer/shade.rs index 1c9a6732f1fc..6143cc0e06c2 100644 --- a/gfx/wr/webrender/src/renderer/shade.rs +++ b/gfx/wr/webrender/src/renderer/shade.rs @@ -1060,6 +1060,7 @@ impl Shaders { key: &BatchKey, mut features: BatchFeatures, debug_flags: DebugFlags, + device: &Device, ) -> &mut LazilyCompiledShader { match key.kind { BatchKind::SplitComposite => { @@ -1089,7 +1090,15 @@ impl Shaders { BrushBatchKind::MixBlend { .. } => { &mut self.brush_mix_blend } + BrushBatchKind::LinearGradient | + BrushBatchKind::RadialGradient | BrushBatchKind::ConicGradient => { + // SWGL uses a native clip mask implementation that bypasses the shader. + // Don't consider it in that case when deciding whether or not to use + // an alpha-pass shader. + if device.get_capabilities().uses_native_clip_mask { + features.remove(BatchFeatures::CLIP_MASK); + } // Gradient brushes can optimistically use the opaque shader even // with a blend mode if they don't require any features. if !features.intersects( @@ -1099,31 +1108,12 @@ impl Shaders { ) { features.remove(BatchFeatures::ALPHA_PASS); } - &mut self.brush_conic_gradient - } - BrushBatchKind::RadialGradient => { - // Gradient brushes can optimistically use the opaque shader even - // with a blend mode if they don't require any features. - if !features.intersects( - BatchFeatures::ANTIALIASING - | BatchFeatures::REPETITION - | BatchFeatures::CLIP_MASK, - ) { - features.remove(BatchFeatures::ALPHA_PASS); + match brush_kind { + BrushBatchKind::LinearGradient => &mut self.brush_linear_gradient, + BrushBatchKind::RadialGradient => &mut self.brush_radial_gradient, + BrushBatchKind::ConicGradient => &mut self.brush_conic_gradient, + _ => panic!(), } - &mut self.brush_radial_gradient - } - BrushBatchKind::LinearGradient => { - // Gradient brushes can optimistically use the opaque shader even - // with a blend mode if they don't require any features. - if !features.intersects( - BatchFeatures::ANTIALIASING - | BatchFeatures::REPETITION - | BatchFeatures::CLIP_MASK, - ) { - features.remove(BatchFeatures::ALPHA_PASS); - } - &mut self.brush_linear_gradient } BrushBatchKind::YuvImage(image_buffer_kind, ..) => { let shader_index =