mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
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.
This commit is contained in:
parent
00e2a1c62a
commit
b5d51dd263
20 changed files with 381 additions and 555 deletions
|
@ -10,16 +10,15 @@ use context::LayoutContext;
|
|||
use euclid::{Point2D, Vector2D, Rect, Size2D};
|
||||
use flow::{self, Flow};
|
||||
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
|
||||
use gfx::display_list::{DisplayItemMetadata, DisplayList, OpaqueNode, ScrollOffsetMap};
|
||||
use gfx::display_list::{DisplayList, OpaqueNode, ScrollOffsetMap};
|
||||
use inline::LAST_FRAGMENT_OF_ELEMENT;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use opaque_node::OpaqueNodeMethods;
|
||||
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse};
|
||||
use script_layout_interface::rpc::{HitTestResponse, LayoutRPC};
|
||||
use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC};
|
||||
use script_layout_interface::rpc::{MarginStyleResponse, NodeGeometryResponse};
|
||||
use script_layout_interface::rpc::{NodeOverflowResponse, OffsetParentResponse};
|
||||
use script_layout_interface::rpc::{NodeScrollRootIdResponse, ResolvedStyleResponse, TextIndexResponse};
|
||||
use script_layout_interface::rpc::{NodeOverflowResponse, NodeScrollRootIdResponse};
|
||||
use script_layout_interface::rpc::{OffsetParentResponse, ResolvedStyleResponse, TextIndexResponse};
|
||||
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
|
||||
use script_traits::LayoutMsg as ConstellationMsg;
|
||||
use script_traits::UntrustedNodeAddress;
|
||||
|
@ -35,7 +34,6 @@ use style::properties::{style_structs, PropertyId, PropertyDeclarationId, Longha
|
|||
use style::properties::longhands::{display, position};
|
||||
use style::selector_parser::PseudoElement;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::cursor::Cursor;
|
||||
use webrender_api::ClipId;
|
||||
use wrapper::LayoutNodeLayoutData;
|
||||
|
||||
|
@ -58,9 +56,6 @@ pub struct LayoutThreadData {
|
|||
/// A queued response for the client {top, left, width, height} of a node in pixels.
|
||||
pub client_rect_response: Rect<i32>,
|
||||
|
||||
/// A queued response for the node at a given point
|
||||
pub hit_test_response: (Option<DisplayItemMetadata>, bool),
|
||||
|
||||
/// A queued response for the scroll root id for a given node.
|
||||
pub scroll_root_id_response: Option<ClipId>,
|
||||
|
||||
|
@ -119,24 +114,6 @@ impl LayoutRPC for LayoutRPCImpl {
|
|||
ContentBoxesResponse(rw_data.content_boxes_response.clone())
|
||||
}
|
||||
|
||||
/// Requests the node containing the point of interest.
|
||||
fn hit_test(&self) -> HitTestResponse {
|
||||
let &LayoutRPCImpl(ref rw_data) = self;
|
||||
let rw_data = rw_data.lock().unwrap();
|
||||
let &(ref result, update_cursor) = &rw_data.hit_test_response;
|
||||
if update_cursor {
|
||||
// Compute the new cursor.
|
||||
let cursor = match *result {
|
||||
None => Cursor::Default,
|
||||
Some(dim) => dim.pointing.unwrap(),
|
||||
};
|
||||
rw_data.constellation_chan.send(ConstellationMsg::SetCursor(cursor)).unwrap();
|
||||
}
|
||||
HitTestResponse {
|
||||
node_address: result.map(|dim| dim.node.to_untrusted_node_address()),
|
||||
}
|
||||
}
|
||||
|
||||
fn nodes_from_point_response(&self) -> Vec<UntrustedNodeAddress> {
|
||||
let &LayoutRPCImpl(ref rw_data) = self;
|
||||
let rw_data = rw_data.lock().unwrap();
|
||||
|
|
|
@ -19,23 +19,12 @@ use style::values::generics::effects::Filter as GenericFilter;
|
|||
use webrender_api::{self, ClipAndScrollInfo, ComplexClipRegion, DisplayListBuilder};
|
||||
use webrender_api::{ExtendMode, LayoutTransform};
|
||||
|
||||
fn prim_info(local_rect: Rect<Au>,
|
||||
local_clip: Option<webrender_api::LocalClip>) -> webrender_api::LayoutPrimitiveInfo {
|
||||
match local_clip {
|
||||
Some(local_clip) => {
|
||||
webrender_api::LayoutPrimitiveInfo::with_clip(local_rect.to_rectf(), local_clip)
|
||||
}
|
||||
None => {
|
||||
webrender_api::LayoutPrimitiveInfo::new(local_rect.to_rectf())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WebRenderDisplayListConverter {
|
||||
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder;
|
||||
}
|
||||
|
||||
trait WebRenderDisplayItemConverter {
|
||||
fn prim_info(&self) -> webrender_api::LayoutPrimitiveInfo;
|
||||
fn convert_to_webrender(&self,
|
||||
builder: &mut DisplayListBuilder,
|
||||
current_clip_and_scroll_info: &mut ClipAndScrollInfo);
|
||||
|
@ -249,6 +238,20 @@ impl WebRenderDisplayListConverter for DisplayList {
|
|||
}
|
||||
|
||||
impl WebRenderDisplayItemConverter for DisplayItem {
|
||||
fn prim_info(&self) -> webrender_api::LayoutPrimitiveInfo {
|
||||
let tag = match self.base().metadata.pointing {
|
||||
Some(cursor) => Some((self.base().metadata.node.0 as u64, cursor as u8)),
|
||||
None => None,
|
||||
};
|
||||
webrender_api::LayoutPrimitiveInfo {
|
||||
rect: self.base().bounds.to_rectf(),
|
||||
local_clip: self.base().local_clip,
|
||||
// TODO(gw): Make use of the WR backface visibility functionality.
|
||||
is_backface_visible: true,
|
||||
tag: tag,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_webrender(&self,
|
||||
builder: &mut DisplayListBuilder,
|
||||
current_clip_and_scroll_info: &mut ClipAndScrollInfo) {
|
||||
|
@ -261,11 +264,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
|
||||
match *self {
|
||||
DisplayItem::SolidColor(ref item) => {
|
||||
let color = item.color;
|
||||
if color.a > 0.0 {
|
||||
builder.push_rect(&prim_info(item.base.bounds, Some(item.base.local_clip)),
|
||||
color);
|
||||
}
|
||||
builder.push_rect(&self.prim_info(), item.color);
|
||||
}
|
||||
DisplayItem::Text(ref item) => {
|
||||
let mut origin = item.baseline_origin.clone();
|
||||
|
@ -294,7 +293,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
}
|
||||
|
||||
if glyphs.len() > 0 {
|
||||
builder.push_text(&prim_info(item.base.bounds, Some(item.base.local_clip)),
|
||||
builder.push_text(&self.prim_info(),
|
||||
&glyphs,
|
||||
item.text_run.font_key,
|
||||
item.text_color,
|
||||
|
@ -305,7 +304,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
if let Some(id) = item.webrender_image.key {
|
||||
if item.stretch_size.width > Au(0) &&
|
||||
item.stretch_size.height > Au(0) {
|
||||
builder.push_image(&prim_info(item.base.bounds, Some(item.base.local_clip)),
|
||||
builder.push_image(&self.prim_info(),
|
||||
item.stretch_size.to_sizef(),
|
||||
item.tile_spacing.to_sizef(),
|
||||
item.image_rendering.to_image_rendering(),
|
||||
|
@ -314,7 +313,6 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
}
|
||||
}
|
||||
DisplayItem::Border(ref item) => {
|
||||
let rect = item.base.bounds;
|
||||
let widths = item.border_widths.to_border_widths();
|
||||
|
||||
let details = match item.details {
|
||||
|
@ -395,7 +393,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
}
|
||||
};
|
||||
|
||||
builder.push_border(&prim_info(rect, Some(item.base.local_clip)), widths, details);
|
||||
builder.push_border(&self.prim_info(), widths, details);
|
||||
}
|
||||
DisplayItem::Gradient(ref item) => {
|
||||
let rect = item.base.bounds;
|
||||
|
@ -410,7 +408,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
end_point,
|
||||
item.gradient.stops.clone(),
|
||||
extend_mode);
|
||||
builder.push_gradient(&prim_info(rect, Some(item.base.local_clip)),
|
||||
builder.push_gradient(&self.prim_info(),
|
||||
gradient,
|
||||
rect.size.to_sizef(),
|
||||
webrender_api::LayoutSize::zero());
|
||||
|
@ -428,14 +426,14 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
radius,
|
||||
item.gradient.stops.clone(),
|
||||
extend_mode);
|
||||
builder.push_radial_gradient(&prim_info(rect, Some(item.base.local_clip)),
|
||||
builder.push_radial_gradient(&self.prim_info(),
|
||||
gradient,
|
||||
rect.size.to_sizef(),
|
||||
webrender_api::LayoutSize::zero());
|
||||
}
|
||||
DisplayItem::Line(ref item) => {
|
||||
let box_bounds = item.base.bounds.to_rectf();
|
||||
builder.push_line(&prim_info(item.base.bounds, Some(item.base.local_clip)),
|
||||
builder.push_line(&self.prim_info(),
|
||||
box_bounds.origin.y + box_bounds.size.height,
|
||||
box_bounds.origin.x,
|
||||
box_bounds.origin.x + box_bounds.size.width,
|
||||
|
@ -445,9 +443,8 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
item.style);
|
||||
}
|
||||
DisplayItem::BoxShadow(ref item) => {
|
||||
let rect = item.base.bounds;
|
||||
let box_bounds = item.box_bounds.to_rectf();
|
||||
builder.push_box_shadow(&prim_info(rect, Some(item.base.local_clip)),
|
||||
builder.push_box_shadow(&self.prim_info(),
|
||||
box_bounds,
|
||||
item.offset.to_vectorf(),
|
||||
item.color,
|
||||
|
@ -457,8 +454,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
item.clip_mode.to_clip_mode());
|
||||
}
|
||||
DisplayItem::PushTextShadow(ref item) => {
|
||||
let rect = item.base.bounds;
|
||||
builder.push_shadow(&prim_info(rect, Some(item.base.local_clip)),
|
||||
builder.push_shadow(&self.prim_info(),
|
||||
webrender_api::Shadow {
|
||||
blur_radius: item.blur_radius.to_f32_px(),
|
||||
offset: item.offset.to_vectorf(),
|
||||
|
@ -469,9 +465,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
builder.pop_all_shadows();
|
||||
}
|
||||
DisplayItem::Iframe(ref item) => {
|
||||
let rect = item.base.bounds;
|
||||
let pipeline_id = item.iframe.to_webrender();
|
||||
builder.push_iframe(&prim_info(rect, Some(item.base.local_clip)), pipeline_id);
|
||||
builder.push_iframe(&self.prim_info(), item.iframe.to_webrender());
|
||||
}
|
||||
DisplayItem::PushStackingContext(ref item) => {
|
||||
let stacking_context = &item.stacking_context;
|
||||
|
@ -484,13 +478,15 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
LayoutTransform::from_untyped(&perspective)
|
||||
});
|
||||
|
||||
builder.push_stacking_context(&prim_info(stacking_context.bounds, None),
|
||||
stacking_context.scroll_policy,
|
||||
transform,
|
||||
stacking_context.transform_style,
|
||||
perspective,
|
||||
stacking_context.mix_blend_mode,
|
||||
stacking_context.filters.to_filter_ops());
|
||||
builder.push_stacking_context(
|
||||
&webrender_api::LayoutPrimitiveInfo::new(stacking_context.bounds.to_rectf()),
|
||||
stacking_context.scroll_policy,
|
||||
transform,
|
||||
stacking_context.transform_style,
|
||||
perspective,
|
||||
stacking_context.mix_blend_mode,
|
||||
stacking_context.filters.to_filter_ops()
|
||||
);
|
||||
}
|
||||
DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
|
||||
DisplayItem::DefineClipScrollNode(ref item) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue