Chromium Code Reviews| 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" |
| 11 #include "cc/playback/display_item_list_settings.h" | 11 #include "cc/playback/display_item_list_settings.h" |
| 12 #include "cc/playback/drawing_display_item.h" | 12 #include "cc/playback/drawing_display_item.h" |
| 13 #include "cc/playback/transform_display_item.h" | 13 #include "cc/playback/transform_display_item.h" |
| 14 #include "cc/trees/layer_tree_host.h" | 14 #include "cc/trees/layer_tree_host.h" |
| 15 #include "cc/trees/property_tree.h" | |
| 15 #include "platform/RuntimeEnabledFeatures.h" | 16 #include "platform/RuntimeEnabledFeatures.h" |
| 16 #include "platform/graphics/paint/ClipPaintPropertyNode.h" | 17 #include "platform/graphics/paint/ClipPaintPropertyNode.h" |
| 17 #include "platform/graphics/paint/DisplayItem.h" | 18 #include "platform/graphics/paint/DisplayItem.h" |
| 18 #include "platform/graphics/paint/DrawingDisplayItem.h" | 19 #include "platform/graphics/paint/DrawingDisplayItem.h" |
| 19 #include "platform/graphics/paint/ForeignLayerDisplayItem.h" | 20 #include "platform/graphics/paint/ForeignLayerDisplayItem.h" |
| 20 #include "platform/graphics/paint/PaintArtifact.h" | 21 #include "platform/graphics/paint/PaintArtifact.h" |
| 21 #include "platform/graphics/paint/TransformPaintPropertyNode.h" | 22 #include "platform/graphics/paint/TransformPaintPropertyNode.h" |
| 22 #include "public/platform/Platform.h" | 23 #include "public/platform/Platform.h" |
| 23 #include "public/platform/WebCompositorSupport.h" | 24 #include "public/platform/WebCompositorSupport.h" |
| 24 #include "public/platform/WebLayer.h" | 25 #include "public/platform/WebLayer.h" |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 static const int kSecondaryRootNodeId = 1; | 263 static const int kSecondaryRootNodeId = 1; |
| 263 static const int kPropertyTreeSequenceNumber = 1; | 264 static const int kPropertyTreeSequenceNumber = 1; |
| 264 | 265 |
| 265 // Creates a minimal set of property trees for the compositor. | 266 // Creates a minimal set of property trees for the compositor. |
| 266 void setMinimalPropertyTrees(cc::PropertyTrees* propertyTrees, int ownerId) | 267 void setMinimalPropertyTrees(cc::PropertyTrees* propertyTrees, int ownerId) |
| 267 { | 268 { |
| 268 // cc's property trees expect a child of the actual root to be used. So we | 269 // cc's property trees expect a child of the actual root to be used. So we |
| 269 // need to create and populate an additional node for each type of tree. | 270 // need to create and populate an additional node for each type of tree. |
| 270 | 271 |
| 271 cc::TransformTree& transformTree = propertyTrees->transform_tree; | 272 cc::TransformTree& transformTree = propertyTrees->transform_tree; |
| 272 if (transformTree.size() < 2) { | 273 transformTree.clear(); |
| 273 transformTree.Insert(cc::TransformNode(), kRealRootNodeId); | 274 transformTree.Insert(cc::TransformNode(), kRealRootNodeId); |
| 274 cc::TransformNode& transformNode = *transformTree.back(); | 275 cc::TransformNode& transformNode = *transformTree.back(); |
| 275 transformTree.SetTargetId(transformNode.id, kRealRootNodeId); | 276 transformTree.SetTargetId(transformNode.id, kRealRootNodeId); |
| 276 transformTree.SetContentTargetId(transformNode.id, kSecondaryRootNodeId) ; | 277 transformTree.SetContentTargetId(transformNode.id, kSecondaryRootNodeId); |
| 277 transformNode.data.source_node_id = kRealRootNodeId; | 278 transformNode.data.source_node_id = kRealRootNodeId; |
| 278 transformNode.data.needs_local_transform_update = true; | 279 transformNode.data.needs_local_transform_update = true; |
| 279 transformNode.owner_id = ownerId; | 280 transformNode.owner_id = ownerId; |
| 280 transformTree.set_needs_update(true); | 281 transformTree.set_needs_update(true); |
| 281 } | |
| 282 DCHECK_EQ(transformTree.size(), 2u); | |
| 283 | 282 |
| 284 cc::ClipTree& clipTree = propertyTrees->clip_tree; | 283 cc::ClipTree& clipTree = propertyTrees->clip_tree; |
| 285 if (clipTree.size() < 2) { | 284 clipTree.clear(); |
| 286 clipTree.Insert(cc::ClipNode(), kRealRootNodeId); | 285 clipTree.Insert(cc::ClipNode(), kRealRootNodeId); |
| 287 cc::ClipNode& clipNode = *clipTree.back(); | 286 cc::ClipNode& clipNode = *clipTree.back(); |
| 288 clipNode.data.transform_id = kSecondaryRootNodeId; | 287 clipNode.data.transform_id = kSecondaryRootNodeId; |
| 289 clipNode.data.target_id = kSecondaryRootNodeId; | 288 clipNode.data.target_id = kSecondaryRootNodeId; |
| 290 clipNode.owner_id = ownerId; | 289 clipNode.owner_id = ownerId; |
| 291 clipTree.set_needs_update(true); | 290 clipTree.set_needs_update(true); |
| 292 } | |
| 293 DCHECK_EQ(clipTree.size(), 2u); | |
| 294 | 291 |
| 295 cc::EffectTree& effectTree = propertyTrees->effect_tree; | 292 cc::EffectTree& effectTree = propertyTrees->effect_tree; |
| 296 if (effectTree.size() < 2) { | 293 effectTree.clear(); |
| 297 // This matches what cc does right now: the secondary root isn't a child | 294 // This matches what cc does right now: the secondary root isn't a child |
| 298 // of the first root (at index 0). This may not have been intentional. | 295 // of the first root (at index 0). This may not have been intentional. |
| 299 effectTree.Insert(cc::EffectNode(), kInvalidNodeId); | 296 effectTree.Insert(cc::EffectNode(), kInvalidNodeId); |
| 300 cc::EffectNode& effectNode = *effectTree.back(); | 297 cc::EffectNode& effectNode = *effectTree.back(); |
| 301 effectNode.data.has_render_surface = true; | 298 effectNode.data.has_render_surface = true; |
| 302 effectNode.data.transform_id = kRealRootNodeId; | 299 effectNode.data.transform_id = kRealRootNodeId; |
| 303 effectNode.data.clip_id = kRealRootNodeId; | 300 effectNode.data.clip_id = kRealRootNodeId; |
| 304 effectNode.owner_id = ownerId; | 301 effectNode.owner_id = ownerId; |
| 305 effectTree.set_needs_update(true); | 302 effectTree.set_needs_update(true); |
| 306 } | |
| 307 DCHECK_EQ(effectTree.size(), 2u); | |
| 308 | 303 |
| 309 cc::ScrollTree& scrollTree = propertyTrees->scroll_tree; | 304 cc::ScrollTree& scrollTree = propertyTrees->scroll_tree; |
| 310 if (scrollTree.size() < 2) { | 305 scrollTree.clear(); |
| 311 scrollTree.Insert(cc::ScrollNode(), kRealRootNodeId); | 306 scrollTree.Insert(cc::ScrollNode(), kRealRootNodeId); |
| 312 cc::ScrollNode& scrollNode = *scrollTree.back(); | 307 cc::ScrollNode& scrollNode = *scrollTree.back(); |
| 313 scrollNode.data.scrollable = false; | 308 scrollNode.data.scrollable = false; |
| 314 scrollNode.data.transform_id = kSecondaryRootNodeId; | 309 scrollNode.data.transform_id = kSecondaryRootNodeId; |
| 315 scrollNode.owner_id = ownerId; | 310 scrollNode.owner_id = ownerId; |
| 316 scrollTree.set_needs_update(true); | 311 scrollTree.set_needs_update(true); |
| 317 } | |
| 318 DCHECK_EQ(scrollTree.size(), 2u); | |
| 319 } | 312 } |
| 320 | 313 |
| 321 } // namespace | 314 } // namespace |
| 322 | 315 |
| 323 void PaintArtifactCompositor::update(const PaintArtifact& paintArtifact) | 316 void PaintArtifactCompositor::update(const PaintArtifact& paintArtifact) |
| 324 { | 317 { |
| 325 DCHECK(m_rootLayer); | 318 DCHECK(m_rootLayer); |
| 326 | 319 |
| 320 if (m_extraDataForTestingEnabled) | |
| 321 m_extraDataForTesting = wrapUnique(new ExtraDataForTesting); | |
| 322 | |
| 327 // If the compositor is configured to expect using flat layer lists plus | 323 // If the compositor is configured to expect using flat layer lists plus |
| 328 // property trees, then we should provide that format. | 324 // property trees, then we should provide that format. |
| 329 cc::LayerTreeHost* host = m_rootLayer->layer_tree_host(); | 325 cc::LayerTreeHost* host = m_rootLayer->layer_tree_host(); |
| 330 const bool useLayerLists = host && host->settings().use_layer_lists; | 326 const bool useLayerLists = host && host->settings().use_layer_lists; |
| 331 if (useLayerLists) { | 327 if (useLayerLists) { |
| 332 updateInLayerListMode(paintArtifact); | 328 updateInLayerListMode(paintArtifact); |
| 333 return; | 329 return; |
| 334 } | 330 } |
| 335 | 331 |
| 336 // TODO(jbroman): This should be incremental. | 332 // TODO(jbroman): This should be incremental. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 353 if (const auto* clip = paintChunk.properties.clip.get()) { | 349 if (const auto* clip = paintChunk.properties.clip.get()) { |
| 354 FloatPoint offsetDueToClipOffset = clip->clipRect().rect().location( ); | 350 FloatPoint offsetDueToClipOffset = clip->clipRect().rect().location( ); |
| 355 gfx::Transform undoClipOffset; | 351 gfx::Transform undoClipOffset; |
| 356 undoClipOffset.Translate(-offsetDueToClipOffset.x(), -offsetDueToCli pOffset.y()); | 352 undoClipOffset.Translate(-offsetDueToClipOffset.x(), -offsetDueToCli pOffset.y()); |
| 357 transform.ConcatTransform(undoClipOffset); | 353 transform.ConcatTransform(undoClipOffset); |
| 358 } | 354 } |
| 359 layer->SetTransform(transform); | 355 layer->SetTransform(transform); |
| 360 layer->SetDoubleSided(!paintChunk.properties.backfaceHidden); | 356 layer->SetDoubleSided(!paintChunk.properties.backfaceHidden); |
| 361 layer->SetNeedsDisplay(); | 357 layer->SetNeedsDisplay(); |
| 362 parent->AddChild(layer); | 358 parent->AddChild(layer); |
| 359 | |
| 360 if (m_extraDataForTestingEnabled) | |
| 361 m_extraDataForTesting->contentLayers.append(layer); | |
| 363 } | 362 } |
| 364 } | 363 } |
| 365 | 364 |
| 366 scoped_refptr<cc::Layer> PaintArtifactCompositor::layerForPaintChunk(const Paint Artifact& paintArtifact, const PaintChunk& paintChunk, gfx::Vector2dF& layerOffs et) | 365 scoped_refptr<cc::Layer> PaintArtifactCompositor::layerForPaintChunk(const Paint Artifact& paintArtifact, const PaintChunk& paintChunk, gfx::Vector2dF& layerOffs et) |
| 367 { | 366 { |
| 368 DCHECK(paintChunk.size()); | 367 DCHECK(paintChunk.size()); |
| 369 | 368 |
| 370 // If the paint chunk is a foreign layer, just return that layer. | 369 // If the paint chunk is a foreign layer, just return that layer. |
| 371 if (scoped_refptr<cc::Layer> foreignLayer = foreignLayerForPaintChunk(paintA rtifact, paintChunk, layerOffset)) | 370 if (scoped_refptr<cc::Layer> foreignLayer = foreignLayerForPaintChunk(paintA rtifact, paintChunk, layerOffset)) |
| 372 return foreignLayer; | 371 return foreignLayer; |
| 373 | 372 |
| 374 // The common case: create a layer for painted content. | 373 // The common case: create a layer for painted content. |
| 375 gfx::Rect combinedBounds = enclosingIntRect(paintChunk.bounds); | 374 gfx::Rect combinedBounds = enclosingIntRect(paintChunk.bounds); |
| 376 scoped_refptr<cc::DisplayItemList> displayList = recordPaintChunk(paintArtif act, paintChunk, combinedBounds); | 375 scoped_refptr<cc::DisplayItemList> displayList = recordPaintChunk(paintArtif act, paintChunk, combinedBounds); |
| 377 std::unique_ptr<ContentLayerClientImpl> contentLayerClient = wrapUnique( | 376 std::unique_ptr<ContentLayerClientImpl> contentLayerClient = wrapUnique( |
| 378 new ContentLayerClientImpl(std::move(displayList), gfx::Rect(combinedBou nds.size()))); | 377 new ContentLayerClientImpl(std::move(displayList), gfx::Rect(combinedBou nds.size()))); |
| 379 | 378 |
| 380 layerOffset = combinedBounds.OffsetFromOrigin(); | 379 layerOffset = combinedBounds.OffsetFromOrigin(); |
| 381 scoped_refptr<cc::PictureLayer> layer = cc::PictureLayer::Create(contentLaye rClient.get()); | 380 scoped_refptr<cc::PictureLayer> layer = cc::PictureLayer::Create(contentLaye rClient.get()); |
| 382 layer->SetBounds(combinedBounds.size()); | 381 layer->SetBounds(combinedBounds.size()); |
| 383 layer->SetIsDrawable(true); | 382 layer->SetIsDrawable(true); |
| 384 if (paintChunk.knownToBeOpaque) | 383 if (paintChunk.knownToBeOpaque) |
| 385 layer->SetContentsOpaque(true); | 384 layer->SetContentsOpaque(true); |
| 386 m_contentLayerClients.append(std::move(contentLayerClient)); | 385 m_contentLayerClients.append(std::move(contentLayerClient)); |
| 387 return layer; | 386 return layer; |
| 388 } | 387 } |
| 389 | 388 |
| 389 namespace { | |
| 390 | |
| 391 class TransformTreeManager { | |
| 392 WTF_MAKE_NONCOPYABLE(TransformTreeManager); | |
| 393 public: | |
| 394 TransformTreeManager(cc::TransformTree& transformTree, cc::Layer* rootLayer) | |
| 395 : m_transformTree(transformTree) | |
| 396 , m_rootLayer(rootLayer) {} | |
| 397 | |
| 398 int compositorIdForNode(const TransformPaintPropertyNode*); | |
|
pdr.
2016/06/27 23:09:23
WDYT about making the compositor ids an internal i
| |
| 399 | |
| 400 private: | |
| 401 // Transform tree which should be updated by the manager. | |
| 402 cc::TransformTree& m_transformTree; | |
| 403 | |
| 404 // Layer to which transform "owner" layers should be added. These will not | |
| 405 // have any actual children, but at present must exist in the tree. | |
| 406 cc::Layer* m_rootLayer; | |
| 407 | |
| 408 // Map from Blink-side transform nodes to cc transform node indices. | |
| 409 HashMap<const TransformPaintPropertyNode*, int> m_nodeMap; | |
| 410 }; | |
| 411 | |
| 412 int TransformTreeManager::compositorIdForNode(const TransformPaintPropertyNode* transformNode) | |
| 413 { | |
| 414 if (!transformNode) | |
| 415 return kSecondaryRootNodeId; | |
| 416 | |
| 417 auto it = m_nodeMap.find(transformNode); | |
| 418 if (it != m_nodeMap.end()) | |
| 419 return it->value; | |
| 420 | |
| 421 scoped_refptr<cc::Layer> dummyLayer = cc::Layer::Create(); | |
| 422 int parentId = compositorIdForNode(transformNode->parent()); | |
| 423 int id = m_transformTree.Insert(cc::TransformNode(), parentId); | |
| 424 | |
| 425 cc::TransformNode& compositorNode = *m_transformTree.Node(id); | |
| 426 m_transformTree.SetTargetId(id, kSecondaryRootNodeId); | |
| 427 m_transformTree.SetContentTargetId(id, kSecondaryRootNodeId); | |
| 428 compositorNode.owner_id = dummyLayer->id(); | |
| 429 compositorNode.data.source_node_id = parentId; | |
| 430 compositorNode.data.needs_local_transform_update = true; | |
| 431 | |
| 432 FloatPoint3D origin = transformNode->origin(); | |
| 433 compositorNode.data.pre_local.matrix().setTranslate( | |
| 434 -origin.x(), -origin.y(), -origin.z()); | |
| 435 compositorNode.data.local.matrix() = TransformationMatrix::toSkMatrix44(tran sformNode->matrix()); | |
| 436 compositorNode.data.post_local.matrix().setTranslate( | |
| 437 origin.x(), origin.y(), origin.z()); | |
| 438 compositorNode.data.needs_local_transform_update = true; | |
| 439 | |
| 440 m_rootLayer->AddChild(dummyLayer); | |
| 441 dummyLayer->SetTransformTreeIndex(id); | |
| 442 dummyLayer->SetClipTreeIndex(kSecondaryRootNodeId); | |
| 443 dummyLayer->SetEffectTreeIndex(kSecondaryRootNodeId); | |
| 444 dummyLayer->SetScrollTreeIndex(kSecondaryRootNodeId); | |
| 445 dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | |
| 446 | |
| 447 auto result = m_nodeMap.set(transformNode, id); | |
| 448 DCHECK(result.isNewEntry); | |
| 449 m_transformTree.set_needs_update(true); | |
| 450 return id; | |
| 451 } | |
| 452 | |
| 453 } // namespace | |
| 454 | |
| 390 void PaintArtifactCompositor::updateInLayerListMode(const PaintArtifact& paintAr tifact) | 455 void PaintArtifactCompositor::updateInLayerListMode(const PaintArtifact& paintAr tifact) |
| 391 { | 456 { |
| 392 cc::LayerTreeHost* host = m_rootLayer->layer_tree_host(); | 457 cc::LayerTreeHost* host = m_rootLayer->layer_tree_host(); |
| 393 | 458 |
| 394 // The root layer must be the owner so that the render surface | 459 // The root layer must be the owner so that the render surface |
| 395 // validation works. It's expected to own at least the effect node. | 460 // validation works. It's expected to own at least the effect node. |
| 396 setMinimalPropertyTrees(host->property_trees(), m_rootLayer->id()); | 461 setMinimalPropertyTrees(host->property_trees(), m_rootLayer->id()); |
| 397 m_rootLayer->RemoveAllChildren(); | 462 m_rootLayer->RemoveAllChildren(); |
| 398 m_rootLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | 463 m_rootLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); |
| 399 m_rootLayer->SetTransformTreeIndex(kSecondaryRootNodeId); | 464 m_rootLayer->SetTransformTreeIndex(kSecondaryRootNodeId); |
| 400 m_rootLayer->SetClipTreeIndex(kSecondaryRootNodeId); | 465 m_rootLayer->SetClipTreeIndex(kSecondaryRootNodeId); |
| 401 m_rootLayer->SetEffectTreeIndex(kSecondaryRootNodeId); | 466 m_rootLayer->SetEffectTreeIndex(kSecondaryRootNodeId); |
| 402 m_rootLayer->SetScrollTreeIndex(kSecondaryRootNodeId); | 467 m_rootLayer->SetScrollTreeIndex(kSecondaryRootNodeId); |
| 403 | 468 |
| 469 TransformTreeManager transformTreeManager(host->property_trees()->transform_ tree, m_rootLayer.get()); | |
| 404 m_contentLayerClients.clear(); | 470 m_contentLayerClients.clear(); |
| 405 m_contentLayerClients.reserveCapacity(paintArtifact.paintChunks().size()); | 471 m_contentLayerClients.reserveCapacity(paintArtifact.paintChunks().size()); |
| 406 for (const PaintChunk& paintChunk : paintArtifact.paintChunks()) { | 472 for (const PaintChunk& paintChunk : paintArtifact.paintChunks()) { |
| 407 gfx::Vector2dF layerOffset; | 473 gfx::Vector2dF layerOffset; |
| 408 scoped_refptr<cc::Layer> layer = layerForPaintChunk(paintArtifact, paint Chunk, layerOffset); | 474 scoped_refptr<cc::Layer> layer = layerForPaintChunk(paintArtifact, paint Chunk, layerOffset); |
| 409 // This is only good enough to get trivial 2D translations working. | 475 |
| 410 // We'll need to actually create more cc transform nodes to do any | 476 int transformId = transformTreeManager.compositorIdForNode(paintChunk.pr operties.transform.get()); |
| 411 // more; then we'll express offset-to-transform-parent relative to | 477 layer->set_offset_to_transform_parent(layerOffset); |
| 412 // that transform node. | |
| 413 // TODO(jbroman): ^ Do that. | |
| 414 layer->set_offset_to_transform_parent( | |
| 415 transformToTransformSpace(paintChunk.properties.transform.get(), nul lptr).To2dTranslation() | |
| 416 + layerOffset); | |
| 417 | 478 |
| 418 m_rootLayer->AddChild(layer); | 479 m_rootLayer->AddChild(layer); |
| 419 layer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); | 480 layer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); |
| 420 layer->SetTransformTreeIndex(kSecondaryRootNodeId); | 481 layer->SetTransformTreeIndex(transformId); |
| 421 layer->SetClipTreeIndex(kSecondaryRootNodeId); | 482 layer->SetClipTreeIndex(kSecondaryRootNodeId); |
| 422 layer->SetEffectTreeIndex(kSecondaryRootNodeId); | 483 layer->SetEffectTreeIndex(kSecondaryRootNodeId); |
| 423 layer->SetScrollTreeIndex(kSecondaryRootNodeId); | 484 layer->SetScrollTreeIndex(kSecondaryRootNodeId); |
| 485 | |
| 486 if (m_extraDataForTestingEnabled) | |
| 487 m_extraDataForTesting->contentLayers.append(layer); | |
| 424 } | 488 } |
| 425 | 489 |
| 426 // Mark the property trees as having been rebuilt. | 490 // Mark the property trees as having been rebuilt. |
| 427 host->property_trees()->sequence_number = kPropertyTreeSequenceNumber; | 491 host->property_trees()->sequence_number = kPropertyTreeSequenceNumber; |
| 428 host->property_trees()->needs_rebuild = false; | 492 host->property_trees()->needs_rebuild = false; |
| 429 } | 493 } |
| 430 | 494 |
| 431 } // namespace blink | 495 } // namespace blink |
| OLD | NEW |