1/*
2 * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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 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.
24 */
25
26#include "config.h"
27#include "DisplayRefreshMonitorManager.h"
28
29#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
30
31#include "DisplayRefreshMonitor.h"
32#include "DisplayRefreshMonitorClient.h"
33#include <wtf/CurrentTime.h>
34
35namespace WebCore {
36
37DisplayRefreshMonitorManager::~DisplayRefreshMonitorManager()
38{
39}
40
41DisplayRefreshMonitorManager& DisplayRefreshMonitorManager::sharedManager()
42{
43    static NeverDestroyed<DisplayRefreshMonitorManager> manager;
44    return manager.get();
45}
46
47DisplayRefreshMonitor* DisplayRefreshMonitorManager::ensureMonitorForClient(DisplayRefreshMonitorClient* client)
48{
49    DisplayRefreshMonitorMap::iterator it = m_monitors.find(client->displayID());
50    if (it == m_monitors.end()) {
51        RefPtr<DisplayRefreshMonitor> monitor = DisplayRefreshMonitor::create(client);
52        monitor->addClient(client);
53        DisplayRefreshMonitor* result = monitor.get();
54        m_monitors.add(client->displayID(), monitor.release());
55        return result;
56    }
57    it->value->addClient(client);
58    return it->value.get();
59}
60
61void DisplayRefreshMonitorManager::registerClient(DisplayRefreshMonitorClient* client)
62{
63    if (!client->hasDisplayID())
64        return;
65
66    ensureMonitorForClient(client);
67}
68
69void DisplayRefreshMonitorManager::unregisterClient(DisplayRefreshMonitorClient* client)
70{
71    if (!client->hasDisplayID())
72        return;
73
74    DisplayRefreshMonitorMap::iterator it = m_monitors.find(client->displayID());
75    if (it == m_monitors.end())
76        return;
77
78    DisplayRefreshMonitor* monitor = it->value.get();
79    if (monitor->removeClient(client)) {
80        if (!monitor->hasClients())
81            m_monitors.remove(it);
82    }
83}
84
85bool DisplayRefreshMonitorManager::scheduleAnimation(DisplayRefreshMonitorClient* client)
86{
87    if (!client->hasDisplayID())
88        return false;
89
90    DisplayRefreshMonitor* monitor = ensureMonitorForClient(client);
91
92    client->setIsScheduled(true);
93    return monitor->requestRefreshCallback();
94}
95
96void DisplayRefreshMonitorManager::displayDidRefresh(DisplayRefreshMonitor* monitor)
97{
98    if (monitor->shouldBeTerminated()) {
99        ASSERT(m_monitors.contains(monitor->displayID()));
100        m_monitors.remove(monitor->displayID());
101    }
102}
103
104void DisplayRefreshMonitorManager::windowScreenDidChange(PlatformDisplayID displayID, DisplayRefreshMonitorClient* client)
105{
106    if (client->hasDisplayID() && client->displayID() == displayID)
107        return;
108
109    unregisterClient(client);
110    client->setDisplayID(displayID);
111    registerClient(client);
112    if (client->isScheduled())
113        scheduleAnimation(client);
114}
115
116}
117
118#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
119