aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout_thread
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-10-17 17:09:25 -0500
committerGitHub <noreply@github.com>2017-10-17 17:09:25 -0500
commitca08271345f78fa881c174545f5b69a8ccb78143 (patch)
tree6e1244687e960df40313b3a24a167135654dae31 /components/layout_thread
parent0e62a5829b7c29ae2667a21a439aff1e89201bf3 (diff)
parentb5d51dd2636935471447fc741ffbb95c62e37f94 (diff)
downloadservo-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.toml1
-rw-r--r--components/layout_thread/lib.rs71
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 => {}
}