Bug 1409736 - Update webrender to commit d741f472dd3d6c3441646f7bf4e714c71bea39b7. r=jrmuizel

MozReview-Commit-ID: FhFX2PAHwU

--HG--
extra : rebase_source : 34c2d4bedadc940cf4a16dbdd6e0755eee909889
This commit is contained in:
Kartikaya Gupta 2017-10-23 09:46:47 -04:00
parent 20baeb4811
commit 5e25afb9c5
27 changed files with 627 additions and 331 deletions

View File

@ -175,4 +175,4 @@ Troubleshooting tips:
-------------------------------------------------------------------------------
The version of WebRender currently in the tree is:
7892f5364bc4d35c7a9b42949f0ace4cc54f8b3c
d741f472dd3d6c3441646f7bf4e714c71bea39b7

View File

@ -1,6 +1,6 @@
[package]
name = "webrender"
version = "0.52.1"
version = "0.53.0"
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/webrender"

View File

@ -218,7 +218,11 @@ impl Example for App {
rect: (75, 75).by(100, 100),
repeat: false,
};
let complex = ComplexClipRegion::new((50, 50).to(150, 150), BorderRadius::uniform(20.0));
let complex = ComplexClipRegion::new(
(50, 50).to(150, 150),
BorderRadius::uniform(20.0),
ClipMode::Clip
);
let id = builder.define_clip(None, bounds, vec![complex], Some(mask));
builder.push_clip_id(id);
@ -339,7 +343,7 @@ impl Example for App {
color,
blur_radius,
spread_radius,
simple_border_radius,
BorderRadius::uniform(simple_border_radius),
box_shadow_type,
);
}

View File

