summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorvollick@chromium.org <vollick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-06 17:10:58 +0000
committervollick@chromium.org <vollick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-06 17:10:58 +0000
commitaaa1268aa6cd0a4cdce9d2d04d21f11910b1198a (patch)
treed4e832228fe4067d5c28053697a60ab490691a32 /ui
parent947c86a24a345cd22df3d458c6cdb1b4ec68566a (diff)
downloadchromium_src-aaa1268aa6cd0a4cdce9d2d04d21f11910b1198a.zip
chromium_src-aaa1268aa6cd0a4cdce9d2d04d21f11910b1198a.tar.gz
chromium_src-aaa1268aa6cd0a4cdce9d2d04d21f11910b1198a.tar.bz2
Revert 104304 - Avoid overdraw in views desktop.
Make sure that we still allow a view to punch a hole in its parent if it is rotated by a multiple of 90 degrees. BUG=None TEST=None Review URL: http://codereview.chromium.org/7941017 TBR=vollick@chromium.org Review URL: http://codereview.chromium.org/8175008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@104311 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/gfx/compositor/layer.cc59
-rw-r--r--ui/gfx/compositor/layer_unittest.cc56
2 files changed, 62 insertions, 53 deletions
diff --git a/ui/gfx/compositor/layer.cc b/ui/gfx/compositor/layer.cc
index b9b1cd3..af3514fc 100644
--- a/ui/gfx/compositor/layer.cc
+++ b/ui/gfx/compositor/layer.cc
@@ -11,20 +11,8 @@
#include "ui/base/animation/animation.h"
#include "ui/gfx/compositor/layer_animator.h"
#include "ui/gfx/canvas_skia.h"
-#include "ui/gfx/interpolated_transform.h"
#include "ui/gfx/point3.h"
-namespace {
-
-const float EPSILON = 1e-3f;
-
-bool IsApproximateMultilpleOf(float value, float base) {
- float remainder = fmod(fabs(value), base);
- return remainder < EPSILON || base - remainder < EPSILON;
-}
-
-} // namespace
-
namespace ui {
Layer::Layer(Compositor* compositor)
@@ -315,33 +303,48 @@ void Layer::RecomputeHole() {
// Reset to default.
hole_rect_ = gfx::Rect();
- // Find the largest hole
+ // 1) We cannot do any hole punching if any child has a transform.
+ for (size_t i = 0; i < children_.size(); ++i) {
+ if (children_[i]->transform().HasChange() && children_[i]->visible_)
+ return;
+ }
+
+ // 2) 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))
+ if (children_[i]->bounds().size().GetArea() > hole_rect_.size().GetArea()) {
+ hole_rect_ = children_[i]->bounds();
+ }
+ }
+
+ // 3) Make sure hole does not intersect with non-opaque children.
+ for (size_t i = 0; i < children_.size(); ++i) {
+ // Ignore opaque and hidden children.
+ if (children_[i]->IsCompletelyOpaque() || !children_[i]->visible_)
continue;
- gfx::Rect candidate_hole = children_[i]->bounds();
- children_[i]->transform().TransformRect(&candidate_hole);
+ // Ignore non-intersecting children.
+ if (!hole_rect_.Intersects(children_[i]->bounds()))
+ continue;
- // 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 = bounds().Intersect(candidate_hole);
+ // Compute surrounding fragments.
+ std::vector<gfx::Rect> fragments;
+ PunchHole(hole_rect_, children_[i]->bounds(), &fragments);
- // Ensure we have the largest hole.
- if (candidate_hole.size().GetArea() > hole_rect_.size().GetArea())
- hole_rect_ = candidate_hole;
+ // Pick the largest surrounding fragment as the new hole.
+ hole_rect_ = fragments[0];
+ for (size_t j = 1; j < fragments.size(); ++j) {
+ if (fragments[j].size().GetArea() > hole_rect_.size().GetArea()) {
+ hole_rect_ = fragments[j];
+ }
+ }
+ DCHECK(!hole_rect_.IsEmpty());
}
- // Free up texture memory if the hole fills bounds of layer.
+ // 4) Free up texture memory if the hole fills bounds of layer.
if (!ShouldDraw() && !layer_updated_externally_)
texture_ = NULL;
}
diff --git a/ui/gfx/compositor/layer_unittest.cc b/ui/gfx/compositor/layer_unittest.cc
index 953eaba..59ccfdd 100644
--- a/ui/gfx/compositor/layer_unittest.cc
+++ b/ui/gfx/compositor/layer_unittest.cc
@@ -506,6 +506,36 @@ TEST_F(LayerWithNullDelegateTest, LayerTextureNonEmptySchedulePaint) {
EXPECT_TRUE(layer->texture() != NULL);
}
+// Verifies that a hole in a layer does not intersect non completely-opaque
+// layers.
+TEST_F(LayerWithNullDelegateTest, HoleDoesNotIntersectNonOpaque) {
+ scoped_ptr<Layer> parent(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
+ scoped_ptr<Layer> child1(CreateTextureLayer(gfx::Rect(50, 50, 100, 100)));
+ parent->Add(child1.get());
+
+ scoped_ptr<Layer> child2(CreateLayer(Layer::LAYER_HAS_NO_TEXTURE));
+ child2->SetFillsBoundsOpaquely(false);
+ parent->Add(child2.get());
+ Draw();
+
+ // Ensure largest non intersecting hole picked.
+ // largest fragment on bottom.
+ child2->SetBounds(gfx::Rect(20, 20, 60, 80));
+ EXPECT_EQ(gfx::Rect(50, 100, 100, 50), parent->hole_rect());
+
+ // largest fragment on right.
+ child2->SetBounds(gfx::Rect(20, 20, 60, 200));
+ EXPECT_EQ(gfx::Rect(80, 50, 70, 100), parent->hole_rect());
+
+ // largest fragment on top.
+ child2->SetBounds(gfx::Rect(130, 110, 50, 50));
+ EXPECT_EQ(gfx::Rect(50, 50, 100, 60), parent->hole_rect());
+
+ // largest fragment on left.
+ child2->SetBounds(gfx::Rect(130, 20, 50, 200));
+ EXPECT_EQ(gfx::Rect(50, 50, 80, 100), parent->hole_rect());
+}
+
// Verifies that when there are many potential holes, the largest one is picked.
TEST_F(LayerWithNullDelegateTest, LargestHole) {
scoped_ptr<Layer> parent(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400)));
@@ -529,36 +559,12 @@ TEST_F(LayerWithNullDelegateTest, NoHoleWithTransform) {
EXPECT_TRUE(!parent->hole_rect().IsEmpty());
ui::Transform t;
- t.SetTranslate(-75, -75);
- t.ConcatRotate(45.0f);
- t.ConcatTranslate(75, 75);
+ t.SetRotate(90.0f);
child->SetTransform(t);
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(CreateTextureLayer(gfx::Rect(0, 0, 400, 400)));
- scoped_ptr<Layer> child(CreateTextureLayer(gfx::Rect(50, 50, 50, 50)));
- parent->Add(child.get());
-
- EXPECT_TRUE(!parent->hole_rect().IsEmpty());
-
- for (int i = -4; i <= 4; ++i) {
- ui::Transform t;
- t.SetTranslate(-75, -75);
- t.ConcatRotate(90.0f * i);
- t.ConcatTranslate(75, 75);
- child->SetTransform(t);
-
- gfx::Rect target_rect = child->bounds();
- child->transform().TransformRect(&target_rect);
- EXPECT_EQ(target_rect, parent->hole_rect());
- }
-}
-
// Create this hierarchy:
// L1 (no texture)
// +- L11 (texture)