diff --git a/webrender/res/ps_radial_gradient.glsl b/webrender/res/brush_radial_gradient.glsl similarity index 79% rename from webrender/res/ps_radial_gradient.glsl rename to webrender/res/brush_radial_gradient.glsl index 541c7a6d3a..2cc8f3a276 100644 --- a/webrender/res/ps_radial_gradient.glsl +++ b/webrender/res/brush_radial_gradient.glsl @@ -2,7 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include shared,prim_shared +#define VECS_PER_SPECIFIC_BRUSH 2 + +#include shared,prim_shared,brush flat varying int vGradientAddress; flat varying float vGradientRepeat; @@ -14,7 +16,12 @@ flat varying float vEndRadius; varying vec2 vPos; +#ifdef WR_FEATURE_ALPHA_PASS +varying vec2 vLocalPos; +#endif + #ifdef WR_VERTEX_SHADER + struct RadialGradient { vec4 start_end_center; vec4 start_end_radius_ratio_xy_extend_mode; @@ -25,18 +32,16 @@ RadialGradient fetch_radial_gradient(int address) { return RadialGradient(data[0], data[1]); } -void main(void) { - Primitive prim = load_primitive(); - RadialGradient gradient = fetch_radial_gradient(prim.specific_prim_address); +void brush_vs( + VertexInfo vi, + int prim_address, + RectWithSize local_rect, + ivec3 user_data, + PictureTask pic_task +) { + RadialGradient gradient = fetch_radial_gradient(prim_address); - VertexInfo vi = write_vertex(prim.local_rect, - prim.local_clip_rect, - prim.z, - prim.scroll_node, - prim.task, - prim.local_rect); - - vPos = vi.local_pos - prim.local_rect.p0; + vPos = vi.local_pos - local_rect.p0; vStartCenter = gradient.start_end_center.xy; vEndCenter = gradient.start_end_center.zw; @@ -51,17 +56,19 @@ void main(void) { vStartCenter.y *= ratio_xy; vEndCenter.y *= ratio_xy; - vGradientAddress = prim.specific_prim_address + VECS_PER_RADIAL_GRADIENT; + vGradientAddress = user_data.x; // Whether to repeat the gradient instead of clamping. vGradientRepeat = float(int(gradient.start_end_radius_ratio_xy_extend_mode.w) != EXTEND_MODE_CLAMP); - write_clip(vi.screen_pos, prim.clip_area); +#ifdef WR_FEATURE_ALPHA_PASS + vLocalPos = vi.local_pos; +#endif } #endif #ifdef WR_FRAGMENT_SHADER -void main(void) { +vec4 brush_fs() { vec2 cd = vEndCenter - vStartCenter; vec2 pd = vPos - vStartCenter; float rd = vEndRadius - vStartRadius; @@ -105,6 +112,10 @@ void main(void) { offset, vGradientRepeat); - oFragColor = color * do_clip(); +#ifdef WR_FEATURE_ALPHA_PASS + color *= init_transform_fs(vLocalPos); +#endif + + return color; } #endif diff --git a/webrender/res/prim_shared.glsl b/webrender/res/prim_shared.glsl index 79ab8e4a3f..281de1c7a7 100644 --- a/webrender/res/prim_shared.glsl +++ b/webrender/res/prim_shared.glsl @@ -75,7 +75,6 @@ vec4[2] fetch_from_resource_cache_2(int address) { #define VECS_PER_PRIM_HEADER 2 #define VECS_PER_TEXT_RUN 3 #define VECS_PER_GRADIENT 3 -#define VECS_PER_RADIAL_GRADIENT 2 #define VECS_PER_GRADIENT_STOP 2 uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes; diff --git a/webrender/src/batch.rs b/webrender/src/batch.rs index 0b28411d97..ddb939477b 100644 --- a/webrender/src/batch.rs +++ b/webrender/src/batch.rs @@ -40,7 +40,6 @@ pub enum TransformBatchKind { Image(ImageBufferKind), AlignedGradient, AngleGradient, - RadialGradient, BorderCorner, BorderEdge, } @@ -78,6 +77,7 @@ pub enum BrushBatchKind { backdrop_id: RenderTaskId, }, YuvImage(ImageBufferKind, YuvFormat, YuvColorSpace), + RadialGradient, } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -1228,15 +1228,6 @@ impl AlphaBatchBuilder { let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect); batch.push(base_instance.build(0, 0, 0)); } - PrimitiveKind::RadialGradient => { - let kind = BatchKind::Transformable( - transform_kind, - TransformBatchKind::RadialGradient, - ); - let key = BatchKey::new(kind, non_segmented_blend_mode, no_textures); - let batch = self.batch_list.get_suitable_batch(key, &task_relative_bounding_rect); - batch.push(base_instance.build(0, 0, 0)); - } } } @@ -1385,6 +1376,17 @@ impl BrushPrimitive { [0; 3], )) } + BrushKind::RadialGradient { ref stops_handle, .. } => { + Some(( + BrushBatchKind::RadialGradient, + BatchTextures::no_texture(), + [ + stops_handle.as_int(gpu_cache), + 0, + 0, + ], + )) + } BrushKind::YuvImage { format, yuv_key, image_rendering, color_space } => { let mut textures = BatchTextures::no_texture(); let mut uv_rect_addresses = [0; 3]; @@ -1464,7 +1466,6 @@ impl AlphaBatchHelpers for PrimitiveStore { PrimitiveKind::Border | PrimitiveKind::AlignedGradient | PrimitiveKind::AngleGradient | - PrimitiveKind::RadialGradient | PrimitiveKind::Picture => { BlendMode::PremultipliedAlpha } @@ -1485,6 +1486,7 @@ impl AlphaBatchHelpers for PrimitiveStore { BrushKind::Mask { .. } | BrushKind::Line { .. } | BrushKind::YuvImage { .. } | + BrushKind::RadialGradient { .. } | BrushKind::Picture => { BlendMode::PremultipliedAlpha } diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index a72fbb85c0..b856b74100 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -19,7 +19,7 @@ use clip_scroll_tree::{ClipScrollTree, ClipChainIndex}; use euclid::{SideOffsets2D, vec2}; use frame::{FrameId, ClipIdToIndexMapper}; use glyph_rasterizer::FontInstance; -use gpu_cache::GpuCache; +use gpu_cache::{GpuCache, GpuCacheHandle}; use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType}; use hit_test::{HitTester, HitTestingItem, HitTestingRun}; use internal_types::{FastHashMap, FastHashSet}; @@ -27,7 +27,7 @@ use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, GradientPrimitiveCpu}; use prim_store::{ImageCacheKey, ImagePrimitiveCpu, ImageSource, PrimitiveContainer}; use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore}; -use prim_store::{RadialGradientPrimitiveCpu, ScrollNodeAndClipChain, TextRunPrimitiveCpu}; +use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu}; use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters}; use render_task::{ClearMode, RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree}; use resource_cache::{ImageRequest, ResourceCache}; @@ -1318,30 +1318,25 @@ impl FrameBuilder { stops: ItemRange, extend_mode: ExtendMode, ) { - let radial_gradient_cpu = RadialGradientPrimitiveCpu { - stops_range: stops, - extend_mode, - gpu_blocks: [ - [ - start_center.x, - start_center.y, - end_center.x, - end_center.y, - ].into(), - [ - start_radius, - end_radius, - ratio_xy, - pack_as_float(extend_mode as u32), - ].into(), - ], - }; + let prim = BrushPrimitive::new( + BrushKind::RadialGradient { + stops_range: stops, + extend_mode, + stops_handle: GpuCacheHandle::new(), + start_center, + end_center, + start_radius, + end_radius, + ratio_xy, + }, + None, + ); self.add_primitive( clip_and_scroll, info, Vec::new(), - PrimitiveContainer::RadialGradient(radial_gradient_cpu), + PrimitiveContainer::Brush(prim), ); } diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index c153e5bd5a..263b079d41 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -126,7 +126,6 @@ pub enum PrimitiveKind { Border, AlignedGradient, AngleGradient, - RadialGradient, Picture, Brush, } @@ -210,6 +209,16 @@ pub enum BrushKind { format: YuvFormat, color_space: YuvColorSpace, image_rendering: ImageRendering, + }, + RadialGradient { + stops_range: ItemRange, + extend_mode: ExtendMode, + stops_handle: GpuCacheHandle, + start_center: LayerPoint, + end_center: LayerPoint, + start_radius: f32, + end_radius: f32, + ratio_xy: f32, } } @@ -219,7 +228,8 @@ impl BrushKind { BrushKind::Solid { .. } | BrushKind::Picture | BrushKind::Image { .. } | - BrushKind::YuvImage { .. } => true, + BrushKind::YuvImage { .. } | + BrushKind::RadialGradient { .. } => true, BrushKind::Mask { .. } | BrushKind::Clear | @@ -349,6 +359,20 @@ impl BrushPrimitive { 0.0, ]); } + BrushKind::RadialGradient { start_center, end_center, start_radius, end_radius, ratio_xy, extend_mode, .. } => { + request.push([ + start_center.x, + start_center.y, + end_center.x, + end_center.y, + ]); + request.push([ + start_radius, + end_radius, + ratio_xy, + pack_as_float(extend_mode as u32), + ]); + } } } } @@ -631,26 +655,6 @@ impl<'a> GradientGpuBlockBuilder<'a> { } } -#[derive(Debug)] -pub struct RadialGradientPrimitiveCpu { - pub stops_range: ItemRange, - pub extend_mode: ExtendMode, - pub gpu_blocks: [GpuBlockData; 2], -} - -impl RadialGradientPrimitiveCpu { - fn build_gpu_blocks_for_angle_radial( - &self, - display_list: &BuiltDisplayList, - mut request: GpuDataRequest, - ) { - request.extend_from_slice(&self.gpu_blocks); - - let gradient_builder = GradientGpuBlockBuilder::new(self.stops_range, display_list); - gradient_builder.build(false, &mut request); - } -} - #[derive(Debug, Clone)] pub struct TextRunPrimitiveCpu { pub font: FontInstance, @@ -935,7 +939,6 @@ pub enum PrimitiveContainer { Border(BorderPrimitiveCpu), AlignedGradient(GradientPrimitiveCpu), AngleGradient(GradientPrimitiveCpu), - RadialGradient(RadialGradientPrimitiveCpu), Picture(PicturePrimitive), Brush(BrushPrimitive), } @@ -947,7 +950,6 @@ pub struct PrimitiveStore { pub cpu_pictures: Vec, pub cpu_images: Vec, pub cpu_gradients: Vec, - pub cpu_radial_gradients: Vec, pub cpu_metadata: Vec, pub cpu_borders: Vec, } @@ -961,7 +963,6 @@ impl PrimitiveStore { cpu_pictures: Vec::new(), cpu_images: Vec::new(), cpu_gradients: Vec::new(), - cpu_radial_gradients: Vec::new(), cpu_borders: Vec::new(), } } @@ -974,7 +975,6 @@ impl PrimitiveStore { cpu_pictures: recycle_vec(self.cpu_pictures), cpu_images: recycle_vec(self.cpu_images), cpu_gradients: recycle_vec(self.cpu_gradients), - cpu_radial_gradients: recycle_vec(self.cpu_radial_gradients), cpu_borders: recycle_vec(self.cpu_borders), } } @@ -1014,6 +1014,7 @@ impl PrimitiveStore { BrushKind::Line { .. } => PrimitiveOpacity::translucent(), BrushKind::Image { .. } => PrimitiveOpacity::translucent(), BrushKind::YuvImage { .. } => PrimitiveOpacity::opaque(), + BrushKind::RadialGradient { .. } => PrimitiveOpacity::translucent(), BrushKind::Picture => { // TODO(gw): This is not currently used. In the future // we should detect opaque pictures. @@ -1099,18 +1100,6 @@ impl PrimitiveStore { self.cpu_gradients.push(gradient_cpu); metadata } - PrimitiveContainer::RadialGradient(radial_gradient_cpu) => { - let metadata = PrimitiveMetadata { - // TODO: calculate if the gradient is actually opaque - opacity: PrimitiveOpacity::translucent(), - prim_kind: PrimitiveKind::RadialGradient, - cpu_prim_index: SpecificPrimitiveIndex(self.cpu_radial_gradients.len()), - ..base_metadata - }; - - self.cpu_radial_gradients.push(radial_gradient_cpu); - metadata - } }; self.cpu_metadata.push(metadata); @@ -1315,6 +1304,18 @@ impl PrimitiveStore { ); } } + BrushKind::RadialGradient { ref mut stops_handle, stops_range, .. } => { + if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) { + let gradient_builder = GradientGpuBlockBuilder::new( + stops_range, + pic_context.display_list, + ); + gradient_builder.build( + false, + &mut request, + ); + } + } BrushKind::Mask { .. } | BrushKind::Solid { .. } | BrushKind::Clear | @@ -1323,8 +1324,7 @@ impl PrimitiveStore { } } PrimitiveKind::AlignedGradient | - PrimitiveKind::AngleGradient | - PrimitiveKind::RadialGradient => {} + PrimitiveKind::AngleGradient => {} } // Mark this GPU resource as required for this frame. @@ -1356,13 +1356,6 @@ impl PrimitiveStore { request, ); } - PrimitiveKind::RadialGradient => { - let gradient = &self.cpu_radial_gradients[metadata.cpu_prim_index.0]; - gradient.build_gpu_blocks_for_angle_radial( - pic_context.display_list, - request, - ); - } PrimitiveKind::TextRun => { let text = &self.cpu_text_runs[metadata.cpu_prim_index.0]; text.write_gpu_blocks(&mut request); diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index 52c267aafe..16078ecf95 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -83,8 +83,12 @@ const GPU_CACHE_RESIZE_TEST: bool = false; /// Number of GPU blocks per UV rectangle provided for an image. pub const BLOCKS_PER_UV_RECT: usize = 2; +const GPU_TAG_BRUSH_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag { + label: "B_RadialGradient", + color: debug_colors::LIGHTPINK, +}; const GPU_TAG_BRUSH_YUV_IMAGE: GpuProfileTag = GpuProfileTag { - label: "YuvImage", + label: "B_YuvImage", color: debug_colors::DARKGREEN, }; const GPU_TAG_BRUSH_MIXBLEND: GpuProfileTag = GpuProfileTag { @@ -155,10 +159,6 @@ const GPU_TAG_PRIM_ANGLE_GRADIENT: GpuProfileTag = GpuProfileTag { label: "AngleGradient", color: debug_colors::POWDERBLUE, }; -const GPU_TAG_PRIM_RADIAL_GRADIENT: GpuProfileTag = GpuProfileTag { - label: "RadialGradient", - color: debug_colors::LIGHTPINK, -}; const GPU_TAG_PRIM_BORDER_CORNER: GpuProfileTag = GpuProfileTag { label: "BorderCorner", color: debug_colors::DARKSLATEGREY, @@ -202,7 +202,6 @@ impl TransformBatchKind { }, TransformBatchKind::AlignedGradient => "AlignedGradient", TransformBatchKind::AngleGradient => "AngleGradient", - TransformBatchKind::RadialGradient => "RadialGradient", TransformBatchKind::BorderCorner => "BorderCorner", TransformBatchKind::BorderEdge => "BorderEdge", } @@ -216,7 +215,6 @@ impl TransformBatchKind { TransformBatchKind::BorderEdge => GPU_TAG_PRIM_BORDER_EDGE, TransformBatchKind::AlignedGradient => GPU_TAG_PRIM_GRADIENT, TransformBatchKind::AngleGradient => GPU_TAG_PRIM_ANGLE_GRADIENT, - TransformBatchKind::RadialGradient => GPU_TAG_PRIM_RADIAL_GRADIENT, } } } @@ -236,6 +234,7 @@ impl BatchKind { BrushBatchKind::Blend => "Brush (Blend)", BrushBatchKind::MixBlend { .. } => "Brush (Composite)", BrushBatchKind::YuvImage(..) => "Brush (YuvImage)", + BrushBatchKind::RadialGradient => "Brush (RadialGradient)", } } BatchKind::Transformable(_, batch_kind) => batch_kind.debug_name(), @@ -255,6 +254,7 @@ impl BatchKind { BrushBatchKind::Blend => GPU_TAG_BRUSH_BLEND, BrushBatchKind::MixBlend { .. } => GPU_TAG_BRUSH_MIXBLEND, BrushBatchKind::YuvImage(..) => GPU_TAG_BRUSH_YUV_IMAGE, + BrushBatchKind::RadialGradient => GPU_TAG_BRUSH_RADIAL_GRADIENT, } } BatchKind::Transformable(_, batch_kind) => batch_kind.gpu_sampler_tag(), @@ -1617,6 +1617,7 @@ pub struct Renderer { brush_blend: BrushShader, brush_mix_blend: BrushShader, brush_yuv_image: Vec>, + brush_radial_gradient: BrushShader, /// These are "cache clip shaders". These shaders are used to /// draw clip instances into the cached clip mask. The results @@ -1639,7 +1640,6 @@ pub struct Renderer { ps_border_edge: PrimitiveShader, ps_gradient: PrimitiveShader, ps_angle_gradient: PrimitiveShader, - ps_radial_gradient: PrimitiveShader, ps_hw_composite: LazilyCompiledShader, ps_split_composite: LazilyCompiledShader, @@ -1756,6 +1756,7 @@ impl Renderer { let (payload_tx, payload_rx) = try!{ channel::payload_channel() }; let (result_tx, result_rx) = channel(); let gl_type = gl.get_type(); + let dithering_feature = ["DITHERING"]; let debug_server = DebugServer::new(api_tx.clone()); @@ -1872,6 +1873,17 @@ impl Renderer { options.precache_shaders) }; + let brush_radial_gradient = try!{ + BrushShader::new("brush_radial_gradient", + &mut device, + if options.enable_dithering { + &dithering_feature + } else { + &[] + }, + options.precache_shaders) + }; + let cs_blur_a8 = try!{ LazilyCompiledShader::new(ShaderKind::Cache(VertexArrayKind::Blur), "cs_blur", @@ -2018,8 +2030,6 @@ impl Renderer { options.precache_shaders) }; - let dithering_feature = ["DITHERING"]; - let ps_gradient = try!{ PrimitiveShader::new("ps_gradient", &mut device, @@ -2042,17 +2052,6 @@ impl Renderer { options.precache_shaders) }; - let ps_radial_gradient = try!{ - PrimitiveShader::new("ps_radial_gradient", - &mut device, - if options.enable_dithering { - &dithering_feature - } else { - &[] - }, - options.precache_shaders) - }; - let ps_hw_composite = try!{ LazilyCompiledShader::new(ShaderKind::Primitive, "ps_hardware_composite", @@ -2303,6 +2302,7 @@ impl Renderer { brush_blend, brush_mix_blend, brush_yuv_image, + brush_radial_gradient, cs_clip_rectangle, cs_clip_border, cs_clip_image, @@ -2313,7 +2313,6 @@ impl Renderer { ps_border_edge, ps_gradient, ps_angle_gradient, - ps_radial_gradient, ps_hw_composite, ps_split_composite, debug: debug_renderer, @@ -3264,6 +3263,15 @@ impl Renderer { &mut self.renderer_errors, ); } + BrushBatchKind::RadialGradient => { + self.brush_radial_gradient.bind( + &mut self.device, + key.blend_mode, + projection, + 0, + &mut self.renderer_errors, + ); + } BrushBatchKind::YuvImage(image_buffer_kind, format, color_space) => { let shader_index = Renderer::get_yuv_shader_index(image_buffer_kind, format, color_space); @@ -3332,15 +3340,6 @@ impl Renderer { &mut self.renderer_errors, ); } - TransformBatchKind::RadialGradient => { - self.ps_radial_gradient.bind( - &mut self.device, - transform_kind, - projection, - 0, - &mut self.renderer_errors, - ); - } }, }; @@ -4741,6 +4740,7 @@ impl Renderer { self.brush_line.deinit(&mut self.device); self.brush_blend.deinit(&mut self.device); self.brush_mix_blend.deinit(&mut self.device); + self.brush_radial_gradient.deinit(&mut self.device); self.cs_clip_rectangle.deinit(&mut self.device); self.cs_clip_image.deinit(&mut self.device); self.cs_clip_border.deinit(&mut self.device); @@ -4768,7 +4768,6 @@ impl Renderer { self.ps_border_edge.deinit(&mut self.device); self.ps_gradient.deinit(&mut self.device); self.ps_angle_gradient.deinit(&mut self.device); - self.ps_radial_gradient.deinit(&mut self.device); self.ps_hw_composite.deinit(&mut self.device); self.ps_split_composite.deinit(&mut self.device); #[cfg(feature = "capture")] diff --git a/webrender/src/tiling.rs b/webrender/src/tiling.rs index cb5fca3564..e538f3311a 100644 --- a/webrender/src/tiling.rs +++ b/webrender/src/tiling.rs @@ -598,6 +598,7 @@ impl RenderTarget for AlphaRenderTarget { BrushKind::Picture | BrushKind::Line { .. } | BrushKind::YuvImage { .. } | + BrushKind::RadialGradient { .. } | BrushKind::Image { .. } => { unreachable!("bug: unexpected brush here"); } diff --git a/webrender/tests/angle_shader_validation.rs b/webrender/tests/angle_shader_validation.rs index ab6df086db..00e4e71990 100644 --- a/webrender/tests/angle_shader_validation.rs +++ b/webrender/tests/angle_shader_validation.rs @@ -62,10 +62,6 @@ const SHADERS: &[Shader] = &[ name: "ps_angle_gradient", features: PRIM_FEATURES, }, - Shader { - name: "ps_radial_gradient", - features: PRIM_FEATURES, - }, Shader { name: "ps_hardware_composite", features: PRIM_FEATURES, @@ -111,6 +107,10 @@ const SHADERS: &[Shader] = &[ name: "brush_line", features: &[], }, + Shader { + name: "brush_radial_gradient", + features: &[], + }, ]; const VERSION_STRING: &str = "#version 300 es\n"; diff --git a/wrench/reftests/transforms/prim-suite.png b/wrench/reftests/transforms/prim-suite.png index 9e64685ab9..669aa0b45a 100644 Binary files a/wrench/reftests/transforms/prim-suite.png and b/wrench/reftests/transforms/prim-suite.png differ diff --git a/wrench/reftests/transforms/prim-suite.yaml b/wrench/reftests/transforms/prim-suite.yaml index 64c46c0abb..2a170f8fc9 100644 --- a/wrench/reftests/transforms/prim-suite.yaml +++ b/wrench/reftests/transforms/prim-suite.yaml @@ -37,3 +37,9 @@ root: - bounds: [150, 150, 128, 128] image: checkerboard(4, 15, 8) stretch-size: 128 128 + + - type: radial-gradient + bounds: 300 150 100 100 + center: 50 50 + radius: 50 50 + stops: [0, red, 1, blue]