Skip to content

Commit

Permalink
script: Keep the DOM-side viewport up to date when scrolling happens in
Browse files Browse the repository at this point in the history
WebRender.

This happens asynchronously, just as it does in non-WebRender mode.

This functionality is a prerequisite for doing proper display-list-based
hit testing in WebRender, since it moves the scroll offsets into Servo
(and, specifically, into the script thread, enabling iframe event
forwarding) instead of keeping them private to WebRender.

Requires servo/webrender_traits#55 and servo/webrender#277.

Partially addresses #11108.
  • Loading branch information
pcwalton committed May 31, 2016
1 parent 55b0bb0 commit a86f77e
Show file tree
Hide file tree
Showing 32 changed files with 317 additions and 98 deletions.
78 changes: 68 additions & 10 deletions components/compositing/compositor.rs
Expand Up @@ -15,7 +15,8 @@ use euclid::scale_factor::ScaleFactor;
use euclid::size::TypedSize2D;
use euclid::{Matrix4D, Point2D, Rect, Size2D};
use gfx::paint_thread::{ChromeToPaintMsg, PaintRequest};
use gfx_traits::{color, Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, ScrollPolicy};
use gfx_traits::{ScrollPolicy, StackingContextId};
use gfx_traits::{color, Epoch, FrameTreeId, FragmentType, LayerId, LayerKind, LayerProperties};
use gleam::gl;
use gleam::gl::types::{GLint, GLsizei};
use image::{DynamicImage, ImageFormat, RgbImage};
Expand All @@ -35,8 +36,8 @@ use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg};
use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton};
use script_traits::{MouseEventType, TouchpadPressurePhase, TouchEventType, TouchId};
use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton, MouseEventType};
use script_traits::{StackingContextScrollState, TouchpadPressurePhase, TouchEventType, TouchId};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{HashMap, HashSet};
use std::fs::File;
Expand Down Expand Up @@ -91,6 +92,32 @@ impl ConvertPipelineIdFromWebRender for webrender_traits::PipelineId {
}
}

trait ConvertStackingContextFromWebRender {
fn from_webrender(&self) -> StackingContextId;
}

impl ConvertStackingContextFromWebRender for webrender_traits::ServoStackingContextId {
fn from_webrender(&self) -> StackingContextId {
StackingContextId::new_of_type(self.1, self.0.from_webrender())
}
}

trait ConvertFragmentTypeFromWebRender {
fn from_webrender(&self) -> FragmentType;
}

impl ConvertFragmentTypeFromWebRender for webrender_traits::FragmentType {
fn from_webrender(&self) -> FragmentType {
match *self {
webrender_traits::FragmentType::FragmentBody => FragmentType::FragmentBody,
webrender_traits::FragmentType::BeforePseudoContent => {
FragmentType::BeforePseudoContent
}
webrender_traits::FragmentType::AfterPseudoContent => FragmentType::AfterPseudoContent,
}
}
}

/// Holds the state when running reftests that determines when it is
/// safe to save the output image.
#[derive(Copy, Clone, PartialEq)]
Expand Down Expand Up @@ -1620,12 +1647,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {

self.perform_updates_after_scroll();
}

if had_events {
self.send_viewport_rects_for_all_layers();
}
}
}

if had_events {
self.send_viewport_rects_for_all_layers();
}
}

/// Computes new display ports for each layer, taking the scroll position into account, and
Expand Down Expand Up @@ -1887,9 +1914,40 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}

