diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-10-17 17:09:25 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-17 17:09:25 -0500 |
commit | ca08271345f78fa881c174545f5b69a8ccb78143 (patch) | |
tree | 6e1244687e960df40313b3a24a167135654dae31 /components/layout_thread | |
parent | 0e62a5829b7c29ae2667a21a439aff1e89201bf3 (diff) | |
parent | b5d51dd2636935471447fc741ffbb95c62e37f94 (diff) | |
download | servo-ca08271345f78fa881c174545f5b69a8ccb78143.tar.gz servo-ca08271345f78fa881c174545f5b69a8ccb78143.zip |
Auto merge of #18704 - mrobinson:wr-hit-testing, r=jdm,glennw,mbrubeck
Switch to using WebRender hit testing
This trades quite a bit of complicated code in Servo for few more
messages and a significant performance improvement. In particular,
WebRender can search the entire display list at once instead of
ping-ponging down the pipeline tree. This allows us to send mouse
events to the correct pipeline immediately.
<!-- Please describe your changes on the following line: -->
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because they should not change behavior.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18704)
<!-- Reviewable:end -->
Diffstat (limited to 'components/layout_thread')
-rw-r--r-- | components/layout_thread/Cargo.toml | 1 | ||||
-rw-r--r-- | components/layout_thread/lib.rs | 71 |
2 files changed, 35 insertions, 37 deletions
diff --git a/components/layout_thread/Cargo.toml b/components/layout_thread/Cargo.toml index 4106e86e47c..6108c9c2447 100644 --- a/components/layout_thread/Cargo.toml +++ b/components/layout_thread/Cargo.toml @@ -25,6 +25,7 @@ ipc-channel = "0.9" layout = {path = "../layout"} layout_traits = {path = "../layout_traits"} lazy_static = "0.2" +libc = "0.2" log = "0.3.5" metrics = {path = "../metrics"} msg = {path = "../msg"} diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 528e06c6424..ab3e620c16e 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -22,6 +22,7 @@ extern crate layout; extern crate layout_traits; #[macro_use] extern crate lazy_static; +extern crate libc; #[macro_use] extern crate log; extern crate metrics; @@ -73,7 +74,6 @@ use layout::flow::{self, Flow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow_ref::FlowRef; use layout::incremental::{LayoutDamageComputation, REFLOW_ENTIRE_DOCUMENT, RelayoutMode}; use layout::layout_debug; -use layout::opaque_node::OpaqueNodeMethods; use layout::parallel; use layout::query::{LayoutRPCImpl, LayoutThreadData, process_content_box_request, process_content_boxes_request}; use layout::query::{process_margin_style_query, process_node_overflow_request, process_resolved_style_request}; @@ -84,6 +84,7 @@ use layout::traversal::{ComputeStackingRelativePositions, PreorderFlowTraversal, use layout::webrender_helpers::WebRenderDisplayListConverter; use layout::wrapper::LayoutNodeLayoutData; use layout_traits::LayoutThreadFactory; +use libc::c_void; use metrics::{PaintTimeMetrics, ProfilerMetadataFactory}; use msg::constellation_msg::PipelineId; use msg::constellation_msg::TopLevelBrowsingContextId; @@ -92,8 +93,8 @@ use parking_lot::RwLock; use profile_traits::mem::{self, Report, ReportKind, ReportsChan}; use profile_traits::time::{self, TimerMetadata, profile}; use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType}; -use script_layout_interface::message::{Msg, NewLayoutThreadInfo, Reflow, ReflowGoal}; -use script_layout_interface::message::{ScriptReflow, ReflowComplete}; +use script_layout_interface::message::{Msg, NewLayoutThreadInfo, NodesFromPointQueryType, Reflow}; +use script_layout_interface::message::{ReflowComplete, ReflowGoal, ScriptReflow}; use script_layout_interface::rpc::{LayoutRPC, MarginStyleResponse, NodeOverflowResponse, OffsetParentResponse}; use script_layout_interface::rpc::TextIndexResponse; use script_layout_interface::wrapper_traits::LayoutNode; @@ -120,10 +121,8 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::{Receiver, Sender, channel}; use std::thread; use style::animation::Animation; -use style::context::{QuirksMode, SharedStyleContext}; -use style::context::{StyleSystemOptions, ThreadLocalStyleContextCreationInfo}; -use style::context::RegisteredSpeculativePainter; -use style::context::RegisteredSpeculativePainters; +use style::context::{QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters}; +use style::context::{SharedStyleContext, StyleSystemOptions, ThreadLocalStyleContextCreationInfo}; use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode}; use style::driver; use style::error_reporting::{NullReporter, RustLogReporter}; @@ -519,7 +518,6 @@ impl LayoutThread { content_box_response: None, content_boxes_response: Vec::new(), client_rect_response: Rect::zero(), - hit_test_response: (None, false), scroll_root_id_response: None, scroll_area_response: Rect::zero(), overflow_response: NodeOverflowResponse(None), @@ -705,6 +703,14 @@ impl LayoutThread { Msg::UpdateScrollStateFromScript(state) => { let mut rw_data = possibly_locked_rw_data.lock(); rw_data.scroll_offsets.insert(state.scroll_root_id, state.scroll_offset); + + let point = Point2D::new(-state.scroll_offset.x, -state.scroll_offset.y); + self.webrender_api.scroll_node_with_id( + self.webrender_document, + webrender_api::LayoutPoint::from_untyped(&point), + state.scroll_root_id, + webrender_api::ScrollClamping::ToContentBounds + ); } Msg::ReapStyleAndLayoutData(dead_data) => { unsafe { @@ -1078,10 +1084,7 @@ impl LayoutThread { ReflowGoal::ContentBoxesQuery(_) => { rw_data.content_boxes_response = Vec::new(); }, - ReflowGoal::HitTestQuery(..) => { - rw_data.hit_test_response = (None, false); - }, - ReflowGoal::NodesFromPoint(..) => { + ReflowGoal::NodesFromPointQuery(..) => { rw_data.nodes_from_point_response = Vec::new(); }, ReflowGoal::NodeGeometryQuery(_) => { @@ -1355,15 +1358,6 @@ impl LayoutThread { let node = unsafe { ServoLayoutNode::new(&node) }; rw_data.content_boxes_response = process_content_boxes_request(node, root_flow); }, - ReflowGoal::HitTestQuery(client_point, update_cursor) => { - let point = Point2D::new(Au::from_f32_px(client_point.x), - Au::from_f32_px(client_point.y)); - let result = rw_data.display_list - .as_ref() - .expect("Tried to hit test with no display list") - .hit_test(&point, &rw_data.scroll_offsets); - rw_data.hit_test_response = (result.last().cloned(), update_cursor); - }, ReflowGoal::TextIndexQuery(node, mouse_x, mouse_y) => { let node = unsafe { ServoLayoutNode::new(&node) }; let opaque_node = node.opaque(); @@ -1411,25 +1405,28 @@ impl LayoutThread { let node = unsafe { ServoLayoutNode::new(&node) }; rw_data.margin_style_response = process_margin_style_query(node); }, - ReflowGoal::NodesFromPoint(client_point) => { - let client_point = Point2D::new(Au::from_f32_px(client_point.x), - Au::from_f32_px(client_point.y)); - let nodes_from_point_list = { - let result = match rw_data.display_list { - None => panic!("Tried to hit test without a DisplayList"), - Some(ref display_list) => { - display_list.hit_test(&client_point, &rw_data.scroll_offsets) - } - }; - - result + ReflowGoal::NodesFromPointQuery(client_point, ref reflow_goal) => { + let mut flags = match reflow_goal { + &NodesFromPointQueryType::Topmost => webrender_api::HitTestFlags::empty(), + &NodesFromPointQueryType::All => webrender_api::HitTestFlags::FIND_ALL, }; - rw_data.nodes_from_point_response = nodes_from_point_list.iter() - .rev() - .map(|metadata| metadata.node.to_untrusted_node_address()) + // The point we get is not relative to the entire WebRender scene, but to this + // particular pipeline, so we need to tell WebRender about that. + flags.insert(webrender_api::HitTestFlags::POINT_RELATIVE_TO_PIPELINE_VIEWPORT); + + let client_point = webrender_api::WorldPoint::from_untyped(&client_point); + let results = self.webrender_api.hit_test( + self.webrender_document, + Some(self.id.to_webrender()), + client_point, + flags + ); + + rw_data.nodes_from_point_response = results.items.iter() + .map(|item| UntrustedNodeAddress(item.tag.0 as *const c_void)) .collect() - } + }, ReflowGoal::Full | ReflowGoal::TickAnimations => {} } |