Skip to content

Commit

Permalink
Auto merge of #3407 - gw3583:new-tile-deps-8, r=kvark
Browse files Browse the repository at this point in the history
Support picture caching where content rect moves between display lists.

Gecko bakes scroll offsets into new display lists. Consider the
following example:

(a) WR receives a new display list.
(b) Scroll the display list, generating frames but not a new scene.
(c) Generate a new scene, due to hover / click etc.

In this case, the local coordinates of the primitives (and thus the
enclosing content rect) will be different between (a) and (c), due to
the current scroll offsets being baked into the local primitive rects.

Since this is non-trivial to change in Gecko, we need to ensure that
picture caching handles this case correctly.

There are two parts to this:

(a) Interned primitives must be stored and keyed in a true primitive
    local space, removing the local origin. Patches for this have
    already landed, and provide an optimization in cases where the
    same primitive template is instanced multiple times.
(b) Correctly create cache tiles even if the enclosing content rect
    has different coordinates. This is addressed by this patch.

We need to ensure that when generating tiles for a given content rect
the number of tiles (and local offsets) is the same for identical content,
regardless of the location of the content rect. To do this, we need to know
the local bounding rect of the enclosing content, and make tiles placed
relative to that. This moves the tile cache update pass to be done
*after* the initial picture traversal, so we know the content bounding
rect.

This also means we can reconfigure the tile grid once during
update_transforms, rather than checking after adding each primitive
whether we need to re-allocate the tile grid.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/3407)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Dec 13, 2018
2 parents e9ea9d8 + 665d69e commit 22f3f35
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 175 deletions.
8 changes: 7 additions & 1 deletion examples/animation.rs
Expand Up @@ -115,6 +115,8 @@ impl Example for App {
}

