summaryrefslogtreecommitdiff
path: root/Source/WebKit/chromium/tests
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-02-24 16:36:50 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-02-24 16:36:50 +0100
commitad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch)
treeb34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/WebKit/chromium/tests
parent03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff)
downloadqtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/WebKit/chromium/tests')
-rw-r--r--Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp16
-rw-r--r--Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp133
-rw-r--r--Source/WebKit/chromium/tests/CCAnimationTestCommon.h104
-rw-r--r--Source/WebKit/chromium/tests/CCKeyframedAnimationCurveTest.cpp241
-rw-r--r--Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp260
-rw-r--r--Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp215
-rw-r--r--Source/WebKit/chromium/tests/CCLayerImplTest.cpp3
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp177
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp166
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp246
-rw-r--r--Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp1173
-rw-r--r--Source/WebKit/chromium/tests/CCQuadCullerTest.cpp77
-rw-r--r--Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp4
-rw-r--r--Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h5
-rw-r--r--Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp8
-rw-r--r--Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h2
-rw-r--r--Source/WebKit/chromium/tests/LayerChromiumTest.cpp13
-rw-r--r--Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp24
-rw-r--r--Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp86
-rw-r--r--Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp41
-rw-r--r--Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp3
-rw-r--r--Source/WebKit/chromium/tests/WebFrameTest.cpp72
-rw-r--r--Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp157
-rw-r--r--Source/WebKit/chromium/tests/WebSocketExtensionDispatcherTest.cpp179
-rw-r--r--Source/WebKit/chromium/tests/WebURLResponseTest.cpp78
-rw-r--r--Source/WebKit/chromium/tests/data/get_scale_for_auto_zoom_into_div_test.html13
26 files changed, 3103 insertions, 393 deletions
diff --git a/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp b/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp
index 3e93d95de..e14ef9bc0 100644
--- a/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp
+++ b/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp
@@ -25,24 +25,20 @@
#include "config.h"
#include "cc/CCActiveAnimation.h"
-
-#include "cc/CCAnimationCurve.h"
+#include "CCAnimationTestCommon.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <wtf/Vector.h>
-namespace WebCore {
+using namespace WebKitTests;
+using namespace WebCore;
-class FakeFloatAnimation : public CCFloatAnimationCurve {
-public:
- virtual double duration() const { return 1; }
- virtual float getValue(double now) const { return 0; }
-};
+namespace {
PassOwnPtr<CCActiveAnimation> createActiveAnimation(int iterations)
{
- OwnPtr<CCActiveAnimation> toReturn(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimation), 1, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toReturn(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve), 0, 1, CCActiveAnimation::Opacity));
toReturn->setIterations(iterations);
return toReturn.release();
}
@@ -164,4 +160,4 @@ TEST(CCActiveAnimationTest, IsFinished)
EXPECT_TRUE(anim->isFinished());
}
-} // namespace WebCore
+} // namespace
diff --git a/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp b/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp
new file mode 100644
index 000000000..c9240e31f
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "CCAnimationTestCommon.h"
+
+#include "GraphicsLayer.h"
+#include "LayerChromium.h"
+#include "cc/CCLayerAnimationController.h"
+
+using namespace WebCore;
+
+namespace {
+
+template <class Target>
+void addOpacityTransition(Target& target, double duration, float startOpacity, float endOpacity)
+{
+ WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
+ if (duration > 0)
+ values.insert(new FloatAnimationValue(0, startOpacity));
+ values.insert(new FloatAnimationValue(duration, endOpacity));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+
+ target.addAnimation(values, boxSize, animation.get(), 0, 0, 0);
+}
+
+} // namespace
+
+namespace WebKitTests {
+
+FakeFloatAnimationCurve::FakeFloatAnimationCurve()
+{
+}
+
+FakeFloatAnimationCurve::~FakeFloatAnimationCurve()
+{
+}
+
+PassOwnPtr<WebCore::CCAnimationCurve> FakeFloatAnimationCurve::clone() const
+{
+ return adoptPtr(new FakeFloatAnimationCurve);
+}
+
+FakeTransformTransition::FakeTransformTransition(double duration)
+ : m_duration(duration)
+{
+}
+
+FakeTransformTransition::~FakeTransformTransition()
+{
+}
+
+WebCore::TransformationMatrix FakeTransformTransition::getValue(double time, const WebCore::IntSize& size) const
+{
+ return WebCore::TransformationMatrix();
+}
+
+PassOwnPtr<WebCore::CCAnimationCurve> FakeTransformTransition::clone() const
+{
+ return adoptPtr(new FakeTransformTransition(*this));
+}
+
+
+FakeFloatTransition::FakeFloatTransition(double duration, float from, float to)
+ : m_duration(duration)
+ , m_from(from)
+ , m_to(to)
+{
+}
+
+FakeFloatTransition::~FakeFloatTransition()
+{
+}
+
+float FakeFloatTransition::getValue(double time) const
+{
+ time /= m_duration;
+ if (time >= 1)
+ time = 1;
+ return (1 - time) * m_from + time * m_to;
+}
+
+FakeLayerAnimationControllerImplClient::FakeLayerAnimationControllerImplClient()
+ : m_opacity(0)
+{
+}
+
+FakeLayerAnimationControllerImplClient::~FakeLayerAnimationControllerImplClient()
+{
+}
+
+PassOwnPtr<WebCore::CCAnimationCurve> FakeFloatTransition::clone() const
+{
+ return adoptPtr(new FakeFloatTransition(*this));
+}
+
+void addOpacityTransitionToController(WebCore::CCLayerAnimationController& controller, double duration, float startOpacity, float endOpacity)
+{
+ addOpacityTransition(controller, duration, startOpacity, endOpacity);
+}
+
+void addOpacityTransitionToLayer(WebCore::LayerChromium& layer, double duration, float startOpacity, float endOpacity)
+{
+ addOpacityTransition(layer, duration, startOpacity, endOpacity);
+}
+
+} // namespace WebKitTests
diff --git a/Source/WebKit/chromium/tests/CCAnimationTestCommon.h b/Source/WebKit/chromium/tests/CCAnimationTestCommon.h
new file mode 100644
index 000000000..d13e74ca1
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCAnimationTestCommon.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCAnimationTestCommon_h
+#define CCAnimationTestCommon_h
+
+#include "cc/CCAnimationCurve.h"
+#include "cc/CCLayerAnimationControllerImpl.h"
+
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+class CCLayerAnimationController;
+class LayerChromium;
+}
+
+namespace WebKitTests {
+
+class FakeFloatAnimationCurve : public WebCore::CCFloatAnimationCurve {
+public:
+ FakeFloatAnimationCurve();
+ virtual ~FakeFloatAnimationCurve();
+
+ virtual double duration() const { return 1; }
+ virtual float getValue(double now) const { return 0; }
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+};
+
+class FakeTransformTransition : public WebCore::CCTransformAnimationCurve {
+public:
+ FakeTransformTransition(double duration);
+ virtual ~FakeTransformTransition();
+
+ virtual double duration() const { return m_duration; }
+ virtual WebCore::TransformationMatrix getValue(double time, const WebCore::IntSize&) const;
+
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+
+private:
+ double m_duration;
+};
+
+class FakeFloatTransition : public WebCore::CCFloatAnimationCurve {
+public:
+ FakeFloatTransition(double duration, float from, float to);
+ virtual ~FakeFloatTransition();
+
+ virtual double duration() const { return m_duration; }
+ virtual float getValue(double time) const;
+
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+
+private:
+ double m_duration;
+ float m_from;
+ float m_to;
+};
+
+class FakeLayerAnimationControllerImplClient : public WebCore::CCLayerAnimationControllerImplClient {
+public:
+ FakeLayerAnimationControllerImplClient();
+ virtual ~FakeLayerAnimationControllerImplClient();
+
+ virtual int id() const { return 0; }
+ virtual float opacity() const { return m_opacity; }
+ virtual void setOpacity(float opacity) { m_opacity = opacity; }
+ virtual const WebCore::TransformationMatrix& transform() const { return m_transform; }
+ virtual void setTransform(const WebCore::TransformationMatrix& transform) { m_transform = transform; }
+ virtual const WebCore::IntSize& bounds() const { return m_bounds; }
+
+private:
+ float m_opacity;
+ WebCore::TransformationMatrix m_transform;
+ WebCore::IntSize m_bounds;
+};
+
+void addOpacityTransitionToController(WebCore::CCLayerAnimationController&, double duration, float startOpacity, float endOpacity);
+
+void addOpacityTransitionToLayer(WebCore::LayerChromium&, double duration, float startOpacity, float endOpacity);
+
+} // namespace WebKitTests
+
+#endif // CCAnimationTesctCommon_h
diff --git a/Source/WebKit/chromium/tests/CCKeyframedAnimationCurveTest.cpp b/Source/WebKit/chromium/tests/CCKeyframedAnimationCurveTest.cpp
new file mode 100644
index 000000000..b7732aeab
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCKeyframedAnimationCurveTest.cpp
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "cc/CCKeyframedAnimationCurve.h"
+
+#include "Length.h"
+#include "TranslateTransformOperation.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace {
+
+void expectTranslateX(double translateX, const TransformationMatrix& matrix)
+{
+ TransformationMatrix::DecomposedType decomposedType;
+ matrix.decompose(decomposedType);
+ EXPECT_FLOAT_EQ(translateX, decomposedType.translateX);
+}
+
+// Tests that a float animation with one keyframe works as expected.
+TEST(CCKeyframedAnimationCurveTest, OneFloatKeyframe)
+{
+ Vector<CCFloatKeyframe> keyframes;
+ keyframes.append(CCFloatKeyframe(0, 2));
+ OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes));
+ EXPECT_FLOAT_EQ(2, curve->getValue(-1));
+ EXPECT_FLOAT_EQ(2, curve->getValue(0));
+ EXPECT_FLOAT_EQ(2, curve->getValue(0.5));
+ EXPECT_FLOAT_EQ(2, curve->getValue(1));
+ EXPECT_FLOAT_EQ(2, curve->getValue(2));
+}
+
+// Tests that a float animation with two keyframes works as expected.
+TEST(CCKeyframedAnimationCurveTest, TwoFloatKeyframe)
+{
+ Vector<CCFloatKeyframe> keyframes;
+ keyframes.append(CCFloatKeyframe(0, 2));
+ keyframes.append(CCFloatKeyframe(1, 4));
+ OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes));
+ EXPECT_FLOAT_EQ(2, curve->getValue(-1));
+ EXPECT_FLOAT_EQ(2, curve->getValue(0));
+ EXPECT_FLOAT_EQ(3, curve->getValue(0.5));
+ EXPECT_FLOAT_EQ(4, curve->getValue(1));
+ EXPECT_FLOAT_EQ(4, curve->getValue(2));
+}
+
+// Tests that a float animation with three keyframes works as expected.
+TEST(CCKeyframedAnimationCurveTest, ThreeFloatKeyframe)
+{
+ Vector<CCFloatKeyframe> keyframes;
+ keyframes.append(CCFloatKeyframe(0, 2));
+ keyframes.append(CCFloatKeyframe(1, 4));
+ keyframes.append(CCFloatKeyframe(2, 8));
+ OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes));
+ EXPECT_FLOAT_EQ(2, curve->getValue(-1));
+ EXPECT_FLOAT_EQ(2, curve->getValue(0));
+ EXPECT_FLOAT_EQ(3, curve->getValue(0.5));
+ EXPECT_FLOAT_EQ(4, curve->getValue(1));
+ EXPECT_FLOAT_EQ(6, curve->getValue(1.5));
+ EXPECT_FLOAT_EQ(8, curve->getValue(2));
+ EXPECT_FLOAT_EQ(8, curve->getValue(3));
+}
+
+// Tests that a float animation with multiple keys at a given time works sanely.
+TEST(CCKeyframedAnimationCurveTest, RepeatedFloatKeyTimes)
+{
+ Vector<CCFloatKeyframe> keyframes;
+ // A step function.
+ keyframes.append(CCFloatKeyframe(0, 4));
+ keyframes.append(CCFloatKeyframe(1, 4));
+ keyframes.append(CCFloatKeyframe(1, 6));
+ keyframes.append(CCFloatKeyframe(2, 6));
+ OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes));
+
+ EXPECT_FLOAT_EQ(4, curve->getValue(-1));
+ EXPECT_FLOAT_EQ(4, curve->getValue(0));
+ EXPECT_FLOAT_EQ(4, curve->getValue(0.5));
+
+ // There is a discontinuity at 1. Any value between 4 and 6 is valid.
+ float value = curve->getValue(1);
+ EXPECT_TRUE(value >= 4 && value <= 6);
+
+ EXPECT_FLOAT_EQ(6, curve->getValue(1.5));
+ EXPECT_FLOAT_EQ(6, curve->getValue(2));
+ EXPECT_FLOAT_EQ(6, curve->getValue(3));
+}
+
+
+// Tests that a transform animation with one keyframe works as expected.
+TEST(CCKeyframedAnimationCurveTest, OneTransformKeyframe)
+{
+ Vector<CCTransformKeyframe> keyframes;
+ TransformOperations operations;
+ operations.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ keyframes.append(CCTransformKeyframe(0, operations));
+ OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes));
+ IntSize layerSize; // ignored
+ expectTranslateX(2, curve->getValue(-1, layerSize));
+ expectTranslateX(2, curve->getValue(0, layerSize));
+ expectTranslateX(2, curve->getValue(0.5, layerSize));
+ expectTranslateX(2, curve->getValue(1, layerSize));
+ expectTranslateX(2, curve->getValue(2, layerSize));
+}
+
+// Tests that a transform animation with two keyframes works as expected.
+TEST(CCKeyframedAnimationCurveTest, TwoTransformKeyframe)
+{
+ Vector<CCTransformKeyframe> keyframes;
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ keyframes.append(CCTransformKeyframe(0, operations1));
+ keyframes.append(CCTransformKeyframe(1, operations2));
+ OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes));
+ IntSize layerSize; // ignored
+ expectTranslateX(2, curve->getValue(-1, layerSize));
+ expectTranslateX(2, curve->getValue(0, layerSize));
+ expectTranslateX(3, curve->getValue(0.5, layerSize));
+ expectTranslateX(4, curve->getValue(1, layerSize));
+ expectTranslateX(4, curve->getValue(2, layerSize));
+}
+
+// Tests that a transform animation with three keyframes works as expected.
+TEST(CCKeyframedAnimationCurveTest, ThreeTransformKeyframe)
+{
+ Vector<CCTransformKeyframe> keyframes;
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations3;
+ operations3.operations().append(TranslateTransformOperation::create(Length(8, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ keyframes.append(CCTransformKeyframe(0, operations1));
+ keyframes.append(CCTransformKeyframe(1, operations2));
+ keyframes.append(CCTransformKeyframe(2, operations3));
+ OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes));
+ IntSize layerSize; // ignored
+ expectTranslateX(2, curve->getValue(-1, layerSize));
+ expectTranslateX(2, curve->getValue(0, layerSize));
+ expectTranslateX(3, curve->getValue(0.5, layerSize));
+ expectTranslateX(4, curve->getValue(1, layerSize));
+ expectTranslateX(6, curve->getValue(1.5, layerSize));
+ expectTranslateX(8, curve->getValue(2, layerSize));
+ expectTranslateX(8, curve->getValue(3, layerSize));
+}
+
+// Tests that a transform animation with multiple keys at a given time works sanely.
+TEST(CCKeyframedAnimationCurveTest, RepeatedTransformKeyTimes)
+{
+ Vector<CCTransformKeyframe> keyframes;
+ // A step function.
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations3;
+ operations3.operations().append(TranslateTransformOperation::create(Length(6, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations4;
+ operations4.operations().append(TranslateTransformOperation::create(Length(6, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ keyframes.append(CCTransformKeyframe(0, operations1));
+ keyframes.append(CCTransformKeyframe(1, operations2));
+ keyframes.append(CCTransformKeyframe(1, operations3));
+ keyframes.append(CCTransformKeyframe(2, operations4));
+ OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes));
+
+ IntSize layerSize; // ignored
+
+ expectTranslateX(4, curve->getValue(-1, layerSize));
+ expectTranslateX(4, curve->getValue(0, layerSize));
+ expectTranslateX(4, curve->getValue(0.5, layerSize));
+
+ // There is a discontinuity at 1. Any value between 4 and 6 is valid.
+ TransformationMatrix value = curve->getValue(1, layerSize);
+ TransformationMatrix::DecomposedType decomposedType;
+ value.decompose(decomposedType);
+ EXPECT_TRUE(decomposedType.translateX >= 4 && decomposedType.translateX <= 6);
+
+ expectTranslateX(6, curve->getValue(1.5, layerSize));
+ expectTranslateX(6, curve->getValue(2, layerSize));
+ expectTranslateX(6, curve->getValue(3, layerSize));
+}
+
+// Tests that invalid lists of keyframes result in nothing being returned from ::create.
+TEST(CCKeyframedAnimationCurveTest, InvalidKeyframes)
+{
+ // It is invalid to pass an empty vector of keyframes to create.
+ Vector<CCTransformKeyframe> transformKeyframes;
+ OwnPtr<CCKeyframedTransformAnimationCurve> transformCurve = CCKeyframedTransformAnimationCurve::create(transformKeyframes);
+ EXPECT_FALSE(transformCurve.get());
+
+ Vector<CCFloatKeyframe> floatKeyframes;
+ OwnPtr<CCKeyframedFloatAnimationCurve> floatCurve = CCKeyframedFloatAnimationCurve::create(floatKeyframes);
+ EXPECT_FALSE(floatCurve.get());
+
+ // It is invalid to pass a vector of unsorted keyframes to create;
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ transformKeyframes.append(CCTransformKeyframe(1, operations1));
+ transformKeyframes.append(CCTransformKeyframe(0, operations2));
+ transformCurve = CCKeyframedTransformAnimationCurve::create(transformKeyframes);
+ EXPECT_FALSE(transformCurve.get());
+
+ floatKeyframes.append(CCFloatKeyframe(1, 2));
+ floatKeyframes.append(CCFloatKeyframe(0, 4));
+ floatCurve = CCKeyframedFloatAnimationCurve::create(floatKeyframes);
+ EXPECT_FALSE(floatCurve.get());
+}
+
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp
index 3d50d06e6..e1aeccc53 100644
--- a/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp
@@ -24,92 +24,39 @@
#include "config.h"
+#include "CCAnimationTestCommon.h"
#include "cc/CCLayerAnimationControllerImpl.h"
-
-#include "TransformOperations.h"
#include "cc/CCAnimationCurve.h"
-
+#include "cc/CCAnimationEvents.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <wtf/Vector.h>
using namespace WebCore;
+using namespace WebKitTests;
namespace {
-class FakeControllerClient : public CCLayerAnimationControllerImplClient {
-public:
- FakeControllerClient() : m_opacity(0) { }
- virtual ~FakeControllerClient() { }
-
- virtual float opacity() const { return m_opacity; }
- virtual void setOpacity(float opacity) { m_opacity = opacity; }
- virtual const TransformationMatrix& transform() const { return m_transform; }
- virtual void setTransform(const TransformationMatrix& transform) { m_transform = transform; }
- virtual void animationControllerImplDidActivate(CCLayerAnimationControllerImpl* controller)
- {
- m_activeControllers.append(controller);
- }
-
- Vector<CCLayerAnimationControllerImpl*>& activeControllers() { return m_activeControllers; }
-
-private:
- float m_opacity;
- TransformationMatrix m_transform;
- Vector<CCLayerAnimationControllerImpl*> m_activeControllers;
-};
-
-class FakeTransformTransition : public CCTransformAnimationCurve {
-public:
- FakeTransformTransition(double duration) : m_duration(duration) { }
- virtual double duration() const { return m_duration; }
- virtual TransformOperations getValue(double time) const
- {
- return TransformOperations();
- }
-
-private:
- double m_duration;
-};
-
-class FakeFloatTransition : public CCFloatAnimationCurve {
-public:
- FakeFloatTransition(double duration, float from, float to)
- : m_duration(duration)
- , m_from(from)
- , m_to(to)
- {
- }
-
- virtual double duration() const { return m_duration; }
- virtual float getValue(double time) const
- {
- time /= m_duration;
- if (time >= 1)
- time = 1;
- return (1 - time) * m_from + time * m_to;
- }
-
-private:
- double m_duration;
- float m_from;
- float m_to;
-};
+PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int id, CCActiveAnimation::TargetProperty property)
+{
+ return CCActiveAnimation::create(curve, 0, id, property);
+}
// Tests that transitioning opacity from 0 to 1 works as expected.
TEST(CCLayerAnimationControllerImplTest, TrivialTransition)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
controller->add(toAdd.release());
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@@ -117,20 +64,21 @@ TEST(CCLayerAnimationControllerImplTest, TrivialTransition)
// Tests that two queued animations affecting the same property run in sequence.
TEST(CCLayerAnimationControllerImplTest, TrivialQueuing)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
- controller->animate(2);
+ controller->animate(2, *events);
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@@ -138,22 +86,23 @@ TEST(CCLayerAnimationControllerImplTest, TrivialQueuing)
// Tests interrupting a transition with another transition.
TEST(CCLayerAnimationControllerImplTest, Interrupt)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->animate(0);
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
toAdd->setRunState(CCActiveAnimation::WaitingForNextTick, 0);
controller->add(toAdd.release());
- controller->animate(0.5); // second anim starts NOW.
+ controller->animate(0.5, *events); // second anim starts NOW.
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
- controller->animate(1.5);
+ controller->animate(1.5, *events);
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@@ -161,23 +110,24 @@ TEST(CCLayerAnimationControllerImplTest, Interrupt)
// Tests scheduling two animations to run together when only one property is free.
TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWhenAPropertyIsBlocked)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity));
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_EQ(0, dummy.opacity());
EXPECT_TRUE(controller->hasActiveAnimation());
- controller->animate(1);
+ controller->animate(1, *events);
// Should not have started the float transition yet.
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
// The the float animation should have started at time 1 and should be done.
- controller->animate(2);
+ controller->animate(2, *events);
EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@@ -187,29 +137,30 @@ TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWhenAPropertyIsBlocked)
// for both to finish).
TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWithAnAnimWaiting)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
// Anims with id 1 should both start now.
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
// The opacity animation should have finished at time 1, but the group
// of animations with id 1 don't finish until time 2 because of the length
// of the transform animation.
- controller->animate(2);
+ controller->animate(2, *events);
// Should not have started the float transition yet.
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
// The the second opacity animation should start at time 2 and should be
// done by time 3
- controller->animate(3);
+ controller->animate(3, *events);
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@@ -217,22 +168,23 @@ TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWithAnAnimWaiting)
// Tests scheduling an animation to start in the future.
TEST(CCLayerAnimationControllerImplTest, ScheduleAnimation)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
toAdd->setStartTime(1);
controller->add(toAdd.release());
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(2);
+ controller->animate(2, *events);
EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@@ -240,28 +192,29 @@ TEST(CCLayerAnimationControllerImplTest, ScheduleAnimation)
// Tests scheduling an animation to start in the future that's interrupting a running animation.
TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimation)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0.5f, 0)), 2, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0.5f, 0)), 2, CCActiveAnimation::Opacity));
toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
toAdd->setStartTime(1);
controller->add(toAdd.release());
// First 2s opacity transition should start immediately.
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5);
+ controller->animate(0.5, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
- controller->animate(2);
+ controller->animate(2, *events);
EXPECT_EQ(0, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@@ -270,34 +223,35 @@ TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnim
// and there is yet another animation queued to start later.
TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0.5f, 0)), 2, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0.5f, 0)), 2, CCActiveAnimation::Opacity));
toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
toAdd->setStartTime(1);
controller->add(toAdd.release());
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 0.75f)), 3, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75f)), 3, CCActiveAnimation::Opacity));
// First 2s opacity transition should start immediately.
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5);
+ controller->animate(0.5, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
EXPECT_TRUE(controller->hasActiveAnimation());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
- controller->animate(3);
+ controller->animate(3, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(4);
+ controller->animate(4, *events);
EXPECT_EQ(0.75f, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@@ -305,64 +259,66 @@ TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnim
// Test that a looping animation loops and for the correct number of iterations.
TEST(CCLayerAnimationControllerImplTest, TrivialLooping)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
toAdd->setIterations(3);
controller->add(toAdd.release());
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1.25);
+ controller->animate(1.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1.75);
+ controller->animate(1.75, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(2.25);
+ controller->animate(2.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(2.75);
+ controller->animate(2.75, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(3);
+ controller->animate(3, *events);
EXPECT_FALSE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
// Just be extra sure.
- controller->animate(4);
+ controller->animate(4, *events);
EXPECT_EQ(1, dummy.opacity());
}
// Test that an infinitely looping animation does indeed go until aborted.
TEST(CCLayerAnimationControllerImplTest, InfiniteLooping)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
const int id = 1;
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
toAdd->setIterations(-1);
controller->add(toAdd.release());
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1.25);
+ controller->animate(1.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1.75);
+ controller->animate(1.75, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(1073741824.25);
+ controller->animate(1073741824.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1073741824.75);
+ controller->animate(1073741824.75, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
@@ -375,80 +331,66 @@ TEST(CCLayerAnimationControllerImplTest, InfiniteLooping)
// Test that pausing and resuming work as expected.
TEST(CCLayerAnimationControllerImplTest, PauseResume)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
const int id = 1;
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5);
+ controller->animate(0.5, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Paused, 0.5f);
- controller->animate(1024);
+ controller->animate(1024, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Running, 1024);
- controller->animate(1024.25);
+ controller->animate(1024.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(1024.5);
+ controller->animate(1024.5, *events);
EXPECT_FALSE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
}
TEST(CCLayerAnimationControllerImplTest, AbortAGroupedAnimation)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
const int id = 1;
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.75f)), 2, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.75f)), 2, CCActiveAnimation::Opacity));
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 1);
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
- controller->animate(2);
+ controller->animate(2, *events);
EXPECT_TRUE(!controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
}
-// Tests that adding an animation to the controller calls the appropriate callback on the controller client
-// (in this case, adding the controller to the list of active controller).
-TEST(CCLayerAnimationControllerImplTest, DidActivate)
-{
- FakeControllerClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- EXPECT_EQ(size_t(0), dummy.activeControllers().size());
-
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
-
- EXPECT_EQ(size_t(1), dummy.activeControllers().size());
- EXPECT_EQ(controller.get(), dummy.activeControllers()[0]);
-}
-
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
new file mode 100644
index 000000000..c4f103a3c
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "cc/CCLayerAnimationController.h"
+
+#include "CCAnimationTestCommon.h"
+#include "GraphicsLayer.h"
+#include "Length.h"
+#include "TranslateTransformOperation.h"
+#include "cc/CCActiveAnimation.h"
+#include "cc/CCAnimationCurve.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+using namespace WebKitTests;
+
+namespace {
+
+void expectTranslateX(double translateX, const TransformationMatrix& matrix)
+{
+ TransformationMatrix::DecomposedType decomposedType;
+ matrix.decompose(decomposedType);
+ EXPECT_FLOAT_EQ(translateX, decomposedType.translateX);
+}
+
+PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int id, CCActiveAnimation::TargetProperty property)
+{
+ return CCActiveAnimation::create(curve, 0, id, property);
+}
+
+TEST(CCLayerAnimationControllerTest, createOpacityAnimation)
+{
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ const double duration = 1;
+ WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
+ values.insert(new FloatAnimationValue(0, 0));
+ values.insert(new FloatAnimationValue(duration, 1));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+ controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0);
+
+ EXPECT_TRUE(controller->hasActiveAnimation());
+
+ CCActiveAnimation* activeAnimation = controller->getActiveAnimation(0, CCActiveAnimation::Opacity);
+ EXPECT_TRUE(activeAnimation);
+
+ EXPECT_EQ(1, activeAnimation->iterations());
+ EXPECT_EQ(CCActiveAnimation::Opacity, activeAnimation->targetProperty());
+
+ EXPECT_EQ(CCAnimationCurve::Float, activeAnimation->curve()->type());
+
+ const CCFloatAnimationCurve* curve = activeAnimation->curve()->toFloatAnimationCurve();
+ EXPECT_TRUE(curve);
+
+ EXPECT_EQ(0, curve->getValue(0));
+ EXPECT_EQ(1, curve->getValue(duration));
+}
+
+TEST(CCLayerAnimationControllerTest, createTransformAnimation)
+{
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ const double duration = 1;
+ WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform);
+
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ values.insert(new TransformAnimationValue(0, &operations1));
+
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ values.insert(new TransformAnimationValue(duration, &operations2));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+ controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0);
+
+ EXPECT_TRUE(controller->hasActiveAnimation());
+
+ CCActiveAnimation* activeAnimation = controller->getActiveAnimation(0, CCActiveAnimation::Transform);
+ EXPECT_TRUE(activeAnimation);
+
+ EXPECT_EQ(1, activeAnimation->iterations());
+ EXPECT_EQ(CCActiveAnimation::Transform, activeAnimation->targetProperty());
+
+ EXPECT_EQ(CCAnimationCurve::Transform, activeAnimation->curve()->type());
+
+ const CCTransformAnimationCurve* curve = activeAnimation->curve()->toTransformAnimationCurve();
+ EXPECT_TRUE(curve);
+
+ expectTranslateX(2, curve->getValue(0, boxSize));
+ expectTranslateX(4, curve->getValue(duration, boxSize));
+}
+
+TEST(CCLayerAnimationControllerTest, syncNewAnimation)
+{
+ FakeLayerAnimationControllerImplClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ addOpacityTransitionToController(*controller, 1, 0, 1);
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+}
+
+TEST(CCLayerAnimationControllerTest, syncAnimationProperties)
+{
+ FakeLayerAnimationControllerImplClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ addOpacityTransitionToController(*controller, 1, 0, 1);
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ // Push an animation property change to the impl thread (should not cause an animation to be added).
+ controller->pauseAnimation(0, 0);
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+}
+
+TEST(CCLayerAnimationControllerTest, syncAbortedAnimation)
+{
+ FakeLayerAnimationControllerImplClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ addOpacityTransitionToController(*controller, 1, 0, 1);
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ controller->removeAnimation(0);
+
+ // Abort an animation from the main thread.
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+}
+
+TEST(CCLayerAnimationControllerTest, syncCompletedAnimation)
+{
+ FakeLayerAnimationControllerImplClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ addOpacityTransitionToController(*controller, 1, 0, 1);
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ // Step through the animation until it is finished. At the next sync, the main thread's animation should be cleared.
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ controllerImpl->animate(0, *events);
+ controllerImpl->animate(2, *events);
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_TRUE(controller->hasActiveAnimation());
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
index 27728cbef..16a25e12e 100644
--- a/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
@@ -88,10 +88,13 @@ TEST(CCLayerImplTest, verifyLayerChangesAreTrackedProperly)
Color arbitraryColor = Color(10, 20, 30);
TransformationMatrix arbitraryTransform;
arbitraryTransform.scale3d(0.1, 0.2, 0.3);
+ FilterOperations arbitraryFilters;
+ arbitraryFilters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY));
// Changing these properties affects the entire subtree of layers.
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setAnchorPoint(arbitraryFloatPoint));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setAnchorPointZ(arbitraryNumber));
+ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setFilters(arbitraryFilters));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setMaskLayer(dummyMask));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setMasksToBounds(true));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setOpaque(true));
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
index b1fa72918..d2e1cfef9 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
@@ -28,7 +28,6 @@
#include "CCLayerTreeTestCommon.h"
#include "LayerChromium.h"
-#include "Region.h"
#include "TransformationMatrix.h"
#include <gmock/gmock.h>
@@ -36,12 +35,6 @@
using namespace WebCore;
-#define EXPECT_EQ_RECT(a, b) \
- EXPECT_EQ(a.x(), b.x()); \
- EXPECT_EQ(a.y(), b.y()); \
- EXPECT_EQ(a.width(), b.width()); \
- EXPECT_EQ(a.height(), b.height());
-
namespace {
void setLayerPropertiesForTesting(LayerChromium* layer, const TransformationMatrix& transform, const TransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D)
@@ -602,174 +595,4 @@ TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces)
// - test the other functions in CCLayerTreeHostCommon
//
-TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegion)
-{
- // This tests that the right transforms are being used.
- Region occluded;
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(layer);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
-
- layer->setOpaque(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- occluded = Region();
- layer->addSelfToOccludedScreenSpace(occluded);
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occluded.bounds());
- EXPECT_EQ(1u, occluded.rects().size());
-}
-
-TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithRotation)
-{
- // This tests that the right transforms are being used.
- Region occluded;
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(layer);
-
- TransformationMatrix layerTransform;
- layerTransform.translate(250, 250);
- layerTransform.rotate(90);
- layerTransform.translate(-250, -250);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
- setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
-
- layer->setOpaque(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- occluded = Region();
- layer->addSelfToOccludedScreenSpace(occluded);
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occluded.bounds());
- EXPECT_EQ(1u, occluded.rects().size());
-}
-
-TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithTranslation)
-{
- // This tests that the right transforms are being used.
- Region occluded;
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(layer);
-
- TransformationMatrix layerTransform;
- layerTransform.translate(20, 20);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
- setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
-
- layer->setOpaque(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- occluded = Region();
- layer->addSelfToOccludedScreenSpace(occluded);
- EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occluded.bounds());
- EXPECT_EQ(1u, occluded.rects().size());
-}
-
-TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithRotatedSurface)
-{
- // This tests that the right transforms are being used.
- Region occluded;
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromium> child = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(child);
- child->addChild(layer);
-
- TransformationMatrix childTransform;
- childTransform.translate(250, 250);
- childTransform.rotate(90);
- childTransform.translate(-250, -250);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
- setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), false);
-
- child->setMasksToBounds(true);
- layer->setOpaque(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too.
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- occluded = Region();
- layer->addSelfToOccludedScreenSpace(occluded);
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occluded.bounds());
- EXPECT_EQ(1u, occluded.rects().size());
-
- /* Justification for the above opaque rect from |layer|:
- 100
- +---------------------+ +---------------------+
- | | | |30 Visible region of |layer|: /////
- | 30 | rotate(90) | |
- | 30 + ---------------------------------+ | +---------------------------------+
- 100 | | 10 | | ==> | | |10 |
- | |10+---------------------------------+ | +---------------------------------+ |
- | | | | | | | | |///////////////| 420 | |
- | | | | | | | | |///////////////|60 | |
- | | | | | | | | |///////////////| | |
- +----|--|-------------+ | | +--|--|---------------+ | |
- | | | | 20|10| 70 | |
- | | | | | | | |
- | | | |500 | | | |
- | | | | | | | |
- | | | | | | | |
- | | | | | | | |
- | | | | | | |10|
- +--|-------------------------------+ | | +------------------------------|--+
- | | | 490 |
- +---------------------------------+ +---------------------------------+
- 500 500
- */
-}
-
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
index f59893de9..9ba1cf4ad 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
@@ -52,6 +52,7 @@ public:
virtual void onSwapBuffersCompleteOnImplThread() { }
virtual void setNeedsRedrawOnImplThread() { m_didRequestRedraw = true; }
virtual void setNeedsCommitOnImplThread() { m_didRequestCommit = true; }
+ virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>) { }
static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer)
{
@@ -67,7 +68,8 @@ public:
for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) {
if (scrollInfo.scrolls[i].layerId != id)
continue;
- ASSERT_EQ(scrollInfo.scrolls[i].scrollDelta, scrollDelta);
+ EXPECT_EQ(scrollDelta.width(), scrollInfo.scrolls[i].scrollDelta.width());
+ EXPECT_EQ(scrollDelta.height(), scrollInfo.scrolls[i].scrollDelta.height());
timesEncountered++;
}
@@ -89,6 +91,11 @@ public:
}
protected:
+ PassRefPtr<GraphicsContext3D> createContext()
+ {
+ return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3D()), GraphicsContext3D::RenderDirectlyToHostWindow);
+ }
+
DebugScopedSetImplThread m_alwaysImplThread;
OwnPtr<CCLayerTreeHostImpl> m_hostImpl;
bool m_didRequestCommit;
@@ -142,14 +149,14 @@ TEST_F(CCLayerTreeHostImplTest, scrollDeltaRepeatedScrolls)
scrollInfo = m_hostImpl->processScrollDeltas();
ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
EXPECT_EQ(root->sentScrollDelta(), scrollDelta);
- expectContains(*scrollInfo.get(), root->id(), scrollDelta);
+ expectContains(*scrollInfo, root->id(), scrollDelta);
IntSize scrollDelta2(-5, 27);
root->scrollBy(scrollDelta2);
scrollInfo = m_hostImpl->processScrollDeltas();
ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
- expectContains(*scrollInfo.get(), root->id(), scrollDelta + scrollDelta2);
+ expectContains(*scrollInfo, root->id(), scrollDelta + scrollDelta2);
root->scrollBy(IntSize());
scrollInfo = m_hostImpl->processScrollDeltas();
@@ -163,13 +170,28 @@ TEST_F(CCLayerTreeHostImplTest, scrollRootCallsCommitAndRedraw)
root->setScrollPosition(IntPoint(0, 0));
root->setMaxScrollPosition(IntSize(100, 100));
m_hostImpl->setRootLayer(root);
- EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0)), CCInputHandlerClient::ScrollStarted);
+ EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
m_hostImpl->scrollBy(IntSize(0, 10));
m_hostImpl->scrollEnd();
EXPECT_TRUE(m_didRequestRedraw);
EXPECT_TRUE(m_didRequestCommit);
}
+TEST_F(CCLayerTreeHostImplTest, wheelEventHandlers)
+{
+ RefPtr<CCLayerImpl> root = CCLayerImpl::create(0);
+ root->setScrollable(true);
+ root->setScrollPosition(IntPoint(0, 0));
+ root->setMaxScrollPosition(IntSize(100, 100));
+ m_hostImpl->setRootLayer(root);
+ root->setHaveWheelEventHandlers(true);
+ // With registered event handlers, wheel scrolls have to go to the main thread.
+ EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
+
+ // But gesture scrolls can still be handled.
+ EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
+}
+
TEST_F(CCLayerTreeHostImplTest, pinchGesture)
{
setupScrollAndContentsLayers(IntSize(100, 100));
@@ -184,6 +206,7 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture)
{
m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
scrollLayer->setPageScaleDelta(1);
+ scrollLayer->setScrollDelta(IntSize());
float pageScaleDelta = 2;
m_hostImpl->pinchGestureBegin();
@@ -200,6 +223,7 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture)
{
m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
scrollLayer->setPageScaleDelta(1);
+ scrollLayer->setScrollDelta(IntSize());
float pageScaleDelta = 10;
m_hostImpl->pinchGestureBegin();
@@ -214,6 +238,7 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture)
{
m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
scrollLayer->setPageScaleDelta(1);
+ scrollLayer->setScrollDelta(IntSize());
scrollLayer->setScrollPosition(IntPoint(50, 50));
float pageScaleDelta = 0.1;
@@ -225,7 +250,25 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture)
EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
// Pushed to (0,0) via clamping against contents layer size.
- expectContains(*scrollInfo.get(), scrollLayer->id(), IntSize(-50, -50));
+ expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
+ }
+
+ // Two-finger panning
+ {
+ m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
+ scrollLayer->setPageScaleDelta(1);
+ scrollLayer->setScrollDelta(IntSize());
+ scrollLayer->setScrollPosition(IntPoint(20, 20));
+
+ float pageScaleDelta = 1;
+ m_hostImpl->pinchGestureBegin();
+ m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(10, 10));
+ m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(20, 20));
+ m_hostImpl->pinchGestureEnd();
+
+ OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
+ EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
+ expectContains(*scrollInfo, scrollLayer->id(), IntSize(-10, -10));
}
}
@@ -255,7 +298,7 @@ TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation)
OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
EXPECT_EQ(scrollInfo->pageScaleDelta, 2);
- expectContains(*scrollInfo.get(), scrollLayer->id(), IntSize(-50, -50));
+ expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
}
// Anchor zoom-out
@@ -272,8 +315,107 @@ TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation)
OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
// Pushed to (0,0) via clamping against contents layer size.
- expectContains(*scrollInfo.get(), scrollLayer->id(), IntSize(-50, -50));
+ expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
+ }
+}
+
+class DidDrawCheckLayer : public CCLayerImpl {
+public:
+ static PassRefPtr<DidDrawCheckLayer> create(int id) { return adoptRef(new DidDrawCheckLayer(id)); }
+
+ virtual void didDraw()
+ {
+ m_didDrawCalled = true;
+ }
+
+ virtual void willDraw(LayerRendererChromium*)
+ {
+ m_willDrawCalled = true;
+ }
+
+ bool didDrawCalled() const { return m_didDrawCalled; }
+ bool willDrawCalled() const { return m_willDrawCalled; }
+
+private:
+ explicit DidDrawCheckLayer(int id)
+ : CCLayerImpl(id)
+ , m_didDrawCalled(false)
+ , m_willDrawCalled(false)
+ {
+ setAnchorPoint(FloatPoint(0, 0));
+ setBounds(IntSize(10, 10));
+ setDrawsContent(true);
}
+
+ bool m_didDrawCalled;
+ bool m_willDrawCalled;
+};
+
+TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer)
+{
+ RefPtr<GraphicsContext3D> context = createContext();
+ m_hostImpl->initializeLayerRenderer(context);
+
+ // Ensure visibleLayerRect for root layer is empty
+ m_hostImpl->setViewportSize(IntSize(0, 0));
+
+ RefPtr<DidDrawCheckLayer> root = DidDrawCheckLayer::create(0);
+ m_hostImpl->setRootLayer(root);
+
+ EXPECT_FALSE(root->willDrawCalled());
+ EXPECT_FALSE(root->didDrawCalled());
+
+ m_hostImpl->drawLayers();
+
+ EXPECT_FALSE(root->willDrawCalled());
+ EXPECT_FALSE(root->didDrawCalled());
+
+ EXPECT_TRUE(root->visibleLayerRect().isEmpty());
+
+ // Ensure visibleLayerRect for root layer is not empty
+ m_hostImpl->setViewportSize(IntSize(10, 10));
+
+ EXPECT_FALSE(root->willDrawCalled());
+ EXPECT_FALSE(root->didDrawCalled());
+
+ m_hostImpl->drawLayers();
+
+ EXPECT_TRUE(root->willDrawCalled());
+ EXPECT_TRUE(root->didDrawCalled());
+
+ EXPECT_FALSE(root->visibleLayerRect().isEmpty());
+}
+
+TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
+{
+ RefPtr<GraphicsContext3D> context = createContext();
+ m_hostImpl->initializeLayerRenderer(context);
+ m_hostImpl->setViewportSize(IntSize(10, 10));
+
+ RefPtr<DidDrawCheckLayer> root = DidDrawCheckLayer::create(0);
+ m_hostImpl->setRootLayer(root);
+
+ RefPtr<DidDrawCheckLayer> layer1 = DidDrawCheckLayer::create(1);
+ root->addChild(layer1);
+
+ RefPtr<DidDrawCheckLayer> layer2 = DidDrawCheckLayer::create(2);
+ layer1->addChild(layer2);
+
+ layer1->setOpacity(0.3);
+ layer1->setPreserves3D(false);
+
+ EXPECT_FALSE(root->didDrawCalled());
+ EXPECT_FALSE(layer1->didDrawCalled());
+ EXPECT_FALSE(layer2->didDrawCalled());
+
+ m_hostImpl->drawLayers();
+
+ EXPECT_TRUE(root->didDrawCalled());
+ EXPECT_TRUE(layer1->didDrawCalled());
+ EXPECT_TRUE(layer2->didDrawCalled());
+
+ EXPECT_NE(root->renderSurface(), layer1->renderSurface());
+ EXPECT_TRUE(!!layer1->renderSurface());
}
class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
@@ -347,8 +489,7 @@ private:
// https://bugs.webkit.org/show_bug.cgi?id=75783
TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
{
- GraphicsContext3D::Attributes attrs;
- RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new BlendStateTrackerContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+ RefPtr<GraphicsContext3D> context = createContext();
m_hostImpl->initializeLayerRenderer(context);
m_hostImpl->setViewportSize(IntSize(10, 10));
@@ -507,7 +648,6 @@ private:
class FakeDrawableCCLayerImpl: public CCLayerImpl {
public:
explicit FakeDrawableCCLayerImpl(int id) : CCLayerImpl(id) { }
- virtual void draw(LayerRendererChromium* renderer) { }
};
// Only reshape when we know we are going to draw. Otherwise, the reshape
@@ -515,9 +655,8 @@ public:
// viewport size is never set.
TEST_F(CCLayerTreeHostImplTest, reshapeNotCalledUntilDraw)
{
- GraphicsContext3D::Attributes attrs;
ReshapeTrackerContext* reshapeTracker = new ReshapeTrackerContext();
- RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(reshapeTracker), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+ RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(reshapeTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
m_hostImpl->initializeLayerRenderer(context);
m_hostImpl->setViewportSize(IntSize(10, 10));
@@ -559,9 +698,8 @@ private:
// where it should request to swap only the subBuffer that is damaged.
TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
{
- GraphicsContext3D::Attributes attrs;
PartialSwapTrackerContext* partialSwapTracker = new PartialSwapTrackerContext();
- RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+ RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
// This test creates its own CCLayerTreeHostImpl, so
// that we can force partial swap enabled.
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
index fc414f739..10cfa6931 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
@@ -26,14 +26,18 @@
#include "cc/CCLayerTreeHost.h"
+#include "CCAnimationTestCommon.h"
#include "CompositorFakeWebGraphicsContext3D.h"
#include "ContentLayerChromium.h"
+#include "FilterOperations.h"
#include "GraphicsContext3DPrivate.h"
#include "LayerChromium.h"
#include "Region.h"
#include "TextureManager.h"
#include "WebCompositor.h"
#include "WebKit.h"
+#include "cc/CCActiveAnimation.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHostImpl.h"
#include "cc/CCScopedThreadProxy.h"
@@ -49,6 +53,7 @@
using namespace WebCore;
using namespace WebKit;
+using namespace WebKitTests;
using namespace WTF;
namespace {
@@ -59,6 +64,7 @@ public:
virtual void beginCommitOnCCThread(CCLayerTreeHostImpl*) { }
virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*) { }
virtual void drawLayersOnCCThread(CCLayerTreeHostImpl*) { }
+ virtual void animateLayers(CCLayerTreeHostImpl*) { }
virtual void applyScrollAndScale(const IntSize&, float) { }
virtual void updateAnimations(double frameBeginTime) { }
virtual void layout() { }
@@ -90,6 +96,13 @@ public:
m_testHooks->drawLayersOnCCThread(this);
}
+protected:
+ virtual void animateLayers(double frameBeginTimeMs)
+ {
+ CCLayerTreeHostImpl::animateLayers(frameBeginTimeMs);
+ m_testHooks->animateLayers(this);
+ }
+
private:
MockLayerTreeHostImpl(TestHooks* testHooks, const CCSettings& settings, CCLayerTreeHostImplClient* client)
: CCLayerTreeHostImpl(settings, client)
@@ -105,7 +118,11 @@ class MockLayerTreeHost : public CCLayerTreeHost {
public:
static PassRefPtr<MockLayerTreeHost> create(TestHooks* testHooks, CCLayerTreeHostClient* client, PassRefPtr<LayerChromium> rootLayer, const CCSettings& settings)
{
- RefPtr<MockLayerTreeHost> layerTreeHost = adoptRef(new MockLayerTreeHost(testHooks, client, settings));
+ // For these tests, we will enable threaded animations.
+ CCSettings settingsCopy = settings;
+ settingsCopy.threadedAnimationEnabled = true;
+
+ RefPtr<MockLayerTreeHost> layerTreeHost = adoptRef(new MockLayerTreeHost(testHooks, client, settingsCopy));
bool success = layerTreeHost->initialize();
EXPECT_TRUE(success);
layerTreeHost->setRootLayer(rootLayer);
@@ -118,7 +135,10 @@ public:
virtual PassOwnPtr<CCLayerTreeHostImpl> createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
{
- return MockLayerTreeHostImpl::create(m_testHooks, settings(), client);
+ // For these tests, we will enable threaded animations.
+ CCSettings settings;
+ settings.threadedAnimationEnabled = true;
+ return MockLayerTreeHostImpl::create(m_testHooks, settings, client);
}
private:
@@ -207,10 +227,7 @@ public:
webAttrs.alpha = attrs.alpha;
OwnPtr<WebGraphicsContext3D> webContext = CompositorFakeWebGraphicsContext3DWithTextureTracking::create(webAttrs);
- return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(
- webContext.release(), attrs, 0,
- GraphicsContext3D::RenderDirectlyToHostWindow,
- GraphicsContext3DPrivate::ForUseOnAnotherThread);
+ return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow);
}
virtual void didCommitAndDrawFrame()
@@ -225,7 +242,9 @@ public:
{
}
- virtual void scheduleComposite() { }
+ virtual void scheduleComposite()
+ {
+ }
private:
explicit MockLayerTreeHostClient(TestHooks* testHooks) : m_testHooks(testHooks) { }
@@ -255,6 +274,11 @@ public:
callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsAnimate, this);
}
+ void postAddAnimationToMainThread()
+ {
+ callOnMainThread(CCLayerTreeHostTest::dispatchAddAnimation, this);
+ }
+
void postSetNeedsCommitToMainThread()
{
callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsCommit, this);
@@ -270,7 +294,6 @@ public:
callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsAnimateAndCommit, this);
}
-
void postSetVisibleToMainThread(bool visible)
{
callOnMainThread(visible ? CCLayerTreeHostTest::dispatchSetVisible : CCLayerTreeHostTest::dispatchSetInvisible, this);
@@ -313,6 +336,15 @@ protected:
test->m_layerTreeHost->setNeedsAnimate();
}
+ static void dispatchAddAnimation(void* self)
+ {
+ ASSERT(isMainThread());
+ CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
+ ASSERT(test);
+ if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
+ addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 1);
+ }
+
static void dispatchSetNeedsAnimateAndCommit(void* self)
{
ASSERT(isMainThread());
@@ -789,6 +821,47 @@ TEST_F(CCLayerTreeHostTestSetNeedsAnimateInsideAnimationCallback, runMultiThread
runTestThreaded();
}
+// Add a layer animation and confirm that CCLayerTreeHostImpl::animateLayers does get
+// called and continues to get called.
+class CCLayerTreeHostTestAddAnimation : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestAddAnimation()
+ : m_numAnimates(0)
+ , m_layerTreeHostImpl(0)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ postAddAnimationToMainThread();
+ }
+
+ virtual void animateLayers(CCLayerTreeHostImpl* layerTreeHostImpl)
+ {
+ if (!m_numAnimates) {
+ // The animation had zero duration so layerTreeHostImpl should no
+ // longer need to animate its layers.
+ EXPECT_FALSE(layerTreeHostImpl->needsAnimateLayers());
+ m_numAnimates++;
+ return;
+ }
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ int m_numAnimates;
+ CCLayerTreeHostImpl* m_layerTreeHostImpl;
+};
+
+TEST_F(CCLayerTreeHostTestAddAnimation, runMultiThread)
+{
+ runTestThreaded();
+}
+
class CCLayerTreeHostTestScrollSimple : public CCLayerTreeHostTestThreadOnly {
public:
CCLayerTreeHostTestScrollSimple()
@@ -938,6 +1011,75 @@ TEST_F(CCLayerTreeHostTestScrollMultipleRedraw, DISABLED_runMultiThread)
runTestThreaded();
}
+// Verifies that startPageScaleAnimation events propagate correctly from CCLayerTreeHost to
+// CCLayerTreeHostImpl in the MT compositor.
+class CCLayerTreeHostTestStartPageScaleAnimation : public CCLayerTreeHostTest {
+public:
+
+ CCLayerTreeHostTestStartPageScaleAnimation()
+ : m_animationRequested(false)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ m_layerTreeHost->rootLayer()->setScrollable(true);
+ m_layerTreeHost->rootLayer()->setScrollPosition(IntPoint());
+ postSetNeedsRedrawToMainThread();
+ }
+
+ static void requestStartPageScaleAnimation(void* self)
+ {
+ CCLayerTreeHostTestStartPageScaleAnimation* test = static_cast<CCLayerTreeHostTestStartPageScaleAnimation*>(self);
+ if (test->layerTreeHost())
+ test->layerTreeHost()->startPageScaleAnimation(IntSize(), false, 1.25, 0);
+ }
+
+ virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ impl->rootLayer()->setScrollable(true);
+ impl->rootLayer()->setScrollPosition(IntPoint());
+ impl->setPageScaleFactorAndLimits(impl->pageScale(), 0.5, 2);
+
+ // We request animation only once.
+ if (!m_animationRequested) {
+ callOnMainThread(CCLayerTreeHostTestStartPageScaleAnimation::requestStartPageScaleAnimation, this);
+ m_animationRequested = true;
+ }
+ }
+
+ virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale)
+ {
+ IntPoint position = m_layerTreeHost->rootLayer()->scrollPosition();
+ m_layerTreeHost->rootLayer()->setScrollPosition(position + scrollDelta);
+ m_layerTreeHost->setPageScaleFactorAndLimits(scale, 0.5, 2);
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ impl->processScrollDeltas();
+ // We get one commit before the first draw, and the animation doesn't happen until the second draw,
+ // so results available on the third commit.
+ if (impl->frameNumber() == 2) {
+ EXPECT_EQ(1.25, impl->pageScale());
+ endTest();
+ } else
+ postSetNeedsRedrawToMainThread();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ bool m_animationRequested;
+};
+
+TEST_F(CCLayerTreeHostTestStartPageScaleAnimation, runTest)
+{
+ runTest(true);
+}
+
class CCLayerTreeHostTestSetVisible : public CCLayerTreeHostTest {
public:
@@ -1596,6 +1738,94 @@ public:
SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusion)
+class CCLayerTreeHostTestLayerOcclusionWithFilters : public CCLayerTreeHostTest {
+public:
+ CCLayerTreeHostTestLayerOcclusionWithFilters() { }
+
+ virtual void beginTest()
+ {
+ RefPtr<TestLayerChromium> rootLayer = TestLayerChromium::create();
+ RefPtr<TestLayerChromium> child = TestLayerChromium::create();
+ RefPtr<TestLayerChromium> child2 = TestLayerChromium::create();
+ RefPtr<TestLayerChromium> grandChild = TestLayerChromium::create();
+ RefPtr<TestLayerChromium> mask = TestLayerChromium::create();
+
+ TransformationMatrix identityMatrix;
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ child->setMasksToBounds(true);
+
+ // If the child layer has a filter that changes alpha values, and is below child2, then child2 should contribute to occlusion on everything,
+ // and child shouldn't contribute to the rootLayer
+ setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
+
+ {
+ FilterOperations filters;
+ filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY));
+ child->setFilters(filters);
+ }
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), grandChild->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
+ EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
+
+ // If the child layer has a filter that moves pixels/changes alpha, and is below child2, then child should not inherit occlusion from outside its subtree,
+ // and should not contribute to the rootLayer
+ setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
+
+ {
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR));
+ child->setFilters(filters);
+ }
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
+ EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
+
+ // Kill the layerTreeHost immediately.
+ m_layerTreeHost->setRootLayer(0);
+ m_layerTreeHost.clear();
+
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusionWithFilters)
+
class CCLayerTreeHostTestManySurfaces : public CCLayerTreeHostTest {
public:
CCLayerTreeHostTestManySurfaces() { }
diff --git a/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp b/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp
new file mode 100644
index 000000000..678ec9645
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp
@@ -0,0 +1,1173 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "cc/CCOcclusionTracker.h"
+
+#include "FilterOperations.h"
+#include "LayerChromium.h"
+#include "Region.h"
+#include "TransformationMatrix.h"
+#include "cc/CCLayerTreeHostCommon.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+#define EXPECT_EQ_RECT(a, b) \
+ EXPECT_EQ(a.x(), b.x()); \
+ EXPECT_EQ(a.y(), b.y()); \
+ EXPECT_EQ(a.width(), b.width()); \
+ EXPECT_EQ(a.height(), b.height());
+
+namespace {
+
+void setLayerPropertiesForTesting(LayerChromium* layer, const TransformationMatrix& transform, const TransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool opaque)
+{
+ layer->setTransform(transform);
+ layer->setSublayerTransform(sublayerTransform);
+ layer->setAnchorPoint(anchor);
+ layer->setPosition(position);
+ layer->setBounds(bounds);
+ layer->setOpaque(opaque);
+}
+
+class LayerChromiumWithForcedDrawsContent : public LayerChromium {
+public:
+ LayerChromiumWithForcedDrawsContent()
+ : LayerChromium()
+ {
+ }
+
+ virtual bool drawsContent() const { return true; }
+};
+
+// A subclass to expose the total current occlusion.
+class TestCCOcclusionTracker : public CCOcclusionTracker {
+public:
+ Region occlusionInScreenSpace() const { return CCOcclusionTracker::m_stack.last().occlusionInScreen; }
+ Region occlusionInTargetSurface() const { return CCOcclusionTracker::m_stack.last().occlusionInTarget; }
+
+ void setOcclusionInScreenSpace(const Region& region) { CCOcclusionTracker::m_stack.last().occlusionInScreen = region; }
+ void setOcclusionInTargetSurface(const Region& region) { CCOcclusionTracker::m_stack.last().occlusionInTarget = region; }
+};
+
+TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegion)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(layer);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+ occlusion.markOccludedBehindLayer(layer.get());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 31, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 31, 70, 70)));
+}
+
+TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithRotation)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(layer);
+
+ TransformationMatrix layerTransform;
+ layerTransform.translate(250, 250);
+ layerTransform.rotate(90);
+ layerTransform.translate(-250, -250);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+ occlusion.markOccludedBehindLayer(layer.get());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 31, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 31, 70, 70)));
+}
+
+TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithTranslation)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(layer);
+
+ TransformationMatrix layerTransform;
+ layerTransform.translate(20, 20);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+ occlusion.markOccludedBehindLayer(layer.get());
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(50, 50, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(49, 50, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 49, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(51, 50, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 51, 50, 50)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(50, 50, 50, 50)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 50, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 49, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 49, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(51, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 49, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(100, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 50, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(51, 51, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 51, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(50, 100, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 51, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(49, 51, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 51, 50, 50)));
+}
+
+TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithRotatedSurface)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(child);
+ child->addChild(layer);
+
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+
+ child->setMasksToBounds(true);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(child->renderSurface());
+ occlusion.markOccludedBehindLayer(layer.get());
+
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 430, 61, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 71)));
+
+ occlusion.markOccludedBehindLayer(child.get());
+ occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
+
+
+ /* Justification for the above occlusion from |layer|:
+ 100
+ +---------------------+ +---------------------+
+ | | | |30 Visible region of |layer|: /////
+ | 30 | rotate(90) | |
+ | 30 + ---------------------------------+ | +---------------------------------+
+ 100 | | 10 | | ==> | | |10 |
+ | |10+---------------------------------+ | +---------------------------------+ |
+ | | | | | | | | |///////////////| 420 | |
+ | | | | | | | | |///////////////|60 | |
+ | | | | | | | | |///////////////| | |
+ +----|--|-------------+ | | +--|--|---------------+ | |
+ | | | | 20|10| 70 | |
+ | | | | | | | |
+ | | | |500 | | | |
+ | | | | | | | |
+ | | | | | | | |
+ | | | | | | | |
+ | | | | | | |10|
+ +--|-------------------------------+ | | +------------------------------|--+
+ | | | 490 |
+ +---------------------------------+ +---------------------------------+
+ 500 500
+ */
+}
+
+TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithSurfaceAlreadyOnStack)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(child);
+ child->addChild(layer);
+ parent->addChild(child2);
+
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+
+ // |child2| makes |parent|'s surface get considered by CCOcclusionTracker first, instead of |child|'s. This exercises different code in
+ // leaveToTargetRenderSurface, as the target surface has already been seen.
+ setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(60, 20), true);
+
+ child->setMasksToBounds(true);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+ occlusion.markOccludedBehindLayer(child2.get());
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ occlusion.enterTargetRenderSurface(child->renderSurface());
+ occlusion.markOccludedBehindLayer(layer.get());
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty());
+ // This is the little piece not occluded by child2
+ EXPECT_EQ_RECT(IntRect(9, 430, 1, 10), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70)));
+ // This extends past both sides of child2, so it will be the original rect.
+ EXPECT_EQ_RECT(IntRect(9, 430, 60, 80), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 80)));
+ // This extends past two adjacent sides of child2, and should included the unoccluded parts of each side.
+ // This also demonstrates that the rect can be arbitrary and does not get clipped to the layer's visibleLayerRect().
+ EXPECT_EQ_RECT(IntRect(-10, 430, 20, 70), occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 70)));
+ // This extends past three adjacent sides of child2, so it should contain the unoccluded parts of each side. The left
+ // and bottom edges are completely unoccluded for some row/column so we get back the original query rect.
+ EXPECT_EQ_RECT(IntRect(-10, 430, 60, 80), occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 80)));
+ EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70)));
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.surfaceUnoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)));
+
+ occlusion.markOccludedBehindLayer(child.get());
+ // |child2| should get merged with the surface we are leaving now
+ occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+
+ Vector<IntRect> screen = occlusion.occlusionInScreenSpace().rects();
+ Vector<IntRect> target = occlusion.occlusionInTargetSurface().rects();
+
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(90, 30, 10, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)));
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 60, 10)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 60, 10)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 60, 10)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 60, 10)));
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 31, 60, 10)));
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 60, 10)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 30, 1, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 60, 10)));
+ EXPECT_EQ_RECT(IntRect(30, 29, 60, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 60, 10)));
+ EXPECT_EQ_RECT(IntRect(90, 30, 1, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 60, 10)));
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 60, 10)).isEmpty());
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 40, 70, 60)));
+ // This rect is mostly occluded by |child2|.
+ EXPECT_EQ_RECT(IntRect(90, 39, 10, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 39, 70, 60)));
+ // This rect extends past top/right ends of |child2|.
+ EXPECT_EQ_RECT(IntRect(30, 29, 70, 11), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
+ // This rect extends past left/right ends of |child2|.
+ EXPECT_EQ_RECT(IntRect(20, 39, 80, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(20, 39, 80, 60)));
+ EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 40, 70, 60)));
+ EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 41, 70, 60)));
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)));
+
+
+ /* Justification for the above occlusion from |layer|:
+ 100
+ +---------------------+ +---------------------+
+ | | | |30 Visible region of |layer|: /////
+ | 30 | rotate(90) | 30 60 | |child2|: \\\\\
+ | 30 + ------------+--------------------+ | 30 +------------+--------------------+
+ 100 | | 10 | | | ==> | |\\\\\\\\\\\\| |10 |
+ | |10+----------|----------------------+ | +--|\\\\\\\\\\\\|-----------------+ |
+ | + ------------+ | | | | | +------------+//| 420 | |
+ | | | | | | | | |///////////////|60 | |
+ | | | | | | | | |///////////////| | |
+ +----|--|-------------+ | | +--|--|---------------+ | |
+ | | | | 20|10| 70 | |
+ | | | | | | | |
+ | | | |500 | | | |
+ | | | | | | | |
+ | | | | | | | |
+ | | | | | | | |
+ | | | | | | |10|
+ +--|-------------------------------+ | | +------------------------------|--+
+ | | | 490 |
+ +---------------------------------+ +---------------------------------+
+ 500 500
+ */
+}
+
+TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithRotatedOffAxisSurface)
+{
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(child);
+ child->addChild(layer);
+
+ // Now rotate the child a little more so it is not axis-aligned. The parent will no longer be occluded by |layer|, but
+ // the child's occlusion should be unchanged.
+
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(95);
+ childTransform.translate(-250, -250);
+
+ TransformationMatrix layerTransform;
+ layerTransform.translate(10, 10);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), true);
+
+ child->setMasksToBounds(true);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ IntRect clippedLayerInChild = layerTransform.mapRect(layer->visibleLayerRect());
+
+ occlusion.enterTargetRenderSurface(child->renderSurface());
+ occlusion.markOccludedBehindLayer(layer.get());
+
+ EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(clippedLayerInChild, occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child.get(), clippedLayerInChild));
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(-1, 0);
+ EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
+ EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(1, 0);
+ clippedLayerInChild.move(1, 0);
+ EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
+ EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(-1, 0);
+ clippedLayerInChild.move(0, -1);
+ EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
+ EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(0, 1);
+ clippedLayerInChild.move(0, 1);
+ EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
+ EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(0, -1);
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(0, 0, 500, 500), occlusion.surfaceUnoccludedContentRect(child.get(), IntRect(0, 0, 500, 500)));
+
+ occlusion.markOccludedBehindLayer(child.get());
+ occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(75, 55, 1, 1)));
+ EXPECT_EQ_RECT(IntRect(75, 55, 1, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(75, 55, 1, 1)));
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(0, 0, 100, 100)));
+}
+
+TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithMultipleOpaqueLayers)
+{
+ // This is similar to the previous test but now we make a few opaque layers inside of |child| so that the occluded parts of child are not a simple rect.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(child);
+ child->addChild(layer1);
+ child->addChild(layer2);
+
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(layer1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 440), true);
+ setLayerPropertiesForTesting(layer2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 450), IntSize(500, 60), true);
+
+ child->setMasksToBounds(true);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(child->renderSurface());
+ occlusion.markOccludedBehindLayer(layer2.get());
+ occlusion.markOccludedBehindLayer(layer1.get());
+
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(9, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70)));
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.surfaceUnoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)));
+
+ occlusion.markOccludedBehindLayer(child.get());
+ occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 40, 70, 60)));
+ EXPECT_EQ_RECT(IntRect(30, 39, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 39, 70, 60)));
+ EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 40, 70, 60)));
+ EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 41, 70, 60)));
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)));
+
+
+ /* Justification for the above occlusion from |layer1| and |layer2|:
+
+ +---------------------+
+ | |30 Visible region of |layer1|: /////
+ | | Visible region of |layer2|: \\\\\
+ | +---------------------------------+
+ | | |10 |
+ | +---------------+-----------------+ |
+ | | |\\\\\\\\\\\\|//| 420 | |
+ | | |\\\\\\\\\\\\|//|60 | |
+ | | |\\\\\\\\\\\\|//| | |
+ +--|--|------------|--+ | |
+ 20|10| 70 | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | |10|
+ | +------------|-----------------|--+
+ | | 490 |
+ +---------------+-----------------+
+ 60 440
+ */
+}
+
+TEST(CCOcclusionTrackerTest, surfaceOcclusionWithOverlappingSiblingSurfaces)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child1 = LayerChromium::create();
+ RefPtr<LayerChromium> child2 = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(child1);
+ parent->addChild(child2);
+ child1->addChild(layer1);
+ child2->addChild(layer2);
+
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(child1.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(layer1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(child2.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(20, 40), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(layer2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), true);
+
+ child1->setMasksToBounds(true);
+ child2->setMasksToBounds(true);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(child2->renderSurface());
+ occlusion.markOccludedBehindLayer(layer2.get());
+
+ EXPECT_EQ_RECT(IntRect(20, 40, 80, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 420, 60, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(0, 420, 60, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-1, 420, 60, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 419, 60, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 420, 61, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 420, 60, 81)));
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(0, 420, 60, 80), occlusion.surfaceUnoccludedContentRect(child2.get(), IntRect(0, 420, 60, 80)));
+
+ occlusion.markOccludedBehindLayer(child2.get());
+ occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ occlusion.enterTargetRenderSurface(child1->renderSurface());
+ occlusion.markOccludedBehindLayer(layer1.get());
+
+ EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(0, 430, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-1, 430, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 429, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 430, 71, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 430, 70, 71)));
+
+ // Surface is not occluded by things that draw into itself, but the |child1| surface should be occluded by the |child2| surface.
+ EXPECT_EQ_RECT(IntRect(0, 430, 10, 70), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(0, 430, 70, 70)));
+
+ occlusion.markOccludedBehindLayer(child1.get());
+ occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 30, 80, 70)));
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(20, 40, 80, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(19, 40, 80, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 39, 80, 60)));
+
+ // |child1| and |child2| both draw into parent so they should not occlude it.
+ EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(20, 30, 80, 70)));
+
+
+ /* Justification for the above occlusion:
+ 100
+ +---------------------+
+ | |
+ | 30 | child1
+ | 30+ ---------------------------------+
+ 100 | 40| | child2 |
+ |20+----------------------------------+ |
+ | | | | | |
+ | | | | | |
+ | | | | | |
+ +--|-|----------------+ | |
+ | | | | 500
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | +--------------------------------|-+
+ | |
+ +----------------------------------+
+ 500
+ */
+}
+
+TEST(CCOcclusionTrackerTest, surfaceOcclusionInScreenSpace)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child1 = LayerChromium::create();
+ RefPtr<LayerChromium> child2 = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(child1);
+ parent->addChild(child2);
+ child1->addChild(layer1);
+ child2->addChild(layer2);
+
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ // The owning layers have very different bounds from the surfaces that they own.
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(child1.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(layer1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-10, -10), IntSize(510, 510), true);
+ setLayerPropertiesForTesting(child2.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(20, 40), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(layer2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-10, -10), IntSize(510, 510), true);
+
+ // Make them both render surfaces
+ FilterOperations filters;
+ filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
+ child1->setFilters(filters);
+ child2->setFilters(filters);
+
+ child1->setMasksToBounds(false);
+ child2->setMasksToBounds(false);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(child2->renderSurface());
+ occlusion.markOccludedBehindLayer(layer2.get());
+
+ EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81)));
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.surfaceUnoccludedContentRect(child2.get(), IntRect(-10, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child2.get(), IntRect(30, 250, 1, 1)));
+
+ occlusion.markOccludedBehindLayer(child2.get());
+ occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ occlusion.enterTargetRenderSurface(child1->renderSurface());
+ occlusion.markOccludedBehindLayer(layer1.get());
+
+ EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(-10, 430, 80, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(-10, 430, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-11, 430, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 429, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 430, 81, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 430, 80, 71)));
+
+ // Surface is not occluded by things that draw into itself, but the |child1| surface should be occluded by the |child2| surface.
+ EXPECT_EQ_RECT(IntRect(-10, 430, 10, 80), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(-10, 430, 70, 80)));
+ EXPECT_TRUE(occlusion.surfaceOccluded(child1.get(), IntRect(0, 430, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(-1, 430, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(0, 429, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(1, 430, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(0, 431, 70, 80)));
+
+ occlusion.markOccludedBehindLayer(child1.get());
+ occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 20, 80, 80)));
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 20, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 20, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 19, 70, 80)));
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(20, 30, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(19, 30, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 29, 80, 70)));
+
+ // |child1| and |child2| both draw into parent so they should not occlude it.
+ EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(20, 20, 80, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(50, 50, 1, 1)));
+
+
+ /* Justification for the above occlusion:
+ 100
+ +---------------------+
+ | 20 | layer1
+ | 30+ ---------------------------------+
+ 100 | 30| | layer2 |
+ |20+----------------------------------+ |
+ | | | | | |
+ | | | | | |
+ | | | | | |
+ +--|-|----------------+ | |
+ | | | | 510
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | +--------------------------------|-+
+ | |
+ +----------------------------------+
+ 510
+ */
+}
+
+TEST(CCOcclusionTrackerTest, surfaceOcclusionInScreenSpaceDifferentTransforms)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child1 = LayerChromium::create();
+ RefPtr<LayerChromium> child2 = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(child1);
+ parent->addChild(child2);
+ child1->addChild(layer1);
+ child2->addChild(layer2);
+
+ TransformationMatrix child1Transform;
+ child1Transform.translate(250, 250);
+ child1Transform.rotate(-90);
+ child1Transform.translate(-250, -250);
+
+ TransformationMatrix child2Transform;
+ child2Transform.translate(250, 250);
+ child2Transform.rotate(90);
+ child2Transform.translate(-250, -250);
+
+ // The owning layers have very different bounds from the surfaces that they own.
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(child1.get(), child1Transform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 20), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(layer1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-10, -20), IntSize(510, 520), true);
+ setLayerPropertiesForTesting(child2.get(), child2Transform, identityMatrix, FloatPoint(0, 0), FloatPoint(20, 40), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(layer2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-10, -10), IntSize(510, 510), true);
+
+ // Make them both render surfaces
+ FilterOperations filters;
+ filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
+ child1->setFilters(filters);
+ child2->setFilters(filters);
+
+ child1->setMasksToBounds(false);
+ child2->setMasksToBounds(false);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ occlusion.enterTargetRenderSurface(child2->renderSurface());
+ occlusion.markOccludedBehindLayer(layer2.get());
+
+ EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81)));
+
+ // Surface is not occluded by things that draw into itself.
+ EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.surfaceUnoccludedContentRect(child2.get(), IntRect(-10, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child2.get(), IntRect(30, 250, 1, 1)));
+
+ occlusion.markOccludedBehindLayer(child2.get());
+ occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ occlusion.enterTargetRenderSurface(child1->renderSurface());
+ occlusion.markOccludedBehindLayer(layer1.get());
+
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(420, -20, 80, 90)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(419, -20, 80, 90)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(420, -21, 80, 90)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(420, -19, 80, 90)));
+ EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(421, -20, 80, 90)));
+
+ // Surface is not occluded by things that draw into itself, but the |child1| surface should be occluded by the |child2| surface.
+ EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(420, -20, 80, 90)));
+ EXPECT_EQ_RECT(IntRect(490, -10, 10, 80), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(420, -10, 80, 80)));
+ EXPECT_EQ_RECT(IntRect(420, -20, 70, 10), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(420, -20, 70, 90)));
+ EXPECT_TRUE(occlusion.surfaceOccluded(child1.get(), IntRect(420, -10, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(419, -10, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(420, -11, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(421, -10, 70, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(420, -9, 70, 80)));
+
+ occlusion.markOccludedBehindLayer(child1.get());
+ occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(10, 20, 90, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(9, 20, 90, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(10, 19, 90, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(11, 20, 90, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(10, 21, 90, 80)));
+
+ // |child1| and |child2| both draw into parent so they should not occlude it.
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(10, 20, 90, 80)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(10, 20, 1, 1)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(99, 20, 1, 1)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(10, 9, 1, 1)));
+ EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(99, 99, 1, 1)));
+
+
+ /* Justification for the above occlusion:
+ 100
+ +---------------------+
+ |20 | layer1
+ 10+----------------------------------+
+ 100 || 30 | layer2 |
+ |20+----------------------------------+
+ || | | | |
+ || | | | |
+ || | | | |
+ +|-|------------------+ | |
+ | | | | 510
+ | | 510 | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | 520 | |
+ +----------------------------------+ |
+ | |
+ +----------------------------------+
+ 510
+ */
+}
+
+TEST(CCOcclusionTrackerTest, occlusionInteractionWithFilters)
+{
+ // This tests that the right transforms are being used.
+ TestCCOcclusionTracker occlusion;
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> blurLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> opacityLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> opaqueLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(blurLayer);
+ parent->addChild(opacityLayer);
+ parent->addChild(opaqueLayer);
+
+ TransformationMatrix layerTransform;
+ layerTransform.translate(250, 250);
+ layerTransform.rotate(90);
+ layerTransform.translate(-250, -250);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(blurLayer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(opaqueLayer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(opacityLayer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+
+ {
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR));
+ blurLayer->setFilters(filters);
+ }
+
+ {
+ FilterOperations filters;
+ filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
+ opaqueLayer->setFilters(filters);
+ }
+
+ {
+ FilterOperations filters;
+ filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY));
+ opacityLayer->setFilters(filters);
+ }
+
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ // Opacity layer won't contribute to occlusion.
+ occlusion.enterTargetRenderSurface(opacityLayer->renderSurface());
+ occlusion.markOccludedBehindLayer(opacityLayer.get());
+ occlusion.finishedTargetRenderSurface(opacityLayer.get(), opacityLayer->renderSurface());
+
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+ EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+ // And has nothing to contribute to its parent surface.
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+ EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+ // Opaque layer will contribute to occlusion.
+ occlusion.enterTargetRenderSurface(opaqueLayer->renderSurface());
+ occlusion.markOccludedBehindLayer(opaqueLayer.get());
+ occlusion.finishedTargetRenderSurface(opaqueLayer.get(), opaqueLayer->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // And it gets translated to the parent surface.
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // The blur layer needs to throw away any occlusion from outside its subtree.
+ occlusion.enterTargetRenderSurface(blurLayer->renderSurface());
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+ EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+ // And it won't contribute to occlusion.
+ occlusion.markOccludedBehindLayer(blurLayer.get());
+ occlusion.finishedTargetRenderSurface(blurLayer.get(), blurLayer->renderSurface());
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+ EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+ // But the opaque layer's occlusion is preserved on the parent.
+ occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp b/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
index 299e5c7e5..d49703e14 100644
--- a/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
@@ -79,7 +79,7 @@ TEST(CCQuadCullerTest, verifyCullChildLinesUpTopLeft)
setQuads(rootState.get(), childState.get(), quadList);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 9u);
}
@@ -92,7 +92,7 @@ TEST(CCQuadCullerTest, verifyCullWhenChildOpacityNotOne)
setQuads(rootState.get(), childState.get(), quadList);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 13u);
}
@@ -105,7 +105,7 @@ TEST(CCQuadCullerTest, verifyCullWhenChildOpaqueFlagFalse)
setQuads(rootState.get(), childState.get(), quadList);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 13u);
}
@@ -120,7 +120,7 @@ TEST(CCQuadCullerTest, verifyCullCenterTileOnly)
setQuads(rootState.get(), childState.get(), quadList);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 12u);
IntRect quadVisibleRect1 = quadList[1].get()->quadVisibleRect();
@@ -158,7 +158,7 @@ TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize1)
quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100))));
EXPECT_EQ(quadList.size(), 2u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 2u);
}
@@ -181,7 +181,7 @@ TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize2)
quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100))));
EXPECT_EQ(quadList.size(), 2u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 2u);
}
@@ -196,7 +196,7 @@ TEST(CCQuadCullerTest, verifyCullChildLinesUpBottomRight)
setQuads(rootState.get(), childState.get(), quadList);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 9u);
}
@@ -212,7 +212,7 @@ TEST(CCQuadCullerTest, verifyCullSubRegion)
setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 12u);
}
@@ -228,7 +228,7 @@ TEST(CCQuadCullerTest, verifyCullSubRegion2)
setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 12u);
}
@@ -244,7 +244,7 @@ TEST(CCQuadCullerTest, verifyCullSubRegionCheckOvercull)
setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 13u);
}
@@ -260,7 +260,7 @@ TEST(CCQuadCullerTest, verifyNonAxisAlignedQuadsDontOcclude)
setQuads(rootState.get(), childState.get(), quadList);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 13u);
}
@@ -282,8 +282,61 @@ TEST(CCQuadCullerTest, verifyNonAxisAlignedQuadsSafelyCulled)
setQuads(rootState.get(), childState.get(), quadList);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList);
+ CCQuadCuller::cullOccludedQuads(quadList, false, IntRect());
EXPECT_EQ(quadList.size(), 12u);
}
+TEST(CCQuadCullerTest, veriftyCullOutsideScissorOverTile)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+
+ setQuads(rootState.get(), childState.get(), quadList);
+ EXPECT_EQ(quadList.size(), 13u);
+ CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(200, 100, 100, 100));
+ EXPECT_EQ(quadList.size(), 1u);
+}
+
+TEST(CCQuadCullerTest, veriftyCullOutsideScissorOverCulledTile)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+
+ setQuads(rootState.get(), childState.get(), quadList);
+ EXPECT_EQ(quadList.size(), 13u);
+ CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(100, 100, 100, 100));
+ EXPECT_EQ(quadList.size(), 1u);
+}
+
+TEST(CCQuadCullerTest, veriftyCullOutsideScissorOverPartialTiles)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+
+ setQuads(rootState.get(), childState.get(), quadList);
+ EXPECT_EQ(quadList.size(), 13u);
+ CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(50, 50, 200, 200));
+ EXPECT_EQ(quadList.size(), 9u);
+}
+
+TEST(CCQuadCullerTest, veriftyCullOutsideScissorOverNoTiles)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+
+ setQuads(rootState.get(), childState.get(), quadList);
+ EXPECT_EQ(quadList.size(), 13u);
+ CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(500, 500, 100, 100));
+ EXPECT_EQ(quadList.size(), 0u);
+}
+
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
index 4b3dd27d3..ec0ce0c6a 100644
--- a/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
@@ -79,8 +79,8 @@ protected:
{
GraphicsContext3D::Attributes attrs;
- RefPtr<GraphicsContext3D> mainContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
- RefPtr<GraphicsContext3D> implContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+ RefPtr<GraphicsContext3D> mainContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), GraphicsContext3D::RenderDirectlyToHostWindow);
+ RefPtr<GraphicsContext3D> implContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), GraphicsContext3D::RenderDirectlyToHostWindow);
MockCanvasContext& mainMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(mainContext.get()));
MockCanvasContext& implMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(implContext.get()));
diff --git a/Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h b/Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h
index 1f0897341..937b62d4c 100644
--- a/Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h
+++ b/Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h
@@ -37,10 +37,7 @@ static PassRefPtr<GraphicsContext3D> createCompositorMockGraphicsContext3D(Graph
webAttrs.alpha = attrs.alpha;
OwnPtr<WebKit::WebGraphicsContext3D> webContext = WebKit::CompositorFakeWebGraphicsContext3D::create(webAttrs);
- return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(
- webContext.release(), attrs, 0,
- GraphicsContext3D::RenderDirectlyToHostWindow,
- GraphicsContext3DPrivate::ForUseOnAnotherThread);
+ return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow);
}
}
diff --git a/Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp b/Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp
index 2b76b80ad..71cb8bab1 100644
--- a/Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp
+++ b/Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp
@@ -52,7 +52,7 @@ private:
TEST(FakeGraphicsContext3DTest, CanOverrideManually)
{
GraphicsContext3D::Attributes attrs;
- RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FrameCountingContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+ RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FrameCountingContext()), GraphicsContext3D::RenderDirectlyToHostWindow);
FrameCountingContext& mockContext = *static_cast<FrameCountingContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get()));
for (int i = 0; i < 10; i++) {
@@ -73,7 +73,7 @@ public:
TEST(FakeGraphicsContext3DTest, CanUseGMock)
{
GraphicsContext3D::Attributes attrs;
- RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new GMockContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+ RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new GMockContext()), GraphicsContext3D::RenderDirectlyToHostWindow);
GMockContext& mockContext = *static_cast<GMockContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get()));
EXPECT_CALL(mockContext, getError())
@@ -104,7 +104,7 @@ private:
TEST(FakeGraphicsContext3DTest, ContextForThisThreadShouldNotMakeCurrent)
{
GraphicsContext3D::Attributes attrs;
- RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ContextThatCountsMakeCurrents()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+ RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ContextThatCountsMakeCurrents()), GraphicsContext3D::RenderDirectlyToHostWindow);
EXPECT_TRUE(context);
ContextThatCountsMakeCurrents& mockContext = *static_cast<ContextThatCountsMakeCurrents*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get()));
EXPECT_EQ(0, mockContext.makeCurrentCount());
@@ -113,7 +113,7 @@ TEST(FakeGraphicsContext3DTest, ContextForThisThreadShouldNotMakeCurrent)
TEST(FakeGraphicsContext3DTest, ContextForAnotherThreadShouldNotMakeCurrent)
{
GraphicsContext3D::Attributes attrs;
- RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ContextThatCountsMakeCurrents()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnAnotherThread);
+ RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ContextThatCountsMakeCurrents()), GraphicsContext3D::RenderDirectlyToHostWindow);
EXPECT_TRUE(context);
ContextThatCountsMakeCurrents& mockContext = *static_cast<ContextThatCountsMakeCurrents*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get()));
EXPECT_EQ(0, mockContext.makeCurrentCount());
diff --git a/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h b/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h
index cf0651b77..ae27da730 100644
--- a/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h
+++ b/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h
@@ -65,6 +65,8 @@ public:
virtual void setVisibilityCHROMIUM(bool visible) { }
+ virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { }
+
virtual WebString getRequestableExtensionsCHROMIUM() { return WebString(); }
virtual void requestExtensionCHROMIUM(const char*) { }
diff --git a/Source/WebKit/chromium/tests/LayerChromiumTest.cpp b/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
index 43083a1d7..2e9ca9661 100644
--- a/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
@@ -515,6 +515,7 @@ TEST_F(LayerChromiumTest, checkPropertyChangeCausesCorrectBehavior)
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setReplicaLayer(dummyLayer.get()));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setSublayerTransform(TransformationMatrix(0, 0, 0, 0, 0, 0)));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setScrollable(true));
+ EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setHaveWheelEventHandlers(true));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setScrollPosition(IntPoint(10, 10)));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setTransform(TransformationMatrix(0, 0, 0, 0, 0, 0)));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setDoubleSided(false));
@@ -539,10 +540,21 @@ public:
return true;
}
+ virtual void setNeedsDisplayRect(const FloatRect& dirtyRect)
+ {
+ m_lastNeedsDisplayRect = dirtyRect;
+ LayerChromium::setNeedsDisplayRect(dirtyRect);
+ }
+
void resetNeedsDisplay()
{
m_needsDisplay = false;
}
+
+ const FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; }
+
+private:
+ FloatRect m_lastNeedsDisplayRect;
};
TEST_F(LayerChromiumTest, checkContentsScaleChangeTriggersNeedsDisplay)
@@ -558,6 +570,7 @@ TEST_F(LayerChromiumTest, checkContentsScaleChangeTriggersNeedsDisplay)
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setContentsScale(testLayer->contentsScale() + 1.f));
EXPECT_TRUE(testLayer->needsDisplay());
+ EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 320, 240), testLayer->lastNeedsDisplayRect());
}
class FakeCCLayerTreeHost : public CCLayerTreeHost {
diff --git a/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp b/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp
index 924b42d28..d097c499a 100644
--- a/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp
+++ b/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp
@@ -163,6 +163,30 @@ TEST(PlatformContextSkiaTest, trackOpaqueClipTest)
context.clearRect(FloatRect(10, 10, 90, 90));
EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+ // The transform and the clip need to interact correctly (transform first)
+ context.save();
+ context.translate(10, 10);
+ context.clip(FloatRect(20, 20, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 10, 10), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+
+ // The transform and the clip need to interact correctly (clip first)
+ context.save();
+ context.clip(FloatRect(20, 20, 10, 10));
+ context.translate(10, 10);
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+
Path path;
path.moveTo(FloatPoint(0, 0));
path.addLineTo(FloatPoint(100, 0));
diff --git a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
index fcd3878a6..e03559046 100644
--- a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
@@ -162,6 +162,14 @@ public:
return TiledLayerChromium::skipsDraw();
}
+ virtual void setNeedsDisplayRect(const FloatRect& rect)
+ {
+ m_lastNeedsDisplayRect = rect;
+ TiledLayerChromium::setNeedsDisplayRect(rect);
+ }
+
+ const FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; }
+
FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); }
virtual TextureManager* textureManager() const { return m_textureManager; }
@@ -181,6 +189,7 @@ private:
RefPtr<FakeLayerTextureUpdater> m_fakeTextureUpdater;
TextureManager* m_textureManager;
+ FloatRect m_lastNeedsDisplayRect;
};
class FakeTiledLayerWithScaledBounds : public FakeTiledLayerChromium {
@@ -434,6 +443,57 @@ TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled)
EXPECT_FLOAT_RECT_EQ(FloatRect(45, 80, 15, 8), layer->updateRect());
}
+TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ RefPtr<FakeCCTiledLayerImpl> layerImpl = adoptRef(new FakeCCTiledLayerImpl(0));
+
+ FakeTextureAllocator textureAllocator;
+ CCTextureUpdater updater(&textureAllocator);
+
+ // Create a layer with one tile.
+ layer->setBounds(IntSize(100, 100));
+
+ // Invalidate the entire layer.
+ layer->setNeedsDisplay();
+ EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
+
+ // Push the tiles to the impl side and check that there is exactly one.
+ layer->prepareToUpdate(IntRect(0, 0, 100, 100));
+ layer->updateCompositorResources(0, updater);
+ layer->pushPropertiesTo(layerImpl.get());
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
+ EXPECT_FALSE(layerImpl->hasTileAt(1, 0));
+ EXPECT_FALSE(layerImpl->hasTileAt(1, 1));
+
+ // Change the contents scale and verify that the content rectangle requiring painting
+ // is not scaled.
+ layer->setContentsScale(2);
+ EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
+
+ // The impl side should get 2x2 tiles now.
+ layer->prepareToUpdate(IntRect(0, 0, 200, 200));
+ layer->updateCompositorResources(0, updater);
+ layer->pushPropertiesTo(layerImpl.get());
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
+ EXPECT_TRUE(layerImpl->hasTileAt(1, 0));
+ EXPECT_TRUE(layerImpl->hasTileAt(1, 1));
+
+ // Invalidate the entire layer again, but do not paint. All tiles should be gone now from the
+ // impl side.
+ layer->setNeedsDisplay();
+ layer->updateCompositorResources(0, updater);
+ layer->pushPropertiesTo(layerImpl.get());
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
+ EXPECT_FALSE(layerImpl->hasTileAt(1, 0));
+ EXPECT_FALSE(layerImpl->hasTileAt(1, 1));
+}
+
TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
{
// Initialize without threading support.
@@ -524,7 +584,7 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion)
occluded = Region();
layer->addSelfToOccludedScreenSpace(occluded);
EXPECT_EQ_RECT(IntRect(), occluded.bounds());
- EXPECT_EQ(1u, occluded.rects().size());
+ EXPECT_EQ(0u, occluded.rects().size());
// If the layer paints opaque content, then the occluded region should match the visible opaque content.
IntRect opaquePaintRect = IntRect(10, 10, 90, 190);
@@ -546,6 +606,28 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion)
EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds());
EXPECT_EQ(1u, occluded.rects().size());
+ // If we repaint a non-opaque part of the tile, then it shouldn't lose its opaque-ness. And other tiles should
+ // not be affected.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+ layer->invalidateRect(IntRect(0, 0, 1, 1));
+ layer->prepareToUpdate(contentBounds);
+
+ occluded = Region();
+ layer->addSelfToOccludedScreenSpace(occluded);
+ EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds());
+ EXPECT_EQ(1u, occluded.rects().size());
+
+ // If we repaint an opaque part of the tile, then it should lose its opaque-ness. But other tiles should still
+ // not be affected.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+ layer->invalidateRect(IntRect(10, 10, 1, 1));
+ layer->prepareToUpdate(contentBounds);
+
+ occluded = Region();
+ layer->addSelfToOccludedScreenSpace(occluded);
+ EXPECT_EQ_RECT(intersection(IntRect(10, 100, 90, 100), visibleBounds), occluded.bounds());
+ EXPECT_EQ(1u, occluded.rects().size());
+
// If the layer is transformed then the resulting occluded area needs to be transformed to its target space.
TransformationMatrix transform;
transform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
@@ -556,6 +638,8 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion)
screenSpaceTransform *= transform;
screenSpaceTransform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
layer->setScreenSpaceTransform(screenSpaceTransform);
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
+ layer->invalidateRect(opaquePaintRect);
layer->prepareToUpdate(contentBounds);
occluded = Region();
diff --git a/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp b/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
index 1557a7d93..4724b4a43 100644
--- a/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
+++ b/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
@@ -26,13 +26,16 @@
#include "TreeSynchronizer.h"
+#include "CCAnimationTestCommon.h"
#include "LayerChromium.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCProxy.h"
#include "cc/CCSingleThreadProxy.h"
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace WebKitTests;
namespace {
@@ -91,6 +94,30 @@ private:
Vector<int>* m_ccLayerDestructionList;
};
+class FakeLayerAnimationController : public CCLayerAnimationController {
+public:
+ static PassOwnPtr<FakeLayerAnimationController> create()
+ {
+ return adoptPtr(new FakeLayerAnimationController);
+ }
+
+ bool synchronizedAnimations() const { return m_synchronizedAnimations; }
+
+private:
+ FakeLayerAnimationController()
+ : m_synchronizedAnimations(false)
+ {
+ }
+
+ virtual void synchronizeAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+ {
+ CCLayerAnimationController::synchronizeAnimations(controllerImpl);
+ m_synchronizedAnimations = true;
+ }
+
+ bool m_synchronizedAnimations;
+};
+
void expectTreesAreIdentical(LayerChromium* layer, CCLayerImpl* ccLayer)
{
ASSERT_TRUE(layer);
@@ -307,5 +334,19 @@ TEST(TreeSynchronizerTest, syncMaskReplicaAndReplicaMaskLayers)
expectTreesAreIdentical(layerTreeRoot.get(), ccLayerTreeRoot.get());
}
+TEST(TreeSynchronizerTest, synchronizeAnimations)
+{
+ DebugScopedSetImplThread impl;
+ RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create();
+
+ layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create());
+
+ EXPECT_FALSE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());
+
+ RefPtr<CCLayerImpl> ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), 0);
+ ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), ccLayerTreeRoot.get());
+
+ EXPECT_TRUE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());
+}
} // namespace
diff --git a/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp b/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp
index ad5810524..459255e02 100644
--- a/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp
@@ -67,14 +67,13 @@ public:
private:
virtual void setNeedsRedraw() OVERRIDE { }
- virtual ScrollStatus scrollBegin(const WebCore::IntPoint&) OVERRIDE
+ virtual ScrollStatus scrollBegin(const WebCore::IntPoint&, WebCore::CCInputHandlerClient::ScrollInputType) OVERRIDE
{
return m_scrollStatus;
}
virtual void scrollBy(const WebCore::IntSize&) OVERRIDE { }
virtual void scrollEnd() OVERRIDE { }
- virtual bool haveWheelEventHandlers() OVERRIDE { return false; }
virtual void pinchGestureBegin() OVERRIDE
{
m_pinchStarted = true;
diff --git a/Source/WebKit/chromium/tests/WebFrameTest.cpp b/Source/WebKit/chromium/tests/WebFrameTest.cpp
index b59001860..f61e98648 100644
--- a/Source/WebKit/chromium/tests/WebFrameTest.cpp
+++ b/Source/WebKit/chromium/tests/WebFrameTest.cpp
@@ -151,6 +151,78 @@ TEST_F(WebFrameTest, ChromePageNoJavascript)
EXPECT_EQ(std::string::npos, content.find("Clobbered"));
}
+#if ENABLE(GESTURE_EVENTS)
+TEST_F(WebFrameTest, DivAutoZoomParamsTest)
+{
+ registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
+
+ WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html", true));
+ int pageWidth = 640;
+ int pageHeight = 480;
+ int divPosX = 200;
+ int divPosY = 200;
+ int divWidth = 200;
+ int divHeight = 150;
+ WebRect doubleTapPoint(250, 250, 0, 0);
+ webViewImpl->resize(WebSize(pageWidth, pageHeight));
+ float scale;
+ WebPoint scroll;
+
+ // Test for Doubletap scaling
+
+ // Tests for zooming in and out without clamping.
+ // Set device scale and scale limits so we dont get clamped.
+ webViewImpl->setDeviceScaleFactor(4);
+ webViewImpl->setPageScaleFactorLimits(0, 4 / webViewImpl->deviceScaleFactor());
+
+ // Test zooming into div.
+ webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll);
+ float scaledDivWidth = divWidth * scale;
+ float scaledDivHeight = divHeight * scale;
+ int hScroll = ((divPosX * scale) - ((pageWidth - scaledDivWidth) / 2)) / scale;
+ int vScroll = ((divPosY * scale) - ((pageHeight - scaledDivHeight) / 2)) / scale;
+ EXPECT_NEAR(pageWidth / divWidth, scale, 0.1);
+ EXPECT_EQ(hScroll, scroll.x);
+ EXPECT_EQ(vScroll, scroll.y);
+
+ // Test zoom out to overview scale.
+ webViewImpl->applyScrollAndScale(WebCore::IntSize(scroll.x, scroll.y), scale / webViewImpl->pageScaleFactor());
+ webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll);
+ EXPECT_FLOAT_EQ(1, scale);
+ EXPECT_EQ(WebPoint(0, 0), scroll);
+
+ // Tests for clamped scaling.
+ // Test clamp to device scale:
+ webViewImpl->applyScrollAndScale(WebCore::IntSize(scroll.x, scroll.y), scale / webViewImpl->pageScaleFactor());
+ webViewImpl->setDeviceScaleFactor(2.5);
+ webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll);
+ EXPECT_FLOAT_EQ(2.5, scale);
+
+ // Test clamp to minimum scale:
+ webViewImpl->applyScrollAndScale(WebCore::IntSize(scroll.x, scroll.y), scale / webViewImpl->pageScaleFactor());
+ webViewImpl->setPageScaleFactorLimits(1.5 / webViewImpl->deviceScaleFactor(), 4 / webViewImpl->deviceScaleFactor());
+ webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll);
+ EXPECT_FLOAT_EQ(1.5, scale);
+ EXPECT_EQ(WebPoint(0, 0), scroll);
+
+ // Test clamp to maximum scale:
+ webViewImpl->applyScrollAndScale(WebCore::IntSize(scroll.x, scroll.y), scale / webViewImpl->pageScaleFactor());
+ webViewImpl->setDeviceScaleFactor(4);
+ webViewImpl->setPageScaleFactorLimits(0, 3 / webViewImpl->deviceScaleFactor());
+ webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll);
+ EXPECT_FLOAT_EQ(3, scale);
+
+
+ // Test for Non-doubletap scaling
+ webViewImpl->setPageScaleFactor(1, WebPoint(0, 0));
+ webViewImpl->setDeviceScaleFactor(4);
+ webViewImpl->setPageScaleFactorLimits(0, 4 / webViewImpl->deviceScaleFactor());
+ // Test zooming into div.
+ webViewImpl->computeScaleAndScrollForHitRect(WebRect(250, 250, 10, 10), WebViewImpl::FindInPage, scale, scroll);
+ EXPECT_NEAR(pageWidth / divWidth, scale, 0.1);
+}
+#endif
+
class TestReloadDoesntRedirectWebFrameClient : public WebFrameClient {
public:
virtual WebNavigationPolicy decidePolicyForNavigation(
diff --git a/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp b/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp
new file mode 100644
index 000000000..423a5969f
--- /dev/null
+++ b/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "WebSocketDeflater.h"
+
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace {
+
+TEST(WebSocketDeflaterTest, TestCompressHello)
+{
+ // Test the first example on section 4.3 of the specification.
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
+ ASSERT_TRUE(deflater->initialize());
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
+ ASSERT_TRUE(inflater->initialize());
+ const char* inputData = "Hello";
+ const size_t inputLength = strlen(inputData);
+
+ ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
+ ASSERT_TRUE(deflater->finish());
+ const char expectedFirst[] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00};
+ EXPECT_EQ(sizeof(expectedFirst), deflater->size());
+ EXPECT_EQ(0, memcmp(expectedFirst, deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputLength, inflater->size());
+ EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
+
+ deflater->reset();
+ inflater->reset();
+
+ ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
+ ASSERT_TRUE(deflater->finish());
+ const char expectedSecond[] = {0xf2, 0x00, 0x11, 0x00, 0x00};
+ EXPECT_EQ(sizeof(expectedSecond), deflater->size());
+ EXPECT_EQ(0, memcmp(expectedSecond, deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputLength, inflater->size());
+ EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
+}
+
+TEST(WebSocketDeflaterTest, TestMultipleAddBytesCalls)
+{
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
+ ASSERT_TRUE(deflater->initialize());
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
+ ASSERT_TRUE(inflater->initialize());
+ Vector<char> inputData(32);
+ inputData.fill('a');
+
+ for (size_t i = 0; i < inputData.size(); ++i)
+ ASSERT_TRUE(deflater->addBytes(inputData.data() + i, 1));
+ ASSERT_TRUE(deflater->finish());
+ for (size_t i = 0; i < deflater->size(); ++i)
+ ASSERT_TRUE(inflater->addBytes(deflater->data() + i, 1));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputData.size(), inflater->size());
+ EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
+}
+
+TEST(WebSocketDeflaterTest, TestNoContextTakeOver)
+{
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15, WebSocketDeflater::DoNotTakeOverContext);
+ ASSERT_TRUE(deflater->initialize());
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
+ ASSERT_TRUE(inflater->initialize());
+ const char expected[] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00};
+ const char* inputData = "Hello";
+ const size_t inputLength = strlen(inputData);
+
+ // If we don't take over context, the second result should be the identical
+ // with the first one.
+ for (size_t i = 0; i < 2; ++i) {
+ ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
+ ASSERT_TRUE(deflater->finish());
+ EXPECT_EQ(sizeof(expected), deflater->size());
+ EXPECT_EQ(0, memcmp(expected, deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputLength, inflater->size());
+ EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size()));
+ deflater->reset();
+ inflater->reset();
+ }
+}
+
+TEST(WebSocketDeflaterTest, TestWindowBits)
+{
+ Vector<char> inputData(1024 + 64 * 2);
+ inputData.fill('a');
+ // Modify the head and tail of the inputData so that back-reference
+ // can be used if the window size is sufficiently-large.
+ for (size_t j = 0; j < 64; ++j) {
+ inputData[j] = 'b';
+ inputData[inputData.size() - j - 1] = 'b';
+ }
+
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(8);
+ ASSERT_TRUE(deflater->initialize());
+ ASSERT_TRUE(deflater->addBytes(inputData.data(), inputData.size()));
+ ASSERT_TRUE(deflater->finish());
+
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create(8);
+ ASSERT_TRUE(inflater->initialize());
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputData.size(), inflater->size());
+ EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
+}
+
+TEST(WebSocketDeflaterTest, TestLargeData)
+{
+ OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15);
+ ASSERT_TRUE(deflater->initialize());
+ OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
+ ASSERT_TRUE(inflater->initialize());
+ Vector<char> inputData(16 * 1024 * 1024);
+ inputData.fill('a');
+
+ ASSERT_TRUE(deflater->addBytes(inputData.data(), inputData.size()));
+ ASSERT_TRUE(deflater->finish());
+ ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
+ ASSERT_TRUE(inflater->finish());
+ EXPECT_EQ(inputData.size(), inflater->size());
+ EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size()));
+}
+
+}
diff --git a/Source/WebKit/chromium/tests/WebSocketExtensionDispatcherTest.cpp b/Source/WebKit/chromium/tests/WebSocketExtensionDispatcherTest.cpp
new file mode 100644
index 000000000..358983b83
--- /dev/null
+++ b/Source/WebKit/chromium/tests/WebSocketExtensionDispatcherTest.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "WebSocketExtensionDispatcher.h"
+
+#include "WebSocketExtensionProcessor.h"
+
+#include <gtest/gtest.h>
+#include <wtf/text/StringHash.h>
+
+using namespace WebCore;
+
+namespace {
+
+class WebSocketExtensionDispatcherTest;
+
+class MockWebSocketExtensionProcessor : public WebSocketExtensionProcessor {
+public:
+ MockWebSocketExtensionProcessor(const String& name, WebSocketExtensionDispatcherTest* test)
+ : WebSocketExtensionProcessor(name)
+ , m_test(test)
+ {
+ }
+ virtual String handshakeString() OVERRIDE { return extensionToken(); }
+ virtual bool processResponse(const HashMap<String, String>&) OVERRIDE;
+
+private:
+ WebSocketExtensionDispatcherTest* m_test;
+};
+
+class WebSocketExtensionDispatcherTest : public testing::Test {
+public:
+ WebSocketExtensionDispatcherTest() { }
+
+ void SetUp() { }
+
+ void TearDown() { }
+
+ void addMockProcessor(const String& extensionToken)
+ {
+ m_extensions.addProcessor(adoptPtr(new MockWebSocketExtensionProcessor(extensionToken, this)));
+
+ }
+
+ void appendResult(const String& extensionToken, const HashMap<String, String>& parameters)
+ {
+ m_parsedExtensionTokens.append(extensionToken);
+ m_parsedParameters.append(parameters);
+ }
+
+protected:
+ WebSocketExtensionDispatcher m_extensions;
+ Vector<String> m_parsedExtensionTokens;
+ Vector<HashMap<String, String> > m_parsedParameters;
+};
+
+bool MockWebSocketExtensionProcessor::processResponse(const HashMap<String, String>& parameters)
+{
+ m_test->appendResult(extensionToken(), parameters);
+ return true;
+}
+
+TEST_F(WebSocketExtensionDispatcherTest, TestSingle)
+{
+ addMockProcessor("deflate-frame");
+ EXPECT_TRUE(m_extensions.processHeaderValue("deflate-frame"));
+ EXPECT_EQ(1UL, m_parsedExtensionTokens.size());
+ EXPECT_EQ("deflate-frame", m_parsedExtensionTokens[0]);
+ EXPECT_EQ("deflate-frame", m_extensions.acceptedExtensions());
+ EXPECT_EQ(0, m_parsedParameters[0].size());
+}
+
+TEST_F(WebSocketExtensionDispatcherTest, TestParameters)
+{
+ addMockProcessor("mux");
+ EXPECT_TRUE(m_extensions.processHeaderValue("mux; max-channels=4; flow-control "));
+ EXPECT_EQ(1UL, m_parsedExtensionTokens.size());
+ EXPECT_EQ("mux", m_parsedExtensionTokens[0]);
+ EXPECT_EQ(2, m_parsedParameters[0].size());
+ HashMap<String, String>::iterator parameter = m_parsedParameters[0].find("max-channels");
+ EXPECT_TRUE(parameter != m_parsedParameters[0].end());
+ EXPECT_EQ("4", parameter->second);
+ parameter = m_parsedParameters[0].find("flow-control");
+ EXPECT_TRUE(parameter != m_parsedParameters[0].end());
+ EXPECT_TRUE(parameter->second.isNull());
+}
+
+TEST_F(WebSocketExtensionDispatcherTest, TestMultiple)
+{
+ struct {
+ String token;
+ HashMap<String, String> parameters;
+ } expected[2];
+ expected[0].token = "mux";
+ expected[0].parameters.add("max-channels", "4");
+ expected[0].parameters.add("flow-control", String());
+ expected[1].token = "deflate-frame";
+
+ addMockProcessor("mux");
+ addMockProcessor("deflate-frame");
+ EXPECT_TRUE(m_extensions.processHeaderValue("mux ; max-channels =4;flow-control, deflate-frame "));
+ EXPECT_TRUE(m_extensions.acceptedExtensions().find("mux") != notFound);
+ EXPECT_TRUE(m_extensions.acceptedExtensions().find("deflate-frame") != notFound);
+ for (size_t i = 0; i < sizeof(expected) / sizeof(expected[0]); ++i) {
+ EXPECT_EQ(expected[i].token, m_parsedExtensionTokens[i]);
+ const HashMap<String, String>& expectedParameters = expected[i].parameters;
+ const HashMap<String, String>& parsedParameters = m_parsedParameters[i];
+ EXPECT_EQ(expected[i].parameters.size(), m_parsedParameters[i].size());
+ for (HashMap<String, String>::const_iterator iterator = expectedParameters.begin(); iterator != expectedParameters.end(); ++iterator) {
+ HashMap<String, String>::const_iterator parsed = parsedParameters.find(iterator->first);
+ EXPECT_TRUE(parsed != parsedParameters.end());
+ if (iterator->second.isNull())
+ EXPECT_TRUE(parsed->second.isNull());
+ else
+ EXPECT_EQ(iterator->second, parsed->second);
+ }
+ }
+}
+
+TEST_F(WebSocketExtensionDispatcherTest, TestQuotedString)
+{
+ addMockProcessor("x-foo");
+ EXPECT_TRUE(m_extensions.processHeaderValue("x-foo; param1=\"quoted string\"; param2=\"\\\"quoted\\\" string\\\\\""));
+ EXPECT_EQ(2, m_parsedParameters[0].size());
+ EXPECT_EQ("quoted string", m_parsedParameters[0].get("param1"));
+ EXPECT_EQ("\"quoted\" string\\", m_parsedParameters[0].get("param2"));
+}
+
+TEST_F(WebSocketExtensionDispatcherTest, TestInvalid)
+{
+ const char* inputs[] = {
+ "\"x-foo\"",
+ "x-baz",
+ "x-foo\\",
+ "x-(foo)",
+ "x-foo; ",
+ "x-foo; bar=",
+ "x-foo; bar=x y",
+ "x-foo; bar=\"mismatch quote",
+ "x-foo; bar=\"\\\"",
+ "x-foo; \"bar\"=baz",
+ "x-foo x-bar",
+ "x-foo, x-baz"
+ "x-foo, ",
+ };
+ for (size_t i = 0; i < sizeof(inputs) / sizeof(inputs[0]); ++i) {
+ m_extensions.reset();
+ addMockProcessor("x-foo");
+ addMockProcessor("x-bar");
+ EXPECT_FALSE(m_extensions.processHeaderValue(inputs[i]));
+ EXPECT_TRUE(m_extensions.acceptedExtensions().isNull());
+ }
+}
+
+}
diff --git a/Source/WebKit/chromium/tests/WebURLResponseTest.cpp b/Source/WebKit/chromium/tests/WebURLResponseTest.cpp
new file mode 100644
index 000000000..112ed8601
--- /dev/null
+++ b/Source/WebKit/chromium/tests/WebURLResponseTest.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "platform/WebURLResponse.h"
+
+#include <gtest/gtest.h>
+
+using namespace WebKit;
+
+namespace {
+
+class TestExtraData : public WebURLResponse::ExtraData {
+public:
+ explicit TestExtraData(bool* alive)
+ : m_alive(alive)
+ {
+ *alive = true;
+ }
+
+ virtual ~TestExtraData() { *m_alive = false; }
+
+private:
+ bool* m_alive;
+};
+
+TEST(WebURLResponseTest, ExtraData)
+{
+ bool alive = false;
+ {
+ WebURLResponse urlResponse;
+ TestExtraData* extraData = new TestExtraData(&alive);
+ EXPECT_TRUE(alive);
+
+ urlResponse.initialize();
+ urlResponse.setExtraData(extraData);
+ EXPECT_EQ(extraData, urlResponse.extraData());
+ {
+ WebURLResponse otherUrlResponse = urlResponse;
+ EXPECT_TRUE(alive);
+ EXPECT_EQ(extraData, otherUrlResponse.extraData());
+ EXPECT_EQ(extraData, urlResponse.extraData());
+ }
+ EXPECT_TRUE(alive);
+ EXPECT_EQ(extraData, urlResponse.extraData());
+ }
+ EXPECT_FALSE(alive);
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/data/get_scale_for_auto_zoom_into_div_test.html b/Source/WebKit/chromium/tests/data/get_scale_for_auto_zoom_into_div_test.html
new file mode 100644
index 000000000..1817dc47d
--- /dev/null
+++ b/Source/WebKit/chromium/tests/data/get_scale_for_auto_zoom_into_div_test.html
@@ -0,0 +1,13 @@
+<html>
+ <body>
+ <div style="background-color: green; position: absolute; left: 0px; top: 0px; width: 640px; height: 480px">
+ <p>Top Div</p>
+ <div style="background-color: white; position: absolute; left: 200px; top: 200px; width: 200px; height: 150px">
+ <p id="innerDiv">Div to zoom to</p>
+ <div style="background-color: red; position: fixed; left: 220px; top: 350px; width: 160px; height: 40px">
+ <p id="innerInnerDiv">Div NOT to zoom to</p>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>