Bug 1442422 - Update webrender to commit 0da6c839b3a0e165f1115fb9fe286be7540c24ed. r=jrmuizel

MozReview-Commit-ID: DmcL7siJnZ2

--HG--
extra : rebase_source : 62cf0b5cacd771b0c97a4282761fcf0edc3cf3ef
This commit is contained in:
Kartikaya Gupta 2018-03-07 10:15:43 -05:00
Родитель 6043805daf
Коммит ff7771db98
14 изменённых файлов: 141 добавлений и 113 удалений

Просмотреть файл

@ -40,7 +40,7 @@ base64 = { optional = true, version = "0.3.0" }
ron = { optional = true, version = "0.1.7" }
[dev-dependencies]
angle = {git = "https://github.com/servo/angle", branch = "servo"}
mozangle = "0.1"
env_logger = "0.5"
rand = "0.3" # for the benchmarks
glutin = "0.12" # for the example apps

Просмотреть файл

@ -71,7 +71,7 @@ vec4[2] fetch_from_resource_cache_2(int address) {
#ifdef WR_VERTEX_SHADER
#define VECS_PER_CLIP_SCROLL_NODE 5
#define VECS_PER_CLIP_SCROLL_NODE 9
#define VECS_PER_LOCAL_CLIP_RECT 1
#define VECS_PER_RENDER_TASK 3
#define VECS_PER_PRIM_HEADER 2
@ -86,6 +86,16 @@ uniform HIGHP_SAMPLER_FLOAT sampler2D sRenderTasks;
in ivec4 aData0;
in ivec4 aData1;
// Work around Angle bug that forgets to update sampler metadata,
// by making the use of those samplers uniform across programs.
// https://github.com/servo/webrender/wiki/Driver-issues#texturesize-in-vertex-shaders
void markCacheTexturesUsed() {
vec2 size = vec2(textureSize(sCacheA8, 0)) + vec2(textureSize(sCacheRGBA8, 0));
if (size.x > 1000000.0) {
gl_Position = vec4(0.0);
}
}
// get_fetch_uv is a macro to work around a macOS Intel driver parsing bug.
// TODO: convert back to a function once the driver issues are resolved, if ever.
// https://github.com/servo/webrender/pull/623
@ -154,6 +164,7 @@ vec4 fetch_from_resource_cache_1(int address) {
struct ClipScrollNode {
mat4 transform;
mat4 inv_transform;
bool is_axis_aligned;
};
@ -166,13 +177,19 @@ ClipScrollNode fetch_clip_scroll_node(int index) {
// of OSX.
ivec2 uv = get_fetch_uv(index, VECS_PER_CLIP_SCROLL_NODE);
ivec2 uv0 = ivec2(uv.x + 0, uv.y);
ivec2 uv1 = ivec2(uv.x + 8, uv.y);
node.transform[0] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(0, 0));
node.transform[1] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(1, 0));
node.transform[2] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(2, 0));
node.transform[3] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(3, 0));
vec4 misc = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(4, 0));
node.inv_transform[0] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(4, 0));
node.inv_transform[1] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(5, 0));
node.inv_transform[2] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(6, 0));
node.inv_transform[3] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(7, 0));
vec4 misc = TEXEL_FETCH(sClipScrollNodes, uv1, 0, ivec2(0, 0));
node.is_axis_aligned = misc.x == 0.0;
return node;
@ -358,6 +375,8 @@ PrimitiveInstance fetch_prim_instance() {
pi.user_data1 = aData1.z;
pi.user_data2 = aData1.w;
markCacheTexturesUsed();
return pi;
}
@ -385,6 +404,8 @@ CompositeInstance fetch_composite_instance() {
ci.user_data2 = aData1.z;
ci.user_data3 = aData1.w;
markCacheTexturesUsed();
return ci;
}
@ -476,9 +497,8 @@ vec4 get_node_pos(vec2 pos, ClipScrollNode node) {
vec3 a = ah.xyz / ah.w;
// get the normal to the scroll node plane
mat4 inv_transform = inverse(node.transform);
vec3 n = transpose(mat3(inv_transform)) * vec3(0.0, 0.0, 1.0);
return untransform(pos, n, a, inv_transform);
vec3 n = transpose(mat3(node.inv_transform)) * vec3(0.0, 0.0, 1.0);
return untransform(pos, n, a, node.inv_transform);
}
// Compute a snapping offset in world space (adjusted to pixel ratio),

