Commit d82d06a8 authored by pdr's avatar pdr Committed by Commit bot

Calculate and track display item opaqueness

Performance requires that some opaque chunks (such as the background)
are drawn using a layer set to be opaque. This patch implements this
idea by adding a bit to DrawingDisplayItem for whether the item is
known to be opaque. The "knownToBeOpaque" bit is used to mark layers
as explicitly opaque which lets us pass 2x more tests.

BUG=580355

Review URL: https://codereview.chromium.org/1632263002

Cr-Commit-Position: refs/heads/master@{#371941}
parent 1d6711a6
......@@ -402,7 +402,45 @@ crbug.com/537409 virtual/spv2/ [ Skip ]
crbug.com/563667 virtual/spv2/fast/block/basic/001.html [ Pass ]
crbug.com/563667 virtual/spv2/fast/block/positioning/static-distance-with-positioned-ancestor.html [ Pass ]
crbug.com/563667 virtual/spv2/fast/block/float/clamped-right-float.html [ Pass ]
crbug.com/577995 virtual/spv2/fast/block/basic/013.html [ Pass ]
crbug.com/580355 fast/block/basic/018.html [ Pass ]
crbug.com/580355 fast/block/basic/adding-near-anonymous-block.html [ Pass ]
crbug.com/580355 fast/block/basic/text-indent-rtl.html [ Pass ]
crbug.com/580355 fast/block/basic/truncation-rtl.html [ Pass ]
crbug.com/580355 fast/block/basic/white-space-pre-wraps.html [ Pass ]
crbug.com/580355 fast/block/float/001.html [ Pass ]
crbug.com/580355 fast/block/float/002.html [ Pass ]
crbug.com/580355 fast/block/float/float-in-float-hit-testing.html [ Pass ]
crbug.com/580355 fast/block/float/independent-align-positioning.html [ Pass ]
crbug.com/580355 fast/block/float/intruding-painted-twice.html [ Pass ]
crbug.com/580355 fast/block/float/nopaint-after-layer-destruction.html [ Pass ]
crbug.com/580355 fast/block/float/nopaint-after-layer-destruction2.html [ Pass ]
crbug.com/580355 fast/block/float/shrink-to-fit-width.html [ Pass ]
crbug.com/580355 fast/block/float/table-relayout.html [ Pass ]
crbug.com/580355 fast/block/float/vertical-move-relayout.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/001.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/005.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/010.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/011.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/012.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/015.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/016.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/017.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/019.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/020.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/056.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/059.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/001.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/005.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/010.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/011.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/012.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/015.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/016.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/017.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/019.html [ Pass ]
crbug.com/580355 fast/block/margin-collapse/block-inside-inline/020.html [ Pass ]
crbug.com/580355 fast/block/positioning/height-change.html [ Pass ]
crbug.com/580355 fast/block/positioning/relayout-on-position-change.html [ Pass ]
# In imported/web-platform-tests/html/, we prefer checking in failure
# expectation files. The following tests with [ Failure ] don't have failure
......
......@@ -57,6 +57,8 @@ public:
LayoutObjectDrawingRecorder(GraphicsContext& context, const LayoutObject& layoutObject, PaintPhase phase, const IntRect& clip, const LayoutPoint& paintOffset)
: LayoutObjectDrawingRecorder(context, layoutObject, DisplayItem::paintPhaseToDrawingType(phase), FloatRect(clip), paintOffset) { }
void setKnownToBeOpaque() { ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); m_drawingRecorder->setKnownToBeOpaque(); }
#if ENABLE(ASSERT)
void setUnderInvalidationCheckingMode(DrawingDisplayItem::UnderInvalidationCheckingMode mode) { m_drawingRecorder->setUnderInvalidationCheckingMode(mode); }
#endif
......
......@@ -129,10 +129,13 @@ void ViewPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo)
}
Color combinedBackgroundColor = shouldDrawBackgroundInSeparateBuffer ? rootBackgroundColor : baseBackgroundColor.blend(rootBackgroundColor);
if (combinedBackgroundColor.alpha())
if (combinedBackgroundColor.alpha()) {
if (!combinedBackgroundColor.hasAlpha() && RuntimeEnabledFeatures::slimmingPaintV2Enabled())
recorder.setKnownToBeOpaque();
context.fillRect(backgroundRect, combinedBackgroundColor, (shouldDrawBackgroundInSeparateBuffer || shouldClearCanvas) ? SkXfermode::kSrc_Mode : SkXfermode::kSrcOver_Mode);
else if (shouldClearCanvas && !shouldDrawBackgroundInSeparateBuffer)
} else if (shouldClearCanvas && !shouldDrawBackgroundInSeparateBuffer) {
context.fillRect(backgroundRect, Color(), SkXfermode::kClear_Mode);
}
for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); ++it) {
ASSERT((*it)->clip() == BorderFillBox);
......
......@@ -140,6 +140,8 @@ void PaintArtifactCompositor::update(const PaintArtifact& paintArtifact)
layer->SetBounds(combinedBounds.size());
layer->SetTransform(transformToRoot(paintChunk.properties.transform.get()));
layer->SetIsDrawable(true);
if (paintChunk.knownToBeOpaque)
layer->SetContentsOpaque(true);
layer->SetNeedsDisplay();
m_contentLayerClients.append(contentLayerClient.release());
......
......@@ -6,6 +6,7 @@
#define DrawingDisplayItem_h
#include "platform/PlatformExport.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/geometry/FloatPoint.h"
#include "platform/graphics/paint/DisplayItem.h"
#include "third_party/skia/include/core/SkPicture.h"
......@@ -25,12 +26,14 @@ public:
DrawingDisplayItem(const DisplayItemClient& client
, Type type
, PassRefPtr<const SkPicture> picture
, bool knownToBeOpaque = false
#if ENABLE(ASSERT)
, UnderInvalidationCheckingMode underInvalidationCheckingMode = CheckPicture
#endif
)
: DisplayItem(client, type, sizeof(*this))
, m_picture(picture && picture->approximateOpCount() ? picture : nullptr)
, m_knownToBeOpaque(knownToBeOpaque)
#if ENABLE(ASSERT)
, m_underInvalidationCheckingMode(underInvalidationCheckingMode)
#endif
......@@ -44,6 +47,8 @@ public:
const SkPicture* picture() const { return m_picture.get(); }
bool knownToBeOpaque() const { ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); return m_knownToBeOpaque; }
#if ENABLE(ASSERT)
UnderInvalidationCheckingMode underInvalidationCheckingMode() const { return m_underInvalidationCheckingMode; }
bool equals(const DisplayItem& other) const final;
......@@ -56,6 +61,9 @@ private:
RefPtr<const SkPicture> m_picture;
// True if there are no transparent areas. Only used for SlimmingPaintV2.
const bool m_knownToBeOpaque;
#if ENABLE(ASSERT)
UnderInvalidationCheckingMode m_underInvalidationCheckingMode;
#endif
......
......@@ -36,6 +36,7 @@ DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClie
: m_context(context)
, m_displayItemClient(displayItemClient)
, m_displayItemType(displayItemType)
, m_knownToBeOpaque(false)
#if ENABLE(ASSERT)
, m_displayItemPosition(m_context.paintController().newDisplayItemList().size())
, m_underInvalidationCheckingMode(DrawingDisplayItem::CheckPicture)
......@@ -90,6 +91,7 @@ DrawingRecorder::~DrawingRecorder()
m_context.paintController().createAndAppend<DrawingDisplayItem>(m_displayItemClient
, m_displayItemType
, m_context.endRecording()
, m_knownToBeOpaque
#if ENABLE(ASSERT)
, m_underInvalidationCheckingMode
#endif
......
......@@ -29,6 +29,8 @@ public:
DrawingRecorder(GraphicsContext&, const DisplayItemClient&, DisplayItem::Type, const FloatRect& cullRect);
~DrawingRecorder();
void setKnownToBeOpaque() { ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); m_knownToBeOpaque = true; }
#if ENABLE(ASSERT)
void setUnderInvalidationCheckingMode(DrawingDisplayItem::UnderInvalidationCheckingMode mode) { m_underInvalidationCheckingMode = mode; }
#endif
......@@ -37,6 +39,10 @@ private:
GraphicsContext& m_context;
const DisplayItemClient& m_displayItemClient;
const DisplayItem::Type m_displayItemType;
// True if there are no transparent areas. Only used for SlimmingPaintV2.
bool m_knownToBeOpaque;
#if ENABLE(ASSERT)
size_t m_displayItemPosition;
DrawingDisplayItem::UnderInvalidationCheckingMode m_underInvalidationCheckingMode;
......
......@@ -7,23 +7,36 @@
#include "platform/TraceEvent.h"
#include "platform/geometry/IntRect.h"
#include "platform/graphics/paint/DrawingDisplayItem.h"
#include "third_party/skia/include/core/SkRegion.h"
namespace blink {
namespace {
void computeChunkBounds(const DisplayItemList& displayItems, Vector<PaintChunk>& paintChunks)
void computeChunkBoundsAndOpaqueness(const DisplayItemList& displayItems, Vector<PaintChunk>& paintChunks)
{
for (PaintChunk& chunk : paintChunks) {
FloatRect bounds;
SkRegion knownToBeOpaqueRegion;
for (const DisplayItem& item : displayItems.itemsInPaintChunk(chunk)) {
if (!item.isDrawing())
continue;
const auto& drawing = static_cast<const DrawingDisplayItem&>(item);
if (const SkPicture* picture = drawing.picture())
bounds.unite(picture->cullRect());
if (const SkPicture* picture = drawing.picture()) {
const SkRect& pictureRect = picture->cullRect();
bounds.unite(pictureRect);
if (drawing.knownToBeOpaque()) {
// TODO(pdr): This may be too conservative and fail due to
// floating point precision issues.
SkIRect conservativelyRoundedPictureRect;
pictureRect.roundIn(&conservativelyRoundedPictureRect);
knownToBeOpaqueRegion.op(conservativelyRoundedPictureRect, SkRegion::kUnion_Op);
}
}
}
chunk.bounds = bounds;
if (knownToBeOpaqueRegion.contains(enclosingIntRect(bounds)))
chunk.knownToBeOpaque = true;
}
}
......@@ -38,7 +51,7 @@ PaintArtifact::PaintArtifact(DisplayItemList displayItems, Vector<PaintChunk> pa
: m_displayItemList(std::move(displayItems))
, m_paintChunks(std::move(paintChunks))
{
computeChunkBounds(m_displayItemList, m_paintChunks);
computeChunkBoundsAndOpaqueness(m_displayItemList, m_paintChunks);
}
PaintArtifact::PaintArtifact(PaintArtifact&& source)
......
......@@ -20,9 +20,9 @@ namespace blink {
// This is a Slimming Paint v2 class.
struct PaintChunk {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
PaintChunk() : beginIndex(0), endIndex(0) { }
PaintChunk() : beginIndex(0), endIndex(0), knownToBeOpaque(false) { }
PaintChunk(unsigned begin, unsigned end, const PaintChunkProperties& props)
: beginIndex(begin), endIndex(end), properties(props) { }
: beginIndex(begin), endIndex(end), properties(props), knownToBeOpaque(false) { }
// Index of the first drawing in this chunk.
unsigned beginIndex;
......@@ -36,6 +36,9 @@ struct PaintChunk {
// The total bounds of this paint chunk's contents.
FloatRect bounds;
// True if the bounds are filled entirely with opaque contents.
bool knownToBeOpaque;
};
inline bool operator==(const PaintChunk& a, const PaintChunk& b)
......@@ -43,7 +46,8 @@ inline bool operator==(const PaintChunk& a, const PaintChunk& b)
return a.beginIndex == b.beginIndex
&& a.endIndex == b.endIndex
&& a.properties == b.properties
&& a.bounds == b.bounds;
&& a.bounds == b.bounds
&& a.knownToBeOpaque == b.knownToBeOpaque;
}
inline bool operator!=(const PaintChunk& a, const PaintChunk& b)
......
......@@ -49,7 +49,7 @@ void PrintTo(const PaintChunk& chunk, std::ostream* os)
PrintTo(chunk.properties, os);
*os << ", bounds=";
PrintTo(chunk.bounds, os);
*os << ")";
*os << ", knownToBeOpaque=" << chunk.knownToBeOpaque << ")";
}
void PrintTo(const PaintChunkProperties& properties, std::ostream* os)
......
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