+2012-03-21 Dana Jansens <danakj@chromium.org>
+
+ [chromium] Early out in a new prepareToDraw() step if checkerboarding an accelerated animation in order to skip the frame
+ https://bugs.webkit.org/show_bug.cgi?id=81437
+
+ Reviewed by Adrienne Walker.
+
+ Split CCLayerTreeHostImpl::drawLayers() into two phases:
+ prepareToDraw() and drawLayers().
+
+ When calculating a RenderPass, and we checkerboard a quad on a
+ layer, bubble this info back up to CCLayerTreeHostImpl. If the
+ layer is transforming in an animation, then abort the prepareToDraw()
+ phase and cause it to return false back to the thread proxy.
+
+ Unit test: CCLayerTreeHostImplTest.prepareToDrawFailsWhenAnimationUsesCheckerboard
+
+ * platform/graphics/chromium/cc/CCLayerImpl.cpp:
+ (WebCore::CCLayerImpl::appendQuads):
+ * platform/graphics/chromium/cc/CCLayerImpl.h:
+ (CCLayerImpl):
+ * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
+ (WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
+ (WebCore::CCLayerTreeHostImpl::prepareToDraw):
+ (WebCore):
+ (WebCore::CCLayerTreeHostImpl::drawLayers):
+ * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
+ (CCLayerTreeHostImpl):
+ (FrameData):
+ * platform/graphics/chromium/cc/CCQuadCuller.cpp:
+ (WebCore::CCQuadCuller::append):
+ * platform/graphics/chromium/cc/CCQuadCuller.h:
+ (CCQuadCuller):
+ * platform/graphics/chromium/cc/CCRenderPass.cpp:
+ (WebCore::CCRenderPass::appendQuadsForLayer):
+ * platform/graphics/chromium/cc/CCRenderPass.h:
+ (CCRenderPass):
+ * platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp:
+ (WebCore::CCScrollbarLayerImpl::appendQuads):
+ * platform/graphics/chromium/cc/CCScrollbarLayerImpl.h:
+ (CCScrollbarLayerImpl):
+ * platform/graphics/chromium/cc/CCSingleThreadProxy.cpp:
+ (WebCore::CCSingleThreadProxy::doComposite):
+ * platform/graphics/chromium/cc/CCSolidColorLayerImpl.cpp:
+ (WebCore::CCSolidColorLayerImpl::appendQuads):
+ * platform/graphics/chromium/cc/CCSolidColorLayerImpl.h:
+ (CCSolidColorLayerImpl):
+ * platform/graphics/chromium/cc/CCTextureLayerImpl.cpp:
+ (WebCore::CCTextureLayerImpl::appendQuads):
+ * platform/graphics/chromium/cc/CCTextureLayerImpl.h:
+ (CCTextureLayerImpl):
+ * platform/graphics/chromium/cc/CCThreadProxy.cpp:
+ (WebCore::CCThreadProxy::scheduledActionDrawAndSwap):
+ * platform/graphics/chromium/cc/CCTiledLayerImpl.cpp:
+ (WebCore::CCTiledLayerImpl::appendQuads):
+ * platform/graphics/chromium/cc/CCTiledLayerImpl.h:
+ (CCTiledLayerImpl):
+ * platform/graphics/chromium/cc/CCVideoLayerImpl.cpp:
+ (WebCore::CCVideoLayerImpl::appendQuads):
+ * platform/graphics/chromium/cc/CCVideoLayerImpl.h:
+ (CCVideoLayerImpl):
+
2012-03-21 Enrica Casucci <enrica@apple.com>
WebKitURLWithTitles pasteboard format should support URLs containing Emoji characters.
return CCSharedQuadState::create(quadTransform(), drawTransform(), visibleLayerRect(), layerClipRect, drawOpacity(), opaque());
}
-void CCLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState)
+void CCLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
appendGutterQuads(quadList, sharedQuadState);
}
PassOwnPtr<CCSharedQuadState> createSharedQuadState() const;
virtual void willDraw(LayerRendererChromium*) { }
- virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& usedCheckerboard);
virtual void didDraw() { }
void appendDebugBorderQuad(CCQuadCuller&, const CCSharedQuadState*) const;
return surfaceDamageRect;
}
-void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList)
+bool CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList)
{
- TRACE_EVENT1("webkit", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(renderSurfaceLayerList.size()));
+ ASSERT(passes.isEmpty());
+ ASSERT(renderSurfaceLayerList.isEmpty());
renderSurfaceLayerList.append(rootLayer());
CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer(), rootLayer(), identityMatrix, identityMatrix, renderSurfaceLayerList, rootLayer()->renderSurface()->layerList(), &m_layerSorter, layerRendererCapabilities().maxTextureSize);
}
+ TRACE_EVENT1("webkit", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(renderSurfaceLayerList.size()));
+
if (layerRendererCapabilities().usingPartialSwap)
trackDamageForAllSurfaces(rootLayer(), renderSurfaceLayerList);
m_rootDamageRect = rootLayer()->renderSurface()->damageTracker()->currentDamageRect();
// Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
+ // If we are unable to draw an animation on some layer, then we abort the entire frame.
+ bool drawFrame = true;
+
CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
CCRenderSurface* renderSurface = it.targetRenderSurfaceLayer()->renderSurface();
}
it->willDraw(m_layerRenderer.get());
- pass->appendQuadsForLayer(*it, &occlusionTracker);
+
+ bool usedCheckerboard = false;
+ pass->appendQuadsForLayer(*it, &occlusionTracker, usedCheckerboard);
+ if (usedCheckerboard) {
+ bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
+ if (layerHasAnimatingTransform) {
+ drawFrame = false;
+ break;
+ }
+ }
+
occlusionTracker.markOccludedBehindLayer(*it);
}
- occlusionTracker.overdrawMetrics().recordMetrics(this);
+ if (drawFrame)
+ occlusionTracker.overdrawMetrics().recordMetrics(this);
+ return drawFrame;
}
void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
return m_scrollLayerImpl->children()[0]->contentBounds();
}
-void CCLayerTreeHostImpl::drawLayers()
+bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
{
- TRACE_EVENT("CCLayerTreeHostImpl::drawLayers", this, 0);
- ASSERT(m_layerRenderer);
+ TRACE_EVENT("CCLayerTreeHostImpl::prepareToDraw", this, 0);
+
+ frame.renderPasses.clear();
+ frame.renderSurfaceLayerList.clear();
if (!rootLayer())
- return;
+ return false;
- CCRenderPassList passes;
- CCLayerList renderSurfaceLayerList;
- calculateRenderPasses(passes, renderSurfaceLayerList);
+ if (!calculateRenderPasses(frame.renderPasses, frame.renderSurfaceLayerList)) {
+ frame.renderPasses.clear();
+ frame.renderSurfaceLayerList.clear();
+ return false;
+ }
+
+ // If we return true, then we expect drawLayers() to be called before this function is called again.
+ return true;
+}
+
+void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
+{
+ TRACE_EVENT("CCLayerTreeHostImpl::drawLayers", this, 0);
+ ASSERT(m_layerRenderer);
m_layerRenderer->beginDrawingFrame();
- for (size_t i = 0; i < passes.size(); ++i)
- m_layerRenderer->drawRenderPass(passes[i].get());
+ for (size_t i = 0; i < frame.renderPasses.size(); ++i)
+ m_layerRenderer->drawRenderPass(frame.renderPasses[i].get());
typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
- CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
- for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
+ CCLayerIteratorType end = CCLayerIteratorType::end(&frame.renderSurfaceLayerList);
+ for (CCLayerIteratorType it = CCLayerIteratorType::begin(&frame.renderSurfaceLayerList); it != end; ++it) {
if (it.representsItself() && !it->visibleLayerRect().isEmpty())
it->didDraw();
}
// CCLayerTreeHostImpl owns the CCLayerImpl tree as well as associated rendering state
class CCLayerTreeHostImpl : public CCInputHandlerClient, LayerRendererChromiumClient {
WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImpl);
+ typedef Vector<CCLayerImpl*> CCLayerList;
+
public:
static PassOwnPtr<CCLayerTreeHostImpl> create(const CCSettings&, CCLayerTreeHostImplClient*);
virtual ~CCLayerTreeHostImpl();
virtual void setActiveGestureAnimation(PassOwnPtr<CCActiveGestureAnimation>);
virtual void scheduleAnimation();
+ struct FrameData {
+ CCRenderPassList renderPasses;
+ CCLayerList renderSurfaceLayerList;
+ };
+
// Virtual for testing.
virtual void beginCommit();
virtual void commitComplete();
virtual void animate(double monotonicTime, double wallClockTime);
- virtual void drawLayers();
+ virtual bool prepareToDraw(FrameData&);
+ virtual void drawLayers(const FrameData&);
// LayerRendererChromiumClient implementation
virtual const IntSize& viewportSize() const { return m_viewportSize; }
int m_frameNumber;
private:
- typedef Vector<CCLayerImpl*> CCLayerList;
-
void computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo);
void computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo);
void makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale);
void adjustScrollsForPageScaleChange(float);
void updateMaxScrollPosition();
void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
- void calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList);
+ // Returns false if the frame should not be displayed.
+ bool calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList);
void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector*, bool& didAnimate, bool& needsAnimateLayers);
IntSize contentSize() const;
void sendDidLoseContextRecursive(CCLayerImpl*);
{
}
-void CCQuadCuller::append(PassOwnPtr<CCDrawQuad> passDrawQuad)
+bool CCQuadCuller::append(PassOwnPtr<CCDrawQuad> passDrawQuad)
{
OwnPtr<CCDrawQuad> drawQuad(passDrawQuad);
IntRect culledRect = m_occlusionTracker->unoccludedContentRect(m_layer, drawQuad->quadRect());
// Release the quad after we're done using it.
if (keepQuad)
m_quadList.append(drawQuad.release());
+ return keepQuad;
}
} // namespace WebCore
// done to estimate over draw statistics.
CCQuadCuller(CCQuadList&, CCLayerImpl*, CCOcclusionTrackerImpl*);
- virtual void append(PassOwnPtr<CCDrawQuad> passDrawQuad);
+ // Returns true if the quad is added to the list, and false if the quad is entirely culled.
+ virtual bool append(PassOwnPtr<CCDrawQuad> passDrawQuad);
private:
CCQuadList& m_quadList;
ASSERT(m_targetSurface);
}
-void CCRenderPass::appendQuadsForLayer(CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker)
+void CCRenderPass::appendQuadsForLayer(CCLayerImpl* layer, CCOcclusionTrackerImpl* occlusionTracker, bool& usedCheckerboard)
{
CCQuadCuller quadCuller(m_quadList, layer, occlusionTracker);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
layer->appendDebugBorderQuad(quadCuller, sharedQuadState.get());
m_sharedQuadStateList.append(sharedQuadState.release());
}
public:
static PassOwnPtr<CCRenderPass> create(CCRenderSurface*);
- void appendQuadsForLayer(CCLayerImpl*, CCOcclusionTrackerImpl*);
+ void appendQuadsForLayer(CCLayerImpl*, CCOcclusionTrackerImpl*, bool& usedCheckerboard);
void appendQuadsForRenderSurfaceLayer(CCLayerImpl*);
const CCQuadList& quadList() const { return m_quadList; }
}
}
-void CCScrollbarLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState)
+void CCScrollbarLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
if (!m_texture->isReserved())
return;
void setScrollLayer(CCLayerImpl* scrollLayer) { m_scrollLayer = scrollLayer; }
virtual void willDraw(LayerRendererChromium*);
- virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& usedCheckerboard);
virtual void didDraw();
protected:
double wallClockTime = currentTime();
m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
- m_layerTreeHostImpl->drawLayers();
+ CCLayerTreeHostImpl::FrameData frame;
+ m_layerTreeHostImpl->prepareToDraw(frame);
+ m_layerTreeHostImpl->drawLayers(frame);
}
if (m_layerTreeHostImpl->isContextLost()) {
return solidColorTransform;
}
-void CCSolidColorLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState)
+void CCSolidColorLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
// We create a series of smaller quads instead of just one large one so that the
// culler can reduce the total pixels drawn.
virtual ~CCSolidColorLayerImpl();
virtual TransformationMatrix quadTransform() const;
- virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& usedCheckerboard);
protected:
explicit CCSolidColorLayerImpl(int id);
}
}
-void CCTextureLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState)
+void CCTextureLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
IntRect quadRect(IntPoint(), bounds());
quadList.append(CCTextureDrawQuad::create(sharedQuadState, quadRect, m_textureId, m_hasAlpha, m_premultipliedAlpha, m_uvRect, m_flipped, m_ioSurfaceSize, m_ioSurfaceTextureId));
}
virtual ~CCTextureLayerImpl();
- virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& usedCheckerboard);
typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> ProgramFlip;
typedef ProgramBinding<VertexShaderPosTexStretch, FragmentShaderRGBATexAlpha> ProgramStretch;
m_inputHandlerOnImplThread->animate(monotonicTime);
m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
- m_layerTreeHostImpl->drawLayers();
+ CCLayerTreeHostImpl::FrameData frame;
+ m_layerTreeHostImpl->prepareToDraw(frame);
+ m_layerTreeHostImpl->drawLayers(frame);
// Check for a pending compositeAndReadback.
if (m_readbackRequestOnImplThread) {
return transform;
}
-void CCTiledLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState)
+void CCTiledLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool& usedCheckerboard)
{
const IntRect& layerRect = visibleLayerRect();
continue;
if (!tile || !tile->textureId()) {
- quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()));
+ usedCheckerboard |= quadList.append(CCSolidColorDrawQuad::create(sharedQuadState, tileRect, backgroundColor()));
continue;
}
}
virtual ~CCTiledLayerImpl();
- virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& usedCheckerboard);
virtual void bindContentsTexture(LayerRendererChromium*);
}
}
-void CCVideoLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState)
+void CCVideoLayerImpl::appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
if (!m_frame)
return;
virtual ~CCVideoLayerImpl();
virtual void willDraw(LayerRendererChromium*);
- virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*);
+ virtual void appendQuads(CCQuadCuller&, const CCSharedQuadState*, bool& usedCheckerboard);
virtual void didDraw();
typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram;
+2012-03-21 Dana Jansens <danakj@chromium.org>
+
+ [chromium] Early out in a new prepareToDraw() step if checkerboarding an accelerated animation in order to skip the frame
+ https://bugs.webkit.org/show_bug.cgi?id=81437
+
+ Reviewed by Adrienne Walker.
+
+ * tests/CCAnimationTestCommon.cpp:
+ (WebCore):
+ (WebCore::addAnimatedTransform):
+ (WebKitTests::addOpacityTransitionToLayer):
+ (WebKitTests):
+ (WebKitTests::addAnimatedTransformToLayer):
+ * tests/CCAnimationTestCommon.h:
+ (WebCore):
+ (WebKitTests):
+ * tests/CCLayerTreeHostImplTest.cpp:
+ (WebKitTests::TEST_F):
+ (DidDrawCheckLayer):
+ (WebKitTests::DidDrawCheckLayer::DidDrawCheckLayer):
+ (MissingTextureAnimatingLayer):
+ (WebKitTests::MissingTextureAnimatingLayer::create):
+ (WebKitTests::MissingTextureAnimatingLayer::MissingTextureAnimatingLayer):
+ (WebKitTests):
+ (WebKitTests::BlendStateCheckLayer::appendQuads):
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF::TestHooks::prepareToDrawOnCCThread):
+ (WTF::MockLayerTreeHostImpl::prepareToDraw):
+ (MockLayerTreeHostImpl):
+ (WTF::MockLayerTreeHostImpl::drawLayers):
+ * tests/CCQuadCullerTest.cpp:
+ (WebCore::appendQuads):
+ * tests/CCSolidColorLayerImplTest.cpp:
+ (CCLayerTestCommon::TEST):
+ * tests/CCTiledLayerImplTest.cpp:
+ (CCLayerTestCommon::TEST):
+ (CCLayerTestCommon::getQuads):
+ * tests/MockCCQuadCuller.h:
+ (WebCore::MockCCQuadCuller::append):
+
2012-03-21 Alexandru Chiculita <achicu@adobe.com>
[CSS Shaders] Make CSS Shaders compile on Chromium
#include "GraphicsLayer.h"
#include "LayerChromium.h"
+#include "TranslateTransformOperation.h"
#include "cc/CCLayerAnimationController.h"
+#include "cc/CCLayerImpl.h"
using namespace WebCore;
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, Fixed), Length(deltaY, 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 {
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)
+{
+ addAnimatedTransform(layer, duration, deltaX, deltaY);
+}
+
+void addAnimatedTransformToLayer(WebCore::CCLayerImpl& layer, double duration, int deltaX, int deltaY)
+{
+ addAnimatedTransform(*layer.layerAnimationController(), duration, deltaX, deltaY);
+}
+
} // namespace WebKitTests
#include <wtf/OwnPtr.h>
namespace WebCore {
+class CCLayerImpl;
class LayerChromium;
}
void addOpacityTransitionToController(WebCore::CCLayerAnimationController&, double duration, float startOpacity, float endOpacity, bool useTimingFunction);
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
#include "cc/CCLayerTreeHostImpl.h"
+#include "CCAnimationTestCommon.h"
#include "FakeWebGraphicsContext3D.h"
#include "GraphicsContext3DPrivate.h"
#include "LayerRendererChromium.h"
using namespace WebCore;
using namespace WebKit;
+using namespace WebKitTests;
namespace {
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);
}
}
-class DidDrawCheckLayer : public CCLayerImpl {
+class DidDrawCheckLayer : public CCTiledLayerImpl {
public:
static PassOwnPtr<DidDrawCheckLayer> create(int id) { return adoptPtr(new DidDrawCheckLayer(id)); }
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)
{
setDrawsContent(true);
}
+private:
bool m_didDrawCalled;
bool m_willDrawCalled;
};
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);
EXPECT_FALSE(root->willDrawCalled());
EXPECT_FALSE(root->didDrawCalled());
EXPECT_FALSE(root->willDrawCalled());
EXPECT_FALSE(root->didDrawCalled());
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(root->willDrawCalled());
EXPECT_TRUE(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);
EXPECT_TRUE(root->didDrawCalled());
EXPECT_TRUE(layer1->didDrawCalled());
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));
+ DidDrawCheckLayer* layer = static_cast<MissingTextureAnimatingLayer*>(root->children()[0].get());
+
+ CCLayerTreeHostImpl::FrameData frame;
+
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(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));
+ layer = static_cast<MissingTextureAnimatingLayer*>(root->children()[0].get());
+
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+
+ // When a texture is missing and we're animating, we don't draw anything.
+ m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
+ root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
+ root->addChild(MissingTextureAnimatingLayer::create(1, true, false, true));
+ layer = static_cast<MissingTextureAnimatingLayer*>(root->children()[0].get());
+
+ EXPECT_FALSE(m_hostImpl->prepareToDraw(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));
+ layer = static_cast<MissingTextureAnimatingLayer*>(root->children()[0].get());
+
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
+}
+
class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
public:
BlendStateTrackerContext() : m_blend(false) { }
public:
static PassOwnPtr<BlendStateCheckLayer> create(int id) { return adoptPtr(new BlendStateCheckLayer(id)); }
- virtual void appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState)
+ virtual void appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&)
{
m_quadsAppended = true;
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->setOpaqueContents(true);
layer1->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
// Layer with translucent content, but opaque content, so drawn without blending.
layer1->setOpaque(false);
layer1->setOpaqueContents(true);
layer1->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
// Layer with translucent content and painting, so drawn with blending.
layer1->setOpaque(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());
// Layer with translucent opacity, drawn with blending.
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());
// Layer with translucent opacity and painting, drawn with blending.
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());
layer1->addChild(BlendStateCheckLayer::create(2));
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());
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());
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());
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());
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());
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());
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());
layer1->setOpaqueContents(false);
layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
layer1->setExpectation(true, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
// Layer with partially opaque contents partially culled, drawn with blending.
layer1->setOpaqueContents(false);
layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
layer1->setExpectation(true, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
// Layer with partially opaque contents culled, drawn with blending.
layer1->setOpaqueContents(false);
layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
layer1->setExpectation(true, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
// Layer with partially opaque contents and translucent contents culled, drawn without blending.
layer1->setOpaqueContents(false);
layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
layer1->setExpectation(false, false);
- m_hostImpl->drawLayers();
+ EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+ m_hostImpl->drawLayers(frame);
EXPECT_TRUE(layer1->quadsAppended());
}
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());
}
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->swapBuffers();
IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
// 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);
layerTreeHostImpl->swapBuffers();
actualSwapRect = partialSwapTracker->partialSwapRect();
expectedSwapRect = IntRect(IntPoint(0, 500-28), IntSize(26, 28));
// 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();
+ EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
+ layerTreeHostImpl->drawLayers(frame);
layerTreeHostImpl->swapBuffers();
actualSwapRect = partialSwapTracker->partialSwapRect();
expectedSwapRect = IntRect(IntPoint::zero(), IntSize(10, 10));
root->setDrawsContent(true);
layerTreeHostImpl->setRootLayer(adoptPtr(root));
+ CCLayerTreeHostImpl::FrameData frame;
+
// First frame: ignore.
- layerTreeHostImpl->drawLayers();
+ EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
+ layerTreeHostImpl->drawLayers(frame);
layerTreeHostImpl->swapBuffers();
// Second frame: nothing has changed --- so we souldn't push anything with partial swap.
- layerTreeHostImpl->drawLayers();
+ EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
+ layerTreeHostImpl->drawLayers(frame);
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();
+ EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
+ layerTreeHostImpl->drawLayers(frame);
layerTreeHostImpl->swapBuffers();
IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
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 applyScrollAndScale(const IntSize&, float) { }
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);
}
{
CCQuadCuller quadCuller(quadList, layer, &occlusionTracker);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
sharedStateList.append(sharedQuadState.release());
}
layer->setBounds(layerSize);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
verifyQuadsExactlyCoverRect(quadCuller.quadList(), visibleLayerRect);
}
layer->setBackgroundColor(testColor);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
ASSERT_EQ(quadCuller.quadList().size(), 1U);
EXPECT_EQ(quadCuller.quadList()[0]->toSolidColorDrawQuad()->color(), testColor);
OwnPtr<CCTiledLayerImpl> layer = createLayer(tileSize, layerSize, CCLayerTilingData::NoBorderTexels);
MockCCQuadCuller quadCuller;
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
const unsigned numTiles = numTilesX * numTilesY;
EXPECT_EQ(quadCuller.quadList().size(), numTiles);
}
MockCCQuadCuller quadCuller;
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
EXPECT_EQ(quadCuller.quadList().size(), 0u);
}
MockCCQuadCuller quadCuller;
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
EXPECT_EQ(quadCuller.quadList().size(), 0u);
}
MockCCQuadCuller quadCuller;
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
EXPECT_EQ(quadCuller.quadList().size(), 0u);
}
}
// No checkerboarding
{
MockCCQuadCuller quadCuller;
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
EXPECT_EQ(quadCuller.quadList().size(), 4u);
+ EXPECT_FALSE(usedCheckerboard);
for (size_t i = 0; i < quadCuller.quadList().size(); ++i)
EXPECT_EQ(quadCuller.quadList()[i]->material(), CCDrawQuad::TiledContent);
// All checkerboarding
{
MockCCQuadCuller quadCuller;
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
+ EXPECT_TRUE(usedCheckerboard);
EXPECT_EQ(quadCuller.quadList().size(), 4u);
for (size_t i = 0; i < quadCuller.quadList().size(); ++i)
EXPECT_EQ(quadCuller.quadList()[i]->material(), CCDrawQuad::SolidColor);
MockCCQuadCuller quadCuller(quads);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
return sharedQuadState.release(); // The shared data must be owned as long as the quad list exists.
}
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
MockCCQuadCuller quadCuller;
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
EXPECT_EQ(quadCuller.quadList().size(), numTiles);
for (size_t i = 0; i < quadCuller.quadList().size(); ++i)
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
MockCCQuadCuller quadCuller;
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
for (size_t i = 0; i < quadCuller.quadList().size(); ++i)
EXPECT_EQ(quadCuller.quadList()[i]->material(), CCDrawQuad::SolidColor);
OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState();
MockCCQuadCuller quadCuller;
- layer->appendQuads(quadCuller, sharedQuadState.get());
+ bool usedCheckerboard = false;
+ layer->appendQuads(quadCuller, sharedQuadState.get(), usedCheckerboard);
unsigned numContentTiles = 0, numGutterTiles = 0;
for (size_t i = 0; i < quadCuller.quadList().size(); ++i) {
, m_activeQuadList(externalQuadList)
{ }
- virtual void append(WTF::PassOwnPtr<WebCore::CCDrawQuad> newQuad)
+ virtual bool append(WTF::PassOwnPtr<WebCore::CCDrawQuad> newQuad)
{
OwnPtr<WebCore::CCDrawQuad> drawQuad = newQuad;
- if (!drawQuad->quadRect().isEmpty())
+ if (!drawQuad->quadRect().isEmpty()) {
m_activeQuadList.append(drawQuad.release());
+ return true;
+ }
+ return false;
}
const WebCore::CCQuadList& quadList() const { return m_activeQuadList; };