Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync changes from mozilla-central gfx/wr #3847

Merged
merged 2 commits into from Feb 3, 2020
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -20,9 +20,9 @@ that can handle all CSS content.

# Current Design

All positioning and clipping is handled by the `ClipScrollTree`. The name is a
All positioning and clipping is handled by the `SpatialTree`. The name is a
holdover from when this tree was a tree of `Layers` which handled both
positioning and clipping. Currently the `ClipScrollTree` holds:
positioning and clipping. Currently the `SpatialTree` holds:
1. A hierarchical collection of `SpatialNodes`, with the final screen
transformation of each node depending on the relative transformation of the
node combined with the transformations of all of its ancestors. These nodes
@@ -57,7 +57,7 @@ There are three types of `SpatialNodes`:
This is also an 2D translation.

`SpatialNodes` are defined as items in the display list. After scene building
each node is traversed hierarchically during the `ClipScrollTree::update()` step.
each node is traversed hierarchically during the `SpatialTree::update()` step.
Once reference frame transforms and relative offsets are calculated, a to screen
space transformation can be calculated for each `SpatialNode`. This transformation
is added the `TransformPalette` and becomes directly available to WebRender shaders.
@@ -79,7 +79,7 @@ screen space rectangle. This rectangle is called the _outer rectangle_ of the
clip. `ClipNodes` may also have an _inner rectangle_, which is an area within
the boundaries of the _outer rectangle_ that is completely unclipped.

These rectangles are calculated during the `ClipScrollTree::update()` phase. In
These rectangles are calculated during the `SpatialTree::update()` phase. In
addition, each `ClipNode` produces a template `ClipChainNode` used to build
the `ClipChains` which use that node.

@@ -127,24 +127,24 @@ per-pipeline indices, to global scene-wide indices. Internally this is a
conversion from `ClipId` into `ClipNodeIndex` or `ClipChainIndex`, and from
`SpatialId` into `SpatialNodeIndex`. In order to make this conversion cheaper, the
`DisplayListFlattner` assigns offsets for each pipeline and node type in the
scene-wide `ClipScrollTree`.
scene-wide `SpatialTree`.

Nodes are added to their respective arrays sequentially as the display list is
processed during scene building. When encountering an iframe, the
`DisplayListFlattener` must start processing the nodes for that iframe's
pipeline, meaning that nodes are now being added out of order to the node arrays
of the `ClipScrollTree`. In this case, the `ClipScrollTree` fills in the gaps in
of the `SpatialTree`. In this case, the `SpatialTree` fills in the gaps in
the node arrays with placeholder nodes.

# Hit Testing

Hit testing is the responsibility of the `HitTester` data structure. This
structure copies information necessary for hit testing from the
`ClipScrollTree`. This is done so that hit testing can still take place while a
new `ClipScrollTree` is under construction.
`SpatialTree`. This is done so that hit testing can still take place while a
new `SpatialTree` is under construction.

