WIP: update webrender draft
authorAlexis Beingessner <a.beingessner@gmail.com>
Tue, 11 Jul 2017 10:49:34 -0400
changeset 608675 9e1d068ba329ec601f1133631b49008d61981892
parent 608674 8bb2c64ba96f7820accd76857005d5f0a15fa2db
child 637387 ecb91361018a961f5445131f94822a45d56489a5
push id68368
push userbmo:a.beingessner@gmail.com
push dateFri, 14 Jul 2017 01:37:37 +0000
milestone56.0a1
WIP: update webrender MozReview-Commit-ID: CgXdorbaZn5
gfx/webrender/examples/basic.rs
gfx/webrender/src/frame.rs
gfx/webrender/src/frame_builder.rs
gfx/webrender_api/src/display_item.rs
gfx/webrender_api/src/display_list.rs
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/webrender/examples/basic.rs
+++ b/gfx/webrender/examples/basic.rs
@@ -285,17 +285,16 @@ fn body(api: &RenderApi,
         ];
 
         builder.push_text(text_bounds,
                           None,
                           &glyphs,
                           font_key,
                           ColorF::new(1.0, 1.0, 0.0, 1.0),
                           Au::from_px(32),
-                          0.0,
                           None);
     }
 
     if false { // draw box shadow?
         let rect = LayoutRect::zero();
         let simple_box_bounds = (20, 200).by(50, 50);
         let offset = vec2(10.0, 10.0);
         let color = ColorF::new(1.0, 1.0, 1.0, 1.0);
--- a/gfx/webrender/src/frame.rs
+++ b/gfx/webrender/src/frame.rs
@@ -578,17 +578,16 @@ impl Frame {
                                               info.image_rendering);
             }
             SpecificDisplayItem::Text(ref text_info) => {
                 context.builder.add_text(clip_and_scroll,
                                          item.rect(),
                                          item.local_clip(),
                                          text_info.font_key,
                                          text_info.size,
-                                         text_info.blur_radius,
                                          &text_info.color,
                                          item.glyphs(),
                                          item.display_list().get(item.glyphs()).count(),
                                          text_info.glyph_options);
             }
             SpecificDisplayItem::Rectangle(ref info) => {
                 if !self.try_to_add_rectangle_splitting_on_clip(context,
                                                                 &item.rect(),
@@ -713,16 +712,22 @@ impl Frame {
             }
             SpecificDisplayItem::PopNestedDisplayList => context.pop_nested_display_list_ids(),
 
             // Do nothing; these are dummy items for the display list parser
             SpecificDisplayItem::SetGradientStops => { }
 
             SpecificDisplayItem::PopStackingContext =>
                 unreachable!("Should have returned in parent method."),
+            SpecificDisplayItem::PushTextShadow(shadow) => {
+                context.builder.push_text_shadow(shadow);
+            }
+            SpecificDisplayItem::PopTextShadow => {
+                context.builder.pop_text_shadow();
+            }
         }
         None
     }
 
     /// Try to optimize the rendering of a solid rectangle that is clipped by a single
     /// rounded rectangle, by only masking the parts of the rectangle that intersect
     /// the rounded parts of the clip. This is pretty simple now, so has a lot of
     /// potential for further optimizations.
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -1,18 +1,18 @@
 /* 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, BoxShadowClipMode, ClipAndScrollInfo, ClipId, ColorF};
 use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
 use api::{ExtendMode, FontKey, FontRenderMode, GlyphInstance, GlyphOptions, GradientStop};
 use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize};
-use api::{LayerToScrollTransform, LayerVector2D, LocalClip, PipelineId, RepeatMode, TileOffset};
-use api::{TransformStyle, WebGLContextId, WorldPixel, YuvColorSpace, YuvData};
+use api::{LayerToScrollTransform, LayerVector2D, LocalClip, PipelineId, RepeatMode, TextShadow};
+use api::{TileOffset, TransformStyle, WebGLContextId, WorldPixel, YuvColorSpace, YuvData};
 use app_units::Au;
 use frame::FrameId;
 use gpu_cache::GpuCache;
 use internal_types::HardwareCompositeOp;
 use mask_cache::{ClipMode, ClipRegion, ClipSource, MaskCacheInfo};
 use plane_split::{BspSplitter, Polygon, Splitter};
 use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu};
 use prim_store::{ImagePrimitiveKind, PrimitiveContainer, PrimitiveIndex};
@@ -111,16 +111,17 @@ pub struct FrameBuilder {
     background_color: Option<ColorF>,
     prim_store: PrimitiveStore,
     cmds: Vec<PrimitiveRunCmd>,
     config: FrameBuilderConfig,
 
     stacking_context_store: Vec<StackingContext>,
     clip_scroll_group_store: Vec<ClipScrollGroup>,
     packed_layers: Vec<PackedLayer>,
+    text_shadows: Vec<TextShadow>,
 
     scrollbar_prims: Vec<ScrollbarPrimitive>,
 
     /// A stack of scroll nodes used during display list processing to properly
     /// parent new scroll nodes.
     reference_frame_stack: Vec<ClipId>,
 
     /// A stack of stacking contexts used for creating ClipScrollGroups as
@@ -139,32 +140,34 @@ impl FrameBuilder {
                config: FrameBuilderConfig) -> FrameBuilder {
         match previous {
             Some(prev) => {
                 FrameBuilder {
                     stacking_context_store: recycle_vec(prev.stacking_context_store),
                     clip_scroll_group_store: recycle_vec(prev.clip_scroll_group_store),
                     cmds: recycle_vec(prev.cmds),
                     packed_layers: recycle_vec(prev.packed_layers),
+                    text_shadows: recycle_vec(prev.text_shadows),
                     scrollbar_prims: recycle_vec(prev.scrollbar_prims),
                     reference_frame_stack: recycle_vec(prev.reference_frame_stack),
                     stacking_context_stack: recycle_vec(prev.stacking_context_stack),
                     prim_store: prev.prim_store.recycle(),
                     screen_size,
                     background_color,
                     config,
                     has_root_stacking_context: false,
                 }
             }
             None => {
                 FrameBuilder {
                     stacking_context_store: Vec::new(),
                     clip_scroll_group_store: Vec::new(),
                     cmds: Vec::new(),
                     packed_layers: Vec::new(),
+                    text_shadows: Vec::new(),
                     scrollbar_prims: Vec::new(),
                     reference_frame_stack: Vec::new(),
                     stacking_context_stack: Vec::new(),
                     prim_store: PrimitiveStore::new(),
                     screen_size,
                     background_color,
                     config,
                     has_root_stacking_context: false,
@@ -282,16 +285,18 @@ impl FrameBuilder {
         self.has_root_stacking_context = true;
         self.cmds.push(PrimitiveRunCmd::PushStackingContext(stacking_context_index));
         self.stacking_context_stack.push(stacking_context_index);
     }
 
     pub fn pop_stacking_context(&mut self) {
         self.cmds.push(PrimitiveRunCmd::PopStackingContext);
         self.stacking_context_stack.pop();
+        assert!(self.text_shadows.is_empty(),
+            "Found unpopped text shadows when popping stacking context!");
     }
 
     pub fn push_reference_frame(&mut self,
                                 parent_id: Option<ClipId>,
                                 pipeline_id: PipelineId,
                                 rect: &LayerRect,
                                 transform: &LayerToScrollTransform,
                                 clip_scroll_tree: &mut ClipScrollTree)
@@ -387,16 +392,24 @@ impl FrameBuilder {
 
         clip_scroll_tree.add_node(node, new_node_id);
     }
 
     pub fn pop_reference_frame(&mut self) {
         self.reference_frame_stack.pop();
     }
 
+    pub fn push_text_shadow(&mut self, shadow: TextShadow) {
+        self.text_shadows.push(shadow);
+    }
+
+    pub fn pop_text_shadow(&mut self) {
+        self.text_shadows.pop().expect("Too many PopTextShadows?");
+    }
+
     pub fn add_solid_rectangle(&mut self,
                                clip_and_scroll: ClipAndScrollInfo,
                                rect: &LayerRect,
                                local_clip: &LocalClip,
                                color: &ColorF,
                                flags: PrimitiveFlags) {
         if color.a == 0.0 {
             return;
@@ -727,29 +740,30 @@ impl FrameBuilder {
     }
 
     pub fn add_text(&mut self,
                     clip_and_scroll: ClipAndScrollInfo,
                     rect: LayerRect,
                     local_clip: &LocalClip,
                     font_key: FontKey,
                     size: Au,
-                    blur_radius: f32,
                     color: &ColorF,
                     glyph_range: ItemRange<GlyphInstance>,
                     glyph_count: usize,
                     glyph_options: Option<GlyphOptions>) {
         if color.a == 0.0 {
             return
         }
 
         if size.0 <= 0 {
             return
         }
 
+        let mut blur_radius = 0.0; // TODO: remove this in favour of PushTextShadow handling
+
         // Expand the rectangle of the text run by the blur radius.
         let rect = rect.inflate(blur_radius, blur_radius);
 
         // TODO(gw): Use a proper algorithm to select
         // whether this item should be rendered with
         // subpixel AA!
         let mut render_mode = self.config.default_font_render_mode;
 
--- a/gfx/webrender_api/src/display_item.rs
+++ b/gfx/webrender_api/src/display_item.rs
@@ -60,16 +60,18 @@ pub enum SpecificDisplayItem {
     Gradient(GradientDisplayItem),
     RadialGradient(RadialGradientDisplayItem),
     Iframe(IframeDisplayItem),
     PushStackingContext(PushStackingContextDisplayItem),
     PopStackingContext,
     SetGradientStops,
     PushNestedDisplayList,
     PopNestedDisplayList,
+    PushTextShadow(TextShadow),
+    PopTextShadow,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct ClipDisplayItem {
     pub id: ClipId,
     pub parent_id: ClipId,
     pub image_mask: Option<ImageMask>,
 }
@@ -79,17 +81,16 @@ pub struct RectangleDisplayItem {
     pub color: ColorF,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct TextDisplayItem {
     pub font_key: FontKey,
     pub size: Au,
     pub color: ColorF,
-    pub blur_radius: f32,
     pub glyph_options: Option<GlyphOptions>,
 } // IMPLICIT: glyphs: Vec<GlyphInstance>
 
 #[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
 pub struct GlyphOptions {
     // These are currently only used on windows for dwrite fonts.
     pub use_embedded_bitmap: bool,
     pub force_gdi_rendering: bool,
@@ -219,16 +220,23 @@ pub struct BoxShadowDisplayItem {
     pub offset: LayoutVector2D,
     pub color: ColorF,
     pub blur_radius: f32,
     pub spread_radius: f32,
     pub border_radius: f32,
     pub clip_mode: BoxShadowClipMode,
 }
 
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
+pub struct TextShadow {
+    pub offset: LayoutVector2D,
+    pub color: ColorF,
+    pub blur_radius: f32,
+}
+
 #[repr(u32)]
 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
 pub enum ExtendMode {
     Clamp,
     Repeat,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
--- a/gfx/webrender_api/src/display_list.rs
+++ b/gfx/webrender_api/src/display_list.rs
@@ -9,17 +9,17 @@ use serde::ser::{SerializeSeq, Serialize
 use time::precise_time_ns;
 use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem};
 use {ClipAndScrollInfo, ClipDisplayItem, ClipId, ColorF, ComplexClipRegion, DisplayItem};
 use {ExtendMode, FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem};
 use {GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering};
 use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, LocalClip};
 use {MixBlendMode, PipelineId, PropertyBinding, PushStackingContextDisplayItem, RadialGradient};
 use {RadialGradientDisplayItem, RectangleDisplayItem, ScrollPolicy, SpecificDisplayItem};
-use {StackingContext, TextDisplayItem, TransformStyle, WebGLContextId, WebGLDisplayItem};
+use {StackingContext, TextDisplayItem, TextShadow, TransformStyle, WebGLContextId, WebGLDisplayItem};
 use {YuvColorSpace, YuvData, YuvImageDisplayItem};
 use std::marker::PhantomData;
 
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub struct ItemRange<T> {
     start: usize,
     length: usize,
@@ -538,30 +538,28 @@ impl DisplayListBuilder {
 
     pub fn push_text(&mut self,
                      rect: LayoutRect,
                      local_clip: Option<LocalClip>,
                      glyphs: &[GlyphInstance],
                      font_key: FontKey,
                      color: ColorF,
                      size: Au,
-                     blur_radius: f32,
                      glyph_options: Option<GlyphOptions>) {
         // Sanity check - anything with glyphs bigger than this
         // is probably going to consume too much memory to render
         // efficiently anyway. This is specifically to work around
         // the font_advance.html reftest, which creates a very large
         // font as a crash test - the rendering is also ignored
         // by the azure renderer.
         if size < Au::from_px(4096) {
             let item = SpecificDisplayItem::Text(TextDisplayItem {
                 color,
                 font_key,
                 size,
-                blur_radius,
                 glyph_options,
             });
 
             self.push_item(item, rect, local_clip);
             self.push_iter(glyphs);
         }
     }
 
@@ -909,16 +907,24 @@ impl DisplayListBuilder {
     // will replace references to the root scroll frame id with the current scroll frame
     // id.
     pub fn push_nested_display_list(&mut self, built_display_list: &BuiltDisplayList) {
         self.push_new_empty_item(SpecificDisplayItem::PushNestedDisplayList);
         self.data.extend_from_slice(&built_display_list.data);
         self.push_new_empty_item(SpecificDisplayItem::PopNestedDisplayList);
     }
 
+    pub fn push_text_shadow(&mut self, shadow: TextShadow) {
+        self.push_new_empty_item(SpecificDisplayItem::PushTextShadow(shadow));
+    }
+
+    pub fn pop_text_shadow(&mut self) {
+        self.push_new_empty_item(SpecificDisplayItem::PopTextShadow);
+    }
+
     pub fn finalize(self) -> (PipelineId, LayoutSize, BuiltDisplayList) {
         let end_time = precise_time_ns();
 
         (self.pipeline_id,
          self.content_size,
          BuiltDisplayList {
             descriptor: BuiltDisplayListDescriptor {
                 builder_start_time: self.builder_start_time,
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -455,16 +455,28 @@ struct WrGlyphInstance {
   WrPoint point;
 
   bool operator==(const WrGlyphInstance& aOther) const {
     return index == aOther.index &&
            point == aOther.point;
   }
 };
 
+struct WrTextShadow {
+  WrPoint offset;
+  WrColor color;
+  float blur_radius;
+
+  bool operator==(const WrTextShadow& aOther) const {
+    return offset == aOther.offset &&
+           color == aOther.color &&
+           blur_radius == aOther.blur_radius;
+  }
+};
+
 struct MutByteSlice {
   uint8_t *buffer;
   size_t len;
 
   bool operator==(const MutByteSlice& aOther) const {
     return buffer == aOther.buffer &&
            len == aOther.len;
   }
@@ -668,16 +680,20 @@ WR_INLINE
 void wr_dp_pop_scroll_layer(WrState *aState)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_pop_stacking_context(WrState *aState)
 WR_FUNC;
 
 WR_INLINE
+void wr_dp_pop_text_shadow(WrState *aState)
+WR_FUNC;
+
+WR_INLINE
 void wr_dp_push_border(WrState *aState,
                        WrRect aRect,
                        WrRect aClip,
                        WrBorderWidths aWidths,
                        WrBorderSide aTop,
                        WrBorderSide aRight,
                        WrBorderSide aBottom,
                        WrBorderSide aLeft,
@@ -830,16 +846,21 @@ void wr_dp_push_text(WrState *aState,
                      WrColor aColor,
                      WrFontKey aFontKey,
                      const WrGlyphInstance *aGlyphs,
                      uint32_t aGlyphCount,
                      float aGlyphSize)
 WR_FUNC;
 
 WR_INLINE
+void wr_dp_push_text_shadow(WrState *aState,
+                            WrTextShadow aShadow)
+WR_FUNC;
+
+WR_INLINE
 void wr_dp_push_yuv_NV12_image(WrState *aState,
                                WrRect aBounds,
                                WrRect aClip,
                                WrImageKey aImageKey0,
                                WrImageKey aImageKey1,
                                WrYuvColorSpace aColorSpace,
                                WrImageRendering aImageRendering)
 WR_FUNC;