fn send_viewport_rects_for_all_layers(&self) {
match self.scene.root {
Some(ref root) => self.send_viewport_rect_for_layer(root.clone()),
None => {},
if opts::get().use_webrender {
return self.send_webrender_viewport_rects()
}

if let Some(ref root) = self.scene.root {
self.send_viewport_rect_for_layer(root.clone())
}
}

fn send_webrender_viewport_rects(&self) {
let mut stacking_context_scroll_states_per_pipeline = HashMap::new();
if let Some(ref webrender_api) = self.webrender_api {
for scroll_layer_state in webrender_api.get_scroll_layer_state() {
let stacking_context_scroll_state = StackingContextScrollState {
stacking_context_id: scroll_layer_state.stacking_context_id.from_webrender(),
scroll_offset: scroll_layer_state.scroll_offset,
};
let pipeline_id = scroll_layer_state.pipeline_id;
match stacking_context_scroll_states_per_pipeline.entry(pipeline_id) {
Vacant(mut entry) => {
entry.insert(vec![stacking_context_scroll_state]);
}
Occupied(mut entry) => entry.get_mut().push(stacking_context_scroll_state),
}
}

for (pipeline_id, stacking_context_scroll_states) in
stacking_context_scroll_states_per_pipeline {
if let Some(pipeline) = self.pipeline(pipeline_id.from_webrender()) {
let msg = LayoutControlMsg::SetStackingContextScrollStates(
stacking_context_scroll_states);
let _ = pipeline.layout_chan.send(msg);
}
}
}
}

Expand Down
33 changes: 1 addition & 32 deletions components/gfx/display_list/mod.rs
Expand Up @@ -22,7 +22,7 @@ use euclid::num::Zero;
use euclid::rect::TypedRect;
use euclid::{Matrix2D, Matrix4D, Point2D, Rect, SideOffsets2D, Size2D};
use fnv::FnvHasher;
use gfx_traits::{LayerId, ScrollPolicy};
use gfx_traits::{LayerId, ScrollPolicy, StackingContextId};
use ipc_channel::ipc::IpcSharedMemory;
use msg::constellation_msg::PipelineId;
use net_traits::image::base::{Image, PixelFormat};
Expand Down Expand Up @@ -1395,37 +1395,6 @@ impl fmt::Debug for DisplayItem {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf, RustcEncodable)]
pub enum FragmentType {
/// A StackingContext for the fragment body itself.
FragmentBody,
/// A StackingContext created to contain ::before pseudo-element content.
BeforePseudoContent,
/// A StackingContext created to contain ::after pseudo-element content.
AfterPseudoContent,
}

/// A unique ID for every stacking context.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, RustcEncodable, Serialize)]
pub struct StackingContextId(
/// The identifier for this StackingContext, derived from the Flow's memory address
/// and fragment type. As a space optimization, these are combined into a single word.
usize
);

impl StackingContextId {
#[inline(always)]
pub fn new(id: usize) -> StackingContextId {
StackingContextId::new_of_type(id, FragmentType::FragmentBody)
}

#[inline(always)]
pub fn new_of_type(id: usize, fragment_type: FragmentType) -> StackingContextId {
debug_assert_eq!(id & fragment_type as usize, 0);
StackingContextId(id | fragment_type as usize)
}
}

#[derive(Copy, Clone, HeapSizeOf, Deserialize, Serialize)]
pub struct WebRenderImageInfo {
pub width: u32,
Expand Down
3 changes: 2 additions & 1 deletion components/gfx/paint_thread.rs
Expand Up @@ -8,13 +8,14 @@ use app_units::Au;
use azure::AzFloat;
use azure::azure_hl::{BackendType, Color, DrawTarget, SurfaceFormat};
use display_list::{DisplayItem, DisplayList, DisplayListTraversal};
use display_list::{LayerInfo, StackingContext, StackingContextId, StackingContextType};
use display_list::{LayerInfo, StackingContext, StackingContextType};
use euclid::Matrix4D;
use euclid::point::Point2D;
use euclid::rect::Rect;
use euclid::size::Size2D;
use font_cache_thread::FontCacheThread;
use font_context::FontContext;
use gfx_traits::StackingContextId;
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener};
use ipc_channel::ipc::IpcSender;
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
Expand Down
55 changes: 55 additions & 0 deletions components/gfx_traits/lib.rs
Expand Up @@ -149,3 +149,58 @@ impl FrameTreeId {
self.0 += 1;
}
}

/// A unique ID for every stacking context.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, Serialize)]
pub struct StackingContextId(
/// The identifier for this StackingContext, derived from the Flow's memory address
/// and fragment type. As a space optimization, these are combined into a single word.
usize
);

impl StackingContextId {
#[inline(always)]
pub fn new(id: usize) -> StackingContextId {
StackingContextId::new_of_type(id, FragmentType::FragmentBody)
}

#[inline(always)]
pub fn new_of_type(id: usize, fragment_type: FragmentType) -> StackingContextId {
debug_assert_eq!(id & fragment_type as usize, 0);
StackingContextId(id | fragment_type as usize)
}

#[inline]
pub fn fragment_type(&self) -> FragmentType {
FragmentType::from_usize(self.0 & 3)
}

#[inline]
pub fn id(&self) -> usize {
self.0 & !3
}
}


