summaryrefslogtreecommitdiff
path: root/Source/WebKit/chromium/tests
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
commitcd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch)
tree8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Source/WebKit/chromium/tests
parentd11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff)
downloadqtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Source/WebKit/chromium/tests')
-rw-r--r--Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp64
-rw-r--r--Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp167
-rw-r--r--Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp2
-rw-r--r--Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp454
-rw-r--r--Source/WebKit/chromium/tests/CCLayerImplTest.cpp1
-rw-r--r--Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp2
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTestCommon.cpp63
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTestCommon.h40
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp243
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp218
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp451
-rw-r--r--Source/WebKit/chromium/tests/CCQuadCullerTest.cpp156
-rw-r--r--Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp27
-rw-r--r--Source/WebKit/chromium/tests/CCSchedulerTest.cpp15
-rw-r--r--Source/WebKit/chromium/tests/CCSchedulerTestCommon.h1
-rw-r--r--Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp81
-rw-r--r--Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp137
-rw-r--r--Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp4
-rw-r--r--Source/WebKit/chromium/tests/ClipboardChromiumTest.cpp89
-rw-r--r--Source/WebKit/chromium/tests/CompositorFakeWebGraphicsContext3D.h2
-rwxr-xr-xSource/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h54
-rw-r--r--Source/WebKit/chromium/tests/FrameTestHelpers.cpp5
-rw-r--r--Source/WebKit/chromium/tests/IDBBindingUtilitiesTest.cpp2
-rw-r--r--Source/WebKit/chromium/tests/ImageLayerChromiumTest.cpp4
-rw-r--r--Source/WebKit/chromium/tests/KURLTest.cpp2
-rw-r--r--Source/WebKit/chromium/tests/LayerChromiumTest.cpp165
-rw-r--r--Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp198
-rw-r--r--Source/WebKit/chromium/tests/PaintAggregatorTest.cpp493
-rw-r--r--Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp464
-rw-r--r--Source/WebKit/chromium/tests/TextureManagerTest.cpp65
-rw-r--r--Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp311
-rw-r--r--Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp32
-rw-r--r--Source/WebKit/chromium/tests/WebFrameTest.cpp52
-rw-r--r--Source/WebKit/chromium/tests/data/find.html6
34 files changed, 3772 insertions, 298 deletions
diff --git a/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp b/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp
index 62d12b400..677865ac0 100644
--- a/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp
+++ b/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp
@@ -40,6 +40,7 @@
#include "platform/WebURLLoaderClient.h"
#include "platform/WebURLRequest.h"
#include "platform/WebURLResponse.h"
+#include <wtf/text/WTFString.h>
#include <googleurl/src/gurl.h>
#include <gtest/gtest.h>
@@ -137,6 +138,7 @@ public:
void didReceiveResponse(WebURLLoader* loader, const WebURLResponse& response)
{
m_didReceiveResponse = true;
+ m_actualResponse = WebURLResponse(response);
EXPECT_EQ(m_expectedLoader, loader);
EXPECT_EQ(m_expectedResponse.url(), response.url());
EXPECT_EQ(m_expectedResponse.httpStatusCode(), response.httpStatusCode());
@@ -220,12 +222,49 @@ public:
EXPECT_FALSE(m_didReceiveResponse);
}
+ bool CheckAccessControlHeaders(const char* headerName, bool exposed)
+ {
+ std::string id("http://www.other.com/CheckAccessControlExposeHeaders_");
+ id.append(headerName);
+ if (exposed)
+ id.append("-Exposed");
+ id.append(".html");
+
+ GURL url = GURL(id);
+ WebURLRequest request;
+ request.initialize();
+ request.setURL(url);
+
+ WebString headerNameString(WebString::fromUTF8(headerName));
+ m_expectedResponse = WebURLResponse();
+ m_expectedResponse.initialize();
+ m_expectedResponse.setMIMEType("text/html");
+ m_expectedResponse.addHTTPHeaderField("Access-Control-Allow-Origin", "*");
+ if (exposed)
+ m_expectedResponse.addHTTPHeaderField("access-control-expose-header", headerNameString);
+ m_expectedResponse.addHTTPHeaderField(headerNameString, "foo");
+ webkit_support::RegisterMockedURL(url, m_expectedResponse, m_frameFilePath);
+
+ WebURLLoaderOptions options;
+ options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
+ m_expectedLoader = createAssociatedURLLoader(options);
+ EXPECT_TRUE(m_expectedLoader);
+ m_expectedLoader->loadAsynchronously(request, this);
+ serveRequests();
+ EXPECT_TRUE(m_didReceiveResponse);
+ EXPECT_TRUE(m_didReceiveData);
+ EXPECT_TRUE(m_didFinishLoading);
+
+ return !m_actualResponse.httpHeaderField(headerNameString).isEmpty();
+ }
+
protected:
WebString m_frameFilePath;
TestWebFrameClient m_webFrameClient;
WebView* m_webView;
WebURLLoader* m_expectedLoader;
+ WebURLResponse m_actualResponse;
WebURLResponse m_expectedResponse;
WebURLRequest m_expectedNewRequest;
WebURLResponse m_expectedRedirectResponse;
@@ -487,4 +526,29 @@ TEST_F(AssociatedURLLoaderTest, UntrustedCheckHeaders)
CheckHeaderFails("foo", "bar\x0d\x0ax-csrf-token:\x20test1234");
}
+// Test that the loader filters response headers according to the CORS standard.
+TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderWhitelisting)
+{
+ // Test that whitelisted headers are returned without exposing them.
+ EXPECT_TRUE(CheckAccessControlHeaders("cache-control", false));
+ EXPECT_TRUE(CheckAccessControlHeaders("content-language", false));
+ EXPECT_TRUE(CheckAccessControlHeaders("content-type", false));
+ EXPECT_TRUE(CheckAccessControlHeaders("expires", false));
+ EXPECT_TRUE(CheckAccessControlHeaders("last-modified", false));
+ EXPECT_TRUE(CheckAccessControlHeaders("pragma", false));
+
+ // Test that non-whitelisted headers aren't returned.
+ EXPECT_FALSE(CheckAccessControlHeaders("non-whitelisted", false));
+
+ // Test that Set-Cookie headers aren't returned.
+ EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", false));
+ EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie2", false));
+
+ // Test that exposed headers that aren't whitelisted are returned.
+ EXPECT_TRUE(CheckAccessControlHeaders("non-whitelisted", true));
+
+ // Test that Set-Cookie headers aren't returned, even if exposed.
+ EXPECT_FALSE(CheckAccessControlHeaders("Set-Cookie", true));
+}
+
}
diff --git a/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp b/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp
new file mode 100644
index 000000000..3e93d95de
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp
@@ -0,0 +1,167 @@
+/*
+ * 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/CCActiveAnimation.h"
+
+#include "cc/CCAnimationCurve.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FakeFloatAnimation : public CCFloatAnimationCurve {
+public:
+ virtual double duration() const { return 1; }
+ virtual float getValue(double now) const { return 0; }
+};
+
+PassOwnPtr<CCActiveAnimation> createActiveAnimation(int iterations)
+{
+ OwnPtr<CCActiveAnimation> toReturn(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimation), 1, CCActiveAnimation::Opacity));
+ toReturn->setIterations(iterations);
+ return toReturn.release();
+}
+
+TEST(CCActiveAnimationTest, TrimTimeZeroIterations)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(0));
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(-1));
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(0));
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(1));
+}
+
+TEST(CCActiveAnimationTest, TrimTimeOneIteration)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(-1));
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(0));
+ EXPECT_EQ(1, anim->trimTimeToCurrentIteration(1));
+ EXPECT_EQ(1, anim->trimTimeToCurrentIteration(2));
+}
+
+TEST(CCActiveAnimationTest, TrimTimeInfiniteIterations)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(-1));
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(0));
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(0.5));
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(1));
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(1.5));
+}
+
+TEST(CCActiveAnimationTest, TrimTimeStartTime)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
+ anim->setStartTime(4);
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(0));
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(4));
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(4.5));
+ EXPECT_EQ(1, anim->trimTimeToCurrentIteration(5));
+ EXPECT_EQ(1, anim->trimTimeToCurrentIteration(6));
+}
+
+TEST(CCActiveAnimationTest, TrimTimePauseResume)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
+ anim->setRunState(CCActiveAnimation::Running, 0);
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(0));
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(0.5));
+ anim->setRunState(CCActiveAnimation::Paused, 0.5);
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(1024));
+ anim->setRunState(CCActiveAnimation::Running, 1024);
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(1024));
+ EXPECT_EQ(1, anim->trimTimeToCurrentIteration(1024.5));
+}
+
+TEST(CCActiveAnimationTest, IsFinishedAtZeroIterations)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(0));
+ anim->setRunState(CCActiveAnimation::Running, 0);
+ EXPECT_FALSE(anim->isFinishedAt(-1));
+ EXPECT_TRUE(anim->isFinishedAt(0));
+ EXPECT_TRUE(anim->isFinishedAt(1));
+}
+
+TEST(CCActiveAnimationTest, IsFinishedAtOneIteration)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
+ anim->setRunState(CCActiveAnimation::Running, 0);
+ EXPECT_FALSE(anim->isFinishedAt(-1));
+ EXPECT_FALSE(anim->isFinishedAt(0));
+ EXPECT_TRUE(anim->isFinishedAt(1));
+ EXPECT_TRUE(anim->isFinishedAt(2));
+}
+
+TEST(CCActiveAnimationTest, IsFinishedAtInfiniteIterations)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(-1));
+ anim->setRunState(CCActiveAnimation::Running, 0);
+ EXPECT_FALSE(anim->isFinishedAt(0));
+ EXPECT_FALSE(anim->isFinishedAt(0.5));
+ EXPECT_FALSE(anim->isFinishedAt(1));
+ EXPECT_FALSE(anim->isFinishedAt(1.5));
+}
+
+TEST(CCActiveAnimationTest, IsFinishedAtNotRunning)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(0));
+ anim->setRunState(CCActiveAnimation::Running, 0);
+ EXPECT_TRUE(anim->isFinishedAt(0));
+ anim->setRunState(CCActiveAnimation::Paused, 0);
+ EXPECT_FALSE(anim->isFinishedAt(0));
+ anim->setRunState(CCActiveAnimation::WaitingForNextTick, 0);
+ EXPECT_FALSE(anim->isFinishedAt(0));
+ anim->setRunState(CCActiveAnimation::WaitingForTargetAvailability, 0);
+ EXPECT_FALSE(anim->isFinishedAt(0));
+ anim->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ EXPECT_FALSE(anim->isFinishedAt(0));
+ anim->setRunState(CCActiveAnimation::Finished, 0);
+ EXPECT_TRUE(anim->isFinishedAt(0));
+ anim->setRunState(CCActiveAnimation::Aborted, 0);
+ EXPECT_TRUE(anim->isFinishedAt(0));
+}
+
+TEST(CCActiveAnimationTest, IsFinished)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
+ anim->setRunState(CCActiveAnimation::Running, 0);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::Paused, 0);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::WaitingForNextTick, 0);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::WaitingForTargetAvailability, 0);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::Finished, 0);
+ EXPECT_TRUE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::Aborted, 0);
+ EXPECT_TRUE(anim->isFinished());
+}
+
+} // namespace WebCore
diff --git a/Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp b/Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp
index 41c9d119e..867d56ea8 100644
--- a/Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp
+++ b/Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp
@@ -46,10 +46,12 @@ TEST(CCDelayBasedTimeSourceTest, TaskPostedAndTickCalled)
timer->setMonotonicallyIncreasingTimeMs(0);
timer->setActive(true);
+ EXPECT_TRUE(timer->active());
EXPECT_TRUE(thread.hasPendingTask());
timer->setMonotonicallyIncreasingTimeMs(16);
thread.runPendingTask();
+ EXPECT_TRUE(timer->active());
EXPECT_TRUE(client.tickCalled());
}
diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp
new file mode 100644
index 000000000..3d50d06e6
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp
@@ -0,0 +1,454 @@
+/*
+ * 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/CCLayerAnimationControllerImpl.h"
+
+#include "TransformOperations.h"
+#include "cc/CCAnimationCurve.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+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;
+};
+
+// Tests that transitioning opacity from 0 to 1 works as expected.
+TEST(CCLayerAnimationControllerImplTest, TrivialTransition)
+{
+ FakeControllerClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controller(
+ CCLayerAnimationControllerImpl::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ controller->add(toAdd.release());
+ controller->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1);
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests that two queued animations affecting the same property run in sequence.
+TEST(CCLayerAnimationControllerImplTest, TrivialQueuing)
+{
+ FakeControllerClient 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->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(2);
+ EXPECT_EQ(0.5f, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests interrupting a transition with another transition.
+TEST(CCLayerAnimationControllerImplTest, Interrupt)
+{
+ FakeControllerClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controller(
+ CCLayerAnimationControllerImpl::create(&dummy));
+ controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+
+ OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(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.
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(1.5);
+ EXPECT_EQ(0.5f, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling two animations to run together when only one property is free.
+TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWhenAPropertyIsBlocked)
+{
+ FakeControllerClient 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->animate(0);
+ EXPECT_EQ(0, dummy.opacity());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ controller->animate(1);
+ // 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);
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling two animations to run together with different lengths and another
+// animation queued to start when the shorter animation finishes (should wait
+// for both to finish).
+TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWithAnAnimWaiting)
+{
+ FakeControllerClient 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));
+
+ // Anims with id 1 should both start now.
+ controller->animate(0);
+ 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);
+ // 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);
+ EXPECT_EQ(0.5f, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling an animation to start in the future.
+TEST(CCLayerAnimationControllerImplTest, ScheduleAnimation)
+{
+ FakeControllerClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controller(
+ CCLayerAnimationControllerImpl::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
+
+ controller->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(2);
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling an animation to start in the future that's interrupting a running animation.
+TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimation)
+{
+ FakeControllerClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controller(
+ CCLayerAnimationControllerImpl::create(&dummy));
+
+ controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(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);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25f, dummy.opacity());
+ controller->animate(1);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5f, dummy.opacity());
+ controller->animate(2);
+ EXPECT_EQ(0, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling an animation to start in the future that interrupts a running animation
+// and there is yet another animation queued to start later.
+TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue)
+{
+ FakeControllerClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controller(
+ CCLayerAnimationControllerImpl::create(&dummy));
+
+ controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(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));
+
+ // First 2s opacity transition should start immediately.
+ controller->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25f, dummy.opacity());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ controller->animate(1);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5f, dummy.opacity());
+ controller->animate(3);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(4);
+ EXPECT_EQ(0.75f, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Test that a looping animation loops and for the correct number of iterations.
+TEST(CCLayerAnimationControllerImplTest, TrivialLooping)
+{
+ FakeControllerClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controller(
+ CCLayerAnimationControllerImpl::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setIterations(3);
+ controller->add(toAdd.release());
+
+ controller->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1.25);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25f, dummy.opacity());
+ controller->animate(1.75);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75f, dummy.opacity());
+ controller->animate(2.25);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25f, dummy.opacity());
+ controller->animate(2.75);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75f, dummy.opacity());
+ controller->animate(3);
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+
+ // Just be extra sure.
+ controller->animate(4);
+ EXPECT_EQ(1, dummy.opacity());
+}
+
+// Test that an infinitely looping animation does indeed go until aborted.
+TEST(CCLayerAnimationControllerImplTest, InfiniteLooping)
+{
+ FakeControllerClient 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));
+ toAdd->setIterations(-1);
+ controller->add(toAdd.release());
+
+ controller->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1.25);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25f, dummy.opacity());
+ controller->animate(1.75);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75f, dummy.opacity());
+
+ controller->animate(1073741824.25);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25f, dummy.opacity());
+ controller->animate(1073741824.75);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75f, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 0.75f);
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75f, dummy.opacity());
+}
+
+// Test that pausing and resuming work as expected.
+TEST(CCLayerAnimationControllerImplTest, PauseResume)
+{
+ FakeControllerClient 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->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5);
+ 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);
+ 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);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75f, dummy.opacity());
+ controller->animate(1024.5);
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+}
+
+TEST(CCLayerAnimationControllerImplTest, AbortAGroupedAnimation)
+{
+ FakeControllerClient 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->animate(0);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1);
+ 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);
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(2);
+ 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/CCLayerImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
index 165405d49..27728cbef 100644
--- a/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
@@ -112,6 +112,7 @@ TEST(CCLayerImplTest, verifyLayerChangesAreTrackedProperly)
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setDebugBorderWidth(arbitraryNumber));
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setDrawsContent(true));
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setBackgroundColor(Color::gray));
+ EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setBackgroundCoversViewport(true));
// Special case: check that sublayer transform changes all layer's descendants, but not the layer itself.
root->resetAllChangeTrackingForSubtree();
diff --git a/Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp b/Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp
index 47a6fd4dc..bff7e1ba9 100644
--- a/Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp
@@ -52,7 +52,7 @@ public:
private:
TestLayerChromium()
- : LayerChromium(0)
+ : LayerChromium()
, m_drawsContent(true)
{
setBounds(IntSize(100, 100));
diff --git a/Source/WebKit/chromium/tests/CCLayerTestCommon.cpp b/Source/WebKit/chromium/tests/CCLayerTestCommon.cpp
new file mode 100644
index 000000000..9fe377766
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCLayerTestCommon.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 "CCLayerTestCommon.h"
+
+#include <gtest/gtest.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace CCLayerTestCommon {
+
+// Align with expected and actual output
+const char* quadString = " Quad: ";
+
+bool completelyContains(const Region& container, const IntRect& rect)
+{
+ Region tester(rect);
+ Vector<IntRect> rects = container.rects();
+ for (size_t i = 0; i < rects.size(); ++i)
+ tester.subtract(rects[i]);
+ return tester.isEmpty();
+}
+
+void verifyQuadsExactlyCoverRect(const CCQuadList& quads, const IntRect& rect)
+{
+ Region remaining(rect);
+
+ for (size_t i = 0; i < quads.size(); ++i) {
+ CCDrawQuad* quad = quads[i].get();
+
+ EXPECT_TRUE(rect.contains(quad->quadRect())) << quadString << i;
+ EXPECT_TRUE(completelyContains(remaining, quad->quadRect())) << quadString << i;
+ remaining.subtract(Region(quad->quadRect()));
+ }
+
+ EXPECT_TRUE(remaining.isEmpty());
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerTestCommon.h b/Source/WebKit/chromium/tests/CCLayerTestCommon.h
new file mode 100644
index 000000000..c5add93a9
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCLayerTestCommon.h
@@ -0,0 +1,40 @@
+/*
+ * 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 CCLayerTestCommon_h
+#define CCLayerTestCommon_h
+
+#include "IntRect.h"
+#include "Region.h"
+#include "cc/CCRenderPass.h"
+
+namespace CCLayerTestCommon {
+
+extern const char* quadString;
+
+bool completelyContains(const WebCore::Region&, const WebCore::IntRect&);
+void verifyQuadsExactlyCoverRect(const WebCore::CCQuadList&, const WebCore::IntRect&);
+
+} // namespace CCLayerTestCommon
+#endif // CCLayerTestCommon_h
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
index a35d96522..b1fa72918 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
@@ -28,6 +28,7 @@
#include "CCLayerTreeTestCommon.h"
#include "LayerChromium.h"
+#include "Region.h"
#include "TransformationMatrix.h"
#include <gmock/gmock.h>
@@ -35,6 +36,12 @@
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)
@@ -71,8 +78,8 @@ TransformationMatrix remove3DComponentOfMatrix(const TransformationMatrix& mat)
class LayerChromiumWithForcedDrawsContent : public LayerChromium {
public:
- explicit LayerChromiumWithForcedDrawsContent(CCLayerDelegate* delegate)
- : LayerChromium(delegate)
+ LayerChromiumWithForcedDrawsContent()
+ : LayerChromium()
{
}
@@ -86,9 +93,9 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForNoOpLayer)
// screenSpaceTransform, and the hierarchy passed on to children
// layers should also be identity transforms.
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child = LayerChromium::create(0);
- RefPtr<LayerChromium> grandChild = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild = LayerChromium::create();
parent->createRenderSurface();
parent->addChild(child);
child->addChild(grandChild);
@@ -116,7 +123,7 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleLayer)
// different position. When we initialize layers for testing here, we need to initialize that unintutive position value.
TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> layer = LayerChromium::create(0);
+ RefPtr<LayerChromium> layer = LayerChromium::create();
layer->createRenderSurface();
// Case 1: setting the sublayer transform should not affect this layer's draw transform or screen-space transform.
@@ -181,9 +188,9 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleLayer)
TEST(CCLayerTreeHostCommonTest, verifyTransformsForSimpleHierarchy)
{
TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child = LayerChromium::create(0);
- RefPtr<LayerChromium> grandChild = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild = LayerChromium::create();
parent->createRenderSurface();
parent->addChild(child);
child->addChild(grandChild);
@@ -263,9 +270,9 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForSimpleHierarchy)
TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleRenderSurface)
{
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child = LayerChromium::create(0);
- RefPtr<LayerChromiumWithForcedDrawsContent> grandChild = adoptRef(new LayerChromiumWithForcedDrawsContent(0));
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> grandChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
parent->createRenderSurface();
parent->addChild(child);
child->addChild(grandChild);
@@ -318,15 +325,15 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
// - Sanity check on recursion: verify transforms of layers described w.r.t. a render surface that is described w.r.t. an ancestor render surface.
// - verifying that each layer has a reference to the correct renderSurface and targetRenderSurface values.
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> renderSurface1 = LayerChromium::create(0);
- RefPtr<LayerChromium> renderSurface2 = LayerChromium::create(0);
- RefPtr<LayerChromium> childOfRoot = LayerChromium::create(0);
- RefPtr<LayerChromium> childOfRS1 = LayerChromium::create(0);
- RefPtr<LayerChromium> childOfRS2 = LayerChromium::create(0);
- RefPtr<LayerChromium> grandChildOfRoot = LayerChromium::create(0);
- RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS1 = adoptRef(new LayerChromiumWithForcedDrawsContent(0));
- RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS2 = adoptRef(new LayerChromiumWithForcedDrawsContent(0));
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
+ RefPtr<LayerChromium> renderSurface2 = LayerChromium::create();
+ RefPtr<LayerChromium> childOfRoot = LayerChromium::create();
+ RefPtr<LayerChromium> childOfRS1 = LayerChromium::create();
+ RefPtr<LayerChromium> childOfRS2 = LayerChromium::create();
+ RefPtr<LayerChromium> grandChildOfRoot = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
parent->createRenderSurface();
parent->addChild(renderSurface1);
parent->addChild(childOfRoot);
@@ -454,9 +461,9 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForClipLayer)
{
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> renderSurface1 = LayerChromium::create(0);
- RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent(0));
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
renderSurface1->setOpacity(0.9);
const TransformationMatrix identityMatrix;
@@ -483,9 +490,9 @@ TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForClipLayer)
TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForTransparentChild)
{
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> renderSurface1 = LayerChromium::create(0);
- RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent(0));
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
renderSurface1->setOpacity(0);
const TransformationMatrix identityMatrix;
@@ -526,12 +533,12 @@ TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces)
//
const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child = LayerChromium::create(0);
- RefPtr<LayerChromium> grandChild = LayerChromium::create(0);
- RefPtr<LayerChromium> greatGrandChild = LayerChromium::create(0);
- RefPtr<LayerChromiumWithForcedDrawsContent> leafNode1 = adoptRef(new LayerChromiumWithForcedDrawsContent(0));
- RefPtr<LayerChromiumWithForcedDrawsContent> leafNode2 = adoptRef(new LayerChromiumWithForcedDrawsContent(0));
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild = LayerChromium::create();
+ RefPtr<LayerChromium> greatGrandChild = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> leafNode1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> leafNode2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
parent->createRenderSurface();
parent->addChild(child);
child->addChild(grandChild);
@@ -595,4 +602,174 @@ 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 9b87d00fa..f59893de9 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
@@ -31,6 +31,7 @@
#include "LayerRendererChromium.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCSingleThreadProxy.h"
+#include "cc/CCSolidColorDrawQuad.h"
#include <gtest/gtest.h>
using namespace WebCore;
@@ -73,6 +74,20 @@ public:
ASSERT_EQ(timesEncountered, 1);
}
+ void setupScrollAndContentsLayers(const IntSize& contentSize)
+ {
+ RefPtr<CCLayerImpl> root = CCLayerImpl::create(0);
+ root->setScrollable(true);
+ root->setScrollPosition(IntPoint(0, 0));
+ root->setMaxScrollPosition(contentSize);
+ RefPtr<CCLayerImpl> contents = CCLayerImpl::create(1);
+ contents->setDrawsContent(true);
+ contents->setBounds(contentSize);
+ contents->setContentBounds(contentSize);
+ root->addChild(contents);
+ m_hostImpl->setRootLayer(root);
+ }
+
protected:
DebugScopedSetImplThread m_alwaysImplThread;
OwnPtr<CCLayerTreeHostImpl> m_hostImpl;
@@ -155,6 +170,112 @@ TEST_F(CCLayerTreeHostImplTest, scrollRootCallsCommitAndRedraw)
EXPECT_TRUE(m_didRequestCommit);
}
+TEST_F(CCLayerTreeHostImplTest, pinchGesture)
+{
+ setupScrollAndContentsLayers(IntSize(100, 100));
+ m_hostImpl->setViewportSize(IntSize(50, 50));
+
+ CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
+ ASSERT(scrollLayer);
+
+ const float minPageScale = 0.5, maxPageScale = 4;
+
+ // Basic pinch zoom in gesture
+ {
+ m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
+ scrollLayer->setPageScaleDelta(1);
+
+ float pageScaleDelta = 2;
+ m_hostImpl->pinchGestureBegin();
+ m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
+ m_hostImpl->pinchGestureEnd();
+ EXPECT_TRUE(m_didRequestRedraw);
+ EXPECT_TRUE(m_didRequestCommit);
+
+ OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
+ EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
+ }
+
+ // Zoom-in clamping
+ {
+ m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
+ scrollLayer->setPageScaleDelta(1);
+ float pageScaleDelta = 10;
+
+ m_hostImpl->pinchGestureBegin();
+ m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
+ m_hostImpl->pinchGestureEnd();
+
+ OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
+ EXPECT_EQ(scrollInfo->pageScaleDelta, maxPageScale);
+ }
+
+ // Zoom-out clamping
+ {
+ m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
+ scrollLayer->setPageScaleDelta(1);
+ scrollLayer->setScrollPosition(IntPoint(50, 50));
+
+ float pageScaleDelta = 0.1;
+ m_hostImpl->pinchGestureBegin();
+ m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(0, 0));
+ m_hostImpl->pinchGestureEnd();
+
+ 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));
+ }
+}
+
+TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation)
+{
+ setupScrollAndContentsLayers(IntSize(100, 100));
+ m_hostImpl->setViewportSize(IntSize(50, 50));
+
+ CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
+ ASSERT(scrollLayer);
+
+ const float minPageScale = 0.5, maxPageScale = 4;
+ const double startTimeMs = 1000;
+ const double durationMs = 100;
+
+ // Non-anchor zoom-in
+ {
+ m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
+ scrollLayer->setPageScaleDelta(1);
+ scrollLayer->setScrollPosition(IntPoint(50, 50));
+
+ m_hostImpl->startPageScaleAnimation(IntSize(0, 0), false, 2, startTimeMs, durationMs);
+ m_hostImpl->animate(startTimeMs + durationMs / 2);
+ EXPECT_TRUE(m_didRequestRedraw);
+ m_hostImpl->animate(startTimeMs + durationMs);
+ EXPECT_TRUE(m_didRequestCommit);
+
+ OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
+ EXPECT_EQ(scrollInfo->pageScaleDelta, 2);
+ expectContains(*scrollInfo.get(), scrollLayer->id(), IntSize(-50, -50));
+ }
+
+ // Anchor zoom-out
+ {
+ m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
+ scrollLayer->setPageScaleDelta(1);
+ scrollLayer->setScrollPosition(IntPoint(50, 50));
+
+ m_hostImpl->startPageScaleAnimation(IntSize(25, 25), true, minPageScale, startTimeMs, durationMs);
+ m_hostImpl->animate(startTimeMs + durationMs);
+ EXPECT_TRUE(m_didRequestRedraw);
+ EXPECT_TRUE(m_didRequestCommit);
+
+ 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));
+ }
+}
+
class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
public:
BlendStateTrackerContext() : m_blend(false) { }
@@ -183,11 +304,13 @@ class BlendStateCheckLayer : public CCLayerImpl {
public:
static PassRefPtr<BlendStateCheckLayer> create(int id) { return adoptRef(new BlendStateCheckLayer(id)); }
- virtual void draw(LayerRendererChromium* renderer)
+ virtual void appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
{
- m_drawn = true;
- BlendStateTrackerContext* context = static_cast<BlendStateTrackerContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(renderer->context()));
- EXPECT_EQ(m_blend, context->blend());
+ m_quadsAppended = true;
+
+ Color color = m_opaqueColor ? Color::white : Color(0, 0, 0, 0);
+ OwnPtr<CCDrawQuad> testBlendingDrawQuad = CCSolidColorDrawQuad::create(sharedQuadState, IntRect(5, 5, 5, 5), color);
+ EXPECT_EQ(m_blend, testBlendingDrawQuad->needsBlending());
EXPECT_EQ(m_hasRenderSurface, !!renderSurface());
}
@@ -195,17 +318,20 @@ public:
{
m_blend = blend;
m_hasRenderSurface = hasRenderSurface;
- m_drawn = false;
+ m_quadsAppended = false;
}
- bool drawn() const { return m_drawn; }
+ bool quadsAppended() const { return m_quadsAppended; }
+
+ void setOpaqueColor(bool opaqueColor) { m_opaqueColor = opaqueColor; }
private:
explicit BlendStateCheckLayer(int id)
: CCLayerImpl(id)
, m_blend(false)
, m_hasRenderSurface(false)
- , m_drawn(false)
+ , m_quadsAppended(false)
+ , m_opaqueColor(true)
{
setAnchorPoint(FloatPoint(0, 0));
setBounds(IntSize(10, 10));
@@ -214,7 +340,8 @@ private:
bool m_blend;
bool m_hasRenderSurface;
- bool m_drawn;
+ bool m_quadsAppended;
+ bool m_opaqueColor;
};
// https://bugs.webkit.org/show_bug.cgi?id=75783
@@ -236,45 +363,76 @@ TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
// Opaque layer, drawn without blending.
layer1->setOpaque(true);
+ layer1->setOpaqueColor(true);
layer1->setExpectation(false, false);
m_hostImpl->drawLayers();
- EXPECT_TRUE(layer1->drawn());
+ EXPECT_TRUE(layer1->quadsAppended());
- // Layer with translucent content, drawn with blending.
+ // Layer with translucent content, but solid color is opaque, so drawn without blending.
layer1->setOpaque(false);
+ layer1->setOpaqueColor(true);
+ layer1->setExpectation(false, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->quadsAppended());
+
+ // Layer with translucent content and painting, so drawn with blending.
+ layer1->setOpaque(false);
+ layer1->setOpaqueColor(false);
layer1->setExpectation(true, false);
m_hostImpl->drawLayers();
- EXPECT_TRUE(layer1->drawn());
+ EXPECT_TRUE(layer1->quadsAppended());
// Layer with translucent opacity, drawn with blending.
layer1->setOpaque(true);
+ layer1->setOpaqueColor(true);
+ layer1->setOpacity(0.5);
+ layer1->setExpectation(true, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->quadsAppended());
+
+ // Layer with translucent opacity and painting, drawn with blending.
+ layer1->setOpaque(true);
+ layer1->setOpaqueColor(false);
layer1->setOpacity(0.5);
layer1->setExpectation(true, false);
m_hostImpl->drawLayers();
- EXPECT_TRUE(layer1->drawn());
+ EXPECT_TRUE(layer1->quadsAppended());
RefPtr<BlendStateCheckLayer> layer2 = BlendStateCheckLayer::create(2);
layer1->addChild(layer2);
// 2 opaque layers, drawn without blending.
layer1->setOpaque(true);
+ layer1->setOpaqueColor(true);
layer1->setOpacity(1);
layer1->setExpectation(false, false);
layer2->setOpaque(true);
+ layer2->setOpaqueColor(true);
layer2->setOpacity(1);
layer2->setExpectation(false, false);
m_hostImpl->drawLayers();
- EXPECT_FALSE(layer1->drawn());
- EXPECT_TRUE(layer2->drawn());
+ EXPECT_TRUE(layer1->quadsAppended());
+ EXPECT_TRUE(layer2->quadsAppended());
// Parent layer with translucent content, drawn with blending.
// Child layer with opaque content, drawn without blending.
layer1->setOpaque(false);
+ layer1->setOpaqueColor(false);
layer1->setExpectation(true, false);
layer2->setExpectation(false, false);
m_hostImpl->drawLayers();
- EXPECT_FALSE(layer1->drawn());
- EXPECT_TRUE(layer2->drawn());
+ EXPECT_TRUE(layer1->quadsAppended());
+ EXPECT_TRUE(layer2->quadsAppended());
+
+ // Parent layer with translucent content but opaque painting, drawn without blending.
+ // Child layer with opaque content, drawn without blending.
+ layer1->setOpaque(false);
+ layer1->setOpaqueColor(true);
+ layer1->setExpectation(false, false);
+ layer2->setExpectation(false, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->quadsAppended());
+ EXPECT_TRUE(layer2->quadsAppended());
// Parent layer with translucent opacity and opaque content. Since it has a
// drawing child, it's drawn to a render surface which carries the opacity,
@@ -282,35 +440,51 @@ TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
// Child layer with opaque content, drawn without blending (parent surface
// carries the inherited opacity).
layer1->setOpaque(true);
+ layer1->setOpaqueColor(true);
layer1->setOpacity(0.5);
layer1->setExpectation(false, true);
layer2->setExpectation(false, false);
m_hostImpl->drawLayers();
- EXPECT_FALSE(layer1->drawn());
- EXPECT_TRUE(layer2->drawn());
+ EXPECT_TRUE(layer1->quadsAppended());
+ EXPECT_TRUE(layer2->quadsAppended());
// Draw again, but with child non-opaque, to make sure
// layer1 not culled.
layer1->setOpaque(true);
+ layer1->setOpaqueColor(true);
layer1->setOpacity(1);
layer1->setExpectation(false, false);
layer2->setOpaque(true);
+ layer2->setOpaqueColor(true);
layer2->setOpacity(0.5);
layer2->setExpectation(true, false);
m_hostImpl->drawLayers();
- EXPECT_TRUE(layer1->drawn());
- EXPECT_TRUE(layer2->drawn());
+ EXPECT_TRUE(layer1->quadsAppended());
+ EXPECT_TRUE(layer2->quadsAppended());
// A second way of making the child non-opaque.
layer1->setOpaque(true);
layer1->setOpacity(1);
layer1->setExpectation(false, false);
layer2->setOpaque(false);
+ layer2->setOpaqueColor(false);
layer2->setOpacity(1);
layer2->setExpectation(true, false);
m_hostImpl->drawLayers();
- EXPECT_TRUE(layer1->drawn());
- EXPECT_TRUE(layer2->drawn());
+ EXPECT_TRUE(layer1->quadsAppended());
+ EXPECT_TRUE(layer2->quadsAppended());
+
+ // And when the layer says its not opaque but is painted opaque, it is not blended.
+ layer1->setOpaque(true);
+ layer1->setOpacity(1);
+ layer1->setExpectation(false, false);
+ layer2->setOpaque(false);
+ layer2->setOpaqueColor(true);
+ layer2->setOpacity(1);
+ layer2->setExpectation(false, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->quadsAppended());
+ EXPECT_TRUE(layer2->quadsAppended());
}
class ReshapeTrackerContext: public FakeWebGraphicsContext3D {
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
index bfa1b0822..41fe4fb65 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
@@ -26,10 +26,11 @@
#include "cc/CCLayerTreeHost.h"
-#include "CompositorFakeGraphicsContext3D.h"
+#include "CompositorFakeWebGraphicsContext3D.h"
#include "ContentLayerChromium.h"
-#include "FakeWebGraphicsContext3D.h"
+#include "GraphicsContext3DPrivate.h"
#include "LayerChromium.h"
+#include "Region.h"
#include "TextureManager.h"
#include "WebCompositor.h"
#include "WebKit.h"
@@ -40,8 +41,8 @@
#include "cc/CCThreadTask.h"
#include "platform/WebKitPlatformSupport.h"
#include "platform/WebThread.h"
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <webkit/support/webkit_support.h>
#include <wtf/MainThread.h>
#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
@@ -130,6 +131,52 @@ private:
TestHooks* m_testHooks;
};
+class CompositorFakeWebGraphicsContext3DWithTextureTracking : public CompositorFakeWebGraphicsContext3D {
+public:
+ static PassOwnPtr<CompositorFakeWebGraphicsContext3DWithTextureTracking> create(Attributes attrs)
+ {
+ return adoptPtr(new CompositorFakeWebGraphicsContext3DWithTextureTracking(attrs));
+ }
+
+ virtual WebGLId createTexture()
+ {
+ WebGLId texture = m_textures.size() + 1;
+ m_textures.append(texture);
+ return texture;
+ }
+
+ virtual void deleteTexture(WebGLId texture)
+ {
+ for (size_t i = 0; i < m_textures.size(); i++) {
+ if (m_textures[i] == texture) {
+ m_textures.remove(i);
+ break;
+ }
+ }
+ }
+
+ virtual void bindTexture(WGC3Denum /* target */, WebGLId texture)
+ {
+ m_usedTextures.add(texture);
+ }
+
+ int numTextures() const { return static_cast<int>(m_textures.size()); }
+ int texture(int i) const { return m_textures[i]; }
+ void resetTextures() { m_textures.clear(); }
+
+ int numUsedTextures() const { return static_cast<int>(m_usedTextures.size()); }
+ bool usedTexture(int texture) const { return m_usedTextures.find(texture) != m_usedTextures.end(); }
+ void resetUsedTextures() { m_usedTextures.clear(); }
+
+private:
+ explicit CompositorFakeWebGraphicsContext3DWithTextureTracking(Attributes attrs) : CompositorFakeWebGraphicsContext3D(attrs)
+ {
+ }
+
+ Vector<WebGLId> m_textures;
+ HashSet<WebGLId> m_usedTextures;
+};
+
// Implementation of CCLayerTreeHost callback interface.
class MockLayerTreeHostClient : public CCLayerTreeHostClient {
public:
@@ -155,7 +202,15 @@ public:
virtual PassRefPtr<GraphicsContext3D> createLayerTreeHostContext3D()
{
- return createCompositorMockGraphicsContext3D(GraphicsContext3D::Attributes());
+ GraphicsContext3D::Attributes attrs;
+ WebGraphicsContext3D::Attributes webAttrs;
+ webAttrs.alpha = attrs.alpha;
+
+ OwnPtr<WebGraphicsContext3D> webContext = CompositorFakeWebGraphicsContext3DWithTextureTracking::create(webAttrs);
+ return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(
+ webContext.release(), attrs, 0,
+ GraphicsContext3D::RenderDirectlyToHostWindow,
+ GraphicsContext3DPrivate::ForUseOnAnotherThread);
}
virtual void didCommitAndDrawFrame()
@@ -243,16 +298,10 @@ protected:
void doBeginTest();
- static void onBeginTest(void* self)
- {
- static_cast<CCLayerTreeHostTest*>(self)->doBeginTest();
- }
-
static void onEndTest(void* self)
{
ASSERT(isMainThread());
- webkit_support::QuitMessageLoop();
- webkit_support::RunAllPendingMessages();
+ webKitPlatformSupport()->currentThread()->exitRunLoop();
}
static void dispatchSetNeedsAnimate(void* self)
@@ -311,7 +360,7 @@ protected:
test->m_layerTreeHost->setVisible(false);
}
- class TimeoutTask : public webkit_support::TaskAdaptor {
+ class TimeoutTask : public WebThread::Task {
public:
explicit TimeoutTask(CCLayerTreeHostTest* test)
: m_test(test)
@@ -329,7 +378,7 @@ protected:
m_test->clearTimeout();
}
- virtual void Run()
+ virtual void run()
{
if (m_test)
m_test->timeout();
@@ -339,10 +388,24 @@ protected:
CCLayerTreeHostTest* m_test;
};
+ class BeginTask : public WebThread::Task {
+ public:
+ explicit BeginTask(CCLayerTreeHostTest* test)
+ : m_test(test)
+ {
+ }
+
+ virtual ~BeginTask() { }
+ virtual void run()
+ {
+ m_test->doBeginTest();
+ }
+ private:
+ CCLayerTreeHostTest* m_test;
+ };
+
virtual void runTest(bool threaded)
{
- m_settings.refreshRate = 100.0;
-
if (threaded) {
m_webThread = adoptPtr(webKitPlatformSupport()->createThread("CCLayerTreeHostTest"));
WebCompositor::initialize(m_webThread.get());
@@ -352,11 +415,11 @@ protected:
ASSERT(CCProxy::isMainThread());
m_mainThreadProxy = CCScopedThreadProxy::create(CCProxy::mainThread());
- webkit_support::PostDelayedTask(CCLayerTreeHostTest::onBeginTest, static_cast<void*>(this), 0);
+ m_beginTask = new BeginTask(this);
+ webKitPlatformSupport()->currentThread()->postDelayedTask(m_beginTask, 0); // postDelayedTask takes ownership of the task
m_timeoutTask = new TimeoutTask(this);
- webkit_support::PostDelayedTask(m_timeoutTask, 5000); // webkit_support takes ownership of the task
- webkit_support::RunMessageLoop();
- webkit_support::RunAllPendingMessages();
+ webKitPlatformSupport()->currentThread()->postDelayedTask(m_timeoutTask, 5000);
+ webKitPlatformSupport()->currentThread()->enterRunLoop();
if (m_layerTreeHost && m_layerTreeHost->rootLayer())
m_layerTreeHost->rootLayer()->setLayerTreeHost(0);
@@ -388,6 +451,7 @@ private:
OwnPtr<WebThread> m_webThread;
RefPtr<CCScopedThreadProxy> m_mainThreadProxy;
TimeoutTask* m_timeoutTask;
+ BeginTask* m_beginTask;
};
void CCLayerTreeHostTest::doBeginTest()
@@ -395,7 +459,7 @@ void CCLayerTreeHostTest::doBeginTest()
ASSERT(isMainThread());
m_client = MockLayerTreeHostClient::create(this);
- RefPtr<LayerChromium> rootLayer = LayerChromium::create(0);
+ RefPtr<LayerChromium> rootLayer = LayerChromium::create();
m_layerTreeHost = MockLayerTreeHost::create(this, m_client.get(), rootLayer, m_settings);
ASSERT_TRUE(m_layerTreeHost);
rootLayer->setLayerTreeHost(m_layerTreeHost.get());
@@ -912,7 +976,7 @@ TEST_F(CCLayerTreeHostTestSetVisible, runMultiThread)
runTest(true);
}
-class TestOpacityChangeLayerDelegate : public CCLayerDelegate {
+class TestOpacityChangeLayerDelegate : public ContentLayerDelegate {
public:
TestOpacityChangeLayerDelegate(CCLayerTreeHostTest* test)
: m_test(test)
@@ -933,7 +997,7 @@ private:
class ContentLayerChromiumWithUpdateTracking : public ContentLayerChromium {
public:
- static PassRefPtr<ContentLayerChromiumWithUpdateTracking> create(CCLayerDelegate *delegate) { return adoptRef(new ContentLayerChromiumWithUpdateTracking(delegate)); }
+ static PassRefPtr<ContentLayerChromiumWithUpdateTracking> create(ContentLayerDelegate *delegate) { return adoptRef(new ContentLayerChromiumWithUpdateTracking(delegate)); }
int paintContentsCount() { return m_paintContentsCount; }
int idlePaintContentsCount() { return m_idlePaintContentsCount; }
@@ -942,9 +1006,9 @@ public:
int updateCount() { return m_updateCount; }
void resetUpdateCount() { m_updateCount = 0; }
- virtual void paintContentsIfDirty()
+ virtual void paintContentsIfDirty(const Region& occludedScreenSpace)
{
- ContentLayerChromium::paintContentsIfDirty();
+ ContentLayerChromium::paintContentsIfDirty(occludedScreenSpace);
m_paintContentsCount++;
}
@@ -961,7 +1025,7 @@ public:
}
private:
- explicit ContentLayerChromiumWithUpdateTracking(CCLayerDelegate *delegate)
+ explicit ContentLayerChromiumWithUpdateTracking(ContentLayerDelegate* delegate)
: ContentLayerChromium(delegate)
, m_paintContentsCount(0)
, m_idlePaintContentsCount(0)
@@ -1068,4 +1132,341 @@ TEST_F(CCLayerTreeHostTestSetViewportSize, runSingleThread)
runTest(false);
}
+class MockContentLayerDelegate : public ContentLayerDelegate {
+public:
+ bool drawsContent() const { return true; }
+ MOCK_CONST_METHOD0(preserves3D, bool());
+ void paintContents(GraphicsContext&, const IntRect&) { }
+ void notifySyncRequired() { }
+};
+
+// Verify atomicity of commits and reuse of textures.
+class CCLayerTreeHostTestAtomicCommit : public CCLayerTreeHostTest {
+public:
+ CCLayerTreeHostTestAtomicCommit()
+ : m_updateCheckLayer(ContentLayerChromiumWithUpdateTracking::create(&m_delegate))
+ , m_numCommits(0)
+ {
+ // Make sure partial texture updates are turned off.
+ m_settings.partialTextureUpdates = false;
+ }
+
+ virtual void beginTest()
+ {
+ m_layerTreeHost->setRootLayer(m_updateCheckLayer);
+ m_layerTreeHost->setViewportSize(IntSize(10, 10));
+
+ postSetNeedsCommitToMainThread();
+ postSetNeedsRedrawToMainThread();
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
+
+ switch (impl->frameNumber()) {
+ case 0:
+ // Number of textures should be one.
+ EXPECT_EQ(1, context->numTextures());
+ // Number of textures used for commit should be one.
+ EXPECT_EQ(1, context->numUsedTextures());
+ // Verify used texture is correct.
+ EXPECT_TRUE(context->usedTexture(context->texture(0)));
+
+ context->resetUsedTextures();
+ break;
+ case 1:
+ // Number of textures should be two as the first texture
+ // is used by impl thread and cannot by used for update.
+ EXPECT_EQ(2, context->numTextures());
+ // Number of textures used for commit should still be one.
+ EXPECT_EQ(1, context->numUsedTextures());
+ // First texture should not have been used.
+ EXPECT_FALSE(context->usedTexture(context->texture(0)));
+ // New texture should have been used.
+ EXPECT_TRUE(context->usedTexture(context->texture(1)));
+
+ context->resetUsedTextures();
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
+
+ // Number of textures used for draw should always be one.
+ EXPECT_EQ(1, context->numUsedTextures());
+
+ if (impl->frameNumber() < 2) {
+ context->resetUsedTextures();
+ postSetNeedsAnimateAndCommitToMainThread();
+ postSetNeedsRedrawToMainThread();
+ } else
+ endTest();
+ }
+
+ virtual void layout()
+ {
+ m_updateCheckLayer->setNeedsDisplay();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ MockContentLayerDelegate m_delegate;
+ RefPtr<ContentLayerChromiumWithUpdateTracking> m_updateCheckLayer;
+ int m_numCommits;
+};
+
+TEST_F(CCLayerTreeHostTestAtomicCommit, runMultiThread)
+{
+ runTest(true);
+}
+
+#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());
+
+class TestLayerChromium : public LayerChromium {
+public:
+ static PassRefPtr<TestLayerChromium> create() { return adoptRef(new TestLayerChromium()); }
+
+ virtual void paintContentsIfDirty(const Region& occludedScreenSpace)
+ {
+ m_occludedScreenSpace = occludedScreenSpace;
+ }
+
+ virtual bool drawsContent() const { return true; }
+
+ const Region& occludedScreenSpace() const { return m_occludedScreenSpace; }
+ void clearOccludedScreenSpace() { m_occludedScreenSpace = Region(); }
+
+private:
+ TestLayerChromium() : LayerChromium() { }
+
+ Region m_occludedScreenSpace;
+};
+
+static void setLayerPropertiesForTesting(TestLayerChromium* layer, LayerChromium* parent, const TransformationMatrix& transform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool opaque)
+{
+ layer->removeAllChildren();
+ if (parent)
+ parent->addChild(layer);
+ layer->setTransform(transform);
+ layer->setAnchorPoint(anchor);
+ layer->setPosition(position);
+ layer->setBounds(bounds);
+ layer->setOpaque(opaque);
+ layer->clearOccludedScreenSpace();
+}
+
+class CCLayerTreeHostTestLayerOcclusion : public CCLayerTreeHostTest {
+public:
+ CCLayerTreeHostTestLayerOcclusion() { }
+
+ 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);
+
+ // See CCLayerTreeHostCommonTest.layerAddsSelfToOccludedRegionWithRotatedSurface for a nice visual of these layers and how they end up
+ // positioned on the screen.
+
+ // The child layer is rotated and the grandChild is opaque, but clipped to the child and 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), false);
+ setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ 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(30, 40, 70, 60), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
+
+ // If the child layer is opaque, then it adds to the occlusion seen by 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);
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ 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(30, 30, 70, 70), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
+
+ // Add a second child to the root layer and the regions should merge
+ setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(70, 20), IntSize(500, 500), 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);
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ 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(30, 30, 70, 70), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, child2->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 20, 70, 80), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ(2u, rootLayer->occludedScreenSpace().rects().size());
+
+ // Move the second child to be sure.
+ setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), 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);
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ 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(30, 30, 70, 70), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, child2->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 30, 90, 70), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ(2u, rootLayer->occludedScreenSpace().rects().size());
+
+ // If the child layer has a mask on it, then it shouldn't contribute to occlusion on stuff below it
+ setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), 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);
+
+ child->setMaskLayer(mask.get());
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ 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(), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ(0u, child2->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 with a mask 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);
+
+ child->setMaskLayer(mask.get());
+
+ 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 non-opaque drawOpacity, then it shouldn't contribute to occlusion on stuff below it
+ setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), 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);
+
+ child->setMaskLayer(0);
+ child->setOpacity(0.5);
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ 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(), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ(0u, child2->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 with non-opaque drawOpacity 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);
+
+ child->setMaskLayer(0);
+ child->setOpacity(0.5);
+
+ 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());
+
+ // Kill the layerTreeHost immediately.
+ m_layerTreeHost->setRootLayer(0);
+ m_layerTreeHost.clear();
+
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusion)
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp b/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
index ed15e6c10..299e5c7e5 100644
--- a/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
@@ -26,6 +26,7 @@
#include "cc/CCQuadCuller.h"
+#include "cc/CCTileDrawQuad.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -36,37 +37,29 @@ namespace {
class CCQuadCullerTest : public testing::Test {
};
-class TestDrawQuad : public CCDrawQuad {
-public:
- TestDrawQuad(const CCSharedQuadState* state, Material m, const IntRect& rect)
- : CCDrawQuad(state, m, rect)
- {
- }
-
- static PassOwnPtr<TestDrawQuad> create(const CCSharedQuadState* state, Material m, const IntRect& rect)
- {
- return adoptPtr(new TestDrawQuad(state, m, rect));
- }
-};
+static PassOwnPtr<CCDrawQuad> MakeTileQuad(CCSharedQuadState* state, const IntRect& rect, const IntRect& opaqueRect = IntRect())
+{
+ return CCTileDrawQuad::create(state, rect, intersection(rect, opaqueRect), 1, IntPoint(1, 1), IntSize(100, 100), 0, false, false, false, false, false);
+}
-void setQuads(CCSharedQuadState* rootState, CCSharedQuadState* childState, CCQuadList& quadList)
+void setQuads(CCSharedQuadState* rootState, CCSharedQuadState* childState, CCQuadList& quadList, const IntRect& opaqueRect = IntRect())
{
quadList.clear();
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 0), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(200, 0), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(0, 100), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 100), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(200, 100), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(0, 200), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 200), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(200, 200), IntSize(100, 100))));
-
- quadList.append(TestDrawQuad::create(childState, CCDrawQuad::TiledContent, IntRect(IntPoint(), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(childState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 0), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(childState, CCDrawQuad::TiledContent, IntRect(IntPoint(0, 100), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(childState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 100), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(100, 0), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(200, 0), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(0, 100), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(100, 100), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(200, 100), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(0, 200), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(100, 200), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(200, 200), IntSize(100, 100)), opaqueRect));
+
+ quadList.append(MakeTileQuad(childState, IntRect(IntPoint(), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(childState, IntRect(IntPoint(100, 0), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(childState, IntRect(IntPoint(0, 100), IntSize(100, 100)), opaqueRect));
+ quadList.append(MakeTileQuad(childState, IntRect(IntPoint(100, 100), IntSize(100, 100)), opaqueRect));
}
#define DECLARE_AND_INITIALIZE_TEST_QUADS \
@@ -129,6 +122,67 @@ TEST(CCQuadCullerTest, verifyCullCenterTileOnly)
EXPECT_EQ(quadList.size(), 13u);
CCQuadCuller::cullOccludedQuads(quadList);
EXPECT_EQ(quadList.size(), 12u);
+
+ IntRect quadVisibleRect1 = quadList[1].get()->quadVisibleRect();
+ EXPECT_EQ(quadVisibleRect1.height(), 50);
+
+ IntRect quadVisibleRect3 = quadList[3].get()->quadVisibleRect();
+ EXPECT_EQ(quadVisibleRect3.width(), 50);
+
+ // Next index is 4, not 5, since centre quad culled.
+ IntRect quadVisibleRect4 = quadList[4].get()->quadVisibleRect();
+ EXPECT_EQ(quadVisibleRect4.width(), 50);
+ EXPECT_EQ(quadVisibleRect4.x(), 250);
+
+ IntRect quadVisibleRect6 = quadList[6].get()->quadVisibleRect();
+ EXPECT_EQ(quadVisibleRect6.height(), 50);
+ EXPECT_EQ(quadVisibleRect6.y(), 250);
+}
+
+TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize1)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ childTransform.translate(100, 100);
+
+ // Create root layer tile with extent (99.1, 99.1) -> (200.9, 200.9) to make
+ // sure it doesn't get culled due to transform rounding.
+ TransformationMatrix rootTransform;
+ rootTransform.translate(99.1, 99.1);
+ rootTransform.scale(1.018);
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(rootTransform, TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+
+ quadList.append(MakeTileQuad(rootState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+
+ EXPECT_EQ(quadList.size(), 2u);
+ CCQuadCuller::cullOccludedQuads(quadList);
+ EXPECT_EQ(quadList.size(), 2u);
+}
+
+TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize2)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ // Make the child quad slightly smaller than, and centred over, the root layer tile.
+ // Verify the child does not cause the quad below to be culled due to rounding.
+ childTransform.translate(100.1, 100.1);
+ childTransform.scale(0.982);
+
+ TransformationMatrix rootTransform;
+ rootTransform.translate(100, 100);
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(rootTransform, TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+
+ quadList.append(MakeTileQuad(rootState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+
+ EXPECT_EQ(quadList.size(), 2u);
+ CCQuadCuller::cullOccludedQuads(quadList);
+ EXPECT_EQ(quadList.size(), 2u);
}
TEST(CCQuadCullerTest, verifyCullChildLinesUpBottomRight)
@@ -146,6 +200,54 @@ TEST(CCQuadCullerTest, verifyCullChildLinesUpBottomRight)
EXPECT_EQ(quadList.size(), 9u);
}
+TEST(CCQuadCullerTest, verifyCullSubRegion)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ childTransform.translate(50, 50);
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, false);
+ IntRect childOpaqueRect(childRect.x() + childRect.width() / 4, childRect.y() + childRect.height() / 4, childRect.width() / 2, childRect.height() / 2);
+
+ setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
+ EXPECT_EQ(quadList.size(), 13u);
+ CCQuadCuller::cullOccludedQuads(quadList);
+ EXPECT_EQ(quadList.size(), 12u);
+}
+
+TEST(CCQuadCullerTest, verifyCullSubRegion2)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ childTransform.translate(50, 10);
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, false);
+ IntRect childOpaqueRect(childRect.x() + childRect.width() / 4, childRect.y() + childRect.height() / 4, childRect.width() / 2, childRect.height() * 3 / 4);
+
+ setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
+ EXPECT_EQ(quadList.size(), 13u);
+ CCQuadCuller::cullOccludedQuads(quadList);
+ EXPECT_EQ(quadList.size(), 12u);
+}
+
+TEST(CCQuadCullerTest, verifyCullSubRegionCheckOvercull)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ childTransform.translate(50, 49);
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, false);
+ IntRect childOpaqueRect(childRect.x() + childRect.width() / 4, childRect.y() + childRect.height() / 4, childRect.width() / 2, childRect.height() / 2);
+
+ setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
+ EXPECT_EQ(quadList.size(), 13u);
+ CCQuadCuller::cullOccludedQuads(quadList);
+ EXPECT_EQ(quadList.size(), 13u);
+}
+
TEST(CCQuadCullerTest, verifyNonAxisAlignedQuadsDontOcclude)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
diff --git a/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp b/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp
index 48a3fda1f..3908f40a9 100644
--- a/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp
+++ b/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp
@@ -77,8 +77,11 @@ TEST(CCSchedulerStateMachineTest, TestNextActionBeginsFrameIfNeeded)
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
+ EXPECT_FALSE(state.vsyncCallbackNeeded());
+
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ EXPECT_FALSE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
@@ -91,6 +94,7 @@ TEST(CCSchedulerStateMachineTest, TestNextActionBeginsFrameIfNeeded)
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
+ EXPECT_FALSE(state.vsyncCallbackNeeded());
}
// Begin the frame, make sure needsCommit and commitState update correctly.
@@ -100,6 +104,7 @@ TEST(CCSchedulerStateMachineTest, TestNextActionBeginsFrameIfNeeded)
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, state.commitState());
EXPECT_FALSE(state.needsCommit());
+ EXPECT_FALSE(state.vsyncCallbackNeeded());
}
}
@@ -108,6 +113,7 @@ TEST(CCSchedulerStateMachineTest, TestSetForcedRedrawDoesNotSetsNormalRedraw)
CCSchedulerStateMachine state;
state.setNeedsForcedRedraw();
EXPECT_FALSE(state.redrawPending());
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
}
TEST(CCSchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame)
@@ -115,6 +121,7 @@ TEST(CCSchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame)
CCSchedulerStateMachine state;
state.setVisible(true);
state.setNeedsRedraw();
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW);
@@ -126,10 +133,12 @@ TEST(CCSchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame)
// Move to another frame. This should now draw.
state.didLeaveVSync();
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW);
+ EXPECT_FALSE(state.vsyncCallbackNeeded());
}
TEST(CCSchedulerStateMachineTest, TestNextActionDrawsOnVSync)
@@ -140,34 +149,42 @@ TEST(CCSchedulerStateMachineTest, TestNextActionDrawsOnVSync)
for (unsigned j = 0; j < 2; ++j) {
StateMachine state;
state.setCommitState(allCommitStates[i]);
- if (!j) {
+ bool visible = j;
+ if (!visible) {
state.didEnterVSync();
state.setVisible(false);
- }
+ } else
+ state.setVisible(true);
// Case 1: needsCommit=false updateMoreResourcesPending=false.
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(false);
+ EXPECT_FALSE(state.vsyncCallbackNeeded());
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
// Case 2: needsCommit=false updateMoreResourcesPending=true.
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(true);
+ if (visible)
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
// Case 3: needsCommit=true updateMoreResourcesPending=false.
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(false);
+ EXPECT_FALSE(state.vsyncCallbackNeeded());
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
// Case 4: needsCommit=true updateMoreResourcesPending=true.
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(true);
+ if (visible)
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
}
}
- // When on vsync, or not on vsync but needsForcedRedraw set, should always draw expect if you're ready to commit, in which case commit.
+ // When on vsync, or not on vsync but needsForcedRedraw set, should always draw except if you're ready to commit, in which case commit.
for (size_t i = 0; i < numCommitStates; ++i) {
for (unsigned j = 0; j < 2; ++j) {
StateMachine state;
@@ -188,21 +205,25 @@ TEST(CCSchedulerStateMachineTest, TestNextActionDrawsOnVSync)
// Case 1: needsCommit=false updateMoreResourcesPending=false.
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(false);
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_EQ(expectedAction, state.nextAction());
// Case 2: needsCommit=false updateMoreResourcesPending=true.
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(true);
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_EQ(expectedAction, state.nextAction());
// Case 3: needsCommit=true updateMoreResourcesPending=false.
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(false);
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_EQ(expectedAction, state.nextAction());
// Case 4: needsCommit=true updateMoreResourcesPending=true.
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(true);
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_EQ(expectedAction, state.nextAction());
}
}
diff --git a/Source/WebKit/chromium/tests/CCSchedulerTest.cpp b/Source/WebKit/chromium/tests/CCSchedulerTest.cpp
index 0fe811d86..475987f13 100644
--- a/Source/WebKit/chromium/tests/CCSchedulerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCSchedulerTest.cpp
@@ -77,6 +77,7 @@ TEST(CCSchedulerTest, RequestCommit)
scheduler->setNeedsCommit();
EXPECT_EQ(1, client.numActions());
EXPECT_STREQ("scheduledActionBeginFrame", client.action(0));
+ EXPECT_FALSE(timeSource->active());
client.reset();
// Since, hasMoreResourceUpdates is set to false,
@@ -86,17 +87,18 @@ TEST(CCSchedulerTest, RequestCommit)
EXPECT_EQ(2, client.numActions());
EXPECT_STREQ("scheduledActionUpdateMoreResources", client.action(0));
EXPECT_STREQ("scheduledActionCommit", client.action(1));
+ EXPECT_TRUE(timeSource->active());
client.reset();
// Tick should draw.
timeSource->tick();
EXPECT_EQ(1, client.numActions());
EXPECT_STREQ("scheduledActionDrawAndSwap", client.action(0));
+ EXPECT_FALSE(timeSource->active());
client.reset();
- // Tick should do nothing.
- timeSource->tick();
- EXPECT_EQ(0, client.numActions());
+ // Timer should be off.
+ EXPECT_FALSE(timeSource->active());
}
TEST(CCSchedulerTest, RequestCommitAfterBeginFrame)
@@ -126,6 +128,7 @@ TEST(CCSchedulerTest, RequestCommitAfterBeginFrame)
// Tick should draw but then begin another frame.
timeSource->tick();
+ EXPECT_FALSE(timeSource->active());
EXPECT_EQ(2, client.numActions());
EXPECT_STREQ("scheduledActionDrawAndSwap", client.action(0));
EXPECT_STREQ("scheduledActionBeginFrame", client.action(1));
@@ -175,15 +178,18 @@ TEST(CCSchedulerTest, RequestRedrawInsideDraw)
scheduler->setNeedsRedraw();
EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
EXPECT_EQ(0, client.numDraws());
timeSource->tick();
EXPECT_EQ(1, client.numDraws());
EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
timeSource->tick();
EXPECT_EQ(2, client.numDraws());
EXPECT_FALSE(scheduler->redrawPending());
+ EXPECT_FALSE(timeSource->active());
}
class SchedulerClientThatSetNeedsCommitInsideDraw : public CCSchedulerClient {
@@ -228,14 +234,17 @@ TEST(CCSchedulerTest, RequestCommitInsideDraw)
scheduler->setNeedsRedraw();
EXPECT_TRUE(scheduler->redrawPending());
EXPECT_EQ(0, client.numDraws());
+ EXPECT_TRUE(timeSource->active());
timeSource->tick();
+ EXPECT_FALSE(timeSource->active());
EXPECT_EQ(1, client.numDraws());
EXPECT_TRUE(scheduler->commitPending());
scheduler->beginFrameComplete();
timeSource->tick();
EXPECT_EQ(2, client.numDraws());
+ EXPECT_FALSE(timeSource->active());
EXPECT_FALSE(scheduler->redrawPending());
}
diff --git a/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h b/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h
index fcf703e51..9b5e0383e 100644
--- a/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h
+++ b/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h
@@ -91,6 +91,7 @@ public:
virtual void setClient(WebCore::CCTimeSourceClient* client) { m_client = client; }
virtual void setActive(bool b) { m_active = b; }
+ virtual bool active() const { return m_active; }
void tick()
{
diff --git a/Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp b/Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp
new file mode 100644
index 000000000..059ef2adc
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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/CCSolidColorLayerImpl.h"
+
+#include "CCLayerTestCommon.h"
+#include "cc/CCSingleThreadProxy.h"
+#include "cc/CCSolidColorDrawQuad.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+using namespace CCLayerTestCommon;
+
+namespace {
+
+TEST(CCSolidColorLayerImplTest, verifyTilingCompleteAndNoOverlap)
+{
+ DebugScopedSetImplThread scopedImplThread;
+
+ CCQuadList quadList;
+ IntSize layerSize = IntSize(800, 600);
+ IntRect visibleLayerRect = IntRect(IntPoint(), layerSize);
+
+ RefPtr<CCSolidColorLayerImpl> layer = CCSolidColorLayerImpl::create(0);
+ layer->setVisibleLayerRect(visibleLayerRect);
+ layer->setBounds(layerSize);
+
+ OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
+ layer->appendQuads(quadList, sharedQuadState.get());
+
+ verifyQuadsExactlyCoverRect(quadList, visibleLayerRect);
+}
+
+TEST(CCSolidColorLayerImplTest, verifyCorrectBackgroundColorInQuad)
+{
+ DebugScopedSetImplThread scopedImplThread;
+
+ const Color testColor = 0xFFA55AFF;
+
+ CCQuadList quadList;
+ IntSize layerSize = IntSize(100, 100);
+ IntRect visibleLayerRect = IntRect(IntPoint(), layerSize);
+
+ RefPtr<CCSolidColorLayerImpl> layer = CCSolidColorLayerImpl::create(0);
+ layer->setVisibleLayerRect(visibleLayerRect);
+ layer->setBounds(layerSize);
+ layer->setBackgroundColor(testColor);
+
+ OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
+ layer->appendQuads(quadList, sharedQuadState.get());
+
+ ASSERT_EQ(quadList.size(), 1U);
+ EXPECT_EQ(quadList[0]->toSolidColorDrawQuad()->color(), testColor);
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp b/Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp
index a2eea9440..d55c0bc16 100644
--- a/Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp
@@ -26,13 +26,14 @@
#include "cc/CCTiledLayerImpl.h"
-#include "Region.h"
+#include "CCLayerTestCommon.h"
#include "cc/CCSingleThreadProxy.h"
#include "cc/CCTileDrawQuad.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace CCLayerTestCommon;
namespace {
@@ -46,11 +47,12 @@ static PassRefPtr<CCTiledLayerImpl> createLayer(const IntSize& tileSize, const I
layer->setTilingData(*tiler);
layer->setSkipsDraw(false);
layer->setVisibleLayerRect(IntRect(IntPoint(), layerSize));
+ layer->setDrawOpacity(1);
int textureId = 1;
for (int i = 0; i < tiler->numTilesX(); ++i)
for (int j = 0; j < tiler->numTilesY(); ++j)
- layer->syncTextureId(i, j, static_cast<Platform3DObject>(textureId++));
+ layer->pushTileProperties(i, j, static_cast<Platform3DObject>(textureId++), IntRect(0, 0, 1, 1));
return layer.release();
}
@@ -134,7 +136,7 @@ TEST(CCTiledLayerImplTest, checkerboarding)
for (int i = 0; i < numTilesX; ++i)
for (int j = 0; j < numTilesY; ++j)
- layer->syncTextureId(i, j, static_cast<Platform3DObject>(0));
+ layer->pushTileProperties(i, j, static_cast<Platform3DObject>(0), IntRect());
// All checkerboarding
{
@@ -146,16 +148,7 @@ TEST(CCTiledLayerImplTest, checkerboarding)
}
}
-static bool completelyContains(const Region& container, const IntRect& rect)
-{
- Region tester(rect);
- Vector<IntRect> rects = container.rects();
- for (size_t i = 0; i < rects.size(); ++i)
- tester.subtract(rects[i]);
- return tester.isEmpty();
-}
-
-static void getQuads(CCQuadList& quads, IntSize tileSize, const IntSize& layerSize, CCLayerTilingData::BorderTexelOption borderTexelOption, const IntRect& visibleLayerRect)
+static PassOwnPtr<CCSharedQuadState> getQuads(CCQuadList& quads, IntSize tileSize, const IntSize& layerSize, CCLayerTilingData::BorderTexelOption borderTexelOption, const IntRect& visibleLayerRect)
{
RefPtr<CCTiledLayerImpl> layer = createLayer(tileSize, layerSize, borderTexelOption);
layer->setVisibleLayerRect(visibleLayerRect);
@@ -163,24 +156,7 @@ static void getQuads(CCQuadList& quads, IntSize tileSize, const IntSize& layerSi
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
layer->appendQuads(quads, sharedQuadState.get());
-}
-
-// Align with expected and actual output
-static const char* quadString = " Quad: ";
-
-static void verifyQuadsExactlyCoverRect(const CCQuadList& quads, const IntRect& rect)
-{
- Region remaining(rect);
-
- for (size_t i = 0; i < quads.size(); ++i) {
- CCDrawQuad* quad = quads[i].get();
-
- EXPECT_TRUE(rect.contains(quad->quadRect())) << quadString << i;
- EXPECT_TRUE(completelyContains(remaining, quad->quadRect())) << quadString << i;
- remaining.subtract(Region(quad->quadRect()));
- }
-
- EXPECT_TRUE(remaining.isEmpty());
+ return sharedQuadState.release(); // The shared data must be owned as long as the quad list exists.
}
// Test with both border texels and without.
@@ -200,7 +176,8 @@ static void coverageVisibleRectOnTileBoundaries(CCLayerTilingData::BorderTexelOp
IntSize layerSize(1000, 1000);
CCQuadList quads;
- getQuads(quads, IntSize(100, 100), layerSize, borders, IntRect(IntPoint(), layerSize));
+ OwnPtr<CCSharedQuadState> sharedState;
+ sharedState = getQuads(quads, IntSize(100, 100), layerSize, borders, IntRect(IntPoint(), layerSize));
verifyQuadsExactlyCoverRect(quads, IntRect(IntPoint(), layerSize));
}
WITH_AND_WITHOUT_BORDER_TEST(coverageVisibleRectOnTileBoundaries);
@@ -216,7 +193,8 @@ static void coverageVisibleRectIntersectsTiles(CCLayerTilingData::BorderTexelOpt
IntSize layerSize(250, 250);
CCQuadList quads;
- getQuads(quads, IntSize(50, 50), IntSize(250, 250), CCLayerTilingData::NoBorderTexels, visibleLayerRect);
+ OwnPtr<CCSharedQuadState> sharedState;
+ sharedState = getQuads(quads, IntSize(50, 50), IntSize(250, 250), CCLayerTilingData::NoBorderTexels, visibleLayerRect);
verifyQuadsExactlyCoverRect(quads, visibleLayerRect);
}
WITH_AND_WITHOUT_BORDER_TEST(coverageVisibleRectIntersectsTiles);
@@ -228,7 +206,8 @@ static void coverageVisibleRectIntersectsBounds(CCLayerTilingData::BorderTexelOp
IntSize layerSize(220, 210);
IntRect visibleLayerRect(IntPoint(), layerSize);
CCQuadList quads;
- getQuads(quads, IntSize(100, 100), layerSize, CCLayerTilingData::NoBorderTexels, visibleLayerRect);
+ OwnPtr<CCSharedQuadState> sharedState;
+ sharedState = getQuads(quads, IntSize(100, 100), layerSize, CCLayerTilingData::NoBorderTexels, visibleLayerRect);
verifyQuadsExactlyCoverRect(quads, visibleLayerRect);
}
WITH_AND_WITHOUT_BORDER_TEST(coverageVisibleRectIntersectsBounds);
@@ -240,7 +219,8 @@ TEST(CCTiledLayerImplTest, textureInfoForLayerNoBorders)
IntSize tileSize(50, 50);
IntSize layerSize(250, 250);
CCQuadList quads;
- getQuads(quads, tileSize, layerSize, CCLayerTilingData::NoBorderTexels, IntRect(IntPoint(), layerSize));
+ OwnPtr<CCSharedQuadState> sharedState;
+ sharedState = getQuads(quads, tileSize, layerSize, CCLayerTilingData::NoBorderTexels, IntRect(IntPoint(), layerSize));
for (size_t i = 0; i < quads.size(); ++i) {
ASSERT_EQ(quads[i]->material(), CCDrawQuad::TiledContent) << quadString << i;
@@ -249,8 +229,95 @@ TEST(CCTiledLayerImplTest, textureInfoForLayerNoBorders)
EXPECT_NE(quad->textureId(), 0u) << quadString << i;
EXPECT_EQ(quad->textureOffset(), IntPoint()) << quadString << i;
EXPECT_EQ(quad->textureSize(), tileSize) << quadString << i;
+ EXPECT_EQ(IntRect(0, 0, 1, 1), quad->opaqueRect()) << quadString << i;
+ }
+}
+
+TEST(CCTiledLayerImplTest, tileOpaqueRectForLayerNoBorders)
+{
+ DebugScopedSetImplThread scopedImplThread;
+
+ IntSize tileSize(50, 50);
+ IntSize layerSize(250, 250);
+ CCQuadList quads;
+ OwnPtr<CCSharedQuadState> sharedState;
+ sharedState = getQuads(quads, tileSize, layerSize, CCLayerTilingData::NoBorderTexels, IntRect(IntPoint(), layerSize));
+
+ for (size_t i = 0; i < quads.size(); ++i) {
+ ASSERT_EQ(quads[i]->material(), CCDrawQuad::TiledContent) << quadString << i;
+ CCTileDrawQuad* quad = static_cast<CCTileDrawQuad*>(quads[i].get());
+
+ EXPECT_EQ(IntRect(0, 0, 1, 1), quad->opaqueRect()) << quadString << i;
}
}
+TEST(CCTiledLayerImplTest, backgroundCoversViewport)
+{
+ DebugScopedSetImplThread scopedImplThread;
+
+ const IntSize tileSize(10, 10);
+ const int numTilesX = 2;
+ const int numTilesY = 2;
+ const unsigned numTiles = numTilesX * numTilesY;
+ const IntSize layerSize(tileSize.width() * numTilesX, tileSize.height() * numTilesY);
+ RefPtr<CCTiledLayerImpl> layer = createLayer(tileSize, layerSize, CCLayerTilingData::NoBorderTexels);
+ layer->setBackgroundColor(Color::gray);
+ layer->setBackgroundCoversViewport(true);
+
+ // No gutter rects
+ {
+ IntRect clipRect = IntRect(IntPoint(), layerSize);
+ layer->setClipRect(clipRect);
+ layer->setVisibleLayerRect(IntRect(IntPoint(), layerSize));
+
+ OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
+
+ CCQuadList quads;
+ layer->appendQuads(quads, sharedQuadState.get());
+ EXPECT_EQ(quads.size(), numTiles);
+
+ for (size_t i = 0; i < quads.size(); ++i)
+ EXPECT_EQ(quads[i]->material(), CCDrawQuad::TiledContent);
+ }
+
+ // Empty visible content area (fullscreen gutter rect)
+ {
+ IntRect clipRect = IntRect(100, 100, 100, 100);
+ layer->setClipRect(clipRect);
+ layer->setVisibleLayerRect(IntRect());
+
+ OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
+ CCQuadList quads;
+ layer->appendQuads(quads, sharedQuadState.get());
+
+ for (size_t i = 0; i < quads.size(); ++i)
+ EXPECT_EQ(quads[i]->material(), CCDrawQuad::SolidColor);
+
+ verifyQuadsExactlyCoverRect(quads, clipRect);
+ }
+
+ // Content area in middle of clip rect (four surrounding gutter rects)
+ {
+ IntRect clipRect = IntRect(-50, -50, 100, 100);
+ layer->setClipRect(clipRect);
+ layer->setVisibleLayerRect(IntRect(IntPoint(), layerSize));
+
+ OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
+ CCQuadList quads;
+ layer->appendQuads(quads, sharedQuadState.get());
+
+ unsigned numContentTiles = 0, numGutterTiles = 0;
+ for (size_t i = 0; i < quads.size(); ++i) {
+ if (quads[i]->material() == CCDrawQuad::TiledContent)
+ numContentTiles++;
+ else if (quads[i]->material() == CCDrawQuad::SolidColor)
+ numGutterTiles++;
+ }
+ EXPECT_EQ(numContentTiles, numTiles);
+ EXPECT_GE(numGutterTiles, 4u);
+
+ verifyQuadsExactlyCoverRect(quads, clipRect);
+ }
+}
} // namespace
diff --git a/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
index f0b5c411b..1df27c011 100644
--- a/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
@@ -29,6 +29,7 @@
#include "CCSchedulerTestCommon.h"
#include "FakeWebGraphicsContext3D.h"
#include "GraphicsContext3DPrivate.h"
+#include "Region.h"
#include "TextureManager.h"
#include "cc/CCCanvasLayerImpl.h"
#include "cc/CCSingleThreadProxy.h"
@@ -138,7 +139,8 @@ protected:
canvas->contentChanged();
EXPECT_TRUE(canvas->needsDisplay());
- canvas->paintContentsIfDirty();
+ Region occludedScreenSpace;
+ canvas->paintContentsIfDirty(occludedScreenSpace);
EXPECT_FALSE(canvas->needsDisplay());
{
DebugScopedSetImplThread scopedImplThread;
diff --git a/Source/WebKit/chromium/tests/ClipboardChromiumTest.cpp b/Source/WebKit/chromium/tests/ClipboardChromiumTest.cpp
new file mode 100644
index 000000000..24c11a4ec
--- /dev/null
+++ b/Source/WebKit/chromium/tests/ClipboardChromiumTest.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 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 "ClipboardChromium.h"
+
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+#if OS(WINDOWS)
+const char invalidCharacters[] = "\x00/\\:*?\"<>|";
+#else
+const char invalidCharacters[] =
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "\x7f/";
+#endif
+const char longString[] =
+ "0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,"
+ "75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352";
+
+TEST(ClipboardChromiumTest, Normal)
+{
+ String name = "name";
+ String extension = "ext";
+ ClipboardChromium::validateFilename(name, extension);
+ EXPECT_EQ("name", name);
+ EXPECT_EQ("ext", extension);
+}
+
+TEST(ClipboardChromiumTest, InvalidCharacters)
+{
+ String name = makeString("na", String(invalidCharacters, arraysize(invalidCharacters)), "me");
+ String extension = makeString("e", String(invalidCharacters, arraysize(invalidCharacters)), "xt");
+ ClipboardChromium::validateFilename(name, extension);
+ EXPECT_EQ("name", name);
+ EXPECT_EQ("ext", extension);
+}
+
+TEST(ClipboardChromiumTest, ExtensionTooLong)
+{
+ String name;
+ String extension = makeString(longString, longString);
+ ClipboardChromium::validateFilename(name, extension);
+ EXPECT_EQ(String(), extension);
+}
+
+TEST(ClipboardChromiumTest, NamePlusExtensionTooLong)
+{
+ String name = makeString(longString, longString);
+ String extension = longString;
+ ClipboardChromium::validateFilename(name, extension);
+ EXPECT_EQ("0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,109", name);
+ EXPECT_EQ(longString, extension);
+ EXPECT_EQ(254u, name.length() + extension.length());
+}
+
+} // anonymous namespace
diff --git a/Source/WebKit/chromium/tests/CompositorFakeWebGraphicsContext3D.h b/Source/WebKit/chromium/tests/CompositorFakeWebGraphicsContext3D.h
index de1409bd4..0790639d5 100644
--- a/Source/WebKit/chromium/tests/CompositorFakeWebGraphicsContext3D.h
+++ b/Source/WebKit/chromium/tests/CompositorFakeWebGraphicsContext3D.h
@@ -43,7 +43,7 @@ public:
virtual void getShaderiv(WebGLId, WGC3Denum, WGC3Dint* value) { *value = 1; }
virtual void getProgramiv(WebGLId, WGC3Denum, WGC3Dint* value) { *value = 1; }
-private:
+protected:
explicit CompositorFakeWebGraphicsContext3D(Attributes attrs)
{
m_attrs = attrs;
diff --git a/Source/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h b/Source/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h
new file mode 100755
index 000000000..23231038a
--- /dev/null
+++ b/Source/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+#ifndef FakeCCLayerTreeHostClient_h
+#define FakeCCLayerTreeHostClient_h
+
+#include "config.h"
+
+#include "cc/CCLayerTreeHost.h"
+#include "CompositorFakeGraphicsContext3D.h"
+
+namespace WebCore {
+
+class FakeCCLayerTreeHostClient : public CCLayerTreeHostClient {
+public:
+ virtual void updateAnimations(double frameBeginTime) { }
+ virtual void layout() { }
+ virtual void applyScrollAndScale(const IntSize& scrollDelta, float pageScale) { }
+ virtual PassRefPtr<GraphicsContext3D> createLayerTreeHostContext3D()
+ {
+ GraphicsContext3D::Attributes attrs;
+ return createCompositorMockGraphicsContext3D(attrs);
+ }
+ virtual void didRecreateGraphicsContext(bool success) { }
+ virtual void didCommitAndDrawFrame() { }
+ virtual void didCompleteSwapBuffers() { }
+
+ // Used only in the single-threaded path.
+ virtual void scheduleComposite() { }
+};
+
+}
+#endif // FakeCCLayerTreeHostClient_h
diff --git a/Source/WebKit/chromium/tests/FrameTestHelpers.cpp b/Source/WebKit/chromium/tests/FrameTestHelpers.cpp
index 1a1145631..ba6666699 100644
--- a/Source/WebKit/chromium/tests/FrameTestHelpers.cpp
+++ b/Source/WebKit/chromium/tests/FrameTestHelpers.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "FrameTestHelpers.h"
+#include "StdLibExtras.h"
#include "WebFrame.h"
#include "WebFrameClient.h"
#include "WebSettings.h"
@@ -71,7 +72,7 @@ class TestWebFrameClient : public WebFrameClient {
static WebFrameClient* defaultWebFrameClient()
{
- static TestWebFrameClient client;
+ DEFINE_STATIC_LOCAL(TestWebFrameClient, client, ());
return &client;
}
@@ -80,7 +81,7 @@ class TestWebViewClient : public WebViewClient {
static WebViewClient* defaultWebViewClient()
{
- static TestWebViewClient client;
+ DEFINE_STATIC_LOCAL(TestWebViewClient, client, ());
return &client;
}
diff --git a/Source/WebKit/chromium/tests/IDBBindingUtilitiesTest.cpp b/Source/WebKit/chromium/tests/IDBBindingUtilitiesTest.cpp
index 7de6a6c8f..adceadf08 100644
--- a/Source/WebKit/chromium/tests/IDBBindingUtilitiesTest.cpp
+++ b/Source/WebKit/chromium/tests/IDBBindingUtilitiesTest.cpp
@@ -159,7 +159,7 @@ TEST(InjectIDBKeyTest, SubProperty)
checkInjection(IDBKey::createArray(IDBKey::KeyArray()), SerializedScriptValue::create(object), "bar");
checkInjectionFails(IDBKey::createString("zoo"), SerializedScriptValue::create(object), "foo.bar.baz");
- checkInjectionFails(IDBKey::createString("zoo"), SerializedScriptValue::create(object), "foo.xyz.foo");
+ checkInjection(IDBKey::createString("zoo"), SerializedScriptValue::create(object), "foo.xyz.foo");
}
} // namespace
diff --git a/Source/WebKit/chromium/tests/ImageLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/ImageLayerChromiumTest.cpp
index b28f8e8b4..bf889594c 100644
--- a/Source/WebKit/chromium/tests/ImageLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/ImageLayerChromiumTest.cpp
@@ -41,8 +41,8 @@ class MockGraphicsLayerClient : public GraphicsLayerClient {
virtual void notifyAnimationStarted(const GraphicsLayer*, double time) { }
virtual void notifySyncRequired(const GraphicsLayer*) { }
virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) { }
- virtual bool showDebugBorders() const { return false; }
- virtual bool showRepaintCounter() const { return false; }
+ virtual bool showDebugBorders(const GraphicsLayer*) const { return false; }
+ virtual bool showRepaintCounter(const GraphicsLayer*) const { return false; }
};
class TestImage : public Image {
diff --git a/Source/WebKit/chromium/tests/KURLTest.cpp b/Source/WebKit/chromium/tests/KURLTest.cpp
index f2abda56b..394c664b1 100644
--- a/Source/WebKit/chromium/tests/KURLTest.cpp
+++ b/Source/WebKit/chromium/tests/KURLTest.cpp
@@ -316,7 +316,7 @@ TEST(KURLTest, Encode)
{"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
"%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F"},
{" !\"#$%&'()*+,-./",
- "%20!%22%23%24%25%26'()*%2B%2C-.%2F"},
+ "%20!%22%23%24%25%26'()*%2B%2C-./"},
{"0123456789:;<=>?",
"0123456789%3A%3B%3C%3D%3E%3F"},
{"@ABCDEFGHIJKLMNO",
diff --git a/Source/WebKit/chromium/tests/LayerChromiumTest.cpp b/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
index bc27c4329..43083a1d7 100644
--- a/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
@@ -28,6 +28,7 @@
#include "cc/CCLayerTreeHost.h"
#include "CCLayerTreeTestCommon.h"
+#include "FakeCCLayerTreeHostClient.h"
#include "LayerPainterChromium.h"
#include "NonCompositedContentHost.h"
#include "WebCompositor.h"
@@ -50,20 +51,6 @@ using ::testing::AnyNumber;
namespace {
-class FakeCCLayerTreeHostClient : public CCLayerTreeHostClient {
-public:
- virtual void updateAnimations(double frameBeginTime) { }
- virtual void layout() { }
- virtual void applyScrollAndScale(const IntSize& scrollDelta, float pageScale) { }
- virtual PassRefPtr<GraphicsContext3D> createLayerTreeHostContext3D() { return 0; }
- virtual void didRecreateGraphicsContext(bool success) { }
- virtual void didCommitAndDrawFrame() { }
- virtual void didCompleteSwapBuffers() { }
-
- // Used only in the single-threaded path.
- virtual void scheduleComposite() { }
-};
-
class MockCCLayerTreeHost : public CCLayerTreeHost {
public:
MockCCLayerTreeHost()
@@ -135,13 +122,13 @@ protected:
void createSimpleTestTree()
{
- m_parent = LayerChromium::create(0);
- m_child1 = LayerChromium::create(0);
- m_child2 = LayerChromium::create(0);
- m_child3 = LayerChromium::create(0);
- m_grandChild1 = LayerChromium::create(0);
- m_grandChild2 = LayerChromium::create(0);
- m_grandChild3 = LayerChromium::create(0);
+ m_parent = LayerChromium::create();
+ m_child1 = LayerChromium::create();
+ m_child2 = LayerChromium::create();
+ m_child3 = LayerChromium::create();
+ m_grandChild1 = LayerChromium::create();
+ m_grandChild2 = LayerChromium::create();
+ m_grandChild3 = LayerChromium::create();
EXPECT_CALL(*m_layerTreeHost, setNeedsCommit()).Times(AnyNumber());
m_layerTreeHost->setRootLayer(m_parent);
@@ -164,7 +151,7 @@ protected:
TEST_F(LayerChromiumTest, basicCreateAndDestroy)
{
- RefPtr<LayerChromium> testLayer = LayerChromium::create(0);
+ RefPtr<LayerChromium> testLayer = LayerChromium::create();
ASSERT_TRUE(testLayer);
EXPECT_CALL(*m_layerTreeHost, setNeedsCommit()).Times(0);
@@ -173,8 +160,8 @@ TEST_F(LayerChromiumTest, basicCreateAndDestroy)
TEST_F(LayerChromiumTest, addAndRemoveChild)
{
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
// Upon creation, layers should not have children or parent.
ASSERT_EQ(static_cast<size_t>(0), parent->children().size());
@@ -194,11 +181,11 @@ TEST_F(LayerChromiumTest, addAndRemoveChild)
TEST_F(LayerChromiumTest, insertChild)
{
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child1 = LayerChromium::create(0);
- RefPtr<LayerChromium> child2 = LayerChromium::create(0);
- RefPtr<LayerChromium> child3 = LayerChromium::create(0);
- RefPtr<LayerChromium> child4 = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child1 = LayerChromium::create();
+ RefPtr<LayerChromium> child2 = LayerChromium::create();
+ RefPtr<LayerChromium> child3 = LayerChromium::create();
+ RefPtr<LayerChromium> child4 = LayerChromium::create();
parent->setLayerTreeHost(m_layerTreeHost.get());
@@ -240,9 +227,9 @@ TEST_F(LayerChromiumTest, insertChild)
TEST_F(LayerChromiumTest, insertChildPastEndOfList)
{
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child1 = LayerChromium::create(0);
- RefPtr<LayerChromium> child2 = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child1 = LayerChromium::create();
+ RefPtr<LayerChromium> child2 = LayerChromium::create();
ASSERT_EQ(static_cast<size_t>(0), parent->children().size());
@@ -262,9 +249,9 @@ TEST_F(LayerChromiumTest, insertChildPastEndOfList)
TEST_F(LayerChromiumTest, insertSameChildTwice)
{
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child1 = LayerChromium::create(0);
- RefPtr<LayerChromium> child2 = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child1 = LayerChromium::create();
+ RefPtr<LayerChromium> child2 = LayerChromium::create();
parent->setLayerTreeHost(m_layerTreeHost.get());
@@ -291,7 +278,7 @@ TEST_F(LayerChromiumTest, insertSameChildTwice)
TEST_F(LayerChromiumTest, replaceChildWithNewChild)
{
createSimpleTestTree();
- RefPtr<LayerChromium> child4 = LayerChromium::create(0);
+ RefPtr<LayerChromium> child4 = LayerChromium::create();
EXPECT_FALSE(child4->parent());
@@ -311,8 +298,8 @@ TEST_F(LayerChromiumTest, replaceChildWithNewChildThatHasOtherParent)
createSimpleTestTree();
// create another simple tree with testLayer and child4.
- RefPtr<LayerChromium> testLayer = LayerChromium::create(0);
- RefPtr<LayerChromium> child4 = LayerChromium::create(0);
+ RefPtr<LayerChromium> testLayer = LayerChromium::create();
+ RefPtr<LayerChromium> child4 = LayerChromium::create();
testLayer->addChild(child4);
ASSERT_EQ(static_cast<size_t>(1), testLayer->children().size());
EXPECT_EQ(child4, testLayer->children()[0]);
@@ -356,11 +343,11 @@ TEST_F(LayerChromiumTest, removeAllChildren)
TEST_F(LayerChromiumTest, setChildren)
{
- RefPtr<LayerChromium> oldParent = LayerChromium::create(0);
- RefPtr<LayerChromium> newParent = LayerChromium::create(0);
+ RefPtr<LayerChromium> oldParent = LayerChromium::create();
+ RefPtr<LayerChromium> newParent = LayerChromium::create();
- RefPtr<LayerChromium> child1 = LayerChromium::create(0);
- RefPtr<LayerChromium> child2 = LayerChromium::create(0);
+ RefPtr<LayerChromium> child1 = LayerChromium::create();
+ RefPtr<LayerChromium> child2 = LayerChromium::create();
Vector<RefPtr<LayerChromium> > newChildren;
newChildren.append(child1);
@@ -390,7 +377,7 @@ TEST_F(LayerChromiumTest, getRootLayerAfterTreeManipulations)
// For this test we don't care about setNeedsCommit calls.
EXPECT_CALL(*m_layerTreeHost, setNeedsCommit()).Times(AtLeast(1));
- RefPtr<LayerChromium> child4 = LayerChromium::create(0);
+ RefPtr<LayerChromium> child4 = LayerChromium::create();
EXPECT_EQ(m_parent.get(), m_parent->rootLayer());
EXPECT_EQ(m_parent.get(), m_child1->rootLayer());
@@ -443,7 +430,7 @@ TEST_F(LayerChromiumTest, checkSetNeedsDisplayCausesCorrectBehavior)
// 1. sets needsDisplay flag appropriately.
// 2. indirectly calls setNeedsCommit, exactly once for each call to setNeedsDisplay.
- RefPtr<LayerChromium> testLayer = LayerChromium::create(0);
+ RefPtr<LayerChromium> testLayer = LayerChromium::create();
testLayer->setLayerTreeHost(m_layerTreeHost.get());
IntSize testBounds = IntSize(501, 508);
@@ -458,7 +445,7 @@ TEST_F(LayerChromiumTest, checkSetNeedsDisplayCausesCorrectBehavior)
// This is just initialization, but setNeedsCommit behavior is verified anyway to avoid warnings.
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setBounds(testBounds));
- testLayer = LayerChromium::create(0);
+ testLayer = LayerChromium::create();
testLayer->setLayerTreeHost(m_layerTreeHost.get());
EXPECT_FALSE(testLayer->needsDisplay());
@@ -477,43 +464,26 @@ TEST_F(LayerChromiumTest, checkSetNeedsDisplayCausesCorrectBehavior)
EXPECT_TRUE(testLayer->needsDisplay());
// Case 4: LayerChromium should accept dirty rects that go beyond its bounds.
- testLayer = LayerChromium::create(0);
+ testLayer = LayerChromium::create();
testLayer->setLayerTreeHost(m_layerTreeHost.get());
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setBounds(testBounds));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setNeedsDisplayRect(outOfBoundsDirtyRect));
EXPECT_TRUE(testLayer->needsDisplay());
// Case 5: setNeedsDisplay() without the dirty rect arg.
- testLayer = LayerChromium::create(0);
+ testLayer = LayerChromium::create();
testLayer->setLayerTreeHost(m_layerTreeHost.get());
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setBounds(testBounds));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setNeedsDisplay());
EXPECT_TRUE(testLayer->needsDisplay());
}
-TEST_F(LayerChromiumTest, checkSetNeedsDisplayWithNullDelegate)
-{
- RefPtr<LayerChromium> testLayer = LayerChromium::create(0);
- IntSize testBounds = IntSize(501, 508);
-
- FloatRect dirty = FloatRect(10.0f, 15.0f, 1.0f, 2.0f);
-
- testLayer->setBounds(testBounds);
- EXPECT_TRUE(testLayer->needsDisplay());
-
- testLayer = LayerChromium::create(0);
- EXPECT_FALSE(testLayer->needsDisplay());
-
- testLayer->setNeedsDisplayRect(dirty);
- EXPECT_TRUE(testLayer->needsDisplay());
-}
-
TEST_F(LayerChromiumTest, checkPropertyChangeCausesCorrectBehavior)
{
- RefPtr<LayerChromium> testLayer = LayerChromium::create(0);
+ RefPtr<LayerChromium> testLayer = LayerChromium::create();
testLayer->setLayerTreeHost(m_layerTreeHost.get());
- RefPtr<LayerChromium> dummyLayer = LayerChromium::create(0); // just a dummy layer for this test case.
+ RefPtr<LayerChromium> dummyLayer = LayerChromium::create(); // just a dummy layer for this test case.
// sanity check of initial test condition
EXPECT_FALSE(testLayer->needsDisplay());
@@ -536,6 +506,7 @@ TEST_F(LayerChromiumTest, checkPropertyChangeCausesCorrectBehavior)
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setAnchorPoint(FloatPoint(1.23f, 4.56f)));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setAnchorPointZ(0.7f));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setBackgroundColor(Color(0.4f, 0.4f, 0.4f)));
+ EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setBackgroundCoversViewport(true));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setMasksToBounds(true));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setMaskLayer(dummyLayer.get()));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setOpacity(0.5f));
@@ -558,8 +529,8 @@ TEST_F(LayerChromiumTest, checkPropertyChangeCausesCorrectBehavior)
class LayerChromiumWithContentScaling : public LayerChromium {
public:
- explicit LayerChromiumWithContentScaling(CCLayerDelegate* delegate)
- : LayerChromium(delegate)
+ explicit LayerChromiumWithContentScaling()
+ : LayerChromium()
{
}
@@ -576,7 +547,7 @@ public:
TEST_F(LayerChromiumTest, checkContentsScaleChangeTriggersNeedsDisplay)
{
- RefPtr<LayerChromiumWithContentScaling> testLayer = adoptRef(new LayerChromiumWithContentScaling(0));
+ RefPtr<LayerChromiumWithContentScaling> testLayer = adoptRef(new LayerChromiumWithContentScaling());
testLayer->setLayerTreeHost(m_layerTreeHost.get());
IntSize testBounds = IntSize(320, 240);
@@ -626,11 +597,11 @@ void assertLayerTreeHostMatchesForSubtree(LayerChromium* layer, CCLayerTreeHost*
TEST(LayerChromiumLayerTreeHostTest, enteringTree)
{
WebKit::WebCompositor::initialize(0);
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child = LayerChromium::create(0);
- RefPtr<LayerChromium> mask = LayerChromium::create(0);
- RefPtr<LayerChromium> replica = LayerChromium::create(0);
- RefPtr<LayerChromium> replicaMask = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> mask = LayerChromium::create();
+ RefPtr<LayerChromium> replica = LayerChromium::create();
+ RefPtr<LayerChromium> replicaMask = LayerChromium::create();
// Set up a detached tree of layers. The host pointer should be nil for these layers.
parent->addChild(child);
@@ -658,7 +629,7 @@ TEST(LayerChromiumLayerTreeHostTest, enteringTree)
TEST(LayerChromiumLayerTreeHostTest, addingLayerSubtree)
{
WebKit::WebCompositor::initialize(0);
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
RefPtr<FakeCCLayerTreeHost> layerTreeHost = FakeCCLayerTreeHost::create();
layerTreeHost->setRootLayer(parent.get());
@@ -666,16 +637,16 @@ TEST(LayerChromiumLayerTreeHostTest, addingLayerSubtree)
EXPECT_EQ(parent->layerTreeHost(), layerTreeHost.get());
// Adding a subtree to a layer already associated with a host should set the host pointer on all layers in that subtree.
- RefPtr<LayerChromium> child = LayerChromium::create(0);
- RefPtr<LayerChromium> grandChild = LayerChromium::create(0);
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild = LayerChromium::create();
child->addChild(grandChild);
// Masks, replicas, and replica masks should pick up the new host too.
- RefPtr<LayerChromium> childMask = LayerChromium::create(0);
+ RefPtr<LayerChromium> childMask = LayerChromium::create();
child->setMaskLayer(childMask.get());
- RefPtr<LayerChromium> childReplica = LayerChromium::create(0);
+ RefPtr<LayerChromium> childReplica = LayerChromium::create();
child->setReplicaLayer(childReplica.get());
- RefPtr<LayerChromium> childReplicaMask = LayerChromium::create(0);
+ RefPtr<LayerChromium> childReplicaMask = LayerChromium::create();
childReplica->setMaskLayer(childReplicaMask.get());
parent->addChild(child);
@@ -689,11 +660,11 @@ TEST(LayerChromiumLayerTreeHostTest, addingLayerSubtree)
TEST(LayerChromiumLayerTreeHostTest, changeHost)
{
WebKit::WebCompositor::initialize(0);
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> child = LayerChromium::create(0);
- RefPtr<LayerChromium> mask = LayerChromium::create(0);
- RefPtr<LayerChromium> replica = LayerChromium::create(0);
- RefPtr<LayerChromium> replicaMask = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> mask = LayerChromium::create();
+ RefPtr<LayerChromium> replica = LayerChromium::create();
+ RefPtr<LayerChromium> replicaMask = LayerChromium::create();
// Same setup as the previous test.
parent->addChild(child);
@@ -722,11 +693,11 @@ TEST(LayerChromiumLayerTreeHostTest, changeHost)
TEST(LayerChromiumLayerTreeHostTest, changeHostInSubtree)
{
WebKit::WebCompositor::initialize(0);
- RefPtr<LayerChromium> firstParent = LayerChromium::create(0);
- RefPtr<LayerChromium> firstChild = LayerChromium::create(0);
- RefPtr<LayerChromium> secondParent = LayerChromium::create(0);
- RefPtr<LayerChromium> secondChild = LayerChromium::create(0);
- RefPtr<LayerChromium> secondGrandChild = LayerChromium::create(0);
+ RefPtr<LayerChromium> firstParent = LayerChromium::create();
+ RefPtr<LayerChromium> firstChild = LayerChromium::create();
+ RefPtr<LayerChromium> secondParent = LayerChromium::create();
+ RefPtr<LayerChromium> secondChild = LayerChromium::create();
+ RefPtr<LayerChromium> secondGrandChild = LayerChromium::create();
// First put all children under the first parent and set the first host.
firstParent->addChild(firstChild);
@@ -759,13 +730,13 @@ TEST(LayerChromiumLayerTreeHostTest, changeHostInSubtree)
TEST(LayerChromiumLayerTreeHostTest, replaceMaskAndReplicaLayer)
{
WebKit::WebCompositor::initialize(0);
- RefPtr<LayerChromium> parent = LayerChromium::create(0);
- RefPtr<LayerChromium> mask = LayerChromium::create(0);
- RefPtr<LayerChromium> replica = LayerChromium::create(0);
- RefPtr<LayerChromium> maskChild = LayerChromium::create(0);
- RefPtr<LayerChromium> replicaChild = LayerChromium::create(0);
- RefPtr<LayerChromium> maskReplacement = LayerChromium::create(0);
- RefPtr<LayerChromium> replicaReplacement = LayerChromium::create(0);
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> mask = LayerChromium::create();
+ RefPtr<LayerChromium> replica = LayerChromium::create();
+ RefPtr<LayerChromium> maskChild = LayerChromium::create();
+ RefPtr<LayerChromium> replicaChild = LayerChromium::create();
+ RefPtr<LayerChromium> maskReplacement = LayerChromium::create();
+ RefPtr<LayerChromium> replicaReplacement = LayerChromium::create();
parent->setMaskLayer(mask.get());
parent->setReplicaLayer(replica.get());
diff --git a/Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp b/Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp
new file mode 100644
index 000000000..bdbf7bb09
--- /dev/null
+++ b/Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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 "LayerTextureUpdater.h"
+
+#include "BitmapCanvasLayerTextureUpdater.h"
+#include "BitmapSkPictureCanvasLayerTextureUpdater.h"
+#include "FrameBufferSkPictureCanvasLayerTextureUpdater.h"
+#include "GraphicsContext.h"
+#include "LayerPainterChromium.h"
+#include "PlatformContextSkia.h"
+#include "SkPictureCanvasLayerTextureUpdater.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+struct PaintCallback {
+ virtual void operator()(GraphicsContext&, const IntRect&) = 0;
+};
+
+class TestLayerPainterChromium : public LayerPainterChromium {
+public:
+ TestLayerPainterChromium(PaintCallback& callback) : m_callback(callback) { }
+
+ virtual void paint(GraphicsContext& context, const IntRect& contentRect)
+ {
+ m_callback(context, contentRect);
+ }
+
+ private:
+ PaintCallback& m_callback;
+};
+
+// Paint callback functions
+
+struct PaintFillOpaque : public PaintCallback {
+ virtual void operator()(GraphicsContext& context, const IntRect& contentRect)
+ {
+ Color opaque(255, 0, 0, 255);
+ IntRect top(contentRect.x(), contentRect.y(), contentRect.width(), contentRect.height() / 2);
+ IntRect bottom(contentRect.x(), contentRect.y() + contentRect.height() / 2, contentRect.width(), contentRect.height() / 2);
+ context.fillRect(top, opaque, ColorSpaceDeviceRGB);
+ context.fillRect(bottom, opaque, ColorSpaceDeviceRGB);
+ }
+};
+
+struct PaintFillAlpha : public PaintCallback {
+ virtual void operator()(GraphicsContext& context, const IntRect& contentRect)
+ {
+ Color alpha(0, 0, 0, 0);
+ context.fillRect(contentRect, alpha, ColorSpaceDeviceRGB);
+ }
+};
+
+#define EXPECT_EQ_RECT(a, b) \
+ EXPECT_EQ(a.x(), b.x()); \
+ EXPECT_EQ(a.maxX(), b.maxX()); \
+ EXPECT_EQ(a.y(), b.y()); \
+ EXPECT_EQ(a.maxY(), b.maxY());
+
+TEST(LayerTextureUpdaterTest, testOpaqueRectPresentAfterOpaquePaint)
+{
+ PaintFillOpaque fillOpaque;
+ RefPtr<LayerTextureUpdater> updater;
+ IntRect opaqueRect;
+ OwnPtr<TestLayerPainterChromium> painter;
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillOpaque));
+ updater = BitmapCanvasLayerTextureUpdater::create(painter.release(), false);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 400, 400), opaqueRect);
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillOpaque));
+ updater = BitmapSkPictureCanvasLayerTextureUpdater::create(painter.release(), false);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 400, 400), opaqueRect);
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillOpaque));
+ updater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(painter.release());
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 400, 400), opaqueRect);
+}
+
+TEST(LayerTextureUpdaterTest, testOpaqueRectNotPresentAfterNonOpaquePaint)
+{
+ PaintFillAlpha fillAlpha;
+ RefPtr<LayerTextureUpdater> updater;
+ IntRect opaqueRect;
+ OwnPtr<TestLayerPainterChromium> painter;
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillAlpha));
+ updater = BitmapCanvasLayerTextureUpdater::create(painter.release(), false);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillAlpha));
+ updater = BitmapSkPictureCanvasLayerTextureUpdater::create(painter.release(), false);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillAlpha));
+ updater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(painter.release());
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+}
+
+TEST(LayerTextureUpdaterTest, testOpaqueRectNotPresentForOpaqueLayerWithOpaquePaint)
+{
+ PaintFillOpaque fillOpaque;
+ RefPtr<LayerTextureUpdater> updater;
+ IntRect opaqueRect;
+ OwnPtr<TestLayerPainterChromium> painter;
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillOpaque));
+ updater = BitmapCanvasLayerTextureUpdater::create(painter.release(), false);
+ updater->setOpaque(true);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillOpaque));
+ updater = BitmapSkPictureCanvasLayerTextureUpdater::create(painter.release(), false);
+ updater->setOpaque(true);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillOpaque));
+ updater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(painter.release());
+ updater->setOpaque(true);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+}
+
+TEST(LayerTextureUpdaterTest, testOpaqueRectNotPresentForOpaqueLayerWithNonOpaquePaint)
+{
+ PaintFillAlpha fillAlpha;
+ RefPtr<LayerTextureUpdater> updater;
+ IntRect opaqueRect;
+ OwnPtr<TestLayerPainterChromium> painter;
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillAlpha));
+ updater = BitmapCanvasLayerTextureUpdater::create(painter.release(), false);
+ updater->setOpaque(true);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillAlpha));
+ updater = BitmapSkPictureCanvasLayerTextureUpdater::create(painter.release(), false);
+ updater->setOpaque(true);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+
+ opaqueRect = IntRect();
+ painter = adoptPtr(new TestLayerPainterChromium(fillAlpha));
+ updater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(painter.release());
+ updater->setOpaque(true);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, &opaqueRect);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/PaintAggregatorTest.cpp b/Source/WebKit/chromium/tests/PaintAggregatorTest.cpp
new file mode 100644
index 000000000..fcf374b47
--- /dev/null
+++ b/Source/WebKit/chromium/tests/PaintAggregatorTest.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2010 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 "painting/PaintAggregator.h"
+
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+using namespace WebKit;
+
+namespace {
+
+TEST(PaintAggregator, InitialState)
+{
+ PaintAggregator greg;
+ EXPECT_FALSE(greg.hasPendingUpdate());
+}
+
+TEST(PaintAggregator, SingleInvalidation)
+{
+ PaintAggregator greg;
+
+ IntRect rect(2, 4, 10, 16);
+ greg.invalidateRect(rect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.scrollRect.isEmpty());
+ ASSERT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(rect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, DoubleDisjointInvalidation)
+{
+ PaintAggregator greg;
+
+ IntRect r1(2, 4, 2, 40);
+ IntRect r2(4, 2, 40, 2);
+
+ greg.invalidateRect(r1);
+ greg.invalidateRect(r2);
+
+ IntRect expectedBounds = unionRect(r1, r2);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.scrollRect.isEmpty());
+ EXPECT_EQ(2U, update.paintRects.size());
+
+ EXPECT_EQ(expectedBounds, update.calculatePaintBounds());
+}
+
+TEST(PaintAggregator, DisjointInvalidationsCombined)
+{
+ PaintAggregator greg;
+
+ // Make the rectangles such that they don't overlap but cover a very large
+ // percentage of the area of covered by their union. This is so we're not
+ // very sensitive to the combining heuristic in the paint aggregator.
+ IntRect r1(2, 4, 2, 1000);
+ IntRect r2(5, 2, 2, 1000);
+
+ greg.invalidateRect(r1);
+ greg.invalidateRect(r2);
+
+ IntRect expectedBounds = unionRect(r1, r2);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.scrollRect.isEmpty());
+ ASSERT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(expectedBounds, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, SingleScroll)
+{
+ PaintAggregator greg;
+
+ IntRect rect(1, 2, 3, 4);
+ IntPoint delta(1, 0);
+ greg.scrollRect(delta.x(), delta.y(), rect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.paintRects.isEmpty());
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+
+ EXPECT_EQ(rect, update.scrollRect);
+
+ EXPECT_EQ(delta.x(), update.scrollDelta.x());
+ EXPECT_EQ(delta.y(), update.scrollDelta.y());
+
+ IntRect resultingDamage = update.calculateScrollDamage();
+ IntRect expectedDamage(1, 2, 1, 4);
+ EXPECT_EQ(expectedDamage, resultingDamage);
+}
+
+TEST(PaintAggregator, DoubleOverlappingScroll)
+{
+ PaintAggregator greg;
+
+ IntRect rect(1, 2, 3, 4);
+ IntPoint delta1(1, 0);
+ IntPoint delta2(1, 0);
+ greg.scrollRect(delta1.x(), delta1.y(), rect);
+ greg.scrollRect(delta2.x(), delta2.y(), rect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.paintRects.isEmpty());
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+
+ EXPECT_EQ(rect, update.scrollRect);
+
+ IntPoint expectedDelta(delta1.x() + delta2.x(),
+ delta1.y() + delta2.y());
+ EXPECT_EQ(expectedDelta.x(), update.scrollDelta.x());
+ EXPECT_EQ(expectedDelta.y(), update.scrollDelta.y());
+
+ IntRect resultingDamage = update.calculateScrollDamage();
+ IntRect expectedDamage(1, 2, 2, 4);
+ EXPECT_EQ(expectedDamage, resultingDamage);
+}
+
+TEST(PaintAggregator, NegatingScroll)
+{
+ PaintAggregator greg;
+
+ // Scroll twice in opposite directions by equal amounts. The result
+ // should be no scrolling.
+
+ IntRect rect(1, 2, 3, 4);
+ IntPoint delta1(1, 0);
+ IntPoint delta2(-1, 0);
+ greg.scrollRect(delta1.x(), delta1.y(), rect);
+ greg.scrollRect(delta2.x(), delta2.y(), rect);
+
+ EXPECT_FALSE(greg.hasPendingUpdate());
+}
+
+TEST(PaintAggregator, DiagonalScroll)
+{
+ PaintAggregator greg;
+
+ // We don't support optimized diagonal scrolling, so this should result in
+ // repainting.
+
+ IntRect rect(1, 2, 3, 4);
+ IntPoint delta(1, 1);
+ greg.scrollRect(delta.x(), delta.y(), rect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.scrollRect.isEmpty());
+ ASSERT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(rect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, ContainedPaintAfterScroll)
+{
+ PaintAggregator greg;
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(2, 0, scrollRect);
+
+ IntRect paintRect(4, 4, 2, 2);
+ greg.invalidateRect(paintRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ // expecting a paint rect inside the scroll rect
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(scrollRect, update.scrollRect);
+ EXPECT_EQ(paintRect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, ContainedPaintBeforeScroll)
+{
+ PaintAggregator greg;
+
+ IntRect paintRect(4, 4, 2, 2);
+ greg.invalidateRect(paintRect);
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(2, 0, scrollRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ // Expecting a paint rect inside the scroll rect
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ paintRect.move(2, 0);
+
+ EXPECT_EQ(scrollRect, update.scrollRect);
+ EXPECT_EQ(paintRect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, ContainedPaintsBeforeAndAfterScroll)
+{
+ PaintAggregator greg;
+
+ IntRect paintRect1(4, 4, 2, 2);
+ greg.invalidateRect(paintRect1);
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(2, 0, scrollRect);
+
+ IntRect paintRect2(6, 4, 2, 2);
+ greg.invalidateRect(paintRect2);
+
+ IntRect expectedPaintRect = paintRect2;
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ // Expecting a paint rect inside the scroll rect
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(scrollRect, update.scrollRect);
+ EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, LargeContainedPaintAfterScroll)
+{
+ PaintAggregator greg;
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(0, 1, scrollRect);
+
+ IntRect paintRect(0, 0, 10, 9); // Repaint 90%
+ greg.invalidateRect(paintRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(scrollRect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, LargeContainedPaintBeforeScroll)
+{
+ PaintAggregator greg;
+
+ IntRect paintRect(0, 0, 10, 9); // Repaint 90%
+ greg.invalidateRect(paintRect);
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(0, 1, scrollRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(scrollRect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, OverlappingPaintBeforeScroll)
+{
+ PaintAggregator greg;
+
+ IntRect paintRect(4, 4, 10, 2);
+ greg.invalidateRect(paintRect);
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(2, 0, scrollRect);
+
+ IntRect expectedPaintRect = unionRect(scrollRect, paintRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, OverlappingPaintAfterScroll)
+{
+ PaintAggregator greg;
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(2, 0, scrollRect);
+
+ IntRect paintRect(4, 4, 10, 2);
+ greg.invalidateRect(paintRect);
+
+ IntRect expectedPaintRect = unionRect(scrollRect, paintRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_TRUE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, DisjointPaintBeforeScroll)
+{
+ PaintAggregator greg;
+
+ IntRect paintRect(4, 4, 10, 2);
+ greg.invalidateRect(paintRect);
+
+ IntRect scrollRect(0, 0, 2, 10);
+ greg.scrollRect(2, 0, scrollRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(paintRect, update.paintRects[0]);
+ EXPECT_EQ(scrollRect, update.scrollRect);
+}
+
+TEST(PaintAggregator, DisjointPaintAfterScroll)
+{
+ PaintAggregator greg;
+
+ IntRect scrollRect(0, 0, 2, 10);
+ greg.scrollRect(2, 0, scrollRect);
+
+ IntRect paintRect(4, 4, 10, 2);
+ greg.invalidateRect(paintRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(paintRect, update.paintRects[0]);
+ EXPECT_EQ(scrollRect, update.scrollRect);
+}
+
+TEST(PaintAggregator, ContainedPaintTrimmedByScroll)
+{
+ PaintAggregator greg;
+
+ IntRect paintRect(4, 4, 6, 6);
+ greg.invalidateRect(paintRect);
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(2, 0, scrollRect);
+
+ // The paint rect should have become narrower.
+ IntRect expectedPaintRect(6, 4, 4, 6);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
+ EXPECT_EQ(scrollRect, update.scrollRect);
+}
+
+TEST(PaintAggregator, ContainedPaintEliminatedByScroll)
+{
+ PaintAggregator greg;
+
+ IntRect paintRect(4, 4, 6, 6);
+ greg.invalidateRect(paintRect);
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(6, 0, scrollRect);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_TRUE(update.paintRects.isEmpty());
+
+ EXPECT_EQ(scrollRect, update.scrollRect);
+}
+
+TEST(PaintAggregator, ContainedPaintAfterScrollTrimmedByScrollDamage)
+{
+ PaintAggregator greg;
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(4, 0, scrollRect);
+
+ IntRect paintRect(2, 0, 4, 10);
+ greg.invalidateRect(paintRect);
+
+ IntRect expectedScrollDamage(0, 0, 4, 10);
+ IntRect expectedPaintRect(4, 0, 2, 10);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_EQ(1U, update.paintRects.size());
+
+ EXPECT_EQ(scrollRect, update.scrollRect);
+ EXPECT_EQ(expectedScrollDamage, update.calculateScrollDamage());
+ EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
+}
+
+TEST(PaintAggregator, ContainedPaintAfterScrollEliminatedByScrollDamage)
+{
+ PaintAggregator greg;
+
+ IntRect scrollRect(0, 0, 10, 10);
+ greg.scrollRect(4, 0, scrollRect);
+
+ IntRect paintRect(2, 0, 2, 10);
+ greg.invalidateRect(paintRect);
+
+ IntRect expectedScrollDamage(0, 0, 4, 10);
+
+ EXPECT_TRUE(greg.hasPendingUpdate());
+ PaintAggregator::PendingUpdate update;
+ greg.popPendingUpdate(&update);
+
+ EXPECT_FALSE(update.scrollRect.isEmpty());
+ EXPECT_TRUE(update.paintRects.isEmpty());
+
+ EXPECT_EQ(scrollRect, update.scrollRect);
+ EXPECT_EQ(expectedScrollDamage, update.calculateScrollDamage());
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp b/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp
new file mode 100644
index 000000000..0ff539023
--- /dev/null
+++ b/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp
@@ -0,0 +1,464 @@
+/*
+ * 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 "PlatformContextSkia.h"
+
+#include "BitmapImageSingleFrameSkia.h"
+#include "GraphicsContext.h"
+#include "NativeImageSkia.h"
+#include "SkCanvas.h"
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+#define EXPECT_EQ_RECT(a, b) \
+ EXPECT_EQ(a.x(), b.x()); \
+ EXPECT_EQ(a.maxX(), b.maxX()); \
+ EXPECT_EQ(a.y(), b.y()); \
+ EXPECT_EQ(a.maxY(), b.maxY());
+
+#define EXPECT_PIXELS_MATCH(bitmap, opaqueRect) \
+{ \
+ SkAutoLockPixels locker(bitmap); \
+ for (int y = opaqueRect.y(); y < opaqueRect.maxY(); ++y) \
+ for (int x = opaqueRect.x(); x < opaqueRect.maxX(); ++x) { \
+ int alpha = *bitmap.getAddr32(x, y) >> 24; \
+ EXPECT_EQ(255, alpha); \
+ } \
+}
+
+TEST(PlatformContextSkiaTest, trackOpaqueTest)
+{
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
+ bitmap.allocPixels();
+ SkCanvas canvas(bitmap);
+
+ PlatformContextSkia platformContext(&canvas);
+ platformContext.setTrackOpaqueRegion(true);
+ GraphicsContext context(&platformContext);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), alpha, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), opaque, ColorSpaceDeviceRGB, CompositePlusLighter);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), alpha, ColorSpaceDeviceRGB, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 10, 89, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(8, 8, 3, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOut);
+ EXPECT_EQ_RECT(IntRect(11, 10, 88, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(30, 30, 290, 290), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(40, 20, 290, 50), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), opaque, ColorSpaceDeviceRGB, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), alpha, ColorSpaceDeviceRGB);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 10, 290, 310), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+}
+
+TEST(PlatformContextSkiaTest, trackOpaqueJoinTest)
+{
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
+ bitmap.allocPixels();
+ SkCanvas canvas(bitmap);
+
+ PlatformContextSkia platformContext(&canvas);
+ platformContext.setTrackOpaqueRegion(true);
+ GraphicsContext context(&platformContext);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(31, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(30, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(20, 31, 20, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(20, 30, 20, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(9, 20, 10, 20), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(10, 20, 10, 20), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(10, 9, 30, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(10, 10, 30, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 30, 30), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+}
+
+TEST(PlatformContextSkiaTest, trackOpaqueLineTest)
+{
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
+ bitmap.allocPixels();
+ SkCanvas canvas(bitmap);
+
+ PlatformContextSkia platformContext(&canvas);
+ platformContext.setTrackOpaqueRegion(true);
+ GraphicsContext context(&platformContext);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.setShouldAntialias(false);
+ context.setMiterLimit(0);
+ context.setStrokeThickness(4);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+ context.setCompositeOperation(CompositeSourceOver);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.save();
+ context.setStrokeColor(alpha, ColorSpaceDeviceRGB);
+ context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(opaque, ColorSpaceDeviceRGB);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha, ColorSpaceDeviceRGB);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha, ColorSpaceDeviceRGB);
+ context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+ context.setCompositeOperation(CompositeSourceOver);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.save();
+ context.setStrokeColor(alpha, ColorSpaceDeviceRGB);
+ context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setShouldAntialias(false);
+ context.save();
+ context.setStrokeColor(opaque, ColorSpaceDeviceRGB);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+ context.save();
+ context.setStrokeColor(opaque, ColorSpaceDeviceRGB);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha, ColorSpaceDeviceRGB);
+ context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+}
+
+TEST(PlatformContextSkiaTest, trackOpaquePathTest)
+{
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
+ bitmap.allocPixels();
+ SkCanvas canvas(bitmap);
+
+ PlatformContextSkia platformContext(&canvas);
+ platformContext.setTrackOpaqueRegion(true);
+ GraphicsContext context(&platformContext);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+ context.setCompositeOperation(CompositeSourceIn);
+
+ Path path;
+
+ context.setFillColor(alpha, ColorSpaceDeviceRGB);
+ path.moveTo(FloatPoint(0, 0));
+ path.addLineTo(FloatPoint(100, 0));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(opaque, ColorSpaceDeviceRGB);
+ path.moveTo(FloatPoint(0, 10));
+ path.addLineTo(FloatPoint(100, 13));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(alpha, ColorSpaceDeviceRGB);
+ path.moveTo(FloatPoint(0, 10));
+ path.addLineTo(FloatPoint(100, 13));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(alpha, ColorSpaceDeviceRGB);
+ path.moveTo(FloatPoint(0, 14));
+ path.addLineTo(FloatPoint(100, 10));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ path.clear();
+}
+
+TEST(PlatformContextSkiaTest, trackOpaqueImageTest)
+{
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
+ bitmap.allocPixels();
+ SkCanvas canvas(bitmap);
+
+ PlatformContextSkia platformContext(&canvas);
+ platformContext.setTrackOpaqueRegion(true);
+ GraphicsContext context(&platformContext);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ SkBitmap drawBitmap;
+ drawBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
+ drawBitmap.allocPixels();
+
+ drawBitmap.setIsOpaque(true);
+ for (int y = 0; y < drawBitmap.height(); ++y)
+ for (int x = 0; x < drawBitmap.width(); ++x)
+ *drawBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+ RefPtr<BitmapImageSingleFrameSkia> opaqueImage = BitmapImageSingleFrameSkia::create(drawBitmap, true);
+ EXPECT_FALSE(opaqueImage->currentFrameHasAlpha());
+
+ drawBitmap.setIsOpaque(false);
+ for (int y = 0; y < drawBitmap.height(); ++y)
+ for (int x = 0; x < drawBitmap.width(); ++x)
+ *drawBitmap.getAddr32(x, y) = 0x00000000;
+ RefPtr<BitmapImageSingleFrameSkia> alphaImage = BitmapImageSingleFrameSkia::create(drawBitmap, true);
+ EXPECT_TRUE(alphaImage->currentFrameHasAlpha());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), ColorSpaceDeviceRGB, IntPoint(0, 0));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), ColorSpaceDeviceRGB, IntPoint(0, 0));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), ColorSpaceDeviceRGB, IntPoint(5, 5));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), ColorSpaceDeviceRGB, IntPoint(5, 5));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), ColorSpaceDeviceRGB, IntPoint(10, 10));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), ColorSpaceDeviceRGB, IntPoint(10, 10));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.drawImage(alphaImage.get(), ColorSpaceDeviceRGB, IntPoint(20, 10), CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.save();
+ context.setAlpha(0.5);
+ context.drawImage(opaqueImage.get(), ColorSpaceDeviceRGB, IntPoint(25, 15), CompositeSourceIn);
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 25, 90, 75), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.drawImage(alphaImage.get(), ColorSpaceDeviceRGB, IntPoint(10, 20), CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(20, 10, 80, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.save();
+ context.setAlpha(0.5);
+ context.drawImage(opaqueImage.get(), ColorSpaceDeviceRGB, IntPoint(15, 25), CompositeSourceIn);
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(25, 10, 75, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+}
+
+TEST(PlatformContextSkiaTest, trackOpaqueOvalTest)
+{
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
+ bitmap.allocPixels();
+ SkCanvas canvas(bitmap);
+
+ PlatformContextSkia platformContext(&canvas);
+ platformContext.setTrackOpaqueRegion(true);
+ GraphicsContext context(&platformContext);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.drawEllipse(IntRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.setShouldAntialias(false);
+
+ context.setFillColor(opaque, ColorSpaceDeviceRGB);
+ context.drawEllipse(IntRect(10, 10, 50, 30));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setFillColor(alpha, ColorSpaceDeviceRGB);
+ context.drawEllipse(IntRect(10, 10, 30, 50));
+ EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+
+ context.setFillColor(opaque, ColorSpaceDeviceRGB);
+ context.drawEllipse(IntRect(10, 10, 50, 30));
+ EXPECT_EQ_RECT(IntRect(40, 41, 60, 59), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+
+ context.setFillColor(alpha, ColorSpaceDeviceRGB);
+ context.drawEllipse(IntRect(20, 10, 30, 50));
+ EXPECT_EQ_RECT(IntRect(51, 41, 49, 59), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/TextureManagerTest.cpp b/Source/WebKit/chromium/tests/TextureManagerTest.cpp
index 7c088dabc..6fe616c24 100644
--- a/Source/WebKit/chromium/tests/TextureManagerTest.cpp
+++ b/Source/WebKit/chromium/tests/TextureManagerTest.cpp
@@ -35,34 +35,49 @@ namespace {
class FakeTextureAllocator : public TextureAllocator {
public:
+ virtual ~FakeTextureAllocator() { }
virtual unsigned createTexture(const IntSize&, GC3Denum) { return 1; }
virtual void deleteTexture(unsigned, const IntSize&, GC3Denum) { }
};
-FakeTextureAllocator fakeTextureAllocator;
-const IntSize textureSize(256, 256);
-const GC3Denum textureFormat = GraphicsContext3D::RGBA;
+class TextureManagerTest : public testing::Test {
+public:
+ TextureManagerTest()
+ : m_textureSize(256, 256)
+ , m_textureFormat(GraphicsContext3D::RGBA)
+ {
+ }
-size_t texturesMemorySize(size_t textureCount)
-{
- return TextureManager::memoryUseBytes(textureSize, textureFormat) * textureCount;
-}
+ virtual ~TextureManagerTest()
+ {
+ }
-PassOwnPtr<TextureManager> createTextureManager(size_t maxTextures, size_t preferredTextures)
-{
- return TextureManager::create(texturesMemorySize(maxTextures), texturesMemorySize(preferredTextures), 1024);
-}
+ size_t texturesMemorySize(size_t textureCount)
+ {
+ return TextureManager::memoryUseBytes(m_textureSize, m_textureFormat) * textureCount;
+ }
-bool requestTexture(TextureManager* manager, TextureToken token)
-{
- unsigned textureId;
- bool result = manager->requestTexture(token, textureSize, textureFormat, textureId);
- if (result)
- manager->allocateTexture(&fakeTextureAllocator, token);
- return result;
-}
+ PassOwnPtr<TextureManager> createTextureManager(size_t maxTextures, size_t preferredTextures)
+ {
+ return TextureManager::create(texturesMemorySize(maxTextures), texturesMemorySize(preferredTextures), 1024);
+ }
+
+ bool requestTexture(TextureManager* manager, TextureToken token)
+ {
+ unsigned textureId;
+ bool result = manager->requestTexture(token, m_textureSize, m_textureFormat, textureId);
+ if (result)
+ manager->allocateTexture(&m_fakeTextureAllocator, token);
+ return result;
+ }
+
+private:
+ FakeTextureAllocator m_fakeTextureAllocator;
+ const IntSize m_textureSize;
+ const GC3Denum m_textureFormat;
+};
-TEST(TextureManagerTest, requestTextureInPreferredLimit)
+TEST_F(TextureManagerTest, requestTextureInPreferredLimit)
{
const size_t preferredTextures = 8;
OwnPtr<TextureManager> textureManager = createTextureManager(preferredTextures * 2, preferredTextures);
@@ -82,7 +97,7 @@ TEST(TextureManagerTest, requestTextureInPreferredLimit)
EXPECT_EQ(texturesMemorySize(preferredTextures), textureManager->currentMemoryUseBytes());
}
-TEST(TextureManagerTest, requestTextureExceedingPreferredLimit)
+TEST_F(TextureManagerTest, requestTextureExceedingPreferredLimit)
{
const size_t maxTextures = 8;
const size_t preferredTextures = 4;
@@ -114,7 +129,7 @@ TEST(TextureManagerTest, requestTextureExceedingPreferredLimit)
EXPECT_EQ(texturesMemorySize(preferredTextures), textureManager->currentMemoryUseBytes());
}
-TEST(TextureManagerTest, requestTextureExceedingMaxLimit)
+TEST_F(TextureManagerTest, requestTextureExceedingMaxLimit)
{
const size_t maxTextures = 8;
const size_t preferredTextures = 4;
@@ -146,7 +161,7 @@ TEST(TextureManagerTest, requestTextureExceedingMaxLimit)
EXPECT_FALSE(textureManager->hasTexture(tokens[3]));
}
-TEST(TextureManagerTest, reduceMemoryToLimit)
+TEST_F(TextureManagerTest, reduceMemoryToLimit)
{
const size_t maxTextures = 8;
const size_t preferredTextures = 4;
@@ -179,7 +194,7 @@ TEST(TextureManagerTest, reduceMemoryToLimit)
EXPECT_EQ(texturesMemorySize(preferredTextures), textureManager->preferredMemoryLimitBytes());
}
-TEST(TextureManagerTest, setMaxMemoryLimitBytes)
+TEST_F(TextureManagerTest, setMaxMemoryLimitBytes)
{
const size_t maxTextures = 8;
const size_t preferredTextures = 4;
@@ -203,7 +218,7 @@ TEST(TextureManagerTest, setMaxMemoryLimitBytes)
EXPECT_EQ(texturesMemorySize(preferredTextures), textureManager->maxMemoryLimitBytes());
}
-TEST(TextureManagerTest, setPreferredMemoryLimitBytes)
+TEST_F(TextureManagerTest, setPreferredMemoryLimitBytes)
{
const size_t maxTextures = 8;
const size_t preferredTextures = 4;
diff --git a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
index 93e2ee8be..b0350db49 100644
--- a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
@@ -26,8 +26,12 @@
#include "TiledLayerChromium.h"
+#include "CCLayerTreeTestCommon.h"
+#include "FakeCCLayerTreeHostClient.h"
#include "LayerTextureUpdater.h"
+#include "Region.h"
#include "TextureManager.h"
+#include "WebCompositor.h"
#include "cc/CCSingleThreadProxy.h" // For DebugScopedSetImplThread
#include "cc/CCTextureUpdater.h"
#include "cc/CCTiledLayerImpl.h"
@@ -36,6 +40,12 @@
using namespace WebCore;
using namespace WTF;
+#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 {
class FakeTextureAllocator : public TextureAllocator {
@@ -44,6 +54,8 @@ public:
virtual void deleteTexture(unsigned, const IntSize&, GC3Denum) { }
};
+class FakeTiledLayerChromium;
+
class FakeLayerTextureUpdater : public LayerTextureUpdater {
public:
class Texture : public LayerTextureUpdater::Texture {
@@ -54,12 +66,32 @@ public:
virtual void updateRect(GraphicsContext3D*, TextureAllocator*, const IntRect&, const IntRect&) { }
};
- FakeLayerTextureUpdater() { }
+ FakeLayerTextureUpdater() : m_prepareCount(0) { }
virtual ~FakeLayerTextureUpdater() { }
+ // Sets the rect to invalidate during the next call to prepareToUpdate(). After the next
+ // call to prepareToUpdate() the rect is reset.
+ void setRectToInvalidate(const IntRect&, FakeTiledLayerChromium*);
+
+ // Number of times prepareToUpdate has been invoked.
+ int prepareCount() const { return m_prepareCount; }
+ void clearPrepareCount() { m_prepareCount = 0; }
+
+ void setOpaquePaintRect(const IntRect& opaquePaintRect) { m_opaquePaintRect = opaquePaintRect; }
+
+ // Last rect passed to prepareToUpdate().
+ const IntRect& lastUpdateRect() const { return m_lastUpdateRect; }
+
virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager* manager) { return adoptPtr(new Texture(ManagedTexture::create(manager))); }
virtual SampledTexelFormat sampledTexelFormat(GC3Denum) { return SampledTexelFormatRGBA; }
- virtual void prepareToUpdate(const IntRect&, const IntSize&, int, float) { }
+ virtual void prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect);
+
+private:
+ int m_prepareCount;
+ IntRect m_rectToInvalidate;
+ IntRect m_lastUpdateRect;
+ IntRect m_opaquePaintRect;
+ RefPtr<FakeTiledLayerChromium> m_layer;
};
class FakeCCTiledLayerImpl : public CCTiledLayerImpl {
@@ -77,7 +109,7 @@ public:
class FakeTiledLayerChromium : public TiledLayerChromium {
public:
explicit FakeTiledLayerChromium(TextureManager* textureManager)
- : TiledLayerChromium(0)
+ : TiledLayerChromium()
, m_fakeTextureUpdater(adoptRef(new FakeLayerTextureUpdater))
, m_textureManager(textureManager)
{
@@ -108,8 +140,20 @@ public:
return TiledLayerChromium::needsIdlePaint(rect);
}
+ bool skipsDraw() const
+ {
+ return TiledLayerChromium::skipsDraw();
+ }
+
+ FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); }
+
virtual TextureManager* textureManager() const { return m_textureManager; }
+ virtual void paintContentsIfDirty(const Region& /* occludedScreenSpace */)
+ {
+ prepareToUpdate(visibleLayerRect());
+ }
+
private:
virtual void createTextureUpdater(const CCLayerTreeHost*) { }
@@ -122,6 +166,40 @@ private:
TextureManager* m_textureManager;
};
+class FakeTiledLayerWithScaledBounds : public FakeTiledLayerChromium {
+public:
+ explicit FakeTiledLayerWithScaledBounds(TextureManager* textureManager)
+ : FakeTiledLayerChromium(textureManager)
+ {
+ }
+
+ void setContentBounds(const IntSize& contentBounds) { m_forcedContentBounds = contentBounds; }
+ virtual IntSize contentBounds() const { return m_forcedContentBounds; }
+
+ FloatRect updateRect() { return m_updateRect; }
+
+protected:
+ IntSize m_forcedContentBounds;
+};
+
+void FakeLayerTextureUpdater::setRectToInvalidate(const IntRect& rect, FakeTiledLayerChromium* layer)
+{
+ m_rectToInvalidate = rect;
+ m_layer = layer;
+}
+
+void FakeLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect)
+{
+ m_prepareCount++;
+ m_lastUpdateRect = contentRect;
+ if (!m_rectToInvalidate.isEmpty()) {
+ m_layer->invalidateRect(m_rectToInvalidate);
+ m_rectToInvalidate = IntRect();
+ m_layer = 0;
+ }
+ *resultingOpaqueRect = m_opaquePaintRect;
+}
+
TEST(TiledLayerChromiumTest, pushDirtyTiles)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
@@ -259,4 +337,231 @@ TEST(TiledLayerChromiumTest, idlePaintOutOfMemory)
layer->pushPropertiesTo(layerImpl.get());
}
+TEST(TiledLayerChromiumTest, invalidateFromPrepare)
+{
+ 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);
+
+ // The tile size is 100x100, so this invalidates and then paints two tiles.
+ layer->setBounds(IntSize(100, 200));
+ layer->invalidateRect(IntRect(0, 0, 100, 200));
+ layer->prepareToUpdate(IntRect(0, 0, 100, 200));
+ layer->updateCompositorResources(0, updater);
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should have both tiles on the impl side.
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
+
+ textureManager->unprotectAllTextures();
+
+ layer->fakeLayerTextureUpdater()->clearPrepareCount();
+ // Invoke prepareToUpdate again. As the layer is valid prepareToUpdate shouldn't be invoked on
+ // the LayerTextureUpdater.
+ layer->prepareToUpdate(IntRect(0, 0, 100, 200));
+ EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareCount());
+
+ layer->invalidateRect(IntRect(0, 0, 50, 50));
+ // setRectToInvalidate triggers invalidateRect() being invoked from prepareToUpdate.
+ layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(25, 25, 50, 50), layer.get());
+ layer->fakeLayerTextureUpdater()->clearPrepareCount();
+ layer->prepareToUpdate(IntRect(0, 0, 100, 200));
+ EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
+ layer->fakeLayerTextureUpdater()->clearPrepareCount();
+ // The layer should still be invalid as prepareToUpdate invoked invalidate.
+ layer->prepareToUpdate(IntRect(0, 0, 100, 200));
+ EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
+}
+
+TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled)
+{
+ // The updateRect (that indicates what was actually painted) should be in
+ // layer space, not the content space.
+
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerWithScaledBounds> layer = adoptRef(new FakeTiledLayerWithScaledBounds(textureManager.get()));
+
+ FakeTextureAllocator textureAllocator;
+ CCTextureUpdater updater(&textureAllocator);
+
+ IntRect layerBounds(0, 0, 300, 200);
+ IntRect contentBounds(0, 0, 200, 250);
+
+ layer->setBounds(layerBounds.size());
+ layer->setContentBounds(contentBounds.size());
+ layer->setVisibleLayerRect(contentBounds);
+
+ // On first update, the updateRect includes all tiles, even beyond the boundaries of the layer.
+ // However, it should still be in layer space, not content space.
+ layer->invalidateRect(contentBounds);
+ layer->prepareToUpdate(contentBounds);
+ layer->updateCompositorResources(0, updater);
+ EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 300, 300 * 0.8), layer->updateRect());
+
+ // After the tiles are updated once, another invalidate only needs to update the bounds of the layer.
+ layer->invalidateRect(contentBounds);
+ layer->prepareToUpdate(contentBounds);
+ layer->updateCompositorResources(0, updater);
+ EXPECT_FLOAT_RECT_EQ(FloatRect(layerBounds), layer->updateRect());
+
+ // Partial re-paint should also be represented by the updateRect in layer space, not content space.
+ IntRect partialDamage(30, 100, 10, 10);
+ layer->invalidateRect(partialDamage);
+ layer->prepareToUpdate(contentBounds);
+ layer->updateCompositorResources(0, updater);
+ EXPECT_FLOAT_RECT_EQ(FloatRect(45, 80, 15, 8), layer->updateRect());
+}
+
+TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
+{
+ // Initialize without threading support.
+ WebKit::WebCompositor::initialize(0);
+ FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
+ RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, CCSettings());
+
+ // Create two 300 x 300 tiled layers.
+ IntSize contentBounds(300, 300);
+ IntRect contentRect(IntPoint::zero(), contentBounds);
+
+ RefPtr<FakeTiledLayerChromium> rootLayer = adoptRef(new FakeTiledLayerChromium(ccLayerTreeHost->contentsTextureManager()));
+ RefPtr<FakeTiledLayerChromium> childLayer = adoptRef(new FakeTiledLayerChromium(ccLayerTreeHost->contentsTextureManager()));
+ rootLayer->addChild(childLayer);
+
+ rootLayer->setBounds(contentBounds);
+ rootLayer->setPosition(FloatPoint(150, 150));
+ childLayer->setBounds(contentBounds);
+ childLayer->setPosition(FloatPoint(150, 150));
+ rootLayer->invalidateRect(contentRect);
+ childLayer->invalidateRect(contentRect);
+
+ // We have enough memory for only one of the two layers.
+ int memoryLimit = 4 * 300 * 300; // 4 bytes per pixel.
+
+ FakeTextureAllocator textureAllocator;
+ CCTextureUpdater updater(&textureAllocator);
+
+ ccLayerTreeHost->setRootLayer(rootLayer);
+ ccLayerTreeHost->setViewportSize(IntSize(300, 300));
+ ccLayerTreeHost->contentsTextureManager()->setMaxMemoryLimitBytes(memoryLimit);
+ ccLayerTreeHost->updateLayers();
+ ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
+
+ // We'll skip the root layer.
+ EXPECT_TRUE(rootLayer->skipsDraw());
+ EXPECT_FALSE(childLayer->skipsDraw());
+
+ ccLayerTreeHost->commitComplete();
+
+ // Remove the child layer.
+ rootLayer->removeAllChildren();
+
+ // Need to set the max limit again as it gets overwritten by updateLayers().
+ ccLayerTreeHost->contentsTextureManager()->setMaxMemoryLimitBytes(memoryLimit);
+ ccLayerTreeHost->updateLayers();
+ EXPECT_FALSE(rootLayer->skipsDraw());
+
+ ccLayerTreeHost->setRootLayer(0);
+ ccLayerTreeHost.clear();
+ WebKit::WebCompositor::shutdown();
+}
+
+TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+
+ // The tile size is 100x100, so this invalidates and then paints two tiles in various ways.
+
+ Region occluded;
+ IntRect contentBounds = IntRect(0, 0, 100, 200);
+ IntRect visibleBounds = IntRect(0, 0, 100, 150);
+
+ layer->setBounds(contentBounds.size());
+ layer->setVisibleLayerRect(visibleBounds);
+ layer->setDrawOpacity(1);
+
+ // The screenSpaceTransform is verified in CCLayerTreeHostCommonTests
+ TransformationMatrix screenSpaceTransform;
+ layer->setScreenSpaceTransform(screenSpaceTransform);
+
+ // If the layer is opaque then the occluded region should be the whole layer's visible region.
+ layer->setOpaque(true);
+ layer->invalidateRect(contentBounds);
+ layer->prepareToUpdate(contentBounds);
+
+ occluded = Region();
+ layer->addSelfToOccludedScreenSpace(occluded);
+ EXPECT_EQ_RECT(visibleBounds, occluded.bounds());
+ EXPECT_EQ(1u, occluded.rects().size());
+
+ // If the layer is not opaque then the occluded region should be empty.
+ layer->setOpaque(false);
+ layer->invalidateRect(contentBounds);
+ layer->prepareToUpdate(contentBounds);
+
+ occluded = Region();
+ layer->addSelfToOccludedScreenSpace(occluded);
+ EXPECT_EQ_RECT(IntRect(), occluded.bounds());
+ EXPECT_EQ(1u, 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);
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
+ layer->invalidateRect(contentBounds);
+ layer->prepareToUpdate(contentBounds);
+
+ occluded = Region();
+ layer->addSelfToOccludedScreenSpace(occluded);
+ EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds());
+ EXPECT_EQ(1u, occluded.rects().size());
+
+ // If we paint again without invalidating, the same stuff should be occluded.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+ layer->prepareToUpdate(contentBounds);
+
+ occluded = Region();
+ layer->addSelfToOccludedScreenSpace(occluded);
+ EXPECT_EQ_RECT(intersection(opaquePaintRect, 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);
+ transform.rotate(90);
+ transform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
+ transform.translate(10, 10);
+ screenSpaceTransform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
+ screenSpaceTransform *= transform;
+ screenSpaceTransform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
+ layer->setScreenSpaceTransform(screenSpaceTransform);
+ layer->prepareToUpdate(contentBounds);
+
+ occluded = Region();
+ layer->addSelfToOccludedScreenSpace(occluded);
+ EXPECT_EQ_RECT(screenSpaceTransform.mapRect(intersection(opaquePaintRect, visibleBounds)), occluded.bounds());
+ EXPECT_EQ(1u, occluded.rects().size());
+
+ // But a non-axis-aligned transform does not get considered for occlusion.
+ transform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
+ transform.rotate(5);
+ transform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
+ screenSpaceTransform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
+ screenSpaceTransform *= transform;
+ screenSpaceTransform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
+ layer->setScreenSpaceTransform(screenSpaceTransform);
+ layer->prepareToUpdate(contentBounds);
+
+ occluded = Region();
+ layer->addSelfToOccludedScreenSpace(occluded);
+ // FIXME: If we find an opaque rect contained in the rotated non-axis-aligned rect, then
+ // this won't be an empty result.
+ EXPECT_EQ_RECT(IntRect(), occluded.bounds());
+ EXPECT_EQ(0u, occluded.rects().size());
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp b/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
index ca83846c2..1557a7d93 100644
--- a/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
+++ b/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
@@ -83,7 +83,7 @@ public:
}
private:
MockLayerChromium(Vector<int>* ccLayerDestructionList)
- : LayerChromium(0)
+ : LayerChromium()
, m_ccLayerDestructionList(ccLayerDestructionList)
{
}
@@ -119,9 +119,9 @@ void expectTreesAreIdentical(LayerChromium* layer, CCLayerImpl* ccLayer)
TEST(TreeSynchronizerTest, syncSimpleTreeFromEmpty)
{
DebugScopedSetImplThread impl;
- RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create(0);
- layerTreeRoot->addChild(LayerChromium::create(0));
- layerTreeRoot->addChild(LayerChromium::create(0));
+ RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create();
+ layerTreeRoot->addChild(LayerChromium::create());
+ layerTreeRoot->addChild(LayerChromium::create());
RefPtr<CCLayerImpl> ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), 0);
@@ -158,9 +158,9 @@ TEST(TreeSynchronizerTest, syncSimpleTreeReusingLayers)
TEST(TreeSynchronizerTest, syncSimpleTreeAndProperties)
{
DebugScopedSetImplThread impl;
- RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create(0);
- layerTreeRoot->addChild(LayerChromium::create(0));
- layerTreeRoot->addChild(LayerChromium::create(0));
+ RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create();
+ layerTreeRoot->addChild(LayerChromium::create());
+ layerTreeRoot->addChild(LayerChromium::create());
// Pick some random properties to set. The values are not important, we're just testing that at least some properties are making it through.
FloatPoint rootPosition = FloatPoint(2.3, 7.4);
@@ -254,7 +254,7 @@ TEST(TreeSynchronizerTest, syncSimpleTreeThenDestroy)
oldLayerTreeRoot->removeAllChildren();
// Synchronize again. After the sync all CCLayerImpls from the old tree should be deleted.
- RefPtr<LayerChromium> newLayerTreeRoot = LayerChromium::create(0);
+ RefPtr<LayerChromium> newLayerTreeRoot = LayerChromium::create();
ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(newLayerTreeRoot.get(), ccLayerTreeRoot.release());
expectTreesAreIdentical(newLayerTreeRoot.get(), ccLayerTreeRoot.get());
@@ -268,22 +268,22 @@ TEST(TreeSynchronizerTest, syncSimpleTreeThenDestroy)
TEST(TreeSynchronizerTest, syncMaskReplicaAndReplicaMaskLayers)
{
DebugScopedSetImplThread impl;
- RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create(0);
- layerTreeRoot->addChild(LayerChromium::create(0));
- layerTreeRoot->addChild(LayerChromium::create(0));
- layerTreeRoot->addChild(LayerChromium::create(0));
+ RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create();
+ layerTreeRoot->addChild(LayerChromium::create());
+ layerTreeRoot->addChild(LayerChromium::create());
+ layerTreeRoot->addChild(LayerChromium::create());
// First child gets a mask layer.
- RefPtr<LayerChromium> maskLayer = LayerChromium::create(0);
+ RefPtr<LayerChromium> maskLayer = LayerChromium::create();
layerTreeRoot->children()[0]->setMaskLayer(maskLayer.get());
// Second child gets a replica layer.
- RefPtr<LayerChromium> replicaLayer = LayerChromium::create(0);
+ RefPtr<LayerChromium> replicaLayer = LayerChromium::create();
layerTreeRoot->children()[1]->setReplicaLayer(replicaLayer.get());
// Third child gets a replica layer with a mask layer.
- RefPtr<LayerChromium> replicaLayerWithMask = LayerChromium::create(0);
- RefPtr<LayerChromium> replicaMaskLayer = LayerChromium::create(0);
+ RefPtr<LayerChromium> replicaLayerWithMask = LayerChromium::create();
+ RefPtr<LayerChromium> replicaMaskLayer = LayerChromium::create();
replicaLayerWithMask->setMaskLayer(replicaMaskLayer.get());
layerTreeRoot->children()[2]->setReplicaLayer(replicaLayerWithMask.get());
diff --git a/Source/WebKit/chromium/tests/WebFrameTest.cpp b/Source/WebKit/chromium/tests/WebFrameTest.cpp
index 2b2ea7601..06b26469a 100644
--- a/Source/WebKit/chromium/tests/WebFrameTest.cpp
+++ b/Source/WebKit/chromium/tests/WebFrameTest.cpp
@@ -33,9 +33,11 @@
#include "FrameTestHelpers.h"
#include "ResourceError.h"
#include "WebDocument.h"
+#include "WebFindOptions.h"
#include "WebFormElement.h"
#include "WebFrame.h"
#include "WebFrameClient.h"
+#include "WebRange.h"
#include "WebScriptSource.h"
#include "WebSearchableFormData.h"
#include "WebSecurityPolicy.h"
@@ -379,4 +381,54 @@ TEST_F(WebFrameTest, ContextNotificationsIsolatedWorlds)
EXPECT_EQ(1, matchCount);
}
+TEST_F(WebFrameTest, DISABLED_FindInPage)
+{
+ registerMockedHttpURLLoad("find.html");
+ WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "find.html");
+ WebFrame* frame = webView->mainFrame();
+ const int findIdentifier = 12345;
+ WebFindOptions options;
+
+ // Find in a <div> element.
+ EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar1"), options, false, 0));
+ frame->stopFinding(false);
+ WebRange range = frame->selectionRange();
+ EXPECT_EQ(5, range.startOffset());
+ EXPECT_EQ(9, range.endOffset());
+ EXPECT_TRUE(frame->document().focusedNode().isNull());
+
+ // Find in an <input> value.
+ EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar2"), options, false, 0));
+ // Confirm stopFinding(false) sets the selection on the found text.
+ frame->stopFinding(false);
+ range = frame->selectionRange();
+ ASSERT_FALSE(range.isNull());
+ EXPECT_EQ(5, range.startOffset());
+ EXPECT_EQ(9, range.endOffset());
+ EXPECT_EQ(WebString::fromUTF8("INPUT"), frame->document().focusedNode().nodeName());
+
+ // Find in a <textarea> content.
+ EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar3"), options, false, 0));
+ // Confirm stopFinding(false) sets the selection on the found text.
+ frame->stopFinding(false);
+ range = frame->selectionRange();
+ ASSERT_FALSE(range.isNull());
+ EXPECT_EQ(5, range.startOffset());
+ EXPECT_EQ(9, range.endOffset());
+ EXPECT_EQ(WebString::fromUTF8("TEXTAREA"), frame->document().focusedNode().nodeName());
+
+ // Find in a contentEditable element.
+ EXPECT_TRUE(frame->find(findIdentifier, WebString::fromUTF8("bar4"), options, false, 0));
+ // Confirm stopFinding(false) sets the selection on the found text.
+ frame->stopFinding(false);
+ range = frame->selectionRange();
+ ASSERT_FALSE(range.isNull());
+ EXPECT_EQ(0, range.startOffset());
+ EXPECT_EQ(4, range.endOffset());
+ // "bar4" is surrounded by <span>, but the focusable node should be the parent <div>.
+ EXPECT_EQ(WebString::fromUTF8("DIV"), frame->document().focusedNode().nodeName());
+
+ webView->close();
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/data/find.html b/Source/WebKit/chromium/tests/data/find.html
new file mode 100644
index 000000000..952c823fb
--- /dev/null
+++ b/Source/WebKit/chromium/tests/data/find.html
@@ -0,0 +1,6 @@
+<body>
+<div>foo1 bar1 baz1</div>
+<input value="foo2 bar2 baz2">
+<textarea>foo3 bar3 baz3</textarea>
+<div contentEditable="true">foo4 <span>bar4</span> baz4</div>
+</body>