summaryrefslogtreecommitdiff
path: root/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
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/CCLayerTreeHostImplTest.cpp
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/CCLayerTreeHostImplTest.cpp')
-rw-r--r--Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp641
1 files changed, 544 insertions, 97 deletions
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