blob: fafd3a8ec58e6ef461539d9a9742776f5c79746b [file] [log] [blame]
[email protected]7d929c02012-09-20 17:26:571// 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.
4
5#include "config.h"
6
7#include "CCDelegatedRendererLayerImpl.h"
8
9#include "CCAppendQuadsData.h"
10#include "CCQuadSink.h"
11#include "CCRenderPassDrawQuad.h"
12#include "CCRenderPassSink.h"
13
14namespace cc {
15
16CCDelegatedRendererLayerImpl::CCDelegatedRendererLayerImpl(int id)
17 : CCLayerImpl(id)
18{
19}
20
21CCDelegatedRendererLayerImpl::~CCDelegatedRendererLayerImpl()
22{
23 clearRenderPasses();
24}
25
26bool CCDelegatedRendererLayerImpl::descendantDrawsContent()
27{
28 // FIXME: This could possibly return false even though there are some
29 // quads present as they could all be from a single layer (or set of
30 // layers without children). If this happens, then make a test that
31 // ensures the opacity is being changed on quads in the root RenderPass
32 // when this layer doesn't own a RenderSurface.
33 return !m_renderPassesInDrawOrder.isEmpty();
34}
35
36bool CCDelegatedRendererLayerImpl::hasContributingDelegatedRenderPasses() const
37{
38 // The root RenderPass for the layer is merged with its target
39 // RenderPass in each frame. So we only have extra RenderPasses
40 // to merge when we have a non-root RenderPass present.
41 return m_renderPassesInDrawOrder.size() > 1;
42}
43
44void CCDelegatedRendererLayerImpl::setRenderPasses(OwnPtrVector<CCRenderPass>& renderPassesInDrawOrder)
45{
46 FloatRect oldRootDamage;
47 if (!m_renderPassesInDrawOrder.isEmpty())
48 oldRootDamage = m_renderPassesInDrawOrder.last()->damageRect();
49
50 clearRenderPasses();
51
52 for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) {
53 m_renderPassesIndexById.set(renderPassesInDrawOrder[i]->id(), i);
54 m_renderPassesInDrawOrder.append(renderPassesInDrawOrder.take(i));
55 }
56 renderPassesInDrawOrder.clear();
57
58 if (!m_renderPassesInDrawOrder.isEmpty()) {
59 FloatRect newRootDamage = m_renderPassesInDrawOrder.last()->damageRect();
60 m_renderPassesInDrawOrder.last()->setDamageRect(unionRect(oldRootDamage, newRootDamage));
61 }
62}
63
64void CCDelegatedRendererLayerImpl::clearRenderPasses()
65{
66 // FIXME: Release the resources back to the nested compositor.
67 m_renderPassesIndexById.clear();
68 m_renderPassesInDrawOrder.clear();
69}
70
71void CCDelegatedRendererLayerImpl::didLoseContext()
72{
73 clearRenderPasses();
74}
75
76static inline int indexToId(int index) { return index + 1; }
77static inline int idToIndex(int id) { return id - 1; }
78
79CCRenderPass::Id CCDelegatedRendererLayerImpl::firstContributingRenderPassId() const
80{
81 return CCRenderPass::Id(id(), indexToId(0));
82}
83
84CCRenderPass::Id CCDelegatedRendererLayerImpl::nextContributingRenderPassId(CCRenderPass::Id previous) const
85{
86 return CCRenderPass::Id(previous.layerId, previous.index + 1);
87}
88
89CCRenderPass::Id CCDelegatedRendererLayerImpl::convertDelegatedRenderPassId(CCRenderPass::Id delegatedRenderPassId) const
90{
91 unsigned delegatedRenderPassIndex = m_renderPassesIndexById.get(delegatedRenderPassId);
92 return CCRenderPass::Id(id(), indexToId(delegatedRenderPassIndex));
93}
94
95void CCDelegatedRendererLayerImpl::appendContributingRenderPasses(CCRenderPassSink& renderPassSink)
96{
97 ASSERT(hasContributingDelegatedRenderPasses());
98
99 for (size_t i = 0; i < m_renderPassesInDrawOrder.size() - 1; ++i) {
100 CCRenderPass::Id outputRenderPassId = convertDelegatedRenderPassId(m_renderPassesInDrawOrder[i]->id());
101
102 // Don't clash with the RenderPass we generate if we own a RenderSurface.
103 ASSERT(outputRenderPassId.index > 0);
104
105 renderPassSink.appendRenderPass(m_renderPassesInDrawOrder[i]->copy(outputRenderPassId));
106 }
107}
108
109void CCDelegatedRendererLayerImpl::appendQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData)
110{
111 if (m_renderPassesInDrawOrder.isEmpty())
112 return;
113
114 CCRenderPass::Id targetRenderPassId = appendQuadsData.renderPassId;
115
116 // If the index of the renderPassId is 0, then it is a renderPass generated for a layer
117 // in this compositor, not the delegated renderer. Then we want to merge our root renderPass with
118 // the target renderPass. Otherwise, it is some renderPass which we added from the delegated
119 // renderer.
120 bool shouldMergeRootRenderPassWithTarget = !targetRenderPassId.index;
121 if (shouldMergeRootRenderPassWithTarget) {
122 // Verify that the renderPass we are appending to is created our renderTarget.
123 ASSERT(targetRenderPassId.layerId == renderTarget()->id());
124
125 CCRenderPass* rootDelegatedRenderPass = m_renderPassesInDrawOrder.last();
126 appendRenderPassQuads(quadSink, appendQuadsData, rootDelegatedRenderPass);
127 } else {
128 // Verify that the renderPass we are appending to was created by us.
129 ASSERT(targetRenderPassId.layerId == id());
130
131 int renderPassIndex = idToIndex(targetRenderPassId.index);
132 CCRenderPass* delegatedRenderPass = m_renderPassesInDrawOrder[renderPassIndex];
133 appendRenderPassQuads(quadSink, appendQuadsData, delegatedRenderPass);
134 }
135}
136
137void CCDelegatedRendererLayerImpl::appendRenderPassQuads(CCQuadSink& quadSink, CCAppendQuadsData& appendQuadsData, CCRenderPass* delegatedRenderPass) const
138{
139 const CCSharedQuadState* currentSharedQuadState = 0;
140 CCSharedQuadState* copiedSharedQuadState = 0;
141 for (size_t i = 0; i < delegatedRenderPass->quadList().size(); ++i) {
142 CCDrawQuad* quad = delegatedRenderPass->quadList()[i];
143
144 if (quad->sharedQuadState() != currentSharedQuadState) {
145 currentSharedQuadState = quad->sharedQuadState();
146 copiedSharedQuadState = quadSink.useSharedQuadState(currentSharedQuadState->copy());
147 }
148 ASSERT(copiedSharedQuadState);
149
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);
156
157 copiedSharedQuadState->quadTransform = copiedSharedQuadState->quadTransform * drawTransform();
158 copiedSharedQuadState->opacity *= drawOpacity();
159 }
160
161 OwnPtr<CCDrawQuad> copyQuad;
162 if (quad->material() != CCDrawQuad::RenderPass)
163 copyQuad = quad->copy(copiedSharedQuadState);
164 else {
165 CCRenderPass::Id contributingDelegatedRenderPassId = CCRenderPassDrawQuad::materialCast(quad)->renderPassId();
166 CCRenderPass::Id contributingRenderPassId = convertDelegatedRenderPassId(contributingDelegatedRenderPassId);
167 ASSERT(contributingRenderPassId != appendQuadsData.renderPassId);
168
169 copyQuad = CCRenderPassDrawQuad::materialCast(quad)->copy(copiedSharedQuadState, contributingRenderPassId);
170 }
171 ASSERT(copyQuad);
172
173 quadSink.append(copyQuad.release(), appendQuadsData);
174 }
175}
176
177}