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.
5 #include "cc/delegated_renderer_layer_impl.h"
7 #include "cc/append_quads_data.h"
8 #include "cc/math_util.h"
9 #include "cc/quad_sink.h"
10 #include "cc/render_pass_draw_quad.h"
11 #include "cc/render_pass_sink.h"
15 DelegatedRendererLayerImpl::DelegatedRendererLayerImpl(
16 LayerTreeImpl
* tree_impl
, int id
)
17 : LayerImpl(tree_impl
, id
) {
20 DelegatedRendererLayerImpl::~DelegatedRendererLayerImpl() {
24 bool DelegatedRendererLayerImpl::hasDelegatedContent() const {
25 return !render_passes_in_draw_order_
.empty();
28 bool DelegatedRendererLayerImpl::hasContributingDelegatedRenderPasses() const {
29 // The root RenderPass for the layer is merged with its target
30 // RenderPass in each frame. So we only have extra RenderPasses
31 // to merge when we have a non-root RenderPass present.
32 return render_passes_in_draw_order_
.size() > 1;
35 void DelegatedRendererLayerImpl::SetRenderPasses(
36 ScopedPtrVector
<RenderPass
>& render_passes_in_draw_order
) {
37 gfx::RectF old_root_damage
;
38 if (!render_passes_in_draw_order_
.empty())
39 old_root_damage
= render_passes_in_draw_order_
.back()->damage_rect
;
43 for (size_t i
= 0; i
< render_passes_in_draw_order
.size(); ++i
) {
44 render_passes_index_by_id_
.insert(
45 std::pair
<RenderPass::Id
, int>(render_passes_in_draw_order
[i
]->id
, i
));
46 scoped_ptr
<RenderPass
> passed_render_pass
=
47 render_passes_in_draw_order
.take(
48 render_passes_in_draw_order
.begin() + i
);
49 render_passes_in_draw_order_
.push_back(passed_render_pass
.Pass());
51 render_passes_in_draw_order
.clear();
53 if (!render_passes_in_draw_order_
.empty())
54 render_passes_in_draw_order_
.back()->damage_rect
.Union(old_root_damage
);
57 void DelegatedRendererLayerImpl::ClearRenderPasses() {
58 // FIXME: Release the resources back to the nested compositor.
59 render_passes_index_by_id_
.clear();
60 render_passes_in_draw_order_
.clear();
63 scoped_ptr
<LayerImpl
> DelegatedRendererLayerImpl::createLayerImpl(LayerTreeImpl
* treeImpl
)
65 return DelegatedRendererLayerImpl::create(treeImpl
, id()).PassAs
<LayerImpl
>();
68 void DelegatedRendererLayerImpl::didLoseOutputSurface() {
72 static inline int IndexToId(int index
) { return index
+ 1; }
73 static inline int IdToIndex(int id
) { return id
- 1; }
75 RenderPass::Id
DelegatedRendererLayerImpl::firstContributingRenderPassId()
77 return RenderPass::Id(id(), IndexToId(0));
80 RenderPass::Id
DelegatedRendererLayerImpl::nextContributingRenderPassId(
81 RenderPass::Id previous
) const {
82 return RenderPass::Id(previous
.layer_id
, previous
.index
+ 1);
85 RenderPass::Id
DelegatedRendererLayerImpl::ConvertDelegatedRenderPassId(
86 RenderPass::Id delegated_render_pass_id
) const {
87 base::hash_map
<RenderPass::Id
, int>::const_iterator found
=
88 render_passes_index_by_id_
.find(delegated_render_pass_id
);
89 DCHECK(found
!= render_passes_index_by_id_
.end());
90 unsigned delegatedRenderPassIndex
= found
->second
;
91 return RenderPass::Id(id(), IndexToId(delegatedRenderPassIndex
));
94 void DelegatedRendererLayerImpl::AppendContributingRenderPasses(
95 RenderPassSink
* render_pass_sink
) {
96 DCHECK(hasContributingDelegatedRenderPasses());
98 for (size_t i
= 0; i
< render_passes_in_draw_order_
.size() - 1; ++i
) {
99 RenderPass::Id output_render_pass_id
=
100 ConvertDelegatedRenderPassId(render_passes_in_draw_order_
[i
]->id
);
102 // Don't clash with the RenderPass we generate if we own a RenderSurface.
103 DCHECK(output_render_pass_id
.index
> 0);
105 render_pass_sink
->appendRenderPass(
106 render_passes_in_draw_order_
[i
]->Copy(output_render_pass_id
));
110 void DelegatedRendererLayerImpl::appendQuads(
111 QuadSink
& quad_sink
, AppendQuadsData
& append_quads_data
) {
112 if (render_passes_in_draw_order_
.empty())
115 RenderPass::Id target_render_pass_id
= append_quads_data
.renderPassId
;
117 const RenderPass
* root_delegated_render_pass
=
118 render_passes_in_draw_order_
.back();
120 DCHECK(root_delegated_render_pass
->output_rect
.origin().IsOrigin());
121 gfx::Size frame_size
= root_delegated_render_pass
->output_rect
.size();
123 // If the index of the renderPassId is 0, then it is a renderPass generated
124 // for a layer in this compositor, not the delegated renderer. Then we want to
125 // merge our root renderPass with the target renderPass. Otherwise, it is some
126 // renderPass which we added from the delegated renderer.
127 bool should_merge_root_render_pass_with_target
= !target_render_pass_id
.index
;
128 if (should_merge_root_render_pass_with_target
) {
129 // Verify that the renderPass we are appending to is created our
131 DCHECK(target_render_pass_id
.layer_id
== renderTarget()->id());
133 AppendRenderPassQuads(
134 &quad_sink
, &append_quads_data
, root_delegated_render_pass
, frame_size
);
136 // Verify that the renderPass we are appending to was created by us.
137 DCHECK(target_render_pass_id
.layer_id
== id());
139 int render_pass_index
= IdToIndex(target_render_pass_id
.index
);
140 const RenderPass
* delegated_render_pass
=
141 render_passes_in_draw_order_
[render_pass_index
];
142 AppendRenderPassQuads(
143 &quad_sink
, &append_quads_data
, delegated_render_pass
, frame_size
);
147 void DelegatedRendererLayerImpl::AppendRenderPassQuads(
149 AppendQuadsData
* append_quads_data
,
150 const RenderPass
* delegated_render_pass
,
151 gfx::Size frame_size
) const {
153 const SharedQuadState
* delegated_shared_quad_state
= NULL
;
154 SharedQuadState
* output_shared_quad_state
= NULL
;
156 for (size_t i
= 0; i
< delegated_render_pass
->quad_list
.size(); ++i
) {
157 const DrawQuad
* delegated_quad
= delegated_render_pass
->quad_list
[i
];
159 if (delegated_quad
->shared_quad_state
!= delegated_shared_quad_state
) {
160 delegated_shared_quad_state
= delegated_quad
->shared_quad_state
;
161 output_shared_quad_state
= quad_sink
->useSharedQuadState(
162 delegated_shared_quad_state
->Copy());
164 bool is_root_delegated_render_pass
=
165 delegated_render_pass
== render_passes_in_draw_order_
.back();
166 if (is_root_delegated_render_pass
) {
167 // Don't allow areas inside the bounds that are empty.
168 DCHECK(display_size_
.IsEmpty() ||
169 gfx::Rect(display_size_
).Contains(gfx::Rect(bounds())));
170 gfx::Size display_size
=
171 display_size_
.IsEmpty() ? bounds() : display_size_
;
173 gfx::Transform delegated_frame_to_layer_space_transform
;
174 delegated_frame_to_layer_space_transform
.Scale(
175 static_cast<double>(display_size
.width()) / frame_size
.width(),
176 static_cast<double>(display_size
.height()) / frame_size
.height());
178 gfx::Transform delegated_frame_to_target_transform
=
179 drawTransform() * delegated_frame_to_layer_space_transform
;
181 output_shared_quad_state
->content_to_target_transform
.ConcatTransform(
182 delegated_frame_to_target_transform
);
184 if (renderTarget() == this) {
185 DCHECK(!isClipped());
186 DCHECK(renderSurface());
187 output_shared_quad_state
->clip_rect
= MathUtil::mapClippedRect(
188 delegated_frame_to_target_transform
,
189 output_shared_quad_state
->clip_rect
);
191 gfx::Rect clip_rect
= drawableContentRect();
192 if (output_shared_quad_state
->is_clipped
) {
193 clip_rect
.Intersect(MathUtil::mapClippedRect(
194 delegated_frame_to_target_transform
,
195 output_shared_quad_state
->clip_rect
));
197 output_shared_quad_state
->clip_rect
= clip_rect
;
198 output_shared_quad_state
->is_clipped
= true;
201 output_shared_quad_state
->opacity
*= drawOpacity();
204 DCHECK(output_shared_quad_state
);
206 scoped_ptr
<DrawQuad
> output_quad
;
207 if (delegated_quad
->material
!= DrawQuad::RENDER_PASS
) {
208 output_quad
= delegated_quad
->Copy(output_shared_quad_state
);
210 RenderPass::Id delegated_contributing_render_pass_id
=
211 RenderPassDrawQuad::MaterialCast(delegated_quad
)->render_pass_id
;
212 RenderPass::Id output_contributing_render_pass_id
=
213 ConvertDelegatedRenderPassId(delegated_contributing_render_pass_id
);
214 DCHECK(output_contributing_render_pass_id
!=
215 append_quads_data
->renderPassId
);
217 output_quad
= RenderPassDrawQuad::MaterialCast(delegated_quad
)->Copy(
218 output_shared_quad_state
,
219 output_contributing_render_pass_id
).PassAs
<DrawQuad
>();
221 DCHECK(output_quad
.get());
223 quad_sink
->append(output_quad
.Pass(), *append_quads_data
);
227 const char* DelegatedRendererLayerImpl::layerTypeAsString() const {
228 return "DelegatedRendererLayer";