Bug 1479432 - Update webrender to commit 7a1b919e37d6cd0155077aa90f98cfcdf9fa5bae. r=jrmuizel

MozReview-Commit-ID: 1SJgRWEp2qf

--HG--
extra : rebase_source : ec6ffe0686f8ef0bf8149347fcfd48e3870bc316
This commit is contained in:
Kartikaya Gupta 2018-08-02 10:20:04 -04:00
Родитель cad8bf3a7e
Коммит 83d156a753
27 изменённых файлов: 457 добавлений и 369 удалений

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

@ -18,20 +18,20 @@ pathfinder = ["pathfinder_font_renderer", "pathfinder_gfx_utils", "pathfinder_pa
serialize_program = ["serde"]
[dependencies]
app_units = "0.6"
app_units = "0.7"
base64 = { optional = true, version = "0.6" }
bincode = "1.0"
bitflags = "1.0"
byteorder = "1.0"
cfg-if = "0.1.2"
euclid = "0.18"
euclid = "0.19"
fxhash = "0.2.1"
gleam = "0.6"
image = { optional = true, version = "0.19" }
lazy_static = "1"
log = "0.4"
num-traits = "0.1.43"
plane-split = "0.10"
num-traits = "0.2"
plane-split = "0.12"
png = { optional = true, version = "0.12" }
rayon = "1"
ron = { optional = true, version = "0.1.7" }

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

@ -70,7 +70,6 @@ void main(void) {
#endif
} else {
bvec4 edge_mask = notEqual(edge_flags & ivec4(1, 2, 4, 8), ivec4(0));
bool do_perspective_interpolation = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0;
vi = write_transform_vertex(
local_segment_rect,
@ -79,8 +78,7 @@ void main(void) {
mix(vec4(0.0), vec4(1.0), edge_mask),
ph.z,
transform,
pic_task,
do_perspective_interpolation
pic_task
);
}
@ -92,7 +90,7 @@ void main(void) {
// implies the other, for now.
#ifdef WR_FEATURE_ALPHA_PASS
write_clip(
vi.screen_pos,
vi.world_pos,
clip_area
);
#endif

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

@ -29,9 +29,9 @@ void brush_vs(
) {
PictureTask src_task = fetch_picture_task(user_data.x);
vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
vec2 uv = vi.snapped_device_pos +
src_task.common_data.task_rect.p0 -
src_task.content_origin;
vec2 uv = snap_device_pos(vi) +
src_task.common_data.task_rect.p0 -
src_task.content_origin;
vUv = vec3(uv / texture_size, src_task.common_data.texture_layer_index);
vec2 uv0 = src_task.common_data.task_rect.p0;

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

@ -11,7 +11,8 @@ varying vec2 vLocalPos;
#endif
// Interpolated uv coordinates in xy, and layer in z.
varying vec3 vUv;
// W is 1 when perspective interpolation is enabled.
varying vec4 vUv;
// Normalized bounds of the source image in the texture.
flat varying vec4 vUvBounds;
// Normalized bounds of the source image in the texture, adjusted to avoid
@ -106,6 +107,7 @@ void brush_vs(
}
vUv.z = res.layer;
vUv.w = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;
// Handle case where the UV coords are inverted (e.g. from an
// external image).
@ -151,6 +153,10 @@ void brush_vs(
vUv.xy = mix(uv0, uv1, f) - min_uv;
vUv.xy /= texture_size;
vUv.xy *= repeat.xy;
if ((brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) == 0) {
// Multiply by W to compensate for perspective interpolation.
vUv.xy *= gl_Position.w;
}
#ifdef WR_FEATURE_TEXTURE_RECT
vUvBounds = vec4(0.0, 0.0, vec2(textureSize(sColor0)));
@ -196,12 +202,14 @@ void brush_vs(
Fragment brush_fs() {
vec2 uv_size = vUvBounds.zw - vUvBounds.xy;
// Unapply the W scaler when no perspective interpolation is enabled.
vec2 base_uv = vUv.xy * mix(gl_FragCoord.w, 1.0, vUv.w);
#ifdef WR_FEATURE_ALPHA_PASS
// This prevents the uv on the top and left parts of the primitive that was inflated
// for anti-aliasing purposes from going beyound the range covered by the regular
// (non-inflated) primitive.
vec2 local_uv = max(vUv.xy, vec2(0.0));
vec2 local_uv = max(base_uv, vec2(0.0));
// Handle horizontal and vertical repetitions.
vec2 repeated_uv = mod(local_uv, uv_size) + vUvBounds.xy;
@ -217,7 +225,7 @@ Fragment brush_fs() {
}
#else
// Handle horizontal and vertical repetitions.
vec2 repeated_uv = mod(vUv.xy, uv_size) + vUvBounds.xy;
vec2 repeated_uv = mod(base_uv, uv_size) + vUvBounds.xy;
#endif
// Clamp the uvs to avoid sampling artifacts.

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

@ -23,17 +23,18 @@ void brush_vs(
int brush_flags,
vec4 unused
) {
vec2 snapped_device_pos = snap_device_pos(vi);
vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
vOp = user_data.x;
PictureTask src_task = fetch_picture_task(user_data.z);
vec2 src_uv = vi.snapped_device_pos +
vec2 src_uv = snapped_device_pos +
src_task.common_data.task_rect.p0 -
src_task.content_origin;
vSrcUv = vec3(src_uv / texture_size, src_task.common_data.texture_layer_index);
RenderTaskCommonData backdrop_task = fetch_render_task_common_data(user_data.y);
vec2 backdrop_uv = vi.snapped_device_pos +
vec2 backdrop_uv = snapped_device_pos +
backdrop_task.task_rect.p0 -
src_task.content_origin;
vBackdropUv = vec3(backdrop_uv / texture_size, backdrop_task.texture_layer_index);

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

@ -27,7 +27,8 @@ vec2 clamp_rect(vec2 pt, RectWithSize rect) {
// TODO: convert back to RectWithEndPoint if driver issues are resolved, if ever.
flat varying vec4 vClipMaskUvBounds;
varying vec3 vClipMaskUv;
// XY and W are homogeneous coordinates, Z is the layer index
varying vec4 vClipMaskUv;
#ifdef WR_VERTEX_SHADER
@ -86,11 +87,15 @@ PrimitiveHeader fetch_prim_header(int index) {
struct VertexInfo {
vec2 local_pos;
vec2 screen_pos;
float w;
vec2 snapped_device_pos;
vec2 snap_offset;
vec4 world_pos;
};
//Note: this function is unsafe for `vi.world_pos.w <= 0.0`
vec2 snap_device_pos(VertexInfo vi) {
return vi.world_pos.xy * uDevicePixelRatio / max(0.0, vi.world_pos.w) + vi.snap_offset;
}
VertexInfo write_vertex(RectWithSize instance_rect,
RectWithSize local_clip_rect,
float z,
@ -119,8 +124,7 @@ VertexInfo write_vertex(RectWithSize instance_rect,
vec2 device_pos = world_pos.xy / world_pos.w * uDevicePixelRatio;
// Apply offsets for the render task to get correct screen location.
vec2 snapped_device_pos = device_pos + snap_offset;
vec2 final_pos = snapped_device_pos -
vec2 final_pos = device_pos + snap_offset -
task.content_origin +
task.common_data.task_rect.p0;
@ -128,9 +132,8 @@ VertexInfo write_vertex(RectWithSize instance_rect,
VertexInfo vi = VertexInfo(
clamped_local_pos,
device_pos,
world_pos.w,
snapped_device_pos
snap_offset,
world_pos
);
return vi;
@ -161,8 +164,7 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
vec4 clip_edge_mask,
float z,
Transform transform,
PictureTask task,
bool do_perspective_interpolation) {
PictureTask task) {
// Calculate a clip rect from local_rect + local clip
RectWithEndpoint clip_rect = to_rect_with_endpoint(local_clip_rect);
RectWithEndpoint segment_rect = to_rect_with_endpoint(local_segment_rect);
@ -192,23 +194,17 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
// Select the corner of the local rect that we are processing.
vec2 local_pos = local_segment_rect.p0 + local_segment_rect.size * aPosition.xy;
// Transform the current vertex to the world cpace.
vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
// Convert the world positions to device pixel space.
vec2 device_pos = world_pos.xy / world_pos.w * uDevicePixelRatio;
vec2 task_offset = task.common_data.task_rect.p0 - task.content_origin;
// Force w = 1, if we don't want perspective interpolation (for
// example, drawing a screen-space quad on an element with a
// perspective transform).
world_pos.w = mix(1.0, world_pos.w, do_perspective_interpolation);
// Transform the current vertex to the world cpace.
vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
vec4 final_pos = vec4(
world_pos.xy * uDevicePixelRatio + task_offset * world_pos.w,
z * world_pos.w,
world_pos.w
);
// We want the world space coords to be perspective divided by W.
// We also want that to apply to any interpolators. However, we
// want a constant Z across the primitive, since we're using it
// for draw ordering - so scale by the W coord to ensure this.
vec4 final_pos = vec4(device_pos + task_offset, z, 1.0) * world_pos.w;
gl_Position = uTransform * final_pos;
init_transform_vs(mix(
@ -219,36 +215,44 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect,
VertexInfo vi = VertexInfo(
local_pos,
device_pos,
world_pos.w,
device_pos
vec2(0.0),
world_pos
);
return vi;
}
void write_clip(vec2 global_pos, ClipArea area) {
vec2 uv = global_pos +
area.common_data.task_rect.p0 -
area.screen_origin;
void write_clip(vec4 world_pos, ClipArea area) {
vec2 uv = world_pos.xy * uDevicePixelRatio +
world_pos.w * (area.common_data.task_rect.p0 - area.screen_origin);
vClipMaskUvBounds = vec4(
area.common_data.task_rect.p0,
area.common_data.task_rect.p0 + area.common_data.task_rect.size
);
vClipMaskUv = vec3(uv, area.common_data.texture_layer_index);
vClipMaskUv = vec4(uv, area.common_data.texture_layer_index, world_pos.w);
}
#endif //WR_VERTEX_SHADER
#ifdef WR_FRAGMENT_SHADER
float do_clip() {
// anything outside of the mask is considered transparent
bvec4 inside = lessThanEqual(
vec4(vClipMaskUvBounds.xy, vClipMaskUv.xy),
vec4(vClipMaskUv.xy, vClipMaskUvBounds.zw));
// check for the dummy bounds, which are given to the opaque objects
return vClipMaskUvBounds.xy == vClipMaskUvBounds.zw ? 1.0:
all(inside) ? texelFetch(sCacheA8, ivec3(vClipMaskUv), 0).r : 0.0;
if (vClipMaskUvBounds.xy == vClipMaskUvBounds.zw) {
return 1.0;
}
// anything outside of the mask is considered transparent
//Note: we assume gl_FragCoord.w == interpolated(1 / vClipMaskUv.w)
vec2 mask_uv = vClipMaskUv.xy * gl_FragCoord.w;
bvec4 inside = lessThanEqual(
vec4(vClipMaskUvBounds.xy, mask_uv),
vec4(mask_uv, vClipMaskUvBounds.zw));
// bail out if the pixel is outside the valid bounds
if (!all(inside)) {
return 0.0;
}
// finally, the slow path - fetch the mask value from an image
ivec3 tc = ivec3(mask_uv, vClipMaskUv.z);
return texelFetch(sCacheA8, tc, 0).r;
}
#ifdef WR_FEATURE_DITHERING

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

@ -73,37 +73,33 @@ VertexInfo write_text_vertex(vec2 clamped_local_pos,
// Convert the world positions to device pixel space.
float device_scale = uDevicePixelRatio / world_pos.w;
vec2 device_pos = world_pos.xy * device_scale;
// Apply offsets for the render task to get correct screen location.
vec2 final_pos = device_pos -
task.content_origin +
task.common_data.task_rect.p0;
vec2 snap_offset = vec2(0.0);
#if defined(WR_FEATURE_GLYPH_TRANSFORM)
bool remove_subpx_offset = true;
#else
// Compute the snapping offset only if the scroll node transform is axis-aligned.
bool remove_subpx_offset = transform.is_axis_aligned;
#endif
// Compute the snapping offset only if the scroll node transform is axis-aligned.
if (remove_subpx_offset) {
// Ensure the transformed text offset does not contain a subpixel translation
// such that glyph snapping is stable for equivalent glyph subpixel positions.
vec2 world_text_offset = mat2(transform.m) * text_offset;
vec2 device_text_pos = (transform.m[3].xy + world_text_offset) * device_scale;
final_pos += floor(device_text_pos + 0.5) - device_text_pos;
snap_offset += floor(device_text_pos + 0.5) - device_text_pos;
#ifdef WR_FEATURE_GLYPH_TRANSFORM
// For transformed subpixels, we just need to align the glyph origin to a device pixel.
// The transformed text offset has already been snapped, so remove it from the glyph
// origin when snapping the glyph.
vec2 snap_offset = snap_rect.p0 - world_text_offset * device_scale;
final_pos += floor(snap_offset + snap_bias) - snap_offset;
vec2 rough_offset = snap_rect.p0 - world_text_offset * device_scale;
snap_offset += floor(rough_offset + snap_bias) - rough_offset;
#else
// The transformed text offset has already been snapped, so remove it from the transform
// when snapping the glyph.
mat4 snap_transform = transform.m;
snap_transform[3].xy = -world_text_offset;
final_pos += compute_snap_offset(
snap_offset += compute_snap_offset(
clamped_local_pos,
snap_transform,
snap_rect,
@ -112,13 +108,17 @@ VertexInfo write_text_vertex(vec2 clamped_local_pos,
#endif
}
// Apply offsets for the render task to get correct screen location.
vec2 final_pos = device_pos + snap_offset -
task.content_origin +
task.common_data.task_rect.p0;
gl_Position = uTransform * vec4(final_pos, z, 1.0);
VertexInfo vi = VertexInfo(
clamped_local_pos,
device_pos,
world_pos.w,
final_pos
snap_offset,
world_pos
);
return vi;
@ -223,7 +223,7 @@ void main(void) {
vec2 f = (vi.local_pos - glyph_rect.p0) / glyph_rect.size;
#endif
write_clip(vi.screen_pos, clip_area);
write_clip(vi.world_pos, clip_area);
switch (color_mode) {
case COLOR_MODE_ALPHA:

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

@ -1788,7 +1788,7 @@ impl ClipBatcher {
) {
let mut coordinate_system_id = coordinate_system_id;
for work_item in clips.iter() {
let info = clip_store.get(work_item.clip_sources_index);
let info = &clip_store[work_item.clip_sources_index];
let instance = ClipMaskInstance {
render_task_address: task_address,
transform_id: transforms.get_id(info.spatial_node_index),

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

@ -9,10 +9,20 @@ use app_units::Au;
use ellipse::Ellipse;
use display_list_flattener::DisplayListFlattener;
use gpu_types::{BorderInstance, BorderSegment, BrushFlags};
use prim_store::{BrushKind, BrushPrimitive, BrushSegment};
use prim_store::{BrushKind, BrushPrimitive, BrushSegment, VECS_PER_SEGMENT};
use prim_store::{BorderSource, EdgeAaSegmentMask, PrimitiveContainer, ScrollNodeAndClipChain};
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
use util::{lerp, RectHelpers};
// Using 2048 as the maximum radius in device space before which we
// start stretching is up for debate.
// the value must be chosen so that the corners will not use an
// unreasonable amount of memory but should allow crisp corners in the
// common cases.
/// Maximum resolution in device pixels at which borders are rasterized.
pub const MAX_BORDER_RESOLUTION: u32 = 2048;
trait AuSizeConverter {
fn to_au(&self) -> LayoutSizeAu;
}
@ -345,18 +355,24 @@ impl BorderCornerClipSource {
1.0 - 2.0 * outer_scale.y,
);
// No point in pushing more clips as it will blow up the maximum amount of
// segments per primitive later down the road.
// See #2915 for a better fix.
let clip_limit = MAX_VERTEX_TEXTURE_WIDTH / VECS_PER_SEGMENT;
let max_clip_count = self.max_clip_count.min(clip_limit);
match self.kind {
BorderCornerClipKind::Dash => {
// Get the correct dash arc length.
let dash_arc_length =
0.5 * self.ellipse.total_arc_length / self.max_clip_count as f32;
0.5 * self.ellipse.total_arc_length / max_clip_count as f32;
// Start the first dash at one quarter the length of a single dash
// along the arc line. This is arbitrary but looks reasonable in
// most cases. We need to spend some time working on a more
// sophisticated dash placement algorithm that takes into account
// the offset of the dashes along edge segments.
let mut current_arc_length = 0.25 * dash_arc_length;
for _ in 0 .. self.max_clip_count {
for _ in 0 .. max_clip_count {
let arc_length0 = current_arc_length;
current_arc_length += dash_arc_length;
@ -401,7 +417,7 @@ impl BorderCornerClipSource {
]);
}
}
BorderCornerClipKind::Dot if self.max_clip_count == 1 => {
BorderCornerClipKind::Dot if max_clip_count == 1 => {
let dot_diameter = lerp(self.widths.width, self.widths.height, 0.5);
dot_dash_data.push([
self.widths.width / 2.0, self.widths.height / 2.0, 0.5 * dot_diameter, 0.,
@ -422,7 +438,7 @@ impl BorderCornerClipSource {
self.widths.height,
));
for dot_index in 0 .. self.max_clip_count {
for dot_index in 0 .. max_clip_count {
let prev_forward_pos = *forward_dots.last().unwrap();
let prev_back_pos = *back_dots.last().unwrap();
@ -927,6 +943,23 @@ impl BorderRenderTaskInfo {
instances
}
/// Computes the maximum scale that we allow for this set of border radii.
/// capping the scale will result in rendering very large corners at a lower
/// resolution and stretching them, so they will have the right shape, but
/// blurrier.
pub fn get_max_scale(radii: &BorderRadius) -> LayoutToDeviceScale {
let r = radii.top_left.width
.max(radii.top_left.height)
.max(radii.top_right.width)
.max(radii.top_right.height)
.max(radii.bottom_left.width)
.max(radii.bottom_left.height)
.max(radii.bottom_right.width)
.max(radii.bottom_right.height);
LayoutToDeviceScale::new(MAX_BORDER_RESOLUTION as f32 / r)
}
}
fn add_brush_segment(

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

@ -14,8 +14,9 @@ use gpu_types::BoxShadowStretchMode;
use prim_store::{ClipData, ImageMaskData};
use render_task::to_cache_size;
use resource_cache::{ImageRequest, ResourceCache};
use util::{LayoutToWorldFastTransform, MaxRect, calculate_screen_bounding_rect};
use util::{extract_inner_rect_safe, pack_as_float, recycle_vec};
use util::{LayoutToWorldFastTransform, MaxRect, TransformedRectKind};
use util::{calculate_screen_bounding_rect, extract_inner_rect_safe, pack_as_float, recycle_vec};
use std::{iter, ops};
use std::sync::Arc;
#[derive(Debug, Copy, Clone)]
@ -28,13 +29,13 @@ pub struct ClipStore {
}
impl ClipStore {
pub fn new() -> ClipStore {
pub fn new() -> Self {
ClipStore {
clip_sources: Vec::new(),
}
}
pub fn recycle(self) -> ClipStore {
pub fn recycle(self) -> Self {
ClipStore {
clip_sources: recycle_vec(self.clip_sources),
}
@ -45,12 +46,17 @@ impl ClipStore {
self.clip_sources.push(clip_sources);
index
}
}
pub fn get(&self, index: ClipSourcesIndex) -> &ClipSources {
impl ops::Index<ClipSourcesIndex> for ClipStore {
type Output = ClipSources;
fn index(&self, index: ClipSourcesIndex) -> &Self::Output {
&self.clip_sources[index.0]
}
}
pub fn get_mut(&mut self, index: ClipSourcesIndex) -> &mut ClipSources {
impl ops::IndexMut<ClipSourcesIndex> for ClipStore {
fn index_mut(&mut self, index: ClipSourcesIndex) -> &mut Self::Output {
&mut self.clip_sources[index.0]
}
}
@ -63,51 +69,77 @@ pub struct LineDecorationClipSource {
wavy_line_thickness: f32,
}
#[derive(Clone, Debug)]
pub struct ClipRegion {
pub main: LayoutRect,
pub image_mask: Option<ImageMask>,
pub complex_clips: Vec<ComplexClipRegion>,
pub struct ComplexTranslateIter<I> {
source: I,
offset: LayoutVector2D,
}
impl ClipRegion {
impl<I: Iterator<Item = ComplexClipRegion>> Iterator for ComplexTranslateIter<I> {
type Item = ComplexClipRegion;
fn next(&mut self) -> Option<Self::Item> {
self.source
.next()
.map(|mut complex| {
complex.rect = complex.rect.translate(&self.offset);
complex
})
}
}
#[derive(Clone, Debug)]
pub struct ClipRegion<I> {
pub main: LayoutRect,
pub image_mask: Option<ImageMask>,
pub complex_clips: I,
}
impl<J> ClipRegion<ComplexTranslateIter<J>> {
pub fn create_for_clip_node(
rect: LayoutRect,
mut complex_clips: Vec<ComplexClipRegion>,
complex_clips: J,
mut image_mask: Option<ImageMask>,
reference_frame_relative_offset: &LayoutVector2D,
) -> ClipRegion {
let rect = rect.translate(reference_frame_relative_offset);
) -> Self
where
J: Iterator<Item = ComplexClipRegion>
{
if let Some(ref mut image_mask) = image_mask {
image_mask.rect = image_mask.rect.translate(reference_frame_relative_offset);
}
for complex_clip in complex_clips.iter_mut() {
complex_clip.rect = complex_clip.rect.translate(reference_frame_relative_offset);
}
ClipRegion {
main: rect,
main: rect.translate(reference_frame_relative_offset),
image_mask,
complex_clips,
complex_clips: ComplexTranslateIter {
source: complex_clips,
offset: *reference_frame_relative_offset,
},
}
}
}
impl ClipRegion<Option<ComplexClipRegion>> {
pub fn create_for_clip_node_with_local_clip(
local_clip: &LocalClip,
reference_frame_relative_offset: &LayoutVector2D
) -> ClipRegion {
let complex_clips = match *local_clip {
LocalClip::Rect(_) => Vec::new(),
LocalClip::RoundedRect(_, ref region) => vec![region.clone()],
};
ClipRegion::create_for_clip_node(
*local_clip.clip_rect(),
complex_clips,
None,
reference_frame_relative_offset
)
) -> Self {
ClipRegion {
main: local_clip
.clip_rect()
.translate(reference_frame_relative_offset),
image_mask: None,
complex_clips: match *local_clip {
LocalClip::Rect(_) => None,
LocalClip::RoundedRect(_, ref region) => {
Some(ComplexClipRegion {
rect: region.rect.translate(reference_frame_relative_offset),
radii: region.radii,
mode: region.mode,
})
},
}
}
}
}
@ -280,6 +312,92 @@ impl ClipSource {
}
}
struct BoundsAccumulator {
local_outer: Option<LayoutRect>,
local_inner: Option<LayoutRect>,
can_calculate_inner_rect: bool,
can_calculate_outer_rect: bool,
}
impl BoundsAccumulator {
fn new() -> Self {
BoundsAccumulator {
local_outer: Some(LayoutRect::max_rect()),
local_inner: Some(LayoutRect::max_rect()),
can_calculate_inner_rect: true,
can_calculate_outer_rect: false,
}
}
fn add(&mut self, source: &ClipSource) {
// Depending on the complexity of the clip, we may either know the outer and/or inner
// rect, or neither or these. In the case of a clip-out, we currently set the mask bounds
// to be unknown. This is conservative, but ensures correctness. In the future we can make
// this a lot more clever with some proper region handling.
if !self.can_calculate_inner_rect {
return
}
match *source {
ClipSource::Image(ref mask) => {
if !mask.repeat {
self.can_calculate_outer_rect = true;
self.local_outer = self.local_outer.and_then(|r| r.intersection(&mask.rect));
}
self.local_inner = None;
}
ClipSource::Rectangle(rect, mode) => {
// Once we encounter a clip-out, we just assume the worst
// case clip mask size, for now.
if mode == ClipMode::ClipOut {
self.can_calculate_inner_rect = false;
return
}
self.can_calculate_outer_rect = true;
self.local_outer = self.local_outer.and_then(|r| r.intersection(&rect));
self.local_inner = self.local_inner.and_then(|r| r.intersection(&rect));
}
ClipSource::RoundedRectangle(ref rect, ref radius, mode) => {
// Once we encounter a clip-out, we just assume the worst
// case clip mask size, for now.
if mode == ClipMode::ClipOut {
self.can_calculate_inner_rect = false;
return
}
self.can_calculate_outer_rect = true;
self.local_outer = self.local_outer.and_then(|r| r.intersection(rect));
let inner_rect = extract_inner_rect_safe(rect, radius);
self.local_inner = self.local_inner
.and_then(|r| inner_rect.and_then(|ref inner| r.intersection(inner)));
}
ClipSource::BoxShadow(..) |
ClipSource::LineDecoration(..) => {
self.can_calculate_inner_rect = false;
}
}
}
fn finish(self) -> (LayoutRect, Option<LayoutRect>) {
(
if self.can_calculate_inner_rect {
self.local_inner.unwrap_or_else(LayoutRect::zero)
} else {
LayoutRect::zero()
},
if self.can_calculate_outer_rect {
Some(self.local_outer.unwrap_or_else(LayoutRect::zero))
} else {
None
},
)
}
}
#[derive(Debug)]
pub struct ClipSources {
pub clips: Vec<(ClipSource, GpuCacheHandle)>,
@ -291,20 +409,24 @@ pub struct ClipSources {
}
impl ClipSources {
pub fn new(
clips: Vec<ClipSource>,
spatial_node_index: SpatialNodeIndex,
) -> Self {
let (local_inner_rect, local_outer_rect) = Self::calculate_inner_and_outer_rects(&clips);
pub fn new<I>(clip_iter: I, spatial_node_index: SpatialNodeIndex) -> Self
where
I: IntoIterator<Item = ClipSource>,
{
let mut clips = Vec::new();
let mut bounds_accum = BoundsAccumulator::new();
let mut has_image_or_line_decoration_clip = false;
let mut only_rectangular_clips = true;
let has_image_or_line_decoration_clip =
clips.iter().any(|clip| clip.is_image_or_line_decoration_clip());
let only_rectangular_clips =
!has_image_or_line_decoration_clip && clips.iter().all(|clip| clip.is_rect());
let clips = clips
.into_iter()
.map(|clip| (clip, GpuCacheHandle::new()))
.collect();
for clip in clip_iter {
bounds_accum.add(&clip);
has_image_or_line_decoration_clip |= clip.is_image_or_line_decoration_clip();
only_rectangular_clips &= clip.is_rect();
clips.push((clip, GpuCacheHandle::new()));
}
only_rectangular_clips &= !has_image_or_line_decoration_clip;
let (local_inner_rect, local_outer_rect) = bounds_accum.finish();
ClipSources {
clips,
@ -316,105 +438,31 @@ impl ClipSources {
}
}
pub fn from_region(
region: ClipRegion,
pub fn from_region<I>(
region: ClipRegion<I>,
spatial_node_index: SpatialNodeIndex,
) -> ClipSources {
let mut clips = Vec::new();
if let Some(info) = region.image_mask {
clips.push(ClipSource::Image(info));
}
clips.push(ClipSource::Rectangle(region.main, ClipMode::Clip));
for complex in region.complex_clips {
clips.push(ClipSource::new_rounded_rect(
) -> ClipSources
where
I: IntoIterator<Item = ComplexClipRegion>
{
let clip_rect = iter::once(ClipSource::Rectangle(region.main, ClipMode::Clip));
let clip_image = region.image_mask.map(ClipSource::Image);
let clips_complex = region.complex_clips
.into_iter()
.map(|complex| ClipSource::new_rounded_rect(
complex.rect,
complex.radii,
complex.mode,
));
}
ClipSources::new(clips, spatial_node_index)
let clips_all = clip_rect.chain(clip_image).chain(clips_complex);
ClipSources::new(clips_all, spatial_node_index)
}
pub fn clips(&self) -> &[(ClipSource, GpuCacheHandle)] {
&self.clips
}
fn calculate_inner_and_outer_rects(clips: &Vec<ClipSource>) -> (LayoutRect, Option<LayoutRect>) {
if clips.is_empty() {
return (LayoutRect::zero(), None);
}
// Depending on the complexity of the clip, we may either know the outer and/or inner
// rect, or neither or these. In the case of a clip-out, we currently set the mask bounds
// to be unknown. This is conservative, but ensures correctness. In the future we can make
// this a lot more clever with some proper region handling.
let mut local_outer = Some(LayoutRect::max_rect());
let mut local_inner = local_outer;
let mut can_calculate_inner_rect = true;
let mut can_calculate_outer_rect = false;
for source in clips {
match *source {
ClipSource::Image(ref mask) => {
if !mask.repeat {
can_calculate_outer_rect = true;
local_outer = local_outer.and_then(|r| r.intersection(&mask.rect));
}
local_inner = None;
}
ClipSource::Rectangle(rect, mode) => {
// Once we encounter a clip-out, we just assume the worst
// case clip mask size, for now.
if mode == ClipMode::ClipOut {
can_calculate_inner_rect = false;
break;
}
can_calculate_outer_rect = true;
local_outer = local_outer.and_then(|r| r.intersection(&rect));
local_inner = local_inner.and_then(|r| r.intersection(&rect));
}
ClipSource::RoundedRectangle(ref rect, ref radius, mode) => {
// Once we encounter a clip-out, we just assume the worst
// case clip mask size, for now.
if mode == ClipMode::ClipOut {
can_calculate_inner_rect = false;
break;
}
can_calculate_outer_rect = true;
local_outer = local_outer.and_then(|r| r.intersection(rect));
let inner_rect = extract_inner_rect_safe(rect, radius);
local_inner = local_inner
.and_then(|r| inner_rect.and_then(|ref inner| r.intersection(inner)));
}
ClipSource::BoxShadow(..) |
ClipSource::LineDecoration(..) => {
can_calculate_inner_rect = false;
break;
}
}
}
let outer = if can_calculate_outer_rect {
Some(local_outer.unwrap_or_else(LayoutRect::zero))
} else {
None
};
let inner = if can_calculate_inner_rect {
local_inner.unwrap_or_else(LayoutRect::zero)
} else {
LayoutRect::zero()
};
(inner, outer)
}
pub fn update(
&mut self,
gpu_cache: &mut GpuCache,
@ -523,7 +571,8 @@ impl ClipSources {
// rectangle so that we can do screen inner rectangle optimizations for these kind of
// cilps.
let can_calculate_inner_rect =
transform.preserves_2d_axis_alignment() && !transform.has_perspective_component();
transform.kind() == TransformedRectKind::AxisAligned &&
!transform.has_perspective_component();
let screen_inner_rect = if can_calculate_inner_rect {
calculate_screen_bounding_rect(transform, &self.local_inner_rect, device_pixel_scale, screen_rect)
.unwrap_or(DeviceIntRect::zero())

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

@ -37,7 +37,7 @@ impl ClipNode {
clip_chains: &mut [ClipChain],
spatial_nodes: &[SpatialNode],
) {
let clip_sources = clip_store.get_mut(self.clip_sources_index);
let clip_sources = &mut clip_store[self.clip_sources_index];
clip_sources.update(gpu_cache, resource_cache, device_pixel_scale);
let spatial_node = &spatial_nodes[clip_sources.spatial_node_index.0];
@ -60,10 +60,8 @@ impl ClipNode {
clip_sources_index: self.clip_sources_index,
coordinate_system_id: spatial_node.coordinate_system_id,
},
local_clip_rect: spatial_node
.coordinate_system_relative_transform
.transform_rect(&local_outer_rect)
.expect("clip node transform is not valid"),
local_clip_rect: local_outer_rect
.translate(&spatial_node.coordinate_system_relative_offset),
screen_outer_rect,
screen_inner_rect,
prev: None,

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

@ -14,7 +14,7 @@ use print_tree::{PrintTree, PrintTreePrinter};
use resource_cache::ResourceCache;
use scene::SceneProperties;
use spatial_node::{ScrollFrameInfo, SpatialNode, SpatialNodeType, StickyFrameInfo};
use util::{LayoutFastTransform, LayoutToWorldFastTransform};
use util::LayoutToWorldFastTransform;
pub type ScrollStates = FastHashMap<ExternalScrollId, ScrollFrameInfo>;
@ -103,8 +103,8 @@ pub struct TransformUpdateState {
/// coordinate systems which are relatively axis aligned.
pub current_coordinate_system_id: CoordinateSystemId,
/// Transform from the coordinate system that started this compatible coordinate system.
pub coordinate_system_relative_transform: LayoutFastTransform,
/// Offset from the coordinate system that started this compatible coordinate system.
pub coordinate_system_relative_offset: LayoutVector2D,
/// True if this node is transformed by an invertible transform. If not, display items
/// transformed by this node will not be displayed and display items not transformed by this
@ -242,7 +242,7 @@ impl ClipScrollTree {
nearest_scrolling_ancestor_offset: LayoutVector2D::zero(),
nearest_scrolling_ancestor_viewport: LayoutRect::zero(),
current_coordinate_system_id: CoordinateSystemId::root(),
coordinate_system_relative_transform: LayoutFastTransform::identity(),
coordinate_system_relative_offset: LayoutVector2D::zero(),
invertible: true,
};

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

@ -71,16 +71,18 @@ pub struct GpuFrameProfile<T> {
samplers: QuerySet<GpuSampler<T>>,
frame_id: FrameId,
inside_frame: bool,
ext_debug_marker: bool
}
impl<T> GpuFrameProfile<T> {
fn new(gl: Rc<gl::Gl>) -> Self {
fn new(gl: Rc<gl::Gl>, ext_debug_marker: bool) -> Self {
GpuFrameProfile {
gl,
timers: QuerySet::new(),
samplers: QuerySet::new(),
frame_id: FrameId::new(0),
inside_frame: false,
ext_debug_marker
}
}
@ -140,7 +142,7 @@ impl<T: NamedTag> GpuFrameProfile<T> {
fn start_timer(&mut self, tag: T) -> GpuTimeQuery {
self.finish_timer();
let marker = GpuMarker::new(&self.gl, tag.get_label());
let marker = GpuMarker::new(&self.gl, tag.get_label(), self.ext_debug_marker);
if let Some(query) = self.timers.add(GpuTimer { tag, time_ns: 0 }) {
self.gl.begin_query(gl::TIME_ELAPSED, query);
@ -187,19 +189,21 @@ pub struct GpuProfiler<T> {
gl: Rc<gl::Gl>,
frames: Vec<GpuFrameProfile<T>>,
next_frame: usize,
ext_debug_marker: bool
}
impl<T> GpuProfiler<T> {
pub fn new(gl: Rc<gl::Gl>) -> Self {
pub fn new(gl: Rc<gl::Gl>, ext_debug_marker: bool) -> Self {
const MAX_PROFILE_FRAMES: usize = 4;
let frames = (0 .. MAX_PROFILE_FRAMES)
.map(|_| GpuFrameProfile::new(Rc::clone(&gl)))
.map(|_| GpuFrameProfile::new(Rc::clone(&gl), ext_debug_marker))
.collect();
GpuProfiler {
gl,
next_frame: 0,
frames,
ext_debug_marker
}
}
@ -263,33 +267,42 @@ impl<T: NamedTag> GpuProfiler<T> {
}
pub fn start_marker(&mut self, label: &str) -> GpuMarker {
GpuMarker::new(&self.gl, label)
GpuMarker::new(&self.gl, label, self.ext_debug_marker)
}
pub fn place_marker(&mut self, label: &str) {
GpuMarker::fire(&self.gl, label)
GpuMarker::fire(&self.gl, label, self.ext_debug_marker)
}
}
#[must_use]
pub struct GpuMarker {
gl: Rc<gl::Gl>,
gl: Option<Rc<gl::Gl>>
}
impl GpuMarker {
fn new(gl: &Rc<gl::Gl>, message: &str) -> Self {
gl.push_group_marker_ext(message);
GpuMarker { gl: Rc::clone(gl) }
fn new(gl: &Rc<gl::Gl>, message: &str, ext_debug_marker: bool) -> Self {
let gl = if ext_debug_marker {
gl.push_group_marker_ext(message);
Some(Rc::clone(gl))
} else {
None
};
GpuMarker { gl }
}
fn fire(gl: &Rc<gl::Gl>, message: &str) {
gl.insert_event_marker_ext(message);
fn fire(gl: &Rc<gl::Gl>, message: &str, ext_debug_marker: bool) {
if ext_debug_marker {
gl.insert_event_marker_ext(message);
}
}
}
impl Drop for GpuMarker {
fn drop(&mut self) {
self.gl.pop_group_marker_ext();
if let Some(ref gl) = self.gl {
gl.pop_group_marker_ext();
}
}
}

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

@ -224,22 +224,22 @@ impl<'a> DisplayListFlattener<'a> {
&self,
pipeline_id: PipelineId,
complex_clips: ItemRange<ComplexClipRegion>,
) -> Vec<ComplexClipRegion> {
if complex_clips.is_empty() {
return vec![];
}
self.scene.get_display_list_for_pipeline(pipeline_id).get(complex_clips).collect()
) -> impl 'a + Iterator<Item = ComplexClipRegion> {
//Note: we could make this a bit more complex to early out
// on `complex_clips.is_empty()` if it's worth it
self.scene
.get_display_list_for_pipeline(pipeline_id)
.get(complex_clips)
}
fn get_clip_chain_items(
&self,
pipeline_id: PipelineId,
items: ItemRange<ClipId>,
) -> Vec<ClipId> {
if items.is_empty() {
return vec![];
}
self.scene.get_display_list_for_pipeline(pipeline_id).get(items).collect()
) -> impl 'a + Iterator<Item = ClipId> {
self.scene
.get_display_list_for_pipeline(pipeline_id)
.get(items)
}
fn flatten_root(&mut self, pipeline: &'a ScenePipeline, frame_size: &LayoutSize) {
@ -685,8 +685,7 @@ impl<'a> DisplayListFlattener<'a> {
}
SpecificDisplayItem::ClipChain(ref info) => {
let items = self.get_clip_chain_items(pipeline_id, item.clip_chain_items())
.iter()
.map(|id| self.id_to_index_mapper.get_clip_node_index(*id))
.map(|id| self.id_to_index_mapper.get_clip_node_index(id))
.collect();
let parent = match info.parent {
Some(id) => Some(
@ -1241,12 +1240,15 @@ impl<'a> DisplayListFlattener<'a> {
);
}
pub fn add_clip_node(
pub fn add_clip_node<I>(
&mut self,
new_node_id: ClipId,
parent_id: ClipId,
clip_region: ClipRegion,
) -> ClipChainIndex {
clip_region: ClipRegion<I>,
) -> ClipChainIndex
where
I: IntoIterator<Item = ComplexClipRegion>
{
let parent_clip_chain_index = self.id_to_index_mapper.get_clip_chain_index(&parent_id);
let spatial_node = self.id_to_index_mapper.get_spatial_node_index(parent_id);

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

@ -104,7 +104,7 @@ pub struct PictureState {
}
impl PictureState {
pub fn new() -> PictureState {
pub fn new() -> Self {
PictureState {
tasks: Vec::new(),
has_non_root_coord_system: false,
@ -117,7 +117,7 @@ pub struct PrimitiveRunContext<'a> {
pub clip_chain: &'a ClipChain,
pub scroll_node: &'a SpatialNode,
pub spatial_node_index: SpatialNodeIndex,
pub transform: Transform,
pub transform: Transform<'a>,
pub local_clip_rect: LayoutRect,
}
@ -127,7 +127,7 @@ impl<'a> PrimitiveRunContext<'a> {
scroll_node: &'a SpatialNode,
spatial_node_index: SpatialNodeIndex,
local_clip_rect: LayoutRect,
transform: Transform,
transform: Transform<'a>,
) -> Self {
PrimitiveRunContext {
clip_chain,

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

@ -8,7 +8,7 @@ use clip_scroll_tree::SpatialNodeIndex;
use gpu_cache::{GpuCacheAddress, GpuDataRequest};
use prim_store::{EdgeAaSegmentMask, Transform};
use render_task::RenderTaskAddress;
use util::{MatrixHelpers, TransformedRectKind};
use util::{LayoutToWorldFastTransform, TransformedRectKind};
// Contains type that must exactly match the same structures declared in GLSL.
@ -374,12 +374,12 @@ impl TransformPaletteId {
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[repr(C)]
pub struct TransformData {
pub transform: LayoutToWorldTransform,
pub inv_transform: WorldToLayoutTransform,
transform: LayoutToWorldTransform,
inv_transform: WorldToLayoutTransform,
}
impl TransformData {
pub fn invalid() -> Self {
fn invalid() -> Self {
TransformData {
transform: LayoutToWorldTransform::identity(),
inv_transform: WorldToLayoutTransform::identity(),
@ -389,7 +389,7 @@ impl TransformData {
// Extra data stored about each transform palette entry.
pub struct TransformMetadata {
pub transform_kind: TransformedRectKind,
transform_kind: TransformedRectKind,
}
// Stores a contiguous list of TransformData structs, that
@ -405,38 +405,60 @@ pub struct TransformPalette {
}
impl TransformPalette {
pub fn new(spatial_node_count: usize) -> TransformPalette {
pub fn new(spatial_node_count: usize) -> Self {
TransformPalette {
transforms: Vec::with_capacity(spatial_node_count),
metadata: Vec::with_capacity(spatial_node_count),
}
}
// Set the local -> world transform for a given spatial
// node in the transform palette.
pub fn set(
&mut self,
index: SpatialNodeIndex,
data: TransformData,
) {
let index = index.0 as usize;
#[inline]
fn grow(&mut self, index: SpatialNodeIndex) {
// Pad the vectors out if they are not long enough to
// account for this index. This can occur, for instance,
// when we stop recursing down the CST due to encountering
// a node with an invalid transform.
while index >= self.transforms.len() {
while self.transforms.len() <= index.0 as usize {
self.transforms.push(TransformData::invalid());
self.metadata.push(TransformMetadata {
transform_kind: TransformedRectKind::AxisAligned,
});
}
}
// Store the transform itself, along with metadata about it.
self.metadata[index] = TransformMetadata {
transform_kind: data.transform.transform_kind(),
pub fn invalidate(&mut self, index: SpatialNodeIndex) {
self.grow(index);
self.metadata[index.0 as usize] = TransformMetadata {
transform_kind: TransformedRectKind::AxisAligned,
};
self.transforms[index] = data;
self.transforms[index.0 as usize] = TransformData::invalid();
}
// Set the local -> world transform for a given spatial
// node in the transform palette.
pub fn set(
&mut self, index: SpatialNodeIndex, fast_transform: &LayoutToWorldFastTransform,
) -> bool {
self.grow(index);
match fast_transform.inverse() {
Some(inverted) => {
// Store the transform itself, along with metadata about it.
self.metadata[index.0 as usize] = TransformMetadata {
transform_kind: fast_transform.kind()
};
// Write the data that will be made available to the GPU for this node.
self.transforms[index.0 as usize] = TransformData {
transform: fast_transform.to_transform().into_owned(),
inv_transform: inverted.to_transform().into_owned(),
};
true
}
None => {
self.invalidate(index);
false
}
}
}
// Get the relevant information about a given transform that is
@ -448,14 +470,13 @@ impl TransformPalette {
&self,
index: SpatialNodeIndex,
) -> Transform {
let index = index.0;
let transform = &self.transforms[index];
let metadata = &self.metadata[index];
let data = &self.transforms[index.0 as usize];
let metadata = &self.metadata[index.0 as usize];
Transform {
m: transform.transform,
m: &data.transform,
transform_kind: metadata.transform_kind,
backface_is_visible: transform.transform.is_backface_visible(),
backface_is_visible: data.transform.is_backface_visible(),
}
}

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

@ -36,7 +36,7 @@ pub struct HitTestClipNode {
impl HitTestClipNode {
fn new(node: &ClipNode, clip_store: &ClipStore) -> Self {
let clips = clip_store.get(node.clip_sources_index);
let clips = &clip_store[node.clip_sources_index];
let regions = clips.clips().iter().map(|source| {
match source.0 {
ClipSource::Rectangle(ref rect, mode) => HitTestRegion::Rectangle(*rect, mode),

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

@ -63,8 +63,8 @@ impl ScrollNodeAndClipChain {
// the information in the clip-scroll tree. However, if we decide
// to rasterize a picture in local space, then this will be the
// transform relative to that picture's coordinate system.
pub struct Transform {
pub m: LayoutToWorldTransform,
pub struct Transform<'a> {
pub m: &'a LayoutToWorldTransform,
pub backface_is_visible: bool,
pub transform_kind: TransformedRectKind,
}
@ -1495,7 +1495,9 @@ impl PrimitiveStore {
// scale factor from the world transform to get an appropriately
// sized border task.
let world_scale = LayoutToWorldScale::new(1.0);
let scale = world_scale * frame_context.device_pixel_scale;
let mut scale = world_scale * frame_context.device_pixel_scale;
let max_scale = BorderRenderTaskInfo::get_max_scale(&border.radius);
scale.0 = scale.0.min(max_scale.0);
let scale_au = Au::from_f32_px(scale.0);
let needs_update = scale_au != cache_key.scale;
let mut new_segments = Vec::new();
@ -1572,7 +1574,7 @@ impl PrimitiveStore {
PrimitiveKind::TextRun => {
let text = &mut self.cpu_text_runs[metadata.cpu_prim_index.0];
// The transform only makes sense for screen space rasterization
let transform = prim_run_context.scroll_node.world_content_transform.into();
let transform = prim_run_context.scroll_node.world_content_transform.to_transform();
text.prepare_for_render(
frame_context.device_pixel_scale,
&transform,
@ -2062,7 +2064,7 @@ impl PrimitiveStore {
continue;
}
let local_clips = frame_state.clip_store.get(clip_item.clip_sources_index);
let local_clips = &frame_state.clip_store[clip_item.clip_sources_index];
rect_clips_only = rect_clips_only && local_clips.only_rectangular_clips;
// TODO(gw): We can easily extend the segment builder to support these clip sources in
@ -2289,7 +2291,7 @@ impl PrimitiveStore {
let extra_clip = {
let metadata = &self.cpu_metadata[prim_index.0];
metadata.clip_sources_index.map(|clip_sources_index| {
let prim_clips = frame_state.clip_store.get_mut(clip_sources_index);
let prim_clips = &mut frame_state.clip_store[clip_sources_index];
prim_clips.update(
frame_state.gpu_cache,
frame_state.resource_cache,
@ -2964,8 +2966,8 @@ fn get_local_clip_rect_for_nodes(
})
}
)
.and_then(|local_rect| {
scroll_node.coordinate_system_relative_transform.unapply(&local_rect)
.map(|local_rect| {
local_rect.translate(&-scroll_node.coordinate_system_relative_offset)
})
}

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

@ -403,7 +403,7 @@ impl RenderTask {
// whether a ClipSources contains any box-shadows and skip
// this iteration for the majority of cases.
for clip_item in &clips {
let clip_sources = clip_store.get_mut(clip_item.clip_sources_index);
let clip_sources = &mut clip_store[clip_item.clip_sources_index];
for &mut (ref mut clip, _) in &mut clip_sources.clips {
match *clip {
ClipSource::BoxShadow(ref mut info) => {

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

@ -1767,7 +1767,8 @@ impl Renderer {
}
})?;
let gpu_profile = GpuProfiler::new(Rc::clone(device.rc_gl()));
let ext_debug_marker = device.supports_extension("GL_EXT_debug_marker");
let gpu_profile = GpuProfiler::new(Rc::clone(device.rc_gl()), ext_debug_marker);
#[cfg(feature = "capture")]
let read_fbo = device.create_fbo_for_external_texture(0);

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

@ -8,9 +8,9 @@ use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollLoc
use api::{ScrollSensitivity, StickyOffsetBounds};
use clip_scroll_tree::{CoordinateSystemId, SpatialNodeIndex, TransformUpdateState};
use euclid::SideOffsets2D;
use gpu_types::{TransformData, TransformPalette};
use gpu_types::TransformPalette;
use scene::SceneProperties;
use util::{LayoutFastTransform, LayoutToWorldFastTransform, TransformedRectKind};
use util::{LayoutFastTransform, LayoutToWorldFastTransform, MatrixHelpers, TransformedRectKind};
#[derive(Clone, Debug)]
pub enum SpatialNodeType {
@ -66,7 +66,7 @@ pub struct SpatialNode {
/// The transformation from the coordinate system which established our compatible coordinate
/// system (same coordinate system id) and us. This can change via scroll offsets and via new
/// reference frame transforms.
pub coordinate_system_relative_transform: LayoutFastTransform,
pub coordinate_system_relative_offset: LayoutVector2D,
}
impl SpatialNode {
@ -85,7 +85,7 @@ impl SpatialNode {
node_type,
invertible: true,
coordinate_system_id: CoordinateSystemId(0),
coordinate_system_relative_transform: LayoutFastTransform::identity(),
coordinate_system_relative_offset: LayoutVector2D::zero(),
}
}
@ -204,25 +204,11 @@ impl SpatialNode {
node_index: SpatialNodeIndex,
) {
if !self.invertible {
transform_palette.set(node_index, TransformData::invalid());
transform_palette.invalidate(node_index);
return;
}
let inv_transform = match self.world_content_transform.inverse() {
Some(inverted) => inverted.to_transform(),
None => {
transform_palette.set(node_index, TransformData::invalid());
return;
}
};
let data = TransformData {
transform: self.world_content_transform.into(),
inv_transform,
};
// Write the data that will be made available to the GPU for this node.
transform_palette.set(node_index, data);
transform_palette.set(node_index, &self.world_content_transform);
}
pub fn update(
@ -239,12 +225,7 @@ impl SpatialNode {
}
self.update_transform(state, next_coordinate_system_id, scene_properties);
self.transform_kind = if self.world_content_transform.preserves_2d_axis_alignment() {
TransformedRectKind::AxisAligned
} else {
TransformedRectKind::Complex
};
self.transform_kind = self.world_content_transform.kind();
// If this node is a reference frame, we check if it has a non-invertible matrix.
// For non-reference-frames we assume that they will produce only additional
@ -292,13 +273,16 @@ impl SpatialNode {
// Try to update our compatible coordinate system transform. If we cannot, start a new
// incompatible coordinate system.
match state.coordinate_system_relative_transform.update(relative_transform) {
Some(offset) => self.coordinate_system_relative_transform = offset,
None => {
self.coordinate_system_relative_transform = LayoutFastTransform::identity();
state.current_coordinate_system_id = *next_coordinate_system_id;
next_coordinate_system_id.advance();
}
if relative_transform.is_simple_2d_translation() {
self.coordinate_system_relative_offset =
state.coordinate_system_relative_offset +
LayoutVector2D::new(relative_transform.m41, relative_transform.m42);
} else {
// If we break 2D axis alignment or have a perspective component, we need to start a
// new incompatible coordinate system with which we cannot share clips without masking.
self.coordinate_system_relative_offset = LayoutVector2D::zero();
state.current_coordinate_system_id = *next_coordinate_system_id;
next_coordinate_system_id.advance();
}
self.coordinate_system_id = state.current_coordinate_system_id;
@ -330,8 +314,8 @@ impl SpatialNode {
};
let added_offset = state.parent_accumulated_scroll_offset + sticky_offset + scroll_offset;
self.coordinate_system_relative_transform =
state.coordinate_system_relative_transform.offset(added_offset);
self.coordinate_system_relative_offset =
state.coordinate_system_relative_offset + added_offset;
if let SpatialNodeType::StickyFrame(ref mut info) = self.node_type {
info.current_offset = sticky_offset;
@ -478,8 +462,7 @@ impl SpatialNode {
SpatialNodeType::ReferenceFrame(ref info) => {
state.parent_reference_frame_transform = self.world_viewport_transform;
state.parent_accumulated_scroll_offset = LayoutVector2D::zero();
state.coordinate_system_relative_transform =
self.coordinate_system_relative_transform.clone();
state.coordinate_system_relative_offset = self.coordinate_system_relative_offset;
let translation = -info.origin_in_parent_reference_frame;
state.nearest_scrolling_ancestor_viewport =
state.nearest_scrolling_ancestor_viewport

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

@ -11,6 +11,8 @@ use euclid::{HomogeneousVector};
use num_traits::Zero;
use plane_split::{Clipper, Plane, Polygon};
use std::{i32, f32};
use std::borrow::Cow;
// Matches the definition of SK_ScalarNearlyZero in Skia.
const NEARLY_ZERO: f32 = 1.0 / 4096.0;
@ -486,11 +488,20 @@ impl<Src, Dst> FastTransform<Src, Dst> {
FastTransform::Transform { transform, inverse, is_2d}
}
pub fn to_transform(&self) -> TypedTransform3D<f32, Src, Dst> {
pub fn kind(&self) -> TransformedRectKind {
match *self {
FastTransform::Offset(offset) =>
TypedTransform3D::create_translation(offset.x, offset.y, 0.0),
FastTransform::Transform { transform, .. } => transform
FastTransform::Offset(_) => TransformedRectKind::AxisAligned,
FastTransform::Transform { ref transform, .. } if transform.preserves_2d_axis_alignment() => TransformedRectKind::AxisAligned,
FastTransform::Transform { .. } => TransformedRectKind::Complex,
}
}
pub fn to_transform(&self) -> Cow<TypedTransform3D<f32, Src, Dst>> {
match *self {
FastTransform::Offset(offset) => Cow::Owned(
TypedTransform3D::create_translation(offset.x, offset.y, 0.0)
),
FastTransform::Transform { ref transform, .. } => Cow::Borrowed(transform),
}
}
@ -528,15 +539,6 @@ impl<Src, Dst> FastTransform<Src, Dst> {
}
}
#[inline(always)]
pub fn preserves_2d_axis_alignment(&self) -> bool {
match *self {
FastTransform::Offset(..) => true,
FastTransform::Transform { ref transform, .. } =>
transform.preserves_2d_axis_alignment(),
}
}
#[inline(always)]
pub fn has_perspective_component(&self) -> bool {
match *self {
@ -596,17 +598,6 @@ impl<Src, Dst> FastTransform<Src, Dst> {
}
}
#[inline(always)]
pub fn offset(&self, new_offset: TypedVector2D<f32, Src>) -> Self {
match *self {
FastTransform::Offset(offset) => FastTransform::Offset(offset + new_offset),
FastTransform::Transform { ref transform, .. } => {
let transform = transform.pre_translate(new_offset.to_3d());
FastTransform::with_transform(transform)
}
}
}
pub fn post_translate(&self, new_offset: TypedVector2D<f32, Dst>) -> Self {
match *self {
FastTransform::Offset(offset) => {
@ -635,16 +626,6 @@ impl<Src, Dst> FastTransform<Src, Dst> {
}
}
pub fn update(&self, transform: TypedTransform3D<f32, Src, Dst>) -> Option<Self> {
if transform.is_simple_2d_translation() {
Some(self.offset(TypedVector2D::new(transform.m41, transform.m42)))
} else {
// If we break 2D axis alignment or have a perspective component, we need to start a
// new incompatible coordinate system with which we cannot share clips without masking.
None
}
}
}
impl<Src, Dst> From<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
@ -653,12 +634,6 @@ impl<Src, Dst> From<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst>
}
}
impl<Src, Dst> Into<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
fn into(self) -> TypedTransform3D<f32, Src, Dst> {
self.to_transform()
}
}
impl<Src, Dst> From<TypedVector2D<f32, Src>> for FastTransform<Src, Dst> {
fn from(vector: TypedVector2D<f32, Src>) -> Self {
FastTransform::with_vector(vector)

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

@ -12,12 +12,12 @@ serialize = []
deserialize = []
[dependencies]
app_units = "0.6"
app_units = "0.7"
bincode = "1.0"
bitflags = "1.0"
byteorder = "1.2.1"
ipc-channel = {version = "0.10.0", optional = true}
euclid = { version = "0.18", features = ["serde"] }
euclid = { version = "0.19", features = ["serde"] }
serde = { version = "=1.0.66", features = ["rc"] }
serde_derive = { version = "=1.0.66", features = ["deserialize_in_place"] }
serde_bytes = "0.10"

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

@ -123,7 +123,7 @@ pub struct AuxIter<'a, T> {
impl BuiltDisplayListDescriptor {}
impl BuiltDisplayList {
pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> BuiltDisplayList {
pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> Self {
BuiltDisplayList { data, descriptor }
}

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

@ -7,8 +7,8 @@ license = "MPL-2.0"
[dependencies]
rayon = "1"
thread_profiler = "0.1.1"
euclid = { version = "0.18", features = ["serde"] }
app_units = "0.6"
euclid = { version = "0.19", features = ["serde"] }
app_units = "0.7"
gleam = "0.6"
log = "0.4"
nsstring = { path = "../../servo/support/gecko/nsstring" }

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

@ -1 +1 @@
8a4fe66528aa362721e4048aac3cd5abf7faaf2c
7a1b919e37d6cd0155077aa90f98cfcdf9fa5bae

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

@ -10,10 +10,10 @@ base64 = "0.6"
bincode = "1.0"
byteorder = "1.0"
env_logger = { version = "0.5", optional = true }
euclid = "0.18"
euclid = "0.19"
gleam = "0.6"
glutin = "0.17"
app_units = "0.6"
app_units = "0.7"
image = "0.19"
clap = { version = "2", features = ["yaml"] }
lazy_static = "1"