--- a/gfx/webrender/src/border.rs
+++ b/gfx/webrender/src/border.rs
@@ -3,17 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderSide, BorderStyle, BorderWidths, ClipAndScrollInfo, ColorF, LayerPoint, LayerRect};
use api::{LayerPrimitiveInfo, LayerSize, NormalBorder, RepeatMode};
use clip::ClipSource;
use ellipse::Ellipse;
use frame_builder::FrameBuilder;
use gpu_cache::GpuDataRequest;
-use prim_store::{BorderPrimitiveCpu, PrimitiveContainer, TexelRect};
+use prim_store::{BorderPrimitiveCpu, FillOrClear, PrimitiveContainer, TexelRect};
use tiling::PrimitiveFlags;
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.
@@ -380,56 +380,56 @@ impl FrameBuilder {
// Add a solid rectangle for each visible edge/corner combination.
if top_edge == BorderEdgeKind::Solid {
let mut info = info.clone();
info.rect = LayerRect::new(p0, LayerSize::new(rect_width, top_len));
self.add_solid_rectangle(
clip_and_scroll,
&info,
- &border.top.color,
+ &FillOrClear::Fill(border.top.color),
PrimitiveFlags::None,
);
}
if left_edge == BorderEdgeKind::Solid {
let mut info = info.clone();
info.rect = LayerRect::new(
LayerPoint::new(p0.x, p0.y + top_len),
LayerSize::new(left_len, rect_height - top_len - bottom_len),
);
self.add_solid_rectangle(
clip_and_scroll,
&info,
- &border.left.color,
+ &FillOrClear::Fill(border.left.color),
PrimitiveFlags::None,
);
}
if right_edge == BorderEdgeKind::Solid {
let mut info = info.clone();
info.rect = LayerRect::new(
LayerPoint::new(p1.x - right_len, p0.y + top_len),
LayerSize::new(right_len, rect_height - top_len - bottom_len),
);
self.add_solid_rectangle(
clip_and_scroll,
&info,
- &border.right.color,
+ &FillOrClear::Fill(border.right.color),
PrimitiveFlags::None,
);
}
if bottom_edge == BorderEdgeKind::Solid {
let mut info = info.clone();
info.rect = LayerRect::new(
LayerPoint::new(p0.x, p1.y - bottom_len),
LayerSize::new(rect_width, bottom_len),
);
self.add_solid_rectangle(
clip_and_scroll,
&info,
- &border.bottom.color,
+ &FillOrClear::Fill(border.bottom.color),
PrimitiveFlags::None,
);
}
} else {
// Create clip masks for border corners, if required.
let mut extra_clips = Vec::new();
let mut corner_instances = [BorderCornerInstance::Single; 4];
--- a/gfx/webrender/src/device.rs
+++ b/gfx/webrender/src/device.rs
@@ -1872,16 +1872,21 @@ impl Device {
}
}
pub fn set_blend_mode_premultiplied_alpha(&self) {
self.gl.blend_func(gl::ONE, gl::ONE_MINUS_SRC_ALPHA);
self.gl.blend_equation(gl::FUNC_ADD);
}
+ pub fn set_blend_mode_premultiplied_dest_out(&self) {
+ self.gl.blend_func(gl::ZERO, gl::ONE_MINUS_SRC_ALPHA);
+ self.gl.blend_equation(gl::FUNC_ADD);
+ }
+
pub fn set_blend_mode_alpha(&self) {
self.gl.blend_func_separate(
gl::SRC_ALPHA,
gl::ONE_MINUS_SRC_ALPHA,
gl::ONE,
gl::ONE_MINUS_SRC_ALPHA,
);
self.gl.blend_equation(gl::FUNC_ADD);
--- a/gfx/webrender/src/frame.rs
+++ b/gfx/webrender/src/frame.rs
@@ -11,16 +11,17 @@ use api::{LocalClip, PipelineId, ScrollC
use api::{ScrollLocation, ScrollPolicy, ScrollSensitivity, SpecificDisplayItem, StackingContext};
use api::{ClipMode, TileOffset, TransformStyle, WorldPoint};
use clip::ClipRegion;
use clip_scroll_tree::{ClipScrollTree, ScrollStates};
use euclid::rect;
use frame_builder::{FrameBuilder, FrameBuilderConfig};
use gpu_cache::GpuCache;
use internal_types::{FastHashMap, FastHashSet, RendererFrame};
+use prim_store::FillOrClear;
use profiler::{GpuCacheProfileCounters, TextureCacheProfileCounters};
use resource_cache::{ResourceCache, TiledImageMap};
use scene::{Scene, StackingContextHelpers, ScenePipeline};
use tiling::{CompositeOps, PrimitiveFlags};
use util::{subtract_rect, ComplexClipRegionHelpers};
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Eq, Ord)]
pub struct FrameId(pub u32);
@@ -515,21 +516,29 @@ impl Frame {
context,
&prim_info,
&info.color,
&clip_and_scroll,
) {
context.builder.add_solid_rectangle(
clip_and_scroll,
&prim_info,
- &info.color,
+ &FillOrClear::Fill(info.color),
PrimitiveFlags::None,
);
}
}
+ SpecificDisplayItem::ClearRectangle => {
+ context.builder.add_solid_rectangle(
+ clip_and_scroll,
+ &prim_info,
+ &FillOrClear::Clear,
+ PrimitiveFlags::None,
+ );
+ }
SpecificDisplayItem::Line(ref info) => {
let prim_info = LayerPrimitiveInfo {
rect: LayerRect::zero(),
local_clip: *item.local_clip(),
is_backface_visible: prim_info.is_backface_visible,
tag: prim_info.tag,
};
@@ -727,34 +736,34 @@ impl Frame {
if context.scene.root_pipeline_id != Some(pipeline_id) {
if let Some(pipeline) = context.scene.pipelines.get(&pipeline_id) {
if let Some(bg_color) = pipeline.background_color {
let root_bounds = LayerRect::new(LayerPoint::zero(), *content_size);
let info = LayerPrimitiveInfo::new(root_bounds);
context.builder.add_solid_rectangle(
ClipAndScrollInfo::simple(clip_id),
&info,
- &bg_color,
+ &FillOrClear::Fill(bg_color),
PrimitiveFlags::None,
);
}
}
}
self.flatten_items(traversal, pipeline_id, context, LayerVector2D::zero());
if self.frame_builder_config.enable_scrollbars {
let scrollbar_rect = LayerRect::new(LayerPoint::zero(), LayerSize::new(10.0, 70.0));
let info = LayerPrimitiveInfo::new(scrollbar_rect);
context.builder.add_solid_rectangle(
ClipAndScrollInfo::simple(clip_id),
&info,
- &DEFAULT_SCROLLBAR_COLOR,
+ &FillOrClear::Fill(DEFAULT_SCROLLBAR_COLOR),
PrimitiveFlags::Scrollbar(self.clip_scroll_tree.topmost_scrolling_node_id(), 4.0),
);
}
context.builder.pop_stacking_context();
}
fn flatten_items<'a>(
@@ -1174,24 +1183,24 @@ fn try_to_add_rectangle_splitting_on_cli
local_clip: LocalClip::from(*info.local_clip.clip_rect()),
is_backface_visible: info.is_backface_visible,
tag: None,
};
context.builder.add_solid_rectangle(
*clip_and_scroll,
&prim_info,
- color,
+ &FillOrClear::Fill(*color),
PrimitiveFlags::None,
);
for clipped_rect in &clipped_rects {
let mut info = info.clone();
info.rect = *clipped_rect;
context.builder.add_solid_rectangle(
*clip_and_scroll,
&info,
- color,
+ &FillOrClear::Fill(*color),
PrimitiveFlags::None,
);
}
true
}
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -22,17 +22,17 @@ use frame::FrameId;
use gpu_cache::GpuCache;
use internal_types::{FastHashMap, FastHashSet, HardwareCompositeOp};
use picture::{PicturePrimitive};
use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{BrushPrimitive, TexelRect, YuvImagePrimitiveCpu};
use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu, LinePrimitive, PrimitiveKind};
use prim_store::{PrimitiveContainer, PrimitiveIndex};
use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu};
-use prim_store::{RectanglePrimitive, TextRunPrimitiveCpu};
+use prim_store::{FillOrClear, RectanglePrimitive, TextRunPrimitiveCpu};
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
use render_task::{AlphaRenderItem, ClearMode, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation};
use render_task::RenderTaskTree;
use resource_cache::ResourceCache;
use scene::ScenePipeline;
use std::{mem, usize, f32, i32};
use tiling::{ClipScrollGroup, ClipScrollGroupIndex, CompositeOps, Frame};
use tiling::{ContextIsolation, RenderTargetKind, StackingContextIndex};
@@ -610,27 +610,33 @@ impl FrameBuilder {
mem::replace(&mut self.pending_shadow_contents, pending_primitives);
mem::replace(&mut self.shadow_prim_stack, shadows);
}
pub fn add_solid_rectangle(
&mut self,
clip_and_scroll: ClipAndScrollInfo,
info: &LayerPrimitiveInfo,
- color: &ColorF,
+ operation: &FillOrClear,
flags: PrimitiveFlags,
) {
- let prim = RectanglePrimitive { color: *color };
-
- // Don't add transparent rectangles to the draw list, but do consider them for hit
- // testing. This allows specifying invisible hit testing areas.
- if color.a == 0.0 {
- self.add_primitive_to_hit_testing_list(info, clip_and_scroll);
- return;
- }
+ let prim = match operation {
+ &FillOrClear::Fill(ref color) => {
+ // Don't add transparent rectangles to the draw list, but do consider them for hit
+ // testing. This allows specifying invisible hit testing areas.
+ if color.a == 0.0 {
+ self.add_primitive_to_hit_testing_list(info, clip_and_scroll);
+ return;
+ }
+ RectanglePrimitive { operation: *operation }
+ }
+ &FillOrClear::Clear => {
+ RectanglePrimitive { operation: *operation }
+ }
+ };
let prim_index = self.add_primitive(
clip_and_scroll,
info,
Vec::new(),
PrimitiveContainer::Rectangle(prim),
);
@@ -1330,17 +1336,17 @@ impl FrameBuilder {
}
};
self.add_primitive(
clip_and_scroll,
&fast_info,
clips,
PrimitiveContainer::Rectangle(RectanglePrimitive {
- color: *color,
+ operation: FillOrClear::Fill(*color),
}),
);
} else {
let blur_offset = 2.0 * blur_radius;
let mut extra_clips = vec![];
let mut blur_regions = vec![];
match clip_mode {
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -133,39 +133,53 @@ impl GpuCacheAddress {
#[derive(Debug)]
pub struct PrimitiveMetadata {
pub opacity: PrimitiveOpacity,
pub clip_sources: ClipSourcesHandle,
pub prim_kind: PrimitiveKind,
pub cpu_prim_index: SpecificPrimitiveIndex,
pub gpu_location: GpuCacheHandle,
pub clip_task_id: Option<RenderTaskId>,
+ pub is_clear: bool,
// TODO(gw): In the future, we should just pull these
// directly from the DL item, instead of
// storing them here.
pub local_rect: LayerRect,
pub local_clip_rect: LayerRect,
pub is_backface_visible: bool,
pub screen_rect: Option<DeviceIntRect>,
/// A tag used to identify this primitive outside of WebRender. This is
/// used for returning useful data during hit testing.
pub tag: Option<ItemTag>,
}
+#[derive(Debug,Clone,Copy)]
+pub enum FillOrClear {
+ Fill(ColorF),
+ Clear,
+}
+
#[derive(Debug)]
-#[repr(C)]
pub struct RectanglePrimitive {
- pub color: ColorF,
+ pub operation: FillOrClear,
}
impl ToGpuBlocks for RectanglePrimitive {
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
- request.push(self.color);
+ match &self.operation {
+ &FillOrClear::Fill(ref color) => {
+ request.push(color.premultiplied());
+ }
+ &FillOrClear::Clear => {
+ // Opaque black with operator dest out
+ request.push(ColorF::new(0.0, 0.0, 0.0, 1.0));
+ }
+ }
}
}
#[derive(Debug)]
pub struct BrushPrimitive {
pub clip_mode: ClipMode,
pub radius: BorderRadius,
}
@@ -862,24 +876,34 @@ impl PrimitiveStore {
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
is_backface_visible: is_backface_visible,
screen_rect: None,
tag,
opacity: PrimitiveOpacity::translucent(),
+ is_clear: false,
prim_kind: PrimitiveKind::Rectangle,
cpu_prim_index: SpecificPrimitiveIndex(0),
};
let metadata = match container {
PrimitiveContainer::Rectangle(rect) => {
+ let (opacity, is_clear) = match &rect.operation {
+ &FillOrClear::Fill(ref color) => {
+ (PrimitiveOpacity::from_alpha(color.a), false)
+ }
+ &FillOrClear::Clear => {
+ (PrimitiveOpacity::opaque(), true)
+ }
+ };
let metadata = PrimitiveMetadata {
- opacity: PrimitiveOpacity::from_alpha(rect.color.a),
+ opacity,
+ is_clear,
prim_kind: PrimitiveKind::Rectangle,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_rectangles.len()),
..base_metadata
};
self.cpu_rectangles.push(rect);
metadata
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -686,16 +686,17 @@ trait ToDebugString {
#[cfg(feature = "debugger")]
impl ToDebugString for SpecificDisplayItem {
fn debug_string(&self) -> String {
match *self {
SpecificDisplayItem::Image(..) => String::from("image"),
SpecificDisplayItem::YuvImage(..) => String::from("yuv_image"),
SpecificDisplayItem::Text(..) => String::from("text"),
SpecificDisplayItem::Rectangle(..) => String::from("rectangle"),
+ SpecificDisplayItem::ClearRectangle => String::from("clear_rectangle"),
SpecificDisplayItem::Line(..) => String::from("line"),
SpecificDisplayItem::Gradient(..) => String::from("gradient"),
SpecificDisplayItem::RadialGradient(..) => String::from("radial_gradient"),
SpecificDisplayItem::BoxShadow(..) => String::from("box_shadow"),
SpecificDisplayItem::Border(..) => String::from("border"),
SpecificDisplayItem::PushStackingContext(..) => String::from("push_stacking_context"),
SpecificDisplayItem::Iframe(..) => String::from("iframe"),
SpecificDisplayItem::Clip(..) => String::from("clip"),
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -613,16 +613,17 @@ impl SourceTextureResolver {
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum BlendMode {
None,
Alpha,
PremultipliedAlpha,
+ PremultipliedDestOut,
Subpixel,
}
// Tracks the state of each row in the GPU cache texture.
struct CacheRow {
is_dirty: bool,
}
@@ -2345,16 +2346,17 @@ impl Renderer {
GPU_TAG_PRIM_BLEND
}
BatchKind::Transformable(transform_kind, batch_kind) => match batch_kind {
TransformBatchKind::Rectangle(needs_clipping) => {
debug_assert!(
!needs_clipping || match key.blend_mode {
BlendMode::Alpha |
BlendMode::PremultipliedAlpha |
+ BlendMode::PremultipliedDestOut |
BlendMode::Subpixel => true,
BlendMode::None => false,
}
);
if needs_clipping {
self.ps_rectangle_clip.bind(
&mut self.device,
@@ -2710,16 +2712,17 @@ impl Renderer {
self.gpu_profile.add_sampler(GPU_SAMPLER_TAG_TRANSPARENT);
for batch in &target.alpha_batcher.batch_list.alpha_batch_list.batches {
if self.debug_flags.contains(DebugFlags::ALPHA_PRIM_DBG) {
let color = match batch.key.blend_mode {
BlendMode::None => ColorF::new(0.3, 0.3, 0.3, 1.0),
BlendMode::Alpha => ColorF::new(0.0, 0.9, 0.1, 1.0),
BlendMode::PremultipliedAlpha => ColorF::new(0.0, 0.3, 0.7, 1.0),
+ BlendMode::PremultipliedDestOut => ColorF::new(0.6, 0.2, 0.0, 1.0),
BlendMode::Subpixel => ColorF::new(0.5, 0.0, 0.4, 1.0),
}.into();
for item_rect in &batch.item_rects {
self.debug.add_rect(item_rect, color);
}
}
match batch.key.kind {
@@ -2786,17 +2789,17 @@ impl Renderer {
// When drawing the 2nd pass, we know that the VAO, textures etc
// are all set up from the previous draw_instanced_batch call,
// so just issue a draw call here to avoid re-uploading the
// instances and re-binding textures etc.
self.device
.draw_indexed_triangles_instanced_u16(6, batch.instances.len() as i32);
}
- BlendMode::Alpha | BlendMode::None => {
+ BlendMode::Alpha | BlendMode::PremultipliedDestOut | BlendMode::None => {
unreachable!("bug: bad blend mode for text");
}
}
prev_blend_mode = BlendMode::None;
self.device.set_blend(false);
}
_ => {
@@ -2808,16 +2811,20 @@ impl Renderer {
BlendMode::Alpha => {
self.device.set_blend(true);
self.device.set_blend_mode_alpha();
}
BlendMode::PremultipliedAlpha => {
self.device.set_blend(true);
self.device.set_blend_mode_premultiplied_alpha();
}
+ BlendMode::PremultipliedDestOut => {
+ self.device.set_blend(true);
+ self.device.set_blend_mode_premultiplied_dest_out();
+ }
BlendMode::Subpixel => {
unreachable!("bug: subpx text handled earlier");
}
}
prev_blend_mode = batch.key.blend_mode;
}
self.submit_batch(
--- a/gfx/webrender/src/tiling.rs
+++ b/gfx/webrender/src/tiling.rs
@@ -56,17 +56,24 @@ impl AlphaBatchHelpers for PrimitiveStor
PrimitiveKind::TextRun => {
let text_run_cpu = &self.cpu_text_runs[metadata.cpu_prim_index.0];
match text_run_cpu.font.render_mode {
FontRenderMode::Subpixel => BlendMode::Subpixel,
FontRenderMode::Alpha |
FontRenderMode::Mono |
FontRenderMode::Bitmap => BlendMode::PremultipliedAlpha,
}
- }
+ },
+ PrimitiveKind::Rectangle => if metadata.is_clear {
+ BlendMode::PremultipliedDestOut
+ } else if needs_blending {
+ BlendMode::PremultipliedAlpha
+ } else {
+ BlendMode::None
+ },
PrimitiveKind::Image |
PrimitiveKind::AlignedGradient |
PrimitiveKind::AngleGradient |
PrimitiveKind::RadialGradient |
PrimitiveKind::Picture => if needs_blending {
BlendMode::PremultipliedAlpha
} else {
BlendMode::None
@@ -248,17 +255,18 @@ impl BatchList {
fn get_suitable_batch(
&mut self,
key: BatchKey,
item_bounding_rect: &DeviceIntRect,
) -> &mut Vec<PrimitiveInstance> {
match key.blend_mode {
BlendMode::None => self.opaque_batch_list.get_suitable_batch(key),
- BlendMode::Alpha | BlendMode::PremultipliedAlpha | BlendMode::Subpixel => {
+ BlendMode::Alpha | BlendMode::PremultipliedAlpha |
+ BlendMode::PremultipliedDestOut | BlendMode::Subpixel => {
self.alpha_batch_list
.get_suitable_batch(key, item_bounding_rect)
}
}
}
fn finalize(&mut self) {
self.opaque_batch_list.finalize()
--- a/gfx/webrender_api/src/display_item.rs
+++ b/gfx/webrender_api/src/display_item.rs
@@ -86,16 +86,17 @@ pub type LayoutPrimitiveInfo = Primitive
pub type LayerPrimitiveInfo = PrimitiveInfo<LayerPixel>;
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum SpecificDisplayItem {
Clip(ClipDisplayItem),
ScrollFrame(ScrollFrameDisplayItem),
StickyFrame(StickyFrameDisplayItem),
Rectangle(RectangleDisplayItem),
+ ClearRectangle,
Line(LineDisplayItem),
Text(TextDisplayItem),
Image(ImageDisplayItem),
YuvImage(YuvImageDisplayItem),
Border(BorderDisplayItem),
BoxShadow(BoxShadowDisplayItem),
Gradient(GradientDisplayItem),
RadialGradient(RadialGradientDisplayItem),
--- a/gfx/webrender_api/src/display_list.rs
+++ b/gfx/webrender_api/src/display_list.rs
@@ -765,16 +765,20 @@ impl DisplayListBuilder {
debug_assert_eq!(len, count);
}
pub fn push_rect(&mut self, info: &LayoutPrimitiveInfo, color: ColorF) {
let item = SpecificDisplayItem::Rectangle(RectangleDisplayItem { color });
self.push_item(item, info);
}
+ pub fn push_clear_rect(&mut self, info: &LayoutPrimitiveInfo) {
+ self.push_item(SpecificDisplayItem::ClearRectangle, info);
+ }
+
pub fn push_line(
&mut self,
info: &LayoutPrimitiveInfo,
baseline: f32,
start: f32,
end: f32,
orientation: LineOrientation,
width: f32,
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -836,16 +836,24 @@ DisplayListBuilder::PushRect(const wr::L
WRDL_LOG("PushRect b=%s cl=%s c=%s\n", mWrState,
Stringify(aBounds).c_str(),
Stringify(aClip).c_str(),
Stringify(aColor).c_str());
wr_dp_push_rect(mWrState, aBounds, aClip, aIsBackfaceVisible, aColor);
}
void
+DisplayListBuilder::PushClearRect(const wr::LayoutRect& aBounds)
+{
+ WRDL_LOG("PushClearRect b=%s\n", mWrState,
+ Stringify(aBounds).c_str());
+ wr_dp_push_clear_rect(mWrState, aBounds);
+}
+
+void
DisplayListBuilder::PushLinearGradient(const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip,
bool aIsBackfaceVisible,
const wr::LayoutPoint& aStartPoint,
const wr::LayoutPoint& aEndPoint,
const nsTArray<wr::GradientStop>& aStops,
wr::ExtendMode aExtendMode,
const wr::LayoutSize aTileSize,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -253,16 +253,18 @@ public:
const wr::WrClipId* aClipId);
void PopClipAndScrollInfo();
void PushRect(const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip,
bool aIsBackfaceVisible,
const wr::ColorF& aColor);
+ void PushClearRect(const wr::LayoutRect& aBounds);
+
void PushLinearGradient(const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip,
bool aIsBackfaceVisible,
const wr::LayoutPoint& aStartPoint,
const wr::LayoutPoint& aEndPoint,
const nsTArray<wr::GradientStop>& aStops,
wr::ExtendMode aExtendMode,
const wr::LayoutSize aTileSize,
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1345,16 +1345,25 @@ pub extern "C" fn wr_dp_push_rect(state:
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
prim_info.is_backface_visible = is_backface_visible;
state.frame_builder.dl_builder.push_rect(&prim_info,
color);
}
#[no_mangle]
+pub extern "C" fn wr_dp_push_clear_rect(state: &mut WrState,
+ rect: LayoutRect) {
+ debug_assert!(unsafe { !is_in_render_thread() });
+
+ let prim_info = LayoutPrimitiveInfo::new(rect);
+ state.frame_builder.dl_builder.push_clear_rect(&prim_info);
+}
+
+#[no_mangle]
pub extern "C" fn wr_dp_push_image(state: &mut WrState,
bounds: LayoutRect,
clip: LayoutRect,
is_backface_visible: bool,
stretch_size: LayoutSize,
tile_spacing: LayoutSize,
image_rendering: ImageRendering,
key: WrImageKey) {
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1,13 +1,13 @@
/* 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/. */
-/* Generated with cbindgen:0.1.26 */
+/* Generated with cbindgen:0.1.25 */
/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
* To generate this file:
* 1. Get the latest cbindgen using `cargo install --force cbindgen`
* a. Alternatively, you can clone `https://github.com/rlhunt/cbindgen` and use a tagged release
* 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --crate webrender_bindings -o gfx/webrender_bindings/webrender_ffi_generated.h`
*/
@@ -274,17 +274,17 @@ struct TypedSize2D_f32__LayerPixel {
}
};
typedef TypedSize2D_f32__LayerPixel LayerSize;
typedef LayerSize LayoutSize;
// Describes the memory layout of a display list.
-//
+//
// A display list consists of some number of display list items, followed by a number of display
// items.
struct BuiltDisplayListDescriptor {
// The first IPC time stamp: before any work has been done
uint64_t builder_start_time;
// The second IPC time stamp: after serialization
uint64_t builder_finish_time;
// The third IPC time stamp: just before sending
@@ -314,27 +314,16 @@ struct WrOpacityProperty {
float opacity;
bool operator==(const WrOpacityProperty& aOther) const {
return id == aOther.id &&
opacity == aOther.opacity;
}
};
-// A 3d transform stored as a 4 by 4 matrix in row-major order in memory.
-//
-// Transforms can be parametrized over the source and destination units, to describe a
-// transformation from a space to another.
-// For example, `TypedTransform3D<f32, WordSpace, ScreenSpace>::transform_point3d`
-// takes a `TypedPoint3D<f32, WordSpace>` and returns a `TypedPoint3D<f32, ScreenSpace>`.
-//
-// Transforms expose a set of convenience methods for pre- and post-transformations.
-// A pre-transformation corresponds to adding an operation that is applied before
-// the rest of the transformation, while a post-transformation adds an operation
-// that is applied after.
struct TypedTransform3D_f32__LayoutPixel__LayoutPixel {
float m11;
float m12;
float m13;
float m14;
float m21;
float m22;
float m23;
@@ -390,34 +379,33 @@ struct IdNamespace {
bool operator<=(const IdNamespace& aOther) const {
return mHandle <= aOther.mHandle;
}
};
typedef IdNamespace WrIdNamespace;
// Represents RGBA screen colors with floating point numbers.
-//
+//
// All components must be between 0.0 and 1.0.
// An alpha value of 1.0 is opaque while 0.0 is fully transparent.
struct ColorF {
float r;
float g;
float b;
float a;
bool operator==(const ColorF& aOther) const {
return r == aOther.r &&
g == aOther.g &&
b == aOther.b &&
a == aOther.a;
}
};
-// A 2d Point tagged with a unit.
struct TypedPoint2D_f32__LayerPixel {
float x;
float y;
bool operator==(const TypedPoint2D_f32__LayerPixel& aOther) const {
return x == aOther.x &&
y == aOther.y;
}
@@ -577,17 +565,16 @@ struct NinePatchDescriptor {
bool operator==(const NinePatchDescriptor& aOther) const {
return width == aOther.width &&
height == aOther.height &&
slice == aOther.slice;
}
};
-// A 2d Vector tagged with a unit.
struct TypedVector2D_f32__LayerPixel {
float x;
float y;
bool operator==(const TypedVector2D_f32__LayerPixel& aOther) const {
return x == aOther.x &&
y == aOther.y;
}
@@ -658,17 +645,16 @@ struct ByteSlice {
size_t len;
bool operator==(const ByteSlice& aOther) const {
return buffer == aOther.buffer &&
len == aOther.len;
}
};
-// A 2d Point tagged with a unit.
struct TypedPoint2D_u16__Tiles {
uint16_t x;
uint16_t y;
bool operator==(const TypedPoint2D_u16__Tiles& aOther) const {
return x == aOther.x &&
y == aOther.y;
}
@@ -1053,16 +1039,21 @@ void wr_dp_push_box_shadow(WrState *aSta
ColorF aColor,
float aBlurRadius,
float aSpreadRadius,
float aBorderRadius,
BoxShadowClipMode aClipMode)
WR_FUNC;
WR_INLINE
+void wr_dp_push_clear_rect(WrState *aState,
+ LayoutRect aRect)
+WR_FUNC;
+
+WR_INLINE
void wr_dp_push_clip(WrState *aState,
uint64_t aClipId)
WR_FUNC;
WR_INLINE
void wr_dp_push_clip_and_scroll_info(WrState *aState,
uint64_t aScrollId,
const uint64_t *aClipId)
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -4649,16 +4649,32 @@ nsDisplayClearBackground::BuildLayer(nsD
bool snap;
nsRect bounds = GetBounds(aBuilder, &snap);
int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
layer->SetBounds(bounds.ToNearestPixels(appUnitsPerDevPixel)); // XXX Do we need to respect the parent layer's scale here?
return layer.forget();
}
+bool
+nsDisplayClearBackground::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+ mozilla::wr::IpcResourceUpdateQueue& aResources,
+ const StackingContextHelper& aSc,
+ mozilla::layers::WebRenderLayerManager* aManager,
+ nsDisplayListBuilder* aDisplayListBuilder)
+{
+ LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
+ nsRect(ToReferenceFrame(), mFrame->GetSize()),
+ mFrame->PresContext()->AppUnitsPerDevPixel());
+
+ aBuilder.PushClearRect(aSc.ToRelativeLayoutRect(bounds));
+
+ return true;
+}
+
nsRect
nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const
{
*aSnap = false;
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
}
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -4090,16 +4090,22 @@ public:
{
return mozilla::LAYER_ACTIVE_FORCE;
}
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
+ bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+ mozilla::wr::IpcResourceUpdateQueue& aResources,
+ const StackingContextHelper& aSc,
+ mozilla::layers::WebRenderLayerManager* aManager,
+ nsDisplayListBuilder* aDisplayListBuilder) override;
+
NS_DISPLAY_DECL_NAME("ClearBackground", TYPE_CLEAR_BACKGROUND)
};
/**
* The standard display item to paint the outer CSS box-shadows of a frame.
*/
class nsDisplayBoxShadowOuter final : public nsDisplayItem {
public: