DisplayRefreshMonitor.h [plain text]
#ifndef DisplayRefreshMonitor_h
#define DisplayRefreshMonitor_h
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
#include "PlatformScreen.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/Threading.h>
#if PLATFORM(BLACKBERRY)
#include <BlackBerryPlatformAnimationFrameRateController.h>
#endif
#if PLATFORM(MAC)
typedef struct __CVDisplayLink *CVDisplayLinkRef;
#endif
namespace WebCore {
class DisplayAnimationClient;
class DisplayRefreshMonitor;
class DisplayRefreshMonitorManager;
class DisplayRefreshMonitorClient {
friend class DisplayRefreshMonitor;
friend class DisplayRefreshMonitorManager;
public:
DisplayRefreshMonitorClient();
virtual ~DisplayRefreshMonitorClient();
virtual void displayRefreshFired(double timestamp) = 0;
private:
void fireDisplayRefreshIfNeeded(double timestamp);
void setDisplayID(PlatformDisplayID displayID)
{
m_displayID = displayID;
m_displayIDIsSet = true;
}
bool m_scheduled;
bool m_displayIDIsSet;
PlatformDisplayID m_displayID;
};
class DisplayRefreshMonitor : public RefCounted<DisplayRefreshMonitor> {
public:
static PassRefPtr<DisplayRefreshMonitor> create(PlatformDisplayID displayID)
{
return adoptRef(new DisplayRefreshMonitor(displayID));
}
~DisplayRefreshMonitor();
bool requestRefreshCallback();
void windowScreenDidChange(PlatformDisplayID);
bool hasClients() const { return m_clients.size(); }
void addClient(DisplayRefreshMonitorClient*);
bool removeClient(DisplayRefreshMonitorClient*);
PlatformDisplayID displayID() const { return m_displayID; }
bool shouldBeTerminated() const
{
const int maxInactiveFireCount = 10;
return !m_scheduled && m_unscheduledFireCount > maxInactiveFireCount;
}
private:
explicit DisplayRefreshMonitor(PlatformDisplayID);
void displayDidRefresh();
static void handleDisplayRefreshedNotificationOnMainThread(void* data);
double m_monotonicAnimationStartTime;
bool m_active;
bool m_scheduled;
bool m_previousFrameDone;
int m_unscheduledFireCount; PlatformDisplayID m_displayID;
Mutex m_mutex;
HashSet<DisplayRefreshMonitorClient*> m_clients;
HashSet<DisplayRefreshMonitorClient*>* m_clientsToBeNotified;
#if PLATFORM(BLACKBERRY)
public:
void displayLinkFired();
private:
DisplayAnimationClient *m_animationClient;
void startAnimationClient();
void stopAnimationClient();
#endif
#if PLATFORM(MAC)
public:
void displayLinkFired(double nowSeconds, double outputTimeSeconds);
private:
CVDisplayLinkRef m_displayLink;
#endif
};
class DisplayRefreshMonitorManager {
public:
static DisplayRefreshMonitorManager* sharedManager();
void registerClient(DisplayRefreshMonitorClient*);
void unregisterClient(DisplayRefreshMonitorClient*);
bool scheduleAnimation(DisplayRefreshMonitorClient*);
void windowScreenDidChange(PlatformDisplayID, DisplayRefreshMonitorClient*);
private:
friend class DisplayRefreshMonitor;
void displayDidRefresh(DisplayRefreshMonitor*);
DisplayRefreshMonitorManager() { }
DisplayRefreshMonitor* ensureMonitorForClient(DisplayRefreshMonitorClient*);
typedef HashMap<uint64_t, RefPtr<DisplayRefreshMonitor>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> DisplayRefreshMonitorMap;
DisplayRefreshMonitorMap m_monitors;
};
}
#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
#endif