不是所有的RenderLayer都需要创建它的Backing Store,只有网页的RenderObject树之RenderLayer满足如下条件:
1 Transform:几何变换
2 Video:页面有<video>
3 Canvas: 页面有<canvas>
4 Plugin
5 Frame
6 3DTransforms
7 Animation
8 Filters:CSS过滤器
9 Position:CSS之定位
10 clipsCompositingDescendants:裁剪区合成到子孙
// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons. // Use needsToBeComposited() to determine if a RL actually needs a compositing layer. // static bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const { RenderObject* renderer = layer->renderer(); // The compositing state of a reflection should match that of its reflected layer. if (layer->isReflection()) { renderer = renderer->parent(); // The RenderReplica's parent is the object being reflected. layer = toRenderBoxModelObject(renderer)->layer(); } // The root layer always has a compositing layer, but it may not have backing. return requiresCompositingForTransform(renderer) || requiresCompositingForVideo(renderer) || requiresCompositingForCanvas(renderer) || requiresCompositingForPlugin(renderer) || requiresCompositingForFrame(renderer) || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden) || clipsCompositingDescendants(layer) || requiresCompositingForAnimation(renderer) || requiresCompositingForFilters(renderer) || requiresCompositingForPosition(renderer, layer); }
创建RenderObject并且设置新样式:
#8 WebCore::RenderObject::setStyle (this=0xc16f18, style=...)RenderObject.cpp:1744
#9 WebCore::RenderObject::setAnimatableStyle (this=0xc16f18, style=...) RenderObject.cpp:1645
#10 WebCore::NodeRendererFactory::createRenderer (this)WebCore/dom/NodeRenderingContext.cpp:291
#11 WebCore::NodeRendererFactory::createRendererIfNeeded (this=0x7fffffffcb50)NodeRenderingContext.cpp:324
#12 WebCore::Node::createRendererIfNeeded (this=0xc0aa80) WebCore/dom/Node.cpp:1378
#13 WebCore::Element::attach (this=0xc0aa80) at WebKit/Source/WebCore/dom/Element.cpp:941
#14 WebCore::executeTask (task=...) WebCore/html/parser/HTMLConstructionSite.cpp:102
#15 WebCore::HTMLConstructionSite::executeQueuedTasks (this=) WebCore/html/parser/HTMLConstructionSite.cpp:142
#16 WebCore::HTMLTreeBuilder::constructTreeFromAtomicToken (this=0xc89840, token=) HTMLTreeBuilder.cpp:475
#17 WebCore::HTMLTreeBuilder::constructTreeFromToken (this=0xc89840, rawToken=...)
更新盒子模型:
#5 RenderBoxModelObject::styleDidChange (this, diff=WebCore::StyleDifferenceEqual, oldStyle) RenderBoxModelObject.cpp:445
#6 RenderBox::styleDidChange (this, diff=WebCore::StyleDifferenceEqual, oldStyle=0x0)RenderBox.cpp:233
#7 WebCore::RenderBlock::styleDidChange (this=0xc16f18, diff=WebCore::StyleDifferenceEqual, oldStyle=0x0)RenderBlock.cpp:315
要求更新整颗RenderLayer树的样式:
#4 WebCore::RenderLayer::styleChanged (this=0xc3d838, oldStyle=0x0) WebCore/rendering/RenderLayer.cpp:4886
RenderLayer就会更新合成器的状态: #3 RenderLayerCompositor::updateLayerCompositingState (layer, shouldRepaint=CompositingChangeRepaintNow)RenderLayerCompositor.cpp:558
并首先更新后端存储区:
#2 RenderLayerCompositor::updateBacking (layer, shouldRepaint=CompositingChangeRepaintNow) RenderLayerCompositor.cpp:495
先检查是否需要后端存储区:
bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint) { bool layerChanged = false; if (<span style="background-color: rgb(51, 255, 51);">needsToBeComposited</span>(layer)) { enableCompositingMode(); if (!layer->backing()) { // If we need to repaint, do so before making backing if (shouldRepaint == CompositingChangeRepaintNow) repaintOnCompositingChange(layer); layer-><span style="background-color: rgb(51, 255, 51);">ensureBacking</span>(); // The RenderLayer's needs to update repaint rects here, because the target // repaintContainer may have changed after becoming a composited layer. // https://bugs.webkit.org/show_bug.cgi?id=80641 if (layer->parent()) layer->computeRepaintRects(); layerChanged = true; }创建后端存储区的管理类:
RenderLayerBacking* RenderLayer::<span style="background-color: rgb(51, 255, 51);">ensureBacking</span>() { if (!m_backing) { m_backing = adoptPtr(new RenderLayerBacking(this)); compositor()->layerBecameComposited(this); #if ENABLE(CSS_FILTERS) updateOrRemoveFilterEffect(); #endif } return m_backing.get(); }
创建Backing Store:
RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) { <span style="background-color: rgb(51, 255, 51);">createPrimaryGraphicsLayer</span>(); }
<pre name="code" class="cpp">void RenderLayerBacking::createPrimaryGraphicsLayer() { String layerName; #ifndef NDEBUG layerName = nameForLayer(); #endif // The call to createGraphicsLayer ends calling back into here as // a GraphicsLayerClient to ask if it shouldUseTileCache(). We only want // the tile cache on our main layer. This is pretty ugly, but saves us from // exposing the API to all clients. m_creatingPrimaryGraphicsLayer = true; m_graphicsLayer = <span style="background-color: rgb(51, 255, 51);">createGraphicsLayer</span>(layerName); }
PassOwnPtr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name) { OwnPtr<GraphicsLayer> graphicsLayer = <span style="background-color: rgb(51, 255, 51);">GraphicsLayer::create(</span>this); graphicsLayer->setMaintainsPixelAlignment(compositor()->keepLayersPixelAligned()); return graphicsLayer.release(); }我们看看chrome的实现:
PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerChromium(client)); }
GraphicsLayerChromium就是Backing Store的抽象类GraphicsLayer之具体实现!
以下是我的测试网页:
<html> <head> <style type="text/css"> div, video, canvas { -webkit-transform: rotateY(10deg) rotateX(-15deg); } </style> </head> <body> <video src=http://media.w3.org/2010/05/sintel/trailer.mp4></video> <div> <canvas id="a12d"></canvas><br> <canvas id="a13d"></canvas> </div> <script type="text/javascript"> var size=100; //2d drawing var a12dCtx = document.getElementById('a12d').getContext.('2d'); a12dCtx.canvas.width = size; a12dCtx.canvas.height = size; a12dCtx.canvas.fillStyle="rgba(0,92,92,80)"; a12dCtx.canvas.fillRect(0,0,100,100); </script> </body> </html>