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 "cc/delegated_renderer_layer_impl.h"
9 #include "cc/append_quads_data.h"
10 #include "cc/math_util.h"
11 #include "cc/quad_sink.h"
12 #include "cc/render_pass_draw_quad.h"
13 #include "cc/render_pass_sink.h"
17 DelegatedRendererLayerImpl::DelegatedRendererLayerImpl(int id
)
22 DelegatedRendererLayerImpl::~DelegatedRendererLayerImpl()
27 bool DelegatedRendererLayerImpl::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 RenderSurfaceImpl.
34 return !m_renderPassesInDrawOrder
.isEmpty();
37 bool DelegatedRendererLayerImpl::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 DelegatedRendererLayerImpl::setRenderPasses(ScopedPtrVector
<RenderPass
>& renderPassesInDrawOrder
)
47 gfx::RectF 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
<RenderPass::Id
, int>(renderPassesInDrawOrder
[i
]->id(), i
));
55 m_renderPassesInDrawOrder
.append(renderPassesInDrawOrder
.take(i
));
57 renderPassesInDrawOrder
.clear();
59 if (!m_renderPassesInDrawOrder
.isEmpty()) {
60 gfx::RectF newRootDamage
= m_renderPassesInDrawOrder
.last()->damageRect();
61 m_renderPassesInDrawOrder
.last()->setDamageRect(gfx::UnionRects(oldRootDamage
, newRootDamage
));
65 void DelegatedRendererLayerImpl::clearRenderPasses()
67 // FIXME: Release the resources back to the nested compositor.
68 m_renderPassesIndexById
.clear();
69 m_renderPassesInDrawOrder
.clear();
72 void DelegatedRendererLayerImpl::didLoseContext()
77 static inline int indexToId(int index
) { return index
+ 1; }
78 static inline int idToIndex(int id
) { return id
- 1; }
80 RenderPass::Id
DelegatedRendererLayerImpl::firstContributingRenderPassId() const
82 return RenderPass::Id(id(), indexToId(0));
85 RenderPass::Id
DelegatedRendererLayerImpl::nextContributingRenderPassId(RenderPass::Id previous
) const
87 return RenderPass::Id(previous
.layerId
, previous
.index
+ 1);
90 RenderPass::Id
DelegatedRendererLayerImpl::convertDelegatedRenderPassId(RenderPass::Id delegatedRenderPassId
) const
92 base::hash_map
<RenderPass::Id
, int>::const_iterator it
= m_renderPassesIndexById
.find(delegatedRenderPassId
);
93 DCHECK(it
!= m_renderPassesIndexById
.end());
94 unsigned delegatedRenderPassIndex
= it
->second
;
95 return RenderPass::Id(id(), indexToId(delegatedRenderPassIndex
));
98 void DelegatedRendererLayerImpl::appendContributingRenderPasses(RenderPassSink
& renderPassSink
)
100 DCHECK(hasContributingDelegatedRenderPasses());
102 for (size_t i
= 0; i
< m_renderPassesInDrawOrder
.size() - 1; ++i
) {
103 RenderPass::Id outputRenderPassId
= convertDelegatedRenderPassId(m_renderPassesInDrawOrder
[i
]->id());
105 // Don't clash with the RenderPass we generate if we own a RenderSurfaceImpl.
106 DCHECK(outputRenderPassId
.index
> 0);
108 renderPassSink
.appendRenderPass(m_renderPassesInDrawOrder
[i
]->copy(outputRenderPassId
));
112 void DelegatedRendererLayerImpl::appendQuads(QuadSink
& quadSink
, AppendQuadsData
& appendQuadsData
)
114 if (m_renderPassesInDrawOrder
.isEmpty())
117 RenderPass::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 DCHECK(targetRenderPassId
.layerId
== renderTarget()->id());
128 RenderPass
* rootDelegatedRenderPass
= m_renderPassesInDrawOrder
.last();
129 appendRenderPassQuads(quadSink
, appendQuadsData
, rootDelegatedRenderPass
);
131 // Verify that the renderPass we are appending to was created by us.
132 DCHECK(targetRenderPassId
.layerId
== id());
134 int renderPassIndex
= idToIndex(targetRenderPassId
.index
);
135 RenderPass
* delegatedRenderPass
= m_renderPassesInDrawOrder
[renderPassIndex
];
136 appendRenderPassQuads(quadSink
, appendQuadsData
, delegatedRenderPass
);
140 void DelegatedRendererLayerImpl::appendRenderPassQuads(QuadSink
& quadSink
, AppendQuadsData
& appendQuadsData
, RenderPass
* delegatedRenderPass
) const
142 const SharedQuadState
* currentSharedQuadState
= 0;
143 SharedQuadState
* copiedSharedQuadState
= 0;
144 for (size_t i
= 0; i
< delegatedRenderPass
->quadList().size(); ++i
) {
145 DrawQuad
* 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 DCHECK(delegatedRenderPass
== m_renderPassesInDrawOrder
.last());
154 // This layer must be drawing to a renderTarget other than itself.
155 DCHECK(renderTarget() != this);
157 copiedSharedQuadState
->clippedRectInTarget
= MathUtil::mapClippedRect(drawTransform(), copiedSharedQuadState
->clippedRectInTarget
);
158 copiedSharedQuadState
->quadTransform
= copiedSharedQuadState
->quadTransform
* drawTransform();
159 copiedSharedQuadState
->opacity
*= drawOpacity();
162 DCHECK(copiedSharedQuadState
);
164 scoped_ptr
<DrawQuad
> copyQuad
;
165 if (quad
->material() != DrawQuad::RenderPass
)
166 copyQuad
= quad
->copy(copiedSharedQuadState
);
168 RenderPass::Id contributingDelegatedRenderPassId
= RenderPassDrawQuad::materialCast(quad
)->renderPassId();
169 RenderPass::Id contributingRenderPassId
= convertDelegatedRenderPassId(contributingDelegatedRenderPassId
);
170 DCHECK(contributingRenderPassId
!= appendQuadsData
.renderPassId
);
172 copyQuad
= RenderPassDrawQuad::materialCast(quad
)->copy(copiedSharedQuadState
, contributingRenderPassId
).PassAs
<DrawQuad
>();
174 DCHECK(copyQuad
.get());
176 quadSink
.append(copyQuad
.Pass(), appendQuadsData
);
180 const char* DelegatedRendererLayerImpl::layerTypeAsString() const
182 return "DelegatedRendererLayer";