Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: ui/gfx/compositor/layer.cc

Issue 8368013: Improve Aura overdraw by changing hole calculation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changes as requested Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 18 matching lines...) Expand all
29 } // namespace 29 } // namespace
30 30
31 namespace ui { 31 namespace ui {
32 32
33 Layer::Layer(Compositor* compositor) 33 Layer::Layer(Compositor* compositor)
34 : type_(LAYER_HAS_TEXTURE), 34 : type_(LAYER_HAS_TEXTURE),
35 compositor_(compositor), 35 compositor_(compositor),
36 parent_(NULL), 36 parent_(NULL),
37 visible_(true), 37 visible_(true),
38 fills_bounds_opaquely_(true), 38 fills_bounds_opaquely_(true),
39 recompute_hole_(false),
39 layer_updated_externally_(false), 40 layer_updated_externally_(false),
40 opacity_(1.0f), 41 opacity_(1.0f),
41 delegate_(NULL) { 42 delegate_(NULL) {
42 #if defined(USE_WEBKIT_COMPOSITOR) 43 #if defined(USE_WEBKIT_COMPOSITOR)
43 CreateWebLayer(); 44 CreateWebLayer();
44 #endif 45 #endif
45 } 46 }
46 47
47 Layer::Layer(Compositor* compositor, LayerType type) 48 Layer::Layer(Compositor* compositor, LayerType type)
48 : type_(type), 49 : type_(type),
49 compositor_(compositor), 50 compositor_(compositor),
50 parent_(NULL), 51 parent_(NULL),
51 visible_(true), 52 visible_(true),
52 fills_bounds_opaquely_(true), 53 fills_bounds_opaquely_(true),
54 recompute_hole_(false),
53 layer_updated_externally_(false), 55 layer_updated_externally_(false),
54 opacity_(1.0f), 56 opacity_(1.0f),
55 delegate_(NULL) { 57 delegate_(NULL) {
56 #if defined(USE_WEBKIT_COMPOSITOR) 58 #if defined(USE_WEBKIT_COMPOSITOR)
57 CreateWebLayer(); 59 CreateWebLayer();
58 #endif 60 #endif
59 } 61 }
60 62
61 Layer::~Layer() { 63 Layer::~Layer() {
62 if (parent_) 64 if (parent_)
(...skipping 20 matching lines...) Expand all
83 85
84 void Layer::Add(Layer* child) { 86 void Layer::Add(Layer* child) {
85 if (child->parent_) 87 if (child->parent_)
86 child->parent_->Remove(child); 88 child->parent_->Remove(child);
87 child->parent_ = this; 89 child->parent_ = this;
88 children_.push_back(child); 90 children_.push_back(child);
89 #if defined(USE_WEBKIT_COMPOSITOR) 91 #if defined(USE_WEBKIT_COMPOSITOR)
90 web_layer_.addChild(child->web_layer_); 92 web_layer_.addChild(child->web_layer_);
91 #endif 93 #endif
92 94
93 RecomputeHole(); 95 SetNeedsToRecomputeHole();
94 } 96 }
95 97
96 void Layer::Remove(Layer* child) { 98 void Layer::Remove(Layer* child) {
97 std::vector<Layer*>::iterator i = 99 std::vector<Layer*>::iterator i =
98 std::find(children_.begin(), children_.end(), child); 100 std::find(children_.begin(), children_.end(), child);
99 DCHECK(i != children_.end()); 101 DCHECK(i != children_.end());
100 children_.erase(i); 102 children_.erase(i);
101 child->parent_ = NULL; 103 child->parent_ = NULL;
102 #if defined(USE_WEBKIT_COMPOSITOR) 104 #if defined(USE_WEBKIT_COMPOSITOR)
103 child->web_layer_.removeFromParent(); 105 child->web_layer_.removeFromParent();
104 #endif 106 #endif
105 107
106 RecomputeHole(); 108 SetNeedsToRecomputeHole();
107 109
108 child->DropTextures(); 110 child->DropTextures();
109 } 111 }
110 112
111 void Layer::MoveToFront(Layer* child) { 113 void Layer::MoveToFront(Layer* child) {
112 std::vector<Layer*>::iterator i = 114 std::vector<Layer*>::iterator i =
113 std::find(children_.begin(), children_.end(), child); 115 std::find(children_.begin(), children_.end(), child);
114 DCHECK(i != children_.end()); 116 DCHECK(i != children_.end());
115 children_.erase(i); 117 children_.erase(i);
116 children_.push_back(child); 118 children_.push_back(child);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 return; 180 return;
179 181
180 bool was_drawn = IsDrawn(); 182 bool was_drawn = IsDrawn();
181 visible_ = visible; 183 visible_ = visible;
182 bool is_drawn = IsDrawn(); 184 bool is_drawn = IsDrawn();
183 if (was_drawn == is_drawn) 185 if (was_drawn == is_drawn)
184 return; 186 return;
185 187
186 if (!is_drawn) 188 if (!is_drawn)
187 DropTextures(); 189 DropTextures();
188 if (parent_) 190 SetNeedsToRecomputeHole();
189 parent_->RecomputeHole();
190 #if defined(USE_WEBKIT_COMPOSITOR) 191 #if defined(USE_WEBKIT_COMPOSITOR)
191 // TODO(piman): Expose a visibility flag on WebLayer. 192 // TODO(piman): Expose a visibility flag on WebLayer.
192 web_layer_.setOpacity(visible_ ? opacity_ : 0.f); 193 web_layer_.setOpacity(visible_ ? opacity_ : 0.f);
193 #endif 194 #endif
194 } 195 }
195 196
196 bool Layer::IsDrawn() const { 197 bool Layer::IsDrawn() const {
197 const Layer* layer = this; 198 const Layer* layer = this;
198 while (layer && layer->visible_) 199 while (layer && layer->visible_)
199 layer = layer->parent_; 200 layer = layer->parent_;
(...skipping 23 matching lines...) Expand all
223 NOTREACHED(); // |source| and |target| are in unrelated hierarchies. 224 NOTREACHED(); // |source| and |target| are in unrelated hierarchies.
224 } 225 }
225 } 226 }
226 227
227 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) { 228 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
228 if (fills_bounds_opaquely_ == fills_bounds_opaquely) 229 if (fills_bounds_opaquely_ == fills_bounds_opaquely)
229 return; 230 return;
230 231
231 fills_bounds_opaquely_ = fills_bounds_opaquely; 232 fills_bounds_opaquely_ = fills_bounds_opaquely;
232 233
233 if (parent()) 234 SetNeedsToRecomputeHole();
234 parent()->RecomputeHole();
235 #if defined(USE_WEBKIT_COMPOSITOR) 235 #if defined(USE_WEBKIT_COMPOSITOR)
236 web_layer_.setOpaque(fills_bounds_opaquely); 236 web_layer_.setOpaque(fills_bounds_opaquely);
237 #endif 237 #endif
238 } 238 }
239 239
240 void Layer::SetExternalTexture(ui::Texture* texture) { 240 void Layer::SetExternalTexture(ui::Texture* texture) {
241 DCHECK(texture); 241 DCHECK(texture);
242 layer_updated_externally_ = true; 242 layer_updated_externally_ = true;
243 texture_ = texture; 243 texture_ = texture;
244 } 244 }
(...skipping 29 matching lines...) Expand all
274 Compositor* compositor = GetCompositor(); 274 Compositor* compositor = GetCompositor();
275 if (compositor) 275 if (compositor)
276 compositor->ScheduleDraw(); 276 compositor->ScheduleDraw();
277 } 277 }
278 278
279 void Layer::Draw() { 279 void Layer::Draw() {
280 #if defined(USE_WEBKIT_COMPOSITOR) 280 #if defined(USE_WEBKIT_COMPOSITOR)
281 NOTREACHED(); 281 NOTREACHED();
282 #else 282 #else
283 DCHECK(GetCompositor()); 283 DCHECK(GetCompositor());
284
285 if (recompute_hole_ && !parent_)
286 RecomputeHole();
287
284 if (!ShouldDraw()) 288 if (!ShouldDraw())
285 return; 289 return;
286 290
287 UpdateLayerCanvas(); 291 UpdateLayerCanvas();
288 292
289 // Layer drew nothing, no texture was created. 293 // Layer drew nothing, no texture was created.
290 if (!texture_.get()) 294 if (!texture_.get())
291 return; 295 return;
292 296
293 ui::TextureDrawParams texture_draw_params; 297 ui::TextureDrawParams texture_draw_params;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 return; 383 return;
380 } 384 }
381 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvas( 385 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvas(
382 draw_rect.width(), draw_rect.height(), false)); 386 draw_rect.width(), draw_rect.height(), false));
383 canvas->TranslateInt(-draw_rect.x(), -draw_rect.y()); 387 canvas->TranslateInt(-draw_rect.x(), -draw_rect.y());
384 delegate_->OnPaintLayer(canvas.get()); 388 delegate_->OnPaintLayer(canvas.get());
385 SetCanvas(*canvas->GetSkCanvas(), draw_rect.origin()); 389 SetCanvas(*canvas->GetSkCanvas(), draw_rect.origin());
386 #endif 390 #endif
387 } 391 }
388 392
389 void Layer::RecomputeHole() { 393 void Layer::SetNeedsToRecomputeHole() {
390 if (type_ == LAYER_HAS_NO_TEXTURE) 394 Layer* root_layer = this;
395 while (root_layer->parent_)
396 root_layer = root_layer->parent_;
397
398 root_layer->recompute_hole_ = true;
399 }
400
401 void Layer::ClearHoleRects() {
402 hole_rect_ = gfx::Rect();
403
404 for (size_t i = 0; i < children_.size(); i++)
405 children_[i]->ClearHoleRects();
406 }
407
408 void Layer::GetLayerProperties(std::vector<LayerProperties>* traversal,
409 const ui::Transform& parent_transform) {
410 if (!visible_ || opacity_ != 1.0f)
391 return; 411 return;
392 412
393 // Reset to default. 413 ui::Transform current_transform;
394 hole_rect_ = gfx::Rect(); 414 current_transform.ConcatTransform(parent_transform);
415 if (transform().HasChange())
416 current_transform.ConcatTransform(transform());
417 current_transform.ConcatTranslate(
418 static_cast<float>(bounds().x()),
419 static_cast<float>(bounds().y()));
395 420
396 // Find the largest hole 421 if (fills_bounds_opaquely_ && type_ == LAYER_HAS_TEXTURE) {
397 for (size_t i = 0; i < children_.size(); ++i) { 422 LayerProperties properties;
398 // Ignore non-opaque and hidden children. 423 properties.layer = this;
399 if (!children_[i]->IsCompletelyOpaque() || !children_[i]->visible_) 424 properties.transform_relative_to_root = current_transform;
400 continue; 425 traversal->push_back(properties);
401
402 // Ignore children that aren't rotated by multiples of 90 degrees.
403 float degrees;
404 if (!InterpolatedTransform::FactorTRS(children_[i]->transform(),
405 NULL, &degrees, NULL) ||
406 !IsApproximateMultilpleOf(degrees, 90.0f))
407 continue;
408
409 // The reason why we don't just take the bounds and apply the transform is
410 // that the bounds encodes a position, too, so the effective transformation
411 // matrix is actually different that the one reported. As well, the bounds
412 // will not necessarily be at the origin.
413 gfx::Rect candidate_hole(children_[i]->bounds_.size());
414 ui::Transform transform = children_[i]->transform();
415 transform.ConcatTranslate(static_cast<float>(children_[i]->bounds_.x()),
416 static_cast<float>(children_[i]->bounds_.y()));
417 transform.TransformRect(&candidate_hole);
418
419 // This layer might not contain the child (e.g., a portion of the child may
420 // be offscreen). Only the portion of the child that overlaps this layer is
421 // of any importance, so take the intersection.
422 candidate_hole = gfx::Rect(bounds().size()).Intersect(candidate_hole);
423
424 // Ensure we have the largest hole.
425 if (candidate_hole.size().GetArea() > hole_rect_.size().GetArea())
426 hole_rect_ = candidate_hole;
427 } 426 }
428 427
429 // Free up texture memory if the hole fills bounds of layer. 428 for (size_t i = 0; i < children_.size(); i++)
430 if (!ShouldDraw() && !layer_updated_externally_) 429 children_[i]->GetLayerProperties(traversal, current_transform);
431 texture_ = NULL; 430 }
431
432 void Layer::RecomputeHole() {
433 std::vector<LayerProperties> traversal;
434 ui::Transform transform;
435
436 ClearHoleRects();
437 GetLayerProperties(&traversal, transform);
438
439 for (size_t i = 0; i < traversal.size(); i++) {
440 Layer* layer = traversal[i].layer;
441 gfx::Rect bounds = gfx::Rect(layer->bounds().size());
442
443 // Iterate through layers which are after traversal[i] in draw order
444 // and find the largest candidate hole.
445 for (size_t j = i + 1; j < traversal.size(); j++) {
446 gfx::Rect candidate_hole = gfx::Rect(traversal[j].layer->bounds().size());
447
448 // Compute transform to go from bounds of layer |j| to local bounds of
449 // layer |i|.
450 ui::Transform candidate_hole_transform;
451 ui::Transform inverted;
452
453 candidate_hole_transform.ConcatTransform(
454 traversal[j].transform_relative_to_root);
455
456 if (!traversal[i].transform_relative_to_root.GetInverse(&inverted))
457 continue;
458
459 candidate_hole_transform.ConcatTransform(inverted);
460
461 // cannot punch a hole if the relative transform between the two layers
462 // is not multiple of 90.
463 float degrees;
464 gfx::Point p;
465 if (!InterpolatedTransform::FactorTRS(candidate_hole_transform, &p,
466 &degrees, NULL) || !IsApproximateMultilpleOf(degrees, 90.0f))
467 continue;
468
469 candidate_hole_transform.TransformRect(&candidate_hole);
470 candidate_hole = candidate_hole.Intersect(bounds);
471
472 if (candidate_hole.size().GetArea() > layer->hole_rect().size().GetArea())
473 layer->set_hole_rect(candidate_hole);
474 }
475 // Free up texture memory if the hole fills bounds of layer.
476 if (!layer->ShouldDraw() && !layer_updated_externally())
477 layer->DropTexture();
432 478
433 #if defined(USE_WEBKIT_COMPOSITOR) 479 #if defined(USE_WEBKIT_COMPOSITOR)
434 RecomputeDrawsContent(); 480 layer->RecomputeDrawsContent();
435 #endif 481 #endif
436 } 482 }
437 483
438 bool Layer::IsCompletelyOpaque() const { 484 recompute_hole_ = false;
439 return fills_bounds_opaquely() && GetCombinedOpacity() == 1.0f;
440 } 485 }
441 486
442 // static 487 // static
443 void Layer::PunchHole(const gfx::Rect& rect, 488 void Layer::PunchHole(const gfx::Rect& rect,
444 const gfx::Rect& region_to_punch_out, 489 const gfx::Rect& region_to_punch_out,
445 std::vector<gfx::Rect>* sides) { 490 std::vector<gfx::Rect>* sides) {
446 gfx::Rect trimmed_rect = rect.Intersect(region_to_punch_out); 491 gfx::Rect trimmed_rect = rect.Intersect(region_to_punch_out);
447 492
448 if (trimmed_rect.IsEmpty()) { 493 if (trimmed_rect.IsEmpty()) {
449 sides->push_back(rect); 494 sides->push_back(rect);
(...skipping 18 matching lines...) Expand all
468 rect.right() - trimmed_rect.right(), 513 rect.right() - trimmed_rect.right(),
469 trimmed_rect.height())); 514 trimmed_rect.height()));
470 515
471 // Bottom (below the hole). 516 // Bottom (below the hole).
472 sides->push_back(gfx::Rect(rect.x(), 517 sides->push_back(gfx::Rect(rect.x(),
473 trimmed_rect.bottom(), 518 trimmed_rect.bottom(),
474 rect.width(), 519 rect.width(),
475 rect.bottom() - trimmed_rect.bottom())); 520 rect.bottom() - trimmed_rect.bottom()));
476 } 521 }
477 522
478 void Layer::DropTextures() { 523 void Layer::DropTexture() {
479 if (!layer_updated_externally_) 524 if (!layer_updated_externally_)
480 texture_ = NULL; 525 texture_ = NULL;
526 }
527
528 void Layer::DropTextures() {
529 DropTexture();
481 for (size_t i = 0; i < children_.size(); ++i) 530 for (size_t i = 0; i < children_.size(); ++i)
482 children_[i]->DropTextures(); 531 children_[i]->DropTextures();
483 } 532 }
484 533
485 bool Layer::ConvertPointForAncestor(const Layer* ancestor, 534 bool Layer::ConvertPointForAncestor(const Layer* ancestor,
486 gfx::Point* point) const { 535 gfx::Point* point) const {
487 ui::Transform transform; 536 ui::Transform transform;
488 bool result = GetTransformRelativeTo(ancestor, &transform); 537 bool result = GetTransformRelativeTo(ancestor, &transform);
489 gfx::Point3f p(*point); 538 gfx::Point3f p(*point);
490 transform.TransformPoint(p); 539 transform.TransformPoint(p);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 if (property != LayerAnimationManager::TRANSFORM && 582 if (property != LayerAnimationManager::TRANSFORM &&
534 animator_->IsAnimating(LayerAnimationManager::TRANSFORM)) { 583 animator_->IsAnimating(LayerAnimationManager::TRANSFORM)) {
535 SetTransformImmediately(animator_->GetTargetTransform()); 584 SetTransformImmediately(animator_->GetTargetTransform());
536 } 585 }
537 animator_.reset(); 586 animator_.reset();
538 } 587 }
539 588
540 void Layer::SetBoundsImmediately(const gfx::Rect& bounds) { 589 void Layer::SetBoundsImmediately(const gfx::Rect& bounds) {
541 bounds_ = bounds; 590 bounds_ = bounds;
542 591
543 if (parent()) 592 SetNeedsToRecomputeHole();
544 parent()->RecomputeHole();
545 #if defined(USE_WEBKIT_COMPOSITOR) 593 #if defined(USE_WEBKIT_COMPOSITOR)
546 web_layer_.setBounds(bounds.size()); 594 web_layer_.setBounds(bounds.size());
547 RecomputeTransform(); 595 RecomputeTransform();
548 RecomputeDrawsContent(); 596 RecomputeDrawsContent();
549 #endif 597 #endif
550 } 598 }
551 599
552 void Layer::SetTransformImmediately(const ui::Transform& transform) { 600 void Layer::SetTransformImmediately(const ui::Transform& transform) {
553 transform_ = transform; 601 transform_ = transform;
554 602
555 if (parent()) 603 SetNeedsToRecomputeHole();
556 parent()->RecomputeHole();
557 #if defined(USE_WEBKIT_COMPOSITOR) 604 #if defined(USE_WEBKIT_COMPOSITOR)
558 RecomputeTransform(); 605 RecomputeTransform();
559 #endif 606 #endif
560 } 607 }
561 608
562 void Layer::SetOpacityImmediately(float opacity) { 609 void Layer::SetOpacityImmediately(float opacity) {
563 bool was_opaque = GetCombinedOpacity() == 1.0f;
564 opacity_ = opacity; 610 opacity_ = opacity;
565 bool is_opaque = GetCombinedOpacity() == 1.0f; 611 SetNeedsToRecomputeHole();
566
567 // If our opacity has changed we need to recompute our hole, our parent's hole
568 // and the holes of all our descendants.
569 if (was_opaque != is_opaque) {
570 if (parent_)
571 parent_->RecomputeHole();
572 std::queue<Layer*> to_process;
573 to_process.push(this);
574 while (!to_process.empty()) {
575 Layer* current = to_process.front();
576 to_process.pop();
577 current->RecomputeHole();
578 for (size_t i = 0; i < current->children_.size(); ++i)
579 to_process.push(current->children_.at(i));
580 }
581 }
582 #if defined(USE_WEBKIT_COMPOSITOR) 612 #if defined(USE_WEBKIT_COMPOSITOR)
583 if (visible_) 613 if (visible_)
584 web_layer_.setOpacity(opacity); 614 web_layer_.setOpacity(opacity);
585 RecomputeDrawsContent(); 615 RecomputeDrawsContent();
586 #endif 616 #endif
587 } 617 }
588 618
589 void Layer::SetBoundsFromAnimator(const gfx::Rect& bounds) { 619 void Layer::SetBoundsFromAnimator(const gfx::Rect& bounds) {
590 SetBoundsImmediately(bounds); 620 SetBoundsImmediately(bounds);
591 } 621 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 result.append(", color=red"); 710 result.append(", color=red");
681 711
682 if (fills_bounds_opaquely()) 712 if (fills_bounds_opaquely())
683 result.append(", style=filled"); 713 result.append(", style=filled");
684 714
685 return result; 715 return result;
686 } 716 }
687 717
688 #endif 718 #endif
689 719
690 ////////////////////////////////////////////////////////////////////////////////
691
692 } // namespace ui 720 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698