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 ] ...@@ -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/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/positioning/static-distance-with-positioned-ancestor.html [ Pass ]
crbug.com/563667 virtual/spv2/fast/block/float/clamped-right-float.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 # In imported/web-platform-tests/html/, we prefer checking in failure
# expectation files. The following tests with [ Failure ] don't have failure # expectation files. The following tests with [ Failure ] don't have failure
......
...@@ -57,6 +57,8 @@ public: ...@@ -57,6 +57,8 @@ public:
LayoutObjectDrawingRecorder(GraphicsContext& context, const LayoutObject& layoutObject, PaintPhase phase, const IntRect& clip, const LayoutPoint& paintOffset) LayoutObjectDrawingRecorder(GraphicsContext& context, const LayoutObject& layoutObject, PaintPhase phase, const IntRect& clip, const LayoutPoint& paintOffset)
: LayoutObjectDrawingRecorder(context, layoutObject, DisplayItem::paintPhaseToDrawingType(phase), FloatRect(clip), paintOffset) { } : LayoutObjectDrawingRecorder(context, layoutObject, DisplayItem::paintPhaseToDrawingType(phase), FloatRect(clip), paintOffset) { }
void setKnownToBeOpaque() { ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); m_drawingRecorder->setKnownToBeOpaque(); }
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
void setUnderInvalidationCheckingMode(DrawingDisplayItem::UnderInvalidationCheckingMode mode) { m_drawingRecorder->setUnderInvalidationCheckingMode(mode); } void setUnderInvalidationCheckingMode(DrawingDisplayItem::UnderInvalidationCheckingMode mode) { m_drawingRecorder->setUnderInvalidationCheckingMode(mode); }
#endif #endif
......
...@@ -129,10 +129,13 @@ void ViewPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo) ...@@ -129,10 +129,13 @@ void ViewPainter::paintBoxDecorationBackground(const PaintInfo& paintInfo)
} }
Color combinedBackgroundColor = shouldDrawBackgroundInSeparateBuffer ? rootBackgroundColor : baseBackgroundColor.blend(rootBackgroundColor); 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); 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); context.fillRect(backgroundRect, Color(), SkXfermode::kClear_Mode);
}
for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); ++it) { for (auto it = reversedPaintList.rbegin(); it != reversedPaintList.rend(); ++it) {
ASSERT((*it)->clip() == BorderFillBox); ASSERT((*it)->clip() == BorderFillBox);
......
...@@ -140,6 +140,8 @@ void PaintArtifactCompositor::update(const PaintArtifact& paintArtifact) ...@@ -140,6 +140,8 @@ void PaintArtifactCompositor::update(const PaintArtifact& paintArtifact)
layer->SetBounds(combinedBounds.size()); layer->SetBounds(combinedBounds.size());
layer->SetTransform(transformToRoot(paintChunk.properties.transform.get())); layer->SetTransform(transformToRoot(paintChunk.properties.transform.get()));
layer->SetIsDrawable(true); layer->SetIsDrawable(true);
if (paintChunk.knownToBeOpaque)
layer->SetContentsOpaque(true);
layer->SetNeedsDisplay(); layer->SetNeedsDisplay();
m_contentLayerClients.append(contentLayerClient.release()); m_contentLayerClients.append(contentLayerClient.release());
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define DrawingDisplayItem_h #define DrawingDisplayItem_h
#include "platform/PlatformExport.h" #include "platform/PlatformExport.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/geometry/FloatPoint.h" #include "platform/geometry/FloatPoint.h"
#include "platform/graphics/paint/DisplayItem.h" #include "platform/graphics/paint/DisplayItem.h"
#include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/core/SkPicture.h"
...@@ -25,12 +26,14 @@ public: ...@@ -25,12 +26,14 @@ public:
DrawingDisplayItem(const DisplayItemClient& client DrawingDisplayItem(const DisplayItemClient& client
, Type type , Type type
, PassRefPtr<const SkPicture> picture , PassRefPtr<const SkPicture> picture
, bool knownToBeOpaque = false
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
, UnderInvalidationCheckingMode underInvalidationCheckingMode = CheckPicture , UnderInvalidationCheckingMode underInvalidationCheckingMode = CheckPicture
#endif #endif
) )
: DisplayItem(client, type, sizeof(*this)) : DisplayItem(client, type, sizeof(*this))
, m_picture(picture && picture->approximateOpCount() ? picture : nullptr) , m_picture(picture && picture->approximateOpCount() ? picture : nullptr)
, m_knownToBeOpaque(knownToBeOpaque)
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
, m_underInvalidationCheckingMode(underInvalidationCheckingMode) , m_underInvalidationCheckingMode(underInvalidationCheckingMode)
#endif #endif
...@@ -44,6 +47,8 @@ public: ...@@ -44,6 +47,8 @@ public:
const SkPicture* picture() const { return m_picture.get(); } const SkPicture* picture() const { return m_picture.get(); }
bool knownToBeOpaque() const { ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); return m_knownToBeOpaque; }
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
UnderInvalidationCheckingMode underInvalidationCheckingMode() const { return m_underInvalidationCheckingMode; } UnderInvalidationCheckingMode underInvalidationCheckingMode() const { return m_underInvalidationCheckingMode; }
bool equals(const DisplayItem& other) const final; bool equals(const DisplayItem& other) const final;
...@@ -56,6 +61,9 @@ private: ...@@ -56,6 +61,9 @@ private:
RefPtr<const SkPicture> m_picture; RefPtr<const SkPicture> m_picture;
// True if there are no transparent areas. Only used for SlimmingPaintV2.
const bool m_knownToBeOpaque;
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
UnderInvalidationCheckingMode m_underInvalidationCheckingMode; UnderInvalidationCheckingMode m_underInvalidationCheckingMode;
#endif #endif
......
...@@ -36,6 +36,7 @@ DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClie ...@@ -36,6 +36,7 @@ DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClie
: m_context(context) : m_context(context)
, m_displayItemClient(displayItemClient) , m_displayItemClient(displayItemClient)
, m_displayItemType(displayItemType) , m_displayItemType(displayItemType)
, m_knownToBeOpaque(false)
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
, m_displayItemPosition(m_context.paintController().newDisplayItemList().size()) , m_displayItemPosition(m_context.paintController().newDisplayItemList().size())
, m_underInvalidationCheckingMode(DrawingDisplayItem::CheckPicture) , m_underInvalidationCheckingMode(DrawingDisplayItem::CheckPicture)
...@@ -90,6 +91,7 @@ DrawingRecorder::~DrawingRecorder() ...@@ -90,6 +91,7 @@ DrawingRecorder::~DrawingRecorder()
m_context.paintController().createAndAppend<DrawingDisplayItem>(m_displayItemClient m_context.paintController().createAndAppend<DrawingDisplayItem>(m_displayItemClient
, m_displayItemType , m_displayItemType
, m_context.endRecording() , m_context.endRecording()
, m_knownToBeOpaque
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
, m_underInvalidationCheckingMode , m_underInvalidationCheckingMode
#endif #endif
......
...@@ -29,6 +29,8 @@ public: ...@@ -29,6 +29,8 @@ public:
DrawingRecorder(GraphicsContext&, const DisplayItemClient&, DisplayItem::Type, const FloatRect& cullRect); DrawingRecorder(GraphicsContext&, const DisplayItemClient&, DisplayItem::Type, const FloatRect& cullRect);
~DrawingRecorder(); ~DrawingRecorder();
void setKnownToBeOpaque() { ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); m_knownToBeOpaque = true; }
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
void setUnderInvalidationCheckingMode(DrawingDisplayItem::UnderInvalidationCheckingMode mode) { m_underInvalidationCheckingMode = mode; } void setUnderInvalidationCheckingMode(DrawingDisplayItem::UnderInvalidationCheckingMode mode) { m_underInvalidationCheckingMode = mode; }
#endif #endif
...@@ -37,6 +39,10 @@ private: ...@@ -37,6 +39,10 @@ private:
GraphicsContext& m_context; GraphicsContext& m_context;
const DisplayItemClient& m_displayItemClient; const DisplayItemClient& m_displayItemClient;
const DisplayItem::Type m_displayItemType; const DisplayItem::Type m_displayItemType;
// True if there are no transparent areas. Only used for SlimmingPaintV2.
bool m_knownToBeOpaque;
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
size_t m_displayItemPosition; size_t m_displayItemPosition;
DrawingDisplayItem::UnderInvalidationCheckingMode m_underInvalidationCheckingMode; DrawingDisplayItem::UnderInvalidationCheckingMode m_underInvalidationCheckingMode;
......
...@@ -7,23 +7,36 @@ ...@@ -7,23 +7,36 @@
#include "platform/TraceEvent.h" #include "platform/TraceEvent.h"
#include "platform/geometry/IntRect.h" #include "platform/geometry/IntRect.h"
#include "platform/graphics/paint/DrawingDisplayItem.h" #include "platform/graphics/paint/DrawingDisplayItem.h"
#include "third_party/skia/include/core/SkRegion.h"
namespace blink { namespace blink {
namespace { namespace {
void computeChunkBounds(const DisplayItemList& displayItems, Vector<PaintChunk>& paintChunks) void computeChunkBoundsAndOpaqueness(const DisplayItemList& displayItems, Vector<PaintChunk>& paintChunks)
{ {
for (PaintChunk& chunk : paintChunks) { for (PaintChunk& chunk : paintChunks) {
FloatRect bounds; FloatRect bounds;
SkRegion knownToBeOpaqueRegion;
for (const DisplayItem& item : displayItems.itemsInPaintChunk(chunk)) { for (const DisplayItem& item : displayItems.itemsInPaintChunk(chunk)) {
if (!item.isDrawing()) if (!item.isDrawing())
continue; continue;
const auto& drawing = static_cast<const DrawingDisplayItem&>(item); const auto& drawing = static_cast<const DrawingDisplayItem&>(item);
if (const SkPicture* picture = drawing.picture()) if (const SkPicture* picture = drawing.picture()) {
bounds.unite(picture->cullRect()); 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; chunk.bounds = bounds;
if (knownToBeOpaqueRegion.contains(enclosingIntRect(bounds)))
chunk.knownToBeOpaque = true;
} }
} }
...@@ -38,7 +51,7 @@ PaintArtifact::PaintArtifact(DisplayItemList displayItems, Vector<PaintChunk> pa ...@@ -38,7 +51,7 @@ PaintArtifact::PaintArtifact(DisplayItemList displayItems, Vector<PaintChunk> pa
: m_displayItemList(std::move(displayItems)) : m_displayItemList(std::move(displayItems))
, m_paintChunks(std::move(paintChunks)) , m_paintChunks(std::move(paintChunks))
{ {
computeChunkBounds(m_displayItemList, m_paintChunks); computeChunkBoundsAndOpaqueness(m_displayItemList, m_paintChunks);
} }
PaintArtifact::PaintArtifact(PaintArtifact&& source) PaintArtifact::PaintArtifact(PaintArtifact&& source)
......
...@@ -20,9 +20,9 @@ namespace blink { ...@@ -20,9 +20,9 @@ namespace blink {
// This is a Slimming Paint v2 class. // This is a Slimming Paint v2 class.
struct PaintChunk { struct PaintChunk {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); 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) 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. // Index of the first drawing in this chunk.
unsigned beginIndex; unsigned beginIndex;
...@@ -36,6 +36,9 @@ struct PaintChunk { ...@@ -36,6 +36,9 @@ struct PaintChunk {
// The total bounds of this paint chunk's contents. // The total bounds of this paint chunk's contents.
FloatRect bounds; FloatRect bounds;
// True if the bounds are filled entirely with opaque contents.
bool knownToBeOpaque;
}; };
inline bool operator==(const PaintChunk& a, const PaintChunk& b) inline bool operator==(const PaintChunk& a, const PaintChunk& b)
...@@ -43,7 +46,8 @@ 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 return a.beginIndex == b.beginIndex
&& a.endIndex == b.endIndex && a.endIndex == b.endIndex
&& a.properties == b.properties && 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) inline bool operator!=(const PaintChunk& a, const PaintChunk& b)
......
...@@ -49,7 +49,7 @@ void PrintTo(const PaintChunk& chunk, std::ostream* os) ...@@ -49,7 +49,7 @@ void PrintTo(const PaintChunk& chunk, std::ostream* os)
PrintTo(chunk.properties, os); PrintTo(chunk.properties, os);
*os << ", bounds="; *os << ", bounds=";
PrintTo(chunk.bounds, os); PrintTo(chunk.bounds, os);
*os << ")"; *os << ", knownToBeOpaque=" << chunk.knownToBeOpaque << ")";
} }
void PrintTo(const PaintChunkProperties& properties, std::ostream* os) 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