mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 1460861 - Update webrender to commit 9d20df4e76e3b19c569fd89965f70a2c278ff0c8. r=Gankro
MozReview-Commit-ID: C9hlaYMrM7W --HG-- extra : rebase_source : 83eb50452bfa712dd011a90a1fc1ceeddbce758f
This commit is contained in:
parent
95f8f2a563
commit
d76b5fa54a
@ -43,14 +43,14 @@ impl Example for App {
|
||||
let bounds = (0, 0).to(200, 200);
|
||||
|
||||
let filters = vec![
|
||||
FilterOp::Opacity(PropertyBinding::Binding(self.opacity_key), self.opacity),
|
||||
FilterOp::Opacity(PropertyBinding::Binding(self.opacity_key, self.opacity), self.opacity),
|
||||
];
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
Some(PropertyBinding::Binding(self.property_key)),
|
||||
Some(PropertyBinding::Binding(self.property_key, LayoutTransform::identity())),
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -65,7 +65,7 @@ impl Example for App {
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
Some(PropertyBinding::Binding(PropertyBindingKey::new(42))),
|
||||
Some(PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity())),
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -20,8 +20,6 @@ uniform sampler2DArray sCacheRGBA8;
|
||||
// An A8 target for standalone tasks that is available to all passes.
|
||||
uniform sampler2DArray sSharedCacheA8;
|
||||
|
||||
uniform sampler2D sGradients;
|
||||
|
||||
vec2 clamp_rect(vec2 pt, RectWithSize rect) {
|
||||
return clamp(pt, rect.p0, rect.p0 + rect.size);
|
||||
}
|
||||
|
@ -21,7 +21,8 @@ use picture::{PictureCompositeMode, PicturePrimitive, PictureSurface};
|
||||
use plane_split::{BspSplitter, Polygon, Splitter};
|
||||
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentTaskId, CachedGradient, DeferredResolve};
|
||||
use prim_store::{EdgeAaSegmentMask, ImageSource, PictureIndex, PrimitiveIndex, PrimitiveKind};
|
||||
use prim_store::{PrimitiveMetadata, PrimitiveRun, PrimitiveStore};
|
||||
use prim_store::{PrimitiveMetadata, PrimitiveRun, PrimitiveStore, VisibleGradientTile};
|
||||
use prim_store::CachedGradientIndex;
|
||||
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
|
||||
use renderer::{BlendMode, ImageBufferKind};
|
||||
use renderer::{BLOCKS_PER_UV_RECT, ShaderColorMode};
|
||||
@ -615,6 +616,8 @@ impl AlphaBatchBuilder {
|
||||
let brush = &ctx.prim_store.cpu_brushes[prim_metadata.cpu_prim_index.0];
|
||||
match brush.kind {
|
||||
BrushKind::Image { ref visible_tiles, .. } => !visible_tiles.is_empty(),
|
||||
BrushKind::LinearGradient { ref visible_tiles, .. } => !visible_tiles.is_empty(),
|
||||
BrushKind::RadialGradient { ref visible_tiles, .. } => !visible_tiles.is_empty(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -1018,6 +1021,40 @@ impl AlphaBatchBuilder {
|
||||
}
|
||||
}
|
||||
}
|
||||
BrushKind::LinearGradient { gradient_index, ref visible_tiles, .. } if !visible_tiles.is_empty() => {
|
||||
add_gradient_tiles(
|
||||
visible_tiles,
|
||||
gradient_index,
|
||||
BrushBatchKind::LinearGradient,
|
||||
specified_blend_mode,
|
||||
&task_relative_bounding_rect,
|
||||
clip_chain_rect_index,
|
||||
scroll_id,
|
||||
task_address,
|
||||
clip_task_address,
|
||||
z,
|
||||
ctx,
|
||||
gpu_cache,
|
||||
&mut self.batch_list,
|
||||
);
|
||||
}
|
||||
BrushKind::RadialGradient { gradient_index, ref visible_tiles, .. } if !visible_tiles.is_empty() => {
|
||||
add_gradient_tiles(
|
||||
visible_tiles,
|
||||
gradient_index,
|
||||
BrushBatchKind::RadialGradient,
|
||||
specified_blend_mode,
|
||||
&task_relative_bounding_rect,
|
||||
clip_chain_rect_index,
|
||||
scroll_id,
|
||||
task_address,
|
||||
clip_task_address,
|
||||
z,
|
||||
ctx,
|
||||
gpu_cache,
|
||||
&mut self.batch_list,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
if let Some((batch_kind, textures, user_data)) = brush.get_batch_params(
|
||||
ctx.resource_cache,
|
||||
@ -1348,6 +1385,57 @@ impl AlphaBatchBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_gradient_tiles(
|
||||
visible_tiles: &[VisibleGradientTile],
|
||||
gradient_index: CachedGradientIndex,
|
||||
kind: BrushBatchKind,
|
||||
blend_mode: BlendMode,
|
||||
task_relative_bounding_rect: &DeviceIntRect,
|
||||
clip_chain_rect_index: ClipChainRectIndex,
|
||||
scroll_id: ClipScrollNodeIndex,
|
||||
task_address: RenderTaskAddress,
|
||||
clip_task_address: RenderTaskAddress,
|
||||
z: ZBufferId,
|
||||
ctx: &RenderTargetContext,
|
||||
gpu_cache: &GpuCache,
|
||||
batch_list: &mut BatchList,
|
||||
) {
|
||||
batch_list.add_bounding_rect(task_relative_bounding_rect);
|
||||
let batch = batch_list.get_suitable_batch(
|
||||
BatchKey {
|
||||
blend_mode: blend_mode,
|
||||
kind: BatchKind::Brush(kind),
|
||||
textures: BatchTextures::no_texture(),
|
||||
},
|
||||
task_relative_bounding_rect
|
||||
);
|
||||
|
||||
let stops_handle = &ctx.cached_gradients[gradient_index.0].handle;
|
||||
let user_data = [stops_handle.as_int(gpu_cache), 0, 0];
|
||||
|
||||
let base_instance = BrushInstance {
|
||||
picture_address: task_address,
|
||||
prim_address: GpuCacheAddress::invalid(),
|
||||
clip_chain_rect_index,
|
||||
scroll_id,
|
||||
clip_task_address,
|
||||
z,
|
||||
segment_index: 0,
|
||||
edge_flags: EdgeAaSegmentMask::all(),
|
||||
brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION,
|
||||
user_data,
|
||||
};
|
||||
|
||||
for tile in visible_tiles {
|
||||
batch.push(PrimitiveInstance::from(
|
||||
BrushInstance {
|
||||
prim_address: gpu_cache.get_address(&tile.handle),
|
||||
..base_instance
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn get_image_tile_params(
|
||||
resource_cache: &ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
|
@ -1800,7 +1800,7 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_gradient_impl(
|
||||
pub fn add_gradient(
|
||||
&mut self,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
@ -1809,9 +1809,19 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
stops: ItemRange<GradientStop>,
|
||||
stops_count: usize,
|
||||
extend_mode: ExtendMode,
|
||||
gradient_index: CachedGradientIndex,
|
||||
stretch_size: LayoutSize,
|
||||
mut tile_spacing: LayoutSize,
|
||||
) {
|
||||
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
|
||||
self.cached_gradients.push(CachedGradient::new());
|
||||
|
||||
let mut prim_rect = info.rect;
|
||||
simplify_repeated_primitive(&stretch_size, &mut tile_spacing, &mut prim_rect);
|
||||
let info = LayoutPrimitiveInfo {
|
||||
rect: prim_rect,
|
||||
.. *info
|
||||
};
|
||||
|
||||
// Try to ensure that if the gradient is specified in reverse, then so long as the stops
|
||||
// are also supplied in reverse that the rendered result will be equivalent. To do this,
|
||||
// a reference orientation for the gradient line must be chosen, somewhat arbitrarily, so
|
||||
@ -1840,109 +1850,15 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
end_point: ep,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
visible_tiles: Vec::new(),
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
let prim = PrimitiveContainer::Brush(prim);
|
||||
|
||||
self.add_primitive(clip_and_scroll, info, Vec::new(), prim);
|
||||
}
|
||||
|
||||
pub fn add_gradient(
|
||||
&mut self,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
start_point: LayoutPoint,
|
||||
end_point: LayoutPoint,
|
||||
stops: ItemRange<GradientStop>,
|
||||
stops_count: usize,
|
||||
extend_mode: ExtendMode,
|
||||
stretch_size: LayoutSize,
|
||||
mut tile_spacing: LayoutSize,
|
||||
) {
|
||||
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
|
||||
self.cached_gradients.push(CachedGradient::new());
|
||||
|
||||
let mut prim_rect = info.rect;
|
||||
simplify_repeated_primitive(&stretch_size, &mut tile_spacing, &mut prim_rect);
|
||||
let info = LayoutPrimitiveInfo {
|
||||
rect: prim_rect,
|
||||
.. *info
|
||||
};
|
||||
|
||||
if tile_spacing != LayoutSize::zero() {
|
||||
let prim_infos = info.decompose(
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
64 * 64,
|
||||
);
|
||||
|
||||
if !prim_infos.is_empty() {
|
||||
for prim_info in prim_infos {
|
||||
self.add_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
prim_info.rect.size,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.add_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&info,
|
||||
start_point,
|
||||
end_point,
|
||||
stops,
|
||||
stops_count,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
);
|
||||
}
|
||||
|
||||
fn add_radial_gradient_impl(
|
||||
&mut self,
|
||||
clip_and_scroll: ScrollNodeAndClipChain,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
center: LayoutPoint,
|
||||
start_radius: f32,
|
||||
end_radius: f32,
|
||||
ratio_xy: f32,
|
||||
stops: ItemRange<GradientStop>,
|
||||
extend_mode: ExtendMode,
|
||||
gradient_index: CachedGradientIndex,
|
||||
stretch_size: LayoutSize,
|
||||
) {
|
||||
let prim = BrushPrimitive::new(
|
||||
BrushKind::RadialGradient {
|
||||
stops_range: stops,
|
||||
extend_mode,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
info,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Brush(prim),
|
||||
);
|
||||
self.add_primitive(clip_and_scroll, &info, Vec::new(), prim);
|
||||
}
|
||||
|
||||
pub fn add_radial_gradient(
|
||||
@ -1968,44 +1884,27 @@ impl<'a> DisplayListFlattener<'a> {
|
||||
.. *info
|
||||
};
|
||||
|
||||
if tile_spacing != LayoutSize::zero() {
|
||||
let prim_infos = info.decompose(
|
||||
let prim = BrushPrimitive::new(
|
||||
BrushKind::RadialGradient {
|
||||
stops_range: stops,
|
||||
extend_mode,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
64 * 64,
|
||||
);
|
||||
visible_tiles: Vec::new(),
|
||||
},
|
||||
None,
|
||||
);
|
||||
|
||||
if !prim_infos.is_empty() {
|
||||
for prim_info in prim_infos {
|
||||
self.add_radial_gradient_impl(
|
||||
clip_and_scroll,
|
||||
&prim_info,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.add_radial_gradient_impl(
|
||||
self.add_primitive(
|
||||
clip_and_scroll,
|
||||
&info,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
stops,
|
||||
extend_mode,
|
||||
gradient_index,
|
||||
stretch_size,
|
||||
Vec::new(),
|
||||
PrimitiveContainer::Brush(prim),
|
||||
);
|
||||
}
|
||||
|
||||
@ -2208,72 +2107,6 @@ pub fn build_scene(config: &FrameBuilderConfig, request: SceneRequest) -> BuiltS
|
||||
}
|
||||
}
|
||||
|
||||
trait PrimitiveInfoTiler {
|
||||
fn decompose(
|
||||
&self,
|
||||
tile_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
max_prims: usize,
|
||||
) -> Vec<LayoutPrimitiveInfo>;
|
||||
}
|
||||
|
||||
impl PrimitiveInfoTiler for LayoutPrimitiveInfo {
|
||||
fn decompose(
|
||||
&self,
|
||||
tile_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
max_prims: usize,
|
||||
) -> Vec<LayoutPrimitiveInfo> {
|
||||
let mut prims = Vec::new();
|
||||
let tile_repeat = tile_size + tile_spacing;
|
||||
|
||||
if tile_repeat.width <= 0.0 ||
|
||||
tile_repeat.height <= 0.0 {
|
||||
return prims;
|
||||
}
|
||||
|
||||
if tile_repeat.width < self.rect.size.width ||
|
||||
tile_repeat.height < self.rect.size.height {
|
||||
let clip_rect = self.clip_rect
|
||||
.intersection(&self.rect)
|
||||
.unwrap_or_else(LayoutRect::zero);
|
||||
let rect_p0 = self.rect.origin;
|
||||
let rect_p1 = self.rect.bottom_right();
|
||||
|
||||
let mut y0 = rect_p0.y;
|
||||
while y0 < rect_p1.y {
|
||||
let mut x0 = rect_p0.x;
|
||||
|
||||
while x0 < rect_p1.x {
|
||||
prims.push(LayoutPrimitiveInfo {
|
||||
rect: LayoutRect::new(
|
||||
LayoutPoint::new(x0, y0),
|
||||
tile_size,
|
||||
),
|
||||
clip_rect,
|
||||
is_backface_visible: self.is_backface_visible,
|
||||
tag: self.tag,
|
||||
});
|
||||
|
||||
// Mostly a safety against a crazy number of primitives
|
||||
// being generated. If we exceed that amount, just bail
|
||||
// out and only draw the maximum amount.
|
||||
if prims.len() > max_prims {
|
||||
warn!("too many prims found due to repeat/tile. dropping extra prims!");
|
||||
return prims;
|
||||
}
|
||||
|
||||
x0 += tile_repeat.width;
|
||||
}
|
||||
|
||||
y0 += tile_repeat.height;
|
||||
}
|
||||
}
|
||||
|
||||
prims
|
||||
}
|
||||
}
|
||||
|
||||
/// Properties of a stacking context that are maintained
|
||||
/// during creation of the scene. These structures are
|
||||
/// not persisted after the initial scene build.
|
||||
|
@ -163,7 +163,7 @@ impl PicturePrimitive {
|
||||
Some(PictureCompositeMode::Filter(ref mut filter)) => {
|
||||
match *filter {
|
||||
FilterOp::Opacity(ref binding, ref mut value) => {
|
||||
*value = properties.resolve_float(binding, *value);
|
||||
*value = properties.resolve_float(binding);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ impl OpacityBinding {
|
||||
let mut new_opacity = 1.0;
|
||||
|
||||
for binding in &self.bindings {
|
||||
let opacity = scene_properties.resolve_float(binding, 1.0);
|
||||
let opacity = scene_properties.resolve_float(binding);
|
||||
new_opacity = new_opacity * opacity;
|
||||
}
|
||||
|
||||
@ -249,6 +249,11 @@ pub struct VisibleImageTile {
|
||||
pub edge_flags: EdgeAaSegmentMask,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VisibleGradientTile {
|
||||
pub handle: GpuCacheHandle,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BrushKind {
|
||||
Solid {
|
||||
@ -285,6 +290,8 @@ pub enum BrushKind {
|
||||
end_radius: f32,
|
||||
ratio_xy: f32,
|
||||
stretch_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
visible_tiles: Vec<VisibleGradientTile>,
|
||||
},
|
||||
LinearGradient {
|
||||
gradient_index: CachedGradientIndex,
|
||||
@ -295,6 +302,8 @@ pub enum BrushKind {
|
||||
start_point: LayoutPoint,
|
||||
end_point: LayoutPoint,
|
||||
stretch_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
visible_tiles: Vec<VisibleGradientTile>,
|
||||
},
|
||||
Border {
|
||||
request: ImageRequest,
|
||||
@ -1423,7 +1432,7 @@ impl PrimitiveStore {
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
) {
|
||||
let mut is_tiled_image = false;
|
||||
let mut is_tiled = false;
|
||||
let metadata = &mut self.cpu_metadata[prim_index.0];
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
@ -1467,7 +1476,7 @@ impl PrimitiveStore {
|
||||
// Set if we need to request the source image from the cache this frame.
|
||||
if let Some(image_properties) = image_properties {
|
||||
*current_epoch = image_properties.epoch;
|
||||
is_tiled_image = image_properties.tiling.is_some();
|
||||
is_tiled = image_properties.tiling.is_some();
|
||||
|
||||
// If the opacity changed, invalidate the GPU cache so that
|
||||
// the new color for this primitive gets uploaded.
|
||||
@ -1481,7 +1490,7 @@ impl PrimitiveStore {
|
||||
image_properties.descriptor.is_opaque &&
|
||||
opacity_binding.current == 1.0;
|
||||
|
||||
if *tile_spacing != LayoutSize::zero() && !is_tiled_image {
|
||||
if *tile_spacing != LayoutSize::zero() && !is_tiled {
|
||||
*source = ImageSource::Cache {
|
||||
// Size in device-pixels we need to allocate in render task cache.
|
||||
size: DeviceIntSize::new(
|
||||
@ -1496,7 +1505,7 @@ impl PrimitiveStore {
|
||||
// we need to pre-render it to the render task cache.
|
||||
if let Some(rect) = sub_rect {
|
||||
// We don't properly support this right now.
|
||||
debug_assert!(!is_tiled_image);
|
||||
debug_assert!(!is_tiled);
|
||||
*source = ImageSource::Cache {
|
||||
// Size in device-pixels we need to allocate in render task cache.
|
||||
size: rect.size,
|
||||
@ -1698,29 +1707,107 @@ impl PrimitiveStore {
|
||||
);
|
||||
}
|
||||
}
|
||||
BrushKind::RadialGradient { gradient_index, stops_range, .. } => {
|
||||
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
|
||||
let gradient_builder = GradientGpuBlockBuilder::new(
|
||||
stops_range,
|
||||
pic_context.display_list,
|
||||
);
|
||||
gradient_builder.build(
|
||||
false,
|
||||
&mut request,
|
||||
BrushKind::RadialGradient {
|
||||
gradient_index,
|
||||
stops_range,
|
||||
center,
|
||||
start_radius,
|
||||
end_radius,
|
||||
ratio_xy,
|
||||
extend_mode,
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
ref mut visible_tiles,
|
||||
..
|
||||
} => {
|
||||
build_gradient_stops_request(
|
||||
gradient_index,
|
||||
stops_range,
|
||||
false,
|
||||
frame_state,
|
||||
pic_context,
|
||||
);
|
||||
|
||||
if tile_spacing != LayoutSize::zero() {
|
||||
is_tiled = true;
|
||||
|
||||
decompose_repeated_primitive(
|
||||
visible_tiles,
|
||||
metadata,
|
||||
&stretch_size,
|
||||
&tile_spacing,
|
||||
prim_run_context,
|
||||
frame_context,
|
||||
frame_state,
|
||||
&mut |rect, clip_rect, mut request| {
|
||||
request.push(*rect);
|
||||
request.push(*clip_rect);
|
||||
request.push([
|
||||
center.x,
|
||||
center.y,
|
||||
start_radius,
|
||||
end_radius,
|
||||
]);
|
||||
request.push([
|
||||
ratio_xy,
|
||||
pack_as_float(extend_mode as u32),
|
||||
stretch_size.width,
|
||||
stretch_size.height,
|
||||
]);
|
||||
request.write_segment(*rect, [0.0; 4]);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
BrushKind::LinearGradient { gradient_index, stops_range, reverse_stops, .. } => {
|
||||
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
|
||||
let gradient_builder = GradientGpuBlockBuilder::new(
|
||||
stops_range,
|
||||
pic_context.display_list,
|
||||
);
|
||||
gradient_builder.build(
|
||||
reverse_stops,
|
||||
&mut request,
|
||||
BrushKind::LinearGradient {
|
||||
gradient_index,
|
||||
stops_range,
|
||||
reverse_stops,
|
||||
start_point,
|
||||
end_point,
|
||||
extend_mode,
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
ref mut visible_tiles,
|
||||
..
|
||||
} => {
|
||||
|
||||
build_gradient_stops_request(
|
||||
gradient_index,
|
||||
stops_range,
|
||||
reverse_stops,
|
||||
frame_state,
|
||||
pic_context,
|
||||
);
|
||||
|
||||
if tile_spacing != LayoutSize::zero() {
|
||||
is_tiled = true;
|
||||
|
||||
decompose_repeated_primitive(
|
||||
visible_tiles,
|
||||
metadata,
|
||||
&stretch_size,
|
||||
&tile_spacing,
|
||||
prim_run_context,
|
||||
frame_context,
|
||||
frame_state,
|
||||
&mut |rect, clip_rect, mut request| {
|
||||
request.push(*rect);
|
||||
request.push(*clip_rect);
|
||||
request.push([
|
||||
start_point.x,
|
||||
start_point.y,
|
||||
end_point.x,
|
||||
end_point.y,
|
||||
]);
|
||||
request.push([
|
||||
pack_as_float(extend_mode as u32),
|
||||
stretch_size.width,
|
||||
stretch_size.height,
|
||||
0.0,
|
||||
]);
|
||||
request.write_segment(*rect, [0.0; 4]);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1751,7 +1838,7 @@ impl PrimitiveStore {
|
||||
}
|
||||
}
|
||||
|
||||
if is_tiled_image {
|
||||
if is_tiled {
|
||||
// we already requested each tile's gpu data.
|
||||
return;
|
||||
}
|
||||
@ -2480,6 +2567,80 @@ impl PrimitiveStore {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_gradient_stops_request(
|
||||
gradient_index: CachedGradientIndex,
|
||||
stops_range: ItemRange<GradientStop>,
|
||||
reverse_stops: bool,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
pic_context: &PictureContext
|
||||
) {
|
||||
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
|
||||
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
|
||||
let gradient_builder = GradientGpuBlockBuilder::new(
|
||||
stops_range,
|
||||
pic_context.display_list,
|
||||
);
|
||||
gradient_builder.build(
|
||||
reverse_stops,
|
||||
&mut request,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn decompose_repeated_primitive(
|
||||
visible_tiles: &mut Vec<VisibleGradientTile>,
|
||||
metadata: &mut PrimitiveMetadata,
|
||||
stretch_size: &LayoutSize,
|
||||
tile_spacing: &LayoutSize,
|
||||
prim_run_context: &PrimitiveRunContext,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
callback: &mut FnMut(&LayoutRect, &LayoutRect, GpuDataRequest),
|
||||
) {
|
||||
visible_tiles.clear();
|
||||
|
||||
// Tighten the clip rect because decomposing the repeated image can
|
||||
// produce primitives that are partially covering the original image
|
||||
// rect and we want to clip these extra parts out.
|
||||
let tight_clip_rect = metadata.local_clip_rect.intersection(&metadata.local_rect).unwrap();
|
||||
|
||||
let visible_rect = compute_conservative_visible_rect(
|
||||
prim_run_context,
|
||||
frame_context,
|
||||
&tight_clip_rect
|
||||
);
|
||||
let stride = *stretch_size + *tile_spacing;
|
||||
|
||||
for_each_repetition(
|
||||
&metadata.local_rect,
|
||||
&visible_rect,
|
||||
&stride,
|
||||
&mut |origin, _| {
|
||||
|
||||
let mut handle = GpuCacheHandle::new();
|
||||
if let Some(request) = frame_state.gpu_cache.request(&mut handle) {
|
||||
let rect = LayoutRect {
|
||||
origin: *origin,
|
||||
size: *stretch_size,
|
||||
};
|
||||
|
||||
callback(&rect, &tight_clip_rect, request);
|
||||
}
|
||||
|
||||
visible_tiles.push(VisibleGradientTile { handle });
|
||||
}
|
||||
);
|
||||
|
||||
if visible_tiles.is_empty() {
|
||||
// At this point if we don't have tiles to show it means we could probably
|
||||
// have done a better a job at culling during an earlier stage.
|
||||
// Clearing the screen rect has the effect of "culling out" the primitive
|
||||
// from the point of view of the batch builder, and ensures we don't hit
|
||||
// assertions later on because we didn't request any image.
|
||||
metadata.screen_rect = None;
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_conservative_visible_rect(
|
||||
prim_run_context: &PrimitiveRunContext,
|
||||
frame_context: &FrameBuildingContext,
|
||||
|
@ -54,15 +54,11 @@ impl SceneProperties {
|
||||
) -> LayoutTransform {
|
||||
match *property {
|
||||
PropertyBinding::Value(value) => value,
|
||||
PropertyBinding::Binding(ref key) => {
|
||||
PropertyBinding::Binding(ref key, v) => {
|
||||
self.transform_properties
|
||||
.get(&key.id)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
warn!("Property binding has an invalid value.");
|
||||
debug!("key={:?}", key);
|
||||
LayoutTransform::identity()
|
||||
})
|
||||
.unwrap_or(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,20 +66,15 @@ impl SceneProperties {
|
||||
/// Get the current value for a float property.
|
||||
pub fn resolve_float(
|
||||
&self,
|
||||
property: &PropertyBinding<f32>,
|
||||
default_value: f32
|
||||
property: &PropertyBinding<f32>
|
||||
) -> f32 {
|
||||
match *property {
|
||||
PropertyBinding::Value(value) => value,
|
||||
PropertyBinding::Binding(ref key) => {
|
||||
PropertyBinding::Binding(ref key, v) => {
|
||||
self.float_properties
|
||||
.get(&key.id)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
warn!("Property binding has an invalid value.");
|
||||
debug!("key={:?}", key);
|
||||
default_value
|
||||
})
|
||||
.unwrap_or(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1078,10 +1078,13 @@ impl<T> PropertyBindingKey<T> {
|
||||
/// A binding property can either be a specific value
|
||||
/// (the normal, non-animated case) or point to a binding location
|
||||
/// to fetch the current value from.
|
||||
/// Note that Binding has also a non-animated value, the value is
|
||||
/// used for the case where the animation is still in-delay phase
|
||||
/// (i.e. the animation doesn't produce any animation values).
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum PropertyBinding<T> {
|
||||
Value(T),
|
||||
Binding(PropertyBindingKey<T>),
|
||||
Binding(PropertyBindingKey<T>, T),
|
||||
}
|
||||
|
||||
impl<T> From<T> for PropertyBinding<T> {
|
||||
@ -1090,12 +1093,6 @@ impl<T> From<T> for PropertyBinding<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<PropertyBindingKey<T>> for PropertyBinding<T> {
|
||||
fn from(key: PropertyBindingKey<T>) -> PropertyBinding<T> {
|
||||
PropertyBinding::Binding(key)
|
||||
}
|
||||
}
|
||||
|
||||
/// The current value of an animated property. This is
|
||||
/// supplied by the calling code.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
|
@ -1 +1 @@
|
||||
4811a6e7c06f9dd1b4056e5f5e66983842983ba0
|
||||
9d20df4e76e3b19c569fd89965f70a2c278ff0c8
|
||||
|
@ -25,6 +25,12 @@ fn deserialize_blob(blob: &[u8]) -> Result<ColorU, ()> {
|
||||
};
|
||||
}
|
||||
|
||||
// perform floor((x * a) / 255. + 0.5) see "Three wrongs make a right" for deriviation
|
||||
fn premul(x: u8, a: u8) -> u8 {
|
||||
let t = (x as u32) * (a as u32) + 128;
|
||||
((t + (t >> 8)) >> 8) as u8
|
||||
}
|
||||
|
||||
// This is the function that applies the deserialized drawing commands and generates
|
||||
// actual image data.
|
||||
fn render_blob(
|
||||
@ -73,10 +79,11 @@ fn render_blob(
|
||||
|
||||
match descriptor.format {
|
||||
ImageFormat::BGRA8 => {
|
||||
texels[((y * descriptor.width + x) * 4 + 0) as usize] = color.b * checker + tc;
|
||||
texels[((y * descriptor.width + x) * 4 + 1) as usize] = color.g * checker + tc;
|
||||
texels[((y * descriptor.width + x) * 4 + 2) as usize] = color.r * checker + tc;
|
||||
texels[((y * descriptor.width + x) * 4 + 3) as usize] = color.a * checker + tc;
|
||||
let a = color.a * checker + tc;
|
||||
texels[((y * descriptor.width + x) * 4 + 0) as usize] = premul(color.b * checker + tc, a);
|
||||
texels[((y * descriptor.width + x) * 4 + 1) as usize] = premul(color.g * checker + tc, a);
|
||||
texels[((y * descriptor.width + x) * 4 + 2) as usize] = premul(color.r * checker + tc, a);
|
||||
texels[((y * descriptor.width + x) * 4 + 3) as usize] = a;
|
||||
}
|
||||
ImageFormat::R8 => {
|
||||
texels[(y * descriptor.width + x) as usize] = color.a * checker + tc;
|
||||
|
@ -45,27 +45,21 @@ impl SceneProperties {
|
||||
|
||||
match property {
|
||||
PropertyBinding::Value(matrix) => matrix,
|
||||
PropertyBinding::Binding(ref key) => self.transform_properties
|
||||
PropertyBinding::Binding(ref key, v) => self.transform_properties
|
||||
.get(&key.id)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
println!("Property binding {:?} has an invalid value.", key);
|
||||
LayoutTransform::identity()
|
||||
}),
|
||||
.unwrap_or(v),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current value for a float property.
|
||||
pub fn resolve_float(&self, property: &PropertyBinding<f32>, default_value: f32) -> f32 {
|
||||
pub fn resolve_float(&self, property: &PropertyBinding<f32>) -> f32 {
|
||||
match *property {
|
||||
PropertyBinding::Value(value) => value,
|
||||
PropertyBinding::Binding(ref key) => self.float_properties
|
||||
PropertyBinding::Binding(ref key, v) => self.float_properties
|
||||
.get(&key.id)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
println!("Property binding {:?} has an invalid value.", key);
|
||||
default_value
|
||||
}),
|
||||
.unwrap_or(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ fn write_stacking_context(
|
||||
FilterOp::Invert(x) => { filters.push(Yaml::String(format!("invert({})", x))) }
|
||||
FilterOp::Opacity(x, _) => {
|
||||
filters.push(Yaml::String(format!("opacity({})",
|
||||
properties.resolve_float(&x, 1.0))))
|
||||
properties.resolve_float(&x))))
|
||||
}
|
||||
FilterOp::Saturate(x) => { filters.push(Yaml::String(format!("saturate({})", x))) }
|
||||
FilterOp::Sepia(x) => { filters.push(Yaml::String(format!("sepia({})", x))) }
|
||||
|
Loading…
Reference in New Issue
Block a user