| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/graphics/compositing/PaintArtifactCompositor.h" | 5 #include "platform/graphics/compositing/PaintArtifactCompositor.h" |
| 6 | 6 |
| 7 #include "cc/layers/content_layer_client.h" | 7 #include "cc/layers/content_layer_client.h" |
| 8 #include "cc/layers/layer.h" | 8 #include "cc/layers/layer.h" |
| 9 #include "cc/layers/picture_layer.h" | 9 #include "cc/layers/picture_layer.h" |
| 10 #include "cc/playback/display_item_list.h" | 10 #include "cc/playback/display_item_list.h" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 const DisplayItemList& displayItems = artifact.getDisplayItemList(); | 116 const DisplayItemList& displayItems = artifact.getDisplayItemList(); |
| 117 for (const auto& displayItem : displayItems.itemsInPaintChunk(chunk)) | 117 for (const auto& displayItem : displayItems.itemsInPaintChunk(chunk)) |
| 118 appendDisplayItemToCcDisplayItemList(displayItem, list.get()); | 118 appendDisplayItemToCcDisplayItemList(displayItem, list.get()); |
| 119 | 119 |
| 120 list->CreateAndAppendPairedEndItem<cc::EndTransformDisplayItem>(); | 120 list->CreateAndAppendPairedEndItem<cc::EndTransformDisplayItem>(); |
| 121 | 121 |
| 122 list->Finalize(); | 122 list->Finalize(); |
| 123 return list; | 123 return list; |
| 124 } | 124 } |
| 125 | 125 |
| 126 static gfx::Transform transformToTransformSpace(const TransformPaintPropertyNode
* currentSpace, const TransformPaintPropertyNode* targetSpace) | |
| 127 { | |
| 128 TransformationMatrix matrix; | |
| 129 while (currentSpace != targetSpace) { | |
| 130 TransformationMatrix localMatrix = currentSpace->matrix(); | |
| 131 localMatrix.applyTransformOrigin(currentSpace->origin()); | |
| 132 matrix = localMatrix * matrix; | |
| 133 currentSpace = currentSpace->parent(); | |
| 134 } | |
| 135 return gfx::Transform(TransformationMatrix::toSkMatrix44(matrix)); | |
| 136 } | |
| 137 | |
| 138 const TransformPaintPropertyNode* localTransformSpace(const ClipPaintPropertyNod
e* clip) | |
| 139 { | |
| 140 return clip ? clip->localTransformSpace() : nullptr; | |
| 141 } | |
| 142 | |
| 143 scoped_refptr<cc::Layer> createClipLayer(const ClipPaintPropertyNode* node) | |
| 144 { | |
| 145 // TODO(jbroman): Handle rounded-rect clips. | |
| 146 // TODO(jbroman): Handle clips of non-integer size. | |
| 147 gfx::RectF clipRect = node->clipRect().rect(); | |
| 148 | |
| 149 // TODO(jbroman): This, and the similar logic in | |
| 150 // PaintArtifactCompositor::update, will need to be updated to account for | |
| 151 // other kinds of intermediate layers, such as those that apply effects. | |
| 152 // TODO(jbroman): This assumes that the transform space of this node's | |
| 153 // parent is an ancestor of this node's transform space. That's not | |
| 154 // necessarily true, and this should be fixed. crbug.com/597156 | |
| 155 gfx::Transform transform = transformToTransformSpace(localTransformSpace(nod
e), localTransformSpace(node->parent())); | |
| 156 gfx::Vector2dF offset = clipRect.OffsetFromOrigin(); | |
| 157 transform.Translate(offset.x(), offset.y()); | |
| 158 if (node->parent()) { | |
| 159 FloatPoint offsetDueToParentClipOffset = node->parent()->clipRect().rect
().location(); | |
| 160 gfx::Transform undoClipOffset; | |
| 161 undoClipOffset.Translate(-offsetDueToParentClipOffset.x(), -offsetDueToP
arentClipOffset.y()); | |
| 162 transform.ConcatTransform(undoClipOffset); | |
| 163 } | |
| 164 | |
| 165 scoped_refptr<cc::Layer> layer = cc::Layer::Create(); | |
| 166 layer->SetIsDrawable(false); | |
| 167 layer->SetMasksToBounds(true); | |
| 168 layer->SetPosition(gfx::PointF()); | |
| 169 layer->SetBounds(gfx::ToRoundedSize(clipRect.size())); | |
| 170 layer->SetTransform(transform); | |
| 171 return layer; | |
| 172 } | |
| 173 | |
| 174 class ClipLayerManager { | |
| 175 public: | |
| 176 ClipLayerManager(cc::Layer* rootLayer) | |
| 177 { | |
| 178 m_clipLayers.append(NodeLayerPair(nullptr, rootLayer)); | |
| 179 } | |
| 180 | |
| 181 cc::Layer* switchToNewClipLayer(const ClipPaintPropertyNode* clip) | |
| 182 { | |
| 183 // Walk up to the nearest common ancestor. | |
| 184 const auto* ancestor = propertyTreeNearestCommonAncestor<ClipPaintProper
tyNode>(clip, m_clipLayers.last().first); | |
| 185 while (m_clipLayers.last().first != ancestor) | |
| 186 m_clipLayers.removeLast(); | |
| 187 | |
| 188 // If the new one was an ancestor, we're done. | |
| 189 cc::Layer* ancestorClipLayer = m_clipLayers.last().second; | |
| 190 if (ancestor == clip) | |
| 191 return ancestorClipLayer; | |
| 192 | |
| 193 // Otherwise, we need to build new clip layers. | |
| 194 // We do this from the bottom up. | |
| 195 size_t numExistingClipLayers = m_clipLayers.size(); | |
| 196 scoped_refptr<cc::Layer> childLayer; | |
| 197 do { | |
| 198 scoped_refptr<cc::Layer> clipLayer = createClipLayer(clip); | |
| 199 m_clipLayers.append(NodeLayerPair(clip, clipLayer.get())); | |
| 200 if (childLayer) | |
| 201 clipLayer->AddChild(std::move(childLayer)); | |
| 202 childLayer = std::move(clipLayer); | |
| 203 clip = clip->parent(); | |
| 204 } while (ancestor != clip); | |
| 205 ancestorClipLayer->AddChild(std::move(childLayer)); | |
| 206 | |
| 207 // Rearrange the new clip layers to be in top-down order, like they | |
| 208 // should be. | |
| 209 std::reverse(m_clipLayers.begin() + numExistingClipLayers, m_clipLayers.
end()); | |
| 210 | |
| 211 // Return the last (bottom-most) clip layer. | |
| 212 return m_clipLayers.last().second; | |
| 213 } | |
| 214 | |
| 215 private: | |
| 216 using NodeLayerPair = std::pair<const ClipPaintPropertyNode*, cc::Layer*>; | |
| 217 Vector<NodeLayerPair, 16> m_clipLayers; | |
| 218 }; | |
| 219 | |
| 220 scoped_refptr<cc::Layer> foreignLayerForPaintChunk(const PaintArtifact& paintArt
ifact, const PaintChunk& paintChunk, gfx::Vector2dF& layerOffset) | 126 scoped_refptr<cc::Layer> foreignLayerForPaintChunk(const PaintArtifact& paintArt
ifact, const PaintChunk& paintChunk, gfx::Vector2dF& layerOffset) |
| 221 { | 127 { |
| 222 if (paintChunk.size() != 1) | 128 if (paintChunk.size() != 1) |
| 223 return nullptr; | 129 return nullptr; |
| 224 | 130 |
| 225 const auto& displayItem = paintArtifact.getDisplayItemList()[paintChunk.begi
nIndex]; | 131 const auto& displayItem = paintArtifact.getDisplayItemList()[paintChunk.begi
nIndex]; |
| 226 if (!displayItem.isForeignLayer()) | 132 if (!displayItem.isForeignLayer()) |
| 227 return nullptr; | 133 return nullptr; |
| 228 | 134 |
| 229 const auto& foreignLayerDisplayItem = static_cast<const ForeignLayerDisplayI
tem&>(displayItem); | 135 const auto& foreignLayerDisplayItem = static_cast<const ForeignLayerDisplayI
tem&>(displayItem); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 effectNode.owner_id = ownerId; | 172 effectNode.owner_id = ownerId; |
| 267 effectNode.clip_id = clipNode.id; | 173 effectNode.clip_id = clipNode.id; |
| 268 effectNode.has_render_surface = true; | 174 effectNode.has_render_surface = true; |
| 269 | 175 |
| 270 cc::ScrollTree& scrollTree = propertyTrees->scroll_tree; | 176 cc::ScrollTree& scrollTree = propertyTrees->scroll_tree; |
| 271 scrollTree.clear(); | 177 scrollTree.clear(); |
| 272 } | 178 } |
| 273 | 179 |
| 274 } // namespace | 180 } // namespace |
| 275 | 181 |
| 276 void PaintArtifactCompositor::update(const PaintArtifact& paintArtifact) | |
| 277 { | |
| 278 DCHECK(m_rootLayer); | |
| 279 | |
| 280 if (m_extraDataForTestingEnabled) | |
| 281 m_extraDataForTesting = wrapUnique(new ExtraDataForTesting); | |
| 282 | |
| 283 // If the compositor is configured to expect using flat layer lists plus | |
| 284 // property trees, then we should provide that format. | |
| 285 cc::LayerTreeHost* host = m_rootLayer->layer_tree_host(); | |
| 286 const bool useLayerLists = host && host->settings().use_layer_lists; | |
| 287 if (useLayerLists) { | |
| 288 updateInLayerListMode(paintArtifact); | |
| 289 return; | |
| 290 } | |
| 291 | |
| 292 // TODO(jbroman): This should be incremental. | |
| 293 m_rootLayer->RemoveAllChildren(); | |
| 294 m_contentLayerClients.clear(); | |
| 295 | |
| 296 m_contentLayerClients.reserveCapacity(paintArtifact.paintChunks().size()); | |
| 297 ClipLayerManager clipLayerManager(m_rootLayer.get()); | |
| 298 for (const PaintChunk& paintChunk : paintArtifact.paintChunks()) { | |
| 299 cc::Layer* parent = clipLayerManager.switchToNewClipLayer(paintChunk.pro
perties.clip.get()); | |
| 300 | |
| 301 gfx::Vector2dF layerOffset; | |
| 302 scoped_refptr<cc::Layer> layer = layerForPaintChunk(paintArtifact, paint
Chunk, layerOffset); | |
| 303 // TODO(jbroman): Same as above. This assumes the transform space of the
current clip is | |
| 304 // an ancestor of the chunk. It is not necessarily true. crbug.com/59715
6 | |
| 305 gfx::Transform transform = transformToTransformSpace(paintChunk.properti
es.transform.get(), localTransformSpace(paintChunk.properties.clip.get())); | |
| 306 transform.Translate(layerOffset.x(), layerOffset.y()); | |
| 307 // If a clip was applied, its origin needs to be cancelled out in | |
| 308 // this transform. | |
| 309 if (const auto* clip = paintChunk.properties.clip.get()) { | |
| 310 FloatPoint offsetDueToClipOffset = clip->clipRect().rect().location(
); | |
| 311 gfx::Transform undoClipOffset; | |
| 312 undoClipOffset.Translate(-offsetDueToClipOffset.x(), -offsetDueToCli
pOffset.y()); | |
| 313 transform.ConcatTransform(undoClipOffset); | |
| 314 } | |
| 315 layer->SetTransform(transform); | |
| 316 layer->SetDoubleSided(!paintChunk.properties.backfaceHidden); | |
| 317 layer->SetNeedsDisplay(); | |
| 318 parent->AddChild(layer); | |
| 319 | |
| 320 if (m_extraDataForTestingEnabled) | |
| 321 m_extraDataForTesting->contentLayers.append(layer); | |
| 322 } | |
| 323 } | |
| 324 | |
| 325 scoped_refptr<cc::Layer> PaintArtifactCompositor::layerForPaintChunk(const Paint
Artifact& paintArtifact, const PaintChunk& paintChunk, gfx::Vector2dF& layerOffs
et) | 182 scoped_refptr<cc::Layer> PaintArtifactCompositor::layerForPaintChunk(const Paint
Artifact& paintArtifact, const PaintChunk& paintChunk, gfx::Vector2dF& layerOffs
et) |
| 326 { | 183 { |
| 327 DCHECK(paintChunk.size()); | 184 DCHECK(paintChunk.size()); |
| 328 | 185 |
| 329 // If the paint chunk is a foreign layer, just return that layer. | 186 // If the paint chunk is a foreign layer, just return that layer. |
| 330 if (scoped_refptr<cc::Layer> foreignLayer = foreignLayerForPaintChunk(paintA
rtifact, paintChunk, layerOffset)) | 187 if (scoped_refptr<cc::Layer> foreignLayer = foreignLayerForPaintChunk(paintA
rtifact, paintChunk, layerOffset)) |
| 331 return foreignLayer; | 188 return foreignLayer; |
| 332 | 189 |
| 333 // The common case: create a layer for painted content. | 190 // The common case: create a layer for painted content. |
| 334 gfx::Rect combinedBounds = enclosingIntRect(paintChunk.bounds); | 191 gfx::Rect combinedBounds = enclosingIntRect(paintChunk.bounds); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 | 412 |
| 556 dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | 413 dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); |
| 557 dummyLayer->SetTransformTreeIndex(kSecondaryRootNodeId); | 414 dummyLayer->SetTransformTreeIndex(kSecondaryRootNodeId); |
| 558 dummyLayer->SetClipTreeIndex(dummyClip.id); | 415 dummyLayer->SetClipTreeIndex(dummyClip.id); |
| 559 dummyLayer->SetEffectTreeIndex(effectNode.id); | 416 dummyLayer->SetEffectTreeIndex(effectNode.id); |
| 560 dummyLayer->SetScrollTreeIndex(kRealRootNodeId); | 417 dummyLayer->SetScrollTreeIndex(kRealRootNodeId); |
| 561 } | 418 } |
| 562 | 419 |
| 563 } // namespace | 420 } // namespace |
| 564 | 421 |
| 565 void PaintArtifactCompositor::updateInLayerListMode(const PaintArtifact& paintAr
tifact) | 422 void PaintArtifactCompositor::update(const PaintArtifact& paintArtifact) |
| 566 { | 423 { |
| 424 DCHECK(m_rootLayer); |
| 425 |
| 567 cc::LayerTreeHost* host = m_rootLayer->layer_tree_host(); | 426 cc::LayerTreeHost* host = m_rootLayer->layer_tree_host(); |
| 568 | 427 |
| 428 // The host will be null after detaching and this update can be ignored. |
| 429 // See: WebViewImpl::detachPaintArtifactCompositor(). |
| 430 if (!host) |
| 431 return; |
| 432 |
| 433 if (m_extraDataForTestingEnabled) |
| 434 m_extraDataForTesting = wrapUnique(new ExtraDataForTesting); |
| 435 |
| 569 setMinimalPropertyTrees(host->GetLayerTree()->property_trees(), m_rootLayer-
>id()); | 436 setMinimalPropertyTrees(host->GetLayerTree()->property_trees(), m_rootLayer-
>id()); |
| 570 m_rootLayer->RemoveAllChildren(); | 437 m_rootLayer->RemoveAllChildren(); |
| 571 m_rootLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | 438 m_rootLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); |
| 572 m_rootLayer->SetTransformTreeIndex(kSecondaryRootNodeId); | 439 m_rootLayer->SetTransformTreeIndex(kSecondaryRootNodeId); |
| 573 m_rootLayer->SetClipTreeIndex(kSecondaryRootNodeId); | 440 m_rootLayer->SetClipTreeIndex(kSecondaryRootNodeId); |
| 574 m_rootLayer->SetEffectTreeIndex(kSecondaryRootNodeId); | 441 m_rootLayer->SetEffectTreeIndex(kSecondaryRootNodeId); |
| 575 m_rootLayer->SetScrollTreeIndex(kRealRootNodeId); | 442 m_rootLayer->SetScrollTreeIndex(kRealRootNodeId); |
| 576 | 443 |
| 577 PropertyTreeManager propertyTreeManager(*host->GetLayerTree()->property_tree
s(), m_rootLayer.get()); | 444 PropertyTreeManager propertyTreeManager(*host->GetLayerTree()->property_tree
s(), m_rootLayer.get()); |
| 578 m_contentLayerClients.clear(); | 445 m_contentLayerClients.clear(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 603 if (m_extraDataForTestingEnabled) | 470 if (m_extraDataForTestingEnabled) |
| 604 m_extraDataForTesting->contentLayers.append(layer); | 471 m_extraDataForTesting->contentLayers.append(layer); |
| 605 } | 472 } |
| 606 | 473 |
| 607 // Mark the property trees as having been rebuilt. | 474 // Mark the property trees as having been rebuilt. |
| 608 host->GetLayerTree()->property_trees()->sequence_number = kPropertyTreeSeque
nceNumber; | 475 host->GetLayerTree()->property_trees()->sequence_number = kPropertyTreeSeque
nceNumber; |
| 609 host->GetLayerTree()->property_trees()->needs_rebuild = false; | 476 host->GetLayerTree()->property_trees()->needs_rebuild = false; |
| 610 } | 477 } |
| 611 | 478 |
| 612 } // namespace blink | 479 } // namespace blink |
| OLD | NEW |