Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 43 additions & 60 deletions webrender/src/batch.rs

Large diffs are not rendered by default.

109 changes: 30 additions & 79 deletions webrender/src/clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@

use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D, LocalClip};
use api::{BoxShadowClipMode, LayoutToWorldScale, LineOrientation, LineStyle};
use api::{LayoutToWorldTransform, WorldPixel, WorldRect, WorldPoint, WorldSize};
use api::{BoxShadowClipMode, LayoutToWorldScale, LineOrientation, LineStyle, PicturePixel, WorldPixel};
use api::{PictureRect, LayoutPixel, WorldPoint, WorldSize, WorldRect, LayoutToWorldTransform};
use border::{ensure_no_corner_overlap};
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
use clip_scroll_tree::{ClipScrollTree, CoordinateSystemId, SpatialNodeIndex};
use ellipse::Ellipse;
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use gpu_types::BoxShadowStretchMode;
use plane_split::{Clipper, Polygon};
use prim_store::{ClipData, ImageMaskData};
use gpu_types::{BoxShadowStretchMode};
use prim_store::{ClipData, ImageMaskData, SpaceMapper};
use render_task::to_cache_size;
use resource_cache::{ImageRequest, ResourceCache};
use std::{cmp, u32};
use util::{extract_inner_rect_safe, pack_as_float, recycle_vec, MaxRect};
use util::{extract_inner_rect_safe, pack_as_float, project_rect, recycle_vec};