fn on_event(&mut self, win_event: winit::WindowEvent, api: &RenderApi, document_id: DocumentId) -> bool {
let mut rebuild_display_list = false;

match win_event {
winit::WindowEvent::KeyboardInput {
input: winit::KeyboardInput {
Expand All @@ -129,6 +131,10 @@ impl Example for App {
winit::VirtualKeyCode::Up => (0.0, 0.1),
winit::VirtualKeyCode::Right => (1.0, 0.0),
winit::VirtualKeyCode::Left => (-1.0, 0.0),
winit::VirtualKeyCode::R => {
rebuild_display_list = true;
(0.0, 0.0)
}
_ => return false,
};
// Update the transform based on the keyboard input and push it to
Expand Down Expand Up @@ -172,7 +178,7 @@ impl Example for App {
_ => (),
}

false
rebuild_display_list
}
}

Expand Down
13 changes: 2 additions & 11 deletions webrender/src/batch.rs
Expand Up @@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{AlphaType, ClipMode, DeviceIntRect, DeviceIntPoint, DeviceIntSize};
use api::{ExternalImageType, FilterOp, ImageRendering, LayoutRect, LayoutSize};
use api::{ExternalImageType, FilterOp, ImageRendering, LayoutRect};
use api::{YuvColorSpace, YuvFormat, PictureRect, ColorDepth, LayoutPoint};
use clip::{ClipDataStore, ClipNodeFlags, ClipNodeRange, ClipItem, ClipStore};
use clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex};
Expand Down Expand Up @@ -1001,16 +1001,7 @@ impl AlphaBatchBuilder {
}

// Get the local rect of the tile.
let tile_rect = LayoutRect::new(
LayoutPoint::new(
(tile_cache.tile_rect.origin.x + x) as f32 * tile_cache.local_tile_size.width,
(tile_cache.tile_rect.origin.y + y) as f32 * tile_cache.local_tile_size.height,
),
LayoutSize::new(
tile_cache.local_tile_size.width,
tile_cache.local_tile_size.height,
),
);
let tile_rect = tile_cache.get_tile_rect(x, y);

// Construct a local clip rect that ensures we only draw pixels where
// the local bounds of the picture extend to within the edge tiles.
Expand Down
36 changes: 25 additions & 11 deletions webrender/src/frame_builder.rs
Expand Up @@ -12,7 +12,8 @@ use gpu_cache::GpuCache;
use gpu_types::{PrimitiveHeaders, TransformPalette, UvRectKind, ZBufferIdGenerator};
use hit_test::{HitTester, HitTestingRun};
use internal_types::{FastHashMap, PlaneSplitter};
use picture::{PictureSurface, PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex, TileDescriptor};
use picture::{PictureSurface, PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex};
use picture::{TileCacheUpdateState, RetainedTiles};
use prim_store::{PrimitiveStore, SpaceMapper, PictureIndex, PrimitiveDebugId, PrimitiveScratchBuffer};
#[cfg(feature = "replay")]
use prim_store::{PrimitiveStoreStats};
Expand All @@ -25,7 +26,6 @@ use segment::SegmentBuilder;
use spatial_node::SpatialNode;
use std::{f32, mem};
use std::sync::Arc;
use texture_cache::TextureCacheHandle;
use tiling::{Frame, RenderPass, RenderPassKind, RenderTargetContext};
use tiling::{SpecialRenderPasses};

Expand Down Expand Up @@ -64,7 +64,7 @@ pub struct FrameBuilder {
root_pic_index: PictureIndex,
/// Cache of surface tiles from the previous frame builder
/// that can optionally be consumed by this frame builder.
pending_retained_tiles: FastHashMap<TileDescriptor, TextureCacheHandle>,
pending_retained_tiles: RetainedTiles,
pub prim_store: PrimitiveStore,
pub clip_store: ClipStore,
pub hit_testing_runs: Vec<HitTestingRun>,
Expand Down Expand Up @@ -149,7 +149,7 @@ impl FrameBuilder {
window_size: DeviceIntSize::zero(),
background_color: None,
root_pic_index: PictureIndex(0),
pending_retained_tiles: FastHashMap::default(),
pending_retained_tiles: RetainedTiles::new(),
config: FrameBuilderConfig {
default_font_render_mode: FontRenderMode::Mono,
dual_source_blending_is_enabled: true,
Expand All @@ -165,9 +165,9 @@ impl FrameBuilder {
/// first time a new frame builder creates a frame.
pub fn set_retained_tiles(
&mut self,
retained_tiles: FastHashMap<TileDescriptor, TextureCacheHandle>,
retained_tiles: RetainedTiles,
) {
debug_assert!(self.pending_retained_tiles.is_empty());
debug_assert!(self.pending_retained_tiles.tiles.is_empty());
self.pending_retained_tiles = retained_tiles;
}

Expand All @@ -185,7 +185,7 @@ impl FrameBuilder {
screen_rect,
background_color,
window_size,
pending_retained_tiles: FastHashMap::default(),
pending_retained_tiles: RetainedTiles::new(),
config: flattener.config,
}
}
Expand All @@ -194,7 +194,7 @@ impl FrameBuilder {
/// a frame builder is replaced with a newly built scene.
pub fn destroy(
self,
retained_tiles: &mut FastHashMap<TileDescriptor, TextureCacheHandle>,
retained_tiles: &mut RetainedTiles,
) {
self.prim_store.destroy(
retained_tiles,
Expand Down Expand Up @@ -259,7 +259,7 @@ impl FrameBuilder {
let mut pic_update_state = PictureUpdateState::new(surfaces);
let mut retained_tiles = mem::replace(
&mut self.pending_retained_tiles,
FastHashMap::default(),
RetainedTiles::new(),
);

// The first major pass of building a frame is to walk the picture
Expand All @@ -273,18 +273,32 @@ impl FrameBuilder {
self.root_pic_index,
&mut pic_update_state,
&frame_context,
resource_cache,
gpu_cache,
resources,
&self.clip_store,
);

// Update the state of any picture tile caches. This is a no-op on most
// frames (it only does work the first time a new scene is built, or if
// the tile-relative transform dependencies have changed).
let mut tile_cache_state = TileCacheUpdateState::new();
self.prim_store.update_tile_cache(
self.root_pic_index,
&mut tile_cache_state,
&frame_context,
resource_cache,
resources,
&self.clip_store,
&pic_update_state.surfaces,
gpu_cache,
&mut retained_tiles,
);

// If we had any retained tiles from the last scene that were not picked
// up by the new frame, then just discard them eagerly.
// TODO(gw): Maybe it's worth keeping them around for a bit longer in
// some cases?
for (_, handle) in retained_tiles.drain() {
for (_, handle) in retained_tiles.tiles.drain() {
resource_cache.texture_cache.mark_unused(&handle);
}

Expand Down

0 comments on commit 22f3f35

Please sign in to comment.