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

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: Nicer diff 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
« no previous file with comments | « ui/gfx/compositor/layer.h ('k') | ui/gfx/compositor/layer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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::GeneratePreorderTraversal(
409 std::vector<ui::Layer*>* layer_traversal) {
410 if (!visible_)
391 return; 411 return;
392 412
393 // Reset to default. 413 if (fills_bounds_opaquely_ && type_ == LAYER_HAS_TEXTURE)
394 hole_rect_ = gfx::Rect(); 414 layer_traversal->push_back(this);
395 415
396 // Find the largest hole 416 for (size_t i = 0; i < children_.size(); i++)
397 for (size_t i = 0; i < children_.size(); ++i) { 417 children_[i]->GeneratePreorderTraversal(layer_traversal);
398 // Ignore non-opaque and hidden children. 418 }
399 if (!children_[i]->IsCompletelyOpaque() || !children_[i]->visible_)
400 continue;
401 419
402 // Ignore children that aren't rotated by multiples of 90 degrees. 420 void Layer::RecomputeHole() {
403 float degrees; 421 std::vector<ui::Layer*> layer_traversal;
404 if (!InterpolatedTransform::FactorTRS(children_[i]->transform(), 422 std::vector<ui::Transform> transforms_relative_to_root;
405 NULL, &degrees, NULL) || 423 std::vector<float> opacities;
406 !IsApproximateMultilpleOf(degrees, 90.0f))
407 continue;
408 424
409 // The reason why we don't just take the bounds and apply the transform is 425 ClearHoleRects();
410 // that the bounds encodes a position, too, so the effective transformation 426 GeneratePreorderTraversal(&layer_traversal);
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 427
419 // This layer might not contain the child (e.g., a portion of the child may 428 for (size_t i = 0; i < layer_traversal.size(); i++) {
sky 2011/10/24 23:25:50 Seems a lot better to have GeneratePreorderTravers
420 // be offscreen). Only the portion of the child that overlaps this layer is 429 Layer* layer = layer_traversal[i];
421 // of any importance, so take the intersection. 430 ui::Transform layer_transform;
422 candidate_hole = gfx::Rect(bounds().size()).Intersect(candidate_hole); 431 layer->GetTransformRelativeTo(this, &layer_transform);
423 432 transforms_relative_to_root.push_back(layer_transform);
424 // Ensure we have the largest hole. 433 opacities.push_back(layer->GetCombinedOpacity());
425 if (candidate_hole.size().GetArea() > hole_rect_.size().GetArea())
426 hole_rect_ = candidate_hole;
427 } 434 }
428 435
429 // Free up texture memory if the hole fills bounds of layer. 436 for (size_t i = 0; i < layer_traversal.size(); i++) {
430 if (!ShouldDraw() && !layer_updated_externally_) 437 Layer* layer = layer_traversal[i];
431 texture_ = NULL; 438 gfx::Rect bounds = gfx::Rect(layer->bounds().size());
439
440 // Iterate through layers which are after layer_traversal[i] in draw order
441 // and find the largest candidate hole.
442 for (size_t j = i + 1; j < layer_traversal.size(); j++) {
443 gfx::Rect candidate_hole = gfx::Rect(layer_traversal[j]->bounds().size());
444
445 // Compute transform to go from bounds of layer |j| to local bounds of
446 // layer |i|.
447 ui::Transform candidate_hole_transform;
448 ui::Transform inverted;
449
450 candidate_hole_transform.ConcatTransform(transforms_relative_to_root[j]);
451
452 if (!transforms_relative_to_root[i].GetInverse(&inverted))
453 continue;
454
455 candidate_hole_transform.ConcatTransform(inverted);
456
457 // cannot punch a hole if the relative transform between the two layers
458 // is not multiple of 90.
459 float degrees;
460 gfx::Point p;
461 if (!InterpolatedTransform::FactorTRS(candidate_hole_transform, &p,
462 &degrees, NULL) || !IsApproximateMultilpleOf(degrees, 90.0f))
463 continue;
464
465 // can only punch a hole if the two layers have 1.0f opacity.
466 if (opacities[i] != 1.0f || opacities[j] != 1.0f)
sky 2011/10/24 23:25:50 This check is cheap. We should do it first.
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 RecomputeDrawsContent();
sky 2011/10/24 23:25:50 Shouldn't this be outside the for loop?
435 #endif 481 #endif
436 }
437 482
438 bool Layer::IsCompletelyOpaque() const { 483 recompute_hole_ = false;
sky 2011/10/24 23:25:50 Shouldn't this be outside the for loop?
439 return fills_bounds_opaquely() && GetCombinedOpacity() == 1.0f; 484 }
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
523 void Layer::DropTexture() {
524 if (!layer_updated_externally_)
525 texture_ = NULL;
526 }
527
478 void Layer::DropTextures() { 528 void Layer::DropTextures() {
479 if (!layer_updated_externally_) 529 if (!layer_updated_externally_)
sky 2011/10/24 23:25:50 Change this to call DropTexture.
480 texture_ = NULL; 530 texture_ = NULL;
481 for (size_t i = 0; i < children_.size(); ++i) 531 for (size_t i = 0; i < children_.size(); ++i)
482 children_[i]->DropTextures(); 532 children_[i]->DropTextures();
483 } 533 }
484 534
485 bool Layer::ConvertPointForAncestor(const Layer* ancestor, 535 bool Layer::ConvertPointForAncestor(const Layer* ancestor,
486 gfx::Point* point) const { 536 gfx::Point* point) const {
487 ui::Transform transform; 537 ui::Transform transform;
488 bool result = GetTransformRelativeTo(ancestor, &transform); 538 bool result = GetTransformRelativeTo(ancestor, &transform);
489 gfx::Point3f p(*point); 539 gfx::Point3f p(*point);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 if (property != LayerAnimationManager::TRANSFORM && 583 if (property != LayerAnimationManager::TRANSFORM &&
534 animator_->IsAnimating(LayerAnimationManager::TRANSFORM)) { 584 animator_->IsAnimating(LayerAnimationManager::TRANSFORM)) {
535 SetTransformImmediately(animator_->GetTargetTransform()); 585 SetTransformImmediately(animator_->GetTargetTransform());
536 } 586 }
537 animator_.reset(); 587 animator_.reset();
538 } 588 }
539 589
540 void Layer::SetBoundsImmediately(const gfx::Rect& bounds) { 590 void Layer::SetBoundsImmediately(const gfx::Rect& bounds) {
541 bounds_ = bounds; 591 bounds_ = bounds;
542 592
543 if (parent()) 593 SetNeedsToRecomputeHole();
544 parent()->RecomputeHole();
545 #if defined(USE_WEBKIT_COMPOSITOR) 594 #if defined(USE_WEBKIT_COMPOSITOR)
546 web_layer_.setBounds(bounds.size()); 595 web_layer_.setBounds(bounds.size());
547 RecomputeTransform(); 596 RecomputeTransform();
548 RecomputeDrawsContent(); 597 RecomputeDrawsContent();
549 #endif 598 #endif
550 } 599 }
551 600
552 void Layer::SetTransformImmediately(const ui::Transform& transform) { 601 void Layer::SetTransformImmediately(const ui::Transform& transform) {
553 transform_ = transform; 602 transform_ = transform;
554 603
555 if (parent()) 604 SetNeedsToRecomputeHole();
556 parent()->RecomputeHole();
557 #if defined(USE_WEBKIT_COMPOSITOR) 605 #if defined(USE_WEBKIT_COMPOSITOR)
558 RecomputeTransform(); 606 RecomputeTransform();
559 #endif 607 #endif
560 } 608 }
561 609
562 void Layer::SetOpacityImmediately(float opacity) { 610 void Layer::SetOpacityImmediately(float opacity) {
563 bool was_opaque = GetCombinedOpacity() == 1.0f;
564 opacity_ = opacity; 611 opacity_ = opacity;
565 bool is_opaque = GetCombinedOpacity() == 1.0f; 612 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) 613 #if defined(USE_WEBKIT_COMPOSITOR)
583 if (visible_) 614 if (visible_)
584 web_layer_.setOpacity(opacity); 615 web_layer_.setOpacity(opacity);
585 RecomputeDrawsContent(); 616 RecomputeDrawsContent();
586 #endif 617 #endif
587 } 618 }
588 619
589 void Layer::SetBoundsFromAnimator(const gfx::Rect& bounds) { 620 void Layer::SetBoundsFromAnimator(const gfx::Rect& bounds) {
590 SetBoundsImmediately(bounds); 621 SetBoundsImmediately(bounds);
591 } 622 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 result.append(", color=red"); 711 result.append(", color=red");
681 712
682 if (fills_bounds_opaquely()) 713 if (fills_bounds_opaquely())
683 result.append(", style=filled"); 714 result.append(", style=filled");
684 715
685 return result; 716 return result;
686 } 717 }
687 718
688 #endif 719 #endif
689 720
690 ////////////////////////////////////////////////////////////////////////////////
691
692 } // namespace ui 721 } // namespace ui
OLDNEW
« no previous file with comments | « ui/gfx/compositor/layer.h ('k') | ui/gfx/compositor/layer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698