/*

Expand Down Expand Up @@ -322,10 +321,14 @@ pub struct ClipStore {
#[derive(Debug)]
pub struct ClipChainInstance {
pub clips_range: ClipNodeRange,
// Combined clip rect for clips that are in the
// same coordinate system as the primitive.
pub local_clip_rect: LayoutRect,
pub has_non_root_coord_system: bool,
pub has_non_local_clips: bool,
pub world_clip_rect: WorldRect,
// Combined clip rect in picture space (may
// be more conservative that local_clip_rect).
pub pic_clip_rect: PictureRect,
}

impl ClipStore {
Expand Down Expand Up @@ -416,13 +419,14 @@ impl ClipStore {
local_prim_rect: LayoutRect,
local_prim_clip_rect: LayoutRect,
spatial_node_index: SpatialNodeIndex,
prim_to_pic_mapper: &SpaceMapper<LayoutPixel, PicturePixel>,
pic_to_world_mapper: &SpaceMapper<PicturePixel, WorldPixel>,
clip_scroll_tree: &ClipScrollTree,
gpu_cache: &mut GpuCache,
resource_cache: &mut ResourceCache,
device_pixel_scale: DevicePixelScale,
) -> Option<ClipChainInstance> {
let mut local_clip_rect = local_prim_clip_rect;
let mut world_clip_rect = WorldRect::max_rect();
let spatial_nodes = &clip_scroll_tree.spatial_nodes;

// Walk the clip chain to build local rects, and collect the
Expand Down Expand Up @@ -480,19 +484,16 @@ impl ClipStore {
None => return None,
};
}
ClipSpaceConversion::Transform(ref transform) => {
let world_clip_rect_for_item = match project_rect(
transform,
&clip_rect,
) {
Some(rect) => rect,
None => return None,
};

world_clip_rect = match world_clip_rect.intersection(&world_clip_rect_for_item) {
Some(world_clip_rect) => world_clip_rect,
None => return None,
};
ClipSpaceConversion::Transform(..) => {
// TODO(gw): In the future, we can reduce the size
// of the pic_clip_rect here. To do this,
// we can use project_rect or the
// inverse_rect_footprint method, depending
// on the relationship of the clip, pic
// and primitive spatial nodes.
// I have left this for now until we
// find some good test cases where this
// would be a worthwhile perf win.
}
}
}
Expand All @@ -512,15 +513,12 @@ impl ClipStore {
None => return None,
};

let world_bounding_rect = match project_rect(
&ref_spatial_node.world_content_transform.to_transform(),
&local_bounding_rect,
) {
Some(world_bounding_rect) => world_bounding_rect,
let pic_clip_rect = match prim_to_pic_mapper.map(&local_bounding_rect) {
Some(pic_bounding_rect) => pic_bounding_rect,
None => return None,
};

let world_clip_rect = match world_clip_rect.intersection(&world_bounding_rect) {
let world_clip_rect = match pic_to_world_mapper.map(&pic_clip_rect) {
Some(world_clip_rect) => world_clip_rect,
None => return None,
};
Expand Down Expand Up @@ -551,7 +549,7 @@ impl ClipStore {
has_non_local_clips = true;
node.item.get_clip_result_complex(
transform,
&world_bounding_rect,
&world_clip_rect,
)
}
};
Expand Down Expand Up @@ -609,7 +607,7 @@ impl ClipStore {
has_non_root_coord_system,
has_non_local_clips,
local_clip_rect,
world_clip_rect,
pic_clip_rect,
})
}
}
Expand Down Expand Up @@ -870,7 +868,7 @@ impl ClipItem {
fn get_clip_result_complex(
&self,
transform: &LayoutToWorldTransform,
prim_rect: &WorldRect,
prim_world_rect: &WorldRect,
) -> ClipResult {
let (clip_rect, inner_rect) = match *self {
ClipItem::Rectangle(clip_rect, ClipMode::Clip) => {
Expand All @@ -894,7 +892,7 @@ impl ClipItem {
});

if let Some(inner_clip_rect) = inner_clip_rect {
if inner_clip_rect.contains_rect(prim_rect) {
if inner_clip_rect.contains_rect(prim_world_rect) {
return ClipResult::Accept;
}
}
Expand All @@ -904,7 +902,7 @@ impl ClipItem {
None => return ClipResult::Partial,
};

match outer_clip_rect.intersection(prim_rect) {
match outer_clip_rect.intersection(prim_world_rect) {
Some(..) => {
ClipResult::Partial
}
Expand Down Expand Up @@ -1067,53 +1065,6 @@ pub fn rounded_rectangle_contains_point(
true
}

fn project_rect(
transform: &LayoutToWorldTransform,
rect: &LayoutRect,
) -> Option<WorldRect> {
let homogens = [
transform.transform_point2d_homogeneous(&rect.origin),
transform.transform_point2d_homogeneous(&rect.top_right()),
transform.transform_point2d_homogeneous(&rect.bottom_left()),
transform.transform_point2d_homogeneous(&rect.bottom_right()),
];

// Note: we only do the full frustum collision when the polygon approaches the camera plane.
// Otherwise, it will be clamped to the screen bounds anyway.
if homogens.iter().any(|h| h.w <= 0.0) {
let mut clipper = Clipper::new();
clipper.add_frustum(
transform,
None,
);

let polygon = Polygon::from_rect(*rect, 1);
let results = clipper.clip(polygon);
if results.is_empty() {
return None
}

Some(WorldRect::from_points(results
.into_iter()
// filter out parts behind the view plane
.flat_map(|poly| &poly.points)
.map(|p| {
let mut homo = transform.transform_point2d_homogeneous(&p.to_2d());
homo.w = homo.w.max(0.00000001); // avoid infinite values
homo.to_point2d().unwrap()
})
))
} else {
// we just checked for all the points to be in positive hemisphere, so `unwrap` is valid
Some(WorldRect::from_points(&[
homogens[0].to_point2d().unwrap(),
homogens[1].to_point2d().unwrap(),
homogens[2].to_point2d().unwrap(),
homogens[3].to_point2d().unwrap(),
]))
}
}

pub fn project_inner_rect(
transform: &LayoutToWorldTransform,
rect: &LayoutRect,
Expand Down
68 changes: 50 additions & 18 deletions webrender/src/frame_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{ColorF, DeviceIntPoint, DeviceIntRect, DevicePixelScale};
use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize, DocumentLayer, FontRenderMode};
use api::{LayoutPoint, LayoutRect, LayoutSize, PipelineId, WorldPoint};
use api::{ColorF, DeviceIntPoint, DevicePixelScale, LayoutPixel, PicturePixel};
use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize, DocumentLayer, FontRenderMode, PictureRect};
use api::{LayoutPoint, LayoutRect, LayoutSize, PipelineId, WorldPoint, WorldRect, WorldPixel};
use clip::{ClipStore};
use clip_scroll_tree::{ClipScrollTree, SpatialNodeIndex};
use display_list_flattener::{DisplayListFlattener};
Expand All @@ -13,7 +13,7 @@ use gpu_types::{PrimitiveHeaders, TransformPalette, UvRectKind};
use hit_test::{HitTester, HitTestingRun};
use internal_types::{FastHashMap};
use picture::PictureSurface;
use prim_store::{PrimitiveIndex, PrimitiveRun, LocalRectBuilder, PrimitiveStore, Transform};
use prim_store::{PrimitiveIndex, PrimitiveRun, PrimitiveStore, Transform, SpaceMapper};
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
use render_backend::FrameId;
use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
Expand Down Expand Up @@ -71,7 +71,7 @@ pub struct FrameBuildingContext<'a> {
pub device_pixel_scale: DevicePixelScale,
pub scene_properties: &'a SceneProperties,
pub pipelines: &'a FastHashMap<PipelineId, Arc<ScenePipeline>>,
pub screen_rect: DeviceIntRect,
pub world_rect: WorldRect,
pub clip_scroll_tree: &'a ClipScrollTree,
pub transforms: &'a TransformPalette,
pub max_local_clip: LayoutRect,
Expand All @@ -92,35 +92,52 @@ pub struct PictureContext {
pub apply_local_clip_rect: bool,
pub inflation_factor: f32,
pub allow_subpixel_aa: bool,
pub has_surface: bool,
}

#[derive(Debug)]
pub struct PictureState {
pub tasks: Vec<RenderTaskId>,
pub has_non_root_coord_system: bool,
pub local_rect_changed: bool,
pub map_local_to_pic: SpaceMapper<LayoutPixel, PicturePixel>,
pub map_pic_to_world: SpaceMapper<PicturePixel, WorldPixel>,
}

impl PictureState {
pub fn new() -> Self {
pub fn new(
ref_spatial_node_index: SpatialNodeIndex,
clip_scroll_tree: &ClipScrollTree,
) -> Self {
let map_local_to_pic = SpaceMapper::new(ref_spatial_node_index);

let mut map_pic_to_world = SpaceMapper::new(SpatialNodeIndex(0));
map_pic_to_world.set_target_spatial_node(
ref_spatial_node_index,
clip_scroll_tree,
);

PictureState {
tasks: Vec::new(),
has_non_root_coord_system: false,
local_rect_changed: false,
map_local_to_pic,
map_pic_to_world,
}
}
}

pub struct PrimitiveContext<'a> {
pub spatial_node: &'a SpatialNode,
pub spatial_node_index: SpatialNodeIndex,
pub transform: Transform<'a>,
pub transform: Transform,
}

impl<'a> PrimitiveContext<'a> {
pub fn new(
spatial_node: &'a SpatialNode,
spatial_node_index: SpatialNodeIndex,
transform: Transform<'a>,
transform: Transform,
) -> Self {
PrimitiveContext {
spatial_node,
Expand Down Expand Up @@ -201,12 +218,14 @@ impl FrameBuilder {

const MAX_CLIP_COORD: f32 = 1.0e9;

let world_rect = (self.screen_rect.to_f32() / device_pixel_scale).round_out();

let frame_context = FrameBuildingContext {
scene_id: self.scene_id,
device_pixel_scale,
scene_properties,
pipelines,
screen_rect: self.screen_rect.to_i32(),
world_rect,
clip_scroll_tree,
transforms: transform_palette,
max_local_clip: LayoutRect::new(
Expand All @@ -224,33 +243,46 @@ impl FrameBuilder {
special_render_passes,
};

let mut pic_state = PictureState::new();
let mut pic_state = PictureState::new(
root_spatial_node_index,
&frame_context.clip_scroll_tree,
);

let pic_context = self
.prim_store
.get_pic_mut(root_prim_index)
.take_context(true);
.take_context(
true,
scene_properties,
false,
)
.unwrap();

let mut local_rect_builder = LocalRectBuilder::new(
root_spatial_node_index,
);
let mut pic_rect = PictureRect::zero();

self.prim_store.prepare_prim_runs(
&pic_context,
&mut pic_state,
&frame_context,
&mut frame_state,
&mut local_rect_builder,
root_spatial_node_index,
&mut pic_rect,
);

let pic = self
.prim_store
.get_pic_mut(root_prim_index);
pic.restore_context(pic_context, local_rect_builder);
pic.restore_context(
pic_context,
pic_state,
Some(pic_rect),
);

let pic_state = pic.take_state();

let root_render_task = RenderTask::new_picture(
RenderTaskLocation::Fixed(frame_context.screen_rect),
frame_context.screen_rect.size,
RenderTaskLocation::Fixed(self.screen_rect.to_i32()),
self.screen_rect.size.to_f32(),
root_prim_index,
DeviceIntPoint::zero(),
pic_state.tasks,
Expand Down
2 changes: 1 addition & 1 deletion webrender/src/gpu_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ impl TransformPalette {
let metadata = &self.metadata[index.0 as usize];

Transform {
m: &data.transform,
m: data.transform,
transform_kind: metadata.transform_kind,
backface_is_visible: data.transform.is_backface_visible(),
}
Expand Down
Loading