From 0742b33ab012a0a396e680df4e5869a953129b0b Mon Sep 17 00:00:00 2001 From: Bert Peers Date: Thu, 2 Apr 2020 10:00:24 +0000 Subject: [PATCH 1/6] Bug 1624468 - Add a fast path for more gradient types in WR r=gw Differential Revision: https://phabricator.services.mozilla.com/D68945 [ghsync] From https://hg.mozilla.org/mozilla-central/rev/3c84f9fd1f938602e66405605835c4e2a00e9ce9 --- webrender/src/batch.rs | 98 ++++++----- webrender/src/prim_store/gradient.rs | 22 +-- webrender/src/prim_store/mod.rs | 152 ++++++++++++++---- .../gradient/gradient_cache_5stops.yaml | 13 ++ .../gradient/gradient_cache_5stops_ref.yaml | 18 +++ .../gradient_cache_5stops_vertical.yaml | 13 ++ .../gradient_cache_5stops_vertical_ref.yaml | 18 +++ .../gradient/gradient_cache_clamp.yaml | 20 +++ .../gradient/gradient_cache_clamp_ref.yaml | 30 ++++ .../gradient/gradient_cache_hardstop.yaml | 19 +++ .../gradient_cache_hardstop_clip.yaml | 21 +++ .../gradient_cache_hardstop_clip_ref.yaml | 28 ++++ .../gradient/gradient_cache_hardstop_ref.yaml | 24 +++ wrench/reftests/gradient/reftest.list | 11 +- 14 files changed, 399 insertions(+), 88 deletions(-) create mode 100644 wrench/reftests/gradient/gradient_cache_5stops.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_5stops_ref.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_clamp.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_clamp_ref.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_hardstop.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml diff --git a/webrender/src/batch.rs b/webrender/src/batch.rs index cfa766029e..54635b1e45 100644 --- a/webrender/src/batch.rs +++ b/webrender/src/batch.rs @@ -2268,53 +2268,69 @@ impl BatchBuilder { BlendMode::None }; - if let Some(ref cache_handle) = gradient.cache_handle { - let rt_cache_entry = ctx.resource_cache - .get_cached_render_task(cache_handle); - let cache_item = ctx.resource_cache - .get_texture_cache_item(&rt_cache_entry.handle); + if !gradient.cache_segments.is_empty() { - if cache_item.texture_id == TextureSource::Invalid { - return; - } + for segment in &gradient.cache_segments { + let ref cache_handle = segment.handle; + let rt_cache_entry = ctx.resource_cache + .get_cached_render_task(cache_handle); + let cache_item = ctx.resource_cache + .get_texture_cache_item(&rt_cache_entry.handle); - let textures = BatchTextures::color(cache_item.texture_id); - let batch_kind = BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)); - let prim_user_data = ImageBrushData { - color_mode: ShaderColorMode::Image, - alpha_type: AlphaType::PremultipliedAlpha, - raster_space: RasterizationSpace::Local, - opacity: 1.0, - }.encode(); + if cache_item.texture_id == TextureSource::Invalid { + return; + } - let specific_resource_address = cache_item.uv_rect_handle.as_int(gpu_cache); - prim_header.specific_prim_address = gpu_cache.get_address(&ctx.globals.default_image_handle); + let textures = BatchTextures::color(cache_item.texture_id); + let batch_kind = BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)); + let prim_user_data = ImageBrushData { + color_mode: ShaderColorMode::Image, + alpha_type: AlphaType::PremultipliedAlpha, + raster_space: RasterizationSpace::Local, + opacity: 1.0, + }.encode(); + + let specific_resource_address = cache_item.uv_rect_handle.as_int(gpu_cache); + prim_header.specific_prim_address = gpu_cache.get_address(&ctx.globals.default_image_handle); + + let segment_local_clip_rect = prim_header.local_clip_rect.intersection(&segment.local_rect); + if segment_local_clip_rect.is_none() { + continue; + } - let prim_header_index = prim_headers.push( - &prim_header, - z_id, - prim_user_data, - ); + let segment_prim_header = PrimitiveHeader { + local_rect: segment.local_rect, + local_clip_rect: segment_local_clip_rect.unwrap(), + specific_prim_address: prim_header.specific_prim_address, + transform_id: prim_header.transform_id, + }; - let batch_key = BatchKey { - blend_mode: non_segmented_blend_mode, - kind: BatchKind::Brush(batch_kind), - textures, - }; + let prim_header_index = prim_headers.push( + &segment_prim_header, + z_id, + prim_user_data, + ); - self.add_brush_instance_to_batches( - batch_key, - batch_features, - bounding_rect, - z_id, - INVALID_SEGMENT_INDEX, - EdgeAaSegmentMask::all(), - clip_task_address.unwrap(), - BrushFlags::PERSPECTIVE_INTERPOLATION, - prim_header_index, - specific_resource_address, - prim_vis_mask, - ); + let batch_key = BatchKey { + blend_mode: non_segmented_blend_mode, + kind: BatchKind::Brush(batch_kind), + textures, + }; + + self.add_brush_instance_to_batches( + batch_key, + batch_features, + bounding_rect, + z_id, + INVALID_SEGMENT_INDEX, + EdgeAaSegmentMask::all(), + clip_task_address.unwrap(), + BrushFlags::PERSPECTIVE_INTERPOLATION, + prim_header_index, + specific_resource_address, + prim_vis_mask, + ); + } } else if gradient.visible_tiles_range.is_empty() { let batch_params = BrushBatchParameters::shared( BrushBatchKind::LinearGradient, diff --git a/webrender/src/prim_store/gradient.rs b/webrender/src/prim_store/gradient.rs index b8d59c8030..9e2c27be55 100644 --- a/webrender/src/prim_store/gradient.rs +++ b/webrender/src/prim_store/gradient.rs @@ -13,11 +13,10 @@ use crate::frame_builder::FrameBuildingState; use crate::gpu_cache::{GpuCacheHandle, GpuDataRequest}; use crate::intern::{Internable, InternDebug, Handle as InternHandle}; use crate::internal_types::LayoutPrimitiveInfo; -use crate::prim_store::{BrushSegment, GradientTileRange, VectorKey}; +use crate::prim_store::{BrushSegment, CachedGradientSegment, GradientTileRange, VectorKey}; use crate::prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData}; use crate::prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore}; use crate::prim_store::{NinePatchDescriptor, PointKey, SizeKey, InternablePrimitive}; -use crate::render_task_cache::RenderTaskCacheEntryHandle; use std::{hash, ops::{Deref, DerefMut}}; use crate::util::pack_as_float; @@ -152,7 +151,7 @@ impl From for LinearGradientTemplate { // gradient in a smaller task, and drawing as an image. // TODO(gw): Aim to reduce the constraints on fast path gradients in future, // although this catches the vast majority of gradients on real pages. - let mut supports_caching = + let supports_caching = // No repeating support in fast path item.extend_mode == ExtendMode::Clamp && // Gradient must cover entire primitive @@ -161,28 +160,15 @@ impl From for LinearGradientTemplate { // Must be a vertical or horizontal gradient (item.start_point.x.approx_eq(&item.end_point.x) || item.start_point.y.approx_eq(&item.end_point.y)) && - // Fast path supports a limited number of stops - item.stops.len() <= GRADIENT_FP_STOPS && // Fast path not supported on segmented (border-image) gradients. item.nine_patch.is_none(); - let mut prev_offset = None; // Convert the stops to more convenient representation // for the current gradient builder. let stops: Vec = item.stops.iter().map(|stop| { let color: ColorF = stop.color.into(); min_alpha = min_alpha.min(color.a); - // The fast path doesn't support hard color stops, yet. - // Since the length of the gradient is a fixed size (512 device pixels), if there - // is a hard stop you will see bilinear interpolation with this method, instead - // of an abrupt color change. - if prev_offset == Some(stop.offset) { - supports_caching = false; - } - - prev_offset = Some(stop.offset); - GradientStop { offset: stop.offset, color, @@ -318,7 +304,7 @@ impl InternablePrimitive for LinearGradient { _reference_frame_relative_offset: LayoutVector2D, ) -> PrimitiveInstanceKind { let gradient_index = prim_store.linear_gradients.push(LinearGradientPrimitive { - cache_handle: None, + cache_segments: Vec::new(), visible_tiles_range: GradientTileRange::empty(), }); @@ -338,7 +324,7 @@ impl IsVisible for LinearGradient { #[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] pub struct LinearGradientPrimitive { - pub cache_handle: Option, + pub cache_segments: Vec, pub visible_tiles_range: GradientTileRange, } diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index c9c16df149..82d17aa441 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -970,6 +970,13 @@ pub struct VisibleGradientTile { pub local_clip_rect: LayoutRect, } +#[derive(Debug)] +#[cfg_attr(feature = "capture", derive(Serialize))] +pub struct CachedGradientSegment { + pub handle: RenderTaskCacheEntryHandle, + pub local_rect: LayoutRect, +} + /// Information about how to cache a border segment, /// along with the current render task cache entry. #[cfg_attr(feature = "capture", derive(Serialize))] @@ -3284,7 +3291,7 @@ impl PrimitiveStore { }; // Build the cache key, including information about the stops. - let mut stops = [GradientStopKey::empty(); GRADIENT_FP_STOPS]; + let mut stops = vec![GradientStopKey::empty(); prim_data.stops.len()]; // Reverse the stops as required, same as the gradient builder does // for the slow path. @@ -3302,35 +3309,124 @@ impl PrimitiveStore { } } - let cache_key = GradientCacheKey { - orientation, - start_stop_point: VectorKey { - x: start_point, - y: end_point, - }, - stops, - }; + // To support clamping, we need to make sure that quads are emitted for the + // segments before and after the 0.0...1.0 range of offsets. The loop below + // can handle that by duplicating the first and last point if necessary: + if start_point < 0.0 { + stops.insert(0, GradientStopKey { + offset: start_point, + color : stops[0].color + }); + } - // Request the render task each frame. - gradient.cache_handle = Some(frame_state.resource_cache.request_render_task( - RenderTaskCacheKey { - size, - kind: RenderTaskCacheKeyKind::Gradient(cache_key), - }, - frame_state.gpu_cache, - frame_state.render_tasks, - None, - prim_data.stops_opacity.is_opaque, - |render_tasks| { - render_tasks.add().init(RenderTask::new_gradient( - size, - stops, - orientation, - start_point, - end_point, - )) + if end_point > 1.0 { + stops.push( GradientStopKey { + offset: end_point, + color : stops[stops.len()-1].color + }); + } + + gradient.cache_segments.clear(); + + let mut first_stop = 0; + // look for an inclusive range of stops [first_stop, last_stop]. + // once first_stop points at (or past) the last stop, we're done. + while first_stop < stops.len()-1 { + + // if the entire segment starts at an offset that's past the primitive's + // end_point, we're done. + if stops[first_stop].offset > end_point { + break; } - )); + + // accumulate stops until we have GRADIENT_FP_STOPS of them, or we hit + // a hard stop: + let mut last_stop = first_stop; + let mut hard_stop = false; // did we stop on a hard stop? + while last_stop < stops.len()-1 && + last_stop - first_stop + 1 < GRADIENT_FP_STOPS + { + if stops[last_stop+1].offset == stops[last_stop].offset { + hard_stop = true; + break; + } + + last_stop = last_stop + 1; + } + + let num_stops = last_stop - first_stop + 1; + + // repeated hard stops at the same offset, skip + if num_stops == 0 { + first_stop = last_stop + 1; + continue; + } + + // if the last stop offset is before start_point, the segment's not visible: + if stops[last_stop].offset < start_point { + first_stop = if hard_stop { last_stop+1 } else { last_stop }; + continue; + } + + let segment_start_point = start_point.max(stops[first_stop].offset); + let segment_end_point = end_point .min(stops[last_stop ].offset); + + let mut segment_stops = [GradientStopKey::empty(); GRADIENT_FP_STOPS]; + for i in 0..num_stops { + segment_stops[i] = stops[first_stop + i]; + } + + let cache_key = GradientCacheKey { + orientation, + start_stop_point: VectorKey { + x: segment_start_point, + y: segment_end_point, + }, + stops: segment_stops, + }; + + let mut prim_origin = prim_instance.prim_origin; + let mut prim_size = prim_data.common.prim_size; + + let inv_length = 1.0 / ( end_point - start_point ); + if orientation == LineOrientation::Horizontal { + prim_origin.x += ( segment_start_point - start_point ) * inv_length * prim_size.width; + prim_size.width *= ( segment_end_point - segment_start_point ) * inv_length; + } else { + prim_origin.y += ( segment_start_point - start_point ) * inv_length * prim_size.height; + prim_size.height *= ( segment_end_point - segment_start_point ) * inv_length; + } + + let local_rect = LayoutRect::new( prim_origin, prim_size ); + + // Request the render task each frame. + gradient.cache_segments.push( + CachedGradientSegment { + handle: frame_state.resource_cache.request_render_task( + RenderTaskCacheKey { + size, + kind: RenderTaskCacheKeyKind::Gradient(cache_key), + }, + frame_state.gpu_cache, + frame_state.render_tasks, + None, + prim_data.stops_opacity.is_opaque, + |render_tasks| { + render_tasks.add().init(RenderTask::new_gradient( + size, + segment_stops, + orientation, + segment_start_point, + segment_end_point, + )) + }), + local_rect: local_rect, + } + ); + + // if ending on a hardstop, skip past it for the start of the next run: + first_stop = if hard_stop { last_stop + 1 } else { last_stop }; + } } if prim_data.tile_spacing != LayoutSize::zero() { diff --git a/wrench/reftests/gradient/gradient_cache_5stops.yaml b/wrench/reftests/gradient/gradient_cache_5stops.yaml new file mode 100644 index 0000000000..d448723002 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_5stops.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 540 + start: 0 0 + end: 960 0 + stops: [0.0, red, + 0.25, green, + 0.5, blue, + 0.75, [40,40,40,1], + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml b/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml new file mode 100644 index 0000000000..34b6b0e01c --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, red, + 0.5, green, + 1.0, blue] + - type: gradient + bounds: 480 0 480 540 + start: 0 0 + end: 480 0 + stops: [ 0.0, blue, + 0.5, [40,40,40,1], + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml b/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml new file mode 100644 index 0000000000..dd2c8b7c9d --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 540 + start: 0 0 + end: 0 540 + stops: [0.0, red, + 0.25, green, + 0.5, blue, + 0.75, [40,40,40,1], + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml b/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml new file mode 100644 index 0000000000..704b5be2f6 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 270 + start: 0 0 + end: 0 270 + stops: [0.0, red, + 0.5, green, + 1.0, blue] + - type: gradient + bounds: 0 270 960 270 + start: 0 0 + end: 0 270 + stops: [ 0.0, blue, + 0.5, [40,40,40,1], + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_clamp.yaml b/wrench/reftests/gradient/gradient_cache_clamp.yaml new file mode 100644 index 0000000000..1c55a269a1 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_clamp.yaml @@ -0,0 +1,20 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 400 200 + start: 0 100 + end: 100 100 + stops: [0.0, blue, 1.0, blue, 1.0, red] + - type: gradient + bounds: 0 300 400 200 + start: 100 100 + end: 200 100 + stops: [0.0, blue, 1.0, blue, 1.0, red] + - type: gradient + bounds: 0 600 200 400 + start: 0 100 + end: 0 300 + stops: [ + 0.0, blue, + 1.0, red] diff --git a/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml b/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml new file mode 100644 index 0000000000..4631192cd8 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml @@ -0,0 +1,30 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 400 200 + start: 0 100 + end: 400 100 + stops: [ + 0.0, blue, + 0.25, blue, + 0.25, red, + 1.0, red] + - type: gradient + bounds: 0 300 400 200 + start: 0 100 + end: 400 100 + stops: [ + 0.0, blue, + 0.5, blue, + 0.5, red, + 1.0, red] + - type: gradient + bounds: 0 600 200 400 + start: 0 0 + end: 0 400 + stops: [ + 0.0, blue, + 0.25, blue, + 0.75, red, + 1.0, red] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop.yaml b/wrench/reftests/gradient/gradient_cache_hardstop.yaml new file mode 100644 index 0000000000..53c908fb22 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_hardstop.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 540 + start: 0 0 + end: 960 0 + stops: [0.0, red, + 0.125, yellow, + 0.25, red, + 0.25, green, + 0.375, yellow, + 0.5, green, + 0.5, blue, + 0.625, yellow, + 0.75, blue, + 0.75, white, + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml new file mode 100644 index 0000000000..3e7a2e946f --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 540 + start: 0 0 + end: 960 0 + stops: [0.0, red, + 0.125, yellow, + 0.25, red, + 0.25, green, + 0.375, yellow, + 0.5, green, + 0.5, blue, + 0.625, yellow, + 0.75, blue, + 0.75, white, + 1.0, [100,200,50,1]] + complex-clip: + rect: [100, 100, 760, 340] + radius: [32, 32] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml new file mode 100644 index 0000000000..2b27c5649c --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml @@ -0,0 +1,28 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, red, + 0.25, yellow, + 0.5, red, + 0.5, green, + 0.75, yellow, + 1.0, green] + complex-clip: + rect: [100, 100, 760, 340] + radius: [32, 32] + - type: gradient + bounds: 480 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, blue, + 0.25, yellow, + 0.5, blue, + 0.5, white, + 1.0, [100,200,50,1]] + complex-clip: + rect: [100, 100, 760, 340] + radius: [32, 32] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml new file mode 100644 index 0000000000..e4b3928046 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, red, + 0.25, yellow, + 0.5, red, + 0.5, green, + 0.75, yellow, + 1.0, green] + - type: gradient + bounds: 480 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, blue, + 0.25, yellow, + 0.5, blue, + 0.5, white, + 1.0, [100,200,50,1]] + + diff --git a/wrench/reftests/gradient/reftest.list b/wrench/reftests/gradient/reftest.list index ac0b6454b4..c3b3eee9cd 100644 --- a/wrench/reftests/gradient/reftest.list +++ b/wrench/reftests/gradient/reftest.list @@ -16,7 +16,7 @@ platform(linux,mac) fuzzy(1,35000) == linear-stops.yaml linear-stops-ref.png == linear-clamp-1b.yaml linear-clamp-1-ref.yaml == linear-clamp-2.yaml linear-clamp-2-ref.yaml -== linear-hard-stop.yaml linear-hard-stop-ref.png +fuzzy-range(<=1,*4800) == linear-hard-stop.yaml linear-hard-stop-ref.png # dithering requires us to fuzz here fuzzy(1,20000) == linear.yaml linear-ref.yaml @@ -85,3 +85,12 @@ fuzzy(255,166) == conic-angle.yaml conic-angle.png fuzzy(1,1) == conic-angle-wraparound.yaml conic-angle.yaml fuzzy(1,1) == conic-angle-wraparound-negative.yaml conic-angle.yaml fuzzy(1,115) == conic-color-wheel.yaml conic-color-wheel.png + +# gradient caching tests +# replaces a computed gradient by a sampled texture, so a lot of off-by-one +# variation from interpolation, which is fine: +fuzzy-range(<=1,*195000) == gradient_cache_5stops.yaml gradient_cache_5stops_ref.yaml +fuzzy-range(<=1,*169000) == gradient_cache_5stops_vertical.yaml gradient_cache_5stops_vertical_ref.yaml +== gradient_cache_hardstop.yaml gradient_cache_hardstop_ref.yaml +== gradient_cache_hardstop_clip.yaml gradient_cache_hardstop_clip_ref.yaml +== gradient_cache_clamp.yaml gradient_cache_clamp_ref.yaml From 0730de897f0890ebe77610ceac90e0496cf70d8a Mon Sep 17 00:00:00 2001 From: Miko Mynttinen Date: Thu, 2 Apr 2020 10:00:34 +0000 Subject: [PATCH 2/6] Bug 1624016 - Memory report WebRender display list and display item cache r=jrmuizel Differential Revision: https://phabricator.services.mozilla.com/D68279 [ghsync] From https://hg.mozilla.org/mozilla-central/rev/dab7338c2064edf54f3f4112772b8f44e9a2e25e --- webrender/src/scene.rs | 12 ++++++++++++ webrender/src/scene_builder_thread.rs | 1 + webrender_api/src/api.rs | 1 + webrender_api/src/display_item_cache.rs | 11 +++++++++-- webrender_api/src/display_list.rs | 7 +++++++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/webrender/src/scene.rs b/webrender/src/scene.rs index 0f468b494f..7498f9dae5 100644 --- a/webrender/src/scene.rs +++ b/webrender/src/scene.rs @@ -4,7 +4,9 @@ use api::{BuiltDisplayList, DisplayListWithCache, ColorF, DynamicProperties, Epoch, FontRenderMode}; use api::{PipelineId, PropertyBinding, PropertyBindingId, PropertyValue, MixBlendMode, StackingContext}; +use api::MemoryReport; use api::units::*; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use crate::composite::CompositorKind; use crate::clip::{ClipStore, ClipDataStore}; use crate::spatial_tree::{SpatialTree, SpatialNodeIndex}; @@ -236,6 +238,16 @@ impl Scene { false } + + pub fn report_memory( + &self, + ops: &mut MallocSizeOfOps, + report: &mut MemoryReport + ) { + for (_, pipeline) in &self.pipelines { + report.display_list += pipeline.display_list.size_of(ops) + } + } } pub trait StackingContextHelpers { diff --git a/webrender/src/scene_builder_thread.rs b/webrender/src/scene_builder_thread.rs index 4827c5a6a3..c9de7740cc 100644 --- a/webrender/src/scene_builder_thread.rs +++ b/webrender/src/scene_builder_thread.rs @@ -694,6 +694,7 @@ impl SceneBuilderThread { let mut report = MemoryReport::default(); for doc in self.documents.values() { doc.interners.report_memory(ops, &mut report); + doc.scene.report_memory(ops, &mut report); } report diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index ad57931a73..e322e947c7 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -1242,6 +1242,7 @@ pub struct MemoryReport { pub rasterized_blobs: usize, pub shader_cache: usize, pub interning: InterningMemoryReport, + pub display_list: usize, // // GPU memory. diff --git a/webrender_api/src/display_item_cache.rs b/webrender_api/src/display_item_cache.rs index 3f85f0c68f..169e54797a 100644 --- a/webrender_api/src/display_item_cache.rs +++ b/webrender_api/src/display_item_cache.rs @@ -4,6 +4,7 @@ use crate::display_item::*; use crate::display_list::*; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub struct CachedDisplayItem { @@ -21,6 +22,12 @@ impl CachedDisplayItem { } } +impl MallocSizeOf for CachedDisplayItem { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.data.size_of(ops) + } +} + impl From> for CachedDisplayItem { fn from(item_ref: DisplayItemRef) -> Self { let item = item_ref.item(); @@ -38,13 +45,13 @@ impl From> for CachedDisplayItem { } } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] struct CacheEntry { items: Vec, occupied: bool, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Deserialize, MallocSizeOf, Serialize)] pub struct DisplayItemCache { entries: Vec, } diff --git a/webrender_api/src/display_list.rs b/webrender_api/src/display_list.rs index 5e463b6884..7c8235d365 100644 --- a/webrender_api/src/display_list.rs +++ b/webrender_api/src/display_list.rs @@ -16,6 +16,7 @@ use std::ops::Range; use std::mem; use std::collections::HashMap; use time::precise_time_ns; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; // local imports use crate::display_item as di; use crate::display_item_cache::*; @@ -172,6 +173,12 @@ impl DisplayListWithCache { } } +impl MallocSizeOf for DisplayListWithCache { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.display_list.data.size_of(ops) + self.cache.size_of(ops) + } +} + #[cfg(feature = "serialize")] impl Serialize for DisplayListWithCache { fn serialize( From 0e6baec393bc5a663d2c74e5e39b0001c7a2eb47 Mon Sep 17 00:00:00 2001 From: Ciure Andrei Date: Thu, 2 Apr 2020 10:00:43 +0000 Subject: [PATCH 3/6] Backed out changeset 3c84f9fd1f93 (bug 1624468) for causing css-gradients reftest failures CLOSED TREE [ghsync] From https://hg.mozilla.org/mozilla-central/rev/4d16948c70a718218e6d877768eec27b5e75568d --- webrender/src/batch.rs | 98 +++++------ webrender/src/prim_store/gradient.rs | 22 ++- webrender/src/prim_store/mod.rs | 152 ++++-------------- .../gradient/gradient_cache_5stops.yaml | 13 -- .../gradient/gradient_cache_5stops_ref.yaml | 18 --- .../gradient_cache_5stops_vertical.yaml | 13 -- .../gradient_cache_5stops_vertical_ref.yaml | 18 --- .../gradient/gradient_cache_clamp.yaml | 20 --- .../gradient/gradient_cache_clamp_ref.yaml | 30 ---- .../gradient/gradient_cache_hardstop.yaml | 19 --- .../gradient_cache_hardstop_clip.yaml | 21 --- .../gradient_cache_hardstop_clip_ref.yaml | 28 ---- .../gradient/gradient_cache_hardstop_ref.yaml | 24 --- wrench/reftests/gradient/reftest.list | 11 +- 14 files changed, 88 insertions(+), 399 deletions(-) delete mode 100644 wrench/reftests/gradient/gradient_cache_5stops.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_5stops_ref.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_clamp.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_clamp_ref.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_hardstop.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml diff --git a/webrender/src/batch.rs b/webrender/src/batch.rs index 54635b1e45..cfa766029e 100644 --- a/webrender/src/batch.rs +++ b/webrender/src/batch.rs @@ -2268,69 +2268,53 @@ impl BatchBuilder { BlendMode::None }; - if !gradient.cache_segments.is_empty() { - - for segment in &gradient.cache_segments { - let ref cache_handle = segment.handle; - let rt_cache_entry = ctx.resource_cache - .get_cached_render_task(cache_handle); - let cache_item = ctx.resource_cache - .get_texture_cache_item(&rt_cache_entry.handle); + if let Some(ref cache_handle) = gradient.cache_handle { + let rt_cache_entry = ctx.resource_cache + .get_cached_render_task(cache_handle); + let cache_item = ctx.resource_cache + .get_texture_cache_item(&rt_cache_entry.handle); - if cache_item.texture_id == TextureSource::Invalid { - return; - } + if cache_item.texture_id == TextureSource::Invalid { + return; + } - let textures = BatchTextures::color(cache_item.texture_id); - let batch_kind = BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)); - let prim_user_data = ImageBrushData { - color_mode: ShaderColorMode::Image, - alpha_type: AlphaType::PremultipliedAlpha, - raster_space: RasterizationSpace::Local, - opacity: 1.0, - }.encode(); - - let specific_resource_address = cache_item.uv_rect_handle.as_int(gpu_cache); - prim_header.specific_prim_address = gpu_cache.get_address(&ctx.globals.default_image_handle); - - let segment_local_clip_rect = prim_header.local_clip_rect.intersection(&segment.local_rect); - if segment_local_clip_rect.is_none() { - continue; - } + let textures = BatchTextures::color(cache_item.texture_id); + let batch_kind = BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)); + let prim_user_data = ImageBrushData { + color_mode: ShaderColorMode::Image, + alpha_type: AlphaType::PremultipliedAlpha, + raster_space: RasterizationSpace::Local, + opacity: 1.0, + }.encode(); - let segment_prim_header = PrimitiveHeader { - local_rect: segment.local_rect, - local_clip_rect: segment_local_clip_rect.unwrap(), - specific_prim_address: prim_header.specific_prim_address, - transform_id: prim_header.transform_id, - }; + let specific_resource_address = cache_item.uv_rect_handle.as_int(gpu_cache); + prim_header.specific_prim_address = gpu_cache.get_address(&ctx.globals.default_image_handle); - let prim_header_index = prim_headers.push( - &segment_prim_header, - z_id, - prim_user_data, - ); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + prim_user_data, + ); - let batch_key = BatchKey { - blend_mode: non_segmented_blend_mode, - kind: BatchKind::Brush(batch_kind), - textures, - }; + let batch_key = BatchKey { + blend_mode: non_segmented_blend_mode, + kind: BatchKind::Brush(batch_kind), + textures, + }; - self.add_brush_instance_to_batches( - batch_key, - batch_features, - bounding_rect, - z_id, - INVALID_SEGMENT_INDEX, - EdgeAaSegmentMask::all(), - clip_task_address.unwrap(), - BrushFlags::PERSPECTIVE_INTERPOLATION, - prim_header_index, - specific_resource_address, - prim_vis_mask, - ); - } + self.add_brush_instance_to_batches( + batch_key, + batch_features, + bounding_rect, + z_id, + INVALID_SEGMENT_INDEX, + EdgeAaSegmentMask::all(), + clip_task_address.unwrap(), + BrushFlags::PERSPECTIVE_INTERPOLATION, + prim_header_index, + specific_resource_address, + prim_vis_mask, + ); } else if gradient.visible_tiles_range.is_empty() { let batch_params = BrushBatchParameters::shared( BrushBatchKind::LinearGradient, diff --git a/webrender/src/prim_store/gradient.rs b/webrender/src/prim_store/gradient.rs index 9e2c27be55..b8d59c8030 100644 --- a/webrender/src/prim_store/gradient.rs +++ b/webrender/src/prim_store/gradient.rs @@ -13,10 +13,11 @@ use crate::frame_builder::FrameBuildingState; use crate::gpu_cache::{GpuCacheHandle, GpuDataRequest}; use crate::intern::{Internable, InternDebug, Handle as InternHandle}; use crate::internal_types::LayoutPrimitiveInfo; -use crate::prim_store::{BrushSegment, CachedGradientSegment, GradientTileRange, VectorKey}; +use crate::prim_store::{BrushSegment, GradientTileRange, VectorKey}; use crate::prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData}; use crate::prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore}; use crate::prim_store::{NinePatchDescriptor, PointKey, SizeKey, InternablePrimitive}; +use crate::render_task_cache::RenderTaskCacheEntryHandle; use std::{hash, ops::{Deref, DerefMut}}; use crate::util::pack_as_float; @@ -151,7 +152,7 @@ impl From for LinearGradientTemplate { // gradient in a smaller task, and drawing as an image. // TODO(gw): Aim to reduce the constraints on fast path gradients in future, // although this catches the vast majority of gradients on real pages. - let supports_caching = + let mut supports_caching = // No repeating support in fast path item.extend_mode == ExtendMode::Clamp && // Gradient must cover entire primitive @@ -160,15 +161,28 @@ impl From for LinearGradientTemplate { // Must be a vertical or horizontal gradient (item.start_point.x.approx_eq(&item.end_point.x) || item.start_point.y.approx_eq(&item.end_point.y)) && + // Fast path supports a limited number of stops + item.stops.len() <= GRADIENT_FP_STOPS && // Fast path not supported on segmented (border-image) gradients. item.nine_patch.is_none(); + let mut prev_offset = None; // Convert the stops to more convenient representation // for the current gradient builder. let stops: Vec = item.stops.iter().map(|stop| { let color: ColorF = stop.color.into(); min_alpha = min_alpha.min(color.a); + // The fast path doesn't support hard color stops, yet. + // Since the length of the gradient is a fixed size (512 device pixels), if there + // is a hard stop you will see bilinear interpolation with this method, instead + // of an abrupt color change. + if prev_offset == Some(stop.offset) { + supports_caching = false; + } + + prev_offset = Some(stop.offset); + GradientStop { offset: stop.offset, color, @@ -304,7 +318,7 @@ impl InternablePrimitive for LinearGradient { _reference_frame_relative_offset: LayoutVector2D, ) -> PrimitiveInstanceKind { let gradient_index = prim_store.linear_gradients.push(LinearGradientPrimitive { - cache_segments: Vec::new(), + cache_handle: None, visible_tiles_range: GradientTileRange::empty(), }); @@ -324,7 +338,7 @@ impl IsVisible for LinearGradient { #[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] pub struct LinearGradientPrimitive { - pub cache_segments: Vec, + pub cache_handle: Option, pub visible_tiles_range: GradientTileRange, } diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index 82d17aa441..c9c16df149 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -970,13 +970,6 @@ pub struct VisibleGradientTile { pub local_clip_rect: LayoutRect, } -#[derive(Debug)] -#[cfg_attr(feature = "capture", derive(Serialize))] -pub struct CachedGradientSegment { - pub handle: RenderTaskCacheEntryHandle, - pub local_rect: LayoutRect, -} - /// Information about how to cache a border segment, /// along with the current render task cache entry. #[cfg_attr(feature = "capture", derive(Serialize))] @@ -3291,7 +3284,7 @@ impl PrimitiveStore { }; // Build the cache key, including information about the stops. - let mut stops = vec![GradientStopKey::empty(); prim_data.stops.len()]; + let mut stops = [GradientStopKey::empty(); GRADIENT_FP_STOPS]; // Reverse the stops as required, same as the gradient builder does // for the slow path. @@ -3309,124 +3302,35 @@ impl PrimitiveStore { } } - // To support clamping, we need to make sure that quads are emitted for the - // segments before and after the 0.0...1.0 range of offsets. The loop below - // can handle that by duplicating the first and last point if necessary: - if start_point < 0.0 { - stops.insert(0, GradientStopKey { - offset: start_point, - color : stops[0].color - }); - } - - if end_point > 1.0 { - stops.push( GradientStopKey { - offset: end_point, - color : stops[stops.len()-1].color - }); - } - - gradient.cache_segments.clear(); - - let mut first_stop = 0; - // look for an inclusive range of stops [first_stop, last_stop]. - // once first_stop points at (or past) the last stop, we're done. - while first_stop < stops.len()-1 { - - // if the entire segment starts at an offset that's past the primitive's - // end_point, we're done. - if stops[first_stop].offset > end_point { - break; - } - - // accumulate stops until we have GRADIENT_FP_STOPS of them, or we hit - // a hard stop: - let mut last_stop = first_stop; - let mut hard_stop = false; // did we stop on a hard stop? - while last_stop < stops.len()-1 && - last_stop - first_stop + 1 < GRADIENT_FP_STOPS - { - if stops[last_stop+1].offset == stops[last_stop].offset { - hard_stop = true; - break; - } - - last_stop = last_stop + 1; - } - - let num_stops = last_stop - first_stop + 1; - - // repeated hard stops at the same offset, skip - if num_stops == 0 { - first_stop = last_stop + 1; - continue; - } - - // if the last stop offset is before start_point, the segment's not visible: - if stops[last_stop].offset < start_point { - first_stop = if hard_stop { last_stop+1 } else { last_stop }; - continue; - } - - let segment_start_point = start_point.max(stops[first_stop].offset); - let segment_end_point = end_point .min(stops[last_stop ].offset); - - let mut segment_stops = [GradientStopKey::empty(); GRADIENT_FP_STOPS]; - for i in 0..num_stops { - segment_stops[i] = stops[first_stop + i]; - } - - let cache_key = GradientCacheKey { - orientation, - start_stop_point: VectorKey { - x: segment_start_point, - y: segment_end_point, - }, - stops: segment_stops, - }; - - let mut prim_origin = prim_instance.prim_origin; - let mut prim_size = prim_data.common.prim_size; + let cache_key = GradientCacheKey { + orientation, + start_stop_point: VectorKey { + x: start_point, + y: end_point, + }, + stops, + }; - let inv_length = 1.0 / ( end_point - start_point ); - if orientation == LineOrientation::Horizontal { - prim_origin.x += ( segment_start_point - start_point ) * inv_length * prim_size.width; - prim_size.width *= ( segment_end_point - segment_start_point ) * inv_length; - } else { - prim_origin.y += ( segment_start_point - start_point ) * inv_length * prim_size.height; - prim_size.height *= ( segment_end_point - segment_start_point ) * inv_length; + // Request the render task each frame. + gradient.cache_handle = Some(frame_state.resource_cache.request_render_task( + RenderTaskCacheKey { + size, + kind: RenderTaskCacheKeyKind::Gradient(cache_key), + }, + frame_state.gpu_cache, + frame_state.render_tasks, + None, + prim_data.stops_opacity.is_opaque, + |render_tasks| { + render_tasks.add().init(RenderTask::new_gradient( + size, + stops, + orientation, + start_point, + end_point, + )) } - - let local_rect = LayoutRect::new( prim_origin, prim_size ); - - // Request the render task each frame. - gradient.cache_segments.push( - CachedGradientSegment { - handle: frame_state.resource_cache.request_render_task( - RenderTaskCacheKey { - size, - kind: RenderTaskCacheKeyKind::Gradient(cache_key), - }, - frame_state.gpu_cache, - frame_state.render_tasks, - None, - prim_data.stops_opacity.is_opaque, - |render_tasks| { - render_tasks.add().init(RenderTask::new_gradient( - size, - segment_stops, - orientation, - segment_start_point, - segment_end_point, - )) - }), - local_rect: local_rect, - } - ); - - // if ending on a hardstop, skip past it for the start of the next run: - first_stop = if hard_stop { last_stop + 1 } else { last_stop }; - } + )); } if prim_data.tile_spacing != LayoutSize::zero() { diff --git a/wrench/reftests/gradient/gradient_cache_5stops.yaml b/wrench/reftests/gradient/gradient_cache_5stops.yaml deleted file mode 100644 index d448723002..0000000000 --- a/wrench/reftests/gradient/gradient_cache_5stops.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 540 - start: 0 0 - end: 960 0 - stops: [0.0, red, - 0.25, green, - 0.5, blue, - 0.75, [40,40,40,1], - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml b/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml deleted file mode 100644 index 34b6b0e01c..0000000000 --- a/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, red, - 0.5, green, - 1.0, blue] - - type: gradient - bounds: 480 0 480 540 - start: 0 0 - end: 480 0 - stops: [ 0.0, blue, - 0.5, [40,40,40,1], - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml b/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml deleted file mode 100644 index dd2c8b7c9d..0000000000 --- a/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 540 - start: 0 0 - end: 0 540 - stops: [0.0, red, - 0.25, green, - 0.5, blue, - 0.75, [40,40,40,1], - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml b/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml deleted file mode 100644 index 704b5be2f6..0000000000 --- a/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 270 - start: 0 0 - end: 0 270 - stops: [0.0, red, - 0.5, green, - 1.0, blue] - - type: gradient - bounds: 0 270 960 270 - start: 0 0 - end: 0 270 - stops: [ 0.0, blue, - 0.5, [40,40,40,1], - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_clamp.yaml b/wrench/reftests/gradient/gradient_cache_clamp.yaml deleted file mode 100644 index 1c55a269a1..0000000000 --- a/wrench/reftests/gradient/gradient_cache_clamp.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 400 200 - start: 0 100 - end: 100 100 - stops: [0.0, blue, 1.0, blue, 1.0, red] - - type: gradient - bounds: 0 300 400 200 - start: 100 100 - end: 200 100 - stops: [0.0, blue, 1.0, blue, 1.0, red] - - type: gradient - bounds: 0 600 200 400 - start: 0 100 - end: 0 300 - stops: [ - 0.0, blue, - 1.0, red] diff --git a/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml b/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml deleted file mode 100644 index 4631192cd8..0000000000 --- a/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml +++ /dev/null @@ -1,30 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 400 200 - start: 0 100 - end: 400 100 - stops: [ - 0.0, blue, - 0.25, blue, - 0.25, red, - 1.0, red] - - type: gradient - bounds: 0 300 400 200 - start: 0 100 - end: 400 100 - stops: [ - 0.0, blue, - 0.5, blue, - 0.5, red, - 1.0, red] - - type: gradient - bounds: 0 600 200 400 - start: 0 0 - end: 0 400 - stops: [ - 0.0, blue, - 0.25, blue, - 0.75, red, - 1.0, red] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop.yaml b/wrench/reftests/gradient/gradient_cache_hardstop.yaml deleted file mode 100644 index 53c908fb22..0000000000 --- a/wrench/reftests/gradient/gradient_cache_hardstop.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 540 - start: 0 0 - end: 960 0 - stops: [0.0, red, - 0.125, yellow, - 0.25, red, - 0.25, green, - 0.375, yellow, - 0.5, green, - 0.5, blue, - 0.625, yellow, - 0.75, blue, - 0.75, white, - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml deleted file mode 100644 index 3e7a2e946f..0000000000 --- a/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 540 - start: 0 0 - end: 960 0 - stops: [0.0, red, - 0.125, yellow, - 0.25, red, - 0.25, green, - 0.375, yellow, - 0.5, green, - 0.5, blue, - 0.625, yellow, - 0.75, blue, - 0.75, white, - 1.0, [100,200,50,1]] - complex-clip: - rect: [100, 100, 760, 340] - radius: [32, 32] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml deleted file mode 100644 index 2b27c5649c..0000000000 --- a/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, red, - 0.25, yellow, - 0.5, red, - 0.5, green, - 0.75, yellow, - 1.0, green] - complex-clip: - rect: [100, 100, 760, 340] - radius: [32, 32] - - type: gradient - bounds: 480 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, blue, - 0.25, yellow, - 0.5, blue, - 0.5, white, - 1.0, [100,200,50,1]] - complex-clip: - rect: [100, 100, 760, 340] - radius: [32, 32] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml deleted file mode 100644 index e4b3928046..0000000000 --- a/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, red, - 0.25, yellow, - 0.5, red, - 0.5, green, - 0.75, yellow, - 1.0, green] - - type: gradient - bounds: 480 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, blue, - 0.25, yellow, - 0.5, blue, - 0.5, white, - 1.0, [100,200,50,1]] - - diff --git a/wrench/reftests/gradient/reftest.list b/wrench/reftests/gradient/reftest.list index c3b3eee9cd..ac0b6454b4 100644 --- a/wrench/reftests/gradient/reftest.list +++ b/wrench/reftests/gradient/reftest.list @@ -16,7 +16,7 @@ platform(linux,mac) fuzzy(1,35000) == linear-stops.yaml linear-stops-ref.png == linear-clamp-1b.yaml linear-clamp-1-ref.yaml == linear-clamp-2.yaml linear-clamp-2-ref.yaml -fuzzy-range(<=1,*4800) == linear-hard-stop.yaml linear-hard-stop-ref.png +== linear-hard-stop.yaml linear-hard-stop-ref.png # dithering requires us to fuzz here fuzzy(1,20000) == linear.yaml linear-ref.yaml @@ -85,12 +85,3 @@ fuzzy(255,166) == conic-angle.yaml conic-angle.png fuzzy(1,1) == conic-angle-wraparound.yaml conic-angle.yaml fuzzy(1,1) == conic-angle-wraparound-negative.yaml conic-angle.yaml fuzzy(1,115) == conic-color-wheel.yaml conic-color-wheel.png - -# gradient caching tests -# replaces a computed gradient by a sampled texture, so a lot of off-by-one -# variation from interpolation, which is fine: -fuzzy-range(<=1,*195000) == gradient_cache_5stops.yaml gradient_cache_5stops_ref.yaml -fuzzy-range(<=1,*169000) == gradient_cache_5stops_vertical.yaml gradient_cache_5stops_vertical_ref.yaml -== gradient_cache_hardstop.yaml gradient_cache_hardstop_ref.yaml -== gradient_cache_hardstop_clip.yaml gradient_cache_hardstop_clip_ref.yaml -== gradient_cache_clamp.yaml gradient_cache_clamp_ref.yaml From dfd014b48fdaa1d34d5600e7cc179358010fb998 Mon Sep 17 00:00:00 2001 From: Bert Peers Date: Thu, 2 Apr 2020 10:00:56 +0000 Subject: [PATCH 4/6] Bug 1624468 - Add a fast path for more gradient types in WR r=gw Differential Revision: https://phabricator.services.mozilla.com/D68945 [ghsync] From https://hg.mozilla.org/mozilla-central/rev/9dc84057c6a93793865a92a15e54a9231c0f9b03 --- webrender/src/batch.rs | 98 ++++++----- webrender/src/prim_store/gradient.rs | 22 +-- webrender/src/prim_store/mod.rs | 152 ++++++++++++++---- .../gradient/gradient_cache_5stops.yaml | 13 ++ .../gradient/gradient_cache_5stops_ref.yaml | 18 +++ .../gradient_cache_5stops_vertical.yaml | 13 ++ .../gradient_cache_5stops_vertical_ref.yaml | 18 +++ .../gradient/gradient_cache_clamp.yaml | 20 +++ .../gradient/gradient_cache_clamp_ref.yaml | 30 ++++ .../gradient/gradient_cache_hardstop.yaml | 19 +++ .../gradient_cache_hardstop_clip.yaml | 21 +++ .../gradient_cache_hardstop_clip_ref.yaml | 28 ++++ .../gradient/gradient_cache_hardstop_ref.yaml | 24 +++ wrench/reftests/gradient/reftest.list | 11 +- 14 files changed, 399 insertions(+), 88 deletions(-) create mode 100644 wrench/reftests/gradient/gradient_cache_5stops.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_5stops_ref.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_clamp.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_clamp_ref.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_hardstop.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml create mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml diff --git a/webrender/src/batch.rs b/webrender/src/batch.rs index cfa766029e..54635b1e45 100644 --- a/webrender/src/batch.rs +++ b/webrender/src/batch.rs @@ -2268,53 +2268,69 @@ impl BatchBuilder { BlendMode::None }; - if let Some(ref cache_handle) = gradient.cache_handle { - let rt_cache_entry = ctx.resource_cache - .get_cached_render_task(cache_handle); - let cache_item = ctx.resource_cache - .get_texture_cache_item(&rt_cache_entry.handle); + if !gradient.cache_segments.is_empty() { - if cache_item.texture_id == TextureSource::Invalid { - return; - } + for segment in &gradient.cache_segments { + let ref cache_handle = segment.handle; + let rt_cache_entry = ctx.resource_cache + .get_cached_render_task(cache_handle); + let cache_item = ctx.resource_cache + .get_texture_cache_item(&rt_cache_entry.handle); - let textures = BatchTextures::color(cache_item.texture_id); - let batch_kind = BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)); - let prim_user_data = ImageBrushData { - color_mode: ShaderColorMode::Image, - alpha_type: AlphaType::PremultipliedAlpha, - raster_space: RasterizationSpace::Local, - opacity: 1.0, - }.encode(); + if cache_item.texture_id == TextureSource::Invalid { + return; + } - let specific_resource_address = cache_item.uv_rect_handle.as_int(gpu_cache); - prim_header.specific_prim_address = gpu_cache.get_address(&ctx.globals.default_image_handle); + let textures = BatchTextures::color(cache_item.texture_id); + let batch_kind = BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)); + let prim_user_data = ImageBrushData { + color_mode: ShaderColorMode::Image, + alpha_type: AlphaType::PremultipliedAlpha, + raster_space: RasterizationSpace::Local, + opacity: 1.0, + }.encode(); + + let specific_resource_address = cache_item.uv_rect_handle.as_int(gpu_cache); + prim_header.specific_prim_address = gpu_cache.get_address(&ctx.globals.default_image_handle); + + let segment_local_clip_rect = prim_header.local_clip_rect.intersection(&segment.local_rect); + if segment_local_clip_rect.is_none() { + continue; + } - let prim_header_index = prim_headers.push( - &prim_header, - z_id, - prim_user_data, - ); + let segment_prim_header = PrimitiveHeader { + local_rect: segment.local_rect, + local_clip_rect: segment_local_clip_rect.unwrap(), + specific_prim_address: prim_header.specific_prim_address, + transform_id: prim_header.transform_id, + }; - let batch_key = BatchKey { - blend_mode: non_segmented_blend_mode, - kind: BatchKind::Brush(batch_kind), - textures, - }; + let prim_header_index = prim_headers.push( + &segment_prim_header, + z_id, + prim_user_data, + ); - self.add_brush_instance_to_batches( - batch_key, - batch_features, - bounding_rect, - z_id, - INVALID_SEGMENT_INDEX, - EdgeAaSegmentMask::all(), - clip_task_address.unwrap(), - BrushFlags::PERSPECTIVE_INTERPOLATION, - prim_header_index, - specific_resource_address, - prim_vis_mask, - ); + let batch_key = BatchKey { + blend_mode: non_segmented_blend_mode, + kind: BatchKind::Brush(batch_kind), + textures, + }; + + self.add_brush_instance_to_batches( + batch_key, + batch_features, + bounding_rect, + z_id, + INVALID_SEGMENT_INDEX, + EdgeAaSegmentMask::all(), + clip_task_address.unwrap(), + BrushFlags::PERSPECTIVE_INTERPOLATION, + prim_header_index, + specific_resource_address, + prim_vis_mask, + ); + } } else if gradient.visible_tiles_range.is_empty() { let batch_params = BrushBatchParameters::shared( BrushBatchKind::LinearGradient, diff --git a/webrender/src/prim_store/gradient.rs b/webrender/src/prim_store/gradient.rs index b8d59c8030..9e2c27be55 100644 --- a/webrender/src/prim_store/gradient.rs +++ b/webrender/src/prim_store/gradient.rs @@ -13,11 +13,10 @@ use crate::frame_builder::FrameBuildingState; use crate::gpu_cache::{GpuCacheHandle, GpuDataRequest}; use crate::intern::{Internable, InternDebug, Handle as InternHandle}; use crate::internal_types::LayoutPrimitiveInfo; -use crate::prim_store::{BrushSegment, GradientTileRange, VectorKey}; +use crate::prim_store::{BrushSegment, CachedGradientSegment, GradientTileRange, VectorKey}; use crate::prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData}; use crate::prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore}; use crate::prim_store::{NinePatchDescriptor, PointKey, SizeKey, InternablePrimitive}; -use crate::render_task_cache::RenderTaskCacheEntryHandle; use std::{hash, ops::{Deref, DerefMut}}; use crate::util::pack_as_float; @@ -152,7 +151,7 @@ impl From for LinearGradientTemplate { // gradient in a smaller task, and drawing as an image. // TODO(gw): Aim to reduce the constraints on fast path gradients in future, // although this catches the vast majority of gradients on real pages. - let mut supports_caching = + let supports_caching = // No repeating support in fast path item.extend_mode == ExtendMode::Clamp && // Gradient must cover entire primitive @@ -161,28 +160,15 @@ impl From for LinearGradientTemplate { // Must be a vertical or horizontal gradient (item.start_point.x.approx_eq(&item.end_point.x) || item.start_point.y.approx_eq(&item.end_point.y)) && - // Fast path supports a limited number of stops - item.stops.len() <= GRADIENT_FP_STOPS && // Fast path not supported on segmented (border-image) gradients. item.nine_patch.is_none(); - let mut prev_offset = None; // Convert the stops to more convenient representation // for the current gradient builder. let stops: Vec = item.stops.iter().map(|stop| { let color: ColorF = stop.color.into(); min_alpha = min_alpha.min(color.a); - // The fast path doesn't support hard color stops, yet. - // Since the length of the gradient is a fixed size (512 device pixels), if there - // is a hard stop you will see bilinear interpolation with this method, instead - // of an abrupt color change. - if prev_offset == Some(stop.offset) { - supports_caching = false; - } - - prev_offset = Some(stop.offset); - GradientStop { offset: stop.offset, color, @@ -318,7 +304,7 @@ impl InternablePrimitive for LinearGradient { _reference_frame_relative_offset: LayoutVector2D, ) -> PrimitiveInstanceKind { let gradient_index = prim_store.linear_gradients.push(LinearGradientPrimitive { - cache_handle: None, + cache_segments: Vec::new(), visible_tiles_range: GradientTileRange::empty(), }); @@ -338,7 +324,7 @@ impl IsVisible for LinearGradient { #[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] pub struct LinearGradientPrimitive { - pub cache_handle: Option, + pub cache_segments: Vec, pub visible_tiles_range: GradientTileRange, } diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index c9c16df149..82d17aa441 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -970,6 +970,13 @@ pub struct VisibleGradientTile { pub local_clip_rect: LayoutRect, } +#[derive(Debug)] +#[cfg_attr(feature = "capture", derive(Serialize))] +pub struct CachedGradientSegment { + pub handle: RenderTaskCacheEntryHandle, + pub local_rect: LayoutRect, +} + /// Information about how to cache a border segment, /// along with the current render task cache entry. #[cfg_attr(feature = "capture", derive(Serialize))] @@ -3284,7 +3291,7 @@ impl PrimitiveStore { }; // Build the cache key, including information about the stops. - let mut stops = [GradientStopKey::empty(); GRADIENT_FP_STOPS]; + let mut stops = vec![GradientStopKey::empty(); prim_data.stops.len()]; // Reverse the stops as required, same as the gradient builder does // for the slow path. @@ -3302,35 +3309,124 @@ impl PrimitiveStore { } } - let cache_key = GradientCacheKey { - orientation, - start_stop_point: VectorKey { - x: start_point, - y: end_point, - }, - stops, - }; + // To support clamping, we need to make sure that quads are emitted for the + // segments before and after the 0.0...1.0 range of offsets. The loop below + // can handle that by duplicating the first and last point if necessary: + if start_point < 0.0 { + stops.insert(0, GradientStopKey { + offset: start_point, + color : stops[0].color + }); + } - // Request the render task each frame. - gradient.cache_handle = Some(frame_state.resource_cache.request_render_task( - RenderTaskCacheKey { - size, - kind: RenderTaskCacheKeyKind::Gradient(cache_key), - }, - frame_state.gpu_cache, - frame_state.render_tasks, - None, - prim_data.stops_opacity.is_opaque, - |render_tasks| { - render_tasks.add().init(RenderTask::new_gradient( - size, - stops, - orientation, - start_point, - end_point, - )) + if end_point > 1.0 { + stops.push( GradientStopKey { + offset: end_point, + color : stops[stops.len()-1].color + }); + } + + gradient.cache_segments.clear(); + + let mut first_stop = 0; + // look for an inclusive range of stops [first_stop, last_stop]. + // once first_stop points at (or past) the last stop, we're done. + while first_stop < stops.len()-1 { + + // if the entire segment starts at an offset that's past the primitive's + // end_point, we're done. + if stops[first_stop].offset > end_point { + break; } - )); + + // accumulate stops until we have GRADIENT_FP_STOPS of them, or we hit + // a hard stop: + let mut last_stop = first_stop; + let mut hard_stop = false; // did we stop on a hard stop? + while last_stop < stops.len()-1 && + last_stop - first_stop + 1 < GRADIENT_FP_STOPS + { + if stops[last_stop+1].offset == stops[last_stop].offset { + hard_stop = true; + break; + } + + last_stop = last_stop + 1; + } + + let num_stops = last_stop - first_stop + 1; + + // repeated hard stops at the same offset, skip + if num_stops == 0 { + first_stop = last_stop + 1; + continue; + } + + // if the last stop offset is before start_point, the segment's not visible: + if stops[last_stop].offset < start_point { + first_stop = if hard_stop { last_stop+1 } else { last_stop }; + continue; + } + + let segment_start_point = start_point.max(stops[first_stop].offset); + let segment_end_point = end_point .min(stops[last_stop ].offset); + + let mut segment_stops = [GradientStopKey::empty(); GRADIENT_FP_STOPS]; + for i in 0..num_stops { + segment_stops[i] = stops[first_stop + i]; + } + + let cache_key = GradientCacheKey { + orientation, + start_stop_point: VectorKey { + x: segment_start_point, + y: segment_end_point, + }, + stops: segment_stops, + }; + + let mut prim_origin = prim_instance.prim_origin; + let mut prim_size = prim_data.common.prim_size; + + let inv_length = 1.0 / ( end_point - start_point ); + if orientation == LineOrientation::Horizontal { + prim_origin.x += ( segment_start_point - start_point ) * inv_length * prim_size.width; + prim_size.width *= ( segment_end_point - segment_start_point ) * inv_length; + } else { + prim_origin.y += ( segment_start_point - start_point ) * inv_length * prim_size.height; + prim_size.height *= ( segment_end_point - segment_start_point ) * inv_length; + } + + let local_rect = LayoutRect::new( prim_origin, prim_size ); + + // Request the render task each frame. + gradient.cache_segments.push( + CachedGradientSegment { + handle: frame_state.resource_cache.request_render_task( + RenderTaskCacheKey { + size, + kind: RenderTaskCacheKeyKind::Gradient(cache_key), + }, + frame_state.gpu_cache, + frame_state.render_tasks, + None, + prim_data.stops_opacity.is_opaque, + |render_tasks| { + render_tasks.add().init(RenderTask::new_gradient( + size, + segment_stops, + orientation, + segment_start_point, + segment_end_point, + )) + }), + local_rect: local_rect, + } + ); + + // if ending on a hardstop, skip past it for the start of the next run: + first_stop = if hard_stop { last_stop + 1 } else { last_stop }; + } } if prim_data.tile_spacing != LayoutSize::zero() { diff --git a/wrench/reftests/gradient/gradient_cache_5stops.yaml b/wrench/reftests/gradient/gradient_cache_5stops.yaml new file mode 100644 index 0000000000..d448723002 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_5stops.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 540 + start: 0 0 + end: 960 0 + stops: [0.0, red, + 0.25, green, + 0.5, blue, + 0.75, [40,40,40,1], + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml b/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml new file mode 100644 index 0000000000..34b6b0e01c --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, red, + 0.5, green, + 1.0, blue] + - type: gradient + bounds: 480 0 480 540 + start: 0 0 + end: 480 0 + stops: [ 0.0, blue, + 0.5, [40,40,40,1], + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml b/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml new file mode 100644 index 0000000000..dd2c8b7c9d --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml @@ -0,0 +1,13 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 540 + start: 0 0 + end: 0 540 + stops: [0.0, red, + 0.25, green, + 0.5, blue, + 0.75, [40,40,40,1], + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml b/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml new file mode 100644 index 0000000000..704b5be2f6 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml @@ -0,0 +1,18 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 270 + start: 0 0 + end: 0 270 + stops: [0.0, red, + 0.5, green, + 1.0, blue] + - type: gradient + bounds: 0 270 960 270 + start: 0 0 + end: 0 270 + stops: [ 0.0, blue, + 0.5, [40,40,40,1], + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_clamp.yaml b/wrench/reftests/gradient/gradient_cache_clamp.yaml new file mode 100644 index 0000000000..1c55a269a1 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_clamp.yaml @@ -0,0 +1,20 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 400 200 + start: 0 100 + end: 100 100 + stops: [0.0, blue, 1.0, blue, 1.0, red] + - type: gradient + bounds: 0 300 400 200 + start: 100 100 + end: 200 100 + stops: [0.0, blue, 1.0, blue, 1.0, red] + - type: gradient + bounds: 0 600 200 400 + start: 0 100 + end: 0 300 + stops: [ + 0.0, blue, + 1.0, red] diff --git a/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml b/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml new file mode 100644 index 0000000000..4631192cd8 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml @@ -0,0 +1,30 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 400 200 + start: 0 100 + end: 400 100 + stops: [ + 0.0, blue, + 0.25, blue, + 0.25, red, + 1.0, red] + - type: gradient + bounds: 0 300 400 200 + start: 0 100 + end: 400 100 + stops: [ + 0.0, blue, + 0.5, blue, + 0.5, red, + 1.0, red] + - type: gradient + bounds: 0 600 200 400 + start: 0 0 + end: 0 400 + stops: [ + 0.0, blue, + 0.25, blue, + 0.75, red, + 1.0, red] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop.yaml b/wrench/reftests/gradient/gradient_cache_hardstop.yaml new file mode 100644 index 0000000000..53c908fb22 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_hardstop.yaml @@ -0,0 +1,19 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 540 + start: 0 0 + end: 960 0 + stops: [0.0, red, + 0.125, yellow, + 0.25, red, + 0.25, green, + 0.375, yellow, + 0.5, green, + 0.5, blue, + 0.625, yellow, + 0.75, blue, + 0.75, white, + 1.0, [100,200,50,1]] + diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml new file mode 100644 index 0000000000..3e7a2e946f --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml @@ -0,0 +1,21 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 960 540 + start: 0 0 + end: 960 0 + stops: [0.0, red, + 0.125, yellow, + 0.25, red, + 0.25, green, + 0.375, yellow, + 0.5, green, + 0.5, blue, + 0.625, yellow, + 0.75, blue, + 0.75, white, + 1.0, [100,200,50,1]] + complex-clip: + rect: [100, 100, 760, 340] + radius: [32, 32] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml new file mode 100644 index 0000000000..2b27c5649c --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml @@ -0,0 +1,28 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, red, + 0.25, yellow, + 0.5, red, + 0.5, green, + 0.75, yellow, + 1.0, green] + complex-clip: + rect: [100, 100, 760, 340] + radius: [32, 32] + - type: gradient + bounds: 480 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, blue, + 0.25, yellow, + 0.5, blue, + 0.5, white, + 1.0, [100,200,50,1]] + complex-clip: + rect: [100, 100, 760, 340] + radius: [32, 32] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml new file mode 100644 index 0000000000..e4b3928046 --- /dev/null +++ b/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml @@ -0,0 +1,24 @@ +--- +root: + items: + - type: gradient + bounds: 0 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, red, + 0.25, yellow, + 0.5, red, + 0.5, green, + 0.75, yellow, + 1.0, green] + - type: gradient + bounds: 480 0 480 540 + start: 0 0 + end: 480 0 + stops: [0.0, blue, + 0.25, yellow, + 0.5, blue, + 0.5, white, + 1.0, [100,200,50,1]] + + diff --git a/wrench/reftests/gradient/reftest.list b/wrench/reftests/gradient/reftest.list index ac0b6454b4..c3b3eee9cd 100644 --- a/wrench/reftests/gradient/reftest.list +++ b/wrench/reftests/gradient/reftest.list @@ -16,7 +16,7 @@ platform(linux,mac) fuzzy(1,35000) == linear-stops.yaml linear-stops-ref.png == linear-clamp-1b.yaml linear-clamp-1-ref.yaml == linear-clamp-2.yaml linear-clamp-2-ref.yaml -== linear-hard-stop.yaml linear-hard-stop-ref.png +fuzzy-range(<=1,*4800) == linear-hard-stop.yaml linear-hard-stop-ref.png # dithering requires us to fuzz here fuzzy(1,20000) == linear.yaml linear-ref.yaml @@ -85,3 +85,12 @@ fuzzy(255,166) == conic-angle.yaml conic-angle.png fuzzy(1,1) == conic-angle-wraparound.yaml conic-angle.yaml fuzzy(1,1) == conic-angle-wraparound-negative.yaml conic-angle.yaml fuzzy(1,115) == conic-color-wheel.yaml conic-color-wheel.png + +# gradient caching tests +# replaces a computed gradient by a sampled texture, so a lot of off-by-one +# variation from interpolation, which is fine: +fuzzy-range(<=1,*195000) == gradient_cache_5stops.yaml gradient_cache_5stops_ref.yaml +fuzzy-range(<=1,*169000) == gradient_cache_5stops_vertical.yaml gradient_cache_5stops_vertical_ref.yaml +== gradient_cache_hardstop.yaml gradient_cache_hardstop_ref.yaml +== gradient_cache_hardstop_clip.yaml gradient_cache_hardstop_clip_ref.yaml +== gradient_cache_clamp.yaml gradient_cache_clamp_ref.yaml From f568c5b95012e1c22881e4af77c7327b2757d4e9 Mon Sep 17 00:00:00 2001 From: Ciure Andrei Date: Thu, 2 Apr 2020 10:01:06 +0000 Subject: [PATCH 5/6] Backed out changeset 9dc84057c6a9 (bug 1624468) for causing gradient-move-stops.html to fail CLOSED TREE [ghsync] From https://hg.mozilla.org/mozilla-central/rev/4e874b1ed303fa1ca1960d3caed4cced4288c49d --- webrender/src/batch.rs | 98 +++++------ webrender/src/prim_store/gradient.rs | 22 ++- webrender/src/prim_store/mod.rs | 152 ++++-------------- .../gradient/gradient_cache_5stops.yaml | 13 -- .../gradient/gradient_cache_5stops_ref.yaml | 18 --- .../gradient_cache_5stops_vertical.yaml | 13 -- .../gradient_cache_5stops_vertical_ref.yaml | 18 --- .../gradient/gradient_cache_clamp.yaml | 20 --- .../gradient/gradient_cache_clamp_ref.yaml | 30 ---- .../gradient/gradient_cache_hardstop.yaml | 19 --- .../gradient_cache_hardstop_clip.yaml | 21 --- .../gradient_cache_hardstop_clip_ref.yaml | 28 ---- .../gradient/gradient_cache_hardstop_ref.yaml | 24 --- wrench/reftests/gradient/reftest.list | 11 +- 14 files changed, 88 insertions(+), 399 deletions(-) delete mode 100644 wrench/reftests/gradient/gradient_cache_5stops.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_5stops_ref.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_clamp.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_clamp_ref.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_hardstop.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml delete mode 100644 wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml diff --git a/webrender/src/batch.rs b/webrender/src/batch.rs index 54635b1e45..cfa766029e 100644 --- a/webrender/src/batch.rs +++ b/webrender/src/batch.rs @@ -2268,69 +2268,53 @@ impl BatchBuilder { BlendMode::None }; - if !gradient.cache_segments.is_empty() { - - for segment in &gradient.cache_segments { - let ref cache_handle = segment.handle; - let rt_cache_entry = ctx.resource_cache - .get_cached_render_task(cache_handle); - let cache_item = ctx.resource_cache - .get_texture_cache_item(&rt_cache_entry.handle); + if let Some(ref cache_handle) = gradient.cache_handle { + let rt_cache_entry = ctx.resource_cache + .get_cached_render_task(cache_handle); + let cache_item = ctx.resource_cache + .get_texture_cache_item(&rt_cache_entry.handle); - if cache_item.texture_id == TextureSource::Invalid { - return; - } + if cache_item.texture_id == TextureSource::Invalid { + return; + } - let textures = BatchTextures::color(cache_item.texture_id); - let batch_kind = BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)); - let prim_user_data = ImageBrushData { - color_mode: ShaderColorMode::Image, - alpha_type: AlphaType::PremultipliedAlpha, - raster_space: RasterizationSpace::Local, - opacity: 1.0, - }.encode(); - - let specific_resource_address = cache_item.uv_rect_handle.as_int(gpu_cache); - prim_header.specific_prim_address = gpu_cache.get_address(&ctx.globals.default_image_handle); - - let segment_local_clip_rect = prim_header.local_clip_rect.intersection(&segment.local_rect); - if segment_local_clip_rect.is_none() { - continue; - } + let textures = BatchTextures::color(cache_item.texture_id); + let batch_kind = BrushBatchKind::Image(get_buffer_kind(cache_item.texture_id)); + let prim_user_data = ImageBrushData { + color_mode: ShaderColorMode::Image, + alpha_type: AlphaType::PremultipliedAlpha, + raster_space: RasterizationSpace::Local, + opacity: 1.0, + }.encode(); - let segment_prim_header = PrimitiveHeader { - local_rect: segment.local_rect, - local_clip_rect: segment_local_clip_rect.unwrap(), - specific_prim_address: prim_header.specific_prim_address, - transform_id: prim_header.transform_id, - }; + let specific_resource_address = cache_item.uv_rect_handle.as_int(gpu_cache); + prim_header.specific_prim_address = gpu_cache.get_address(&ctx.globals.default_image_handle); - let prim_header_index = prim_headers.push( - &segment_prim_header, - z_id, - prim_user_data, - ); + let prim_header_index = prim_headers.push( + &prim_header, + z_id, + prim_user_data, + ); - let batch_key = BatchKey { - blend_mode: non_segmented_blend_mode, - kind: BatchKind::Brush(batch_kind), - textures, - }; + let batch_key = BatchKey { + blend_mode: non_segmented_blend_mode, + kind: BatchKind::Brush(batch_kind), + textures, + }; - self.add_brush_instance_to_batches( - batch_key, - batch_features, - bounding_rect, - z_id, - INVALID_SEGMENT_INDEX, - EdgeAaSegmentMask::all(), - clip_task_address.unwrap(), - BrushFlags::PERSPECTIVE_INTERPOLATION, - prim_header_index, - specific_resource_address, - prim_vis_mask, - ); - } + self.add_brush_instance_to_batches( + batch_key, + batch_features, + bounding_rect, + z_id, + INVALID_SEGMENT_INDEX, + EdgeAaSegmentMask::all(), + clip_task_address.unwrap(), + BrushFlags::PERSPECTIVE_INTERPOLATION, + prim_header_index, + specific_resource_address, + prim_vis_mask, + ); } else if gradient.visible_tiles_range.is_empty() { let batch_params = BrushBatchParameters::shared( BrushBatchKind::LinearGradient, diff --git a/webrender/src/prim_store/gradient.rs b/webrender/src/prim_store/gradient.rs index 9e2c27be55..b8d59c8030 100644 --- a/webrender/src/prim_store/gradient.rs +++ b/webrender/src/prim_store/gradient.rs @@ -13,10 +13,11 @@ use crate::frame_builder::FrameBuildingState; use crate::gpu_cache::{GpuCacheHandle, GpuDataRequest}; use crate::intern::{Internable, InternDebug, Handle as InternHandle}; use crate::internal_types::LayoutPrimitiveInfo; -use crate::prim_store::{BrushSegment, CachedGradientSegment, GradientTileRange, VectorKey}; +use crate::prim_store::{BrushSegment, GradientTileRange, VectorKey}; use crate::prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData}; use crate::prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore}; use crate::prim_store::{NinePatchDescriptor, PointKey, SizeKey, InternablePrimitive}; +use crate::render_task_cache::RenderTaskCacheEntryHandle; use std::{hash, ops::{Deref, DerefMut}}; use crate::util::pack_as_float; @@ -151,7 +152,7 @@ impl From for LinearGradientTemplate { // gradient in a smaller task, and drawing as an image. // TODO(gw): Aim to reduce the constraints on fast path gradients in future, // although this catches the vast majority of gradients on real pages. - let supports_caching = + let mut supports_caching = // No repeating support in fast path item.extend_mode == ExtendMode::Clamp && // Gradient must cover entire primitive @@ -160,15 +161,28 @@ impl From for LinearGradientTemplate { // Must be a vertical or horizontal gradient (item.start_point.x.approx_eq(&item.end_point.x) || item.start_point.y.approx_eq(&item.end_point.y)) && + // Fast path supports a limited number of stops + item.stops.len() <= GRADIENT_FP_STOPS && // Fast path not supported on segmented (border-image) gradients. item.nine_patch.is_none(); + let mut prev_offset = None; // Convert the stops to more convenient representation // for the current gradient builder. let stops: Vec = item.stops.iter().map(|stop| { let color: ColorF = stop.color.into(); min_alpha = min_alpha.min(color.a); + // The fast path doesn't support hard color stops, yet. + // Since the length of the gradient is a fixed size (512 device pixels), if there + // is a hard stop you will see bilinear interpolation with this method, instead + // of an abrupt color change. + if prev_offset == Some(stop.offset) { + supports_caching = false; + } + + prev_offset = Some(stop.offset); + GradientStop { offset: stop.offset, color, @@ -304,7 +318,7 @@ impl InternablePrimitive for LinearGradient { _reference_frame_relative_offset: LayoutVector2D, ) -> PrimitiveInstanceKind { let gradient_index = prim_store.linear_gradients.push(LinearGradientPrimitive { - cache_segments: Vec::new(), + cache_handle: None, visible_tiles_range: GradientTileRange::empty(), }); @@ -324,7 +338,7 @@ impl IsVisible for LinearGradient { #[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] pub struct LinearGradientPrimitive { - pub cache_segments: Vec, + pub cache_handle: Option, pub visible_tiles_range: GradientTileRange, } diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index 82d17aa441..c9c16df149 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -970,13 +970,6 @@ pub struct VisibleGradientTile { pub local_clip_rect: LayoutRect, } -#[derive(Debug)] -#[cfg_attr(feature = "capture", derive(Serialize))] -pub struct CachedGradientSegment { - pub handle: RenderTaskCacheEntryHandle, - pub local_rect: LayoutRect, -} - /// Information about how to cache a border segment, /// along with the current render task cache entry. #[cfg_attr(feature = "capture", derive(Serialize))] @@ -3291,7 +3284,7 @@ impl PrimitiveStore { }; // Build the cache key, including information about the stops. - let mut stops = vec![GradientStopKey::empty(); prim_data.stops.len()]; + let mut stops = [GradientStopKey::empty(); GRADIENT_FP_STOPS]; // Reverse the stops as required, same as the gradient builder does // for the slow path. @@ -3309,124 +3302,35 @@ impl PrimitiveStore { } } - // To support clamping, we need to make sure that quads are emitted for the - // segments before and after the 0.0...1.0 range of offsets. The loop below - // can handle that by duplicating the first and last point if necessary: - if start_point < 0.0 { - stops.insert(0, GradientStopKey { - offset: start_point, - color : stops[0].color - }); - } - - if end_point > 1.0 { - stops.push( GradientStopKey { - offset: end_point, - color : stops[stops.len()-1].color - }); - } - - gradient.cache_segments.clear(); - - let mut first_stop = 0; - // look for an inclusive range of stops [first_stop, last_stop]. - // once first_stop points at (or past) the last stop, we're done. - while first_stop < stops.len()-1 { - - // if the entire segment starts at an offset that's past the primitive's - // end_point, we're done. - if stops[first_stop].offset > end_point { - break; - } - - // accumulate stops until we have GRADIENT_FP_STOPS of them, or we hit - // a hard stop: - let mut last_stop = first_stop; - let mut hard_stop = false; // did we stop on a hard stop? - while last_stop < stops.len()-1 && - last_stop - first_stop + 1 < GRADIENT_FP_STOPS - { - if stops[last_stop+1].offset == stops[last_stop].offset { - hard_stop = true; - break; - } - - last_stop = last_stop + 1; - } - - let num_stops = last_stop - first_stop + 1; - - // repeated hard stops at the same offset, skip - if num_stops == 0 { - first_stop = last_stop + 1; - continue; - } - - // if the last stop offset is before start_point, the segment's not visible: - if stops[last_stop].offset < start_point { - first_stop = if hard_stop { last_stop+1 } else { last_stop }; - continue; - } - - let segment_start_point = start_point.max(stops[first_stop].offset); - let segment_end_point = end_point .min(stops[last_stop ].offset); - - let mut segment_stops = [GradientStopKey::empty(); GRADIENT_FP_STOPS]; - for i in 0..num_stops { - segment_stops[i] = stops[first_stop + i]; - } - - let cache_key = GradientCacheKey { - orientation, - start_stop_point: VectorKey { - x: segment_start_point, - y: segment_end_point, - }, - stops: segment_stops, - }; - - let mut prim_origin = prim_instance.prim_origin; - let mut prim_size = prim_data.common.prim_size; + let cache_key = GradientCacheKey { + orientation, + start_stop_point: VectorKey { + x: start_point, + y: end_point, + }, + stops, + }; - let inv_length = 1.0 / ( end_point - start_point ); - if orientation == LineOrientation::Horizontal { - prim_origin.x += ( segment_start_point - start_point ) * inv_length * prim_size.width; - prim_size.width *= ( segment_end_point - segment_start_point ) * inv_length; - } else { - prim_origin.y += ( segment_start_point - start_point ) * inv_length * prim_size.height; - prim_size.height *= ( segment_end_point - segment_start_point ) * inv_length; + // Request the render task each frame. + gradient.cache_handle = Some(frame_state.resource_cache.request_render_task( + RenderTaskCacheKey { + size, + kind: RenderTaskCacheKeyKind::Gradient(cache_key), + }, + frame_state.gpu_cache, + frame_state.render_tasks, + None, + prim_data.stops_opacity.is_opaque, + |render_tasks| { + render_tasks.add().init(RenderTask::new_gradient( + size, + stops, + orientation, + start_point, + end_point, + )) } - - let local_rect = LayoutRect::new( prim_origin, prim_size ); - - // Request the render task each frame. - gradient.cache_segments.push( - CachedGradientSegment { - handle: frame_state.resource_cache.request_render_task( - RenderTaskCacheKey { - size, - kind: RenderTaskCacheKeyKind::Gradient(cache_key), - }, - frame_state.gpu_cache, - frame_state.render_tasks, - None, - prim_data.stops_opacity.is_opaque, - |render_tasks| { - render_tasks.add().init(RenderTask::new_gradient( - size, - segment_stops, - orientation, - segment_start_point, - segment_end_point, - )) - }), - local_rect: local_rect, - } - ); - - // if ending on a hardstop, skip past it for the start of the next run: - first_stop = if hard_stop { last_stop + 1 } else { last_stop }; - } + )); } if prim_data.tile_spacing != LayoutSize::zero() { diff --git a/wrench/reftests/gradient/gradient_cache_5stops.yaml b/wrench/reftests/gradient/gradient_cache_5stops.yaml deleted file mode 100644 index d448723002..0000000000 --- a/wrench/reftests/gradient/gradient_cache_5stops.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 540 - start: 0 0 - end: 960 0 - stops: [0.0, red, - 0.25, green, - 0.5, blue, - 0.75, [40,40,40,1], - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml b/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml deleted file mode 100644 index 34b6b0e01c..0000000000 --- a/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, red, - 0.5, green, - 1.0, blue] - - type: gradient - bounds: 480 0 480 540 - start: 0 0 - end: 480 0 - stops: [ 0.0, blue, - 0.5, [40,40,40,1], - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml b/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml deleted file mode 100644 index dd2c8b7c9d..0000000000 --- a/wrench/reftests/gradient/gradient_cache_5stops_vertical.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 540 - start: 0 0 - end: 0 540 - stops: [0.0, red, - 0.25, green, - 0.5, blue, - 0.75, [40,40,40,1], - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml b/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml deleted file mode 100644 index 704b5be2f6..0000000000 --- a/wrench/reftests/gradient/gradient_cache_5stops_vertical_ref.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 270 - start: 0 0 - end: 0 270 - stops: [0.0, red, - 0.5, green, - 1.0, blue] - - type: gradient - bounds: 0 270 960 270 - start: 0 0 - end: 0 270 - stops: [ 0.0, blue, - 0.5, [40,40,40,1], - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_clamp.yaml b/wrench/reftests/gradient/gradient_cache_clamp.yaml deleted file mode 100644 index 1c55a269a1..0000000000 --- a/wrench/reftests/gradient/gradient_cache_clamp.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 400 200 - start: 0 100 - end: 100 100 - stops: [0.0, blue, 1.0, blue, 1.0, red] - - type: gradient - bounds: 0 300 400 200 - start: 100 100 - end: 200 100 - stops: [0.0, blue, 1.0, blue, 1.0, red] - - type: gradient - bounds: 0 600 200 400 - start: 0 100 - end: 0 300 - stops: [ - 0.0, blue, - 1.0, red] diff --git a/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml b/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml deleted file mode 100644 index 4631192cd8..0000000000 --- a/wrench/reftests/gradient/gradient_cache_clamp_ref.yaml +++ /dev/null @@ -1,30 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 400 200 - start: 0 100 - end: 400 100 - stops: [ - 0.0, blue, - 0.25, blue, - 0.25, red, - 1.0, red] - - type: gradient - bounds: 0 300 400 200 - start: 0 100 - end: 400 100 - stops: [ - 0.0, blue, - 0.5, blue, - 0.5, red, - 1.0, red] - - type: gradient - bounds: 0 600 200 400 - start: 0 0 - end: 0 400 - stops: [ - 0.0, blue, - 0.25, blue, - 0.75, red, - 1.0, red] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop.yaml b/wrench/reftests/gradient/gradient_cache_hardstop.yaml deleted file mode 100644 index 53c908fb22..0000000000 --- a/wrench/reftests/gradient/gradient_cache_hardstop.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 540 - start: 0 0 - end: 960 0 - stops: [0.0, red, - 0.125, yellow, - 0.25, red, - 0.25, green, - 0.375, yellow, - 0.5, green, - 0.5, blue, - 0.625, yellow, - 0.75, blue, - 0.75, white, - 1.0, [100,200,50,1]] - diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml deleted file mode 100644 index 3e7a2e946f..0000000000 --- a/wrench/reftests/gradient/gradient_cache_hardstop_clip.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 960 540 - start: 0 0 - end: 960 0 - stops: [0.0, red, - 0.125, yellow, - 0.25, red, - 0.25, green, - 0.375, yellow, - 0.5, green, - 0.5, blue, - 0.625, yellow, - 0.75, blue, - 0.75, white, - 1.0, [100,200,50,1]] - complex-clip: - rect: [100, 100, 760, 340] - radius: [32, 32] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml deleted file mode 100644 index 2b27c5649c..0000000000 --- a/wrench/reftests/gradient/gradient_cache_hardstop_clip_ref.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, red, - 0.25, yellow, - 0.5, red, - 0.5, green, - 0.75, yellow, - 1.0, green] - complex-clip: - rect: [100, 100, 760, 340] - radius: [32, 32] - - type: gradient - bounds: 480 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, blue, - 0.25, yellow, - 0.5, blue, - 0.5, white, - 1.0, [100,200,50,1]] - complex-clip: - rect: [100, 100, 760, 340] - radius: [32, 32] diff --git a/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml b/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml deleted file mode 100644 index e4b3928046..0000000000 --- a/wrench/reftests/gradient/gradient_cache_hardstop_ref.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -root: - items: - - type: gradient - bounds: 0 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, red, - 0.25, yellow, - 0.5, red, - 0.5, green, - 0.75, yellow, - 1.0, green] - - type: gradient - bounds: 480 0 480 540 - start: 0 0 - end: 480 0 - stops: [0.0, blue, - 0.25, yellow, - 0.5, blue, - 0.5, white, - 1.0, [100,200,50,1]] - - diff --git a/wrench/reftests/gradient/reftest.list b/wrench/reftests/gradient/reftest.list index c3b3eee9cd..ac0b6454b4 100644 --- a/wrench/reftests/gradient/reftest.list +++ b/wrench/reftests/gradient/reftest.list @@ -16,7 +16,7 @@ platform(linux,mac) fuzzy(1,35000) == linear-stops.yaml linear-stops-ref.png == linear-clamp-1b.yaml linear-clamp-1-ref.yaml == linear-clamp-2.yaml linear-clamp-2-ref.yaml -fuzzy-range(<=1,*4800) == linear-hard-stop.yaml linear-hard-stop-ref.png +== linear-hard-stop.yaml linear-hard-stop-ref.png # dithering requires us to fuzz here fuzzy(1,20000) == linear.yaml linear-ref.yaml @@ -85,12 +85,3 @@ fuzzy(255,166) == conic-angle.yaml conic-angle.png fuzzy(1,1) == conic-angle-wraparound.yaml conic-angle.yaml fuzzy(1,1) == conic-angle-wraparound-negative.yaml conic-angle.yaml fuzzy(1,115) == conic-color-wheel.yaml conic-color-wheel.png - -# gradient caching tests -# replaces a computed gradient by a sampled texture, so a lot of off-by-one -# variation from interpolation, which is fine: -fuzzy-range(<=1,*195000) == gradient_cache_5stops.yaml gradient_cache_5stops_ref.yaml -fuzzy-range(<=1,*169000) == gradient_cache_5stops_vertical.yaml gradient_cache_5stops_vertical_ref.yaml -== gradient_cache_hardstop.yaml gradient_cache_hardstop_ref.yaml -== gradient_cache_hardstop_clip.yaml gradient_cache_hardstop_clip_ref.yaml -== gradient_cache_clamp.yaml gradient_cache_clamp_ref.yaml From 6a03bf142f1895f946d7a102db51a5affce87a63 Mon Sep 17 00:00:00 2001 From: sotaro Date: Thu, 2 Apr 2020 10:01:15 +0000 Subject: [PATCH 6/6] Bug 1624817 - Fix Tile invalidation during disabling WR native compositor r=gw Differential Revision: https://phabricator.services.mozilla.com/D69168 [ghsync] From https://hg.mozilla.org/mozilla-central/rev/95ddb3213aecaf87c0a4f2d3559bd17e0194148c --- webrender/src/picture.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webrender/src/picture.rs b/webrender/src/picture.rs index 4120b203ed..73ce7c1a2c 100644 --- a/webrender/src/picture.rs +++ b/webrender/src/picture.rs @@ -2787,10 +2787,10 @@ impl TileCacheInstance { if let Some(TileSurface::Texture { descriptor: SurfaceTextureDescriptor::Native { ref mut id, .. }, .. }) = tile.surface { if let Some(id) = id.take() { frame_state.resource_cache.destroy_compositor_tile(id); - tile.surface = None; - // Invalidate the entire tile to force a redraw. - tile.invalidate(None, InvalidationReason::CompositorKindChanged); } + tile.surface = None; + // Invalidate the entire tile to force a redraw. + tile.invalidate(None, InvalidationReason::CompositorKindChanged); } }