Commit ec37d4cc authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[PE] Fix subpixel accumulation for composited content layers

The content box rect was improperly snapped in the local space.
We should snap in the layout space instead, including subpixel
accumulation.

This is a duplicate of trchen@'s old CL
https://codereview.chromium.org/2172503002/ rebased on the current
trunk.

Bug: 627683
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_layout_tests_slimming_paint_v2;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I737871c4bafead28f1040d486a59f3203c0b0ead
Reviewed-on: https://chromium-review.googlesource.com/c/1271582
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarKenneth Russell <kbr@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600811}
parent 431f4144
......@@ -131,6 +131,11 @@ class PixelExpectations(GpuTestExpectations):
self.Fail('Pixel_OffscreenCanvasWebGLPaintAfterResize',
['android', 'nvidia'], bug=868596)
# TODO(wangxianzhu): temporarily suppress these two tests until new
# reference images are generated.
self.Fail('Pixel_OffscreenCanvasTransferToImageBitmap', bug=627683)
self.Fail('Pixel_OffscreenCanvasTransferToImageBitmapWorker', bug=627683)
# Fails on Nexus 5, 6 and 6P
self.Fail('Pixel_BackgroundImage',
['android', ('qualcomm', 'Adreno (TM) 330')], bug=883500)
......
......@@ -445,14 +445,14 @@ def ExperimentalCanvasFeaturesPages(base_name):
'pixel_offscreenCanvas_transferToImageBitmap_main.html',
base_name + '_OffscreenCanvasTransferToImageBitmap',
test_rect=[0, 0, 300, 300],
revision=5,
revision=6,
browser_args=browser_args),
PixelTestPage(
'pixel_offscreenCanvas_transferToImageBitmap_worker.html',
base_name + '_OffscreenCanvasTransferToImageBitmapWorker',
test_rect=[0, 0, 300, 300],
revision=5,
revision=6,
browser_args=browser_args),
PixelTestPage(
......
<!DOCTYPE html>
<style>
img {
width: 40.4px;
height: 30.3px;
}
</style>
<div>
Passes if each image is at the exact same location when they are composited or not.
</div>
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<!DOCTYPE html>
<style>
img {
width: 40.4px;
height: 30.3px;
will-change: transform;
}
</style>
<div>
Passes if each image is at the exact same location when they are composited or not.
</div>
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
<img src="../images/resources/blue-100.png">
......@@ -84,28 +84,20 @@ namespace blink {
using namespace HTMLNames;
static IntRect ContentsRect(const LayoutObject& layout_object) {
static LayoutRect ContentsRect(const LayoutObject& layout_object) {
if (!layout_object.IsBox())
return IntRect();
if (layout_object.IsCanvas()) {
return PixelSnappedIntRect(
ToLayoutHTMLCanvas(layout_object).ReplacedContentRect());
}
if (layout_object.IsVideo()) {
return PixelSnappedIntRect(
ToLayoutVideo(layout_object).ReplacedContentRect());
}
return PixelSnappedIntRect(
ToLayoutBox(layout_object).PhysicalContentBoxRect());
return LayoutRect();
if (layout_object.IsLayoutReplaced())
return ToLayoutReplaced(layout_object).ReplacedContentRect();
return ToLayoutBox(layout_object).PhysicalContentBoxRect();
}
static IntRect BackgroundRect(const LayoutObject& layout_object) {
static LayoutRect BackgroundRect(const LayoutObject& layout_object) {
if (!layout_object.IsBox())
return IntRect();
return LayoutRect();
const LayoutBox& box = ToLayoutBox(layout_object);
return PixelSnappedIntRect(box.PhysicalBackgroundRect(kBackgroundClipRect));
return box.PhysicalBackgroundRect(kBackgroundClipRect);
}
static inline bool IsTextureLayerCanvas(const LayoutObject& layout_object) {
......@@ -198,7 +190,6 @@ static FloatPoint StickyPositionOffsetForLayer(PaintLayer& layer) {
CompositedLayerMapping::CompositedLayerMapping(PaintLayer& layer)
: owning_layer_(layer),
content_offset_in_compositing_layer_dirty_(false),
pending_update_scope_(kGraphicsLayerUpdateNone),
is_main_frame_layout_view_layer_(false),
scrolling_contents_are_empty_(false),
......@@ -518,7 +509,6 @@ void CompositedLayerMapping::UpdateCompositedBounds() {
// FIXME: if this is really needed for performance, it would be better to
// store it on Layer.
composited_bounds_ = owning_layer_.BoundingBoxForCompositing();
content_offset_in_compositing_layer_dirty_ = true;
}
GraphicsLayer* CompositedLayerMapping::FrameContentsGraphicsLayer() const {
......@@ -565,7 +555,7 @@ void CompositedLayerMapping::UpdateAfterPartResize() {
child_containment_layer_
? FloatPoint(child_containment_layer_->GetPosition())
: FloatPoint();
document_layer->SetPosition(FloatPoint(FlooredIntPoint(
document_layer->SetPosition(FloatPoint(RoundedIntSize(
FloatPoint(ContentsBox().Location()) - parent_position)));
}
}
......@@ -1218,8 +1208,6 @@ void CompositedLayerMapping::UpdateGraphicsLayerGeometry(
UpdateOverflowControlsHostLayerGeometry(compositing_stacking_context,
compositing_container,
graphics_layer_parent_location);
UpdateContentsOffsetInCompositingLayer(
snapped_offset_from_composited_ancestor, graphics_layer_parent_location);
UpdateStickyConstraints(GetLayoutObject().StyleRef());
UpdateSquashingLayerGeometry(
graphics_layer_parent_location, compositing_container,
......@@ -1606,16 +1594,13 @@ void CompositedLayerMapping::UpdateChildContainmentLayerGeometry() {
void CompositedLayerMapping::UpdateChildTransformLayerGeometry() {
if (!child_transform_layer_)
return;
const IntRect border_box =
ToLayoutBox(owning_layer_.GetLayoutObject())
.PixelSnappedBorderBoxRect(SubpixelAccumulation());
child_transform_layer_->SetSize(gfx::Size(border_box.Size()));
child_transform_layer_->SetOffsetFromLayoutObject(
ToIntSize(border_box.Location()));
IntPoint parent_location(
child_transform_layer_->Parent()->OffsetFromLayoutObject());
child_transform_layer_->SetPosition(
FloatPoint(border_box.Location() - parent_location));
LayoutRect border_box =
ToLayoutBox(owning_layer_.GetLayoutObject()).BorderBoxRect();
border_box.Move(ContentOffsetInCompositingLayer());
child_transform_layer_->SetSize(gfx::Size(border_box.PixelSnappedSize()));
child_transform_layer_->SetOffsetFromLayoutObject(IntSize());
child_transform_layer_->SetPosition(FloatPoint(border_box.Location()));
}
void CompositedLayerMapping::UpdateMaskLayerGeometry() {
......@@ -1913,59 +1898,6 @@ void CompositedLayerMapping::UpdateContentsRect() {
graphics_layer_->SetContentsRect(PixelSnappedIntRect(ContentsBox()));
}
void CompositedLayerMapping::UpdateContentsOffsetInCompositingLayer(
const IntPoint& snapped_offset_from_composited_ancestor,
const IntPoint& graphics_layer_parent_location) {
// m_graphicsLayer is positioned relative to our compositing ancestor
// PaintLayer, but it's not positioned at the origin of m_owningLayer, it's
// offset by m_contentBounds.location(). This is what
// contentOffsetInCompositingLayer is meant to capture, roughly speaking
// (ignoring rounding and subpixel accumulation).
//
// Our ancestor graphics layers in this CLM (m_graphicsLayer and potentially
// m_ancestorClippingLayer) have pixel snapped, so if we don't adjust this
// offset, we'll see accumulated rounding errors due to that snapping.
//
// In order to ensure that we account for this rounding, we compute
// contentsOffsetInCompositingLayer in a somewhat roundabout way.
//
// our position = (desired position) - (inherited graphics layer offset).
//
// Precisely,
// Offset = snappedOffsetFromCompositedAncestor -
// offsetDueToAncestorGraphicsLayers (See code below)
// = snappedOffsetFromCompositedAncestor -
// (m_graphicsLayer->position() + graphicsLayerParentLocation)
// = snappedOffsetFromCompositedAncestor -
// (relativeCompositingBounds.location() -
// graphicsLayerParentLocation +
// graphicsLayerParentLocation)
// (See updateMainGraphicsLayerGeometry)
// = snappedOffsetFromCompositedAncestor -
// relativeCompositingBounds.location()
// = snappedOffsetFromCompositedAncestor -
// (pixelSnappedIntRect(contentBounds.location()) +
// snappedOffsetFromCompositedAncestor)
// (See computeBoundsOfOwningLayer)
// = -pixelSnappedIntRect(contentBounds.location())
//
// As you can see, we've ended up at the same spot
// (-contentBounds.location()), but by subtracting off our ancestor graphics
// layers positions, we can be sure we've accounted correctly for any pixel
// snapping due to ancestor graphics layers.
//
// And drawing of composited children takes into account the subpixel
// accumulation of this CLM already (through its own
// graphicsLayerParentLocation it appears).
FloatPoint offset_due_to_ancestor_graphics_layers =
FloatPoint(graphics_layer_->GetPosition()) +
graphics_layer_parent_location;
content_offset_in_compositing_layer_ =
LayoutSize(snapped_offset_from_composited_ancestor -
offset_due_to_ancestor_graphics_layers);
content_offset_in_compositing_layer_dirty_ = false;
}
void CompositedLayerMapping::UpdateDrawsContent() {
bool in_overlay_fullscreen_video = false;
if (GetLayoutObject().IsVideo()) {
......@@ -2958,12 +2890,12 @@ FloatPoint3D CompositedLayerMapping::ComputeTransformOrigin(
// Return the offset from the top-left of this compositing layer at which the
// LayoutObject's contents are painted.
LayoutSize CompositedLayerMapping::ContentOffsetInCompositingLayer() const {
DCHECK(!content_offset_in_compositing_layer_dirty_);
return content_offset_in_compositing_layer_;
return owning_layer_.SubpixelAccumulation() -
LayoutSize(graphics_layer_->OffsetFromLayoutObject());
}
LayoutRect CompositedLayerMapping::ContentsBox() const {
LayoutRect contents_box = LayoutRect(ContentsRect(GetLayoutObject()));
LayoutRect contents_box = ContentsRect(GetLayoutObject());
contents_box.Move(ContentOffsetInCompositingLayer());
return contents_box;
}
......
......@@ -455,9 +455,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
Color LayoutObjectBackgroundColor() const;
void UpdateBackgroundColor();
void UpdateContentsRect();
void UpdateContentsOffsetInCompositingLayer(
const IntPoint& snapped_offset_from_composited_ancestor,
const IntPoint& graphics_layer_parent_location);
void UpdateAfterPartResize();
void UpdateCompositingReasons();
......@@ -666,8 +663,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
LayoutRect composited_bounds_;
LayoutSize content_offset_in_compositing_layer_;
// We keep track of the scrolling contents offset, so that when it changes we
// can notify the ScrollingCoordinator, which passes on main-thread scrolling
// updates to the compositor.
......@@ -675,8 +670,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
const PaintLayer* clip_inheritance_ancestor_;
unsigned content_offset_in_compositing_layer_dirty_ : 1;
unsigned pending_update_scope_ : 2;
unsigned is_main_frame_layout_view_layer_ : 1;
......
......@@ -1177,35 +1177,35 @@ TEST_F(CompositedLayerMappingTest,
// direction to compensate. To make this a little clearer, for the first
// example here the layer positions are calculated as:
//
// m_graphicsLayer x = left_pos - shadow_spread + shadow_x_offset
// graphics_layer_ x = left_pos - shadow_spread + shadow_x_offset
// = 50 - 10 - 10
// = 30
//
// m_graphicsLayer y = top_pos - shadow_spread + shadow_y_offset
// graphics_layer_ y = top_pos - shadow_spread + shadow_y_offset
// = 50 - 10 + 0
// = 40
//
// contents x = 50 - m_graphicsLayer x = 50 - 30 = 20
// contents y = 50 - m_graphicsLayer y = 50 - 40 = 10
// contents x = 50 - graphics_layer_ x = 50 - 30 = 20
// contents y = 50 - graphics_layer_ y = 50 - 40 = 10
//
// The reason that perspective matters is that it affects which 'contents'
// layer is offset; m_childTransformLayer when using perspective, or
// m_scrollingLayer when there is no perspective.
// layer is offset; child_transform_layer_ when using perspective, or
// scrolling_layer_ when there is no perspective.
SetBodyInnerHTML(
"<div id='scroller' style='position: absolute; top: 50px; left: 50px; "
"width: 400px; height: 245px; overflow: auto; will-change: transform; "
"box-shadow: -10px 0 0 10px; perspective: 1px;'>"
" <div style='position: absolute; top: 50px; bottom: 0; width: 200px; "
"height: 200px;'></div>"
"</div>"
"<div id='scroller2' style='position: absolute; top: 400px; left: 50px; "
"width: 400px; height: 245px; overflow: auto; will-change: transform; "
"box-shadow: -10px 0 0 10px;'>"
" <div style='position: absolute; top: 50px; bottom: 0; width: 200px; "
"height: 200px;'></div>"
"</div>");
SetBodyInnerHTML(R"HTML(
<div id='scroller' style='position: absolute; top: 50px; left: 50px;
width: 400px; height: 245px; overflow: auto; will-change: transform;
box-shadow: -10px 0 0 10px; perspective: 1px;'>
<div style='position: absolute; top: 50px; bottom: 0; width: 200px;
height: 200px;'></div>
</div>
<div id='scroller2' style='position: absolute; top: 400px; left: 50px;
width: 400px; height: 245px; overflow: auto; will-change: transform;
box-shadow: -10px 0 0 10px;'>
<div style='position: absolute; top: 50px; bottom: 0; width: 200px;
height: 200px;'></div>
</div>
)HTML");
CompositedLayerMapping* mapping =
ToLayoutBlock(GetLayoutObjectByElementId("scroller"))
......
......@@ -30,10 +30,6 @@ void EmbeddedContentPainter::PaintReplaced(const PaintInfo& paint_info,
paint_offset +
layout_embedded_content_.ReplacedContentRect().Location()));
// Views don't support painting with a paint offset, but instead
// offset themselves using the frame rect location. To paint Views at
// our desired location, we need to apply paint offset as a transform, with
// the frame rect neutralized.
IntSize view_paint_offset =
paint_location - embedded_content_view->FrameRect().Location();
CullRect adjusted_cull_rect(paint_info.GetCullRect(), -view_paint_offset);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment