CCSchedulerTest.cpp [plain text]
#include "config.h"
#include "cc/CCScheduler.h"
#include "CCSchedulerTestCommon.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <wtf/OwnPtr.h>
using namespace WTF;
using namespace WebCore;
using namespace WebKitTests;
namespace {
class FakeCCSchedulerClient : public CCSchedulerClient {
public:
FakeCCSchedulerClient() { reset(); }
void reset()
{
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]; }
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;
};
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);
scheduler->setNeedsCommit();
EXPECT_EQ(1, client.numActions());
EXPECT_STREQ("scheduledActionBeginFrame", client.action(0));
EXPECT_FALSE(timeSource->active());
client.reset();
scheduler->beginFrameComplete();
EXPECT_EQ(2, client.numActions());
EXPECT_STREQ("scheduledActionUpdateMoreResources", client.action(0));
EXPECT_STREQ("scheduledActionCommit", client.action(1));
EXPECT_TRUE(timeSource->active());
client.reset();
timeSource->tick();
EXPECT_EQ(1, client.numActions());
EXPECT_STREQ("scheduledActionDrawAndSwapIfPossible", client.action(0));
EXPECT_FALSE(timeSource->active());
client.reset();
EXPECT_FALSE(timeSource->active());
}
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);
scheduler->setNeedsCommit();
EXPECT_EQ(1, client.numActions());
EXPECT_STREQ("scheduledActionBeginFrame", client.action(0));
client.reset();
scheduler->setNeedsCommit();
scheduler->beginFrameComplete();
EXPECT_EQ(2, client.numActions());
EXPECT_STREQ("scheduledActionUpdateMoreResources", client.action(0));
EXPECT_STREQ("scheduledActionCommit", client.action(1));
client.reset();
timeSource->tick();
EXPECT_FALSE(timeSource->active());
EXPECT_EQ(2, client.numActions());
EXPECT_STREQ("scheduledActionDrawAndSwapIfPossible", client.action(0));
EXPECT_STREQ("scheduledActionBeginFrame", client.action(1));
client.reset();
}
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();
EXPECT_FALSE(timeSource->active());
scheduler->beginFrameComplete();
EXPECT_TRUE(timeSource->active());
client.reset();
scheduler->setMainThreadNeedsLayerTextures();
EXPECT_EQ(0, client.numActions());
client.reset();
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();
scheduler->setVisible(false);
EXPECT_EQ(1, client.numActions());
EXPECT_STREQ("scheduledActionAcquireLayerTexturesForMainThread", client.action(0));
client.reset();
scheduler->setVisible(true);
EXPECT_EQ(1, client.numActions());
EXPECT_STREQ("scheduledActionBeginFrame", client.action(0));
client.reset();
}
class SchedulerClientThatSetNeedsDrawInsideDraw : public FakeCCSchedulerClient {
public:
SchedulerClientThatSetNeedsDrawInsideDraw()
: m_scheduler(0) { }
void setScheduler(CCScheduler* scheduler) { m_scheduler = scheduler; }
virtual void scheduledActionBeginFrame() OVERRIDE { }
virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE
{
if (!m_numDraws)
m_scheduler->setNeedsRedraw();
return FakeCCSchedulerClient::scheduledActionDrawAndSwapIfPossible();
}
virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE
{
ASSERT_NOT_REACHED();
return CCScheduledActionDrawAndSwapResult(true, true);
}
virtual void scheduledActionUpdateMoreResources() OVERRIDE { }
virtual void scheduledActionCommit() OVERRIDE { }
virtual void scheduledActionBeginContextRecreation() OVERRIDE { }
protected:
CCScheduler* m_scheduler;
};
TEST(CCSchedulerTest, RequestRedrawInsideDraw)
{
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);
scheduler->setNeedsRedraw();
EXPECT_TRUE(scheduler->redrawPending());
EXPECT_TRUE(timeSource->active());
EXPECT_EQ(0, client.numDraws());
timeSource->tick();
EXPECT_EQ(1, client.numDraws());
EXPECT_TRUE(scheduler->redrawPending());
EXPECT_TRUE(timeSource->active());
timeSource->tick();
EXPECT_EQ(2, client.numDraws());
EXPECT_FALSE(scheduler->redrawPending());
EXPECT_FALSE(timeSource->active());
}
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());
timeSource->tick();
EXPECT_EQ(1, client.numDraws());
EXPECT_TRUE(scheduler->commitPending());
EXPECT_TRUE(scheduler->redrawPending());
EXPECT_TRUE(timeSource->active());
timeSource->tick();
EXPECT_EQ(2, client.numDraws());
EXPECT_TRUE(scheduler->commitPending());
EXPECT_TRUE(scheduler->redrawPending());
EXPECT_TRUE(timeSource->active());
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_scheduler(0) { }
void setScheduler(CCScheduler* scheduler) { m_scheduler = scheduler; }
virtual void scheduledActionBeginFrame() OVERRIDE { }
virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapIfPossible() OVERRIDE
{
if (!m_numDraws)
m_scheduler->setNeedsCommit();
return FakeCCSchedulerClient::scheduledActionDrawAndSwapIfPossible();
}
virtual CCScheduledActionDrawAndSwapResult scheduledActionDrawAndSwapForced() OVERRIDE
{
ASSERT_NOT_REACHED();
return CCScheduledActionDrawAndSwapResult(true, true);
}
virtual void scheduledActionUpdateMoreResources() OVERRIDE { }
virtual void scheduledActionCommit() OVERRIDE { }
virtual void scheduledActionBeginContextRecreation() OVERRIDE { }
protected:
CCScheduler* m_scheduler;
};
TEST(CCSchedulerTest, RequestCommitInsideDraw)
{
SchedulerClientThatSetNeedsCommitInsideDraw 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);
scheduler->setNeedsRedraw();
EXPECT_TRUE(scheduler->redrawPending());
EXPECT_EQ(0, client.numDraws());
EXPECT_TRUE(timeSource->active());
timeSource->tick();
EXPECT_FALSE(timeSource->active());
EXPECT_EQ(1, client.numDraws());
EXPECT_TRUE(scheduler->commitPending());
scheduler->beginFrameComplete();
timeSource->tick();
EXPECT_EQ(2, client.numDraws());
EXPECT_FALSE(timeSource->active());
EXPECT_FALSE(scheduler->redrawPending());
}
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());
timeSource->tick();
EXPECT_EQ(1, client.numDraws());
EXPECT_TRUE(scheduler->commitPending());
EXPECT_TRUE(scheduler->redrawPending());
EXPECT_TRUE(timeSource->active());
timeSource->tick();
EXPECT_EQ(2, client.numDraws());
EXPECT_TRUE(scheduler->commitPending());
EXPECT_TRUE(scheduler->redrawPending());
EXPECT_TRUE(timeSource->active());
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());
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());
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());
client.setDrawWillHappen(true);
client.setSwapWillHappenIfDrawHappens(false);
scheduler->setNeedsRedraw();
scheduler->setNeedsForcedRedraw();
EXPECT_TRUE(client.hasAction("scheduledActionDrawAndSwapForced"));
EXPECT_EQ(0, controllerPtr->numFramesPending());
}
}