@ -17,8 +17,8 @@ use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::sync::Arc;
use std::sync::mpsc::{channel, Receiver, Sender};
use webrender::api::{self, DisplayListBuilder, DocumentId, LayoutSize, PipelineId, RenderApi,
ResourceUpdates};
use webrender::api::{self, DeviceUintRect, DisplayListBuilder, DocumentId, LayoutSize, PipelineId,
RenderApi, ResourceUpdates};
// This example shows how to implement a very basic BlobImageRenderer that can only render
// a checkerboard pattern.
@ -145,7 +145,7 @@ impl api::BlobImageRenderer for CheckerboardRenderer {
.insert(key, Arc::new(deserialize_blob(&cmds[..]).unwrap()));
}
fn update(&mut self, key: api::ImageKey, cmds: api::BlobImageData) {
fn update(&mut self, key: api::ImageKey, cmds: api::BlobImageData, _dirty_rect: Option<DeviceUintRect>) {
// Here, updating is just replacing the current version of the commands with
// the new one (no incremental updates).
self.image_cmds

View File

@ -22,12 +22,18 @@ impl Notifier {
}
impl RenderNotifier for Notifier {
fn new_frame_ready(&mut self) {
fn clone(&self) -> Box<RenderNotifier> {
Box::new(Notifier {
window_proxy: self.window_proxy.clone(),
})
}
fn new_frame_ready(&self) {
#[cfg(not(target_os = "android"))]
self.window_proxy.wakeup_event_loop();
}
fn new_scroll_frame_ready(&mut self, _composite_needed: bool) {
fn new_scroll_frame_ready(&self, _composite_needed: bool) {
#[cfg(not(target_os = "android"))]
self.window_proxy.wakeup_event_loop();
}
@ -125,13 +131,11 @@ pub fn main_wrapper(example: &mut Example, options: Option<webrender::RendererOp
};
let size = DeviceUintSize::new(width, height);
let (mut renderer, sender) = webrender::Renderer::new(gl.clone(), opts).unwrap();
let notifier = Box::new(Notifier::new(window.create_window_proxy()));
let (mut renderer, sender) = webrender::Renderer::new(gl.clone(), notifier, opts).unwrap();
let api = sender.create_api();
let document_id = api.add_document(size);
let notifier = Box::new(Notifier::new(window.create_window_proxy()));
renderer.set_render_notifier(notifier);
if let Some(external_image_handler) = example.get_external_image_handler() {
renderer.set_external_image_handler(external_image_handler);
}

View File

@ -14,12 +14,15 @@ flat varying vec4 vClipCenter_Radius_BL;
struct BrushPrimitive {
float clip_mode;
float radius;
vec2 radius_tl;
vec2 radius_tr;
vec2 radius_br;
vec2 radius_bl;
};
BrushPrimitive fetch_brush_primitive(int address) {
vec4 data = fetch_from_resource_cache_1(address);
return BrushPrimitive(data.x, data.y);
vec4 data[3] = fetch_from_resource_cache_3(address);
return BrushPrimitive(data[0].x, data[1].xy, data[1].zw, data[2].xy, data[2].zw);
}
void brush_vs(int prim_address, vec4 prim_rect) {
@ -29,11 +32,10 @@ void brush_vs(int prim_address, vec4 prim_rect) {
// Write clip parameters
vClipMode = prim.clip_mode;
vec2 r = vec2(prim.radius);
vClipCenter_Radius_TL = vec4(prim_rect.xy + vec2(r.x, r.y), r);
vClipCenter_Radius_TR = vec4(prim_rect.zy + vec2(-r.x, r.y), r);
vClipCenter_Radius_BR = vec4(prim_rect.zw + vec2(-r.x, -r.y), r);
vClipCenter_Radius_BL = vec4(prim_rect.xw + vec2(r.x, -r.y), r);
vClipCenter_Radius_TL = vec4(prim_rect.xy + prim.radius_tl, prim.radius_tl);
vClipCenter_Radius_TR = vec4(prim_rect.zy + vec2(-prim.radius_tr.x, prim.radius_tr.y), prim.radius_tr);
vClipCenter_Radius_BR = vec4(prim_rect.zw - prim.radius_br, prim.radius_br);
vClipCenter_Radius_BL = vec4(prim_rect.xw + vec2(prim.radius_bl.x, -prim.radius_bl.y), prim.radius_bl);
}
#endif

View File

@ -20,16 +20,14 @@ flat varying int vBlurRadius;
in int aBlurRenderTaskAddress;
in int aBlurSourceTaskAddress;
in int aBlurDirection;
in vec4 aBlurRegion;
void main(void) {
RenderTaskData task = fetch_render_task(aBlurRenderTaskAddress);
RenderTaskData src_task = fetch_render_task(aBlurSourceTaskAddress);
vec4 local_rect = task.data0;
vec2 pos = mix(local_rect.xy,
local_rect.xy + local_rect.zw,
aPosition.xy);
vec4 src_rect = src_task.data0;
vec4 target_rect = task.data0;
#if defined WR_FEATURE_COLOR
vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0).xy);
@ -49,12 +47,20 @@ void main(void) {
break;
}
vUvRect = vec4(src_task.data0.xy + vec2(0.5),
src_task.data0.xy + src_task.data0.zw - vec2(0.5));
vUvRect = vec4(src_rect.xy + vec2(0.5),
src_rect.xy + src_rect.zw - vec2(0.5));
vUvRect /= texture_size.xyxy;
vec2 uv0 = src_task.data0.xy / texture_size;
vec2 uv1 = (src_task.data0.xy + src_task.data0.zw) / texture_size;
if (aBlurRegion.z > 0.0) {
vec4 blur_region = aBlurRegion * uDevicePixelRatio;
src_rect = vec4(src_rect.xy + blur_region.xy, blur_region.zw);
target_rect = vec4(target_rect.xy + blur_region.xy, blur_region.zw);
}
vec2 pos = target_rect.xy + target_rect.zw * aPosition.xy;
vec2 uv0 = src_rect.xy / texture_size;
vec2 uv1 = (src_rect.xy + src_rect.zw) / texture_size;
vUv.xy = mix(uv0, uv1, aPosition.xy);
gl_Position = uTransform * vec4(pos, 0.0, 1.0);

View File

@ -15,6 +15,7 @@ use util::{lerp, pack_as_float};
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum BorderCornerInstance {
None,
Single, // Single instance needed - corner styles are same or similar.
Double, // Different corner styles. Draw two instances, one per style.
}
@ -128,8 +129,8 @@ impl NormalBorderHelpers for NormalBorder {
corner: BorderCorner,
border_rect: &LayerRect,
) -> BorderCornerKind {
// If either width is zero, a corner isn't formed.
if width0 == 0.0 || width1 == 0.0 {
// If both widths are zero, a corner isn't formed.
if width0 == 0.0 && width1 == 0.0 {
return BorderCornerKind::None;
}
@ -139,9 +140,13 @@ impl NormalBorderHelpers for NormalBorder {
}
match (edge0.style, edge1.style) {
// If either edge is none or hidden, no corner is needed.
(BorderStyle::None, _) | (_, BorderStyle::None) => BorderCornerKind::None,
(BorderStyle::Hidden, _) | (_, BorderStyle::Hidden) => BorderCornerKind::None,
// If both edges are none or hidden, no corner is needed.
(BorderStyle::None, BorderStyle::None) |
(BorderStyle::None, BorderStyle::Hidden) |
(BorderStyle::Hidden, BorderStyle::None) |
(BorderStyle::Hidden, BorderStyle::Hidden) => {
BorderCornerKind::None
}
// If both borders are solid, we can draw them with a simple rectangle if
// both the colors match and there is no radius.
@ -429,16 +434,19 @@ impl FrameBuilder {
let mut corner_instances = [BorderCornerInstance::Single; 4];
for (i, corner) in corners.iter().enumerate() {
match corner {
&BorderCornerKind::Mask(corner_data, corner_radius, widths, kind) => {
match *corner {
BorderCornerKind::Mask(corner_data, corner_radius, widths, kind) => {
let clip_source =
BorderCornerClipSource::new(corner_data, corner_radius, widths, kind);
extra_clips.push(ClipSource::BorderCorner(clip_source));
}
&BorderCornerKind::Clip(instance_kind) => {
BorderCornerKind::Clip(instance_kind) => {
corner_instances[i] = instance_kind;
}
_ => {}
BorderCornerKind::Solid => {}
BorderCornerKind::None => {
corner_instances[i] = BorderCornerInstance::None;
}
}
}

View File

@ -3,14 +3,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, ImageRendering, LayerPoint};
use api::{LayerRect, LayerSize, LayerToWorldTransform, LayoutPoint, LayoutVector2D, LocalClip};
use api::{ClipMode, LayerRect, LayerSize};
use api::{LayerToWorldTransform, LayoutPoint, LayoutVector2D, LocalClip};
use border::BorderCornerClipSource;
use ellipse::Ellipse;
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use prim_store::{ClipData, ImageMaskData};
use resource_cache::ResourceCache;
use std::ops::Not;
use util::{extract_inner_rect_safe, TransformedRect};
const MAX_CLIP: f32 = 1000000.0;
@ -61,24 +61,6 @@ impl ClipRegion {
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ClipMode {
Clip, // Pixels inside the region are visible.
ClipOut, // Pixels outside the region are visible.
}
impl Not for ClipMode {
type Output = ClipMode;
fn not(self) -> ClipMode {
match self {
ClipMode::Clip => ClipMode::ClipOut,
ClipMode::ClipOut => ClipMode::Clip,
}
}
}
#[derive(Debug)]
pub enum ClipSource {
Rectangle(LayerRect),
@ -105,7 +87,7 @@ impl From<ClipRegion> for ClipSources {
clips.push(ClipSource::RoundedRectangle(
complex.rect,
complex.radii,
ClipMode::Clip,
complex.mode,
));
}

View File

@ -9,7 +9,7 @@ use api::{HitTestResult, ImageDisplayItem, ItemRange, LayerPoint, LayerPrimitive
use api::{LayerSize, LayerToScrollTransform, LayerVector2D, LayoutSize, LayoutTransform};
use api::{LocalClip, PipelineId, ScrollClamping, ScrollEventPhase, ScrollLayerState};
use api::{ScrollLocation, ScrollPolicy, ScrollSensitivity, SpecificDisplayItem, StackingContext};
use api::{TileOffset, TransformStyle, WorldPoint};
use api::{ClipMode, TileOffset, TransformStyle, WorldPoint};
use clip::ClipRegion;
use clip_scroll_tree::{ClipScrollTree, ScrollStates};
use euclid::rect;
@ -1151,7 +1151,12 @@ fn try_to_add_rectangle_splitting_on_clip(
let inner_unclipped_rect = match &info.local_clip {
&LocalClip::Rect(_) => return false,
&LocalClip::RoundedRect(_, ref region) => region.get_inner_rect_full(),
&LocalClip::RoundedRect(_, ref region) => {
if region.mode == ClipMode::ClipOut {
return false;
}
region.get_inner_rect_full()
}
};
let inner_unclipped_rect = match inner_unclipped_rect {
Some(rect) => rect,

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, BuiltDisplayList};
use api::{ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF};
use api::{ClipMode, ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF, LayoutSize};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
use api::{ExtendMode, FilterOp, FontInstance, FontRenderMode};
use api::{GlyphInstance, GlyphOptions, GradientStop, HitTestFlags, HitTestItem, HitTestResult};
@ -14,7 +14,7 @@ use api::{ScrollSensitivity, Shadow, TileOffset, TransformStyle};
use api::{WorldPixel, WorldPoint, YuvColorSpace, YuvData, device_length};
use app_units::Au;
use border::ImageBorderSegment;
use clip::{ClipMode, ClipRegion, ClipSource, ClipSources, ClipStore, Contains};
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore, Contains};
use clip_scroll_node::{ClipInfo, ClipScrollNode, NodeType};
use clip_scroll_tree::{ClipScrollTree, CoordinateSystemId};
use euclid::{SideOffsets2D, TypedTransform3D, vec2, vec3};
@ -29,7 +29,7 @@ use prim_store::{PrimitiveContainer, PrimitiveIndex};
use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu};
use prim_store::{RectanglePrimitive, TextRunPrimitiveCpu};
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
use render_task::{AlphaRenderItem, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation};
use render_task::{AlphaRenderItem, ClearMode, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation};
use render_task::RenderTaskTree;
use resource_cache::ResourceCache;
use scene::ScenePipeline;
@ -40,6 +40,9 @@ use tiling::{PackedLayer, PackedLayerIndex, PrimitiveFlags, PrimitiveRunCmd, Ren
use tiling::{RenderTargetContext, ScrollbarPrimitive, StackingContext};
use util::{self, pack_as_float, RectHelpers, recycle_vec};
// The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
const BLUR_SAMPLE_SCALE: f32 = 3.0;
/// Construct a polygon from stacking context boundaries.
/// `anchor` here is an index that's going to be preserved in all the
/// splits of the polygon.
@ -242,7 +245,7 @@ impl FrameBuilder {
clip_sources.push(ClipSource::RoundedRectangle(
region.rect,
region.radii,
ClipMode::Clip,
region.mode,
));
}
@ -557,7 +560,7 @@ impl FrameBuilder {
clip_and_scroll: ClipAndScrollInfo,
info: &LayerPrimitiveInfo,
) {
let prim = PicturePrimitive::new_shadow(shadow, RenderTargetKind::Color);
let prim = PicturePrimitive::new_text_shadow(shadow);
// Create an empty shadow primitive. Insert it into
// the draw lists immediately so that it will be drawn
@ -587,7 +590,7 @@ impl FrameBuilder {
// is then used when blitting the shadow to the final location.
let metadata = &mut self.prim_store.cpu_metadata[prim_index.0];
let prim = &self.prim_store.cpu_pictures[metadata.cpu_prim_index.0];
let shadow = prim.as_shadow();
let shadow = prim.as_text_shadow();
metadata.local_rect = metadata.local_rect.translate(&shadow.offset);
}
@ -676,7 +679,7 @@ impl FrameBuilder {
for (idx, &(shadow_prim_index, _)) in self.shadow_prim_stack.iter().enumerate() {
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
let picture = &self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
let shadow = picture.as_shadow();
let shadow = picture.as_text_shadow();
if shadow.blur_radius == 0.0 {
fast_shadow_prims.push((idx, shadow.clone()));
}
@ -719,7 +722,7 @@ impl FrameBuilder {
debug_assert_eq!(shadow_metadata.prim_kind, PrimitiveKind::Picture);
let picture =
&mut self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
let blur_radius = picture.as_shadow().blur_radius;
let blur_radius = picture.as_text_shadow().blur_radius;
// Only run real blurs here (fast path zero blurs are handled above).
if blur_radius > 0.0 {
@ -1183,7 +1186,7 @@ impl FrameBuilder {
for (idx, &(shadow_prim_index, _)) in self.shadow_prim_stack.iter().enumerate() {
let shadow_metadata = &self.prim_store.cpu_metadata[shadow_prim_index.0];
let picture_prim = &self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
let shadow = picture_prim.as_shadow();
let shadow = picture_prim.as_text_shadow();
if shadow.blur_radius == 0.0 {
let mut text_prim = prim.clone();
text_prim.font.color = shadow.color.into();
@ -1238,7 +1241,7 @@ impl FrameBuilder {
&mut self.prim_store.cpu_pictures[shadow_metadata.cpu_prim_index.0];
// Only run real blurs here (fast path zero blurs are handled above).
let blur_radius = picture_prim.as_shadow().blur_radius;
let blur_radius = picture_prim.as_text_shadow().blur_radius;
if blur_radius > 0.0 {
let shadow_rect = rect.inflate(
blur_radius,
@ -1258,7 +1261,7 @@ impl FrameBuilder {
color: &ColorF,
blur_radius: f32,
spread_radius: f32,
border_radius: f32,
border_radius: BorderRadius,
clip_mode: BoxShadowClipMode,
) {
if color.a == 0.0 {
@ -1274,15 +1277,11 @@ impl FrameBuilder {
}
};
// Adjust the shadow box radius as per:
// https://drafts.csswg.org/css-backgrounds-3/#shadow-shape
let sharpness_scale = if border_radius < spread_radius {
let r = border_radius / spread_amount;
1.0 + (r - 1.0) * (r - 1.0) * (r - 1.0)
} else {
1.0
};
let shadow_radius = (border_radius + spread_amount * sharpness_scale).max(0.0);
let shadow_radius = adjust_border_radius_for_box_shadow(
border_radius,
spread_amount,
spread_radius
);
let shadow_rect = prim_info.rect
.translate(box_offset)
.inflate(spread_amount, spread_amount);
@ -1295,7 +1294,7 @@ impl FrameBuilder {
// TODO(gw): Add a fast path for ClipOut + zero border radius!
clips.push(ClipSource::RoundedRectangle(
prim_info.rect,
BorderRadius::uniform(border_radius),
border_radius,
ClipMode::ClipOut
));
@ -1303,14 +1302,18 @@ impl FrameBuilder {
shadow_rect,
LocalClip::RoundedRect(
shadow_rect,
ComplexClipRegion::new(shadow_rect, BorderRadius::uniform(shadow_radius)),
ComplexClipRegion::new(
shadow_rect,
shadow_radius,
ClipMode::Clip,
),
),
)
}
BoxShadowClipMode::Inset => {
clips.push(ClipSource::RoundedRectangle(
shadow_rect,
BorderRadius::uniform(shadow_radius),
shadow_radius,
ClipMode::ClipOut
));
@ -1318,7 +1321,11 @@ impl FrameBuilder {
prim_info.rect,
LocalClip::RoundedRect(
prim_info.rect,
ComplexClipRegion::new(prim_info.rect, BorderRadius::uniform(border_radius)),
ComplexClipRegion::new(
prim_info.rect,
border_radius,
ClipMode::Clip
),
),
)
}
@ -1333,17 +1340,11 @@ impl FrameBuilder {
}),
);
} else {
let shadow = Shadow {
blur_radius,
color: *color,
offset: LayerVector2D::zero(),
};
let blur_offset = 2.0 * blur_radius;
let mut extra_clips = vec![];
let mut pic_prim = PicturePrimitive::new_shadow(shadow, RenderTargetKind::Alpha);
let mut blur_regions = vec![];
let pic_info = match clip_mode {
match clip_mode {
BoxShadowClipMode::Outset => {
let brush_prim = BrushPrimitive {
clip_mode: ClipMode::Clip,
@ -1362,16 +1363,72 @@ impl FrameBuilder {
PrimitiveContainer::Brush(brush_prim),
);
let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
let blur_range = BLUR_SAMPLE_SCALE * blur_radius;
let size = pic_rect.size;
let tl = LayerSize::new(
blur_radius.max(border_radius.top_left.width),
blur_radius.max(border_radius.top_left.height)
) * BLUR_SAMPLE_SCALE;
let tr = LayerSize::new(
blur_radius.max(border_radius.top_right.width),
blur_radius.max(border_radius.top_right.height)
) * BLUR_SAMPLE_SCALE;
let br = LayerSize::new(
blur_radius.max(border_radius.bottom_right.width),
blur_radius.max(border_radius.bottom_right.height)
) * BLUR_SAMPLE_SCALE;
let bl = LayerSize::new(
blur_radius.max(border_radius.bottom_left.width),
blur_radius.max(border_radius.bottom_left.height)
) * BLUR_SAMPLE_SCALE;
let max_width = tl.width.max(tr.width.max(bl.width.max(br.width)));
let max_height = tl.height.max(tr.height.max(bl.height.max(br.height)));
// Apply a conservative test that if any of the blur regions below
// will overlap, we won't bother applying the region optimization
// and will just blur the entire thing. This should only happen
// in rare cases, where either the blur radius or border radius
// is very large, in which case there's no real point in trying
// to only blur a small region anyway.
if max_width < 0.5 * size.width && max_height < 0.5 * size.height {
blur_regions.push(LayerRect::from_floats(0.0, 0.0, tl.width, tl.height));
blur_regions.push(LayerRect::from_floats(size.width - tr.width, 0.0, size.width, tr.height));
blur_regions.push(LayerRect::from_floats(size.width - br.width, size.height - br.height, size.width, size.height));
blur_regions.push(LayerRect::from_floats(0.0, size.height - bl.height, bl.width, size.height));
blur_regions.push(LayerRect::from_floats(0.0, tl.height, blur_range, size.height - bl.height));
blur_regions.push(LayerRect::from_floats(size.width - blur_range, tr.height, size.width, size.height - br.height));
blur_regions.push(LayerRect::from_floats(tl.width, 0.0, size.width - tr.width, blur_range));
blur_regions.push(LayerRect::from_floats(bl.width, size.height - blur_range, size.width - br.width, size.height));
}
let mut pic_prim = PicturePrimitive::new_box_shadow(
blur_radius,
*color,
blur_regions,
BoxShadowClipMode::Outset,
);
pic_prim.add_primitive(brush_prim_index, clip_and_scroll);
extra_clips.push(ClipSource::RoundedRectangle(
prim_info.rect,
BorderRadius::uniform(border_radius),
border_radius,
ClipMode::ClipOut,
));
let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
LayerPrimitiveInfo::new(pic_rect)
let pic_info = LayerPrimitiveInfo::new(pic_rect);
self.add_primitive(
clip_and_scroll,
&pic_info,
extra_clips,
PrimitiveContainer::Picture(pic_prim),
);
}
BoxShadowClipMode::Inset => {
let brush_prim = BrushPrimitive {
@ -1392,25 +1449,35 @@ impl FrameBuilder {
PrimitiveContainer::Brush(brush_prim),
);
let pic_rect = prim_info.rect.inflate(blur_offset, blur_offset);
// TODO(gw): Apply minimal blur regions for inset box shadows.
let mut pic_prim = PicturePrimitive::new_box_shadow(
blur_radius,
*color,
blur_regions,
BoxShadowClipMode::Inset,
);
pic_prim.add_primitive(brush_prim_index, clip_and_scroll);
extra_clips.push(ClipSource::RoundedRectangle(
prim_info.rect,
BorderRadius::uniform(border_radius),
border_radius,
ClipMode::Clip,
));
let pic_rect = prim_info.rect.inflate(blur_offset, blur_offset);
LayerPrimitiveInfo::with_clip_rect(pic_rect, prim_info.rect)
}
};
let pic_info = LayerPrimitiveInfo::with_clip_rect(pic_rect, prim_info.rect);
self.add_primitive(
clip_and_scroll,
&pic_info,
extra_clips,
PrimitiveContainer::Picture(pic_prim),
);
self.add_primitive(
clip_and_scroll,
&pic_info,
extra_clips,
PrimitiveContainer::Picture(pic_prim),
);
}
}
}
}
@ -1770,8 +1837,9 @@ impl FrameBuilder {
let transform = scroll_node.world_content_transform;
if !packed_layer.set_transform(transform) {
group.screen_bounding_rect = None;
debug!("\t\tUnable to set transform {:?}", transform);
return;
continue;
}
// Here we move the viewport rectangle into the coordinate system
@ -2045,6 +2113,8 @@ impl FrameBuilder {
current_task_id,
render_tasks,
RenderTargetKind::Color,
&[],
ClearMode::Transparent,
);
let blur_render_task_id = render_tasks.add(blur_render_task);
let item = AlphaRenderItem::HardwareComposite(
@ -2326,3 +2396,67 @@ impl FrameBuilder {
}
}
}
fn adjust_border_radius_for_box_shadow(
radius: BorderRadius,
spread_amount: f32,
spread_radius: f32,
) -> BorderRadius {
BorderRadius {
top_left: adjust_corner_for_box_shadow(
radius.top_left,
spread_radius,
spread_amount,
),
top_right: adjust_corner_for_box_shadow(
radius.top_right,
spread_radius,
spread_amount,
),
bottom_right: adjust_corner_for_box_shadow(
radius.bottom_right,
spread_radius,
spread_amount,
),
bottom_left: adjust_corner_for_box_shadow(
radius.bottom_left,
spread_radius,
spread_amount,
),
}
}
fn adjust_corner_for_box_shadow(
corner: LayoutSize,
spread_amount: f32,
spread_radius: f32,
) -> LayoutSize {
LayoutSize::new(
adjust_radius_for_box_shadow(
corner.width,
spread_radius,
spread_amount
),
adjust_radius_for_box_shadow(
corner.height,
spread_radius,
spread_amount
),
)
}
fn adjust_radius_for_box_shadow(
border_radius: f32,
spread_amount: f32,
spread_radius: f32,
) -> f32 {
// Adjust the shadow box radius as per:
// https://drafts.csswg.org/css-backgrounds-3/#shadow-shape
let sharpness_scale = if border_radius < spread_radius {
let r = border_radius / spread_amount;
1.0 + (r - 1.0) * (r - 1.0) * (r - 1.0)
} else {
1.0
};
(border_radius + spread_amount * sharpness_scale).max(0.0)
}

View File

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::LayerRect;
use gpu_cache::GpuCacheAddress;
use render_task::RenderTaskAddress;
use tiling::PackedLayerIndex;
@ -18,7 +19,7 @@ impl From<PackedLayerIndex> for PackedLayerAddress {
}
#[repr(i32)]
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub enum BlurDirection {
Horizontal = 0,
Vertical,
@ -30,6 +31,7 @@ pub struct BlurInstance {
pub task_address: RenderTaskAddress,
pub src_task_address: RenderTaskAddress,
pub blur_direction: BlurDirection,
pub region: LayerRect,
}
/// A clipping primitive drawn into the clipping mask.

View File

@ -2,9 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{ClipAndScrollInfo, Shadow};
use prim_store::PrimitiveIndex;
use render_task::RenderTaskId;
use api::{ColorF, ClipAndScrollInfo, device_length, DeviceIntSize};
use api::{BoxShadowClipMode, LayerRect, Shadow};
use frame_builder::PrimitiveContext;
use gpu_cache::GpuDataRequest;
use prim_store::{PrimitiveIndex, PrimitiveMetadata};
use render_task::{ClearMode, RenderTask, RenderTaskId, RenderTaskTree};
use tiling::RenderTargetKind;
/*
@ -25,19 +28,23 @@ pub struct PrimitiveRun {
}
#[derive(Debug)]
pub enum CompositeOp {
Shadow(Shadow),
// TODO(gw): Support other composite ops, such
// as blur, blend etc.
pub enum PictureKind {
TextShadow {
shadow: Shadow,
},
BoxShadow {
blur_radius: f32,
color: ColorF,
blur_regions: Vec<LayerRect>,
clip_mode: BoxShadowClipMode,
},
}
#[derive(Debug)]
pub struct PicturePrimitive {
pub prim_runs: Vec<PrimitiveRun>,
pub composite_op: CompositeOp,
pub render_task_id: Option<RenderTaskId>,
pub kind: RenderTargetKind,
pub kind: PictureKind,
// TODO(gw): Add a mode that specifies if this
// picture should be rasterized in
@ -45,21 +52,38 @@ pub struct PicturePrimitive {
}
impl PicturePrimitive {
pub fn new_shadow(
shadow: Shadow,
kind: RenderTargetKind,
) -> PicturePrimitive {
pub fn new_text_shadow(shadow: Shadow) -> PicturePrimitive {
PicturePrimitive {
prim_runs: Vec::new(),
composite_op: CompositeOp::Shadow(shadow),
render_task_id: None,
kind,
kind: PictureKind::TextShadow {
shadow,
},
}
}
pub fn as_shadow(&self) -> &Shadow {
match self.composite_op {
CompositeOp::Shadow(ref shadow) => shadow,
pub fn new_box_shadow(
blur_radius: f32,
color: ColorF,
blur_regions: Vec<LayerRect>,
clip_mode: BoxShadowClipMode,
) -> PicturePrimitive {
PicturePrimitive {
prim_runs: Vec::new(),
render_task_id: None,
kind: PictureKind::BoxShadow {
blur_radius,
color,
blur_regions,
clip_mode,
},
}
}
pub fn as_text_shadow(&self) -> &Shadow {
match self.kind {
PictureKind::TextShadow { ref shadow } => shadow,
PictureKind::BoxShadow { .. } => panic!("bug: not a text shadow")
}
}
@ -82,4 +106,83 @@ impl PicturePrimitive {
clip_and_scroll,
});
}
pub fn prepare_for_render(
&mut self,
prim_index: PrimitiveIndex,
prim_metadata: &PrimitiveMetadata,
prim_context: &PrimitiveContext,
render_tasks: &mut RenderTaskTree,
) {
// This is a shadow element. Create a render task that will
// render the text run to a target, and then apply a gaussian
// blur to that text run in order to build the actual primitive
// which will be blitted to the framebuffer.
let cache_width =
(prim_metadata.local_rect.size.width * prim_context.device_pixel_ratio).ceil() as i32;
let cache_height =
(prim_metadata.local_rect.size.height * prim_context.device_pixel_ratio).ceil() as i32;
let cache_size = DeviceIntSize::new(cache_width, cache_height);
let (blur_radius, target_kind, blur_regions, clear_mode) = match self.kind {
PictureKind::TextShadow { ref shadow } => {
let dummy: &[LayerRect] = &[];
(shadow.blur_radius, RenderTargetKind::Color, dummy, ClearMode::Transparent)
}
PictureKind::BoxShadow { blur_radius, clip_mode, ref blur_regions, .. } => {
let clear_mode = match clip_mode {
BoxShadowClipMode::Outset => ClearMode::One,
BoxShadowClipMode::Inset => ClearMode::Zero,
};
(blur_radius, RenderTargetKind::Alpha, blur_regions.as_slice(), clear_mode)
}
};
let blur_radius = device_length(blur_radius, prim_context.device_pixel_ratio);
let picture_task = RenderTask::new_picture(
cache_size,
prim_index,
target_kind,
);
let picture_task_id = render_tasks.add(picture_task);
let render_task = RenderTask::new_blur(
blur_radius,
picture_task_id,
render_tasks,
target_kind,
blur_regions,
clear_mode,
);
self.render_task_id = Some(render_tasks.add(render_task));
}
pub fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
match self.kind {
PictureKind::TextShadow { ref shadow } => {
request.push(shadow.color);
request.push([
shadow.offset.x,
shadow.offset.y,
shadow.blur_radius,
0.0,
]);
}
PictureKind::BoxShadow { blur_radius, color, .. } => {
request.push(color);
request.push([
0.0,
0.0,
blur_radius,
0.0,
]);
}
}
}
pub fn target_kind(&self) -> RenderTargetKind {
match self.kind {
PictureKind::TextShadow { .. } => RenderTargetKind::Color,
PictureKind::BoxShadow { .. } => RenderTargetKind::Alpha,
}
}
}

View File

@ -2,13 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderRadius, BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect, DeviceIntSize};
use api::{BorderRadius, BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect};
use api::{DevicePoint, ExtendMode, FontInstance, FontRenderMode, GlyphInstance, GlyphKey};
use api::{GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag, LayerPoint, LayerRect};
use api::{LayerSize, LayerVector2D, LineOrientation, LineStyle};
use api::{TileOffset, YuvColorSpace, YuvFormat, device_length};
use api::{ClipMode, LayerSize, LayerVector2D, LineOrientation, LineStyle};
use api::{TileOffset, YuvColorSpace, YuvFormat};
use border::BorderCornerInstance;
use clip::{ClipMode, ClipSourcesHandle, ClipStore, Geometry};
use clip::{ClipSourcesHandle, ClipStore, Geometry};
use frame_builder::PrimitiveContext;
use gpu_cache::{GpuBlockData, GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest,
ToGpuBlocks};
@ -167,17 +167,29 @@ impl ToGpuBlocks for RectanglePrimitive {
#[derive(Debug)]
pub struct BrushPrimitive {
pub clip_mode: ClipMode,
pub radius: f32,
pub radius: BorderRadius,
}
impl ToGpuBlocks for BrushPrimitive {
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
request.push([
self.clip_mode as u32 as f32,
self.radius,
0.0,
0.0,
0.0
]);
request.push([
self.radius.top_left.width,
self.radius.top_left.height,
self.radius.top_right.width,
self.radius.top_right.height,
]);
request.push([
self.radius.bottom_right.width,
self.radius.bottom_right.height,
self.radius.bottom_left.width,
self.radius.bottom_left.height,
]);
}
}
@ -1037,46 +1049,20 @@ impl PrimitiveStore {
prim_context: &PrimitiveContext,
resource_cache: &mut ResourceCache,
gpu_cache: &mut GpuCache,
// For some primitives, we need to mark dependencies as needed for rendering
// without spawning new tasks, since there will be another call to
// `prepare_prim_for_render_inner` specifically for this primitive later on.
render_tasks: Option<&mut RenderTaskTree>,
render_tasks: &mut RenderTaskTree,
text_run_mode: TextRunMode,
) {
let metadata = &mut self.cpu_metadata[prim_index.0];
match metadata.prim_kind {
PrimitiveKind::Rectangle | PrimitiveKind::Border | PrimitiveKind::Line => {}
PrimitiveKind::Picture => {
let picture = &mut self.cpu_pictures[metadata.cpu_prim_index.0];
// This is a shadow element. Create a render task that will
// render the text run to a target, and then apply a gaussian
// blur to that text run in order to build the actual primitive
// which will be blitted to the framebuffer.
let cache_width =
(metadata.local_rect.size.width * prim_context.device_pixel_ratio).ceil() as i32;
let cache_height =
(metadata.local_rect.size.height * prim_context.device_pixel_ratio).ceil() as i32;
let cache_size = DeviceIntSize::new(cache_width, cache_height);
let blur_radius = picture.as_shadow().blur_radius;
let blur_radius = device_length(blur_radius, prim_context.device_pixel_ratio);
// ignore new tasks if we are in a dependency context
picture.render_task_id = render_tasks.map(|rt| {
let picture_task = RenderTask::new_picture(
cache_size,
self.cpu_pictures[metadata.cpu_prim_index.0]
.prepare_for_render(
prim_index,
picture.kind,
metadata,
prim_context,
render_tasks
);
let picture_task_id = rt.add(picture_task);
let render_task = RenderTask::new_blur(
blur_radius,
picture_task_id,
rt,
picture.kind
);
rt.add(render_task)
});
}
PrimitiveKind::TextRun => {
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
@ -1173,15 +1159,8 @@ impl PrimitiveStore {
text.write_gpu_blocks(&mut request);
}
PrimitiveKind::Picture => {
let picture = &self.cpu_pictures[metadata.cpu_prim_index.0];
let shadow = picture.as_shadow();
request.push(shadow.color);
request.push([
shadow.offset.x,
shadow.offset.y,
shadow.blur_radius,
0.0,
]);
self.cpu_pictures[metadata.cpu_prim_index.0]
.write_gpu_blocks(request);
}
PrimitiveKind::Brush => {
let brush = &self.cpu_brushes[metadata.cpu_prim_index.0];
@ -1342,7 +1321,7 @@ impl PrimitiveStore {
prim_context,
resource_cache,
gpu_cache,
None,
render_tasks,
TextRunMode::Shadow,
);
}
@ -1365,7 +1344,7 @@ impl PrimitiveStore {
prim_context,
resource_cache,
gpu_cache,
Some(render_tasks),
render_tasks,
TextRunMode::Normal,
);

View File

@ -22,7 +22,8 @@ use resource_cache::ResourceCache;
use scene::Scene;
#[cfg(feature = "debugger")]
use serde_json;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::u32;
use texture_cache::TextureCache;
@ -124,6 +125,9 @@ enum DocumentOp {
Rendered(RendererFrame),
}
/// The unique id for WR resource identification.
static NEXT_NAMESPACE_ID: AtomicUsize = ATOMIC_USIZE_INIT;
/// The render backend is responsible for transforming high level display lists into
/// GPU-friendly work which is then submitted to the renderer in the form of a frame::Frame.
///
@ -133,7 +137,6 @@ pub struct RenderBackend {
payload_rx: PayloadReceiver,
payload_tx: PayloadSender,
result_tx: Sender<ResultMsg>,
next_namespace_id: IdNamespace,
default_device_pixel_ratio: f32,
gpu_cache: GpuCache,
@ -142,7 +145,7 @@ pub struct RenderBackend {
frame_config: FrameBuilderConfig,
documents: FastHashMap<DocumentId, Document>,
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
notifier: Box<RenderNotifier>,
recorder: Option<Box<ApiRecordingReceiver>>,
enable_render_on_scroll: bool,
@ -157,12 +160,15 @@ impl RenderBackend {
default_device_pixel_ratio: f32,
texture_cache: TextureCache,
workers: Arc<ThreadPool>,
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
notifier: Box<RenderNotifier>,
frame_config: FrameBuilderConfig,
recorder: Option<Box<ApiRecordingReceiver>>,
blob_image_renderer: Option<Box<BlobImageRenderer>>,
enable_render_on_scroll: bool,
) -> RenderBackend {
// The namespace_id should start from 1.
NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed);
let resource_cache = ResourceCache::new(texture_cache, workers, blob_image_renderer);
register_thread_with_profiler("Backend".to_string());
@ -177,7 +183,6 @@ impl RenderBackend {
gpu_cache: GpuCache::new(),
frame_config,
documents: FastHashMap::default(),
next_namespace_id: IdNamespace(1),
notifier,
recorder,
@ -421,6 +426,10 @@ impl RenderBackend {
}
}
fn next_namespace_id(&self) -> IdNamespace {
IdNamespace(NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed) as u32)
}
pub fn run(&mut self, mut profile_counters: BackendProfileCounters) {
let mut frame_counter: u32 = 0;
@ -435,8 +444,7 @@ impl RenderBackend {
msg
}
Err(..) => {
let notifier = self.notifier.lock();
notifier.unwrap().as_mut().unwrap().shut_down();
self.notifier.shut_down();
break;
}
};
@ -463,9 +471,7 @@ impl RenderBackend {
tx.send(glyph_indices).unwrap();
}
ApiMsg::CloneApi(sender) => {
let namespace = self.next_namespace_id;
self.next_namespace_id = IdNamespace(namespace.0 + 1);
sender.send(namespace).unwrap();
sender.send(self.next_namespace_id()).unwrap();
}
ApiMsg::AddDocument(document_id, initial_size) => {
let document = Document::new(
@ -504,8 +510,7 @@ impl RenderBackend {
self.documents.remove(&document_id);
}
ApiMsg::ExternalEvent(evt) => {
let notifier = self.notifier.lock();
notifier.unwrap().as_mut().unwrap().external_event(evt);
self.notifier.external_event(evt);
}
ApiMsg::ClearNamespace(namespace_id) => {
self.resource_cache.clear_namespace(namespace_id);
@ -530,12 +535,7 @@ impl RenderBackend {
// We use new_frame_ready to wake up the renderer and get the
// resource updates processed, but the UpdateResources message
// will cancel rendering the frame.
self.notifier
.lock()
.unwrap()
.as_mut()
.unwrap()
.new_frame_ready();
self.notifier.new_frame_ready();
}
ApiMsg::DebugCommand(option) => {
let msg = match option {
@ -550,12 +550,10 @@ impl RenderBackend {
_ => ResultMsg::DebugCommand(option),
};
self.result_tx.send(msg).unwrap();
let notifier = self.notifier.lock();
notifier.unwrap().as_mut().unwrap().new_frame_ready();
self.notifier.new_frame_ready();
}
ApiMsg::ShutDown => {
let notifier = self.notifier.lock();
notifier.unwrap().as_mut().unwrap().shut_down();
self.notifier.shut_down();
break;
}
}
@ -582,31 +580,11 @@ impl RenderBackend {
) {
self.publish_frame(document_id, frame, profile_counters);
// TODO(gw): This is kindof bogus to have to lock the notifier
// each time it's used. This is due to some nastiness
// in initialization order for Servo. Perhaps find a
// cleaner way to do this, or use the OnceMutex on crates.io?
let mut notifier = self.notifier.lock();
notifier
.as_mut()
.unwrap()
.as_mut()
.unwrap()
.new_frame_ready();
self.notifier.new_frame_ready();
}
fn notify_compositor_of_new_scroll_frame(&mut self, composite_needed: bool) {
// TODO(gw): This is kindof bogus to have to lock the notifier
// each time it's used. This is due to some nastiness
// in initialization order for Servo. Perhaps find a
// cleaner way to do this, or use the OnceMutex on crates.io?
let mut notifier = self.notifier.lock();
notifier
.as_mut()
.unwrap()
.as_mut()
.unwrap()
.new_scroll_frame_ready(composite_needed);
fn notify_compositor_of_new_scroll_frame(&self, composite_needed: bool) {
self.notifier.new_scroll_frame_ready(composite_needed);
}

View File

@ -4,7 +4,7 @@
use api::{ClipId, DeviceIntLength, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{FilterOp, MixBlendMode};
use api::PipelineId;
use api::{LayerRect, PipelineId};
use clip::{ClipSource, ClipSourcesWeakHandle, ClipStore};
use clip_scroll_tree::CoordinateSystemId;
use gpu_cache::GpuCacheHandle;
@ -264,6 +264,7 @@ pub struct PictureTask {
pub struct BlurTask {
pub blur_radius: DeviceIntLength,
pub target_kind: RenderTargetKind,
pub regions: Vec<LayerRect>,
}
#[derive(Debug)]
@ -282,12 +283,23 @@ pub enum RenderTaskKind {
Alias(RenderTaskId),
}
#[derive(Debug, Copy, Clone)]
pub enum ClearMode {
// Applicable to color and alpha targets.
Zero,
One,
// Applicable to color targets only.
Transparent,
}
#[derive(Debug)]
pub struct RenderTask {
pub cache_key: Option<RenderTaskKey>,
pub location: RenderTaskLocation,
pub children: Vec<RenderTaskId>,
pub kind: RenderTaskKind,
pub clear_mode: ClearMode,
}
impl RenderTask {
@ -305,6 +317,7 @@ impl RenderTask {
items: Vec::new(),
frame_output_pipeline_id,
}),
clear_mode: ClearMode::Transparent,
}
}
@ -321,6 +334,11 @@ impl RenderTask {
prim_index: PrimitiveIndex,
target_kind: RenderTargetKind,
) -> RenderTask {
let clear_mode = match target_kind {
RenderTargetKind::Color => ClearMode::Transparent,
RenderTargetKind::Alpha => ClearMode::One,
};
RenderTask {
cache_key: None,
children: Vec::new(),
@ -329,6 +347,7 @@ impl RenderTask {
prim_index,
target_kind,
}),
clear_mode,
}
}
@ -338,6 +357,7 @@ impl RenderTask {
children: Vec::new(),
location: RenderTaskLocation::Dynamic(None, screen_rect.size),
kind: RenderTaskKind::Readback(screen_rect),
clear_mode: ClearMode::Transparent,
}
}
@ -420,6 +440,7 @@ impl RenderTask {
geometry_kind,
coordinate_system_id: prim_coordinate_system_id,
}),
clear_mode: ClearMode::One,
})
}
@ -443,6 +464,8 @@ impl RenderTask {
src_task_id: RenderTaskId,
render_tasks: &mut RenderTaskTree,
target_kind: RenderTargetKind,
regions: &[LayerRect],
clear_mode: ClearMode,
) -> RenderTask {
let blur_target_size = render_tasks.get(src_task_id).get_dynamic_size();
@ -453,7 +476,9 @@ impl RenderTask {
kind: RenderTaskKind::VerticalBlur(BlurTask {
blur_radius,
target_kind,
regions: regions.to_vec(),
}),
clear_mode,
};
let blur_task_v_id = render_tasks.add(blur_task_v);
@ -465,7 +490,9 @@ impl RenderTask {
kind: RenderTaskKind::HorizontalBlur(BlurTask {
blur_radius,
target_kind,
regions: regions.to_vec(),
}),
clear_mode,
};
blur_task_h

View File

@ -55,7 +55,7 @@ use std::f32;
use std::mem;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use texture_cache::TextureCache;
@ -325,6 +325,11 @@ const DESC_BLUR: VertexDescriptor = VertexDescriptor {
count: 1,
kind: VertexAttributeKind::I32,
},
VertexAttribute {
name: "aBlurRegion",
count: 4,
kind: VertexAttributeKind::F32
},
],
};
@ -925,20 +930,14 @@ struct PrimitiveShader {
}
struct FileWatcher {
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
notifier: Box<RenderNotifier>,
result_tx: Sender<ResultMsg>,
}
impl FileWatcherHandler for FileWatcher {
fn file_changed(&self, path: PathBuf) {
self.result_tx.send(ResultMsg::RefreshShader(path)).ok();
let mut notifier = self.notifier.lock();
notifier
.as_mut()
.unwrap()
.as_mut()
.unwrap()
.new_frame_ready();
self.notifier.new_frame_ready();
}
}
@ -1132,8 +1131,6 @@ pub struct Renderer {
ps_split_composite: LazilyCompiledShader,
ps_composite: LazilyCompiledShader,
notifier: Arc<Mutex<Option<Box<RenderNotifier>>>>,
max_texture_size: u32,
max_recorded_profiles: usize,
@ -1229,6 +1226,7 @@ impl Renderer {
/// [rendereroptions]: struct.RendererOptions.html
pub fn new(
gl: Rc<gl::Gl>,
notifier: Box<RenderNotifier>,
mut options: RendererOptions,
) -> Result<(Renderer, RenderApiSender), RendererError> {
let (api_tx, api_rx) = try!{ channel::msg_channel() };
@ -1236,12 +1234,11 @@ impl Renderer {
let (result_tx, result_rx) = channel();
let gl_type = gl.get_type();
let notifier = Arc::new(Mutex::new(None));
let debug_server = DebugServer::new(api_tx.clone());
let file_watch_handler = FileWatcher {
result_tx: result_tx.clone(),
notifier: Arc::clone(&notifier),
notifier: notifier.clone(),
};
let mut device = Device::new(
@ -1652,7 +1649,7 @@ impl Renderer {
device.end_frame();
let backend_notifier = Arc::clone(&notifier);
let backend_notifier = notifier.clone();
let default_font_render_mode = match (options.enable_aa, options.enable_subpixel_aa) {
(true, true) => FontRenderMode::Subpixel,
@ -1735,7 +1732,6 @@ impl Renderer {
ps_split_composite,
ps_composite,
ps_line,
notifier,
debug: debug_renderer,
debug_flags,
enable_batcher: options.enable_batcher,
@ -1794,15 +1790,6 @@ impl Renderer {
(color_space as usize)
}
/// Sets the new RenderNotifier.
///
/// The RenderNotifier will be called when processing e.g. of a (scrolling) frame is done,
/// and therefore the screen should be updated.
pub fn set_render_notifier(&self, notifier: Box<RenderNotifier>) {
let mut notifier_arc = self.notifier.lock().unwrap();
*notifier_arc = Some(notifier);
}
/// Returns the Epoch of the current frame in a pipeline.
pub fn current_epoch(&self, pipeline_id: PipelineId) -> Option<Epoch> {
self.pipeline_epoch_map.get(&pipeline_id).cloned()
@ -2890,6 +2877,7 @@ impl Renderer {
target: &AlphaRenderTarget,
target_size: DeviceUintSize,
projection: &Transform3D<f32>,
render_tasks: &RenderTaskTree,
) {
self.gpu_profile.add_sampler(GPU_SAMPLER_TAG_ALPHA);
@ -2908,6 +2896,14 @@ impl Renderer {
let clear_color = [1.0, 1.0, 1.0, 0.0];
self.device
.clear_target_rect(Some(clear_color), None, target.used_rect());
let zero_color = [0.0, 0.0, 0.0, 0.0];
for task_id in &target.zero_clears {
let task = render_tasks.get(*task_id);
let (rect, _) = task.get_target_rect();
self.device
.clear_target_rect(Some(zero_color), None, rect);
}
}
// Draw any blurs for this target.
@ -3238,6 +3234,7 @@ impl Renderer {
target,
pass.max_alpha_target_size,
&projection,
&frame.render_tasks,
);
}

View File

@ -430,7 +430,7 @@ impl ResourceCache {
self.blob_image_renderer
.as_mut()
.unwrap()
.update(image_key, mem::replace(blob, BlobImageData::new()));
.update(image_key, mem::replace(blob, BlobImageData::new()), dirty_rect);
}
ImageResource {

View File

@ -21,7 +21,7 @@ use prim_store::{DeferredResolve, TextRunMode};
use profiler::FrameProfileCounters;
use render_task::{AlphaRenderItem, ClipWorkItem, MaskGeometryKind, MaskSegment};
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKey, RenderTaskKind};
use render_task::{RenderTaskLocation, RenderTaskTree};
use render_task::{BlurTask, ClearMode, RenderTaskLocation, RenderTaskTree};
use renderer::BlendMode;
use renderer::ImageBufferKind;
use resource_cache::{GlyphFetchResult, ResourceCache};
@ -427,6 +427,7 @@ impl AlphaRenderItem {
{
let sub_index = i as i32;
match *instance_kind {
BorderCornerInstance::None => {}
BorderCornerInstance::Single => {
batch.push(base_instance.build(
sub_index,
@ -580,7 +581,7 @@ impl AlphaRenderItem {
let textures = BatchTextures::render_target_cache();
let kind = BatchKind::Transformable(
transform_kind,
TransformBatchKind::CacheImage(picture.kind),
TransformBatchKind::CacheImage(picture.target_kind()),
);
let key = BatchKey::new(kind, blend_mode, textures);
let batch = batch_list.get_suitable_batch(key, item_bounding_rect);
@ -1137,23 +1138,23 @@ impl RenderTarget for ColorRenderTarget {
});
}
}
RenderTaskKind::VerticalBlur(..) => {
// Find the child render task that we are applying
// a vertical blur on.
self.vertical_blurs.push(BlurInstance {
task_address: render_tasks.get_task_address(task_id),
src_task_address: render_tasks.get_task_address(task.children[0]),
blur_direction: BlurDirection::Vertical,
});
RenderTaskKind::VerticalBlur(ref info) => {
info.add_instances(
&mut self.vertical_blurs,
task_id,
task.children[0],
BlurDirection::Vertical,
render_tasks,
);
}
RenderTaskKind::HorizontalBlur(..) => {
// Find the child render task that we are applying
// a horizontal blur on.
self.horizontal_blurs.push(BlurInstance {
task_address: render_tasks.get_task_address(task_id),
src_task_address: render_tasks.get_task_address(task.children[0]),
blur_direction: BlurDirection::Horizontal,
});
RenderTaskKind::HorizontalBlur(ref info) => {
info.add_instances(
&mut self.horizontal_blurs,
task_id,
task.children[0],
BlurDirection::Horizontal,
render_tasks,
);
}
RenderTaskKind::Picture(ref task_info) => {
let prim_metadata = ctx.prim_store.get_metadata(task_info.prim_index);
@ -1244,6 +1245,7 @@ pub struct AlphaRenderTarget {
// List of blur operations to apply for this render target.
pub vertical_blurs: Vec<BlurInstance>,
pub horizontal_blurs: Vec<BlurInstance>,
pub zero_clears: Vec<RenderTaskId>,
allocator: TextureAllocator,
}
@ -1258,6 +1260,7 @@ impl RenderTarget for AlphaRenderTarget {
rect_cache_prims: Vec::new(),
vertical_blurs: Vec::new(),
horizontal_blurs: Vec::new(),
zero_clears: Vec::new(),
allocator: TextureAllocator::new(size.expect("bug: alpha targets need size")),
}
}
@ -1275,6 +1278,17 @@ impl RenderTarget for AlphaRenderTarget {
clip_store: &ClipStore,
) {
let task = render_tasks.get(task_id);
match task.clear_mode {
ClearMode::Zero => {
self.zero_clears.push(task_id);
}
ClearMode::One => {}
ClearMode::Transparent => {
panic!("bug: invalid clear mode for alpha task");
}
}
match task.kind {
RenderTaskKind::Alias(..) => {
panic!("BUG: add_task() called on invalidated task");
@ -1283,23 +1297,23 @@ impl RenderTarget for AlphaRenderTarget {
RenderTaskKind::Readback(..) => {
panic!("Should not be added to alpha target!");
}
RenderTaskKind::VerticalBlur(..) => {
// Find the child render task that we are applying
// a vertical blur on.
self.vertical_blurs.push(BlurInstance {
task_address: render_tasks.get_task_address(task_id),
src_task_address: render_tasks.get_task_address(task.children[0]),
blur_direction: BlurDirection::Vertical,
});
RenderTaskKind::VerticalBlur(ref info) => {
info.add_instances(
&mut self.vertical_blurs,
task_id,
task.children[0],
BlurDirection::Vertical,
render_tasks,
);
}
RenderTaskKind::HorizontalBlur(..) => {
// Find the child render task that we are applying
// a horizontal blur on.
self.horizontal_blurs.push(BlurInstance {
task_address: render_tasks.get_task_address(task_id),
src_task_address: render_tasks.get_task_address(task.children[0]),
blur_direction: BlurDirection::Horizontal,
});
RenderTaskKind::HorizontalBlur(ref info) => {
info.add_instances(
&mut self.horizontal_blurs,
task_id,
task.children[0],
BlurDirection::Horizontal,
render_tasks,
);
}
RenderTaskKind::Picture(ref task_info) => {
let prim_metadata = ctx.prim_store.get_metadata(task_info.prim_index);
@ -1873,3 +1887,32 @@ fn resolve_image(
None => (SourceTexture::Invalid, GpuCacheHandle::new()),
}
}
impl BlurTask {
fn add_instances(
&self,
instances: &mut Vec<BlurInstance>,
task_id: RenderTaskId,
source_task_id: RenderTaskId,
blur_direction: BlurDirection,
render_tasks: &RenderTaskTree,
) {
let instance = BlurInstance {
task_address: render_tasks.get_task_address(task_id),
src_task_address: render_tasks.get_task_address(source_task_id),
blur_direction,
region: LayerRect::zero(),
};
if self.regions.is_empty() {
instances.push(instance);
} else {
for region in &self.regions {
instances.push(BlurInstance {
region: *region,
..instance
});
}
}
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "webrender_api"
version = "0.52.1"
version = "0.53.0"
authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
license = "MPL-2.0"
repository = "https://github.com/servo/webrender"
@ -15,7 +15,6 @@ bitflags = "1.0"
bincode = "0.9"
byteorder = "1.0"
euclid = "0.15"
heapsize = ">= 0.3.6, < 0.5"
ipc-channel = {version = "0.9", optional = true}
serde = { version = "1.0", features = ["rc", "derive"] }
time = "0.1"

View File

@ -873,10 +873,11 @@ pub struct DynamicProperties {
}
pub trait RenderNotifier: Send {
fn new_frame_ready(&mut self);
fn new_scroll_frame_ready(&mut self, composite_needed: bool);
fn external_event(&mut self, _evt: ExternalEvent) {
fn clone(&self) -> Box<RenderNotifier>;
fn new_frame_ready(&self);
fn new_scroll_frame_ready(&self, composite_needed: bool);
fn external_event(&self, _evt: ExternalEvent) {
unimplemented!()
}
fn shut_down(&mut self) {}
fn shut_down(&self) {}
}

View File

@ -16,7 +16,6 @@ pub struct ColorF {
pub b: f32,
pub a: f32,
}
known_heap_size!(0, ColorF);
impl ColorF {
/// Constructs a new `ColorF` from its components.

View File

@ -6,6 +6,7 @@ use {ColorF, FontInstanceKey, ImageKey, LayerPixel, LayoutPixel, LayoutPoint, La
LayoutSize, LayoutTransform};
use {GlyphOptions, LayoutVector2D, PipelineId, PropertyBinding};
use euclid::{SideOffsets2D, TypedRect, TypedSideOffsets2D};
use std::ops::Not;
// NOTE: some of these structs have an "IMPLICIT" comment.
// This indicates that the BuiltDisplayList will have serialized
@ -297,7 +298,7 @@ pub struct BoxShadowDisplayItem {
pub color: ColorF,
pub blur_radius: f32,
pub spread_radius: f32,
pub border_radius: f32,
pub border_radius: BorderRadius,
pub clip_mode: BoxShadowClipMode,
}
@ -336,7 +337,6 @@ pub struct GradientStop {
pub offset: f32,
pub color: ColorF,
}
known_heap_size!(0, GradientStop);
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct RadialGradient {
@ -376,8 +376,6 @@ pub enum ScrollPolicy {
Fixed = 1,
}
known_heap_size!(0, ScrollPolicy);
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum TransformStyle {
@ -547,12 +545,31 @@ impl LocalClip {
ComplexClipRegion {
rect: complex.rect.translate(offset),
radii: complex.radii,
mode: complex.mode,
},
),
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ClipMode {
Clip, // Pixels inside the region are visible.
ClipOut, // Pixels outside the region are visible.
}
impl Not for ClipMode {
type Output = ClipMode;
fn not(self) -> ClipMode {
match self {
ClipMode::Clip => ClipMode::ClipOut,
ClipMode::ClipOut => ClipMode::Clip,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ComplexClipRegion {
@ -560,6 +577,9 @@ pub struct ComplexClipRegion {
pub rect: LayoutRect,
/// Border radii of this rectangle.
pub radii: BorderRadius,
/// Whether we are clipping inside or outside
/// the region.
pub mode: ClipMode,
}
impl BorderRadius {
@ -619,8 +639,12 @@ impl BorderRadius {
impl ComplexClipRegion {
/// Create a new complex clip region.
pub fn new(rect: LayoutRect, radii: BorderRadius) -> ComplexClipRegion {
ComplexClipRegion { rect, radii }
pub fn new(
rect: LayoutRect,
radii: BorderRadius,
mode: ClipMode,
) -> ComplexClipRegion {
ComplexClipRegion { rect, radii, mode }
}
}
@ -672,21 +696,3 @@ impl ClipId {
}
}
}
macro_rules! define_empty_heap_size_of {
($name:ident) => {
impl ::heapsize::HeapSizeOf for $name {
fn heap_size_of_children(&self) -> usize { 0 }
}
}
}
define_empty_heap_size_of!(ClipAndScrollInfo);
define_empty_heap_size_of!(ClipId);
define_empty_heap_size_of!(ImageKey);
define_empty_heap_size_of!(LocalClip);
define_empty_heap_size_of!(MixBlendMode);
define_empty_heap_size_of!(RepeatMode);
define_empty_heap_size_of!(ScrollSensitivity);
define_empty_heap_size_of!(StickySideConstraint);
define_empty_heap_size_of!(TransformStyle);

View File

@ -12,7 +12,7 @@ use {LineDisplayItem, LineOrientation, LineStyle, LocalClip, MixBlendMode, Pipel
use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
use {RectangleDisplayItem, ScrollFrameDisplayItem, ScrollPolicy, ScrollSensitivity};
use {SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, StickyFrameInfo};
use {TextDisplayItem, Shadow, TransformStyle, YuvColorSpace, YuvData};
use {BorderRadius, TextDisplayItem, Shadow, TransformStyle, YuvColorSpace, YuvData};
use YuvImageDisplayItem;
use bincode;
use serde::{Deserialize, Serialize, Serializer};
@ -153,23 +153,25 @@ fn skip_slice<T: for<'de> Deserialize<'de>>(
data: &mut &[u8],
) -> (ItemRange<T>, usize) {
let base = list.data.as_ptr() as usize;
let start = data.as_ptr() as usize;
// Read through the values (this is a bit of a hack to reuse logic)
let mut iter = AuxIter::<T>::new(*data);
let count = iter.len();
for _ in &mut iter {}
let end = iter.data.as_ptr() as usize;
let byte_size: usize = bincode::deserialize_from(data, bincode::Infinite)
.expect("MEH: malicious input?");
let start = data.as_ptr() as usize;
let item_count: usize = bincode::deserialize_from(data, bincode::Infinite)
.expect("MEH: malicious input?");
// Remember how many bytes item_count occupied
let item_count_size = data.as_ptr() as usize - start;
let range = ItemRange {
start: start - base,
length: end - start,
start: start - base, // byte offset to item_count
length: byte_size + item_count_size, // number of bytes for item_count + payload
_boo: PhantomData,
};
// Adjust data pointer to skip read values
*data = &data[range.length ..];
(range, count)
*data = &data[byte_size ..];
(range, item_count)
}
@ -737,12 +739,29 @@ impl DisplayListBuilder {
let len = iter.len();
let mut count = 0;
// Format:
// payload_byte_size: usize, item_count: usize, [I; item_count]
// We write a dummy value so there's room for later
let byte_size_offset = self.data.len();
serialize_fast(&mut self.data, &0usize);
serialize_fast(&mut self.data, &len);
let payload_offset = self.data.len();
for elem in iter {
count += 1;
serialize_fast(&mut self.data, &elem);
}
// Now write the actual byte_size
let final_offset = self.data.len();
let byte_size = final_offset - payload_offset;
// Note we don't use serialize_fast because we don't want to change the Vec's len
bincode::serialize_into(&mut &mut self.data[byte_size_offset..],
&byte_size,
bincode::Infinite).unwrap();
debug_assert_eq!(len, count);
}
@ -1024,7 +1043,7 @@ impl DisplayListBuilder {
color: ColorF,
blur_radius: f32,
spread_radius: f32,
border_radius: f32,
border_radius: BorderRadius,
clip_mode: BoxShadowClipMode,
) {
let item = SpecificDisplayItem::BoxShadow(BoxShadowDisplayItem {

View File

@ -151,7 +151,7 @@ pub trait BlobImageResources {
pub trait BlobImageRenderer: Send {
fn add(&mut self, key: ImageKey, data: BlobImageData, tiling: Option<TileSize>);
fn update(&mut self, key: ImageKey, data: BlobImageData);
fn update(&mut self, key: ImageKey, data: BlobImageData, dirty_rect: Option<DeviceUintRect>);
fn delete(&mut self, key: ImageKey);

View File

@ -13,8 +13,6 @@ extern crate byteorder;
#[cfg(feature = "nightly")]
extern crate core;
extern crate euclid;
#[macro_use]
extern crate heapsize;
#[cfg(feature = "ipc")]
extern crate ipc_channel;
#[macro_use]

View File

@ -5,7 +5,7 @@ authors = ["The Mozilla Project Developers"]
license = "MPL-2.0"
[dependencies]
webrender_api = {path = "../webrender_api", version = "0.52.1"}
webrender_api = {path = "../webrender_api", version = "0.53.0"}
bincode = "0.8"
rayon = "0.8"
thread_profiler = "0.1.1"
@ -15,5 +15,5 @@ gleam = "0.4"
[dependencies.webrender]
path = "../webrender"
version = "0.52.1"
version = "0.53.0"
default-features = false