#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf)]
pub enum FragmentType {
/// A StackingContext for the fragment body itself.
FragmentBody,
/// A StackingContext created to contain ::before pseudo-element content.
BeforePseudoContent,
/// A StackingContext created to contain ::after pseudo-element content.
AfterPseudoContent,
}

impl FragmentType {
#[inline]
pub fn from_usize(n: usize) -> FragmentType {
debug_assert!(n < 3);
match n {
0 => FragmentType::FragmentBody,
1 => FragmentType::BeforePseudoContent,
_ => FragmentType::AfterPseudoContent,
}
}
}

4 changes: 2 additions & 2 deletions components/layout/block.rs
Expand Up @@ -43,8 +43,8 @@ use flow_list::FlowList;
use flow_ref::FlowRef;
use fragment::SpecificFragmentInfo;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER, Overflow};
use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId};
use gfx_traits::LayerId;
use gfx::display_list::{ClippingRegion, StackingContext};
use gfx_traits::{LayerId, StackingContextId};
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT};
use layout_debug;
use layout_thread::DISPLAY_PORT_SIZE_FACTOR;
Expand Down
11 changes: 5 additions & 6 deletions components/layout/display_list_builder.rs
Expand Up @@ -21,17 +21,16 @@ use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref;
use fragment::SpecificFragmentInfo;
use fragment::{CoordinateSystem, Fragment, HAS_LAYER, ImageFragmentInfo, ScannedTextFragmentInfo};
use gfx::display_list::GradientDisplayItem;
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection};
use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem, LayeredItem, LayerInfo};
use gfx::display_list::{LineDisplayItem, OpaqueNode, SolidColorDisplayItem};
use gfx::display_list::{StackingContext, StackingContextId, StackingContextType};
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection, GradientDisplayItem};
use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem};
use gfx::display_list::{LayeredItem, LayerInfo, LineDisplayItem, OpaqueNode};
use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType};
use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo};
use gfx::paint_thread::THREAD_TINT_COLORS;
use gfx::text::glyph::ByteIndex;
use gfx_traits::{color, ScrollPolicy};
use gfx_traits::{color, ScrollPolicy, StackingContextId};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc;
use list_item::ListItemFlow;
Expand Down
3 changes: 2 additions & 1 deletion components/layout/flex.rs
Expand Up @@ -17,7 +17,8 @@ use flow::{Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
use flow::{INLINE_POSITION_IS_STATIC, IS_ABSOLUTELY_POSITIONED};
use flow_ref::{self, FlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
use model::{IntrinsicISizes, MaybeAuto, MinMaxConstraint};
Expand Down
4 changes: 2 additions & 2 deletions components/layout/flow.rs
Expand Up @@ -34,8 +34,8 @@ use floats::{Floats, SpeculatedFloatPlacement};
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
use flow_ref::{self, FlowRef, WeakFlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId};
use gfx_traits::{LayerId, LayerType};
use gfx::display_list::{ClippingRegion, StackingContext};
use gfx_traits::{LayerId, LayerType, StackingContextId};
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use inline::InlineFlow;
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
Expand Down
4 changes: 2 additions & 2 deletions components/layout/fragment.rs
Expand Up @@ -14,10 +14,10 @@ use floats::ClearType;
use flow::{self, ImmutableFlowUtils};
use flow_ref::{self, FlowRef};
use gfx;
use gfx::display_list::{BLUR_INFLATION_FACTOR, FragmentType, OpaqueNode, StackingContextId};
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
use gfx::text::glyph::ByteIndex;
use gfx::text::text_run::{TextRun, TextRunSlice};
use gfx_traits::{LayerId, LayerType};
use gfx_traits::{FragmentType, LayerId, LayerType, StackingContextId};
use incremental::{RECONSTRUCT_FLOW, RestyleDamage};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo};
use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};
Expand Down
3 changes: 2 additions & 1 deletion components/layout/inline.rs
Expand Up @@ -17,9 +17,10 @@ use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, IS_ABSOLUTELY_P
use flow_ref;
use fragment::SpecificFragmentInfo;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{OpaqueNode, StackingContext, StackingContextId};
use gfx::display_list::{OpaqueNode, StackingContext};
use gfx::font::FontMetrics;
use gfx::font_context::FontContext;
use gfx_traits::StackingContextId;
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RESOLVE_GENERATED_CONTENT};
use layout_debug;
use model::IntrinsicISizesContribution;
Expand Down

0 comments on commit a86f77e

Please sign in to comment.