OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/compositor/layer.h" | 5 #include "ui/gfx/compositor/layer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebContentLa
yer.h" | 13 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebContentLa
yer.h" |
14 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebExternalT
extureLayer.h" | 14 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebExternalT
extureLayer.h" |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatPoin
t.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatPoin
t.h" |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatRect
.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatRect
.h" |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" |
18 #include "ui/base/animation/animation.h" | 18 #include "ui/base/animation/animation.h" |
19 #include "ui/gfx/canvas_skia.h" | 19 #include "ui/gfx/canvas_skia.h" |
20 #include "ui/gfx/compositor/compositor_switches.h" | 20 #include "ui/gfx/compositor/compositor_switches.h" |
21 #include "ui/gfx/compositor/layer_animator.h" | 21 #include "ui/gfx/compositor/layer_animator.h" |
22 #include "ui/gfx/interpolated_transform.h" | 22 #include "ui/gfx/interpolated_transform.h" |
23 #include "ui/gfx/point3.h" | 23 #include "ui/gfx/point3.h" |
24 | 24 |
25 #if defined(USE_WEBKIT_COMPOSITOR) | |
26 #include "ui/gfx/compositor/compositor_cc.h" | 25 #include "ui/gfx/compositor/compositor_cc.h" |
27 #endif | |
28 | 26 |
29 namespace { | 27 namespace { |
30 | 28 |
31 const float EPSILON = 1e-3f; | 29 const float EPSILON = 1e-3f; |
32 | 30 |
33 bool IsApproximateMultilpleOf(float value, float base) { | 31 bool IsApproximateMultilpleOf(float value, float base) { |
34 float remainder = fmod(fabs(value), base); | 32 float remainder = fmod(fabs(value), base); |
35 return remainder < EPSILON || base - remainder < EPSILON; | 33 return remainder < EPSILON || base - remainder < EPSILON; |
36 } | 34 } |
37 | 35 |
38 const ui::Layer* GetRoot(const ui::Layer* layer) { | 36 const ui::Layer* GetRoot(const ui::Layer* layer) { |
39 return layer->parent() ? GetRoot(layer->parent()) : layer; | 37 return layer->parent() ? GetRoot(layer->parent()) : layer; |
40 } | 38 } |
41 | 39 |
42 } // namespace | 40 } // namespace |
43 | 41 |
44 namespace ui { | 42 namespace ui { |
45 | 43 |
46 Layer::Layer() | 44 Layer::Layer() |
47 : type_(LAYER_HAS_TEXTURE), | 45 : type_(LAYER_HAS_TEXTURE), |
48 compositor_(NULL), | 46 compositor_(NULL), |
49 parent_(NULL), | 47 parent_(NULL), |
50 visible_(true), | 48 visible_(true), |
51 fills_bounds_opaquely_(true), | 49 fills_bounds_opaquely_(true), |
52 recompute_hole_(false), | |
53 layer_updated_externally_(false), | 50 layer_updated_externally_(false), |
54 opacity_(1.0f), | 51 opacity_(1.0f), |
55 delegate_(NULL) { | 52 delegate_(NULL) { |
56 #if defined(USE_WEBKIT_COMPOSITOR) | |
57 CreateWebLayer(); | 53 CreateWebLayer(); |
58 #endif | |
59 } | 54 } |
60 | 55 |
61 Layer::Layer(LayerType type) | 56 Layer::Layer(LayerType type) |
62 : type_(type), | 57 : type_(type), |
63 compositor_(NULL), | 58 compositor_(NULL), |
64 parent_(NULL), | 59 parent_(NULL), |
65 visible_(true), | 60 visible_(true), |
66 fills_bounds_opaquely_(true), | 61 fills_bounds_opaquely_(true), |
67 recompute_hole_(false), | |
68 layer_updated_externally_(false), | 62 layer_updated_externally_(false), |
69 opacity_(1.0f), | 63 opacity_(1.0f), |
70 delegate_(NULL) { | 64 delegate_(NULL) { |
71 #if defined(USE_WEBKIT_COMPOSITOR) | |
72 CreateWebLayer(); | 65 CreateWebLayer(); |
73 #endif | |
74 } | 66 } |
75 | 67 |
76 Layer::~Layer() { | 68 Layer::~Layer() { |
77 if (compositor_) | 69 if (compositor_) |
78 compositor_->SetRootLayer(NULL); | 70 compositor_->SetRootLayer(NULL); |
79 if (parent_) | 71 if (parent_) |
80 parent_->Remove(this); | 72 parent_->Remove(this); |
81 for (size_t i = 0; i < children_.size(); ++i) | 73 for (size_t i = 0; i < children_.size(); ++i) |
82 children_[i]->parent_ = NULL; | 74 children_[i]->parent_ = NULL; |
83 #if defined(USE_WEBKIT_COMPOSITOR) | |
84 web_layer_.removeFromParent(); | 75 web_layer_.removeFromParent(); |
85 #endif | |
86 } | 76 } |
87 | 77 |
88 Compositor* Layer::GetCompositor() { | 78 Compositor* Layer::GetCompositor() { |
89 return GetRoot(this)->compositor_; | 79 return GetRoot(this)->compositor_; |
90 } | 80 } |
91 | 81 |
92 void Layer::SetCompositor(Compositor* compositor) { | 82 void Layer::SetCompositor(Compositor* compositor) { |
93 // This function must only be called to set the compositor on the root layer, | 83 // This function must only be called to set the compositor on the root layer, |
94 // or to reset it. | 84 // or to reset it. |
95 DCHECK(!compositor || !compositor_); | 85 DCHECK(!compositor || !compositor_); |
96 DCHECK(!compositor || compositor->root_layer() == this); | 86 DCHECK(!compositor || compositor->root_layer() == this); |
97 DCHECK(!parent_); | 87 DCHECK(!parent_); |
98 compositor_ = compositor; | 88 compositor_ = compositor; |
99 } | 89 } |
100 | 90 |
101 void Layer::Add(Layer* child) { | 91 void Layer::Add(Layer* child) { |
102 DCHECK(!child->compositor_); | 92 DCHECK(!child->compositor_); |
103 if (child->parent_) | 93 if (child->parent_) |
104 child->parent_->Remove(child); | 94 child->parent_->Remove(child); |
105 child->parent_ = this; | 95 child->parent_ = this; |
106 children_.push_back(child); | 96 children_.push_back(child); |
107 #if defined(USE_WEBKIT_COMPOSITOR) | |
108 web_layer_.addChild(child->web_layer_); | 97 web_layer_.addChild(child->web_layer_); |
109 #endif | |
110 | |
111 SetNeedsToRecomputeHole(); | |
112 } | 98 } |
113 | 99 |
114 void Layer::Remove(Layer* child) { | 100 void Layer::Remove(Layer* child) { |
115 std::vector<Layer*>::iterator i = | 101 std::vector<Layer*>::iterator i = |
116 std::find(children_.begin(), children_.end(), child); | 102 std::find(children_.begin(), children_.end(), child); |
117 DCHECK(i != children_.end()); | 103 DCHECK(i != children_.end()); |
118 children_.erase(i); | 104 children_.erase(i); |
119 child->parent_ = NULL; | 105 child->parent_ = NULL; |
120 #if defined(USE_WEBKIT_COMPOSITOR) | |
121 child->web_layer_.removeFromParent(); | 106 child->web_layer_.removeFromParent(); |
122 #endif | |
123 | |
124 SetNeedsToRecomputeHole(); | |
125 | |
126 child->DropTextures(); | |
127 } | 107 } |
128 | 108 |
129 void Layer::StackAtTop(Layer* child) { | 109 void Layer::StackAtTop(Layer* child) { |
130 if (children_.size() <= 1 || child == children_.back()) | 110 if (children_.size() <= 1 || child == children_.back()) |
131 return; // Already in front. | 111 return; // Already in front. |
132 StackAbove(child, children_.back()); | 112 StackAbove(child, children_.back()); |
133 } | 113 } |
134 | 114 |
135 void Layer::StackAbove(Layer* child, Layer* other) { | 115 void Layer::StackAbove(Layer* child, Layer* other) { |
136 StackRelativeTo(child, other, true); | 116 StackRelativeTo(child, other, true); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 float Layer::GetTargetOpacity() const { | 173 float Layer::GetTargetOpacity() const { |
194 if (animator_.get() && animator_->is_animating()) | 174 if (animator_.get() && animator_->is_animating()) |
195 return animator_->GetTargetOpacity(); | 175 return animator_->GetTargetOpacity(); |
196 return opacity_; | 176 return opacity_; |
197 } | 177 } |
198 | 178 |
199 void Layer::SetVisible(bool visible) { | 179 void Layer::SetVisible(bool visible) { |
200 if (visible_ == visible) | 180 if (visible_ == visible) |
201 return; | 181 return; |
202 | 182 |
203 bool was_drawn = IsDrawn(); | |
204 visible_ = visible; | 183 visible_ = visible; |
205 #if defined(USE_WEBKIT_COMPOSITOR) | |
206 // TODO(piman): Expose a visibility flag on WebLayer. | 184 // TODO(piman): Expose a visibility flag on WebLayer. |
207 web_layer_.setOpacity(visible_ ? opacity_ : 0.f); | 185 web_layer_.setOpacity(visible_ ? opacity_ : 0.f); |
208 #endif | |
209 bool is_drawn = IsDrawn(); | |
210 if (was_drawn == is_drawn) | |
211 return; | |
212 | |
213 if (!is_drawn) | |
214 DropTextures(); | |
215 SetNeedsToRecomputeHole(); | |
216 } | 186 } |
217 | 187 |
218 bool Layer::IsDrawn() const { | 188 bool Layer::IsDrawn() const { |
219 const Layer* layer = this; | 189 const Layer* layer = this; |
220 while (layer && layer->visible_) | 190 while (layer && layer->visible_) |
221 layer = layer->parent_; | 191 layer = layer->parent_; |
222 return layer == NULL; | 192 return layer == NULL; |
223 } | 193 } |
224 | 194 |
225 bool Layer::ShouldDraw() const { | 195 bool Layer::ShouldDraw() const { |
226 return type_ == LAYER_HAS_TEXTURE && GetCombinedOpacity() > 0.0f && | 196 return type_ == LAYER_HAS_TEXTURE && GetCombinedOpacity() > 0.0f; |
227 !hole_rect_.Contains(gfx::Rect(gfx::Point(0, 0), bounds_.size())); | |
228 } | 197 } |
229 | 198 |
230 // static | 199 // static |
231 void Layer::ConvertPointToLayer(const Layer* source, | 200 void Layer::ConvertPointToLayer(const Layer* source, |
232 const Layer* target, | 201 const Layer* target, |
233 gfx::Point* point) { | 202 gfx::Point* point) { |
234 if (source == target) | 203 if (source == target) |
235 return; | 204 return; |
236 | 205 |
237 const Layer* root_layer = GetRoot(source); | 206 const Layer* root_layer = GetRoot(source); |
238 CHECK_EQ(root_layer, GetRoot(target)); | 207 CHECK_EQ(root_layer, GetRoot(target)); |
239 | 208 |
240 if (source != root_layer) | 209 if (source != root_layer) |
241 source->ConvertPointForAncestor(root_layer, point); | 210 source->ConvertPointForAncestor(root_layer, point); |
242 if (target != root_layer) | 211 if (target != root_layer) |
243 target->ConvertPointFromAncestor(root_layer, point); | 212 target->ConvertPointFromAncestor(root_layer, point); |
244 } | 213 } |
245 | 214 |
246 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) { | 215 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) { |
247 if (fills_bounds_opaquely_ == fills_bounds_opaquely) | 216 if (fills_bounds_opaquely_ == fills_bounds_opaquely) |
248 return; | 217 return; |
249 | 218 |
250 fills_bounds_opaquely_ = fills_bounds_opaquely; | 219 fills_bounds_opaquely_ = fills_bounds_opaquely; |
251 | 220 |
252 SetNeedsToRecomputeHole(); | |
253 #if defined(USE_WEBKIT_COMPOSITOR) | |
254 web_layer_.setOpaque(fills_bounds_opaquely); | 221 web_layer_.setOpaque(fills_bounds_opaquely); |
255 RecomputeDebugBorderColor(); | 222 RecomputeDebugBorderColor(); |
256 #endif | |
257 } | 223 } |
258 | 224 |
259 void Layer::SetExternalTexture(ui::Texture* texture) { | 225 void Layer::SetExternalTexture(ui::Texture* texture) { |
260 layer_updated_externally_ = !!texture; | 226 layer_updated_externally_ = !!texture; |
261 texture_ = texture; | 227 texture_ = texture; |
262 #if defined(USE_WEBKIT_COMPOSITOR) | |
263 if (web_layer_is_accelerated_ != layer_updated_externally_) { | 228 if (web_layer_is_accelerated_ != layer_updated_externally_) { |
264 // Switch to a different type of layer. | 229 // Switch to a different type of layer. |
265 web_layer_.removeAllChildren(); | 230 web_layer_.removeAllChildren(); |
266 WebKit::WebLayer new_layer; | 231 WebKit::WebLayer new_layer; |
267 if (layer_updated_externally_) | 232 if (layer_updated_externally_) |
268 new_layer = WebKit::WebExternalTextureLayer::create(); | 233 new_layer = WebKit::WebExternalTextureLayer::create(); |
269 else | 234 else |
270 new_layer = WebKit::WebContentLayer::create(this); | 235 new_layer = WebKit::WebContentLayer::create(this); |
271 if (parent_) { | 236 if (parent_) { |
272 DCHECK(!parent_->web_layer_.isNull()); | 237 DCHECK(!parent_->web_layer_.isNull()); |
(...skipping 13 matching lines...) Expand all Loading... |
286 RecomputeDebugBorderColor(); | 251 RecomputeDebugBorderColor(); |
287 } | 252 } |
288 if (texture) { | 253 if (texture) { |
289 TextureCC* texture_cc = static_cast<TextureCC*>(texture); | 254 TextureCC* texture_cc = static_cast<TextureCC*>(texture); |
290 texture_cc->Update(); | 255 texture_cc->Update(); |
291 WebKit::WebExternalTextureLayer texture_layer = | 256 WebKit::WebExternalTextureLayer texture_layer = |
292 web_layer_.to<WebKit::WebExternalTextureLayer>(); | 257 web_layer_.to<WebKit::WebExternalTextureLayer>(); |
293 texture_layer.setFlipped(texture_cc->flipped()); | 258 texture_layer.setFlipped(texture_cc->flipped()); |
294 } | 259 } |
295 RecomputeDrawsContentAndUVRect(); | 260 RecomputeDrawsContentAndUVRect(); |
296 #endif | |
297 } | 261 } |
298 | 262 |
299 void Layer::SetCanvas(const SkCanvas& canvas, const gfx::Point& origin) { | 263 void Layer::SetCanvas(const SkCanvas& canvas, const gfx::Point& origin) { |
300 #if defined(USE_WEBKIT_COMPOSITOR) | |
301 NOTREACHED(); | 264 NOTREACHED(); |
302 #else | |
303 DCHECK_EQ(type_, LAYER_HAS_TEXTURE); | |
304 | |
305 if (!texture_.get()) | |
306 texture_ = GetCompositor()->CreateTexture(); | |
307 | |
308 texture_->SetCanvas(canvas, origin, bounds_.size()); | |
309 invalid_rect_ = gfx::Rect(); | |
310 #endif | |
311 } | 265 } |
312 | 266 |
313 void Layer::SchedulePaint(const gfx::Rect& invalid_rect) { | 267 void Layer::SchedulePaint(const gfx::Rect& invalid_rect) { |
314 #if defined(USE_WEBKIT_COMPOSITOR) | |
315 WebKit::WebFloatRect web_rect( | 268 WebKit::WebFloatRect web_rect( |
316 invalid_rect.x(), | 269 invalid_rect.x(), |
317 invalid_rect.y(), | 270 invalid_rect.y(), |
318 invalid_rect.width(), | 271 invalid_rect.width(), |
319 invalid_rect.height()); | 272 invalid_rect.height()); |
320 if (!web_layer_is_accelerated_) | 273 if (!web_layer_is_accelerated_) |
321 web_layer_.to<WebKit::WebContentLayer>().invalidateRect(web_rect); | 274 web_layer_.to<WebKit::WebContentLayer>().invalidateRect(web_rect); |
322 else | 275 else |
323 web_layer_.to<WebKit::WebExternalTextureLayer>().invalidateRect(web_rect); | 276 web_layer_.to<WebKit::WebExternalTextureLayer>().invalidateRect(web_rect); |
324 #else | |
325 invalid_rect_ = invalid_rect_.Union(invalid_rect); | |
326 ScheduleDraw(); | |
327 #endif | |
328 } | 277 } |
329 | 278 |
330 void Layer::ScheduleDraw() { | 279 void Layer::ScheduleDraw() { |
331 Compositor* compositor = GetCompositor(); | 280 Compositor* compositor = GetCompositor(); |
332 if (compositor) | 281 if (compositor) |
333 compositor->ScheduleDraw(); | 282 compositor->ScheduleDraw(); |
334 } | 283 } |
335 | 284 |
336 void Layer::Draw() { | |
337 TRACE_EVENT0("ui", "Layer::Draw"); | |
338 #if defined(USE_WEBKIT_COMPOSITOR) | |
339 NOTREACHED(); | |
340 #else | |
341 DCHECK(GetCompositor()); | |
342 | |
343 if (recompute_hole_ && !parent_) | |
344 RecomputeHole(); | |
345 | |
346 if (!ShouldDraw()) | |
347 return; | |
348 | |
349 UpdateLayerCanvas(); | |
350 | |
351 // Layer drew nothing, no texture was created. | |
352 if (!texture_.get()) | |
353 return; | |
354 | |
355 ui::TextureDrawParams texture_draw_params; | |
356 for (Layer* layer = this; layer; layer = layer->parent_) { | |
357 texture_draw_params.transform.ConcatTransform(layer->transform_); | |
358 texture_draw_params.transform.ConcatTranslate( | |
359 static_cast<float>(layer->bounds_.x()), | |
360 static_cast<float>(layer->bounds_.y())); | |
361 } | |
362 | |
363 const float combined_opacity = GetCombinedOpacity(); | |
364 | |
365 // Only blend for transparent child layers (and when we're forcing | |
366 // transparency). The root layer will clobber the cleared bg. | |
367 const bool is_root = parent_ == NULL; | |
368 const bool forcing_transparency = combined_opacity < 1.0f; | |
369 const bool is_opaque = fills_bounds_opaquely_ || !has_valid_alpha_channel(); | |
370 texture_draw_params.blend = !is_root && (forcing_transparency || !is_opaque); | |
371 | |
372 texture_draw_params.compositor_size = GetCompositor()->size(); | |
373 texture_draw_params.opacity = combined_opacity; | |
374 texture_draw_params.has_valid_alpha_channel = has_valid_alpha_channel(); | |
375 | |
376 #if defined(OS_WIN) | |
377 // TODO(beng): figure out why the other branch of this code renders improperly | |
378 // on Windows, and fix it, otherwise just remove all of this when | |
379 // WK compositor is default. | |
380 texture_->Draw(texture_draw_params, gfx::Rect(gfx::Point(), bounds().size())); | |
381 #else | |
382 std::vector<gfx::Rect> regions_to_draw; | |
383 PunchHole(gfx::Rect(gfx::Point(), bounds().size()), hole_rect_, | |
384 ®ions_to_draw); | |
385 | |
386 for (size_t i = 0; i < regions_to_draw.size(); ++i) { | |
387 if (!regions_to_draw[i].IsEmpty()) | |
388 texture_->Draw(texture_draw_params, regions_to_draw[i]); | |
389 } | |
390 #endif | |
391 #endif | |
392 } | |
393 | |
394 void Layer::DrawTree() { | |
395 #if defined(USE_WEBKIT_COMPOSITOR) | |
396 NOTREACHED(); | |
397 #else | |
398 if (!visible_) | |
399 return; | |
400 | |
401 Draw(); | |
402 for (size_t i = 0; i < children_.size(); ++i) | |
403 children_.at(i)->DrawTree(); | |
404 #endif | |
405 } | |
406 | |
407 void Layer::paintContents(WebKit::WebCanvas* web_canvas, | 285 void Layer::paintContents(WebKit::WebCanvas* web_canvas, |
408 const WebKit::WebRect& clip) { | 286 const WebKit::WebRect& clip) { |
409 TRACE_EVENT0("ui", "Layer::paintContents"); | 287 TRACE_EVENT0("ui", "Layer::paintContents"); |
410 #if defined(USE_WEBKIT_COMPOSITOR) | |
411 gfx::CanvasSkia canvas(web_canvas); | 288 gfx::CanvasSkia canvas(web_canvas); |
412 if (delegate_) | 289 if (delegate_) |
413 delegate_->OnPaintLayer(&canvas); | 290 delegate_->OnPaintLayer(&canvas); |
414 #else | |
415 NOTREACHED(); | |
416 #endif | |
417 } | 291 } |
418 | 292 |
419 float Layer::GetCombinedOpacity() const { | 293 float Layer::GetCombinedOpacity() const { |
420 float opacity = opacity_; | 294 float opacity = opacity_; |
421 Layer* current = this->parent_; | 295 Layer* current = this->parent_; |
422 while (current) { | 296 while (current) { |
423 opacity *= current->opacity_; | 297 opacity *= current->opacity_; |
424 current = current->parent_; | 298 current = current->parent_; |
425 } | 299 } |
426 return opacity; | 300 return opacity; |
427 } | 301 } |
428 | 302 |
429 void Layer::UpdateLayerCanvas() { | |
430 TRACE_EVENT0("ui", "Layer::UpdateLayerCanvas"); | |
431 #if defined(USE_WEBKIT_COMPOSITOR) | |
432 NOTREACHED(); | |
433 #else | |
434 // If we have no delegate, that means that whoever constructed the Layer is | |
435 // setting its canvas directly with SetCanvas(). | |
436 if (!delegate_ || layer_updated_externally_) | |
437 return; | |
438 gfx::Rect local_bounds = gfx::Rect(gfx::Point(), bounds_.size()); | |
439 gfx::Rect draw_rect = texture_.get() ? invalid_rect_.Intersect(local_bounds) : | |
440 local_bounds; | |
441 if (draw_rect.IsEmpty()) { | |
442 invalid_rect_ = gfx::Rect(); | |
443 return; | |
444 } | |
445 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvas(draw_rect.size(), | |
446 false)); | |
447 canvas->Translate(gfx::Point().Subtract(draw_rect.origin())); | |
448 if (delegate_) | |
449 delegate_->OnPaintLayer(canvas.get()); | |
450 SetCanvas(*canvas->GetSkCanvas(), draw_rect.origin()); | |
451 #endif | |
452 } | |
453 | |
454 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) { | 303 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) { |
455 DCHECK_NE(child, other); | 304 DCHECK_NE(child, other); |
456 DCHECK_EQ(this, child->parent()); | 305 DCHECK_EQ(this, child->parent()); |
457 DCHECK_EQ(this, other->parent()); | 306 DCHECK_EQ(this, other->parent()); |
458 | 307 |
459 const size_t child_i = | 308 const size_t child_i = |
460 std::find(children_.begin(), children_.end(), child) - children_.begin(); | 309 std::find(children_.begin(), children_.end(), child) - children_.begin(); |
461 const size_t other_i = | 310 const size_t other_i = |
462 std::find(children_.begin(), children_.end(), other) - children_.begin(); | 311 std::find(children_.begin(), children_.end(), other) - children_.begin(); |
463 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i)) | 312 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i)) |
464 return; | 313 return; |
465 | 314 |
466 const size_t dest_i = | 315 const size_t dest_i = |
467 above ? | 316 above ? |
468 (child_i < other_i ? other_i : other_i + 1) : | 317 (child_i < other_i ? other_i : other_i + 1) : |
469 (child_i < other_i ? other_i - 1 : other_i); | 318 (child_i < other_i ? other_i - 1 : other_i); |
470 children_.erase(children_.begin() + child_i); | 319 children_.erase(children_.begin() + child_i); |
471 children_.insert(children_.begin() + dest_i, child); | 320 children_.insert(children_.begin() + dest_i, child); |
472 | 321 |
473 SetNeedsToRecomputeHole(); | |
474 | |
475 #if defined(USE_WEBKIT_COMPOSITOR) | |
476 child->web_layer_.removeFromParent(); | 322 child->web_layer_.removeFromParent(); |
477 web_layer_.insertChild(child->web_layer_, dest_i); | 323 web_layer_.insertChild(child->web_layer_, dest_i); |
478 #endif | |
479 } | |
480 | |
481 void Layer::SetNeedsToRecomputeHole() { | |
482 Layer* root_layer = this; | |
483 while (root_layer->parent_) | |
484 root_layer = root_layer->parent_; | |
485 | |
486 root_layer->recompute_hole_ = true; | |
487 } | |
488 | |
489 void Layer::ClearHoleRects() { | |
490 hole_rect_ = gfx::Rect(); | |
491 | |
492 for (size_t i = 0; i < children_.size(); i++) | |
493 children_[i]->ClearHoleRects(); | |
494 } | 324 } |
495 | 325 |
496 void Layer::GetLayerProperties(const ui::Transform& parent_transform, | 326 void Layer::GetLayerProperties(const ui::Transform& parent_transform, |
497 std::vector<LayerProperties>* traversal) { | 327 std::vector<LayerProperties>* traversal) { |
498 if (!visible_ || opacity_ != 1.0f) | 328 if (!visible_ || opacity_ != 1.0f) |
499 return; | 329 return; |
500 | 330 |
501 ui::Transform current_transform; | 331 ui::Transform current_transform; |
502 if (transform().HasChange()) | 332 if (transform().HasChange()) |
503 current_transform.ConcatTransform(transform()); | 333 current_transform.ConcatTransform(transform()); |
504 current_transform.ConcatTranslate( | 334 current_transform.ConcatTranslate( |
505 static_cast<float>(bounds().x()), | 335 static_cast<float>(bounds().x()), |
506 static_cast<float>(bounds().y())); | 336 static_cast<float>(bounds().y())); |
507 current_transform.ConcatTransform(parent_transform); | 337 current_transform.ConcatTransform(parent_transform); |
508 | 338 |
509 if (fills_bounds_opaquely_ && type_ == LAYER_HAS_TEXTURE) { | 339 if (fills_bounds_opaquely_ && type_ == LAYER_HAS_TEXTURE) { |
510 LayerProperties properties; | 340 LayerProperties properties; |
511 properties.layer = this; | 341 properties.layer = this; |
512 properties.transform_relative_to_root = current_transform; | 342 properties.transform_relative_to_root = current_transform; |
513 traversal->push_back(properties); | 343 traversal->push_back(properties); |
514 } | 344 } |
515 | 345 |
516 for (size_t i = 0; i < children_.size(); i++) | 346 for (size_t i = 0; i < children_.size(); i++) |
517 children_[i]->GetLayerProperties(current_transform, traversal); | 347 children_[i]->GetLayerProperties(current_transform, traversal); |
518 } | 348 } |
519 | 349 |
520 void Layer::RecomputeHole() { | |
521 std::vector<LayerProperties> traversal; | |
522 ui::Transform transform; | |
523 | |
524 ClearHoleRects(); | |
525 GetLayerProperties(transform, &traversal); | |
526 | |
527 for (size_t i = 0; i < traversal.size(); i++) { | |
528 Layer* layer = traversal[i].layer; | |
529 gfx::Rect bounds = gfx::Rect(layer->bounds().size()); | |
530 | |
531 // Iterate through layers which are after traversal[i] in draw order | |
532 // and find the largest candidate hole. | |
533 for (size_t j = i + 1; j < traversal.size(); j++) { | |
534 gfx::Rect candidate_hole = gfx::Rect(traversal[j].layer->bounds().size()); | |
535 | |
536 // Compute transform to go from bounds of layer |j| to local bounds of | |
537 // layer |i|. | |
538 ui::Transform candidate_hole_transform; | |
539 ui::Transform inverted; | |
540 | |
541 candidate_hole_transform.ConcatTransform( | |
542 traversal[j].transform_relative_to_root); | |
543 | |
544 if (!traversal[i].transform_relative_to_root.GetInverse(&inverted)) | |
545 continue; | |
546 | |
547 candidate_hole_transform.ConcatTransform(inverted); | |
548 | |
549 // cannot punch a hole if the relative transform between the two layers | |
550 // is not multiple of 90. | |
551 float degrees; | |
552 gfx::Point p; | |
553 if (!InterpolatedTransform::FactorTRS(candidate_hole_transform, &p, | |
554 °rees, NULL) || !IsApproximateMultilpleOf(degrees, 90.0f)) | |
555 continue; | |
556 | |
557 candidate_hole_transform.TransformRect(&candidate_hole); | |
558 candidate_hole = candidate_hole.Intersect(bounds); | |
559 | |
560 if (candidate_hole.size().GetArea() > | |
561 layer->hole_rect().size().GetArea()) { | |
562 layer->set_hole_rect(candidate_hole); | |
563 } | |
564 } | |
565 // Free up texture memory if the hole fills bounds of layer. | |
566 if (!layer->ShouldDraw() && !layer_updated_externally()) | |
567 layer->DropTexture(); | |
568 | |
569 #if defined(USE_WEBKIT_COMPOSITOR) | |
570 RecomputeDrawsContentAndUVRect(); | |
571 #endif | |
572 } | |
573 | |
574 recompute_hole_ = false; | |
575 } | |
576 | |
577 // static | |
578 void Layer::PunchHole(const gfx::Rect& rect, | |
579 const gfx::Rect& region_to_punch_out, | |
580 std::vector<gfx::Rect>* sides) { | |
581 gfx::Rect trimmed_rect = rect.Intersect(region_to_punch_out); | |
582 | |
583 if (trimmed_rect.IsEmpty()) { | |
584 sides->push_back(rect); | |
585 return; | |
586 } | |
587 | |
588 // Top (above the hole). | |
589 sides->push_back(gfx::Rect(rect.x(), | |
590 rect.y(), | |
591 rect.width(), | |
592 trimmed_rect.y() - rect.y())); | |
593 | |
594 // Left (of the hole). | |
595 sides->push_back(gfx::Rect(rect.x(), | |
596 trimmed_rect.y(), | |
597 trimmed_rect.x() - rect.x(), | |
598 trimmed_rect.height())); | |
599 | |
600 // Right (of the hole). | |
601 sides->push_back(gfx::Rect(trimmed_rect.right(), | |
602 trimmed_rect.y(), | |
603 rect.right() - trimmed_rect.right(), | |
604 trimmed_rect.height())); | |
605 | |
606 // Bottom (below the hole). | |
607 sides->push_back(gfx::Rect(rect.x(), | |
608 trimmed_rect.bottom(), | |
609 rect.width(), | |
610 rect.bottom() - trimmed_rect.bottom())); | |
611 } | |
612 | |
613 void Layer::DropTexture() { | |
614 if (!layer_updated_externally_) | |
615 texture_ = NULL; | |
616 } | |
617 | |
618 void Layer::DropTextures() { | |
619 DropTexture(); | |
620 for (size_t i = 0; i < children_.size(); ++i) | |
621 children_[i]->DropTextures(); | |
622 } | |
623 | |
624 bool Layer::ConvertPointForAncestor(const Layer* ancestor, | 350 bool Layer::ConvertPointForAncestor(const Layer* ancestor, |
625 gfx::Point* point) const { | 351 gfx::Point* point) const { |
626 ui::Transform transform; | 352 ui::Transform transform; |
627 bool result = GetTransformRelativeTo(ancestor, &transform); | 353 bool result = GetTransformRelativeTo(ancestor, &transform); |
628 gfx::Point3f p(*point); | 354 gfx::Point3f p(*point); |
629 transform.TransformPoint(p); | 355 transform.TransformPoint(p); |
630 *point = p.AsPoint(); | 356 *point = p.AsPoint(); |
631 return result; | 357 return result; |
632 } | 358 } |
633 | 359 |
(...skipping 25 matching lines...) Expand all Loading... |
659 | 385 |
660 bool was_move = bounds_.size() == bounds.size(); | 386 bool was_move = bounds_.size() == bounds.size(); |
661 bounds_ = bounds; | 387 bounds_ = bounds; |
662 if (IsDrawn()) { | 388 if (IsDrawn()) { |
663 if (was_move) | 389 if (was_move) |
664 ScheduleDraw(); | 390 ScheduleDraw(); |
665 else | 391 else |
666 SchedulePaint(gfx::Rect(bounds.size())); | 392 SchedulePaint(gfx::Rect(bounds.size())); |
667 } | 393 } |
668 | 394 |
669 SetNeedsToRecomputeHole(); | |
670 #if defined(USE_WEBKIT_COMPOSITOR) | |
671 RecomputeTransform(); | 395 RecomputeTransform(); |
672 RecomputeDrawsContentAndUVRect(); | 396 RecomputeDrawsContentAndUVRect(); |
673 #endif | |
674 } | 397 } |
675 | 398 |
676 void Layer::SetTransformImmediately(const ui::Transform& transform) { | 399 void Layer::SetTransformImmediately(const ui::Transform& transform) { |
677 transform_ = transform; | 400 transform_ = transform; |
678 | 401 |
679 SetNeedsToRecomputeHole(); | |
680 #if defined(USE_WEBKIT_COMPOSITOR) | |
681 RecomputeTransform(); | 402 RecomputeTransform(); |
682 #endif | |
683 } | 403 } |
684 | 404 |
685 void Layer::SetOpacityImmediately(float opacity) { | 405 void Layer::SetOpacityImmediately(float opacity) { |
686 bool schedule_draw = (opacity != opacity_ && IsDrawn()); | 406 bool schedule_draw = (opacity != opacity_ && IsDrawn()); |
687 bool was_opaque = GetCombinedOpacity() == 1.0f; | |
688 opacity_ = opacity; | 407 opacity_ = opacity; |
689 bool is_opaque = GetCombinedOpacity() == 1.0f; | |
690 | 408 |
691 // If our opacity has changed we need to recompute our hole, our parent's hole | |
692 // and the holes of all our descendants. | |
693 if (was_opaque != is_opaque) | |
694 SetNeedsToRecomputeHole(); | |
695 #if defined(USE_WEBKIT_COMPOSITOR) | |
696 if (visible_) | 409 if (visible_) |
697 web_layer_.setOpacity(opacity); | 410 web_layer_.setOpacity(opacity); |
698 RecomputeDebugBorderColor(); | 411 RecomputeDebugBorderColor(); |
699 #endif | |
700 if (schedule_draw) | 412 if (schedule_draw) |
701 ScheduleDraw(); | 413 ScheduleDraw(); |
702 } | 414 } |
703 | 415 |
704 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) { | 416 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) { |
705 SetBoundsImmediately(bounds); | 417 SetBoundsImmediately(bounds); |
706 } | 418 } |
707 | 419 |
708 void Layer::SetTransformFromAnimation(const Transform& transform) { | 420 void Layer::SetTransformFromAnimation(const Transform& transform) { |
709 SetTransformImmediately(transform); | 421 SetTransformImmediately(transform); |
(...skipping 12 matching lines...) Expand all Loading... |
722 } | 434 } |
723 | 435 |
724 const Transform& Layer::GetTransformForAnimation() const { | 436 const Transform& Layer::GetTransformForAnimation() const { |
725 return transform(); | 437 return transform(); |
726 } | 438 } |
727 | 439 |
728 float Layer::GetOpacityForAnimation() const { | 440 float Layer::GetOpacityForAnimation() const { |
729 return opacity(); | 441 return opacity(); |
730 } | 442 } |
731 | 443 |
732 #if defined(USE_WEBKIT_COMPOSITOR) | |
733 void Layer::CreateWebLayer() { | 444 void Layer::CreateWebLayer() { |
734 web_layer_ = WebKit::WebContentLayer::create(this); | 445 web_layer_ = WebKit::WebContentLayer::create(this); |
735 web_layer_.setAnchorPoint(WebKit::WebFloatPoint(0.f, 0.f)); | 446 web_layer_.setAnchorPoint(WebKit::WebFloatPoint(0.f, 0.f)); |
736 web_layer_.setOpaque(true); | 447 web_layer_.setOpaque(true); |
737 web_layer_is_accelerated_ = false; | 448 web_layer_is_accelerated_ = false; |
738 show_debug_borders_ = CommandLine::ForCurrentProcess()->HasSwitch( | 449 show_debug_borders_ = CommandLine::ForCurrentProcess()->HasSwitch( |
739 switches::kUIShowLayerBorders); | 450 switches::kUIShowLayerBorders); |
740 web_layer_.setDebugBorderWidth(show_debug_borders_ ? 2 : 0); | 451 web_layer_.setDebugBorderWidth(show_debug_borders_ ? 2 : 0); |
741 RecomputeDrawsContentAndUVRect(); | 452 RecomputeDrawsContentAndUVRect(); |
742 RecomputeDebugBorderColor(); | 453 RecomputeDebugBorderColor(); |
743 } | 454 } |
744 | 455 |
745 void Layer::RecomputeTransform() { | 456 void Layer::RecomputeTransform() { |
746 ui::Transform transform = transform_; | 457 ui::Transform transform = transform_; |
747 transform.ConcatTranslate(bounds_.x(), bounds_.y()); | 458 transform.ConcatTranslate(bounds_.x(), bounds_.y()); |
748 web_layer_.setTransform(transform.matrix()); | 459 web_layer_.setTransform(transform.matrix()); |
749 } | 460 } |
750 | 461 |
751 void Layer::RecomputeDrawsContentAndUVRect() { | 462 void Layer::RecomputeDrawsContentAndUVRect() { |
752 DCHECK(!web_layer_.isNull()); | 463 DCHECK(!web_layer_.isNull()); |
753 bool should_draw = type_ == LAYER_HAS_TEXTURE && | 464 bool should_draw = type_ == LAYER_HAS_TEXTURE; |
754 !hole_rect_.Contains(gfx::Rect(gfx::Point(0, 0), bounds_.size())); | |
755 if (!web_layer_is_accelerated_) { | 465 if (!web_layer_is_accelerated_) { |
756 web_layer_.to<WebKit::WebContentLayer>().setDrawsContent(should_draw); | 466 web_layer_.to<WebKit::WebContentLayer>().setDrawsContent(should_draw); |
757 web_layer_.setBounds(bounds_.size()); | 467 web_layer_.setBounds(bounds_.size()); |
758 } else { | 468 } else { |
759 DCHECK(texture_); | 469 DCHECK(texture_); |
760 TextureCC* texture_cc = static_cast<TextureCC*>(texture_.get()); | 470 TextureCC* texture_cc = static_cast<TextureCC*>(texture_.get()); |
761 unsigned int texture_id = texture_cc->texture_id(); | 471 unsigned int texture_id = texture_cc->texture_id(); |
762 WebKit::WebExternalTextureLayer texture_layer = | 472 WebKit::WebExternalTextureLayer texture_layer = |
763 web_layer_.to<WebKit::WebExternalTextureLayer>(); | 473 web_layer_.to<WebKit::WebExternalTextureLayer>(); |
764 texture_layer.setTextureId(should_draw ? texture_id : 0); | 474 texture_layer.setTextureId(should_draw ? texture_id : 0); |
(...skipping 12 matching lines...) Expand all Loading... |
777 void Layer::RecomputeDebugBorderColor() { | 487 void Layer::RecomputeDebugBorderColor() { |
778 if (!show_debug_borders_) | 488 if (!show_debug_borders_) |
779 return; | 489 return; |
780 unsigned int color = 0xFF000000; | 490 unsigned int color = 0xFF000000; |
781 color |= web_layer_is_accelerated_ ? 0x0000FF00 : 0x00FF0000; | 491 color |= web_layer_is_accelerated_ ? 0x0000FF00 : 0x00FF0000; |
782 bool opaque = fills_bounds_opaquely_ && (GetCombinedOpacity() == 1.f); | 492 bool opaque = fills_bounds_opaquely_ && (GetCombinedOpacity() == 1.f); |
783 if (!opaque) | 493 if (!opaque) |
784 color |= 0xFF; | 494 color |= 0xFF; |
785 web_layer_.setDebugBorderColor(color); | 495 web_layer_.setDebugBorderColor(color); |
786 } | 496 } |
787 #endif | |
788 | 497 |
789 } // namespace ui | 498 } // namespace ui |
OLD | NEW |