OLD | NEW |
| (Empty) |
1 // Copyright 2011 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 "cc/render_surface_impl.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/stringprintf.h" | |
11 #include "cc/base/math_util.h" | |
12 #include "cc/debug/debug_colors.h" | |
13 #include "cc/delegated_renderer_layer_impl.h" | |
14 #include "cc/layer_impl.h" | |
15 #include "cc/quad_sink.h" | |
16 #include "cc/quads/debug_border_draw_quad.h" | |
17 #include "cc/quads/render_pass.h" | |
18 #include "cc/quads/render_pass_draw_quad.h" | |
19 #include "cc/quads/shared_quad_state.h" | |
20 #include "cc/render_pass_sink.h" | |
21 #include "cc/trees/damage_tracker.h" | |
22 #include "third_party/skia/include/core/SkImageFilter.h" | |
23 #include "ui/gfx/rect_conversions.h" | |
24 #include "ui/gfx/transform.h" | |
25 | |
26 namespace cc { | |
27 | |
28 RenderSurfaceImpl::RenderSurfaceImpl(LayerImpl* owning_layer) | |
29 : owning_layer_(owning_layer), | |
30 surface_property_changed_(false), | |
31 draw_opacity_(1), | |
32 draw_opacity_is_animating_(false), | |
33 target_surface_transforms_are_animating_(false), | |
34 screen_space_transforms_are_animating_(false), | |
35 is_clipped_(false), | |
36 nearest_ancestor_that_moves_pixels_(NULL), | |
37 target_render_surface_layer_index_history_(0), | |
38 current_layer_index_history_(0) { | |
39 damage_tracker_ = DamageTracker::Create(); | |
40 } | |
41 | |
42 RenderSurfaceImpl::~RenderSurfaceImpl() {} | |
43 | |
44 gfx::RectF RenderSurfaceImpl::DrawableContentRect() const { | |
45 gfx::RectF drawable_content_rect = | |
46 MathUtil::MapClippedRect(draw_transform_, content_rect_); | |
47 if (owning_layer_->has_replica()) { | |
48 drawable_content_rect.Union( | |
49 MathUtil::MapClippedRect(replica_draw_transform_, content_rect_)); | |
50 } | |
51 | |
52 return drawable_content_rect; | |
53 } | |
54 | |
55 std::string RenderSurfaceImpl::Name() const { | |
56 return base::StringPrintf("RenderSurfaceImpl(id=%i,owner=%s)", | |
57 owning_layer_->id(), | |
58 owning_layer_->debug_name().data()); | |
59 } | |
60 | |
61 static std::string IndentString(int indent) { | |
62 std::string str; | |
63 for (int i = 0; i != indent; ++i) | |
64 str.append(" "); | |
65 return str; | |
66 } | |
67 | |
68 void RenderSurfaceImpl::DumpSurface(std::string* str, int indent) const { | |
69 std::string indent_str = IndentString(indent); | |
70 str->append(indent_str); | |
71 base::StringAppendF(str, "%s\n", Name().data()); | |
72 | |
73 indent_str.append(" "); | |
74 str->append(indent_str); | |
75 base::StringAppendF(str, | |
76 "content_rect: (%d, %d, %d, %d)\n", | |
77 content_rect_.x(), | |
78 content_rect_.y(), | |
79 content_rect_.width(), | |
80 content_rect_.height()); | |
81 | |
82 str->append(indent_str); | |
83 base::StringAppendF(str, | |
84 "draw_transform: " | |
85 "%f, %f, %f, %f, " | |
86 "%f, %f, %f, %f, " | |
87 "%f, %f, %f, %f, " | |
88 "%f, %f, %f, %f\n", | |
89 draw_transform_.matrix().getDouble(0, 0), | |
90 draw_transform_.matrix().getDouble(0, 1), | |
91 draw_transform_.matrix().getDouble(0, 2), | |
92 draw_transform_.matrix().getDouble(0, 3), | |
93 draw_transform_.matrix().getDouble(1, 0), | |
94 draw_transform_.matrix().getDouble(1, 1), | |
95 draw_transform_.matrix().getDouble(1, 2), | |
96 draw_transform_.matrix().getDouble(1, 3), | |
97 draw_transform_.matrix().getDouble(2, 0), | |
98 draw_transform_.matrix().getDouble(2, 1), | |
99 draw_transform_.matrix().getDouble(2, 2), | |
100 draw_transform_.matrix().getDouble(2, 3), | |
101 draw_transform_.matrix().getDouble(3, 0), | |
102 draw_transform_.matrix().getDouble(3, 1), | |
103 draw_transform_.matrix().getDouble(3, 2), | |
104 draw_transform_.matrix().getDouble(3, 3)); | |
105 | |
106 str->append(indent_str); | |
107 base::StringAppendF(str, | |
108 "damageRect is pos(%f, %f), size(%f, %f)\n", | |
109 damage_tracker_->current_damage_rect().x(), | |
110 damage_tracker_->current_damage_rect().y(), | |
111 damage_tracker_->current_damage_rect().width(), | |
112 damage_tracker_->current_damage_rect().height()); | |
113 } | |
114 | |
115 int RenderSurfaceImpl::OwningLayerId() const { | |
116 return owning_layer_ ? owning_layer_->id() : 0; | |
117 } | |
118 | |
119 | |
120 void RenderSurfaceImpl::SetClipRect(gfx::Rect clip_rect) { | |
121 if (clip_rect_ == clip_rect) | |
122 return; | |
123 | |
124 surface_property_changed_ = true; | |
125 clip_rect_ = clip_rect; | |
126 } | |
127 | |
128 bool RenderSurfaceImpl::ContentsChanged() const { | |
129 return !damage_tracker_->current_damage_rect().IsEmpty(); | |
130 } | |
131 | |
132 void RenderSurfaceImpl::SetContentRect(gfx::Rect content_rect) { | |
133 if (content_rect_ == content_rect) | |
134 return; | |
135 | |
136 surface_property_changed_ = true; | |
137 content_rect_ = content_rect; | |
138 } | |
139 | |
140 bool RenderSurfaceImpl::SurfacePropertyChanged() const { | |
141 // Surface property changes are tracked as follows: | |
142 // | |
143 // - surface_property_changed_ is flagged when the clip_rect or content_rect | |
144 // change. As of now, these are the only two properties that can be affected | |
145 // by descendant layers. | |
146 // | |
147 // - all other property changes come from the owning layer (or some ancestor | |
148 // layer that propagates its change to the owning layer). | |
149 // | |
150 DCHECK(owning_layer_); | |
151 return surface_property_changed_ || owning_layer_->LayerPropertyChanged(); | |
152 } | |
153 | |
154 bool RenderSurfaceImpl::SurfacePropertyChangedOnlyFromDescendant() const { | |
155 return surface_property_changed_ && !owning_layer_->LayerPropertyChanged(); | |
156 } | |
157 | |
158 void RenderSurfaceImpl::AddContributingDelegatedRenderPassLayer( | |
159 LayerImpl* layer) { | |
160 DCHECK(std::find(layer_list_.begin(), layer_list_.end(), layer) != | |
161 layer_list_.end()); | |
162 DelegatedRendererLayerImpl* delegated_renderer_layer = | |
163 static_cast<DelegatedRendererLayerImpl*>(layer); | |
164 contributing_delegated_render_pass_layer_list_.push_back( | |
165 delegated_renderer_layer); | |
166 } | |
167 | |
168 void RenderSurfaceImpl::ClearLayerLists() { | |
169 layer_list_.clear(); | |
170 contributing_delegated_render_pass_layer_list_.clear(); | |
171 } | |
172 | |
173 RenderPass::Id RenderSurfaceImpl::RenderPassId() { | |
174 int layer_id = owning_layer_->id(); | |
175 int sub_id = 0; | |
176 DCHECK_GT(layer_id, 0); | |
177 return RenderPass::Id(layer_id, sub_id); | |
178 } | |
179 | |
180 void RenderSurfaceImpl::AppendRenderPasses(RenderPassSink* pass_sink) { | |
181 for (size_t i = 0; | |
182 i < contributing_delegated_render_pass_layer_list_.size(); | |
183 ++i) { | |
184 DelegatedRendererLayerImpl* delegated_renderer_layer = | |
185 contributing_delegated_render_pass_layer_list_[i]; | |
186 delegated_renderer_layer->AppendContributingRenderPasses(pass_sink); | |
187 } | |
188 | |
189 scoped_ptr<RenderPass> pass = RenderPass::Create(); | |
190 pass->SetNew(RenderPassId(), | |
191 content_rect_, | |
192 damage_tracker_->current_damage_rect(), | |
193 screen_space_transform_); | |
194 pass_sink->AppendRenderPass(pass.Pass()); | |
195 } | |
196 | |
197 void RenderSurfaceImpl::AppendQuads(QuadSink* quad_sink, | |
198 AppendQuadsData* append_quads_data, | |
199 bool for_replica, | |
200 RenderPass::Id render_pass_id) { | |
201 DCHECK(!for_replica || owning_layer_->has_replica()); | |
202 | |
203 const gfx::Transform& draw_transform = | |
204 for_replica ? replica_draw_transform_ : draw_transform_; | |
205 SharedQuadState* shared_quad_state = | |
206 quad_sink->UseSharedQuadState(SharedQuadState::Create()); | |
207 shared_quad_state->SetAll(draw_transform, | |
208 content_rect_.size(), | |
209 content_rect_, | |
210 clip_rect_, | |
211 is_clipped_, | |
212 draw_opacity_); | |
213 | |
214 if (owning_layer_->ShowDebugBorders()) { | |
215 SkColor color = for_replica ? | |
216 DebugColors::SurfaceReplicaBorderColor() : | |
217 DebugColors::SurfaceBorderColor(); | |
218 float width = for_replica ? | |
219 DebugColors::SurfaceReplicaBorderWidth( | |
220 owning_layer_->layer_tree_impl()) : | |
221 DebugColors::SurfaceBorderWidth( | |
222 owning_layer_->layer_tree_impl()); | |
223 scoped_ptr<DebugBorderDrawQuad> debug_border_quad = | |
224 DebugBorderDrawQuad::Create(); | |
225 debug_border_quad->SetNew(shared_quad_state, content_rect_, color, width); | |
226 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data); | |
227 } | |
228 | |
229 // FIXME: By using the same RenderSurfaceImpl for both the content and its | |
230 // reflection, it's currently not possible to apply a separate mask to the | |
231 // reflection layer or correctly handle opacity in reflections (opacity must | |
232 // be applied after drawing both the layer and its reflection). The solution | |
233 // is to introduce yet another RenderSurfaceImpl to draw the layer and its | |
234 // reflection in. For now we only apply a separate reflection mask if the | |
235 // contents don't have a mask of their own. | |
236 LayerImpl* mask_layer = owning_layer_->mask_layer(); | |
237 if (mask_layer && | |
238 (!mask_layer->DrawsContent() || mask_layer->bounds().IsEmpty())) | |
239 mask_layer = NULL; | |
240 | |
241 if (!mask_layer && for_replica) { | |
242 mask_layer = owning_layer_->replica_layer()->mask_layer(); | |
243 if (mask_layer && | |
244 (!mask_layer->DrawsContent() || mask_layer->bounds().IsEmpty())) | |
245 mask_layer = NULL; | |
246 } | |
247 | |
248 gfx::RectF mask_uv_rect(0.f, 0.f, 1.f, 1.f); | |
249 if (mask_layer) { | |
250 gfx::Vector2dF owning_layer_draw_scale = | |
251 MathUtil::ComputeTransform2dScaleComponents( | |
252 owning_layer_->draw_transform(), 1.f); | |
253 gfx::SizeF unclipped_surface_size = gfx::ScaleSize( | |
254 owning_layer_->content_bounds(), | |
255 owning_layer_draw_scale.x(), | |
256 owning_layer_draw_scale.y()); | |
257 // This assumes that the owning layer clips its subtree when a mask is | |
258 // present. | |
259 DCHECK(gfx::RectF(unclipped_surface_size).Contains(content_rect_)); | |
260 | |
261 float uv_scale_x = content_rect_.width() / unclipped_surface_size.width(); | |
262 float uv_scale_y = content_rect_.height() / unclipped_surface_size.height(); | |
263 | |
264 mask_uv_rect = gfx::RectF( | |
265 uv_scale_x * content_rect_.x() / content_rect_.width(), | |
266 uv_scale_y * content_rect_.y() / content_rect_.height(), | |
267 uv_scale_x, | |
268 uv_scale_y); | |
269 } | |
270 | |
271 ResourceProvider::ResourceId mask_resource_id = | |
272 mask_layer ? mask_layer->ContentsResourceId() : 0; | |
273 gfx::Rect contents_changed_since_last_frame = | |
274 ContentsChanged() ? content_rect_ : gfx::Rect(); | |
275 | |
276 scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create(); | |
277 quad->SetNew(shared_quad_state, | |
278 content_rect_, | |
279 render_pass_id, | |
280 for_replica, | |
281 mask_resource_id, | |
282 contents_changed_since_last_frame, | |
283 mask_uv_rect, | |
284 owning_layer_->filters(), | |
285 owning_layer_->filter(), | |
286 owning_layer_->background_filters()); | |
287 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
288 } | |
289 | |
290 } // namespace cc | |
OLD | NEW |