summaryrefslogtreecommitdiff
path: root/Source/WebKit/chromium/tests
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
commit2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch)
tree988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebKit/chromium/tests
parentdd91e772430dc294e3bf478c119ef8d43c0a3358 (diff)
downloadqtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebKit/chromium/tests')
-rw-r--r--Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp42
-rw-r--r--Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp55
-rw-r--r--Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp57
-rw-r--r--Source/WebKit/chromium/tests/CCAnimationTestCommon.h50
-rw-r--r--Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp260
-rw-r--r--Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp82
-rw-r--r--Source/WebKit/chromium/tests/CCFrameRateControllerTest.cpp62
-rw-r--r--Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp396
-rw-r--r--Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp519
-rw-r--r--Source/WebKit/chromium/tests/CCLayerImplTest.cpp4
-rw-r--r--Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp2
-rw-r--r--Source/WebKit/chromium/tests/CCLayerSorterTest.cpp246
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp759
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp641
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp708
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeTestCommon.h8
-rw-r--r--Source/WebKit/chromium/tests/CCMathUtilTest.cpp102
-rw-r--r--Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp4681
-rw-r--r--Source/WebKit/chromium/tests/CCOcclusionTrackerTestCommon.h57
-rw-r--r--Source/WebKit/chromium/tests/CCQuadCullerTest.cpp397
-rw-r--r--Source/WebKit/chromium/tests/CCRenderSurfaceTest.cpp36
-rw-r--r--Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp357
-rw-r--r--Source/WebKit/chromium/tests/CCSchedulerTest.cpp316
-rw-r--r--Source/WebKit/chromium/tests/CCSchedulerTestCommon.h34
-rw-r--r--Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp40
-rw-r--r--Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp128
-rw-r--r--Source/WebKit/chromium/tests/CCTiledLayerTestCommon.cpp129
-rw-r--r--Source/WebKit/chromium/tests/CCTiledLayerTestCommon.h168
-rw-r--r--Source/WebKit/chromium/tests/CCTimerTest.cpp6
-rw-r--r--Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp125
-rw-r--r--Source/WebKit/chromium/tests/DrawingBufferChromiumTest.cpp (renamed from Source/WebKit/chromium/tests/WebGLLayerChromiumTest.cpp)16
-rwxr-xr-xSource/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h18
-rw-r--r--Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h13
-rw-r--r--Source/WebKit/chromium/tests/FloatQuadTest.cpp4
-rw-r--r--Source/WebKit/chromium/tests/FrameTestHelpers.cpp9
-rw-r--r--Source/WebKit/chromium/tests/FrameTestHelpers.h4
-rw-r--r--Source/WebKit/chromium/tests/LayerChromiumTest.cpp56
-rw-r--r--Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp277
-rw-r--r--Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp93
-rw-r--r--Source/WebKit/chromium/tests/LevelDBTest.cpp105
-rw-r--r--Source/WebKit/chromium/tests/LocaleWinTest.cpp163
-rw-r--r--Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp4
-rw-r--r--Source/WebKit/chromium/tests/MockCCQuadCuller.h65
-rw-r--r--Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp255
-rw-r--r--Source/WebKit/chromium/tests/PlatformGestureCurveTest.cpp34
-rw-r--r--Source/WebKit/chromium/tests/PopupMenuTest.cpp9
-rw-r--r--Source/WebKit/chromium/tests/RegionTest.cpp127
-rw-r--r--Source/WebKit/chromium/tests/RenderTableCellTest.cpp23
-rw-r--r--Source/WebKit/chromium/tests/RenderTableRowTest.cpp118
-rw-r--r--Source/WebKit/chromium/tests/ScrollAnimatorNoneTest.cpp22
-rw-r--r--Source/WebKit/chromium/tests/ScrollbarLayerChromiumTest.cpp2
-rw-r--r--Source/WebKit/chromium/tests/TextureCopierTest.cpp85
-rw-r--r--Source/WebKit/chromium/tests/TextureManagerTest.cpp9
-rw-r--r--Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp1046
-rwxr-xr-xSource/WebKit/chromium/tests/TilingDataTest.cpp686
-rw-r--r--Source/WebKit/chromium/tests/TransparencyWinTest.cpp60
-rw-r--r--Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp66
-rw-r--r--Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp614
-rw-r--r--Source/WebKit/chromium/tests/WebExternalTextureLayerImplTest.cpp51
-rw-r--r--Source/WebKit/chromium/tests/WebFrameTest.cpp44
-rw-r--r--Source/WebKit/chromium/tests/WebLayerTest.cpp7
-rw-r--r--Source/WebKit/chromium/tests/WebMediaPlayerClientImplTest.cpp120
-rw-r--r--Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp12
-rw-r--r--Source/WebKit/chromium/tests/WebViewTest.cpp125
-rw-r--r--Source/WebKit/chromium/tests/data/no_viewport_tag.html5
-rw-r--r--Source/WebKit/chromium/tests/data/specify_size.html16
66 files changed, 10437 insertions, 4393 deletions
diff --git a/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp b/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp
index a168ebca9..bdf3a3ab4 100644
--- a/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp
+++ b/Source/WebKit/chromium/tests/AssociatedURLLoaderTest.cpp
@@ -432,9 +432,40 @@ TEST_F(AssociatedURLLoaderTest, RedirectSuccess)
EXPECT_TRUE(m_didFinishLoading);
}
-// Test a successful redirect and cross-origin load using CORS.
-// FIXME: Enable this when DocumentThreadableLoader supports cross-origin redirects.
-TEST_F(AssociatedURLLoaderTest, DISABLED_RedirectCrossOriginWithAccessControlSuccess)
+// Test that a cross origin redirect response without CORS headers fails.
+TEST_F(AssociatedURLLoaderTest, RedirectCrossOriginWithAccessControlFailure)
+{
+ GURL url = GURL("http://www.test.com/RedirectCrossOriginWithAccessControlFailure.html");
+ char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlFailure.html"; // Cross-origin
+ GURL redirectURL = GURL(redirect);
+
+ WebURLRequest request;
+ request.initialize();
+ request.setURL(url);
+
+ // Create a redirect response without CORS headers.
+ m_expectedRedirectResponse = WebURLResponse();
+ m_expectedRedirectResponse.initialize();
+ m_expectedRedirectResponse.setMIMEType("text/html");
+ m_expectedRedirectResponse.setHTTPStatusCode(301);
+ m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
+ webkit_support::RegisterMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);
+
+ WebURLLoaderOptions options;
+ options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
+ m_expectedLoader = createAssociatedURLLoader(options);
+ EXPECT_TRUE(m_expectedLoader);
+ m_expectedLoader->loadAsynchronously(request, this);
+ serveRequests();
+ // We should not receive a notification for the redirect or any response.
+ EXPECT_FALSE(m_willSendRequest);
+ EXPECT_FALSE(m_didReceiveResponse);
+ EXPECT_FALSE(m_didReceiveData);
+ EXPECT_FALSE(m_didFail);
+}
+
+// Test that a cross origin redirect response with CORS headers that allow the requesting origin succeeds.
+TEST_F(AssociatedURLLoaderTest, RedirectCrossOriginWithAccessControlSuccess)
{
GURL url = GURL("http://www.test.com/RedirectCrossOriginWithAccessControlSuccess.html");
char redirect[] = "http://www.other.com/RedirectCrossOriginWithAccessControlSuccess.html"; // Cross-origin
@@ -444,11 +475,13 @@ TEST_F(AssociatedURLLoaderTest, DISABLED_RedirectCrossOriginWithAccessControlSuc
request.initialize();
request.setURL(url);
+ // Create a redirect response that allows the redirect to pass the access control checks.
m_expectedRedirectResponse = WebURLResponse();
m_expectedRedirectResponse.initialize();
m_expectedRedirectResponse.setMIMEType("text/html");
m_expectedRedirectResponse.setHTTPStatusCode(301);
m_expectedRedirectResponse.setHTTPHeaderField("Location", redirect);
+ m_expectedRedirectResponse.addHTTPHeaderField("access-control-allow-origin", "*");
webkit_support::RegisterMockedURL(url, m_expectedRedirectResponse, m_frameFilePath);
m_expectedNewRequest = WebURLRequest();
@@ -467,7 +500,8 @@ TEST_F(AssociatedURLLoaderTest, DISABLED_RedirectCrossOriginWithAccessControlSuc
EXPECT_TRUE(m_expectedLoader);
m_expectedLoader->loadAsynchronously(request, this);
serveRequests();
- EXPECT_TRUE(m_willSendRequest);
+ // We should not receive a notification for the redirect.
+ EXPECT_FALSE(m_willSendRequest);
EXPECT_TRUE(m_didReceiveResponse);
EXPECT_TRUE(m_didReceiveData);
EXPECT_TRUE(m_didFinishLoading);
diff --git a/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp b/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp
index e14ef9bc0..a1ab770b7 100644
--- a/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp
+++ b/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp
@@ -80,6 +80,17 @@ TEST(CCActiveAnimationTest, TrimTimeStartTime)
EXPECT_EQ(1, anim->trimTimeToCurrentIteration(6));
}
+TEST(CCActiveAnimationTest, TrimTimeTimeOffset)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
+ anim->setTimeOffset(4);
+ anim->setStartTime(4);
+ EXPECT_EQ(0, anim->trimTimeToCurrentIteration(0));
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(0.5));
+ EXPECT_EQ(1, anim->trimTimeToCurrentIteration(1));
+ EXPECT_EQ(1, anim->trimTimeToCurrentIteration(1));
+}
+
TEST(CCActiveAnimationTest, TrimTimePauseResume)
{
OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
@@ -93,6 +104,19 @@ TEST(CCActiveAnimationTest, TrimTimePauseResume)
EXPECT_EQ(1, anim->trimTimeToCurrentIteration(1024.5));
}
+TEST(CCActiveAnimationTest, TrimTimeSuspendResume)
+{
+ 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->suspend(0.5);
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(1024));
+ anim->resume(1024);
+ EXPECT_EQ(0.5, anim->trimTimeToCurrentIteration(1024));
+ EXPECT_EQ(1, anim->trimTimeToCurrentIteration(1024.5));
+}
+
TEST(CCActiveAnimationTest, IsFinishedAtZeroIterations)
{
OwnPtr<CCActiveAnimation> anim(createActiveAnimation(0));
@@ -160,4 +184,35 @@ TEST(CCActiveAnimationTest, IsFinished)
EXPECT_TRUE(anim->isFinished());
}
+TEST(CCActiveAnimationTest, IsFinishedNeedsSynchronizedStartTime)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
+ anim->setRunState(CCActiveAnimation::Running, 2);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::Paused, 2);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::WaitingForNextTick, 2);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::WaitingForTargetAvailability, 2);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::WaitingForStartTime, 2);
+ EXPECT_FALSE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::Finished, 0);
+ EXPECT_TRUE(anim->isFinished());
+ anim->setRunState(CCActiveAnimation::Aborted, 0);
+ EXPECT_TRUE(anim->isFinished());
+}
+
+TEST(CCActiveAnimationTest, RunStateChangesIgnoredWhileSuspended)
+{
+ OwnPtr<CCActiveAnimation> anim(createActiveAnimation(1));
+ anim->suspend(0);
+ EXPECT_EQ(CCActiveAnimation::Paused, anim->runState());
+ anim->setRunState(CCActiveAnimation::Running, 0);
+ EXPECT_EQ(CCActiveAnimation::Paused, anim->runState());
+ anim->resume(0);
+ anim->setRunState(CCActiveAnimation::Running, 0);
+ EXPECT_EQ(CCActiveAnimation::Running, anim->runState());
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp b/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp
index c9240e31f..36f79818e 100644
--- a/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp
+++ b/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp
@@ -28,14 +28,16 @@
#include "GraphicsLayer.h"
#include "LayerChromium.h"
+#include "TranslateTransformOperation.h"
#include "cc/CCLayerAnimationController.h"
+#include "cc/CCLayerImpl.h"
using namespace WebCore;
namespace {
template <class Target>
-void addOpacityTransition(Target& target, double duration, float startOpacity, float endOpacity)
+void addOpacityTransition(Target& target, double duration, float startOpacity, float endOpacity, bool useTimingFunction)
{
WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
if (duration > 0)
@@ -45,11 +47,32 @@ void addOpacityTransition(Target& target, double duration, float startOpacity, f
RefPtr<Animation> animation = Animation::create();
animation->setDuration(duration);
+ if (useTimingFunction)
+ animation->setTimingFunction(LinearTimingFunction::create());
+
IntSize boxSize;
target.addAnimation(values, boxSize, animation.get(), 0, 0, 0);
}
+template <class Target>
+void addAnimatedTransform(Target& target, double duration, int deltaX, int deltaY)
+{
+ static int id = 0;
+ WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform);
+
+ TransformOperations operations;
+ operations.operations().append(TranslateTransformOperation::create(Length(deltaX, WebCore::Fixed), Length(deltaY, WebCore::Fixed), TransformOperation::TRANSLATE_X));
+ values.insert(new TransformAnimationValue(0, &operations));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+
+ target.addAnimation(values, boxSize, animation.get(), ++id, 0, 0);
+}
+
} // namespace
namespace WebKitTests {
@@ -106,12 +129,12 @@ float FakeFloatTransition::getValue(double time) const
return (1 - time) * m_from + time * m_to;
}
-FakeLayerAnimationControllerImplClient::FakeLayerAnimationControllerImplClient()
+FakeLayerAnimationControllerClient::FakeLayerAnimationControllerClient()
: m_opacity(0)
{
}
-FakeLayerAnimationControllerImplClient::~FakeLayerAnimationControllerImplClient()
+FakeLayerAnimationControllerClient::~FakeLayerAnimationControllerClient()
{
}
@@ -120,14 +143,34 @@ PassOwnPtr<WebCore::CCAnimationCurve> FakeFloatTransition::clone() const
return adoptPtr(new FakeFloatTransition(*this));
}
-void addOpacityTransitionToController(WebCore::CCLayerAnimationController& controller, double duration, float startOpacity, float endOpacity)
+void addOpacityTransitionToController(WebCore::CCLayerAnimationController& controller, double duration, float startOpacity, float endOpacity, bool useTimingFunction)
+{
+ addOpacityTransition(controller, duration, startOpacity, endOpacity, useTimingFunction);
+}
+
+void addAnimatedTransformToController(WebCore::CCLayerAnimationController& controller, double duration, int deltaX, int deltaY)
+{
+ addAnimatedTransform(controller, duration, deltaX, deltaY);
+}
+
+void addOpacityTransitionToLayer(WebCore::LayerChromium& layer, double duration, float startOpacity, float endOpacity, bool useTimingFunction)
+{
+ addOpacityTransition(layer, duration, startOpacity, endOpacity, useTimingFunction);
+}
+
+void addOpacityTransitionToLayer(WebCore::CCLayerImpl& layer, double duration, float startOpacity, float endOpacity, bool useTimingFunction)
+{
+ addOpacityTransition(*layer.layerAnimationController(), duration, startOpacity, endOpacity, useTimingFunction);
+}
+
+void addAnimatedTransformToLayer(WebCore::LayerChromium& layer, double duration, int deltaX, int deltaY)
{
- addOpacityTransition(controller, duration, startOpacity, endOpacity);
+ addAnimatedTransform(layer, duration, deltaX, deltaY);
}
-void addOpacityTransitionToLayer(WebCore::LayerChromium& layer, double duration, float startOpacity, float endOpacity)
+void addAnimatedTransformToLayer(WebCore::CCLayerImpl& layer, double duration, int deltaX, int deltaY)
{
- addOpacityTransition(layer, duration, startOpacity, endOpacity);
+ addAnimatedTransform(*layer.layerAnimationController(), duration, deltaX, deltaY);
}
} // namespace WebKitTests
diff --git a/Source/WebKit/chromium/tests/CCAnimationTestCommon.h b/Source/WebKit/chromium/tests/CCAnimationTestCommon.h
index d13e74ca1..776b75c8d 100644
--- a/Source/WebKit/chromium/tests/CCAnimationTestCommon.h
+++ b/Source/WebKit/chromium/tests/CCAnimationTestCommon.h
@@ -26,12 +26,12 @@
#define CCAnimationTestCommon_h
#include "cc/CCAnimationCurve.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
+#include "cc/CCLayerAnimationController.h"
#include <wtf/OwnPtr.h>
namespace WebCore {
-class CCLayerAnimationController;
+class CCLayerImpl;
class LayerChromium;
}
@@ -42,9 +42,9 @@ public:
FakeFloatAnimationCurve();
virtual ~FakeFloatAnimationCurve();
- virtual double duration() const { return 1; }
- virtual float getValue(double now) const { return 0; }
- virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+ virtual double duration() const OVERRIDE { return 1; }
+ virtual float getValue(double now) const OVERRIDE { return 0; }
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const OVERRIDE;
};
class FakeTransformTransition : public WebCore::CCTransformAnimationCurve {
@@ -52,10 +52,10 @@ public:
FakeTransformTransition(double duration);
virtual ~FakeTransformTransition();
- virtual double duration() const { return m_duration; }
- virtual WebCore::TransformationMatrix getValue(double time, const WebCore::IntSize&) const;
+ virtual double duration() const OVERRIDE { return m_duration; }
+ virtual WebCore::TransformationMatrix getValue(double time, const WebCore::IntSize&) const OVERRIDE;
- virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const OVERRIDE;
private:
double m_duration;
@@ -66,10 +66,10 @@ public:
FakeFloatTransition(double duration, float from, float to);
virtual ~FakeFloatTransition();
- virtual double duration() const { return m_duration; }
- virtual float getValue(double time) const;
+ virtual double duration() const OVERRIDE { return m_duration; }
+ virtual float getValue(double time) const OVERRIDE;
- virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const OVERRIDE;
private:
double m_duration;
@@ -77,17 +77,18 @@ private:
float m_to;
};
-class FakeLayerAnimationControllerImplClient : public WebCore::CCLayerAnimationControllerImplClient {
+class FakeLayerAnimationControllerClient : public WebCore::CCLayerAnimationControllerClient {
public:
- FakeLayerAnimationControllerImplClient();
- virtual ~FakeLayerAnimationControllerImplClient();
+ FakeLayerAnimationControllerClient();
+ virtual ~FakeLayerAnimationControllerClient();
- virtual int id() const { return 0; }
- virtual float opacity() const { return m_opacity; }
- virtual void setOpacity(float opacity) { m_opacity = opacity; }
- virtual const WebCore::TransformationMatrix& transform() const { return m_transform; }
- virtual void setTransform(const WebCore::TransformationMatrix& transform) { m_transform = transform; }
- virtual const WebCore::IntSize& bounds() const { return m_bounds; }
+ // CCLayerAnimationControllerClient implementation
+ virtual int id() const OVERRIDE { return 0; }
+ virtual void setOpacityFromAnimation(float opacity) OVERRIDE { m_opacity = opacity; }
+ virtual float opacity() const OVERRIDE { return m_opacity; }
+ virtual void setTransformFromAnimation(const WebCore::TransformationMatrix& transform) OVERRIDE { m_transform = transform; }
+ virtual const WebCore::TransformationMatrix& transform() const OVERRIDE { return m_transform; }
+ virtual const WebCore::IntSize& bounds() const OVERRIDE { return m_bounds; }
private:
float m_opacity;
@@ -95,9 +96,14 @@ private:
WebCore::IntSize m_bounds;
};
-void addOpacityTransitionToController(WebCore::CCLayerAnimationController&, double duration, float startOpacity, float endOpacity);
+void addOpacityTransitionToController(WebCore::CCLayerAnimationController&, double duration, float startOpacity, float endOpacity, bool useTimingFunction);
+void addAnimatedTransformToController(WebCore::CCLayerAnimationController&, double duration, int deltaX, int deltaY);
-void addOpacityTransitionToLayer(WebCore::LayerChromium&, double duration, float startOpacity, float endOpacity);
+void addOpacityTransitionToLayer(WebCore::LayerChromium&, double duration, float startOpacity, float endOpacity, bool useTimingFunction);
+void addOpacityTransitionToLayer(WebCore::CCLayerImpl&, double duration, float startOpacity, float endOpacity, bool useTimingFunction);
+
+void addAnimatedTransformToLayer(WebCore::LayerChromium&, double duration, int deltaX, int deltaY);
+void addAnimatedTransformToLayer(WebCore::CCLayerImpl&, double duration, int deltaX, int deltaY);
} // namespace WebKitTests
diff --git a/Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp b/Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp
index 74d635b40..11a88784b 100644
--- a/Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp
@@ -30,6 +30,7 @@
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerSorter.h"
#include "cc/CCLayerTreeHostCommon.h"
+#include "cc/CCMathUtil.h"
#include "cc/CCSingleThreadProxy.h"
#include <gtest/gtest.h>
@@ -70,7 +71,7 @@ void emulateDrawingOneFrame(CCLayerImpl* root)
// Iterate back-to-front, so that damage correctly propagates from descendant surfaces to ancestors.
for (int i = renderSurfaceLayerList.size() - 1; i >= 0; --i) {
CCRenderSurface* targetSurface = renderSurfaceLayerList[i]->renderSurface();
- targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), renderSurfaceLayerList[i]->maskLayer());
+ targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), targetSurface->surfacePropertyChangedOnlyFromDescendant(), targetSurface->contentRect(), renderSurfaceLayerList[i]->maskLayer(), renderSurfaceLayerList[i]->filters());
}
root->resetAllChangeTrackingForSubtree();
@@ -180,7 +181,7 @@ TEST_F(CCDamageTrackerTest, sanityCheckTestTreeWithOneSurface)
OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface();
- EXPECT_EQ(static_cast<size_t>(2), root->renderSurface()->layerList().size());
+ EXPECT_EQ(2u, root->renderSurface()->layerList().size());
EXPECT_EQ(1, root->renderSurface()->layerList()[0]->id());
EXPECT_EQ(2, root->renderSurface()->layerList()[1]->id());
@@ -202,8 +203,8 @@ TEST_F(CCDamageTrackerTest, sanityCheckTestTreeWithTwoSurfaces)
ASSERT_TRUE(child1->renderSurface());
EXPECT_FALSE(child2->renderSurface());
- EXPECT_EQ(static_cast<size_t>(3), root->renderSurface()->layerList().size());
- EXPECT_EQ(static_cast<size_t>(2), child1->renderSurface()->layerList().size());
+ EXPECT_EQ(3u, root->renderSurface()->layerList().size());
+ EXPECT_EQ(2u, child1->renderSurface()->layerList().size());
// The render surface for child1 only has a contentRect that encloses grandChild1 and grandChild2, because child1 does not draw content.
EXPECT_FLOAT_RECT_EQ(FloatRect(190, 190, 16, 18), childDamageRect);
@@ -254,7 +255,7 @@ TEST_F(CCDamageTrackerTest, verifyDamageForPropertyChanges)
// Sanity check - we should not have accidentally created a separate render surface for the translucent layer.
ASSERT_FALSE(child->renderSurface());
- ASSERT_EQ(static_cast<size_t>(2), root->renderSurface()->layerList().size());
+ ASSERT_EQ(2u, root->renderSurface()->layerList().size());
// Damage should be the entire child layer in targetSurface space.
FloatRect expectedRect = FloatRect(100, 100, 30, 30);
@@ -315,6 +316,146 @@ TEST_F(CCDamageTrackerTest, verifyDamageForTransformedLayer)
EXPECT_FLOAT_RECT_EQ(expectedRect, rootDamageRect);
}
+TEST_F(CCDamageTrackerTest, verifyDamageForPerspectiveClippedLayer)
+{
+ // If a layer has a perspective transform that causes w < 0, then not clipping the
+ // layer can cause an invalid damage rect. This test checks that the w < 0 case is
+ // tracked properly.
+ //
+ // The transform is constructed so that if w < 0 clipping is not performed, the
+ // incorrect rect will be very small, specifically: position (-3.153448, -2.750628) and size 8.548689 x 5.661383.
+ // Instead, the correctly transformed rect should actually be very huge (i.e. in theory, infinite)
+
+ OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface();
+ CCLayerImpl* child = root->children()[0].get();
+
+ TransformationMatrix transform;
+ transform.applyPerspective(1);
+ transform.translate3d(-150, -50, 0);
+ transform.rotate3d(0, 45, 0);
+ transform.translate3d(-50, -50, 0);
+
+ // Set up the child
+ child->setPosition(FloatPoint(0, 0));
+ child->setBounds(IntSize(100, 100));
+ child->setTransform(transform);
+ emulateDrawingOneFrame(root.get());
+
+ // Sanity check that the child layer's bounds would actually get clipped by w < 0,
+ // otherwise this test is not actually testing the intended scenario.
+ FloatQuad testQuad(FloatRect(FloatPoint::zero(), FloatSize(100, 100)));
+ bool clipped = false;
+ CCMathUtil::mapQuad(transform, testQuad, clipped);
+ EXPECT_TRUE(clipped);
+
+ // Damage the child without moving it.
+ child->setOpacity(0.5);
+ emulateDrawingOneFrame(root.get());
+
+ // The expected damage should cover the entire root surface (500x500), but we don't
+ // care whether the damage rect was clamped or is larger than the surface for this test.
+ FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ EXPECT_GE(rootDamageRect.width(), 500);
+ EXPECT_GE(rootDamageRect.height(), 500);
+}
+
+TEST_F(CCDamageTrackerTest, verifyDamageForBlurredSurface)
+{
+ OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface();
+ CCLayerImpl* child = root->children()[0].get();
+
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(5, WebCore::Fixed), FilterOperation::BLUR));
+ int outsetTop, outsetRight, outsetBottom, outsetLeft;
+ filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
+ root->setFilters(filters);
+
+ // Setting the filter will damage the whole surface.
+ emulateDrawingOneFrame(root.get());
+
+ // Setting the update rect should cause the corresponding damage to the surface, blurred based on the size of the blur filter.
+ child->setUpdateRect(FloatRect(10, 11, 12, 13));
+ emulateDrawingOneFrame(root.get());
+
+ // Damage position on the surface should be: position of updateRect (10, 11) relative to the child (100, 100), but expanded by the blur outsets.
+ FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ FloatRect expectedDamageRect = FloatRect(110, 111, 12, 13);
+ expectedDamageRect.move(-outsetLeft, -outsetTop);
+ expectedDamageRect.expand(outsetLeft + outsetRight, outsetTop + outsetBottom);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+}
+
+TEST_F(CCDamageTrackerTest, verifyDamageForBackgroundBlurredChild)
+{
+ OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
+ CCLayerImpl* child1 = root->children()[0].get();
+ CCLayerImpl* child2 = root->children()[1].get();
+
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(2, WebCore::Fixed), FilterOperation::BLUR));
+ int outsetTop, outsetRight, outsetBottom, outsetLeft;
+ filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
+ child1->setBackgroundFilters(filters);
+
+ // Setting the filter will damage the whole surface.
+ emulateDrawingOneFrame(root.get());
+
+ // CASE 1: Setting the update rect should cause the corresponding damage to
+ // the surface, blurred based on the size of the child's background blur
+ // filter.
+ root->setUpdateRect(FloatRect(297, 297, 2, 2));
+
+ emulateDrawingOneFrame(root.get());
+
+ FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ // Damage position on the surface should be a composition of the damage on the root and on child2.
+ // Damage on the root should be: position of updateRect (297, 297), but expanded by the blur outsets.
+ FloatRect expectedDamageRect = FloatRect(297, 297, 2, 2);
+ expectedDamageRect.move(-outsetLeft, -outsetTop);
+ expectedDamageRect.expand(outsetLeft + outsetRight, outsetTop + outsetBottom);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+
+ // CASE 2: Setting the update rect should cause the corresponding damage to
+ // the surface, blurred based on the size of the child's background blur
+ // filter. Since the damage extends to the right/bottom outside of the
+ // blurred layer, only the left/top should end up expanded.
+ root->setUpdateRect(FloatRect(297, 297, 30, 30));
+
+ emulateDrawingOneFrame(root.get());
+
+ rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ // Damage position on the surface should be a composition of the damage on the root and on child2.
+ // Damage on the root should be: position of updateRect (297, 297), but expanded on the left/top
+ // by the blur outsets.
+ expectedDamageRect = FloatRect(297, 297, 30, 30);
+ expectedDamageRect.move(-outsetLeft, -outsetTop);
+ expectedDamageRect.expand(outsetLeft, outsetTop);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+
+ // CASE 3: Setting this update rect outside the contentBounds of the blurred
+ // child1 will not cause it to be expanded.
+ root->setUpdateRect(FloatRect(30, 30, 2, 2));
+
+ emulateDrawingOneFrame(root.get());
+
+ rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ // Damage on the root should be: position of updateRect (30, 30), not
+ // expanded.
+ expectedDamageRect = FloatRect(30, 30, 2, 2);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+
+ // CASE 4: Setting the update rect on child2, which is above child1, will
+ // not get blurred by child1, so it does not need to get expanded.
+ child2->setUpdateRect(FloatRect(0, 0, 1, 1));
+
+ emulateDrawingOneFrame(root.get());
+
+ rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ // Damage on child2 should be: position of updateRect offset by the child's position (11, 11), and not expanded by anything.
+ expectedDamageRect = FloatRect(11, 11, 1, 1);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+}
+
TEST_F(CCDamageTrackerTest, verifyDamageForAddingAndRemovingLayer)
{
OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface();
@@ -334,7 +475,7 @@ TEST_F(CCDamageTrackerTest, verifyDamageForAddingAndRemovingLayer)
emulateDrawingOneFrame(root.get());
// Sanity check - all 3 layers should be on the same render surface; render surfaces are tested elsewhere.
- ASSERT_EQ(static_cast<size_t>(3), root->renderSurface()->layerList().size());
+ ASSERT_EQ(3u, root->renderSurface()->layerList().size());
FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
EXPECT_FLOAT_RECT_EQ(FloatRect(400, 380, 6, 8), rootDamageRect);
@@ -353,6 +494,36 @@ TEST_F(CCDamageTrackerTest, verifyDamageForAddingAndRemovingLayer)
EXPECT_FLOAT_RECT_EQ(FloatRect(100, 100, 30, 30), rootDamageRect);
}
+TEST_F(CCDamageTrackerTest, verifyDamageForNewUnchangedLayer)
+{
+ // If child2 is added to the layer tree, but it doesn't have any explicit damage of
+ // its own, it should still indeed damage the target surface.
+
+ OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface();
+
+ {
+ OwnPtr<CCLayerImpl> child2 = CCLayerImpl::create(3);
+ child2->setPosition(FloatPoint(400, 380));
+ child2->setAnchorPoint(FloatPoint::zero());
+ child2->setBounds(IntSize(6, 8));
+ child2->setDrawsContent(true);
+ child2->resetAllChangeTrackingForSubtree();
+ // Sanity check the initial conditions of the test, if these asserts trigger, it
+ // means the test no longer actually covers the intended scenario.
+ ASSERT_FALSE(child2->layerPropertyChanged());
+ ASSERT_TRUE(child2->updateRect().isEmpty());
+ root->addChild(child2.release());
+ }
+
+ emulateDrawingOneFrame(root.get());
+
+ // Sanity check - all 3 layers should be on the same render surface; render surfaces are tested elsewhere.
+ ASSERT_EQ(3u, root->renderSurface()->layerList().size());
+
+ FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ EXPECT_FLOAT_RECT_EQ(FloatRect(400, 380, 6, 8), rootDamageRect);
+}
+
TEST_F(CCDamageTrackerTest, verifyDamageForMultipleLayers)
{
OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface();
@@ -402,8 +573,8 @@ TEST_F(CCDamageTrackerTest, verifyDamageForNestedSurfaces)
// CASE 2: Same as previous case, but with additional damage elsewhere that should be properly unioned.
// - child1 surface damage in root surface space: FloatRect(300, 300, 6, 8);
// - child2 damage in root surface space: FloatRect(11, 11, 18, 18);
- grandChild1->setOpacity(0.7);
- child2->setOpacity(0.7);
+ grandChild1->setOpacity(0.7f);
+ child2->setOpacity(0.7f);
emulateDrawingOneFrame(root.get());
childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
@@ -485,7 +656,7 @@ TEST_F(CCDamageTrackerTest, verifyDamageForAddingAndRemovingRenderSurfaces)
// Sanity check that there is only one surface now.
ASSERT_FALSE(child1->renderSurface());
- ASSERT_EQ(static_cast<size_t>(4), root->renderSurface()->layerList().size());
+ ASSERT_EQ(4u, root->renderSurface()->layerList().size());
rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
EXPECT_FLOAT_RECT_EQ(FloatRect(290, 290, 16, 18), rootDamageRect);
@@ -503,8 +674,8 @@ TEST_F(CCDamageTrackerTest, verifyDamageForAddingAndRemovingRenderSurfaces)
// Sanity check that there is a new surface now.
ASSERT_TRUE(child1->renderSurface());
- EXPECT_EQ(static_cast<size_t>(3), root->renderSurface()->layerList().size());
- EXPECT_EQ(static_cast<size_t>(2), child1->renderSurface()->layerList().size());
+ EXPECT_EQ(3u, root->renderSurface()->layerList().size());
+ EXPECT_EQ(2u, child1->renderSurface()->layerList().size());
childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
@@ -746,7 +917,7 @@ TEST_F(CCDamageTrackerTest, verifyDamageForReplicaMask)
ASSERT_TRUE(grandChild1->renderSurface());
// CASE 1: a property change on the mask should damage only the reflected region on the target surface.
- replicaMaskLayer->setOpacity(0.6);
+ replicaMaskLayer->setOpacity(0.6f);
emulateDrawingOneFrame(root.get());
FloatRect grandChildDamageRect = grandChild1->renderSurface()->damageTracker()->currentDamageRect();
@@ -767,7 +938,53 @@ TEST_F(CCDamageTrackerTest, verifyDamageForReplicaMask)
EXPECT_FLOAT_RECT_EQ(FloatRect(194, 200, 6, 8), childDamageRect);
}
-TEST_F(CCDamageTrackerTest, verifyDamageWhenReset)
+TEST_F(CCDamageTrackerTest, verifyDamageForReplicaMaskWithAnchor)
+{
+ OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
+ CCLayerImpl* child1 = root->children()[0].get();
+ CCLayerImpl* grandChild1 = child1->children()[0].get();
+
+ // Verify that the correct replicaOriginTransform is used for the replicaMask; the
+ // incorrect old code incorrectly accounted for the anchor for the replica. A
+ // non-zero anchor point should not affect the replica reflection.
+
+ grandChild1->setAnchorPoint(FloatPoint(1.0, 0.0)); // This is the anchor being tested.
+
+ {
+ OwnPtr<CCLayerImpl> grandChild1Replica = CCLayerImpl::create(6);
+ grandChild1Replica->setPosition(FloatPoint::zero());
+ grandChild1Replica->setAnchorPoint(FloatPoint::zero()); // note, this is not the anchor being tested.
+ TransformationMatrix reflection;
+ reflection.scale3d(-1.0, 1.0, 1.0);
+ grandChild1Replica->setTransform(reflection);
+ grandChild1->setReplicaLayer(grandChild1Replica.release());
+ }
+ CCLayerImpl* grandChild1Replica = grandChild1->replicaLayer();
+
+ // Set up the mask layer on the replica layer
+ {
+ OwnPtr<CCLayerImpl> replicaMaskLayer = CCLayerImpl::create(7);
+ replicaMaskLayer->setPosition(FloatPoint::zero());
+ replicaMaskLayer->setAnchorPoint(FloatPoint::zero()); // note, this is not the anchor being tested.
+ replicaMaskLayer->setBounds(grandChild1->bounds());
+ grandChild1Replica->setMaskLayer(replicaMaskLayer.release());
+ }
+ CCLayerImpl* replicaMaskLayer = grandChild1Replica->maskLayer();
+
+ emulateDrawingOneFrame(root.get());
+
+ // Sanity check that the appropriate render surfaces were created
+ ASSERT_TRUE(grandChild1->renderSurface());
+
+ // A property change on the replicaMask should damage the reflected region on the target surface.
+ replicaMaskLayer->setOpacity(0.6f);
+ emulateDrawingOneFrame(root.get());
+
+ FloatRect childDamageRect = child1->renderSurface()->damageTracker()->currentDamageRect();
+ EXPECT_FLOAT_RECT_EQ(FloatRect(194, 200, 6, 8), childDamageRect);
+}
+
+TEST_F(CCDamageTrackerTest, verifyDamageWhenForcedFullDamage)
{
OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface();
CCLayerImpl* child = root->children()[0].get();
@@ -790,4 +1007,21 @@ TEST_F(CCDamageTrackerTest, verifyDamageWhenReset)
EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 500, 500), rootDamageRect);
}
+TEST_F(CCDamageTrackerTest, verifyDamageForEmptyLayerList)
+{
+ // Though it should never happen, its a good idea to verify that the damage tracker
+ // does not crash when it receives an empty layerList.
+
+ OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
+ root->createRenderSurface();
+
+ ASSERT_TRUE(root->renderSurface() == root->targetRenderSurface());
+ CCRenderSurface* targetSurface = root->renderSurface();
+ targetSurface->clearLayerList();
+ targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), false, IntRect(), 0, FilterOperations());
+
+ FloatRect damageRect = targetSurface->damageTracker()->currentDamageRect();
+ EXPECT_TRUE(damageRect.isEmpty());
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp b/Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp
index 867d56ea8..93e84a4af 100644
--- a/Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp
+++ b/Source/WebKit/chromium/tests/CCDelayBasedTimeSourceTest.cpp
@@ -41,15 +41,15 @@ TEST(CCDelayBasedTimeSourceTest, TaskPostedAndTickCalled)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
timer->setClient(&client);
- timer->setMonotonicallyIncreasingTimeMs(0);
+ timer->setMonotonicallyIncreasingTime(0);
timer->setActive(true);
EXPECT_TRUE(timer->active());
EXPECT_TRUE(thread.hasPendingTask());
- timer->setMonotonicallyIncreasingTimeMs(16);
+ timer->setMonotonicallyIncreasingTime(0.016);
thread.runPendingTask();
EXPECT_TRUE(timer->active());
EXPECT_TRUE(client.tickCalled());
@@ -59,7 +59,7 @@ TEST(CCDelayBasedTimeSource, TickNotCalledWithTaskPosted)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
timer->setClient(&client);
timer->setActive(true);
EXPECT_TRUE(thread.hasPendingTask());
@@ -72,7 +72,7 @@ TEST(CCDelayBasedTimeSource, StartTwiceEnqueuesOneTask)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
timer->setClient(&client);
timer->setActive(true);
EXPECT_TRUE(thread.hasPendingTask());
@@ -85,7 +85,7 @@ TEST(CCDelayBasedTimeSource, StartWhenRunningDoesntTick)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
timer->setClient(&client);
timer->setActive(true);
thread.runPendingTask();
@@ -100,19 +100,19 @@ TEST(CCDelayBasedTimeSource, NextDelaySaneWhenExactlyOnRequestedTime)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- double interval = 1000.0 / 60.0;
+ double interval = 1.0 / 60.0;
RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
timer->setClient(&client);
timer->setActive(true);
// Run the first task, as that activates the timer and picks up a timebase.
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
- timer->setMonotonicallyIncreasingTimeMs(interval);
+ timer->setMonotonicallyIncreasingTime(interval);
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
}
// At 60Hz, when the tick returns at slightly after the requested next time, make sure
@@ -121,19 +121,19 @@ TEST(CCDelayBasedTimeSource, NextDelaySaneWhenSlightlyAfterRequestedTime)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- double interval = 1000.0 / 60.0;
+ double interval = 1.0 / 60.0;
RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
timer->setClient(&client);
timer->setActive(true);
// Run the first task, as that activates the timer and picks up a timebase.
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
- timer->setMonotonicallyIncreasingTimeMs(interval + 0.0001);
+ timer->setMonotonicallyIncreasingTime(interval + 0.0000001);
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
}
// At 60Hz, when the tick returns at exactly 2*interval after the requested next time, make sure
@@ -142,19 +142,19 @@ TEST(CCDelayBasedTimeSource, NextDelaySaneWhenExactlyTwiceAfterRequestedTime)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- double interval = 1000.0 / 60.0;
+ double interval = 1.0 / 60.0;
RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
timer->setClient(&client);
timer->setActive(true);
// Run the first task, as that activates the timer and picks up a timebase.
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
- timer->setMonotonicallyIncreasingTimeMs(2*interval);
+ timer->setMonotonicallyIncreasingTime(2*interval);
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
}
// At 60Hz, when the tick returns at 2*interval and a bit after the requested next time, make sure
@@ -163,19 +163,19 @@ TEST(CCDelayBasedTimeSource, NextDelaySaneWhenSlightlyAfterTwiceRequestedTime)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- double interval = 1000.0 / 60.0;
+ double interval = 1.0 / 60.0;
RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
timer->setClient(&client);
timer->setActive(true);
// Run the first task, as that activates the timer and picks up a timebase.
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
- timer->setMonotonicallyIncreasingTimeMs(2*interval + 0.0001);
+ timer->setMonotonicallyIncreasingTime(2*interval + 0.0000001);
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
}
// At 60Hz, when the tick returns halfway to the next frame time, make sure
@@ -184,19 +184,19 @@ TEST(CCDelayBasedTimeSource, NextDelaySaneWhenHalfAfterRequestedTime)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- double interval = 1000.0 / 60.0;
+ double interval = 1.0 / 60.0;
RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
timer->setClient(&client);
timer->setActive(true);
// Run the first task, as that activates the timer and picks up a timebase.
thread.runPendingTask();
- EXPECT_EQ(16, thread.pendingDelay());
+ EXPECT_EQ(16, thread.pendingDelayMs());
- timer->setMonotonicallyIncreasingTimeMs(interval + interval * 0.5);
+ timer->setMonotonicallyIncreasingTime(interval + interval * 0.5);
thread.runPendingTask();
- EXPECT_EQ(8, thread.pendingDelay());
+ EXPECT_EQ(8, thread.pendingDelayMs());
}
@@ -206,31 +206,31 @@ TEST(CCDelayBasedTimeSourceTest, AchievesTargetRateWithNoNoise)
FakeCCThread thread;
FakeCCTimeSourceClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
timer->setClient(&client);
timer->setActive(true);
double totalFrameTime = 0;
for (int i = 0; i < numIterations; ++i) {
- long long delay = thread.pendingDelay();
+ long long delayMs = thread.pendingDelayMs();
// accumulate the "delay"
- totalFrameTime += delay;
+ totalFrameTime += delayMs / 1000.0;
// Run the callback exactly when asked
- double now = timer->monotonicallyIncreasingTimeMs() + delay;
- timer->setMonotonicallyIncreasingTimeMs(now);
+ double now = timer->monotonicallyIncreasingTime() + delayMs / 1000.0;
+ timer->setMonotonicallyIncreasingTime(now);
thread.runPendingTask();
}
double averageInterval = totalFrameTime / static_cast<double>(numIterations);
- EXPECT_NEAR(1000.0 / 60.0, averageInterval, 0.1);
+ EXPECT_NEAR(1.0 / 60.0, averageInterval, 0.1);
}
TEST(CCDelayBasedTimeSource, TestDeactivateWhilePending)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
timer->setClient(&client);
timer->setActive(true); // Should post a task.
timer->setActive(false);
@@ -242,12 +242,12 @@ TEST(CCDelayBasedTimeSource, TestDeactivateAndReactivateBeforeNextTickTime)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
timer->setClient(&client);
// Should run the activate task, and pick up a new timebase.
timer->setActive(true);
- timer->setMonotonicallyIncreasingTimeMs(0);
+ timer->setMonotonicallyIncreasingTime(0);
thread.runPendingTask();
// Stop the timer
@@ -258,21 +258,21 @@ TEST(CCDelayBasedTimeSource, TestDeactivateAndReactivateBeforeNextTickTime)
// Start the timer again, but before the next tick time the timer previously
// planned on using. That same tick time should still be targeted.
- timer->setMonotonicallyIncreasingTimeMs(4);
+ timer->setMonotonicallyIncreasingTime(0.004);
timer->setActive(true);
- EXPECT_EQ(12, thread.pendingDelay());
+ EXPECT_EQ(12, thread.pendingDelayMs());
}
TEST(CCDelayBasedTimeSource, TestDeactivateAndReactivateAfterNextTickTime)
{
FakeCCThread thread;
FakeCCTimeSourceClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
timer->setClient(&client);
// Should run the activate task, and pick up a new timebase.
timer->setActive(true);
- timer->setMonotonicallyIncreasingTimeMs(0);
+ timer->setMonotonicallyIncreasingTime(0);
thread.runPendingTask();
// Stop the timer
@@ -283,9 +283,9 @@ TEST(CCDelayBasedTimeSource, TestDeactivateAndReactivateAfterNextTickTime)
// Start the timer again, but before the next tick time the timer previously
// planned on using. That same tick time should still be targeted.
- timer->setMonotonicallyIncreasingTimeMs(20);
+ timer->setMonotonicallyIncreasingTime(0.02);
timer->setActive(true);
- EXPECT_EQ(13, thread.pendingDelay());
+ EXPECT_EQ(13, thread.pendingDelayMs());
}
}
diff --git a/Source/WebKit/chromium/tests/CCFrameRateControllerTest.cpp b/Source/WebKit/chromium/tests/CCFrameRateControllerTest.cpp
index ae43d41c1..c9a60cfaa 100644
--- a/Source/WebKit/chromium/tests/CCFrameRateControllerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCFrameRateControllerTest.cpp
@@ -39,13 +39,13 @@ class FakeCCFrameRateControllerClient : public WebCore::CCFrameRateControllerCli
public:
FakeCCFrameRateControllerClient() { reset(); }
- void reset() { m_frameBegun = false; }
- bool frameBegun() const { return m_frameBegun; }
+ void reset() { m_vsyncTicked = false; }
+ bool vsyncTicked() const { return m_vsyncTicked; }
- virtual void beginFrame() { m_frameBegun = true; }
+ virtual void vsyncTick() { m_vsyncTicked = true; }
protected:
- bool m_frameBegun;
+ bool m_vsyncTicked;
};
@@ -53,7 +53,7 @@ TEST(CCFrameRateControllerTest, TestFrameThrottling_ImmediateAck)
{
FakeCCThread thread;
FakeCCFrameRateControllerClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timeSource = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timeSource = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
CCFrameRateController controller(timeSource);
controller.setClient(&client);
@@ -62,32 +62,32 @@ TEST(CCFrameRateControllerTest, TestFrameThrottling_ImmediateAck)
double elapsed = 0; // Muck around with time a bit
// Trigger one frame, make sure the vsync callback is called
- elapsed += thread.pendingDelay();
- timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
+ elapsed += thread.pendingDelayMs() / 1000.0;
+ timeSource->setMonotonicallyIncreasingTime(elapsed);
thread.runPendingTask();
- EXPECT_TRUE(client.frameBegun());
+ EXPECT_TRUE(client.vsyncTicked());
client.reset();
// Tell the controller we drew
controller.didBeginFrame();
// Tell the controller the frame ended 5ms later
- timeSource->setMonotonicallyIncreasingTimeMs(timeSource->monotonicallyIncreasingTimeMs() + 5);
+ timeSource->setMonotonicallyIncreasingTime(timeSource->monotonicallyIncreasingTime() + 0.005);
controller.didFinishFrame();
// Trigger another frame, make sure vsync runs again
- elapsed += thread.pendingDelay();
- EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTimeMs()); // Sanity check that previous code didn't move time backward.
- timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
+ elapsed += thread.pendingDelayMs() / 1000.0;
+ EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTime()); // Sanity check that previous code didn't move time backward.
+ timeSource->setMonotonicallyIncreasingTime(elapsed);
thread.runPendingTask();
- EXPECT_TRUE(client.frameBegun());
+ EXPECT_TRUE(client.vsyncTicked());
}
TEST(CCFrameRateControllerTest, TestFrameThrottling_TwoFramesInFlight)
{
FakeCCThread thread;
FakeCCFrameRateControllerClient client;
- RefPtr<FakeCCDelayBasedTimeSource> timeSource = FakeCCDelayBasedTimeSource::create(1000.0 / 60.0, &thread);
+ RefPtr<FakeCCDelayBasedTimeSource> timeSource = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
CCFrameRateController controller(timeSource);
controller.setClient(&client);
@@ -97,46 +97,46 @@ TEST(CCFrameRateControllerTest, TestFrameThrottling_TwoFramesInFlight)
double elapsed = 0; // Muck around with time a bit
// Trigger one frame, make sure the vsync callback is called
- elapsed += thread.pendingDelay();
- timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
+ elapsed += thread.pendingDelayMs() / 1000.0;
+ timeSource->setMonotonicallyIncreasingTime(elapsed);
thread.runPendingTask();
- EXPECT_TRUE(client.frameBegun());
+ EXPECT_TRUE(client.vsyncTicked());
client.reset();
// Tell the controller we drew
controller.didBeginFrame();
// Trigger another frame, make sure vsync callback runs again
- elapsed += thread.pendingDelay();
- EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTimeMs()); // Sanity check that previous code didn't move time backward.
- timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
+ elapsed += thread.pendingDelayMs() / 1000.0;
+ EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTime()); // Sanity check that previous code didn't move time backward.
+ timeSource->setMonotonicallyIncreasingTime(elapsed);
thread.runPendingTask();
- EXPECT_TRUE(client.frameBegun());
+ EXPECT_TRUE(client.vsyncTicked());
client.reset();
// Tell the controller we drew, again.
controller.didBeginFrame();
// Trigger another frame. Since two frames are pending, we should not draw.
- elapsed += thread.pendingDelay();
- EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTimeMs()); // Sanity check that previous code didn't move time backward.
- timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
+ elapsed += thread.pendingDelayMs() / 1000.0;
+ EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTime()); // Sanity check that previous code didn't move time backward.
+ timeSource->setMonotonicallyIncreasingTime(elapsed);
thread.runPendingTask();
- EXPECT_FALSE(client.frameBegun());
+ EXPECT_FALSE(client.vsyncTicked());
// Tell the controller the first frame ended 5ms later
- timeSource->setMonotonicallyIncreasingTimeMs(timeSource->monotonicallyIncreasingTimeMs() + 5);
+ timeSource->setMonotonicallyIncreasingTime(timeSource->monotonicallyIncreasingTime() + 0.005);
controller.didFinishFrame();
// Tick should not have been called
- EXPECT_FALSE(client.frameBegun());
+ EXPECT_FALSE(client.vsyncTicked());
// Trigger yet another frame. Since one frames is pending, another vsync callback should run.
- elapsed += thread.pendingDelay();
- EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTimeMs()); // Sanity check that previous code didn't move time backward.
- timeSource->setMonotonicallyIncreasingTimeMs(elapsed);
+ elapsed += thread.pendingDelayMs() / 1000.0;
+ EXPECT_TRUE(elapsed >= timeSource->monotonicallyIncreasingTime()); // Sanity check that previous code didn't move time backward.
+ timeSource->setMonotonicallyIncreasingTime(elapsed);
thread.runPendingTask();
- EXPECT_TRUE(client.frameBegun());
+ EXPECT_TRUE(client.vsyncTicked());
}
}
diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp
deleted file mode 100644
index e1aeccc53..000000000
--- a/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "CCAnimationTestCommon.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
-#include "cc/CCAnimationCurve.h"
-#include "cc/CCAnimationEvents.h"
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <wtf/Vector.h>
-
-using namespace WebCore;
-using namespace WebKitTests;
-
-namespace {
-
-PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int id, CCActiveAnimation::TargetProperty property)
-{
- return CCActiveAnimation::create(curve, 0, id, property);
-}
-
-// Tests that transitioning opacity from 0 to 1 works as expected.
-TEST(CCLayerAnimationControllerImplTest, TrivialTransition)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
-
- controller->add(toAdd.release());
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_EQ(1, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests that two queued animations affecting the same property run in sequence.
-TEST(CCLayerAnimationControllerImplTest, TrivialQueuing)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
- controller->animate(2, *events);
- EXPECT_EQ(0.5f, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests interrupting a transition with another transition.
-TEST(CCLayerAnimationControllerImplTest, Interrupt)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
- toAdd->setRunState(CCActiveAnimation::WaitingForNextTick, 0);
- controller->add(toAdd.release());
-
- controller->animate(0.5, *events); // second anim starts NOW.
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
- controller->animate(1.5, *events);
- 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)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform));
- controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity));
-
- controller->animate(0, *events);
- EXPECT_EQ(0, dummy.opacity());
- EXPECT_TRUE(controller->hasActiveAnimation());
- controller->animate(1, *events);
- // Should not have started the float transition yet.
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- // The the float animation should have started at time 1 and should be done.
- controller->animate(2, *events);
- 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)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
-
- // Anims with id 1 should both start now.
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- // The opacity animation should have finished at time 1, but the group
- // of animations with id 1 don't finish until time 2 because of the length
- // of the transform animation.
- controller->animate(2, *events);
- // Should not have started the float transition yet.
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
-
- // The the second opacity animation should start at time 2 and should be
- // done by time 3
- controller->animate(3, *events);
- EXPECT_EQ(0.5f, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests scheduling an animation to start in the future.
-TEST(CCLayerAnimationControllerImplTest, ScheduleAnimation)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
- toAdd->setStartTime(1);
- controller->add(toAdd.release());
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(2, *events);
- 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)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0.5f, 0)), 2, CCActiveAnimation::Opacity));
- toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
- toAdd->setStartTime(1);
- controller->add(toAdd.release());
-
- // First 2s opacity transition should start immediately.
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
- controller->animate(2, *events);
- 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)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0.5f, 0)), 2, CCActiveAnimation::Opacity));
- toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
- toAdd->setStartTime(1);
- controller->add(toAdd.release());
-
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75f)), 3, CCActiveAnimation::Opacity));
-
- // First 2s opacity transition should start immediately.
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- EXPECT_TRUE(controller->hasActiveAnimation());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
- controller->animate(3, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(4, *events);
- 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)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- toAdd->setIterations(3);
- controller->add(toAdd.release());
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1.75, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(2.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(2.75, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(3, *events);
- EXPECT_FALSE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
-
- // Just be extra sure.
- controller->animate(4, *events);
- EXPECT_EQ(1, dummy.opacity());
-}
-
-// Test that an infinitely looping animation does indeed go until aborted.
-TEST(CCLayerAnimationControllerImplTest, InfiniteLooping)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- const int id = 1;
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
- toAdd->setIterations(-1);
- controller->add(toAdd.release());
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1.75, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
-
- controller->animate(1073741824.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1073741824.75, *events);
- 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)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- const int id = 1;
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
-
- EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
- controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Paused, 0.5f);
-
- controller->animate(1024, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
-
- EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
- controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Running, 1024);
-
- controller->animate(1024.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(1024.5, *events);
- EXPECT_FALSE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
-}
-
-TEST(CCLayerAnimationControllerImplTest, AbortAGroupedAnimation)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- const int id = 1;
- controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.75f)), 2, CCActiveAnimation::Opacity));
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
-
- EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
- controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 1);
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
- controller->animate(2, *events);
- EXPECT_TRUE(!controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
-}
-
-} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
index c4f103a3c..fa95a2ac5 100644
--- a/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp
@@ -56,7 +56,8 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve>
TEST(CCLayerAnimationControllerTest, createOpacityAnimation)
{
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
const double duration = 1;
WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
values.insert(new FloatAnimationValue(0, 0));
@@ -85,9 +86,37 @@ TEST(CCLayerAnimationControllerTest, createOpacityAnimation)
EXPECT_EQ(1, curve->getValue(duration));
}
+TEST(CCLayerAnimationControllerTest, ignoreUnsupportedAnimationDirections)
+{
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
+ const double duration = 1;
+ WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
+ values.insert(new FloatAnimationValue(0, 0));
+ values.insert(new FloatAnimationValue(duration, 1));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+
+ animation->setDirection(Animation::AnimationDirectionAlternate);
+ EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+
+ animation->setDirection(Animation::AnimationDirectionAlternateReverse);
+ EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+
+ animation->setDirection(Animation::AnimationDirectionReverse);
+ EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+
+ animation->setDirection(Animation::AnimationDirectionNormal);
+ EXPECT_TRUE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+}
+
TEST(CCLayerAnimationControllerTest, createTransformAnimation)
{
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
const double duration = 1;
WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform);
@@ -124,92 +153,504 @@ TEST(CCLayerAnimationControllerTest, createTransformAnimation)
TEST(CCLayerAnimationControllerTest, syncNewAnimation)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ addOpacityTransitionToController(*controller, 1, 0, 1, false);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
}
-TEST(CCLayerAnimationControllerTest, syncAnimationProperties)
+// If an animation is started on the impl thread before it is ticked on the main
+// thread, we must be sure to respect the synchronized start time.
+TEST(CCLayerAnimationControllerTest, doNotClobberStartTimes)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ addOpacityTransitionToController(*controller, 1, 0, 1, false);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- // Push an animation property change to the impl thread (should not cause an animation to be added).
- controller->pauseAnimation(0, 0);
- controller->synchronizeAnimations(controllerImpl.get());
+ CCAnimationEventsVector events;
+ controllerImpl->animate(1, &events);
- EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+ // Synchronize the start times.
+ EXPECT_EQ(1u, events.size());
+ controller->notifyAnimationStarted(events[0]);
+ EXPECT_EQ(controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime(), controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime());
+
+ // Start the animation on the main thread. Should not affect the start time.
+ controller->animate(1.5, 0);
+ EXPECT_EQ(controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime(), controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->startTime());
}
-TEST(CCLayerAnimationControllerTest, syncAbortedAnimation)
+TEST(CCLayerAnimationControllerTest, syncPauseAndResume)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ addOpacityTransitionToController(*controller, 1, 0, 1, false);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- controller->removeAnimation(0);
+ // Start the animations on each controller.
+ CCAnimationEventsVector events;
+ controllerImpl->animate(0, &events);
+ controller->animate(0, 0);
+ EXPECT_EQ(CCActiveAnimation::Running, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+ EXPECT_EQ(CCActiveAnimation::Running, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- // Abort an animation from the main thread.
- controller->synchronizeAnimations(controllerImpl.get());
+ // Pause the main-thread animation.
+ controller->suspendAnimations(1);
+ EXPECT_EQ(CCActiveAnimation::Paused, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ // The pause run state change should make it to the impl thread controller.
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
+ EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ // Resume the main-thread animation.
+ controller->resumeAnimations(2);
+ EXPECT_EQ(CCActiveAnimation::Running, controller->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ // The pause run state change should make it to the impl thread controller.
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
+ EXPECT_EQ(CCActiveAnimation::Running, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
}
-TEST(CCLayerAnimationControllerTest, syncCompletedAnimation)
+
+TEST(CCLayerAnimationControllerTest, doNotSyncFinishedAnimation)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ addOpacityTransitionToController(*controller, 1, 0, 1, false);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
- // Step through the animation until it is finished. At the next sync, the main thread's animation should be cleared.
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- controllerImpl->animate(0, *events);
- controllerImpl->animate(2, *events);
+ // Notify main thread controller that the animation has started.
+ CCAnimationEvent animationStartedEvent(CCAnimationEvent::Started, 0, 0, CCActiveAnimation::Opacity, 0);
+ controller->notifyAnimationStarted(animationStartedEvent);
+
+ // Force animation to complete on impl thread.
+ controllerImpl->removeAnimation(0);
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
+
+ // Even though the main thread has a 'new' animation, it should not be pushed because the animation has already completed on the impl thread.
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+}
+
+// Tests that transitioning opacity from 0 to 1 works as expected.
+TEST(CCLayerAnimationControllerTest, TrivialTransition)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ controller->add(toAdd.release());
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests animations that are waiting for a synchronized start time do not finish.
+TEST(CCLayerAnimationControllerTest, AnimationsWaitingForStartTimeDoNotFinishIfTheyWaitLongerToStartThanTheirDuration)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setNeedsSynchronizedStartTime(true);
+
+ // We should pause at the first keyframe indefinitely waiting for that animation to start.
+ controller->add(toAdd.release());
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+
+ // Send the synchronized start time.
+ controller->notifyAnimationStarted(CCAnimationEvent(CCAnimationEvent::Started, 0, 1, CCActiveAnimation::Opacity, 2));
+ controller->animate(5, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests that two queued animations affecting the same property run in sequence.
+TEST(CCLayerAnimationControllerTest, TrivialQueuing)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_EQ(0.5, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests interrupting a transition with another transition.
+TEST(CCLayerAnimationControllerTest, Interrupt)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForNextTick, 0);
+ controller->add(toAdd.release());
+
+ // Since the animation was in the WaitingForNextTick state, it should start right in
+ // this call to animate.
+ controller->animate(0.5, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(1.5, events.get());
+ EXPECT_EQ(0.5, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling two animations to run together when only one property is free.
+TEST(CCLayerAnimationControllerTest, ScheduleTogetherWhenAPropertyIsBlocked)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity));
+ controller->animate(0, events.get());
+ EXPECT_EQ(0, dummy.opacity());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ controller->animate(1, events.get());
+ // Should not have started the float transition yet.
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ // The float animation should have started at time 1 and should be done.
+ controller->animate(2, events.get());
+ 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(CCLayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
+
+ // Animations with id 1 should both start now.
+ controller->animate(0, events.get());
+ 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, events.get());
+ // Should not have started the float transition yet.
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+
+ // The second opacity animation should start at time 2 and should be done by time 3
+ controller->animate(3, events.get());
+ EXPECT_EQ(0.5, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Tests scheduling an animation to start in the future.
+TEST(CCLayerAnimationControllerTest, ScheduleAnimation)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(2, events.get());
+ 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(CCLayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimation)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0.5, 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, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+ controller->animate(2, events.get());
+ 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(CCLayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0.5, 0)), 2, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75)), 3, CCActiveAnimation::Opacity));
+
+ // First 2s opacity transition should start immediately.
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+ controller->animate(3, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(4, events.get());
+ EXPECT_EQ(0.75, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Test that a looping animation loops and for the correct number of iterations.
+TEST(CCLayerAnimationControllerTest, TrivialLooping)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setIterations(3);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(2.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(2.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(3, events.get());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+
+ // Just be extra sure.
+ controller->animate(4, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+}
+
+// Test that an infinitely looping animation does indeed go until aborted.
+TEST(CCLayerAnimationControllerTest, InfiniteLooping)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+ toAdd->setIterations(-1);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+
+ controller->animate(1073741824.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1073741824.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 0.75);
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+}
+
+// Test that pausing and resuming work as expected.
+TEST(CCLayerAnimationControllerTest, PauseResume)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Paused, 0.5);
+
+ controller->animate(1024, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Running, 1024);
+
+ controller->animate(1024.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(1024.5, events.get());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+}
+
+TEST(CCLayerAnimationControllerTest, AbortAGroupedAnimation)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.75)), 2, CCActiveAnimation::Opacity));
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 1);
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_TRUE(!controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
index 8a9f35dc8..36c1082b7 100644
--- a/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerImplTest.cpp
@@ -81,7 +81,7 @@ TEST(CCLayerImplTest, verifyLayerChangesAreTrackedProperly)
IntSize arbitraryIntSize = IntSize(111, 222);
IntPoint arbitraryIntPoint = IntPoint(333, 444);
IntRect arbitraryIntRect = IntRect(arbitraryIntPoint, arbitraryIntSize);
- FloatRect arbitraryFloatRect = FloatRect(arbitraryFloatPoint, FloatSize(1.234, 5.678));
+ FloatRect arbitraryFloatRect = FloatRect(arbitraryFloatPoint, FloatSize(1.234f, 5.678f));
Color arbitraryColor = Color(10, 20, 30);
TransformationMatrix arbitraryTransform;
arbitraryTransform.scale3d(0.1, 0.2, 0.3);
@@ -112,7 +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));
+ EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setBackgroundFilters(arbitraryFilters));
// 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 2f5a7a25d..f5eae7f84 100644
--- a/Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp
@@ -47,7 +47,7 @@ public:
int m_countRepresentingContributingSurface;
int m_countRepresentingItself;
- virtual bool drawsContent() const { return m_drawsContent; }
+ virtual bool drawsContent() const OVERRIDE { return m_drawsContent; }
void setDrawsContent(bool drawsContent) { m_drawsContent = drawsContent; }
private:
diff --git a/Source/WebKit/chromium/tests/CCLayerSorterTest.cpp b/Source/WebKit/chromium/tests/CCLayerSorterTest.cpp
index a533c9373..65db549ba 100644
--- a/Source/WebKit/chromium/tests/CCLayerSorterTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerSorterTest.cpp
@@ -27,6 +27,7 @@
#include "cc/CCLayerSorter.h"
#include "cc/CCLayerImpl.h"
+#include "cc/CCMathUtil.h"
#include "cc/CCSingleThreadProxy.h"
#include <gtest/gtest.h>
@@ -34,81 +35,94 @@ using namespace WebCore;
namespace {
-TEST(CCLayerSorterTest, PointInTriangle)
+// Note: In the following overlap tests, the "camera" is looking down the negative Z axis,
+// meaning that layers with smaller z values (more negative) are further from the camera
+// and therefore must be drawn before layers with higher z values.
+
+TEST(CCLayerSorterTest, BasicOverlap)
{
- FloatPoint a(10.0, 10.0);
- FloatPoint b(30.0, 10.0);
- FloatPoint c(20.0, 20.0);
-
- // Point in the center is in the triangle.
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(20.0, 15.0), a, b, c));
-
- // Permuting the corners doesn't change the result.
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(20.0, 15.0), a, c, b));
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(20.0, 15.0), b, a, c));
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(20.0, 15.0), b, c, a));
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(20.0, 15.0), c, a, b));
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(20.0, 15.0), c, b, a));
-
- // Points on the edges are not in the triangle.
- EXPECT_FALSE(CCLayerSorter::pointInTriangle(FloatPoint(20.0, 10.0), a, b, c));
- EXPECT_FALSE(CCLayerSorter::pointInTriangle(FloatPoint(15.0, 15.0), a, b, c));
- EXPECT_FALSE(CCLayerSorter::pointInTriangle(FloatPoint(25.0, 15.0), a, b, c));
-
- // Points just inside the edges are in the triangle.
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(20.0, 10.01), a, b, c));
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(15.01, 15.0), a, b, c));
- EXPECT_TRUE(CCLayerSorter::pointInTriangle(FloatPoint(24.99, 15.0), a, b, c));
-
- // Zero-area triangle doesn't intersect any point.
- EXPECT_FALSE(CCLayerSorter::pointInTriangle(FloatPoint(15.0, 10.0), a, b, FloatPoint(20.0, 10.0)));
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ // Trivial test, with one layer directly obscuring the other.
+ TransformationMatrix neg4Translate;
+ neg4Translate.translate3d(0, 0, -4);
+ CCLayerSorter::LayerShape front(2, 2, neg4Translate);
+
+ TransformationMatrix neg5Translate;
+ neg5Translate.translate3d(0, 0, -5);
+ CCLayerSorter::LayerShape back(2, 2, neg5Translate);
+
+ overlapResult = CCLayerSorter::checkOverlap(&front, &back, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::BBeforeA, overlapResult);
+ EXPECT_EQ(1, weight);
+
+ overlapResult = CCLayerSorter::checkOverlap(&back, &front, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult);
+ EXPECT_EQ(1, weight);
+
+ // One layer translated off to the right. No overlap should be detected.
+ TransformationMatrix rightTranslate;
+ rightTranslate.translate3d(10, 0, -5);
+ CCLayerSorter::LayerShape backRight(2, 2, rightTranslate);
+ overlapResult = CCLayerSorter::checkOverlap(&front, &backRight, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::None, overlapResult);
+
+ // When comparing a layer with itself, z difference is always 0.
+ overlapResult = CCLayerSorter::checkOverlap(&front, &front, zThreshold, weight);
+ EXPECT_EQ(0, weight);
}
-TEST(CCLayerSorterTest, CalculateZDiff)
+TEST(CCLayerSorterTest, RightAngleOverlap)
{
- // This should be bigger than the range of z values used.
- const float threshold = 10.0;
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ TransformationMatrix perspectiveMatrix;
+ perspectiveMatrix.applyPerspective(1000);
+
+ // Two layers forming a right angle with a perspective viewing transform.
+ TransformationMatrix leftFaceMatrix;
+ leftFaceMatrix.rotate3d(0, 1, 0, -90).translateRight3d(-1, 0, -5);
+ CCLayerSorter::LayerShape leftFace(2, 2, perspectiveMatrix * leftFaceMatrix);
+ TransformationMatrix frontFaceMatrix;
+ frontFaceMatrix.translate3d(0, 0, -4);
+ CCLayerSorter::LayerShape frontFace(2, 2, perspectiveMatrix * frontFaceMatrix);
+
+ overlapResult = CCLayerSorter::checkOverlap(&frontFace, &leftFace, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::BBeforeA, overlapResult);
+}
- // Trivial test, with one layer directly obscuring the other.
+TEST(CCLayerSorterTest, IntersectingLayerOverlap)
+{
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ TransformationMatrix perspectiveMatrix;
+ perspectiveMatrix.applyPerspective(1000);
+
+ // Intersecting layers. An explicit order will be returned based on relative z
+ // values at the overlapping features but the weight returned should be zero.
+ TransformationMatrix frontFaceMatrix;
+ frontFaceMatrix.translate3d(0, 0, -4);
+ CCLayerSorter::LayerShape frontFace(2, 2, perspectiveMatrix * frontFaceMatrix);
+
+ TransformationMatrix throughMatrix;
+ throughMatrix.rotate3d(0, 1, 0, 45).translateRight3d(0, 0, -4);
+ CCLayerSorter::LayerShape rotatedFace(2, 2, perspectiveMatrix * throughMatrix);
+ overlapResult = CCLayerSorter::checkOverlap(&frontFace, &rotatedFace, zThreshold, weight);
+ EXPECT_NE(CCLayerSorter::None, overlapResult);
+ EXPECT_EQ(0, weight);
+}
- CCLayerSorter::LayerShape front(
- FloatPoint3D(-1.0, 1.0, 5.0),
- FloatPoint3D(1.0, 1.0, 5.0),
- FloatPoint3D(1.0, -1.0, 5.0),
- FloatPoint3D(-1.0, -1.0, 5.0));
-
- CCLayerSorter::LayerShape back(
- FloatPoint3D(-1.0, 1.0, 4.0),
- FloatPoint3D(1.0, 1.0, 4.0),
- FloatPoint3D(1.0, -1.0, 4.0),
- FloatPoint3D(-1.0, -1.0, 4.0));
-
- EXPECT_GT(CCLayerSorter::calculateZDiff(front, back, threshold), 0.0);
- EXPECT_LT(CCLayerSorter::calculateZDiff(back, front, threshold), 0.0);
-
- // When comparing a layer with itself, zDiff is always 0.
- EXPECT_EQ(CCLayerSorter::calculateZDiff(front, front, threshold), 0.0);
- EXPECT_EQ(CCLayerSorter::calculateZDiff(back, back, threshold), 0.0);
-
- // Same again but with two layers that intersect only at one point (0,0).
- // This *does* count as obscuring, so we should get the same results.
-
- front = CCLayerSorter::LayerShape(
- FloatPoint3D(-1.0, 0.0, 5.0),
- FloatPoint3D(0.0, 0.0, 5.0),
- FloatPoint3D(0.0, -1.0, 5.0),
- FloatPoint3D(-1.0, -1.0, 5.0));
-
- back = CCLayerSorter::LayerShape(
- FloatPoint3D(0.0, 1.0, 4.0),
- FloatPoint3D(1.0, 1.0, 4.0),
- FloatPoint3D(1.0, 0.0, 4.0),
- FloatPoint3D(0.0, 0.0, 4.0));
-
- EXPECT_GT(CCLayerSorter::calculateZDiff(front, back, threshold), 0.0);
- EXPECT_LT(CCLayerSorter::calculateZDiff(back, front, threshold), 0.0);
- EXPECT_EQ(CCLayerSorter::calculateZDiff(front, front, threshold), 0.0);
- EXPECT_EQ(CCLayerSorter::calculateZDiff(back, back, threshold), 0.0);
+TEST(CCLayerSorterTest, LayersAtAngleOverlap)
+{
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
// Trickier test with layers at an angle.
//
@@ -120,42 +134,64 @@ TEST(CCLayerSorterTest, CalculateZDiff)
// +z /
//
// C is in front of A and behind B (not what you'd expect by comparing centers).
- // A and B don't overlap, so they're incomparable (zDiff = 0).
-
- const float yHi = 10.0;
- const float yLo = -10.0;
- const float zA = 1.0;
- const float zB = -1.0;
-
- CCLayerSorter::LayerShape layerA(
- FloatPoint3D(-10.0, yHi, zA),
- FloatPoint3D(-2.0, yHi, zA),
- FloatPoint3D(-2.0, yLo, zA),
- FloatPoint3D(-10.0, yLo, zA));
-
- CCLayerSorter::LayerShape layerB(
- FloatPoint3D(2.0, yHi, zB),
- FloatPoint3D(10.0, yHi, zB),
- FloatPoint3D(10.0, yLo, zB),
- FloatPoint3D(2.0, yLo, zB));
-
- CCLayerSorter::LayerShape layerC(
- FloatPoint3D(-5.0, yHi, 5.0),
- FloatPoint3D(5.0, yHi, -5.0),
- FloatPoint3D(5.0, yLo, -5.0),
- FloatPoint3D(-5.0, yLo, 5.0));
-
- EXPECT_EQ(CCLayerSorter::calculateZDiff(layerA, layerA, threshold), 0.0);
- EXPECT_EQ(CCLayerSorter::calculateZDiff(layerA, layerB, threshold), 0.0);
- EXPECT_LT(CCLayerSorter::calculateZDiff(layerA, layerC, threshold), 0.0);
-
- EXPECT_EQ(CCLayerSorter::calculateZDiff(layerB, layerA, threshold), 0.0);
- EXPECT_EQ(CCLayerSorter::calculateZDiff(layerB, layerB, threshold), 0.0);
- EXPECT_GT(CCLayerSorter::calculateZDiff(layerB, layerC, threshold), 0.0);
-
- EXPECT_GT(CCLayerSorter::calculateZDiff(layerC, layerA, threshold), 0.0);
- EXPECT_LT(CCLayerSorter::calculateZDiff(layerC, layerB, threshold), 0.0);
- EXPECT_EQ(CCLayerSorter::calculateZDiff(layerC, layerC, threshold), 0.0);
+ // A and B don't overlap, so they're incomparable.
+
+ TransformationMatrix transformA;
+ transformA.translate3d(-6, 0, 1);
+ CCLayerSorter::LayerShape layerA(8, 20, transformA);
+
+ TransformationMatrix transformB;
+ transformB.translate3d(6, 0, -1);
+ CCLayerSorter::LayerShape layerB(8, 20, transformB);
+
+ TransformationMatrix transformC;
+ transformC.rotate3d(0, 1, 0, 40);
+ CCLayerSorter::LayerShape layerC(8, 20, transformC);
+
+ overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerC, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult);
+ overlapResult = CCLayerSorter::checkOverlap(&layerC, &layerB, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult);
+ overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerB, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::None, overlapResult);
+}
+
+TEST(CCLayerSorterTest, LayersUnderPathologicalPerspectiveTransform)
+{
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ // On perspective projection, if w becomes negative, the re-projected point will be
+ // invalid and un-usable. Correct code needs to clip away portions of the geometry
+ // where w < 0. If the code uses the invalid value, it will think that a layer has
+ // different bounds than it really does, which can cause things to sort incorrectly.
+
+ TransformationMatrix perspectiveMatrix;
+ perspectiveMatrix.applyPerspective(1);
+
+ TransformationMatrix transformA;
+ transformA.translate3d(-15, 0, -2);
+ CCLayerSorter::LayerShape layerA(10, 10, perspectiveMatrix * transformA);
+
+ // With this sequence of transforms, when layer B is correctly clipped, it will be
+ // visible on the left half of the projection plane, in front of layerA. When it is
+ // not clipped, its bounds will actually incorrectly appear much smaller and the
+ // correct sorting dependency will not be found.
+ TransformationMatrix transformB;
+ transformB.translate3d(0, 0, 0.7);
+ transformB.rotate3d(0, 45, 0);
+ CCLayerSorter::LayerShape layerB(10, 10, perspectiveMatrix * transformB);
+
+ // Sanity check that the test case actually covers the intended scenario, where part
+ // of layer B go behind the w = 0 plane.
+ FloatQuad testQuad = FloatQuad(FloatRect(FloatPoint(-0.5, -0.5), FloatSize(1, 1)));
+ bool clipped = false;
+ CCMathUtil::mapQuad(perspectiveMatrix * transformB, testQuad, clipped);
+ ASSERT_TRUE(clipped);
+
+ overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerB, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult);
}
TEST(CCLayerSorterTest, verifyExistingOrderingPreservedWhenNoZDiff)
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
index e6206cc58..51a032618 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
@@ -26,14 +26,19 @@
#include "cc/CCLayerTreeHostCommon.h"
+#include "CCAnimationTestCommon.h"
#include "CCLayerTreeTestCommon.h"
#include "LayerChromium.h"
#include "TransformationMatrix.h"
+#include "TranslateTransformOperation.h"
+#include "cc/CCLayerAnimationController.h"
+#include "cc/CCMathUtil.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace WebKitTests;
namespace {
@@ -76,7 +81,7 @@ public:
{
}
- virtual bool drawsContent() const { return true; }
+ virtual bool drawsContent() const OVERRIDE { return true; }
};
TEST(CCLayerTreeHostCommonTest, verifyTransformsForNoOpLayer)
@@ -308,6 +313,56 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleRenderSurface)
EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->targetRenderSurface()->originTransform());
EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->targetRenderSurface()->drawTransform());
+ // The screen space is the same as the target since the child surface draws into the root.
+ EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->targetRenderSurface()->screenSpaceTransform());
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyTransformsForReplica)
+{
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> childReplica = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> grandChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ parent->createRenderSurface();
+ parent->addChild(child);
+ child->addChild(grandChild);
+ child->setReplicaLayer(childReplica.get());
+
+ // Child is set up so that a new render surface should be created.
+ child->setOpacity(0.5f);
+
+ TransformationMatrix identityMatrix;
+ TransformationMatrix parentLayerTransform;
+ parentLayerTransform.scale3d(2.0, 2.0, 1.0);
+ TransformationMatrix parentTranslationToAnchor;
+ parentTranslationToAnchor.translate(2.5, 3.0);
+ TransformationMatrix parentSublayerMatrix;
+ parentSublayerMatrix.scale3d(10.0, 10.0, 3.3);
+ TransformationMatrix parentTranslationToCenter;
+ parentTranslationToCenter.translate(5.0, 6.0);
+ TransformationMatrix parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse()
+ * parentTranslationToCenter * parentSublayerMatrix * parentTranslationToCenter.inverse();
+ TransformationMatrix childTranslationToCenter;
+ childTranslationToCenter.translate(8.0, 9.0);
+ TransformationMatrix replicaLayerTransform;
+ replicaLayerTransform.scale3d(3.0, 3.0, 1.0);
+ TransformationMatrix replicaCompositeTransform = parentCompositeTransform * replicaLayerTransform;
+
+ // Child's render surface should not exist yet.
+ ASSERT_FALSE(child->renderSurface());
+
+ setLayerPropertiesForTesting(parent.get(), parentLayerTransform, parentSublayerMatrix, FloatPoint(0.25f, 0.25f), FloatPoint(2.5f, 3.0f), IntSize(10, 12), false);
+ setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(16, 18), false);
+ setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(-0.5f, -0.5f), IntSize(1, 1), false);
+ setLayerPropertiesForTesting(childReplica.get(), replicaLayerTransform, identityMatrix, FloatPoint(0.0f, 0.0f), FloatPoint(0.0f, 0.0f), IntSize(0, 0), false);
+ executeCalculateDrawTransformsAndVisibility(parent.get());
+
+ // Render surface should have been created now.
+ ASSERT_TRUE(child->renderSurface());
+ ASSERT_EQ(child->renderSurface(), child->targetRenderSurface());
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(replicaCompositeTransform, child->targetRenderSurface()->replicaOriginTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(replicaCompositeTransform, child->targetRenderSurface()->replicaScreenSpaceTransform());
}
TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
@@ -315,6 +370,7 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
// This test creates a more complex tree and verifies it all at once. This covers the following cases:
// - layers that are described w.r.t. a render surface: should have draw transforms described w.r.t. that surface
// - A render surface described w.r.t. an ancestor render surface: should have a draw transform described w.r.t. that ancestor surface
+ // - Replicas of a render surface are described w.r.t. the replica's transform around its anchor, along with the surface itself.
// - 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.
@@ -324,6 +380,8 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
RefPtr<LayerChromium> childOfRoot = LayerChromium::create();
RefPtr<LayerChromium> childOfRS1 = LayerChromium::create();
RefPtr<LayerChromium> childOfRS2 = LayerChromium::create();
+ RefPtr<LayerChromium> replicaOfRS1 = LayerChromium::create();
+ RefPtr<LayerChromium> replicaOfRS2 = LayerChromium::create();
RefPtr<LayerChromium> grandChildOfRoot = LayerChromium::create();
RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
RefPtr<LayerChromiumWithForcedDrawsContent> grandChildOfRS2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
@@ -336,6 +394,8 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
childOfRoot->addChild(grandChildOfRoot);
childOfRS1->addChild(grandChildOfRS1);
childOfRS2->addChild(grandChildOfRS2);
+ renderSurface1->setReplicaLayer(replicaOfRS1.get());
+ renderSurface2->setReplicaLayer(replicaOfRS2.get());
// In combination with descendantDrawsContent, opacity != 1 forces the layer to have a new renderSurface.
renderSurface1->setOpacity(0.5f);
@@ -344,6 +404,7 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
// All layers in the tree are initialized with an anchor at 2.5 and a size of (10,10).
// matrix "A" is the composite layer transform used in all layers, centered about the anchor point
// matrix "B" is the sublayer transform used in all layers, centered about the center position of the layer.
+ // matrix "R" is the composite replica transform used in all replica layers.
//
// x component tests that layerTransform and sublayerTransform are done in the right order (translation and scale are noncommutative).
// y component has a translation by 1.0 for every ancestor, which indicates the "depth" of the layer in the hierarchy.
@@ -355,9 +416,12 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
layerTransform.translate(1.0, 1.0);
TransformationMatrix sublayerTransform;
sublayerTransform.scale3d(10.0, 1.0, 1.0);
+ TransformationMatrix replicaLayerTransform;
+ replicaLayerTransform.scale3d(-2.0, 5.0, 1.0);
TransformationMatrix A = translationToAnchor * layerTransform * translationToAnchor.inverse();
TransformationMatrix B = translationToCenter * sublayerTransform * translationToCenter.inverse();
+ TransformationMatrix R = A * translationToAnchor * replicaLayerTransform * translationToAnchor.inverse();
setLayerPropertiesForTesting(parent.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
setLayerPropertiesForTesting(renderSurface1.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
@@ -368,6 +432,8 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
setLayerPropertiesForTesting(grandChildOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
setLayerPropertiesForTesting(grandChildOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
setLayerPropertiesForTesting(grandChildOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(replicaOfRS1.get(), replicaLayerTransform, sublayerTransform, FloatPoint(), FloatPoint(2.5f, 0.0f), IntSize(), false);
+ setLayerPropertiesForTesting(replicaOfRS2.get(), replicaLayerTransform, sublayerTransform, FloatPoint(), FloatPoint(2.5f, 0.0f), IntSize(), false);
executeCalculateDrawTransformsAndVisibility(parent.get());
@@ -433,8 +499,14 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy)
//
// Origin transform of render surface 1 is described with respect to root.
EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->renderSurface()->originTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * R, renderSurface1->renderSurface()->replicaOriginTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->renderSurface()->screenSpaceTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * R, renderSurface1->renderSurface()->replicaScreenSpaceTransform());
// Origin transform of render surface 2 is described with respect to render surface 2.
EXPECT_TRANSFORMATION_MATRIX_EQ(B * A, renderSurface2->renderSurface()->originTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(B * R, renderSurface2->renderSurface()->replicaOriginTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, renderSurface2->renderSurface()->screenSpaceTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * R, renderSurface2->renderSurface()->replicaScreenSpaceTransform());
// Sanity check. If these fail there is probably a bug in the test itself.
// It is expected that we correctly set up transforms so that the y-component of the screen-space transform
@@ -457,7 +529,7 @@ TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForClipLayer)
RefPtr<LayerChromium> parent = LayerChromium::create();
RefPtr<LayerChromium> renderSurface1 = LayerChromium::create();
RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
- renderSurface1->setOpacity(0.9);
+ renderSurface1->setOpacity(0.9f);
const TransformationMatrix identityMatrix;
setLayerPropertiesForTesting(renderSurface1.get(), identityMatrix, identityMatrix, FloatPoint::zero(), FloatPoint::zero(), IntSize(10, 10), false);
@@ -550,9 +622,58 @@ TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces)
setLayerPropertiesForTesting(leafNode2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
child->setMasksToBounds(true);
- child->setOpacity(0.4);
- grandChild->setOpacity(0.5);
- greatGrandChild->setOpacity(0.4);
+ child->setOpacity(0.4f);
+ grandChild->setOpacity(0.5f);
+ greatGrandChild->setOpacity(0.4f);
+
+ 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->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent.get());
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ ASSERT_EQ(2U, renderSurfaceLayerList.size());
+ EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
+ EXPECT_EQ(child->id(), renderSurfaceLayerList[1]->id());
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfacesCrashRepro)
+{
+ // This is a similar situation as verifyClipRectCullsRenderSurfaces, except that
+ // it reproduces a crash bug http://code.google.com/p/chromium/issues/detail?id=106734.
+
+ const TransformationMatrix identityMatrix;
+ 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);
+ grandChild->addChild(greatGrandChild);
+
+ // leafNode1 ensures that parent and child are kept on the renderSurfaceLayerList,
+ // even though grandChild and greatGrandChild should be clipped.
+ child->addChild(leafNode1);
+ greatGrandChild->addChild(leafNode2);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
+ setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(45, 45), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(greatGrandChild.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(leafNode1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(leafNode2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
+
+ child->setMasksToBounds(true);
+ child->setOpacity(0.4f);
+ grandChild->setOpacity(0.5f);
+ greatGrandChild->setOpacity(0.4f);
// Contaminate the grandChild and greatGrandChild's clipRect to reproduce the crash
// bug found in http://code.google.com/p/chromium/issues/detail?id=106734. In this
@@ -561,9 +682,6 @@ TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces)
// renderSurface remains on the renderSurfaceLayerList, which violates the assumption
// that an empty renderSurface will always be the last item on the list, which
// ultimately caused the crash.
- //
- // FIXME: it is also useful to test with this commented out. Eventually we should
- // create several test cases that test clipRect/drawableContentRect computation.
child->setClipRect(IntRect(IntPoint::zero(), IntSize(20, 20)));
greatGrandChild->setClipRect(IntRect(IntPoint::zero(), IntSize(1234, 1234)));
@@ -582,6 +700,631 @@ TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces)
EXPECT_EQ(child->id(), renderSurfaceLayerList[1]->id());
}
+TEST(CCLayerTreeHostCommonTest, verifyClipRectIsPropagatedCorrectlyToLayers)
+{
+ // Verify that layers get the appropriate clipRects when their parent masksToBounds is true.
+ //
+ // grandChild1 - completely inside the region; clipRect should be the mask region (larger than this layer's bounds).
+ // grandChild2 - partially clipped but NOT masksToBounds; the clipRect should be the parent's clipRect regardless of the layer's bounds.
+ // grandChild3 - partially clipped and masksToBounds; the clipRect will be the intersection of layerBounds and the mask region.
+ // grandChild4 - outside parent's clipRect, and masksToBounds; the clipRect should be empty.
+ //
+
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild1 = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild2 = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild3 = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild4 = LayerChromium::create();
+
+ parent->createRenderSurface();
+ parent->addChild(child);
+ child->addChild(grandChild1);
+ child->addChild(grandChild2);
+ child->addChild(grandChild3);
+ child->addChild(grandChild4);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
+ setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(5, 5), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChild2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(15, 15), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChild3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(15, 15), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChild4.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(45, 45), IntSize(10, 10), false);
+
+ child->setMasksToBounds(true);
+ grandChild3->setMasksToBounds(true);
+ grandChild4->setMasksToBounds(true);
+
+ // Force everyone to be a render surface.
+ child->setOpacity(0.4f);
+ grandChild1->setOpacity(0.5f);
+ grandChild2->setOpacity(0.5f);
+ grandChild3->setOpacity(0.5f);
+ grandChild4->setOpacity(0.5f);
+
+ 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->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent.get());
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ EXPECT_INT_RECT_EQ(IntRect(IntPoint::zero(), IntSize(20, 20)), grandChild1->clipRect());
+ EXPECT_INT_RECT_EQ(IntRect(IntPoint::zero(), IntSize(20, 20)), grandChild2->clipRect());
+ EXPECT_INT_RECT_EQ(IntRect(IntPoint(15, 15), IntSize(5, 5)), grandChild3->clipRect());
+ EXPECT_TRUE(grandChild4->clipRect().isEmpty());
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyClipRectIsPropagatedCorrectlyToSurfaces)
+{
+ // Verify that renderSurfaces (and their layers) get the appropriate clipRects when their parent masksToBounds is true.
+ //
+ // Layers that own renderSurfaces (at least for now) do not inherit any clipRect;
+ // instead the surface will enforce the clip for the entire subtree. They may still
+ // have a clipRect of their own layer bounds, however, if masksToBounds was true.
+ //
+
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromium> child = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild1 = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild2 = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild3 = LayerChromium::create();
+ RefPtr<LayerChromium> grandChild4 = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> leafNode1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> leafNode2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> leafNode3 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> leafNode4 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+
+ parent->createRenderSurface();
+ parent->addChild(child);
+ child->addChild(grandChild1);
+ child->addChild(grandChild2);
+ child->addChild(grandChild3);
+ child->addChild(grandChild4);
+
+ // the leaf nodes ensure that these grandChildren become renderSurfaces for this test.
+ grandChild1->addChild(leafNode1);
+ grandChild2->addChild(leafNode2);
+ grandChild3->addChild(leafNode3);
+ grandChild4->addChild(leafNode4);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
+ setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(20, 20), false);
+ setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(5, 5), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChild2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(15, 15), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChild3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(15, 15), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChild4.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(45, 45), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(leafNode1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(leafNode2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(leafNode3.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(leafNode4.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), false);
+
+ child->setMasksToBounds(true);
+ grandChild3->setMasksToBounds(true);
+ grandChild4->setMasksToBounds(true);
+
+ // Force everyone to be a render surface.
+ child->setOpacity(0.4f);
+ grandChild1->setOpacity(0.5f);
+ grandChild2->setOpacity(0.5f);
+ grandChild3->setOpacity(0.5f);
+ grandChild4->setOpacity(0.5f);
+
+ 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->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent.get());
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ ASSERT_TRUE(grandChild1->renderSurface());
+ ASSERT_TRUE(grandChild2->renderSurface());
+ ASSERT_TRUE(grandChild3->renderSurface());
+ EXPECT_FALSE(grandChild4->renderSurface()); // Because grandChild4 is entirely clipped, it is expected to not have a renderSurface.
+
+ // Surfaces are clipped by their parent, but un-affected by the owning layer's masksToBounds.
+ EXPECT_INT_RECT_EQ(IntRect(IntPoint(0, 0), IntSize(20, 20)), grandChild1->renderSurface()->clipRect());
+ EXPECT_INT_RECT_EQ(IntRect(IntPoint(0, 0), IntSize(20, 20)), grandChild2->renderSurface()->clipRect());
+ EXPECT_INT_RECT_EQ(IntRect(IntPoint(0, 0), IntSize(20, 20)), grandChild3->renderSurface()->clipRect());
+
+ // Layers do not inherit the clipRect from their owned surfaces, but if masksToBounds is true, they do create their own clipRect.
+ EXPECT_FALSE(grandChild1->usesLayerClipping());
+ EXPECT_FALSE(grandChild2->usesLayerClipping());
+ EXPECT_TRUE(grandChild3->usesLayerClipping());
+ EXPECT_TRUE(grandChild4->usesLayerClipping());
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyAnimationsForRenderSurfaceHierarchy)
+{
+ 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);
+ renderSurface1->addChild(childOfRS1);
+ renderSurface1->addChild(renderSurface2);
+ renderSurface2->addChild(childOfRS2);
+ childOfRoot->addChild(grandChildOfRoot);
+ childOfRS1->addChild(grandChildOfRS1);
+ childOfRS2->addChild(grandChildOfRS2);
+
+ // In combination with descendantDrawsContent, opacity != 1 forces the layer to have a new renderSurface.
+ addOpacityTransitionToController(*renderSurface1->layerAnimationController(), 10, 1, 0, false);
+
+ // Also put an animated opacity on a layer without descendants.
+ addOpacityTransitionToController(*grandChildOfRoot->layerAnimationController(), 10, 1, 0, false);
+
+ TransformationMatrix layerTransform;
+ layerTransform.translate(1.0, 1.0);
+ TransformationMatrix sublayerTransform;
+ sublayerTransform.scale3d(10.0, 1.0, 1.0);
+
+ // In combination with descendantDrawsContent, an animated transform forces the layer to have a new renderSurface.
+ addAnimatedTransformToController(*renderSurface2->layerAnimationController(), 10, 30, 0);
+
+ // Also put transform animations on grandChildOfRoot, and grandChildOfRS2
+ addAnimatedTransformToController(*grandChildOfRoot->layerAnimationController(), 10, 30, 0);
+ addAnimatedTransformToController(*grandChildOfRS2->layerAnimationController(), 10, 30, 0);
+
+ setLayerPropertiesForTesting(parent.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(renderSurface1.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(renderSurface2.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(childOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(childOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(childOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChildOfRoot.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChildOfRS1.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+ setLayerPropertiesForTesting(grandChildOfRS2.get(), layerTransform, sublayerTransform, FloatPoint(0.25f, 0.0f), FloatPoint(2.5f, 0.0f), IntSize(10, 10), false);
+
+ executeCalculateDrawTransformsAndVisibility(parent.get());
+
+ // Only layers that are associated with render surfaces should have an actual renderSurface() value.
+ //
+ ASSERT_TRUE(parent->renderSurface());
+ ASSERT_FALSE(childOfRoot->renderSurface());
+ ASSERT_FALSE(grandChildOfRoot->renderSurface());
+
+ ASSERT_TRUE(renderSurface1->renderSurface());
+ ASSERT_FALSE(childOfRS1->renderSurface());
+ ASSERT_FALSE(grandChildOfRS1->renderSurface());
+
+ ASSERT_TRUE(renderSurface2->renderSurface());
+ ASSERT_FALSE(childOfRS2->renderSurface());
+ ASSERT_FALSE(grandChildOfRS2->renderSurface());
+
+ // Verify all targetRenderSurface accessors
+ //
+ EXPECT_EQ(parent->renderSurface(), parent->targetRenderSurface());
+ EXPECT_EQ(parent->renderSurface(), childOfRoot->targetRenderSurface());
+ EXPECT_EQ(parent->renderSurface(), grandChildOfRoot->targetRenderSurface());
+
+ EXPECT_EQ(renderSurface1->renderSurface(), renderSurface1->targetRenderSurface());
+ EXPECT_EQ(renderSurface1->renderSurface(), childOfRS1->targetRenderSurface());
+ EXPECT_EQ(renderSurface1->renderSurface(), grandChildOfRS1->targetRenderSurface());
+
+ EXPECT_EQ(renderSurface2->renderSurface(), renderSurface2->targetRenderSurface());
+ EXPECT_EQ(renderSurface2->renderSurface(), childOfRS2->targetRenderSurface());
+ EXPECT_EQ(renderSurface2->renderSurface(), grandChildOfRS2->targetRenderSurface());
+
+ // Verify drawOpacityIsAnimating values
+ //
+ EXPECT_FALSE(parent->drawOpacityIsAnimating());
+ EXPECT_FALSE(childOfRoot->drawOpacityIsAnimating());
+ EXPECT_TRUE(grandChildOfRoot->drawOpacityIsAnimating());
+ EXPECT_FALSE(renderSurface1->drawOpacityIsAnimating());
+ EXPECT_TRUE(renderSurface1->renderSurface()->drawOpacityIsAnimating());
+ EXPECT_FALSE(childOfRS1->drawOpacityIsAnimating());
+ EXPECT_FALSE(grandChildOfRS1->drawOpacityIsAnimating());
+ EXPECT_FALSE(renderSurface2->drawOpacityIsAnimating());
+ EXPECT_FALSE(renderSurface2->renderSurface()->drawOpacityIsAnimating());
+ EXPECT_FALSE(childOfRS2->drawOpacityIsAnimating());
+ EXPECT_FALSE(grandChildOfRS2->drawOpacityIsAnimating());
+
+ // Verify drawTransformsAnimatingInTarget values
+ //
+ EXPECT_FALSE(parent->drawTransformIsAnimating());
+ EXPECT_FALSE(childOfRoot->drawTransformIsAnimating());
+ EXPECT_TRUE(grandChildOfRoot->drawTransformIsAnimating());
+ EXPECT_FALSE(renderSurface1->drawTransformIsAnimating());
+ EXPECT_FALSE(renderSurface1->renderSurface()->targetSurfaceTransformsAreAnimating());
+ EXPECT_FALSE(childOfRS1->drawTransformIsAnimating());
+ EXPECT_FALSE(grandChildOfRS1->drawTransformIsAnimating());
+ EXPECT_FALSE(renderSurface2->drawTransformIsAnimating());
+ EXPECT_TRUE(renderSurface2->renderSurface()->targetSurfaceTransformsAreAnimating());
+ EXPECT_FALSE(childOfRS2->drawTransformIsAnimating());
+ EXPECT_TRUE(grandChildOfRS2->drawTransformIsAnimating());
+
+ // Verify drawTransformsAnimatingInScreen values
+ //
+ EXPECT_FALSE(parent->screenSpaceTransformIsAnimating());
+ EXPECT_FALSE(childOfRoot->screenSpaceTransformIsAnimating());
+ EXPECT_TRUE(grandChildOfRoot->screenSpaceTransformIsAnimating());
+ EXPECT_FALSE(renderSurface1->screenSpaceTransformIsAnimating());
+ EXPECT_FALSE(renderSurface1->renderSurface()->screenSpaceTransformsAreAnimating());
+ EXPECT_FALSE(childOfRS1->screenSpaceTransformIsAnimating());
+ EXPECT_FALSE(grandChildOfRS1->screenSpaceTransformIsAnimating());
+ EXPECT_TRUE(renderSurface2->screenSpaceTransformIsAnimating());
+ EXPECT_TRUE(renderSurface2->renderSurface()->screenSpaceTransformsAreAnimating());
+ EXPECT_TRUE(childOfRS2->screenSpaceTransformIsAnimating());
+ EXPECT_TRUE(grandChildOfRS2->screenSpaceTransformIsAnimating());
+
+
+ // Sanity check. If these fail there is probably a bug in the test itself.
+ // It is expected that we correctly set up transforms so that the y-component of the screen-space transform
+ // encodes the "depth" of the layer in the tree.
+ EXPECT_FLOAT_EQ(1.0, parent->screenSpaceTransform().m42());
+ EXPECT_FLOAT_EQ(2.0, childOfRoot->screenSpaceTransform().m42());
+ EXPECT_FLOAT_EQ(3.0, grandChildOfRoot->screenSpaceTransform().m42());
+
+ EXPECT_FLOAT_EQ(2.0, renderSurface1->screenSpaceTransform().m42());
+ EXPECT_FLOAT_EQ(3.0, childOfRS1->screenSpaceTransform().m42());
+ EXPECT_FLOAT_EQ(4.0, grandChildOfRS1->screenSpaceTransform().m42());
+
+ EXPECT_FLOAT_EQ(3.0, renderSurface2->screenSpaceTransform().m42());
+ EXPECT_FLOAT_EQ(4.0, childOfRS2->screenSpaceTransform().m42());
+ EXPECT_FLOAT_EQ(5.0, grandChildOfRS2->screenSpaceTransform().m42());
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyVisibleRectForIdentityTransform)
+{
+ // Test the calculateVisibleRect() function works correctly for identity transforms.
+
+ IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ TransformationMatrix layerToSurfaceTransform;
+
+ // Case 1: Layer is contained within the surface.
+ IntRect layerContentRect = IntRect(IntPoint(10, 10), IntSize(30, 30));
+ IntRect expected = IntRect(IntPoint(10, 10), IntSize(30, 30));
+ IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+
+ // Case 2: Layer is outside the surface rect.
+ layerContentRect = IntRect(IntPoint(120, 120), IntSize(30, 30));
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_TRUE(actual.isEmpty());
+
+ // Case 3: Layer is partially overlapping the surface rect.
+ layerContentRect = IntRect(IntPoint(80, 80), IntSize(30, 30));
+ expected = IntRect(IntPoint(80, 80), IntSize(20, 20));
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyVisibleRectForTranslations)
+{
+ // Test the calculateVisibleRect() function works correctly for scaling transforms.
+
+ IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ IntRect layerContentRect = IntRect(IntPoint(0, 0), IntSize(30, 30));
+ TransformationMatrix layerToSurfaceTransform;
+
+ // Case 1: Layer is contained within the surface.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.translate(10, 10);
+ IntRect expected = IntRect(IntPoint(0, 0), IntSize(30, 30));
+ IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+
+ // Case 2: Layer is outside the surface rect.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.translate(120, 120);
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_TRUE(actual.isEmpty());
+
+ // Case 3: Layer is partially overlapping the surface rect.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.translate(80, 80);
+ expected = IntRect(IntPoint(0, 0), IntSize(20, 20));
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor2DRotations)
+{
+ // Test the calculateVisibleRect() function works correctly for rotations about z-axis (i.e. 2D rotations).
+ // Remember that calculateVisibleRect() should return the visible rect in the layer's space.
+
+ IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ IntRect layerContentRect = IntRect(IntPoint(0, 0), IntSize(30, 30));
+ TransformationMatrix layerToSurfaceTransform;
+
+ // Case 1: Layer is contained within the surface.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.translate(50, 50);
+ layerToSurfaceTransform.rotate(45);
+ IntRect expected = IntRect(IntPoint(0, 0), IntSize(30, 30));
+ IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+
+ // Case 2: Layer is outside the surface rect.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.translate(-50, 0);
+ layerToSurfaceTransform.rotate(45);
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_TRUE(actual.isEmpty());
+
+ // Case 3: The layer is rotated about its top-left corner. In surface space, the layer
+ // is oriented diagonally, with the left half outside of the renderSurface. In
+ // this case, the visible rect should still be the entire layer (remember the
+ // visible rect is computed in layer space); both the top-left and
+ // bottom-right corners of the layer are still visible.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.rotate(45);
+ expected = IntRect(IntPoint(0, 0), IntSize(30, 30));
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+
+ // Case 4: The layer is rotated about its top-left corner, and translated upwards. In
+ // surface space, the layer is oriented diagonally, with only the top corner
+ // of the surface overlapping the layer. In layer space, the render surface
+ // overlaps the right side of the layer. The visible rect should be the
+ // layer's right half.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.translate(0, -sqrt(2.0) * 15);
+ layerToSurfaceTransform.rotate(45);
+ expected = IntRect(IntPoint(15, 0), IntSize(15, 30)); // right half of layer bounds.
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor3dOrthographicTransform)
+{
+ // Test that the calculateVisibleRect() function works correctly for 3d transforms.
+
+ IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ IntRect layerContentRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ TransformationMatrix layerToSurfaceTransform;
+
+ // Case 1: Orthographic projection of a layer rotated about y-axis by 45 degrees, should be fully contained in the renderSurface.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.rotate3d(0, 45, 0);
+ IntRect expected = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+
+ // Case 2: Orthographic projection of a layer rotated about y-axis by 45 degrees, but
+ // shifted to the side so only the right-half the layer would be visible on
+ // the surface.
+ double halfWidthOfRotatedLayer = (100.0 / sqrt(2.0)) * 0.5; // 100.0 is the un-rotated layer width; divided by sqrt(2.0) is the rotated width.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.translate(-halfWidthOfRotatedLayer, 0);
+ layerToSurfaceTransform.rotate3d(0, 45, 0); // rotates about the left edge of the layer
+ expected = IntRect(IntPoint(50, 0), IntSize(50, 100)); // right half of the layer.
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor3dPerspectiveTransform)
+{
+ // Test the calculateVisibleRect() function works correctly when the layer has a
+ // perspective projection onto the target surface.
+
+ IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ IntRect layerContentRect = IntRect(IntPoint(-50, -50), IntSize(200, 200));
+ TransformationMatrix layerToSurfaceTransform;
+
+ // Case 1: Even though the layer is twice as large as the surface, due to perspective
+ // foreshortening, the layer will fit fully in the surface when its translated
+ // more than the perspective amount.
+ layerToSurfaceTransform.makeIdentity();
+
+ // The following sequence of transforms applies the perspective about the center of the surface.
+ layerToSurfaceTransform.translate(50, 50);
+ layerToSurfaceTransform.applyPerspective(9);
+ layerToSurfaceTransform.translate(-50, -50);
+
+ // This translate places the layer in front of the surface's projection plane.
+ layerToSurfaceTransform.translate3d(0, 0, -27);
+
+ IntRect expected = IntRect(IntPoint(-50, -50), IntSize(200, 200));
+ IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+
+ // Case 2: same projection as before, except that the layer is also translated to the
+ // side, so that only the right half of the layer should be visible.
+ //
+ // Explanation of expected result:
+ // The perspective ratio is (z distance between layer and camera origin) / (z distance between projection plane and camera origin) == ((-27 - 9) / 9)
+ // Then, by similar triangles, if we want to move a layer by translating -50 units in projected surface units (so that only half of it is
+ // visible), then we would need to translate by (-36 / 9) * -50 == -200 in the layer's units.
+ //
+ layerToSurfaceTransform.translate3d(-200, 0, 0);
+ expected = IntRect(IntPoint(50, -50), IntSize(100, 200)); // The right half of the layer's bounding rect.
+ actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor3dOrthographicIsNotClippedBehindSurface)
+{
+ // There is currently no explicit concept of an orthographic projection plane in our
+ // code (nor in the CSS spec to my knowledge). Therefore, layers that are technically
+ // behind the surface in an orthographic world should not be clipped when they are
+ // flattened to the surface.
+
+ IntRect targetSurfaceRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ IntRect layerContentRect = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ TransformationMatrix layerToSurfaceTransform;
+
+ // This sequence of transforms effectively rotates the layer about the y-axis at the
+ // center of the layer.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.translate(50, 0);
+ layerToSurfaceTransform.rotate3d(0, 45, 0);
+ layerToSurfaceTransform.translate(-50, 0);
+
+ IntRect expected = IntRect(IntPoint(0, 0), IntSize(100, 100));
+ IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyVisibleRectFor3dPerspectiveIsClipped)
+{
+ // Test the calculateVisibleRect() function works correctly when projecting a surface
+ // onto a layer, but the layer is partially behind the camera (not just behind the
+ // projection plane). In this case, the cartesian coordinates may seem to be valid,
+ // but actually they are not. The visibleRect needs to be properly clipped by the
+ // w = 0 plane in homogeneous coordinates before converting to cartesian coordinates.
+
+ IntRect targetSurfaceRect = IntRect(IntPoint(-50, -50), IntSize(100, 100));
+ IntRect layerContentRect = IntRect(IntPoint(-10, -1), IntSize(20, 2));
+ TransformationMatrix layerToSurfaceTransform;
+
+ // The layer is positioned so that the right half of the layer should be in front of
+ // the camera, while the other half is behind the surface's projection plane. The
+ // following sequence of transforms applies the perspective and rotation about the
+ // center of the layer.
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.applyPerspective(1);
+ layerToSurfaceTransform.translate3d(0, 0, 1);
+ layerToSurfaceTransform.rotate3d(0, 45, 0);
+
+ // Sanity check that this transform does indeed cause w < 0 when applying the
+ // transform, otherwise this code is not testing the intended scenario.
+ bool clipped = false;
+ CCMathUtil::mapQuad(layerToSurfaceTransform, FloatQuad(FloatRect(layerContentRect)), clipped);
+ ASSERT_TRUE(clipped);
+
+ int expectedXPosition = -10;
+ int expectedWidth = 10;
+ IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_EQ(expectedXPosition, actual.x());
+ EXPECT_EQ(expectedWidth, actual.width());
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyVisibleRectForPerspectiveUnprojection)
+{
+ // To determine visibleRect in layer space, there needs to be an un-projection from
+ // surface space to layer space. When the original transform was a perspective
+ // projection that was clipped, it returns a rect that encloses the clipped bounds.
+ // Un-projecting this new rect may require clipping again.
+
+ // This sequence of transforms causes one corner of the layer to protrude across the w = 0 plane, and should be clipped.
+ IntRect targetSurfaceRect = IntRect(IntPoint(-50, -50), IntSize(100, 100));
+ IntRect layerContentRect = IntRect(IntPoint(-10, -10), IntSize(20, 20));
+ TransformationMatrix layerToSurfaceTransform;
+ layerToSurfaceTransform.makeIdentity();
+ layerToSurfaceTransform.applyPerspective(1);
+ layerToSurfaceTransform.translate3d(0, 0, -5);
+ layerToSurfaceTransform.rotate3d(0, 45, 0);
+ layerToSurfaceTransform.rotate3d(80, 0, 0);
+
+ // Sanity check that un-projection does indeed cause w < 0, otherwise this code is not
+ // testing the intended scenario.
+ bool clipped = false;
+ FloatRect clippedRect = CCMathUtil::mapClippedRect(layerToSurfaceTransform, layerContentRect);
+ CCMathUtil::projectQuad(layerToSurfaceTransform.inverse(), FloatQuad(clippedRect), clipped);
+ ASSERT_TRUE(clipped);
+
+ // Only the corner of the layer is not visible on the surface because of being
+ // clipped. But, the net result of rounding visible region to an axis-aligned rect is
+ // that the entire layer should still be considered visible.
+ IntRect expected = IntRect(IntPoint(-10, -10), IntSize(20, 20));
+ IntRect actual = CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceRect, layerContentRect, layerToSurfaceTransform);
+ EXPECT_INT_RECT_EQ(expected, actual);
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyBackFaceCulling)
+{
+ // Verify that layers are appropriately culled when their back face is showing and they are not double sided.
+ //
+ // Layers that are animating do not get culled on the main thread, as their transforms should be
+ // treated as "unknown" so we can not be sure that their back face is really showing.
+ //
+
+ const TransformationMatrix identityMatrix;
+ RefPtr<LayerChromium> parent = LayerChromium::create();
+ RefPtr<LayerChromiumWithForcedDrawsContent> child = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> animatingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> childOfAnimatingSurface = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> animatingChild = adoptRef(new LayerChromiumWithForcedDrawsContent());
+ RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
+
+ parent->createRenderSurface();
+ parent->addChild(child);
+ parent->addChild(animatingSurface);
+ animatingSurface->addChild(childOfAnimatingSurface);
+ parent->addChild(animatingChild);
+ parent->addChild(child2);
+
+ // Nothing is double-sided
+ child->setDoubleSided(false);
+ child2->setDoubleSided(false);
+ animatingSurface->setDoubleSided(false);
+ childOfAnimatingSurface->setDoubleSided(false);
+ animatingChild->setDoubleSided(false);
+
+ TransformationMatrix backfaceMatrix;
+ backfaceMatrix.translate(50, 50);
+ backfaceMatrix.rotate3d(0, 1, 0, 180);
+ backfaceMatrix.translate(-50, -50);
+
+ // Having a descendent, and animating transforms, will make the animatingSurface own a render surface.
+ addAnimatedTransformToController(*animatingSurface->layerAnimationController(), 10, 30, 0);
+ // This is just an animating layer, not a surface.
+ addAnimatedTransformToController(*animatingChild->layerAnimationController(), 10, 30, 0);
+
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(animatingSurface.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(childOfAnimatingSurface.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(animatingChild.get(), backfaceMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+ setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false);
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->renderSurface()->setContentRect(IntRect(IntPoint(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent.get());
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ EXPECT_FALSE(child->renderSurface());
+ EXPECT_TRUE(animatingSurface->renderSurface());
+ EXPECT_FALSE(childOfAnimatingSurface->renderSurface());
+ EXPECT_FALSE(animatingChild->renderSurface());
+ EXPECT_FALSE(child2->renderSurface());
+
+ // Verify that the animatingChild and childOfAnimatingSurface were not culled, but that child was.
+ ASSERT_EQ(2u, renderSurfaceLayerList.size());
+ EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id());
+ EXPECT_EQ(animatingSurface->id(), renderSurfaceLayerList[1]->id());
+
+ // The non-animating child be culled from the layer list for the parent render surface.
+ ASSERT_EQ(3u, renderSurfaceLayerList[0]->renderSurface()->layerList().size());
+ EXPECT_EQ(animatingSurface->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[0]->id());
+ EXPECT_EQ(animatingChild->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[1]->id());
+ EXPECT_EQ(child2->id(), renderSurfaceLayerList[0]->renderSurface()->layerList()[2]->id());
+
+ ASSERT_EQ(2u, renderSurfaceLayerList[1]->renderSurface()->layerList().size());
+ EXPECT_EQ(animatingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[0]->id());
+ EXPECT_EQ(childOfAnimatingSurface->id(), renderSurfaceLayerList[1]->renderSurface()->layerList()[1]->id());
+
+ EXPECT_FALSE(child2->visibleLayerRect().isEmpty());
+
+ // But if the back face is visible, then the visibleLayerRect should be empty.
+ EXPECT_TRUE(animatingChild->visibleLayerRect().isEmpty());
+ EXPECT_TRUE(animatingSurface->visibleLayerRect().isEmpty());
+ // And any layers in the subtree should not be considered visible either.
+ EXPECT_TRUE(childOfAnimatingSurface->visibleLayerRect().isEmpty());
+}
+
// FIXME:
// continue working on https://bugs.webkit.org/show_bug.cgi?id=68942
// - add a test to verify clipping that changes the "center point"
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
index d75c12890..ff2497085 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
@@ -26,16 +26,28 @@
#include "cc/CCLayerTreeHostImpl.h"
+#include "CCAnimationTestCommon.h"
+#include "CCLayerTestCommon.h"
#include "FakeWebGraphicsContext3D.h"
#include "GraphicsContext3DPrivate.h"
#include "LayerRendererChromium.h"
#include "cc/CCLayerImpl.h"
+#include "cc/CCLayerTilingData.h"
+#include "cc/CCQuadCuller.h"
+#include "cc/CCScrollbarLayerImpl.h"
#include "cc/CCSingleThreadProxy.h"
-#include "cc/CCSolidColorDrawQuad.h"
+#include "cc/CCTextureLayerImpl.h"
+#include "cc/CCTileDrawQuad.h"
+#include "cc/CCTiledLayerImpl.h"
+#include "cc/CCVideoLayerImpl.h"
#include <gtest/gtest.h>
+#include <public/WebVideoFrame.h>
+#include <public/WebVideoFrameProvider.h>
+using namespace CCLayerTestCommon;
using namespace WebCore;
using namespace WebKit;
+using namespace WebKitTests;
namespace {
@@ -49,11 +61,12 @@ public:
m_hostImpl = CCLayerTreeHostImpl::create(settings, this);
}
- virtual void didLoseContextOnImplThread() { }
- virtual void onSwapBuffersCompleteOnImplThread() { }
- virtual void setNeedsRedrawOnImplThread() { m_didRequestRedraw = true; }
- virtual void setNeedsCommitOnImplThread() { m_didRequestCommit = true; }
- virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) { }
+ virtual void didLoseContextOnImplThread() OVERRIDE { }
+ virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE { }
+ virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_didRequestRedraw = true; }
+ virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; }
+ virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE { }
+ virtual void postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t) OVERRIDE { }
static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer)
{
@@ -250,7 +263,9 @@ TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionWithOffset)
root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
root->setPosition(FloatPoint(-25, 0));
m_hostImpl->setRootLayer(root.release());
- m_hostImpl->drawLayers(); // Update draw transforms so we can correctly map points into layer space.
+ CCLayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame); // Update draw transforms so we can correctly map points into layer space.
// This point would fall into the non-fast scrollable region except that we've moved the layer down by 25 pixels.
EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(40, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
@@ -310,7 +325,7 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture)
scrollLayer->setScrollDelta(IntSize());
scrollLayer->setScrollPosition(IntPoint(50, 50));
- float pageScaleDelta = 0.1;
+ float pageScaleDelta = 0.1f;
m_hostImpl->pinchGestureBegin();
m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(0, 0));
m_hostImpl->pinchGestureEnd();
@@ -390,7 +405,7 @@ TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation)
}
}
-class DidDrawCheckLayer : public CCLayerImpl {
+class DidDrawCheckLayer : public CCTiledLayerImpl {
public:
static PassOwnPtr<DidDrawCheckLayer> create(int id) { return adoptPtr(new DidDrawCheckLayer(id)); }
@@ -407,9 +422,9 @@ public:
bool didDrawCalled() const { return m_didDrawCalled; }
bool willDrawCalled() const { return m_willDrawCalled; }
-private:
+protected:
explicit DidDrawCheckLayer(int id)
- : CCLayerImpl(id)
+ : CCTiledLayerImpl(id)
, m_didDrawCalled(false)
, m_willDrawCalled(false)
{
@@ -418,6 +433,7 @@ private:
setDrawsContent(true);
}
+private:
bool m_didDrawCalled;
bool m_willDrawCalled;
};
@@ -432,10 +448,14 @@ TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer)
m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
+ CCLayerTreeHostImpl::FrameData frame;
+
EXPECT_FALSE(root->willDrawCalled());
EXPECT_FALSE(root->didDrawCalled());
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
EXPECT_FALSE(root->willDrawCalled());
EXPECT_FALSE(root->didDrawCalled());
@@ -448,7 +468,9 @@ TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer)
EXPECT_FALSE(root->willDrawCalled());
EXPECT_FALSE(root->didDrawCalled());
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
EXPECT_TRUE(root->willDrawCalled());
EXPECT_TRUE(root->didDrawCalled());
@@ -470,14 +492,17 @@ TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
layer1->addChild(DidDrawCheckLayer::create(2));
DidDrawCheckLayer* layer2 = static_cast<DidDrawCheckLayer*>(layer1->children()[0].get());
- layer1->setOpacity(0.3);
+ layer1->setOpacity(0.3f);
layer1->setPreserves3D(false);
EXPECT_FALSE(root->didDrawCalled());
EXPECT_FALSE(layer1->didDrawCalled());
EXPECT_FALSE(layer2->didDrawCalled());
- m_hostImpl->drawLayers();
+ CCLayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
EXPECT_TRUE(root->didDrawCalled());
EXPECT_TRUE(layer1->didDrawCalled());
@@ -487,6 +512,71 @@ TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
EXPECT_TRUE(!!layer1->renderSurface());
}
+class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
+public:
+ static PassOwnPtr<MissingTextureAnimatingLayer> create(int id, bool tileMissing, bool skipsDraw, bool animating) { return adoptPtr(new MissingTextureAnimatingLayer(id, tileMissing, skipsDraw, animating)); }
+
+private:
+ explicit MissingTextureAnimatingLayer(int id, bool tileMissing, bool skipsDraw, bool animating)
+ : DidDrawCheckLayer(id)
+ {
+ OwnPtr<CCLayerTilingData> tilingData = CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels);
+ tilingData->setBounds(bounds());
+ setTilingData(*tilingData.get());
+ setSkipsDraw(skipsDraw);
+ if (!tileMissing)
+ pushTileProperties(0, 0, 1, IntRect());
+ if (animating)
+ addAnimatedTransformToLayer(*this, 10, 3, 0);
+ }
+};
+
+TEST_F(CCLayerTreeHostImplTest, prepareToDrawFailsWhenAnimationUsesCheckerboard)
+{
+ m_hostImpl->initializeLayerRenderer(createContext());
+ m_hostImpl->setViewportSize(IntSize(10, 10));
+
+ // When the texture is not missing, we draw as usual.
+ m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
+ DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
+ root->addChild(MissingTextureAnimatingLayer::create(1, false, false, true));
+
+ CCLayerTreeHostImpl::FrameData frame;
+
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+
+ // When a texture is missing and we're not animating, we draw as usual with checkerboarding.
+ m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
+ root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
+ root->addChild(MissingTextureAnimatingLayer::create(1, true, false, false));
+
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+
+ // When a texture is missing and we're animating, we don't want to draw anything.
+ m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
+ root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
+ root->addChild(MissingTextureAnimatingLayer::create(1, true, false, true));
+
+ m_didRequestCommit = false;
+ EXPECT_FALSE(m_hostImpl->prepareToDraw(frame));
+ EXPECT_TRUE(m_didRequestCommit);
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+
+ // When the layer skips draw and we're animating, we still draw the frame.
+ m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
+ root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
+ root->addChild(MissingTextureAnimatingLayer::create(1, false, true, true));
+
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+}
+
class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
public:
BlendStateTrackerContext() : m_blend(false) { }
@@ -513,14 +603,20 @@ class BlendStateCheckLayer : public CCLayerImpl {
public:
static PassOwnPtr<BlendStateCheckLayer> create(int id) { return adoptPtr(new BlendStateCheckLayer(id)); }
- virtual void appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState)
+ virtual void appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&) OVERRIDE
{
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);
+ IntRect opaqueRect;
+ if (opaque() || m_opaqueContents)
+ opaqueRect = m_quadRect;
+ else
+ opaqueRect = m_opaqueContentRect;
+ OwnPtr<CCDrawQuad> testBlendingDrawQuad = CCTileDrawQuad::create(sharedQuadState, m_quadRect, opaqueRect, 0, IntPoint(), IntSize(1, 1), 0, false, false, false, false, false);
+ testBlendingDrawQuad->setQuadVisibleRect(m_quadVisibleRect);
EXPECT_EQ(m_blend, testBlendingDrawQuad->needsBlending());
EXPECT_EQ(m_hasRenderSurface, !!renderSurface());
+ quadList.append(testBlendingDrawQuad.release());
}
void setExpectation(bool blend, bool hasRenderSurface)
@@ -532,7 +628,10 @@ public:
bool quadsAppended() const { return m_quadsAppended; }
- void setOpaqueColor(bool opaqueColor) { m_opaqueColor = opaqueColor; }
+ void setQuadRect(const IntRect& rect) { m_quadRect = rect; }
+ void setQuadVisibleRect(const IntRect& rect) { m_quadVisibleRect = rect; }
+ void setOpaqueContents(bool opaque) { m_opaqueContents = opaque; }
+ void setOpaqueContentRect(const IntRect& rect) { m_opaqueContentRect = rect; }
private:
explicit BlendStateCheckLayer(int id)
@@ -540,7 +639,9 @@ private:
, m_blend(false)
, m_hasRenderSurface(false)
, m_quadsAppended(false)
- , m_opaqueColor(true)
+ , m_opaqueContents(false)
+ , m_quadRect(5, 5, 5, 5)
+ , m_quadVisibleRect(5, 5, 5, 5)
{
setAnchorPoint(FloatPoint(0, 0));
setBounds(IntSize(10, 10));
@@ -550,7 +651,10 @@ private:
bool m_blend;
bool m_hasRenderSurface;
bool m_quadsAppended;
- bool m_opaqueColor;
+ bool m_opaqueContents;
+ IntRect m_quadRect;
+ IntRect m_opaqueContentRect;
+ IntRect m_quadVisibleRect;
};
// https://bugs.webkit.org/show_bug.cgi?id=75783
@@ -571,78 +675,96 @@ TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
root->addChild(BlendStateCheckLayer::create(1));
BlendStateCheckLayer* layer1 = static_cast<BlendStateCheckLayer*>(root->children()[0].get());
+ CCLayerTreeHostImpl::FrameData frame;
+
// Opaque layer, drawn without blending.
layer1->setOpaque(true);
- layer1->setOpaqueColor(true);
+ layer1->setOpaqueContents(true);
layer1->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
- // Layer with translucent content, but solid color is opaque, so drawn without blending.
+ // Layer with translucent content, but opaque content, so drawn without blending.
layer1->setOpaque(false);
- layer1->setOpaqueColor(true);
+ layer1->setOpaqueContents(true);
layer1->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// Layer with translucent content and painting, so drawn with blending.
layer1->setOpaque(false);
- layer1->setOpaqueColor(false);
+ layer1->setOpaqueContents(false);
layer1->setExpectation(true, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// Layer with translucent opacity, drawn with blending.
layer1->setOpaque(true);
- layer1->setOpaqueColor(true);
+ layer1->setOpaqueContents(true);
layer1->setOpacity(0.5);
layer1->setExpectation(true, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// Layer with translucent opacity and painting, drawn with blending.
layer1->setOpaque(true);
- layer1->setOpaqueColor(false);
+ layer1->setOpaqueContents(false);
layer1->setOpacity(0.5);
layer1->setExpectation(true, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
layer1->addChild(BlendStateCheckLayer::create(2));
BlendStateCheckLayer* layer2 = static_cast<BlendStateCheckLayer*>(layer1->children()[0].get());
// 2 opaque layers, drawn without blending.
layer1->setOpaque(true);
- layer1->setOpaqueColor(true);
+ layer1->setOpaqueContents(true);
layer1->setOpacity(1);
layer1->setExpectation(false, false);
layer2->setOpaque(true);
- layer2->setOpaqueColor(true);
+ layer2->setOpaqueContents(true);
layer2->setOpacity(1);
layer2->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
EXPECT_TRUE(layer2->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// Parent layer with translucent content, drawn with blending.
// Child layer with opaque content, drawn without blending.
layer1->setOpaque(false);
- layer1->setOpaqueColor(false);
+ layer1->setOpaqueContents(false);
layer1->setExpectation(true, false);
layer2->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
EXPECT_TRUE(layer2->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// 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->setOpaqueContents(true);
layer1->setExpectation(false, false);
layer2->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
EXPECT_TRUE(layer2->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// 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,
@@ -650,53 +772,196 @@ 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->setOpaqueContents(true);
layer1->setOpacity(0.5);
layer1->setExpectation(false, true);
layer2->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
EXPECT_TRUE(layer2->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// Draw again, but with child non-opaque, to make sure
// layer1 not culled.
layer1->setOpaque(true);
- layer1->setOpaqueColor(true);
+ layer1->setOpaqueContents(true);
layer1->setOpacity(1);
layer1->setExpectation(false, false);
layer2->setOpaque(true);
- layer2->setOpaqueColor(true);
+ layer2->setOpaqueContents(true);
layer2->setOpacity(0.5);
layer2->setExpectation(true, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
EXPECT_TRUE(layer2->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// 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->setOpaqueContents(false);
layer2->setOpacity(1);
layer2->setExpectation(true, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
EXPECT_TRUE(layer2->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
// 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->setOpaqueContents(true);
layer2->setOpacity(1);
layer2->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
EXPECT_TRUE(layer2->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
+
+ // Layer with partially opaque contents, drawn with blending.
+ layer1->setOpaque(false);
+ layer1->setQuadRect(IntRect(5, 5, 5, 5));
+ layer1->setQuadVisibleRect(IntRect(5, 5, 5, 5));
+ layer1->setOpaqueContents(false);
+ layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
+ layer1->setExpectation(true, false);
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
+
+ // Layer with partially opaque contents partially culled, drawn with blending.
+ layer1->setOpaque(false);
+ layer1->setQuadRect(IntRect(5, 5, 5, 5));
+ layer1->setQuadVisibleRect(IntRect(5, 5, 5, 2));
+ layer1->setOpaqueContents(false);
+ layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
+ layer1->setExpectation(true, false);
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
+
+ // Layer with partially opaque contents culled, drawn with blending.
+ layer1->setOpaque(false);
+ layer1->setQuadRect(IntRect(5, 5, 5, 5));
+ layer1->setQuadVisibleRect(IntRect(7, 5, 3, 5));
+ layer1->setOpaqueContents(false);
+ layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
+ layer1->setExpectation(true, false);
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
+
+ // Layer with partially opaque contents and translucent contents culled, drawn without blending.
+ layer1->setOpaque(false);
+ layer1->setQuadRect(IntRect(5, 5, 5, 5));
+ layer1->setQuadVisibleRect(IntRect(5, 5, 2, 5));
+ layer1->setOpaqueContents(false);
+ layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
+ layer1->setExpectation(false, false);
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ EXPECT_TRUE(layer1->quadsAppended());
+ m_hostImpl->didDrawAllLayers(frame);
+
}
+TEST_F(CCLayerTreeHostImplTest, viewportCovered)
+{
+ m_hostImpl->initializeLayerRenderer(createContext());
+ m_hostImpl->setBackgroundColor(Color::gray);
+
+ IntSize viewportSize(1000, 1000);
+ m_hostImpl->setViewportSize(viewportSize);
+
+ m_hostImpl->setRootLayer(BlendStateCheckLayer::create(0));
+ BlendStateCheckLayer* root = static_cast<BlendStateCheckLayer*>(m_hostImpl->rootLayer());
+ root->setExpectation(false, true);
+ root->setOpaque(true);
+
+ // No gutter rects
+ {
+ IntRect layerRect(0, 0, 1000, 1000);
+ root->setPosition(layerRect.location());
+ root->setBounds(layerRect.size());
+ root->setContentBounds(layerRect.size());
+ root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
+ root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
+
+ CCLayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ ASSERT_EQ(1u, frame.renderPasses.size());
+
+ size_t numGutterQuads = 0;
+ for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
+ numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
+ EXPECT_EQ(0u, numGutterQuads);
+ EXPECT_EQ(1u, frame.renderPasses[0]->quadList().size());
+
+ verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
+ m_hostImpl->didDrawAllLayers(frame);
+ }
+
+ // Empty visible content area (fullscreen gutter rect)
+ {
+ IntRect layerRect(0, 0, 0, 0);
+ root->setPosition(layerRect.location());
+ root->setBounds(layerRect.size());
+ root->setContentBounds(layerRect.size());
+ root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
+ root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
+
+ CCLayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ ASSERT_EQ(1u, frame.renderPasses.size());
+ m_hostImpl->didDrawAllLayers(frame);
+
+ size_t numGutterQuads = 0;
+ for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
+ numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
+ EXPECT_EQ(1u, numGutterQuads);
+ EXPECT_EQ(1u, frame.renderPasses[0]->quadList().size());
+
+ verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
+ m_hostImpl->didDrawAllLayers(frame);
+ }
+
+ // Content area in middle of clip rect (four surrounding gutter rects)
+ {
+ IntRect layerRect(500, 500, 200, 200);
+ root->setPosition(layerRect.location());
+ root->setBounds(layerRect.size());
+ root->setContentBounds(layerRect.size());
+ root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
+ root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
+
+ CCLayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ ASSERT_EQ(1u, frame.renderPasses.size());
+
+ size_t numGutterQuads = 0;
+ for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
+ numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
+ EXPECT_EQ(4u, numGutterQuads);
+ EXPECT_EQ(5u, frame.renderPasses[0]->quadList().size());
+
+ verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
+ m_hostImpl->didDrawAllLayers(frame);
+ }
+
+}
+
+
class ReshapeTrackerContext: public FakeWebGraphicsContext3D {
public:
ReshapeTrackerContext() : m_reshapeCalled(false) { }
@@ -734,8 +999,11 @@ TEST_F(CCLayerTreeHostImplTest, reshapeNotCalledUntilDraw)
m_hostImpl->setRootLayer(adoptPtr(root));
EXPECT_FALSE(reshapeTracker->reshapeCalled());
- m_hostImpl->drawLayers();
+ CCLayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(reshapeTracker->reshapeCalled());
+ m_hostImpl->didDrawAllLayers(frame);
}
class PartialSwapTrackerContext : public FakeWebGraphicsContext3D {
@@ -786,8 +1054,12 @@ TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
root->addChild(adoptPtr(child));
layerTreeHostImpl->setRootLayer(adoptPtr(root));
+ CCLayerTreeHostImpl::FrameData frame;
+
// First frame, the entire screen should get swapped.
- layerTreeHostImpl->drawLayers();
+ EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
+ layerTreeHostImpl->drawLayers(frame);
+ layerTreeHostImpl->didDrawAllLayers(frame);
layerTreeHostImpl->swapBuffers();
IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
@@ -801,7 +1073,9 @@ TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
// expected damage rect: IntRect(IntPoint::zero(), IntSize(26, 28));
// expected swap rect: vertically flipped, with origin at bottom left corner.
child->setPosition(FloatPoint(0, 0));
- layerTreeHostImpl->drawLayers();
+ EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
+ layerTreeHostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
layerTreeHostImpl->swapBuffers();
actualSwapRect = partialSwapTracker->partialSwapRect();
expectedSwapRect = IntRect(IntPoint(0, 500-28), IntSize(26, 28));
@@ -814,8 +1088,10 @@ TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
// expected damage rect: IntRect(IntPoint::zero(), IntSize(500, 500));
// expected swap rect: flipped damage rect, but also clamped to viewport
layerTreeHostImpl->setViewportSize(IntSize(10, 10));
- root->setOpacity(0.7); // this will damage everything
- layerTreeHostImpl->drawLayers();
+ root->setOpacity(0.7f); // this will damage everything
+ EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
+ layerTreeHostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
layerTreeHostImpl->swapBuffers();
actualSwapRect = partialSwapTracker->partialSwapRect();
expectedSwapRect = IntRect(IntPoint::zero(), IntSize(10, 10));
@@ -825,55 +1101,12 @@ TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
}
-// Make sure that we reset damage tracking on visibility change because the
-// state of the front buffer that we push to with PostSubBuffer is undefined.
-TEST_F(CCLayerTreeHostImplTest, visibilityChangeResetsDamage)
-{
- PartialSwapTrackerContext* partialSwapTracker = new PartialSwapTrackerContext();
- RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
-
- // This test creates its own CCLayerTreeHostImpl, so
- // that we can force partial swap enabled.
- CCSettings settings;
- settings.partialSwapEnabled = true;
- OwnPtr<CCLayerTreeHostImpl> layerTreeHostImpl = CCLayerTreeHostImpl::create(settings, this);
- layerTreeHostImpl->initializeLayerRenderer(context);
- layerTreeHostImpl->setViewportSize(IntSize(500, 500));
-
- CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
- root->setAnchorPoint(FloatPoint(0, 0));
- root->setBounds(IntSize(500, 500));
- root->setDrawsContent(true);
- layerTreeHostImpl->setRootLayer(adoptPtr(root));
-
- // First frame: ignore.
- layerTreeHostImpl->drawLayers();
- layerTreeHostImpl->swapBuffers();
-
- // Second frame: nothing has changed --- so we souldn't push anything with partial swap.
- layerTreeHostImpl->drawLayers();
- layerTreeHostImpl->swapBuffers();
- EXPECT_TRUE(partialSwapTracker->partialSwapRect().isEmpty());
-
- // Third frame: visibility change --- so we should push a full frame with partial swap.
- layerTreeHostImpl->setVisible(false);
- layerTreeHostImpl->setVisible(true);
- layerTreeHostImpl->drawLayers();
- layerTreeHostImpl->swapBuffers();
- IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
- IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
- EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
- EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
- EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
- EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
-}
-
// Make sure that context lost notifications are propagated through the tree.
class ContextLostNotificationCheckLayer : public CCLayerImpl {
public:
static PassOwnPtr<ContextLostNotificationCheckLayer> create(int id) { return adoptPtr(new ContextLostNotificationCheckLayer(id)); }
- virtual void didLoseContext()
+ virtual void didLoseContext() OVERRIDE
{
m_didLoseContextCalled = true;
}
@@ -927,4 +1160,218 @@ TEST_F(CCLayerTreeHostImplTest, finishAllRenderingAfterContextLost)
m_hostImpl->finishAllRendering();
}
+class ScrollbarLayerFakePaint : public CCScrollbarLayerImpl {
+public:
+ static PassOwnPtr<ScrollbarLayerFakePaint> create(int id) { return adoptPtr(new ScrollbarLayerFakePaint(id)); }
+
+ virtual void paint(GraphicsContext*) { }
+
+private:
+ ScrollbarLayerFakePaint(int id) : CCScrollbarLayerImpl(id) { }
+};
+
+TEST_F(CCLayerTreeHostImplTest, scrollbarLayerLostContext)
+{
+ m_hostImpl->initializeLayerRenderer(createContext());
+ m_hostImpl->setViewportSize(IntSize(10, 10));
+
+ m_hostImpl->setRootLayer(ScrollbarLayerFakePaint::create(0));
+ ScrollbarLayerFakePaint* scrollbar = static_cast<ScrollbarLayerFakePaint*>(m_hostImpl->rootLayer());
+ scrollbar->setBounds(IntSize(1, 1));
+ scrollbar->setContentBounds(IntSize(1, 1));
+ scrollbar->setDrawsContent(true);
+
+ for (int i = 0; i < 2; ++i) {
+ CCLayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ ASSERT(frame.renderPasses.size() == 1);
+ CCRenderPass* renderPass = frame.renderPasses[0].get();
+ // Scrollbar layer should always generate quads, even after lost context
+ EXPECT_GT(renderPass->quadList().size(), 0u);
+ m_hostImpl->didDrawAllLayers(frame);
+ m_hostImpl->initializeLayerRenderer(createContext());
+ }
+}
+
+// Fake WebGraphicsContext3D that will cause a failure if trying to use a
+// resource that wasn't created by it (resources created by
+// FakeWebGraphicsContext3D have an id of 1).
+class StrictWebGraphicsContext3D : public FakeWebGraphicsContext3D {
+public:
+ virtual WebGLId createBuffer() { return 2; }
+ virtual WebGLId createFramebuffer() { return 3; }
+ virtual WebGLId createProgram() { return 4; }
+ virtual WebGLId createRenderbuffer() { return 5; }
+ virtual WebGLId createShader(WGC3Denum) { return 6; }
+ virtual WebGLId createTexture() { return 7; }
+
+ virtual void deleteBuffer(WebGLId id)
+ {
+ if (id != 2)
+ ADD_FAILURE() << "Trying to delete buffer id " << id;
+ }
+
+ virtual void deleteFramebuffer(WebGLId id)
+ {
+ if (id != 3)
+ ADD_FAILURE() << "Trying to delete framebuffer id " << id;
+ }
+
+ virtual void deleteProgram(WebGLId id)
+ {
+ if (id != 4)
+ ADD_FAILURE() << "Trying to delete program id " << id;
+ }
+
+ virtual void deleteRenderbuffer(WebGLId id)
+ {
+ if (id != 5)
+ ADD_FAILURE() << "Trying to delete renderbuffer id " << id;
+ }
+
+ virtual void deleteShader(WebGLId id)
+ {
+ if (id != 6)
+ ADD_FAILURE() << "Trying to delete shader id " << id;
+ }
+
+ virtual void deleteTexture(WebGLId id)
+ {
+ if (id != 7)
+ ADD_FAILURE() << "Trying to delete texture id " << id;
+ }
+
+ virtual void bindBuffer(WGC3Denum, WebGLId id)
+ {
+ if (id != 2 && id)
+ ADD_FAILURE() << "Trying to bind buffer id " << id;
+ }
+
+ virtual void bindFramebuffer(WGC3Denum, WebGLId id)
+ {
+ if (id != 3 && id)
+ ADD_FAILURE() << "Trying to bind framebuffer id " << id;
+ }
+
+ virtual void useProgram(WebGLId id)
+ {
+ if (id != 4)
+ ADD_FAILURE() << "Trying to use program id " << id;
+ }
+
+ virtual void bindRenderbuffer(WGC3Denum, WebGLId id)
+ {
+ if (id != 5 && id)
+ ADD_FAILURE() << "Trying to bind renderbuffer id " << id;
+ }
+
+ virtual void attachShader(WebGLId program, WebGLId shader)
+ {
+ if ((program != 4) || (shader != 6))
+ ADD_FAILURE() << "Trying to attach shader id " << shader << " to program id " << program;
+ }
+
+ virtual void bindTexture(WGC3Denum, WebGLId id)
+ {
+ if (id != 7 && id)
+ ADD_FAILURE() << "Trying to bind texture id " << id;
+ }
+
+ static PassRefPtr<GraphicsContext3D> createGraphicsContext()
+ {
+ return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new StrictWebGraphicsContext3D()), GraphicsContext3D::RenderDirectlyToHostWindow);
+ }
+};
+
+// Fake video frame that represents a 4x4 YUV video frame.
+class FakeVideoFrame: public WebVideoFrame {
+public:
+ FakeVideoFrame() { memset(m_data, 0x80, sizeof(m_data)); }
+ virtual ~FakeVideoFrame() { }
+ virtual Format format() const { return FormatYV12; }
+ virtual unsigned width() const { return 4; }
+ virtual unsigned height() const { return 4; }
+ virtual unsigned planes() const { return 3; }
+ virtual int stride(unsigned plane) const { return 4; }
+ virtual const void* data(unsigned plane) const { return m_data; }
+ virtual unsigned textureId() const { return 0; }
+ virtual unsigned textureTarget() const { return 0; }
+
+private:
+ char m_data[16];
+};
+
+// Fake video frame provider that always provides the same FakeVideoFrame.
+class FakeVideoFrameProvider: public WebVideoFrameProvider {
+public:
+ FakeVideoFrameProvider() : m_client(0) { }
+ virtual ~FakeVideoFrameProvider()
+ {
+ if (m_client)
+ m_client->stopUsingProvider();
+ }
+
+ virtual void setVideoFrameProviderClient(Client* client) { m_client = client; }
+ virtual WebVideoFrame* getCurrentFrame() { return &m_frame; }
+ virtual void putCurrentFrame(WebVideoFrame*) { }
+
+private:
+ FakeVideoFrame m_frame;
+ Client* m_client;
+};
+
+TEST_F(CCLayerTreeHostImplTest, dontUseOldResourcesAfterLostContext)
+{
+ m_hostImpl->initializeLayerRenderer(createContext());
+ m_hostImpl->setViewportSize(IntSize(10, 10));
+
+ OwnPtr<CCLayerImpl> rootLayer(CCLayerImpl::create(0));
+ rootLayer->setBounds(IntSize(10, 10));
+ rootLayer->setAnchorPoint(FloatPoint(0, 0));
+
+ OwnPtr<CCTiledLayerImpl> tileLayer = CCTiledLayerImpl::create(1);
+ tileLayer->setBounds(IntSize(10, 10));
+ tileLayer->setAnchorPoint(FloatPoint(0, 0));
+ tileLayer->setContentBounds(IntSize(10, 10));
+ tileLayer->setDrawsContent(true);
+ tileLayer->setSkipsDraw(false);
+ OwnPtr<CCLayerTilingData> tilingData(CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels));
+ tilingData->setBounds(IntSize(10, 10));
+ tileLayer->setTilingData(*tilingData);
+ tileLayer->pushTileProperties(0, 0, 1, IntRect(0, 0, 10, 10));
+ rootLayer->addChild(tileLayer.release());
+
+ OwnPtr<CCTextureLayerImpl> textureLayer = CCTextureLayerImpl::create(2);
+ textureLayer->setBounds(IntSize(10, 10));
+ textureLayer->setAnchorPoint(FloatPoint(0, 0));
+ textureLayer->setContentBounds(IntSize(10, 10));
+ textureLayer->setDrawsContent(true);
+ textureLayer->setTextureId(1);
+ rootLayer->addChild(textureLayer.release());
+
+ FakeVideoFrameProvider provider;
+ OwnPtr<CCVideoLayerImpl> videoLayer = CCVideoLayerImpl::create(3, &provider);
+ videoLayer->setBounds(IntSize(10, 10));
+ videoLayer->setAnchorPoint(FloatPoint(0, 0));
+ videoLayer->setContentBounds(IntSize(10, 10));
+ videoLayer->setDrawsContent(true);
+ rootLayer->addChild(videoLayer.release());
+
+ m_hostImpl->setRootLayer(rootLayer.release());
+
+ CCLayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+ m_hostImpl->swapBuffers();
+
+ // Lose the context, replacing it with a StrictWebGraphicsContext3D, that
+ // will warn if any resource from the previous context gets used.
+ m_hostImpl->initializeLayerRenderer(StrictWebGraphicsContext3D::createGraphicsContext());
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+ m_hostImpl->didDrawAllLayers(frame);
+ m_hostImpl->swapBuffers();
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
index 2c4e7ce59..f2382b359 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
+++ b/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp
@@ -27,12 +27,13 @@
#include "cc/CCLayerTreeHost.h"
#include "CCAnimationTestCommon.h"
+#include "CCOcclusionTrackerTestCommon.h"
+#include "CCTiledLayerTestCommon.h"
#include "CompositorFakeWebGraphicsContext3D.h"
#include "ContentLayerChromium.h"
#include "FilterOperations.h"
#include "GraphicsContext3DPrivate.h"
#include "LayerChromium.h"
-#include "Region.h"
#include "TextureManager.h"
#include "WebCompositor.h"
#include "WebKit.h"
@@ -44,10 +45,10 @@
#include "cc/CCScopedThreadProxy.h"
#include "cc/CCTextureUpdater.h"
#include "cc/CCThreadTask.h"
-#include "platform/WebKitPlatformSupport.h"
#include "platform/WebThread.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <public/Platform.h>
#include <wtf/MainThread.h>
#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
@@ -64,8 +65,10 @@ class TestHooks : public CCLayerAnimationDelegate {
public:
virtual void beginCommitOnCCThread(CCLayerTreeHostImpl*) { }
virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*) { }
+ virtual void prepareToDrawOnCCThread(CCLayerTreeHostImpl*) { }
virtual void drawLayersOnCCThread(CCLayerTreeHostImpl*) { }
virtual void animateLayers(CCLayerTreeHostImpl*, double monotonicTime) { }
+ virtual void willAnimateLayers(CCLayerTreeHostImpl*, double monotonicTime) { }
virtual void applyScrollAndScale(const IntSize&, float) { }
virtual void updateAnimations(double monotonicTime) { }
virtual void layout() { }
@@ -74,7 +77,7 @@ public:
// Implementation of CCLayerAnimationDelegate
virtual void notifyAnimationStarted(double time) { }
- virtual void notifyAnimationFinished(int animationId) { }
+ virtual void notifyAnimationFinished(double time) { }
};
// Adapts CCLayerTreeHostImpl for test. Runs real code, then invokes test hooks.
@@ -97,15 +100,23 @@ public:
m_testHooks->commitCompleteOnCCThread(this);
}
- virtual void drawLayers()
+ virtual bool prepareToDraw(FrameData& frame)
{
- CCLayerTreeHostImpl::drawLayers();
+ bool result = CCLayerTreeHostImpl::prepareToDraw(frame);
+ m_testHooks->prepareToDrawOnCCThread(this);
+ return result;
+ }
+
+ virtual void drawLayers(const FrameData& frame)
+ {
+ CCLayerTreeHostImpl::drawLayers(frame);
m_testHooks->drawLayersOnCCThread(this);
}
protected:
virtual void animateLayers(double monotonicTime, double wallClockTime)
{
+ m_testHooks->willAnimateLayers(this, monotonicTime);
CCLayerTreeHostImpl::animateLayers(monotonicTime, wallClockTime);
m_testHooks->animateLayers(this, monotonicTime);
}
@@ -123,13 +134,13 @@ private:
// Adapts CCLayerTreeHost for test. Injects MockLayerTreeHostImpl.
class MockLayerTreeHost : public CCLayerTreeHost {
public:
- static PassRefPtr<MockLayerTreeHost> create(TestHooks* testHooks, CCLayerTreeHostClient* client, PassRefPtr<LayerChromium> rootLayer, const CCSettings& settings)
+ static PassOwnPtr<MockLayerTreeHost> create(TestHooks* testHooks, CCLayerTreeHostClient* client, PassRefPtr<LayerChromium> rootLayer, const CCSettings& settings)
{
// For these tests, we will enable threaded animations.
CCSettings settingsCopy = settings;
settingsCopy.threadedAnimationEnabled = true;
- RefPtr<MockLayerTreeHost> layerTreeHost = adoptRef(new MockLayerTreeHost(testHooks, client, settingsCopy));
+ OwnPtr<MockLayerTreeHost> layerTreeHost(adoptPtr(new MockLayerTreeHost(testHooks, client, settingsCopy)));
bool success = layerTreeHost->initialize();
EXPECT_TRUE(success);
layerTreeHost->setRootLayer(rootLayer);
@@ -203,7 +214,7 @@ private:
}
Vector<WebGLId> m_textures;
- HashSet<WebGLId> m_usedTextures;
+ HashSet<WebGLId, DefaultHash<WebGLId>::Hash, UnsignedWithZeroKeyHashTraits<WebGLId> > m_usedTextures;
};
// Implementation of CCLayerTreeHost callback interface.
@@ -214,22 +225,26 @@ public:
return adoptPtr(new MockLayerTreeHostClient(testHooks));
}
- virtual void updateAnimations(double monotonicTime)
+ virtual void willBeginFrame() OVERRIDE
+ {
+ }
+
+ virtual void updateAnimations(double monotonicTime) OVERRIDE
{
m_testHooks->updateAnimations(monotonicTime);
}
- virtual void layout()
+ virtual void layout() OVERRIDE
{
m_testHooks->layout();
}
- virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale)
+ virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale) OVERRIDE
{
m_testHooks->applyScrollAndScale(scrollDelta, scale);
}
- virtual PassRefPtr<GraphicsContext3D> createContext()
+ virtual PassRefPtr<GraphicsContext3D> createContext() OVERRIDE
{
GraphicsContext3D::Attributes attrs;
WebGraphicsContext3D::Attributes webAttrs;
@@ -239,21 +254,25 @@ public:
return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow);
}
- virtual void didCommitAndDrawFrame()
+ virtual void didCommit() OVERRIDE
+ {
+ }
+
+ virtual void didCommitAndDrawFrame() OVERRIDE
{
m_testHooks->didCommitAndDrawFrame();
}
- virtual void didCompleteSwapBuffers()
+ virtual void didCompleteSwapBuffers() OVERRIDE
{
}
- virtual void didRecreateContext(bool succeeded)
+ virtual void didRecreateContext(bool succeeded) OVERRIDE
{
m_testHooks->didRecreateContext(succeeded);
}
- virtual void scheduleComposite()
+ virtual void scheduleComposite() OVERRIDE
{
}
@@ -300,6 +319,11 @@ public:
callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsCommit, this);
}
+ void AcquireLayerTextures()
+ {
+ callOnMainThread(CCLayerTreeHostTest::dispatchAcquireLayerTextures, this);
+ }
+
void postSetNeedsRedrawToMainThread()
{
callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsRedraw, this);
@@ -340,7 +364,7 @@ protected:
static void onEndTest(void* self)
{
ASSERT(isMainThread());
- webKitPlatformSupport()->currentThread()->exitRunLoop();
+ WebKit::Platform::current()->currentThread()->exitRunLoop();
}
static void dispatchSetNeedsAnimate(void* self)
@@ -358,7 +382,7 @@ protected:
CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
ASSERT(test);
if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
- addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 1);
+ addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 0.5, false);
}
static void dispatchAddAnimation(void* self)
@@ -367,7 +391,7 @@ protected:
CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
ASSERT(test);
if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
- addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 10, 0, 1);
+ addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 10, 0, 0.5, true);
}
static void dispatchSetNeedsAnimateAndCommit(void* self)
@@ -390,6 +414,15 @@ protected:
test->m_layerTreeHost->setNeedsCommit();
}
+ static void dispatchAcquireLayerTextures(void* self)
+ {
+ ASSERT(isMainThread());
+ CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
+ ASSERT_TRUE(test);
+ if (test->m_layerTreeHost)
+ test->m_layerTreeHost->acquireLayerTextures();
+ }
+
static void dispatchSetNeedsRedraw(void* self)
{
ASSERT(isMainThread());
@@ -464,7 +497,7 @@ protected:
virtual void runTest(bool threaded)
{
if (threaded) {
- m_webThread = adoptPtr(webKitPlatformSupport()->createThread("CCLayerTreeHostTest"));
+ m_webThread = adoptPtr(WebKit::Platform::current()->createThread("CCLayerTreeHostTest"));
WebCompositor::initialize(m_webThread.get());
} else
WebCompositor::initialize(0);
@@ -473,10 +506,10 @@ protected:
m_mainThreadProxy = CCScopedThreadProxy::create(CCProxy::mainThread());
m_beginTask = new BeginTask(this);
- webKitPlatformSupport()->currentThread()->postDelayedTask(m_beginTask, 0); // postDelayedTask takes ownership of the task
+ WebKit::Platform::current()->currentThread()->postDelayedTask(m_beginTask, 0); // postDelayedTask takes ownership of the task
m_timeoutTask = new TimeoutTask(this);
- webKitPlatformSupport()->currentThread()->postDelayedTask(m_timeoutTask, 5000);
- webKitPlatformSupport()->currentThread()->enterRunLoop();
+ WebKit::Platform::current()->currentThread()->postDelayedTask(m_timeoutTask, 5000);
+ WebKit::Platform::current()->currentThread()->enterRunLoop();
if (m_layerTreeHost && m_layerTreeHost->rootLayer())
m_layerTreeHost->rootLayer()->setLayerTreeHost(0);
@@ -498,7 +531,7 @@ protected:
CCSettings m_settings;
OwnPtr<MockLayerTreeHostClient> m_client;
- RefPtr<CCLayerTreeHost> m_layerTreeHost;
+ OwnPtr<CCLayerTreeHost> m_layerTreeHost;
private:
bool m_beginning;
@@ -520,6 +553,7 @@ void CCLayerTreeHostTest::doBeginTest()
m_layerTreeHost = MockLayerTreeHost::create(this, m_client.get(), rootLayer, m_settings);
ASSERT_TRUE(m_layerTreeHost);
rootLayer->setLayerTreeHost(m_layerTreeHost.get());
+ m_layerTreeHost->setSurfaceReady();
m_beginning = true;
beginTest();
@@ -806,6 +840,134 @@ TEST_F(CCLayerTreeHostTestSetNeedsRedraw, runMultiThread)
runTestThreaded();
}
+
+// beginLayerWrite should prevent draws from executing until a commit occurs
+class CCLayerTreeHostTestWriteLayersRedraw : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestWriteLayersRedraw()
+ : m_numCommits(0)
+ , m_numDraws(0)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ AcquireLayerTextures();
+ postSetNeedsRedrawToMainThread(); // should be inhibited without blocking
+ postSetNeedsCommitToMainThread();
+ }
+
+ virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ EXPECT_EQ(1, impl->sourceFrameNumber());
+ m_numDraws++;
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
+ {
+ m_numCommits++;
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ EXPECT_EQ(0, m_numDraws);
+ EXPECT_EQ(1, m_numCommits);
+ }
+
+private:
+ int m_numCommits;
+ int m_numDraws;
+};
+
+TEST_F(CCLayerTreeHostTestWriteLayersRedraw, runMultiThread)
+{
+ runTestThreaded();
+}
+
+// Verify that when resuming visibility, requesting layer write permission
+// will not deadlock the main thread even though there are not yet any
+// scheduled redraws. This behavior is critical for reliably surviving tab
+// switching. There are no failure conditions to this test, it just passes
+// by not timing out.
+class CCLayerTreeHostTestWriteLayersAfterVisible : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestWriteLayersAfterVisible()
+ : m_numCommits(0)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ postSetNeedsCommitToMainThread();
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
+ {
+ m_numCommits++;
+ if (m_numCommits == 2)
+ endTest();
+ else {
+ postSetVisibleToMainThread(false);
+ postSetVisibleToMainThread(true);
+ AcquireLayerTextures();
+ postSetNeedsCommitToMainThread();
+ }
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ int m_numCommits;
+};
+
+TEST_F(CCLayerTreeHostTestWriteLayersAfterVisible, runMultiThread)
+{
+ runTestThreaded();
+}
+
+// A compositeAndReadback while invisible should force a normal commit without assertion.
+class CCLayerTreeHostTestCompositeAndReadbackWhileInvisible : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestCompositeAndReadbackWhileInvisible()
+ : m_numCommits(0)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ }
+
+ virtual void didCommitAndDrawFrame()
+ {
+ m_numCommits++;
+ if (m_numCommits == 1) {
+ m_layerTreeHost->setVisible(false);
+ m_layerTreeHost->setNeedsCommit();
+ m_layerTreeHost->setNeedsCommit();
+ OwnArrayPtr<char> pixels(adoptArrayPtr(new char[4]));
+ m_layerTreeHost->compositeAndReadback(static_cast<void*>(pixels.get()), IntRect(0, 0, 1, 1));
+ } else
+ endTest();
+
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ int m_numCommits;
+};
+
+TEST_F(CCLayerTreeHostTestCompositeAndReadbackWhileInvisible, runMultiThread)
+{
+ runTestThreaded();
+}
+
+
// Trigger a frame with setNeedsCommit. Then, inside the resulting animate
// callback, requet another frame using setNeedsAnimate. End the test when
// animate gets called yet-again, indicating that the proxy is correctly
@@ -853,7 +1015,6 @@ public:
CCLayerTreeHostTestAddAnimation()
: m_numAnimates(0)
, m_receivedAnimationStartedNotification(false)
- , m_receivedAnimationFinishedNotification(false)
, m_startTime(0)
, m_firstMonotonicTime(0)
{
@@ -878,7 +1039,6 @@ public:
EXPECT_LT(0, m_firstMonotonicTime);
EXPECT_NE(m_startTime, m_firstMonotonicTime);
EXPECT_TRUE(m_receivedAnimationStartedNotification);
- EXPECT_TRUE(m_receivedAnimationFinishedNotification);
endTest();
}
@@ -888,11 +1048,6 @@ public:
m_startTime = wallClockTime;
}
- virtual void notifyAnimationFinished(int)
- {
- m_receivedAnimationFinishedNotification = true;
- }
-
virtual void afterTest()
{
}
@@ -900,7 +1055,6 @@ public:
private:
int m_numAnimates;
bool m_receivedAnimationStartedNotification;
- bool m_receivedAnimationFinishedNotification;
double m_startTime;
double m_firstMonotonicTime;
};
@@ -947,6 +1101,153 @@ TEST_F(CCLayerTreeHostTestTickAnimationWhileBackgrounded, runMultiThread)
runTestThreaded();
}
+// Ensures that animations continue to be ticked when we are backgrounded.
+class CCLayerTreeHostTestAddAnimationWithTimingFunction : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestAddAnimationWithTimingFunction()
+ {
+ }
+
+ virtual void beginTest()
+ {
+ postAddAnimationToMainThread();
+ }
+
+ virtual void animateLayers(CCLayerTreeHostImpl* layerTreeHostImpl, double monotonicTime)
+ {
+ const CCFloatAnimationCurve* curve = m_layerTreeHost->rootLayer()->layerAnimationController()->getActiveAnimation(0, CCActiveAnimation::Opacity)->curve()->toFloatAnimationCurve();
+ float startOpacity = curve->getValue(0);
+ float endOpacity = curve->getValue(curve->duration());
+ float linearlyInterpolatedOpacity = 0.25 * endOpacity + 0.75 * startOpacity;
+ double time = curve->duration() * 0.25;
+ // If the linear timing function associated with this animation was not picked up,
+ // then the linearly interpolated opacity would be different because of the
+ // default ease timing function.
+ EXPECT_FLOAT_EQ(linearlyInterpolatedOpacity, curve->getValue(time));
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+};
+
+TEST_F(CCLayerTreeHostTestAddAnimationWithTimingFunction, runMultiThread)
+{
+ runTestThreaded();
+}
+
+// Ensures that when opacity is being animated, this value does not cause the subtree to be skipped.
+class CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity()
+ {
+ }
+
+ virtual void beginTest()
+ {
+ m_layerTreeHost->rootLayer()->setDrawOpacity(1);
+ m_layerTreeHost->setViewportSize(IntSize(10, 10));
+ m_layerTreeHost->rootLayer()->setOpacity(0);
+ postAddAnimationToMainThread();
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
+ {
+ // If the subtree was skipped when preparing to draw, the layer's draw opacity
+ // will not have been updated. It should be set to 0 due to the animation.
+ // Without the animation, the layer will be skipped since it has zero opacity.
+ EXPECT_EQ(0, m_layerTreeHost->rootLayer()->drawOpacity());
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+};
+
+TEST_F(CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity, runMultiThread)
+{
+ runTestThreaded();
+}
+
+// Ensures that main thread animations have their start times synchronized with impl thread animations.
+class CCLayerTreeHostTestSynchronizeAnimationStartTimes : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestSynchronizeAnimationStartTimes()
+ : m_layerTreeHostImpl(0)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ postAddAnimationToMainThread();
+ }
+
+ // This is guaranteed to be called before CCLayerTreeHostImpl::animateLayers.
+ virtual void willAnimateLayers(CCLayerTreeHostImpl* layerTreeHostImpl, double monotonicTime)
+ {
+ m_layerTreeHostImpl = layerTreeHostImpl;
+ }
+
+ virtual void notifyAnimationStarted(double time)
+ {
+ EXPECT_TRUE(m_layerTreeHostImpl);
+
+ CCLayerAnimationController* controllerImpl = m_layerTreeHostImpl->rootLayer()->layerAnimationController();
+ CCLayerAnimationController* controller = m_layerTreeHost->rootLayer()->layerAnimationController();
+ CCActiveAnimation* animationImpl = controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity);
+ CCActiveAnimation* animation = controller->getActiveAnimation(0, CCActiveAnimation::Opacity);
+
+ EXPECT_EQ(animationImpl->startTime(), animation->startTime());
+
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ CCLayerTreeHostImpl* m_layerTreeHostImpl;
+};
+
+TEST_F(CCLayerTreeHostTestSynchronizeAnimationStartTimes, runMultiThread)
+{
+ runTestThreaded();
+}
+
+// Ensures that main thread animations have their start times synchronized with impl thread animations.
+class CCLayerTreeHostTestAnimationFinishedEvents : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestAnimationFinishedEvents()
+ {
+ }
+
+ virtual void beginTest()
+ {
+ postAddInstantAnimationToMainThread();
+ }
+
+ virtual void notifyAnimationFinished(double time)
+ {
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+};
+
+TEST_F(CCLayerTreeHostTestAnimationFinishedEvents, runMultiThread)
+{
+ runTestThreaded();
+}
+
class CCLayerTreeHostTestScrollSimple : public CCLayerTreeHostTestThreadOnly {
public:
CCLayerTreeHostTestScrollSimple()
@@ -1096,6 +1397,38 @@ TEST_F(CCLayerTreeHostTestScrollMultipleRedraw, DISABLED_runMultiThread)
runTestThreaded();
}
+// This test verifies that properties on the layer tree host are commited to the impl side.
+class CCLayerTreeHostTestCommit : public CCLayerTreeHostTest {
+public:
+
+ CCLayerTreeHostTestCommit() { }
+
+ virtual void beginTest()
+ {
+ m_layerTreeHost->setViewportSize(IntSize(20, 20));
+ m_layerTreeHost->setBackgroundColor(Color::gray);
+ m_layerTreeHost->setPageScaleFactorAndLimits(5, 5, 5);
+
+ postSetNeedsCommitToMainThread();
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ EXPECT_EQ(IntSize(20, 20), impl->viewportSize());
+ EXPECT_EQ(Color::gray, impl->backgroundColor());
+ EXPECT_EQ(5, impl->pageScale());
+
+ endTest();
+ }
+
+ virtual void afterTest() { }
+};
+
+TEST_F(CCLayerTreeHostTestCommit, runTest)
+{
+ runTest(true);
+}
+
// Verifies that startPageScaleAnimation events propagate correctly from CCLayerTreeHost to
// CCLayerTreeHostImpl in the MT compositor.
class CCLayerTreeHostTestStartPageScaleAnimation : public CCLayerTreeHostTest {
@@ -1230,33 +1563,23 @@ public:
int idlePaintContentsCount() { return m_idlePaintContentsCount; }
void resetPaintContentsCount() { m_paintContentsCount = 0; m_idlePaintContentsCount = 0;}
- int updateCount() { return m_updateCount; }
- void resetUpdateCount() { m_updateCount = 0; }
-
- virtual void paintContentsIfDirty(const Region& occludedScreenSpace)
+ virtual void update(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion) OVERRIDE
{
- ContentLayerChromium::paintContentsIfDirty(occludedScreenSpace);
+ ContentLayerChromium::update(updater, occlusion);
m_paintContentsCount++;
}
- virtual void idlePaintContentsIfDirty(const Region& occluded)
+ virtual void idleUpdate(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion) OVERRIDE
{
- ContentLayerChromium::idlePaintContentsIfDirty(occluded);
+ ContentLayerChromium::idleUpdate(updater, occlusion);
m_idlePaintContentsCount++;
}
- virtual void updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
- {
- ContentLayerChromium::updateCompositorResources(context, updater);
- m_updateCount++;
- }
-
private:
explicit ContentLayerChromiumWithUpdateTracking(ContentLayerDelegate* delegate)
: ContentLayerChromium(delegate)
, m_paintContentsCount(0)
, m_idlePaintContentsCount(0)
- , m_updateCount(0)
{
setBounds(IntSize(10, 10));
setIsDrawable(true);
@@ -1264,7 +1587,6 @@ private:
int m_paintContentsCount;
int m_idlePaintContentsCount;
- int m_updateCount;
};
// Layer opacity change during paint should not prevent compositor resources from being updated during commit.
@@ -1291,17 +1613,12 @@ public:
virtual void afterTest()
{
- // paintContentsIfDirty() should have been called once.
+ // update() should have been called once.
EXPECT_EQ(1, m_updateCheckLayer->paintContentsCount());
- // idlePaintContentsIfDirty() should have been called once
+ // idleUpdate() should have been called once
EXPECT_EQ(1, m_updateCheckLayer->idlePaintContentsCount());
- // updateCompositorResources() should have been called the same
- // amout of times as paintContentsIfDirty().
- EXPECT_EQ(m_updateCheckLayer->paintContentsCount(),
- m_updateCheckLayer->updateCount());
-
// clear m_updateCheckLayer so CCLayerTreeHost dies.
m_updateCheckLayer.clear();
}
@@ -1330,7 +1647,8 @@ public:
IntSize viewportSize(10, 10);
layerTreeHost()->setViewportSize(viewportSize);
- layerTreeHost()->updateLayers();
+ CCTextureUpdater updater;
+ layerTreeHost()->updateLayers(updater);
EXPECT_EQ(viewportSize, layerTreeHost()->viewportSize());
EXPECT_EQ(TextureManager::highLimitBytes(viewportSize), layerTreeHost()->contentsTextureManager()->maxMemoryLimitBytes());
@@ -1457,6 +1775,18 @@ TEST_F(CCLayerTreeHostTestAtomicCommit, runMultiThread)
runTest(true);
}
+static void setLayerPropertiesForTesting(LayerChromium* 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);
+}
+
class CCLayerTreeHostTestAtomicCommitWithPartialUpdate : public CCLayerTreeHostTest {
public:
CCLayerTreeHostTestAtomicCommitWithPartialUpdate()
@@ -1471,10 +1801,11 @@ public:
virtual void beginTest()
{
m_layerTreeHost->setRootLayer(m_parent);
- m_layerTreeHost->setViewportSize(IntSize(10, 10));
- m_parent->addChild(m_child);
- m_child->setOpacity(0.5);
- m_child->setBounds(IntSize(20, 20));
+ m_layerTreeHost->setViewportSize(IntSize(10, 20));
+
+ TransformationMatrix identityMatrix;
+ setLayerPropertiesForTesting(m_parent.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 20), true);
+ setLayerPropertiesForTesting(m_child.get(), m_parent.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(0, 10), IntSize(10, 10), false);
postSetNeedsCommitToMainThread();
postSetNeedsRedrawToMainThread();
@@ -1518,15 +1849,31 @@ public:
EXPECT_EQ(3, context->numTextures());
// Number of textures used for commit should still be two.
EXPECT_EQ(2, context->numUsedTextures());
- // First texture should not have been used.
- EXPECT_FALSE(context->usedTexture(context->texture(0)));
- // Second texture should have been used.
- EXPECT_TRUE(context->usedTexture(context->texture(1)));
- // New textures should have been used.
+ // First texture should have been used.
+ EXPECT_TRUE(context->usedTexture(context->texture(0)));
+ // Second texture should not have been used.
+ EXPECT_FALSE(context->usedTexture(context->texture(1)));
+ // Third texture should have been used.
EXPECT_TRUE(context->usedTexture(context->texture(2)));
context->resetUsedTextures();
break;
+ case 3:
+ // Number of textures should be two.
+ EXPECT_EQ(2, context->numTextures());
+ // No textures should be used for commit.
+ EXPECT_EQ(0, context->numUsedTextures());
+
+ context->resetUsedTextures();
+ break;
+ case 4:
+ // Number of textures should be two.
+ EXPECT_EQ(2, context->numTextures());
+ // Number of textures used for commit should be one.
+ EXPECT_EQ(1, context->numUsedTextures());
+
+ context->resetUsedTextures();
+ break;
default:
ASSERT_NOT_REACHED();
break;
@@ -1537,10 +1884,14 @@ public:
{
CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
- // Number of textures used for drawing should always be two.
- EXPECT_EQ(2, context->numUsedTextures());
+ // Number of textures used for drawing should two except for frame 4
+ // where the viewport only contains one layer.
+ if (impl->frameNumber() == 4)
+ EXPECT_EQ(1, context->numUsedTextures());
+ else
+ EXPECT_EQ(2, context->numUsedTextures());
- if (impl->frameNumber() < 3) {
+ if (impl->frameNumber() < 5) {
context->resetUsedTextures();
postSetNeedsAnimateAndCommitToMainThread();
postSetNeedsRedrawToMainThread();
@@ -1561,6 +1912,13 @@ public:
m_parent->setNeedsDisplayRect(FloatRect(0, 0, 5, 5));
m_child->setNeedsDisplayRect(FloatRect(0, 0, 5, 5));
break;
+ case 3:
+ m_child->setNeedsDisplay();
+ m_layerTreeHost->setViewportSize(IntSize(10, 10));
+ break;
+ case 4:
+ m_layerTreeHost->setViewportSize(IntSize(10, 20));
+ break;
default:
ASSERT_NOT_REACHED();
break;
@@ -1593,12 +1951,14 @@ class TestLayerChromium : public LayerChromium {
public:
static PassRefPtr<TestLayerChromium> create() { return adoptRef(new TestLayerChromium()); }
- virtual void paintContentsIfDirty(const Region& occludedScreenSpace)
+ virtual void update(CCTextureUpdater&, const CCOcclusionTracker* occlusion) OVERRIDE
{
- m_occludedScreenSpace = occludedScreenSpace;
+ // Gain access to internals of the CCOcclusionTracker.
+ const TestCCOcclusionTracker* testOcclusion = static_cast<const TestCCOcclusionTracker*>(occlusion);
+ m_occludedScreenSpace = testOcclusion ? testOcclusion->occlusionInScreenSpace() : Region();
}
- virtual bool drawsContent() const { return true; }
+ virtual bool drawsContent() const OVERRIDE { return true; }
const Region& occludedScreenSpace() const { return m_occludedScreenSpace; }
void clearOccludedScreenSpace() { m_occludedScreenSpace = Region(); }
@@ -1609,16 +1969,9 @@ private:
Region m_occludedScreenSpace;
};
-static void setLayerPropertiesForTesting(TestLayerChromium* layer, LayerChromium* parent, const TransformationMatrix& transform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool opaque)
+static void setTestLayerPropertiesForTesting(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);
+ setLayerPropertiesForTesting(layer, parent, transform, anchor, position, bounds, opaque);
layer->clearOccludedScreenSpace();
}
@@ -1646,81 +1999,82 @@ public:
// 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);
+ setTestLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), true);
+ setTestLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
+ setTestLayerPropertiesForTesting(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();
+ CCTextureUpdater updater;
+ m_layerTreeHost->updateLayers(updater);
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_RECT(IntRect(30, 40, 170, 160), child->occludedScreenSpace().bounds());
EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(30, 40, 170, 160), 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(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), 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->updateLayers(updater);
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_RECT(IntRect(30, 40, 170, 160), child->occludedScreenSpace().bounds());
EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(30, 30, 170, 170), 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);
+ setTestLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), true);
+ setTestLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(70, 20), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(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->updateLayers(updater);
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_RECT(IntRect(30, 40, 170, 160), child->occludedScreenSpace().bounds());
EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(30, 30, 170, 170), child2->occludedScreenSpace().bounds());
EXPECT_EQ(1u, child2->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 20, 70, 80), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(30, 20, 170, 180), 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);
+ setTestLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), true);
+ setTestLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(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->updateLayers(updater);
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_RECT(IntRect(30, 40, 170, 160), child->occludedScreenSpace().bounds());
EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(30, 30, 170, 170), child2->occludedScreenSpace().bounds());
EXPECT_EQ(1u, child2->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 30, 90, 70), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(10, 30, 190, 170), 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(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), 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);
@@ -1729,20 +2083,20 @@ public:
m_layerTreeHost->setRootLayer(rootLayer);
m_layerTreeHost->setViewportSize(rootLayer->bounds());
- m_layerTreeHost->updateLayers();
+ m_layerTreeHost->updateLayers(updater);
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_RECT(IntRect(30, 40, 170, 160), 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_RECT(IntRect(10, 70, 190, 130), 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(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), 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);
@@ -1751,62 +2105,62 @@ public:
m_layerTreeHost->setRootLayer(rootLayer);
m_layerTreeHost->setViewportSize(rootLayer->bounds());
- m_layerTreeHost->updateLayers();
+ m_layerTreeHost->updateLayers(updater);
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_RECT(IntRect(10, 70, 190, 130), grandChild->occludedScreenSpace().bounds());
EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(10, 40, 190, 160), child->occludedScreenSpace().bounds());
EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(10, 70, 190, 130), 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);
+ setTestLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), true);
+ setTestLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(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->updateLayers(updater);
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_RECT(IntRect(30, 40, 170, 160), 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_RECT(IntRect(10, 70, 190, 130), 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);
+ setTestLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), true);
+ setTestLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(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->updateLayers(updater);
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_RECT(IntRect(10, 70, 190, 130), grandChild->occludedScreenSpace().bounds());
EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(10, 40, 190, 160), child->occludedScreenSpace().bounds());
EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(10, 70, 190, 130), rootLayer->occludedScreenSpace().bounds());
EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
// Kill the layerTreeHost immediately.
@@ -1845,10 +2199,10 @@ public:
// If the child layer has a filter that changes alpha values, and is below child2, then child2 should contribute to occlusion on everything,
// and child shouldn't contribute to the rootLayer
- setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
- setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
- setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
- setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), true);
+ setTestLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
{
FilterOperations filters;
@@ -1858,24 +2212,25 @@ public:
m_layerTreeHost->setRootLayer(rootLayer);
m_layerTreeHost->setViewportSize(rootLayer->bounds());
- m_layerTreeHost->updateLayers();
+ CCTextureUpdater updater;
+ m_layerTreeHost->updateLayers(updater);
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_RECT(IntRect(10, 70, 190, 130), grandChild->occludedScreenSpace().bounds());
EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(10, 40, 190, 160), child->occludedScreenSpace().bounds());
EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(10, 70, 190, 130), rootLayer->occludedScreenSpace().bounds());
EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
// If the child layer has a filter that moves pixels/changes alpha, and is below child2, then child should not inherit occlusion from outside its subtree,
// and should not contribute to the rootLayer
- setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
- setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
- setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
- setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), true);
+ setTestLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+ setTestLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
{
FilterOperations filters;
@@ -1885,22 +2240,23 @@ public:
m_layerTreeHost->setRootLayer(rootLayer);
m_layerTreeHost->setViewportSize(rootLayer->bounds());
- m_layerTreeHost->updateLayers();
+ m_layerTreeHost->updateLayers(updater);
m_layerTreeHost->commitComplete();
EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(30, 40, 170, 160), child->occludedScreenSpace().bounds());
EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(10, 70, 190, 130), rootLayer->occludedScreenSpace().bounds());
EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
// Kill the layerTreeHost immediately.
m_layerTreeHost->setRootLayer(0);
m_layerTreeHost.clear();
+ CCLayerTreeHost::setNeedsFilterContext(false);
endTest();
}
@@ -1928,10 +2284,10 @@ public:
for (int i = 0; i < numSurfaces; ++i) {
layers.append(TestLayerChromium::create());
if (!i) {
- setLayerPropertiesForTesting(layers.last().get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setTestLayerPropertiesForTesting(layers.last().get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(200, 200), true);
layers.last()->createRenderSurface();
} else {
- setLayerPropertiesForTesting(layers.last().get(), layers[layers.size()-2].get(), identityMatrix, FloatPoint(0, 0), FloatPoint(1, 1), IntSize(100-i, 100-i), true);
+ setTestLayerPropertiesForTesting(layers.last().get(), layers[layers.size()-2].get(), identityMatrix, FloatPoint(0, 0), FloatPoint(1, 1), IntSize(200-i, 200-i), true);
layers.last()->setMasksToBounds(true);
layers.last()->setReplicaLayer(replica.get()); // Make it have a RenderSurface
}
@@ -1939,16 +2295,17 @@ public:
for (int i = 1; i < numSurfaces; ++i) {
children.append(TestLayerChromium::create());
- setLayerPropertiesForTesting(children.last().get(), layers[i].get(), identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
+ setTestLayerPropertiesForTesting(children.last().get(), layers[i].get(), identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
}
m_layerTreeHost->setRootLayer(layers[0].get());
m_layerTreeHost->setViewportSize(layers[0]->bounds());
- m_layerTreeHost->updateLayers();
+ CCTextureUpdater updater;
+ m_layerTreeHost->updateLayers(updater);
m_layerTreeHost->commitComplete();
for (int i = 0; i < numSurfaces-1; ++i) {
- IntRect expectedOcclusion(i+1, i+1, 100-i-1, 100-i-1);
+ IntRect expectedOcclusion(i+1, i+1, 200-i-1, 200-i-1);
EXPECT_EQ_RECT(expectedOcclusion, layers[i]->occludedScreenSpace().bounds());
EXPECT_EQ(1u, layers[i]->occludedScreenSpace().rects().size());
@@ -2036,4 +2393,57 @@ TEST_F(CCLayerTreeHostTestSetRepeatedLostContext, runMultiThread)
runTestThreaded();
}
+class CCLayerTreeHostTestFractionalScroll : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestFractionalScroll()
+ : m_scrollAmount(1.75, 0)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ m_layerTreeHost->rootLayer()->setScrollable(true);
+ postSetNeedsCommitToMainThread();
+ }
+
+ virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ CCLayerImpl* root = impl->rootLayer();
+ root->setMaxScrollPosition(IntSize(100, 100));
+
+ // Check that a fractional scroll delta is correctly accumulated over multiple commits.
+ if (impl->frameNumber() == 1) {
+ EXPECT_EQ(root->scrollPosition(), IntPoint(0, 0));
+ EXPECT_EQ(root->scrollDelta(), FloatSize(0, 0));
+ postSetNeedsCommitToMainThread();
+ } else if (impl->frameNumber() == 2) {
+ EXPECT_EQ(root->scrollPosition(), flooredIntPoint(m_scrollAmount));
+ EXPECT_EQ(root->scrollDelta(), FloatSize(fmod(m_scrollAmount.width(), 1), 0));
+ postSetNeedsCommitToMainThread();
+ } else if (impl->frameNumber() == 3) {
+ EXPECT_EQ(root->scrollPosition(), flooredIntPoint(m_scrollAmount + m_scrollAmount));
+ EXPECT_EQ(root->scrollDelta(), FloatSize(fmod(2 * m_scrollAmount.width(), 1), 0));
+ endTest();
+ }
+ root->scrollBy(m_scrollAmount);
+ }
+
+ virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale)
+ {
+ IntPoint position = m_layerTreeHost->rootLayer()->scrollPosition();
+ m_layerTreeHost->rootLayer()->setScrollPosition(position + scrollDelta);
+ }
+
+ virtual void afterTest()
+ {
+ }
+private:
+ FloatSize m_scrollAmount;
+};
+
+TEST_F(CCLayerTreeHostTestFractionalScroll, runMultiThread)
+{
+ runTestThreaded();
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCLayerTreeTestCommon.h b/Source/WebKit/chromium/tests/CCLayerTreeTestCommon.h
index 0b83dacab..75e487a4a 100644
--- a/Source/WebKit/chromium/tests/CCLayerTreeTestCommon.h
+++ b/Source/WebKit/chromium/tests/CCLayerTreeTestCommon.h
@@ -27,13 +27,19 @@
namespace WebKitTests {
-// This is a macro instead of function so that we get useful line numbers where a test failed.
+// These are macros instead of functions so that we get useful line numbers where a test failed.
#define EXPECT_FLOAT_RECT_EQ(expected, actual) \
EXPECT_FLOAT_EQ((expected).location().x(), (actual).location().x()); \
EXPECT_FLOAT_EQ((expected).location().y(), (actual).location().y()); \
EXPECT_FLOAT_EQ((expected).size().width(), (actual).size().width()); \
EXPECT_FLOAT_EQ((expected).size().height(), (actual).size().height())
+#define EXPECT_INT_RECT_EQ(expected, actual) \
+ EXPECT_EQ((expected).location().x(), (actual).location().x()); \
+ EXPECT_EQ((expected).location().y(), (actual).location().y()); \
+ EXPECT_EQ((expected).size().width(), (actual).size().width()); \
+ EXPECT_EQ((expected).size().height(), (actual).size().height())
+
// This is a macro instead of a function so that we get useful line numbers where a test failed.
// Even though TransformationMatrix values are double precision, there are many other floating-point values used that affect
// the transforms, and so we only expect them to be accurate up to floating-point precision.
diff --git a/Source/WebKit/chromium/tests/CCMathUtilTest.cpp b/Source/WebKit/chromium/tests/CCMathUtilTest.cpp
new file mode 100644
index 000000000..db0a4e53f
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCMathUtilTest.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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/CCMathUtil.h"
+
+#include "TransformationMatrix.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+TEST(CCMathUtilTest, verifyBackfaceVisibilityBasicCases)
+{
+ TransformationMatrix transform;
+
+ transform.makeIdentity();
+ EXPECT_FALSE(transform.isBackFaceVisible());
+
+ transform.makeIdentity();
+ transform.rotate3d(0, 80, 0);
+ EXPECT_FALSE(transform.isBackFaceVisible());
+
+ transform.makeIdentity();
+ transform.rotate3d(0, 100, 0);
+ EXPECT_TRUE(transform.isBackFaceVisible());
+
+ // Edge case, 90 degree rotation should return false.
+ transform.makeIdentity();
+ transform.rotate3d(0, 90, 0);
+ EXPECT_FALSE(transform.isBackFaceVisible());
+}
+
+TEST(CCMathUtilTest, verifyBackfaceVisibilityForPerspective)
+{
+ TransformationMatrix layerSpaceToProjectionPlane;
+
+ // This tests if isBackFaceVisible works properly under perspective transforms.
+ // Specifically, layers that may have their back face visible in orthographic
+ // projection, may not actually have back face visible under perspective projection.
+
+ // Case 1: Layer is rotated by slightly more than 90 degrees, at the center of the
+ // prespective projection. In this case, the layer's back-side is visible to
+ // the camera.
+ layerSpaceToProjectionPlane.makeIdentity();
+ layerSpaceToProjectionPlane.applyPerspective(1);
+ layerSpaceToProjectionPlane.translate3d(0, 0, 0);
+ layerSpaceToProjectionPlane.rotate3d(0, 100, 0);
+ EXPECT_TRUE(layerSpaceToProjectionPlane.isBackFaceVisible());
+
+ // Case 2: Layer is rotated by slightly more than 90 degrees, but shifted off to the
+ // side of the camera. Because of the wide field-of-view, the layer's front
+ // side is still visible.
+ //
+ // |<-- front side of layer is visible to perspective camera
+ // \ | /
+ // \ | /
+ // \| /
+ // | /
+ // |\ /<-- camera field of view
+ // | \ /
+ // back side of layer -->| \ /
+ // \./ <-- camera origin
+ //
+ layerSpaceToProjectionPlane.makeIdentity();
+ layerSpaceToProjectionPlane.applyPerspective(1);
+ layerSpaceToProjectionPlane.translate3d(-10, 0, 0);
+ layerSpaceToProjectionPlane.rotate3d(0, 100, 0);
+ EXPECT_FALSE(layerSpaceToProjectionPlane.isBackFaceVisible());
+
+ // Case 3: Additionally rotating the layer by 180 degrees should of course show the
+ // opposite result of case 2.
+ layerSpaceToProjectionPlane.rotate3d(0, 180, 0);
+ EXPECT_TRUE(layerSpaceToProjectionPlane.isBackFaceVisible());
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp b/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp
index 26d52523b..73b4d8273 100644
--- a/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp
@@ -26,16 +26,23 @@
#include "cc/CCOcclusionTracker.h"
+#include "CCAnimationTestCommon.h"
+#include "CCOcclusionTrackerTestCommon.h"
#include "FilterOperations.h"
#include "LayerChromium.h"
#include "Region.h"
#include "TransformationMatrix.h"
+#include "TranslateTransformOperation.h"
+#include "cc/CCLayerAnimationController.h"
+#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHostCommon.h"
+#include "cc/CCSingleThreadProxy.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace WebKitTests;
#define EXPECT_EQ_RECT(a, b) \
EXPECT_EQ(a.x(), b.x()); \
@@ -45,2168 +52,2890 @@ using namespace WebCore;
namespace {
-class LayerChromiumWithForcedDrawsContent : public LayerChromium {
+class TestContentLayerChromium : public LayerChromium {
public:
- LayerChromiumWithForcedDrawsContent()
+ TestContentLayerChromium()
: LayerChromium()
+ , m_overrideOpaqueContentsRect(false)
{
}
- virtual bool drawsContent() const { return true; }
- virtual Region opaqueContentsRegion() const
+ virtual bool drawsContent() const OVERRIDE { return true; }
+ virtual Region visibleContentOpaqueRegion() const OVERRIDE
{
- return intersection(m_opaquePaintRect, visibleLayerRect());
+ if (m_overrideOpaqueContentsRect)
+ return intersection(m_opaqueContentsRect, visibleLayerRect());
+ return LayerChromium::visibleContentOpaqueRegion();
+ }
+ void setOpaqueContentsRect(const IntRect& opaqueContentsRect)
+ {
+ m_overrideOpaqueContentsRect = true;
+ m_opaqueContentsRect = opaqueContentsRect;
}
-
- void setOpaquePaintRect(const IntRect& opaquePaintRect) { m_opaquePaintRect = opaquePaintRect; }
private:
- IntRect m_opaquePaintRect;
+ bool m_overrideOpaqueContentsRect;
+ IntRect m_opaqueContentsRect;
};
-void setLayerPropertiesForTesting(LayerChromium* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
-{
- layer->setTransform(transform);
- layer->setSublayerTransform(TransformationMatrix());
- layer->setAnchorPoint(FloatPoint(0, 0));
- layer->setPosition(position);
- layer->setBounds(bounds);
-}
-
-void setLayerPropertiesForTesting(LayerChromiumWithForcedDrawsContent* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque, bool opaqueLayers)
-{
- setLayerPropertiesForTesting(layer, transform, position, bounds);
- if (opaqueLayers)
- layer->setOpaque(opaque);
- else {
- layer->setOpaque(false);
- if (opaque)
- layer->setOpaquePaintRect(IntRect(IntPoint(), bounds));
- else
- layer->setOpaquePaintRect(IntRect());
- }
-}
-
-// A subclass to expose the total current occlusion.
-class TestCCOcclusionTracker : public CCOcclusionTracker {
+class TestContentLayerImpl : public CCLayerImpl {
public:
- TestCCOcclusionTracker(IntRect screenScissorRect)
- : CCOcclusionTracker(screenScissorRect)
- , m_overrideLayerScissorRect(false)
+ TestContentLayerImpl(int id)
+ : CCLayerImpl(id)
+ , m_overrideOpaqueContentsRect(false)
{
+ setDrawsContent(true);
}
- TestCCOcclusionTracker(IntRect screenScissorRect, const CCOcclusionTrackerDamageClient* damageClient)
- : CCOcclusionTracker(screenScissorRect, damageClient)
- , m_overrideLayerScissorRect(false)
+ virtual Region visibleContentOpaqueRegion() const OVERRIDE
+ {
+ if (m_overrideOpaqueContentsRect)
+ return intersection(m_opaqueContentsRect, visibleLayerRect());
+ return CCLayerImpl::visibleContentOpaqueRegion();
+ }
+ void setOpaqueContentsRect(const IntRect& opaqueContentsRect)
{
+ m_overrideOpaqueContentsRect = true;
+ m_opaqueContentsRect = opaqueContentsRect;
}
- Region occlusionInScreenSpace() const { return CCOcclusionTracker::m_stack.last().occlusionInScreen; }
- Region occlusionInTargetSurface() const { return CCOcclusionTracker::m_stack.last().occlusionInTarget; }
+private:
+ bool m_overrideOpaqueContentsRect;
+ IntRect m_opaqueContentsRect;
+};
- void setOcclusionInScreenSpace(const Region& region) { CCOcclusionTracker::m_stack.last().occlusionInScreen = region; }
- void setOcclusionInTargetSurface(const Region& region) { CCOcclusionTracker::m_stack.last().occlusionInTarget = region; }
+template<typename LayerType, typename RenderSurfaceType>
+class TestCCOcclusionTrackerWithScissor : public TestCCOcclusionTrackerBase<LayerType, RenderSurfaceType> {
+public:
+ TestCCOcclusionTrackerWithScissor(IntRect screenScissorRect, bool recordMetricsForFrame = false)
+ : TestCCOcclusionTrackerBase<LayerType, RenderSurfaceType>(screenScissorRect, recordMetricsForFrame)
+ , m_overrideLayerScissorRect(false)
+ {
+ }
void setLayerScissorRect(const IntRect& rect) { m_overrideLayerScissorRect = true; m_layerScissorRect = rect;}
void useDefaultLayerScissorRect() { m_overrideLayerScissorRect = false; }
protected:
- virtual IntRect layerScissorRectInTargetSurface(const LayerChromium* layer) const { return m_overrideLayerScissorRect ? m_layerScissorRect : CCOcclusionTracker::layerScissorRectInTargetSurface(layer); }
+ virtual IntRect layerScissorRectInTargetSurface(const LayerType* layer) const { return m_overrideLayerScissorRect ? m_layerScissorRect : CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerScissorRectInTargetSurface(layer); }
private:
bool m_overrideLayerScissorRect;
IntRect m_layerScissorRect;
};
-class TestDamageClient : public CCOcclusionTrackerDamageClient {
-public:
- // The interface
- virtual FloatRect damageRect(const RenderSurfaceChromium*) const { return m_damageRect; }
-
- // Testing stuff
- TestDamageClient(const FloatRect& damageRect) : m_damageRect(damageRect) { }
- void setDamageRect(const FloatRect& damageRect) { m_damageRect = damageRect; }
+struct CCOcclusionTrackerTestMainThreadTypes {
+ typedef LayerChromium LayerType;
+ typedef RenderSurfaceChromium RenderSurfaceType;
+ typedef TestContentLayerChromium ContentLayerType;
+ typedef RefPtr<LayerChromium> LayerPtrType;
+ typedef PassRefPtr<LayerChromium> PassLayerPtrType;
+ typedef RefPtr<ContentLayerType> ContentLayerPtrType;
+ typedef PassRefPtr<ContentLayerType> PassContentLayerPtrType;
+ typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> LayerIterator;
+ typedef CCOcclusionTracker OcclusionTrackerType;
+
+ static PassLayerPtrType createLayer() { return LayerChromium::create(); }
+ static PassContentLayerPtrType createContentLayer() { return adoptRef(new ContentLayerType()); }
+};
-private:
- FloatRect m_damageRect;
+struct CCOcclusionTrackerTestImplThreadTypes {
+ typedef CCLayerImpl LayerType;
+ typedef CCRenderSurface RenderSurfaceType;
+ typedef TestContentLayerImpl ContentLayerType;
+ typedef OwnPtr<CCLayerImpl> LayerPtrType;
+ typedef PassOwnPtr<CCLayerImpl> PassLayerPtrType;
+ typedef OwnPtr<ContentLayerType> ContentLayerPtrType;
+ typedef PassOwnPtr<ContentLayerType> PassContentLayerPtrType;
+ typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> LayerIterator;
+ typedef CCOcclusionTrackerImpl OcclusionTrackerType;
+
+ static PassLayerPtrType createLayer() { return CCLayerImpl::create(nextCCLayerImplId++); }
+ static PassContentLayerPtrType createContentLayer() { return adoptPtr(new ContentLayerType(nextCCLayerImplId++)); }
+ static int nextCCLayerImplId;
};
-#define TEST_OPAQUE_AND_PAINTED_OPAQUE(FULLTESTNAME, SHORTTESTNAME) \
- TEST(FULLTESTNAME, opaqueLayer) \
- { \
- SHORTTESTNAME(true); \
- } \
- TEST(FULLTESTNAME, opaquePaintRect) \
- { \
- SHORTTESTNAME(false); \
+int CCOcclusionTrackerTestImplThreadTypes::nextCCLayerImplId = 0;
+
+template<typename Types, bool opaqueLayers>
+class CCOcclusionTrackerTest : public testing::Test {
+protected:
+ CCOcclusionTrackerTest()
+ : testing::Test()
+ { }
+
+ virtual void runMyTest() = 0;
+
+ virtual void TearDown()
+ {
+ m_root.clear();
+ m_renderSurfaceLayerListChromium.clear();
+ m_renderSurfaceLayerListImpl.clear();
+ m_replicaLayers.clear();
+ CCLayerTreeHost::setNeedsFilterContext(false);
}
-void layerAddedToOccludedRegion(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(layer);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(parent->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)).isEmpty());
- EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 70, 70)));
- EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 29, 70, 70)));
- EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
- EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 29, 70, 70)));
- EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 70, 70)));
- EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 31, 70, 70)));
- EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 70, 70)));
- EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 31, 70, 70)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegion, layerAddedToOccludedRegion);
-
-void layerAddedToOccludedRegionWithRotation(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- 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, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(layer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(parent->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70)));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)).isEmpty());
- EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 70, 70)));
- EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 29, 70, 70)));
- EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
- EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 29, 70, 70)));
- EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 70, 70)));
- EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 31, 70, 70)));
- EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 70, 70)));
- EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 31, 70, 70)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithRotation, layerAddedToOccludedRegionWithRotation);
-
-void layerAddedToOccludedRegionWithTranslation(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- 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, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(layer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(parent->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
- EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(50, 50, 50, 50)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(49, 50, 50, 50)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 49, 50, 50)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(51, 50, 50, 50)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 51, 50, 50)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(50, 50, 50, 50)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(49, 50, 50, 50)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 49, 50, 50)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(51, 50, 50, 50)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(50, 51, 50, 50)));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(50, 50, 50, 50)).isEmpty());
- EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 50, 50, 50)));
- EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 49, 50, 50)));
- EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 49, 50, 50)));
- EXPECT_EQ_RECT(IntRect(51, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 49, 50, 50)));
- EXPECT_EQ_RECT(IntRect(100, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 50, 50, 50)));
- EXPECT_EQ_RECT(IntRect(51, 51, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 51, 50, 50)));
- EXPECT_EQ_RECT(IntRect(50, 100, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 51, 50, 50)));
- EXPECT_EQ_RECT(IntRect(49, 51, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 51, 50, 50)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(50, 50, 50, 50)).isEmpty());
- EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 50, 50, 50)));
- EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 49, 50, 50)));
- EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 49, 50, 50)));
- EXPECT_EQ_RECT(IntRect(51, 49, 49, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 49, 50, 50)));
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(51, 50, 50, 50)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(51, 51, 50, 50)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(50, 51, 50, 50)).isEmpty());
- EXPECT_EQ_RECT(IntRect(49, 51, 1, 49), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 51, 50, 50)));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithTranslation, layerAddedToOccludedRegionWithTranslation);
-
-void layerAddedToOccludedRegionWithRotatedSurface(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- 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, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(child.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true, opaqueLayers);
-
- child->setMasksToBounds(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(child->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
-
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 430, 61, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 71)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 61, 70)));
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 71)));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- occlusion.markOccludedBehindLayer(child.get());
- occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 41, 70, 60)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(31, 40, 70, 60)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 41, 70, 60)));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
-
- /* Justification for the above occlusion from |layer|:
- 100
- +---------------------+ +---------------------+
- | | | |30 Visible region of |layer|: /////
- | 30 | rotate(90) | |
- | 30 + ---------------------------------+ | +---------------------------------+
- 100 | | 10 | | ==> | | |10 |
- | |10+---------------------------------+ | +---------------------------------+ |
- | | | | | | | | |///////////////| 420 | |
- | | | | | | | | |///////////////|60 | |
- | | | | | | | | |///////////////| | |
- +----|--|-------------+ | | +--|--|---------------+ | |
- | | | | 20|10| 70 | |
- | | | | | | | |
- | | | |500 | | | |
- | | | | | | | |
- | | | | | | | |
- | | | | | | | |
- | | | | | | |10|
- +--|-------------------------------+ | | +------------------------------|--+
- | | | 490 |
- +---------------------------------+ +---------------------------------+
- 500 500
- */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithRotatedSurface, layerAddedToOccludedRegionWithRotatedSurface);
-
-void layerAddedToOccludedRegionWithSurfaceAlreadyOnStack(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromium> child = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(child);
- child->addChild(layer);
- parent->addChild(child2);
-
- TransformationMatrix childTransform;
- childTransform.translate(250, 250);
- childTransform.rotate(90);
- childTransform.translate(-250, -250);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(child.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true, opaqueLayers);
-
- // |child2| makes |parent|'s surface get considered by CCOcclusionTracker first, instead of |child|'s. This exercises different code in
- // leaveToTargetRenderSurface, as the target surface has already been seen.
- setLayerPropertiesForTesting(child2.get(), identityMatrix, FloatPoint(30, 30), IntSize(60, 20), true, opaqueLayers);
-
- child->setMasksToBounds(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(parent->renderSurface());
- occlusion.markOccludedBehindLayer(child2.get());
-
- EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- occlusion.enterTargetRenderSurface(child->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
-
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70)));
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70)));
- occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty());
- // This is the little piece not occluded by child2
- EXPECT_EQ_RECT(IntRect(9, 430, 1, 10), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70)));
- // This extends past both sides of child2, so it will be the original rect.
- EXPECT_EQ_RECT(IntRect(9, 430, 60, 80), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 80)));
- // This extends past two adjacent sides of child2, and should included the unoccluded parts of each side.
- // This also demonstrates that the rect can be arbitrary and does not get clipped to the layer's visibleLayerRect().
- EXPECT_EQ_RECT(IntRect(-10, 430, 20, 70), occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 70)));
- // This extends past three adjacent sides of child2, so it should contain the unoccluded parts of each side. The left
- // and bottom edges are completely unoccluded for some row/column so we get back the original query rect.
- EXPECT_EQ_RECT(IntRect(-10, 430, 60, 80), occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 80)));
- EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70)));
- EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70)));
- EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 80)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 70)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 80)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70)).isEmpty());
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- occlusion.markOccludedBehindLayer(child.get());
- // |child2| should get merged with the surface we are leaving now
- occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
-
- Vector<IntRect> screen = occlusion.occlusionInScreenSpace().rects();
- Vector<IntRect> target = occlusion.occlusionInTargetSurface().rects();
-
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
- EXPECT_EQ_RECT(IntRect(90, 30, 10, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)));
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 60, 10)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 60, 10)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 60, 10)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 60, 10)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 31, 60, 10)));
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 60, 10)).isEmpty());
- EXPECT_EQ_RECT(IntRect(29, 30, 1, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 60, 10)));
- EXPECT_EQ_RECT(IntRect(30, 29, 60, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 60, 10)));
- EXPECT_EQ_RECT(IntRect(90, 30, 1, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 60, 10)));
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 60, 10)).isEmpty());
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)).isEmpty());
- EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 40, 70, 60)));
- // This rect is mostly occluded by |child2|.
- EXPECT_EQ_RECT(IntRect(90, 39, 10, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 39, 70, 60)));
- // This rect extends past top/right ends of |child2|.
- EXPECT_EQ_RECT(IntRect(30, 29, 70, 11), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70)));
- // This rect extends past left/right ends of |child2|.
- EXPECT_EQ_RECT(IntRect(20, 39, 80, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(20, 39, 80, 60)));
- EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 40, 70, 60)));
- EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 41, 70, 60)));
-
- /* Justification for the above occlusion from |layer|:
- 100
- +---------------------+ +---------------------+
- | | | |30 Visible region of |layer|: /////
- | 30 | rotate(90) | 30 60 | |child2|: \\\\\
- | 30 + ------------+--------------------+ | 30 +------------+--------------------+
- 100 | | 10 | | | ==> | |\\\\\\\\\\\\| |10 |
- | |10+----------|----------------------+ | +--|\\\\\\\\\\\\|-----------------+ |
- | + ------------+ | | | | | +------------+//| 420 | |
- | | | | | | | | |///////////////|60 | |
- | | | | | | | | |///////////////| | |
- +----|--|-------------+ | | +--|--|---------------+ | |
- | | | | 20|10| 70 | |
- | | | | | | | |
- | | | |500 | | | |
- | | | | | | | |
- | | | | | | | |
- | | | | | | | |
- | | | | | | |10|
- +--|-------------------------------+ | | +------------------------------|--+
- | | | 490 |
- +---------------------------------+ +---------------------------------+
- 500 500
- */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithSurfaceAlreadyOnStack, layerAddedToOccludedRegionWithSurfaceAlreadyOnStack);
-
-void layerAddedToOccludedRegionWithRotatedOffAxisSurface(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromium> child = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(child);
- child->addChild(layer);
-
- // Now rotate the child a little more so it is not axis-aligned. The parent will no longer be occluded by |layer|, but
- // the child's occlusion should be unchanged.
-
- TransformationMatrix childTransform;
- childTransform.translate(250, 250);
- childTransform.rotate(95);
- childTransform.translate(-250, -250);
-
- TransformationMatrix layerTransform;
- layerTransform.translate(10, 10);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(child.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
- setLayerPropertiesForTesting(layer.get(), layerTransform, FloatPoint(0, 0), IntSize(500, 500), true, opaqueLayers);
-
- child->setMasksToBounds(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- IntRect clippedLayerInChild = layerTransform.mapRect(layer->visibleLayerRect());
-
- occlusion.enterTargetRenderSurface(child->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
-
- EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(clippedLayerInChild, occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child.get(), clippedLayerInChild));
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
- clippedLayerInChild.move(-1, 0);
- EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
- EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
- clippedLayerInChild.move(1, 0);
- clippedLayerInChild.move(1, 0);
- EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
- EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
- clippedLayerInChild.move(-1, 0);
- clippedLayerInChild.move(0, -1);
- EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
- EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
- clippedLayerInChild.move(0, 1);
- clippedLayerInChild.move(0, 1);
- EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild));
- EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty());
- clippedLayerInChild.move(0, -1);
-
- occlusion.markOccludedBehindLayer(child.get());
- occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(75, 55, 1, 1)));
- EXPECT_EQ_RECT(IntRect(75, 55, 1, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(75, 55, 1, 1)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithRotatedOffAxisSurface, layerAddedToOccludedRegionWithRotatedOffAxisSurface);
-
-void layerAddedToOccludedRegionWithMultipleOpaqueLayers(bool opaqueLayers)
-{
- // This is similar to the previous test but now we make a few opaque layers inside of |child| so that the occluded parts of child are not a simple rect.
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromium> child = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(child);
- child->addChild(layer1);
- child->addChild(layer2);
-
- TransformationMatrix childTransform;
- childTransform.translate(250, 250);
- childTransform.rotate(90);
- childTransform.translate(-250, -250);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(child.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
- setLayerPropertiesForTesting(layer1.get(), identityMatrix, FloatPoint(10, 10), IntSize(500, 440), true, opaqueLayers);
- setLayerPropertiesForTesting(layer2.get(), identityMatrix, FloatPoint(10, 450), IntSize(500, 60), true, opaqueLayers);
-
- child->setMasksToBounds(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(child->renderSurface());
- occlusion.markOccludedBehindLayer(layer2.get());
- occlusion.markOccludedBehindLayer(layer1.get());
-
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70)));
- EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70)));
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty());
- EXPECT_EQ_RECT(IntRect(9, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70)));
- EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70)));
- EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70)));
- EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70)));
-
- occlusion.markOccludedBehindLayer(child.get());
- occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60)));
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)).isEmpty());
- EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 40, 70, 60)));
- EXPECT_EQ_RECT(IntRect(30, 39, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 39, 70, 60)));
- EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 40, 70, 60)));
- EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 41, 70, 60)));
-
- /* Justification for the above occlusion from |layer1| and |layer2|:
-
- +---------------------+
- | |30 Visible region of |layer1|: /////
- | | Visible region of |layer2|: \\\\\
- | +---------------------------------+
- | | |10 |
- | +---------------+-----------------+ |
- | | |\\\\\\\\\\\\|//| 420 | |
- | | |\\\\\\\\\\\\|//|60 | |
- | | |\\\\\\\\\\\\|//| | |
- +--|--|------------|--+ | |
- 20|10| 70 | | |
- | | | | |
- | | | | |
- | | | | |
- | | | | |
- | | | | |
- | | | |10|
- | +------------|-----------------|--+
- | | 490 |
- +---------------+-----------------+
- 60 440
- */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerAddedToOccludedRegionWithMultipleOpaqueLayers, layerAddedToOccludedRegionWithMultipleOpaqueLayers);
-
-void surfaceOcclusionWithOverlappingSiblingSurfaces(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromium> child1 = LayerChromium::create();
- RefPtr<LayerChromium> child2 = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(child1);
- parent->addChild(child2);
- child1->addChild(layer1);
- child2->addChild(layer2);
-
- TransformationMatrix childTransform;
- childTransform.translate(250, 250);
- childTransform.rotate(90);
- childTransform.translate(-250, -250);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(child1.get(), childTransform, FloatPoint(30, 30), IntSize(500, 500));
- setLayerPropertiesForTesting(layer1.get(), identityMatrix, FloatPoint(0, 0), IntSize(500, 500), true, opaqueLayers);
- setLayerPropertiesForTesting(child2.get(), childTransform, FloatPoint(20, 40), IntSize(500, 500));
- setLayerPropertiesForTesting(layer2.get(), identityMatrix, FloatPoint(0, 0), IntSize(500, 500), true, opaqueLayers);
-
- child1->setMasksToBounds(true);
- child2->setMasksToBounds(true);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(child2->renderSurface());
- occlusion.markOccludedBehindLayer(layer2.get());
-
- EXPECT_EQ_RECT(IntRect(20, 40, 80, 60), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(0, 420, 60, 80), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(0, 420, 60, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-1, 420, 60, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 419, 60, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 420, 61, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 420, 60, 81)));
-
- occlusion.markOccludedBehindLayer(child2.get());
- occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(child1->renderSurface());
- occlusion.markOccludedBehindLayer(layer1.get());
-
- EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(0, 430, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-1, 430, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 429, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 430, 71, 70)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 430, 70, 71)));
-
- occlusion.markOccludedBehindLayer(child1.get());
- occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 30, 80, 70)));
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70)));
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(20, 40, 80, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(19, 40, 80, 60)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 39, 80, 60)));
-
- /* Justification for the above occlusion:
- 100
- +---------------------+
- | |
- | 30 | child1
- | 30+ ---------------------------------+
- 100 | 40| | child2 |
- |20+----------------------------------+ |
- | | | | | |
- | | | | | |
- | | | | | |
- +--|-|----------------+ | |
- | | | | 500
- | | | |
- | | | |
- | | | |
- | | | |
- | | | |
- | | | |
- | +--------------------------------|-+
- | |
- +----------------------------------+
- 500
- */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_surfaceOcclusionWithOverlappingSiblingSurfaces, surfaceOcclusionWithOverlappingSiblingSurfaces);
-
-void surfaceOcclusionInScreenSpace(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromium> child1 = LayerChromium::create();
- RefPtr<LayerChromium> child2 = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(child1);
- parent->addChild(child2);
- child1->addChild(layer1);
- child2->addChild(layer2);
-
- TransformationMatrix childTransform;
- childTransform.translate(250, 250);
- childTransform.rotate(90);
- childTransform.translate(-250, -250);
-
- // The owning layers have very different bounds from the surfaces that they own.
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(child1.get(), childTransform, FloatPoint(30, 30), IntSize(10, 10));
- setLayerPropertiesForTesting(layer1.get(), identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true, opaqueLayers);
- setLayerPropertiesForTesting(child2.get(), childTransform, FloatPoint(20, 40), IntSize(10, 10));
- setLayerPropertiesForTesting(layer2.get(), identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true, opaqueLayers);
-
- // Make them both render surfaces
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- child1->setFilters(filters);
- child2->setFilters(filters);
-
- child1->setMasksToBounds(false);
- child2->setMasksToBounds(false);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(-20, -20, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(child2->renderSurface());
- occlusion.markOccludedBehindLayer(layer2.get());
-
- EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80)));
- EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80)));
- EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80)));
- EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80)));
- EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81)));
- occlusion.setLayerScissorRect(IntRect(-20, -20, 1000, 1000));
-
- occlusion.markOccludedBehindLayer(child2.get());
- occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(child1->renderSurface());
- occlusion.markOccludedBehindLayer(layer1.get());
-
- EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(-10, 430, 80, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(-10, 430, 80, 70)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-11, 430, 80, 70)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 429, 80, 70)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 430, 81, 70)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 430, 80, 71)));
-
- occlusion.markOccludedBehindLayer(child1.get());
- occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 20, 80, 80)));
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 20, 70, 80)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 20, 70, 80)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 19, 70, 80)));
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(20, 30, 80, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(19, 30, 80, 70)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 29, 80, 70)));
-
- /* Justification for the above occlusion:
- 100
- +---------------------+
- | 20 | layer1
- | 30+ ---------------------------------+
- 100 | 30| | layer2 |
- |20+----------------------------------+ |
- | | | | | |
- | | | | | |
- | | | | | |
- +--|-|----------------+ | |
- | | | | 510
- | | | |
- | | | |
- | | | |
- | | | |
- | | | |
- | | | |
- | +--------------------------------|-+
- | |
- +----------------------------------+
- 510
- */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_surfaceOcclusionInScreenSpace, surfaceOcclusionInScreenSpace);
-
-void surfaceOcclusionInScreenSpaceDifferentTransforms(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromium> child1 = LayerChromium::create();
- RefPtr<LayerChromium> child2 = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(child1);
- parent->addChild(child2);
- child1->addChild(layer1);
- child2->addChild(layer2);
-
- TransformationMatrix child1Transform;
- child1Transform.translate(250, 250);
- child1Transform.rotate(-90);
- child1Transform.translate(-250, -250);
-
- TransformationMatrix child2Transform;
- child2Transform.translate(250, 250);
- child2Transform.rotate(90);
- child2Transform.translate(-250, -250);
-
- // The owning layers have very different bounds from the surfaces that they own.
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(child1.get(), child1Transform, FloatPoint(30, 20), IntSize(10, 10));
- setLayerPropertiesForTesting(layer1.get(), identityMatrix, FloatPoint(-10, -20), IntSize(510, 520), true, opaqueLayers);
- setLayerPropertiesForTesting(child2.get(), child2Transform, FloatPoint(20, 40), IntSize(10, 10));
- setLayerPropertiesForTesting(layer2.get(), identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true, opaqueLayers);
-
- // Make them both render surfaces
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- child1->setFilters(filters);
- child2->setFilters(filters);
-
- child1->setMasksToBounds(false);
- child2->setMasksToBounds(false);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(-30, -30, 1000, 1000));
-
- occlusion.enterTargetRenderSurface(child2->renderSurface());
- occlusion.markOccludedBehindLayer(layer2.get());
-
- EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80)));
- EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81)));
-
- occlusion.markOccludedBehindLayer(child2.get());
- occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(child1->renderSurface());
- occlusion.markOccludedBehindLayer(layer1.get());
-
- EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(420, -20, 80, 90)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(419, -20, 80, 90)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(420, -21, 80, 90)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(420, -19, 80, 90)));
- EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(421, -20, 80, 90)));
-
- occlusion.markOccludedBehindLayer(child1.get());
- occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(10, 20, 90, 80)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(9, 20, 90, 80)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(10, 19, 90, 80)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(11, 20, 90, 80)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(10, 21, 90, 80)));
-
- /* Justification for the above occlusion:
- 100
- +---------------------+
- |20 | layer1
- 10+----------------------------------+
- 100 || 30 | layer2 |
- |20+----------------------------------+
- || | | | |
- || | | | |
- || | | | |
- +|-|------------------+ | |
- | | | | 510
- | | 510 | |
- | | | |
- | | | |
- | | | |
- | | | |
- | | 520 | |
- +----------------------------------+ |
- | |
- +----------------------------------+
- 510
- */
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_surfaceOcclusionInScreenSpaceDifferentTransforms, surfaceOcclusionInScreenSpaceDifferentTransforms);
-
-void occlusionInteractionWithFilters(bool opaqueLayers)
-{
- // This tests that the right transforms are being used.
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> blurLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> opacityLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> opaqueLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(blurLayer);
- parent->addChild(opacityLayer);
- parent->addChild(opaqueLayer);
-
- TransformationMatrix layerTransform;
- layerTransform.translate(250, 250);
- layerTransform.rotate(90);
- layerTransform.translate(-250, -250);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
- setLayerPropertiesForTesting(blurLayer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
- setLayerPropertiesForTesting(opaqueLayer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
- setLayerPropertiesForTesting(opacityLayer.get(), layerTransform, FloatPoint(30, 30), IntSize(500, 500), true, opaqueLayers);
+ typename Types::ContentLayerType* createRoot(const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+ {
+ typename Types::ContentLayerPtrType layer(Types::createContentLayer());
+ typename Types::ContentLayerType* layerPtr = layer.get();
+ setProperties(layerPtr, transform, position, bounds);
+
+ ASSERT(!m_root);
+ m_root = layer.release();
+ return layerPtr;
+ }
+
+ typename Types::LayerType* createLayer(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+ {
+ typename Types::LayerPtrType layer(Types::createLayer());
+ typename Types::LayerType* layerPtr = layer.get();
+ setProperties(layerPtr, transform, position, bounds);
+ parent->addChild(layer.release());
+ return layerPtr;
+ }
+ typename Types::LayerType* createSurface(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
{
+ typename Types::LayerType* layer = createLayer(parent, transform, position, bounds);
FilterOperations filters;
- filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR));
- blurLayer->setFilters(filters);
+ filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
+ layer->setFilters(filters);
+ return layer;
}
+ typename Types::ContentLayerType* createDrawingLayer(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque)
{
+ typename Types::ContentLayerPtrType layer(Types::createContentLayer());
+ typename Types::ContentLayerType* layerPtr = layer.get();
+ setProperties(layerPtr, transform, position, bounds);
+
+ if (opaqueLayers)
+ layerPtr->setOpaque(opaque);
+ else {
+ layerPtr->setOpaque(false);
+ if (opaque)
+ layerPtr->setOpaqueContentsRect(IntRect(IntPoint(), bounds));
+ else
+ layerPtr->setOpaqueContentsRect(IntRect());
+ }
+
+ parent->addChild(layer.release());
+ return layerPtr;
+ }
+
+ typename Types::LayerType* createReplicaLayer(typename Types::LayerType* owningLayer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+ {
+ typename Types::ContentLayerPtrType layer(Types::createContentLayer());
+ typename Types::ContentLayerType* layerPtr = layer.get();
+ setProperties(layerPtr, transform, position, bounds);
+ setReplica(owningLayer, layer.release());
+ return layerPtr;
+ }
+
+ typename Types::ContentLayerType* createDrawingSurface(typename Types::LayerType* parent, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds, bool opaque)
+ {
+ typename Types::ContentLayerType* layer = createDrawingLayer(parent, transform, position, bounds, opaque);
FilterOperations filters;
filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- opaqueLayer->setFilters(filters);
+ layer->setFilters(filters);
+ return layer;
+ }
+
+ void calcDrawEtc(TestContentLayerImpl* root)
+ {
+ ASSERT(root == m_root.get());
+ Vector<CCLayerImpl*> dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ ASSERT(!root->renderSurface());
+ root->createRenderSurface();
+ root->renderSurface()->setContentRect(IntRect(IntPoint::zero(), root->bounds()));
+ root->setClipRect(IntRect(IntPoint::zero(), root->bounds()));
+ m_renderSurfaceLayerListImpl.append(m_root.get());
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(root, root, identityMatrix, identityMatrix, m_renderSurfaceLayerListImpl, dummyLayerList, 0, dummyMaxTextureSize);
+ m_layerIterator = m_layerIteratorBegin = Types::LayerIterator::begin(&m_renderSurfaceLayerListImpl);
+ }
+
+ void calcDrawEtc(TestContentLayerChromium* root)
+ {
+ ASSERT(root == m_root.get());
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ ASSERT(!root->renderSurface());
+ root->createRenderSurface();
+ root->renderSurface()->setContentRect(IntRect(IntPoint::zero(), root->bounds()));
+ root->setClipRect(IntRect(IntPoint::zero(), root->bounds()));
+ m_renderSurfaceLayerListChromium.append(m_root);
+
+ CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(root, root, identityMatrix, identityMatrix, m_renderSurfaceLayerListChromium, dummyLayerList, dummyMaxTextureSize);
+ m_layerIterator = m_layerIteratorBegin = Types::LayerIterator::begin(&m_renderSurfaceLayerListChromium);
}
+ void enterLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
{
+ ASSERT_EQ(layer, *m_layerIterator);
+ ASSERT_TRUE(m_layerIterator.representsItself());
+ occlusion.enterLayer(m_layerIterator);
+ }
+
+ void leaveLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
+ {
+ ASSERT_EQ(layer, *m_layerIterator);
+ ASSERT_TRUE(m_layerIterator.representsItself());
+ occlusion.leaveLayer(m_layerIterator);
+ ++m_layerIterator;
+ }
+
+ void visitLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
+ {
+ enterLayer(layer, occlusion);
+ leaveLayer(layer, occlusion);
+ }
+
+ void enterContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
+ {
+ ASSERT_EQ(layer, *m_layerIterator);
+ ASSERT_TRUE(m_layerIterator.representsTargetRenderSurface());
+ occlusion.enterLayer(m_layerIterator);
+ occlusion.leaveLayer(m_layerIterator);
+ ++m_layerIterator;
+ ASSERT_TRUE(m_layerIterator.representsContributingRenderSurface());
+ occlusion.enterLayer(m_layerIterator);
+ }
+
+ void leaveContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
+ {
+ ASSERT_EQ(layer, *m_layerIterator);
+ ASSERT_TRUE(m_layerIterator.representsContributingRenderSurface());
+ occlusion.leaveLayer(m_layerIterator);
+ ++m_layerIterator;
+ }
+
+ void visitContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion)
+ {
+ enterContributingSurface(layer, occlusion);
+ leaveContributingSurface(layer, occlusion);
+ }
+
+ void resetLayerIterator()
+ {
+ m_layerIterator = m_layerIteratorBegin;
+ }
+
+ const TransformationMatrix identityMatrix;
+
+private:
+ void setBaseProperties(typename Types::LayerType* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+ {
+ layer->setTransform(transform);
+ layer->setSublayerTransform(TransformationMatrix());
+ layer->setAnchorPoint(FloatPoint(0, 0));
+ layer->setPosition(position);
+ layer->setBounds(bounds);
+ }
+
+ void setProperties(LayerChromium* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+ {
+ setBaseProperties(layer, transform, position, bounds);
+ }
+
+ void setProperties(CCLayerImpl* layer, const TransformationMatrix& transform, const FloatPoint& position, const IntSize& bounds)
+ {
+ setBaseProperties(layer, transform, position, bounds);
+
+ layer->setContentBounds(layer->bounds());
+ }
+
+ void setReplica(LayerChromium* owningLayer, PassRefPtr<LayerChromium> layer)
+ {
+ owningLayer->setReplicaLayer(layer.get());
+ m_replicaLayers.append(layer);
+ }
+
+ void setReplica(CCLayerImpl* owningLayer, PassOwnPtr<CCLayerImpl> layer)
+ {
+ owningLayer->setReplicaLayer(layer);
+ }
+
+ // These hold ownership of the layers for the duration of the test.
+ typename Types::LayerPtrType m_root;
+ Vector<RefPtr<LayerChromium> > m_renderSurfaceLayerListChromium;
+ Vector<CCLayerImpl*> m_renderSurfaceLayerListImpl;
+ typename Types::LayerIterator m_layerIteratorBegin;
+ typename Types::LayerIterator m_layerIterator;
+ typename Types::LayerType* m_lastLayerVisited;
+ Vector<RefPtr<LayerChromium> > m_replicaLayers;
+};
+
+#define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
+ class ClassName##MainThreadOpaqueLayers : public ClassName<CCOcclusionTrackerTestMainThreadTypes, true> { \
+ public: \
+ ClassName##MainThreadOpaqueLayers() : ClassName<CCOcclusionTrackerTestMainThreadTypes, true>() { } \
+ }; \
+ TEST_F(ClassName##MainThreadOpaqueLayers, runTest) { runMyTest(); }
+#define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
+ class ClassName##MainThreadOpaquePaints : public ClassName<CCOcclusionTrackerTestMainThreadTypes, false> { \
+ public: \
+ ClassName##MainThreadOpaquePaints() : ClassName<CCOcclusionTrackerTestMainThreadTypes, false>() { } \
+ }; \
+ TEST_F(ClassName##MainThreadOpaquePaints, runTest) { runMyTest(); }
+
+#define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
+ class ClassName##ImplThreadOpaqueLayers : public ClassName<CCOcclusionTrackerTestImplThreadTypes, true> { \
+ DebugScopedSetImplThread impl; \
+ public: \
+ ClassName##ImplThreadOpaqueLayers() : ClassName<CCOcclusionTrackerTestImplThreadTypes, true>() { } \
+ }; \
+ TEST_F(ClassName##ImplThreadOpaqueLayers, runTest) { runMyTest(); }
+#define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \
+ class ClassName##ImplThreadOpaquePaints : public ClassName<CCOcclusionTrackerTestImplThreadTypes, false> { \
+ DebugScopedSetImplThread impl; \
+ public: \
+ ClassName##ImplThreadOpaquePaints() : ClassName<CCOcclusionTrackerTestImplThreadTypes, false>() { } \
+ }; \
+ TEST_F(ClassName##ImplThreadOpaquePaints, runTest) { runMyTest(); }
+
+#define ALL_CCOCCLUSIONTRACKER_TEST(ClassName) \
+ RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
+ RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \
+ RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
+ RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)
+
+#define MAIN_THREAD_TEST(ClassName) \
+ RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)
+
+#define MAIN_AND_IMPL_THREAD_TEST(ClassName) \
+ RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
+ RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestIdentityTransforms : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(30, 30), IntSize(500, 500), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 31, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 31, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 31, 70, 70)));
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestIdentityTransforms);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestRotatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix layerTransform;
+ layerTransform.translate(250, 250);
+ layerTransform.rotate(90);
+ layerTransform.translate(-250, -250);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 70, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 70, 70)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 30, 70, 70)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 70, 70)));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 29, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(31, 31, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 31, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent, IntRect(29, 31, 70, 70)));
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestRotatedChild);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestTranslatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix layerTransform;
+ layerTransform.translate(20, 20);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 50, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(49, 50, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 49, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(51, 50, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 51, 50, 50)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 50, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(49, 50, 50, 50)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(50, 49, 50, 50)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(51, 50, 50, 50)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(50, 51, 50, 50)));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 50, 50, 50)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 50, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 49, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 49, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(51, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 49, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(100, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 50, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(51, 51, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(51, 51, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(50, 100, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 51, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(49, 51, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 51, 50, 50)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 50, 50, 50)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 50, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(49, 49, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent, IntRect(50, 49, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(51, 49, 49, 1), occlusion.unoccludedContentRect(parent, IntRect(51, 49, 50, 50)));
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(51, 50, 50, 50)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(51, 51, 50, 50)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(50, 51, 50, 50)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(49, 51, 1, 49), occlusion.unoccludedContentRect(parent, IntRect(49, 51, 50, 50)));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestTranslatedChild);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestChildInRotatedChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
+ child->setMasksToBounds(true);
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(layer, occlusion);
+ this->enterContributingSurface(child, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 430, 61, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 430, 60, 71)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 61, 70)));
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 71)));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->leaveContributingSurface(child, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 41, 70, 60)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(31, 40, 70, 60)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 41, 70, 60)));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+
+ /* Justification for the above occlusion from |layer|:
+ 100
+ +---------------------+ +---------------------+
+ | | | |30 Visible region of |layer|: /////
+ | 30 | rotate(90) | |
+ | 30 + ---------------------------------+ | +---------------------------------+
+ 100 | | 10 | | ==> | | |10 |
+ | |10+---------------------------------+ | +---------------------------------+ |
+ | | | | | | | | |///////////////| 420 | |
+ | | | | | | | | |///////////////|60 | |
+ | | | | | | | | |///////////////| | |
+ +----|--|-------------+ | | +--|--|---------------+ | |
+ | | | | 20|10| 70 | |
+ | | | | | | | |
+ | | | |500 | | | |
+ | | | | | | | |
+ | | | | | | | |
+ | | | | | | | |
+ | | | | | | |10|
+ +--|-------------------------------+ | | +------------------------------|--+
+ | | | 490 |
+ +---------------------------------+ +---------------------------------+
+ 500 500
+ */
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestChildInRotatedChild);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestVisitTargetTwoTimes : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
+ child->setMasksToBounds(true);
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
+ // |child2| makes |parent|'s surface get considered by CCOcclusionTracker first, instead of |child|'s. This exercises different code in
+ // leaveToTargetRenderSurface, as the target surface has already been seen.
+ typename Types::ContentLayerType* child2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(30, 30), IntSize(60, 20), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
+
+ this->visitLayer(child2, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ this->visitLayer(layer, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ this->enterContributingSurface(child, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
+ occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
+ // This is the little piece not occluded by child2
+ EXPECT_EQ_RECT(IntRect(9, 430, 1, 10), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)));
+ // This extends past both sides of child2, so it will be the original rect.
+ EXPECT_EQ_RECT(IntRect(9, 430, 60, 80), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 80)));
+ // This extends past two adjacent sides of child2, and should included the unoccluded parts of each side.
+ // This also demonstrates that the rect can be arbitrary and does not get clipped to the layer's visibleLayerRect().
+ EXPECT_EQ_RECT(IntRect(-10, 430, 20, 70), occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 70)));
+ // This extends past three adjacent sides of child2, so it should contain the unoccluded parts of each side. The left
+ // and bottom edges are completely unoccluded for some row/column so we get back the original query rect.
+ EXPECT_EQ_RECT(IntRect(-10, 430, 60, 80), occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 80)));
+ EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 80)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 70)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 80)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)).isEmpty());
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ // Occlusion in |child2| should get merged with the |child| surface we are leaving now.
+ this->leaveContributingSurface(child, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 30, 70, 70)));
+ EXPECT_EQ_RECT(IntRect(90, 30, 10, 10), occlusion.unoccludedContentRect(parent, IntRect(30, 30, 70, 70)));
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 30, 60, 10)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 30, 60, 10)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 29, 60, 10)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(31, 30, 60, 10)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 31, 60, 10)));
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 30, 60, 10)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 30, 1, 10), occlusion.unoccludedContentRect(parent, IntRect(29, 30, 60, 10)));
+ EXPECT_EQ_RECT(IntRect(30, 29, 60, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 60, 10)));
+ EXPECT_EQ_RECT(IntRect(90, 30, 1, 10), occlusion.unoccludedContentRect(parent, IntRect(31, 30, 60, 10)));
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 31, 60, 10)).isEmpty());
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 40, 70, 60)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(29, 40, 70, 60)));
+ // This rect is mostly occluded by |child2|.
+ EXPECT_EQ_RECT(IntRect(90, 39, 10, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 39, 70, 60)));
+ // This rect extends past top/right ends of |child2|.
+ EXPECT_EQ_RECT(IntRect(30, 29, 70, 11), occlusion.unoccludedContentRect(parent, IntRect(30, 29, 70, 70)));
+ // This rect extends past left/right ends of |child2|.
+ EXPECT_EQ_RECT(IntRect(20, 39, 80, 60), occlusion.unoccludedContentRect(parent, IntRect(20, 39, 80, 60)));
+ EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(31, 40, 70, 60)));
+ EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 41, 70, 60)));
+
+ /* Justification for the above occlusion from |layer|:
+ 100
+ +---------------------+ +---------------------+
+ | | | |30 Visible region of |layer|: /////
+ | 30 | rotate(90) | 30 60 | |child2|: \\\\\
+ | 30 + ------------+--------------------+ | 30 +------------+--------------------+
+ 100 | | 10 | | | ==> | |\\\\\\\\\\\\| |10 |
+ | |10+----------|----------------------+ | +--|\\\\\\\\\\\\|-----------------+ |
+ | + ------------+ | | | | | +------------+//| 420 | |
+ | | | | | | | | |///////////////|60 | |
+ | | | | | | | | |///////////////| | |
+ +----|--|-------------+ | | +--|--|---------------+ | |
+ | | | | 20|10| 70 | |
+ | | | | | | | |
+ | | | |500 | | | |
+ | | | | | | | |
+ | | | | | | | |
+ | | | | | | | |
+ | | | | | | |10|
+ +--|-------------------------------+ | | +------------------------------|--+
+ | | | 490 |
+ +---------------------------------+ +---------------------------------+
+ 500 500
+ */
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestVisitTargetTwoTimes);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceRotatedOffAxis : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(95);
+ childTransform.translate(-250, -250);
+
+ TransformationMatrix layerTransform;
+ layerTransform.translate(10, 10);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
+ child->setMasksToBounds(true);
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(child, layerTransform, FloatPoint(0, 0), IntSize(500, 500), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ IntRect clippedLayerInChild = layerTransform.mapRect(layer->visibleLayerRect());
+
+ this->visitLayer(layer, occlusion);
+ this->enterContributingSurface(child, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(clippedLayerInChild, occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child, clippedLayerInChild));
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(-1, 0);
+ EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
+ EXPECT_FALSE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(1, 0);
+ clippedLayerInChild.move(1, 0);
+ EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
+ EXPECT_FALSE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(-1, 0);
+ clippedLayerInChild.move(0, -1);
+ EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
+ EXPECT_FALSE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(0, 1);
+ clippedLayerInChild.move(0, 1);
+ EXPECT_FALSE(occlusion.occluded(child, clippedLayerInChild));
+ EXPECT_FALSE(occlusion.unoccludedContentRect(child, clippedLayerInChild).isEmpty());
+ clippedLayerInChild.move(0, -1);
+
+ this->leaveContributingSurface(child, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(75, 55, 1, 1)));
+ EXPECT_EQ_RECT(IntRect(75, 55, 1, 1), occlusion.unoccludedContentRect(parent, IntRect(75, 55, 1, 1)));
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceRotatedOffAxis);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::LayerType* child = this->createLayer(parent, childTransform, FloatPoint(30, 30), IntSize(500, 500));
+ child->setMasksToBounds(true);
+ typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 10), IntSize(500, 500), true);
+ typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child, this->identityMatrix, FloatPoint(10, 450), IntSize(500, 60), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(layer2, occlusion);
+ this->visitLayer(layer1, occlusion);
+ this->enterContributingSurface(child, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
+ EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(9, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)));
+ EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)));
+
+ this->leaveContributingSurface(child, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 40, 70, 60)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 39, 70, 60)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(30, 40, 70, 60)).isEmpty());
+ EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(29, 40, 70, 60)));
+ EXPECT_EQ_RECT(IntRect(30, 39, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 39, 70, 60)));
+ EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent, IntRect(31, 40, 70, 60)));
+ EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent, IntRect(30, 41, 70, 60)));
+
+ /* Justification for the above occlusion from |layer1| and |layer2|:
+
+ +---------------------+
+ | |30 Visible region of |layer1|: /////
+ | | Visible region of |layer2|: \\\\\
+ | +---------------------------------+
+ | | |10 |
+ | +---------------+-----------------+ |
+ | | |\\\\\\\\\\\\|//| 420 | |
+ | | |\\\\\\\\\\\\|//|60 | |
+ | | |\\\\\\\\\\\\|//| | |
+ +--|--|------------|--+ | |
+ 20|10| 70 | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | |10|
+ | +------------|-----------------|--+
+ | | 490 |
+ +---------------+-----------------+
+ 60 440
+ */
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceWithTwoOpaqueChildren);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestOverlappingSurfaceSiblings : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::LayerType* child1 = this->createSurface(parent, childTransform, FloatPoint(30, 30), IntSize(10, 10));
+ typename Types::LayerType* child2 = this->createSurface(parent, childTransform, FloatPoint(20, 40), IntSize(10, 10));
+ typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
+ typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(-20, -20, 1000, 1000));
+
+ this->visitLayer(layer2, occlusion);
+ this->enterContributingSurface(child2, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
+ EXPECT_TRUE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
+ EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
+ EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
+ EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
+ occlusion.setLayerScissorRect(IntRect(-20, -20, 1000, 1000));
+
+ // There is nothing above child2's surface in the z-order.
+ EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.unoccludedContributingSurfaceContentRect(child2->renderSurface(), false, IntRect(-10, 420, 70, 80)));
+
+ this->leaveContributingSurface(child2, occlusion);
+ this->visitLayer(layer1, occlusion);
+ this->enterContributingSurface(child1, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(-10, 430, 80, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child1, IntRect(-10, 430, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1, IntRect(-11, 430, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 429, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 430, 81, 70)));
+ EXPECT_FALSE(occlusion.occluded(child1, IntRect(-10, 430, 80, 71)));
+
+ // child2's contents will occlude child1 below it.
+ EXPECT_EQ_RECT(IntRect(-10, 430, 10, 70), occlusion.unoccludedContributingSurfaceContentRect(child1->renderSurface(), false, IntRect(-10, 430, 80, 70)));
+
+ this->leaveContributingSurface(child1, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(20, 20, 80, 80)));
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(30, 20, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(29, 20, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(30, 19, 70, 80)));
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(20, 30, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(19, 30, 80, 70)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(20, 29, 80, 70)));
+
+ /* Justification for the above occlusion:
+ 100
+ +---------------------+
+ | 20 | layer1
+ | 30+ ---------------------------------+
+ 100 | 30| | layer2 |
+ |20+----------------------------------+ |
+ | | | | | |
+ | | | | | |
+ | | | | | |
+ +--|-|----------------+ | |
+ | | | | 510
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | +--------------------------------|-+
+ | |
+ +----------------------------------+
+ 510
+ */
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestOverlappingSurfaceSiblings);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix child1Transform;
+ child1Transform.translate(250, 250);
+ child1Transform.rotate(-90);
+ child1Transform.translate(-250, -250);
+
+ TransformationMatrix child2Transform;
+ child2Transform.translate(250, 250);
+ child2Transform.rotate(90);
+ child2Transform.translate(-250, -250);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::LayerType* child1 = this->createSurface(parent, child1Transform, FloatPoint(30, 20), IntSize(10, 10));
+ typename Types::LayerType* child2 = this->createDrawingSurface(parent, child2Transform, FloatPoint(20, 40), IntSize(10, 10), false);
+ typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, FloatPoint(-10, -20), IntSize(510, 510), true);
+ typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, FloatPoint(-10, -10), IntSize(510, 510), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(-30, -30, 1000, 1000));
+
+ this->visitLayer(layer2, occlusion);
+ this->enterLayer(child2, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child2, IntRect(-10, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2, IntRect(-11, 420, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 419, 70, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 71, 80)));
+ EXPECT_FALSE(occlusion.occluded(child2, IntRect(-10, 420, 70, 81)));
+
+ this->leaveLayer(child2, occlusion);
+ this->enterContributingSurface(child2, occlusion);
+
+ // There is nothing above child2's surface in the z-order.
+ EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.unoccludedContributingSurfaceContentRect(child2->renderSurface(), false, IntRect(-10, 420, 70, 80)));
+
+ this->leaveContributingSurface(child2, occlusion);
+ this->visitLayer(layer1, occlusion);
+ this->enterContributingSurface(child1, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(child1, IntRect(420, -20, 80, 90)));
+ EXPECT_FALSE(occlusion.occluded(child1, IntRect(419, -20, 80, 90)));
+ EXPECT_FALSE(occlusion.occluded(child1, IntRect(420, -21, 80, 90)));
+ EXPECT_FALSE(occlusion.occluded(child1, IntRect(420, -19, 80, 90)));
+ EXPECT_FALSE(occlusion.occluded(child1, IntRect(421, -20, 80, 90)));
+
+ // child2's contents will occlude child1 below it.
+ EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.unoccludedContributingSurfaceContentRect(child1->renderSurface(), false, IntRect(420, -20, 80, 90)));
+ EXPECT_EQ_RECT(IntRect(490, -10, 10, 80), occlusion.unoccludedContributingSurfaceContentRect(child1->renderSurface(), false, IntRect(420, -10, 80, 90)));
+ EXPECT_EQ_RECT(IntRect(420, -20, 70, 10), occlusion.unoccludedContributingSurfaceContentRect(child1->renderSurface(), false, IntRect(420, -20, 70, 90)));
+
+ this->leaveContributingSurface(child1, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(10, 20, 90, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(9, 20, 90, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(10, 19, 90, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(11, 20, 90, 80)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(10, 21, 90, 80)));
+
+ /* Justification for the above occlusion:
+ 100
+ +---------------------+
+ |20 | layer1
+ 10+----------------------------------+
+ 100 || 30 | layer2 |
+ |20+----------------------------------+
+ || | | | |
+ || | | | |
+ || | | | |
+ +|-|------------------+ | |
+ | | | | 510
+ | | 510 | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | 520 | |
+ +----------------------------------+ |
+ | |
+ +----------------------------------+
+ 510
+ */
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestFilters : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix layerTransform;
+ layerTransform.translate(250, 250);
+ layerTransform.rotate(90);
+ layerTransform.translate(-250, -250);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::ContentLayerType* blurLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+ typename Types::ContentLayerType* opaqueLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+ typename Types::ContentLayerType* opacityLayer = this->createDrawingLayer(parent, layerTransform, FloatPoint(30, 30), IntSize(500, 500), true);
+
FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR));
+ blurLayer->setFilters(filters);
+
+ filters.operations().clear();
+ filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
+ opaqueLayer->setFilters(filters);
+
+ filters.operations().clear();
filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY));
opacityLayer->setFilters(filters);
+
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ // Opacity layer won't contribute to occlusion.
+ this->visitLayer(opacityLayer, occlusion);
+ this->enterContributingSurface(opacityLayer, occlusion);
+
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+ EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+ // And has nothing to contribute to its parent surface.
+ this->leaveContributingSurface(opacityLayer, occlusion);
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+ EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+ // Opaque layer will contribute to occlusion.
+ this->visitLayer(opaqueLayer, occlusion);
+ this->enterContributingSurface(opaqueLayer, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // And it gets translated to the parent surface.
+ this->leaveContributingSurface(opaqueLayer, occlusion);
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // The blur layer needs to throw away any occlusion from outside its subtree.
+ this->enterLayer(blurLayer, occlusion);
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+ EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+ // And it won't contribute to occlusion.
+ this->leaveLayer(blurLayer, occlusion);
+ this->enterContributingSurface(blurLayer, occlusion);
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
+ EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+
+ // But the opaque layer's occlusion is preserved on the parent.
+ this->leaveContributingSurface(blurLayer, occlusion);
+ this->enterLayer(parent, occlusion);
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
}
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestFilters);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestReplicaDoesOcclude : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
+ typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(50, 50), true);
+ this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(50, 50), IntSize());
+ this->calcDrawEtc(parent);
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+ this->visitLayer(surface, occlusion);
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+ EXPECT_EQ_RECT(IntRect(0, 100, 50, 50), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ this->visitContributingSurface(surface, occlusion);
+ this->enterLayer(parent, occlusion);
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+ // The surface and replica should both be occluding the parent.
+ EXPECT_EQ_RECT(IntRect(0, 100, 100, 100), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+ }
+};
- // Opacity layer won't contribute to occlusion.
- occlusion.enterTargetRenderSurface(opacityLayer->renderSurface());
- occlusion.markOccludedBehindLayer(opacityLayer.get());
- occlusion.finishedTargetRenderSurface(opacityLayer.get(), opacityLayer->renderSurface());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReplicaDoesOcclude);
- EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
- EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestReplicaWithClipping : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 170));
+ typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(50, 50), true);
+ this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(50, 50), IntSize());
+ this->calcDrawEtc(parent);
- // And has nothing to contribute to its parent surface.
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
- EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
- // Opaque layer will contribute to occlusion.
- occlusion.enterTargetRenderSurface(opaqueLayer->renderSurface());
- occlusion.markOccludedBehindLayer(opaqueLayer.get());
- occlusion.finishedTargetRenderSurface(opaqueLayer.get(), opaqueLayer->renderSurface());
+ this->visitLayer(surface, occlusion);
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 100, 50, 50), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- // And it gets translated to the parent surface.
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ this->visitContributingSurface(surface, occlusion);
+ this->enterLayer(parent, occlusion);
- // The blur layer needs to throw away any occlusion from outside its subtree.
- occlusion.enterTargetRenderSurface(blurLayer->renderSurface());
- EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
- EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+ // The surface and replica should both be occluding the parent.
+ EXPECT_EQ_RECT(IntRect(0, 100, 100, 70), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+ }
+};
- // And it won't contribute to occlusion.
- occlusion.markOccludedBehindLayer(blurLayer.get());
- occlusion.finishedTargetRenderSurface(blurLayer.get(), blurLayer->renderSurface());
- EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty());
- EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReplicaWithClipping);
- // But the opaque layer's occlusion is preserved on the parent.
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds());
- EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
-}
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectOutsideChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(200, 100, 100, 100));
+
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+ occlusion.setLayerScissorRect(IntRect(200, 100, 100, 100));
+
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+ EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ }
+};
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_occlusionInteractionWithFilters, occlusionInteractionWithFilters);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectOutsideChild);
-void layerScissorRectOverTile(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
-
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(200, 100, 100, 100));
-
- occlusion.enterTargetRenderSurface(layer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
-
- occlusion.useDefaultLayerScissorRect();
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
- occlusion.setLayerScissorRect(IntRect(200, 100, 100, 100));
-
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectOverTile, layerScissorRectOverTile);
-
-void screenScissorRectOverTile(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestScreenScissorRectOutsideChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(200, 100, 100, 100));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+
+ occlusion.useDefaultLayerScissorRect();
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+ EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ }
+};
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestScreenScissorRectOutsideChild);
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(100, 100, 100, 100));
+
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+ }
+};
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectOverChild);
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestScreenScissorRectOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(100, 100, 100, 100));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+ }
+};
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestScreenScissorRectOverChild);
- TestCCOcclusionTracker occlusion(IntRect(200, 100, 100, 100));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectPartlyOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(50, 50, 200, 200));
+
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+ EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)));
+ EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)));
+ EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)));
+ }
+};
- occlusion.enterTargetRenderSurface(layer->renderSurface());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectPartlyOverChild);
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestScreenScissorRectPartlyOverChild : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(50, 50, 200, 200));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+ EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)));
+ EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)));
+ EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)));
+ }
+};
- // Occluded since its outside the surface bounds.
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestScreenScissorRectPartlyOverChild);
- // Test without any scissors.
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
- occlusion.useDefaultLayerScissorRect();
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectOverNothing : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(500, 500, 100, 100));
+
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)).isEmpty());
+ }
+};
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectOverNothing);
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestScreenScissorRectOverNothing : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(500, 500, 100, 100));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 0, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(0, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 200, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 100)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(0, 100, 300, 100)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(200, 100, 100, 100)).isEmpty());
+ EXPECT_TRUE(occlusion.unoccludedContentRect(parent, IntRect(100, 200, 100, 100)).isEmpty());
+ }
+};
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestScreenScissorRectOverNothing);
- EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-}
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerScissorRectForLayerOffOrigin : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ this->enterLayer(layer, occlusion);
+
+ // This layer is translated when drawn into its target. So if the scissor rect given from the target surface
+ // is not in that target space, then after translating these query rects into the target, they will fall outside
+ // the scissor and be considered occluded.
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
+ }
+};
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_screenScissorRectOverTile, screenScissorRectOverTile);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestLayerScissorRectForLayerOffOrigin);
-void layerScissorRectOverCulledTile(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestOpaqueContentsRegionEmpty : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 200), false);
+ this->calcDrawEtc(parent);
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ this->enterLayer(layer, occlusion);
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 0, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(0, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(100, 100, 100, 100)));
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+ // Occluded since its outside the surface bounds.
+ EXPECT_TRUE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+ // Test without any scissors.
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+ EXPECT_FALSE(occlusion.occluded(layer, IntRect(200, 100, 100, 100)));
+ occlusion.useDefaultLayerScissorRect();
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ this->leaveLayer(layer, occlusion);
+ this->visitContributingSurface(layer, occlusion);
+ this->enterLayer(parent, occlusion);
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(100, 100, 100, 100));
+ EXPECT_TRUE(occlusion.occlusionInScreenSpace().bounds().isEmpty());
+ EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+ }
+};
- occlusion.enterTargetRenderSurface(layer->renderSurface());
+MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestOpaqueContentsRegionEmpty);
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 100), IntSize(200, 200), false);
+ this->calcDrawEtc(parent);
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+ {
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ layer->setOpaqueContentsRect(IntRect(0, 0, 100, 100));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+ this->resetLayerIterator();
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ EXPECT_EQ_RECT(IntRect(100, 100, 100, 100), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-}
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+ }
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectOverCulledTile, layerScissorRectOverCulledTile);
+ {
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ layer->setOpaqueContentsRect(IntRect(20, 20, 180, 180));
-void screenScissorRectOverCulledTile(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
+ this->resetLayerIterator();
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
+ EXPECT_EQ_RECT(IntRect(120, 120, 180, 180), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_TRUE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+ }
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+ {
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ layer->setOpaqueContentsRect(IntRect(150, 150, 100, 100));
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+ this->resetLayerIterator();
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ EXPECT_EQ_RECT(IntRect(250, 250, 50, 50), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- TestCCOcclusionTracker occlusion(IntRect(100, 100, 100, 100));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(0, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(100, 100, 100, 100)));
+ EXPECT_FALSE(occlusion.occluded(parent, IntRect(200, 200, 100, 100)));
+ }
+ }
+};
- occlusion.enterTargetRenderSurface(layer->renderSurface());
+MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty);
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTest3dTransform : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix transform;
+ transform.rotate3d(0, 30, 0);
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, FloatPoint(100, 100), IntSize(200, 200), true);
+ this->calcDrawEtc(parent);
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ this->enterLayer(layer, occlusion);
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ // The layer is rotated in 3d but without preserving 3d, so it only gets resized.
+ EXPECT_EQ_RECT(IntRect(0, 0, 200, 200), occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)));
+ }
+};
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-}
+MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTest3dTransform);
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_screenScissorRectOverCulledTile, screenScissorRectOverCulledTile);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestPerspectiveTransform : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix transform;
+ transform.translate(150, 150);
+ transform.applyPerspective(400);
+ transform.rotate3d(1, 0, 0, -30);
+ transform.translate(-150, -150);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, FloatPoint(100, 100), IntSize(200, 200), true);
+ container->setPreserves3D(true);
+ layer->setPreserves3D(true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ this->enterLayer(layer, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 200, 200), occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)));
+ }
+};
-void layerScissorRectOverPartialTiles(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
-
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(50, 50, 200, 200));
-
- occlusion.enterTargetRenderSurface(layer->renderSurface());
-
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
- EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)));
- EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)));
- EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)));
- EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectOverPartialTiles, layerScissorRectOverPartialTiles);
-
-void screenScissorRectOverPartialTiles(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
-
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(50, 50, 200, 200));
-
- occlusion.enterTargetRenderSurface(layer->renderSurface());
-
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
- EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)));
- EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)));
- EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)));
- EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_screenScissorRectOverPartialTiles, screenScissorRectOverPartialTiles);
-
-void layerScissorRectOverNoTiles(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
-
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.setLayerScissorRect(IntRect(500, 500, 100, 100));
-
- occlusion.enterTargetRenderSurface(layer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)).isEmpty());
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectOverNoTiles, layerScissorRectOverNoTiles);
-
-void screenScissorRectOverNoTiles(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
-
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestCCOcclusionTracker occlusion(IntRect(500, 500, 100, 100));
-
- occlusion.enterTargetRenderSurface(layer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)).isEmpty());
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_screenScissorRectOverNoTiles, screenScissorRectOverNoTiles);
-
-void layerScissorRectForLayerOffOrigin(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
+MAIN_THREAD_TEST(CCOcclusionTrackerTestPerspectiveTransform);
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestPerspectiveTransformBehindCamera : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ // This test is based on the platform/chromium/compositing/3d-corners.html layout test.
+ TransformationMatrix transform;
+ transform.translate(250, 50);
+ transform.applyPerspective(10);
+ transform.translate(-250, -50);
+ transform.translate(250, 50);
+ transform.rotate3d(1, 0, 0, -167);
+ transform.translate(-250, -50);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(500, 100));
+ typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(500, 500));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, FloatPoint(0, 0), IntSize(500, 500), true);
+ container->setPreserves3D(true);
+ layer->setPreserves3D(true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ this->enterLayer(layer, occlusion);
+
+ // The bottom 11 pixel rows of this layer remain visible inside the container, after translation to the target surface. When translated back,
+ // this will include many more pixels but must include at least the bottom 11 rows.
+ EXPECT_TRUE(occlusion.unoccludedContentRect(layer, IntRect(0, 0, 500, 500)).contains(IntRect(0, 489, 500, 11)));
+ }
+};
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(100, 100), IntSize(200, 200), true, opaqueLayers);
+MAIN_THREAD_TEST(CCOcclusionTrackerTestPerspectiveTransformBehindCamera);
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix transform;
+ transform.translate(50, 50);
+ transform.applyPerspective(100);
+ transform.translate3d(0, 0, 110);
+ transform.translate(-50, -50);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, transform, FloatPoint(0, 0), IntSize(100, 100), true);
+ parent->setPreserves3D(true);
+ layer->setPreserves3D(true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+
+ // The |layer| is entirely behind the camera and should not occlude.
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+ EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+ EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+ }
+};
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+MAIN_THREAD_TEST(CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude);
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix transform;
+ transform.translate(50, 50);
+ transform.applyPerspective(100);
+ transform.translate3d(0, 0, 99);
+ transform.translate(-50, -50);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, transform, FloatPoint(0, 0), IntSize(100, 100), true);
+ parent->setPreserves3D(true);
+ layer->setPreserves3D(true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+
+ // This is very close to the camera, so pixels in its visibleLayerRect will actually go outside of the layer's clipRect.
+ // Ensure that those pixels don't occlude things outside the clipRect.
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ EXPECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ }
+};
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
+MAIN_THREAD_TEST(CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect);
- occlusion.enterTargetRenderSurface(layer->renderSurface());
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestAnimationOpacity1OnMainThread : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
+ typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
+ typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 300), true);
+ typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
+ typename Types::ContentLayerType* parent2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false);
+ typename Types::ContentLayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 0), IntSize(50, 300), true);
+
+ addOpacityTransitionToController(*layer->layerAnimationController(), 10, 0, 1, false);
+ addOpacityTransitionToController(*surface->layerAnimationController(), 10, 0, 1, false);
+ this->calcDrawEtc(parent);
+
+ EXPECT_TRUE(layer->drawOpacityIsAnimating());
+ EXPECT_FALSE(surface->drawOpacityIsAnimating());
+ EXPECT_TRUE(surface->renderSurface()->drawOpacityIsAnimating());
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(topmost, occlusion);
+ this->enterLayer(parent2, occlusion);
+ // This occlusion will affect all surfaces.
+ EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent2, IntRect(0, 0, 300, 300)));
+ this->leaveLayer(parent2, occlusion);
+
+ this->visitLayer(surfaceChild2, occlusion);
+ this->enterLayer(surfaceChild, occlusion);
+ EXPECT_EQ_RECT(IntRect(100, 0, 150, 300), occlusion.unoccludedContentRect(surfaceChild, IntRect(0, 0, 300, 300)));
+ this->leaveLayer(surfaceChild, occlusion);
+ this->enterLayer(surface, occlusion);
+ EXPECT_EQ_RECT(IntRect(200, 0, 50, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
+ this->leaveLayer(surface, occlusion);
+
+ this->enterContributingSurface(surface, occlusion);
+ // Occlusion within the surface is lost when leaving the animating surface.
+ EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), false, IntRect(0, 0, 300, 300)));
+ this->leaveContributingSurface(surface, occlusion);
+
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ // Occlusion is not added for the animating |layer|.
+ EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ }
+};
- // This layer is translated when drawn into its target. So if the scissor rect given from the target surface
- // is not in that target space, then after translating these query rects into the target, they will fall outside
- // the scissor and be considered occluded.
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-}
+MAIN_THREAD_TEST(CCOcclusionTrackerTestAnimationOpacity1OnMainThread);
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_layerScissorRectForLayerOffOrigin, layerScissorRectForLayerOffOrigin);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestAnimationOpacity0OnMainThread : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
+ typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
+ typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 300), true);
+ typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
+ typename Types::ContentLayerType* parent2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false);
+ typename Types::ContentLayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 0), IntSize(50, 300), true);
+
+ addOpacityTransitionToController(*layer->layerAnimationController(), 10, 1, 0, false);
+ addOpacityTransitionToController(*surface->layerAnimationController(), 10, 1, 0, false);
+ this->calcDrawEtc(parent);
+
+ EXPECT_TRUE(layer->drawOpacityIsAnimating());
+ EXPECT_FALSE(surface->drawOpacityIsAnimating());
+ EXPECT_TRUE(surface->renderSurface()->drawOpacityIsAnimating());
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(topmost, occlusion);
+ this->enterLayer(parent2, occlusion);
+ // This occlusion will affect all surfaces.
+ EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ this->leaveLayer(parent2, occlusion);
+
+ this->visitLayer(surfaceChild2, occlusion);
+ this->enterLayer(surfaceChild, occlusion);
+ EXPECT_EQ_RECT(IntRect(100, 0, 150, 300), occlusion.unoccludedContentRect(surfaceChild, IntRect(0, 0, 300, 300)));
+ this->leaveLayer(surfaceChild, occlusion);
+ this->enterLayer(surface, occlusion);
+ EXPECT_EQ_RECT(IntRect(200, 0, 50, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
+ this->leaveLayer(surface, occlusion);
+
+ this->enterContributingSurface(surface, occlusion);
+ // Occlusion within the surface is lost when leaving the animating surface.
+ EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), false, IntRect(0, 0, 300, 300)));
+ this->leaveContributingSurface(surface, occlusion);
+
+ this->visitLayer(layer, occlusion);
+ this->enterLayer(parent, occlusion);
+
+ // Occlusion is not added for the animating |layer|.
+ EXPECT_EQ_RECT(IntRect(0, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ }
+};
-void damageRectOverTile(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
+MAIN_THREAD_TEST(CCOcclusionTrackerTestAnimationOpacity0OnMainThread);
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestAnimationTranslateOnMainThread : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
+ typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300), true);
+ typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(200, 300), true);
+ typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 300), true);
+ typename Types::ContentLayerType* surface2 = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(50, 300), true);
+
+ addAnimatedTransformToController(*layer->layerAnimationController(), 10, 30, 0);
+ addAnimatedTransformToController(*surface->layerAnimationController(), 10, 30, 0);
+ addAnimatedTransformToController(*surfaceChild->layerAnimationController(), 10, 30, 0);
+ this->calcDrawEtc(parent);
+
+ EXPECT_TRUE(layer->drawTransformIsAnimating());
+ EXPECT_TRUE(layer->screenSpaceTransformIsAnimating());
+ EXPECT_TRUE(surface->renderSurface()->targetSurfaceTransformsAreAnimating());
+ EXPECT_TRUE(surface->renderSurface()->screenSpaceTransformsAreAnimating());
+ // The surface owning layer doesn't animate against its own surface.
+ EXPECT_FALSE(surface->drawTransformIsAnimating());
+ EXPECT_TRUE(surface->screenSpaceTransformIsAnimating());
+ EXPECT_TRUE(surfaceChild->drawTransformIsAnimating());
+ EXPECT_TRUE(surfaceChild->screenSpaceTransformIsAnimating());
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(surface2, occlusion);
+ this->enterContributingSurface(surface2, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 300), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+ this->leaveContributingSurface(surface2, occlusion);
+ this->enterLayer(surfaceChild2, occlusion);
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+ // surfaceChild2 is moving in screen space but not relative to its target, so occlusion should happen in its target space only.
+ // It also means that things occluding in screen space (e.g. surface2) cannot occlude this layer.
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 300), occlusion.unoccludedContentRect(surfaceChild2, IntRect(0, 0, 100, 300)));
+ EXPECT_FALSE(occlusion.occluded(surfaceChild, IntRect(0, 0, 50, 300)));
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+ this->leaveLayer(surfaceChild2, occlusion);
+ this->enterLayer(surfaceChild, occlusion);
+ EXPECT_FALSE(occlusion.occluded(surfaceChild, IntRect(0, 0, 100, 300)));
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 300), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 300), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ EXPECT_EQ_RECT(IntRect(100, 0, 200, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
+
+ // The surfaceChild is occluded by the surfaceChild2, but is moving relative its target and the screen, so it
+ // can't be occluded.
+ EXPECT_EQ_RECT(IntRect(0, 0, 200, 300), occlusion.unoccludedContentRect(surfaceChild, IntRect(0, 0, 200, 300)));
+ EXPECT_FALSE(occlusion.occluded(surfaceChild, IntRect(0, 0, 50, 300)));
+
+ this->leaveLayer(surfaceChild, occlusion);
+ this->enterLayer(surface, occlusion);
+ // The surfaceChild is moving in screen space but not relative to its target, so occlusion should happen in its target space only.
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 300), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 300), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ EXPECT_EQ_RECT(IntRect(100, 0, 200, 300), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ this->leaveLayer(surface, occlusion);
+ // The surface's owning layer is moving in screen space but not relative to its target, so occlusion should happen in its target space only.
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 300), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 300), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.unoccludedContentRect(surface, IntRect(0, 0, 300, 300)));
+
+ this->enterContributingSurface(surface, occlusion);
+ // The contributing |surface| is animating so it can't be occluded.
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 300), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), false, IntRect(0, 0, 300, 300)));
+ this->leaveContributingSurface(surface, occlusion);
+
+ this->enterLayer(layer, occlusion);
+ // The |surface| is moving in the screen and in its target, so all occlusion within the surface is lost when leaving it.
+ EXPECT_EQ_RECT(IntRect(50, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ this->leaveLayer(layer, occlusion);
+
+ this->enterLayer(parent, occlusion);
+ // The |layer| is animating in the screen and in its target, so no occlusion is added.
+ EXPECT_EQ_RECT(IntRect(50, 0, 250, 300), occlusion.unoccludedContentRect(parent, IntRect(0, 0, 300, 300)));
+ }
+};
- TestDamageClient damage(FloatRect(200, 100, 100, 100));
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000), &damage);
+MAIN_THREAD_TEST(CCOcclusionTrackerTestAnimationTranslateOnMainThread);
- occlusion.enterTargetRenderSurface(layer->renderSurface());
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceOcclusionTranslatesToParent : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix surfaceTransform;
+ surfaceTransform.translate(300, 300);
+ surfaceTransform.scale(2);
+ surfaceTransform.translate(-150, -150);
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(500, 500));
+ typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, surfaceTransform, FloatPoint(0, 0), IntSize(300, 300), false);
+ typename Types::ContentLayerType* surface2 = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(50, 50), IntSize(300, 300), false);
+ surface->setOpaqueContentsRect(IntRect(0, 0, 200, 200));
+ surface2->setOpaqueContentsRect(IntRect(0, 0, 200, 200));
+ this->calcDrawEtc(parent);
- // Outside the layer's clip rect.
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+ this->visitLayer(surface2, occlusion);
+ this->visitContributingSurface(surface2, occlusion);
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ // Clear any stored occlusion.
+ occlusion.setOcclusionInScreenSpace(Region());
+ occlusion.setOcclusionInTargetSurface(Region());
- EXPECT_EQ_RECT(IntRect(200, 100, 100, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
-}
+ this->visitLayer(surface, occlusion);
+ this->visitContributingSurface(surface, occlusion);
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_damageRectOverTile, damageRectOverTile);
+ EXPECT_EQ_RECT(IntRect(0, 0, 400, 400), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 400, 400), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ }
+};
-void damageRectOverCulledTile(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
+MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestSurfaceOcclusionTranslatesToParent);
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(500, 300), false);
+ surface->setOpaqueContentsRect(IntRect(0, 0, 400, 200));
+ this->calcDrawEtc(parent);
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+ this->visitLayer(surface, occlusion);
+ this->visitContributingSurface(surface, occlusion);
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 200), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 200), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ }
+};
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping);
- TestDamageClient damage(FloatRect(100, 100, 100, 100));
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000), &damage);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestReplicaOccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
+ typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
+ this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
+ typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100), true);
+ this->calcDrawEtc(parent);
- occlusion.enterTargetRenderSurface(layer->renderSurface());
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+ // |topmost| occludes the replica, but not the surface itself.
+ this->visitLayer(topmost, occlusion);
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
+ EXPECT_EQ_RECT(IntRect(0, 100, 100, 100), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 100, 100, 100), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ this->visitLayer(surface, occlusion);
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 200), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ this->enterContributingSurface(surface, occlusion);
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
-}
+ // Surface is not occluded so it shouldn't think it is.
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), false, IntRect(0, 0, 100, 100)));
+ }
+};
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_damageRectOverCulledTile, damageRectOverCulledTile);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReplicaOccluded);
-void damageRectOverPartialTiles(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
-
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestDamageClient damage(FloatRect(50, 50, 200, 200));
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000), &damage);
-
- occlusion.enterTargetRenderSurface(layer->renderSurface());
-
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_EQ_RECT(IntRect(50, 50, 200, 200), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)));
- EXPECT_EQ_RECT(IntRect(200, 50, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)));
- EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)));
- EXPECT_EQ_RECT(IntRect(200, 100, 50, 100), occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)));
- EXPECT_EQ_RECT(IntRect(100, 200, 100, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)));
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_damageRectOverPartialTiles, damageRectOverPartialTiles);
-
-void damageRectOverNoTiles(bool opaqueLayers)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> parentLayer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(parentLayer);
- parent->addChild(layer);
-
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- parentLayer->setFilters(filters);
- layer->setFilters(filters);
-
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(parentLayer.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300), false, opaqueLayers);
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), true, opaqueLayers);
-
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
-
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
-
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
-
- TestDamageClient damage(FloatRect(500, 500, 100, 100));
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000), &damage);
-
- occlusion.enterTargetRenderSurface(layer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
-
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
- occlusion.enterTargetRenderSurface(parentLayer->renderSurface());
-
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 0, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(0, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(100, 200, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parentLayer.get(), IntRect(200, 200, 100, 100)));
-
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
-
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 300)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 0, 300, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(0, 100, 300, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(200, 100, 100, 100)).isEmpty());
- EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(100, 200, 100, 100)).isEmpty());
-}
-
-TEST_OPAQUE_AND_PAINTED_OPAQUE(CCOcclusionTrackerTest_damageRectOverNoTiles, damageRectOverNoTiles);
-
-TEST(CCOcclusionTrackerTest, opaqueContentsRegionEmpty)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(layer);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
+ typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
+ this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
+ typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 110), true);
+ this->calcDrawEtc(parent);
- FilterOperations filters;
- filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE));
- layer->setFilters(filters);
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(0, 0), IntSize(200, 200), false, false);
+ // |topmost| occludes the surface, but not the entire surface's replica.
+ this->visitLayer(topmost, occlusion);
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 110), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 110), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+ this->visitLayer(surface, occlusion);
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 110), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
+ this->enterContributingSurface(surface, occlusion);
- occlusion.enterTargetRenderSurface(layer->renderSurface());
+ // Surface is occluded, but only the top 10px of the replica.
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), false, IntRect(0, 0, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(0, 10, 100, 90), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), true, IntRect(0, 0, 100, 100)));
+ }
+};
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 0, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(100, 100, 100, 100)));
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceWithReplicaUnoccluded);
- // Occluded since its outside the surface bounds.
- EXPECT_TRUE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
+ typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
+ this->createReplicaLayer(surface, this->identityMatrix, FloatPoint(0, 100), IntSize(100, 100));
+ typename Types::LayerType* overSurface = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(40, 100), true);
+ typename Types::LayerType* overReplica = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(50, 100), true);
+ this->calcDrawEtc(parent);
- // Test without any scissors.
- occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
- EXPECT_FALSE(occlusion.occluded(layer.get(), IntRect(200, 100, 100, 100)));
- occlusion.useDefaultLayerScissorRect();
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
- occlusion.markOccludedBehindLayer(layer.get());
- occlusion.leaveToTargetRenderSurface(parent->renderSurface());
+ // These occlude the surface and replica differently, so we can test each one.
+ this->visitLayer(overReplica, occlusion);
+ this->visitLayer(overSurface, occlusion);
- EXPECT_TRUE(occlusion.occlusionInScreenSpace().bounds().isEmpty());
- EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
-}
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 200), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 200), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
-TEST(CCOcclusionTrackerTest, opaqueContentsRegionNonEmpty)
-{
- const TransformationMatrix identityMatrix;
- RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent());
- parent->createRenderSurface();
- parent->addChild(layer);
+ this->visitLayer(surface, occlusion);
- setLayerPropertiesForTesting(parent.get(), identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
- setLayerPropertiesForTesting(layer.get(), identityMatrix, FloatPoint(100, 100), IntSize(200, 200), false, false);
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 200), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
- Vector<RefPtr<LayerChromium> > dummyLayerList;
- int dummyMaxTextureSize = 512;
+ this->enterContributingSurface(surface, occlusion);
- parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds()));
- parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
- renderSurfaceLayerList.append(parent);
+ // Surface and replica are occluded different amounts.
+ EXPECT_EQ_RECT(IntRect(40, 0, 60, 100), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), false, IntRect(0, 0, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(50, 0, 50, 100), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), true, IntRect(0, 0, 100, 100)));
+ }
+};
- CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceAndReplicaOccludedDifferently);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceChildOfSurface : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
{
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- layer->setOpaquePaintRect(IntRect(0, 0, 100, 100));
+ // This test verifies that the surface cliprect does not end up empty and clip away the entire unoccluded rect.
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 200));
+ typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
+ typename Types::LayerType* surfaceChild = this->createDrawingSurface(surface, this->identityMatrix, FloatPoint(0, 10), IntSize(100, 50), true);
+ typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 50), true);
+ this->calcDrawEtc(parent);
- occlusion.enterTargetRenderSurface(parent->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(-100, -100, 1000, 1000));
- EXPECT_EQ_RECT(IntRect(100, 100, 100, 100), occlusion.occlusionInScreenSpace().bounds());
+ // |topmost| occludes everything partially so we know occlusion is happening at all.
+ this->visitLayer(topmost, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 50), occlusion.occlusionInScreenSpace().bounds());
EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ this->visitLayer(surfaceChild, occlusion);
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(0, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(100, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(200, 200, 100, 100)));
+ // surfaceChild increases the occlusion in the screen by a narrow sliver.
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ // In its own surface, surfaceChild is at 0,0 as is its occlusion.
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // The root layer always has a clipRect. So the parent of |surface| has a clipRect. However, the owning layer for |surface| does not
+ // mask to bounds, so it doesn't have a clipRect of its own. Thus the parent of |surfaceChild| exercises different code paths
+ // as its parent does not have a clipRect.
+
+ this->enterContributingSurface(surfaceChild, occlusion);
+ // The surfaceChild's parent does not have a clipRect as it owns a render surface. Make sure the unoccluded rect
+ // does not get clipped away inappropriately.
+ EXPECT_EQ_RECT(IntRect(0, 40, 100, 10), occlusion.unoccludedContributingSurfaceContentRect(surfaceChild->renderSurface(), false, IntRect(0, 0, 100, 50)));
+ this->leaveContributingSurface(surfaceChild, occlusion);
+
+ // When the surfaceChild's occlusion is transformed up to its parent, make sure it is not clipped away inappropriately also.
+ this->enterLayer(surface, occlusion);
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 60), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 10, 100, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ this->leaveLayer(surface, occlusion);
+
+ this->enterContributingSurface(surface, occlusion);
+ // The surface's parent does have a clipRect as it is the root layer.
+ EXPECT_EQ_RECT(IntRect(0, 50, 100, 50), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), false, IntRect(0, 0, 100, 100)));
}
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceChildOfSurface);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestSurfaceChildOfClippingSurface : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
{
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- layer->setOpaquePaintRect(IntRect(20, 20, 180, 180));
+ // This test verifies that the surface cliprect does not end up empty and clip away the entire unoccluded rect.
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(80, 200));
+ typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), true);
+ typename Types::LayerType* surfaceChild = this->createDrawingSurface(surface, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100), false);
+ typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(100, 50), true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
- occlusion.enterTargetRenderSurface(parent->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
+ // |topmost| occludes everything partially so we know occlusion is happening at all.
+ this->visitLayer(topmost, occlusion);
- EXPECT_EQ_RECT(IntRect(120, 120, 180, 180), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ_RECT(IntRect(0, 0, 80, 50), occlusion.occlusionInScreenSpace().bounds());
EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 80, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(100, 100, 100, 100)));
- EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(200, 200, 100, 100)));
+ // surfaceChild is not opaque and does not occlude, so we have a non-empty unoccluded area on surface.
+ this->visitLayer(surfaceChild, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 80, 50), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // The root layer always has a clipRect. So the parent of |surface| has a clipRect. However, the owning layer for |surface| does not
+ // mask to bounds, so it doesn't have a clipRect of its own. Thus the parent of |surfaceChild| exercises different code paths
+ // as its parent does not have a clipRect.
+
+ this->enterContributingSurface(surfaceChild, occlusion);
+ // The surfaceChild's parent does not have a clipRect as it owns a render surface.
+ EXPECT_EQ_RECT(IntRect(0, 50, 80, 50), occlusion.unoccludedContributingSurfaceContentRect(surfaceChild->renderSurface(), false, IntRect(0, 0, 100, 100)));
+ this->leaveContributingSurface(surfaceChild, occlusion);
+
+ this->visitLayer(surface, occlusion);
+ this->enterContributingSurface(surface, occlusion);
+ // The surface's parent does have a clipRect as it is the root layer.
+ EXPECT_EQ_RECT(IntRect(0, 50, 80, 50), occlusion.unoccludedContributingSurfaceContentRect(surface->renderSurface(), false, IntRect(0, 0, 100, 100)));
}
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestSurfaceChildOfClippingSurface);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
{
- TestCCOcclusionTracker occlusion(IntRect(0, 0, 1000, 1000));
- layer->setOpaquePaintRect(IntRect(150, 150, 100, 100));
+ TransformationMatrix scaleByHalf;
+ scaleByHalf.scale(0.5);
+
+ // Make a surface and its replica, each 50x50, that are completely surrounded by opaque layers which are above them in the z-order.
+ // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface
+ // appears at 50, 50 and the replica at 200, 50.
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
+ typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(50, 50), IntSize(100, 100), false);
+ this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(300, 0), IntSize());
+ typename Types::LayerType* occludingLayer1 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 50), true);
+ typename Types::LayerType* occludingLayer2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(300, 50), true);
+ typename Types::LayerType* occludingLayer3 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 50), IntSize(50, 50), true);
+ typename Types::LayerType* occludingLayer4 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 50), IntSize(100, 50), true);
+ typename Types::LayerType* occludingLayer5 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 50), IntSize(50, 50), true);
+
+ // Filters make the layer own a surface.
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Fixed), FilterOperation::BLUR));
+ filteredSurface->setBackgroundFilters(filters);
+
+ // Save the distance of influence for the blur effect.
+ int outsetTop, outsetRight, outsetBottom, outsetLeft;
+ filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
+
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ // These layers occlude pixels directly beside the filteredSurface. Because filtered surface blends pixels in a radius, it will
+ // need to see some of the pixels (up to radius far) underneath the occludingLayers.
+ this->visitLayer(occludingLayer5, occlusion);
+ this->visitLayer(occludingLayer4, occlusion);
+ this->visitLayer(occludingLayer3, occlusion);
+ this->visitLayer(occludingLayer2, occlusion);
+ this->visitLayer(occludingLayer1, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // Everything outside the surface/replica is occluded but the surface/replica itself is not.
+ this->enterLayer(filteredSurface, occlusion);
+ EXPECT_EQ_RECT(IntRect(1, 0, 99, 100), occlusion.unoccludedContentRect(filteredSurface, IntRect(1, 0, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(0, 1, 100, 99), occlusion.unoccludedContentRect(filteredSurface, IntRect(0, 1, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(0, 0, 99, 100), occlusion.unoccludedContentRect(filteredSurface, IntRect(-1, 0, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(0, 0, 100, 99), occlusion.unoccludedContentRect(filteredSurface, IntRect(0, -1, 100, 100)));
+
+ EXPECT_EQ_RECT(IntRect(300 + 1, 0, 99, 100), occlusion.unoccludedContentRect(filteredSurface, IntRect(300 + 1, 0, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(300 + 0, 1, 100, 99), occlusion.unoccludedContentRect(filteredSurface, IntRect(300 + 0, 1, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(300 + 0, 0, 99, 100), occlusion.unoccludedContentRect(filteredSurface, IntRect(300 - 1, 0, 100, 100)));
+ EXPECT_EQ_RECT(IntRect(300 + 0, 0, 100, 99), occlusion.unoccludedContentRect(filteredSurface, IntRect(300 + 0, -1, 100, 100)));
+ this->leaveLayer(filteredSurface, occlusion);
+
+ // The filtered layer/replica does not occlude.
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // The surface has a background blur, so it needs pixels that are currently considered occluded in order to be drawn. So the pixels
+ // it needs should be removed some the occluded area so that when we get to the parent they are drawn.
+ this->visitContributingSurface(filteredSurface, occlusion);
+
+ this->enterLayer(parent, occlusion);
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInTargetSurface().rects().size());
+
+ IntRect outsetRect;
+ IntRect testRect;
+
+ // Nothing in the blur outsets for the filteredSurface is occluded.
+ outsetRect = IntRect(50 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom);
+ testRect = outsetRect;
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+
+ // Stuff outside the blur outsets is still occluded though.
+ testRect = outsetRect;
+ testRect.expand(1, 0);
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+ testRect = outsetRect;
+ testRect.expand(0, 1);
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+ testRect = outsetRect;
+ testRect.move(-1, 0);
+ testRect.expand(1, 0);
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+ testRect = outsetRect;
+ testRect.move(0, -1);
+ testRect.expand(0, 1);
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+
+ // Nothing in the blur outsets for the filteredSurface's replica is occluded.
+ outsetRect = IntRect(200 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom);
+ testRect = outsetRect;
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+
+ // Stuff outside the blur outsets is still occluded though.
+ testRect = outsetRect;
+ testRect.expand(1, 0);
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+ testRect = outsetRect;
+ testRect.expand(0, 1);
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+ testRect = outsetRect;
+ testRect.move(-1, 0);
+ testRect.expand(1, 0);
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+ testRect = outsetRect;
+ testRect.move(0, -1);
+ testRect.expand(0, 1);
+ EXPECT_EQ_RECT(outsetRect, occlusion.unoccludedContentRect(parent, testRect));
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix scaleByHalf;
+ scaleByHalf.scale(0.5);
+
+ // Makes two surfaces that completely cover |parent|. The occlusion both above and below the filters will be reduced by each of them.
+ typename Types::ContentLayerType* root = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(75, 75));
+ typename Types::LayerType* parent = this->createSurface(root, scaleByHalf, FloatPoint(0, 0), IntSize(150, 150));
+ parent->setMasksToBounds(true);
+ typename Types::LayerType* filteredSurface1 = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(0, 0), IntSize(300, 300), false);
+ typename Types::LayerType* filteredSurface2 = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(0, 0), IntSize(300, 300), false);
+ typename Types::LayerType* occludingLayerAbove = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 100), IntSize(50, 50), true);
+
+ // Filters make the layers own surfaces.
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(3, WebCore::Fixed), FilterOperation::BLUR));
+ filteredSurface1->setBackgroundFilters(filters);
+ filteredSurface2->setBackgroundFilters(filters);
+
+ // Save the distance of influence for the blur effect.
+ int outsetTop, outsetRight, outsetBottom, outsetLeft;
+ filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
- occlusion.enterTargetRenderSurface(parent->renderSurface());
- occlusion.markOccludedBehindLayer(layer.get());
+ this->calcDrawEtc(root);
- EXPECT_EQ_RECT(IntRect(250, 250, 50, 50), occlusion.occlusionInScreenSpace().bounds());
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(occludingLayerAbove, occlusion);
+ EXPECT_EQ_RECT(IntRect(100 / 2, 100 / 2, 50 / 2, 50 / 2), occlusion.occlusionInScreenSpace().bounds());
EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(100, 100, 50, 50), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+
+ this->visitLayer(filteredSurface2, occlusion);
+ this->visitContributingSurface(filteredSurface2, occlusion);
+ this->visitLayer(filteredSurface1, occlusion);
+ this->visitContributingSurface(filteredSurface1, occlusion);
+
+ ASSERT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ ASSERT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(0, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(100, 100, 100, 100)));
- EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(200, 200, 100, 100)));
+ // Test expectations in the target.
+ IntRect expectedOcclusion = IntRect(100 + outsetRight * 2, 100 + outsetBottom * 2, 50 - (outsetLeft + outsetRight) * 2, 50 - (outsetTop + outsetBottom) * 2);
+ EXPECT_EQ_RECT(expectedOcclusion, occlusion.occlusionInTargetSurface().rects()[0]);
+
+ // Test expectations in the screen. Take the ceiling of half of the outsets.
+ outsetTop = (outsetTop + 1) / 2;
+ outsetRight = (outsetRight + 1) / 2;
+ outsetBottom = (outsetBottom + 1) / 2;
+ outsetLeft = (outsetLeft + 1) / 2;
+ expectedOcclusion = IntRect(100 / 2 + outsetRight * 2, 100 / 2 + outsetBottom * 2, 50 / 2 - (outsetLeft + outsetRight) * 2, 50 /2 - (outsetTop + outsetBottom) * 2);
+
+ EXPECT_EQ_RECT(expectedOcclusion, occlusion.occlusionInScreenSpace().rects()[0]);
}
-}
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ // Make a surface and its replica, each 50x50, that are completely surrounded by opaque layers which are above them in the z-order.
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
+ // We stick the filtered surface inside a clipping surface so that we can make sure the clip is honored when exposing pixels for
+ // the background filter.
+ typename Types::LayerType* clippingSurface = this->createSurface(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 70));
+ clippingSurface->setMasksToBounds(true);
+ typename Types::LayerType* filteredSurface = this->createDrawingLayer(clippingSurface, this->identityMatrix, FloatPoint(50, 50), IntSize(50, 50), false);
+ this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(150, 0), IntSize());
+ typename Types::LayerType* occludingLayer1 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 50), true);
+ typename Types::LayerType* occludingLayer2 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 100), IntSize(300, 50), true);
+ typename Types::LayerType* occludingLayer3 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 50), IntSize(50, 50), true);
+ typename Types::LayerType* occludingLayer4 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(100, 50), IntSize(100, 50), true);
+ typename Types::LayerType* occludingLayer5 = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(250, 50), IntSize(50, 50), true);
+
+ // Filters make the layer own a surface. This filter is large enough that it goes outside the bottom of the clippingSurface.
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(12, WebCore::Fixed), FilterOperation::BLUR));
+ filteredSurface->setBackgroundFilters(filters);
+
+ // Save the distance of influence for the blur effect.
+ int outsetTop, outsetRight, outsetBottom, outsetLeft;
+ filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
+
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ // These layers occlude pixels directly beside the filteredSurface. Because filtered surface blends pixels in a radius, it will
+ // need to see some of the pixels (up to radius far) underneath the occludingLayers.
+ this->visitLayer(occludingLayer5, occlusion);
+ this->visitLayer(occludingLayer4, occlusion);
+ this->visitLayer(occludingLayer3, occlusion);
+ this->visitLayer(occludingLayer2, occlusion);
+ this->visitLayer(occludingLayer1, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // Everything outside the surface/replica is occluded but the surface/replica itself is not.
+ this->enterLayer(filteredSurface, occlusion);
+ EXPECT_EQ_RECT(IntRect(1, 0, 49, 50), occlusion.unoccludedContentRect(filteredSurface, IntRect(1, 0, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(0, 1, 50, 49), occlusion.unoccludedContentRect(filteredSurface, IntRect(0, 1, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(0, 0, 49, 50), occlusion.unoccludedContentRect(filteredSurface, IntRect(-1, 0, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(0, 0, 50, 49), occlusion.unoccludedContentRect(filteredSurface, IntRect(0, -1, 50, 50)));
+
+ EXPECT_EQ_RECT(IntRect(150 + 1, 0, 49, 50), occlusion.unoccludedContentRect(filteredSurface, IntRect(150 + 1, 0, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(150 + 0, 1, 50, 49), occlusion.unoccludedContentRect(filteredSurface, IntRect(150 + 0, 1, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(150 + 0, 0, 49, 50), occlusion.unoccludedContentRect(filteredSurface, IntRect(150 - 1, 0, 50, 50)));
+ EXPECT_EQ_RECT(IntRect(150 + 0, 0, 50, 49), occlusion.unoccludedContentRect(filteredSurface, IntRect(150 + 0, -1, 50, 50)));
+ this->leaveLayer(filteredSurface, occlusion);
+
+ // The filtered layer/replica does not occlude.
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // The surface has a background blur, so it needs pixels that are currently considered occluded in order to be drawn. So the pixels
+ // it needs should be removed some the occluded area so that when we get to the parent they are drawn.
+ this->visitContributingSurface(filteredSurface, occlusion);
+
+ this->enterContributingSurface(clippingSurface, occlusion);
+ EXPECT_EQ_RECT(IntRect(0, 0, 300, 150), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(5u, occlusion.occlusionInScreenSpace().rects().size());
+
+ IntRect outsetRect;
+ IntRect clippedOutsetRect;
+ IntRect testRect;
+
+ // Nothing in the (clipped) blur outsets for the filteredSurface is occluded.
+ outsetRect = IntRect(50 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom);
+ clippedOutsetRect = intersection(outsetRect, IntRect(0 - outsetLeft, 0 - outsetTop, 300 + outsetLeft + outsetRight, 70 + outsetTop + outsetBottom));
+ testRect = outsetRect;
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+
+ // Stuff outside the (clipped) blur outsets is still occluded though.
+ testRect = outsetRect;
+ testRect.expand(1, 0);
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+ testRect = outsetRect;
+ testRect.expand(0, 1);
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+ testRect = outsetRect;
+ testRect.move(-1, 0);
+ testRect.expand(1, 0);
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+ testRect = outsetRect;
+ testRect.move(0, -1);
+ testRect.expand(0, 1);
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+
+ // Nothing in the (clipped) blur outsets for the filteredSurface's replica is occluded.
+ outsetRect = IntRect(200 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom);
+ clippedOutsetRect = intersection(outsetRect, IntRect(0 - outsetLeft, 0 - outsetTop, 300 + outsetLeft + outsetRight, 70 + outsetTop + outsetBottom));
+ testRect = outsetRect;
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+
+ // Stuff outside the (clipped) blur outsets is still occluded though.
+ testRect = outsetRect;
+ testRect.expand(1, 0);
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+ testRect = outsetRect;
+ testRect.expand(0, 1);
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+ testRect = outsetRect;
+ testRect.move(-1, 0);
+ testRect.expand(1, 0);
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+ testRect = outsetRect;
+ testRect.move(0, -1);
+ testRect.expand(0, 1);
+ EXPECT_EQ_RECT(clippedOutsetRect, occlusion.unoccludedContentRect(clippingSurface, testRect));
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix scaleByHalf;
+ scaleByHalf.scale(0.5);
+
+ // Make a surface and its replica, each 50x50, with a smaller 30x30 layer centered below each.
+ // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface
+ // appears at 50, 50 and the replica at 200, 50.
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
+ typename Types::LayerType* behindSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(60, 60), IntSize(30, 30), true);
+ typename Types::LayerType* behindReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(210, 60), IntSize(30, 30), true);
+ typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(50, 50), IntSize(100, 100), false);
+ this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(300, 0), IntSize());
+
+ // Filters make the layer own a surface.
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(3, WebCore::Fixed), FilterOperation::BLUR));
+ filteredSurface->setBackgroundFilters(filters);
+
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ // The surface has a background blur, so it blurs non-opaque pixels below it.
+ this->visitLayer(filteredSurface, occlusion);
+ this->visitContributingSurface(filteredSurface, occlusion);
+
+ this->visitLayer(behindReplicaLayer, occlusion);
+ this->visitLayer(behindSurfaceLayer, occlusion);
+
+ // The layers behind the surface are not blurred, and their occlusion does not change, until we leave the surface.
+ // So it should not be modified by the filter here.
+ IntRect occlusionBehindSurface = IntRect(60, 60, 30, 30);
+ IntRect occlusionBehindReplica = IntRect(210, 60, 30, 30);
+
+ IntRect expectedOpaqueBounds = unionRect(occlusionBehindSurface, occlusionBehindReplica);
+ EXPECT_EQ_RECT(expectedOpaqueBounds, occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(expectedOpaqueBounds, occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix scaleByHalf;
+ scaleByHalf.scale(0.5);
+
+ // Make a surface and its replica, each 50x50, that are completely occluded by opaque layers which are above them in the z-order.
+ // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface
+ // appears at 50, 50 and the replica at 200, 50.
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
+ typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(50, 50), IntSize(100, 100), false);
+ this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(300, 0), IntSize());
+ typename Types::LayerType* aboveSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(50, 50), IntSize(50, 50), true);
+ typename Types::LayerType* aboveReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(200, 50), IntSize(50, 50), true);
+
+ // Filters make the layer own a surface.
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(3, WebCore::Fixed), FilterOperation::BLUR));
+ filteredSurface->setBackgroundFilters(filters);
+
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(aboveReplicaLayer, occlusion);
+ this->visitLayer(aboveSurfaceLayer, occlusion);
+
+ // The surface has a background blur, so it blurs non-opaque pixels below it.
+ this->visitLayer(filteredSurface, occlusion);
+ this->visitContributingSurface(filteredSurface, occlusion);
+
+ // The filter is completely occluded, so it should not blur anything and reduce any occlusion.
+ IntRect occlusionAboveSurface = IntRect(50, 50, 50, 50);
+ IntRect occlusionAboveReplica = IntRect(200, 50, 50, 50);
+
+ IntRect expectedOpaqueBounds = unionRect(occlusionAboveSurface, occlusionAboveReplica);
+ EXPECT_EQ_RECT(expectedOpaqueBounds, occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(expectedOpaqueBounds, occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size());
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix scaleByHalf;
+ scaleByHalf.scale(0.5);
+
+ // Make a surface and its replica, each 50x50, that are partially occluded by opaque layers which are above them in the z-order.
+ // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface
+ // appears at 50, 50 and the replica at 200, 50.
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 150));
+ typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, FloatPoint(50, 50), IntSize(100, 100), false);
+ this->createReplicaLayer(filteredSurface, this->identityMatrix, FloatPoint(300, 0), IntSize());
+ typename Types::LayerType* aboveSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(70, 50), IntSize(30, 50), true);
+ typename Types::LayerType* aboveReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(200, 50), IntSize(30, 50), true);
+ typename Types::LayerType* besideSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(90, 40), IntSize(10, 10), true);
+ typename Types::LayerType* besideReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(200, 40), IntSize(10, 10), true);
+
+ // Filters make the layer own a surface.
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(3, WebCore::Fixed), FilterOperation::BLUR));
+ filteredSurface->setBackgroundFilters(filters);
+
+ // Save the distance of influence for the blur effect.
+ int outsetTop, outsetRight, outsetBottom, outsetLeft;
+ filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
+
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+
+ this->visitLayer(besideReplicaLayer, occlusion);
+ this->visitLayer(besideSurfaceLayer, occlusion);
+ this->visitLayer(aboveReplicaLayer, occlusion);
+ this->visitLayer(aboveSurfaceLayer, occlusion);
+
+ // The surface has a background blur, so it blurs non-opaque pixels below it.
+ this->visitLayer(filteredSurface, occlusion);
+ this->visitContributingSurface(filteredSurface, occlusion);
+
+ // The filter in the surface and replica are partially unoccluded. Only the unoccluded parts should reduce occlusion.
+ // This means it will push back the occlusion that touches the unoccluded part (occlusionAbove___), but it will not
+ // touch occlusionBeside____ since that is not beside the unoccluded part of the surface, even though it is beside
+ // the occluded part of the surface.
+ IntRect occlusionAboveSurface = IntRect(70 + outsetRight, 50, 30 - outsetRight, 50);
+ IntRect occlusionAboveReplica = IntRect(200, 50, 30 - outsetLeft, 50);
+ IntRect occlusionBesideSurface = IntRect(90, 40, 10, 10);
+ IntRect occlusionBesideReplica = IntRect(200, 40, 10, 10);
+
+ Region expectedOcclusion;
+ expectedOcclusion.unite(occlusionAboveSurface);
+ expectedOcclusion.unite(occlusionAboveReplica);
+ expectedOcclusion.unite(occlusionBesideSurface);
+ expectedOcclusion.unite(occlusionBesideReplica);
+
+ ASSERT_EQ(expectedOcclusion.rects().size(), occlusion.occlusionInTargetSurface().rects().size());
+ ASSERT_EQ(expectedOcclusion.rects().size(), occlusion.occlusionInScreenSpace().rects().size());
+
+ for (size_t i = 0; i < expectedOcclusion.rects().size(); ++i) {
+ IntRect expectedRect = expectedOcclusion.rects()[i];
+ IntRect screenRect = occlusion.occlusionInScreenSpace().rects()[i];
+ IntRect targetRect = occlusion.occlusionInTargetSurface().rects()[i];
+ EXPECT_EQ(expectedRect, screenRect);
+ EXPECT_EQ(expectedRect, targetRect);
+ }
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestMinimumTrackingSize : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ IntSize trackingSize(100, 100);
+ IntSize belowTrackingSize(99, 99);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(400, 400));
+ typename Types::LayerType* large = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), trackingSize, true);
+ typename Types::LayerType* small = this->createDrawingLayer(parent, this->identityMatrix, FloatPoint(0, 0), belowTrackingSize, true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+ occlusion.setMinimumTrackingSize(trackingSize);
+
+ // The small layer is not tracked because it is too small.
+ this->visitLayer(small, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+
+ // The large layer is tracked as it is large enough.
+ this->visitLayer(large, occlusion);
+
+ EXPECT_EQ_RECT(IntRect(IntPoint(), trackingSize), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(IntPoint(), trackingSize), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ }
+};
+
+ALL_CCOCCLUSIONTRACKER_TEST(CCOcclusionTrackerTestMinimumTrackingSize);
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCOcclusionTrackerTestCommon.h b/Source/WebKit/chromium/tests/CCOcclusionTrackerTestCommon.h
new file mode 100644
index 000000000..fcdc3ed6c
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCOcclusionTrackerTestCommon.h
@@ -0,0 +1,57 @@
+/*
+ * 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 CCOcclusionTrackerTestCommon_h
+#define CCOcclusionTrackerTestCommon_h
+
+#include "IntRect.h"
+#include "Region.h"
+#include "RenderSurfaceChromium.h"
+#include "cc/CCOcclusionTracker.h"
+#include "cc/CCRenderSurface.h"
+
+namespace WebKitTests {
+
+// A subclass to expose the total current occlusion.
+template<typename LayerType, typename RenderSurfaceType>
+class TestCCOcclusionTrackerBase : public WebCore::CCOcclusionTrackerBase<LayerType, RenderSurfaceType> {
+public:
+ TestCCOcclusionTrackerBase(WebCore::IntRect screenScissorRect, bool recordMetricsForFrame = false)
+ : WebCore::CCOcclusionTrackerBase<LayerType, RenderSurfaceType>(screenScissorRect, recordMetricsForFrame)
+ {
+ }
+
+ WebCore::Region occlusionInScreenSpace() const { return WebCore::CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::m_stack.last().occlusionInScreen; }
+ WebCore::Region occlusionInTargetSurface() const { return WebCore::CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::m_stack.last().occlusionInTarget; }
+
+ void setOcclusionInScreenSpace(const WebCore::Region& region) { WebCore::CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::m_stack.last().occlusionInScreen = region; }
+ void setOcclusionInTargetSurface(const WebCore::Region& region) { WebCore::CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::m_stack.last().occlusionInTarget = region; }
+};
+
+typedef TestCCOcclusionTrackerBase<WebCore::LayerChromium, WebCore::RenderSurfaceChromium> TestCCOcclusionTracker;
+typedef TestCCOcclusionTrackerBase<WebCore::CCLayerImpl, WebCore::CCRenderSurface> TestCCOcclusionTrackerImpl;
+
+}
+
+#endif // CCOcclusionTrackerTestCommon_h
diff --git a/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp b/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
index 42776bc94..991cddc46 100644
--- a/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
@@ -26,6 +26,10 @@
#include "cc/CCQuadCuller.h"
+#include "cc/CCOcclusionTracker.h"
+#include "cc/CCOverdrawMetrics.h"
+#include "cc/CCSingleThreadProxy.h"
+#include "cc/CCTiledLayerImpl.h"
#include "cc/CCTileDrawQuad.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -34,89 +38,145 @@ using namespace WebCore;
namespace {
-class CCQuadCullerTest : public testing::Test {
+class TestCCOcclusionTrackerImpl : public CCOcclusionTrackerImpl {
+public:
+ TestCCOcclusionTrackerImpl(const IntRect& scissorRectInScreen, bool recordMetricsForFrame = true)
+ : CCOcclusionTrackerImpl(scissorRectInScreen, recordMetricsForFrame)
+ , m_scissorRectInScreen(scissorRectInScreen)
+ {
+ }
+
+protected:
+ virtual IntRect layerScissorRectInTargetSurface(const CCLayerImpl* layer) const { return m_scissorRectInScreen; }
+
+private:
+ IntRect m_scissorRectInScreen;
};
-static PassOwnPtr<CCDrawQuad> MakeTileQuad(CCSharedQuadState* state, const IntRect& rect, const IntRect& opaqueRect = IntRect())
+typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
+
+static PassOwnPtr<CCTiledLayerImpl> makeLayer(CCTiledLayerImpl* parent, const TransformationMatrix& drawTransform, const IntRect& layerRect, float opacity, bool opaque, const IntRect& layerOpaqueRect, Vector<CCLayerImpl*>& surfaceLayerList)
{
- return CCTileDrawQuad::create(state, rect, intersection(rect, opaqueRect), 1, IntPoint(1, 1), IntSize(100, 100), 0, false, false, false, false, false);
+ OwnPtr<CCTiledLayerImpl> layer = CCTiledLayerImpl::create(0);
+ OwnPtr<CCLayerTilingData> tiler = CCLayerTilingData::create(IntSize(100, 100), CCLayerTilingData::NoBorderTexels);
+ tiler->setBounds(layerRect.size());
+ layer->setTilingData(*tiler);
+ layer->setSkipsDraw(false);
+ layer->setDrawTransform(drawTransform);
+ layer->setScreenSpaceTransform(drawTransform);
+ layer->setVisibleLayerRect(layerRect);
+ layer->setDrawOpacity(opacity);
+ layer->setOpaque(opaque);
+
+ int textureId = 1;
+ for (int i = 0; i < tiler->numTilesX(); ++i)
+ for (int j = 0; j < tiler->numTilesY(); ++j) {
+ IntRect tileOpaqueRect = opaque ? tiler->tileBounds(i, j) : intersection(tiler->tileBounds(i, j), layerOpaqueRect);
+ layer->pushTileProperties(i, j, static_cast<Platform3DObject>(textureId++), tileOpaqueRect);
+ }
+
+ if (!parent) {
+ layer->createRenderSurface();
+ layer->setTargetRenderSurface(layer->renderSurface());
+ surfaceLayerList.append(layer.get());
+ layer->renderSurface()->layerList().append(layer.get());
+ } else {
+ layer->setTargetRenderSurface(parent->targetRenderSurface());
+ parent->renderSurface()->layerList().append(layer.get());
+ }
+
+ return layer.release();
}
-void setQuads(CCSharedQuadState* rootState, CCSharedQuadState* childState, CCQuadList& quadList, const IntRect& opaqueRect = IntRect())
+static void appendQuads(CCQuadList& quadList, Vector<OwnPtr<CCSharedQuadState> >& sharedStateList, CCTiledLayerImpl* layer, CCLayerIteratorType& it, CCOcclusionTrackerImpl& occlusionTracker)
{
- quadList.clear();
-
- 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));
+ occlusionTracker.enterLayer(it);
+ CCQuadCuller quadCuller(quadList, layer, &occlusionTracker);
+ OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
+ sharedStateList.append(sharedQuadState.release());
+ occlusionTracker.leaveLayer(it);
+ ++it;
}
#define DECLARE_AND_INITIALIZE_TEST_QUADS \
+ DebugScopedSetImplThread impl; \
CCQuadList quadList; \
- CCOverdrawCounts overdraw; \
+ Vector<OwnPtr<CCSharedQuadState> > sharedStateList; \
+ Vector<CCLayerImpl*> renderSurfaceLayerList; \
TransformationMatrix childTransform; \
IntSize rootSize = IntSize(300, 300); \
IntRect rootRect = IntRect(IntPoint(), rootSize); \
IntSize childSize = IntSize(200, 200); \
IntRect childRect = IntRect(IntPoint(), childSize);
-TEST(CCQuadCullerTest, verifyCullChildLinesUpTopLeft)
+TEST(CCQuadCullerTest, verifyNoCulling)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), TransformationMatrix(), childRect, 1.0, false, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 90000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 40000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 0, 1);
+}
+
+TEST(CCQuadCullerTest, verifyCullChildLinesUpTopLeft)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), TransformationMatrix(), childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
+
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 9u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 90000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 40000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 90000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 40000, 1);
}
TEST(CCQuadCullerTest, verifyCullWhenChildOpacityNotOne)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 0.9, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 0.9f, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
- EXPECT_EQ(quadList.size(), 13u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 90000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 40000, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 90000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 40000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 0, 1);
}
TEST(CCQuadCullerTest, verifyCullWhenChildOpaqueFlagFalse)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, false);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, false, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 13u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 90000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 40000, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 90000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 40000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 0, 1);
}
TEST(CCQuadCullerTest, verifyCullCenterTileOnly)
@@ -125,32 +185,33 @@ TEST(CCQuadCullerTest, verifyCullCenterTileOnly)
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, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 12u);
- IntRect quadVisibleRect1 = quadList[1].get()->quadVisibleRect();
+ IntRect quadVisibleRect1 = quadList[5].get()->quadVisibleRect();
EXPECT_EQ(quadVisibleRect1.height(), 50);
- IntRect quadVisibleRect3 = quadList[3].get()->quadVisibleRect();
+ IntRect quadVisibleRect3 = quadList[7].get()->quadVisibleRect();
EXPECT_EQ(quadVisibleRect3.width(), 50);
- // Next index is 4, not 5, since centre quad culled.
- IntRect quadVisibleRect4 = quadList[4].get()->quadVisibleRect();
+ // Next index is 8, not 9, since centre quad culled.
+ IntRect quadVisibleRect4 = quadList[8].get()->quadVisibleRect();
EXPECT_EQ(quadVisibleRect4.width(), 50);
EXPECT_EQ(quadVisibleRect4.x(), 250);
- IntRect quadVisibleRect6 = quadList[6].get()->quadVisibleRect();
+ IntRect quadVisibleRect6 = quadList[10].get()->quadVisibleRect();
EXPECT_EQ(quadVisibleRect6.height(), 50);
EXPECT_EQ(quadVisibleRect6.y(), 250);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 100000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 30000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 100000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 30000, 1);
}
TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize1)
@@ -159,32 +220,33 @@ TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize1)
childTransform.translate(100, 100);
- // Create root layer tile with extent (99.1, 99.1) -> (200.9, 200.9) to make
+ // Make the root layer's quad have 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);
+ rootRect = childRect = IntRect(0, 0, 100, 100);
- quadList.append(MakeTileQuad(rootState.get(), IntRect(IntPoint(), IntSize(100, 100))));
- quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, rootTransform, rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- EXPECT_EQ(quadList.size(), 2u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 2u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 20363, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 20363, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 0, 1);
}
TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize2)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
- // Make the child quad slightly smaller than, and centred over, the root layer tile.
+ // Make the child's 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);
@@ -192,19 +254,20 @@ TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize2)
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);
+ rootRect = childRect = IntRect(0, 0, 100, 100);
- quadList.append(MakeTileQuad(rootState.get(), IntRect(IntPoint(), IntSize(100, 100))));
- quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, rootTransform, rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- EXPECT_EQ(quadList.size(), 2u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 2u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 19643, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 19643, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 0, 1);
}
TEST(CCQuadCullerTest, verifyCullChildLinesUpBottomRight)
@@ -213,16 +276,17 @@ TEST(CCQuadCullerTest, verifyCullChildLinesUpBottomRight)
childTransform.translate(100, 100);
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 9u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 90000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 40000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 90000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 40000, 1);
}
TEST(CCQuadCullerTest, verifyCullSubRegion)
@@ -231,17 +295,18 @@ TEST(CCQuadCullerTest, verifyCullSubRegion)
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);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
IntRect childOpaqueRect(childRect.x() + childRect.width() / 4, childRect.y() + childRect.height() / 4, childRect.width() / 2, childRect.height() / 2);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, false, childOpaqueRect, renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 12u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 90000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 30000, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 10000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 90000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 30000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 10000, 1);
}
TEST(CCQuadCullerTest, verifyCullSubRegion2)
@@ -250,17 +315,18 @@ TEST(CCQuadCullerTest, verifyCullSubRegion2)
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);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
IntRect childOpaqueRect(childRect.x() + childRect.width() / 4, childRect.y() + childRect.height() / 4, childRect.width() / 2, childRect.height() * 3 / 4);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, false, childOpaqueRect, renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 12u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 90000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 25000, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 15000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 90000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 25000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 15000, 1);
}
TEST(CCQuadCullerTest, verifyCullSubRegionCheckOvercull)
@@ -269,14 +335,18 @@ TEST(CCQuadCullerTest, verifyCullSubRegionCheckOvercull)
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);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
IntRect childOpaqueRect(childRect.x() + childRect.width() / 4, childRect.y() + childRect.height() / 4, childRect.width() / 2, childRect.height() / 2);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, false, childOpaqueRect, renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 13u);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 90000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 30000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 10000, 1);
}
TEST(CCQuadCullerTest, verifyNonAxisAlignedQuadsDontOcclude)
@@ -286,16 +356,17 @@ TEST(CCQuadCullerTest, verifyNonAxisAlignedQuadsDontOcclude)
// Use a small rotation so as to not disturb the geometry significantly.
childTransform.rotate(1);
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), childTransform, childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 13u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 130000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 130000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 0, 1);
}
// This test requires some explanation: here we are rotating the quads to be culled.
@@ -311,74 +382,102 @@ TEST(CCQuadCullerTest, verifyNonAxisAlignedQuadsSafelyCulled)
TransformationMatrix parentTransform;
parentTransform.rotate(1);
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(parentTransform, TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), childRect, IntRect(), 1.0, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, parentTransform, rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), TransformationMatrix(), childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(-100, -100, 1000, 1000));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, false, IntRect(), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 12u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 120000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 10000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 100600, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 29400, 1);
}
TEST(CCQuadCullerTest, verifyCullOutsideScissorOverTile)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), TransformationMatrix(), childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(200, 100, 100, 100));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(200, 100, 100, 100), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 1u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 10000, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 120000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 10000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 120000, 1);
}
TEST(CCQuadCullerTest, verifyCullOutsideScissorOverCulledTile)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), TransformationMatrix(), childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(100, 100, 100, 100));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(100, 100, 100, 100), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 1u);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 10000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 120000, 1);
}
TEST(CCQuadCullerTest, verifyCullOutsideScissorOverPartialTiles)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), TransformationMatrix(), childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(50, 50, 200, 200));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(50, 50, 200, 200), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 9u);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 40000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 90000, 1);
}
TEST(CCQuadCullerTest, verifyCullOutsideScissorOverNoTiles)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
- OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true);
- OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), TransformationMatrix(), childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(500, 500, 100, 100));
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
- setQuads(rootState.get(), childState.get(), quadList);
- EXPECT_EQ(quadList.size(), 13u);
- CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(500, 500, 100, 100), &overdraw);
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
EXPECT_EQ(quadList.size(), 0u);
- EXPECT_NEAR(overdraw.m_pixelsDrawnOpaque, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsDrawnTransparent, 0, 1);
- EXPECT_NEAR(overdraw.m_pixelsCulled, 130000, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 130000, 1);
+}
+
+TEST(CCQuadCullerTest, verifyWithoutMetrics)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ OwnPtr<CCTiledLayerImpl> rootLayer = makeLayer(0, TransformationMatrix(), rootRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ OwnPtr<CCTiledLayerImpl> childLayer = makeLayer(rootLayer.get(), TransformationMatrix(), childRect, 1.0, true, IntRect(), renderSurfaceLayerList);
+ TestCCOcclusionTrackerImpl occlusionTracker(IntRect(50, 50, 200, 200), false);
+ CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList);
+
+ appendQuads(quadList, sharedStateList, childLayer.get(), it, occlusionTracker);
+ appendQuads(quadList, sharedStateList, rootLayer.get(), it, occlusionTracker);
+ EXPECT_EQ(quadList.size(), 9u);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsDrawnTranslucent(), 0, 1);
+ EXPECT_NEAR(occlusionTracker.overdrawMetrics().pixelsCulledForDrawing(), 0, 1);
}
diff --git a/Source/WebKit/chromium/tests/CCRenderSurfaceTest.cpp b/Source/WebKit/chromium/tests/CCRenderSurfaceTest.cpp
index 1201587c7..7dac005d2 100644
--- a/Source/WebKit/chromium/tests/CCRenderSurfaceTest.cpp
+++ b/Source/WebKit/chromium/tests/CCRenderSurfaceTest.cpp
@@ -26,7 +26,9 @@
#include "cc/CCRenderSurface.h"
+#include "TransformationMatrix.h"
#include "cc/CCLayerImpl.h"
+#include "cc/CCSharedQuadState.h"
#include "cc/CCSingleThreadProxy.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -89,4 +91,38 @@ TEST(CCRenderSurfaceTest, verifySurfaceChangesAreTrackedProperly)
EXECUTE_AND_VERIFY_SURFACE_DID_NOT_CHANGE(renderSurface->setMaskLayer(dummyMask.get()));
}
+TEST(CCRenderSurfaceTest, sanityCheckSurfaceCreatesCorrectSharedQuadState)
+{
+ // This will fake that we are on the correct thread for testing purposes.
+ DebugScopedSetImplThread setImplThread;
+
+ OwnPtr<CCLayerImpl> owningLayer = CCLayerImpl::create(0);
+ owningLayer->createRenderSurface();
+ ASSERT_TRUE(owningLayer->renderSurface());
+ CCRenderSurface* renderSurface = owningLayer->renderSurface();
+
+ IntRect contentRect = IntRect(IntPoint::zero(), IntSize(50, 50));
+ IntRect clipRect = IntRect(IntPoint(5, 5), IntSize(40, 40));
+ TransformationMatrix draw;
+ TransformationMatrix origin;
+
+ draw.translate(30, 40);
+
+ renderSurface->setDrawTransform(draw);
+ renderSurface->setOriginTransform(origin);
+ renderSurface->setContentRect(contentRect);
+ renderSurface->setClipRect(clipRect);
+ renderSurface->setDrawOpacity(1);
+
+ OwnPtr<CCSharedQuadState> sharedQuadState = renderSurface->createSharedQuadState();
+
+ EXPECT_TRUE(sharedQuadState->quadTransform().isIdentity());
+ EXPECT_EQ(30, sharedQuadState->layerTransform().m41());
+ EXPECT_EQ(40, sharedQuadState->layerTransform().m42());
+ EXPECT_EQ(contentRect, sharedQuadState->layerRect());
+ EXPECT_EQ(clipRect, sharedQuadState->clipRect());
+ EXPECT_EQ(1, sharedQuadState->opacity());
+ EXPECT_FALSE(sharedQuadState->isOpaque());
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp b/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp
index 0853e5a36..2731c76fd 100644
--- a/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp
+++ b/Source/WebKit/chromium/tests/CCSchedulerStateMachineTest.cpp
@@ -52,6 +52,9 @@ public:
void setNeedsCommit(bool b) { m_needsCommit = b; }
bool needsCommit() const { return m_needsCommit; }
+ void setNeedsForcedCommit(bool b) { m_needsForcedCommit = b; }
+ bool needsForcedCommit() const { return m_needsForcedCommit; }
+
void setNeedsRedraw(bool b) { m_needsRedraw = b; }
bool needsRedraw() const { return m_needsRedraw; }
@@ -72,6 +75,7 @@ TEST(CCSchedulerStateMachineTest, TestNextActionBeginsFrameIfNeeded)
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.setCanBeginFrame(true);
state.setNeedsRedraw(false);
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(false);
@@ -86,10 +90,30 @@ TEST(CCSchedulerStateMachineTest, TestNextActionBeginsFrameIfNeeded)
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
+ // If commit requested but canBeginFrame is still false, do nothing.
+ {
+ StateMachine state;
+ state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.setNeedsRedraw(false);
+ state.setNeedsCommit(false);
+ 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());
+ }
+
+
// If commit requested, begin a frame
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.setCanBeginFrame(true);
state.setNeedsRedraw(false);
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(false);
@@ -100,6 +124,7 @@ TEST(CCSchedulerStateMachineTest, TestNextActionBeginsFrameIfNeeded)
// Begin the frame, make sure needsCommit and commitState update correctly.
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setVisible(true);
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, state.commitState());
@@ -116,6 +141,180 @@ TEST(CCSchedulerStateMachineTest, TestSetForcedRedrawDoesNotSetsNormalRedraw)
EXPECT_TRUE(state.vsyncCallbackNeeded());
}
+TEST(CCSchedulerStateMachineTest, TestFailedDrawSetsNeedsCommitAndDoesNotDrawAgain)
+{
+ CCSchedulerStateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(true);
+ state.setNeedsRedraw();
+ EXPECT_TRUE(state.redrawPending());
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+ state.didEnterVSync();
+
+ // We're drawing now.
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ EXPECT_FALSE(state.redrawPending());
+ EXPECT_FALSE(state.commitPending());
+
+ // Failing the draw makes us require a commit.
+ state.didDrawIfPossibleCompleted(false);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
+ EXPECT_TRUE(state.redrawPending());
+ EXPECT_TRUE(state.commitPending());
+}
+
+TEST(CCSchedulerStateMachineTest, TestSetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw)
+{
+ CCSchedulerStateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(true);
+ state.setNeedsRedraw();
+ EXPECT_TRUE(state.redrawPending());
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+ state.didEnterVSync();
+
+ // We're drawing now.
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ EXPECT_FALSE(state.redrawPending());
+ EXPECT_FALSE(state.commitPending());
+
+ // While still in the same vsync callback, set needs redraw again.
+ // This should not redraw.
+ state.setNeedsRedraw();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+
+ // Failing the draw makes us require a commit.
+ state.didDrawIfPossibleCompleted(false);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+ EXPECT_TRUE(state.redrawPending());
+}
+
+TEST(CCSchedulerStateMachineTest, TestCommitAfterFailedDrawAllowsDrawInSameFrame)
+{
+ CCSchedulerStateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(true);
+
+ // Start a commit.
+ state.setNeedsCommit();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
+ EXPECT_TRUE(state.commitPending());
+
+ // Then initiate a draw.
+ state.setNeedsRedraw();
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+ state.didEnterVSync();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ EXPECT_TRUE(state.redrawPending());
+
+ // Fail the draw.
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ state.didDrawIfPossibleCompleted(false);
+ EXPECT_TRUE(state.redrawPending());
+ // But the commit is ongoing.
+ EXPECT_TRUE(state.commitPending());
+
+ // Finish the commit.
+ state.beginFrameComplete();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
+ state.beginUpdateMoreResourcesComplete(false);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_TRUE(state.redrawPending());
+
+ // And we should be allowed to draw again.
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+}
+
+TEST(CCSchedulerStateMachineTest, TestCommitAfterFailedAndSuccessfulDrawDoesNotAllowDrawInSameFrame)
+{
+ CCSchedulerStateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(true);
+
+ // Start a commit.
+ state.setNeedsCommit();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
+ EXPECT_TRUE(state.commitPending());
+
+ // Then initiate a draw.
+ state.setNeedsRedraw();
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+ state.didEnterVSync();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ EXPECT_TRUE(state.redrawPending());
+
+ // Fail the draw.
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ state.didDrawIfPossibleCompleted(false);
+ EXPECT_TRUE(state.redrawPending());
+ // But the commit is ongoing.
+ EXPECT_TRUE(state.commitPending());
+
+ // Force a draw.
+ state.setNeedsForcedRedraw();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_FORCED, state.nextAction());
+
+ // Do the forced draw.
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_FORCED);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ EXPECT_FALSE(state.redrawPending());
+ // And the commit is still ongoing.
+ EXPECT_TRUE(state.commitPending());
+
+ // Finish the commit.
+ state.beginFrameComplete();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
+ state.beginUpdateMoreResourcesComplete(false);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_TRUE(state.redrawPending());
+
+ // And we should not be allowed to draw again in the same frame..
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+}
+
+TEST(CCSchedulerStateMachineTest, TestFailedDrawIsRetriedNextVSync)
+{
+ CCSchedulerStateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(true);
+
+ // Start a draw.
+ state.setNeedsRedraw();
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+ state.didEnterVSync();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ EXPECT_TRUE(state.redrawPending());
+
+ // Fail the draw.
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ state.didDrawIfPossibleCompleted(false);
+ EXPECT_TRUE(state.redrawPending());
+
+ // We should not be trying to draw again now, but we have a commit pending.
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+
+ state.didLeaveVSync();
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+ state.didEnterVSync();
+
+ // We should try draw again in the next vsync.
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+}
+
TEST(CCSchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame)
{
CCSchedulerStateMachine state;
@@ -123,8 +322,8 @@ TEST(CCSchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame)
state.setNeedsRedraw();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
- state.updateState(CCSchedulerStateMachine::ACTION_DRAW);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
// While still in the same vsync callback, set needs redraw again.
// This should not redraw.
@@ -132,12 +331,14 @@ TEST(CCSchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame)
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
// Move to another frame. This should now draw.
+ state.didDrawIfPossibleCompleted(true);
state.didLeaveVSync();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
- state.updateState(CCSchedulerStateMachine::ACTION_DRAW);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ state.didDrawIfPossibleCompleted(true);
EXPECT_FALSE(state.vsyncCallbackNeeded());
}
@@ -156,31 +357,13 @@ TEST(CCSchedulerStateMachineTest, TestNextActionDrawsOnVSync)
} 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.
+ // Case 1: needsCommit=false
state.setNeedsCommit(false);
- state.setUpdateMoreResourcesPending(true);
- if (visible)
- EXPECT_TRUE(state.vsyncCallbackNeeded());
- EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
- // Case 3: needsCommit=true updateMoreResourcesPending=false.
+ // Case 2: needsCommit=true
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());
+ EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
}
}
@@ -189,7 +372,8 @@ TEST(CCSchedulerStateMachineTest, TestNextActionDrawsOnVSync)
for (unsigned j = 0; j < 2; ++j) {
StateMachine state;
state.setCommitState(allCommitStates[i]);
- if (!j) {
+ bool forcedDraw = j;
+ if (!forcedDraw) {
state.didEnterVSync();
state.setNeedsRedraw(true);
state.setVisible(true);
@@ -198,7 +382,7 @@ TEST(CCSchedulerStateMachineTest, TestNextActionDrawsOnVSync)
CCSchedulerStateMachine::Action expectedAction;
if (allCommitStates[i] != CCSchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT)
- expectedAction = CCSchedulerStateMachine::ACTION_DRAW;
+ expectedAction = forcedDraw ? CCSchedulerStateMachine::ACTION_DRAW_FORCED : CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE;
else
expectedAction = CCSchedulerStateMachine::ACTION_COMMIT;
@@ -246,22 +430,22 @@ TEST(CCSchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible)
// Case 1: needsCommit=false updateMoreResourcesPending=false.
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(false);
- EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
// Case 2: needsCommit=false updateMoreResourcesPending=true.
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(true);
- EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
// Case 3: needsCommit=true updateMoreResourcesPending=false.
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(false);
- EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
// Case 4: needsCommit=true updateMoreResourcesPending=true.
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(true);
- EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
}
}
}
@@ -281,7 +465,7 @@ TEST(CCSchedulerStateMachineTest, TestCanRedraw_StopsDraw)
state.didEnterVSync();
state.setCanDraw(false);
- EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
}
}
}
@@ -290,6 +474,7 @@ TEST(CCSchedulerStateMachineTest, TestCanRedrawWithWaitingForFirstDrawMakesProgr
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
+ state.setCanBeginFrame(true);
state.setNeedsCommit(true);
state.setNeedsRedraw(true);
state.setUpdateMoreResourcesPending(false);
@@ -368,6 +553,20 @@ TEST(CCSchedulerStateMachineTest, TestUpdates_NoRedraw_TwoRoundsOfUpdates)
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
}
+
+TEST(CCSchedulerStateMachineTest, TestVSyncNeededWhenUpdatesPendingButInvisible)
+{
+ StateMachine state;
+ state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES);
+ state.setNeedsRedraw(false);
+ state.setVisible(false);
+ state.setUpdateMoreResourcesPending(true);
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+
+ state.setUpdateMoreResourcesPending(false);
+ EXPECT_TRUE(state.vsyncCallbackNeeded());
+}
+
TEST(CCSchedulerStateMachineTest, TestUpdates_WithRedraw_OneRoundOfUpdates)
{
StateMachine state;
@@ -382,8 +581,9 @@ TEST(CCSchedulerStateMachineTest, TestUpdates_WithRedraw_OneRoundOfUpdates)
// Ensure we draw on the next vsync even though an update is in-progress.
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
- state.updateState(CCSchedulerStateMachine::ACTION_DRAW);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ state.didDrawIfPossibleCompleted(true);
// Ensure that we once we have drawn, we dont do anything else.
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
@@ -418,6 +618,7 @@ TEST(CCSchedulerStateMachineTest, TestUpdates_WithRedraw_OneRoundOfUpdates)
TEST(CCSchedulerStateMachineTest, TestSetNeedsCommitIsNotLost)
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setNeedsCommit(true);
state.setVisible(true);
@@ -447,9 +648,10 @@ TEST(CCSchedulerStateMachineTest, TestSetNeedsCommitIsNotLost)
// Commit and make sure we draw on next vsync
state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, state.commitState());
- state.updateState(CCSchedulerStateMachine::ACTION_DRAW);
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ state.didDrawIfPossibleCompleted(true);
// Verify that another commit will begin.
state.didLeaveVSync();
@@ -459,6 +661,7 @@ TEST(CCSchedulerStateMachineTest, TestSetNeedsCommitIsNotLost)
TEST(CCSchedulerStateMachineTest, TestFullCycle)
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setVisible(true);
// Start clean and set commit.
@@ -492,8 +695,9 @@ TEST(CCSchedulerStateMachineTest, TestFullCycle)
// At vsync, draw.
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
- state.updateState(CCSchedulerStateMachine::ACTION_DRAW);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ state.didDrawIfPossibleCompleted(true);
state.didLeaveVSync();
// Should be synchronized, no draw needed, no action needed.
@@ -505,6 +709,7 @@ TEST(CCSchedulerStateMachineTest, TestFullCycle)
TEST(CCSchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween)
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setVisible(true);
// Start clean and set commit.
@@ -542,8 +747,9 @@ TEST(CCSchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween)
// At vsync, draw.
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
- state.updateState(CCSchedulerStateMachine::ACTION_DRAW);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
+ state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
+ state.didDrawIfPossibleCompleted(true);
state.didLeaveVSync();
// Should be synchronized, no draw needed, no action needed.
@@ -562,6 +768,7 @@ TEST(CCSchedulerStateMachineTest, TestRequestCommitInvisible)
TEST(CCSchedulerStateMachineTest, TestGoesInvisibleMidCommit)
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setVisible(true);
// Start clean and set commit.
@@ -607,6 +814,7 @@ TEST(CCSchedulerStateMachineTest, TestGoesInvisibleMidCommit)
TEST(CCSchedulerStateMachineTest, TestContextLostWhenCompletelyIdle)
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setVisible(true);
state.didLoseContext();
@@ -628,6 +836,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhenCompletelyIdle)
TEST(CCSchedulerStateMachineTest, TestContextLostWhenIdleAndCommitRequestedWhileRecreating)
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setVisible(true);
state.didLoseContext();
@@ -653,7 +862,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhenIdleAndCommitRequestedWhile
// setCanDraw.
state.setNeedsRedraw(true);
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.setCanDraw(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.setCanDraw(true);
@@ -663,6 +872,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhenIdleAndCommitRequestedWhile
TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgress)
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setVisible(true);
// Get a commit in flight.
@@ -673,7 +883,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgress)
// Set damage and expect a draw.
state.setNeedsRedraw(true);
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(state.nextAction());
state.didLeaveVSync();
@@ -703,6 +913,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgress)
TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgressAndAnotherCommitRequested)
{
StateMachine state;
+ state.setCanBeginFrame(true);
state.setVisible(true);
// Get a commit in flight.
@@ -713,7 +924,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgressAndAnother
// Set damage and expect a draw.
state.setNeedsRedraw(true);
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(state.nextAction());
state.didLeaveVSync();
@@ -739,7 +950,7 @@ TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgressAndAnother
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, state.commitState());
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(state.nextAction());
// Expect to be told to begin context recreation, independent of vsync state
@@ -761,7 +972,7 @@ TEST(CCSchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost)
// Ask a forced redraw and verify it ocurrs.
state.setNeedsForcedRedraw(true);
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_FORCED, state.nextAction());
state.didLeaveVSync();
// Clear the forced redraw bit.
@@ -774,8 +985,60 @@ TEST(CCSchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost)
// Ask a forced redraw and verify it ocurrs.
state.setNeedsForcedRedraw(true);
state.didEnterVSync();
- EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW, state.nextAction());
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_FORCED, state.nextAction());
state.didLeaveVSync();
}
+TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenInvisibleAndForceCommit)
+{
+ StateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(false);
+ state.setNeedsCommit(true);
+ state.setNeedsForcedCommit(true);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+}
+
+TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenCanBeginFrameFalseAndForceCommit)
+{
+ StateMachine state;
+ state.setVisible(true);
+ state.setNeedsCommit(true);
+ state.setNeedsForcedCommit(true);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+}
+
+TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenCommitInProgress)
+{
+ StateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(false);
+ state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS);
+ state.setNeedsCommit(true);
+ state.setNeedsForcedCommit(true);
+
+ state.beginFrameComplete();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
+ state.updateState(state.nextAction());
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
+ state.beginUpdateMoreResourcesComplete(false);
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
+ state.updateState(state.nextAction());
+
+ EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_IDLE, state.commitState());
+
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+}
+
+TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenContextLost)
+{
+ StateMachine state;
+ state.setCanBeginFrame(true);
+ state.setVisible(true);
+ state.setNeedsCommit(true);
+ state.setNeedsForcedCommit(true);
+ state.didLoseContext();
+ EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
+}
+
}
diff --git a/Source/WebKit/chromium/tests/CCSchedulerTest.cpp b/Source/WebKit/chromium/tests/CCSchedulerTest.cpp
index 45f61b90b..41250884b 100644
--- a/Source/WebKit/chromium/tests/CCSchedulerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCSchedulerTest.cpp
@@ -45,25 +45,56 @@ public:
m_actions.clear();
m_hasMoreResourceUpdates = false;
m_canDraw = true;
+ m_drawWillHappen = true;
+ m_swapWillHappenIfDrawHappens = true;
+ m_numDraws = 0;
}
void setHasMoreResourceUpdates(bool b) { m_hasMoreResourceUpdates = b; }
void setCanDraw(bool b) { m_canDraw = b; }
+ int numDraws() const { return m_numDraws; }
int numActions() const { return static_cast<int>(m_actions.size()); }
const char* action(int i) const { return m_actions[i]; }
- virtual bool canDraw() { return m_canDraw; }
- virtual bool hasMoreResourceUpdates() const { return m_hasMoreResourceUpdates; }
- virtual void scheduledActionBeginFrame() { m_actions.push_back("scheduledActionBeginFrame"); }
- virtual void scheduledActionDrawAndSwap() { m_actions.push_back("scheduledActionDrawAndSwap"); }
- virtual void scheduledActionUpdateMoreResources() { m_actions.push_back("scheduledActionUpdateMoreResources"); }
- virtual void scheduledActionCommit() { m_actions.push_back("scheduledActionCommit"); }
- virtual void scheduledActionBeginContextRecreation() { m_actions.push_back("scheduledActionBeginContextRecreation"); }
+ bool hasAction(const char* action) const
+ {
+ for (size_t i = 0; i < m_actions.size(); i++)
+ if (!strcmp(m_actions[i], action))
+ return true;
+ return false;
+ }
+
+ virtual bool canDraw() OVERRIDE { return m_canDraw; }
+ virtual bool hasMoreResourceUpdates() const OVERRIDE { return m_hasMoreResourceUpdates; }
+ virtual void scheduledActionBeginFrame() OVERRIDE { m_actions.push_back("scheduledActionBeginFrame"); }
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE
+ {
+ m_actions.push_back("scheduledActionDrawAndSwapIfPossible");
+ m_numDraws++;
+ return CCScheduledActionDrawAndSwapResult(m_drawWillHappen, m_drawWillHappen && m_swapWillHappenIfDrawHappens);
+ }
+
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE
+ {
+ m_actions.push_back("scheduledActionDrawAndSwapForced");
+ return CCScheduledActionDrawAndSwapResult(true, m_swapWillHappenIfDrawHappens);
+ }
+
+ virtual void scheduledActionUpdateMoreResources() OVERRIDE { m_actions.push_back("scheduledActionUpdateMoreResources"); }
+ virtual void scheduledActionCommit() OVERRIDE { m_actions.push_back("scheduledActionCommit"); }
+ virtual void scheduledActionBeginContextRecreation() OVERRIDE { m_actions.push_back("scheduledActionBeginContextRecreation"); }
+ virtual void scheduledActionAcquireLayerTexturesForMainThread() OVERRIDE { m_actions.push_back("scheduledActionAcquireLayerTexturesForMainThread"); }
+
+ void setDrawWillHappen(bool drawWillHappen) { m_drawWillHappen = drawWillHappen; }
+ void setSwapWillHappenIfDrawHappens(bool swapWillHappenIfDrawHappens) { m_swapWillHappenIfDrawHappens = swapWillHappenIfDrawHappens; }
protected:
bool m_hasMoreResourceUpdates;
bool m_canDraw;
+ bool m_drawWillHappen;
+ bool m_swapWillHappenIfDrawHappens;
+ int m_numDraws;
std::vector<const char*> m_actions;
};
@@ -72,6 +103,7 @@ TEST(CCSchedulerTest, RequestCommit)
FakeCCSchedulerClient client;
RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
+ scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
// SetNeedsCommit should begin the frame.
@@ -94,7 +126,7 @@ TEST(CCSchedulerTest, RequestCommit)
// Tick should draw.
timeSource->tick();
EXPECT_EQ(1, client.numActions());
- EXPECT_STREQ("scheduledActionDrawAndSwap", client.action(0));
+ EXPECT_STREQ("scheduledActionDrawAndSwapIfPossible", client.action(0));
EXPECT_FALSE(timeSource->active());
client.reset();
@@ -107,6 +139,7 @@ TEST(CCSchedulerTest, RequestCommitAfterBeginFrame)
FakeCCSchedulerClient client;
RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
+ scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
// SetNedsCommit should begin the frame.
@@ -131,38 +164,104 @@ TEST(CCSchedulerTest, RequestCommitAfterBeginFrame)
timeSource->tick();
EXPECT_FALSE(timeSource->active());
EXPECT_EQ(2, client.numActions());
- EXPECT_STREQ("scheduledActionDrawAndSwap", client.action(0));
+ EXPECT_STREQ("scheduledActionDrawAndSwapIfPossible", client.action(0));
EXPECT_STREQ("scheduledActionBeginFrame", client.action(1));
client.reset();
}
-class SchedulerClientThatSetNeedsDrawInsideDraw : public CCSchedulerClient {
+TEST(CCSchedulerTest, TextureAcquisitionCollision)
+{
+ FakeCCSchedulerClient client;
+ RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
+ OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
+ scheduler->setCanBeginFrame(true);
+ scheduler->setVisible(true);
+
+ scheduler->setNeedsCommit();
+ scheduler->setMainThreadNeedsLayerTextures();
+ EXPECT_EQ(2, client.numActions());
+ EXPECT_STREQ("scheduledActionBeginFrame", client.action(0));
+ EXPECT_STREQ("scheduledActionAcquireLayerTexturesForMainThread", client.action(1));
+ client.reset();
+
+ // Compositor not scheduled to draw because textures are locked by main thread
+ EXPECT_FALSE(timeSource->active());
+
+ // Trigger the commit
+ scheduler->beginFrameComplete();
+ EXPECT_TRUE(timeSource->active());
+ client.reset();
+
+ // Between commit and draw, texture acquisition for main thread delayed,
+ // and main thread blocks.
+ scheduler->setMainThreadNeedsLayerTextures();
+ EXPECT_EQ(0, client.numActions());
+ client.reset();
+
+ // Once compositor draw complete, the delayed texture acquisition fires.
+ timeSource->tick();
+ EXPECT_EQ(3, client.numActions());
+ EXPECT_STREQ("scheduledActionDrawAndSwapIfPossible", client.action(0));
+ EXPECT_STREQ("scheduledActionAcquireLayerTexturesForMainThread", client.action(1));
+ EXPECT_STREQ("scheduledActionBeginFrame", client.action(2));
+ client.reset();
+}
+
+TEST(CCSchedulerTest, VisibilitySwitchWithTextureAcquisition)
+{
+ FakeCCSchedulerClient client;
+ RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
+ OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
+ scheduler->setCanBeginFrame(true);
+ scheduler->setVisible(true);
+
+ scheduler->setNeedsCommit();
+ scheduler->beginFrameComplete();
+ scheduler->setMainThreadNeedsLayerTextures();
+ client.reset();
+ // Verify that pending texture acquisition fires when visibility
+ // is lost in order to avoid a deadlock.
+ scheduler->setVisible(false);
+ EXPECT_EQ(1, client.numActions());
+ EXPECT_STREQ("scheduledActionAcquireLayerTexturesForMainThread", client.action(0));
+ client.reset();
+
+ // Regaining visibility with textures acquired by main thread while
+ // compositor is waiting for first draw should result in a request
+ // for a new frame in order to escape a deadlock.
+ scheduler->setVisible(true);
+ EXPECT_EQ(1, client.numActions());
+ EXPECT_STREQ("scheduledActionBeginFrame", client.action(0));
+ client.reset();
+}
+
+class SchedulerClientThatSetNeedsDrawInsideDraw : public FakeCCSchedulerClient {
public:
SchedulerClientThatSetNeedsDrawInsideDraw()
- : m_numDraws(0)
- , m_scheduler(0) { }
+ : m_scheduler(0) { }
void setScheduler(CCScheduler* scheduler) { m_scheduler = scheduler; }
- int numDraws() const { return m_numDraws; }
-
- virtual bool hasMoreResourceUpdates() const { return false; }
- virtual bool canDraw() { return true; }
- virtual void scheduledActionBeginFrame() { }
- virtual void scheduledActionDrawAndSwap()
+ virtual void scheduledActionBeginFrame() OVERRIDE { }
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE
{
// Only setNeedsRedraw the first time this is called
if (!m_numDraws)
m_scheduler->setNeedsRedraw();
- m_numDraws++;
+ return FakeCCSchedulerClient::scheduledActionDrawAndSwapIfPossible();
}
- virtual void scheduledActionUpdateMoreResources() { }
- virtual void scheduledActionCommit() { }
- virtual void scheduledActionBeginContextRecreation() { }
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE
+ {
+ ASSERT_NOT_REACHED();
+ return CCScheduledActionDrawAndSwapResult(true, true);
+ }
+
+ virtual void scheduledActionUpdateMoreResources() OVERRIDE { }
+ virtual void scheduledActionCommit() OVERRIDE { }
+ virtual void scheduledActionBeginContextRecreation() OVERRIDE { }
protected:
- int m_numDraws;
CCScheduler* m_scheduler;
};
@@ -176,6 +275,7 @@ TEST(CCSchedulerTest, RequestRedrawInsideDraw)
RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
client.setScheduler(scheduler.get());
+ scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setNeedsRedraw();
@@ -194,33 +294,74 @@ TEST(CCSchedulerTest, RequestRedrawInsideDraw)
EXPECT_FALSE(timeSource->active());
}
-class SchedulerClientThatSetNeedsCommitInsideDraw : public CCSchedulerClient {
+// Test that requesting redraw inside a failed draw doesn't lose the request.
+TEST(CCSchedulerTest, RequestRedrawInsideFailedDraw)
+{
+ SchedulerClientThatSetNeedsDrawInsideDraw client;
+ RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
+ OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
+ client.setScheduler(scheduler.get());
+ scheduler->setCanBeginFrame(true);
+ scheduler->setVisible(true);
+ client.setDrawWillHappen(false);
+
+ scheduler->setNeedsRedraw();
+ EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
+ EXPECT_EQ(0, client.numDraws());
+
+ // Fail the draw.
+ timeSource->tick();
+ EXPECT_EQ(1, client.numDraws());
+
+ // We have a commit pending and the draw failed, and we didn't lose the redraw request.
+ EXPECT_TRUE(scheduler->commitPending());
+ EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
+
+ // Fail the draw again.
+ timeSource->tick();
+ EXPECT_EQ(2, client.numDraws());
+ EXPECT_TRUE(scheduler->commitPending());
+ EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
+
+ // Draw successfully.
+ client.setDrawWillHappen(true);
+ timeSource->tick();
+ EXPECT_EQ(3, client.numDraws());
+ EXPECT_TRUE(scheduler->commitPending());
+ EXPECT_FALSE(scheduler->redrawPending());
+ EXPECT_FALSE(timeSource->active());
+}
+
+class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeCCSchedulerClient {
public:
SchedulerClientThatSetNeedsCommitInsideDraw()
- : m_numDraws(0)
- , m_scheduler(0) { }
+ : m_scheduler(0) { }
void setScheduler(CCScheduler* scheduler) { m_scheduler = scheduler; }
- int numDraws() const { return m_numDraws; }
-
- virtual bool hasMoreResourceUpdates() const { return false; }
- virtual bool canDraw() { return true; }
- virtual void scheduledActionBeginFrame() { }
- virtual void scheduledActionDrawAndSwap()
+ virtual void scheduledActionBeginFrame() OVERRIDE { }
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE
{
// Only setNeedsCommit the first time this is called
if (!m_numDraws)
m_scheduler->setNeedsCommit();
- m_numDraws++;
+ return FakeCCSchedulerClient::scheduledActionDrawAndSwapIfPossible();
+ }
+
+ virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE
+ {
+ ASSERT_NOT_REACHED();
+ return CCScheduledActionDrawAndSwapResult(true, true);
}
- virtual void scheduledActionUpdateMoreResources() { }
- virtual void scheduledActionCommit() { }
- virtual void scheduledActionBeginContextRecreation() { }
+ virtual void scheduledActionUpdateMoreResources() OVERRIDE { }
+ virtual void scheduledActionCommit() OVERRIDE { }
+ virtual void scheduledActionBeginContextRecreation() OVERRIDE { }
protected:
- int m_numDraws;
CCScheduler* m_scheduler;
};
@@ -232,6 +373,7 @@ TEST(CCSchedulerTest, RequestCommitInsideDraw)
RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
client.setScheduler(scheduler.get());
+ scheduler->setCanBeginFrame(true);
scheduler->setVisible(true);
scheduler->setNeedsRedraw();
@@ -251,4 +393,104 @@ TEST(CCSchedulerTest, RequestCommitInsideDraw)
EXPECT_FALSE(scheduler->redrawPending());
}
+// Tests that when a draw fails then the pending commit should not be dropped.
+TEST(CCSchedulerTest, RequestCommitInsideFailedDraw)
+{
+ SchedulerClientThatSetNeedsDrawInsideDraw client;
+ RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
+ OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, adoptPtr(new CCFrameRateController(timeSource)));
+ client.setScheduler(scheduler.get());
+ scheduler->setCanBeginFrame(true);
+ scheduler->setVisible(true);
+ client.setDrawWillHappen(false);
+
+ scheduler->setNeedsRedraw();
+ EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
+ EXPECT_EQ(0, client.numDraws());
+
+ // Fail the draw.
+ timeSource->tick();
+ EXPECT_EQ(1, client.numDraws());
+
+ // We have a commit pending and the draw failed, and we didn't lose the commit request.
+ EXPECT_TRUE(scheduler->commitPending());
+ EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
+
+ // Fail the draw again.
+ timeSource->tick();
+ EXPECT_EQ(2, client.numDraws());
+ EXPECT_TRUE(scheduler->commitPending());
+ EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
+
+ // Draw successfully.
+ client.setDrawWillHappen(true);
+ timeSource->tick();
+ EXPECT_EQ(3, client.numDraws());
+ EXPECT_TRUE(scheduler->commitPending());
+ EXPECT_FALSE(scheduler->redrawPending());
+ EXPECT_FALSE(timeSource->active());
+}
+
+TEST(CCSchedulerTest, NoBeginFrameWhenDrawFails)
+{
+ RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
+ SchedulerClientThatSetNeedsCommitInsideDraw client;
+ OwnPtr<FakeCCFrameRateController> controller = adoptPtr(new FakeCCFrameRateController(timeSource));
+ FakeCCFrameRateController* controllerPtr = controller.get();
+ OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, controller.release());
+ client.setScheduler(scheduler.get());
+ scheduler->setCanBeginFrame(true);
+ scheduler->setVisible(true);
+
+ EXPECT_EQ(0, controllerPtr->numFramesPending());
+
+ scheduler->setNeedsRedraw();
+ EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
+ EXPECT_EQ(0, client.numDraws());
+
+ // Draw successfully, this starts a new frame.
+ timeSource->tick();
+ EXPECT_EQ(1, client.numDraws());
+ EXPECT_EQ(1, controllerPtr->numFramesPending());
+ scheduler->didSwapBuffersComplete();
+ EXPECT_EQ(0, controllerPtr->numFramesPending());
+
+ scheduler->setNeedsRedraw();
+ EXPECT_TRUE(scheduler->redrawPending());
+ EXPECT_TRUE(timeSource->active());
+
+ // Fail to draw, this should not start a frame.
+ client.setDrawWillHappen(false);
+ timeSource->tick();
+ EXPECT_EQ(2, client.numDraws());
+ EXPECT_EQ(0, controllerPtr->numFramesPending());
+}
+
+TEST(CCSchedulerTest, NoBeginFrameWhenSwapFailsDuringForcedCommit)
+{
+ RefPtr<FakeCCTimeSource> timeSource = adoptRef(new FakeCCTimeSource());
+ FakeCCSchedulerClient client;
+ OwnPtr<FakeCCFrameRateController> controller = adoptPtr(new FakeCCFrameRateController(timeSource));
+ FakeCCFrameRateController* controllerPtr = controller.get();
+ OwnPtr<CCScheduler> scheduler = CCScheduler::create(&client, controller.release());
+
+ EXPECT_EQ(0, controllerPtr->numFramesPending());
+
+ // Tell the client that it will fail to swap.
+ client.setDrawWillHappen(true);
+ client.setSwapWillHappenIfDrawHappens(false);
+
+ // Get the compositor to do a scheduledActionDrawAndSwapForced.
+ scheduler->setNeedsRedraw();
+ scheduler->setNeedsForcedRedraw();
+ EXPECT_TRUE(client.hasAction("scheduledActionDrawAndSwapForced"));
+
+ // We should not have told the frame rate controller that we began a frame.
+ EXPECT_EQ(0, controllerPtr->numFramesPending());
+}
+
}
diff --git a/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h b/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h
index 9b5e0383e..6257ec888 100644
--- a/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h
+++ b/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h
@@ -26,6 +26,7 @@
#define CCSchedulerTestCommon_h
#include "cc/CCDelayBasedTimeSource.h"
+#include "cc/CCFrameRateController.h"
#include "cc/CCThread.h"
#include <gtest/gtest.h>
#include <wtf/OwnPtr.h>
@@ -38,7 +39,7 @@ public:
void reset() { m_tickCalled = false; }
bool tickCalled() const { return m_tickCalled; }
- virtual void onTimerTick() { m_tickCalled = true; }
+ virtual void onTimerTick() OVERRIDE { m_tickCalled = true; }
protected:
bool m_tickCalled;
@@ -61,7 +62,7 @@ public:
task->performTask();
}
- long long pendingDelay() const
+ long long pendingDelayMs() const
{
EXPECT_TRUE(hasPendingTask());
return m_pendingTaskDelay;
@@ -89,9 +90,9 @@ public:
virtual ~FakeCCTimeSource() { }
- virtual void setClient(WebCore::CCTimeSourceClient* client) { m_client = client; }
- virtual void setActive(bool b) { m_active = b; }
- virtual bool active() const { return m_active; }
+ virtual void setClient(WebCore::CCTimeSourceClient* client) OVERRIDE { m_client = client; }
+ virtual void setActive(bool b) OVERRIDE { m_active = b; }
+ virtual bool active() const OVERRIDE { return m_active; }
void tick()
{
@@ -107,20 +108,27 @@ protected:
class FakeCCDelayBasedTimeSource : public WebCore::CCDelayBasedTimeSource {
public:
- static PassRefPtr<FakeCCDelayBasedTimeSource> create(double intervalMs, WebCore::CCThread* thread)
+ static PassRefPtr<FakeCCDelayBasedTimeSource> create(double interval, WebCore::CCThread* thread)
{
- return adoptRef(new FakeCCDelayBasedTimeSource(intervalMs, thread));
+ return adoptRef(new FakeCCDelayBasedTimeSource(interval, thread));
}
- void setMonotonicallyIncreasingTimeMs(double time) { m_monotonicallyIncreasingTimeMs = time; }
- virtual double monotonicallyIncreasingTimeMs() const { return m_monotonicallyIncreasingTimeMs; }
+ void setMonotonicallyIncreasingTime(double time) { m_monotonicallyIncreasingTime = time; }
+ virtual double monotonicallyIncreasingTime() const { return m_monotonicallyIncreasingTime; }
protected:
- FakeCCDelayBasedTimeSource(double intervalMs, WebCore::CCThread* thread)
- : CCDelayBasedTimeSource(intervalMs, thread)
- , m_monotonicallyIncreasingTimeMs(0) { }
+ FakeCCDelayBasedTimeSource(double interval, WebCore::CCThread* thread)
+ : CCDelayBasedTimeSource(interval, thread)
+ , m_monotonicallyIncreasingTime(0) { }
- double m_monotonicallyIncreasingTimeMs;
+ double m_monotonicallyIncreasingTime;
+};
+
+class FakeCCFrameRateController : public WebCore::CCFrameRateController {
+public:
+ FakeCCFrameRateController(PassRefPtr<WebCore::CCTimeSource> timer) : WebCore::CCFrameRateController(timer) { }
+
+ int numFramesPending() const { return m_numFramesPending; }
};
}
diff --git a/Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp b/Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp
index 02dc908ab..6b7124975 100644
--- a/Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp
@@ -27,6 +27,7 @@
#include "cc/CCSolidColorLayerImpl.h"
#include "CCLayerTestCommon.h"
+#include "MockCCQuadCuller.h"
#include "cc/CCSingleThreadProxy.h"
#include "cc/CCSolidColorDrawQuad.h"
@@ -42,7 +43,7 @@ TEST(CCSolidColorLayerImplTest, verifyTilingCompleteAndNoOverlap)
{
DebugScopedSetImplThread scopedImplThread;
- CCQuadList quadList;
+ MockCCQuadCuller quadCuller;
IntSize layerSize = IntSize(800, 600);
IntRect visibleLayerRect = IntRect(IntPoint(), layerSize);
@@ -51,9 +52,10 @@ TEST(CCSolidColorLayerImplTest, verifyTilingCompleteAndNoOverlap)
layer->setBounds(layerSize);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadList, sharedQuadState.get());
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
- verifyQuadsExactlyCoverRect(quadList, visibleLayerRect);
+ verifyQuadsExactlyCoverRect(quadCuller.quadList(), visibleLayerRect);
}
TEST(CCSolidColorLayerImplTest, verifyCorrectBackgroundColorInQuad)
@@ -62,7 +64,7 @@ TEST(CCSolidColorLayerImplTest, verifyCorrectBackgroundColorInQuad)
const Color testColor = 0xFFA55AFF;
- CCQuadList quadList;
+ MockCCQuadCuller quadCuller;
IntSize layerSize = IntSize(100, 100);
IntRect visibleLayerRect = IntRect(IntPoint(), layerSize);
@@ -72,10 +74,34 @@ TEST(CCSolidColorLayerImplTest, verifyCorrectBackgroundColorInQuad)
layer->setBackgroundColor(testColor);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadList, sharedQuadState.get());
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
- ASSERT_EQ(quadList.size(), 1U);
- EXPECT_EQ(quadList[0]->toSolidColorDrawQuad()->color(), testColor);
+ ASSERT_EQ(quadCuller.quadList().size(), 1U);
+ EXPECT_EQ(quadCuller.quadList()[0]->toSolidColorDrawQuad()->color(), testColor);
+}
+
+TEST(CCSolidColorLayerImplTest, verifyCorrectOpacityInQuad)
+{
+ DebugScopedSetImplThread scopedImplThread;
+
+ const float opacity = 0.5f;
+
+ MockCCQuadCuller quadCuller;
+ IntSize layerSize = IntSize(100, 100);
+ IntRect visibleLayerRect = IntRect(IntPoint(), layerSize);
+
+ OwnPtr<CCSolidColorLayerImpl> layer = CCSolidColorLayerImpl::create(0);
+ layer->setVisibleLayerRect(visibleLayerRect);
+ layer->setBounds(layerSize);
+ layer->setDrawOpacity(opacity);
+
+ OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
+
+ ASSERT_EQ(quadCuller.quadList().size(), 1U);
+ EXPECT_EQ(opacity, quadCuller.quadList()[0]->toSolidColorDrawQuad()->opacity());
}
} // namespace
diff --git a/Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp b/Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp
index ff7daa3c9..48a46dae1 100644
--- a/Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp
@@ -27,6 +27,7 @@
#include "cc/CCTiledLayerImpl.h"
#include "CCLayerTestCommon.h"
+#include "MockCCQuadCuller.h"
#include "cc/CCSingleThreadProxy.h"
#include "cc/CCTileDrawQuad.h"
#include <gmock/gmock.h>
@@ -69,11 +70,12 @@ TEST(CCTiledLayerImplTest, emptyQuadList)
// Verify default layer does creates quads
{
OwnPtr<CCTiledLayerImpl> layer = createLayer(tileSize, layerSize, CCLayerTilingData::NoBorderTexels);
- CCQuadList quads;
+ MockCCQuadCuller quadCuller;
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quads, sharedQuadState.get());
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
const unsigned numTiles = numTilesX * numTilesY;
- EXPECT_EQ(quads.size(), numTiles);
+ EXPECT_EQ(quadCuller.quadList().size(), numTiles);
}
// Layer with empty visible layer rect produces no quads
@@ -81,10 +83,11 @@ TEST(CCTiledLayerImplTest, emptyQuadList)
OwnPtr<CCTiledLayerImpl> layer = createLayer(tileSize, layerSize, CCLayerTilingData::NoBorderTexels);
layer->setVisibleLayerRect(IntRect());
- CCQuadList quads;
+ MockCCQuadCuller quadCuller;
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quads, sharedQuadState.get());
- EXPECT_EQ(quads.size(), 0u);
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
+ EXPECT_EQ(quadCuller.quadList().size(), 0u);
}
// Layer with non-intersecting visible layer rect produces no quads
@@ -94,10 +97,11 @@ TEST(CCTiledLayerImplTest, emptyQuadList)
IntRect outsideBounds(IntPoint(-100, -100), IntSize(50, 50));
layer->setVisibleLayerRect(outsideBounds);
- CCQuadList quads;
+ MockCCQuadCuller quadCuller;
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quads, sharedQuadState.get());
- EXPECT_EQ(quads.size(), 0u);
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
+ EXPECT_EQ(quadCuller.quadList().size(), 0u);
}
// Layer with skips draw produces no quads
@@ -105,10 +109,11 @@ TEST(CCTiledLayerImplTest, emptyQuadList)
OwnPtr<CCTiledLayerImpl> layer = createLayer(tileSize, layerSize, CCLayerTilingData::NoBorderTexels);
layer->setSkipsDraw(true);
- CCQuadList quads;
+ MockCCQuadCuller quadCuller;
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quads, sharedQuadState.get());
- EXPECT_EQ(quads.size(), 0u);
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
+ EXPECT_EQ(quadCuller.quadList().size(), 0u);
}
}
@@ -126,12 +131,14 @@ TEST(CCTiledLayerImplTest, checkerboarding)
// No checkerboarding
{
- CCQuadList quads;
- layer->appendQuads(quads, sharedQuadState.get());
- EXPECT_EQ(quads.size(), 4u);
-
- for (size_t i = 0; i < quads.size(); ++i)
- EXPECT_EQ(quads[i]->material(), CCDrawQuad::TiledContent);
+ MockCCQuadCuller quadCuller;
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
+ EXPECT_EQ(quadCuller.quadList().size(), 4u);
+ EXPECT_FALSE(hadMissingTiles);
+
+ for (size_t i = 0; i < quadCuller.quadList().size(); ++i)
+ EXPECT_EQ(quadCuller.quadList()[i]->material(), CCDrawQuad::TiledContent);
}
for (int i = 0; i < numTilesX; ++i)
@@ -140,11 +147,13 @@ TEST(CCTiledLayerImplTest, checkerboarding)
// All checkerboarding
{
- CCQuadList quads;
- layer->appendQuads(quads, sharedQuadState.get());
- EXPECT_EQ(quads.size(), 4u);
- for (size_t i = 0; i < quads.size(); ++i)
- EXPECT_EQ(quads[i]->material(), CCDrawQuad::SolidColor);
+ MockCCQuadCuller quadCuller;
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
+ EXPECT_TRUE(hadMissingTiles);
+ EXPECT_EQ(quadCuller.quadList().size(), 4u);
+ for (size_t i = 0; i < quadCuller.quadList().size(); ++i)
+ EXPECT_NE(quadCuller.quadList()[i]->material(), CCDrawQuad::TiledContent);
}
}
@@ -154,8 +163,10 @@ static PassOwnPtr<CCSharedQuadState> getQuads(CCQuadList& quads, IntSize tileSiz
layer->setVisibleLayerRect(visibleLayerRect);
layer->setBounds(layerSize);
+ MockCCQuadCuller quadCuller(quads);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quads, sharedQuadState.get());
+ bool hadMissingTiles = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), hadMissingTiles);
return sharedQuadState.release(); // The shared data must be owned as long as the quad list exists.
}
@@ -251,73 +262,4 @@ TEST(CCTiledLayerImplTest, tileOpaqueRectForLayerNoBorders)
}
}
-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);
- OwnPtr<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/CCTiledLayerTestCommon.cpp b/Source/WebKit/chromium/tests/CCTiledLayerTestCommon.cpp
new file mode 100644
index 000000000..46d11a96e
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCTiledLayerTestCommon.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 "CCTiledLayerTestCommon.h"
+
+using namespace WebCore;
+
+namespace WebKitTests {
+
+FakeLayerTextureUpdater::Texture::Texture(FakeLayerTextureUpdater* layer, PassOwnPtr<ManagedTexture> texture)
+ : LayerTextureUpdater::Texture(texture)
+ , m_layer(layer)
+{
+}
+
+FakeLayerTextureUpdater::Texture::~Texture()
+{
+}
+
+void FakeLayerTextureUpdater::Texture::updateRect(GraphicsContext3D*, TextureAllocator* allocator, const IntRect&, const IntRect&)
+{
+ if (allocator)
+ texture()->allocate(allocator);
+ m_layer->updateRect();
+}
+
+void FakeLayerTextureUpdater::Texture::prepareRect(const IntRect&)
+{
+ m_layer->prepareRect();
+}
+
+FakeLayerTextureUpdater::FakeLayerTextureUpdater()
+ : m_prepareCount(0)
+ , m_updateCount(0)
+ , m_prepareRectCount(0)
+{
+}
+
+FakeLayerTextureUpdater::~FakeLayerTextureUpdater()
+{
+}
+
+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;
+}
+
+void FakeLayerTextureUpdater::setRectToInvalidate(const IntRect& rect, FakeTiledLayerChromium* layer)
+{
+ m_rectToInvalidate = rect;
+ m_layer = layer;
+}
+
+PassOwnPtr<LayerTextureUpdater::Texture> FakeLayerTextureUpdater::createTexture(TextureManager* manager)
+{
+ return adoptPtr(new Texture(this, ManagedTexture::create(manager)));
+}
+
+FakeCCTiledLayerImpl::FakeCCTiledLayerImpl(int id)
+ : CCTiledLayerImpl(id)
+{
+}
+
+FakeCCTiledLayerImpl::~FakeCCTiledLayerImpl()
+{
+}
+
+FakeTiledLayerChromium::FakeTiledLayerChromium(TextureManager* textureManager)
+ : TiledLayerChromium()
+ , m_fakeTextureUpdater(adoptRef(new FakeLayerTextureUpdater))
+ , m_textureManager(textureManager)
+{
+ setTileSize(tileSize());
+ setTextureFormat(GraphicsContext3D::RGBA);
+ setBorderTexelOption(CCLayerTilingData::NoBorderTexels);
+ setIsDrawable(true); // So that we don't get false positives if any of these tests expect to return false from drawsContent() for other reasons.
+}
+
+FakeTiledLayerChromium::~FakeTiledLayerChromium()
+{
+}
+
+void FakeTiledLayerChromium::setNeedsDisplayRect(const FloatRect& rect)
+{
+ m_lastNeedsDisplayRect = rect;
+ TiledLayerChromium::setNeedsDisplayRect(rect);
+}
+
+void FakeTiledLayerChromium::update(CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
+{
+ updateLayerRect(updater, visibleLayerRect(), occlusion);
+}
+
+FakeTiledLayerWithScaledBounds::FakeTiledLayerWithScaledBounds(TextureManager* textureManager)
+ : FakeTiledLayerChromium(textureManager)
+{
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/CCTiledLayerTestCommon.h b/Source/WebKit/chromium/tests/CCTiledLayerTestCommon.h
new file mode 100644
index 000000000..c028ea725
--- /dev/null
+++ b/Source/WebKit/chromium/tests/CCTiledLayerTestCommon.h
@@ -0,0 +1,168 @@
+/*
+ * 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 CCTiledLayerTestCommon_h
+#define CCTiledLayerTestCommon_h
+
+#include "GraphicsContext3D.h"
+#include "IntRect.h"
+#include "IntSize.h"
+#include "LayerTextureUpdater.h"
+#include "Region.h"
+#include "TextureCopier.h"
+#include "TextureManager.h"
+#include "TextureUploader.h"
+#include "TiledLayerChromium.h"
+#include "cc/CCTextureUpdater.h"
+#include "cc/CCTiledLayerImpl.h"
+
+namespace WebKitTests {
+
+class FakeTiledLayerChromium;
+
+class FakeLayerTextureUpdater : public WebCore::LayerTextureUpdater {
+public:
+ class Texture : public WebCore::LayerTextureUpdater::Texture {
+ public:
+ Texture(FakeLayerTextureUpdater*, PassOwnPtr<WebCore::ManagedTexture>);
+ virtual ~Texture();
+
+ virtual void updateRect(WebCore::GraphicsContext3D*, WebCore::TextureAllocator* , const WebCore::IntRect&, const WebCore::IntRect&);
+ virtual void prepareRect(const WebCore::IntRect&);
+
+ private:
+ FakeLayerTextureUpdater* m_layer;
+ };
+
+ FakeLayerTextureUpdater();
+ virtual ~FakeLayerTextureUpdater();
+
+ virtual PassOwnPtr<WebCore::LayerTextureUpdater::Texture> createTexture(WebCore::TextureManager*);
+ virtual SampledTexelFormat sampledTexelFormat(GC3Denum) { return SampledTexelFormatRGBA; }
+
+ virtual void prepareToUpdate(const WebCore::IntRect& contentRect, const WebCore::IntSize&, int, float, WebCore::IntRect& resultingOpaqueRect);
+ // Sets the rect to invalidate during the next call to prepareToUpdate(). After the next
+ // call to prepareToUpdate() the rect is reset.
+ void setRectToInvalidate(const WebCore::IntRect&, FakeTiledLayerChromium*);
+ // Last rect passed to prepareToUpdate().
+ const WebCore::IntRect& lastUpdateRect() const { return m_lastUpdateRect; }
+
+ // Number of times prepareToUpdate has been invoked.
+ int prepareCount() const { return m_prepareCount; }
+ void clearPrepareCount() { m_prepareCount = 0; }
+
+ // Number of times updateRect has been invoked.
+ int updateCount() const { return m_updateCount; }
+ void clearUpdateCount() { m_updateCount = 0; }
+ void updateRect() { m_updateCount++; }
+
+ // Number of times prepareRect() has been invoked on a texture.
+ int prepareRectCount() const { return m_prepareRectCount; }
+ void clearPrepareRectCount() { m_prepareRectCount = 0; }
+ void prepareRect() { m_prepareRectCount++; }
+
+ void setOpaquePaintRect(const WebCore::IntRect& opaquePaintRect) { m_opaquePaintRect = opaquePaintRect; }
+
+private:
+ int m_prepareCount;
+ int m_updateCount;
+ int m_prepareRectCount;
+ WebCore::IntRect m_rectToInvalidate;
+ WebCore::IntRect m_lastUpdateRect;
+ WebCore::IntRect m_opaquePaintRect;
+ RefPtr<FakeTiledLayerChromium> m_layer;
+};
+
+class FakeCCTiledLayerImpl : public WebCore::CCTiledLayerImpl {
+public:
+ explicit FakeCCTiledLayerImpl(int id);
+ virtual ~FakeCCTiledLayerImpl();
+
+ using WebCore::CCTiledLayerImpl::hasTileAt;
+ using WebCore::CCTiledLayerImpl::hasTextureIdForTileAt;
+};
+
+class FakeTiledLayerChromium : public WebCore::TiledLayerChromium {
+public:
+ explicit FakeTiledLayerChromium(WebCore::TextureManager*);
+ virtual ~FakeTiledLayerChromium();
+
+ static WebCore::IntSize tileSize() { return WebCore::IntSize(100, 100); }
+
+ using WebCore::TiledLayerChromium::invalidateRect;
+ using WebCore::TiledLayerChromium::updateLayerRect;
+ using WebCore::TiledLayerChromium::idleUpdateLayerRect;
+ using WebCore::TiledLayerChromium::needsIdlePaint;
+ using WebCore::TiledLayerChromium::skipsDraw;
+ using WebCore::TiledLayerChromium::numPaintedTiles;
+ using WebCore::TiledLayerChromium::idlePaintRect;
+
+ virtual void setNeedsDisplayRect(const WebCore::FloatRect&) OVERRIDE;
+ const WebCore::FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; }
+
+ // Updates the visibleLayerRect().
+ virtual void update(WebCore::CCTextureUpdater&, const WebCore::CCOcclusionTracker*) OVERRIDE;
+
+ virtual WebCore::TextureManager* textureManager() const OVERRIDE { return m_textureManager; }
+ FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); }
+ WebCore::FloatRect updateRect() { return m_updateRect; }
+
+private:
+ virtual WebCore::LayerTextureUpdater* textureUpdater() const OVERRIDE { return m_fakeTextureUpdater.get(); }
+ virtual void createTextureUpdaterIfNeeded() OVERRIDE { }
+
+ RefPtr<FakeLayerTextureUpdater> m_fakeTextureUpdater;
+ WebCore::TextureManager* m_textureManager;
+ WebCore::FloatRect m_lastNeedsDisplayRect;
+};
+
+class FakeTiledLayerWithScaledBounds : public FakeTiledLayerChromium {
+public:
+ explicit FakeTiledLayerWithScaledBounds(WebCore::TextureManager*);
+
+ void setContentBounds(const WebCore::IntSize& contentBounds) { m_forcedContentBounds = contentBounds; }
+ virtual WebCore::IntSize contentBounds() const OVERRIDE { return m_forcedContentBounds; }
+
+protected:
+ WebCore::IntSize m_forcedContentBounds;
+};
+
+class FakeTextureAllocator : public WebCore::TextureAllocator {
+public:
+ virtual unsigned createTexture(const WebCore::IntSize&, GC3Denum) { return 1; }
+ virtual void deleteTexture(unsigned, const WebCore::IntSize&, GC3Denum) { }
+};
+
+class FakeTextureCopier : public WebCore::TextureCopier {
+public:
+ virtual void copyTexture(WebCore::GraphicsContext3D*, unsigned, unsigned, const WebCore::IntSize&) { }
+};
+
+class FakeTextureUploader : public WebCore::TextureUploader {
+public:
+ virtual void uploadTexture(WebCore::GraphicsContext3D* context, WebCore::LayerTextureUpdater::Texture* texture, WebCore::TextureAllocator* allocator, const WebCore::IntRect sourceRect, const WebCore::IntRect destRect) { texture->updateRect(context, allocator, sourceRect, destRect); }
+};
+
+}
+#endif // CCTiledLayerTestCommon_h
diff --git a/Source/WebKit/chromium/tests/CCTimerTest.cpp b/Source/WebKit/chromium/tests/CCTimerTest.cpp
index 298b69562..398fca56e 100644
--- a/Source/WebKit/chromium/tests/CCTimerTest.cpp
+++ b/Source/WebKit/chromium/tests/CCTimerTest.cpp
@@ -54,7 +54,7 @@ protected:
TEST_F(CCTimerTest, OneShot)
{
CCTimer timer(&m_thread, this);
- timer.startOneShot(1);
+ timer.startOneShot(0.001);
m_thread.runPendingTask();
EXPECT_TRUE(m_flag);
@@ -64,7 +64,7 @@ TEST_F(CCTimerTest, OneShot)
TEST_F(CCTimerTest, StopManually)
{
CCTimer timer(&m_thread, this);
- timer.startOneShot(1);
+ timer.startOneShot(0.001);
timer.stop();
m_thread.runPendingTask();
@@ -76,7 +76,7 @@ TEST_F(CCTimerTest, StopByScope)
{
{
CCTimer timer(&m_thread, this);
- timer.startOneShot(1);
+ timer.startOneShot(0.001);
}
m_thread.runPendingTask();
diff --git a/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
index 580f15791..f464dcbbc 100644
--- a/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp
@@ -27,13 +27,19 @@
#include "Canvas2DLayerChromium.h"
#include "CCSchedulerTestCommon.h"
+#include "FakeCCLayerTreeHostClient.h"
#include "FakeWebGraphicsContext3D.h"
#include "GraphicsContext3DPrivate.h"
#include "Region.h"
+#include "TextureCopier.h"
#include "TextureManager.h"
-#include "cc/CCCanvasLayerImpl.h"
+#include "WebCompositor.h"
+#include "WebKit.h"
#include "cc/CCSingleThreadProxy.h"
+#include "cc/CCTextureLayerImpl.h"
#include "cc/CCTextureUpdater.h"
+#include "platform/WebKitPlatformSupport.h"
+#include "platform/WebThread.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -48,19 +54,27 @@ using testing::Test;
namespace {
-class MockCanvasContext : public FakeWebGraphicsContext3D {
+class FakeCCLayerTreeHost : public CCLayerTreeHost {
public:
- MOCK_METHOD0(createFramebuffer, WebGLId());
- MOCK_METHOD0(createTexture, WebGLId());
+ static PassOwnPtr<FakeCCLayerTreeHost> create()
+ {
+ OwnPtr<FakeCCLayerTreeHost> host(adoptPtr(new FakeCCLayerTreeHost));
+ host->initialize();
+ return host.release();
+ }
- MOCK_METHOD2(bindFramebuffer, void(WGC3Denum, WebGLId));
- MOCK_METHOD5(framebufferTexture2D, void(WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint));
+private:
+ FakeCCLayerTreeHost()
+ : CCLayerTreeHost(&m_client, CCSettings())
+ {
+ }
- MOCK_METHOD2(bindTexture, void(WGC3Denum, WebGLId));
- MOCK_METHOD8(copyTexSubImage2D, void(WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei));
+ FakeCCLayerTreeHostClient m_client;
+};
- MOCK_METHOD1(deleteFramebuffer, void(WebGLId));
- MOCK_METHOD1(deleteTexture, void(WebGLId));
+class MockCanvasContext : public FakeWebGraphicsContext3D {
+public:
+ MOCK_METHOD0(flush, void(void));
};
class MockTextureAllocator : public TextureAllocator {
@@ -69,13 +83,21 @@ public:
MOCK_METHOD3(deleteTexture, void(unsigned, const IntSize&, GC3Denum));
};
-} // namespace
+class MockTextureCopier : public TextureCopier {
+public:
+ MOCK_METHOD4(copyTexture, void(GraphicsContext3D*, unsigned, unsigned, const IntSize&));
+};
+
+class MockTextureUploader : public TextureUploader {
+public:
+ MOCK_METHOD5(uploadTexture, void(GraphicsContext3D*, LayerTextureUpdater::Texture*, TextureAllocator*, const IntRect, const IntRect));
+};
-namespace WebCore {
+} // namespace
class Canvas2DLayerChromiumTest : public Test {
protected:
- void fullLifecycleTest(bool threaded)
+ void fullLifecycleTest(bool threaded, bool deferred)
{
GraphicsContext3D::Attributes attrs;
@@ -86,84 +108,95 @@ protected:
MockCanvasContext& implMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(implContext.get()));
MockTextureAllocator allocatorMock;
- CCTextureUpdater updater(&allocatorMock);
+ MockTextureCopier copierMock;
+ MockTextureUploader uploaderMock;
+ CCTextureUpdater updater;
const IntSize size(300, 150);
- const size_t maxTextureSize = size.width() * size.height() * 4;
- OwnPtr<TextureManager> textureManager = TextureManager::create(maxTextureSize, maxTextureSize, maxTextureSize);
+ OwnPtr<WebThread> thread;
if (threaded)
- CCProxy::setImplThread(new FakeCCThread);
+ thread = adoptPtr(WebKit::Platform::current()->createThread("Canvas2DLayerChromiumTest"));
+ WebCompositor::initialize(thread.get());
+
+ OwnPtr<FakeCCLayerTreeHost> layerTreeHost(FakeCCLayerTreeHost::create());
+ // Force an update, so that we get a valid TextureManager.
+ layerTreeHost->updateLayers(updater);
const WebGLId backTextureId = 1;
const WebGLId frontTextureId = 2;
- const WebGLId fboId = 3;
{
InSequence sequence;
- // Note that the canvas backing texture is doublebuffered only when using the threaded
- // compositor.
- if (threaded) {
- // Setup Canvas2DLayerChromium (on the main thread).
- EXPECT_CALL(mainMock, createFramebuffer())
- .WillOnce(Return(fboId));
+ // Paint canvas contents on the main thread.
+ EXPECT_CALL(mainMock, flush());
+ // Note that the canvas backing texture is doublebuffered only when using the threaded
+ // compositor and not using deferred canvas rendering
+ if (threaded && !deferred) {
// Create texture and do the copy (on the impl thread).
EXPECT_CALL(allocatorMock, createTexture(size, GraphicsContext3D::RGBA))
.WillOnce(Return(frontTextureId));
- EXPECT_CALL(implMock, bindTexture(GraphicsContext3D::TEXTURE_2D, frontTextureId));
- EXPECT_CALL(implMock, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, fboId));
- EXPECT_CALL(implMock, framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, backTextureId, 0));
- EXPECT_CALL(implMock, copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, 300, 150));
- EXPECT_CALL(implMock, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
-
- // Teardown Canvas2DLayerChromium.
- EXPECT_CALL(mainMock, deleteFramebuffer(fboId));
+ EXPECT_CALL(copierMock, copyTexture(implContext.get(), backTextureId, frontTextureId, size));
+ EXPECT_CALL(implMock, flush());
// Teardown TextureManager.
EXPECT_CALL(allocatorMock, deleteTexture(frontTextureId, size, GraphicsContext3D::RGBA));
}
}
- RefPtr<Canvas2DLayerChromium> canvas = Canvas2DLayerChromium::create(mainContext.get(), size);
+ RefPtr<Canvas2DLayerChromium> canvas = Canvas2DLayerChromium::create(mainContext.get(), size, deferred ? Deferred : NonDeferred);
canvas->setIsDrawable(true);
- canvas->setTextureManager(textureManager.get());
+ canvas->setLayerTreeHost(layerTreeHost.get());
canvas->setBounds(IntSize(600, 300));
canvas->setTextureId(backTextureId);
canvas->setNeedsDisplay();
EXPECT_TRUE(canvas->needsDisplay());
- Region occludedScreenSpace;
- canvas->paintContentsIfDirty(occludedScreenSpace);
+ canvas->update(updater, 0);
EXPECT_FALSE(canvas->needsDisplay());
{
DebugScopedSetImplThread scopedImplThread;
OwnPtr<CCLayerImpl> layerImpl = canvas->createCCLayerImpl();
- EXPECT_EQ(0u, static_cast<CCCanvasLayerImpl*>(layerImpl.get())->textureId());
+ EXPECT_EQ(0u, static_cast<CCTextureLayerImpl*>(layerImpl.get())->textureId());
- canvas->updateCompositorResources(implContext.get(), updater);
+ updater.update(implContext.get(), &allocatorMock, &copierMock, &uploaderMock, 1);
canvas->pushPropertiesTo(layerImpl.get());
- if (threaded)
- EXPECT_EQ(frontTextureId, static_cast<CCCanvasLayerImpl*>(layerImpl.get())->textureId());
+ if (threaded && !deferred)
+ EXPECT_EQ(frontTextureId, static_cast<CCTextureLayerImpl*>(layerImpl.get())->textureId());
else
- EXPECT_EQ(backTextureId, static_cast<CCCanvasLayerImpl*>(layerImpl.get())->textureId());
+ EXPECT_EQ(backTextureId, static_cast<CCTextureLayerImpl*>(layerImpl.get())->textureId());
}
canvas.clear();
- textureManager->reduceMemoryToLimit(0);
- textureManager->deleteEvictedTextures(&allocatorMock);
+ layerTreeHost->contentsTextureManager()->reduceMemoryToLimit(0);
+ layerTreeHost->contentsTextureManager()->deleteEvictedTextures(&allocatorMock);
+ layerTreeHost.clear();
+ WebCompositor::shutdown();
}
};
+namespace {
+
TEST_F(Canvas2DLayerChromiumTest, testFullLifecycleSingleThread)
{
- fullLifecycleTest(false);
+ fullLifecycleTest(false, false);
}
TEST_F(Canvas2DLayerChromiumTest, testFullLifecycleThreaded)
{
- fullLifecycleTest(true);
+ fullLifecycleTest(true, false);
}
-} // namespace webcore
+TEST_F(Canvas2DLayerChromiumTest, testFullLifecycleSingleThreadDeferred)
+{
+ fullLifecycleTest(false, true);
+}
+
+TEST_F(Canvas2DLayerChromiumTest, testFullLifecycleThreadedDeferred)
+{
+ fullLifecycleTest(true, true);
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/WebGLLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/DrawingBufferChromiumTest.cpp
index 66ea690fa..27ef49281 100644
--- a/Source/WebKit/chromium/tests/WebGLLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/DrawingBufferChromiumTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * 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
@@ -24,10 +24,10 @@
#include "config.h"
-#include "WebGLLayerChromium.h"
+#include "DrawingBuffer.h"
#include "CompositorFakeGraphicsContext3D.h"
-#include "DrawingBuffer.h"
+#include "LayerChromium.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -36,7 +36,7 @@ using namespace WebKit;
namespace {
-TEST(WebGLLayerChromiumTest, opaqueFormats)
+TEST(DrawingBufferChromiumTest, opaqueFormats)
{
RefPtr<DrawingBuffer> buffer;
@@ -50,14 +50,14 @@ TEST(WebGLLayerChromiumTest, opaqueFormats)
RefPtr<GraphicsContext3D> opaqueContext = createCompositorMockGraphicsContext3D(opaqueAttrs);
EXPECT_TRUE(opaqueContext);
- buffer = DrawingBuffer::create(alphaContext.get(), IntSize(), false);
+ buffer = DrawingBuffer::create(alphaContext.get(), IntSize(), DrawingBuffer::Preserve, DrawingBuffer::Alpha);
EXPECT_FALSE(buffer->platformLayer()->opaque());
- buffer = DrawingBuffer::create(alphaContext.get(), IntSize(), true);
+ buffer = DrawingBuffer::create(alphaContext.get(), IntSize(), DrawingBuffer::Discard, DrawingBuffer::Alpha);
EXPECT_FALSE(buffer->platformLayer()->opaque());
- buffer = DrawingBuffer::create(opaqueContext.get(), IntSize(), false);
+ buffer = DrawingBuffer::create(opaqueContext.get(), IntSize(), DrawingBuffer::Preserve, DrawingBuffer::Opaque);
EXPECT_TRUE(buffer->platformLayer()->opaque());
- buffer = DrawingBuffer::create(opaqueContext.get(), IntSize(), true);
+ buffer = DrawingBuffer::create(opaqueContext.get(), IntSize(), DrawingBuffer::Discard, DrawingBuffer::Opaque);
EXPECT_TRUE(buffer->platformLayer()->opaque());
}
diff --git a/Source/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h b/Source/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h
index 38876d737..513fd0cbc 100755
--- a/Source/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h
+++ b/Source/WebKit/chromium/tests/FakeCCLayerTreeHostClient.h
@@ -34,20 +34,22 @@ 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> createContext()
+ virtual void willBeginFrame() OVERRIDE { }
+ virtual void updateAnimations(double monotonicFrameBeginTime) OVERRIDE { }
+ virtual void layout() OVERRIDE { }
+ virtual void applyScrollAndScale(const IntSize& scrollDelta, float pageScale) OVERRIDE { }
+ virtual PassRefPtr<GraphicsContext3D> createContext() OVERRIDE
{
GraphicsContext3D::Attributes attrs;
return createCompositorMockGraphicsContext3D(attrs);
}
- virtual void didRecreateContext(bool success) { }
- virtual void didCommitAndDrawFrame() { }
- virtual void didCompleteSwapBuffers() { }
+ virtual void didRecreateContext(bool success) OVERRIDE { }
+ virtual void didCommit() OVERRIDE { }
+ virtual void didCommitAndDrawFrame() OVERRIDE { }
+ virtual void didCompleteSwapBuffers() OVERRIDE { }
// Used only in the single-threaded path.
- virtual void scheduleComposite() { }
+ virtual void scheduleComposite() OVERRIDE { }
};
}
diff --git a/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h b/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h
index 268dc1da3..191d05f5f 100644
--- a/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h
+++ b/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h
@@ -63,6 +63,9 @@ public:
virtual void setVisibilityCHROMIUM(bool visible) { }
+ virtual void discardFramebufferEXT(WGC3Denum target, WGC3Dsizei numAttachments, const WGC3Denum* attachments) { }
+ virtual void ensureFramebufferCHROMIUM() { }
+
virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { }
virtual WebString getRequestableExtensionsCHROMIUM() { return WebString(); }
@@ -155,7 +158,7 @@ public:
}
virtual WebString getShaderInfoLog(WebGLId shader) { return WebString(); }
-
+ virtual void getShaderPrecisionFormat(WGC3Denum shadertype, WGC3Denum precisiontype, WGC3Dint* range, WGC3Dint* precision) { }
virtual WebString getShaderSource(WebGLId shader) { return WebString(); }
virtual WebString getString(WGC3Denum name) { return WebString(); }
virtual void getTexParameterfv(WGC3Denum target, WGC3Denum pname, WGC3Dfloat* value) { }
@@ -255,6 +258,14 @@ public:
virtual void texStorage2DEXT(WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat,
WGC3Dint width, WGC3Dint height) { }
+ virtual WebGLId createQueryEXT() { return 1; }
+ virtual void deleteQueryEXT(WebGLId) { }
+ virtual GC3Dboolean isQueryEXT(WebGLId) { return true; }
+ virtual void beginQueryEXT(GC3Denum, WebGLId) { }
+ virtual void endQueryEXT(GC3Denum) { }
+ virtual void getQueryivEXT(GC3Denum, GC3Denum, GC3Dint*) { }
+ virtual void getQueryObjectuivEXT(WebGLId, GC3Denum, GC3Duint*) { }
+
protected:
Attributes m_attrs;
};
diff --git a/Source/WebKit/chromium/tests/FloatQuadTest.cpp b/Source/WebKit/chromium/tests/FloatQuadTest.cpp
index 7633dcf15..6c7091ca4 100644
--- a/Source/WebKit/chromium/tests/FloatQuadTest.cpp
+++ b/Source/WebKit/chromium/tests/FloatQuadTest.cpp
@@ -50,7 +50,7 @@ TEST(FloatQuadTest, IsRectilinearTest)
rectilinearTrans[7].rotate(180);
for (int i = 0; i < numRectilinear; ++i) {
- FloatQuad quad = rectilinearTrans[i].mapQuad(FloatRect(0.01010101, 0.01010101, 100.01010101, 100.01010101));
+ FloatQuad quad = rectilinearTrans[i].mapQuad(FloatRect(0.01010101f, 0.01010101f, 100.01010101f, 100.01010101f));
EXPECT_TRUE(quad.isRectilinear());
}
@@ -68,7 +68,7 @@ TEST(FloatQuadTest, IsRectilinearTest)
nonRectilinearTrans[9].skewY(0.00001);
for (int i = 0; i < numNonRectilinear; ++i) {
- FloatQuad quad = nonRectilinearTrans[i].mapQuad(FloatRect(0.01010101, 0.01010101, 100.01010101, 100.01010101));
+ FloatQuad quad = nonRectilinearTrans[i].mapQuad(FloatRect(0.01010101f, 0.01010101f, 100.01010101f, 100.01010101f));
EXPECT_FALSE(quad.isRectilinear());
}
}
diff --git a/Source/WebKit/chromium/tests/FrameTestHelpers.cpp b/Source/WebKit/chromium/tests/FrameTestHelpers.cpp
index ba6666699..e406413dd 100644
--- a/Source/WebKit/chromium/tests/FrameTestHelpers.cpp
+++ b/Source/WebKit/chromium/tests/FrameTestHelpers.cpp
@@ -31,7 +31,7 @@
#include "config.h"
#include "FrameTestHelpers.h"
-#include "StdLibExtras.h"
+#include <wtf/StdLibExtras.h>
#include "WebFrame.h"
#include "WebFrameClient.h"
#include "WebSettings.h"
@@ -48,6 +48,11 @@ namespace FrameTestHelpers {
void registerMockedURLLoad(const std::string& base, const std::string& fileName)
{
+ registerMockedURLLoad(GURL(base + fileName), fileName);
+}
+
+void registerMockedURLLoad(GURL url, const std::string& fileName)
+{
WebURLResponse response;
response.initialize();
response.setMIMEType("text/html");
@@ -56,7 +61,7 @@ void registerMockedURLLoad(const std::string& base, const std::string& fileName)
filePath += "/Source/WebKit/chromium/tests/data/";
filePath += fileName;
- webkit_support::RegisterMockedURL(GURL(base + fileName), response, WebString::fromUTF8(filePath));
+ webkit_support::RegisterMockedURL(url, response, WebString::fromUTF8(filePath));
}
void loadFrame(WebFrame* frame, const std::string& url)
diff --git a/Source/WebKit/chromium/tests/FrameTestHelpers.h b/Source/WebKit/chromium/tests/FrameTestHelpers.h
index 290acfe13..fc2fa2d36 100644
--- a/Source/WebKit/chromium/tests/FrameTestHelpers.h
+++ b/Source/WebKit/chromium/tests/FrameTestHelpers.h
@@ -33,6 +33,8 @@
#include <string>
+class GURL;
+
namespace WebKit {
class WebFrame;
@@ -43,6 +45,8 @@ class WebViewClient;
namespace FrameTestHelpers {
void registerMockedURLLoad(const std::string& base, const std::string& fileName);
+// Like the previous overload, but it allows more flexibility in the url since it is given by the caller.
+void registerMockedURLLoad(GURL, const std::string& fileName);
void loadFrame(WebFrame*, const std::string& url);
diff --git a/Source/WebKit/chromium/tests/LayerChromiumTest.cpp b/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
index d8858cc12..a93eac7fa 100644
--- a/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/LayerChromiumTest.cpp
@@ -26,13 +26,14 @@
#include "LayerChromium.h"
-#include "cc/CCLayerTreeHost.h"
#include "CCLayerTreeTestCommon.h"
#include "FakeCCLayerTreeHostClient.h"
#include "LayerPainterChromium.h"
#include "NonCompositedContentHost.h"
#include "WebCompositor.h"
+#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHost.h"
+#include "cc/CCSingleThreadProxy.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -77,7 +78,7 @@ protected:
{
// Initialize without threading support.
WebKit::WebCompositor::initialize(0);
- m_layerTreeHost = adoptRef(new MockCCLayerTreeHost);
+ m_layerTreeHost = adoptPtr(new MockCCLayerTreeHost);
}
virtual void TearDown()
@@ -145,7 +146,7 @@ protected:
verifyTestTreeInitialState();
}
- RefPtr<MockCCLayerTreeHost> m_layerTreeHost;
+ OwnPtr<MockCCLayerTreeHost> m_layerTreeHost;
RefPtr<LayerChromium> m_parent, m_child1, m_child2, m_child3, m_grandChild1, m_grandChild2, m_grandChild3;
};
@@ -504,8 +505,7 @@ TEST_F(LayerChromiumTest, checkPropertyChangeCausesCorrectBehavior)
// All properties need to be set to new values in order for setNeedsCommit to be called.
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->setBackgroundColor(Color(0.4f, 0.4f, 0.4f, 1.0f)));
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));
@@ -521,6 +521,7 @@ TEST_F(LayerChromiumTest, checkPropertyChangeCausesCorrectBehavior)
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setTransform(TransformationMatrix(0, 0, 0, 0, 0, 0)));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setDoubleSided(false));
EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setDebugName("Test Layer"));
+ EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setDrawCheckerboardForMissingTiles(!testLayer->drawCheckerboardForMissingTiles()));
// The above tests should not have caused a change to the needsDisplay flag.
EXPECT_FALSE(testLayer->needsDisplay());
@@ -530,6 +531,29 @@ TEST_F(LayerChromiumTest, checkPropertyChangeCausesCorrectBehavior)
EXPECT_TRUE(testLayer->needsDisplay());
}
+TEST_F(LayerChromiumTest, verifyPushPropertiesAccumulatesUpdateRect)
+{
+ DebugScopedSetImplThread setImplThread;
+
+ RefPtr<LayerChromium> testLayer = LayerChromium::create();
+ OwnPtr<CCLayerImpl> implLayer = CCLayerImpl::create(1);
+
+ testLayer->setNeedsDisplayRect(FloatRect(FloatPoint::zero(), FloatSize(5, 5)));
+ testLayer->pushPropertiesTo(implLayer.get());
+ EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint::zero(), FloatSize(5, 5)), implLayer->updateRect());
+
+ // The CCLayerImpl's updateRect should be accumulated here, since we did not do anything to clear it.
+ testLayer->setNeedsDisplayRect(FloatRect(FloatPoint(10, 10), FloatSize(5, 5)));
+ testLayer->pushPropertiesTo(implLayer.get());
+ EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint::zero(), FloatSize(15, 15)), implLayer->updateRect());
+
+ // If we do clear the CCLayerImpl side, then the next updateRect should be fresh without accumulation.
+ implLayer->resetAllChangeTrackingForSubtree();
+ testLayer->setNeedsDisplayRect(FloatRect(FloatPoint(10, 10), FloatSize(5, 5)));
+ testLayer->pushPropertiesTo(implLayer.get());
+ EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(10, 10), FloatSize(5, 5)), implLayer->updateRect());
+}
+
class LayerChromiumWithContentScaling : public LayerChromium {
public:
explicit LayerChromiumWithContentScaling()
@@ -537,12 +561,12 @@ public:
{
}
- virtual bool needsContentsScale() const
+ virtual bool needsContentsScale() const OVERRIDE
{
return true;
}
- virtual void setNeedsDisplayRect(const FloatRect& dirtyRect)
+ virtual void setNeedsDisplayRect(const FloatRect& dirtyRect) OVERRIDE
{
m_lastNeedsDisplayRect = dirtyRect;
LayerChromium::setNeedsDisplayRect(dirtyRect);
@@ -577,9 +601,9 @@ TEST_F(LayerChromiumTest, checkContentsScaleChangeTriggersNeedsDisplay)
class FakeCCLayerTreeHost : public CCLayerTreeHost {
public:
- static PassRefPtr<FakeCCLayerTreeHost> create()
+ static PassOwnPtr<FakeCCLayerTreeHost> create()
{
- RefPtr<FakeCCLayerTreeHost> host = adoptRef(new FakeCCLayerTreeHost);
+ OwnPtr<FakeCCLayerTreeHost> host(adoptPtr(new FakeCCLayerTreeHost));
// The initialize call will fail, since our client doesn't provide a valid GraphicsContext3D, but it doesn't matter in the tests that use this fake so ignore the return value.
host->initialize();
return host.release();
@@ -626,7 +650,7 @@ TEST(LayerChromiumLayerTreeHostTest, enteringTree)
assertLayerTreeHostMatchesForSubtree(parent.get(), 0);
- RefPtr<FakeCCLayerTreeHost> layerTreeHost = FakeCCLayerTreeHost::create();
+ OwnPtr<FakeCCLayerTreeHost> layerTreeHost(FakeCCLayerTreeHost::create());
// Setting the root layer should set the host pointer for all layers in the tree.
layerTreeHost->setRootLayer(parent.get());
@@ -645,7 +669,7 @@ TEST(LayerChromiumLayerTreeHostTest, addingLayerSubtree)
{
WebKit::WebCompositor::initialize(0);
RefPtr<LayerChromium> parent = LayerChromium::create();
- RefPtr<FakeCCLayerTreeHost> layerTreeHost = FakeCCLayerTreeHost::create();
+ OwnPtr<FakeCCLayerTreeHost> layerTreeHost(FakeCCLayerTreeHost::create());
layerTreeHost->setRootLayer(parent.get());
@@ -687,14 +711,14 @@ TEST(LayerChromiumLayerTreeHostTest, changeHost)
child->setReplicaLayer(replica.get());
replica->setMaskLayer(mask.get());
- RefPtr<FakeCCLayerTreeHost> firstLayerTreeHost = FakeCCLayerTreeHost::create();
+ OwnPtr<FakeCCLayerTreeHost> firstLayerTreeHost(FakeCCLayerTreeHost::create());
firstLayerTreeHost->setRootLayer(parent.get());
assertLayerTreeHostMatchesForSubtree(parent.get(), firstLayerTreeHost.get());
// Now re-root the tree to a new host (simulating what we do on a context lost event).
// This should update the host pointers for all layers in the tree.
- RefPtr<FakeCCLayerTreeHost> secondLayerTreeHost = FakeCCLayerTreeHost::create();
+ OwnPtr<FakeCCLayerTreeHost> secondLayerTreeHost(FakeCCLayerTreeHost::create());
secondLayerTreeHost->setRootLayer(parent.get());
assertLayerTreeHostMatchesForSubtree(parent.get(), secondLayerTreeHost.get());
@@ -719,13 +743,13 @@ TEST(LayerChromiumLayerTreeHostTest, changeHostInSubtree)
secondChild->addChild(secondGrandChild);
firstParent->addChild(secondChild);
- RefPtr<FakeCCLayerTreeHost> firstLayerTreeHost = FakeCCLayerTreeHost::create();
+ OwnPtr<FakeCCLayerTreeHost> firstLayerTreeHost(FakeCCLayerTreeHost::create());
firstLayerTreeHost->setRootLayer(firstParent.get());
assertLayerTreeHostMatchesForSubtree(firstParent.get(), firstLayerTreeHost.get());
// Now reparent the subtree starting at secondChild to a layer in a different tree.
- RefPtr<FakeCCLayerTreeHost> secondLayerTreeHost = FakeCCLayerTreeHost::create();
+ OwnPtr<FakeCCLayerTreeHost> secondLayerTreeHost(FakeCCLayerTreeHost::create());
secondLayerTreeHost->setRootLayer(secondParent.get());
secondParent->addChild(secondChild);
@@ -758,7 +782,7 @@ TEST(LayerChromiumLayerTreeHostTest, replaceMaskAndReplicaLayer)
mask->addChild(maskChild);
replica->addChild(replicaChild);
- RefPtr<FakeCCLayerTreeHost> layerTreeHost = FakeCCLayerTreeHost::create();
+ OwnPtr<FakeCCLayerTreeHost> layerTreeHost(FakeCCLayerTreeHost::create());
layerTreeHost->setRootLayer(parent.get());
assertLayerTreeHostMatchesForSubtree(parent.get(), layerTreeHost.get());
diff --git a/Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp b/Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp
new file mode 100644
index 000000000..ddab17564
--- /dev/null
+++ b/Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp
@@ -0,0 +1,277 @@
+/*
+ * 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 "LayerRendererChromium.h"
+
+#include "FakeWebGraphicsContext3D.h"
+#include "GraphicsContext3D.h"
+#include "GraphicsContext3DPrivate.h"
+#include "cc/CCSingleThreadProxy.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+using namespace WebKit;
+
+class FrameCountingMemoryAllocationSettingContext : public FakeWebGraphicsContext3D {
+public:
+ FrameCountingMemoryAllocationSettingContext() : m_frame(0) { }
+
+ // WebGraphicsContext3D methods.
+
+ // This method would normally do a glSwapBuffers under the hood.
+ virtual void prepareTexture() { m_frame++; }
+ virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { m_memoryAllocationChangedCallback = callback; }
+ virtual WebString getString(WebKit::WGC3Denum name)
+ {
+ if (name == GraphicsContext3D::EXTENSIONS)
+ return WebString("GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager GL_CHROMIUM_discard_framebuffer");
+ return WebString();
+ }
+
+ // Methods added for test.
+ int frameCount() { return m_frame; }
+ void setMemoryAllocation(WebGraphicsMemoryAllocation allocation) { m_memoryAllocationChangedCallback->onMemoryAllocationChanged(allocation); }
+
+private:
+ int m_frame;
+ WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* m_memoryAllocationChangedCallback;
+};
+
+class FakeLayerRendererChromiumClient : public LayerRendererChromiumClient {
+public:
+ FakeLayerRendererChromiumClient()
+ : m_setFullRootLayerDamageCount(0)
+ , m_rootLayer(CCLayerImpl::create(1))
+ {
+ m_rootLayer->createRenderSurface();
+ }
+
+ // LayerRendererChromiumClient methods.
+ virtual const IntSize& viewportSize() const OVERRIDE { static IntSize fakeSize; return fakeSize; }
+ virtual const CCSettings& settings() const OVERRIDE { static CCSettings fakeSettings; return fakeSettings; }
+ virtual void didLoseContext() OVERRIDE { }
+ virtual void onSwapBuffersComplete() OVERRIDE { }
+ virtual void setFullRootLayerDamage() OVERRIDE { m_setFullRootLayerDamageCount++; }
+ virtual void setContentsMemoryAllocationLimitBytes(size_t) OVERRIDE { }
+
+ // Methods added for test.
+ int setFullRootLayerDamageCount() const { return m_setFullRootLayerDamageCount; }
+
+ CCLayerImpl* rootLayer() { return m_rootLayer.get(); }
+
+private:
+ int m_setFullRootLayerDamageCount;
+ DebugScopedSetImplThread m_implThread;
+ OwnPtr<CCLayerImpl> m_rootLayer;
+};
+
+class FakeLayerRendererChromium : public LayerRendererChromium {
+public:
+ FakeLayerRendererChromium(LayerRendererChromiumClient* client, PassRefPtr<GraphicsContext3D> context) : LayerRendererChromium(client, context) { }
+
+ // LayerRendererChromium methods.
+
+ // Changing visibility to public.
+ using LayerRendererChromium::initialize;
+ using LayerRendererChromium::isFramebufferDiscarded;
+};
+
+class LayerRendererChromiumTest : public testing::Test {
+protected:
+ LayerRendererChromiumTest()
+ : m_suggestHaveBackbufferYes(1, true)
+ , m_suggestHaveBackbufferNo(1, false)
+ , m_context(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FrameCountingMemoryAllocationSettingContext()), GraphicsContext3D::RenderDirectlyToHostWindow))
+ , m_mockContext(*static_cast<FrameCountingMemoryAllocationSettingContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_context.get())))
+ , m_layerRendererChromium(&m_mockClient, m_context.release())
+ {
+ }
+
+ virtual void SetUp()
+ {
+ m_layerRendererChromium.initialize();
+ }
+
+ void swapBuffers()
+ {
+ m_layerRendererChromium.swapBuffers(IntRect());
+ }
+
+ WebGraphicsMemoryAllocation m_suggestHaveBackbufferYes;
+ WebGraphicsMemoryAllocation m_suggestHaveBackbufferNo;
+
+ RefPtr<GraphicsContext3D> m_context;
+ FrameCountingMemoryAllocationSettingContext& m_mockContext;
+ FakeLayerRendererChromiumClient m_mockClient;
+ FakeLayerRendererChromium m_layerRendererChromium;
+};
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Suggest recreating framebuffer when one already exists.
+// Expected: it does nothing.
+TEST_F(LayerRendererChromiumTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferYes);
+ EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
+ EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
+
+ swapBuffers();
+ EXPECT_EQ(1, m_mockContext.frameCount());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Suggest discarding framebuffer when one exists.
+// Expected: it is discarded and damage tracker is reset.
+TEST_F(LayerRendererChromiumTest, SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayer)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Suggest discarding framebuffer when one does not exist.
+// Expected: it does nothing.
+TEST_F(LayerRendererChromiumTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Suggest discarding framebuffer, then try to swapBuffers.
+// Expected: framebuffer is discarded, swaps are ignored, and damage is reset after discard and after each swap.
+TEST_F(LayerRendererChromiumTest, SwapBuffersWhileBackbufferDiscardedShouldIgnoreSwapAndDamageRootLayer)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+
+ swapBuffers();
+ EXPECT_EQ(0, m_mockContext.frameCount());
+ EXPECT_EQ(2, m_mockClient.setFullRootLayerDamageCount());
+
+ swapBuffers();
+ EXPECT_EQ(0, m_mockContext.frameCount());
+ EXPECT_EQ(3, m_mockClient.setFullRootLayerDamageCount());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Begin drawing a frame while a framebuffer is discarded.
+// Expected: will recreate framebuffer.
+TEST_F(LayerRendererChromiumTest, DiscardedBackbufferIsRecreatredForScopeDuration)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+
+ m_layerRendererChromium.beginDrawingFrame(m_mockClient.rootLayer()->renderSurface());
+ EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
+
+ swapBuffers();
+ EXPECT_EQ(1, m_mockContext.frameCount());
+}
+
+class ForbidSynchronousCallContext : public FakeWebGraphicsContext3D {
+public:
+ ForbidSynchronousCallContext() { }
+
+ virtual bool getActiveAttrib(WebGLId program, WGC3Duint index, ActiveInfo&) { ADD_FAILURE(); return false; }
+ virtual bool getActiveUniform(WebGLId program, WGC3Duint index, ActiveInfo&) { ADD_FAILURE(); return false; }
+ virtual void getAttachedShaders(WebGLId program, WGC3Dsizei maxCount, WGC3Dsizei* count, WebGLId* shaders) { ADD_FAILURE(); }
+ virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) { ADD_FAILURE(); return 0; }
+ virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) { ADD_FAILURE(); }
+ virtual void getBufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
+ virtual Attributes getContextAttributes() { ADD_FAILURE(); return m_attrs; }
+ virtual WGC3Denum getError() { ADD_FAILURE(); return 0; }
+ virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
+ virtual void getFramebufferAttachmentParameteriv(WGC3Denum target, WGC3Denum attachment, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
+ virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value)
+ {
+ if (pname == WebCore::GraphicsContext3D::MAX_TEXTURE_SIZE)
+ *value = 1024; // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
+ else
+ ADD_FAILURE();
+ }
+
+ // We allow querying the shader compilation and program link status in debug mode, but not release.
+ virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
+ {
+#ifndef NDEBUG
+ *value = 1;
+#else
+ ADD_FAILURE();
+#endif
+ }
+
+ virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
+ {
+#ifndef NDEBUG
+ *value = 1;
+#else
+ ADD_FAILURE();
+#endif
+ }
+
+ virtual WebString getString(WGC3Denum name)
+ {
+ // We allow querying the extension string.
+ // FIXME: It'd be better to check that we only do this before starting any other expensive work (like starting a compilation)
+ if (name != WebCore::GraphicsContext3D::EXTENSIONS)
+ ADD_FAILURE();
+ return WebString();
+ }
+
+ virtual WebString getProgramInfoLog(WebGLId program) { ADD_FAILURE(); return WebString(); }
+ virtual void getRenderbufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
+
+ virtual WebString getShaderInfoLog(WebGLId shader) { ADD_FAILURE(); return WebString(); }
+ virtual void getShaderPrecisionFormat(WGC3Denum shadertype, WGC3Denum precisiontype, WGC3Dint* range, WGC3Dint* precision) { ADD_FAILURE(); }
+ virtual WebString getShaderSource(WebGLId shader) { ADD_FAILURE(); return WebString(); }
+ virtual void getTexParameterfv(WGC3Denum target, WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
+ virtual void getTexParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
+ virtual void getUniformfv(WebGLId program, WGC3Dint location, WGC3Dfloat* value) { ADD_FAILURE(); }
+ virtual void getUniformiv(WebGLId program, WGC3Dint location, WGC3Dint* value) { ADD_FAILURE(); }
+ virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name) { ADD_FAILURE(); return 0; }
+ virtual void getVertexAttribfv(WGC3Duint index, WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
+ virtual void getVertexAttribiv(WGC3Duint index, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
+ virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index, WGC3Denum pname) { ADD_FAILURE(); return 0; }
+};
+
+// This test isn't using the same fixture as LayerRendererChromiumTest, and you can't mix TEST() and TEST_F() with the same name, hence LRC2.
+TEST(LayerRendererChromiumTest2, initializationDoesNotMakeSynchronousCalls)
+{
+ FakeLayerRendererChromiumClient mockClient;
+ FakeLayerRendererChromium layerRendererChromium(&mockClient, GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ForbidSynchronousCallContext), GraphicsContext3D::RenderDirectlyToHostWindow));
+
+ EXPECT_TRUE(layerRendererChromium.initialize());
+}
diff --git a/Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp b/Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp
index bdbf7bb09..d1a97bb5b 100644
--- a/Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp
+++ b/Source/WebKit/chromium/tests/LayerTextureUpdaterTest.cpp
@@ -79,6 +79,27 @@ struct PaintFillAlpha : public PaintCallback {
}
};
+struct PaintFillPartialOpaque : public PaintCallback {
+ PaintFillPartialOpaque(IntRect opaqueRect)
+ : m_opaqueRect(opaqueRect)
+ {
+ }
+
+ virtual void operator()(GraphicsContext& context, const IntRect& contentRect)
+ {
+ Color alpha(0, 0, 0, 0);
+ context.fillRect(contentRect, alpha, ColorSpaceDeviceRGB);
+
+ IntRect fillOpaque = m_opaqueRect;
+ fillOpaque.intersect(contentRect);
+
+ Color opaque(255, 255, 255, 255);
+ context.fillRect(fillOpaque, opaque, ColorSpaceDeviceRGB);
+ }
+
+ IntRect m_opaqueRect;
+};
+
#define EXPECT_EQ_RECT(a, b) \
EXPECT_EQ(a.x(), b.x()); \
EXPECT_EQ(a.maxX(), b.maxX()); \
@@ -95,19 +116,19 @@ TEST(LayerTextureUpdaterTest, testOpaqueRectPresentAfterOpaquePaint)
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);
+ 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);
+ 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);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, opaqueRect);
EXPECT_EQ_RECT(IntRect(0, 0, 400, 400), opaqueRect);
}
@@ -121,19 +142,19 @@ TEST(LayerTextureUpdaterTest, testOpaqueRectNotPresentAfterNonOpaquePaint)
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);
+ 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);
+ 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);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, opaqueRect);
EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
}
@@ -148,21 +169,21 @@ TEST(LayerTextureUpdaterTest, testOpaqueRectNotPresentForOpaqueLayerWithOpaquePa
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);
+ 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);
+ 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);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, opaqueRect);
EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
}
@@ -177,22 +198,70 @@ TEST(LayerTextureUpdaterTest, testOpaqueRectNotPresentForOpaqueLayerWithNonOpaqu
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);
+ 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);
+ 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);
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, opaqueRect);
EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), opaqueRect);
}
+TEST(LayerTextureUpdaterTest, testPartialOpaqueRectNoTransform)
+{
+ IntRect partialRect(100, 200, 50, 75);
+ PaintFillPartialOpaque fillPartial(partialRect);
+ OwnPtr<TestLayerPainterChromium> painter(adoptPtr(new TestLayerPainterChromium(fillPartial)));
+ RefPtr<LayerTextureUpdater> updater = BitmapCanvasLayerTextureUpdater::create(painter.release(), false);
+
+ IntRect opaqueRect;
+ updater->prepareToUpdate(IntRect(0, 0, 400, 400), IntSize(400, 400), 0, 1, opaqueRect);
+ EXPECT_EQ_RECT(partialRect, opaqueRect);
+}
+
+TEST(LayerTextureUpdaterTest, testPartialOpaqueRectTranslation)
+{
+ IntRect partialRect(100, 200, 50, 75);
+ PaintFillPartialOpaque fillPartial(partialRect);
+
+ OwnPtr<TestLayerPainterChromium> painter(adoptPtr(new TestLayerPainterChromium(fillPartial)));
+ RefPtr<LayerTextureUpdater> updater = BitmapCanvasLayerTextureUpdater::create(painter.release(), false);
+
+ IntRect opaqueRect;
+ IntRect contentRect(11, 12, 389, 388);
+ updater->prepareToUpdate(contentRect, IntSize(400, 400), 0, 1, opaqueRect);
+ EXPECT_EQ_RECT(partialRect, opaqueRect);
+}
+
+TEST(LayerTextureUpdaterTest, testPartialOpaqueRectScale)
+{
+ float contentsScale = 0.5;
+
+ IntRect partialRect(9, 20, 50, 75);
+ IntRect partialDeviceRect(partialRect);
+ PaintFillPartialOpaque fillPartial(partialDeviceRect);
+ OwnPtr<TestLayerPainterChromium> painter(adoptPtr(new TestLayerPainterChromium(fillPartial)));
+ RefPtr<LayerTextureUpdater> updater = BitmapCanvasLayerTextureUpdater::create(painter.release(), false);
+
+ IntRect opaqueRect;
+ IntRect contentRect(4, 6, 396, 394);
+ updater->prepareToUpdate(contentRect, IntSize(400, 400), 0, contentsScale, opaqueRect);
+
+ // Original rect: 9, 20, 50, 75
+ // Scaled down to half size: 4.5, 10, 25, 37.5
+ // Enclosed int rect: 5, 10, 24, 37
+ // Scaled back up to content: 10, 20, 48, 74
+ IntRect scaledRect(10, 20, 48, 74);
+ EXPECT_EQ_RECT(scaledRect, opaqueRect);
+}
+
} // namespace
diff --git a/Source/WebKit/chromium/tests/LevelDBTest.cpp b/Source/WebKit/chromium/tests/LevelDBTest.cpp
new file mode 100644
index 000000000..2a00ae686
--- /dev/null
+++ b/Source/WebKit/chromium/tests/LevelDBTest.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(LEVELDB)
+
+#include "FileSystem.h"
+#include "LevelDBComparator.h"
+#include "LevelDBDatabase.h"
+#include "LevelDBSlice.h"
+#include <gtest/gtest.h>
+#include <webkit/support/webkit_support.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace {
+
+class SimpleComparator : public LevelDBComparator {
+public:
+ virtual int compare(const LevelDBSlice& a, const LevelDBSlice& b) const OVERRIDE
+ {
+ size_t len = std::min(a.end() - a.begin(), b.end() - b.begin());
+ return memcmp(a.begin(), b.begin(), len);
+ }
+ virtual const char* name() const OVERRIDE { return "temp_comparator"; }
+};
+
+Vector<char> encodeString(const std::string& s)
+{
+ Vector<char> ret(s.size());
+ for (size_t i = 0; i < s.size(); ++i)
+ ret.append(s[i]);
+ return ret;
+}
+
+TEST(LevelDBDatabaseTest, CorruptionTest)
+{
+ OwnPtr<webkit_support::ScopedTempDirectory> tempDirectory = adoptPtr(webkit_support::CreateScopedTempDirectory());
+ tempDirectory->CreateUniqueTempDir();
+ const String path = String::fromUTF8(tempDirectory->path().c_str());
+
+ const Vector<char> key = encodeString("key");
+ const Vector<char> putValue = encodeString("value");
+ Vector<char> gotValue;
+ SimpleComparator comparator;
+
+ OwnPtr<LevelDBDatabase> leveldb = LevelDBDatabase::open(path, &comparator);
+ EXPECT_TRUE(leveldb);
+ bool success = leveldb->put(key, putValue);
+ EXPECT_TRUE(success);
+ leveldb.release();
+ EXPECT_FALSE(leveldb);
+
+ leveldb = LevelDBDatabase::open(path, &comparator);
+ EXPECT_TRUE(leveldb);
+ success = leveldb->get(key, gotValue);
+ EXPECT_TRUE(success);
+ EXPECT_EQ(putValue, gotValue);
+ leveldb.release();
+ EXPECT_FALSE(leveldb);
+
+ const String filepath = pathByAppendingComponent(path, "CURRENT");
+ PlatformFileHandle handle = openFile(filepath, OpenForWrite);
+ truncateFile(handle, 0);
+ closeFile(handle);
+
+ leveldb = LevelDBDatabase::open(path, &comparator);
+ EXPECT_FALSE(leveldb);
+
+ bool destroyed = LevelDBDatabase::destroy(path);
+ EXPECT_TRUE(destroyed);
+
+ leveldb = LevelDBDatabase::open(path, &comparator);
+ EXPECT_TRUE(leveldb);
+ success = leveldb->get(key, gotValue);
+ EXPECT_FALSE(success);
+}
+
+} // namespace
+
+#endif // USE(LEVELDB)
diff --git a/Source/WebKit/chromium/tests/LocaleWinTest.cpp b/Source/WebKit/chromium/tests/LocaleWinTest.cpp
new file mode 100644
index 000000000..d64e902a5
--- /dev/null
+++ b/Source/WebKit/chromium/tests/LocaleWinTest.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LocaleWin.h"
+
+#include <gtest/gtest.h>
+#include <wtf/DateMath.h>
+#include <wtf/MathExtras.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+using namespace std;
+
+enum {
+ January = 0, February, March,
+ April, May, June,
+ July, August, September,
+ October, November, December,
+};
+
+static double msForDate(int year, int month, int day)
+{
+ return dateToDaysFrom1970(year, month, day) * msPerDay;
+}
+
+TEST(LocaleWinTest, TestLocalizedDateFormatText)
+{
+ EXPECT_STREQ("year/month/day", LocaleWin::dateFormatText("y/M/d", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("year/month/day", LocaleWin::dateFormatText("yy/MM/dd", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("year/month/day", LocaleWin::dateFormatText("yyy/MMM/ddd", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("year/month/day", LocaleWin::dateFormatText("yyyy/MMMM/dddd", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("/month/day, year", LocaleWin::dateFormatText("/MM/dd, yyyy", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("month/day, year=year.", LocaleWin::dateFormatText("MM/dd, 'year='yyyy.", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("month-day 'year", LocaleWin::dateFormatText("MM-dd ''yyy", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("month-day aaa'bbb year", LocaleWin::dateFormatText("MM-dd 'aaa''bbb' yyy", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("year/month/day/year/month/day", LocaleWin::dateFormatText("yyyy/MMMM/dddd/yyyy/MMMM/dddd", "year", "month", "day").utf8().data());
+ EXPECT_STREQ("YY/mm/DD", LocaleWin::dateFormatText("YY/mm/DD", "year", "month", "day").utf8().data());
+}
+
+TEST(LocaleWinTest, TestFormat)
+{
+ const LCID EnglishUS = 0x0409;
+ OwnPtr<LocaleWin> locale = LocaleWin::create(EnglishUS);
+
+ EXPECT_STREQ("4/7/2", locale->formatDate("M/d/y", 2012, 2012, April, 7).utf8().data());
+ EXPECT_STREQ("4/7/2007", locale->formatDate("M/d/y", 2012, 2007, April, 7).utf8().data());
+ EXPECT_STREQ("4/7/8", locale->formatDate("M/d/y", 2012, 2008, April, 7).utf8().data());
+ EXPECT_STREQ("4/7/7", locale->formatDate("M/d/y", 2012, 2017, April, 7).utf8().data());
+ EXPECT_STREQ("4/7/2018", locale->formatDate("M/d/y", 2012, 2018, April, 7).utf8().data());
+ EXPECT_STREQ("12/31/2062", locale->formatDate("M/d/y", 2012, 2062, December, 31).utf8().data());
+ EXPECT_STREQ("4/7/0002", locale->formatDate("M/d/y", 2012, 2, April, 7).utf8().data());
+
+ EXPECT_STREQ("04/27/12", locale->formatDate("MM/dd/yy", 2012, 2012, April, 27).utf8().data());
+ EXPECT_STREQ("04/07/1962", locale->formatDate("MM/dd/yy", 2012, 1962, April, 7).utf8().data());
+ EXPECT_STREQ("04/07/63", locale->formatDate("MM/dd/yy", 2012, 1963, April, 7).utf8().data());
+ EXPECT_STREQ("01/31/00", locale->formatDate("MM/dd/yy", 2012, 2000, January, 31).utf8().data());
+ EXPECT_STREQ("04/07/62", locale->formatDate("MM/dd/yy", 2012, 2062, April, 7).utf8().data());
+ EXPECT_STREQ("04/07/2063", locale->formatDate("MM/dd/yy", 2012, 2063, April, 7).utf8().data());
+ EXPECT_STREQ("04/07/0001", locale->formatDate("MM/dd/yy", 2012, 1, April, 7).utf8().data());
+
+ EXPECT_STREQ("Jan/7/2012", locale->formatDate("MMM/d/yyyy", 2012, 2012, January, 7).utf8().data());
+ EXPECT_STREQ("Feb/7/2008", locale->formatDate("MMM/d/yyyy", 2012, 2008, February, 7).utf8().data());
+ EXPECT_STREQ("Mar/7/2017", locale->formatDate("MMM/d/yyyy", 2012, 2017, March, 7).utf8().data());
+ EXPECT_STREQ("Apr/7/2012", locale->formatDate("MMM/d/yyyy", 2012, 2012, April, 7).utf8().data());
+ EXPECT_STREQ("May/7/0002", locale->formatDate("MMM/d/yyyy", 2012, 2, May, 7).utf8().data());
+ EXPECT_STREQ("Jun/7/2008", locale->formatDate("MMM/d/yyyy", 2012, 2008, June, 7).utf8().data());
+ EXPECT_STREQ("Jul/7/2017", locale->formatDate("MMM/d/yyyy", 2012, 2017, July, 7).utf8().data());
+ EXPECT_STREQ("Aug/31/2062", locale->formatDate("MMM/d/yyyy", 2012, 2062, August, 31).utf8().data());
+ EXPECT_STREQ("Sep/7/0002", locale->formatDate("MMM/d/yyyy", 2012, 2, September, 7).utf8().data());
+ EXPECT_STREQ("Oct/7/2012", locale->formatDate("MMM/d/yyyy", 2012, 2012, October, 7).utf8().data());
+ EXPECT_STREQ("Nov/7/2008", locale->formatDate("MMM/d/yyyy", 2012, 2008, November, 7).utf8().data());
+ EXPECT_STREQ("Dec/31/2062", locale->formatDate("MMM/d/yyyy", 2012, 2062, December, 31).utf8().data());
+
+ EXPECT_STREQ("January-7-2017", locale->formatDate("MMMM-d-yyyy", 2012, 2017, January, 7).utf8().data());
+ EXPECT_STREQ("February-31-2062", locale->formatDate("MMMM-d-yyyy", 2012, 2062, February, 31).utf8().data());
+ EXPECT_STREQ("March-7-0002", locale->formatDate("MMMM-d-yyyy", 2012, 2, March, 7).utf8().data());
+ EXPECT_STREQ("April-7-22012", locale->formatDate("MMMM-d-yyyy", 2012, 22012, April, 7).utf8().data());
+ EXPECT_STREQ("May-7-12008", locale->formatDate("MMMM-d-yyyy", 2012, 12008, May, 7).utf8().data());
+ EXPECT_STREQ("June-7-22012", locale->formatDate("MMMM-d-yyyy", 2012, 22012, June, 7).utf8().data());
+ EXPECT_STREQ("July-7-12008", locale->formatDate("MMMM-d-yyyy", 2012, 12008, July, 7).utf8().data());
+ EXPECT_STREQ("August-7-2017", locale->formatDate("MMMM-d-yyyy", 2012, 2017, August, 7).utf8().data());
+ EXPECT_STREQ("September-31-2062", locale->formatDate("MMMM-d-yyyy", 2012, 2062, September, 31).utf8().data());
+ EXPECT_STREQ("October-7-0002", locale->formatDate("MMMM-d-yyyy", 2012, 2, October, 7).utf8().data());
+ EXPECT_STREQ("November-7-22012", locale->formatDate("MMMM-d-yyyy", 2012, 22012, November, 7).utf8().data());
+ EXPECT_STREQ("December-7-12008", locale->formatDate("MMMM-d-yyyy", 2012, 12008, December, 7).utf8().data());
+
+ EXPECT_STREQ("Jan-1-0001", locale->formatDate("MMM-d-yyyy", 2012, 1, January, 1).utf8().data());
+ EXPECT_STREQ("Sep-13-275760", locale->formatDate("MMM-d-yyyy", 2012, 275760, September, 13).utf8().data());
+
+
+ // For the following test, we'd like to confirm they don't crash and their
+ // results are not important because we can assume invalid arguments are
+ // never passed.
+ EXPECT_STREQ("2012-13-00", locale->formatDate("yyyy-MM-dd", -1, 2012, December + 1, 0).utf8().data());
+ EXPECT_STREQ("-1-00--1", locale->formatDate("y-MM-dd", -1, -1, -1, -1).utf8().data());
+ EXPECT_STREQ("-1-124-33", locale->formatDate("y-MM-dd", 2012, -1, 123, 33).utf8().data());
+
+}
+
+TEST(LocaleWinTest, TestParse)
+{
+ const LCID EnglishUS = 0x0409;
+ OwnPtr<LocaleWin> locale = LocaleWin::create(EnglishUS);
+
+ EXPECT_EQ(msForDate(2012, April, 27), locale->parseDate("MM/dd/yy", 2012, "04/27/12"));
+ EXPECT_EQ(msForDate(2062, April, 27), locale->parseDate("MM/dd/yy", 2012, "04/27/62"));
+ EXPECT_EQ(msForDate(1963, April, 27), locale->parseDate("MM/dd/yy", 2012, "04/27/63"));
+ EXPECT_EQ(msForDate(2012, April, 27), locale->parseDate("MM/dd/yy", 2012, "4/27/2012"));
+ EXPECT_EQ(msForDate(2012, April, 27), locale->parseDate("MM/dd/yy", 2012, "Apr/27/2012"));
+ EXPECT_EQ(msForDate(2, April, 27), locale->parseDate("MM/d/yy", 2012, "April/27/2"));
+ EXPECT_EQ(msForDate(2, April, 27), locale->parseDate("MM/d/yy", 2012, "april/27/2"));
+ EXPECT_TRUE(isnan(locale->parseDate("MM/d/yy", 2012, "april/27")));
+ EXPECT_TRUE(isnan(locale->parseDate("MM/d/yy", 2012, "april/27/")));
+ EXPECT_TRUE(isnan(locale->parseDate("MM/d/yy", 2012, " april/27/")));
+
+ EXPECT_EQ(msForDate(12, April, 7), locale->parseDate("MMM/d/yyyy", 2012, "04/7/12"));
+ EXPECT_EQ(msForDate(62, April, 7), locale->parseDate("MMM/d/yyyy", 2012, "04/07/62"));
+ EXPECT_EQ(msForDate(63, April, 7), locale->parseDate("MMM/d/yyyy", 2012, "04/07/63"));
+ EXPECT_EQ(msForDate(2012, April, 7), locale->parseDate("MMM/d/yyyy", 2012, "4/7/2012"));
+ EXPECT_EQ(msForDate(2012, May, 7), locale->parseDate("MMM/d/yyyy", 2012, "May/007/2012"));
+ EXPECT_EQ(msForDate(2, May, 27), locale->parseDate("MM/d/yyyy", 2012, "May/0027/2"));
+ EXPECT_TRUE(isnan(locale->parseDate("MM/d/yyyy", 2012, "May///0027///2")));
+ EXPECT_TRUE(isnan(locale->parseDate("MM/d/yyyy", 2012, "Mayyyyyy/0027/2")));
+
+ EXPECT_EQ(msForDate(2012, April, 27), locale->parseDate("MMMM/dd/y", 2012, "04/27/2"));
+ EXPECT_EQ(msForDate(2017, April, 27), locale->parseDate("MMMM/dd/y", 2012, "04/27/7"));
+ EXPECT_EQ(msForDate(2008, April, 27), locale->parseDate("MMMM/dd/y", 2012, "04/27/8"));
+ EXPECT_EQ(msForDate(2012, April, 27), locale->parseDate("MMMM/dd/y", 2012, "4/27/2012"));
+ EXPECT_EQ(msForDate(2012, December, 27), locale->parseDate("MMMM/dd/y", 2012, "December/27/2012"));
+ EXPECT_EQ(msForDate(2012, November, 27), locale->parseDate("MMMM/d/y", 2012, "November/27/2"));
+ EXPECT_TRUE(isnan(locale->parseDate("MMMM/d/y", 2012, "November 27 2")));
+ EXPECT_TRUE(isnan(locale->parseDate("MMMM/d/y", 2012, "November 32 2")));
+ EXPECT_TRUE(isnan(locale->parseDate("MMMM/d/y", 2012, "-1/-1/-1")));
+}
diff --git a/Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp b/Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp
index 6203d35d7..92f85c6bb 100644
--- a/Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp
+++ b/Source/WebKit/chromium/tests/LocalizedNumberICUTest.cpp
@@ -29,8 +29,8 @@
*/
#include "config.h"
-#include "LocalizedNumberICU.h"
+#include "LocaleICU.h"
#include <gtest/gtest.h>
#include <wtf/PassOwnPtr.h>
@@ -38,7 +38,7 @@ using namespace WebCore;
void testNumberIsReversible(const char* localeString, const char* original, const char* shouldHave = 0)
{
- OwnPtr<ICULocale> locale = ICULocale::create(localeString);
+ OwnPtr<LocaleICU> locale = LocaleICU::create(localeString);
String localized = locale->convertToLocalizedNumber(original);
if (shouldHave)
EXPECT_TRUE(localized.contains(shouldHave));
diff --git a/Source/WebKit/chromium/tests/MockCCQuadCuller.h b/Source/WebKit/chromium/tests/MockCCQuadCuller.h
new file mode 100644
index 000000000..d9cd31326
--- /dev/null
+++ b/Source/WebKit/chromium/tests/MockCCQuadCuller.h
@@ -0,0 +1,65 @@
+/*
+ * 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 MockCCQuadCuller_h
+#define MockCCQuadCuller_h
+
+#include "IntRect.h"
+#include "cc/CCDrawQuad.h"
+#include "cc/CCQuadCuller.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class MockCCQuadCuller : public WebCore::CCQuadCuller {
+public:
+ MockCCQuadCuller()
+ : CCQuadCuller(m_quadListStorage, 0, 0)
+ , m_activeQuadList(m_quadListStorage)
+ { }
+
+ explicit MockCCQuadCuller(CCQuadList& externalQuadList)
+ : CCQuadCuller(externalQuadList, 0, 0)
+ , m_activeQuadList(externalQuadList)
+ { }
+
+ virtual bool append(WTF::PassOwnPtr<WebCore::CCDrawQuad> newQuad)
+ {
+ OwnPtr<WebCore::CCDrawQuad> drawQuad = newQuad;
+ if (!drawQuad->quadRect().isEmpty()) {
+ m_activeQuadList.append(drawQuad.release());
+ return true;
+ }
+ return false;
+ }
+
+ const WebCore::CCQuadList& quadList() const { return m_activeQuadList; };
+
+private:
+ WebCore::CCQuadList& m_activeQuadList;
+ WebCore::CCQuadList m_quadListStorage;
+};
+
+} // namespace WebCore
+#endif // MockCCQuadCuller_h
diff --git a/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp b/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp
index b0d86ddf6..721f1fabb 100644
--- a/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp
+++ b/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp
@@ -39,9 +39,9 @@ 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());
+ EXPECT_EQ(a.width(), b.width()); \
+ EXPECT_EQ(a.height(), b.height());
#define EXPECT_PIXELS_MATCH(bitmap, opaqueRect) \
{ \
@@ -53,6 +53,17 @@ namespace {
} \
}
+#define EXPECT_PIXELS_MATCH_EXACT(bitmap, opaqueRect) \
+{ \
+ SkAutoLockPixels locker(bitmap); \
+ for (int y = 0; y < bitmap.height(); ++y) \
+ for (int x = 0; x < bitmap.width(); ++x) { \
+ int alpha = *bitmap.getAddr32(x, y) >> 24; \
+ bool opaque = opaqueRect.contains(x, y); \
+ EXPECT_EQ(opaque, alpha == 255); \
+ } \
+}
+
TEST(PlatformContextSkiaTest, trackOpaqueTest)
{
SkBitmap bitmap;
@@ -215,9 +226,90 @@ TEST(PlatformContextSkiaTest, trackOpaqueClipTest)
context.save();
context.clipToImageBuffer(alphaImage.get(), FloatRect(30, 30, 10, 10));
context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ context.restore();
EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
- context.restore();
+}
+
+TEST(PlatformContextSkiaTest, trackImageMask)
+{
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
+ bitmap.allocPixels();
+ bitmap.eraseColor(0);
+ 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);
+
+ // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
+ // out a transparency layer below that is filled with the mask color. In the end this should
+ // not be marked opaque.
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.beginTransparencyLayer(1);
+ context.fillRect(FloatRect(10, 10, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+
+ context.setCompositeOperation(CompositeDestinationIn);
+ context.beginTransparencyLayer(1);
+
+ OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
+ alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha, ColorSpaceDeviceRGB);
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.drawImageBuffer(alphaImage.get(), ColorSpaceDeviceRGB, FloatRect(10, 10, 10, 10));
+
+ context.endTransparencyLayer();
+ context.endTransparencyLayer();
+
+ EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, platformContext.opaqueRegion().asRect());
+}
+
+TEST(PlatformContextSkiaTest, trackImageMaskWithOpaqueRect)
+{
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
+ bitmap.allocPixels();
+ bitmap.eraseColor(0);
+ 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);
+
+ // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
+ // out a transparency layer below that is filled with the mask color. In the end this should
+ // not be marked opaque.
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.beginTransparencyLayer(1);
+ context.fillRect(FloatRect(10, 10, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+
+ context.setCompositeOperation(CompositeDestinationIn);
+ context.beginTransparencyLayer(1);
+
+ OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
+ alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha, ColorSpaceDeviceRGB);
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.drawImageBuffer(alphaImage.get(), ColorSpaceDeviceRGB, FloatRect(10, 10, 10, 10));
+
+ // We can't have an opaque mask actually, but we can pretend here like it would look if we did.
+ context.fillRect(FloatRect(12, 12, 3, 3), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+
+ context.endTransparencyLayer();
+ context.endTransparencyLayer();
+
+ EXPECT_EQ_RECT(IntRect(12, 12, 3, 3), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, platformContext.opaqueRegion().asRect());
}
TEST(PlatformContextSkiaTest, trackOpaqueJoinTest)
@@ -572,113 +664,170 @@ TEST(PlatformContextSkiaTest, trackOpaqueOvalTest)
EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
}
-TEST(PlatformContextSkiaTest, layerTransformTranslateOpaqueTest)
+TEST(PlatformContextSkiaTest, contextTransparencyLayerTest)
{
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
bitmap.allocPixels();
bitmap.eraseColor(0);
SkCanvas canvas(bitmap);
- AffineTransform transform;
- transform.translate(10, 10);
PlatformContextSkia platformContext(&canvas);
platformContext.setTrackOpaqueRegion(true);
- platformContext.setOpaqueRegionTransform(transform);
GraphicsContext context(&platformContext);
-
+
Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
-
- context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
- EXPECT_EQ_RECT(IntRect(20, 20, 90, 90), platformContext.opaqueRegion().asRect());
- EXPECT_PIXELS_MATCH(bitmap, transform.inverse().mapRect(platformContext.opaqueRegion().asRect()));
-
- context.clearRect(FloatRect(10, 10, 90, 90));
+
+ 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());
+
+ context.clearRect(FloatRect(20, 20, 10, 10));
EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
- context.translate(30, 30);
+ context.beginTransparencyLayer(0.5);
+ context.save();
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ context.restore();
+ context.endTransparencyLayer();
+ EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
- context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
- EXPECT_EQ_RECT(IntRect(50, 50, 90, 90), platformContext.opaqueRegion().asRect());
- EXPECT_PIXELS_MATCH(bitmap, transform.inverse().mapRect(platformContext.opaqueRegion().asRect()));
+ context.clearRect(FloatRect(20, 20, 10, 10));
+ EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
- context.clearRect(FloatRect(10, 10, 90, 90));
+ context.beginTransparencyLayer(0.5);
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ context.endTransparencyLayer();
EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
}
-TEST(PlatformContextSkiaTest, layerTransformScaleOpaqueTest)
+TEST(PlatformContextSkiaTest, UnboundedDrawsAreClipped)
{
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
bitmap.allocPixels();
bitmap.eraseColor(0);
SkCanvas canvas(bitmap);
- AffineTransform transform;
- transform.scale(2);
PlatformContextSkia platformContext(&canvas);
platformContext.setTrackOpaqueRegion(true);
- platformContext.setOpaqueRegionTransform(transform);
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(40, 40, 20, 20), platformContext.opaqueRegion().asRect());
- EXPECT_PIXELS_MATCH(bitmap, transform.inverse().mapRect(platformContext.opaqueRegion().asRect()));
+ Path path;
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
- context.clearRect(FloatRect(20, 20, 10, 10));
- EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+ // Make skia unable to compute fast bounds for our paths.
+ Vector<float> dashArray;
+ dashArray.append(1);
+ dashArray.append(0);
+ context.setLineDash(dashArray, 0);
- context.scale(FloatSize(2, 1));
- context.translate(0, 10);
+ // Make the device opaque in 10,10 40x40.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, platformContext.opaqueRegion().asRect());
- context.fillRect(FloatRect(20, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
- EXPECT_EQ_RECT(IntRect(80, 60, 40, 20), platformContext.opaqueRegion().asRect());
- EXPECT_PIXELS_MATCH(bitmap, transform.inverse().mapRect(platformContext.opaqueRegion().asRect()));
+ // Clip to the left edge of the opaque area.
+ context.clip(IntRect(10, 10, 10, 40));
- context.clearRect(FloatRect(20, 20, 10, 10));
- EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+ // Draw a path that gets clipped. This should destroy the opaque area but only inside the clip.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.setFillColor(alpha, ColorSpaceDeviceRGB);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
+ EXPECT_EQ_RECT(IntRect(20, 10, 30, 40), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect());
}
-TEST(PlatformContextSkiaTest, contextTransparencyLayerTest)
+TEST(PlatformContextSkiaTest, PreserveOpaqueOnlyMattersForFirstLayer)
{
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
bitmap.allocPixels();
bitmap.eraseColor(0);
SkCanvas canvas(bitmap);
- AffineTransform transform;
- transform.scale(2);
PlatformContextSkia platformContext(&canvas);
platformContext.setTrackOpaqueRegion(true);
- platformContext.setOpaqueRegionTransform(transform);
GraphicsContext context(&platformContext);
-
+
Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
-
- context.fillRect(FloatRect(20, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
- EXPECT_EQ_RECT(IntRect(40, 40, 20, 20), platformContext.opaqueRegion().asRect());
- EXPECT_PIXELS_MATCH(bitmap, transform.inverse().mapRect(platformContext.opaqueRegion().asRect()));
-
- context.clearRect(FloatRect(20, 20, 10, 10));
- EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+ Path path;
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+
+ // Make skia unable to compute fast bounds for our paths.
+ Vector<float> dashArray;
+ dashArray.append(1);
+ dashArray.append(0);
+ context.setLineDash(dashArray, 0);
+
+ // Make the device opaque in 10,10 40x40.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Begin a layer that preserves opaque.
+ context.setCompositeOperation(CompositeSourceOver);
context.beginTransparencyLayer(0.5);
- context.save();
- context.fillRect(FloatRect(20, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
- context.restore();
+
+ // Begin a layer that does not preserve opaque.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.beginTransparencyLayer(0.5);
+
+ // This should not destroy the device opaqueness.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+
+ // This should not destroy the device opaqueness either.
+ context.setFillColor(opaque, ColorSpaceDeviceRGB);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
context.endTransparencyLayer();
- EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+ context.endTransparencyLayer();
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, platformContext.opaqueRegion().asRect());
- context.clearRect(FloatRect(20, 20, 10, 10));
+ // Now begin a layer that does not preserve opaque and draw through it to the device.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.beginTransparencyLayer(0.5);
+
+ // This should destroy the device opaqueness.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+
+ context.endTransparencyLayer();
EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, platformContext.opaqueRegion().asRect());
+
+ // Now we draw with a path for which it cannot compute fast bounds. This should destroy the entire opaque region.
+ context.setCompositeOperation(CompositeSourceOut);
context.beginTransparencyLayer(0.5);
- context.fillRect(FloatRect(20, 20, 10, 10), opaque, ColorSpaceDeviceRGB, CompositeSourceOver);
+
+ // This should nuke the device opaqueness.
+ context.setFillColor(opaque, ColorSpaceDeviceRGB);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
context.endTransparencyLayer();
EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, platformContext.opaqueRegion().asRect());
}
} // namespace
diff --git a/Source/WebKit/chromium/tests/PlatformGestureCurveTest.cpp b/Source/WebKit/chromium/tests/PlatformGestureCurveTest.cpp
index 74ca57667..362727c04 100644
--- a/Source/WebKit/chromium/tests/PlatformGestureCurveTest.cpp
+++ b/Source/WebKit/chromium/tests/PlatformGestureCurveTest.cpp
@@ -29,7 +29,7 @@
#include "ActivePlatformGestureAnimation.h"
#include "PlatformGestureCurveTarget.h"
-#include "TouchFlingPlatformGestureCurve.h"
+#include "TouchpadFlingPlatformGestureCurve.h"
#include "WheelFlingPlatformGestureCurve.h"
#include "cc/CCActiveGestureAnimation.h"
#include "cc/CCGestureCurve.h"
@@ -42,7 +42,7 @@ using namespace WebCore;
class MockPlatformGestureCurveTarget : public PlatformGestureCurveTarget {
public:
- virtual void setScrollIncrement(const IntPoint& delta)
+ virtual void scrollBy(const IntPoint& delta)
{
m_cumulativeDelta = m_cumulativeDelta + delta;
}
@@ -57,7 +57,7 @@ private:
TEST(PlatformGestureCurve, flingCurve)
{
MockPlatformGestureCurveTarget target;
- OwnPtr<ActivePlatformGestureAnimation> animation = ActivePlatformGestureAnimation::create(0, WheelFlingPlatformGestureCurve::create(FloatPoint(100, 0)), &target);
+ OwnPtr<ActivePlatformGestureAnimation> animation = ActivePlatformGestureAnimation::create(WheelFlingPlatformGestureCurve::create(FloatPoint(100, 0)), &target);
// Note: the expectations below are dependent on the value of sigma hard-coded in the Rayleigh
// curve. If sigma changes, these test expectations will also change.
@@ -69,23 +69,24 @@ TEST(PlatformGestureCurve, flingCurve)
EXPECT_FALSE(animation->animate(1001));
// Since the Rayleigh CDF maxes out at 1, we expect the cumulative scroll increments to
// match the input velocity parameter.
- // Since we can be off by +/-0.5 on each conversion to int for setScrollIncrement,
- // pick the 'nearness' to be within the number of times animate returns true.
EXPECT_NEAR(target.cumulativeDelta().x(), 100, 1);
EXPECT_EQ(target.cumulativeDelta().y(), 0);
+ // Test animation when not starting at t = 0.
double baseTime = 42.42;
- animation = ActivePlatformGestureAnimation::create(baseTime, WheelFlingPlatformGestureCurve::create(FloatPoint(100, 0)), &target);
+ animation = ActivePlatformGestureAnimation::create(WheelFlingPlatformGestureCurve::create(FloatPoint(100, 0)), &target);
target.resetCumulativeDelta();
EXPECT_TRUE(animation->animate(baseTime + 0.35));
EXPECT_TRUE(animation->animate(baseTime + 1.35));
- EXPECT_FALSE(animation->animate(baseTime + 1000));
+ EXPECT_TRUE(animation->animate(baseTime + 1000));
+ EXPECT_FALSE(animation->animate(baseTime + 1001));
EXPECT_NEAR(target.cumulativeDelta().x(), 100, 1);
- animation = ActivePlatformGestureAnimation::create(0, WheelFlingPlatformGestureCurve::create(FloatPoint(50, 150)), &target);
+ animation = ActivePlatformGestureAnimation::create(WheelFlingPlatformGestureCurve::create(FloatPoint(50, 150)), &target);
target.resetCumulativeDelta();
+ // Test animation with both horizontal and vertical scroll velocities.
EXPECT_TRUE(animation->animate(0));
EXPECT_TRUE(animation->animate(0.25));
EXPECT_TRUE(animation->animate(0.45));
@@ -98,21 +99,18 @@ TEST(PlatformGestureCurve, flingCurve)
TEST(PlatformGestureCurve, flingCurveTouch)
{
+ double initialVelocity = 5000;
MockPlatformGestureCurveTarget target;
- OwnPtr<ActivePlatformGestureAnimation> animation = ActivePlatformGestureAnimation::create(0, TouchFlingPlatformGestureCurve::create(FloatPoint(1000, 0)), &target);
+ OwnPtr<ActivePlatformGestureAnimation> animation = ActivePlatformGestureAnimation::create(TouchpadFlingPlatformGestureCurve::create(FloatPoint(initialVelocity, 0)), &target);
- // Note: the expectations below are dependent on the value of sigma hard-coded in the Rayleigh
- // curve. If sigma changes, these test expectations will also change.
+ // Note: the expectations below are dependent on the value of sigma hard-coded in the curve parameters.
+ // If the parameters change, then the tests values/expectations will need to be updated.
EXPECT_TRUE(animation->animate(0));
EXPECT_TRUE(animation->animate(0.25));
EXPECT_TRUE(animation->animate(0.45)); // Use non-uniform tick spacing.
- EXPECT_TRUE(animation->animate(0.75));
- EXPECT_TRUE(animation->animate(0.9));
- EXPECT_TRUE(animation->animate(1000));
- EXPECT_FALSE(animation->animate(1001));
- // Since we can be off by +/-0.5 on each conversion to int for setScrollIncrement,
- // pick the 'nearness' to be within the 5 * number of times animate returns true.
- EXPECT_NEAR(target.cumulativeDelta().x(), 1000, 1);
+ EXPECT_TRUE(animation->animate(1));
+ EXPECT_FALSE(animation->animate(1.5));
+ EXPECT_NEAR(target.cumulativeDelta().x(), 1193, 1);
EXPECT_EQ(target.cumulativeDelta().y(), 0);
}
diff --git a/Source/WebKit/chromium/tests/PopupMenuTest.cpp b/Source/WebKit/chromium/tests/PopupMenuTest.cpp
index f053ca410..1db65ec6e 100644
--- a/Source/WebKit/chromium/tests/PopupMenuTest.cpp
+++ b/Source/WebKit/chromium/tests/PopupMenuTest.cpp
@@ -42,6 +42,7 @@
#include "PopupMenu.h"
#include "PopupMenuClient.h"
#include "PopupMenuChromium.h"
+#include "RuntimeEnabledFeatures.h"
#include "WebDocument.h"
#include "WebElement.h"
#include "WebFrame.h"
@@ -154,7 +155,7 @@ public:
// We need to override this so that the popup menu size is not 0
// (the layout code checks to see if the popup fits on the screen).
virtual WebScreenInfo screenInfo()
- {
+ {
WebScreenInfo screenInfo;
screenInfo.availableRect.height = 2000;
screenInfo.availableRect.width = 2000;
@@ -181,6 +182,10 @@ public:
protected:
virtual void SetUp()
{
+ // When touch is enabled, padding is added to option elements
+ // In these tests, we'll assume touch is disabled.
+ m_touchWasEnabled = RuntimeEnabledFeatures::touchEnabled();
+ RuntimeEnabledFeatures::setTouchEnabled(false);
m_webView = static_cast<WebViewImpl*>(WebView::create(&m_webviewClient));
m_webView->initializeMainFrame(&m_webFrameClient);
m_popupMenu = adoptRef(new PopupMenuChromium(&m_popupMenuClient));
@@ -191,6 +196,7 @@ protected:
m_popupMenu = 0;
m_webView->close();
webkit_support::UnregisterAllMockedURLs();
+ RuntimeEnabledFeatures::setTouchEnabled(m_touchWasEnabled);
}
// Returns true if there currently is a select popup in the WebView.
@@ -278,6 +284,7 @@ protected:
TestWebFrameClient m_webFrameClient;
TestPopupMenuClient m_popupMenuClient;
RefPtr<PopupMenu> m_popupMenu;
+ bool m_touchWasEnabled;
std::string baseURL;
};
diff --git a/Source/WebKit/chromium/tests/RegionTest.cpp b/Source/WebKit/chromium/tests/RegionTest.cpp
new file mode 100644
index 000000000..d202ab40c
--- /dev/null
+++ b/Source/WebKit/chromium/tests/RegionTest.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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 "Region.h"
+
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+#define TEST_INSIDE_RECT(r, x, y, w, h) \
+ EXPECT_TRUE(r.contains(IntPoint(x, y))); \
+ EXPECT_TRUE(r.contains(IntPoint(x + w - 1, y))); \
+ EXPECT_TRUE(r.contains(IntPoint(x, y + h - 1))); \
+ EXPECT_TRUE(r.contains(IntPoint(x + w - 1, y + h - 1))); \
+ EXPECT_TRUE(r.contains(IntPoint(x, y + h / 2))); \
+ EXPECT_TRUE(r.contains(IntPoint(x + w - 1, y + h / 2))); \
+ EXPECT_TRUE(r.contains(IntPoint(x + w / 2, y))); \
+ EXPECT_TRUE(r.contains(IntPoint(x + w / 2, y + h - 1))); \
+ EXPECT_TRUE(r.contains(IntPoint(x + w / 2, y + h / 2))); \
+
+#define TEST_LEFT_OF_RECT(r, x, y, w, h) \
+ EXPECT_FALSE(r.contains(IntPoint(x - 1, y))); \
+ EXPECT_FALSE(r.contains(IntPoint(x - 1, y + h - 1))); \
+
+#define TEST_RIGHT_OF_RECT(r, x, y, w, h) \
+ EXPECT_FALSE(r.contains(IntPoint(x + w, y))); \
+ EXPECT_FALSE(r.contains(IntPoint(x + w, y + h - 1))); \
+
+#define TEST_TOP_OF_RECT(r, x, y, w, h) \
+ EXPECT_FALSE(r.contains(IntPoint(x, y - 1))); \
+ EXPECT_FALSE(r.contains(IntPoint(x + w - 1, y - 1))); \
+
+#define TEST_BOTTOM_OF_RECT(r, x, y, w, h) \
+ EXPECT_FALSE(r.contains(IntPoint(x, y + h))); \
+ EXPECT_FALSE(r.contains(IntPoint(x + w - 1, y + h))); \
+
+TEST(RegionTest, containsPoint)
+{
+ Region r;
+
+ EXPECT_FALSE(r.contains(IntPoint(0, 0)));
+
+ r.unite(IntRect(35, 35, 1, 1));
+ TEST_INSIDE_RECT(r, 35, 35, 1, 1);
+ TEST_LEFT_OF_RECT(r, 35, 35, 1, 1);
+ TEST_RIGHT_OF_RECT(r, 35, 35, 1, 1);
+ TEST_TOP_OF_RECT(r, 35, 35, 1, 1);
+ TEST_BOTTOM_OF_RECT(r, 35, 35, 1, 1);
+
+ r.unite(IntRect(30, 30, 10, 10));
+ TEST_INSIDE_RECT(r, 30, 30, 10, 10);
+ TEST_LEFT_OF_RECT(r, 30, 30, 10, 10);
+ TEST_RIGHT_OF_RECT(r, 30, 30, 10, 10);
+ TEST_TOP_OF_RECT(r, 30, 30, 10, 10);
+ TEST_BOTTOM_OF_RECT(r, 30, 30, 10, 10);
+
+ r.unite(IntRect(31, 40, 10, 10));
+ EXPECT_FALSE(r.contains(IntPoint(30, 40)));
+ EXPECT_TRUE(r.contains(IntPoint(31, 40)));
+ EXPECT_FALSE(r.contains(IntPoint(40, 39)));
+ EXPECT_TRUE(r.contains(IntPoint(40, 40)));
+
+ TEST_INSIDE_RECT(r, 30, 30, 10, 10);
+ TEST_LEFT_OF_RECT(r, 30, 30, 10, 10);
+ TEST_RIGHT_OF_RECT(r, 30, 30, 10, 10);
+ TEST_TOP_OF_RECT(r, 30, 30, 10, 10);
+ TEST_INSIDE_RECT(r, 31, 40, 10, 10);
+ TEST_LEFT_OF_RECT(r, 31, 40, 10, 10);
+ TEST_RIGHT_OF_RECT(r, 31, 40, 10, 10);
+ TEST_BOTTOM_OF_RECT(r, 31, 40, 10, 10);
+
+ r.unite(IntRect(42, 40, 10, 10));
+
+ TEST_INSIDE_RECT(r, 42, 40, 10, 10);
+ TEST_LEFT_OF_RECT(r, 42, 40, 10, 10);
+ TEST_RIGHT_OF_RECT(r, 42, 40, 10, 10);
+ TEST_TOP_OF_RECT(r, 42, 40, 10, 10);
+ TEST_BOTTOM_OF_RECT(r, 42, 40, 10, 10);
+
+ TEST_INSIDE_RECT(r, 30, 30, 10, 10);
+ TEST_LEFT_OF_RECT(r, 30, 30, 10, 10);
+ TEST_RIGHT_OF_RECT(r, 30, 30, 10, 10);
+ TEST_TOP_OF_RECT(r, 30, 30, 10, 10);
+ TEST_INSIDE_RECT(r, 31, 40, 10, 10);
+ TEST_LEFT_OF_RECT(r, 31, 40, 10, 10);
+ TEST_RIGHT_OF_RECT(r, 31, 40, 10, 10);
+ TEST_BOTTOM_OF_RECT(r, 31, 40, 10, 10);
+}
+
+TEST(RegionTest, emptySpan)
+{
+ Region r;
+ r.unite(IntRect(5, 0, 10, 10));
+ r.unite(IntRect(0, 5, 10, 10));
+ r.subtract(IntRect(7, 7, 10, 0));
+
+ Vector<IntRect> rects = r.rects();
+ for (size_t i = 0; i < rects.size(); ++i)
+ EXPECT_FALSE(rects[i].isEmpty());
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/RenderTableCellTest.cpp b/Source/WebKit/chromium/tests/RenderTableCellTest.cpp
index 049b53534..b4c554a76 100644
--- a/Source/WebKit/chromium/tests/RenderTableCellTest.cpp
+++ b/Source/WebKit/chromium/tests/RenderTableCellTest.cpp
@@ -91,25 +91,12 @@ TEST_F(RenderTableCellDeathTest, CanSetColumn)
EXPECT_EQ(columnIndex, m_cell->col());
}
-TEST_F(RenderTableCellDeathTest, CanSetRow)
-{
- static const unsigned rowIndex = 10;
- m_cell->setRow(rowIndex);
- EXPECT_EQ(rowIndex, m_cell->row());
-}
-
TEST_F(RenderTableCellDeathTest, CanSetColumnToMaxColumnIndex)
{
m_cell->setCol(maxColumnIndex);
EXPECT_EQ(maxColumnIndex, m_cell->col());
}
-TEST_F(RenderTableCellDeathTest, CanSetRowToMaxRowIndex)
-{
- m_cell->setRow(maxRowIndex);
- EXPECT_EQ(maxRowIndex, m_cell->row());
-}
-
// FIXME: Re-enable these tests once ASSERT_DEATH is supported for Android.
// See: https://bugs.webkit.org/show_bug.cgi?id=74089
#if !OS(ANDROID)
@@ -119,21 +106,11 @@ TEST_F(RenderTableCellDeathTest, CrashIfColumnOverflowOnSetting)
ASSERT_DEATH(m_cell->setCol(maxColumnIndex + 1), "");
}
-TEST_F(RenderTableCellDeathTest, CrashIfRowOverflowOnSetting)
-{
- ASSERT_DEATH(m_cell->setRow(maxRowIndex + 1), "");
-}
-
TEST_F(RenderTableCellDeathTest, CrashIfSettingUnsetColumnIndex)
{
ASSERT_DEATH(m_cell->setCol(unsetColumnIndex), "");
}
-TEST_F(RenderTableCellDeathTest, CrashIfSettingUnsetRowIndex)
-{
- ASSERT_DEATH(m_cell->setRow(unsetRowIndex), "");
-}
-
#endif
}
diff --git a/Source/WebKit/chromium/tests/RenderTableRowTest.cpp b/Source/WebKit/chromium/tests/RenderTableRowTest.cpp
new file mode 100644
index 000000000..a5ee2a347
--- /dev/null
+++ b/Source/WebKit/chromium/tests/RenderTableRowTest.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+// FIXME: If we get the TestWebKitAPI framework to bring a full Frame + DOM stack
+// in a portable way, this test should be shared with all ports!
+
+#include "config.h"
+
+#include "RenderTableRow.h"
+
+#include "Document.h"
+#include "Frame.h"
+#include "FrameTestHelpers.h"
+#include "RenderArena.h"
+#include "WebFrame.h"
+#include "WebFrameImpl.h"
+#include "WebView.h"
+
+#include <gtest/gtest.h>
+
+using namespace WebKit;
+
+namespace WebCore {
+
+namespace {
+
+class RenderTableRowDeathTest : public testing::Test {
+ // It's unfortunate that we have to get the whole browser stack to test one RenderObject
+ // but the code needs it.
+ static Frame* frame()
+ {
+ static WebView* webView;
+
+ if (webView)
+ return static_cast<WebFrameImpl*>(webView->mainFrame())->frame();
+
+ webView = FrameTestHelpers::createWebViewAndLoad("about:blank");
+ webView->setFocus(true);
+ return static_cast<WebFrameImpl*>(webView->mainFrame())->frame();
+ }
+
+ static Document* document()
+ {
+ return frame()->document();
+ }
+
+ static RenderArena* arena()
+ {
+ return document()->renderArena();
+ }
+
+ virtual void SetUp()
+ {
+ m_row = new (arena()) RenderTableRow(document());
+ }
+
+ virtual void TearDown()
+ {
+ m_row->destroy();
+ }
+
+protected:
+ RenderTableRow* m_row;
+};
+
+TEST_F(RenderTableRowDeathTest, CanSetRow)
+{
+ static const unsigned rowIndex = 10;
+ m_row->setRowIndex(rowIndex);
+ EXPECT_EQ(rowIndex, m_row->rowIndex());
+}
+
+TEST_F(RenderTableRowDeathTest, CanSetRowToMaxRowIndex)
+{
+ m_row->setRowIndex(maxRowIndex);
+ EXPECT_EQ(maxRowIndex, m_row->rowIndex());
+}
+
+// FIXME: Re-enable these tests once ASSERT_DEATH is supported for Android.
+// See: https://bugs.webkit.org/show_bug.cgi?id=74089
+#if !OS(ANDROID)
+
+TEST_F(RenderTableRowDeathTest, CrashIfRowOverflowOnSetting)
+{
+ ASSERT_DEATH(m_row->setRowIndex(maxRowIndex + 1), "");
+}
+
+TEST_F(RenderTableRowDeathTest, CrashIfSettingUnsetRowIndex)
+{
+ ASSERT_DEATH(m_row->setRowIndex(unsetRowIndex), "");
+}
+
+#endif
+
+}
+
+} // namespace WebCore
diff --git a/Source/WebKit/chromium/tests/ScrollAnimatorNoneTest.cpp b/Source/WebKit/chromium/tests/ScrollAnimatorNoneTest.cpp
index 9d21b8a9e..0827267ed 100644
--- a/Source/WebKit/chromium/tests/ScrollAnimatorNoneTest.cpp
+++ b/Source/WebKit/chromium/tests/ScrollAnimatorNoneTest.cpp
@@ -125,7 +125,7 @@ TEST(ScrollAnimatorEnabled, Enabled)
scrollAnimatorNone.reset();
scrollAnimatorNone.scroll(HorizontalScrollbar, ScrollByPixel, 4, 25);
- EXPECT_NE(100, scrollAnimatorNone.currentX());
+ EXPECT_EQ(100, scrollAnimatorNone.currentX());
EXPECT_NE(0, scrollAnimatorNone.currentX());
EXPECT_EQ(0, scrollAnimatorNone.currentY());
scrollAnimatorNone.reset();
@@ -692,21 +692,21 @@ TEST_F(ScrollAnimatorNoneTest, ScrollWheelTrace)
ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
// Constructed from an actual scroll wheel trace that exhibited a glitch.
- bool result = updateDataFromParameters(1, 53.33, 1000, 100.5781, &parameters);
+ bool result = updateDataFromParameters(1, 53.33f, 1000, 100.5781f, &parameters);
result = animateScroll(100.5933);
result = result && animateScroll(100.6085);
- result = result && updateDataFromParameters(1, 53.33, 1000, 100.6485, &parameters);
+ result = result && updateDataFromParameters(1, 53.33f, 1000, 100.6485f, &parameters);
result = result && animateScroll(100.6515);
result = result && animateScroll(100.6853);
- result = result && updateDataFromParameters(1, 53.33, 1000, 100.6863, &parameters);
+ result = result && updateDataFromParameters(1, 53.33f, 1000, 100.6863f, &parameters);
result = result && animateScroll(100.7005);
result = result && animateScroll(100.7157);
result = result && animateScroll(100.7312);
- result = result && updateDataFromParameters(1, 53.33, 1000, 100.7379, &parameters);
+ result = result && updateDataFromParameters(1, 53.33f, 1000, 100.7379f, &parameters);
result = result && animateScroll(100.7464);
result = result && animateScroll(100.7617);
result = result && animateScroll(100.7775);
- result = result && updateDataFromParameters(1, 53.33, 1000, 100.7779, &parameters);
+ result = result && updateDataFromParameters(1, 53.33f, 1000, 100.7779f, &parameters);
for (double t = 100.7928; result && t < 200; t += 0.015)
result = result && animateScroll(t);
}
@@ -716,21 +716,21 @@ TEST_F(ScrollAnimatorNoneTest, ScrollWheelTraceSmoothed)
ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
// Constructed from an actual scroll wheel trace that exhibited a glitch.
- bool result = updateDataFromParameters(1, 53.33, 1000, 100.5781, &parameters);
+ bool result = updateDataFromParameters(1, 53.33f, 1000, 100.5781f, &parameters);
result = animateScroll(100.5933);
result = result && animateScroll(100.6085);
- result = result && updateDataFromParameters(1, 53.33, 1000, 100.6485, &parameters);
+ result = result && updateDataFromParameters(1, 53.33f, 1000, 100.6485f, &parameters);
result = result && animateScroll(100.6515);
result = result && animateScroll(100.6853);
- result = result && updateDataFromParameters(1, 53.33, 1000, 100.6863, &parameters);
+ result = result && updateDataFromParameters(1, 53.33f, 1000, 100.6863f, &parameters);
result = result && animateScroll(100.7005);
result = result && animateScroll(100.7157);
result = result && animateScroll(100.7312);
- result = result && updateDataFromParameters(1, 53.33, 1000, 100.7379, &parameters);
+ result = result && updateDataFromParameters(1, 53.33f, 1000, 100.7379f, &parameters);
result = result && animateScroll(100.7464);
result = result && animateScroll(100.7617);
result = result && animateScroll(100.7775);
- result = result && updateDataFromParameters(1, 53.33, 1000, 100.7779, &parameters);
+ result = result && updateDataFromParameters(1, 53.33f, 1000, 100.7779f, &parameters);
for (double t = 100.7928; result && t < 200; t += 0.015)
result = result && animateScroll(t);
}
diff --git a/Source/WebKit/chromium/tests/ScrollbarLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/ScrollbarLayerChromiumTest.cpp
index 78b96b495..5bf990cde 100644
--- a/Source/WebKit/chromium/tests/ScrollbarLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/ScrollbarLayerChromiumTest.cpp
@@ -27,6 +27,7 @@
#include "ScrollbarLayerChromium.h"
#include "Scrollbar.h"
+#include "Settings.h"
#include "TreeSynchronizer.h"
#include "cc/CCScrollbarLayerImpl.h"
#include "cc/CCSingleThreadProxy.h"
@@ -90,6 +91,7 @@ TEST(ScrollbarLayerChromiumTest, resolveScrollLayerPointer)
{
DebugScopedSetImplThread impl;
+ Settings::setMockScrollbarsEnabled(true);
{
RefPtr<MockScrollbar> scrollbar = adoptRef(new MockScrollbar);
RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create();
diff --git a/Source/WebKit/chromium/tests/TextureCopierTest.cpp b/Source/WebKit/chromium/tests/TextureCopierTest.cpp
new file mode 100644
index 000000000..17173c0a5
--- /dev/null
+++ b/Source/WebKit/chromium/tests/TextureCopierTest.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 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 "TextureCopier.h"
+
+#include "FakeWebGraphicsContext3D.h"
+#include "GraphicsContext3DPrivate.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <wtf/RefPtr.h>
+
+using namespace WebCore;
+using namespace WebKit;
+using testing::InSequence;
+using testing::Test;
+using testing::_;
+
+namespace {
+
+class MockContext : public FakeWebGraphicsContext3D {
+public:
+ MOCK_METHOD2(bindFramebuffer, void(WGC3Denum, WebGLId));
+ MOCK_METHOD3(texParameteri, void(GC3Denum target, GC3Denum pname, GC3Dint param));
+
+ MOCK_METHOD3(drawArrays, void(GC3Denum mode, GC3Dint first, GC3Dsizei count));
+};
+
+TEST(TextureCopierTest, testDrawArraysCopy)
+{
+ GraphicsContext3D::Attributes attrs;
+ RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockContext()), GraphicsContext3D::RenderDirectlyToHostWindow);
+ MockContext& mockContext = *static_cast<MockContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get()));
+
+ {
+ InSequence sequence;
+
+ // Here we check just some essential properties of copyTexture() to avoid mirroring the full implementation.
+ EXPECT_CALL(mockContext, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, _));
+
+ // Make sure linear filtering is disabled during the copy.
+ EXPECT_CALL(mockContext, texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST));
+ EXPECT_CALL(mockContext, texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST));
+
+ EXPECT_CALL(mockContext, drawArrays(_, _, _));
+
+ // Linear filtering should be restored.
+ EXPECT_CALL(mockContext, texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ EXPECT_CALL(mockContext, texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+
+ // Default framebuffer should be restored
+ EXPECT_CALL(mockContext, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
+ }
+
+ int sourceTextureId = 1;
+ int destTextureId = 2;
+ IntSize size(256, 128);
+ OwnPtr<AcceleratedTextureCopier> copier(AcceleratedTextureCopier::create(context));
+ copier->copyTexture(context.get(), sourceTextureId, destTextureId, size);
+}
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/TextureManagerTest.cpp b/Source/WebKit/chromium/tests/TextureManagerTest.cpp
index 3b576af99..d5313f5dc 100644
--- a/Source/WebKit/chromium/tests/TextureManagerTest.cpp
+++ b/Source/WebKit/chromium/tests/TextureManagerTest.cpp
@@ -24,23 +24,18 @@
#include "config.h"
+#include "CCTiledLayerTestCommon.h"
#include "ManagedTexture.h"
#include "TextureManager.h"
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace WebKitTests;
using namespace WTF;
namespace {
-class FakeTextureAllocator : public TextureAllocator {
-public:
- virtual ~FakeTextureAllocator() { }
- virtual unsigned createTexture(const IntSize&, GC3Denum) { return 1; }
- virtual void deleteTexture(unsigned, const IntSize&, GC3Denum) { }
-};
-
class TextureManagerTest : public testing::Test {
public:
TextureManagerTest()
diff --git a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
index 2523230e0..5b7cb0df7 100644
--- a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
@@ -26,18 +26,16 @@
#include "TiledLayerChromium.h"
+#include "CCAnimationTestCommon.h"
#include "CCLayerTreeTestCommon.h"
+#include "CCTiledLayerTestCommon.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"
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace WebKitTests;
using namespace WTF;
#define EXPECT_EQ_RECT(a, b) \
@@ -48,208 +46,38 @@ using namespace WTF;
namespace {
-class FakeTextureAllocator : public TextureAllocator {
+class TestCCOcclusionTracker : public CCOcclusionTracker {
public:
- virtual unsigned createTexture(const IntSize&, GC3Denum) { return 0; }
- virtual void deleteTexture(unsigned, const IntSize&, GC3Denum) { }
-};
-
-class FakeTiledLayerChromium;
-
-class FakeLayerTextureUpdater : public LayerTextureUpdater {
-public:
- class Texture : public LayerTextureUpdater::Texture {
- public:
- Texture(FakeLayerTextureUpdater* layer, PassOwnPtr<ManagedTexture> texture)
- : LayerTextureUpdater::Texture(texture)
- , m_layer(layer)
- {
- }
- virtual ~Texture() { }
-
- virtual void updateRect(GraphicsContext3D*, TextureAllocator*, const IntRect&, const IntRect&) { m_layer->updateRect(); }
- virtual void prepareRect(const IntRect&) { m_layer->prepareRect(); }
-
- private:
- FakeLayerTextureUpdater* m_layer;
- };
-
- FakeLayerTextureUpdater()
- : m_prepareCount(0)
- , m_updateCount(0)
- , m_prepareRectCount(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; }
-
- // Number of times updateRect has been invoked.
- int updateCount() const { return m_updateCount; }
- void clearUpdateCount() { m_updateCount = 0; }
- void updateRect() { m_updateCount++; }
-
- // Number of times prepareRect() has been invoked on a texture.
- int prepareRectCount() const { return m_prepareRectCount; }
- void clearPrepareRectCount() { m_prepareRectCount = 0; }
- void prepareRect() { m_prepareRectCount++; }
-
- 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(this, ManagedTexture::create(manager))); }
- virtual SampledTexelFormat sampledTexelFormat(GC3Denum) { return SampledTexelFormatRGBA; }
- virtual void prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect);
-
-private:
- int m_prepareCount;
- int m_updateCount;
- int m_prepareRectCount;
- IntRect m_rectToInvalidate;
- IntRect m_lastUpdateRect;
- IntRect m_opaquePaintRect;
- RefPtr<FakeTiledLayerChromium> m_layer;
-};
-
-class FakeCCTiledLayerImpl : public CCTiledLayerImpl {
-public:
- explicit FakeCCTiledLayerImpl(int id)
- : CCTiledLayerImpl(id) { }
- virtual ~FakeCCTiledLayerImpl() { }
-
- bool hasTileAt(int i, int j)
+ TestCCOcclusionTracker()
+ : CCOcclusionTracker(IntRect(0, 0, 1000, 1000), true)
+ , m_scissorRectInScreen(IntRect(0, 0, 1000, 1000))
{
- return CCTiledLayerImpl::hasTileAt(i, j);
+ // Pretend we have visited a render surface.
+ m_stack.append(StackObject());
}
-};
-class FakeTiledLayerChromium : public TiledLayerChromium {
-public:
- explicit FakeTiledLayerChromium(TextureManager* textureManager)
- : TiledLayerChromium()
- , m_fakeTextureUpdater(adoptRef(new FakeLayerTextureUpdater))
- , m_textureManager(textureManager)
- {
- setTileSize(IntSize(100, 100));
- setTextureFormat(GraphicsContext3D::RGBA);
- setBorderTexelOption(CCLayerTilingData::NoBorderTexels);
- setIsDrawable(true); // So that we don't get false positives if any of these tests expect to return false from drawsContent() for other reasons.
- }
- virtual ~FakeTiledLayerChromium() { }
+ void setOcclusion(const Region& occlusion) { m_stack.last().occlusionInScreen = occlusion; }
- void invalidateRect(const IntRect& rect)
- {
- TiledLayerChromium::invalidateRect(rect);
- }
-
- void prepareToUpdate(const IntRect& rect, const Region& occluded)
- {
- TiledLayerChromium::prepareToUpdate(rect, occluded);
- }
-
- void prepareToUpdateIdle(const IntRect& rect, const Region& occluded)
- {
- TiledLayerChromium::prepareToUpdateIdle(rect, occluded);
- }
-
- bool needsIdlePaint(const IntRect& rect)
- {
- return TiledLayerChromium::needsIdlePaint(rect);
- }
-
- bool skipsDraw() const
- {
- return TiledLayerChromium::skipsDraw();
- }
-
- virtual void setNeedsDisplayRect(const FloatRect& rect)
- {
- m_lastNeedsDisplayRect = rect;
- TiledLayerChromium::setNeedsDisplayRect(rect);
- }
-
- const FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; }
-
- FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); }
-
- virtual TextureManager* textureManager() const { return m_textureManager; }
-
- virtual void paintContentsIfDirty(const Region& occludedScreenSpace)
- {
- prepareToUpdate(visibleLayerRect(), occludedScreenSpace);
- }
+protected:
+ virtual IntRect layerScissorRectInTargetSurface(const LayerChromium* layer) const { return m_scissorRectInScreen; }
private:
- virtual LayerTextureUpdater* textureUpdater() const
- {
- return m_fakeTextureUpdater.get();
- }
-
- virtual void createTextureUpdaterIfNeeded() { }
-
- RefPtr<FakeLayerTextureUpdater> m_fakeTextureUpdater;
- TextureManager* m_textureManager;
- FloatRect m_lastNeedsDisplayRect;
+ IntRect m_scissorRectInScreen;
};
-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);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- Region noOcclusion;
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
// 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), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
layer->pushPropertiesTo(layerImpl.get());
// We should have both tiles on the impl side.
@@ -261,8 +89,7 @@ TEST(TiledLayerChromiumTest, pushDirtyTiles)
// Invalidates both tiles...
layer->invalidateRect(IntRect(0, 0, 100, 200));
// ....but then only update one of them.
- layer->prepareToUpdate(IntRect(0, 0, 100, 100), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
layer->pushPropertiesTo(layerImpl.get());
// We should only have the first tile since the other tile was invalidated but not painted.
@@ -276,18 +103,22 @@ TEST(TiledLayerChromiumTest, pushOccludedDirtyTiles)
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- Region noOcclusion;
+ TestCCOcclusionTracker occluded;
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
// The tile size is 100x100, so this invalidates and then paints two tiles.
layer->setBounds(IntSize(100, 200));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
+ layer->setVisibleLayerRect(IntRect(0, 0, 100, 200));
layer->invalidateRect(IntRect(0, 0, 100, 200));
- layer->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), &occluded);
layer->pushPropertiesTo(layerImpl.get());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// We should have both tiles on the impl side.
EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
@@ -297,16 +128,59 @@ TEST(TiledLayerChromiumTest, pushOccludedDirtyTiles)
// Invalidates part of the top tile...
layer->invalidateRect(IntRect(0, 0, 50, 50));
// ....but the area is occluded.
- Region occlusion(IntRect(0, 0, 50, 50));
- layer->prepareToUpdate(IntRect(0, 0, 100, 100), occlusion);
- layer->updateCompositorResources(0, updater);
+ occluded.setOcclusion(IntRect(0, 0, 50, 50));
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), &occluded);
layer->pushPropertiesTo(layerImpl.get());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 2500, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// We should still have both tiles, as part of the top tile is still unoccluded.
EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
}
+TEST(TiledLayerChromiumTest, pushDeletedTiles)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+ FakeTextureAllocator allocator;
+
+ // 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->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ 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->evictAndDeleteAllTextures(&allocator);
+ textureManager->setMaxMemoryLimitBytes(4*1024*1024);
+ textureManager->setPreferredMemoryLimitBytes(4*1024*1024);
+
+ // This should drop the tiles on the impl thread.
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should now have no textures on the impl thread.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
+
+ // This should recreate and update the deleted textures.
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should only have the first tile since the other tile was invalidated but not painted.
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
+}
+
TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
@@ -314,25 +188,22 @@ TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
// The tile size is 100x100. Setup 5x5 tiles with one visible tile in the center.
IntSize contentBounds(500, 500);
IntRect contentRect(IntPoint::zero(), contentBounds);
IntRect visibleRect(200, 200, 100, 100);
- Region noOcclusion;
// This invalidates 25 tiles and then paints one visible tile.
layer->setBounds(contentBounds);
layer->setVisibleLayerRect(visibleRect);
layer->invalidateRect(contentRect);
- layer->prepareToUpdate(visibleRect, noOcclusion);
+ layer->updateLayerRect(updater, visibleRect, 0);
// We should need idle-painting for 3x3 tiles in the center.
EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
- layer->updateCompositorResources(0, updater);
layer->pushPropertiesTo(layerImpl.get());
// We should have one tile on the impl side.
@@ -342,10 +213,9 @@ TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
// For the next four updates, we should detect we still need idle painting.
for (int i = 0; i < 4; i++) {
- layer->prepareToUpdate(visibleRect, noOcclusion);
+ layer->updateLayerRect(updater, visibleRect, 0);
EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
- layer->prepareToUpdateIdle(visibleRect, noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->idleUpdateLayerRect(updater, visibleRect, 0);
layer->pushPropertiesTo(layerImpl.get());
textureManager->unprotectAllTextures();
}
@@ -365,6 +235,109 @@ TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
}
}
+TEST(TiledLayerChromiumTest, pushTilesAfterIdlePaintFailed)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(1024*1024, 1024*1024, 1024);
+ DebugScopedSetImplThread implThread;
+ RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl1(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl2(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+ FakeTextureAllocator allocator;
+ FakeTextureCopier copier;
+ FakeTextureUploader uploader;
+
+ // For this test we have two layers. layer1 exhausts most texture memory, leaving room for 2 more tiles from
+ // layer2, but not all three tiles. First we paint layer1, and one tile from layer2. Then when we idle paint
+ // layer2, we will fail on the third tile of layer2, and this should not leave the second tile in a bad state.
+
+ // This requires 4*30000 bytes of memory.
+ IntRect layer2Rect(0, 0, 100, 300);
+ layer2->setBounds(layer2Rect.size());
+ layer2->setVisibleLayerRect(layer2Rect);
+ layer2->invalidateRect(layer2Rect);
+
+ // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough for 2 tiles only in the other layer.
+ IntRect layerRect(IntPoint::zero(), IntSize(100, 2400));
+ layer1->setBounds(layerRect.size());
+ layer1->setVisibleLayerRect(layerRect);
+ layer1->invalidateRect(layerRect);
+ layer1->updateLayerRect(updater, layerRect, 0);
+
+ // Paint a single tile in layer2 so that it will idle paint.
+ layer2->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
+
+ // We should need idle-painting for both remaining tiles in layer2.
+ EXPECT_TRUE(layer2->needsIdlePaint(layer2Rect));
+
+ // Commit the frame over to impl.
+ updater.update(0, &allocator, &copier, &uploader, 5000);
+ layer1->pushPropertiesTo(layerImpl1.get());
+ layer2->pushPropertiesTo(layerImpl2.get());
+
+ // Now idle paint layer2. We are going to run out of memory though!
+ layer2->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
+ layer2->idleUpdateLayerRect(updater, layer2Rect, 0);
+
+ // Oh well, commit the frame and push.
+ updater.update(0, &allocator, &copier, &uploader, 5000);
+ layer1->pushPropertiesTo(layerImpl1.get());
+ layer2->pushPropertiesTo(layerImpl2.get());
+
+ // Sanity check, we should have textures for the big layer.
+ EXPECT_TRUE(layerImpl1->hasTextureIdForTileAt(0, 0));
+
+ // We should only have the first tile from layer2 since it failed to idle update.
+ EXPECT_TRUE(layerImpl2->hasTileAt(0, 0));
+ EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 0));
+ EXPECT_FALSE(layerImpl2->hasTileAt(0, 1));
+ EXPECT_FALSE(layerImpl2->hasTileAt(0, 2));
+
+ // Now if layer2 becomes fully visible, we should be able to paint it and push valid textures.
+ textureManager->unprotectAllTextures();
+
+ layer2->updateLayerRect(updater, layer2Rect, 0);
+ layer1->updateLayerRect(updater, IntRect(), 0);
+
+ updater.update(0, &allocator, &copier, &uploader, 5000);
+ layer1->pushPropertiesTo(layerImpl1.get());
+ layer2->pushPropertiesTo(layerImpl2.get());
+
+ EXPECT_TRUE(layerImpl2->hasTileAt(0, 0));
+ EXPECT_TRUE(layerImpl2->hasTileAt(0, 1));
+ EXPECT_TRUE(layerImpl2->hasTileAt(0, 2));
+ EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 0));
+ EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 1));
+ EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 2));
+}
+
+TEST(TiledLayerChromiumTest, pushIdlePaintedOccludedTiles)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ TestCCOcclusionTracker occluded;
+
+ CCTextureUpdater updater;
+
+ // The tile size is 100x100, so this invalidates one occluded tile, culls it during paint, but prepaints it.
+ occluded.setOcclusion(IntRect(0, 0, 100, 100));
+
+ layer->setBounds(IntSize(100, 100));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
+ layer->setVisibleLayerRect(IntRect(0, 0, 100, 100));
+ layer->invalidateRect(IntRect(0, 0, 100, 100));
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), &occluded);
+ layer->idleUpdateLayerRect(updater, IntRect(0, 0, 100, 100), &occluded);
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should have the prepainted tile on the impl side.
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
+}
+
TEST(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
@@ -372,9 +345,7 @@ TEST(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint)
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
- Region noOcclusion;
+ CCTextureUpdater updater;
// The tile size is 100x100, so this invalidates and then paints two tiles.
// However, during the paint, we invalidate one of the tiles. This should
@@ -382,8 +353,7 @@ TEST(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint)
layer->setBounds(IntSize(100, 200));
layer->invalidateRect(IntRect(0, 0, 100, 200));
layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer.get());
- layer->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
layer->pushPropertiesTo(layerImpl.get());
// We should have both tiles on the impl side.
@@ -400,23 +370,18 @@ TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnNextLayer)
OwnPtr<FakeCCTiledLayerImpl> layer1Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
OwnPtr<FakeCCTiledLayerImpl> layer2Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
- Region noOcclusion;
+ CCTextureUpdater updater;
layer1->setBounds(IntSize(100, 200));
layer1->invalidateRect(IntRect(0, 0, 100, 200));
layer2->setBounds(IntSize(100, 200));
layer2->invalidateRect(IntRect(0, 0, 100, 200));
- layer1->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
+ layer1->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
// Invalidate a tile on layer1
layer2->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer1.get());
- layer2->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
-
- layer1->updateCompositorResources(0, updater);
- layer2->updateCompositorResources(0, updater);
+ layer2->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
layer1->pushPropertiesTo(layer1Impl.get());
layer2->pushPropertiesTo(layer2Impl.get());
@@ -437,9 +402,7 @@ TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
OwnPtr<FakeCCTiledLayerImpl> layer1Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
OwnPtr<FakeCCTiledLayerImpl> layer2Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
- Region noOcclusion;
+ CCTextureUpdater updater;
layer1->setBounds(IntSize(100, 200));
layer1->invalidateRect(IntRect(0, 0, 100, 200));
@@ -448,12 +411,9 @@ TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
// Invalidate a tile on layer2
layer1->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer2.get());
- layer1->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
+ layer1->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
- layer2->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
-
- layer1->updateCompositorResources(0, updater);
- layer2->updateCompositorResources(0, updater);
+ layer2->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
layer1->pushPropertiesTo(layer1Impl.get());
layer2->pushPropertiesTo(layer2Impl.get());
@@ -471,7 +431,6 @@ TEST(TiledLayerChromiumTest, idlePaintOutOfMemory)
IntSize contentBounds(300, 300);
IntRect contentRect(IntPoint::zero(), contentBounds);
IntRect visibleRect(100, 100, 100, 100);
- Region noOcclusion;
// We have enough memory for only the visible rect, so we will run out of memory in first idle paint.
int memoryLimit = 4 * 100 * 100; // 2 tiles, 4 bytes per pixel.
@@ -481,51 +440,243 @@ TEST(TiledLayerChromiumTest, idlePaintOutOfMemory)
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
// This invalidates 9 tiles and then paints one visible tile.
layer->setBounds(contentBounds);
layer->setVisibleLayerRect(visibleRect);
layer->invalidateRect(contentRect);
- layer->prepareToUpdate(visibleRect, noOcclusion);
+ layer->updateLayerRect(updater, visibleRect, 0);
// We should need idle-painting for 3x3 tiles surounding visible tile.
EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
- layer->updateCompositorResources(0, updater);
layer->pushPropertiesTo(layerImpl.get());
// We should have one tile on the impl side.
EXPECT_TRUE(layerImpl->hasTileAt(1, 1));
textureManager->unprotectAllTextures();
- layer->prepareToUpdate(visibleRect, noOcclusion);
- layer->prepareToUpdateIdle(visibleRect, noOcclusion);
+ layer->updateLayerRect(updater, visibleRect, 0);
+ layer->idleUpdateLayerRect(updater, visibleRect, 0);
// We shouldn't signal we need another idle paint after we run out of memory.
EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
- layer->updateCompositorResources(0, updater);
layer->pushPropertiesTo(layerImpl.get());
}
+TEST(TiledLayerChromiumTest, idlePaintZeroSizedLayer)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(20000, 10000, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+
+ // The layer's bounds are empty.
+ IntRect contentRect;
+
+ layer->setBounds(contentRect.size());
+ layer->setVisibleLayerRect(contentRect);
+ layer->invalidateRect(contentRect);
+ layer->updateLayerRect(updater, contentRect, 0);
+
+ // Empty layers don't have tiles.
+ EXPECT_EQ(0u, layer->numPaintedTiles());
+
+ // Empty layers don't need prepaint.
+ EXPECT_FALSE(layer->needsIdlePaint(contentRect));
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // Empty layers don't have tiles.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+
+ // Non-visible layers don't idle paint.
+ layer->idleUpdateLayerRect(updater, contentRect, 0);
+
+ // Empty layers don't have tiles.
+ EXPECT_EQ(0u, layer->numPaintedTiles());
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // Empty layers don't have tiles.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+}
+
+TEST(TiledLayerChromiumTest, idlePaintZeroSizedAnimatingLayer)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(20000, 10000, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+
+ // Pretend the layer is animating.
+ layer->setDrawTransformIsAnimating(true);
+
+ // The layer's bounds are empty.
+ IntRect contentRect;
+
+ layer->setBounds(contentRect.size());
+ layer->setVisibleLayerRect(contentRect);
+ layer->invalidateRect(contentRect);
+ layer->updateLayerRect(updater, contentRect, 0);
+
+ // Empty layers don't have tiles.
+ EXPECT_EQ(0u, layer->numPaintedTiles());
+
+ // Empty layers don't need prepaint.
+ EXPECT_FALSE(layer->needsIdlePaint(contentRect));
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // Empty layers don't have tiles.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+
+ // Non-visible layers don't idle paint.
+ layer->idleUpdateLayerRect(updater, contentRect, 0);
+
+ // Empty layers don't have tiles.
+ EXPECT_EQ(0u, layer->numPaintedTiles());
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // Empty layers don't have tiles.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+}
+
+TEST(TiledLayerChromiumTest, idlePaintNonVisibleLayers)
+{
+ IntSize contentBounds(100, 100);
+ IntRect contentRect(IntPoint::zero(), contentBounds);
+
+ OwnPtr<TextureManager> textureManager = TextureManager::create(20000, 10000, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+
+ // Invalidate the layer but make none of it visible, so nothing paints.
+ IntRect visibleRect;
+
+ layer->setBounds(contentBounds);
+ layer->setVisibleLayerRect(visibleRect);
+ layer->invalidateRect(contentRect);
+ layer->updateLayerRect(updater, visibleRect, 0);
+
+ // Non-visible layers don't need idle paint.
+ EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should not have any tiles pushed since the layer is not visible.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+
+ // Non-visible layers don't idle paint.
+ layer->idleUpdateLayerRect(updater, visibleRect, 0);
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should not have any tiles pushed since the layer is not visible.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+}
+
+static void idlePaintRepeat(int repeatTimes, FakeTiledLayerChromium* layer, FakeCCTiledLayerImpl* layerImpl, CCTextureUpdater& updater, const IntRect& visibleRect)
+{
+ for (int i = 0; i < repeatTimes; ++i) {
+ layer->updateLayerRect(updater, visibleRect, 0);
+ layer->idleUpdateLayerRect(updater, visibleRect, 0);
+ layer->pushPropertiesTo(layerImpl);
+ }
+}
+
+static void testHaveOuterTiles(FakeCCTiledLayerImpl* layerImpl, int width, int height, int have)
+{
+ for (int i = 0; i < width; ++i) {
+ for (int j = 0; j < height; ++j) {
+ bool hasTile = i < have || j < have || i >= width - have || j >= height - have;
+ EXPECT_EQ(hasTile, layerImpl->hasTileAt(i, j));
+ }
+ }
+}
+
+TEST(TiledLayerChromiumTest, idlePaintNonVisibleAnimatingLayers)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(8000*8000*8, 8000*8000*4, 1024);
+ DebugScopedSetImplThread implThread;
+
+ CCTextureUpdater updater;
+
+ int tileWidth = FakeTiledLayerChromium::tileSize().width();
+ int tileHeight = FakeTiledLayerChromium::tileSize().height();
+ int width[] = { 1, 2, 3, 4, 9, 10, 0 };
+ int height[] = { 1, 2, 3, 4, 9, 10, 0 };
+
+ for (int j = 0; height[j]; ++j) {
+ for (int i = 0; width[i]; ++i) {
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ // Pretend the layer is animating.
+ layer->setDrawTransformIsAnimating(true);
+
+ IntSize contentBounds(width[i] * tileWidth, height[j] * tileHeight);
+ IntRect contentRect(IntPoint::zero(), contentBounds);
+ IntRect visibleRect;
+
+ layer->setBounds(contentBounds);
+ layer->setVisibleLayerRect(visibleRect);
+ layer->invalidateRect(contentRect);
+
+ // If idlePaintRect gives back a non-empty result then we should paint it. Otherwise,
+ // we shoud paint nothing.
+ bool shouldPrepaint = !layer->idlePaintRect(visibleRect).isEmpty();
+
+ // This paints the layer but there's nothing visible so it's a no-op.
+ layer->updateLayerRect(updater, visibleRect, 0);
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should not have any tiles pushed yet since the layer is not visible and we've not prepainted.
+ testHaveOuterTiles(layerImpl.get(), width[i], height[j], 0);
+
+ // Normally we don't allow non-visible layers to pre-paint, but if they are animating then we should.
+ EXPECT_EQ(shouldPrepaint, layer->needsIdlePaint(visibleRect));
+
+ // If the layer is to be prepainted at all, then after four updates we should have the outer row/columns painted.
+ idlePaintRepeat(4, layer.get(), layerImpl.get(), updater, visibleRect);
+ testHaveOuterTiles(layerImpl.get(), width[i], height[j], shouldPrepaint ? 1 : 0);
+
+ // We don't currently idle paint past the outermost tiles.
+ EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
+ idlePaintRepeat(4, layer.get(), layerImpl.get(), updater, visibleRect);
+ testHaveOuterTiles(layerImpl.get(), width[i], height[j], shouldPrepaint ? 1 : 0);
+ }
+ }
+}
+
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;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- Region noOcclusion;
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
+ FakeTextureAllocator fakeAllocator;
+ FakeTextureCopier fakeCopier;
+ FakeTextureUploader fakeUploader;
+ RefPtr<GraphicsContext3D> context = createCompositorMockGraphicsContext3D(GraphicsContext3D::Attributes());
// 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), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ updater.update(context.get(), &fakeAllocator, &fakeCopier, &fakeUploader, 1000);
layer->pushPropertiesTo(layerImpl.get());
// We should have both tiles on the impl side.
@@ -535,20 +686,23 @@ TEST(TiledLayerChromiumTest, invalidateFromPrepare)
textureManager->unprotectAllTextures();
layer->fakeLayerTextureUpdater()->clearPrepareCount();
- // Invoke prepareToUpdate again. As the layer is valid prepareToUpdate shouldn't be invoked on
+ // Invoke updateLayerRect again. As the layer is valid updateLayerRect shouldn't be invoked on
// the LayerTextureUpdater.
- layer->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ updater.update(context.get(), &fakeAllocator, &fakeCopier, &fakeUploader, 1000);
EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareCount());
layer->invalidateRect(IntRect(0, 0, 50, 50));
- // setRectToInvalidate triggers invalidateRect() being invoked from prepareToUpdate.
+ // setRectToInvalidate triggers invalidateRect() being invoked from updateLayerRect.
layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(25, 25, 50, 50), layer.get());
layer->fakeLayerTextureUpdater()->clearPrepareCount();
- layer->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ updater.update(context.get(), &fakeAllocator, &fakeCopier, &fakeUploader, 1000);
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), noOcclusion);
+ // The layer should still be invalid as updateLayerRect invoked invalidate.
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ updater.update(context.get(), &fakeAllocator, &fakeCopier, &fakeUploader, 1000);
EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
}
@@ -559,10 +713,8 @@ TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled)
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerWithScaledBounds> layer = adoptRef(new FakeTiledLayerWithScaledBounds(textureManager.get()));
- Region noOcclusion;
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
IntRect layerBounds(0, 0, 300, 200);
IntRect contentBounds(0, 0, 200, 250);
@@ -574,21 +726,18 @@ TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled)
// 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, noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, contentBounds, 0);
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, noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, contentBounds, 0);
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, noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, contentBounds, 0);
EXPECT_FLOAT_RECT_EQ(FloatRect(45, 80, 15, 8), layer->updateRect());
}
@@ -599,9 +748,7 @@ TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
- Region noOcclusion;
+ CCTextureUpdater updater;
// Create a layer with one tile.
layer->setBounds(IntSize(100, 100));
@@ -611,8 +758,7 @@ TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
// Push the tiles to the impl side and check that there is exactly one.
- layer->prepareToUpdate(IntRect(0, 0, 100, 100), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
layer->pushPropertiesTo(layerImpl.get());
EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
@@ -625,8 +771,7 @@ TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
// The impl side should get 2x2 tiles now.
- layer->prepareToUpdate(IntRect(0, 0, 200, 200), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 200, 200), 0);
layer->pushPropertiesTo(layerImpl.get());
EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
@@ -636,8 +781,7 @@ TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
// Invalidate the entire layer again, but do not paint. All tiles should be gone now from the
// impl side.
layer->setNeedsDisplay();
- layer->prepareToUpdate(IntRect(0, 0, 0, 0), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(1, 0, 0, 1), 0);
layer->pushPropertiesTo(layerImpl.get());
EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
@@ -650,7 +794,7 @@ TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
// Initialize without threading support.
WebKit::WebCompositor::initialize(0);
FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
- RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, CCSettings());
+ OwnPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, CCSettings());
// Create two 300 x 300 tiled layers.
IntSize contentBounds(300, 300);
@@ -671,14 +815,12 @@ TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
rootLayer->invalidateRect(contentRect);
childLayer->invalidateRect(contentRect);
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
ccLayerTreeHost->setRootLayer(rootLayer);
ccLayerTreeHost->setViewportSize(IntSize(300, 300));
textureManager->setMaxMemoryLimitBytes(memoryLimit);
- ccLayerTreeHost->updateLayers();
- ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
+ ccLayerTreeHost->updateLayers(updater);
// We'll skip the root layer.
EXPECT_TRUE(rootLayer->skipsDraw());
@@ -690,7 +832,7 @@ TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
// Remove the child layer.
rootLayer->removeAllChildren();
- ccLayerTreeHost->updateLayers();
+ ccLayerTreeHost->updateLayers(updater);
EXPECT_FALSE(rootLayer->skipsDraw());
ccLayerTreeHost->setRootLayer(0);
@@ -702,16 +844,30 @@ TEST(TiledLayerChromiumTest, resizeToSmaller)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region noOcclusion;
+ CCTextureUpdater updater;
layer->setBounds(IntSize(700, 700));
layer->invalidateRect(IntRect(0, 0, 700, 700));
- layer->prepareToUpdate(IntRect(0, 0, 700, 700), noOcclusion);
+ layer->updateLayerRect(updater, IntRect(0, 0, 700, 700), 0);
layer->setBounds(IntSize(200, 200));
layer->invalidateRect(IntRect(0, 0, 200, 200));
}
+TEST(TiledLayerChromiumTest, hugeLayerUpdateCrash)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ CCTextureUpdater updater;
+
+ int size = 1 << 30;
+ layer->setBounds(IntSize(size, size));
+ layer->invalidateRect(IntRect(0, 0, size, size));
+
+ // Ensure no crash for bounds where size * size would overflow an int.
+ layer->updateLayerRect(updater, IntRect(0, 0, 700, 700), 0);
+}
+
TEST(TiledLayerChromiumTest, partialUpdates)
{
CCSettings settings;
@@ -719,7 +875,7 @@ TEST(TiledLayerChromiumTest, partialUpdates)
// Initialize without threading support.
WebKit::WebCompositor::initialize(0);
FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
- RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, settings);
+ OwnPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, settings);
// Create one 500 x 300 tiled layer.
IntSize contentBounds(300, 200);
@@ -731,51 +887,92 @@ TEST(TiledLayerChromiumTest, partialUpdates)
layer->setPosition(FloatPoint(150, 150));
layer->invalidateRect(contentRect);
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
+ FakeTextureAllocator allocator;
+ FakeTextureCopier copier;
+ FakeTextureUploader uploader;
ccLayerTreeHost->setRootLayer(layer);
ccLayerTreeHost->setViewportSize(IntSize(300, 200));
// Full update of all 6 tiles.
- ccLayerTreeHost->updateLayers();
- ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
- updater.update(0, 4);
- EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_TRUE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
- updater.update(0, 4);
- EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_FALSE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ ccLayerTreeHost->updateLayers(updater);
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ layer->pushPropertiesTo(layerImpl.get());
+ }
ccLayerTreeHost->commitComplete();
// Full update of 3 tiles and partial update of 3 tiles.
layer->invalidateRect(IntRect(0, 0, 300, 150));
- ccLayerTreeHost->updateLayers();
- ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
- updater.update(0, 4);
- EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_TRUE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
- updater.update(0, 4);
- EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_FALSE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ ccLayerTreeHost->updateLayers(updater);
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ layer->pushPropertiesTo(layerImpl.get());
+ }
ccLayerTreeHost->commitComplete();
// Partial update of 6 tiles.
layer->invalidateRect(IntRect(50, 50, 200, 100));
- ccLayerTreeHost->updateLayers();
- ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
- updater.update(0, 4);
- EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_TRUE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
- updater.update(0, 4);
- EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_FALSE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ ccLayerTreeHost->updateLayers(updater);
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ layer->pushPropertiesTo(layerImpl.get());
+ }
+ ccLayerTreeHost->commitComplete();
+
+ // Checkerboard all tiles.
+ layer->invalidateRect(IntRect(0, 0, 300, 200));
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ layer->pushPropertiesTo(layerImpl.get());
+ }
+ ccLayerTreeHost->commitComplete();
+
+ // Partail update of 6 checkerboard tiles.
+ layer->invalidateRect(IntRect(50, 50, 200, 100));
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ ccLayerTreeHost->updateLayers(updater);
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ layer->pushPropertiesTo(layerImpl.get());
+ }
ccLayerTreeHost->commitComplete();
ccLayerTreeHost->setRootLayer(0);
@@ -787,13 +984,13 @@ TEST(TiledLayerChromiumTest, tilesPaintedWithoutOcclusion)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ CCTextureUpdater updater;
// 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), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->prepareRectCount());
}
@@ -801,97 +998,137 @@ TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusion)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
layer->setBounds(IntSize(600, 600));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(200, 200, 300, 100);
+ occluded.setOcclusion(IntRect(200, 200, 300, 100));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000, 1);
+ EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
- occluded = IntRect(250, 200, 300, 100);
+ occluded.setOcclusion(IntRect(250, 200, 300, 100));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36-2, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000 + 340000, 1);
+ EXPECT_EQ(3 + 2, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
- occluded = IntRect(250, 250, 300, 100);
+ occluded.setOcclusion(IntRect(250, 250, 300, 100));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000 + 340000 + 360000, 1);
+ EXPECT_EQ(3 + 2, occluded.overdrawMetrics().tilesCulledForUpload());
}
TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndVisiblityConstraints)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
layer->setBounds(IntSize(600, 600));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
// The partially occluded tiles (by the 150 occlusion height) are visible beyond the occlusion, so not culled.
- occluded = IntRect(200, 200, 300, 150);
+ occluded.setOcclusion(IntRect(200, 200, 300, 150));
layer->setVisibleLayerRect(IntRect(0, 0, 600, 360));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
- EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 360), &occluded);
+ EXPECT_EQ(24-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000, 1);
+ EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload());
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
// Now the visible region stops at the edge of the occlusion so the partly visible tiles become fully occluded.
- occluded = IntRect(200, 200, 300, 150);
+ occluded.setOcclusion(IntRect(200, 200, 300, 150));
layer->setVisibleLayerRect(IntRect(0, 0, 600, 350));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
- EXPECT_EQ(36-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 350), &occluded);
+ EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000 + 180000, 1);
+ EXPECT_EQ(3 + 6, occluded.overdrawMetrics().tilesCulledForUpload());
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
// Now the visible region is even smaller than the occlusion, it should have the same result.
- occluded = IntRect(200, 200, 300, 150);
+ occluded.setOcclusion(IntRect(200, 200, 300, 150));
layer->setVisibleLayerRect(IntRect(0, 0, 600, 340));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
- EXPECT_EQ(36-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 340), &occluded);
+ EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000 + 180000 + 180000, 1);
+ EXPECT_EQ(3 + 6 + 6, occluded.overdrawMetrics().tilesCulledForUpload());
+
}
TEST(TiledLayerChromiumTest, tilesNotPaintedWithoutInvalidation)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
layer->setBounds(IntSize(600, 600));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(200, 200, 300, 100);
+ occluded.setOcclusion(IntRect(200, 200, 300, 100));
layer->setVisibleLayerRect(IntRect(0, 0, 600, 600));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000, 1);
+ EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
- // Repaint without marking it dirty.
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ // Repaint without marking it dirty. The culled tiles remained dirty.
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000, 1);
+ EXPECT_EQ(6, occluded.overdrawMetrics().tilesCulledForUpload());
}
TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndTransforms)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
@@ -901,19 +1138,25 @@ TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndTransforms)
TransformationMatrix screenTransform;
screenTransform.scale(0.5);
layer->setScreenSpaceTransform(screenTransform);
+ layer->setDrawTransform(screenTransform * TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(100, 100, 150, 50);
+ occluded.setOcclusion(IntRect(100, 100, 150, 50));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000, 1);
+ EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload());
}
TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
@@ -922,99 +1165,196 @@ TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
// pixels, which means none should be occluded.
layer->setContentsScale(0.5);
layer->setBounds(IntSize(600, 600));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(200, 200, 300, 100);
+ occluded.setOcclusion(IntRect(200, 200, 300, 100));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
// The content is half the size of the layer (so the number of tiles is fewer).
// In this case, the content is 300x300, and since the tile size is 100, the
// number of tiles 3x3.
EXPECT_EQ(9, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
// This makes sure the painting works when the content space is scaled to
// a different layer space. In this case the occluded region catches the
// blown up tiles.
- occluded = IntRect(200, 200, 300, 200);
+ occluded.setOcclusion(IntRect(200, 200, 300, 200));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000 + 80000, 1);
+ EXPECT_EQ(1, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
// This makes sure content scaling and transforms work together.
TransformationMatrix screenTransform;
screenTransform.scale(0.5);
layer->setScreenSpaceTransform(screenTransform);
+ layer->setDrawTransform(screenTransform * TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(100, 100, 150, 100);
+ occluded.setOcclusion(IntRect(100, 100, 150, 100));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000 + 80000 + 80000, 1);
+ EXPECT_EQ(1 + 1, occluded.overdrawMetrics().tilesCulledForUpload());
}
-TEST(TiledLayerChromiumTest, opaqueContentsRegion)
+TEST(TiledLayerChromiumTest, visibleContentOpaqueRegion)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100, so this invalidates and then paints two tiles in various ways.
IntRect opaquePaintRect;
Region opaqueContents;
- Region noOcclusion;
IntRect contentBounds = IntRect(0, 0, 100, 200);
IntRect visibleBounds = IntRect(0, 0, 100, 150);
layer->setBounds(contentBounds.size());
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
layer->setVisibleLayerRect(visibleBounds);
layer->setDrawOpacity(1);
- // If the layer doesn't paint opaque content, then the opaqueContentsRegion should be empty.
- layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
+ // If the layer doesn't paint opaque content, then the visibleContentOpaqueRegion should be empty.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
layer->invalidateRect(contentBounds);
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_TRUE(opaqueContents.isEmpty());
- // opaqueContentsRegion should match the visible part of what is painted opaque.
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
+ // visibleContentOpaqueRegion should match the visible part of what is painted opaque.
opaquePaintRect = IntRect(10, 10, 90, 190);
layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
layer->invalidateRect(contentBounds);
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
EXPECT_EQ(1u, opaqueContents.rects().size());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// If we paint again without invalidating, the same stuff should be opaque.
layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
EXPECT_EQ(1u, opaqueContents.rects().size());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// If we repaint a non-opaque part of the tile, then it shouldn't lose its opaque-ness. And other tiles should
// not be affected.
layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
layer->invalidateRect(IntRect(0, 0, 1, 1));
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
EXPECT_EQ(1u, opaqueContents.rects().size());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2 + 1, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100 + 1, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// If we repaint an opaque part of the tile, then it should lose its opaque-ness. But other tiles should still
// not be affected.
layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
layer->invalidateRect(IntRect(10, 10, 1, 1));
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_EQ_RECT(intersection(IntRect(10, 100, 90, 100), visibleBounds), opaqueContents.bounds());
EXPECT_EQ(1u, opaqueContents.rects().size());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2 + 1 + 1, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100 + 1 + 1, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
+ // No metrics are recorded in prepaint, so the values should not change from above.
+ layer->idleUpdateLayerRect(updater, contentBounds, &occluded);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2 + 1 + 1, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100 + 1 + 1, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+}
+
+TEST(TiledLayerChromiumTest, pixelsPaintedMetrics)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
+
+ // The tile size is 100x100, so this invalidates and then paints two tiles in various ways.
+
+ IntRect opaquePaintRect;
+ Region opaqueContents;
+
+ IntRect contentBounds = IntRect(0, 0, 100, 300);
+ IntRect visibleBounds = IntRect(0, 0, 100, 300);
+
+ layer->setBounds(contentBounds.size());
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
+ layer->setVisibleLayerRect(visibleBounds);
+ layer->setDrawOpacity(1);
+
+ // Invalidates and paints the whole layer.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+ layer->invalidateRect(contentBounds);
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
+ EXPECT_TRUE(opaqueContents.isEmpty());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 30000, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 30000, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
+ // Invalidates an area on the top and bottom tile, which will cause us to paint the tile in the middle,
+ // even though it is not dirty and will not be uploaded.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+ layer->invalidateRect(IntRect(0, 0, 1, 1));
+ layer->invalidateRect(IntRect(50, 200, 10, 10));
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
+ EXPECT_TRUE(opaqueContents.isEmpty());
+
+ // The middle tile was painted even though not invalidated.
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 30000 + 60 * 210, 1);
+ // The pixels uploaded will not include the non-invalidated tile in the middle.
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 30000 + 1 + 100, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
}
} // namespace
diff --git a/Source/WebKit/chromium/tests/TilingDataTest.cpp b/Source/WebKit/chromium/tests/TilingDataTest.cpp
index c29743f86..47c0361ea 100755
--- a/Source/WebKit/chromium/tests/TilingDataTest.cpp
+++ b/Source/WebKit/chromium/tests/TilingDataTest.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "TilingData.h"
+#include <wtf/Assertions.h>
#include <gtest/gtest.h>
@@ -38,385 +39,406 @@ using namespace WebCore;
namespace {
+class TestTiling : public TilingData {
+public:
+ TestTiling(int maxTextureSize, int totalSizeX, int totalSizeY, bool hasBorderTexels)
+ : TilingData(maxTextureSize, totalSizeX, totalSizeY, hasBorderTexels)
+ {
+ }
+
+ // This function only available for testing because of potential overflow.
+ int numTiles() const
+ {
+ int numTiles = numTilesX() * numTilesY();
+
+ // Assert no overflow.
+ EXPECT_GE(numTiles, 0);
+ if (numTiles > 0)
+ EXPECT_EQ(numTiles / numTilesX(), numTilesY());
+
+ return numTiles;
+ }
+};
+
TEST(TilingDataTest, numTiles_NoTiling)
{
- EXPECT_EQ(1, TilingData(16, 16, 16, false).numTiles());
- EXPECT_EQ(1, TilingData(16, 15, 15, true).numTiles());
- EXPECT_EQ(1, TilingData(16, 16, 16, true).numTiles());
- EXPECT_EQ(1, TilingData(16, 1, 16, false).numTiles());
- EXPECT_EQ(1, TilingData(15, 15, 15, true).numTiles());
+ EXPECT_EQ(1, TestTiling(16, 16, 16, false).numTiles());
+ EXPECT_EQ(1, TestTiling(16, 15, 15, true).numTiles());
+ EXPECT_EQ(1, TestTiling(16, 16, 16, true).numTiles());
+ EXPECT_EQ(1, TestTiling(16, 1, 16, false).numTiles());
+ EXPECT_EQ(1, TestTiling(15, 15, 15, true).numTiles());
}
TEST(TilingDataTest, numTiles_TilingNoBorders)
{
- EXPECT_EQ(0, TilingData(0, 0, 0, false).numTiles());
- EXPECT_EQ(0, TilingData(0, 4, 0, false).numTiles());
- EXPECT_EQ(0, TilingData(0, 0, 4, false).numTiles());
- EXPECT_EQ(0, TilingData(4, 4, 0, false).numTiles());
- EXPECT_EQ(0, TilingData(4, 0, 4, false).numTiles());
- EXPECT_EQ(0, TilingData(-8, 1, 1, false).numTiles());
- EXPECT_EQ(0, TilingData(-1, 1, 1, false).numTiles());
- EXPECT_EQ(0, TilingData(0, 1, 1, false).numTiles());
-
- EXPECT_EQ(1, TilingData(1, 1, 1, false).numTiles());
- EXPECT_EQ(2, TilingData(1, 1, 2, false).numTiles());
- EXPECT_EQ(2, TilingData(1, 2, 1, false).numTiles());
- EXPECT_EQ(1, TilingData(2, 1, 1, false).numTiles());
- EXPECT_EQ(1, TilingData(2, 1, 2, false).numTiles());
- EXPECT_EQ(1, TilingData(2, 2, 1, false).numTiles());
- EXPECT_EQ(1, TilingData(2, 2, 2, false).numTiles());
- EXPECT_EQ(1, TilingData(3, 3, 3, false).numTiles());
-
- EXPECT_EQ(1, TilingData(4, 1, 4, false).numTiles());
- EXPECT_EQ(1, TilingData(4, 2, 4, false).numTiles());
- EXPECT_EQ(1, TilingData(4, 3, 4, false).numTiles());
- EXPECT_EQ(1, TilingData(4, 4, 4, false).numTiles());
- EXPECT_EQ(2, TilingData(4, 5, 4, false).numTiles());
- EXPECT_EQ(2, TilingData(4, 6, 4, false).numTiles());
- EXPECT_EQ(2, TilingData(4, 7, 4, false).numTiles());
- EXPECT_EQ(2, TilingData(4, 8, 4, false).numTiles());
- EXPECT_EQ(3, TilingData(4, 9, 4, false).numTiles());
- EXPECT_EQ(3, TilingData(4, 10, 4, false).numTiles());
- EXPECT_EQ(3, TilingData(4, 11, 4, false).numTiles());
-
- EXPECT_EQ(1, TilingData(5, 1, 5, false).numTiles());
- EXPECT_EQ(1, TilingData(5, 2, 5, false).numTiles());
- EXPECT_EQ(1, TilingData(5, 3, 5, false).numTiles());
- EXPECT_EQ(1, TilingData(5, 4, 5, false).numTiles());
- EXPECT_EQ(1, TilingData(5, 5, 5, false).numTiles());
- EXPECT_EQ(2, TilingData(5, 6, 5, false).numTiles());
- EXPECT_EQ(2, TilingData(5, 7, 5, false).numTiles());
- EXPECT_EQ(2, TilingData(5, 8, 5, false).numTiles());
- EXPECT_EQ(2, TilingData(5, 9, 5, false).numTiles());
- EXPECT_EQ(2, TilingData(5, 10, 5, false).numTiles());
- EXPECT_EQ(3, TilingData(5, 11, 5, false).numTiles());
-
- EXPECT_EQ(1, TilingData(16, 16, 16, false).numTiles());
- EXPECT_EQ(1, TilingData(17, 16, 16, false).numTiles());
- EXPECT_EQ(4, TilingData(15, 16, 16, false).numTiles());
- EXPECT_EQ(4, TilingData(8, 16, 16, false).numTiles());
- EXPECT_EQ(6, TilingData(8, 17, 16, false).numTiles());
+ EXPECT_EQ(0, TestTiling(0, 0, 0, false).numTiles());
+ EXPECT_EQ(0, TestTiling(0, 4, 0, false).numTiles());
+ EXPECT_EQ(0, TestTiling(0, 0, 4, false).numTiles());
+ EXPECT_EQ(0, TestTiling(4, 4, 0, false).numTiles());
+ EXPECT_EQ(0, TestTiling(4, 0, 4, false).numTiles());
+ EXPECT_EQ(0, TestTiling(-8, 1, 1, false).numTiles());
+ EXPECT_EQ(0, TestTiling(-1, 1, 1, false).numTiles());
+ EXPECT_EQ(0, TestTiling(0, 1, 1, false).numTiles());
+
+ EXPECT_EQ(1, TestTiling(1, 1, 1, false).numTiles());
+ EXPECT_EQ(2, TestTiling(1, 1, 2, false).numTiles());
+ EXPECT_EQ(2, TestTiling(1, 2, 1, false).numTiles());
+ EXPECT_EQ(1, TestTiling(2, 1, 1, false).numTiles());
+ EXPECT_EQ(1, TestTiling(2, 1, 2, false).numTiles());
+ EXPECT_EQ(1, TestTiling(2, 2, 1, false).numTiles());
+ EXPECT_EQ(1, TestTiling(2, 2, 2, false).numTiles());
+ EXPECT_EQ(1, TestTiling(3, 3, 3, false).numTiles());
+
+ EXPECT_EQ(1, TestTiling(4, 1, 4, false).numTiles());
+ EXPECT_EQ(1, TestTiling(4, 2, 4, false).numTiles());
+ EXPECT_EQ(1, TestTiling(4, 3, 4, false).numTiles());
+ EXPECT_EQ(1, TestTiling(4, 4, 4, false).numTiles());
+ EXPECT_EQ(2, TestTiling(4, 5, 4, false).numTiles());
+ EXPECT_EQ(2, TestTiling(4, 6, 4, false).numTiles());
+ EXPECT_EQ(2, TestTiling(4, 7, 4, false).numTiles());
+ EXPECT_EQ(2, TestTiling(4, 8, 4, false).numTiles());
+ EXPECT_EQ(3, TestTiling(4, 9, 4, false).numTiles());
+ EXPECT_EQ(3, TestTiling(4, 10, 4, false).numTiles());
+ EXPECT_EQ(3, TestTiling(4, 11, 4, false).numTiles());
+
+ EXPECT_EQ(1, TestTiling(5, 1, 5, false).numTiles());
+ EXPECT_EQ(1, TestTiling(5, 2, 5, false).numTiles());
+ EXPECT_EQ(1, TestTiling(5, 3, 5, false).numTiles());
+ EXPECT_EQ(1, TestTiling(5, 4, 5, false).numTiles());
+ EXPECT_EQ(1, TestTiling(5, 5, 5, false).numTiles());
+ EXPECT_EQ(2, TestTiling(5, 6, 5, false).numTiles());
+ EXPECT_EQ(2, TestTiling(5, 7, 5, false).numTiles());
+ EXPECT_EQ(2, TestTiling(5, 8, 5, false).numTiles());
+ EXPECT_EQ(2, TestTiling(5, 9, 5, false).numTiles());
+ EXPECT_EQ(2, TestTiling(5, 10, 5, false).numTiles());
+ EXPECT_EQ(3, TestTiling(5, 11, 5, false).numTiles());
+
+ EXPECT_EQ(1, TestTiling(16, 16, 16, false).numTiles());
+ EXPECT_EQ(1, TestTiling(17, 16, 16, false).numTiles());
+ EXPECT_EQ(4, TestTiling(15, 16, 16, false).numTiles());
+ EXPECT_EQ(4, TestTiling(8, 16, 16, false).numTiles());
+ EXPECT_EQ(6, TestTiling(8, 17, 16, false).numTiles());
}
TEST(TilingDataTest, numTiles_TilingWithBorders)
{
- EXPECT_EQ(0, TilingData(0, 0, 0, true).numTiles());
- EXPECT_EQ(0, TilingData(0, 4, 0, true).numTiles());
- EXPECT_EQ(0, TilingData(0, 0, 4, true).numTiles());
- EXPECT_EQ(0, TilingData(4, 4, 0, true).numTiles());
- EXPECT_EQ(0, TilingData(4, 0, 4, true).numTiles());
- EXPECT_EQ(0, TilingData(-8, 1, 1, true).numTiles());
- EXPECT_EQ(0, TilingData(-1, 1, 1, true).numTiles());
- EXPECT_EQ(0, TilingData(0, 1, 1, true).numTiles());
-
- EXPECT_EQ(1, TilingData(1, 1, 1, true).numTiles());
- EXPECT_EQ(0, TilingData(1, 1, 2, true).numTiles());
- EXPECT_EQ(0, TilingData(1, 2, 1, true).numTiles());
- EXPECT_EQ(1, TilingData(2, 1, 1, true).numTiles());
- EXPECT_EQ(1, TilingData(2, 1, 2, true).numTiles());
- EXPECT_EQ(1, TilingData(2, 2, 1, true).numTiles());
- EXPECT_EQ(1, TilingData(2, 2, 2, true).numTiles());
-
- EXPECT_EQ(1, TilingData(3, 1, 3, true).numTiles());
- EXPECT_EQ(1, TilingData(3, 2, 3, true).numTiles());
- EXPECT_EQ(1, TilingData(3, 3, 3, true).numTiles());
- EXPECT_EQ(2, TilingData(3, 4, 3, true).numTiles());
- EXPECT_EQ(3, TilingData(3, 5, 3, true).numTiles());
- EXPECT_EQ(4, TilingData(3, 6, 3, true).numTiles());
- EXPECT_EQ(5, TilingData(3, 7, 3, true).numTiles());
-
- EXPECT_EQ(1, TilingData(4, 1, 4, true).numTiles());
- EXPECT_EQ(1, TilingData(4, 2, 4, true).numTiles());
- EXPECT_EQ(1, TilingData(4, 3, 4, true).numTiles());
- EXPECT_EQ(1, TilingData(4, 4, 4, true).numTiles());
- EXPECT_EQ(2, TilingData(4, 5, 4, true).numTiles());
- EXPECT_EQ(2, TilingData(4, 6, 4, true).numTiles());
- EXPECT_EQ(3, TilingData(4, 7, 4, true).numTiles());
- EXPECT_EQ(3, TilingData(4, 8, 4, true).numTiles());
- EXPECT_EQ(4, TilingData(4, 9, 4, true).numTiles());
- EXPECT_EQ(4, TilingData(4, 10, 4, true).numTiles());
- EXPECT_EQ(5, TilingData(4, 11, 4, true).numTiles());
-
- EXPECT_EQ(1, TilingData(5, 1, 5, true).numTiles());
- EXPECT_EQ(1, TilingData(5, 2, 5, true).numTiles());
- EXPECT_EQ(1, TilingData(5, 3, 5, true).numTiles());
- EXPECT_EQ(1, TilingData(5, 4, 5, true).numTiles());
- EXPECT_EQ(1, TilingData(5, 5, 5, true).numTiles());
- EXPECT_EQ(2, TilingData(5, 6, 5, true).numTiles());
- EXPECT_EQ(2, TilingData(5, 7, 5, true).numTiles());
- EXPECT_EQ(2, TilingData(5, 8, 5, true).numTiles());
- EXPECT_EQ(3, TilingData(5, 9, 5, true).numTiles());
- EXPECT_EQ(3, TilingData(5, 10, 5, true).numTiles());
- EXPECT_EQ(3, TilingData(5, 11, 5, true).numTiles());
+ EXPECT_EQ(0, TestTiling(0, 0, 0, true).numTiles());
+ EXPECT_EQ(0, TestTiling(0, 4, 0, true).numTiles());
+ EXPECT_EQ(0, TestTiling(0, 0, 4, true).numTiles());
+ EXPECT_EQ(0, TestTiling(4, 4, 0, true).numTiles());
+ EXPECT_EQ(0, TestTiling(4, 0, 4, true).numTiles());
+ EXPECT_EQ(0, TestTiling(-8, 1, 1, true).numTiles());
+ EXPECT_EQ(0, TestTiling(-1, 1, 1, true).numTiles());
+ EXPECT_EQ(0, TestTiling(0, 1, 1, true).numTiles());
+
+ EXPECT_EQ(1, TestTiling(1, 1, 1, true).numTiles());
+ EXPECT_EQ(0, TestTiling(1, 1, 2, true).numTiles());
+ EXPECT_EQ(0, TestTiling(1, 2, 1, true).numTiles());
+ EXPECT_EQ(1, TestTiling(2, 1, 1, true).numTiles());
+ EXPECT_EQ(1, TestTiling(2, 1, 2, true).numTiles());
+ EXPECT_EQ(1, TestTiling(2, 2, 1, true).numTiles());
+ EXPECT_EQ(1, TestTiling(2, 2, 2, true).numTiles());
+
+ EXPECT_EQ(1, TestTiling(3, 1, 3, true).numTiles());
+ EXPECT_EQ(1, TestTiling(3, 2, 3, true).numTiles());
+ EXPECT_EQ(1, TestTiling(3, 3, 3, true).numTiles());
+ EXPECT_EQ(2, TestTiling(3, 4, 3, true).numTiles());
+ EXPECT_EQ(3, TestTiling(3, 5, 3, true).numTiles());
+ EXPECT_EQ(4, TestTiling(3, 6, 3, true).numTiles());
+ EXPECT_EQ(5, TestTiling(3, 7, 3, true).numTiles());
+
+ EXPECT_EQ(1, TestTiling(4, 1, 4, true).numTiles());
+ EXPECT_EQ(1, TestTiling(4, 2, 4, true).numTiles());
+ EXPECT_EQ(1, TestTiling(4, 3, 4, true).numTiles());
+ EXPECT_EQ(1, TestTiling(4, 4, 4, true).numTiles());
+ EXPECT_EQ(2, TestTiling(4, 5, 4, true).numTiles());
+ EXPECT_EQ(2, TestTiling(4, 6, 4, true).numTiles());
+ EXPECT_EQ(3, TestTiling(4, 7, 4, true).numTiles());
+ EXPECT_EQ(3, TestTiling(4, 8, 4, true).numTiles());
+ EXPECT_EQ(4, TestTiling(4, 9, 4, true).numTiles());
+ EXPECT_EQ(4, TestTiling(4, 10, 4, true).numTiles());
+ EXPECT_EQ(5, TestTiling(4, 11, 4, true).numTiles());
+
+ EXPECT_EQ(1, TestTiling(5, 1, 5, true).numTiles());
+ EXPECT_EQ(1, TestTiling(5, 2, 5, true).numTiles());
+ EXPECT_EQ(1, TestTiling(5, 3, 5, true).numTiles());
+ EXPECT_EQ(1, TestTiling(5, 4, 5, true).numTiles());
+ EXPECT_EQ(1, TestTiling(5, 5, 5, true).numTiles());
+ EXPECT_EQ(2, TestTiling(5, 6, 5, true).numTiles());
+ EXPECT_EQ(2, TestTiling(5, 7, 5, true).numTiles());
+ EXPECT_EQ(2, TestTiling(5, 8, 5, true).numTiles());
+ EXPECT_EQ(3, TestTiling(5, 9, 5, true).numTiles());
+ EXPECT_EQ(3, TestTiling(5, 10, 5, true).numTiles());
+ EXPECT_EQ(3, TestTiling(5, 11, 5, true).numTiles());
}
TEST(TilingDataTest, tileXIndexFromSrcCoord)
{
- EXPECT_EQ(0, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(2));
- EXPECT_EQ(1, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(3));
- EXPECT_EQ(1, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(4));
- EXPECT_EQ(1, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(5));
- EXPECT_EQ(2, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(6));
- EXPECT_EQ(2, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(7));
- EXPECT_EQ(2, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(8));
- EXPECT_EQ(3, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(9));
- EXPECT_EQ(3, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(10));
- EXPECT_EQ(3, TilingData(3, 10, 10, false).tileXIndexFromSrcCoord(11));
-
- EXPECT_EQ(0, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(1));
- EXPECT_EQ(1, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(2));
- EXPECT_EQ(2, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(3));
- EXPECT_EQ(3, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(4));
- EXPECT_EQ(4, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(5));
- EXPECT_EQ(5, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(6));
- EXPECT_EQ(6, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(7));
- EXPECT_EQ(7, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(8));
- EXPECT_EQ(7, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(9));
- EXPECT_EQ(7, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(10));
- EXPECT_EQ(7, TilingData(3, 10, 10, true).tileXIndexFromSrcCoord(11));
-
- EXPECT_EQ(0, TilingData(1, 1, 1, false).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(2, 2, 2, false).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(2, 2, 2, false).tileXIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 3, false).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 3, 3, false).tileXIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 3, false).tileXIndexFromSrcCoord(2));
-
- EXPECT_EQ(0, TilingData(3, 4, 3, false).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 4, 3, false).tileXIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 4, 3, false).tileXIndexFromSrcCoord(2));
- EXPECT_EQ(1, TilingData(3, 4, 3, false).tileXIndexFromSrcCoord(3));
-
- EXPECT_EQ(0, TilingData(1, 1, 1, true).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(2, 2, 2, true).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(2, 2, 2, true).tileXIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 3, true).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 3, 3, true).tileXIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 3, true).tileXIndexFromSrcCoord(2));
-
- EXPECT_EQ(0, TilingData(3, 4, 3, true).tileXIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 4, 3, true).tileXIndexFromSrcCoord(1));
- EXPECT_EQ(1, TilingData(3, 4, 3, true).tileXIndexFromSrcCoord(2));
- EXPECT_EQ(1, TilingData(3, 4, 3, true).tileXIndexFromSrcCoord(3));
+ EXPECT_EQ(0, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(2));
+ EXPECT_EQ(1, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(3));
+ EXPECT_EQ(1, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(4));
+ EXPECT_EQ(1, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(5));
+ EXPECT_EQ(2, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(6));
+ EXPECT_EQ(2, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(7));
+ EXPECT_EQ(2, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(8));
+ EXPECT_EQ(3, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(9));
+ EXPECT_EQ(3, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(10));
+ EXPECT_EQ(3, TestTiling(3, 10, 10, false).tileXIndexFromSrcCoord(11));
+
+ EXPECT_EQ(0, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(1));
+ EXPECT_EQ(1, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(2));
+ EXPECT_EQ(2, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(3));
+ EXPECT_EQ(3, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(4));
+ EXPECT_EQ(4, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(5));
+ EXPECT_EQ(5, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(6));
+ EXPECT_EQ(6, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(7));
+ EXPECT_EQ(7, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(8));
+ EXPECT_EQ(7, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(9));
+ EXPECT_EQ(7, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(10));
+ EXPECT_EQ(7, TestTiling(3, 10, 10, true).tileXIndexFromSrcCoord(11));
+
+ EXPECT_EQ(0, TestTiling(1, 1, 1, false).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(2, 2, 2, false).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(2, 2, 2, false).tileXIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, false).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, false).tileXIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, false).tileXIndexFromSrcCoord(2));
+
+ EXPECT_EQ(0, TestTiling(3, 4, 3, false).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 4, 3, false).tileXIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 4, 3, false).tileXIndexFromSrcCoord(2));
+ EXPECT_EQ(1, TestTiling(3, 4, 3, false).tileXIndexFromSrcCoord(3));
+
+ EXPECT_EQ(0, TestTiling(1, 1, 1, true).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(2, 2, 2, true).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(2, 2, 2, true).tileXIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, true).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, true).tileXIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, true).tileXIndexFromSrcCoord(2));
+
+ EXPECT_EQ(0, TestTiling(3, 4, 3, true).tileXIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 4, 3, true).tileXIndexFromSrcCoord(1));
+ EXPECT_EQ(1, TestTiling(3, 4, 3, true).tileXIndexFromSrcCoord(2));
+ EXPECT_EQ(1, TestTiling(3, 4, 3, true).tileXIndexFromSrcCoord(3));
}
TEST(TilingDataTest, tileYIndexFromSrcCoord)
{
- EXPECT_EQ(0, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(2));
- EXPECT_EQ(1, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(3));
- EXPECT_EQ(1, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(4));
- EXPECT_EQ(1, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(5));
- EXPECT_EQ(2, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(6));
- EXPECT_EQ(2, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(7));
- EXPECT_EQ(2, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(8));
- EXPECT_EQ(3, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(9));
- EXPECT_EQ(3, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(10));
- EXPECT_EQ(3, TilingData(3, 10, 10, false).tileYIndexFromSrcCoord(11));
-
- EXPECT_EQ(0, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(1));
- EXPECT_EQ(1, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(2));
- EXPECT_EQ(2, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(3));
- EXPECT_EQ(3, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(4));
- EXPECT_EQ(4, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(5));
- EXPECT_EQ(5, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(6));
- EXPECT_EQ(6, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(7));
- EXPECT_EQ(7, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(8));
- EXPECT_EQ(7, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(9));
- EXPECT_EQ(7, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(10));
- EXPECT_EQ(7, TilingData(3, 10, 10, true).tileYIndexFromSrcCoord(11));
-
- EXPECT_EQ(0, TilingData(1, 1, 1, false).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(2, 2, 2, false).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(2, 2, 2, false).tileYIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 3, false).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 3, 3, false).tileYIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 3, false).tileYIndexFromSrcCoord(2));
-
- EXPECT_EQ(0, TilingData(3, 3, 4, false).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 3, 4, false).tileYIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 4, false).tileYIndexFromSrcCoord(2));
- EXPECT_EQ(1, TilingData(3, 3, 4, false).tileYIndexFromSrcCoord(3));
-
- EXPECT_EQ(0, TilingData(1, 1, 1, true).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(2, 2, 2, true).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(2, 2, 2, true).tileYIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 3, true).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 3, 3, true).tileYIndexFromSrcCoord(1));
- EXPECT_EQ(0, TilingData(3, 3, 3, true).tileYIndexFromSrcCoord(2));
-
- EXPECT_EQ(0, TilingData(3, 3, 4, true).tileYIndexFromSrcCoord(0));
- EXPECT_EQ(0, TilingData(3, 3, 4, true).tileYIndexFromSrcCoord(1));
- EXPECT_EQ(1, TilingData(3, 3, 4, true).tileYIndexFromSrcCoord(2));
- EXPECT_EQ(1, TilingData(3, 3, 4, true).tileYIndexFromSrcCoord(3));
+ EXPECT_EQ(0, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(2));
+ EXPECT_EQ(1, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(3));
+ EXPECT_EQ(1, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(4));
+ EXPECT_EQ(1, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(5));
+ EXPECT_EQ(2, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(6));
+ EXPECT_EQ(2, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(7));
+ EXPECT_EQ(2, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(8));
+ EXPECT_EQ(3, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(9));
+ EXPECT_EQ(3, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(10));
+ EXPECT_EQ(3, TestTiling(3, 10, 10, false).tileYIndexFromSrcCoord(11));
+
+ EXPECT_EQ(0, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(1));
+ EXPECT_EQ(1, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(2));
+ EXPECT_EQ(2, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(3));
+ EXPECT_EQ(3, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(4));
+ EXPECT_EQ(4, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(5));
+ EXPECT_EQ(5, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(6));
+ EXPECT_EQ(6, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(7));
+ EXPECT_EQ(7, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(8));
+ EXPECT_EQ(7, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(9));
+ EXPECT_EQ(7, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(10));
+ EXPECT_EQ(7, TestTiling(3, 10, 10, true).tileYIndexFromSrcCoord(11));
+
+ EXPECT_EQ(0, TestTiling(1, 1, 1, false).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(2, 2, 2, false).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(2, 2, 2, false).tileYIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, false).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, false).tileYIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, false).tileYIndexFromSrcCoord(2));
+
+ EXPECT_EQ(0, TestTiling(3, 3, 4, false).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 4, false).tileYIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 4, false).tileYIndexFromSrcCoord(2));
+ EXPECT_EQ(1, TestTiling(3, 3, 4, false).tileYIndexFromSrcCoord(3));
+
+ EXPECT_EQ(0, TestTiling(1, 1, 1, true).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(2, 2, 2, true).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(2, 2, 2, true).tileYIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, true).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, true).tileYIndexFromSrcCoord(1));
+ EXPECT_EQ(0, TestTiling(3, 3, 3, true).tileYIndexFromSrcCoord(2));
+
+ EXPECT_EQ(0, TestTiling(3, 3, 4, true).tileYIndexFromSrcCoord(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 4, true).tileYIndexFromSrcCoord(1));
+ EXPECT_EQ(1, TestTiling(3, 3, 4, true).tileYIndexFromSrcCoord(2));
+ EXPECT_EQ(1, TestTiling(3, 3, 4, true).tileYIndexFromSrcCoord(3));
}
TEST(TilingDataTest, tileSizeX)
{
- EXPECT_EQ(5, TilingData(5, 5, 5, false).tileSizeX(0));
- EXPECT_EQ(5, TilingData(5, 5, 5, true).tileSizeX(0));
-
- EXPECT_EQ(5, TilingData(5, 6, 6, false).tileSizeX(0));
- EXPECT_EQ(1, TilingData(5, 6, 6, false).tileSizeX(1));
- EXPECT_EQ(4, TilingData(5, 6, 6, true).tileSizeX(0));
- EXPECT_EQ(2, TilingData(5, 6, 6, true).tileSizeX(1));
-
- EXPECT_EQ(5, TilingData(5, 8, 8, false).tileSizeX(0));
- EXPECT_EQ(3, TilingData(5, 8, 8, false).tileSizeX(1));
- EXPECT_EQ(4, TilingData(5, 8, 8, true).tileSizeX(0));
- EXPECT_EQ(4, TilingData(5, 8, 8, true).tileSizeX(1));
-
- EXPECT_EQ(5, TilingData(5, 10, 10, false).tileSizeX(0));
- EXPECT_EQ(5, TilingData(5, 10, 10, false).tileSizeX(1));
- EXPECT_EQ(4, TilingData(5, 10, 10, true).tileSizeX(0));
- EXPECT_EQ(3, TilingData(5, 10, 10, true).tileSizeX(1));
- EXPECT_EQ(3, TilingData(5, 10, 10, true).tileSizeX(2));
-
- EXPECT_EQ(4, TilingData(5, 11, 11, true).tileSizeX(2));
- EXPECT_EQ(3, TilingData(5, 12, 12, true).tileSizeX(2));
+ EXPECT_EQ(5, TestTiling(5, 5, 5, false).tileSizeX(0));
+ EXPECT_EQ(5, TestTiling(5, 5, 5, true).tileSizeX(0));
+
+ EXPECT_EQ(5, TestTiling(5, 6, 6, false).tileSizeX(0));
+ EXPECT_EQ(1, TestTiling(5, 6, 6, false).tileSizeX(1));
+ EXPECT_EQ(4, TestTiling(5, 6, 6, true).tileSizeX(0));
+ EXPECT_EQ(2, TestTiling(5, 6, 6, true).tileSizeX(1));
+
+ EXPECT_EQ(5, TestTiling(5, 8, 8, false).tileSizeX(0));
+ EXPECT_EQ(3, TestTiling(5, 8, 8, false).tileSizeX(1));
+ EXPECT_EQ(4, TestTiling(5, 8, 8, true).tileSizeX(0));
+ EXPECT_EQ(4, TestTiling(5, 8, 8, true).tileSizeX(1));
+
+ EXPECT_EQ(5, TestTiling(5, 10, 10, false).tileSizeX(0));
+ EXPECT_EQ(5, TestTiling(5, 10, 10, false).tileSizeX(1));
+ EXPECT_EQ(4, TestTiling(5, 10, 10, true).tileSizeX(0));
+ EXPECT_EQ(3, TestTiling(5, 10, 10, true).tileSizeX(1));
+ EXPECT_EQ(3, TestTiling(5, 10, 10, true).tileSizeX(2));
+
+ EXPECT_EQ(4, TestTiling(5, 11, 11, true).tileSizeX(2));
+ EXPECT_EQ(3, TestTiling(5, 12, 12, true).tileSizeX(2));
}
TEST(TilingDataTest, tileSizeY)
{
- EXPECT_EQ(5, TilingData(5, 5, 5, false).tileSizeY(0));
- EXPECT_EQ(5, TilingData(5, 5, 5, true).tileSizeY(0));
-
- EXPECT_EQ(5, TilingData(5, 6, 6, false).tileSizeY(0));
- EXPECT_EQ(1, TilingData(5, 6, 6, false).tileSizeY(1));
- EXPECT_EQ(4, TilingData(5, 6, 6, true).tileSizeY(0));
- EXPECT_EQ(2, TilingData(5, 6, 6, true).tileSizeY(1));
-
- EXPECT_EQ(5, TilingData(5, 8, 8, false).tileSizeY(0));
- EXPECT_EQ(3, TilingData(5, 8, 8, false).tileSizeY(1));
- EXPECT_EQ(4, TilingData(5, 8, 8, true).tileSizeY(0));
- EXPECT_EQ(4, TilingData(5, 8, 8, true).tileSizeY(1));
-
- EXPECT_EQ(5, TilingData(5, 10, 10, false).tileSizeY(0));
- EXPECT_EQ(5, TilingData(5, 10, 10, false).tileSizeY(1));
- EXPECT_EQ(4, TilingData(5, 10, 10, true).tileSizeY(0));
- EXPECT_EQ(3, TilingData(5, 10, 10, true).tileSizeY(1));
- EXPECT_EQ(3, TilingData(5, 10, 10, true).tileSizeY(2));
-
- EXPECT_EQ(4, TilingData(5, 11, 11, true).tileSizeY(2));
- EXPECT_EQ(3, TilingData(5, 12, 12, true).tileSizeY(2));
+ EXPECT_EQ(5, TestTiling(5, 5, 5, false).tileSizeY(0));
+ EXPECT_EQ(5, TestTiling(5, 5, 5, true).tileSizeY(0));
+
+ EXPECT_EQ(5, TestTiling(5, 6, 6, false).tileSizeY(0));
+ EXPECT_EQ(1, TestTiling(5, 6, 6, false).tileSizeY(1));
+ EXPECT_EQ(4, TestTiling(5, 6, 6, true).tileSizeY(0));
+ EXPECT_EQ(2, TestTiling(5, 6, 6, true).tileSizeY(1));
+
+ EXPECT_EQ(5, TestTiling(5, 8, 8, false).tileSizeY(0));
+ EXPECT_EQ(3, TestTiling(5, 8, 8, false).tileSizeY(1));
+ EXPECT_EQ(4, TestTiling(5, 8, 8, true).tileSizeY(0));
+ EXPECT_EQ(4, TestTiling(5, 8, 8, true).tileSizeY(1));
+
+ EXPECT_EQ(5, TestTiling(5, 10, 10, false).tileSizeY(0));
+ EXPECT_EQ(5, TestTiling(5, 10, 10, false).tileSizeY(1));
+ EXPECT_EQ(4, TestTiling(5, 10, 10, true).tileSizeY(0));
+ EXPECT_EQ(3, TestTiling(5, 10, 10, true).tileSizeY(1));
+ EXPECT_EQ(3, TestTiling(5, 10, 10, true).tileSizeY(2));
+
+ EXPECT_EQ(4, TestTiling(5, 11, 11, true).tileSizeY(2));
+ EXPECT_EQ(3, TestTiling(5, 12, 12, true).tileSizeY(2));
}
TEST(TilingDataTest, tileSizeX_and_tilePositionX)
{
// Single tile cases:
- EXPECT_EQ(1, TilingData(3, 1, 1, false).tileSizeX(0));
- EXPECT_EQ(0, TilingData(3, 1, 1, false).tilePositionX(0));
- EXPECT_EQ(1, TilingData(3, 1, 100, false).tileSizeX(0));
- EXPECT_EQ(0, TilingData(3, 1, 100, false).tilePositionX(0));
- EXPECT_EQ(3, TilingData(3, 3, 1, false).tileSizeX(0));
- EXPECT_EQ(0, TilingData(3, 3, 1, false).tilePositionX(0));
- EXPECT_EQ(3, TilingData(3, 3, 100, false).tileSizeX(0));
- EXPECT_EQ(0, TilingData(3, 3, 100, false).tilePositionX(0));
- EXPECT_EQ(1, TilingData(3, 1, 1, true).tileSizeX(0));
- EXPECT_EQ(0, TilingData(3, 1, 1, true).tilePositionX(0));
- EXPECT_EQ(1, TilingData(3, 1, 100, true).tileSizeX(0));
- EXPECT_EQ(0, TilingData(3, 1, 100, true).tilePositionX(0));
- EXPECT_EQ(3, TilingData(3, 3, 1, true).tileSizeX(0));
- EXPECT_EQ(0, TilingData(3, 3, 1, true).tilePositionX(0));
- EXPECT_EQ(3, TilingData(3, 3, 100, true).tileSizeX(0));
- EXPECT_EQ(0, TilingData(3, 3, 100, true).tilePositionX(0));
+ EXPECT_EQ(1, TestTiling(3, 1, 1, false).tileSizeX(0));
+ EXPECT_EQ(0, TestTiling(3, 1, 1, false).tilePositionX(0));
+ EXPECT_EQ(1, TestTiling(3, 1, 100, false).tileSizeX(0));
+ EXPECT_EQ(0, TestTiling(3, 1, 100, false).tilePositionX(0));
+ EXPECT_EQ(3, TestTiling(3, 3, 1, false).tileSizeX(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 1, false).tilePositionX(0));
+ EXPECT_EQ(3, TestTiling(3, 3, 100, false).tileSizeX(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 100, false).tilePositionX(0));
+ EXPECT_EQ(1, TestTiling(3, 1, 1, true).tileSizeX(0));
+ EXPECT_EQ(0, TestTiling(3, 1, 1, true).tilePositionX(0));
+ EXPECT_EQ(1, TestTiling(3, 1, 100, true).tileSizeX(0));
+ EXPECT_EQ(0, TestTiling(3, 1, 100, true).tilePositionX(0));
+ EXPECT_EQ(3, TestTiling(3, 3, 1, true).tileSizeX(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 1, true).tilePositionX(0));
+ EXPECT_EQ(3, TestTiling(3, 3, 100, true).tileSizeX(0));
+ EXPECT_EQ(0, TestTiling(3, 3, 100, true).tilePositionX(0));
// Multiple tiles:
// no border
// positions 0, 3
- EXPECT_EQ(2, TilingData(3, 6, 1, false).numTiles());
- EXPECT_EQ(3, TilingData(3, 6, 1, false).tileSizeX(0));
- EXPECT_EQ(3, TilingData(3, 6, 1, false).tileSizeX(1));
- EXPECT_EQ(0, TilingData(3, 6, 1, false).tilePositionX(0));
- EXPECT_EQ(3, TilingData(3, 6, 1, false).tilePositionX(1));
- EXPECT_EQ(3, TilingData(3, 6, 100, false).tileSizeX(0));
- EXPECT_EQ(3, TilingData(3, 6, 100, false).tileSizeX(1));
- EXPECT_EQ(0, TilingData(3, 6, 100, false).tilePositionX(0));
- EXPECT_EQ(3, TilingData(3, 6, 100, false).tilePositionX(1));
+ EXPECT_EQ(2, TestTiling(3, 6, 1, false).numTiles());
+ EXPECT_EQ(3, TestTiling(3, 6, 1, false).tileSizeX(0));
+ EXPECT_EQ(3, TestTiling(3, 6, 1, false).tileSizeX(1));
+ EXPECT_EQ(0, TestTiling(3, 6, 1, false).tilePositionX(0));
+ EXPECT_EQ(3, TestTiling(3, 6, 1, false).tilePositionX(1));
+ EXPECT_EQ(3, TestTiling(3, 6, 100, false).tileSizeX(0));
+ EXPECT_EQ(3, TestTiling(3, 6, 100, false).tileSizeX(1));
+ EXPECT_EQ(0, TestTiling(3, 6, 100, false).tilePositionX(0));
+ EXPECT_EQ(3, TestTiling(3, 6, 100, false).tilePositionX(1));
// Multiple tiles:
// with border
// positions 0, 2, 3, 4
- EXPECT_EQ(4, TilingData(3, 6, 1, true).numTiles());
- EXPECT_EQ(2, TilingData(3, 6, 1, true).tileSizeX(0));
- EXPECT_EQ(1, TilingData(3, 6, 1, true).tileSizeX(1));
- EXPECT_EQ(1, TilingData(3, 6, 1, true).tileSizeX(2));
- EXPECT_EQ(2, TilingData(3, 6, 1, true).tileSizeX(3));
- EXPECT_EQ(0, TilingData(3, 6, 1, true).tilePositionX(0));
- EXPECT_EQ(2, TilingData(3, 6, 1, true).tilePositionX(1));
- EXPECT_EQ(3, TilingData(3, 6, 1, true).tilePositionX(2));
- EXPECT_EQ(4, TilingData(3, 6, 1, true).tilePositionX(3));
- EXPECT_EQ(2, TilingData(3, 6, 100, true).tileSizeX(0));
- EXPECT_EQ(1, TilingData(3, 6, 100, true).tileSizeX(1));
- EXPECT_EQ(1, TilingData(3, 6, 100, true).tileSizeX(2));
- EXPECT_EQ(2, TilingData(3, 6, 100, true).tileSizeX(3));
- EXPECT_EQ(0, TilingData(3, 6, 100, true).tilePositionX(0));
- EXPECT_EQ(2, TilingData(3, 6, 100, true).tilePositionX(1));
- EXPECT_EQ(3, TilingData(3, 6, 100, true).tilePositionX(2));
- EXPECT_EQ(4, TilingData(3, 6, 100, true).tilePositionX(3));
+ EXPECT_EQ(4, TestTiling(3, 6, 1, true).numTiles());
+ EXPECT_EQ(2, TestTiling(3, 6, 1, true).tileSizeX(0));
+ EXPECT_EQ(1, TestTiling(3, 6, 1, true).tileSizeX(1));
+ EXPECT_EQ(1, TestTiling(3, 6, 1, true).tileSizeX(2));
+ EXPECT_EQ(2, TestTiling(3, 6, 1, true).tileSizeX(3));
+ EXPECT_EQ(0, TestTiling(3, 6, 1, true).tilePositionX(0));
+ EXPECT_EQ(2, TestTiling(3, 6, 1, true).tilePositionX(1));
+ EXPECT_EQ(3, TestTiling(3, 6, 1, true).tilePositionX(2));
+ EXPECT_EQ(4, TestTiling(3, 6, 1, true).tilePositionX(3));
+ EXPECT_EQ(2, TestTiling(3, 6, 100, true).tileSizeX(0));
+ EXPECT_EQ(1, TestTiling(3, 6, 100, true).tileSizeX(1));
+ EXPECT_EQ(1, TestTiling(3, 6, 100, true).tileSizeX(2));
+ EXPECT_EQ(2, TestTiling(3, 6, 100, true).tileSizeX(3));
+ EXPECT_EQ(0, TestTiling(3, 6, 100, true).tilePositionX(0));
+ EXPECT_EQ(2, TestTiling(3, 6, 100, true).tilePositionX(1));
+ EXPECT_EQ(3, TestTiling(3, 6, 100, true).tilePositionX(2));
+ EXPECT_EQ(4, TestTiling(3, 6, 100, true).tilePositionX(3));
}
TEST(TilingDataTest, tileSizeY_and_tilePositionY)
{
// Single tile cases:
- EXPECT_EQ(1, TilingData(3, 1, 1, false).tileSizeY(0));
- EXPECT_EQ(0, TilingData(3, 1, 1, false).tilePositionY(0));
- EXPECT_EQ(1, TilingData(3, 100, 1, false).tileSizeY(0));
- EXPECT_EQ(0, TilingData(3, 100, 1, false).tilePositionY(0));
- EXPECT_EQ(3, TilingData(3, 1, 3, false).tileSizeY(0));
- EXPECT_EQ(0, TilingData(3, 1, 3, false).tilePositionY(0));
- EXPECT_EQ(3, TilingData(3, 100, 3, false).tileSizeY(0));
- EXPECT_EQ(0, TilingData(3, 100, 3, false).tilePositionY(0));
- EXPECT_EQ(1, TilingData(3, 1, 1, true).tileSizeY(0));
- EXPECT_EQ(0, TilingData(3, 1, 1, true).tilePositionY(0));
- EXPECT_EQ(1, TilingData(3, 100, 1, true).tileSizeY(0));
- EXPECT_EQ(0, TilingData(3, 100, 1, true).tilePositionY(0));
- EXPECT_EQ(3, TilingData(3, 1, 3, true).tileSizeY(0));
- EXPECT_EQ(0, TilingData(3, 1, 3, true).tilePositionY(0));
- EXPECT_EQ(3, TilingData(3, 100, 3, true).tileSizeY(0));
- EXPECT_EQ(0, TilingData(3, 100, 3, true).tilePositionY(0));
+ EXPECT_EQ(1, TestTiling(3, 1, 1, false).tileSizeY(0));
+ EXPECT_EQ(0, TestTiling(3, 1, 1, false).tilePositionY(0));
+ EXPECT_EQ(1, TestTiling(3, 100, 1, false).tileSizeY(0));
+ EXPECT_EQ(0, TestTiling(3, 100, 1, false).tilePositionY(0));
+ EXPECT_EQ(3, TestTiling(3, 1, 3, false).tileSizeY(0));
+ EXPECT_EQ(0, TestTiling(3, 1, 3, false).tilePositionY(0));
+ EXPECT_EQ(3, TestTiling(3, 100, 3, false).tileSizeY(0));
+ EXPECT_EQ(0, TestTiling(3, 100, 3, false).tilePositionY(0));
+ EXPECT_EQ(1, TestTiling(3, 1, 1, true).tileSizeY(0));
+ EXPECT_EQ(0, TestTiling(3, 1, 1, true).tilePositionY(0));
+ EXPECT_EQ(1, TestTiling(3, 100, 1, true).tileSizeY(0));
+ EXPECT_EQ(0, TestTiling(3, 100, 1, true).tilePositionY(0));
+ EXPECT_EQ(3, TestTiling(3, 1, 3, true).tileSizeY(0));
+ EXPECT_EQ(0, TestTiling(3, 1, 3, true).tilePositionY(0));
+ EXPECT_EQ(3, TestTiling(3, 100, 3, true).tileSizeY(0));
+ EXPECT_EQ(0, TestTiling(3, 100, 3, true).tilePositionY(0));
// Multiple tiles:
// no border
// positions 0, 3
- EXPECT_EQ(2, TilingData(3, 1, 6, false).numTiles());
- EXPECT_EQ(3, TilingData(3, 1, 6, false).tileSizeY(0));
- EXPECT_EQ(3, TilingData(3, 1, 6, false).tileSizeY(1));
- EXPECT_EQ(0, TilingData(3, 1, 6, false).tilePositionY(0));
- EXPECT_EQ(3, TilingData(3, 1, 6, false).tilePositionY(1));
- EXPECT_EQ(3, TilingData(3, 100, 6, false).tileSizeY(0));
- EXPECT_EQ(3, TilingData(3, 100, 6, false).tileSizeY(1));
- EXPECT_EQ(0, TilingData(3, 100, 6, false).tilePositionY(0));
- EXPECT_EQ(3, TilingData(3, 100, 6, false).tilePositionY(1));
+ EXPECT_EQ(2, TestTiling(3, 1, 6, false).numTiles());
+ EXPECT_EQ(3, TestTiling(3, 1, 6, false).tileSizeY(0));
+ EXPECT_EQ(3, TestTiling(3, 1, 6, false).tileSizeY(1));
+ EXPECT_EQ(0, TestTiling(3, 1, 6, false).tilePositionY(0));
+ EXPECT_EQ(3, TestTiling(3, 1, 6, false).tilePositionY(1));
+ EXPECT_EQ(3, TestTiling(3, 100, 6, false).tileSizeY(0));
+ EXPECT_EQ(3, TestTiling(3, 100, 6, false).tileSizeY(1));
+ EXPECT_EQ(0, TestTiling(3, 100, 6, false).tilePositionY(0));
+ EXPECT_EQ(3, TestTiling(3, 100, 6, false).tilePositionY(1));
// Multiple tiles:
// with border
// positions 0, 2, 3, 4
- EXPECT_EQ(4, TilingData(3, 1, 6, true).numTiles());
- EXPECT_EQ(2, TilingData(3, 1, 6, true).tileSizeY(0));
- EXPECT_EQ(1, TilingData(3, 1, 6, true).tileSizeY(1));
- EXPECT_EQ(1, TilingData(3, 1, 6, true).tileSizeY(2));
- EXPECT_EQ(2, TilingData(3, 1, 6, true).tileSizeY(3));
- EXPECT_EQ(0, TilingData(3, 1, 6, true).tilePositionY(0));
- EXPECT_EQ(2, TilingData(3, 1, 6, true).tilePositionY(1));
- EXPECT_EQ(3, TilingData(3, 1, 6, true).tilePositionY(2));
- EXPECT_EQ(4, TilingData(3, 1, 6, true).tilePositionY(3));
- EXPECT_EQ(2, TilingData(3, 100, 6, true).tileSizeY(0));
- EXPECT_EQ(1, TilingData(3, 100, 6, true).tileSizeY(1));
- EXPECT_EQ(1, TilingData(3, 100, 6, true).tileSizeY(2));
- EXPECT_EQ(2, TilingData(3, 100, 6, true).tileSizeY(3));
- EXPECT_EQ(0, TilingData(3, 100, 6, true).tilePositionY(0));
- EXPECT_EQ(2, TilingData(3, 100, 6, true).tilePositionY(1));
- EXPECT_EQ(3, TilingData(3, 100, 6, true).tilePositionY(2));
- EXPECT_EQ(4, TilingData(3, 100, 6, true).tilePositionY(3));
+ EXPECT_EQ(4, TestTiling(3, 1, 6, true).numTiles());
+ EXPECT_EQ(2, TestTiling(3, 1, 6, true).tileSizeY(0));
+ EXPECT_EQ(1, TestTiling(3, 1, 6, true).tileSizeY(1));
+ EXPECT_EQ(1, TestTiling(3, 1, 6, true).tileSizeY(2));
+ EXPECT_EQ(2, TestTiling(3, 1, 6, true).tileSizeY(3));
+ EXPECT_EQ(0, TestTiling(3, 1, 6, true).tilePositionY(0));
+ EXPECT_EQ(2, TestTiling(3, 1, 6, true).tilePositionY(1));
+ EXPECT_EQ(3, TestTiling(3, 1, 6, true).tilePositionY(2));
+ EXPECT_EQ(4, TestTiling(3, 1, 6, true).tilePositionY(3));
+ EXPECT_EQ(2, TestTiling(3, 100, 6, true).tileSizeY(0));
+ EXPECT_EQ(1, TestTiling(3, 100, 6, true).tileSizeY(1));
+ EXPECT_EQ(1, TestTiling(3, 100, 6, true).tileSizeY(2));
+ EXPECT_EQ(2, TestTiling(3, 100, 6, true).tileSizeY(3));
+ EXPECT_EQ(0, TestTiling(3, 100, 6, true).tilePositionY(0));
+ EXPECT_EQ(2, TestTiling(3, 100, 6, true).tilePositionY(1));
+ EXPECT_EQ(3, TestTiling(3, 100, 6, true).tilePositionY(2));
+ EXPECT_EQ(4, TestTiling(3, 100, 6, true).tilePositionY(3));
}
TEST(TilingDataTest, setTotalSize)
{
- TilingData data(5, 5, 5, false);
+ TestTiling data(5, 5, 5, false);
EXPECT_EQ(5, data.totalSizeX());
EXPECT_EQ(5, data.totalSizeY());
EXPECT_EQ(1, data.numTilesX());
@@ -446,7 +468,7 @@ TEST(TilingDataTest, setTotalSize)
TEST(TilingDataTest, setMaxTextureSizeNoBorders)
{
- TilingData data(8, 16, 32, false);
+ TestTiling data(8, 16, 32, false);
EXPECT_EQ(2, data.numTilesX());
EXPECT_EQ(4, data.numTilesY());
@@ -468,7 +490,7 @@ TEST(TilingDataTest, setMaxTextureSizeNoBorders)
TEST(TilingDataTest, setMaxTextureSizeBorders)
{
- TilingData data(8, 16, 32, true);
+ TestTiling data(8, 16, 32, true);
EXPECT_EQ(3, data.numTilesX());
EXPECT_EQ(5, data.numTilesY());
@@ -491,8 +513,8 @@ TEST(TilingDataTest, setMaxTextureSizeBorders)
TEST(TilingDataTest, assignment)
{
{
- TilingData source(8, 16, 32, true);
- TilingData dest = source;
+ TestTiling source(8, 16, 32, true);
+ TestTiling dest = source;
EXPECT_EQ(source.borderTexels(), dest.borderTexels());
EXPECT_EQ(source.maxTextureSize(), dest.maxTextureSize());
EXPECT_EQ(source.numTilesX(), dest.numTilesX());
@@ -501,8 +523,8 @@ TEST(TilingDataTest, assignment)
EXPECT_EQ(source.totalSizeY(), dest.totalSizeY());
}
{
- TilingData source(3, 6, 100, false);
- TilingData dest(source);
+ TestTiling source(3, 6, 100, false);
+ TestTiling dest(source);
EXPECT_EQ(source.borderTexels(), dest.borderTexels());
EXPECT_EQ(source.maxTextureSize(), dest.maxTextureSize());
EXPECT_EQ(source.numTilesX(), dest.numTilesX());
@@ -514,7 +536,7 @@ TEST(TilingDataTest, assignment)
TEST(TilingDataTest, setBorderTexels)
{
- TilingData data(8, 16, 32, false);
+ TestTiling data(8, 16, 32, false);
EXPECT_EQ(2, data.numTilesX());
EXPECT_EQ(4, data.numTilesY());
diff --git a/Source/WebKit/chromium/tests/TransparencyWinTest.cpp b/Source/WebKit/chromium/tests/TransparencyWinTest.cpp
index 5052bb166..ae3090d8c 100644
--- a/Source/WebKit/chromium/tests/TransparencyWinTest.cpp
+++ b/Source/WebKit/chromium/tests/TransparencyWinTest.cpp
@@ -395,6 +395,66 @@ TEST(TransparencyWin, TranslateOpaqueCompositeLayer)
EXPECT_EQ(green, getPixelAt(src->context(), 15, 7));
}
+static void testClippedLayerKeepTransform(TransparencyWin::LayerMode layerMode)
+{
+ // Fill with white.
+ OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), 1, ColorSpaceDeviceRGB));
+ Color white(0xFFFFFFFF);
+ FloatRect fullRect(0, 0, 16, 16);
+ src->context()->fillRect(fullRect, white, ColorSpaceDeviceRGB);
+
+ IntRect clipRect(IntPoint(11, 5), IntSize(1, 1));
+ src->context()->clip(clipRect);
+
+ // Scroll down by 6 (coordinate system goes up).
+ src->context()->save();
+ src->context()->translate(0, -6);
+
+ Color red(0xFFFF0000);
+ Color green(0xFF00FF00);
+ {
+ // The transparency layer after translation will be @ (0, -6) with
+ // a size that would be too large to handle unclipped.
+ TransparencyWin helper;
+ helper.init(src->context(),
+ layerMode,
+ TransparencyWin::KeepTransform,
+ IntRect(0, 0, INT_MAX, INT_MAX));
+
+ // Draw a green pixel at (11, 11). This should be within the clip rect
+ // and at (11, 5) after the transform.
+ FloatRect greenRect(11, 11, 1, 1);
+ helper.context()->fillRect(greenRect, green, ColorSpaceDeviceRGB);
+
+ // Draw a red pixel at (9, 9). This should be outside the clip rect
+ // and not drawn.
+ FloatRect redRect(9, 9, 1, 1);
+ helper.context()->fillRect(redRect, red, ColorSpaceDeviceRGB);
+ helper.composite();
+ }
+
+ src->context()->restore();
+
+ // Verify green pixel got drawn in clip rect and red pixel got clipped.
+ EXPECT_EQ(green, getPixelAt(src->context(), 11, 5));
+ EXPECT_EQ(white, getPixelAt(src->context(), 9, 3));
+}
+
+TEST(TransparencyWin, ClippedKeepTransformNoLayer)
+{
+ testClippedLayerKeepTransform(TransparencyWin::NoLayer);
+}
+
+TEST(TransparencyWin, ClippedKeepTransformOpaqueCompositeLayer)
+{
+ testClippedLayerKeepTransform(TransparencyWin::OpaqueCompositeLayer);
+}
+
+TEST(TransparencyWin, ClippedKeepTransformWhiteLayer)
+{
+ testClippedLayerKeepTransform(TransparencyWin::WhiteLayer);
+}
+
// Same as OpaqueCompositeLayer, but the canvas has a rotation applied. This
// tests that the propert transform is applied to the copied layer.
TEST(TransparencyWin, RotateOpaqueCompositeLayer)
diff --git a/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp b/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
index eb3850dab..098dd2731 100644
--- a/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
+++ b/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp
@@ -28,6 +28,7 @@
#include "CCAnimationTestCommon.h"
#include "LayerChromium.h"
+#include "Region.h"
#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCProxy.h"
@@ -72,12 +73,12 @@ public:
virtual ~MockLayerChromium() { }
- virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl()
+ virtual PassOwnPtr<CCLayerImpl> createCCLayerImpl() OVERRIDE
{
return MockCCLayerImpl::create(m_layerId);
}
- virtual void pushPropertiesTo(CCLayerImpl* ccLayer)
+ virtual void pushPropertiesTo(CCLayerImpl* ccLayer) OVERRIDE
{
LayerChromium::pushPropertiesTo(ccLayer);
@@ -96,22 +97,23 @@ private:
class FakeLayerAnimationController : public CCLayerAnimationController {
public:
- static PassOwnPtr<FakeLayerAnimationController> create()
+ static PassOwnPtr<FakeLayerAnimationController> create(CCLayerAnimationControllerClient* client)
{
- return adoptPtr(new FakeLayerAnimationController);
+ return adoptPtr(new FakeLayerAnimationController(client));
}
bool synchronizedAnimations() const { return m_synchronizedAnimations; }
private:
- FakeLayerAnimationController()
- : m_synchronizedAnimations(false)
+ explicit FakeLayerAnimationController(CCLayerAnimationControllerClient* client)
+ : CCLayerAnimationController(client)
+ , m_synchronizedAnimations(false)
{
}
- virtual void synchronizeAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+ virtual void pushAnimationUpdatesTo(CCLayerAnimationController* controllerImpl)
{
- CCLayerAnimationController::synchronizeAnimations(controllerImpl);
+ CCLayerAnimationController::pushAnimationUpdatesTo(controllerImpl);
m_synchronizedAnimations = true;
}
@@ -125,6 +127,8 @@ void expectTreesAreIdentical(LayerChromium* layer, CCLayerImpl* ccLayer)
EXPECT_EQ(layer->id(), ccLayer->id());
+ EXPECT_EQ(layer->nonFastScrollableRegion(), ccLayer->nonFastScrollableRegion());
+
ASSERT_EQ(!!layer->maskLayer(), !!ccLayer->maskLayer());
if (layer->maskLayer())
expectTreesAreIdentical(layer->maskLayer(), ccLayer->maskLayer());
@@ -142,6 +146,17 @@ void expectTreesAreIdentical(LayerChromium* layer, CCLayerImpl* ccLayer)
expectTreesAreIdentical(layerChildren[i].get(), ccLayerChildren[i].get());
}
+// Attempts to synchronizes a null tree. This should not crash, and should
+// return a null tree.
+TEST(TreeSynchronizerTest, syncNullTree)
+{
+ DebugScopedSetImplThread impl;
+
+ OwnPtr<CCLayerImpl> ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(0, nullptr);
+
+ EXPECT_TRUE(!ccLayerTreeRoot.get());
+}
+
// Constructs a very simple tree and synchronizes it without trying to reuse any preexisting layers.
TEST(TreeSynchronizerTest, syncSimpleTreeFromEmpty)
{
@@ -182,6 +197,34 @@ TEST(TreeSynchronizerTest, syncSimpleTreeReusingLayers)
EXPECT_EQ(secondCCLayerId, ccLayerDestructionList[0]);
}
+// Constructs a very simple tree and checks that a stacking-order change is tracked properly.
+TEST(TreeSynchronizerTest, syncSimpleTreeAndTrackStackingOrderChange)
+{
+ DebugScopedSetImplThread impl;
+ Vector<int> ccLayerDestructionList;
+
+ // Set up the tree and sync once. child2 needs to be synced here, too, even though we
+ // remove it to set up the intended scenario.
+ RefPtr<LayerChromium> layerTreeRoot = MockLayerChromium::create(&ccLayerDestructionList);
+ RefPtr<LayerChromium> child2 = MockLayerChromium::create(&ccLayerDestructionList);
+ layerTreeRoot->addChild(MockLayerChromium::create(&ccLayerDestructionList));
+ layerTreeRoot->addChild(child2);
+ OwnPtr<CCLayerImpl> ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), nullptr);
+ expectTreesAreIdentical(layerTreeRoot.get(), ccLayerTreeRoot.get());
+ ccLayerTreeRoot->resetAllChangeTrackingForSubtree();
+
+ // re-insert the layer and sync again.
+ child2->removeFromParent();
+ layerTreeRoot->addChild(child2);
+ ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), ccLayerTreeRoot.release());
+ expectTreesAreIdentical(layerTreeRoot.get(), ccLayerTreeRoot.get());
+
+ // Check that the impl thread properly tracked the change.
+ EXPECT_FALSE(ccLayerTreeRoot->layerPropertyChanged());
+ EXPECT_FALSE(ccLayerTreeRoot->children()[0]->layerPropertyChanged());
+ EXPECT_TRUE(ccLayerTreeRoot->children()[1]->layerPropertyChanged());
+}
+
TEST(TreeSynchronizerTest, syncSimpleTreeAndProperties)
{
DebugScopedSetImplThread impl;
@@ -190,10 +233,10 @@ TEST(TreeSynchronizerTest, syncSimpleTreeAndProperties)
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);
+ FloatPoint rootPosition = FloatPoint(2.3f, 7.4f);
layerTreeRoot->setPosition(rootPosition);
- float firstChildOpacity = 0.25;
+ float firstChildOpacity = 0.25f;
layerTreeRoot->children()[0]->setOpacity(firstChildOpacity);
IntSize secondChildBounds = IntSize(25, 53);
@@ -339,7 +382,8 @@ TEST(TreeSynchronizerTest, synchronizeAnimations)
DebugScopedSetImplThread impl;
RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create();
- layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummy;
+ layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create(&dummy));
EXPECT_FALSE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());
diff --git a/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp b/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp
index 459255e02..92f006184 100644
--- a/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp
+++ b/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp
@@ -30,115 +30,71 @@
#include "WebCompositor.h"
#include "WebCompositorInputHandlerClient.h"
#include "WebInputEvent.h"
+#include "cc/CCActiveGestureAnimation.h"
#include "cc/CCInputHandler.h"
#include "cc/CCSingleThreadProxy.h"
+#include "platform/WebFloatPoint.h"
+#include "platform/WebPoint.h"
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <wtf/OwnPtr.h>
-using WebKit::WebCompositorInputHandler;
-using WebKit::WebCompositorInputHandlerImpl;
+using namespace WebKit;
namespace {
-class MockInputHandlerClient : public WebCore::CCInputHandlerClient {
- WTF_MAKE_NONCOPYABLE(MockInputHandlerClient);
+class MockCCInputHandlerClient : public WebCore::CCInputHandlerClient {
+ WTF_MAKE_NONCOPYABLE(MockCCInputHandlerClient);
public:
- MockInputHandlerClient()
- : m_scrollStatus(ScrollStarted)
- , m_pinchStarted(false)
- , m_pinchEnded(false)
- , m_pinchMagnification(0)
+ MockCCInputHandlerClient()
{
}
- virtual ~MockInputHandlerClient() { }
+ virtual ~MockCCInputHandlerClient() { }
- void setScrollStatus(ScrollStatus status) { m_scrollStatus = status; }
- bool pinchStarted() const { return m_pinchStarted; }
- bool pinchEnded() const { return m_pinchEnded; }
- float pinchMaginifcation() const { return m_pinchMagnification; }
+ MOCK_METHOD0(pinchGestureBegin, void());
+ MOCK_METHOD2(pinchGestureUpdate, void(float magnifyDelta, const WebCore::IntPoint& anchor));
+ MOCK_METHOD0(pinchGestureEnd, void());
- void resetPinch()
- {
- m_pinchStarted = m_pinchEnded = false;
- m_pinchMagnification = 0;
- }
+ MOCK_METHOD0(scheduleAnimation, void());
-private:
- virtual void setNeedsRedraw() OVERRIDE { }
- virtual ScrollStatus scrollBegin(const WebCore::IntPoint&, WebCore::CCInputHandlerClient::ScrollInputType) OVERRIDE
- {
- return m_scrollStatus;
- }
- virtual void scrollBy(const WebCore::IntSize&) OVERRIDE { }
- virtual void scrollEnd() OVERRIDE { }
+ MOCK_METHOD2(scrollBegin, ScrollStatus(const WebCore::IntPoint&, WebCore::CCInputHandlerClient::ScrollInputType));
+ MOCK_METHOD1(scrollBy, void(const WebCore::IntSize&));
+ MOCK_METHOD0(scrollEnd, void());
- virtual void pinchGestureBegin() OVERRIDE
- {
- m_pinchStarted = true;
- }
- virtual void pinchGestureUpdate(float magnifyDelta, const WebCore::IntPoint& anchor) OVERRIDE
- {
- m_pinchMagnification = magnifyDelta;
- }
- virtual void pinchGestureEnd() OVERRIDE
- {
- m_pinchEnded = true;
- }
+private:
virtual void startPageScaleAnimation(const WebCore::IntSize& targetPosition,
bool anchorPoint,
float pageScale,
double startTimeMs,
double durationMs) OVERRIDE { }
- ScrollStatus m_scrollStatus;
- bool m_pinchStarted;
- bool m_pinchEnded;
- float m_pinchMagnification;
+ virtual WebCore::CCActiveGestureAnimation* activeGestureAnimation() OVERRIDE { return 0; }
+ virtual void setActiveGestureAnimation(PassOwnPtr<WebCore::CCActiveGestureAnimation>) OVERRIDE { }
};
-class MockWebCompositorInputHandlerClient : public WebKit::WebCompositorInputHandlerClient {
+class MockWebCompositorInputHandlerClient : public WebCompositorInputHandlerClient {
WTF_MAKE_NONCOPYABLE(MockWebCompositorInputHandlerClient);
public:
MockWebCompositorInputHandlerClient()
- : m_handled(false)
- , m_sendToWidget(false)
+ : WebCompositorInputHandlerClient()
{
}
virtual ~MockWebCompositorInputHandlerClient() { }
- void reset()
- {
- m_handled = false;
- m_sendToWidget = false;
- }
-
- bool handled() const { return m_handled; }
- bool sendToWidget() const { return m_sendToWidget; }
+ MOCK_METHOD0(willShutdown, void());
+ MOCK_METHOD0(didHandleInputEvent, void());
+ MOCK_METHOD1(didNotHandleInputEvent, void(bool sendToWidget));
-private:
- virtual void willShutdown() OVERRIDE { }
- virtual void didHandleInputEvent() OVERRIDE
- {
- m_handled = true;
- }
- virtual void didNotHandleInputEvent(bool sendToWidget) OVERRIDE
- {
- m_sendToWidget = sendToWidget;
- }
+ MOCK_METHOD1(transferActiveWheelFlingAnimation, void(const WebActiveWheelFlingParameters&));
- bool m_handled;
- bool m_sendToWidget;
};
TEST(WebCompositorInputHandlerImpl, fromIdentifier)
{
- WebKit::WebCompositor::initialize(0);
-#ifndef NDEBUG
- // WebCompositorInputHandler APIs can only be called from the compositor thread.
+ WebCompositor::initialize(0);
WebCore::DebugScopedSetImplThread alwaysImplThread;
-#endif
// Before creating any WebCompositorInputHandlers, lookups for any value should fail and not crash.
EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(2));
@@ -158,126 +114,452 @@ TEST(WebCompositorInputHandlerImpl, fromIdentifier)
// After the compositor is destroyed, its entry should be removed from the map.
EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(compositorIdentifier));
-
- WebKit::WebCompositor::shutdown();
+ WebCompositor::shutdown();
}
-TEST(WebCompositorInputHandlerImpl, gestureScroll)
+class WebCompositorInputHandlerImplTest : public testing::Test {
+public:
+ WebCompositorInputHandlerImplTest()
+ : m_expectedDisposition(DidHandle)
+ {
+ WebCompositor::initialize(0);
+ m_inputHandler = WebCompositorInputHandlerImpl::create(&m_mockCCInputHandlerClient);
+ m_inputHandler->setClient(&m_mockClient);
+ }
+
+ ~WebCompositorInputHandlerImplTest()
+ {
+ m_inputHandler->setClient(0);
+ m_inputHandler.clear();
+ WebCompositor::shutdown();
+ }
+
+ // This is defined as a macro because when an expectation is not satisfied the only output you get
+ // out of gmock is the line number that set the expectation.
+#define VERIFY_AND_RESET_MOCKS() do \
+ { \
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient); \
+ testing::Mock::VerifyAndClearExpectations(&m_mockClient); \
+ switch (m_expectedDisposition) { \
+ case DidHandle: \
+ /* If we expect to handle events, we shouldn't get any didNotHandleInputEvent() calls with any parameter. */ \
+ EXPECT_CALL(m_mockClient, didNotHandleInputEvent(::testing::_)).Times(0); \
+ EXPECT_CALL(m_mockClient, didHandleInputEvent()); \
+ break; \
+ case DidNotHandle: \
+ /* If we aren't expecting to handle events, we shouldn't call didHandleInputEvent(). */ \
+ EXPECT_CALL(m_mockClient, didHandleInputEvent()).Times(0); \
+ EXPECT_CALL(m_mockClient, didNotHandleInputEvent(false)).Times(0); \
+ EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true)); \
+ break; \
+ case DropEvent: \
+ /* If we're expecting to drop, we shouldn't get any didHandle..() or didNotHandleInputEvent(true) calls. */ \
+ EXPECT_CALL(m_mockClient, didHandleInputEvent()).Times(0); \
+ EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true)).Times(0); \
+ EXPECT_CALL(m_mockClient, didNotHandleInputEvent(false)); \
+ break; \
+ } \
+ } while (0)
+
+protected:
+ MockCCInputHandlerClient m_mockCCInputHandlerClient;
+ OwnPtr<WebCompositorInputHandlerImpl> m_inputHandler;
+ MockWebCompositorInputHandlerClient m_mockClient;
+ WebGestureEvent gesture;
+
+ enum ExpectedDisposition { DidHandle, DidNotHandle, DropEvent };
+ ExpectedDisposition m_expectedDisposition;
+
+private:
+ WebCore::DebugScopedSetImplThread m_alwaysImplThread;
+};
+
+
+TEST_F(WebCompositorInputHandlerImplTest, gestureScrollStarted)
{
- WebKit::WebCompositor::initialize(0);
-#ifndef NDEBUG
- // WebCompositorInputHandler APIs can only be called from the compositor thread.
- WebCore::DebugScopedSetImplThread alwaysImplThread;
-#endif
+ // We shouldn't send any events to the widget for this gesture.
+ m_expectedDisposition = DidHandle;
+ VERIFY_AND_RESET_MOCKS();
- MockInputHandlerClient mockInputHandler;
- OwnPtr<WebCompositorInputHandlerImpl> inputHandler = WebCompositorInputHandlerImpl::create(&mockInputHandler);
- MockWebCompositorInputHandlerClient mockClient;
- inputHandler->setClient(&mockClient);
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
- WebKit::WebGestureEvent gesture;
+ gesture.type = WebInputEvent::GestureScrollBegin;
+ m_inputHandler->handleInputEvent(gesture);
- gesture.type = WebKit::WebInputEvent::GestureScrollBegin;
- inputHandler->handleInputEvent(gesture);
- EXPECT_TRUE(mockClient.handled());
- EXPECT_FALSE(mockClient.sendToWidget());
- mockClient.reset();
+ VERIFY_AND_RESET_MOCKS();
- gesture.type = WebKit::WebInputEvent::GestureScrollUpdate;
- gesture.deltaY = 40;
- inputHandler->handleInputEvent(gesture);
- EXPECT_TRUE(mockClient.handled());
- EXPECT_FALSE(mockClient.sendToWidget());
- mockClient.reset();
+ gesture.type = WebInputEvent::GestureScrollUpdate;
+ gesture.deltaY = -40; // -Y means scroll down - i.e. in the +Y direction.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::Property(&WebCore::IntSize::height, testing::Gt(0))));
+ m_inputHandler->handleInputEvent(gesture);
- gesture.type = WebKit::WebInputEvent::GestureScrollEnd;
+ VERIFY_AND_RESET_MOCKS();
+
+ gesture.type = WebInputEvent::GestureScrollEnd;
gesture.deltaY = 0;
- inputHandler->handleInputEvent(gesture);
- EXPECT_TRUE(mockClient.handled());
- EXPECT_FALSE(mockClient.sendToWidget());
- mockClient.reset();
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
+ m_inputHandler->handleInputEvent(gesture);
+}
- mockInputHandler.setScrollStatus(WebCore::CCInputHandlerClient::ScrollFailed);
+TEST_F(WebCompositorInputHandlerImplTest, gestureScrollFailed)
+{
+ // We should send all events to the widget for this gesture.
+ m_expectedDisposition = DidNotHandle;
+ VERIFY_AND_RESET_MOCKS();
- gesture.type = WebKit::WebInputEvent::GestureScrollBegin;
- inputHandler->handleInputEvent(gesture);
- EXPECT_FALSE(mockClient.handled());
- EXPECT_TRUE(mockClient.sendToWidget());
- mockClient.reset();
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(::testing::_, ::testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollFailed));
- gesture.type = WebKit::WebInputEvent::GestureScrollUpdate;
- gesture.deltaY = 40;
- inputHandler->handleInputEvent(gesture);
- EXPECT_FALSE(mockClient.handled());
- EXPECT_TRUE(mockClient.sendToWidget());
- mockClient.reset();
+ gesture.type = WebInputEvent::GestureScrollBegin;
+ m_inputHandler->handleInputEvent(gesture);
- gesture.type = WebKit::WebInputEvent::GestureScrollEnd;
- gesture.deltaY = 0;
- inputHandler->handleInputEvent(gesture);
- EXPECT_FALSE(mockClient.handled());
- EXPECT_TRUE(mockClient.sendToWidget());
- mockClient.reset();
+ VERIFY_AND_RESET_MOCKS();
+
+ gesture.type = WebInputEvent::GestureScrollUpdate;
+ gesture.deltaY = 40;
+ m_inputHandler->handleInputEvent(gesture);
- inputHandler->setClient(0);
+ VERIFY_AND_RESET_MOCKS();
- WebKit::WebCompositor::shutdown();
+ gesture.type = WebInputEvent::GestureScrollEnd;
+ gesture.deltaY = 0;
+ m_inputHandler->handleInputEvent(gesture);
}
-TEST(WebCompositorInputHandlerImpl, gesturePinch)
+TEST_F(WebCompositorInputHandlerImplTest, gestureScrollIgnored)
{
- WebKit::WebCompositor::initialize(0);
-#ifndef NDEBUG
- // WebCompositorInputHandler APIs can only be called from the compositor thread.
- WebCore::DebugScopedSetImplThread alwaysImplThread;
-#endif
+ // We shouldn't handle the GestureScrollBegin.
+ // Instead, we should get one didNotHandleInputEvent(false) call per handleInputEvent(),
+ // indicating that we could determine that there's nothing that could scroll or otherwise
+ // react to this gesture sequence and thus we should drop the whole gesture sequence on the floor.
+ m_expectedDisposition = DropEvent;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollIgnored));
+
+ gesture.type = WebInputEvent::GestureScrollBegin;
+ m_inputHandler->handleInputEvent(gesture);
+}
- MockInputHandlerClient mockInputHandler;
- OwnPtr<WebCompositorInputHandlerImpl> inputHandler = WebCompositorInputHandlerImpl::create(&mockInputHandler);
- MockWebCompositorInputHandlerClient mockClient;
- inputHandler->setClient(&mockClient);
+TEST_F(WebCompositorInputHandlerImplTest, gesturePinch)
+{
+ // We shouldn't send any events to the widget for this gesture.
+ m_expectedDisposition = DidHandle;
+ VERIFY_AND_RESET_MOCKS();
- WebKit::WebGestureEvent gesture;
+ gesture.type = WebInputEvent::GesturePinchBegin;
+ EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureBegin());
+ m_inputHandler->handleInputEvent(gesture);
- gesture.type = WebKit::WebInputEvent::GesturePinchBegin;
- inputHandler->handleInputEvent(gesture);
- EXPECT_TRUE(mockClient.handled());
- EXPECT_FALSE(mockClient.sendToWidget());
- EXPECT_TRUE(mockInputHandler.pinchStarted());
- mockClient.reset();
- mockInputHandler.resetPinch();
+ VERIFY_AND_RESET_MOCKS();
- gesture.type = WebKit::WebInputEvent::GesturePinchUpdate;
+ gesture.type = WebInputEvent::GesturePinchUpdate;
gesture.deltaX = 1.5;
- inputHandler->handleInputEvent(gesture);
- EXPECT_TRUE(mockClient.handled());
- EXPECT_FALSE(mockClient.sendToWidget());
- EXPECT_FALSE(mockInputHandler.pinchEnded());
- EXPECT_EQ(1.5, mockInputHandler.pinchMaginifcation());
- mockClient.reset();
- mockInputHandler.resetPinch();
-
- gesture.type = WebKit::WebInputEvent::GesturePinchUpdate;
+ gesture.x = 7;
+ gesture.y = 13;
+ EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureUpdate(1.5, WebCore::IntPoint(7, 13)));
+ m_inputHandler->handleInputEvent(gesture);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ gesture.type = WebInputEvent::GesturePinchUpdate;
gesture.deltaX = 0.5;
- inputHandler->handleInputEvent(gesture);
- EXPECT_TRUE(mockClient.handled());
- EXPECT_FALSE(mockClient.sendToWidget());
- EXPECT_FALSE(mockInputHandler.pinchEnded());
- EXPECT_EQ(0.5, mockInputHandler.pinchMaginifcation());
- mockClient.reset();
- mockInputHandler.resetPinch();
-
- gesture.type = WebKit::WebInputEvent::GesturePinchEnd;
- inputHandler->handleInputEvent(gesture);
- EXPECT_TRUE(mockClient.handled());
- EXPECT_FALSE(mockClient.sendToWidget());
- EXPECT_TRUE(mockInputHandler.pinchEnded());
- mockClient.reset();
- mockInputHandler.resetPinch();
-
- inputHandler->setClient(0);
-
- WebKit::WebCompositor::shutdown();
+ gesture.x = 9;
+ gesture.y = 6;
+ EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureUpdate(.5, WebCore::IntPoint(9, 6)));
+ m_inputHandler->handleInputEvent(gesture);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ gesture.type = WebInputEvent::GesturePinchEnd;
+ EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureEnd());
+ m_inputHandler->handleInputEvent(gesture);
+}
+
+TEST_F(WebCompositorInputHandlerImplTest, gestureFlingStarted)
+{
+ // We shouldn't send any events to the widget for this gesture.
+ m_expectedDisposition = DidHandle;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
+
+ gesture.type = WebInputEvent::GestureFlingStart;
+ gesture.deltaX = 10;
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ m_inputHandler->handleInputEvent(gesture);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Verify that a GestureFlingCancel during an animation cancels it.
+ gesture.type = WebInputEvent::GestureFlingCancel;
+ m_inputHandler->handleInputEvent(gesture);
+}
+
+TEST_F(WebCompositorInputHandlerImplTest, gestureFlingFailed)
+{
+ // We should send all events to the widget for this gesture.
+ m_expectedDisposition = DidNotHandle;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollFailed));
+
+ gesture.type = WebInputEvent::GestureFlingStart;
+ m_inputHandler->handleInputEvent(gesture);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Even if we didn't start a fling ourselves, we still need to send the cancel event to the widget.
+ gesture.type = WebInputEvent::GestureFlingCancel;
+ m_inputHandler->handleInputEvent(gesture);
+}
+
+TEST_F(WebCompositorInputHandlerImplTest, gestureFlingIgnored)
+{
+ m_expectedDisposition = DidNotHandle;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollIgnored));
+
+ gesture.type = WebInputEvent::GestureFlingStart;
+ m_inputHandler->handleInputEvent(gesture);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Even if we didn't start a fling ourselves, we still need to send the cancel event to the widget.
+ gesture.type = WebInputEvent::GestureFlingCancel;
+ m_inputHandler->handleInputEvent(gesture);
+}
+
+TEST_F(WebCompositorInputHandlerImplTest, gestureFlingAnimates)
+{
+ // We shouldn't send any events to the widget for this gesture.
+ m_expectedDisposition = DidHandle;
+ VERIFY_AND_RESET_MOCKS();
+
+ // On the fling start, we should schedule an animation but not actually start
+ // scrolling.
+ gesture.type = WebInputEvent::GestureFlingStart;
+ WebFloatPoint flingDelta = WebFloatPoint(1000, 0);
+ WebPoint flingPoint = WebPoint(7, 13);
+ WebPoint flingGlobalPoint = WebPoint(17, 23);
+ int modifiers = 7;
+ gesture.deltaX = flingDelta.x;
+ gesture.deltaY = flingDelta.y;
+ gesture.x = flingPoint.x;
+ gesture.y = flingPoint.y;
+ gesture.globalX = flingGlobalPoint.x;
+ gesture.globalY = flingGlobalPoint.y;
+ gesture.modifiers = modifiers;
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
+ m_inputHandler->handleInputEvent(gesture);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+ // The first animate call should let us pick up an animation start time, but we
+ // shouldn't actually move anywhere just yet. The first frame after the fling start
+ // will typically include the last scroll from the gesture that lead to the scroll
+ // (either wheel or gesture scroll), so there should be no visible hitch.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
+ m_inputHandler->animate(10);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // The second call should start scrolling in the -X direction.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::Property(&WebCore::IntSize::width, testing::Lt(0))));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
+ m_inputHandler->animate(10.1);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // Let's say on the third call we hit a non-scrollable region. We should abort the fling and not scroll.
+ // We also should pass the current fling parameters out to the client so the rest of the fling can be
+ // transferred to the main thread.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollFailed));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_)).Times(0);
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
+
+ // Expected wheel fling animation parameters:
+ // *) flingDelta and flingPoint should match the original GestureFlingStart event
+ // *) startTime should be 10 to match the time parameter of the first animate() call after the GestureFlingStart
+ // *) cumulativeScroll depends on the curve, but since we've animated in the -X direction the X value should be < 0
+ EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
+ testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
+ testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
+ testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
+ testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
+ testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(10)),
+ testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
+ testing::Field(&WebSize::width, testing::Gt(0))))));
+ m_inputHandler->animate(10.2);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+ testing::Mock::VerifyAndClearExpectations(&m_mockClient);
+
+ // Since we've aborted the fling, the next animation should be a no-op and should not result in another
+ // frame being requested.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation()).Times(0);
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
+ m_inputHandler->animate(10.3);
+
+ // Since we've transferred the fling to the main thread, we need to pass the next GestureFlingCancel to the main
+ // thread as well.
+ EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true));
+ gesture.type = WebInputEvent::GestureFlingCancel;
+ m_inputHandler->handleInputEvent(gesture);
+}
+
+TEST_F(WebCompositorInputHandlerImplTest, gestureFlingTransferResets)
+{
+ // We shouldn't send any events to the widget for this gesture.
+ m_expectedDisposition = DidHandle;
+ VERIFY_AND_RESET_MOCKS();
+
+ // Start a gesture fling in the -X direction with zero Y movement.
+ gesture.type = WebInputEvent::GestureFlingStart;
+ WebFloatPoint flingDelta = WebFloatPoint(1000, 0);
+ WebPoint flingPoint = WebPoint(7, 13);
+ WebPoint flingGlobalPoint = WebPoint(17, 23);
+ int modifiers = 1;
+ gesture.deltaX = flingDelta.x;
+ gesture.deltaY = flingDelta.y;
+ gesture.x = flingPoint.x;
+ gesture.y = flingPoint.y;
+ gesture.globalX = flingGlobalPoint.x;
+ gesture.globalY = flingGlobalPoint.y;
+ gesture.modifiers = modifiers;
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
+ m_inputHandler->handleInputEvent(gesture);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // Start the fling animation at time 10. This shouldn't actually scroll, just establish a start time.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
+ m_inputHandler->animate(10);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // The second call should start scrolling in the -X direction.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::Property(&WebCore::IntSize::width, testing::Lt(0))));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
+ m_inputHandler->animate(10.1);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // Let's say on the third call we hit a non-scrollable region. We should abort the fling and not scroll.
+ // We also should pass the current fling parameters out to the client so the rest of the fling can be
+ // transferred to the main thread.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollFailed));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_)).Times(0);
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
+
+ // Expected wheel fling animation parameters:
+ // *) flingDelta and flingPoint should match the original GestureFlingStart event
+ // *) startTime should be 10 to match the time parameter of the first animate() call after the GestureFlingStart
+ // *) cumulativeScroll depends on the curve, but since we've animated in the -X direction the X value should be < 0
+ EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
+ testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
+ testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
+ testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
+ testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
+ testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(10)),
+ testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
+ testing::Field(&WebSize::width, testing::Gt(0))))));
+ m_inputHandler->animate(10.2);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+ testing::Mock::VerifyAndClearExpectations(&m_mockClient);
+
+ // Since we've aborted the fling, the next animation should be a no-op and should not result in another
+ // frame being requested.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation()).Times(0);
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
+ m_inputHandler->animate(10.3);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // Since we've transferred the fling to the main thread, we need to pass the next GestureFlingCancel to the main
+ // thread as well.
+ EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true));
+ gesture.type = WebInputEvent::GestureFlingCancel;
+ m_inputHandler->handleInputEvent(gesture);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Start a second gesture fling, this time in the +Y direction with no X.
+ gesture.type = WebInputEvent::GestureFlingStart;
+ flingDelta = WebFloatPoint(0, -1000);
+ flingPoint = WebPoint(95, 87);
+ flingGlobalPoint = WebPoint(32, 71);
+ modifiers = 2;
+ gesture.deltaX = flingDelta.x;
+ gesture.deltaY = flingDelta.y;
+ gesture.x = flingPoint.x;
+ gesture.y = flingPoint.y;
+ gesture.globalX = flingGlobalPoint.x;
+ gesture.globalY = flingGlobalPoint.y;
+ gesture.modifiers = modifiers;
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
+ m_inputHandler->handleInputEvent(gesture);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // Start the second fling animation at time 30.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
+ m_inputHandler->animate(30);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // Tick the second fling once normally.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::Property(&WebCore::IntSize::height, testing::Gt(0))));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
+ m_inputHandler->animate(30.1);
+
+ testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
+
+ // Then abort the second fling.
+ EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollFailed));
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_)).Times(0);
+ EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
+
+ // We should get parameters from the second fling, nothing from the first fling should "leak".
+ EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
+ testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
+ testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
+ testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
+ testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
+ testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(30)),
+ testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
+ testing::Field(&WebSize::height, testing::Lt(0))))));
+ m_inputHandler->animate(30.2);
}
}
diff --git a/Source/WebKit/chromium/tests/WebExternalTextureLayerImplTest.cpp b/Source/WebKit/chromium/tests/WebExternalTextureLayerImplTest.cpp
deleted file mode 100644
index 583d0df70..000000000
--- a/Source/WebKit/chromium/tests/WebExternalTextureLayerImplTest.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "WebExternalTextureLayerImpl.h"
-
-#include <gtest/gtest.h>
-#include <wtf/RefPtr.h>
-
-namespace {
-
-using namespace WebKit;
-using WTF::RefPtr;
-
-class WebExternalTextureLayerImplTest : public WebExternalTextureLayerImpl {
-public:
- bool isDrawable() const { return drawsContent(); }
-};
-
-TEST(WebExternalTextureLayerImpl, testIsDrawable)
-{
- RefPtr<WebExternalTextureLayerImplTest> textureLayer = adoptRef(new WebExternalTextureLayerImplTest());
-
- textureLayer->setTextureId(1);
- EXPECT_TRUE(textureLayer->isDrawable());
-}
-
-}
diff --git a/Source/WebKit/chromium/tests/WebFrameTest.cpp b/Source/WebKit/chromium/tests/WebFrameTest.cpp
index 481bd916f..b8bc2e3c4 100644
--- a/Source/WebKit/chromium/tests/WebFrameTest.cpp
+++ b/Source/WebKit/chromium/tests/WebFrameTest.cpp
@@ -42,6 +42,7 @@
#include "WebSearchableFormData.h"
#include "WebSecurityPolicy.h"
#include "WebSettings.h"
+#include "WebViewClient.h"
#include "WebViewImpl.h"
#include "v8.h"
#include <gtest/gtest.h>
@@ -151,8 +152,42 @@ TEST_F(WebFrameTest, ChromePageNoJavascript)
EXPECT_EQ(std::string::npos, content.find("Clobbered"));
}
+#if ENABLE(VIEWPORT)
+
+class FixedLayoutTestWebViewClient : public WebViewClient {
+ public:
+ virtual WebRect windowRect() OVERRIDE { return m_windowRect; }
+ virtual WebScreenInfo screenInfo() OVERRIDE { return m_screenInfo; }
+
+ WebRect m_windowRect;
+ WebScreenInfo m_screenInfo;
+};
+
+TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag)
+{
+ registerMockedHttpURLLoad("no_viewport_tag.html");
+
+ int viewportWidth = 640;
+ int viewportHeight = 480;
+
+ FixedLayoutTestWebViewClient client;
+ client.m_screenInfo.horizontalDPI = 160;
+ client.m_windowRect = WebRect(0, 0, viewportWidth, viewportHeight);
+
+ WebView* webView = static_cast<WebView*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "no_viewport_tag.html", true, 0, &client));
+
+ webView->resize(WebSize(viewportWidth, viewportHeight));
+ webView->settings()->setViewportEnabled(true);
+ webView->settings()->setDefaultDeviceScaleFactor(2);
+ webView->enableFixedLayoutMode(true);
+ webView->layout();
+
+ EXPECT_EQ(2, webView->deviceScaleFactor());
+}
+#endif
+
#if ENABLE(GESTURE_EVENTS)
-TEST_F(WebFrameTest, DivAutoZoomParamsTest)
+TEST_F(WebFrameTest, FAILS_DivAutoZoomParamsTest)
{
registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html");
@@ -238,7 +273,12 @@ public:
{
// Return a dummy error so the DocumentLoader doesn't assert when
// the reload cancels it.
- return WebURLError(WebCore::ResourceError("", 1, "", "cancelled"));
+ WebURLError webURLError;
+ webURLError.domain = "";
+ webURLError.reason = 1;
+ webURLError.isCancellation = true;
+ webURLError.unreachableURL = WebURL();
+ return webURLError;
}
};
diff --git a/Source/WebKit/chromium/tests/WebLayerTest.cpp b/Source/WebKit/chromium/tests/WebLayerTest.cpp
index 1eed81aea..7c0831f90 100644
--- a/Source/WebKit/chromium/tests/WebLayerTest.cpp
+++ b/Source/WebKit/chromium/tests/WebLayerTest.cpp
@@ -136,7 +136,7 @@ TEST_F(WebLayerTest, Client)
EXPECT_EQ(otherLayer, layer.maskLayer());
EXPECT_CALL(m_client, scheduleComposite()).Times(AtLeast(1));
- float opacity = 0.123;
+ float opacity = 0.123f;
layer.setOpacity(opacity);
Mock::VerifyAndClearExpectations(&m_client);
EXPECT_EQ(opacity, layer.opacity());
@@ -160,18 +160,15 @@ TEST_F(WebLayerTest, Client)
EXPECT_CALL(m_client, scheduleComposite()).Times(AtLeast(1));
textureLayer.setTextureId(3);
Mock::VerifyAndClearExpectations(&m_client);
- EXPECT_EQ(3u, textureLayer.textureId());
EXPECT_CALL(m_client, scheduleComposite()).Times(AtLeast(1));
textureLayer.setFlipped(true);
Mock::VerifyAndClearExpectations(&m_client);
- EXPECT_TRUE(textureLayer.flipped());
EXPECT_CALL(m_client, scheduleComposite()).Times(AtLeast(1));
- WebFloatRect uvRect(0.1, 0.1, 0.9, 0.9);
+ WebFloatRect uvRect(0.1f, 0.1f, 0.9f, 0.9f);
textureLayer.setUVRect(uvRect);
Mock::VerifyAndClearExpectations(&m_client);
- EXPECT_TRUE(textureLayer.flipped());
// Content layer.
diff --git a/Source/WebKit/chromium/tests/WebMediaPlayerClientImplTest.cpp b/Source/WebKit/chromium/tests/WebMediaPlayerClientImplTest.cpp
new file mode 100644
index 000000000..56a1a6e22
--- /dev/null
+++ b/Source/WebKit/chromium/tests/WebMediaPlayerClientImplTest.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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 "WebMediaPlayerClientImpl.h"
+
+#include <gtest/gtest.h>
+#include <wtf/PassOwnPtr.h>
+
+using namespace WebKit;
+
+namespace {
+
+class FakeWebMediaPlayerClientImpl : public WebMediaPlayerClientImpl {
+public:
+ static PassOwnPtr<FakeWebMediaPlayerClientImpl> create() { return adoptPtr(new FakeWebMediaPlayerClientImpl()); }
+
+private:
+ FakeWebMediaPlayerClientImpl() { }
+};
+
+class FakeVideoFrameProviderClient : public WebVideoFrameProvider::Client {
+public:
+ static PassOwnPtr<FakeVideoFrameProviderClient> create(WebVideoFrameProvider* provider)
+ {
+ return adoptPtr(new FakeVideoFrameProviderClient(provider));
+ }
+
+ virtual ~FakeVideoFrameProviderClient()
+ {
+ if (m_provider)
+ m_provider->setVideoFrameProviderClient(0);
+ }
+
+ // WebKit::WebVideoFrameProvider::Client implementation.
+ virtual void didReceiveFrame() { }
+ virtual void didUpdateMatrix(const float*) { }
+ virtual void stopUsingProvider()
+ {
+ m_provider = 0;
+ }
+
+ WebVideoFrameProvider* provider() const { return m_provider; }
+
+private:
+ FakeVideoFrameProviderClient(WebVideoFrameProvider* provider)
+ : m_provider(provider)
+ {
+ m_provider->setVideoFrameProviderClient(this);
+ }
+
+ WebVideoFrameProvider* m_provider;
+};
+
+TEST(WebMediaPlayerClientImplTest, InitialNullVideoClient)
+{
+ // No explict checks in this test; just make sure it doesn't crash.
+ OwnPtr<WebMediaPlayerClientImpl> provider(FakeWebMediaPlayerClientImpl::create());
+ provider->setVideoFrameProviderClient(0);
+}
+
+TEST(WebMediaPlayerClientImplTest, SetAndUnsetVideoClient)
+{
+ OwnPtr<WebMediaPlayerClientImpl> provider(FakeWebMediaPlayerClientImpl::create());
+ OwnPtr<FakeVideoFrameProviderClient> client(FakeVideoFrameProviderClient::create(provider.get()));
+
+ EXPECT_EQ(client->provider(), provider.get());
+
+ provider->setVideoFrameProviderClient(0);
+ ASSERT_FALSE(client->provider());
+}
+
+TEST(WebMediaPlayerClientImplTest, DestroyProvider)
+{
+ OwnPtr<WebMediaPlayerClientImpl> provider(FakeWebMediaPlayerClientImpl::create());
+ OwnPtr<FakeVideoFrameProviderClient> client(FakeVideoFrameProviderClient::create(provider.get()));
+
+ EXPECT_EQ(client->provider(), provider);
+ provider.clear();
+ ASSERT_FALSE(client->provider());
+}
+
+TEST(WebMediaPlayerClientImplTest, SetMultipleVideoClients)
+{
+ OwnPtr<WebMediaPlayerClientImpl> provider(FakeWebMediaPlayerClientImpl::create());
+ OwnPtr<FakeVideoFrameProviderClient> firstClient(FakeVideoFrameProviderClient::create(provider.get()));
+ EXPECT_EQ(firstClient->provider(), provider);
+
+ OwnPtr<FakeVideoFrameProviderClient> secondClient(FakeVideoFrameProviderClient::create(provider.get()));
+ EXPECT_FALSE(firstClient->provider());
+ EXPECT_EQ(secondClient->provider(), provider);
+
+ provider.clear();
+ ASSERT_FALSE(firstClient->provider());
+ ASSERT_FALSE(secondClient->provider());
+}
+
+}
diff --git a/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp b/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp
index 423a5969f..1d7826a69 100644
--- a/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp
+++ b/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp
@@ -46,8 +46,8 @@ TEST(WebSocketDeflaterTest, TestCompressHello)
ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
ASSERT_TRUE(deflater->finish());
- const char expectedFirst[] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00};
- EXPECT_EQ(sizeof(expectedFirst), deflater->size());
+ const char* expectedFirst = "\xf2\x48\xcd\xc9\xc9\x07\x00";
+ EXPECT_EQ(7U, deflater->size());
EXPECT_EQ(0, memcmp(expectedFirst, deflater->data(), deflater->size()));
ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
ASSERT_TRUE(inflater->finish());
@@ -59,8 +59,8 @@ TEST(WebSocketDeflaterTest, TestCompressHello)
ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
ASSERT_TRUE(deflater->finish());
- const char expectedSecond[] = {0xf2, 0x00, 0x11, 0x00, 0x00};
- EXPECT_EQ(sizeof(expectedSecond), deflater->size());
+ const char* expectedSecond = "\xf2\x00\x11\x00\x00";
+ EXPECT_EQ(5U, deflater->size());
EXPECT_EQ(0, memcmp(expectedSecond, deflater->data(), deflater->size()));
ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
ASSERT_TRUE(inflater->finish());
@@ -93,7 +93,7 @@ TEST(WebSocketDeflaterTest, TestNoContextTakeOver)
ASSERT_TRUE(deflater->initialize());
OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create();
ASSERT_TRUE(inflater->initialize());
- const char expected[] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00};
+ const char* expected = "\xf2\x48\xcd\xc9\xc9\x07\x00";
const char* inputData = "Hello";
const size_t inputLength = strlen(inputData);
@@ -102,7 +102,7 @@ TEST(WebSocketDeflaterTest, TestNoContextTakeOver)
for (size_t i = 0; i < 2; ++i) {
ASSERT_TRUE(deflater->addBytes(inputData, inputLength));
ASSERT_TRUE(deflater->finish());
- EXPECT_EQ(sizeof(expected), deflater->size());
+ EXPECT_EQ(7U, deflater->size());
EXPECT_EQ(0, memcmp(expected, deflater->data(), deflater->size()));
ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size()));
ASSERT_TRUE(inflater->finish());
diff --git a/Source/WebKit/chromium/tests/WebViewTest.cpp b/Source/WebKit/chromium/tests/WebViewTest.cpp
index 6580d06eb..00d8a832d 100644
--- a/Source/WebKit/chromium/tests/WebViewTest.cpp
+++ b/Source/WebKit/chromium/tests/WebViewTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2011, 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
@@ -42,6 +42,7 @@
#include "platform/WebSize.h"
#include "WebViewClient.h"
#include "WebViewImpl.h"
+#include <googleurl/src/gurl.h>
#include <gtest/gtest.h>
#include <webkit/support/webkit_support.h>
@@ -49,12 +50,28 @@ using namespace WebKit;
namespace {
+enum HorizontalScrollbarState {
+ NoHorizontalScrollbar,
+ VisibleHorizontalScrollbar,
+};
+
+enum VerticalScrollbarState {
+ NoVerticalScrollbar,
+ VisibleVerticalScrollbar,
+};
+
class TestData {
public:
void setWebView(WebView* webView) { m_webView = static_cast<WebViewImpl*>(webView); }
void setSize(const WebSize& newSize) { m_size = newSize; }
- bool hasHorizontalScrollbar() const { return m_webView->hasHorizontalScrollbar(); }
- bool hasVerticalScrollbar() const { return m_webView->hasVerticalScrollbar(); }
+ HorizontalScrollbarState horizontalScrollbarState() const
+ {
+ return m_webView->hasHorizontalScrollbar() ? VisibleHorizontalScrollbar: NoHorizontalScrollbar;
+ }
+ VerticalScrollbarState verticalScrollbarState() const
+ {
+ return m_webView->hasVerticalScrollbar() ? VisibleVerticalScrollbar : NoVerticalScrollbar;
+ }
int width() const { return m_size.width; }
int height() const { return m_size.height; }
@@ -88,6 +105,11 @@ public:
}
protected:
+ void testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
+ const std::string& pageWidth, const std::string& pageHeight,
+ int expectedWidth, int expectedHeight,
+ HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState);
+
std::string m_baseURL;
};
@@ -119,35 +141,108 @@ TEST_F(WebViewTest, FocusIsInactive)
webView->close();
}
-TEST_F(WebViewTest, AutoResizeMinimumSize)
+void WebViewTest::testAutoResize(const WebSize& minAutoResize, const WebSize& maxAutoResize,
+ const std::string& pageWidth, const std::string& pageHeight,
+ int expectedWidth, int expectedHeight,
+ HorizontalScrollbarState expectedHorizontalState, VerticalScrollbarState expectedVerticalState)
{
AutoResizeWebViewClient client;
- FrameTestHelpers::registerMockedURLLoad(m_baseURL, "specify_size.html");
- WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "specify_size.html", true, 0, &client);
+ std::string url = m_baseURL + "specify_size.html?" + pageWidth + ":" + pageHeight;
+ FrameTestHelpers::registerMockedURLLoad(GURL(url), "specify_size.html");
+ WebView* webView = FrameTestHelpers::createWebViewAndLoad(url, true, 0, &client);
client.testData().setWebView(webView);
- FrameTestHelpers::loadFrame(webView->mainFrame(), "javascript:document.getElementById('sizer').style.height = '56px';");
- FrameTestHelpers::loadFrame(webView->mainFrame(), "javascript:document.getElementById('sizer').style.width = '91px';");
WebFrameImpl* frame = static_cast<WebFrameImpl*>(webView->mainFrame());
WebCore::FrameView* frameView = frame->frame()->view();
+ frameView->layout();
EXPECT_FALSE(frameView->layoutPending());
EXPECT_FALSE(frameView->needsLayout());
- WebSize minSize(91, 56);
- WebSize maxSize(403, 302);
- webView->enableAutoResizeMode(true, minSize, maxSize);
+ webView->enableAutoResizeMode(minAutoResize, maxAutoResize);
EXPECT_TRUE(frameView->layoutPending());
EXPECT_TRUE(frameView->needsLayout());
frameView->layout();
EXPECT_TRUE(frame->frame()->document()->isHTMLDocument());
- EXPECT_EQ(91, client.testData().width());
- EXPECT_EQ(56, client.testData().height());
- EXPECT_FALSE(client.testData().hasHorizontalScrollbar());
- EXPECT_FALSE(client.testData().hasVerticalScrollbar());
+ EXPECT_EQ(expectedWidth, client.testData().width());
+ EXPECT_EQ(expectedHeight, client.testData().height());
+ EXPECT_EQ(expectedHorizontalState, client.testData().horizontalScrollbarState());
+ EXPECT_EQ(expectedVerticalState, client.testData().verticalScrollbarState());
webView->close();
}
+TEST_F(WebViewTest, AutoResizeMinimumSize)
+{
+ WebSize minAutoResize(91, 56);
+ WebSize maxAutoResize(403, 302);
+ std::string pageWidth = "91px";
+ std::string pageHeight = "56px";
+ int expectedWidth = 91;
+ int expectedHeight = 56;
+ testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
+ expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
+}
+
+TEST_F(WebViewTest, AutoResizeHeightOverflowAndFixedWidth)
+{
+ WebSize minAutoResize(90, 95);
+ WebSize maxAutoResize(90, 100);
+ std::string pageWidth = "60px";
+ std::string pageHeight = "200px";
+ int expectedWidth = 90;
+ int expectedHeight = 100;
+ testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
+ expectedWidth, expectedHeight, NoHorizontalScrollbar, VisibleVerticalScrollbar);
+}
+
+TEST_F(WebViewTest, AutoResizeFixedHeightAndWidthOverflow)
+{
+ WebSize minAutoResize(90, 100);
+ WebSize maxAutoResize(200, 100);
+ std::string pageWidth = "300px";
+ std::string pageHeight = "80px";
+ int expectedWidth = 200;
+ int expectedHeight = 100;
+ testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
+ expectedWidth, expectedHeight, VisibleHorizontalScrollbar, NoVerticalScrollbar);
+}
+
+TEST_F(WebViewTest, AutoResizeInBetweenSizes)
+{
+ WebSize minAutoResize(90, 95);
+ WebSize maxAutoResize(200, 300);
+ std::string pageWidth = "100px";
+ std::string pageHeight = "200px";
+ int expectedWidth = 100;
+ int expectedHeight = 200;
+ testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
+ expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
+}
+
+TEST_F(WebViewTest, AutoResizeOverflowSizes)
+{
+ WebSize minAutoResize(90, 95);
+ WebSize maxAutoResize(200, 300);
+ std::string pageWidth = "300px";
+ std::string pageHeight = "400px";
+ int expectedWidth = 200;
+ int expectedHeight = 300;
+ testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
+ expectedWidth, expectedHeight, VisibleHorizontalScrollbar, VisibleVerticalScrollbar);
+}
+
+TEST_F(WebViewTest, AutoResizeMaxSize)
+{
+ WebSize minAutoResize(90, 95);
+ WebSize maxAutoResize(200, 300);
+ std::string pageWidth = "200px";
+ std::string pageHeight = "300px";
+ int expectedWidth = 200;
+ int expectedHeight = 300;
+ testAutoResize(minAutoResize, maxAutoResize, pageWidth, pageHeight,
+ expectedWidth, expectedHeight, NoHorizontalScrollbar, NoVerticalScrollbar);
+}
+
}
diff --git a/Source/WebKit/chromium/tests/data/no_viewport_tag.html b/Source/WebKit/chromium/tests/data/no_viewport_tag.html
new file mode 100644
index 000000000..9ba981574
--- /dev/null
+++ b/Source/WebKit/chromium/tests/data/no_viewport_tag.html
@@ -0,0 +1,5 @@
+<html>
+ <body>
+ <p> Test </p>
+ </body>
+</html>
diff --git a/Source/WebKit/chromium/tests/data/specify_size.html b/Source/WebKit/chromium/tests/data/specify_size.html
index 7b9695fd2..2041e85db 100644
--- a/Source/WebKit/chromium/tests/data/specify_size.html
+++ b/Source/WebKit/chromium/tests/data/specify_size.html
@@ -1,6 +1,20 @@
<!doctype html>
<html>
<body style='margin:0px'>
-<img id='sizer' src='broken.jpg'/>
+<img id='sizer'/>
+<script>
+// The desired size should be specified in the url in the search portion
+// like this ?widthDimension:heightDimension.
+var unitMatch = '([0-9]+[a-zA-Z]+)';
+var searchParser = new RegExp('\\?' + unitMatch + '(?:\\:' + unitMatch + ')');
+var parsedParameters = searchParser.exec(window.location.search);
+
+// Set the sizes.
+var elementToSize = document.getElementById('sizer');
+var width = parsedParameters[1];
+elementToSize.style.width = width;
+var height = parsedParameters[2];
+elementToSize.style.height = height;
+</script>
</body>
</html>