summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-02 21:25:00 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-02 21:25:00 +0000
commit02876f5fdafb3b6e500ba322715c3a848170763a (patch)
tree74d06087d2db6557625a414202a7e3e4367ea7a6 /ui
parent8f2bfca4401f094481cac8fab1fe80c853971d84 (diff)
downloadchromium_src-02876f5fdafb3b6e500ba322715c3a848170763a.zip
chromium_src-02876f5fdafb3b6e500ba322715c3a848170763a.tar.gz
chromium_src-02876f5fdafb3b6e500ba322715c3a848170763a.tar.bz2
Revert r107440 because this causes a crash on touchui on page load.
The CL being reverted: This patch lets the browser window punch a hole in the DesktopBackgroundView, thus eliminating overdraw. To do this, the hole punching logic was changed to look at the entire tree. Drawing the screen is a preorder traversal through all the layers. Thus, to compute the hole, we have to look at all of the layers after a particular layer in the preorder traversal. This is not an efficient algorithm, but it is simplest I could come up with. Plus we will be moving to the WebKit compositor soon. Hopefully this will improve the frame rate for the Aura demos Note: I will put the changes to Transform into another patch. Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=107360 Review URL: http://codereview.chromium.org/8368013 TBR=pkotwicz@chromium.org git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108347 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/gfx/compositor/layer.cc172
-rw-r--r--ui/gfx/compositor/layer_unittest.cc180
2 files changed, 73 insertions, 279 deletions
diff --git a/ui/gfx/compositor/layer.cc b/ui/gfx/compositor/layer.cc
index f632c65..7154a4d 100644
--- a/ui/gfx/compositor/layer.cc
+++ b/ui/gfx/compositor/layer.cc
@@ -42,7 +42,6 @@ Layer::Layer(Compositor* compositor)
parent_(NULL),
visible_(true),
fills_bounds_opaquely_(true),
- recompute_hole_(false),
layer_updated_externally_(false),
opacity_(1.0f),
delegate_(NULL) {
@@ -57,7 +56,6 @@ Layer::Layer(Compositor* compositor, LayerType type)
parent_(NULL),
visible_(true),
fills_bounds_opaquely_(true),
- recompute_hole_(false),
layer_updated_externally_(false),
opacity_(1.0f),
delegate_(NULL) {
@@ -98,7 +96,7 @@ void Layer::Add(Layer* child) {
web_layer_.addChild(child->web_layer_);
#endif
- SetNeedsToRecomputeHole();
+ RecomputeHole();
}
void Layer::Remove(Layer* child) {
@@ -111,7 +109,7 @@ void Layer::Remove(Layer* child) {
child->web_layer_.removeFromParent();
#endif
- SetNeedsToRecomputeHole();
+ RecomputeHole();
child->DropTextures();
}
@@ -194,7 +192,8 @@ void Layer::SetVisible(bool visible) {
if (!is_drawn)
DropTextures();
- SetNeedsToRecomputeHole();
+ if (parent_)
+ parent_->RecomputeHole();
}
bool Layer::IsDrawn() const {
@@ -231,7 +230,8 @@ void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
fills_bounds_opaquely_ = fills_bounds_opaquely;
- SetNeedsToRecomputeHole();
+ if (parent())
+ parent()->RecomputeHole();
#if defined(USE_WEBKIT_COMPOSITOR)
web_layer_.setOpaque(fills_bounds_opaquely);
#endif
@@ -310,10 +310,6 @@ void Layer::Draw() {
NOTREACHED();
#else
DCHECK(GetCompositor());
-
- if (recompute_hole_ && !parent_)
- RecomputeHole();
-
if (!ShouldDraw())
return;
@@ -421,98 +417,57 @@ void Layer::UpdateLayerCanvas() {
#endif
}
-void Layer::SetNeedsToRecomputeHole() {
- Layer* root_layer = this;
- while (root_layer->parent_)
- root_layer = root_layer->parent_;
-
- root_layer->recompute_hole_ = true;
-}
+void Layer::RecomputeHole() {
+ if (type_ == LAYER_HAS_NO_TEXTURE)
+ return;
-void Layer::ClearHoleRects() {
+ // Reset to default.
hole_rect_ = gfx::Rect();
- for (size_t i = 0; i < children_.size(); i++)
- children_[i]->ClearHoleRects();
-}
-
-void Layer::GetLayerProperties(const ui::Transform& parent_transform,
- std::vector<LayerProperties>* traversal) {
- if (!visible_ || opacity_ != 1.0f)
- return;
-
- ui::Transform current_transform;
- current_transform.ConcatTransform(parent_transform);
- if (transform().HasChange())
- current_transform.ConcatTransform(transform());
- current_transform.ConcatTranslate(
- static_cast<float>(bounds().x()),
- static_cast<float>(bounds().y()));
-
- if (fills_bounds_opaquely_ && type_ == LAYER_HAS_TEXTURE) {
- LayerProperties properties;
- properties.layer = this;
- properties.transform_relative_to_root = current_transform;
- traversal->push_back(properties);
+ // Find the largest hole
+ for (size_t i = 0; i < children_.size(); ++i) {
+ // Ignore non-opaque and hidden children.
+ if (!children_[i]->IsCompletelyOpaque() || !children_[i]->visible_)
+ continue;
+
+ // Ignore children that aren't rotated by multiples of 90 degrees.
+ float degrees;
+ if (!InterpolatedTransform::FactorTRS(children_[i]->transform(),
+ NULL, &degrees, NULL) ||
+ !IsApproximateMultilpleOf(degrees, 90.0f))
+ continue;
+
+ // The reason why we don't just take the bounds and apply the transform is
+ // that the bounds encodes a position, too, so the effective transformation
+ // matrix is actually different that the one reported. As well, the bounds
+ // will not necessarily be at the origin.
+ gfx::Rect candidate_hole(children_[i]->bounds_.size());
+ ui::Transform transform = children_[i]->transform();
+ transform.ConcatTranslate(static_cast<float>(children_[i]->bounds_.x()),
+ static_cast<float>(children_[i]->bounds_.y()));
+ transform.TransformRect(&candidate_hole);
+
+ // This layer might not contain the child (e.g., a portion of the child may
+ // be offscreen). Only the portion of the child that overlaps this layer is
+ // of any importance, so take the intersection.
+ candidate_hole = gfx::Rect(bounds().size()).Intersect(candidate_hole);
+
+ // Ensure we have the largest hole.
+ if (candidate_hole.size().GetArea() > hole_rect_.size().GetArea())
+ hole_rect_ = candidate_hole;
}
- for (size_t i = 0; i < children_.size(); i++)
- children_[i]->GetLayerProperties(current_transform, traversal);
-}
-
-void Layer::RecomputeHole() {
- std::vector<LayerProperties> traversal;
- ui::Transform transform;
-
- ClearHoleRects();
- GetLayerProperties(transform, &traversal);
-
- for (size_t i = 0; i < traversal.size(); i++) {
- Layer* layer = traversal[i].layer;
- gfx::Rect bounds = gfx::Rect(layer->bounds().size());
-
- // Iterate through layers which are after traversal[i] in draw order
- // and find the largest candidate hole.
- for (size_t j = i + 1; j < traversal.size(); j++) {
- gfx::Rect candidate_hole = gfx::Rect(traversal[j].layer->bounds().size());
-
- // Compute transform to go from bounds of layer |j| to local bounds of
- // layer |i|.
- ui::Transform candidate_hole_transform;
- ui::Transform inverted;
-
- candidate_hole_transform.ConcatTransform(
- traversal[j].transform_relative_to_root);
-
- if (!traversal[i].transform_relative_to_root.GetInverse(&inverted))
- continue;
-
- candidate_hole_transform.ConcatTransform(inverted);
-
- // cannot punch a hole if the relative transform between the two layers
- // is not multiple of 90.
- float degrees;
- gfx::Point p;
- if (!InterpolatedTransform::FactorTRS(candidate_hole_transform, &p,
- &degrees, NULL) || !IsApproximateMultilpleOf(degrees, 90.0f))
- continue;
-
- candidate_hole_transform.TransformRect(&candidate_hole);
- candidate_hole = candidate_hole.Intersect(bounds);
-
- if (candidate_hole.size().GetArea() > layer->hole_rect().size().GetArea())
- layer->set_hole_rect(candidate_hole);
- }
- // Free up texture memory if the hole fills bounds of layer.
- if (!layer->ShouldDraw() && !layer_updated_externally())
- layer->DropTexture();
+ // Free up texture memory if the hole fills bounds of layer.
+ if (!ShouldDraw() && !layer_updated_externally_)
+ texture_ = NULL;
#if defined(USE_WEBKIT_COMPOSITOR)
- layer->RecomputeDrawsContent();
+ RecomputeDrawsContent();
#endif
- }
+}
- recompute_hole_ = false;
+bool Layer::IsCompletelyOpaque() const {
+ return fills_bounds_opaquely() && GetCombinedOpacity() == 1.0f;
}
// static
@@ -551,13 +506,9 @@ void Layer::PunchHole(const gfx::Rect& rect,
rect.bottom() - trimmed_rect.bottom()));
}
-void Layer::DropTexture() {
+void Layer::DropTextures() {
if (!layer_updated_externally_)
texture_ = NULL;
-}
-
-void Layer::DropTextures() {
- DropTexture();
for (size_t i = 0; i < children_.size(); ++i)
children_[i]->DropTextures();
}
@@ -597,7 +548,8 @@ bool Layer::GetTransformRelativeTo(const Layer* ancestor,
void Layer::SetBoundsImmediately(const gfx::Rect& bounds) {
bounds_ = bounds;
- SetNeedsToRecomputeHole();
+ if (parent())
+ parent()->RecomputeHole();
#if defined(USE_WEBKIT_COMPOSITOR)
web_layer_.setBounds(bounds.size());
RecomputeTransform();
@@ -608,7 +560,8 @@ void Layer::SetBoundsImmediately(const gfx::Rect& bounds) {
void Layer::SetTransformImmediately(const ui::Transform& transform) {
transform_ = transform;
- SetNeedsToRecomputeHole();
+ if (parent())
+ parent()->RecomputeHole();
#if defined(USE_WEBKIT_COMPOSITOR)
RecomputeTransform();
#endif
@@ -616,8 +569,25 @@ void Layer::SetTransformImmediately(const ui::Transform& transform) {
void Layer::SetOpacityImmediately(float opacity) {
bool schedule_draw = (opacity != opacity_ && IsDrawn());
+ bool was_opaque = GetCombinedOpacity() == 1.0f;
opacity_ = opacity;
- SetNeedsToRecomputeHole();
+ bool is_opaque = GetCombinedOpacity() == 1.0f;
+
+ // If our opacity has changed we need to recompute our hole, our parent's hole
+ // and the holes of all our descendants.
+ if (was_opaque != is_opaque) {
+ if (parent_)
+ parent_->RecomputeHole();
+ std::queue<Layer*> to_process;
+ to_process.push(this);
+ while (!to_process.empty()) {
+ Layer* current = to_process.front();
+ to_process.pop();
+ current->RecomputeHole();
+ for (size_t i = 0; i < current->children_.size(); ++i)
+ to_process.push(current->children_.at(i));
+ }
+ }
#if defined(USE_WEBKIT_COMPOSITOR)
if (visible_)
web_layer_.setOpacity(opacity);
diff --git a/ui/gfx/compositor/layer_unittest.cc b/ui/gfx/compositor/layer_unittest.cc
index fceb9c6..9443ab0 100644
--- a/ui/gfx/compositor/layer_unittest.cc
+++ b/ui/gfx/compositor/layer_unittest.cc
@@ -544,120 +544,9 @@ TEST_F(LayerWithNullDelegateTest, LargestHole) {
scoped_ptr<Layer> child2(CreateTextureLayer(gfx::Rect(75, 75, 200, 200)));
parent->Add(child2.get());
- Draw();
-
EXPECT_EQ(gfx::Rect(75, 75, 200, 200), parent->hole_rect());
}
-// Verifies that the largest hole in the draw order is picked
-TEST_F(LayerWithNullDelegateTest, HoleGeneratedFromLeaf) {
- // Layer tree looks like:
- // node 1
- // |_ node 11
- // |_ node 111
- // |_ node 12
- // |_ node 121
-
- scoped_ptr<Layer> node1(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
-
- scoped_ptr<Layer> node11(CreateTextureLayer(gfx::Rect(50, 50, 100, 100)));
- node1->Add(node11.get());
-
- scoped_ptr<Layer> node12(CreateTextureLayer(gfx::Rect(75, 75, 200, 200)));
- node1->Add(node12.get());
-
- scoped_ptr<Layer> node111(CreateTextureLayer(gfx::Rect(10, 10, 20, 20)));
- node11->Add(node111.get());
-
- scoped_ptr<Layer> node121(CreateTextureLayer(gfx::Rect(10, 10, 190, 190)));
- node12->Add(node121.get());
-
- Draw();
-
- EXPECT_EQ(gfx::Rect(75, 75, 200, 200), node1->hole_rect());
- EXPECT_EQ(gfx::Rect(25, 25, 75, 75), node11->hole_rect());
- EXPECT_EQ(gfx::Rect(10, 10, 190, 190), node12->hole_rect());
-}
-
-// Verifies that a hole can only punched into a layer with opacity = 1.0f.
-TEST_F(LayerWithNullDelegateTest, NoHoleWhenPartialOpacity) {
- // Layer tree looks like:
- // node 1
- // |_ node 11
- // |_ node 111
-
- scoped_ptr<Layer> node1(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
-
- scoped_ptr<Layer> node11(CreateTextureLayer(gfx::Rect(50, 50, 100, 100)));
- node1->Add(node11.get());
-
- scoped_ptr<Layer> node111(CreateTextureLayer(gfx::Rect(10, 10, 20, 20)));
- node11->Add(node111.get());
-
- Draw();
- EXPECT_EQ(gfx::Rect(50, 50, 100, 100), node1->hole_rect());
- EXPECT_EQ(gfx::Rect(10, 10, 20, 20), node11->hole_rect());
-
-
- node11->SetOpacity(0.5f);
- Draw();
- EXPECT_TRUE(node1->hole_rect().IsEmpty());
- EXPECT_TRUE(node11->hole_rect().IsEmpty());
-}
-
-// Verifies that a non visible layer or any of its children is not a hole.
-TEST_F(LayerWithNullDelegateTest, NonVisibleLayerCannotBeHole) {
- // Layer tree looks like:
- // node 1
- // |_ node 11
- // |_ node 111
-
- scoped_ptr<Layer> node1(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
-
- scoped_ptr<Layer> node11(CreateTextureLayer(gfx::Rect(50, 50, 100, 100)));
- node1->Add(node11.get());
-
- scoped_ptr<Layer> node111(CreateTextureLayer(gfx::Rect(10, 10, 20, 20)));
- node11->Add(node111.get());
-
- Draw();
- EXPECT_EQ(gfx::Rect(50, 50, 100, 100), node1->hole_rect());
- EXPECT_EQ(gfx::Rect(10, 10, 20, 20), node11->hole_rect());
-
-
- node11->SetVisible(false);
- Draw();
- EXPECT_TRUE(node1->hole_rect().IsEmpty());
- EXPECT_TRUE(node11->hole_rect().IsEmpty());
-}
-
-// Verifies that a layer which doesn't fill its bounds opaquely cannot punch a
-// hole. However its children should still be able to punch a hole.
-TEST_F(LayerWithNullDelegateTest, LayerNotFillingBoundsOpaquelyCannotBeHole) {
- // Layer tree looks like:
- // node 1
- // |_ node 11
- // |_ node 111
-
- scoped_ptr<Layer> node1(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
-
- scoped_ptr<Layer> node11(CreateTextureLayer(gfx::Rect(50, 50, 100, 100)));
- node1->Add(node11.get());
-
- scoped_ptr<Layer> node111(CreateTextureLayer(gfx::Rect(10, 10, 20, 20)));
- node11->Add(node111.get());
-
- Draw();
- EXPECT_EQ(gfx::Rect(50, 50, 100, 100), node1->hole_rect());
- EXPECT_EQ(gfx::Rect(10, 10, 20, 20), node11->hole_rect());
-
-
- node11->SetFillsBoundsOpaquely(false);
- Draw();
- EXPECT_EQ(gfx::Rect(60, 60, 20, 20), node1->hole_rect());
- EXPECT_TRUE(node11->hole_rect().IsEmpty());
-}
-
// Verifies that the hole is with respect to the local bounds of its parent.
TEST_F(LayerWithNullDelegateTest, HoleLocalBounds) {
scoped_ptr<Layer> parent(CreateTextureRootLayer(
@@ -666,20 +555,16 @@ TEST_F(LayerWithNullDelegateTest, HoleLocalBounds) {
scoped_ptr<Layer> child(CreateTextureLayer(gfx::Rect(50, 50, 100, 100)));
parent->Add(child.get());
- Draw();
-
EXPECT_EQ(gfx::Rect(50, 50, 100, 100), parent->hole_rect());
}
// Verifies that there is no hole present when one of the child layers has a
// transform.
TEST_F(LayerWithNullDelegateTest, NoHoleWithTransform) {
- scoped_ptr<Layer> parent(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
+ scoped_ptr<Layer> parent(CreateTextureLayer(gfx::Rect(0, 0, 400, 400)));
scoped_ptr<Layer> child(CreateTextureLayer(gfx::Rect(50, 50, 100, 100)));
parent->Add(child.get());
- Draw();
-
EXPECT_TRUE(!parent->hole_rect().IsEmpty());
ui::Transform t;
@@ -688,20 +573,16 @@ TEST_F(LayerWithNullDelegateTest, NoHoleWithTransform) {
t.ConcatTranslate(50, 50);
child->SetTransform(t);
- Draw();
-
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), parent->hole_rect());
}
// Verifies that if the child layer is rotated by a multiple of ninety degrees
// we punch a hole
TEST_F(LayerWithNullDelegateTest, HoleWithNinetyDegreeTransforms) {
- scoped_ptr<Layer> parent(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
+ scoped_ptr<Layer> parent(CreateTextureLayer(gfx::Rect(0, 0, 400, 400)));
scoped_ptr<Layer> child(CreateTextureLayer(gfx::Rect(50, 50, 50, 50)));
parent->Add(child.get());
- Draw();
-
EXPECT_TRUE(!parent->hole_rect().IsEmpty());
for (int i = -4; i <= 4; ++i) {
@@ -716,67 +597,10 @@ TEST_F(LayerWithNullDelegateTest, HoleWithNinetyDegreeTransforms) {
t.ConcatTranslate(child->bounds().x(), child->bounds().y());
t.TransformRect(&target_rect);
- Draw();
-
EXPECT_EQ(target_rect, parent->hole_rect());
}
}
-// Verifies that a layer which doesn't have a texture cannot punch a
-// hole. However its children should still be able to punch a hole.
-TEST_F(LayerWithNullDelegateTest, HoleWithRelativeNinetyDegreeTransforms) {
- // Layer tree looks like:
- // node 1
- // |_ node 11
- // |_ node 12
-
- scoped_ptr<Layer> node1(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
-
- scoped_ptr<Layer> node11(CreateTextureLayer(gfx::Rect(50, 50, 50, 50)));
- node1->Add(node11.get());
-
- scoped_ptr<Layer> node12(CreateTextureLayer(gfx::Rect(50, 50, 50, 50)));
- node1->Add(node12.get());
-
- Draw();
-
- EXPECT_EQ(gfx::Rect(0, 0, 50, 50), node11->hole_rect());
- EXPECT_TRUE(node12->hole_rect().IsEmpty());
-
- ui::Transform t1;
- // Need to rotate in local coordinates.
- t1.SetTranslate(-25, -25);
- t1.ConcatRotate(45.0f);
- t1.ConcatTranslate(25, 25);
- node11->SetTransform(t1);
-
- Draw();
-
- EXPECT_TRUE(node12->hole_rect().IsEmpty());
- EXPECT_TRUE(node11->hole_rect().IsEmpty());
-
- ui::Transform t2;
- // Need to rotate in local coordinates.
- t2.SetTranslate(-25, -25);
- t2.ConcatRotate(-135.0f);
- t2.ConcatTranslate(25, 25);
- node12->SetTransform(t2);
-
- // Do translation of target rect in order to account for inprecision of
- // using floating point matrices vs integer rects.
- ui::Transform t3;
- gfx::Rect target_rect = gfx::Rect(node11->bounds().size());
- t3.ConcatTransform(t2);
- t1.GetInverse(&t1);
- t3.ConcatTransform(t1);
- t3.TransformRect(&target_rect);
-
- Draw();
-
- EXPECT_TRUE(node12->hole_rect().IsEmpty());
- EXPECT_EQ(target_rect, node11->hole_rect());
-}
-
// Create this hierarchy:
// L1 (no texture)
// +- L11 (texture)