Backed out 6 changesets (bug 1574493) for causing nested-sticky-2.html to perma fail CLOSED TREE

Backed out changeset 358746636448 (bug 1574493)
Backed out changeset 34aef5498237 (bug 1574493)
Backed out changeset 1f88e2031c76 (bug 1574493)
Backed out changeset 07c588b5ea10 (bug 1574493)
Backed out changeset 0685e8d3510e (bug 1574493)
Backed out changeset 15d4390220c4 (bug 1574493)
This commit is contained in:
Ciure Andrei 2019-09-13 19:26:50 +03:00
parent 5f29710fd7
commit a4046ec458
85 changed files with 846 additions and 958 deletions

View File

@ -1,11 +1,11 @@
# The following tests test the async positioning of the scrollbars.
# Basic root-frame scrollbar with async scrolling
fuzzy-if(Android,0-1,0-2) fuzzy-if(webrender&&gtkWidget,14-14,24-24) fuzzy-if(webrender&&cocoaWidget,23-23,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
fuzzy-if(Android,0-4,0-5) fuzzy-if(webrender&&gtkWidget,53-53,14-14) fuzzy-if(webrender&&cocoaWidget,22-22,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
fuzzy-if(Android,0-6,0-6) fuzzy-if(webrender&&gtkWidget,15-15,38-38) fuzzy-if(webrender&&cocoaWidget,18-18,79-79) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
fuzzy-if(Android,0-1,0-2) fuzzy-if(webrender&&gtkWidget,14-14,24-24) fuzzy-if(webrender&&cocoaWidget,23-23,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
fuzzy-if(Android,0-14,0-5) fuzzy-if(webrender&&gtkWidget,53-53,14-14) fuzzy-if(webrender&&cocoaWidget,22-22,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
fuzzy-if(Android,0-8,0-8) fuzzy-if(webrender&&gtkWidget,39-39,38-38) fuzzy-if(webrender&&cocoaWidget,18-18,43-43) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
fuzzy-if(Android,0-1,0-2) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
fuzzy-if(Android,0-4,0-5) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
fuzzy-if(Android,0-3,0-5) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
fuzzy-if(Android,0-1,0-2) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
fuzzy-if(Android,0-4,0-5) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
fuzzy-if(Android,0-3,0-7) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
# Different async zoom levels. Since the scrollthumb gets async-scaled in the
# compositor, the border-radius ends of the scrollthumb are going to be a little

View File

@ -381,7 +381,7 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
params.mix_blend_mode = aPipeline->mMixBlendMode;
Maybe<wr::WrSpatialId> referenceFrameId = builder.PushStackingContext(
params, wr::ToLayoutRect(aPipeline->mScBounds),
params, wr::ToRoundedLayoutRect(aPipeline->mScBounds),
// This is fine to do unconditionally because we only push images here.
wr::RasterSpace::Screen());
@ -402,13 +402,14 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
MOZ_ASSERT(aPipeline->mCurrentTexture->AsWebRenderTextureHost());
Range<wr::ImageKey> range_keys(&keys[0], keys.Length());
aPipeline->mCurrentTexture->PushDisplayItems(
builder, wr::ToLayoutRect(rect), wr::ToLayoutRect(rect),
builder, wr::ToRoundedLayoutRect(rect), wr::ToRoundedLayoutRect(rect),
aPipeline->mFilter, range_keys);
HoldExternalImage(aPipelineId, aEpoch, aPipeline->mCurrentTexture);
} else {
MOZ_ASSERT(keys.Length() == 1);
builder.PushImage(wr::ToLayoutRect(rect), wr::ToLayoutRect(rect), true,
aPipeline->mFilter, keys[0]);
builder.PushImage(wr::ToRoundedLayoutRect(rect),
wr::ToRoundedLayoutRect(rect), true, aPipeline->mFilter,
keys[0]);
}
}

View File

@ -304,8 +304,8 @@ Maybe<wr::WrSpaceAndClip> ClipManager::DefineScrollLayers(
LayoutDevicePoint scrollOffset =
metrics.GetScrollOffset() * metrics.GetDevPixelsPerCSSPixel();
return Some(mBuilder->DefineScrollLayer(
viewId, parent, wr::ToLayoutRect(contentRect),
wr::ToLayoutRect(clipBounds), wr::ToLayoutPoint(scrollOffset)));
viewId, parent, wr::ToRoundedLayoutRect(contentRect),
wr::ToRoundedLayoutRect(clipBounds), wr::ToLayoutPoint(scrollOffset)));
}
Maybe<wr::WrClipChainId> ClipManager::DefineClipChain(
@ -342,7 +342,7 @@ Maybe<wr::WrClipChainId> ClipManager::DefineClipChain(
// Define the clip
spaceAndClip->space = SpatialIdAfterOverride(spaceAndClip->space);
wr::WrClipId clipId = mBuilder->DefineClip(
spaceAndClip, wr::ToLayoutRect(clip), &wrRoundedRects);
spaceAndClip, wr::ToRoundedLayoutRect(clip), &wrRoundedRects);
clipIds.AppendElement(clipId);
cache[chain] = clipId;
CLIP_LOG("cache[%p] <= %zu\n", chain, clipId.id);
@ -373,7 +373,7 @@ void ClipManager::ItemClips::UpdateSeparateLeaf(
Maybe<wr::LayoutRect> clipLeaf;
if (mSeparateLeaf) {
MOZ_ASSERT(mChain);
clipLeaf.emplace(wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(
clipLeaf.emplace(wr::ToRoundedLayoutRect(LayoutDeviceRect::FromAppUnits(
mChain->mClip.GetClipRect(), aAppUnitsPerDevPixel)));
}

View File

@ -1927,8 +1927,8 @@ bool WebRenderCommandBuilder::PushImage(
return false;
}
auto r = wr::ToLayoutRect(aRect);
auto c = wr::ToLayoutRect(aClip);
auto r = wr::ToRoundedLayoutRect(aRect);
auto c = wr::ToRoundedLayoutRect(aClip);
aBuilder.PushImage(r, c, !aItem->BackfaceIsHidden(), rendering, key.value());
return true;
@ -2563,7 +2563,7 @@ bool WebRenderCommandBuilder::PushItemAsImage(
return false;
}
wr::LayoutRect dest = wr::ToLayoutRect(imageRect);
wr::LayoutRect dest = wr::ToRoundedLayoutRect(imageRect);
gfx::SamplingFilter sampleFilter =
nsLayoutUtils::GetSamplingFilterForFrame(aItem->Frame());
aBuilder.PushImage(dest, dest, !aItem->BackfaceIsHidden(),

View File

@ -315,7 +315,7 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
renderRoot == wr::RenderRoot::Default
? LayoutDeviceSize(size)
: LayoutDeviceSize());
wrRects[renderRoot] = wr::ToLayoutRect(rects[renderRoot]);
wrRects[renderRoot] = wr::ToRoundedLayoutRect(rects[renderRoot]);
}
wr::DisplayListBuilder builder(

View File

@ -263,7 +263,7 @@ void WebRenderImageData::CreateAsyncImageWebRenderCommands(
// context need to be done manually and pushed over to the parent side,
// where it will be done when we build the display list for the iframe.
// That happens in AsyncImagePipelineManager.
wr::LayoutRect r = wr::ToLayoutRect(aBounds);
wr::LayoutRect r = wr::ToRoundedLayoutRect(aBounds);
aBuilder.PushIFrame(r, aIsBackfaceVisible, mPipelineId.ref(),
/*ignoreMissingPipelines*/ false);

View File

@ -14,7 +14,7 @@ fuzzy(0-100,0-30) == 1149923.html 1149923-ref.html # use fuzzy due to few distor
== 1444904.html 1444904-ref.html
== 1451168.html 1451168-ref.html
== 1461313.html 1461313-ref.html
fuzzy(5-32,21908-26621) fuzzy-if(webrender,5-5,868-1039) == 1463802.html 1463802-ref.html
fuzzy(5-32,21908-26621) fuzzy-if(webrender,0-9,0-100) == 1463802.html 1463802-ref.html
fuzzy(0-11,0-4) == 1474722.html 1474722-ref.html
== 1501195.html 1501195-ref.html
== 1519754.html 1519754-ref.html

View File

@ -1091,15 +1091,14 @@ void DisplayListBuilder::PushImage(
const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
bool aIsBackfaceVisible, wr::ImageRendering aFilter, wr::ImageKey aImage,
bool aPremultipliedAlpha, const wr::ColorF& aColor) {
wr::LayoutRect clip = MergeClipLeaf(aClip);
WRDL_LOG("PushImage b=%s cl=%s\n", mWrState, Stringify(aBounds).c_str(),
Stringify(clip).c_str());
wr_dp_push_image(mWrState, aBounds, clip, aIsBackfaceVisible,
&mCurrentSpaceAndClipChain, aFilter, aImage,
aPremultipliedAlpha, aColor);
wr::LayoutSize size;
size.width = aBounds.size.width;
size.height = aBounds.size.height;
PushImage(aBounds, aClip, aIsBackfaceVisible, size, size, aFilter, aImage,
aPremultipliedAlpha, aColor);
}
void DisplayListBuilder::PushRepeatingImage(
void DisplayListBuilder::PushImage(
const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
bool aIsBackfaceVisible, const wr::LayoutSize& aStretchSize,
const wr::LayoutSize& aTileSpacing, wr::ImageRendering aFilter,
@ -1108,9 +1107,9 @@ void DisplayListBuilder::PushRepeatingImage(
WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState,
Stringify(aBounds).c_str(), Stringify(clip).c_str(),
Stringify(aStretchSize).c_str(), Stringify(aTileSpacing).c_str());
wr_dp_push_repeating_image(
mWrState, aBounds, clip, aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
aStretchSize, aTileSpacing, aFilter, aImage, aPremultipliedAlpha, aColor);
wr_dp_push_image(mWrState, aBounds, clip, aIsBackfaceVisible,
&mCurrentSpaceAndClipChain, aStretchSize, aTileSpacing,
aFilter, aImage, aPremultipliedAlpha, aColor);
}
void DisplayListBuilder::PushYCbCrPlanarImage(

View File

@ -479,12 +479,11 @@ class DisplayListBuilder final {
wr::ImageKey aImage, bool aPremultipliedAlpha = true,
const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f});
void PushRepeatingImage(
const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
bool aIsBackfaceVisible, const wr::LayoutSize& aStretchSize,
const wr::LayoutSize& aTileSpacing, wr::ImageRendering aFilter,
wr::ImageKey aImage, bool aPremultipliedAlpha = true,
const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f});
void PushImage(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
bool aIsBackfaceVisible, const wr::LayoutSize& aStretchSize,
const wr::LayoutSize& aTileSpacing, wr::ImageRendering aFilter,
wr::ImageKey aImage, bool aPremultipliedAlpha = true,
const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f});
void PushYCbCrPlanarImage(
const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,

View File

@ -2570,6 +2570,8 @@ pub extern "C" fn wr_dp_push_image(state: &mut WrState,
clip: LayoutRect,
is_backface_visible: bool,
parent: &WrSpaceAndClipChain,
stretch_size: LayoutSize,
tile_spacing: LayoutSize,
image_rendering: ImageRendering,
key: WrImageKey,
premultiplied_alpha: bool,
@ -2596,54 +2598,14 @@ pub extern "C" fn wr_dp_push_image(state: &mut WrState,
.dl_builder
.push_image(&prim_info,
bounds,
stretch_size,
tile_spacing,
image_rendering,
alpha_type,
key,
color);
}
#[no_mangle]
pub extern "C" fn wr_dp_push_repeating_image(state: &mut WrState,
bounds: LayoutRect,
clip: LayoutRect,
is_backface_visible: bool,
parent: &WrSpaceAndClipChain,
stretch_size: LayoutSize,
tile_spacing: LayoutSize,
image_rendering: ImageRendering,
key: WrImageKey,
premultiplied_alpha: bool,
color: ColorF) {
debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
let space_and_clip = parent.to_webrender(state.pipeline_id);
let prim_info = CommonItemProperties {
clip_rect: clip,
clip_id: space_and_clip.clip_id,
spatial_id: space_and_clip.spatial_id,
is_backface_visible,
hit_info: state.current_tag,
};
let alpha_type = if premultiplied_alpha {
AlphaType::PremultipliedAlpha
} else {
AlphaType::Alpha
};
state.frame_builder
.dl_builder
.push_repeating_image(&prim_info,
bounds,
stretch_size,
tile_spacing,
image_rendering,
alpha_type,
key,
color);
}
/// Push a 3 planar yuv image.
#[no_mangle]
pub extern "C" fn wr_dp_push_yuv_planar_image(state: &mut WrState,

View File

@ -236,6 +236,8 @@ impl Example for App {
builder.push_image(
&CommonItemProperties::new(bounds, space_and_clip),
bounds,
LayoutSize::new(500.0, 500.0),
LayoutSize::new(0.0, 0.0),
api::ImageRendering::Auto,
api::AlphaType::PremultipliedAlpha,
blob_img1.as_image(),
@ -246,6 +248,8 @@ impl Example for App {
builder.push_image(
&CommonItemProperties::new(bounds, space_and_clip),
bounds,
LayoutSize::new(200.0, 200.0),
LayoutSize::new(0.0, 0.0),
api::ImageRendering::Auto,
api::AlphaType::PremultipliedAlpha,
blob_img2.as_image(),

View File

@ -170,6 +170,8 @@ impl Example for App {
builder.push_image(
&CommonItemProperties::new(bounds, space_and_clip),
bounds,
bounds.size,
LayoutSize::zero(),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
self.external_image_key.unwrap(),

View File

@ -55,6 +55,8 @@ impl Example for App {
space_and_clip,
),
bounds,
image_size,
LayoutSize::zero(),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
self.image_key,
@ -67,6 +69,8 @@ impl Example for App {
space_and_clip,
),
bounds,
image_size,
LayoutSize::zero(),
ImageRendering::Pixelated,
AlphaType::PremultipliedAlpha,
self.image_key,

View File

@ -147,6 +147,8 @@ impl Example for App {
builder.push_image(
&info,
bounds,
image_size,
LayoutSize::zero(),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
*key,
@ -163,6 +165,8 @@ impl Example for App {
builder.push_image(
&info,
bounds,
image_size,
LayoutSize::zero(),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
image_key,
@ -179,6 +183,8 @@ impl Example for App {
builder.push_image(
&info,
bounds,
image_size,
LayoutSize::zero(),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
swap_key,

View File

@ -70,7 +70,9 @@ void main(void) {
ph.local_clip_rect,
ph.z,
transform,
pic_task
pic_task,
ph.local_rect,
ph.snap_offsets
);
// TODO(gw): transform bounds may be referenced by

View File

@ -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/. */
#include rect,render_task,gpu_cache,transform
#include rect,render_task,gpu_cache,snap,transform
#ifdef WR_VERTEX_SHADER
@ -11,6 +11,7 @@ in ivec4 aClipDataResourceAddress;
in vec2 aClipLocalPos;
in vec4 aClipTileRect;
in vec4 aClipDeviceArea;
in vec4 aClipSnapOffsets;
in vec4 aClipOrigins;
in float aDevicePixelScale;
@ -22,6 +23,7 @@ struct ClipMaskInstance {
vec2 local_pos;
RectWithSize tile_rect;
RectWithSize sub_rect;
vec4 snap_offsets;
vec2 task_origin;
vec2 screen_origin;
float device_pixel_scale;
@ -37,6 +39,7 @@ ClipMaskInstance fetch_clip_item() {
cmi.local_pos = aClipLocalPos;
cmi.tile_rect = RectWithSize(aClipTileRect.xy, aClipTileRect.zw);
cmi.sub_rect = RectWithSize(aClipDeviceArea.xy, aClipDeviceArea.zw);
cmi.snap_offsets = aClipSnapOffsets;
cmi.task_origin = aClipOrigins.xy;
cmi.screen_origin = aClipOrigins.zw;
cmi.device_pixel_scale = aDevicePixelScale;
@ -61,10 +64,23 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
Transform prim_transform,
Transform clip_transform,
RectWithSize sub_rect,
vec4 snap_offsets,
vec2 task_origin,
vec2 screen_origin,
float device_pixel_scale) {
vec2 device_pos = screen_origin + sub_rect.p0 + aPosition.xy * sub_rect.size;
// If the primitive we are drawing a clip mask for was snapped, then
// remove the effect of that snapping, so that the local position
// interpolation below works correctly relative to the clip item.
vec2 snap_offset = mix(
snap_offsets.xy,
snap_offsets.zw,
aPosition.xy
);
device_pos -= snap_offset;
vec2 world_pos = device_pos / device_pixel_scale;
vec4 pos = prim_transform.m * vec4(world_pos, 0.0, 1.0);

View File

@ -52,6 +52,7 @@ void main(void) {
prim_transform,
clip_transform,
cmi.sub_rect,
cmi.snap_offsets,
cmi.task_origin,
cmi.screen_origin,
cmi.device_pixel_scale

View File

@ -35,6 +35,7 @@ void main(void) {
prim_transform,
clip_transform,
cmi.sub_rect,
cmi.snap_offsets,
cmi.task_origin,
cmi.screen_origin,
cmi.device_pixel_scale

View File

@ -77,6 +77,7 @@ void main(void) {
prim_transform,
clip_transform,
cmi.sub_rect,
cmi.snap_offsets,
cmi.task_origin,
cmi.screen_origin,
cmi.device_pixel_scale

View File

@ -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/. */
#include rect,render_task,gpu_cache,transform
#include rect,render_task,gpu_cache,snap,transform
#define EXTEND_MODE_CLAMP 0
#define EXTEND_MODE_REPEAT 1
@ -47,12 +47,13 @@ uniform HIGHP_SAMPLER_FLOAT isampler2D sPrimitiveHeadersI;
// Instanced attributes
in ivec4 aData;
#define VECS_PER_PRIM_HEADER_F 2U
#define VECS_PER_PRIM_HEADER_F 3U
#define VECS_PER_PRIM_HEADER_I 2U
struct PrimitiveHeader {
RectWithSize local_rect;
RectWithSize local_clip_rect;
vec4 snap_offsets;
float z;
int specific_prim_address;
int transform_id;
@ -65,6 +66,7 @@ PrimitiveHeader fetch_prim_header(int index) {
ivec2 uv_f = get_fetch_uv(index, VECS_PER_PRIM_HEADER_F);
vec4 local_rect = TEXEL_FETCH(sPrimitiveHeadersF, uv_f, 0, ivec2(0, 0));
vec4 local_clip_rect = TEXEL_FETCH(sPrimitiveHeadersF, uv_f, 0, ivec2(1, 0));
ph.snap_offsets = TEXEL_FETCH(sPrimitiveHeadersF, uv_f, 0, ivec2(2, 0));
ph.local_rect = RectWithSize(local_rect.xy, local_rect.zw);
ph.local_clip_rect = RectWithSize(local_clip_rect.xy, local_clip_rect.zw);
@ -89,7 +91,9 @@ VertexInfo write_vertex(RectWithSize instance_rect,
RectWithSize local_clip_rect,
float z,
Transform transform,
PictureTask task) {
PictureTask task,
RectWithSize snap_rect,
vec4 snap_offsets) {
// Select the corner of the local rect that we are processing.
vec2 local_pos = instance_rect.p0 + instance_rect.size * aPosition.xy;
@ -97,6 +101,13 @@ VertexInfo write_vertex(RectWithSize instance_rect,
// Clamp to the two local clip rects.
vec2 clamped_local_pos = clamp_rect(local_pos, local_clip_rect);
/// Compute the snapping offset.
vec2 snap_offset = compute_snap_offset(
clamped_local_pos,
snap_rect,
snap_offsets
);
// Transform the current vertex to world space.
vec4 world_pos = transform.m * vec4(clamped_local_pos, 0.0, 1.0);
@ -104,13 +115,13 @@ VertexInfo write_vertex(RectWithSize instance_rect,
vec2 device_pos = world_pos.xy * task.device_pixel_scale;
// Apply offsets for the render task to get correct screen location.
vec2 final_offset = -task.content_origin + task.common_data.task_rect.p0;
vec2 final_offset = snap_offset - task.content_origin + task.common_data.task_rect.p0;
gl_Position = uTransform * vec4(device_pos + final_offset * world_pos.w, z * world_pos.w, world_pos.w);
VertexInfo vi = VertexInfo(
clamped_local_pos,
vec2(0.0, 0.0),
snap_offset,
world_pos
);

View File

@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifdef WR_VERTEX_SHADER
/// Given a point within a local rectangle, and the device space corners
/// offsets for the unsnapped primitive, return the snap offsets. This *must*
/// exactly match the logic in the Rust compute_snap_offset_impl function.
vec2 compute_snap_offset(
vec2 reference_pos,
RectWithSize reference_rect,
vec4 snap_positions
) {
/// Compute the position of this vertex inside the snap rectangle.
vec2 normalized_snap_pos = (reference_pos - reference_rect.p0) / reference_rect.size;
/// Compute the actual world offset for this vertex needed to make it snap.
return mix(snap_positions.xy, snap_positions.zw, normalized_snap_pos);
}
#endif //WR_VERTEX_SHADER

View File

@ -10,7 +10,7 @@ use crate::clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNo
use crate::glyph_rasterizer::GlyphFormat;
use crate::gpu_cache::{GpuBlockData, GpuCache, GpuCacheHandle, GpuCacheAddress};
use crate::gpu_types::{BrushFlags, BrushInstance, PrimitiveHeaders, ZBufferId, ZBufferIdGenerator};
use crate::gpu_types::{ClipMaskInstance, SplitCompositeInstance};
use crate::gpu_types::{ClipMaskInstance, SplitCompositeInstance, SnapOffsets};
use crate::gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance};
use crate::gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette};
use crate::internal_types::{FastHashMap, SavedTargetIndex, Swizzle, TextureSource, Filter};
@ -18,6 +18,7 @@ use crate::picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, T
use crate::prim_store::{DeferredResolve, EdgeAaSegmentMask, PrimitiveInstanceKind, PrimitiveVisibilityIndex, PrimitiveVisibilityMask};
use crate::prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity, SegmentInstanceIndex};
use crate::prim_store::{BrushSegment, ClipMaskKind, ClipTaskIndex, VECS_PER_SEGMENT};
use crate::prim_store::{recompute_snap_offsets};
use crate::prim_store::image::ImageSource;
use crate::render_backend::DataStores;
use crate::render_target::RenderTargetContext;
@ -707,7 +708,7 @@ impl BatchBuilder {
let prim_common_data = &ctx.data_stores.as_common_data(&prim_instance);
let prim_rect = LayoutRect::new(
prim_instance.prim_origin,
prim_common_data.prim_size
prim_common_data.prim_size,
);
let mut batch_features = BatchFeatures::empty();
@ -719,6 +720,7 @@ impl BatchBuilder {
batch_features |= BatchFeatures::ANTIALIASING;
}
let snap_offsets = prim_info.snap_offsets;
let prim_vis_mask = prim_info.visibility_mask;
let clip_task_address = ctx.get_prim_clip_task_address(
prim_info.clip_task_index,
@ -749,6 +751,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -815,6 +818,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -866,6 +870,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -1035,6 +1040,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -1071,8 +1077,9 @@ impl BatchBuilder {
let prim_cache_address = gpu_cache.get_address(&ctx.globals.default_image_handle);
let prim_header = PrimitiveHeader {
local_rect: picture.local_rect,
local_rect: picture.snapped_local_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -1097,8 +1104,9 @@ impl BatchBuilder {
);
let prim_header = PrimitiveHeader {
local_rect: pic.local_rect,
local_rect: pic.snapped_local_rect,
local_clip_rect: child_prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: GpuCacheAddress::INVALID,
transform_id: transforms
.get_id(
@ -1217,6 +1225,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: local_tile_rect,
local_clip_rect: local_tile_clip_rect,
snap_offsets: SnapOffsets::empty(),
specific_prim_address: prim_cache_address,
transform_id,
};
@ -1286,6 +1295,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: local_tile_rect,
local_clip_rect: local_tile_clip_rect,
snap_offsets: SnapOffsets::empty(),
specific_prim_address: prim_cache_address,
transform_id,
};
@ -1402,6 +1412,7 @@ impl BatchBuilder {
let shadow_prim_header = PrimitiveHeader {
local_rect: shadow_rect,
snap_offsets: prim_info.shadow_snap_offsets,
specific_prim_address: shadow_prim_address,
..prim_header
};
@ -1694,8 +1705,9 @@ impl BatchBuilder {
};
let prim_header = PrimitiveHeader {
local_rect: picture.local_rect,
local_rect: picture.snapped_local_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -1816,6 +1828,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -1890,6 +1903,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -1999,6 +2013,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -2104,6 +2119,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: prim_cache_address,
transform_id,
};
@ -2152,6 +2168,7 @@ impl BatchBuilder {
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: image_instance.tight_local_clip_rect,
snap_offsets,
specific_prim_address: gpu_cache.get_address(&gpu_handle),
transform_id,
};
@ -2195,6 +2212,7 @@ impl BatchBuilder {
let mut prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: GpuCacheAddress::INVALID,
transform_id,
};
@ -2322,6 +2340,7 @@ impl BatchBuilder {
let mut prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
snap_offsets,
specific_prim_address: GpuCacheAddress::INVALID,
transform_id,
};
@ -2425,9 +2444,10 @@ impl BatchBuilder {
let prim_cache_address = gpu_cache.get_address(&ctx.globals.default_image_handle);
let backdrop_picture = &ctx.prim_store.pictures[backdrop_pic_index.0];
let prim_header = PrimitiveHeader {
local_rect: backdrop_picture.local_rect,
local_rect: backdrop_picture.snapped_local_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
transform_id,
snap_offsets: SnapOffsets::empty(),
specific_prim_address: prim_cache_address,
};
@ -2648,10 +2668,18 @@ impl BatchBuilder {
let user_data = [stops_handle.as_int(gpu_cache), 0, 0, 0];
for tile in visible_tiles {
// Adjust the snap offsets for the tile.
let snap_offsets = recompute_snap_offsets(
tile.local_rect,
base_prim_header.local_rect,
base_prim_header.snap_offsets,
);
let prim_header = PrimitiveHeader {
specific_prim_address: gpu_cache.get_address(&tile.handle),
local_rect: tile.local_rect,
local_clip_rect: tile.local_clip_rect,
snap_offsets,
..*base_prim_header
};
let prim_header_index = prim_headers.push(&prim_header, z_id, user_data);
@ -2921,6 +2949,7 @@ impl ClipBatcher {
local_pos,
tile_rect: LayoutRect::zero(),
sub_rect,
snap_offsets: SnapOffsets::empty(),
task_origin,
screen_origin,
device_pixel_scale,
@ -3046,6 +3075,7 @@ impl ClipBatcher {
actual_rect: DeviceIntRect,
world_rect: &WorldRect,
device_pixel_scale: DevicePixelScale,
snap_offsets: SnapOffsets,
task_origin: DevicePoint,
screen_origin: DevicePoint,
) {
@ -3078,6 +3108,7 @@ impl ClipBatcher {
DevicePoint::zero(),
actual_rect.size.to_f32(),
),
snap_offsets,
task_origin,
screen_origin,
device_pixel_scale: device_pixel_scale.0,

View File

@ -98,13 +98,10 @@ impl<'a> DisplayListFlattener<'a> {
// Apply parameters that affect where the shadow rect
// exists in the local space of the primitive.
let shadow_rect = self.snap_rect(
&prim_info
.rect
.translate(*box_offset)
.inflate(spread_amount, spread_amount),
clip_and_scroll.spatial_node_index,
);
let shadow_rect = prim_info
.rect
.translate(*box_offset)
.inflate(spread_amount, spread_amount);
// If blur radius is zero, we can use a fast path with
// no blur applied.

View File

@ -1002,9 +1002,9 @@ impl ClipItemKeyKind {
}
}
pub fn image_mask(image_mask: &ImageMask, mask_rect: LayoutRect) -> Self {
pub fn image_mask(image_mask: &ImageMask) -> Self {
ClipItemKeyKind::ImageMask(
mask_rect.into(),
image_mask.rect.into(),
image_mask.image,
image_mask.repeat,
)

View File

@ -441,7 +441,6 @@ impl ClipScrollTree {
pub fn update_tree(
&mut self,
pan: WorldPoint,
global_device_pixel_scale: DevicePixelScale,
scene_properties: &SceneProperties,
) {
if self.spatial_nodes.is_empty() {
@ -472,7 +471,7 @@ impl ClipScrollTree {
None => continue,
};
node.update(&mut state, &mut self.coord_systems, global_device_pixel_scale, scene_properties, &*previous);
node.update(&mut state, &mut self.coord_systems, scene_properties, &*previous);
if !node.children.is_empty() {
node.prepare_state_for_children(&mut state);
@ -571,16 +570,12 @@ impl ClipScrollTree {
self.add_spatial_node(node)
}
pub fn add_spatial_node(&mut self, mut node: SpatialNode) -> SpatialNodeIndex {
pub fn add_spatial_node(&mut self, node: SpatialNode) -> SpatialNodeIndex {
let index = SpatialNodeIndex::new(self.spatial_nodes.len());
// When the parent node is None this means we are adding the root.
if let Some(parent_index) = node.parent {
let parent_node = &mut self.spatial_nodes[parent_index.0 as usize];
parent_node.add_child(index);
node.update_snapping(Some(parent_node));
} else {
node.update_snapping(None);
self.spatial_nodes[parent_index.0 as usize].add_child(index);
}
self.spatial_nodes.push(node);
@ -645,15 +640,12 @@ impl ClipScrollTree {
pt.new_level(format!("ReferenceFrame"));
pt.add_item(format!("kind: {:?}", info.kind));
pt.add_item(format!("transform_style: {:?}", info.transform_style));
pt.add_item(format!("source_transform: {:?}", info.source_transform));
pt.add_item(format!("origin_in_parent_reference_frame: {:?}", info.origin_in_parent_reference_frame));
}
}
pt.add_item(format!("index: {:?}", index));
pt.add_item(format!("content_transform: {:?}", node.content_transform));
pt.add_item(format!("viewport_transform: {:?}", node.viewport_transform));
pt.add_item(format!("snapping_transform: {:?}", node.snapping_transform));
pt.add_item(format!("coordinate_system_id: {:?}", node.coordinate_system_id));
for child_index in &node.children {
@ -765,7 +757,7 @@ fn test_cst_simple_translation() {
LayoutVector2D::zero(),
);
cst.update_tree(WorldPoint::zero(), DevicePixelScale::new(1.0), &SceneProperties::new());
cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
test_pt(100.0, 100.0, &cst, child1, root, 200.0, 100.0);
test_pt(100.0, 100.0, &cst, child2, root, 200.0, 150.0);
@ -807,7 +799,7 @@ fn test_cst_simple_scale() {
LayoutVector2D::zero(),
);
cst.update_tree(WorldPoint::zero(), DevicePixelScale::new(1.0), &SceneProperties::new());
cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
test_pt(100.0, 100.0, &cst, child1, root, 400.0, 100.0);
test_pt(100.0, 100.0, &cst, child2, root, 400.0, 200.0);
@ -857,7 +849,7 @@ fn test_cst_scale_translation() {
LayoutVector2D::zero(),
);
cst.update_tree(WorldPoint::zero(), DevicePixelScale::new(1.0), &SceneProperties::new());
cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
test_pt(100.0, 100.0, &cst, child1, root, 200.0, 150.0);
test_pt(100.0, 100.0, &cst, child2, root, 300.0, 450.0);
@ -891,7 +883,7 @@ fn test_cst_translation_rotate() {
LayoutVector2D::zero(),
);
cst.update_tree(WorldPoint::zero(), DevicePixelScale::new(1.0), &SceneProperties::new());
cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
test_pt(100.0, 0.0, &cst, child1, root, 0.0, -100.0);
}

View File

@ -27,7 +27,6 @@ use crate::prim_store::{PrimitiveInstanceKind, NinePatchDescriptor, PrimitiveSto
use crate::prim_store::{ScrollNodeAndClipChain, PictureIndex};
use crate::prim_store::{InternablePrimitive, SegmentInstanceIndex};
use crate::prim_store::{register_prim_chase_id, get_line_decoration_sizes};
use crate::prim_store::{SpaceSnapper};
use crate::prim_store::backdrop::Backdrop;
use crate::prim_store::borders::{ImageBorder, NormalBorderPrim};
use crate::prim_store::gradient::{GradientStopKey, LinearGradient, RadialGradient, RadialGradientParams};
@ -339,13 +338,10 @@ impl<'a> DisplayListFlattener<'a> {
found_explicit_tile_cache: false,
};
let device_pixel_scale = view.accumulated_scale_factor_for_snapping();
flattener.push_root(
root_pipeline_id,
&root_pipeline.viewport_size,
&root_pipeline.content_size,
device_pixel_scale,
);
// In order to ensure we have a single root stacking context for the
@ -369,7 +365,6 @@ impl<'a> DisplayListFlattener<'a> {
ClipChainId::NONE,
RasterSpace::Screen,
/* is_backdrop_root = */ true,
device_pixel_scale,
);
flattener.flatten_items(
@ -940,7 +935,6 @@ impl<'a> DisplayListFlattener<'a> {
clip_chain_id,
stacking_context.raster_space,
stacking_context.is_backdrop_root,
self.sc_stack.last().unwrap().snap_to_device.device_pixel_scale,
);
if cfg!(debug_assertions) && apply_pipeline_clip && clip_chain_id != ClipChainId::NONE {
@ -998,18 +992,8 @@ impl<'a> DisplayListFlattener<'a> {
);
self.pipeline_clip_chain_stack.push(clip_chain_index);
let snap_to_device = &mut self.sc_stack.last_mut().unwrap().snap_to_device;
snap_to_device.set_target_spatial_node(
spatial_node_index,
self.clip_scroll_tree,
);
let bounds = snap_to_device.snap_rect(
&info.bounds.translate(current_offset),
);
let content_size = snap_to_device.snap_size(&pipeline.content_size);
let bounds = info.bounds;
let origin = current_offset + bounds.origin.to_vector();
let spatial_node_index = self.push_reference_frame(
SpatialId::root_reference_frame(iframe_pipeline_id),
Some(spatial_node_index),
@ -1017,7 +1001,7 @@ impl<'a> DisplayListFlattener<'a> {
TransformStyle::Flat,
PropertyBinding::Value(LayoutTransform::identity()),
ReferenceFrameKind::Transform,
bounds.origin.to_vector(),
origin,
);
let iframe_rect = LayoutRect::new(LayoutPoint::zero(), bounds.size);
@ -1027,7 +1011,7 @@ impl<'a> DisplayListFlattener<'a> {
Some(ExternalScrollId(0, iframe_pipeline_id)),
iframe_pipeline_id,
&iframe_rect,
&content_size,
&pipeline.content_size,
ScrollSensitivity::ScriptAndInputEvents,
ScrollFrameKind::PipelineRoot,
LayoutVector2D::zero(),
@ -1071,12 +1055,7 @@ impl<'a> DisplayListFlattener<'a> {
common: &CommonItemProperties,
apply_pipeline_clip: bool
) -> (LayoutPrimitiveInfo, ScrollNodeAndClipChain) {
let (layout, _, clip_and_scroll) = self.process_common_properties_with_bounds(
common,
&common.clip_rect,
apply_pipeline_clip,
);
(layout, clip_and_scroll)
self.process_common_properties_with_bounds(common, &common.clip_rect, apply_pipeline_clip)
}
fn process_common_properties_with_bounds(
@ -1084,7 +1063,7 @@ impl<'a> DisplayListFlattener<'a> {
common: &CommonItemProperties,
bounds: &LayoutRect,
apply_pipeline_clip: bool
) -> (LayoutPrimitiveInfo, LayoutRect, ScrollNodeAndClipChain) {
) -> (LayoutPrimitiveInfo, ScrollNodeAndClipChain) {
let clip_and_scroll = self.get_clip_and_scroll(
&common.clip_id,
&common.spatial_id,
@ -1093,36 +1072,16 @@ impl<'a> DisplayListFlattener<'a> {
let current_offset = self.current_offset(clip_and_scroll.spatial_node_index);
let snap_to_device = &mut self.sc_stack.last_mut().unwrap().snap_to_device;
snap_to_device.set_target_spatial_node(
clip_and_scroll.spatial_node_index,
self.clip_scroll_tree
);
let clip_rect = common.clip_rect.translate(current_offset);
let rect = bounds.translate(current_offset);
let layout = LayoutPrimitiveInfo {
rect: snap_to_device.snap_rect(&rect),
clip_rect: snap_to_device.snap_rect(&clip_rect),
rect,
clip_rect,
is_backface_visible: common.is_backface_visible,
hit_info: common.hit_info,
};
(layout, rect, clip_and_scroll)
}
pub fn snap_rect(
&mut self,
rect: &LayoutRect,
target_spatial_node: SpatialNodeIndex,
) -> LayoutRect {
let snap_to_device = &mut self.sc_stack.last_mut().unwrap().snap_to_device;
snap_to_device.set_target_spatial_node(
target_spatial_node,
self.clip_scroll_tree
);
snap_to_device.snap_rect(rect)
(layout, clip_and_scroll)
}
fn flatten_item<'b>(
@ -1133,7 +1092,7 @@ impl<'a> DisplayListFlattener<'a> {
) -> Option<BuiltDisplayListIter<'a>> {
match *item.item() {
DisplayItem::Image(ref info) => {
let (layout, _, clip_and_scroll) = self.process_common_properties_with_bounds(
let (layout, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.bounds,
apply_pipeline_clip,
@ -1142,32 +1101,7 @@ impl<'a> DisplayListFlattener<'a> {
self.add_image(
clip_and_scroll,
&layout,
layout.rect.size,
LayoutSize::zero(),
None,
info.image_key,
info.image_rendering,
info.alpha_type,
info.color,
);
}
DisplayItem::RepeatingImage(ref info) => {
let (layout, unsnapped_rect, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.bounds,
apply_pipeline_clip,
);
let stretch_size = process_repeat_size(
&layout.rect,
&unsnapped_rect,
info.stretch_size,
);
self.add_image(
clip_and_scroll,
&layout,
stretch_size,
info.tile_spacing,
None,
info.image_key,
@ -1177,7 +1111,7 @@ impl<'a> DisplayListFlattener<'a> {
);
}
DisplayItem::YuvImage(ref info) => {
let (layout, _, clip_and_scroll) = self.process_common_properties_with_bounds(
let (layout, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.bounds,
apply_pipeline_clip,
@ -1194,7 +1128,7 @@ impl<'a> DisplayListFlattener<'a> {
);
}
DisplayItem::Text(ref info) => {
let (layout, _, clip_and_scroll) = self.process_common_properties_with_bounds(
let (layout, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.bounds,
apply_pipeline_clip,
@ -1245,7 +1179,7 @@ impl<'a> DisplayListFlattener<'a> {
);
}
DisplayItem::Line(ref info) => {
let (layout, _, clip_and_scroll) = self.process_common_properties_with_bounds(
let (layout, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.area,
apply_pipeline_clip,
@ -1261,25 +1195,19 @@ impl<'a> DisplayListFlattener<'a> {
);
}
DisplayItem::Gradient(ref info) => {
let (layout, unsnapped_rect, clip_and_scroll) = self.process_common_properties_with_bounds(
let (layout, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.bounds,
apply_pipeline_clip,
);
let tile_size = process_repeat_size(
&layout.rect,
&unsnapped_rect,
info.tile_size,
);
if let Some(prim_key_kind) = self.create_linear_gradient_prim(
&layout,
info.gradient.start_point,
info.gradient.end_point,
item.gradient_stops(),
info.gradient.extend_mode,
tile_size,
info.tile_size,
info.tile_spacing,
None,
) {
@ -1292,18 +1220,12 @@ impl<'a> DisplayListFlattener<'a> {
}
}
DisplayItem::RadialGradient(ref info) => {
let (layout, unsnapped_rect, clip_and_scroll) = self.process_common_properties_with_bounds(
let (layout, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.bounds,
apply_pipeline_clip,
);
let tile_size = process_repeat_size(
&layout.rect,
&unsnapped_rect,
info.tile_size,
);
let prim_key_kind = self.create_radial_gradient_prim(
&layout,
info.gradient.center,
@ -1312,7 +1234,7 @@ impl<'a> DisplayListFlattener<'a> {
info.gradient.radius.width / info.gradient.radius.height,
item.gradient_stops(),
info.gradient.extend_mode,
tile_size,
info.tile_size,
info.tile_spacing,
None,
);
@ -1325,7 +1247,7 @@ impl<'a> DisplayListFlattener<'a> {
);
}
DisplayItem::BoxShadow(ref info) => {
let (layout, _, clip_and_scroll) = self.process_common_properties_with_bounds(
let (layout, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.box_bounds,
apply_pipeline_clip,
@ -1343,7 +1265,7 @@ impl<'a> DisplayListFlattener<'a> {
);
}
DisplayItem::Border(ref info) => {
let (layout, _, clip_and_scroll) = self.process_common_properties_with_bounds(
let (layout, clip_and_scroll) = self.process_common_properties_with_bounds(
&info.common,
&info.bounds,
apply_pipeline_clip,
@ -1760,7 +1682,6 @@ impl<'a> DisplayListFlattener<'a> {
clip_chain_id: ClipChainId,
requested_raster_space: RasterSpace,
is_backdrop_root: bool,
device_pixel_scale: DevicePixelScale,
) {
// Check if this stacking context is the root of a pipeline, and the caller
// has requested it as an output frame.
@ -1863,14 +1784,6 @@ impl<'a> DisplayListFlattener<'a> {
current_clip_chain_id = clip_chain_node.parent_clip_chain_id;
}
let snap_to_device = self.sc_stack.last().map_or(
SpaceSnapper::new(
ROOT_SPATIAL_NODE_INDEX,
device_pixel_scale,
),
|sc| sc.snap_to_device.clone(),
);
// Push the SC onto the stack, so we know how to handle things in
// pop_stacking_context.
self.sc_stack.push(FlattenedStackingContext {
@ -1887,7 +1800,6 @@ impl<'a> DisplayListFlattener<'a> {
context_3d,
create_tile_cache,
is_backdrop_root,
snap_to_device,
});
}
@ -2263,7 +2175,6 @@ impl<'a> DisplayListFlattener<'a> {
pipeline_id: PipelineId,
viewport_size: &LayoutSize,
content_size: &LayoutSize,
device_pixel_scale: DevicePixelScale,
) {
if let ChasePrimitive::Id(id) = self.config.chase_primitive {
println!("Chasing {:?} by index", id);
@ -2282,27 +2193,13 @@ impl<'a> DisplayListFlattener<'a> {
LayoutVector2D::zero(),
);
// We can't use this with the stacking context because it does not exist
// yet. Just create a dedicated snapper for the root.
let snap_to_device = SpaceSnapper::new_with_target(
spatial_node_index,
ROOT_SPATIAL_NODE_INDEX,
device_pixel_scale,
self.clip_scroll_tree,
);
let content_size = snap_to_device.snap_size(content_size);
let viewport_rect = snap_to_device.snap_rect(
&LayoutRect::new(LayoutPoint::zero(), *viewport_size),
);
self.add_scroll_frame(
SpatialId::root_scroll_node(pipeline_id),
spatial_node_index,
Some(ExternalScrollId(0, pipeline_id)),
pipeline_id,
&viewport_rect,
&content_size,
&LayoutRect::new(LayoutPoint::zero(), *viewport_size),
content_size,
ScrollSensitivity::ScriptAndInputEvents,
ScrollFrameKind::PipelineRoot,
LayoutVector2D::zero(),
@ -2326,14 +2223,6 @@ impl<'a> DisplayListFlattener<'a> {
// Map the ClipId for the positioning node to a spatial node index.
let spatial_node_index = self.id_to_index_mapper.get_spatial_node_index(space_and_clip.spatial_id);
let snap_to_device = &mut self.sc_stack.last_mut().unwrap().snap_to_device;
snap_to_device.set_target_spatial_node(
spatial_node_index,
self.clip_scroll_tree,
);
let snapped_clip_rect = snap_to_device.snap_rect(&clip_region.main);
let mut clip_count = 0;
// Intern each clip item in this clip node, and add the interned
@ -2343,7 +2232,7 @@ impl<'a> DisplayListFlattener<'a> {
// Build the clip sources from the supplied region.
let item = ClipItemKey {
kind: ClipItemKeyKind::rectangle(snapped_clip_rect, ClipMode::Clip),
kind: ClipItemKeyKind::rectangle(clip_region.main, ClipMode::Clip),
spatial_node_index,
};
let handle = self
@ -2360,9 +2249,8 @@ impl<'a> DisplayListFlattener<'a> {
clip_count += 1;
if let Some(ref image_mask) = clip_region.image_mask {
let snapped_mask_rect = snap_to_device.snap_rect(&image_mask.rect);
let item = ClipItemKey {
kind: ClipItemKeyKind::image_mask(image_mask, snapped_mask_rect),
kind: ClipItemKeyKind::image_mask(image_mask),
spatial_node_index,
};
@ -2381,10 +2269,9 @@ impl<'a> DisplayListFlattener<'a> {
}
for region in clip_region.complex_clips {
let snapped_region_rect = snap_to_device.snap_rect(&region.rect);
let item = ClipItemKey {
kind: ClipItemKeyKind::rounded_rect(
snapped_region_rect,
region.rect,
region.radii,
region.mode,
),
@ -2657,23 +2544,11 @@ impl<'a> DisplayListFlattener<'a> {
P: InternablePrimitive + CreateShadow,
Interners: AsMut<Interner<P>>,
{
let snap_to_device = &mut self.sc_stack.last_mut().unwrap().snap_to_device;
snap_to_device.set_target_spatial_node(
pending_primitive.clip_and_scroll.spatial_node_index,
self.clip_scroll_tree
);
// Offset the local rect and clip rect by the shadow offset. The pending
// primitive has already been snapped, but we will need to snap the
// shadow after translation. We don't need to worry about the size
// changing because the shadow has the same raster space as the
// primitive, and thus we know the size is already rounded.
// Offset the local rect and clip rect by the shadow offset.
let mut info = pending_primitive.info.clone();
info.rect = snap_to_device.snap_rect(
&info.rect.translate(pending_shadow.shadow.offset),
);
info.clip_rect = snap_to_device.snap_rect(
&info.clip_rect.translate(pending_shadow.shadow.offset),
info.rect = info.rect.translate(pending_shadow.shadow.offset);
info.clip_rect = info.clip_rect.translate(
pending_shadow.shadow.offset
);
// Construct and add a primitive for the given shadow.
@ -3562,13 +3437,6 @@ struct FlattenedStackingContext {
/// True if this stacking context is a backdrop root.
is_backdrop_root: bool,
/// A helper struct to snap local rects in device space. During frame
/// building we may establish new raster roots, however typically that is in
/// cases where we won't be applying snapping (e.g. has perspective), or in
/// edge cases (e.g. SVG filter) where we can accept slightly incorrect
/// behaviour in favour of getting the common case right.
snap_to_device: SpaceSnapper,
}
impl FlattenedStackingContext {
@ -3822,22 +3690,3 @@ fn filter_primitives_for_compositing(
// more efficient than cloning these here.
input_filter_primitives.iter().map(|primitive| primitive.into()).collect()
}
fn process_repeat_size(
snapped_rect: &LayoutRect,
unsnapped_rect: &LayoutRect,
repeat_size: LayoutSize,
) -> LayoutSize {
LayoutSize::new(
if repeat_size.width == unsnapped_rect.size.width {
snapped_rect.size.width
} else {
repeat_size.width
},
if repeat_size.height == unsnapped_rect.size.height {
snapped_rect.size.height
} else {
repeat_size.height
},
)
}

View File

@ -392,7 +392,7 @@ impl FrameBuilder {
&frame_context,
gpu_cache,
&self.clip_store,
data_stores,
&data_stores.clip,
);
{
@ -544,7 +544,6 @@ impl FrameBuilder {
clip_scroll_tree.update_tree(
pan,
global_device_pixel_scale,
scene_properties,
);
let mut transform_palette = clip_scroll_tree.build_transform_palette();

View File

@ -169,6 +169,7 @@ pub struct ClipMaskInstance {
pub local_pos: LayoutPoint,
pub tile_rect: LayoutRect,
pub sub_rect: DeviceRect,
pub snap_offsets: SnapOffsets,
pub task_origin: DevicePoint,
pub screen_origin: DevicePoint,
pub device_pixel_scale: f32,
@ -249,6 +250,7 @@ impl PrimitiveHeaders {
self.headers_float.push(PrimitiveHeaderF {
local_rect: prim_header.local_rect,
local_clip_rect: prim_header.local_clip_rect,
snap_offsets: prim_header.snap_offsets,
});
self.headers_int.push(PrimitiveHeaderI {
@ -269,6 +271,7 @@ impl PrimitiveHeaders {
pub struct PrimitiveHeader {
pub local_rect: LayoutRect,
pub local_clip_rect: LayoutRect,
pub snap_offsets: SnapOffsets,
pub specific_prim_address: GpuCacheAddress,
pub transform_id: TransformPaletteId,
}
@ -281,6 +284,7 @@ pub struct PrimitiveHeader {
pub struct PrimitiveHeaderF {
pub local_rect: LayoutRect,
pub local_clip_rect: LayoutRect,
pub snap_offsets: SnapOffsets,
}
// i32 parts of a primitive header
@ -589,6 +593,33 @@ pub enum UvRectKind {
},
}
/// Represents offsets in device pixels that a primitive
/// was snapped to.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct SnapOffsets {
/// How far the top left corner was snapped
pub top_left: DeviceVector2D,
/// How far the bottom right corner was snapped
pub bottom_right: DeviceVector2D,
}
impl SnapOffsets {
pub fn empty() -> Self {
SnapOffsets {
top_left: DeviceVector2D::zero(),
bottom_right: DeviceVector2D::zero(),
}
}
pub fn is_empty(&self) -> bool {
let zero = DeviceVector2D::zero();
self.top_left == zero && self.bottom_right == zero
}
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]

View File

@ -7,7 +7,7 @@ use api::{PropertyBinding, PropertyBindingId, FilterPrimitive, FontRenderMode};
use api::{DebugFlags, RasterSpace, ImageKey, ColorF};
use api::units::*;
use crate::box_shadow::{BLUR_SAMPLE_SCALE};
use crate::clip::{ClipStore, ClipChainInstance, ClipDataHandle, ClipChainId};
use crate::clip::{ClipStore, ClipDataStore, ClipChainInstance, ClipDataHandle, ClipChainId};
use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX,
ClipScrollTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace, CoordinateSystemId
};
@ -23,7 +23,7 @@ use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
use crate::gpu_types::UvRectKind;
use plane_split::{Clipper, Polygon, Splitter};
use crate::prim_store::{SpaceMapper, PrimitiveVisibilityMask, PointKey, PrimitiveTemplateKind};
use crate::prim_store::{SpaceSnapper, PictureIndex, PrimitiveInstance, PrimitiveInstanceKind};
use crate::prim_store::{PictureIndex, PrimitiveInstance, PrimitiveInstanceKind};
use crate::prim_store::{get_raster_rects, PrimitiveScratchBuffer, RectangleKey};
use crate::prim_store::{OpacityBindingStorage, ImageInstanceStorage, OpacityBindingIndex};
use crate::print_tree::PrintTreePrinter;
@ -1781,7 +1781,7 @@ impl<'a> PictureUpdateState<'a> {
frame_context: &FrameBuildingContext,
gpu_cache: &mut GpuCache,
clip_store: &ClipStore,
data_stores: &mut DataStores,
clip_data_store: &ClipDataStore,
) {
profile_marker!("UpdatePictures");
@ -1798,7 +1798,7 @@ impl<'a> PictureUpdateState<'a> {
frame_context,
gpu_cache,
clip_store,
data_stores,
clip_data_store,
);
if !state.are_raster_roots_assigned {
@ -1861,7 +1861,7 @@ impl<'a> PictureUpdateState<'a> {
frame_context: &FrameBuildingContext,
gpu_cache: &mut GpuCache,
clip_store: &ClipStore,
data_stores: &mut DataStores,
clip_data_store: &ClipDataStore,
) {
if let Some(prim_list) = picture_primitives[pic_index.0].pre_update(
self,
@ -1874,7 +1874,7 @@ impl<'a> PictureUpdateState<'a> {
frame_context,
gpu_cache,
clip_store,
data_stores,
clip_data_store,
);
}
@ -1882,7 +1882,6 @@ impl<'a> PictureUpdateState<'a> {
prim_list,
self,
frame_context,
data_stores,
);
}
}
@ -2197,10 +2196,6 @@ pub struct PrimitiveClusterIndex(pub u32);
#[cfg_attr(feature = "capture", derive(Serialize))]
pub struct ClusterIndex(pub u16);
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "capture", derive(Serialize))]
pub struct PrimitiveIndex(pub u32);
impl ClusterIndex {
pub const INVALID: ClusterIndex = ClusterIndex(u16::MAX);
}
@ -2222,10 +2217,6 @@ pub struct PrimitiveList {
pub pictures: PictureList,
/// List of primitives grouped into clusters.
pub clusters: SmallVec<[PrimitiveCluster; 4]>,
/// List of primitive indicies that can only update
/// the cluster during frame building. This maps to
/// primitives in the prim_instances array.
pub deferred_prims: Vec<PrimitiveIndex>,
}
impl PrimitiveList {
@ -2238,7 +2229,6 @@ impl PrimitiveList {
prim_instances: Vec::new(),
pictures: SmallVec::new(),
clusters: SmallVec::new(),
deferred_prims: Vec::new(),
}
}
@ -2253,11 +2243,10 @@ impl PrimitiveList {
let mut pictures = SmallVec::new();
let mut clusters_map = FastHashMap::default();
let mut clusters: SmallVec<[PrimitiveCluster; 4]> = SmallVec::new();
let mut deferred_prims = Vec::new();
// Walk the list of primitive instances and extract any that
// are pictures.
for (prim_index, prim_instance) in &mut prim_instances.iter_mut().enumerate() {
for prim_instance in &mut prim_instances {
// Check if this primitive is a picture. In future we should
// remove this match and embed this info directly in the primitive instance.
let is_pic = match prim_instance.kind {
@ -2313,12 +2302,8 @@ impl PrimitiveList {
(data.is_backface_visible, data.prim_size)
}
PrimitiveInstanceKind::Backdrop { data_handle, .. } => {
// We don't know the actual size of the backdrop until frame
// building, so use an empty rect for now and add it to the
// deferred primitive list.
let data = &interners.backdrop[data_handle];
deferred_prims.push(PrimitiveIndex(prim_index as u32));
(data.is_backface_visible, LayoutSize::zero())
(data.is_backface_visible, data.prim_size)
}
PrimitiveInstanceKind::PushClipChain |
PrimitiveInstanceKind::PopClipChain => {
@ -2373,7 +2358,6 @@ impl PrimitiveList {
prim_instances,
pictures,
clusters,
deferred_prims,
}
}
}
@ -2439,10 +2423,17 @@ pub struct PicturePrimitive {
/// composited into the parent picture.
pub spatial_node_index: SpatialNodeIndex,
/// The local rect of this picture. It is built
/// dynamically when updating visibility. It takes
/// into account snapping in device space for its
/// children.
pub snapped_local_rect: LayoutRect,
/// The local rect of this picture. It is built
/// dynamically during the first picture traversal. It
/// is composed of already snapped primitives.
pub local_rect: LayoutRect,
/// does not take into account snapping in device for
/// its children.
pub unsnapped_local_rect: LayoutRect,
/// If false, this picture needs to (re)build segments
/// if it supports segment rendering. This can occur
@ -2467,7 +2458,8 @@ impl PicturePrimitive {
) {
pt.new_level(format!("{:?}", self_index));
pt.add_item(format!("prim_count: {:?}", self.prim_list.prim_instances.len()));
pt.add_item(format!("local_rect: {:?}", self.local_rect));
pt.add_item(format!("snapped_local_rect: {:?}", self.snapped_local_rect));
pt.add_item(format!("unsnapped_local_rect: {:?}", self.unsnapped_local_rect));
pt.add_item(format!("spatial_node_index: {:?}", self.spatial_node_index));
pt.add_item(format!("raster_config: {:?}", self.raster_config));
pt.add_item(format!("requested_composite_mode: {:?}", self.requested_composite_mode));
@ -2576,7 +2568,8 @@ impl PicturePrimitive {
is_backface_visible,
requested_raster_space,
spatial_node_index,
local_rect: LayoutRect::zero(),
snapped_local_rect: LayoutRect::zero(),
unsnapped_local_rect: LayoutRect::zero(),
tile_cache,
options,
segments_are_valid: false,
@ -2680,7 +2673,7 @@ impl PicturePrimitive {
match self.raster_config {
Some(ref raster_config) => {
let pic_rect = PictureRect::from_untyped(&self.local_rect.to_untyped());
let pic_rect = PictureRect::from_untyped(&self.snapped_local_rect.to_untyped());
let device_pixel_scale = frame_state
.surfaces[raster_config.surface_index.0]
@ -3451,7 +3444,6 @@ impl PicturePrimitive {
prim_list: PrimitiveList,
state: &mut PictureUpdateState,
frame_context: &FrameBuildingContext,
data_stores: &mut DataStores,
) {
// Restore the pictures list used during recursion.
self.prim_list = prim_list;
@ -3459,59 +3451,6 @@ impl PicturePrimitive {
// Pop the state information about this picture.
state.pop_picture();
// Update any primitives/cluster bounding rects that can only be done
// with information available during frame building.
for prim_index in &self.prim_list.deferred_prims {
let prim_instance = &mut self.prim_list.prim_instances[prim_index.0 as usize];
match prim_instance.kind {
PrimitiveInstanceKind::Backdrop { data_handle, .. } => {
// The actual size and clip rect of this primitive are determined by computing the bounding
// box of the projected rect of the backdrop-filter element onto the backdrop.
let prim_data = &mut data_stores.backdrop[data_handle];
let spatial_node_index = prim_data.kind.spatial_node_index;
// We cannot use the relative transform between the backdrop and the element because
// that doesn't take into account any projection transforms that both spatial nodes are children of.
// Instead, we first project from the element to the world space and get a flattened 2D bounding rect
// in the screen space, we then map this rect from the world space to the backdrop space to get the
// proper bounding box where the backdrop-filter needs to be processed.
let prim_to_world_mapper = SpaceMapper::new_with_target(
ROOT_SPATIAL_NODE_INDEX,
spatial_node_index,
LayoutRect::max_rect(),
frame_context.clip_scroll_tree,
);
let backdrop_to_world_mapper = SpaceMapper::new_with_target(
ROOT_SPATIAL_NODE_INDEX,
prim_instance.spatial_node_index,
LayoutRect::max_rect(),
frame_context.clip_scroll_tree,
);
// First map to the screen and get a flattened rect
let prim_rect = prim_to_world_mapper.map(&prim_data.kind.border_rect).unwrap_or_else(LayoutRect::zero);
// Backwards project the flattened rect onto the backdrop
let prim_rect = backdrop_to_world_mapper.unmap(&prim_rect).unwrap_or_else(LayoutRect::zero);
// TODO(aosmond): Is this safe? Updating the primitive size during
// frame building is usually problematic since scene building will cache
// the primitive information in the GPU already.
prim_instance.prim_origin = prim_rect.origin;
prim_data.common.prim_size = prim_rect.size;
prim_instance.local_clip_rect = prim_rect;
// Update the cluster bounding rect now that we have the backdrop rect.
let cluster = &mut self.prim_list.clusters[prim_instance.cluster_index.0 as usize];
cluster.bounding_rect = cluster.bounding_rect.union(&prim_rect);
}
_ => {
panic!("BUG: unexpected deferred primitive kind for cluster updates");
}
}
}
for cluster in &mut self.prim_list.clusters {
// Skip the cluster if backface culled.
if !cluster.is_backface_visible {
@ -3563,18 +3502,6 @@ impl PicturePrimitive {
// This inflaction factor is to be applied to the surface itself.
if self.options.inflate_if_required {
surface.rect = raster_config.composite_mode.inflate_picture_rect(surface.rect, surface.inflation_factor);
// The picture's local rect is calculated as the union of the
// snapped primitive rects, which should result in a snapped
// local rect, unless it was inflated.
let snap_surface_to_raster = SpaceSnapper::new_with_target(
surface.raster_spatial_node_index,
self.spatial_node_index,
surface.device_pixel_scale,
frame_context.clip_scroll_tree,
);
surface.rect = snap_surface_to_raster.snap_rect(&surface.rect);
}
let mut surface_rect = surface.rect * Scale::new(1.0);
@ -3583,6 +3510,11 @@ impl PicturePrimitive {
let surface_index = state.pop_surface();
debug_assert_eq!(surface_index, raster_config.surface_index);
// Snapping may change the local rect slightly, and as such should just be
// considered an estimated size for determining if we need raster roots and
// preparing the tile cache.
self.unsnapped_local_rect = surface_rect;
// Check if any of the surfaces can't be rasterized in local space but want to.
if raster_config.establishes_raster_root {
if surface_rect.size.width > MAX_SURFACE_SIZE ||
@ -3593,8 +3525,6 @@ impl PicturePrimitive {
}
}
self.local_rect = surface_rect;
// Drop shadows draw both a content and shadow rect, so need to expand the local
// rect of any surfaces to be composited in parent surfaces correctly.
match raster_config.composite_mode {
@ -3663,14 +3593,14 @@ impl PicturePrimitive {
// Basic brush primitive header is (see end of prepare_prim_for_render_inner in prim_store.rs)
// [brush specific data]
// [segment_rect, segment data]
let shadow_rect = self.local_rect.translate(shadow.offset);
let shadow_rect = self.snapped_local_rect.translate(shadow.offset);
// ImageBrush colors
request.push(shadow.color.premultiplied());
request.push(PremultipliedColorF::WHITE);
request.push([
self.local_rect.size.width,
self.local_rect.size.height,
self.snapped_local_rect.size.width,
self.snapped_local_rect.size.height,
0.0,
0.0,
]);

View File

@ -22,7 +22,7 @@ use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureCont
use crate::frame_builder::{FrameVisibilityContext, FrameVisibilityState};
use crate::glyph_rasterizer::GlyphKey;
use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest, ToGpuBlocks};
use crate::gpu_types::{BrushFlags};
use crate::gpu_types::{BrushFlags, SnapOffsets};
use crate::image::{Repetition};
use crate::intern;
use crate::internal_types::PlaneSplitAnchor;
@ -52,7 +52,7 @@ use std::{cmp, fmt, hash, ops, u32, usize, mem};
use std::sync::atomic::{AtomicUsize, Ordering};
use crate::storage;
use crate::texture_cache::TEXTURE_REGION_DIMENSIONS;
use crate::util::{MatrixHelpers, MaxRect, Recycler, ScaleOffset, RectHelpers};
use crate::util::{MatrixHelpers, MaxRect, Recycler};
use crate::util::{clamp_to_scale_factor, pack_as_float, project_rect, raster_rect_to_device_pixels};
use crate::internal_types::{LayoutPrimitiveInfo, Filter};
use smallvec::SmallVec;
@ -132,91 +132,6 @@ impl PrimitiveOpacity {
}
}
#[derive(Clone, Debug)]
pub struct SpaceSnapper {
pub ref_spatial_node_index: SpatialNodeIndex,
current_target_spatial_node_index: SpatialNodeIndex,
snapping_transform: Option<ScaleOffset>,
pub device_pixel_scale: DevicePixelScale,
}
impl SpaceSnapper {
pub fn new(
ref_spatial_node_index: SpatialNodeIndex,
device_pixel_scale: DevicePixelScale,
) -> Self {
SpaceSnapper {
ref_spatial_node_index,
current_target_spatial_node_index: SpatialNodeIndex::INVALID,
snapping_transform: None,
device_pixel_scale,
}
}
pub fn new_with_target(
ref_spatial_node_index: SpatialNodeIndex,
target_node_index: SpatialNodeIndex,
device_pixel_scale: DevicePixelScale,
clip_scroll_tree: &ClipScrollTree,
) -> Self {
let mut snapper = SpaceSnapper {
ref_spatial_node_index,
current_target_spatial_node_index: SpatialNodeIndex::INVALID,
snapping_transform: None,
device_pixel_scale,
};
snapper.set_target_spatial_node(target_node_index, clip_scroll_tree);
snapper
}
pub fn set_target_spatial_node(
&mut self,
target_node_index: SpatialNodeIndex,
clip_scroll_tree: &ClipScrollTree,
) {
if target_node_index == self.current_target_spatial_node_index {
return
}
let ref_spatial_node = &clip_scroll_tree.spatial_nodes[self.ref_spatial_node_index.0 as usize];
let target_spatial_node = &clip_scroll_tree.spatial_nodes[target_node_index.0 as usize];
self.current_target_spatial_node_index = target_node_index;
self.snapping_transform = match (ref_spatial_node.snapping_transform, target_spatial_node.snapping_transform) {
(Some(ref ref_scale_offset), Some(ref target_scale_offset)) => {
Some(ref_scale_offset
.inverse()
.accumulate(target_scale_offset)
.scale(self.device_pixel_scale.0))
}
_ => None,
};
}
pub fn snap_rect<F>(&self, rect: &Rect<f32, F>) -> Rect<f32, F> where F: fmt::Debug {
debug_assert!(self.current_target_spatial_node_index != SpatialNodeIndex::INVALID);
match self.snapping_transform {
Some(ref scale_offset) => {
let snapped_device_rect : DeviceRect = scale_offset.map_rect(rect).snap();
scale_offset.unmap_rect(&snapped_device_rect)
}
None => *rect,
}
}
pub fn snap_size<F>(&self, size: &Size2D<f32, F>) -> Size2D<f32, F> where F: fmt::Debug {
debug_assert!(self.current_target_spatial_node_index != SpatialNodeIndex::INVALID);
match self.snapping_transform {
Some(ref scale_offset) => {
let rect = Rect::<f32, F>::new(Point2D::<f32, F>::zero(), *size);
let snapped_device_rect : DeviceRect = scale_offset.map_rect(&rect).snap();
scale_offset.unmap_rect(&snapped_device_rect).size
}
None => *size,
}
}
}
#[derive(Debug, Clone)]
pub struct SpaceMapper<F, T> {
@ -1018,6 +933,7 @@ impl BrushSegment {
frame_state: &mut FrameBuildingState,
clip_data_store: &mut ClipDataStore,
unclipped: &DeviceRect,
prim_snap_offsets: SnapOffsets,
device_pixel_scale: DevicePixelScale,
) -> ClipMaskKind {
match clip_chain {
@ -1040,8 +956,9 @@ impl BrushSegment {
// Get a minimal device space rect, clipped to the screen that we
// need to allocate for the clip mask, as well as interpolated
// snap offsets.
let device_rect = match get_clipped_device_rect(
let (device_rect, snap_offsets) = match get_clipped_device_rect(
unclipped,
prim_snap_offsets,
&pic_state.map_raster_to_world,
segment_world_rect,
device_pixel_scale,
@ -1061,6 +978,7 @@ impl BrushSegment {
frame_state.resource_cache,
frame_state.render_tasks,
clip_data_store,
snap_offsets,
device_pixel_scale,
frame_context.fb_config,
);
@ -1518,6 +1436,18 @@ pub struct PrimitiveVisibility {
/// The current combined local clip for this primitive, from
/// the primitive local clip above and the current clip chain.
pub combined_local_clip_rect: LayoutRect,
/// The snap offsets in device space for this primitive. They are
/// generated based on the visible rect, which is the local rect
/// clipped by the combined local clip for most primitives, or
/// just the local rect for pictures.
pub snap_offsets: SnapOffsets,
/// The snap offsets in device space for the drop shadow for
/// picture primitives, if applicable. Similar to snap offsets,
/// they are generated based on the local rect translated by the
/// drop shadow offset.
pub shadow_snap_offsets: SnapOffsets,
}
#[derive(Clone, Debug)]
@ -1878,7 +1808,7 @@ impl PrimitiveStore {
world_culling_rect: &WorldRect,
frame_context: &FrameVisibilityContext,
frame_state: &mut FrameVisibilityState,
) {
) -> Option<PictureRect> {
let (mut prim_list, surface_index, apply_local_clip_rect, world_culling_rect, is_composite) = {
let pic = &mut self.pictures[pic_index.0];
let mut world_culling_rect = *world_culling_rect;
@ -1898,7 +1828,7 @@ impl PrimitiveStore {
// relative transforms have changed, which means we need to
// re-map the dependencies of any child primitives.
world_culling_rect = tile_cache.pre_update(
PictureRect::from_untyped(&pic.local_rect.to_untyped()),
PictureRect::from_untyped(&pic.unsnapped_local_rect.to_untyped()),
surface_index,
frame_context,
frame_state,
@ -1932,13 +1862,19 @@ impl PrimitiveStore {
frame_context.clip_scroll_tree,
);
let mut map_local_to_raster = SpaceMapper::new(
surface.raster_spatial_node_index,
RasterRect::max_rect(),
);
let mut surface_rect = PictureRect::zero();
for prim_instance in &mut prim_list.prim_instances {
prim_instance.reset();
if prim_instance.is_chased() {
#[cfg(debug_assertions)] // needed for ".id" part
println!("\tpreparing {:?} in {:?}", prim_instance.id, pic_index);
println!("\t{:?}", prim_instance.kind);
}
// Get the cluster and see if is visible
@ -1954,7 +1890,12 @@ impl PrimitiveStore {
frame_context.clip_scroll_tree,
);
let (is_passthrough, prim_local_rect, prim_shadow_rect) = match prim_instance.kind {
map_local_to_raster.set_target_spatial_node(
prim_instance.spatial_node_index,
frame_context.clip_scroll_tree,
);
let (is_passthrough, snap_to_visible, prim_local_rect, prim_shadow_rect) = match prim_instance.kind {
PrimitiveInstanceKind::PushClipChain => {
frame_state.clip_chain_stack.push_clip(
prim_instance.clip_chain_id,
@ -1976,7 +1917,7 @@ impl PrimitiveStore {
frame_state.clip_store,
);
self.update_visibility(
let pic_surface_rect = self.update_visibility(
pic_index,
surface_index,
&world_culling_rect,
@ -1986,6 +1927,8 @@ impl PrimitiveStore {
frame_state.clip_chain_stack.pop_clip();
let pic = &self.pictures[pic_index.0];
// The local rect of pictures is calculated dynamically based on
// the content of children, which may move due to the spatial
// node they are attached to. Other parts of the code (such as
@ -1995,22 +1938,74 @@ impl PrimitiveStore {
// this way. In future, we could perhaps just store the
// size in the picture primitive, to that there isn't
// any duplicated data.
let pic = &self.pictures[pic_index.0];
prim_instance.prim_origin = pic.local_rect.origin;
prim_instance.prim_origin = pic.snapped_local_rect.origin;
let shadow_rect = if let Some(RasterConfig { composite_mode: PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)), .. }) = pic.raster_config {
// If we have a drop shadow filter, we also need to include the shadow in
// our local rect for the purpose of calculating the size of the picture.
let mut rect = LayoutRect::zero();
for shadow in shadows {
rect = rect.union(&pic.local_rect.translate(shadow.offset));
let shadow_rect = match pic.raster_config {
Some(ref rc) => match rc.composite_mode {
// If we have a drop shadow filter, we also need to include the shadow in
// our local rect for the purpose of calculating the size of the picture.
PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
let mut rect = LayoutRect::zero();
for shadow in shadows {
rect = rect.union(&pic.snapped_local_rect.translate(shadow.offset));
}
rect
}
_ => LayoutRect::zero(),
}
None => {
if let Some(ref rect) = pic_surface_rect {
surface_rect = surface_rect.union(rect);
}
LayoutRect::zero()
}
rect
} else {
LayoutRect::zero()
};
(pic.raster_config.is_none(), pic.local_rect, shadow_rect)
if prim_instance.is_chased() {
if pic.unsnapped_local_rect != pic.snapped_local_rect {
println!("\tsnapped from {:?} to {:?}", pic.unsnapped_local_rect, pic.snapped_local_rect);
}
}
(pic.raster_config.is_none(), false, pic.snapped_local_rect, shadow_rect)
}
PrimitiveInstanceKind::Backdrop { data_handle } => {
// The actual size and clip rect of this primitive are determined by computing the bounding
// box of the projected rect of the backdrop-filter element onto the backdrop.
let prim_data = &mut frame_state.data_stores.backdrop[data_handle];
let spatial_node_index = prim_data.kind.spatial_node_index;
// We cannot use the relative transform between the backdrop and the element because
// that doesn't take into account any projection transforms that both spatial nodes are children of.
// Instead, we first project from the element to the world space and get a flattened 2D bounding rect
// in the screen space, we then map this rect from the world space to the backdrop space to get the
// proper bounding box where the backdrop-filter needs to be processed.
let prim_to_world_mapper = SpaceMapper::new_with_target(
ROOT_SPATIAL_NODE_INDEX,
spatial_node_index,
LayoutRect::max_rect(),
frame_context.clip_scroll_tree,
);
let backdrop_to_world_mapper = SpaceMapper::new_with_target(
ROOT_SPATIAL_NODE_INDEX,
prim_instance.spatial_node_index,
LayoutRect::max_rect(),
frame_context.clip_scroll_tree,
);
// First map to the screen and get a flattened rect
let prim_rect = prim_to_world_mapper.map(&prim_data.kind.border_rect).unwrap_or_else(LayoutRect::zero);
// Backwards project the flattened rect onto the backdrop
let prim_rect = backdrop_to_world_mapper.unmap(&prim_rect).unwrap_or_else(LayoutRect::zero);
prim_instance.prim_origin = prim_rect.origin;
prim_data.common.prim_size = prim_rect.size;
prim_instance.local_clip_rect = prim_rect;
(false, true, prim_rect, LayoutRect::zero())
}
_ => {
let prim_data = &frame_state.data_stores.as_common_data(&prim_instance);
@ -2020,7 +2015,7 @@ impl PrimitiveStore {
prim_data.prim_size,
);
(false, prim_rect, LayoutRect::zero())
(false, true, prim_rect, LayoutRect::zero())
}
};
@ -2033,6 +2028,8 @@ impl PrimitiveStore {
clip_chain: ClipChainInstance::empty(),
clip_task_index: ClipTaskIndex::INVALID,
combined_local_clip_rect: LayoutRect::zero(),
snap_offsets: SnapOffsets::empty(),
shadow_snap_offsets: SnapOffsets::empty(),
visibility_mask: PrimitiveVisibilityMask::empty(),
}
);
@ -2175,6 +2172,56 @@ impl PrimitiveStore {
continue;
}
// All pictures must snap to their primitive rect instead of the
// visible rect like most primitives. This is because the picture's
// visible rect includes the effect of the picture's clip rect,
// which was not considered by the picture's children. The primitive
// rect however is simply the union of the visible rect of the
// children, which they snapped to, which is precisely what we also
// need to snap to in order to be consistent.
let visible_rect = if snap_to_visible {
match combined_local_clip_rect.intersection(&prim_local_rect) {
Some(r) => r,
None => {
if prim_instance.is_chased() {
println!("\tculled for zero visible rectangle");
}
prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
continue;
}
}
} else {
prim_local_rect
};
// This is how primitives get snapped. In general, snapping a picture's
// visible rect here will have no effect, but if it is rasterized in its
// own space, or it has a blur or drop shadow effect applied, it may
// provide a snapping offset.
let (snapped_visible_rect, snap_offsets) = get_snapped_rect(
visible_rect,
&map_local_to_raster,
surface.device_pixel_scale,
).unwrap_or((visible_rect, SnapOffsets::empty()));
let (combined_visible_rect, shadow_snap_offsets) = if !prim_shadow_rect.is_empty() {
let (snapped_shadow_rect, shadow_snap_offsets) = get_snapped_rect(
prim_shadow_rect,
&map_local_to_raster,
surface.device_pixel_scale,
).unwrap_or((prim_shadow_rect, SnapOffsets::empty()));
(snapped_visible_rect.union(&snapped_shadow_rect), shadow_snap_offsets)
} else {
(snapped_visible_rect, SnapOffsets::empty())
};
// Include the snapped primitive/picture local rect, including any shadows,
// in the area affected by the surface.
if let Some(rect) = map_local_to_surface.map(&combined_visible_rect) {
surface_rect = surface_rect.union(&rect);
}
// When the debug display is enabled, paint a colored rectangle around each
// primitive.
if frame_context.debug_flags.contains(::api::DebugFlags::PRIMITIVE_DBG) {
@ -2211,6 +2258,8 @@ impl PrimitiveStore {
clip_chain,
clip_task_index: ClipTaskIndex::INVALID,
combined_local_clip_rect,
snap_offsets,
shadow_snap_offsets,
visibility_mask: PrimitiveVisibilityMask::empty(),
}
);
@ -2241,18 +2290,55 @@ impl PrimitiveStore {
// TODO(gw): In future, if we support specifying a flag which gets the
// stretch size from the segment rect in the shaders, we can
// remove this invalidation here completely.
if let Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) = pic.raster_config {
let mut tile_cache = frame_state.tile_cache.take().unwrap();
if let Some(ref raster_config) = pic.raster_config {
// Inflate the local bounding rect if required by the filter effect.
// This inflaction factor is to be applied to the surface itself.
if pic.options.inflate_if_required {
surface_rect = raster_config.composite_mode.inflate_picture_rect(surface_rect, surface.inflation_factor);
}
// Build the dirty region(s) for this tile cache.
tile_cache.post_update(
frame_state.resource_cache,
frame_state.gpu_cache,
frame_context,
frame_state.scratch,
// Layout space for the picture is picture space from the
// perspective of its child primitives.
let pic_local_rect = surface_rect * Scale::new(1.0);
if pic.snapped_local_rect != pic_local_rect {
match raster_config.composite_mode {
PictureCompositeMode::Filter(Filter::DropShadows(..)) => {
for handle in &pic.extra_gpu_data_handles {
frame_state.gpu_cache.invalidate(handle);
}
}
_ => {}
}
// Invalidate any segments built for this picture, since the local
// rect has changed.
pic.segments_are_valid = false;
pic.snapped_local_rect = pic_local_rect;
}
if let PictureCompositeMode::TileCache { .. } = raster_config.composite_mode {
let mut tile_cache = frame_state.tile_cache.take().unwrap();
// Build the dirty region(s) for this tile cache.
tile_cache.post_update(
frame_state.resource_cache,
frame_state.gpu_cache,
frame_context,
frame_state.scratch,
);
pic.tile_cache = Some(tile_cache);
}
None
} else {
let parent_surface = &frame_context.surfaces[parent_surface_index.0 as usize];
let map_surface_to_parent_surface = SpaceMapper::new_with_target(
parent_surface.surface_spatial_node_index,
surface.surface_spatial_node_index,
PictureRect::max_rect(),
frame_context.clip_scroll_tree,
);
pic.tile_cache = Some(tile_cache);
map_surface_to_parent_surface.map(&surface_rect)
}
}
@ -3230,7 +3316,7 @@ impl PrimitiveStore {
splitter,
frame_context.clip_scroll_tree,
prim_instance.spatial_node_index,
pic.local_rect,
pic.snapped_local_rect,
&prim_info.combined_local_clip_rect,
frame_state.current_dirty_region().combined,
plane_split_anchor,
@ -3540,15 +3626,13 @@ impl<'a> GpuDataRequest<'a> {
impl PrimitiveInstance {
fn build_segments_if_needed(
&mut self,
prim_info: &PrimitiveVisibility,
prim_clip_chain: &ClipChainInstance,
frame_state: &mut FrameBuildingState,
prim_store: &mut PrimitiveStore,
data_stores: &DataStores,
segments_store: &mut SegmentStorage,
segment_instances_store: &mut SegmentInstanceStorage,
) {
let prim_clip_chain = &prim_info.clip_chain;
// Usually, the primitive rect can be found from information
// in the instance and primitive template.
let mut prim_local_rect = LayoutRect::new(
@ -3592,7 +3676,7 @@ impl PrimitiveInstance {
// Override the prim local rect with the dynamically calculated
// local rect for the picture.
prim_local_rect = pic.local_rect;
prim_local_rect = pic.snapped_local_rect;
segment_instance_index
} else {
@ -3779,6 +3863,7 @@ impl PrimitiveInstance {
frame_state,
&mut data_stores.clip,
unclipped,
prim_info.snap_offsets,
device_pixel_scale,
);
clip_mask_instances.push(clip_mask_kind);
@ -3799,7 +3884,10 @@ impl PrimitiveInstance {
let segment_clip_chain = frame_state
.clip_store
.build_clip_chain_instance(
segment.local_rect.translate(self.prim_origin.to_vector()),
segment.local_rect.translate(LayoutVector2D::new(
self.prim_origin.x,
self.prim_origin.y,
)),
&pic_state.map_local_to_pic,
&pic_state.map_pic_to_world,
&frame_context.clip_scroll_tree,
@ -3822,6 +3910,7 @@ impl PrimitiveInstance {
frame_state,
&mut data_stores.clip,
unclipped,
prim_info.snap_offsets,
device_pixel_scale,
);
clip_mask_instances.push(clip_mask_kind);
@ -3860,7 +3949,7 @@ impl PrimitiveInstance {
};
self.build_segments_if_needed(
&prim_info,
&prim_info.clip_chain,
frame_state,
prim_store,
data_stores,
@ -3894,8 +3983,9 @@ impl PrimitiveInstance {
// Get a minimal device space rect, clipped to the screen that we
// need to allocate for the clip mask, as well as interpolated
// snap offsets.
if let Some(device_rect) = get_clipped_device_rect(
if let Some((device_rect, snap_offsets)) = get_clipped_device_rect(
&unclipped,
prim_info.snap_offsets,
&pic_state.map_raster_to_world,
prim_info.clipped_world_rect,
device_pixel_scale,
@ -3909,6 +3999,7 @@ impl PrimitiveInstance {
frame_state.resource_cache,
frame_state.render_tasks,
&mut data_stores.clip,
snap_offsets,
device_pixel_scale,
frame_context.fb_config,
);
@ -3931,6 +4022,80 @@ impl PrimitiveInstance {
}
}
/// Mimics the GLSL mix() function.
fn mix(x: f32, y: f32, a: f32) -> f32 {
x * (1.0 - a) + y * a
}
/// Given a point within a local rectangle, and the device space corners
/// of a snapped primitive, return the snap offsets.
fn compute_snap_offset_impl<PixelSpace>(
reference_pos: Point2D<f32, PixelSpace>,
reference_rect: Rect<f32, PixelSpace>,
prim_top_left: DevicePoint,
prim_bottom_right: DevicePoint,
) -> DeviceVector2D {
let normalized_snap_pos = Point2D::<f32, PixelSpace>::new(
(reference_pos.x - reference_rect.origin.x) / reference_rect.size.width,
(reference_pos.y - reference_rect.origin.y) / reference_rect.size.height,
);
let top_left = DeviceVector2D::new(
(prim_top_left.x + 0.5).floor() - prim_top_left.x,
(prim_top_left.y + 0.5).floor() - prim_top_left.y,
);
let bottom_right = DeviceVector2D::new(
(prim_bottom_right.x + 0.5).floor() - prim_bottom_right.x,
(prim_bottom_right.y + 0.5).floor() - prim_bottom_right.y,
);
DeviceVector2D::new(
mix(top_left.x, bottom_right.x, normalized_snap_pos.x),
mix(top_left.y, bottom_right.y, normalized_snap_pos.y),
)
}
/// Given the snapping offsets for a primitive rectangle, recompute
/// the snapping offsets to be relative to given local rectangle.
/// This *must* exactly match the logic in the GLSL
/// compute_snap_offset function.
pub fn recompute_snap_offsets<PixelSpace>(
local_rect: Rect<f32, PixelSpace>,
prim_rect: Rect<f32, PixelSpace>,
snap_offsets: SnapOffsets,
) -> SnapOffsets
{
if prim_rect.is_empty() || snap_offsets.is_empty() {
return SnapOffsets::empty();
}
let normalized_top_left = Point2D::<f32, PixelSpace>::new(
(local_rect.origin.x - prim_rect.origin.x) / prim_rect.size.width,
(local_rect.origin.y - prim_rect.origin.y) / prim_rect.size.height,
);
let normalized_bottom_right = Point2D::<f32, PixelSpace>::new(
(local_rect.origin.x + local_rect.size.width - prim_rect.origin.x) / prim_rect.size.width,
(local_rect.origin.y + local_rect.size.height - prim_rect.origin.y) / prim_rect.size.height,
);
let top_left = DeviceVector2D::new(
mix(snap_offsets.top_left.x, snap_offsets.bottom_right.x, normalized_top_left.x),
mix(snap_offsets.top_left.y, snap_offsets.bottom_right.y, normalized_top_left.y),
);
let bottom_right = DeviceVector2D::new(
mix(snap_offsets.top_left.x, snap_offsets.bottom_right.x, normalized_bottom_right.x),
mix(snap_offsets.top_left.y, snap_offsets.bottom_right.y, normalized_bottom_right.y),
);
SnapOffsets {
top_left,
bottom_right,
}
}
/// Retrieve the exact unsnapped device space rectangle for a primitive.
fn get_unclipped_device_rect(
prim_rect: PictureRect,
@ -3949,10 +4114,11 @@ fn get_unclipped_device_rect(
/// scale per-raster-root.
fn get_clipped_device_rect(
unclipped: &DeviceRect,
prim_snap_offsets: SnapOffsets,
map_to_world: &SpaceMapper<RasterPixel, WorldPixel>,
prim_bounding_rect: WorldRect,
device_pixel_scale: DevicePixelScale,
) -> Option<DeviceIntRect> {
) -> Option<(DeviceIntRect, SnapOffsets)> {
let unclipped_raster_rect = {
let world_rect = *unclipped * Scale::new(1.0);
let raster_rect = world_rect * device_pixel_scale.inv();
@ -3977,7 +4143,28 @@ fn get_clipped_device_rect(
device_pixel_scale,
);
Some(clipped.to_i32())
let fx0 = (clipped.origin.x - unclipped.origin.x) / unclipped.size.width;
let fy0 = (clipped.origin.y - unclipped.origin.y) / unclipped.size.height;
let fx1 = (clipped.origin.x + clipped.size.width - unclipped.origin.x) / unclipped.size.width;
let fy1 = (clipped.origin.y + clipped.size.height - unclipped.origin.y) / unclipped.size.height;
let top_left = DeviceVector2D::new(
mix(prim_snap_offsets.top_left.x, prim_snap_offsets.bottom_right.x, fx0),
mix(prim_snap_offsets.top_left.y, prim_snap_offsets.bottom_right.y, fy0),
);
let bottom_right = DeviceVector2D::new(
mix(prim_snap_offsets.top_left.x, prim_snap_offsets.bottom_right.x, fx1),
mix(prim_snap_offsets.top_left.y, prim_snap_offsets.bottom_right.y, fy1),
);
let snap_offsets = SnapOffsets {
top_left,
bottom_right,
};
Some((clipped.to_i32(), snap_offsets))
}
pub fn get_raster_rects(
@ -4015,6 +4202,61 @@ pub fn get_raster_rects(
Some((clipped.to_i32(), unclipped))
}
/// Snap the given rect in raster space if the transform is
/// axis-aligned. It return the snapped rect transformed back into the
/// given pixel space, and the snap offsets in device space.
pub fn get_snapped_rect<PixelSpace>(
prim_rect: Rect<f32, PixelSpace>,
map_to_raster: &SpaceMapper<PixelSpace, RasterPixel>,
device_pixel_scale: DevicePixelScale,
) -> Option<(Rect<f32, PixelSpace>, SnapOffsets)> where PixelSpace: fmt::Debug {
let is_axis_aligned = match map_to_raster.kind {
CoordinateSpaceMapping::Local |
CoordinateSpaceMapping::ScaleOffset(..) => true,
CoordinateSpaceMapping::Transform(ref transform) => transform.preserves_2d_axis_alignment(),
};
if is_axis_aligned {
let raster_rect = map_to_raster.map(&prim_rect)?;
let device_rect = {
let world_rect = raster_rect * Scale::new(1.0);
world_rect * device_pixel_scale
};
let top_left = compute_snap_offset_impl(
prim_rect.origin,
prim_rect,
device_rect.origin,
device_rect.bottom_right(),
);
let bottom_right = compute_snap_offset_impl(
prim_rect.bottom_right(),
prim_rect,
device_rect.origin,
device_rect.bottom_right(),
);
let snap_offsets = SnapOffsets {
top_left,
bottom_right,
};
let snapped_device_rect = DeviceRect::new(
device_rect.origin + top_left,
device_rect.size + (bottom_right - top_left).to_size()
);
let snapped_world_rect = snapped_device_rect / device_pixel_scale;
let snapped_raster_rect = snapped_world_rect * Scale::new(1.0);
let snapped_prim_rect = map_to_raster.unmap(&snapped_raster_rect)?;
Some((snapped_prim_rect, snap_offsets))
} else {
None
}
}
/// Get the inline (horizontal) and block (vertical) sizes
/// for a given line decoration.
pub fn get_line_decoration_sizes(

View File

@ -84,13 +84,6 @@ impl DocumentView {
self.pinch_zoom_factor
)
}
pub fn accumulated_scale_factor_for_snapping(&self) -> DevicePixelScale {
DevicePixelScale::new(
self.device_pixel_ratio *
self.page_zoom_factor
)
}
}
#[derive(Copy, Clone, Hash, MallocSizeOf, PartialEq, PartialOrd, Debug, Eq, Ord)]
@ -589,7 +582,6 @@ impl Document {
self.clip_scroll_tree.update_tree(
pan,
accumulated_scale_factor,
&self.dynamic_properties,
);
@ -1758,8 +1750,6 @@ impl RenderBackend {
config.serialize(doc.frame_builder.as_ref().unwrap(), file_name);
let file_name = format!("scratch-{}-{}", id.namespace_id.0, id.id);
config.serialize(&doc.scratch, file_name);
let file_name = format!("properties-{}-{}", id.namespace_id.0, id.id);
config.serialize(&doc.dynamic_properties, file_name);
let file_name = format!("render-tasks-{}-{}.svg", id.namespace_id.0, id.id);
let mut svg_file = fs::File::create(&config.file_path(file_name, "svg"))
.expect("Failed to open the SVG file.");

View File

@ -663,6 +663,7 @@ impl RenderTarget for AlphaRenderTarget {
task_info.actual_rect,
&ctx.screen_world_rect,
task_info.device_pixel_scale,
task_info.snap_offsets,
target_rect.origin.to_f32(),
task_info.actual_rect.origin.to_f32(),
);

View File

@ -14,7 +14,7 @@ use crate::filterdata::SFilterData;
use crate::frame_builder::FrameBuilderConfig;
use crate::freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
use crate::gpu_types::{BorderInstance, ImageSource, UvRectKind};
use crate::gpu_types::{BorderInstance, ImageSource, UvRectKind, SnapOffsets};
use crate::internal_types::{CacheTextureId, FastHashMap, LayerIndex, SavedTargetIndex, TextureSource};
use crate::prim_store::{PictureIndex, PrimitiveVisibilityMask};
use crate::prim_store::image::ImageCacheKey;
@ -125,6 +125,7 @@ pub struct CacheMaskTask {
pub actual_rect: DeviceIntRect,
pub root_spatial_node_index: SpatialNodeIndex,
pub clip_node_range: ClipNodeRange,
pub snap_offsets: SnapOffsets,
pub device_pixel_scale: DevicePixelScale,
}
@ -522,6 +523,7 @@ impl RenderTask {
resource_cache: &mut ResourceCache,
render_tasks: &mut RenderTaskGraph,
clip_data_store: &mut ClipDataStore,
snap_offsets: SnapOffsets,
device_pixel_scale: DevicePixelScale,
fb_config: &FrameBuilderConfig,
) -> Self {
@ -615,6 +617,7 @@ impl RenderTask {
actual_rect: outer_rect,
clip_node_range,
root_spatial_node_index,
snap_offsets,
device_pixel_scale,
}),
clear_mode,

View File

@ -620,6 +620,11 @@ pub(crate) mod desc {
count: 4,
kind: VertexAttributeKind::F32,
},
VertexAttribute {
name: "aClipSnapOffsets",
count: 4,
kind: VertexAttributeKind::F32,
},
VertexAttribute {
name: "aClipOrigins",
count: 4,

View File

@ -7,9 +7,9 @@ use api::{ExternalScrollId, PipelineId, PropertyBinding, PropertyBindingId, Refe
use api::{TransformStyle, ScrollSensitivity, StickyOffsetBounds};
use api::units::*;
use crate::clip_scroll_tree::{CoordinateSystem, CoordinateSystemId, SpatialNodeIndex, TransformUpdateState};
use euclid::{Scale, SideOffsets2D};
use euclid::SideOffsets2D;
use crate::scene::SceneProperties;
use crate::util::{LayoutFastTransform, MatrixHelpers, ScaleOffset, TransformedRectKind, VectorHelpers};
use crate::util::{LayoutFastTransform, MatrixHelpers, ScaleOffset, TransformedRectKind};
#[derive(Clone, Debug)]
pub enum SpatialNodeType {
@ -38,10 +38,6 @@ pub struct SpatialNode {
/// Content scale/offset relative to the coordinate system.
pub content_transform: ScaleOffset,
/// Snapping scale/offset relative to the coordinate system. If None, then
/// we should not snap entities bound to this spatial node.
pub snapping_transform: Option<ScaleOffset>,
/// The axis-aligned coordinate system id of this node.
pub coordinate_system_id: CoordinateSystemId,
@ -106,23 +102,6 @@ fn compute_offset_from(
offset
}
/// Snap an offset to be incorporated into a transform, where the local space
/// may be considered the world space. We convert from world space to device
/// space using the global device pixel scale, which may not always be correct
/// if there are intermediate surfaces used, however those are either cases
/// where snapping is not important (e.g. has perspective or is not axis
/// aligned), or an edge case (e.g. SVG filters) which we can accept
/// imperfection for now.
fn snap_offset(
offset: LayoutVector2D,
global_device_pixel_scale: DevicePixelScale,
) -> LayoutVector2D {
let world_offset = offset * Scale::new(1.0);
let snapped_device_offset = (world_offset * global_device_pixel_scale).snap();
let snapped_world_offset = snapped_device_offset / global_device_pixel_scale;
snapped_world_offset * Scale::new(1.0)
}
impl SpatialNode {
pub fn new(
pipeline_id: PipelineId,
@ -132,7 +111,6 @@ impl SpatialNode {
SpatialNode {
viewport_transform: ScaleOffset::identity(),
content_transform: ScaleOffset::identity(),
snapping_transform: None,
coordinate_system_id: CoordinateSystemId(0),
transform_kind: TransformedRectKind::AxisAligned,
parent: parent_index,
@ -265,7 +243,6 @@ impl SpatialNode {
&mut self,
state: &mut TransformUpdateState,
coord_systems: &mut Vec<CoordinateSystem>,
global_device_pixel_scale: DevicePixelScale,
scene_properties: &SceneProperties,
previous_spatial_nodes: &[SpatialNode],
) {
@ -276,7 +253,7 @@ impl SpatialNode {
return;
}
self.update_transform(state, coord_systems, global_device_pixel_scale, scene_properties, previous_spatial_nodes);
self.update_transform(state, coord_systems, scene_properties, previous_spatial_nodes);
//TODO: remove the field entirely?
self.transform_kind = if self.coordinate_system_id.0 == 0 {
TransformedRectKind::AxisAligned
@ -306,7 +283,6 @@ impl SpatialNode {
&mut self,
state: &mut TransformUpdateState,
coord_systems: &mut Vec<CoordinateSystem>,
global_device_pixel_scale: DevicePixelScale,
scene_properties: &SceneProperties,
previous_spatial_nodes: &[SpatialNode],
) {
@ -349,7 +325,7 @@ impl SpatialNode {
// between our reference frame and this node. Finally, we also include
// whatever local transformation this reference frame provides.
let relative_transform = resolved_transform
.post_translate(snap_offset(state.parent_accumulated_scroll_offset, global_device_pixel_scale))
.post_translate(state.parent_accumulated_scroll_offset)
.to_transform()
.with_destination::<LayoutPixel>();
@ -424,13 +400,13 @@ impl SpatialNode {
// provided by our own sticky positioning.
let accumulated_offset = state.parent_accumulated_scroll_offset + sticky_offset;
self.viewport_transform = state.coordinate_system_relative_scale_offset
.offset(snap_offset(accumulated_offset, global_device_pixel_scale).to_untyped());
.offset(accumulated_offset.to_untyped());
// The transformation for any content inside of us is the viewport transformation, plus
// whatever scrolling offset we supply as well.
let added_offset = accumulated_offset + self.scroll_offset();
self.content_transform = state.coordinate_system_relative_scale_offset
.offset(snap_offset(added_offset, global_device_pixel_scale).to_untyped());
.offset(added_offset.to_untyped());
if let SpatialNodeType::StickyFrame(ref mut info) = self.node_type {
info.current_offset = sticky_offset;
@ -659,55 +635,6 @@ impl SpatialNode {
}
}
/// Updates the snapping transform.
pub fn update_snapping(
&mut self,
parent: Option<&SpatialNode>,
) {
// Reset in case of an early return.
self.snapping_transform = None;
// We need to incorporate the parent scale/offset with the child.
// If the parent does not have a scale/offset, then we know we are
// not 2d axis aligned and thus do not need to snap its children
// either.
let parent_scale_offset = match parent {
Some(parent) => {
match parent.snapping_transform {
Some(scale_offset) => scale_offset,
None => return,
}
},
_ => ScaleOffset::identity(),
};
let scale_offset = match self.node_type {
SpatialNodeType::ReferenceFrame(ref info) => {
match info.source_transform {
PropertyBinding::Value(ref value) => {
// We can only get a ScaleOffset if the transform is 2d axis
// aligned.
match ScaleOffset::from_transform(value) {
Some(scale_offset) => {
let origin_offset = info.origin_in_parent_reference_frame;
ScaleOffset::from_offset(origin_offset.to_untyped())
.accumulate(&scale_offset)
}
None => return,
}
}
// Assume animations start at the identity transform for snapping purposes.
// TODO(aosmond): Is there a better known starting point?
PropertyBinding::Binding(..) => ScaleOffset::identity(),
}
}
_ => ScaleOffset::identity(),
};
self.snapping_transform = Some(parent_scale_offset.accumulate(&scale_offset));
}
/// Returns true for ReferenceFrames whose source_transform is
/// bound to the property binding id.
pub fn is_transform_bound_to_property(&self, id: PropertyBindingId) -> bool {
@ -923,7 +850,7 @@ fn test_cst_perspective_relative_scroll() {
pipeline_id,
);
cst.update_tree(WorldPoint::zero(), DevicePixelScale::new(1.0), &SceneProperties::new());
cst.update_tree(WorldPoint::zero(), &SceneProperties::new());
let scroll_offset = compute_offset_from(
cst.spatial_nodes[ref_frame.0 as usize].parent,

View File

@ -166,13 +166,6 @@ impl ScaleOffset {
})
}
pub fn from_offset(offset: default::Vector2D<f32>) -> Self {
ScaleOffset {
scale: Vector2D::new(1.0, 1.0),
offset,
}
}
pub fn inverse(&self) -> Self {
ScaleOffset {
scale: Vector2D::new(
@ -195,15 +188,6 @@ impl ScaleOffset {
)
}
pub fn scale(&self, scale: f32) -> Self {
self.accumulate(
&ScaleOffset {
scale: Vector2D::new(scale, scale),
offset: Vector2D::zero(),
}
)
}
/// Produce a ScaleOffset that includes both self and other.
/// The 'self' ScaleOffset is applied after other.
/// This is equivalent to `Transform3D::pre_transform`.
@ -421,29 +405,12 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for Transform3D<f32, Src, Dst> {
}
}
pub trait PointHelpers<U>
where
Self: Sized,
{
fn snap(&self) -> Self;
}
impl<U> PointHelpers<U> for Point2D<f32, U> {
fn snap(&self) -> Self {
Point2D::new(
(self.x + 0.5).floor(),
(self.y + 0.5).floor(),
)
}
}
pub trait RectHelpers<U>
where
Self: Sized,
{
fn from_floats(x0: f32, y0: f32, x1: f32, y1: f32) -> Self;
fn is_well_formed_and_nonempty(&self) -> bool;
fn snap(&self) -> Self;
}
impl<U> RectHelpers<U> for Rect<f32, U> {
@ -457,36 +424,6 @@ impl<U> RectHelpers<U> for Rect<f32, U> {
fn is_well_formed_and_nonempty(&self) -> bool {
self.size.width > 0.0 && self.size.height > 0.0
}
fn snap(&self) -> Self {
let origin = Point2D::new(
(self.origin.x + 0.5).floor(),
(self.origin.y + 0.5).floor(),
);
Rect::new(
origin,
Size2D::new(
(self.origin.x + self.size.width + 0.5).floor() - origin.x,
(self.origin.y + self.size.height + 0.5).floor() - origin.y,
),
)
}
}
pub trait VectorHelpers<U>
where
Self: Sized,
{
fn snap(&self) -> Self;
}
impl<U> VectorHelpers<U> for Vector2D<f32, U> {
fn snap(&self) -> Self {
Vector2D::new(
(self.x + 0.5).floor(),
(self.y + 0.5).floor(),
)
}
}
pub fn lerp(a: f32, b: f32, t: f32) -> f32 {

View File

@ -104,7 +104,6 @@ pub enum DisplayItem {
Gradient(GradientDisplayItem),
RadialGradient(RadialGradientDisplayItem),
Image(ImageDisplayItem),
RepeatingImage(RepeatingImageDisplayItem),
YuvImage(YuvImageDisplayItem),
BackdropFilter(BackdropFilterDisplayItem),
@ -149,7 +148,6 @@ pub enum DebugDisplayItem {
Gradient(GradientDisplayItem),
RadialGradient(RadialGradientDisplayItem),
Image(ImageDisplayItem),
RepeatingImage(RepeatingImageDisplayItem),
YuvImage(YuvImageDisplayItem),
BackdropFilter(BackdropFilterDisplayItem),
@ -1073,28 +1071,10 @@ pub struct IframeDisplayItem {
pub ignore_missing_pipeline: bool,
}
/// This describes an image that fills the specified area. It stretches or shrinks
/// the image as necessary. While RepeatingImageDisplayItem could otherwise provide
/// a superset of the functionality, it has been problematic inferring the desired
/// repetition properties when snapping changes the size of the primitive.
/// This describes an image or, more generally, a background-image and its tiling.
/// (A background-image repeats in a grid to fill the specified area).
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ImageDisplayItem {
pub common: CommonItemProperties,
/// The area to tile the image over (first tile starts at origin of this rect)
// FIXME: this should ideally just be `tile_origin` here, with the clip_rect
// defining the bounds of the item. Needs non-trivial backend changes.
pub bounds: LayoutRect,
pub image_key: ImageKey,
pub image_rendering: ImageRendering,
pub alpha_type: AlphaType,
/// A hack used by gecko to color a simple bitmap font used for tofu glyphs
pub color: ColorF,
}
/// This describes a background-image and its tiling. It repeats in a grid to fill
/// the specified area.
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct RepeatingImageDisplayItem {
pub common: CommonItemProperties,
/// The area to tile the image over (first tile starts at origin of this rect)
// FIXME: this should ideally just be `tile_origin` here, with the clip_rect
@ -1426,7 +1406,6 @@ impl DisplayItem {
DisplayItem::Gradient(..) => "gradient",
DisplayItem::Iframe(..) => "iframe",
DisplayItem::Image(..) => "image",
DisplayItem::RepeatingImage(..) => "repeating_image",
DisplayItem::Line(..) => "line",
DisplayItem::PopAllShadows => "pop_all_shadows",
DisplayItem::PopReferenceFrame => "pop_reference_frame",

View File

@ -623,7 +623,6 @@ impl Serialize for BuiltDisplayList {
Real::HitTest(v) => Debug::HitTest(v),
Real::Line(v) => Debug::Line(v),
Real::Image(v) => Debug::Image(v),
Real::RepeatingImage(v) => Debug::RepeatingImage(v),
Real::YuvImage(v) => Debug::YuvImage(v),
Real::Border(v) => Debug::Border(v),
Real::BoxShadow(v) => Debug::BoxShadow(v),
@ -728,7 +727,6 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
Debug::HitTest(v) => Real::HitTest(v),
Debug::Line(v) => Real::Line(v),
Debug::Image(v) => Real::Image(v),
Debug::RepeatingImage(v) => Real::RepeatingImage(v),
Debug::YuvImage(v) => Real::YuvImage(v),
Debug::Border(v) => Real::Border(v),
Debug::BoxShadow(v) => Real::BoxShadow(v),
@ -1003,27 +1001,6 @@ impl DisplayListBuilder {
}
pub fn push_image(
&mut self,
common: &di::CommonItemProperties,
bounds: LayoutRect,
image_rendering: di::ImageRendering,
alpha_type: di::AlphaType,
key: ImageKey,
color: ColorF,
) {
let item = di::DisplayItem::Image(di::ImageDisplayItem {
common: *common,
bounds,
image_key: key,
image_rendering,
alpha_type,
color,
});
self.push_item(&item);
}
pub fn push_repeating_image(
&mut self,
common: &di::CommonItemProperties,
bounds: LayoutRect,
@ -1034,7 +1011,7 @@ impl DisplayListBuilder {
key: ImageKey,
color: ColorF,
) {
let item = di::DisplayItem::RepeatingImage(di::RepeatingImageDisplayItem {
let item = di::DisplayItem::Image(di::ImageDisplayItem {
common: *common,
bounds,
image_key: key,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -9,7 +9,7 @@ fuzzy(8,60) == custom-clip-chains.yaml custom-clip-chains-ref.yaml
== fixed-position-clipping.yaml fixed-position-clipping-ref.yaml
platform(linux,mac) == segmentation-with-other-coordinate-system-clip.yaml segmentation-with-other-coordinate-system-clip.png
skip_on(android,emulator) == segmentation-across-rotation.yaml segmentation-across-rotation-ref.yaml
skip_on(android,device) == color_targets(3) alpha_targets(1) stacking-context-clip.yaml stacking-context-clip-ref.yaml
== color_targets(3) alpha_targets(1) stacking-context-clip.yaml stacking-context-clip-ref.yaml
== snapping.yaml snapping-ref.yaml
skip_on(android,emulator) fuzzy(70,2400) == clip-and-filter-with-rotation.yaml clip-and-filter-with-rotation-ref.yaml
color_targets(2) alpha_targets(0) == clip-out-rotation.yaml blank.yaml # Unexpected color targets, see bug 1580795
color_targets(1) alpha_targets(0) == clip-out-rotation.yaml blank.yaml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 763 B

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -21,4 +21,3 @@ pipelines:
bounds: [1075, -1, 12, 199]
"clip-rect": [1075, -1, 12, 199]
image: checkerboard(4, 8, 8)
stretch-size: 72 72

View File

@ -15,4 +15,3 @@ root:
-
bounds: [350, 200, 260, 300]
image: checkerboard(2, 16, 16)
stretch-size: 260 260

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -22,7 +22,7 @@ platform(linux,mac) == nested-rotate-x-flat.yaml nested-rotate-x-flat.png
platform(linux,mac) == nested-preserve-3d.yaml nested-preserve-3d.png
platform(linux,mac) fuzzy(1,283) == near-plane-clip.yaml near-plane-clip.png
platform(linux,mac) == perspective-mask.yaml perspective-mask.png
skip_on(android,emulator) == rotate-clip.yaml rotate-clip-ref.yaml # Fails on Android emulator
rotate-clip.yaml rotate-clip-ref.yaml
skip_on(android,emulator) == clip-translate.yaml clip-translate-ref.yaml # Fails on Android emulator
platform(linux,mac) == perspective-clip.yaml perspective-clip.png
platform(linux,mac) fuzzy(1,2) == perspective-clip-1.yaml perspective-clip-1.png

View File

@ -163,6 +163,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(64.0, 64.0),
size2(64.0, 64.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
img,
@ -190,6 +192,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(1024.0, 1024.0),
size2(1024.0, 1024.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
img,
@ -214,6 +218,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(1024.0, 1024.0),
size2(1024.0, 1024.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
img,
@ -249,7 +255,7 @@ impl<'a> RawtestHarness<'a> {
let info = self.make_common_properties(rect(448.899994, 74.0, 151.000031, 56.));
// setup some malicious image size parameters
builder.push_repeating_image(
builder.push_image(
&info,
info.clip_rect,
size2(151., 56.0),
@ -329,7 +335,7 @@ impl<'a> RawtestHarness<'a> {
};
// setup some malicious image size parameters
builder.push_repeating_image(
builder.push_image(
&info,
info.clip_rect,
image_size * 2.,
@ -434,7 +440,7 @@ impl<'a> RawtestHarness<'a> {
Some(100),
);
builder.push_repeating_image(
builder.push_image(
&info,
info.clip_rect,
image_size,
@ -471,7 +477,7 @@ impl<'a> RawtestHarness<'a> {
Some(100),
);
builder.push_repeating_image(
builder.push_image(
&info,
info.clip_rect,
image_size,
@ -526,7 +532,7 @@ impl<'a> RawtestHarness<'a> {
let image_size = size2(1510., 1510.);
// setup some malicious image size parameters
builder.push_repeating_image(
builder.push_image(
&info,
info.clip_rect,
image_size,
@ -552,7 +558,7 @@ impl<'a> RawtestHarness<'a> {
let image_size = size2(1510., 1510.);
// setup some malicious image size parameters
builder.push_repeating_image(
builder.push_image(
&info,
info.clip_rect,
image_size,
@ -584,7 +590,7 @@ impl<'a> RawtestHarness<'a> {
let image_size = size2(1510., 1510.);
// setup some malicious image size parameters
builder.push_repeating_image(
builder.push_image(
&info,
info.clip_rect,
image_size,
@ -650,6 +656,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(200.0, 200.0),
size2(0.0, 0.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img.as_image(),
@ -672,6 +680,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(200.0, 200.0),
size2(0.0, 0.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img.as_image(),
@ -757,6 +767,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(200.0, 200.0),
size2(0.0, 0.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img.as_image(),
@ -765,6 +777,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info2,
info2.clip_rect,
size2(200.0, 200.0),
size2(0.0, 0.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img2.as_image(),
@ -856,6 +870,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(200.0, 200.0),
size2(0.0, 0.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img.as_image(),
@ -883,6 +899,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(200.0, 200.0),
size2(0.0, 0.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img.as_image(),
@ -908,6 +926,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(200.0, 200.0),
size2(0.0, 0.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
blob_img.as_image(),
@ -1106,6 +1126,8 @@ impl<'a> RawtestHarness<'a> {
builder.push_image(
&info,
info.clip_rect,
size2(150.0, 50.0),
size2(0.0, 0.0),
ImageRendering::Auto,
AlphaType::PremultipliedAlpha,
image,

View File

@ -1374,6 +1374,10 @@ impl YamlFrameReader {
item["bounds"]
);
};
let stretch_size = item["stretch-size"].as_size().unwrap_or(image_dims);
let tile_spacing = item["tile-spacing"]
.as_size()
.unwrap_or(LayoutSize::new(0.0, 0.0));
let rendering = match item["rendering"].as_str() {
Some("auto") | None => ImageRendering::Auto,
Some("crisp-edges") => ImageRendering::CrispEdges,
@ -1391,29 +1395,16 @@ impl YamlFrameReader {
item
),
};
let stretch_size = item["stretch-size"].as_size();
let tile_spacing = item["tile-spacing"].as_size();
if stretch_size.is_none() && tile_spacing.is_none() {
dl.push_image(
&info,
bounds,
rendering,
alpha_type,
image_key,
ColorF::WHITE,
);
} else {
dl.push_repeating_image(
&info,
bounds,
stretch_size.unwrap_or(image_dims),
tile_spacing.unwrap_or(LayoutSize::zero()),
rendering,
alpha_type,
image_key,
ColorF::WHITE,
);
}
dl.push_image(
&info,
bounds,
stretch_size,
tile_spacing,
rendering,
alpha_type,
image_key,
ColorF::WHITE,
);
}
fn handle_text(

View File

@ -1053,29 +1053,6 @@ impl YamlFrameWriter {
}
}
DisplayItem::Image(item) => {
common_node(&mut v, clip_id_mapper, &item.common);
rect_node(&mut v, "bounds", &item.bounds);
if let Some(path) = self.path_for_image(item.image_key) {
path_node(&mut v, "image", &path);
}
if let Some(&CachedImage {
tiling: Some(tile_size),
..
}) = self.images.get(&item.image_key)
{
u32_node(&mut v, "tile-size", tile_size as u32);
}
match item.image_rendering {
ImageRendering::Auto => (),
ImageRendering::CrispEdges => str_node(&mut v, "rendering", "crisp-edges"),
ImageRendering::Pixelated => str_node(&mut v, "rendering", "pixelated"),
};
match item.alpha_type {
AlphaType::PremultipliedAlpha => str_node(&mut v, "alpha-type", "premultiplied-alpha"),
AlphaType::Alpha => str_node(&mut v, "alpha-type", "alpha"),
};
}
DisplayItem::RepeatingImage(item) => {
common_node(&mut v, clip_id_mapper, &item.common);
rect_node(&mut v, "bounds", &item.bounds);
if let Some(path) = self.path_for_image(item.image_key) {

View File

@ -6967,46 +6967,17 @@ IntSize nsLayoutUtils::ComputeImageContainerDrawingParameters(
}
}
// Attempt to snap pixels, the same as ComputeSnappedImageDrawingParameters.
// Any changes to the algorithm here will need to be reflected there.
bool snapped = false;
gfxSize gfxLayerSize;
const gfx::Matrix& itm = aSc.GetInheritedTransform();
if (!itm.HasNonAxisAlignedTransform() && itm._11 > 0.0 && itm._22 > 0.0) {
gfxRect rect(gfxPoint(aDestRect.X(), aDestRect.Y()),
gfxSize(aDestRect.Width(), aDestRect.Height()));
// Compute our size in layer pixels. We may need to revisit this for Android
// because mobile websites are rarely displayed at a 1:1
// LayoutPixel:ScreenPixel ratio and the snapping here may be insufficient.
const LayerIntSize layerSize =
RoundedToInt(LayerSize(aDestRect.Width() * scaleFactors.width,
aDestRect.Height() * scaleFactors.height));
gfxPoint p1 = ThebesPoint(itm.TransformPoint(ToPoint(rect.TopLeft())));
gfxPoint p2 = ThebesPoint(itm.TransformPoint(ToPoint(rect.TopRight())));
gfxPoint p3 = ThebesPoint(itm.TransformPoint(ToPoint(rect.BottomRight())));
if (p2 == gfxPoint(p1.x, p3.y) || p2 == gfxPoint(p3.x, p1.y)) {
p1.Round();
p3.Round();
rect.MoveTo(gfxPoint(std::min(p1.x, p3.x), std::min(p1.y, p3.y)));
rect.SizeTo(gfxSize(std::max(p1.x, p3.x) - rect.X(),
std::max(p1.y, p3.y) - rect.Y()));
// An empty size is unacceptable so we ensure our suggested size is at
// least 1 pixel wide/tall.
gfxLayerSize =
gfxSize(std::max(rect.Width(), 1.0), std::max(rect.Height(), 1.0));
snapped = true;
}
}
if (!snapped) {
// Compute our size in layer pixels.
const LayerIntSize layerSize =
RoundedToInt(LayerSize(aDestRect.Width() * scaleFactors.width,
aDestRect.Height() * scaleFactors.height));
// An empty size is unacceptable so we ensure our suggested size is at least
// 1 pixel wide/tall.
gfxLayerSize =
gfxSize(std::max(layerSize.width, 1), std::max(layerSize.height, 1));
}
// An empty size is unacceptable so we ensure our suggested size is at least
// 1 pixel wide/tall.
gfxSize gfxLayerSize =
gfxSize(std::max(layerSize.width, 1), std::max(layerSize.height, 1));
return aImage->OptimalImageSizeForDest(
gfxLayerSize, imgIContainer::FRAME_CURRENT, samplingFilter, aFlags);

View File

@ -134,11 +134,11 @@ bool nsDisplayButtonBoxShadowOuter::CreateWebRenderCommands(
nsRect shadowRect = nsRect(ToReferenceFrame(), mFrame->GetSize());
LayoutDeviceRect deviceBox =
LayoutDeviceRect::FromAppUnits(shadowRect, appUnitsPerDevPixel);
wr::LayoutRect deviceBoxRect = wr::ToLayoutRect(deviceBox);
wr::LayoutRect deviceBoxRect = wr::ToRoundedLayoutRect(deviceBox);
LayoutDeviceRect clipRect =
LayoutDeviceRect::FromAppUnits(GetPaintRect(), appUnitsPerDevPixel);
wr::LayoutRect deviceClipRect = wr::ToLayoutRect(clipRect);
wr::LayoutRect deviceClipRect = wr::ToRoundedLayoutRect(clipRect);
bool hasBorderRadius;
Unused << nsCSSRendering::HasBoxShadowNativeTheme(mFrame, hasBorderRadius);

View File

@ -185,12 +185,12 @@ bool nsDisplayFieldSetBorder::CreateWebRenderCommands(
if (!legendRect.IsEmpty()) {
// We need to clip out the part of the border where the legend would go
auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
auto layoutRect = wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(
auto layoutRect = wr::ToRoundedLayoutRect(LayoutDeviceRect::FromAppUnits(
frame->GetVisualOverflowRectRelativeToSelf() + offset,
appUnitsPerDevPixel));
wr::ComplexClipRegion region;
region.rect = wr::ToLayoutRect(
region.rect = wr::ToRoundedLayoutRect(
LayoutDeviceRect::FromAppUnits(legendRect, appUnitsPerDevPixel));
region.mode = wr::ClipMode::ClipOut;
region.radii = wr::EmptyBorderRadius();

View File

@ -84,7 +84,7 @@ class TextDrawTarget : public DrawTarget {
LayoutDeviceRect layoutBoundsRect =
LayoutDeviceRect::FromAppUnits(aBounds, appUnitsPerDevPixel);
LayoutDeviceRect layoutClipRect = layoutBoundsRect;
mBoundsRect = wr::ToLayoutRect(layoutBoundsRect);
mBoundsRect = wr::ToRoundedLayoutRect(layoutBoundsRect);
// Add 1 pixel of dirty area around clip rect to allow us to paint
// antialiased pixels beyond the measured text extents.
@ -275,7 +275,7 @@ class TextDrawTarget : public DrawTarget {
}
wr::Line decoration;
decoration.bounds = wr::ToLayoutRect(LayoutDeviceRect(pos, size));
decoration.bounds = wr::ToRoundedLayoutRect(LayoutDeviceRect(pos, size));
decoration.wavyLineThickness = 0; // dummy value, unused
decoration.color = wr::ToColorF(aColor);
decoration.orientation = aVertical ? wr::LineOrientation::Vertical
@ -310,7 +310,7 @@ class TextDrawTarget : public DrawTarget {
wr::Line decoration;
decoration.bounds =
wr::ToLayoutRect(LayoutDeviceRect::FromUnknownRect(aBounds));
wr::ToRoundedLayoutRect(LayoutDeviceRect::FromUnknownRect(aBounds));
decoration.wavyLineThickness = aThickness;
decoration.color = wr::ToColorF(aColor);
decoration.orientation = aVertical ? wr::LineOrientation::Vertical
@ -347,7 +347,7 @@ class TextDrawTarget : public DrawTarget {
private:
wr::LayoutRect ClipRect() {
return wr::ToLayoutRect(mClipStack.LastElement());
return wr::ToRoundedLayoutRect(mClipStack.LastElement());
}
LayoutDeviceRect GeckoClipRect() { return mClipStack.LastElement(); }
// Whether anything unsupported was encountered. This will result in this
@ -463,7 +463,8 @@ class TextDrawTarget : public DrawTarget {
if (!aRect.Intersects(GeckoClipRect().ToUnknownRect())) {
return;
}
auto rect = wr::ToLayoutRect(LayoutDeviceRect::FromUnknownRect(aRect));
auto rect =
wr::ToRoundedLayoutRect(LayoutDeviceRect::FromUnknownRect(aRect));
auto color =
wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
mBuilder.PushRect(rect, ClipRect(), mBackfaceVisible, color);
@ -490,7 +491,7 @@ class TextDrawTarget : public DrawTarget {
if (!rect.Intersects(GeckoClipRect())) {
return;
}
wr::LayoutRect bounds = wr::ToLayoutRect(rect);
wr::LayoutRect bounds = wr::ToRoundedLayoutRect(rect);
mBuilder.PushBorder(bounds, ClipRect(), true, widths,
Range<const wr::BorderSide>(sides, 4), radius);
}

View File

@ -446,6 +446,7 @@ ImgDrawResult BulletRenderer::CreateWebRenderCommandsForImage(
aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(mDest, appUnitsPerDevPixel);
destRect.Round();
Maybe<SVGImageContext> svgContext;
gfx::IntSize decodeSize =
@ -484,7 +485,7 @@ bool BulletRenderer::CreateWebRenderCommandsForPath(
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
MOZ_ASSERT(IsPathType());
wr::LayoutRect dest = wr::ToLayoutRect(mPathRect);
wr::LayoutRect dest = wr::ToRoundedLayoutRect(mPathRect);
auto color = wr::ToColorF(ToDeviceColor(mColor));
bool isBackfaceVisible = !aItem->BackfaceIsHidden();
switch (mListStyleType) {

View File

@ -372,8 +372,8 @@ bool nsDisplayCanvasBackgroundColor::CreateWebRenderCommands(
LayoutDeviceRect rect =
LayoutDeviceRect::FromAppUnits(bgClipRect, appUnitsPerDevPixel);
wr::LayoutRect r = wr::ToLayoutRect(rect);
aBuilder.PushRect(r, r, !BackfaceIsHidden(),
wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(rect);
aBuilder.PushRect(roundedRect, roundedRect, !BackfaceIsHidden(),
wr::ToColorF(ToDeviceColor(mColor)));
return true;
}

View File

@ -2309,9 +2309,10 @@ bool nsDisplaySelectionOverlay::CreateWebRenderCommands(
const StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
wr::LayoutRect bounds = wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(
nsRect(ToReferenceFrame(), Frame()->GetSize()),
mFrame->PresContext()->AppUnitsPerDevPixel()));
wr::LayoutRect bounds =
wr::ToRoundedLayoutRect(LayoutDeviceRect::FromAppUnits(
nsRect(ToReferenceFrame(), Frame()->GetSize()),
mFrame->PresContext()->AppUnitsPerDevPixel()));
aBuilder.PushRect(bounds, bounds, !BackfaceIsHidden(),
wr::ToColorF(ComputeColor()));
return true;

View File

@ -163,7 +163,7 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem {
// parent side, where it will be done when we build the display list for
// the iframe. That happens in WebRenderCompositableHolder.
wr::LayoutRect r = wr::ToLayoutRect(bounds);
wr::LayoutRect r = wr::ToRoundedLayoutRect(bounds);
aBuilder.PushIFrame(r, !BackfaceIsHidden(), data->GetPipelineId().ref(),
/*ignoreMissingPipelines*/ false);

View File

@ -1569,7 +1569,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedbackWithoutLayer(
// Clip to this rect so we don't render outside the inner rect
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
inner, PresContext()->AppUnitsPerDevPixel());
auto wrBounds = wr::ToLayoutRect(bounds);
auto wrBounds = wr::ToRoundedLayoutRect(bounds);
// Draw image
ImgDrawResult result = ImgDrawResult::NOT_READY;
@ -1609,6 +1609,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedbackWithoutLayer(
const int32_t factor = PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect destRect(LayoutDeviceRect::FromAppUnits(dest, factor));
destRect.Round();
Maybe<SVGImageContext> svgContext;
IntSize decodeSize =
@ -1640,7 +1641,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedbackWithoutLayer(
nsRect rect(iconXPos, inner.y, size, size);
auto devPxRect = LayoutDeviceRect::FromAppUnits(
rect, PresContext()->AppUnitsPerDevPixel());
auto dest = wr::ToLayoutRect(devPxRect);
auto dest = wr::ToRoundedLayoutRect(devPxRect);
auto borderWidths = wr::ToBorderWidths(1.0, 1.0, 1.0, 1.0);
wr::BorderSide side = {color, wr::BorderStyle::Solid};
@ -1655,7 +1656,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedbackWithoutLayer(
size / 2 - twoPX);
devPxRect = LayoutDeviceRect::FromAppUnits(
rect, PresContext()->AppUnitsPerDevPixel());
dest = wr::ToLayoutRect(devPxRect);
dest = wr::ToRoundedLayoutRect(devPxRect);
aBuilder.PushRoundedRect(dest, wrBounds, isBackfaceVisible, color);
}
@ -1890,6 +1891,7 @@ bool nsDisplayImage::CreateWebRenderCommands(
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect destRect(
LayoutDeviceRect::FromAppUnits(GetDestRect(), factor));
destRect.Round();
Maybe<SVGImageContext> svgContext;
IntSize decodeSize = nsLayoutUtils::ComputeImageContainerDrawingParameters(

View File

@ -1505,8 +1505,8 @@ bool nsDisplayRemote::CreateWebRenderCommands(
mFrame->PresContext()->AppUnitsPerDevPixel());
rect += mOffset;
aBuilder.PushIFrame(mozilla::wr::ToLayoutRect(rect), !BackfaceIsHidden(),
mozilla::wr::AsPipelineId(mLayersId),
aBuilder.PushIFrame(mozilla::wr::ToRoundedLayoutRect(rect),
!BackfaceIsHidden(), mozilla::wr::AsPipelineId(mLayersId),
/*ignoreMissingPipelines*/ true);
return true;

View File

@ -3328,7 +3328,7 @@ void nsCSSBorderRenderer::CreateWebRenderCommands(
wr::IpcResourceUpdateQueue& aResources,
const layers::StackingContextHelper& aSc) {
LayoutDeviceRect outerRect = LayoutDeviceRect::FromUnknownRect(mOuterRect);
wr::LayoutRect roundedRect = wr::ToLayoutRect(outerRect);
wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(outerRect);
wr::LayoutRect clipRect = roundedRect;
wr::BorderSide side[4];
NS_FOR_CSS_SIDES(i) {
@ -3345,7 +3345,7 @@ void nsCSSBorderRenderer::CreateWebRenderCommands(
if (mLocalClip) {
LayoutDeviceRect localClip =
LayoutDeviceRect::FromUnknownRect(mLocalClip.value());
clipRect = wr::ToLayoutRect(localClip.Intersect(outerRect));
clipRect = wr::ToRoundedLayoutRect(localClip.Intersect(outerRect));
}
Range<const wr::BorderSide> wrsides(side, 4);
@ -3593,7 +3593,7 @@ ImgDrawResult nsCSSBorderImageRenderer::CreateWebRenderCommands(
if (!mClip.IsEmpty()) {
LayoutDeviceRect clipRect =
LayoutDeviceRect::FromAppUnits(mClip, appUnitsPerDevPixel);
clip = wr::ToLayoutRect(clipRect);
clip = wr::ToRoundedLayoutRect(clipRect);
}
ImgDrawResult drawResult = ImgDrawResult::SUCCESS;

View File

@ -3866,16 +3866,16 @@ bool nsDisplaySolidColor::CreateWebRenderCommands(
LayoutDeviceRect renderRootRect =
aDisplayListBuilder->GetRenderRootRect(renderRoot);
wr::LayoutRect intersection =
wr::ToLayoutRect(bounds.Intersect(renderRootRect));
wr::ToRoundedLayoutRect(bounds.Intersect(renderRootRect));
aBuilder.SubBuilder(renderRoot)
.PushRect(intersection, intersection, !BackfaceIsHidden(),
wr::ToColorF(ToDeviceColor(mColor)));
}
}
} else {
wr::LayoutRect r = wr::ToLayoutRect(bounds);
wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(bounds);
aBuilder.PushRect(r, r, !BackfaceIsHidden(),
aBuilder.PushRect(roundedRect, roundedRect, !BackfaceIsHidden(),
wr::ToColorF(ToDeviceColor(mColor)));
}
@ -3915,8 +3915,8 @@ bool nsDisplaySolidColorRegion::CreateWebRenderCommands(
nsRect rect = iter.Get();
LayoutDeviceRect layerRects = LayoutDeviceRect::FromAppUnits(
rect, mFrame->PresContext()->AppUnitsPerDevPixel());
wr::LayoutRect r = wr::ToLayoutRect(layerRects);
aBuilder.PushRect(r, r, !BackfaceIsHidden(),
wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(layerRects);
aBuilder.PushRect(roundedRect, roundedRect, !BackfaceIsHidden(),
wr::ToColorF(ToDeviceColor(mColor)));
}
@ -5181,9 +5181,9 @@ bool nsDisplayBackgroundColor::CreateWebRenderCommands(
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
mBackgroundRect, mFrame->PresContext()->AppUnitsPerDevPixel());
wr::LayoutRect r = wr::ToLayoutRect(bounds);
wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(bounds);
aBuilder.PushRect(r, r, !BackfaceIsHidden(),
aBuilder.PushRect(roundedRect, roundedRect, !BackfaceIsHidden(),
wr::ToColorF(ToDeviceColor(mColor)));
return true;
@ -5366,7 +5366,7 @@ bool nsDisplayClearBackground::CreateWebRenderCommands(
nsRect(ToReferenceFrame(), mFrame->GetSize()),
mFrame->PresContext()->AppUnitsPerDevPixel());
aBuilder.PushClearRect(wr::ToLayoutRect(bounds));
aBuilder.PushClearRect(wr::ToRoundedLayoutRect(bounds));
return true;
}
@ -5539,7 +5539,7 @@ bool nsDisplayCompositorHitTestInfo::CreateWebRenderCommands(
const LayoutDeviceRect devRect =
LayoutDeviceRect::FromAppUnits(HitTestArea(), mAppUnitsPerDevPixel);
const wr::LayoutRect rect = wr::ToLayoutRect(devRect);
const wr::LayoutRect rect = wr::ToRoundedLayoutRect(devRect);
aBuilder.PushHitTest(rect, rect, !BackfaceIsHidden());
aBuilder.ClearHitTestInfo();
@ -5611,8 +5611,8 @@ bool nsDisplayCaret::CreateWebRenderCommands(
LayoutDeviceRect devHookRect = LayoutDeviceRect::FromAppUnits(
hookRect + ToReferenceFrame(), appUnitsPerDevPixel);
wr::LayoutRect caret = wr::ToLayoutRect(devCaretRect);
wr::LayoutRect hook = wr::ToLayoutRect(devHookRect);
wr::LayoutRect caret = wr::ToRoundedLayoutRect(devCaretRect);
wr::LayoutRect hook = wr::ToRoundedLayoutRect(devHookRect);
// Note, WR will pixel snap anything that is layout aligned.
aBuilder.PushRect(caret, caret, !BackfaceIsHidden(), wr::ToColorF(color));
@ -5886,8 +5886,8 @@ bool nsDisplayBoxShadowOuter::CreateWebRenderCommands(
LayoutDeviceRect deviceBox =
LayoutDeviceRect::FromAppUnits(shadowRect, appUnitsPerDevPixel);
wr::LayoutRect deviceBoxRect = wr::ToLayoutRect(deviceBox);
wr::LayoutRect deviceClipRect = wr::ToLayoutRect(clipRect);
wr::LayoutRect deviceBoxRect = wr::ToRoundedLayoutRect(deviceBox);
wr::LayoutRect deviceClipRect = wr::ToRoundedLayoutRect(clipRect);
LayoutDeviceSize zeroSize;
wr::BorderRadius borderRadius =
@ -6015,7 +6015,7 @@ void nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(
// Now translate everything to device pixels.
LayoutDeviceRect deviceBoxRect =
LayoutDeviceRect::FromAppUnits(shadowRect, appUnitsPerDevPixel);
wr::LayoutRect deviceClipRect = wr::ToLayoutRect(clipRect);
wr::LayoutRect deviceClipRect = wr::ToRoundedLayoutRect(clipRect);
Color shadowColor =
nsCSSRendering::GetShadowColor(shadow.base, aFrame, 1.0);
@ -7736,7 +7736,7 @@ bool nsDisplayStickyPosition::CreateWebRenderCommands(
NSAppUnitsToFloatPixels(appliedOffset.x, auPerDevPixel),
NSAppUnitsToFloatPixels(appliedOffset.y, auPerDevPixel)};
wr::WrSpatialId spatialId = aBuilder.DefineStickyFrame(
wr::ToLayoutRect(bounds), topMargin.ptrOr(nullptr),
wr::ToRoundedLayoutRect(bounds), topMargin.ptrOr(nullptr),
rightMargin.ptrOr(nullptr), bottomMargin.ptrOr(nullptr),
leftMargin.ptrOr(nullptr), vBounds, hBounds, applied);
@ -10031,7 +10031,7 @@ static Maybe<wr::WrClipId> CreateSimpleClipRegion(
wr::ToComplexClipRegion(insetRect, radii, appUnitsPerDevPixel));
}
rect = wr::ToLayoutRect(
rect = wr::ToRoundedLayoutRect(
LayoutDeviceRect::FromAppUnits(insetRect, appUnitsPerDevPixel));
break;
}
@ -10060,7 +10060,7 @@ static Maybe<wr::WrClipId> CreateSimpleClipRegion(
clipRegions.AppendElement(wr::ToComplexClipRegion(
ellipseRect, ellipseRadii, appUnitsPerDevPixel));
rect = wr::ToLayoutRect(
rect = wr::ToRoundedLayoutRect(
LayoutDeviceRect::FromAppUnits(ellipseRect, appUnitsPerDevPixel));
break;
}
@ -10099,7 +10099,7 @@ static Maybe<Pair<wr::WrClipId, HandleOpacity>> CreateWRClipPathAndMasks(
}
wr::WrClipId clipId = aBuilder.DefineClip(
Nothing(), wr::ToLayoutRect(aBounds), nullptr, mask.ptr());
Nothing(), wr::ToRoundedLayoutRect(aBounds), nullptr, mask.ptr());
return Some(MakePair(clipId, HandleOpacity::No));
}
@ -10512,7 +10512,7 @@ bool nsDisplayFilters::CreateWebRenderCommands(
auto devPxRect = LayoutDeviceRect::FromAppUnits(
filterClip.value() + ToReferenceFrame(), auPerDevPixel);
wr::WrClipId clipId =
aBuilder.DefineClip(Nothing(), wr::ToLayoutRect(devPxRect));
aBuilder.DefineClip(Nothing(), wr::ToRoundedLayoutRect(devPxRect));
clip = wr::WrStackingContextClip::ClipId(clipId);
} else {
clip = wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());

View File

@ -603,6 +603,7 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(aDest, appUnitsPerDevPixel);
auto stretchSize = wr::ToLayoutSize(destRect.Size());
destRect.Round();
gfx::IntSize decodeSize =
nsLayoutUtils::ComputeImageContainerDrawingParameters(
@ -629,47 +630,47 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
break;
}
wr::LayoutRect dest = wr::ToLayoutRect(destRect);
nsPoint firstTilePos = nsLayoutUtils::GetBackgroundFirstTilePos(
aDest.TopLeft(), aFill.TopLeft(), aRepeatSize);
LayoutDeviceRect fillRect = LayoutDeviceRect::FromAppUnits(
nsRect(firstTilePos.x, firstTilePos.y, aFill.XMost() - firstTilePos.x,
aFill.YMost() - firstTilePos.y),
appUnitsPerDevPixel);
wr::LayoutRect fill = wr::ToRoundedLayoutRect(fillRect);
wr::LayoutRect clip = wr::ToLayoutRect(
wr::LayoutRect roundedDest = wr::ToLayoutRect(destRect);
// WebRender special cases situations where stretchSize == fillSize to
// infer that it shouldn't use repeat sampling. This makes sure
// we hit those special cases when not repeating.
switch (mExtendMode) {
case ExtendMode::CLAMP:
fill = roundedDest;
stretchSize = roundedDest.size;
break;
case ExtendMode::REPEAT_Y:
fill.origin.x = roundedDest.origin.x;
fill.size.width = roundedDest.size.width;
stretchSize.width = roundedDest.size.width;
break;
case ExtendMode::REPEAT_X:
fill.origin.y = roundedDest.origin.y;
fill.size.height = roundedDest.size.height;
stretchSize.height = roundedDest.size.height;
break;
default:
break;
}
wr::LayoutRect clip = wr::ToRoundedLayoutRect(
LayoutDeviceRect::FromAppUnits(aFill, appUnitsPerDevPixel));
if (mExtendMode == ExtendMode::CLAMP) {
// The image is not repeating. Just push as a regular image.
aBuilder.PushImage(dest, clip, !aItem->BackfaceIsHidden(), rendering,
key.value());
} else {
nsPoint firstTilePos = nsLayoutUtils::GetBackgroundFirstTilePos(
aDest.TopLeft(), aFill.TopLeft(), aRepeatSize);
LayoutDeviceRect fillRect = LayoutDeviceRect::FromAppUnits(
nsRect(firstTilePos.x, firstTilePos.y,
aFill.XMost() - firstTilePos.x,
aFill.YMost() - firstTilePos.y),
appUnitsPerDevPixel);
wr::LayoutRect fill = wr::ToLayoutRect(fillRect);
LayoutDeviceSize gapSize = LayoutDeviceSize::FromAppUnits(
aRepeatSize - aDest.Size(), appUnitsPerDevPixel);
switch (mExtendMode) {
case ExtendMode::REPEAT_Y:
fill.origin.x = dest.origin.x;
fill.size.width = dest.size.width;
stretchSize.width = dest.size.width;
break;
case ExtendMode::REPEAT_X:
fill.origin.y = dest.origin.y;
fill.size.height = dest.size.height;
stretchSize.height = dest.size.height;
break;
default:
break;
}
LayoutDeviceSize gapSize = LayoutDeviceSize::FromAppUnits(
aRepeatSize - aDest.Size(), appUnitsPerDevPixel);
aBuilder.PushRepeatingImage(fill, clip, !aItem->BackfaceIsHidden(),
stretchSize, wr::ToLayoutSize(gapSize),
rendering, key.value());
}
aBuilder.PushImage(fill, clip, !aItem->BackfaceIsHidden(), stretchSize,
wr::ToLayoutSize(gapSize), rendering, key.value());
break;
}
default:

View File

@ -5,7 +5,7 @@ skip-if(!asyncPan) == bg-fixed-cover-3.html bg-fixed-cover-3-ref.html
skip-if(!asyncPan) == bg-fixed-child.html bg-fixed-child-ref.html
skip-if(!asyncPan) == bg-fixed-child-clip-1.html bg-fixed-child-clip-ref.html
skip-if(!asyncPan) == bg-fixed-child-clip-2.html bg-fixed-child-clip-ref.html
fuzzy(0-1,0-246) fuzzy-if(skiaContent,0-2,0-170) fuzzy-if(browserIsRemote&&d2d,0-59,0-187) fuzzy-if(webrender,41-41,166-176) skip-if(!asyncPan) == bg-fixed-child-mask.html bg-fixed-child-mask-ref.html
fuzzy(0-1,0-246) fuzzy-if(skiaContent,0-2,0-170) fuzzy-if(browserIsRemote&&d2d,0-59,0-187) fuzzy-if(webrender,41-41,166-168) skip-if(!asyncPan) == bg-fixed-child-mask.html bg-fixed-child-mask-ref.html
skip-if(!asyncPan) == bg-fixed-in-opacity.html bg-fixed-in-opacity-ref.html
# Passing the test below without WebRender would require implementing CSS filters in the Gecko compositor.
fails-if(!webrender) skip-if(!asyncPan) fuzzy-if(webrender&&gtkWidget,0-1,0-87) fuzzy-if(webrender&&!gtkWidget,0-1,0-3951) == bg-fixed-in-css-filter.html bg-fixed-in-css-filter-ref.html # bug 1454794 for webrender fuzziness
@ -24,7 +24,7 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-3120) skip-if(!asyncPa
skip-if(!asyncPan) == position-fixed-cover-1.html position-fixed-cover-1-ref.html
skip-if(!asyncPan) == position-fixed-cover-2.html position-fixed-cover-2-ref.html
skip-if(!asyncPan) == position-fixed-cover-3.html position-fixed-cover-3-ref.html
fuzzy-if(Android,0-8,0-4) fuzzy-if(webrender&&gtkWidget,60-60,14-14) fuzzy-if(webrender&&cocoaWidget,22-22,44-44) skip-if(!asyncPan) == position-fixed-transformed-1.html position-fixed-transformed-1-ref.html
fuzzy-if(Android,0-5,0-4) skip-if(!asyncPan) == position-fixed-transformed-1.html position-fixed-transformed-1-ref.html
skip-if(!asyncPan) == split-layers-1.html split-layers-1-ref.html
skip-if(!asyncPan) == split-layers-multi-scrolling-1.html split-layers-multi-scrolling-1-ref.html
fuzzy-if(skiaContent,0-2,0-240000) fuzzy-if(browserIsRemote&&!skiaContent&&(cocoaWidget||winWidget),0-1,0-240000) skip-if(!asyncPan) == split-opacity-layers-1.html split-opacity-layers-1-ref.html
@ -49,33 +49,33 @@ skip-if(!asyncPan) fails-if(!webrender) == sticky-inside-transform-1.html sticky
fuzzy(0-1,0-60000) skip-if(!asyncPan) == group-opacity-surface-size-1.html group-opacity-surface-size-1-ref.html
fuzzy-if(Android,0-1,0-197) fuzzy-if(webrender,0-1,0-1) skip-if(!asyncPan) == position-sticky-transformed.html position-sticky-transformed-ref.html
skip-if(!asyncPan) == offscreen-prerendered-active-opacity.html offscreen-prerendered-active-opacity-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(skiaContent&&!Android,0-1,0-34) fuzzy-if(webrender&&gtkWidget,64-64,24-24) fuzzy-if(webrender&&cocoaWidget,7-7,37-37) skip-if(!asyncPan) == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(webrender&&gtkWidget,64-64,14-14) fuzzy-if(webrender&&cocoaWidget,7-7,37-37) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(skiaContent&&!Android,0-1,0-34) skip-if(!asyncPan) == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) skip == offscreen-clipped-blendmode-3.html offscreen-clipped-blendmode-ref.html # bug 1251588 - wrong AGR on mix-blend-mode item
fuzzy-if(Android,0-6,0-4) fuzzy-if(webrender&&gtkWidget,64-64,14-14) fuzzy-if(webrender&&cocoaWidget,7-7,37-37) skip-if(!asyncPan) == offscreen-clipped-blendmode-4.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-7,0-1406) fuzzy-if(webrender&&gtkWidget,1-1,20-20) fuzzy-if(webrender&&cocoaWidget,1-1,19-19) skip-if(!asyncPan) == perspective-scrolling-1.html perspective-scrolling-1-ref.html
fuzzy-if(Android,0-6,0-4) skip-if(!asyncPan) == offscreen-clipped-blendmode-4.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-1.html perspective-scrolling-1-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-2.html perspective-scrolling-2-ref.html
fuzzy-if(Android,0-19,0-4) fuzzy-if(webrender&&gtkWidget,24-24,14-14) fuzzy-if(webrender&&cocoaWidget,13-13,39-39) skip-if(!asyncPan) == perspective-scrolling-3.html perspective-scrolling-3-ref.html
fuzzy-if(Android,0-7,0-4) fuzzy-if(webrender&&gtkWidget,54-54,14-14) fuzzy-if(webrender&&cocoaWidget,20-20,40-40) skip-if(!asyncPan) == perspective-scrolling-4.html perspective-scrolling-4-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-3.html perspective-scrolling-3-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-4.html perspective-scrolling-4-ref.html
skip-if(!asyncPan) == perspective-scrolling-5.html perspective-scrolling-5-ref.html
pref(apz.disable_for_scroll_linked_effects,true) skip-if(!asyncPan) == disable-apz-for-sle-pages.html disable-apz-for-sle-pages-ref.html
fuzzy-if(browserIsRemote&&d2d,0-1,0-22) skip-if(!asyncPan) fuzzy-if(geckoview,2-2,242-242) skip-if(geckoview&&debug) == background-blend-mode-1.html background-blend-mode-1-ref.html # bug 1558286 for GV
skip-if(Android||!asyncPan) != opaque-fractional-displayport-1.html about:blank
skip-if(Android||!asyncPan) != opaque-fractional-displayport-2.html about:blank
fuzzy-if(Android,0-19,0-4) fuzzy-if(webrender&&gtkWidget,35-35,14-14) fuzzy-if(webrender&&cocoaWidget,22-22,44-44) skip-if(!asyncPan) == fixed-pos-scrolled-clip-1.html fixed-pos-scrolled-clip-1-ref.html
fuzzy-if(Android,0-44,0-10) fuzzy-if(webrender&&gtkWidget,48-48,28-28) fuzzy-if(webrender&&cocoaWidget,13-13,76-76) skip-if(!asyncPan) == fixed-pos-scrolled-clip-2.html fixed-pos-scrolled-clip-2-ref.html
fuzzy-if(Android,0-6,0-8) fuzzy-if(webrender&&gtkWidget,53-53,48-48) fuzzy-if(webrender&&cocoaWidget,19-19,72-72) skip-if(!asyncPan) == fixed-pos-scrolled-clip-3.html fixed-pos-scrolled-clip-3-ref.html
fuzzy-if(Android,0-6,0-8) fuzzy-if(webrender&&gtkWidget,53-53,48-48) fuzzy-if(webrender&&cocoaWidget,19-19,72-72) skip-if(!asyncPan) == fixed-pos-scrolled-clip-4.html fixed-pos-scrolled-clip-4-ref.html
fuzzy-if(Android,0-6,0-4) skip-if(!asyncPan) == fixed-pos-scrolled-clip-1.html fixed-pos-scrolled-clip-1-ref.html
fuzzy-if(Android,0-6,0-8) skip-if(!asyncPan) == fixed-pos-scrolled-clip-2.html fixed-pos-scrolled-clip-2-ref.html
fuzzy-if(Android,0-6,0-8) skip-if(!asyncPan) == fixed-pos-scrolled-clip-3.html fixed-pos-scrolled-clip-3-ref.html
fuzzy-if(Android,0-6,0-8) skip-if(!asyncPan) == fixed-pos-scrolled-clip-4.html fixed-pos-scrolled-clip-4-ref.html
skip-if(!asyncPan) == fixed-pos-scrolled-clip-5.html fixed-pos-scrolled-clip-5-ref.html
skip-if(!asyncPan) == position-sticky-bug1434250.html position-sticky-bug1434250-ref.html
fuzzy-if(Android,0-8,0-4) fuzzy-if(webrender&&gtkWidget,47-47,24-24) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) skip-if(!asyncPan) == position-sticky-scrolled-clip-1.html position-sticky-scrolled-clip-1-ref.html
fuzzy-if(Android,0-6,0-4) skip-if(!asyncPan) == position-sticky-scrolled-clip-1.html position-sticky-scrolled-clip-1-ref.html
fuzzy-if(Android,0-6,0-4) skip == position-sticky-scrolled-clip-2.html position-sticky-scrolled-clip-2-ref.html # bug ?????? - incorrectly applying clip to sticky contents
fuzzy-if(Android,0-8,0-4) fuzzy-if(webrender&&cocoaWidget,11-11,39-39) skip-if(!asyncPan) == curtain-effect-1.html curtain-effect-1-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(webrender&&gtkWidget,27-27,24-24) fuzzy-if(webrender&&cocoaWidget,9-9,37-37) skip-if(!asyncPan) == transformed-1.html transformed-1-ref.html
fuzzy-if(Android&&!webrender,2-2,4-4) fuzzy-if(Android&&webrender,7-7,4-4) fuzzy-if(webrender&&gtkWidget,21-21,24-24) fuzzy-if(webrender&&cocoaWidget,6-6,37-37) skip-if(!asyncPan) == position-sticky-transformed-in-scrollframe-1.html position-sticky-transformed-in-scrollframe-1-ref.html
fuzzy-if(Android&&!webrender,3-3,4-4) fuzzy-if(Android&&webrender,10-10,4-4) fuzzy-if(webrender&&gtkWidget,37-37,24-24) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) skip-if(!asyncPan) == position-sticky-transformed-in-scrollframe-2.html position-sticky-transformed-in-scrollframe-2-ref.html
fuzzy-if(Android&&!webrender,3-3,4-4) fuzzy-if(Android&&webrender,13-13,4-4) fuzzy-if(webrender&&gtkWidget,9-9,14-14) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) skip-if(!asyncPan) == position-sticky-in-transformed-scrollframe-1.html position-sticky-in-transformed-scrollframe-ref.html
fuzzy-if(Android&&!webrender,3-3,4-4) fuzzy-if(Android&&webrender,13-13,4-4) fuzzy-if(webrender&&gtkWidget,9-9,14-14) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) skip-if(!asyncPan) == position-sticky-in-transformed-scrollframe-2.html position-sticky-in-transformed-scrollframe-ref.html
fuzzy-if(Android,0-2,0-4) skip-if(!asyncPan) == curtain-effect-1.html curtain-effect-1-ref.html
fuzzy-if(Android,0-1,0-4) skip-if(!asyncPan) == transformed-1.html transformed-1-ref.html
fuzzy-if(Android&&!webrender,2-2,4-4) skip-if(!asyncPan) == position-sticky-transformed-in-scrollframe-1.html position-sticky-transformed-in-scrollframe-1-ref.html
fuzzy-if(Android&&!webrender,3-3,4-4) skip-if(!asyncPan) == position-sticky-transformed-in-scrollframe-2.html position-sticky-transformed-in-scrollframe-2-ref.html
fuzzy-if(Android&&!webrender,3-3,4-4) skip-if(!asyncPan) == position-sticky-in-transformed-scrollframe-1.html position-sticky-in-transformed-scrollframe-ref.html
fuzzy-if(Android&&!webrender,3-3,4-4) skip-if(!asyncPan) == position-sticky-in-transformed-scrollframe-2.html position-sticky-in-transformed-scrollframe-ref.html
# for the following tests, we want to disable the low-precision buffer
# as it will expand the displayport beyond what the test specifies in

View File

@ -48,14 +48,14 @@ fuzzy(0-1,0-149) fuzzy-if(OSX,0-1,0-10595) fuzzy-if(webrender&&!geckoview,1-3,24
fuzzy(0-1,0-433) fuzzy-if(skiaContent,0-1,0-2500) fuzzy-if(webrender&&!geckoview,1-3,83975-85584) == border-image-linear-gradient-slice-fill-1.html border-image-linear-gradient-slice-fill-1-ref.html
fuzzy(0-1,0-177) fuzzy-if(OSX,0-1,0-25771) fuzzy-if(skiaContent&&!Android,0-1,0-400) fuzzy-if(Android,0-1,0-6093) fuzzy-if(webrender&&!geckoview,1-3,57249-57480) == border-image-linear-gradient-slice-fill-2.html border-image-linear-gradient-slice-fill-2-ref.html
fuzzy(0-1,0-48) fuzzy-if(OSX,0-5,0-1676) fuzzy-if(webrender&&!geckoview,1-1,4464-4537) == border-image-linear-gradient-width.html border-image-linear-gradient-width-ref.html
fuzzy(0-1,0-5000) fuzzy-if(OSX,0-1,0-15000) fuzzy-if(webrender&&!geckoview,1-2,60222-60545) == border-image-linear-gradient-slice-width.html border-image-linear-gradient-slice-width-ref.html
fuzzy(0-1,0-3000) fuzzy-if(OSX,0-1,0-6000) fuzzy-if(webrender&&!geckoview,1-3,25940-26688) == border-image-linear-gradient-outset.html border-image-linear-gradient-outset-ref.html
fuzzy(0-1,0-5000) fuzzy-if(OSX,0-1,0-15000) fuzzy-if(webrender&&!geckoview,2-2,58625-58987) == border-image-linear-gradient-slice-width.html border-image-linear-gradient-slice-width-ref.html
fuzzy(0-1,0-3000) fuzzy-if(OSX,0-1,0-6000) fuzzy-if(webrender&&!geckoview,1-3,25940-26413) == border-image-linear-gradient-outset.html border-image-linear-gradient-outset-ref.html
fuzzy(0-1,0-12) fuzzy-if(skiaContent,0-1,0-400) fuzzy-if(webrender&&!geckoview,1-3,25966-26872) == border-image-linear-gradient-repeat-repeat-1.html border-image-linear-gradient-repeat-repeat-1-ref.html
fuzzy(0-1,0-13) fuzzy-if(skiaContent,0-1,0-300) fuzzy-if(webrender&&!geckoview,1-3,26038-27131) == border-image-linear-gradient-repeat-round-1.html border-image-linear-gradient-repeat-round-1-ref.html
fuzzy-if(webrender&&!geckoview,1-2,61283-67805) == border-image-linear-gradient-repeat-repeat-2.html border-image-linear-gradient-repeat-repeat-2-ref.html
fuzzy(0-1,0-576) fuzzy-if(skiaContent,0-1,0-2000) fuzzy-if(webrender&&!geckoview,1-2,61764-68383) == border-image-linear-gradient-repeat-round-2.html border-image-linear-gradient-repeat-round-2-ref.html
fuzzy(0-1,0-8533) fuzzy-if(webrender&&!geckoview,1-3,64622-85925) == border-image-linear-gradient-repeat-repeat-3.html border-image-linear-gradient-repeat-repeat-3-ref.html
fuzzy(0-1,0-7161) fuzzy-if(webrender&&!geckoview,1-3,107185-107548) == border-image-linear-gradient-repeat-round-3.html border-image-linear-gradient-repeat-round-3-ref.html
fuzzy(0-1,0-7161) fuzzy-if(webrender&&!geckoview,1-3,85018-86037) == border-image-linear-gradient-repeat-round-3.html border-image-linear-gradient-repeat-round-3-ref.html
fuzzy-if(webrender,0-1,0-2096) == border-image-radial-gradient.html border-image-radial-gradient-ref.html
fuzzy(0-1,0-42) fuzzy-if(skiaContent,0-2,0-20) fuzzy-if(webrender,0-1,0-37818) == border-image-radial-gradient-slice-1.html border-image-radial-gradient-slice-1-ref.html

View File

@ -11,7 +11,7 @@ random != boxshadow-blur-2.html boxshadow-blur-2-notref.html # fixedpoint divisi
== boxshadow-rounding.html boxshadow-rounding-ref.html
# One uses old path, one uses WR box shadow.
fails-if(Android) == boxshadow-button.html boxshadow-button-ref.html
fuzzy-if(OSX==1010,0-1,0-24) fuzzy-if(d2d,0-16,0-999) fuzzy-if(skiaContent,0-14,0-179) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649
fuzzy-if(OSX==1010,0-1,0-24) fuzzy-if(d2d,0-16,0-999) fuzzy-if(skiaContent,0-14,0-179) fuzzy-if(webrender,5-9,700-1080) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649
fails-if(Android) == boxshadow-fileupload.html boxshadow-fileupload-ref.html
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-98,0-152) fuzzy-if(skiaContent,0-13,0-28) fuzzy-if(webrender,19-19,47-47) == boxshadow-inner-basic.html boxshadow-inner-basic-ref.svg
@ -29,7 +29,7 @@ fuzzy(0-2,0-440) == boxshadow-skiprect.html boxshadow-skiprect-ref.html
fuzzy(0-3,0-500) fuzzy-if(d2d,0-2,0-1080) == boxshadow-border-radius-int.html boxshadow-border-radius-int-ref.html
== boxshadow-inset-neg-spread.html about:blank
== boxshadow-inset-neg-spread2.html boxshadow-inset-neg-spread2-ref.html
fuzzy(0-26,0-3610) fuzzy-if(d2d,0-26,0-5910) fuzzy-if(webrender,18-19,4184-4341) == boxshadow-rotated.html boxshadow-rotated-ref.html # Bug 1211264
fuzzy(0-26,0-3610) fuzzy-if(d2d,0-26,0-5910) == boxshadow-rotated.html boxshadow-rotated-ref.html # Bug 1211264
== boxshadow-inset-large-border-radius.html boxshadow-inset-large-border-radius-ref.html
# fuzzy due to blur going inside, but as long as it's essentially black instead of a light gray its ok.

View File

@ -1603,8 +1603,7 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 600974-2.html 600974-1-r
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 600974-3.html 600974-1-ref.html # Bug 1392106
== 602200-1.html 602200-1-ref.html
== 602200-2.html 602200-2-ref.html
# Canvas with a fractional margin does not snap properly; see bug 1580534
fuzzy-if(Android,0-8,0-20) fails-if(webrender) == 602200-3.html 602200-3-ref.html
fuzzy-if(Android,0-8,0-20) == 602200-3.html 602200-3-ref.html
== 602200-4.html 602200-4-ref.html
== 603423-1.html 603423-1-ref.html
== 604737.html 604737-ref.html
@ -2096,12 +2095,12 @@ skip-if(!asyncPan) == 1544895.html 1544895-ref.html
== 1547759-1.html 1547759-1-ref.html
== 1548809.html 1548809-ref.html
!= 1552789-1.html 1552789-ref-1.html
pref(image.downscale-during-decode.enabled,true) == 1553571-1.html 1553571-1-ref.html
pref(image.downscale-during-decode.enabled,true) fuzzy-if(webrender,3-4,17665-18088) == 1553571-1.html 1553571-1-ref.html
== 1558937-1.html 1558937-1-ref.html
!= 1563484.html 1563484-notref.html
== 1563484.html 1563484-ref.html
fuzzy-if(!webrender||!winWidget,254-255,464-1613) fuzzy-if(geckoview&&webrender,253-253,1392-1397) == 1562733-rotated-nastaliq-1.html 1562733-rotated-nastaliq-1-ref.html
fuzzy-if(winWidget&&webrender,0-31,0-3) fuzzy-if(geckoview&&webrender,0-93,0-26) == 1562733-rotated-nastaliq-2.html 1562733-rotated-nastaliq-2-ref.html
fuzzy-if(winWidget&&webrender,0-31,0-3) fuzzy-if(geckoview&&webrender,0-93,0-16) == 1562733-rotated-nastaliq-2.html 1562733-rotated-nastaliq-2-ref.html
test-pref(plain_text.wrap_long_lines,false) != 1565129.txt 1565129.txt
fuzzy(0-32,0-8) fuzzy-if(Android&&webrender,0-32,0-1458) == 1576553-1.html 1576553-1-ref.html
== 1579953-2.html 1579953-2-ref.html

View File

@ -38,7 +38,7 @@ fuzzy-if(d2d||azureSkia||gtkWidget,0-10,0-4800) == background-blending-soft-ligh
fuzzy-if(azureSkia||d2d||gtkWidget,0-1,0-40000) == background-blending-image-color-959674.html background-blending-image-color-959674-ref.html
#fuzzy due to inconsistencies in rounded rect cliping between parent and child; may be related to antialiasing. Between platforms, the max difference is the same, and the number of different pixels is either 36 or 37. (Win, Mac and Lin)
fuzzy(0-65,0-53) fuzzy-if(geckoview&&webrender,63-64,163-328) == mix-blend-mode-952051.html mix-blend-mode-952051-ref.html
fuzzy(0-65,0-53) fuzzy-if(geckoview&&webrender,64-64,163-163) == mix-blend-mode-952051.html mix-blend-mode-952051-ref.html
fuzzy-if(d3d11,0-49,0-200) == mix-blend-mode-and-filter.html mix-blend-mode-and-filter-ref.html
fuzzy-if(d3d11,0-1,0-5) == mix-blend-mode-and-filter.svg mix-blend-mode-and-filter-ref.svg

View File

@ -1,5 +1,5 @@
== box-decoration-break-1.html box-decoration-break-1-ref.html
fuzzy(0-1,0-20) fuzzy-if(skiaContent,0-1,0-700) == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1-ref.html
fuzzy(0-1,0-20) fuzzy-if(skiaContent,0-1,0-700) fuzzy-if(webrender,20-26,8891-12681) == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1-ref.html
skip-if(verify) fuzzy(0-45,0-460) fuzzy-if(skiaContent,0-57,0-439) fuzzy-if(Android,0-57,0-1330) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == box-decoration-break-with-outset-box-shadow-1.html box-decoration-break-with-outset-box-shadow-1-ref.html # Bug 1386543, bug 1392106
random-if(!gtkWidget||webrender) == box-decoration-break-border-image.html box-decoration-break-border-image-ref.html
== box-decoration-break-block-border-padding.html box-decoration-break-block-border-padding-ref.html

View File

@ -23,7 +23,7 @@ fuzzy-if(cocoaWidget,0-135,0-56) == dir-6a.html dir-6a-ref.html
== css-spacing-1.html css-spacing-1-ref.html
pref(mathml.disabled,true) == disabled-scriptlevel-1.html disabled-scriptlevel-1-ref.html
pref(mathml.disabled,true) == disabled-scriptlevel-1.xhtml disabled-scriptlevel-1-ref.xhtml
random-if(smallScreen&&Android) fuzzy(0-255,0-200) fuzzy-if(geckoview&&webrender,216-216,312-314) fuzzy-if(webrender&&winWidget,114-255,265-361) fuzzy-if(webrender&&OSX,79-79,314-314) == mirror-op-1.html mirror-op-1-ref.html
random-if(smallScreen&&Android) fuzzy(0-255,0-200) fuzzy-if(webrender&&winWidget,114-255,265-304) fuzzy-if(webrender&&OSX,87-87,242-242) == mirror-op-1.html mirror-op-1-ref.html
!= mirror-op-2.html mirror-op-2-ref.html
!= mirror-op-3.html mirror-op-3-ref.html
!= mirror-op-4.html mirror-op-4-ref.html

View File

@ -50,6 +50,6 @@ fuzzy-if(Android,0-8,0-630) fuzzy-if(OSX,0-1,0-11) fuzzy-if(skiaContent,0-1,0-22
== block-in-inline-continuations.html block-in-inline-continuations-ref.html
== iframe-1.html iframe-1-ref.html
== transformed-1.html transformed-1-ref.html
fuzzy-if(Android,0-4,0-4) fuzzy-if(webrender&&gtkWidget,31-31,24-24) fuzzy-if(webrender&&cocoaWidget,8-8,37-37) skip-if(!asyncPan) == transformed-2.html transformed-2-ref.html
skip-if(!asyncPan) fuzzy-if(Android,0-10,0-4) fuzzy-if(webrender&&gtkWidget,57-57,24-24) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) == nested-sticky-1.html nested-sticky-1-ref.html
skip-if(!asyncPan) fuzzy-if(Android,0-10,0-4) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),0-4,0-104) fuzzy-if(webrender&&gtkWidget,57-57,24-24) fuzzy-if(webrender,cocoaWidget,16-16,40-40) == nested-sticky-2.html nested-sticky-2-ref.html
fuzzy-if(Android,0-2,0-4) skip-if(!asyncPan) == transformed-2.html transformed-2-ref.html
skip-if(!asyncPan) fuzzy-if(Android,0-3,0-4) == nested-sticky-1.html nested-sticky-1-ref.html
skip-if(!asyncPan) fuzzy-if(Android,0-3,0-4) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),0-4,0-104) == nested-sticky-2.html nested-sticky-2-ref.html

View File

@ -148,9 +148,9 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1188061-2-nsChangeHint_U
# tests involving sideways-lr mode
== 1193519-sideways-lr-1.html 1193519-sideways-lr-1-ref.html
== 1193519-sideways-lr-2.html 1193519-sideways-lr-2-ref.html
fuzzy-if(winWidget,0-3,0-84) fails-if(webrender&&winWidget) == 1193519-sideways-lr-3.html 1193519-sideways-lr-3-ref.html
fuzzy-if(winWidget,0-3,0-112) fails-if(webrender&&!cocoaWidget) fails-if(Android) == 1193519-sideways-lr-4.html 1193519-sideways-lr-4-ref.html # see bug 1366692. Rounding error with WR enabled, and on Android.
fuzzy-if(gtkWidget,0-255,0-6) fuzzy-if(cocoaWidget,0-65,0-69) fuzzy-if(geckoview&&webrender,0-255,0-7) == 1193519-sideways-lr-decoration-1.html 1193519-sideways-lr-decoration-1-ref.html
fuzzy-if(winWidget,0-3,0-84) fails-if(webrender&&!gtkWidget) == 1193519-sideways-lr-3.html 1193519-sideways-lr-3-ref.html
fuzzy-if(winWidget,0-3,0-112) fails-if(webrender||Android) == 1193519-sideways-lr-4.html 1193519-sideways-lr-4-ref.html # see bug 1366692. Rounding error with WR enabled, and on Android.
fuzzy-if(gtkWidget,0-255,0-6) fuzzy-if(cocoaWidget,0-65,0-69) fuzzy-if(geckoview&&webrender,0-255,0-4) == 1193519-sideways-lr-decoration-1.html 1193519-sideways-lr-decoration-1-ref.html
== 1196887-1-computed-display-inline-block.html 1196887-1-computed-display-inline-block-ref.html
== 1205787-legacy-svg-values-1.html 1205787-legacy-svg-values-1-ref.html

View File

@ -6925,19 +6925,20 @@ static void CreateWRCommandsForBeveledBorder(
for (const auto& segment : segments) {
auto rect = LayoutDeviceRect::FromUnknownRect(NSRectToRect(
segment.mRect + aOffset, aBorderParams.mAppUnitsPerDevPixel));
auto r = wr::ToLayoutRect(rect);
auto roundedRect = wr::ToRoundedLayoutRect(rect);
auto color = wr::ToColorF(ToDeviceColor(segment.mColor));
// Adjust for the start bevel if needed.
AdjustAndPushBevel(aBuilder, r, segment.mColor, segment.mStartBevel,
aBorderParams.mAppUnitsPerDevPixel,
AdjustAndPushBevel(aBuilder, roundedRect, segment.mColor,
segment.mStartBevel, aBorderParams.mAppUnitsPerDevPixel,
aBorderParams.mBackfaceIsVisible, true);
AdjustAndPushBevel(aBuilder, r, segment.mColor, segment.mEndBevel,
AdjustAndPushBevel(aBuilder, roundedRect, segment.mColor, segment.mEndBevel,
aBorderParams.mAppUnitsPerDevPixel,
aBorderParams.mBackfaceIsVisible, false);
aBuilder.PushRect(r, r, aBorderParams.mBackfaceIsVisible, color);
aBuilder.PushRect(roundedRect, roundedRect,
aBorderParams.mBackfaceIsVisible, color);
}
}
@ -6952,7 +6953,7 @@ static void CreateWRCommandsForBorderSegment(
auto borderRect = LayoutDeviceRect::FromUnknownRect(NSRectToRect(
aBorderParams.mBorderRect + aOffset, aBorderParams.mAppUnitsPerDevPixel));
wr::LayoutRect r = wr::ToLayoutRect(borderRect);
wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(borderRect);
wr::BorderSide wrSide[4];
NS_FOR_CSS_SIDES(i) {
wrSide[i] = wr::ToBorderSide(ToDeviceColor(aBorderParams.mBorderColor),
@ -6960,7 +6961,8 @@ static void CreateWRCommandsForBorderSegment(
}
const bool horizontal = aBorderParams.mStartBevelSide == eSideTop ||
aBorderParams.mStartBevelSide == eSideBottom;
auto borderWidth = horizontal ? r.size.height : r.size.width;
auto borderWidth =
horizontal ? roundedRect.size.height : roundedRect.size.width;
// All border style is set to none except left side. So setting the widths of
// each side to width of rect is fine.
@ -6976,8 +6978,9 @@ static void CreateWRCommandsForBorderSegment(
}
Range<const wr::BorderSide> wrsides(wrSide, 4);
aBuilder.PushBorder(r, r, aBorderParams.mBackfaceIsVisible, borderWidths,
wrsides, wr::EmptyBorderRadius());
aBuilder.PushBorder(roundedRect, roundedRect,
aBorderParams.mBackfaceIsVisible, borderWidths, wrsides,
wr::EmptyBorderRadius());
}
void BCBlockDirSeg::CreateWebRenderCommands(

View File

@ -418,6 +418,7 @@ ImgDrawResult nsImageBoxFrame::CreateWebRenderCommands(
const int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect fillRect =
LayoutDeviceRect::FromAppUnits(dest, appUnitsPerDevPixel);
fillRect.Round();
Maybe<SVGImageContext> svgContext;
gfx::IntSize decodeSize =
@ -441,9 +442,12 @@ ImgDrawResult nsImageBoxFrame::CreateWebRenderCommands(
if (key.isNothing()) {
return result;
}
wr::LayoutRect fill = wr::ToLayoutRect(fillRect);
aBuilder.PushImage(fill, fill, !BackfaceIsHidden(), rendering, key.value());
LayoutDeviceSize gapSize(0, 0);
aBuilder.PushImage(fill, fill, !BackfaceIsHidden(),
wr::ToLayoutSize(fillRect.Size()),
wr::ToLayoutSize(gapSize), rendering, key.value());
return result;
}

View File

@ -2,5 +2,3 @@
expected:
if (os == "android") and not e10s: FAIL
if (os == "android") and e10s: PASS
fuzzy:
if webrender: maxDifference=65;totalPixels=340

View File

@ -1,3 +0,0 @@
[mix-blend-mode-parent-with-3D-transform.html]
fuzzy:
if webrender: maxDifference=56;totalPixels=340

View File

@ -3436,8 +3436,8 @@ bool nsNativeThemeCocoa::CreateWebRenderCommandsForWidget(
mozilla::layers::RenderRootStateManager* aManager, nsIFrame* aFrame,
StyleAppearance aAppearance, const nsRect& aRect) {
nsPresContext* presContext = aFrame->PresContext();
wr::LayoutRect bounds =
wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(aRect, presContext->AppUnitsPerDevPixel()));
wr::LayoutRect bounds = wr::ToRoundedLayoutRect(
LayoutDeviceRect::FromAppUnits(aRect, presContext->AppUnitsPerDevPixel()));
EventStates eventState = GetContentState(aFrame, aAppearance);

View File

@ -1243,8 +1243,9 @@ bool nsNativeThemeGTK::CreateWebRenderCommandsForWidget(
mozilla::layers::RenderRootStateManager* aManager, nsIFrame* aFrame,
StyleAppearance aAppearance, const nsRect& aRect) {
nsPresContext* presContext = aFrame->PresContext();
wr::LayoutRect bounds = wr::ToLayoutRect(LayoutDeviceRect::FromAppUnits(
aRect, presContext->AppUnitsPerDevPixel()));
wr::LayoutRect bounds =
wr::ToRoundedLayoutRect(LayoutDeviceRect::FromAppUnits(
aRect, presContext->AppUnitsPerDevPixel()));
switch (aAppearance) {
case StyleAppearance::Window: