1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "CCDelegatedRendererLayerImpl.h"
9 #include "CCAppendQuadsData.h"
10 #include "CCQuadSink.h"
11 #include "CCMathUtil.h"
12 #include "CCRenderPassDrawQuad.h"
13 #include "CCRenderPassSink.h"
17 CCDelegatedRendererLayerImpl::CCDelegatedRendererLayerImpl(int id
)
22 CCDelegatedRendererLayerImpl::~CCDelegatedRendererLayerImpl()
27 bool CCDelegatedRendererLayerImpl::descendantDrawsContent()
29 // FIXME: This could possibly return false even though there are some
30 // quads present as they could all be from a single layer (or set of
31 // layers without children). If this happens, then make a test that
32 // ensures the opacity is being changed on quads in the root RenderPass
33 // when this layer doesn't own a RenderSurface.
34 return !m_renderPassesInDrawOrder
.isEmpty();
37 bool CCDelegatedRendererLayerImpl::hasContributingDelegatedRenderPasses() const
39 // The root RenderPass for the layer is merged with its target
40 // RenderPass in each frame. So we only have extra RenderPasses
41 // to merge when we have a non-root RenderPass present.
42 return m_renderPassesInDrawOrder
.size() > 1;
45 void CCDelegatedRendererLayerImpl::setRenderPasses(ScopedPtrVector
<CCRenderPass
>& renderPassesInDrawOrder
)
47 FloatRect oldRootDamage
;
48 if (!m_renderPassesInDrawOrder
.isEmpty())
49 oldRootDamage
= m_renderPassesInDrawOrder
.last()->damageRect();
53 for (size_t i
= 0; i
< renderPassesInDrawOrder
.size(); ++i
) {
54 m_renderPassesIndexById
.insert(std::pair
<CCRenderPass::Id
, int>(renderPassesInDrawOrder
[i
]->id(), i
));
55 m_renderPassesInDrawOrder
.append(renderPassesInDrawOrder
.take(i
));
57 renderPassesInDrawOrder
.clear();
59 if (!m_renderPassesInDrawOrder
.isEmpty()) {
60 FloatRect newRootDamage
= m_renderPassesInDrawOrder
.last()->damageRect();
61 m_renderPassesInDrawOrder
.last()->setDamageRect(unionRect(oldRootDamage
, newRootDamage
));
65 void CCDelegatedRendererLayerImpl::clearRenderPasses()
67 // FIXME: Release the resources back to the nested compositor.
68 m_renderPassesIndexById
.clear();
69 m_renderPassesInDrawOrder
.clear();
72 void CCDelegatedRendererLayerImpl::didLoseContext()
77 static inline int indexToId(int index
) { return index
+ 1; }
78 static inline int idToIndex(int id
) { return id
- 1; }
80 CCRenderPass::Id
CCDelegatedRendererLayerImpl::firstContributingRenderPassId() const
82 return CCRenderPass::Id(id(), indexToId(0));
85 CCRenderPass::Id
CCDelegatedRendererLayerImpl::nextContributingRenderPassId(CCRenderPass::Id previous
) const
87 return CCRenderPass::Id(previous
.layerId
, previous
.index
+ 1);
90 CCRenderPass::Id
CCDelegatedRendererLayerImpl::convertDelegatedRenderPassId(CCRenderPass::Id delegatedRenderPassId
) const
92 base::hash_map
<CCRenderPass::Id
, int>::const_iterator it
= m_renderPassesIndexById
.find(delegatedRenderPassId
);
93 ASSERT(it
!= m_renderPassesIndexById
.end());
94 unsigned delegatedRenderPassIndex
= it
->second
;
95 return CCRenderPass::Id(id(), indexToId(delegatedRenderPassIndex
));
98 void CCDelegatedRendererLayerImpl::appendContributingRenderPasses(CCRenderPassSink
& renderPassSink
)
100 ASSERT(hasContributingDelegatedRenderPasses());
102 for (size_t i
= 0; i
< m_renderPassesInDrawOrder
.size() - 1; ++i
) {
103 CCRenderPass::Id outputRenderPassId
= convertDelegatedRenderPassId(m_renderPassesInDrawOrder
[i
]->id());
105 // Don't clash with the RenderPass we generate if we own a RenderSurface.
106 ASSERT(outputRenderPassId
.index
> 0);
108 renderPassSink
.appendRenderPass(m_renderPassesInDrawOrder
[i
]->copy(outputRenderPassId
));
112 void CCDelegatedRendererLayerImpl::appendQuads(CCQuadSink
& quadSink
, CCAppendQuadsData
& appendQuadsData
)
114 if (m_renderPassesInDrawOrder
.isEmpty())
117 CCRenderPass::Id targetRenderPassId
= appendQuadsData
.renderPassId
;
119 // If the index of the renderPassId is 0, then it is a renderPass generated for a layer
120 // in this compositor, not the delegated renderer. Then we want to merge our root renderPass with
121 // the target renderPass. Otherwise, it is some renderPass which we added from the delegated
123 bool shouldMergeRootRenderPassWithTarget
= !targetRenderPassId
.index
;
124 if (shouldMergeRootRenderPassWithTarget
) {
125 // Verify that the renderPass we are appending to is created our renderTarget.
126 ASSERT(targetRenderPassId
.layerId
== renderTarget()->id());
128 CCRenderPass
* rootDelegatedRenderPass
= m_renderPassesInDrawOrder
.last();
129 appendRenderPassQuads(quadSink
, appendQuadsData
, rootDelegatedRenderPass
);
131 // Verify that the renderPass we are appending to was created by us.
132 ASSERT(targetRenderPassId
.layerId
== id());
134 int renderPassIndex
= idToIndex(targetRenderPassId
.index
);
135 CCRenderPass
* delegatedRenderPass
= m_renderPassesInDrawOrder
[renderPassIndex
];
136 appendRenderPassQuads(quadSink
, appendQuadsData
, delegatedRenderPass
);
140 void CCDelegatedRendererLayerImpl::appendRenderPassQuads(CCQuadSink
& quadSink
, CCAppendQuadsData
& appendQuadsData
, CCRenderPass
* delegatedRenderPass
) const
142 const CCSharedQuadState
* currentSharedQuadState
= 0;
143 CCSharedQuadState
* copiedSharedQuadState
= 0;
144 for (size_t i
= 0; i
< delegatedRenderPass
->quadList().size(); ++i
) {
145 CCDrawQuad
* quad
= delegatedRenderPass
->quadList()[i
];
147 if (quad
->sharedQuadState() != currentSharedQuadState
) {
148 currentSharedQuadState
= quad
->sharedQuadState();
149 copiedSharedQuadState
= quadSink
.useSharedQuadState(currentSharedQuadState
->copy());
150 bool targetIsFromDelegatedRendererLayer
= appendQuadsData
.renderPassId
.layerId
== id();
151 if (!targetIsFromDelegatedRendererLayer
) {
152 // Should be the root render pass.
153 ASSERT(delegatedRenderPass
== m_renderPassesInDrawOrder
.last());
154 // This layer must be drawing to a renderTarget other than itself.
155 ASSERT(renderTarget() != this);
157 copiedSharedQuadState
->clippedRectInTarget
= CCMathUtil::mapClippedRect(drawTransform(), copiedSharedQuadState
->clippedRectInTarget
);
158 copiedSharedQuadState
->quadTransform
= copiedSharedQuadState
->quadTransform
* drawTransform();
159 copiedSharedQuadState
->opacity
*= drawOpacity();
162 ASSERT(copiedSharedQuadState
);
164 scoped_ptr
<CCDrawQuad
> copyQuad
;
165 if (quad
->material() != CCDrawQuad::RenderPass
)
166 copyQuad
= quad
->copy(copiedSharedQuadState
);
168 CCRenderPass::Id contributingDelegatedRenderPassId
= CCRenderPassDrawQuad::materialCast(quad
)->renderPassId();
169 CCRenderPass::Id contributingRenderPassId
= convertDelegatedRenderPassId(contributingDelegatedRenderPassId
);
170 ASSERT(contributingRenderPassId
!= appendQuadsData
.renderPassId
);
172 copyQuad
= CCRenderPassDrawQuad::materialCast(quad
)->copy(copiedSharedQuadState
, contributingRenderPassId
).PassAs
<CCDrawQuad
>();
174 ASSERT(copyQuad
.get());
176 quadSink
.append(copyQuad
.Pass(), appendQuadsData
);
180 const char* CCDelegatedRendererLayerImpl::layerTypeAsString() const
182 return "DelegatedRendererLayer";