Skip to content

Commit

Permalink
Backed out changeset 3c84f9fd1f93 (bug 1624468) for causing css-gradi…
Browse files Browse the repository at this point in the history
…ents reftest failures CLOSED TREE
  • Loading branch information
SV-ACiure committed Apr 1, 2020
1 parent 28a4757 commit b34bb09
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 399 deletions.
98 changes: 41 additions & 57 deletions gfx/wr/webrender/src/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
22 changes: 18 additions & 4 deletions gfx/wr/webrender/src/prim_store/gradient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -151,7 +152,7 @@ impl From<LinearGradientKey> 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
Expand All @@ -160,15 +161,28 @@ impl From<LinearGradientKey> 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<GradientStop> = 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,
Expand Down Expand Up @@ -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(),
});

Expand All @@ -324,7 +338,7 @@ impl IsVisible for LinearGradient {
#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
pub struct LinearGradientPrimitive {
pub cache_segments: Vec<CachedGradientSegment>,
pub cache_handle: Option<RenderTaskCacheEntryHandle>,
pub visible_tiles_range: GradientTileRange,
}

Expand Down
152 changes: 28 additions & 124 deletions gfx/wr/webrender/src/prim_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down Expand Up @@ -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.
Expand All @@ -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() {
Expand Down
13 changes: 0 additions & 13 deletions gfx/wr/wrench/reftests/gradient/gradient_cache_5stops.yaml

This file was deleted.

18 changes: 0 additions & 18 deletions gfx/wr/wrench/reftests/gradient/gradient_cache_5stops_ref.yaml

This file was deleted.

Loading

0 comments on commit b34bb09

Please sign in to comment.