Просмотреть файл

@ -245,11 +245,6 @@ impl ClipSources {
}
}
/// Whether or not this ClipSources has any clips (does any clipping).
pub fn has_clips(&self) -> bool {
!self.clips.is_empty()
}
pub fn get_screen_bounds(
&self,
transform: &LayerToWorldFastTransform,

Просмотреть файл

@ -286,6 +286,14 @@ impl ClipScrollNode {
return;
}
let inv_transform = match self.world_content_transform.inverse() {
Some(inverted) => inverted.to_transform(),
None => {
node_data.push(ClipScrollNodeData::invalid());
return;
}
};
let transform_kind = if self.world_content_transform.preserves_2d_axis_alignment() {
TransformedRectKind::AxisAligned
} else {
@ -293,6 +301,7 @@ impl ClipScrollNode {
};
let data = ClipScrollNodeData {
transform: self.world_content_transform.into(),
inv_transform,
transform_kind: transform_kind as u32 as f32,
padding: [0.0; 3],
};

Просмотреть файл

@ -216,14 +216,13 @@ impl<'a> DisplayListFlattener<'a> {
view: &DocumentView,
output_pipelines: &FastHashSet<PipelineId>,
frame_builder_config: &FrameBuilderConfig,
pipeline_epochs: &mut FastHashMap<PipelineId, Epoch>,
new_scene: &mut Scene,
) -> FrameBuilder {
// We checked that the root pipeline is available on the render backend.
let root_pipeline_id = scene.root_pipeline_id.unwrap();
let root_pipeline = scene.pipelines.get(&root_pipeline_id).unwrap();
let root_epoch = scene.pipeline_epochs[&root_pipeline_id];
pipeline_epochs.insert(root_pipeline_id, root_epoch);
let background_color = root_pipeline
.background_color
@ -261,7 +260,11 @@ impl<'a> DisplayListFlattener<'a> {
flattener.flatten_root(root_pipeline, &root_pipeline.viewport_size);
debug_assert!(flattener.picture_stack.is_empty());
pipeline_epochs.extend(flattener.pipeline_epochs.drain(..));
new_scene.root_pipeline_id = Some(root_pipeline_id);
new_scene.pipeline_epochs.insert(root_pipeline_id, root_epoch);
new_scene.pipeline_epochs.extend(flattener.pipeline_epochs.drain(..));
new_scene.pipelines = scene.pipelines.clone();
FrameBuilder::with_display_list_flattener(
view.inner_rect,
@ -1164,7 +1167,12 @@ impl<'a> DisplayListFlattener<'a> {
let stacking_context = self.sc_stack.last().expect("bug: no stacking context!");
let clip_sources = self.clip_store.insert(ClipSources::new(clip_sources));
let clip_sources = if clip_sources.is_empty() {
None
} else {
Some(self.clip_store.insert(ClipSources::new(clip_sources)))
};
let prim_index = self.prim_store.add_primitive(
&info.rect,
&info.local_clip.clip_rect(),
@ -1271,9 +1279,6 @@ impl<'a> DisplayListFlattener<'a> {
None,
);
// No clip sources needed for the main framebuffer.
let clip_sources = self.clip_store.insert(ClipSources::new(Vec::new()));
// Add root picture primitive. The provided layer rect
// is zero, because we don't yet know the size of the
// picture. Instead, this is calculated recursively
@ -1282,7 +1287,7 @@ impl<'a> DisplayListFlattener<'a> {
&LayerRect::zero(),
&max_clip,
true,
clip_sources,
None,
None,
PrimitiveContainer::Picture(pic),
);
@ -1351,13 +1356,11 @@ impl<'a> DisplayListFlattener<'a> {
None,
);
let clip_sources = self.clip_store.insert(ClipSources::new(Vec::new()));
let prim_index = self.prim_store.add_primitive(
&LayerRect::zero(),
&max_clip,
is_backface_visible,
clip_sources,
None,
None,
PrimitiveContainer::Picture(container),
);
@ -1402,13 +1405,12 @@ impl<'a> DisplayListFlattener<'a> {
current_reference_frame_index,
None,
);
let src_clip_sources = self.clip_store.insert(ClipSources::new(Vec::new()));
let src_prim_index = self.prim_store.add_primitive(
&LayerRect::zero(),
&max_clip,
is_backface_visible,
src_clip_sources,
None,
None,
PrimitiveContainer::Picture(src_prim),
);
@ -1433,13 +1435,12 @@ impl<'a> DisplayListFlattener<'a> {
current_reference_frame_index,
None,
);
let src_clip_sources = self.clip_store.insert(ClipSources::new(Vec::new()));
let src_prim_index = self.prim_store.add_primitive(
&LayerRect::zero(),
&max_clip,
is_backface_visible,
src_clip_sources,
None,
None,
PrimitiveContainer::Picture(src_prim),
);
@ -1487,12 +1488,11 @@ impl<'a> DisplayListFlattener<'a> {
frame_output_pipeline_id,
);
let sc_clip_sources = self.clip_store.insert(ClipSources::new(Vec::new()));
let sc_prim_index = self.prim_store.add_primitive(
&LayerRect::zero(),
&max_clip,
is_backface_visible,
sc_clip_sources,
None,
None,
PrimitiveContainer::Picture(sc_prim),
);
@ -1646,8 +1646,6 @@ impl<'a> DisplayListFlattener<'a> {
) -> ClipScrollNodeIndex {
let clip_rect = clip_region.main;
let clip_sources = ClipSources::from(clip_region);
debug_assert!(clip_sources.has_clips());
let handle = self.clip_store.insert(clip_sources);
let node_index = self.id_to_index_mapper.get_node_index(new_node_id);
@ -2621,10 +2619,9 @@ impl<'a> DisplayListFlattener<'a> {
}
pub fn build_scene(config: &FrameBuilderConfig, request: SceneRequest) -> BuiltScene {
// TODO: mutably pass the scene and update its own pipeline epoch map instead of
// creating a new one here.
let mut pipeline_epoch_map = FastHashMap::default();
let mut clip_scroll_tree = ClipScrollTree::new();
let mut new_scene = Scene::new();
let frame_builder = DisplayListFlattener::create_frame_builder(
FrameBuilder::empty(), // WIP, we're not really recycling anything here, clean this up.
@ -2635,14 +2632,11 @@ pub fn build_scene(config: &FrameBuilderConfig, request: SceneRequest) -> BuiltS
&request.view,
&request.output_pipelines,
config,
&mut pipeline_epoch_map
&mut new_scene
);
let mut scene = request.scene;
scene.pipeline_epochs = pipeline_epoch_map;
BuiltScene {
scene,
scene: new_scene,
frame_builder,
clip_scroll_tree,
removed_pipelines: request.removed_pipelines,

Просмотреть файл

@ -2,7 +2,7 @@
* 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::{DevicePoint, LayerToWorldTransform, PremultipliedColorF};
use api::{DevicePoint, LayerToWorldTransform, PremultipliedColorF, WorldToLayerTransform};
use gpu_cache::{GpuCacheAddress, GpuDataRequest};
use prim_store::EdgeAaSegmentMask;
use render_task::RenderTaskAddress;
@ -217,6 +217,7 @@ pub struct ClipScrollNodeIndex(pub u32);
#[repr(C)]
pub struct ClipScrollNodeData {
pub transform: LayerToWorldTransform,
pub inv_transform: WorldToLayerTransform,
pub transform_kind: f32,
pub padding: [f32; 3],
}
@ -225,6 +226,7 @@ impl ClipScrollNodeData {
pub fn invalid() -> Self {
ClipScrollNodeData {
transform: LayerToWorldTransform::identity(),
inv_transform: WorldToLayerTransform::identity(),
transform_kind: 0.0,
padding: [0.0; 3],
}
@ -273,4 +275,4 @@ impl ImageSource {
]);
request.push(self.color);
}
}
}

Просмотреть файл

@ -2,8 +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::{BoxShadowClipMode, ColorF, DeviceIntPoint, DeviceIntRect, FilterOp, LayerPoint};
use api::{LayerRect, LayerToWorldScale, LayerVector2D, MixBlendMode, PipelineId};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize};
use api::{LayerPoint, LayerRect, LayerToWorldScale, LayerVector2D};
use api::{BoxShadowClipMode, ColorF, FilterOp, MixBlendMode, PipelineId};
use api::{PremultipliedColorF, Shadow};
use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey};
use clip_scroll_tree::ClipScrollNodeIndex;
@ -18,6 +19,21 @@ use resource_cache::CacheItem;
use scene::{FilterOpHelpers, SceneProperties};
use tiling::RenderTargetKind;
// TODO(gw): Rounding the content rect here to device pixels is not
// technically correct. Ideally we should ceil() here, and ensure that
// the extra part pixel in the case of fractional sizes is correctly
// handled. For now, just use rounding which passes the existing
// Gecko tests.
// Note: zero-square tasks are prohibited in WR task tree, so
// we ensure each dimension to be at least the length of 1 after rounding.
fn to_cache_size(size: DeviceSize) -> DeviceIntSize {
DeviceIntSize::new(
1.max(size.width.round() as i32),
1.max(size.height.round() as i32),
)
}
/*
A picture represents a dynamically rendered image. It consists of:
@ -474,13 +490,7 @@ impl PicturePrimitive {
// render the text run to a target, and then apply a gaussian
// blur to that text run in order to build the actual primitive
// which will be blitted to the framebuffer.
// TODO(gw): Rounding the content rect here to device pixels is not
// technically correct. Ideally we should ceil() here, and ensure that
// the extra part pixel in the case of fractional sizes is correctly
// handled. For now, just use rounding which passes the existing
// Gecko tests.
let cache_size = (content_rect.size * content_scale).round().to_i32();
let cache_size = to_cache_size(content_rect.size * content_scale);
// Quote from https://drafts.csswg.org/css-backgrounds-3/#shadow-blur
// "the image that would be generated by applying to the shadow a
@ -520,7 +530,7 @@ impl PicturePrimitive {
// the extra part pixel in the case of fractional sizes is correctly
// handled. For now, just use rounding which passes the existing
// Gecko tests.
let cache_size = (content_rect.size * content_scale).round().to_i32();
let cache_size = to_cache_size(content_rect.size * content_scale);
// Request the texture cache item for this box-shadow key. If it
// doesn't exist in the cache, the closure is invoked to build

Просмотреть файл

@ -168,7 +168,7 @@ pub struct ScreenRect {
#[derive(Debug)]
pub struct PrimitiveMetadata {
pub opacity: PrimitiveOpacity,
pub clip_sources: ClipSourcesHandle,
pub clip_sources: Option<ClipSourcesHandle>,
pub prim_kind: PrimitiveKind,
pub cpu_prim_index: SpecificPrimitiveIndex,
pub gpu_location: GpuCacheHandle,
@ -964,7 +964,7 @@ impl PrimitiveStore {
local_rect: &LayerRect,
local_clip_rect: &LayerRect,
is_backface_visible: bool,
clip_sources: ClipSourcesHandle,
clip_sources: Option<ClipSourcesHandle>,
tag: Option<ItemTag>,
container: PrimitiveContainer,
) -> PrimitiveIndex {
@ -1570,8 +1570,8 @@ impl PrimitiveStore {
let transform = &prim_run_context.scroll_node.world_content_transform;
let extra_clip = {
let metadata = &self.cpu_metadata[prim_index.0];
let prim_clips = frame_state.clip_store.get_mut(&metadata.clip_sources);
if prim_clips.has_clips() {
metadata.clip_sources.as_ref().map(|ref clip_sources| {
let prim_clips = frame_state.clip_store.get_mut(clip_sources);
prim_clips.update(
frame_state.gpu_cache,
frame_state.resource_cache,
@ -1583,10 +1583,10 @@ impl PrimitiveStore {
combined_outer_rect = combined_outer_rect.and_then(|r| r.intersection(&outer));
}
Some(Arc::new(ClipChainNode {
Arc::new(ClipChainNode {
work_item: ClipWorkItem {
scroll_node_data_index: prim_run_context.scroll_node.node_data_index,
clip_sources: metadata.clip_sources.weak(),
clip_sources: clip_sources.weak(),
coordinate_system_id: prim_coordinate_system_id,
},
// The local_clip_rect a property of ClipChain nodes that are ClipScrollNodes.
@ -1597,10 +1597,8 @@ impl PrimitiveStore {
screen_inner_rect,
screen_outer_rect: screen_outer_rect.unwrap_or(prim_screen_rect),
prev: None,
}))
} else {
None
}
})
})
};
// If everything is clipped out, then we don't need to render this primitive.

Просмотреть файл

@ -172,13 +172,49 @@ impl Document {
// TODO: We will probably get rid of this soon and always forward to the scene building thread.
fn build_scene(&mut self, resource_cache: &mut ResourceCache) {
let frame_builder = self.create_frame_builder(resource_cache);
if self.view.window_size.width == 0 || self.view.window_size.height == 0 {
error!("ERROR: Invalid window dimensions! Please call api.set_window_size()");
}
let old_builder = self.frame_builder.take().unwrap_or_else(FrameBuilder::empty);
let root_pipeline_id = match self.pending.scene.root_pipeline_id {
Some(root_pipeline_id) => root_pipeline_id,
None => return,
};
if !self.pending.scene.pipelines.contains_key(&root_pipeline_id) {
return;
}
// The DisplayListFlattener will re-create the up-to-date current scene's pipeline epoch
// map and clip scroll tree from the information in the pending scene.
self.current.scene.pipeline_epochs.clear();
let old_scrolling_states = self.clip_scroll_tree.drain();
let frame_builder = DisplayListFlattener::create_frame_builder(
old_builder,
&self.pending.scene,
&mut self.clip_scroll_tree,
resource_cache.get_font_instances(),
resource_cache.get_tiled_image_map(),
&self.view,
&self.output_pipelines,
&self.frame_builder_config,
&mut self.current.scene,
);
self.clip_scroll_tree.finalize_and_apply_pending_scroll_offsets(old_scrolling_states);
if !self.current.removed_pipelines.is_empty() {
warn!("Built the scene several times without rendering it.");
}
self.current.removed_pipelines.extend(self.pending.removed_pipelines.drain(..));
self.frame_builder = Some(frame_builder);
self.current.scene = self.pending.scene.clone();
// Advance to the next frame.
self.frame_id.0 += 1;
}
fn forward_transaction_to_scene_builder(
@ -312,48 +348,6 @@ impl Document {
// Advance to the next frame.
self.frame_id.0 += 1;
}
// When changing this, please make the same modification to build_scene,
// which will soon replace this method completely.
pub fn create_frame_builder(&mut self, resource_cache: &mut ResourceCache) -> FrameBuilder {
if self.view.window_size.width == 0 || self.view.window_size.height == 0 {
error!("ERROR: Invalid window dimensions! Please call api.set_window_size()");
}
let old_builder = self.frame_builder.take().unwrap_or_else(FrameBuilder::empty);
let root_pipeline_id = match self.pending.scene.root_pipeline_id {
Some(root_pipeline_id) => root_pipeline_id,
None => return old_builder,
};
if !self.pending.scene.pipelines.contains_key(&root_pipeline_id) {
return old_builder;
}
// The DisplayListFlattener will re-create the up-to-date current scene's pipeline epoch
// map and clip scroll tree from the information in the pending scene.
self.current.scene.pipeline_epochs.clear();
let old_scrolling_states = self.clip_scroll_tree.drain();
let frame_builder = DisplayListFlattener::create_frame_builder(
old_builder,
&self.pending.scene,
&mut self.clip_scroll_tree,
resource_cache.get_font_instances(),
resource_cache.get_tiled_image_map(),
&self.view,
&self.output_pipelines,
&self.frame_builder_config,
&mut self.current.scene.pipeline_epochs,
);
self.clip_scroll_tree.finalize_and_apply_pending_scroll_offsets(old_scrolling_states);
// Advance to the next frame.
self.frame_id.0 += 1;
frame_builder
}
}
struct DocumentOps {
@ -1149,10 +1143,15 @@ impl RenderBackend {
bits: CaptureBits,
profile_counters: &mut BackendProfileCounters,
) -> DebugOutput {
use std::fs;
use capture::CaptureConfig;
debug!("capture: saving {:?}", root);
let (resources, deferred) = self.resource_cache.save_capture(&root);
if !root.is_dir() {
if let Err(e) = fs::create_dir_all(&root) {
panic!("Unable to create capture dir: {:?}", e);
}
}
let config = CaptureConfig::new(root, bits);
for (&id, doc) in &mut self.documents {
@ -1175,6 +1174,9 @@ impl RenderBackend {
}
}
debug!("\tresource cache");
let (resources, deferred) = self.resource_cache.save_capture(&config.root);
info!("\tbackend");
let backend = PlainRenderBackend {
default_device_pixel_ratio: self.default_device_pixel_ratio,

Просмотреть файл

@ -1060,9 +1060,6 @@ impl ResourceCache {
info!("saving resource cache");
let res = &self.resources;
if !root.is_dir() {
fs::create_dir_all(root).unwrap()
}
let path_fonts = root.join("fonts");
if !path_fonts.is_dir() {
fs::create_dir(&path_fonts).unwrap();

Просмотреть файл

@ -146,6 +146,7 @@ impl Scene {
self.root_pipeline_id = None;
}
self.pipelines.remove(&pipeline_id);
self.pipeline_epochs.remove(&pipeline_id);
}
pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {

Просмотреть файл

@ -401,7 +401,7 @@ impl<Src, Dst> FastTransform<Src, Dst> {
match (self, other) {
(&FastTransform::Offset(ref offset), &FastTransform::Offset(ref other_offset)) => {
let offset = TypedVector2D::from_untyped(&offset.to_untyped());
FastTransform::Offset((offset + *other_offset))
FastTransform::Offset(offset + *other_offset)
}
_ => {
let new_transform = self.to_transform().pre_mul(&other.to_transform());

Просмотреть файл

@ -2,10 +2,10 @@
* 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/. */
extern crate angle;
extern crate mozangle;
extern crate webrender;
use angle::hl::{BuiltInResources, Output, ShaderSpec, ShaderValidator};
use mozangle::shaders::{BuiltInResources, Output, ShaderSpec, ShaderValidator};
// from glslang
const FRAGMENT_SHADER: u32 = 0x8B30;
@ -113,7 +113,7 @@ const VERSION_STRING: &str = "#version 300 es\n";
#[test]
fn validate_shaders() {
angle::hl::initialize().unwrap();
mozangle::shaders::initialize().unwrap();
let resources = BuiltInResources::default();
let vs_validator =

Просмотреть файл

@ -1 +1 @@
22b831c02479eea31821f49a0fac7dd699083557
0da6c839b3a0e165f1115fb9fe286be7540c24ed