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* dummyTrans formParent) | |
395 : m_transformTree(transformTree) | |
396 , m_dummyTransformParent(dummyTransformParent) {} | |
397 | |
398 int compositorIdForNode(const TransformPaintPropertyNode*); | |
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_dummyTransformParent; | |
trchen
2016/06/27 21:39:19
This made me thought it's some internal state to c
jbroman
2016/06/27 21:53:58
OK, done. It doesn't have to be the root (we could
| |
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_dummyTransformParent->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 |