2
* Copyright (C) 2010 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
30
#include "DisplayRefreshMonitor.h"
32
#include <wtf/CurrentTime.h>
36
DisplayRefreshMonitorClient::DisplayRefreshMonitorClient()
38
, m_displayIDIsSet(false)
42
DisplayRefreshMonitorClient::~DisplayRefreshMonitorClient()
44
DisplayRefreshMonitorManager::sharedManager()->unregisterClient(this);
47
void DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded(double timestamp)
51
displayRefreshFired(timestamp);
55
DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID)
56
: m_monotonicAnimationStartTime(0)
59
, m_previousFrameDone(true)
60
, m_unscheduledFireCount(0)
61
, m_displayID(displayID)
65
#if PLATFORM(BLACKBERRY)
66
, m_animationClient(0)
71
void DisplayRefreshMonitor::handleDisplayRefreshedNotificationOnMainThread(void* data)
73
DisplayRefreshMonitor* monitor = static_cast<DisplayRefreshMonitor*>(data);
74
monitor->displayDidRefresh();
77
void DisplayRefreshMonitor::addClient(DisplayRefreshMonitorClient* client)
79
m_clients.add(client);
82
bool DisplayRefreshMonitor::removeClient(DisplayRefreshMonitorClient* client)
84
DisplayRefreshMonitorClientSet::iterator it = m_clients.find(client);
85
if (it != m_clients.end()) {
92
void DisplayRefreshMonitor::displayDidRefresh()
94
double monotonicAnimationStartTime;
96
MutexLocker lock(m_mutex);
98
++m_unscheduledFireCount;
100
m_unscheduledFireCount = 0;
103
monotonicAnimationStartTime = m_monotonicAnimationStartTime;
106
// The call back can cause all our clients to be unregistered, so we need to protect
107
// against deletion until the end of the method.
108
RefPtr<DisplayRefreshMonitor> protector(this);
110
Vector<DisplayRefreshMonitorClient*> clients;
111
copyToVector(m_clients, clients);
112
for (size_t i = 0; i < clients.size(); ++i)
113
clients[i]->fireDisplayRefreshIfNeeded(monotonicAnimationStartTime);
116
MutexLocker lock(m_mutex);
117
m_previousFrameDone = true;
120
DisplayRefreshMonitorManager::sharedManager()->displayDidRefresh(this);
123
DisplayRefreshMonitorManager* DisplayRefreshMonitorManager::sharedManager()
125
DEFINE_STATIC_LOCAL(DisplayRefreshMonitorManager, manager, ());
129
DisplayRefreshMonitor* DisplayRefreshMonitorManager::ensureMonitorForClient(DisplayRefreshMonitorClient* client)
131
DisplayRefreshMonitorMap::iterator it = m_monitors.find(client->m_displayID);
132
if (it == m_monitors.end()) {
133
RefPtr<DisplayRefreshMonitor> monitor = DisplayRefreshMonitor::create(client->m_displayID);
134
monitor->addClient(client);
135
DisplayRefreshMonitor* result = monitor.get();
136
m_monitors.add(client->m_displayID, monitor.release());
139
it->value->addClient(client);
140
return it->value.get();
143
void DisplayRefreshMonitorManager::registerClient(DisplayRefreshMonitorClient* client)
145
if (!client->m_displayIDIsSet)
148
ensureMonitorForClient(client);
151
void DisplayRefreshMonitorManager::unregisterClient(DisplayRefreshMonitorClient* client)
153
if (!client->m_displayIDIsSet)
156
DisplayRefreshMonitorMap::iterator it = m_monitors.find(client->m_displayID);
157
if (it == m_monitors.end())
160
DisplayRefreshMonitor* monitor = it->value.get();
161
if (monitor->removeClient(client)) {
162
if (!monitor->hasClients())
163
m_monitors.remove(it);
167
bool DisplayRefreshMonitorManager::scheduleAnimation(DisplayRefreshMonitorClient* client)
169
if (!client->m_displayIDIsSet)
172
DisplayRefreshMonitor* monitor = ensureMonitorForClient(client);
174
client->m_scheduled = true;
175
return monitor->requestRefreshCallback();
178
void DisplayRefreshMonitorManager::displayDidRefresh(DisplayRefreshMonitor* monitor)
180
if (monitor->shouldBeTerminated()) {
181
DisplayRefreshMonitorMap::iterator it = m_monitors.find(monitor->displayID());
182
ASSERT(it != m_monitors.end());
183
m_monitors.remove(it);
187
void DisplayRefreshMonitorManager::windowScreenDidChange(PlatformDisplayID displayID, DisplayRefreshMonitorClient* client)
189
if (client->m_displayIDIsSet && client->m_displayID == displayID)
192
unregisterClient(client);
193
client->setDisplayID(displayID);
194
registerClient(client);
195
if (client->m_scheduled)
196
scheduleAnimation(client);
201
#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)