Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(681)

Unified Diff: third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp

Issue 2565073002: Implement the algorithm to test merging and overlap in PaintArtifactCompositor. (Closed)
Patch Set: none Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
index 3542db9f82d5454f7d6cefb80898514bb72e5b52..ed0ab1fb2aeb0f17b1feefb915d01b8569599671 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
@@ -17,12 +17,15 @@
#include "cc/trees/property_tree.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/transform_node.h"
+#include "core/paint/PaintPropertyTreePrinter.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/paint/ClipPaintPropertyNode.h"
#include "platform/graphics/paint/DisplayItem.h"
#include "platform/graphics/paint/DrawingDisplayItem.h"
#include "platform/graphics/paint/ForeignLayerDisplayItem.h"
+#include "platform/graphics/paint/GeometryMapper.h"
#include "platform/graphics/paint/PaintArtifact.h"
+#include "platform/graphics/paint/PropertyTreeState.h"
#include "platform/graphics/paint/RasterInvalidationTracking.h"
#include "platform/graphics/paint/ScrollPaintPropertyNode.h"
#include "platform/graphics/paint/TransformPaintPropertyNode.h"
@@ -69,7 +72,6 @@ class PaintArtifactCompositor::ContentLayerClientImpl
public:
ContentLayerClientImpl(DisplayItem::Id paintChunkId)
: m_id(paintChunkId),
- m_debugName(paintChunkId.client.debugName()),
m_ccPictureLayer(cc::PictureLayer::Create(this)) {}
void SetDisplayList(scoped_refptr<cc::DisplayItemList> ccDisplayItemList) {
@@ -77,6 +79,12 @@ class PaintArtifactCompositor::ContentLayerClientImpl
}
void SetPaintableRegion(gfx::Rect region) { m_paintableRegion = region; }
+ void addPaintChunkDebugData(std::unique_ptr<JSONArray> json) {
+ m_paintChunkDebugData.append(std::move(json));
+ }
+
+ void clearPaintChunkDebugData() { m_paintChunkDebugData.clear(); }
+
// cc::ContentLayerClient
gfx::Rect PaintableRegion() override { return m_paintableRegion; }
scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList(
@@ -132,7 +140,6 @@ class PaintArtifactCompositor::ContentLayerClientImpl
std::unique_ptr<JSONObject> layerAsJSON() {
std::unique_ptr<JSONObject> json = JSONObject::create();
- json->setString("name", m_debugName);
IntSize bounds(m_ccPictureLayer->bounds().width(),
m_ccPictureLayer->bounds().height());
if (!bounds.isEmpty())
@@ -140,6 +147,12 @@ class PaintArtifactCompositor::ContentLayerClientImpl
json->setBoolean("contentsOpaque", m_ccPictureLayer->contents_opaque());
json->setBoolean("drawsContent", m_ccPictureLayer->DrawsContent());
+ std::unique_ptr<JSONArray> paintChunkContentsArray = JSONArray::create();
+ for (const auto& debugData : m_paintChunkDebugData) {
+ paintChunkContentsArray->pushValue(debugData->clone());
+ }
+ json->setArray("paintChunkContents", std::move(paintChunkContentsArray));
+
ccLayersRasterInvalidationTrackingMap().asJSON(m_ccPictureLayer.get(),
json.get());
return json;
@@ -153,10 +166,11 @@ class PaintArtifactCompositor::ContentLayerClientImpl
private:
PaintChunk::Id m_id;
- String m_debugName;
scoped_refptr<cc::PictureLayer> m_ccPictureLayer;
scoped_refptr<cc::DisplayItemList> m_ccDisplayItemList;
gfx::Rect m_paintableRegion;
+
+ Vector<std::unique_ptr<JSONArray>> m_paintChunkDebugData;
};
PaintArtifactCompositor::PaintArtifactCompositor() {
@@ -224,7 +238,7 @@ static void appendDisplayItemToCcDisplayItemList(const DisplayItem& displayItem,
static scoped_refptr<cc::DisplayItemList> recordPaintChunk(
const PaintArtifact& artifact,
- const PaintChunk& chunk,
+ const PendingLayer& pendingLayer,
const gfx::Rect& combinedBounds) {
cc::DisplayItemListSettings settings;
scoped_refptr<cc::DisplayItemList> list =
@@ -238,8 +252,10 @@ static scoped_refptr<cc::DisplayItemList> recordPaintChunk(
list->CreateAndAppendPairedBeginItem<cc::TransformDisplayItem>(translation);
const DisplayItemList& displayItems = artifact.getDisplayItemList();
- for (const auto& displayItem : displayItems.itemsInPaintChunk(chunk))
- appendDisplayItemToCcDisplayItemList(displayItem, list.get());
+ for (const auto& paintChunk : pendingLayer.paintChunks) {
+ for (const auto& displayItem : displayItems.itemsInPaintChunk(paintChunk))
+ appendDisplayItemToCcDisplayItemList(displayItem, list.get());
+ }
list->CreateAndAppendPairedEndItem<cc::EndTransformDisplayItem>();
@@ -296,50 +312,73 @@ PaintArtifactCompositor::clientForPaintChunk(
: paintArtifact.getDisplayItemList()[paintChunk.beginIndex].getId()));
}
-scoped_refptr<cc::Layer> PaintArtifactCompositor::layerForPaintChunk(
+scoped_refptr<cc::Layer>
+PaintArtifactCompositor::compositedLayerForPendingLayer(
const PaintArtifact& paintArtifact,
- const PaintChunk& paintChunk,
+ const PendingLayer& pendingLayer,
gfx::Vector2dF& layerOffset,
Vector<std::unique_ptr<ContentLayerClientImpl>>& newContentLayerClients,
- RasterInvalidationTracking* tracking) {
- DCHECK(paintChunk.size());
+ RasterInvalidationTrackingMap<const PaintChunk>* trackingMap) {
+ DCHECK(pendingLayer.paintChunks.size());
+ const PaintChunk& firstPaintChunk = pendingLayer.paintChunks[0];
+ DCHECK(firstPaintChunk.size());
+#if DCHECK_IS_ON
+ for (const auto& paintChunk : pendingLayer.paintChunks) {
+ DCHECK(paintChunk.properties == firstPaintChunk.properties);
+ }
+#endif
// If the paint chunk is a foreign layer, just return that layer.
- if (scoped_refptr<cc::Layer> foreignLayer =
- foreignLayerForPaintChunk(paintArtifact, paintChunk, layerOffset))
+ if (scoped_refptr<cc::Layer> foreignLayer = foreignLayerForPaintChunk(
+ paintArtifact, firstPaintChunk, layerOffset)) {
+ DCHECK(pendingLayer.paintChunks.size() == 1);
return foreignLayer;
+ }
// The common case: create or reuse a PictureLayer for painted content.
std::unique_ptr<ContentLayerClientImpl> contentLayerClient =
- clientForPaintChunk(paintChunk, paintArtifact);
+ clientForPaintChunk(firstPaintChunk, paintArtifact);
+
+ IntRect combinedBounds = enclosingIntRect(pendingLayer.bounds);
+ bool knownToBeOpaque = pendingLayer.knownToBeOpaque;
+ gfx::Rect ccCombinedBounds(combinedBounds);
- gfx::Rect combinedBounds = enclosingIntRect(paintChunk.bounds);
scoped_refptr<cc::DisplayItemList> displayList =
- recordPaintChunk(paintArtifact, paintChunk, combinedBounds);
+ recordPaintChunk(paintArtifact, pendingLayer, ccCombinedBounds);
contentLayerClient->SetDisplayList(std::move(displayList));
- contentLayerClient->SetPaintableRegion(gfx::Rect(combinedBounds.size()));
+ contentLayerClient->SetPaintableRegion(gfx::Rect(ccCombinedBounds.size()));
- layerOffset = combinedBounds.OffsetFromOrigin();
+ layerOffset = ccCombinedBounds.OffsetFromOrigin();
scoped_refptr<cc::PictureLayer> ccPictureLayer =
contentLayerClient->ccPictureLayer();
- ccPictureLayer->SetBounds(combinedBounds.size());
+ ccPictureLayer->SetBounds(ccCombinedBounds.size());
ccPictureLayer->SetIsDrawable(true);
- if (paintChunk.knownToBeOpaque)
- ccPictureLayer->SetContentsOpaque(true);
- DCHECK(!tracking ||
- tracking->trackedRasterInvalidations.size() ==
- paintChunk.rasterInvalidationRects.size());
- for (unsigned index = 0; index < paintChunk.rasterInvalidationRects.size();
- ++index) {
- IntRect rect(enclosingIntRect(paintChunk.rasterInvalidationRects[index]));
- gfx::Rect ccInvalidationRect(rect.x(), rect.y(), std::max(0, rect.width()),
- std::max(0, rect.height()));
- // Raster paintChunk.rasterInvalidationRects is in the space of the
- // containing transform node, so need to subtract off the layer offset.
- ccInvalidationRect.Offset(-combinedBounds.OffsetFromOrigin());
- contentLayerClient->setNeedsDisplayRect(
- ccInvalidationRect,
- tracking ? &tracking->trackedRasterInvalidations[index] : nullptr);
+ ccPictureLayer->SetContentsOpaque(knownToBeOpaque);
+ contentLayerClient->clearPaintChunkDebugData();
+
+ for (const auto& paintChunk : pendingLayer.paintChunks) {
+ RasterInvalidationTracking* rasterTracking =
+ trackingMap ? trackingMap->find(&paintChunk) : nullptr;
+ DCHECK(!rasterTracking ||
+ rasterTracking->trackedRasterInvalidations.size() ==
+ paintChunk.rasterInvalidationRects.size());
+ for (unsigned index = 0; index < paintChunk.rasterInvalidationRects.size();
+ ++index) {
+ IntRect rect(enclosingIntRect(paintChunk.rasterInvalidationRects[index]));
+ gfx::Rect ccInvalidationRect(rect.x(), rect.y(),
+ std::max(0, rect.width()),
+ std::max(0, rect.height()));
+ // Raster paintChunk.rasterInvalidationRects is in the space of the
+ // containing transform node, so need to subtract off the layer offset.
+ ccInvalidationRect.Offset(-ccCombinedBounds.OffsetFromOrigin());
+ contentLayerClient->setNeedsDisplayRect(
+ ccInvalidationRect,
+ rasterTracking ? &rasterTracking->trackedRasterInvalidations[index]
+ : nullptr);
+ }
+ contentLayerClient->addPaintChunkDebugData(
+ paintArtifact.getDisplayItemList().subsequenceAsJSON(
+ paintChunk.beginIndex, paintChunk.endIndex, false, true));
}
newContentLayerClients.append(std::move(contentLayerClient));
@@ -755,11 +794,98 @@ void PropertyTreeManager::buildEffectNodesRecursively(
} // namespace
+static bool canMergeInto(const PaintChunk& newChunk,
+ const PendingLayer& candidatePendingLayer) {
+ DCHECK(candidatePendingLayer.paintChunks.size() >= 1);
+ const PaintChunk& firstLayerChunk = candidatePendingLayer.paintChunks[0];
+
+ PropertyTreeState newChunkProperties(
+ newChunk.properties.transform.get(), newChunk.properties.clip.get(),
+ newChunk.properties.effect.get(), newChunk.properties.scroll.get());
+
+ PropertyTreeState currentLayerProperties(
+ firstLayerChunk.properties.transform.get(),
+ firstLayerChunk.properties.clip.get(),
+ firstLayerChunk.properties.effect.get(),
+ firstLayerChunk.properties.scroll.get());
+
+ if (firstLayerChunk.properties.hasDirectCompositingReasons() ||
+ newChunk.properties.hasDirectCompositingReasons())
+ return false;
+
+ for (PropertyTreeStateIterator it(newChunkProperties); it.hasNext();
+ it.next()) {
+ if (it.current().hasDirectCompositingReasons())
+ return false;
+
+ if (it.current() == currentLayerProperties)
+ return true;
+ }
+ return false;
+}
+
+static bool overlaps(const PaintChunk& paintChunk,
+ const PendingLayer& candidatePendingLayer,
+ GeometryMapper& geometryMapper) {
+ PropertyTreeState rootPropertyTreeState(
+ TransformPaintPropertyNode::root(), ClipPaintPropertyNode::root(),
+ EffectPaintPropertyNode::root(), ScrollPaintPropertyNode::root());
+
+ FloatRect paintChunkScreenVisualRect(paintChunk.bounds);
+ PropertyTreeState paintChunkPropertyState(
+ paintChunk.properties.transform.get(), paintChunk.properties.clip.get(),
+ paintChunk.properties.effect.get(), paintChunk.properties.scroll.get());
+ bool success = false;
+ geometryMapper.localToVisualRectInAncestorSpace(
+ paintChunkScreenVisualRect, paintChunkPropertyState,
+ rootPropertyTreeState, success);
+ DCHECK(success);
+
+ PropertyTreeState candidatePendingLayerPropertyState(
+ candidatePendingLayer.paintChunks[0].properties.transform.get(),
+ candidatePendingLayer.paintChunks[0].properties.clip.get(),
+ candidatePendingLayer.paintChunks[0].properties.effect.get(),
+ candidatePendingLayer.paintChunks[0].properties.scroll.get());
+
+ FloatRect pendingLayerScreenVisualRect(candidatePendingLayer.bounds);
+ success = false;
+ geometryMapper.localToVisualRectInAncestorSpace(
+ pendingLayerScreenVisualRect, candidatePendingLayerPropertyState,
+ rootPropertyTreeState, success);
+ DCHECK(success);
+
+ return paintChunkScreenVisualRect.intersects(pendingLayerScreenVisualRect);
+ return true;
+}
+
+void PaintArtifactCompositor::collectPendingLayers(
+ const Vector<PaintChunk>& paintChunks,
+ Vector<PendingLayer>& pendingLayers) {
+ GeometryMapper geometryMapper;
+ for (const PaintChunk& paintChunk : paintChunks) {
+ bool createNew = true;
+ for (Vector<PendingLayer>::reverse_iterator candidatePendingLayer =
+ pendingLayers.rbegin();
+ candidatePendingLayer != pendingLayers.rend();
+ ++candidatePendingLayer) {
+ if (canMergeInto(paintChunk, *candidatePendingLayer)) {
+ candidatePendingLayer->add(paintChunk);
+ createNew = false;
+ break;
+ }
+ if (overlaps(paintChunk, *candidatePendingLayer, geometryMapper)) {
+ break;
+ }
+ }
+ if (createNew)
+ pendingLayers.append(PendingLayer(paintChunk));
+ }
+}
+
void PaintArtifactCompositor::update(
const PaintArtifact& paintArtifact,
RasterInvalidationTrackingMap<const PaintChunk>* rasterChunkInvalidations) {
DCHECK(m_rootLayer);
-
cc::LayerTree* layerTree = m_rootLayer->GetLayerTree();
// The tree will be null after detaching and this update can be ignored.
@@ -776,23 +902,26 @@ void PaintArtifactCompositor::update(
PropertyTreeManager propertyTreeManager(*layerTree->property_trees(),
m_rootLayer.get());
+ Vector<PendingLayer> pendingLayers;
+ collectPendingLayers(paintArtifact.paintChunks(), pendingLayers);
+
Vector<std::unique_ptr<ContentLayerClientImpl>> newContentLayerClients;
newContentLayerClients.reserveCapacity(paintArtifact.paintChunks().size());
- for (const PaintChunk& paintChunk : paintArtifact.paintChunks()) {
+
+ for (const PendingLayer& pendingLayer : pendingLayers) {
gfx::Vector2dF layerOffset;
- scoped_refptr<cc::Layer> layer = layerForPaintChunk(
- paintArtifact, paintChunk, layerOffset, newContentLayerClients,
- rasterChunkInvalidations ? rasterChunkInvalidations->find(&paintChunk)
- : nullptr);
+ scoped_refptr<cc::Layer> layer = compositedLayerForPendingLayer(
+ paintArtifact, pendingLayer, layerOffset, newContentLayerClients,
+ rasterChunkInvalidations);
int transformId = propertyTreeManager.compositorIdForTransformNode(
- paintChunk.properties.transform.get());
+ pendingLayer.paintChunks[0].properties.transform.get());
int scrollId = propertyTreeManager.compositorIdForScrollNode(
- paintChunk.properties.scroll.get());
+ pendingLayer.paintChunks[0].properties.scroll.get());
int clipId = propertyTreeManager.compositorIdForClipNode(
- paintChunk.properties.clip.get());
+ pendingLayer.paintChunks[0].properties.clip.get());
int effectId = propertyTreeManager.switchToEffectNode(
- *paintChunk.properties.effect.get());
+ *pendingLayer.paintChunks[0].properties.effect.get());
propertyTreeManager.updateScrollOffset(layer->id(), scrollId);
@@ -812,7 +941,7 @@ void PaintArtifactCompositor::update(
->sorting_context_id);
layer->SetShouldCheckBackfaceVisibility(
- paintChunk.properties.backfaceHidden);
+ pendingLayer.paintChunks[0].properties.backfaceHidden);
if (m_extraDataForTestingEnabled)
m_extraDataForTesting->contentLayers.append(layer);

Powered by Google App Engine
This is Rietveld 408576698