# Ideas for the Future
1. Expose the difference between `ClipId` and `ClipChainId` in the API.
2. Prevent having to duplicate the `ClipScrollTree` for hit testing.
3. Avoid having to create placeholder nodes in the `ClipScrollTree` while
2. Prevent having to duplicate the `SpatialTree` for hit testing.
3. Avoid having to create placeholder nodes in the `SpatialTree` while
processing iframes.
@@ -6,7 +6,7 @@ use api::{AlphaType, ClipMode, ExternalImageType, ImageRendering};
use api::{YuvColorSpace, YuvFormat, ColorDepth, ColorRange, PremultipliedColorF};
use api::units::*;
use crate::clip::{ClipDataStore, ClipNodeFlags, ClipNodeRange, ClipItemKind, ClipStore};
use crate::clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex, CoordinateSystemId};
use crate::spatial_tree::{SpatialTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex, CoordinateSystemId};
use crate::composite::{CompositeState};
use crate::glyph_rasterizer::GlyphFormat;
use crate::gpu_cache::{GpuBlockData, GpuCache, GpuCacheHandle, GpuCacheAddress};
@@ -718,7 +718,7 @@ impl BatchBuilder {
.get_id(
prim_spatial_node_index,
root_spatial_node_index,
ctx.clip_scroll_tree,
ctx.spatial_tree,
);

// TODO(gw): Calculating this for every primitive is a bit
@@ -1137,7 +1137,7 @@ impl BatchBuilder {
.get_id(
child.spatial_node_index,
root_spatial_node_index,
ctx.clip_scroll_tree,
ctx.spatial_tree,
),
};

@@ -1210,7 +1210,7 @@ impl BatchBuilder {
ROOT_SPATIAL_NODE_INDEX,
tile_cache.spatial_node_index,
ctx.screen_world_rect,
ctx.clip_scroll_tree,
ctx.spatial_tree,
);
let local_tile_clip_rect = LayoutRect::from_untyped(&tile_cache.local_rect.to_untyped());
let local_tile_clip_rect = match local_tile_clip_rect.intersection(&prim_info.combined_local_clip_rect) {
@@ -2833,7 +2833,7 @@ impl ClipBatcher {
mask_screen_rect: DeviceIntRect,
local_clip_rect: LayoutRect,
clip_spatial_node_index: SpatialNodeIndex,
clip_scroll_tree: &ClipScrollTree,
spatial_tree: &SpatialTree,
world_rect: &WorldRect,
device_pixel_scale: DevicePixelScale,
gpu_address: GpuCacheAddress,
@@ -2845,7 +2845,7 @@ impl ClipBatcher {
return false;
}

let clip_spatial_node = &clip_scroll_tree
let clip_spatial_node = &spatial_tree
.spatial_nodes[clip_spatial_node_index.0 as usize];

// Only support clips that are axis-aligned to the root coordinate space,
@@ -2857,7 +2857,7 @@ impl ClipBatcher {

// Get the world rect of the clip rectangle. If we can't transform it due
// to the matrix, just fall back to drawing the entire clip mask.
let transform = clip_scroll_tree.get_world_transform(
let transform = spatial_tree.get_world_transform(
clip_spatial_node_index,
);
let world_clip_rect = match project_rect(
@@ -2937,7 +2937,7 @@ impl ClipBatcher {
resource_cache: &ResourceCache,
gpu_cache: &GpuCache,
clip_store: &ClipStore,
clip_scroll_tree: &ClipScrollTree,
spatial_tree: &SpatialTree,
transforms: &mut TransformPalette,
clip_data_store: &ClipDataStore,
actual_rect: DeviceIntRect,
@@ -2955,13 +2955,13 @@ impl ClipBatcher {
let clip_transform_id = transforms.get_id(
clip_node.item.spatial_node_index,
ROOT_SPATIAL_NODE_INDEX,
clip_scroll_tree,
spatial_tree,
);

let prim_transform_id = transforms.get_id(
root_spatial_node_index,
ROOT_SPATIAL_NODE_INDEX,
clip_scroll_tree,
spatial_tree,
);

let instance = ClipMaskInstance {
@@ -3078,7 +3078,7 @@ impl ClipBatcher {
actual_rect,
rect,
clip_node.item.spatial_node_index,
clip_scroll_tree,
spatial_tree,
world_rect,
device_pixel_scale,
gpu_address,
@@ -97,7 +97,7 @@ use api::{BoxShadowClipMode, ImageKey, ImageRendering};
use api::units::*;
use crate::border::{ensure_no_corner_overlap, BorderRadiusAu};
use crate::box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, SpatialNodeIndex};
use crate::spatial_tree::{ROOT_SPATIAL_NODE_INDEX, SpatialTree, SpatialNodeIndex};
use crate::ellipse::Ellipse;
use crate::gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use crate::gpu_types::{BoxShadowStretchMode};
@@ -289,14 +289,14 @@ impl ClipSpaceConversion {
fn new(
prim_spatial_node_index: SpatialNodeIndex,
clip_spatial_node_index: SpatialNodeIndex,
clip_scroll_tree: &ClipScrollTree,
spatial_tree: &SpatialTree,
) -> Self {
//Note: this code is different from `get_relative_transform` in a way that we only try
// getting the relative transform if it's Local or ScaleOffset,
// falling back to the world transform otherwise.
let clip_spatial_node = &clip_scroll_tree
let clip_spatial_node = &spatial_tree
.spatial_nodes[clip_spatial_node_index.0 as usize];
let prim_spatial_node = &clip_scroll_tree
let prim_spatial_node = &spatial_tree
.spatial_nodes[prim_spatial_node_index.0 as usize];

if prim_spatial_node_index == clip_spatial_node_index {
@@ -308,7 +308,7 @@ impl ClipSpaceConversion {
ClipSpaceConversion::ScaleOffset(scale_offset)
} else {
ClipSpaceConversion::Transform(
clip_scroll_tree
spatial_tree
.get_world_transform(clip_spatial_node_index)
.into_transform()
)
@@ -346,7 +346,7 @@ impl ClipNodeInfo {
clipped_rect: &LayoutRect,
gpu_cache: &mut GpuCache,
resource_cache: &mut ResourceCache,
clip_scroll_tree: &ClipScrollTree,
spatial_tree: &SpatialTree,
request_resources: bool,
) -> Option<ClipNodeInstance> {
// Calculate some flags that are required for the segment
@@ -358,7 +358,7 @@ impl ClipNodeInfo {
// the mask for a single corner at a time then, so can always consider radii uniform.
let is_raster_2d =
flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) ||
clip_scroll_tree
spatial_tree
.get_world_viewport_transform(node.item.spatial_node_index)
.is_2d_axis_aligned();
if is_raster_2d && node.item.kind.supports_fast_path_rendering() {
@@ -752,7 +752,7 @@ impl ClipStore {
local_prim_clip_rect: LayoutRect,
spatial_node_index: SpatialNodeIndex,
clip_chains: &[ClipChainId],
clip_scroll_tree: &ClipScrollTree,
spatial_tree: &SpatialTree,
clip_data_store: &mut ClipDataStore,
) {
self.active_clip_node_info.clear();
@@ -769,7 +769,7 @@ impl ClipStore {
&mut local_clip_rect,
&mut self.active_clip_node_info,
clip_data_store,
clip_scroll_tree,
spatial_tree,
) {
return;
}
@@ -783,7 +783,7 @@ impl ClipStore {
&mut self,
prim_clip_chain: &ClipChainInstance,
prim_spatial_node_index: SpatialNodeIndex,
clip_scroll_tree: &ClipScrollTree,
spatial_tree: &SpatialTree,
clip_data_store: &ClipDataStore,
) {
// TODO(gw): Although this does less work than set_active_clips(), it does
@@ -800,7 +800,7 @@ impl ClipStore {
let conversion = ClipSpaceConversion::new(
prim_spatial_node_index,
clip_node.item.spatial_node_index,
clip_scroll_tree,
spatial_tree,
);
self.active_clip_node_info.push(ClipNodeInfo {
handle: clip_instance.handle,
@@ -816,7 +816,7 @@ impl ClipStore {
local_prim_rect: LayoutRect,
prim_to_pic_mapper: &SpaceMapper<LayoutPixel, PicturePixel>,
pic_to_world_mapper: &SpaceMapper<PicturePixel, WorldPixel>,
clip_scroll_tree: &ClipScrollTree,
spatial_tree: &SpatialTree,
gpu_cache: &mut GpuCache,
resource_cache: &mut ResourceCache,
device_pixel_scale: DevicePixelScale,
@@ -897,7 +897,7 @@ impl ClipStore {
&local_bounding_rect,
gpu_cache,
resource_cache,
clip_scroll_tree,
spatial_tree,
request_resources,
) {
// As a special case, a partial accept of a clip rect that is
@@ -1588,7 +1588,7 @@ fn add_clip_node_to_current_chain(
local_clip_rect: &mut LayoutRect,
clip_node_info: &mut Vec<ClipNodeInfo>,
clip_data_store: &ClipDataStore,
clip_scroll_tree: &ClipScrollTree,
spatial_tree: &SpatialTree,
) -> bool {
let clip_node = &clip_data_store[node.handle];

@@ -1597,7 +1597,7 @@ fn add_clip_node_to_current_chain(
let conversion = ClipSpaceConversion::new(
spatial_node_index,
clip_node.item.spatial_node_index,
clip_scroll_tree,
spatial_tree,
);

// If we can convert spaces, try to reduce the size of the region
@@ -82,7 +82,7 @@ impl ws::Handler for Server {
"fetch_passes" => DebugCommand::FetchPasses,
"fetch_screenshot" => DebugCommand::FetchScreenshot,
"fetch_documents" => DebugCommand::FetchDocuments,
"fetch_clip_scroll_tree" => DebugCommand::FetchClipScrollTree,
"fetch_spatial_tree" => DebugCommand::FetchClipScrollTree,
"fetch_render_tasks" => DebugCommand::FetchRenderTasks,
msg => {
error!("unknown msg {}", msg);
@@ -322,19 +322,19 @@ impl Screenshot {
}
}

// A serializable list of debug information about clip-scroll trees
// A serializable list of debug information about spatial trees
// that can be sent to the client

#[derive(Serialize)]
pub struct ClipScrollTreeList {
pub struct SpatialTreeList {
kind: &'static str,
root: TreeNode,
}

impl ClipScrollTreeList {
impl SpatialTreeList {
pub fn new() -> Self {
ClipScrollTreeList {
kind: "clip_scroll_tree",
SpatialTreeList {
kind: "spatial_tree",
root: TreeNode::new("root"),
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.