DisplayRefreshMonitor.cpp [plain text]
#include "config.h"
#include "DisplayRefreshMonitor.h"
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
#include "DisplayRefreshMonitorClient.h"
#include "DisplayRefreshMonitorIOS.h"
#include "DisplayRefreshMonitorMac.h"
#include "DisplayRefreshMonitorManager.h"
namespace WebCore {
RefPtr<DisplayRefreshMonitor> DisplayRefreshMonitor::createDefaultDisplayRefreshMonitor(PlatformDisplayID displayID)
{
#if PLATFORM(MAC)
return DisplayRefreshMonitorMac::create(displayID);
#endif
#if PLATFORM(IOS)
return DisplayRefreshMonitorIOS::create(displayID);
#endif
return nullptr;
}
RefPtr<DisplayRefreshMonitor> DisplayRefreshMonitor::create(DisplayRefreshMonitorClient& client)
{
return client.createDisplayRefreshMonitor(client.displayID());
}
DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID)
: m_monotonicAnimationStartTime(0)
, m_active(true)
, m_scheduled(false)
, m_previousFrameDone(true)
, m_unscheduledFireCount(0)
, m_displayID(displayID)
, m_clientsToBeNotified(nullptr)
{
}
DisplayRefreshMonitor::~DisplayRefreshMonitor()
{
}
void DisplayRefreshMonitor::handleDisplayRefreshedNotificationOnMainThread(void* data)
{
DisplayRefreshMonitor* monitor = static_cast<DisplayRefreshMonitor*>(data);
monitor->displayDidRefresh();
}
void DisplayRefreshMonitor::addClient(DisplayRefreshMonitorClient& client)
{
m_clients.add(&client);
}
bool DisplayRefreshMonitor::removeClient(DisplayRefreshMonitorClient& client)
{
if (m_clientsToBeNotified)
m_clientsToBeNotified->remove(&client);
return m_clients.remove(&client);
}
void DisplayRefreshMonitor::displayDidRefresh()
{
double monotonicAnimationStartTime;
{
MutexLocker lock(m_mutex);
if (!m_scheduled)
++m_unscheduledFireCount;
else
m_unscheduledFireCount = 0;
m_scheduled = false;
monotonicAnimationStartTime = m_monotonicAnimationStartTime;
}
Ref<DisplayRefreshMonitor> protect(*this);
HashSet<DisplayRefreshMonitorClient*> clientsToBeNotified = m_clients;
m_clientsToBeNotified = &clientsToBeNotified;
while (!clientsToBeNotified.isEmpty()) {
DisplayRefreshMonitorClient* client = clientsToBeNotified.takeAny();
client->fireDisplayRefreshIfNeeded(monotonicAnimationStartTime);
if (m_clientsToBeNotified != &clientsToBeNotified)
break;
}
if (m_clientsToBeNotified == &clientsToBeNotified)
m_clientsToBeNotified = nullptr;
{
MutexLocker lock(m_mutex);
m_previousFrameDone = true;
}
DisplayRefreshMonitorManager::sharedManager().displayDidRefresh(*this);
}
}
#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)