--- a/gfx/webrender/examples/basic.rs
+++ b/gfx/webrender/examples/basic.rs
@@ -334,17 +334,17 @@ impl Example for App {
builder.push_box_shadow(
&info,
simple_box_bounds,
offset,
color,
blur_radius,
spread_radius,
- simple_border_radius,
+ BorderRadius::uniform(simple_border_radius),
box_shadow_type,
);
}
builder.pop_stacking_context();
}
fn on_event(&mut self, event: glutin::Event, api: &RenderApi, document_id: DocumentId) -> bool {
--- a/gfx/webrender/res/brush_mask.glsl
+++ b/gfx/webrender/res/brush_mask.glsl
@@ -9,36 +9,38 @@ flat varying vec4 vClipCenter_Radius_TL;
flat varying vec4 vClipCenter_Radius_TR;
flat varying vec4 vClipCenter_Radius_BR;
flat varying vec4 vClipCenter_Radius_BL;
#ifdef WR_VERTEX_SHADER
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) {
// Load the specific primitive.
BrushPrimitive prim = fetch_brush_primitive(prim_address + 2);
// 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
#ifdef WR_FRAGMENT_SHADER
vec4 brush_fs(vec2 local_pos, vec4 local_rect) {
// TODO(gw): The mask code below is super-inefficient. Once we
// start using primitive segments in brush shaders, this can
// be made much faster.
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -1,14 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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::{BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, BuiltDisplayList};
-use api::{ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF};
+use api::{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};
use api::{ImageKey, ImageRendering, ItemRange, ItemTag, LayerPoint, LayerPrimitiveInfo, LayerRect};
use api::{LayerPixel, LayerSize, LayerToScrollTransform, LayerVector2D, LayoutVector2D, LineOrientation};
use api::{LineStyle, LocalClip, PipelineId, RepeatMode};
use api::{ScrollSensitivity, Shadow, TileOffset, TransformStyle};
use api::{WorldPixel, WorldPoint, YuvColorSpace, YuvData, device_length};
@@ -1253,77 +1253,73 @@ impl FrameBuilder {
pub fn add_box_shadow(
&mut self,
clip_and_scroll: ClipAndScrollInfo,
prim_info: &LayerPrimitiveInfo,
box_offset: &LayerVector2D,
color: &ColorF,
blur_radius: f32,
spread_radius: f32,
- border_radius: f32,
+ border_radius: BorderRadius,
clip_mode: BoxShadowClipMode,
) {
if color.a == 0.0 {
return;
}
let spread_amount = match clip_mode {
BoxShadowClipMode::Outset => {
spread_radius
}
BoxShadowClipMode::Inset => {
-spread_radius
}
};
- // 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);
if blur_radius == 0.0 {
let mut clips = Vec::new();
let fast_info = match clip_mode {
BoxShadowClipMode::Outset => {
// 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
));
LayerPrimitiveInfo::with_clip(
shadow_rect,
LocalClip::RoundedRect(
shadow_rect,
- ComplexClipRegion::new(shadow_rect, BorderRadius::uniform(shadow_radius)),
+ ComplexClipRegion::new(shadow_rect, shadow_radius),
),
)
}
BoxShadowClipMode::Inset => {
clips.push(ClipSource::RoundedRectangle(
shadow_rect,
- BorderRadius::uniform(shadow_radius),
+ shadow_radius,
ClipMode::ClipOut
));
LayerPrimitiveInfo::with_clip(
prim_info.rect,
LocalClip::RoundedRect(
prim_info.rect,
- ComplexClipRegion::new(prim_info.rect, BorderRadius::uniform(border_radius)),
+ ComplexClipRegion::new(prim_info.rect, border_radius),
),
)
}
};
self.add_primitive(
clip_and_scroll,
&fast_info,
@@ -1361,17 +1357,17 @@ impl FrameBuilder {
Vec::new(),
PrimitiveContainer::Brush(brush_prim),
);
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)
}
BoxShadowClipMode::Inset => {
let brush_prim = BrushPrimitive {
@@ -1391,17 +1387,17 @@ impl FrameBuilder {
Vec::new(),
PrimitiveContainer::Brush(brush_prim),
);
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)
}
};
@@ -2321,8 +2317,72 @@ impl FrameBuilder {
passes,
layer_texture_data: self.packed_layers.clone(),
render_tasks,
deferred_resolves,
gpu_cache_updates: Some(gpu_cache_updates),
}
}
}
+
+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)
+}
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -162,27 +162,39 @@ impl ToGpuBlocks for RectanglePrimitive
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
request.push(self.color);
}
}
#[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,
+ ]);
}
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct LinePrimitive {
pub color: ColorF,
pub style: LineStyle,
--- a/gfx/webrender_api/src/display_item.rs
+++ b/gfx/webrender_api/src/display_item.rs
@@ -292,17 +292,17 @@ pub enum BoxShadowClipMode {
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct BoxShadowDisplayItem {
pub box_bounds: LayoutRect,
pub offset: LayoutVector2D,
pub color: ColorF,
pub blur_radius: f32,
pub spread_radius: f32,
- pub border_radius: f32,
+ pub border_radius: BorderRadius,
pub clip_mode: BoxShadowClipMode,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct Shadow {
pub offset: LayoutVector2D,
pub color: ColorF,
--- a/gfx/webrender_api/src/display_list.rs
+++ b/gfx/webrender_api/src/display_list.rs
@@ -7,17 +7,17 @@ use {ClipAndScrollInfo, ClipDisplayItem,
use {ExtendMode, FilterOp, FontInstanceKey, GlyphInstance};
use {GlyphOptions, Gradient, GradientDisplayItem, GradientStop, IframeDisplayItem};
use {ImageDisplayItem, ImageKey, ImageMask, ImageRendering, LayerPrimitiveInfo, LayoutPoint};
use {LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
use {LineDisplayItem, LineOrientation, LineStyle, LocalClip, MixBlendMode, PipelineId};
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};
use serde::ser::{SerializeMap, SerializeSeq};
use std::io::{Read, Write};
use std::{io, ptr};
use std::marker::PhantomData;
use std::slice;
@@ -1019,17 +1019,17 @@ impl DisplayListBuilder {
pub fn push_box_shadow(
&mut self,
info: &LayoutPrimitiveInfo,
box_bounds: LayoutRect,
offset: LayoutVector2D,
color: ColorF,
blur_radius: f32,
spread_radius: f32,
- border_radius: f32,
+ border_radius: BorderRadius,
clip_mode: BoxShadowClipMode,
) {
let item = SpecificDisplayItem::BoxShadow(BoxShadowDisplayItem {
box_bounds,
offset,
color,
blur_radius,
spread_radius,